diff src/org/tmatesoft/hg/core/HgCommitCommand.java @ 617:65c01508f002

Rollback support for commands that modify repository. Strategy to keep complete copy of a file being changed
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 15 May 2013 20:10:09 +0200
parents e447384f3771
children 7c0d2ce340b8
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/core/HgCommitCommand.java	Tue May 14 17:31:35 2013 +0200
+++ b/src/org/tmatesoft/hg/core/HgCommitCommand.java	Wed May 15 20:10:09 2013 +0200
@@ -23,10 +23,13 @@
 import java.util.ArrayList;
 
 import org.tmatesoft.hg.internal.ByteArrayChannel;
+import org.tmatesoft.hg.internal.COWTransaction;
 import org.tmatesoft.hg.internal.CommitFacility;
+import org.tmatesoft.hg.internal.CompleteRepoLock;
 import org.tmatesoft.hg.internal.Experimental;
 import org.tmatesoft.hg.internal.FileContentSupplier;
 import org.tmatesoft.hg.internal.Internals;
+import org.tmatesoft.hg.internal.Transaction;
 import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgDataFile;
 import org.tmatesoft.hg.repo.HgInternals;
@@ -86,6 +89,7 @@
 
 	/**
 	 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state
+	 * @throws HgRepositoryLockException if failed to lock the repo for modifications
 	 * @throws IOException propagated IO errors from status walker over working directory
 	 * @throws CancelledException if execution of the command was cancelled
 	 */
@@ -93,6 +97,8 @@
 		if (message == null) {
 			throw new HgBadArgumentException("Shall supply commit message", null);
 		}
+		final CompleteRepoLock repoLock = new CompleteRepoLock(repo);
+		repoLock.acquire();
 		try {
 			int[] parentRevs = new int[2];
 			detectParentFromDirstate(parentRevs);
@@ -127,7 +133,18 @@
 			}
 			cf.branch(detectBranch());
 			cf.user(detectUser());
-			newRevision = cf.commit(message);
+			Transaction.Factory trFactory = new COWTransaction.Factory();
+			Transaction tr = trFactory.create(repo);
+			try {
+				newRevision = cf.commit(message, tr);
+				tr.commit();
+			} catch (RuntimeException ex) {
+				tr.rollback();
+				throw ex;
+			} catch (HgException ex) {
+				tr.rollback();
+				throw ex;
+			}
 			// TODO toClear list is awful
 			for (FileContentSupplier fcs : toClear) {
 				fcs.done();
@@ -135,6 +152,8 @@
 			return new Outcome(Kind.Success, "Commit ok");
 		} catch (HgRuntimeException ex) {
 			throw new HgLibraryFailureException(ex);
+		} finally {
+			repoLock.release();
 		}
 	}