I am trying to synchronize a workflow where some actions take place across a couple of systems. One of those systems is Subversion, using SharpSvn, another is SqlServer and yet others are systems that support distributed transactions.
Is there a way that I can include the SharpSvn / Subversion within the workflow and enroll it within a transaction such that it could rollback in case of a failure?
In particular, I am thinking Add, Delete which are local transactions affecting the local file system and Update, Revert, Checkout which are all transactions invoked against subversion.
I have not found anything in the subversion red-book about transactions.
Subversion itself doesn't have any notion of "transactions", per se. Subversion commands that modify the remote repository are atomic and many that alter the working copy are easily reversible, so there's typically not a need for a "transaction" in the typical sense. If your application needs transactions, you should be able to put together a custom framework to support this (I don't know of any pre-built solutions).
The problem you'll run into will likely be aborting a transaction. If the transaction's "prepare" command commits the incoming change, there's no easy way to "undo" the commit that already happened. You can issue a second commit that simply reverts the original change (such as a reverse merge), but doing this will add two new revisions to the repository (HEAD looks the same before and after the failed transaction, but it isn't truly unmodified since there is now an intermediate revision). You can use svnadmin
commands to dump the repository and filter out the revision that you want to roll back, but this is risky and can easily lead to problems. Subversion is designed so that it doesn't lose history, so removing something from the repository history is necessarily difficult (other revision control systems, like git
, make this much easier).
One way around this might be to use a git repository as a staging area for incoming commits. When the transaction's "prepare" command is sent, the incoming change is commited into the git repo. If the "abort" command is sent, the commit is removed from the git repo via git reset
. The "commit" command would tell git (via git-svn
) to push the commit to the Subversion repo. This way, the Subversion repository isn't modified unless the transaction is committed, but the server still has the data cached in a way that's easy to work with.