Author: ivan
Date: Wed Apr  2 11:45:06 2014
New Revision: 1583977

URL: http://svn.apache.org/r1583977
Log:
Do not leave dead transaction if commit is blocked by start-commit hook. Also
fix svn_repos_fs_begin_txn_for_commit2() API promise regression that was 
broken in r1376201.

* subversion/libsvn_repos/fs-wrap.c
  (svn_repos_fs_begin_txn_for_commit2): Abort created transaction if error 
   happens between transaction creation and successful return from 
   function as promised in docstring. Also keep output *TXN_P 
   parameter unaffected on failure as promised in docstring.

* subversion/tests/cmdline/commit_tests.py
  (start_commit_hook_test): Verify that there is no dead transaction left 
   when commit was blocked by start-commit hook.

Modified:
    subversion/trunk/subversion/libsvn_repos/fs-wrap.c
    subversion/trunk/subversion/tests/cmdline/commit_tests.py

Modified: subversion/trunk/subversion/libsvn_repos/fs-wrap.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/fs-wrap.c?rev=1583977&r1=1583976&r2=1583977&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/trunk/subversion/libsvn_repos/fs-wrap.c Wed Apr  2 11:45:06 2014
@@ -136,6 +136,8 @@ svn_repos_fs_begin_txn_for_commit2(svn_f
   const char *txn_name;
   svn_string_t *author = svn_hash_gets(revprop_table, 
SVN_PROP_REVISION_AUTHOR);
   apr_hash_t *hooks_env;
+  svn_error_t *err;
+  svn_fs_txn_t *txn;
 
   /* Parse the hooks-env file (if any). */
   SVN_ERR(svn_repos__parse_hooks_env(&hooks_env, repos->hooks_env_path,
@@ -143,21 +145,30 @@ svn_repos_fs_begin_txn_for_commit2(svn_f
 
   /* Begin the transaction, ask for the fs to do on-the-fly lock checks.
      We fetch its name, too, so the start-commit hook can use it.  */
-  SVN_ERR(svn_fs_begin_txn2(txn_p, repos->fs, rev,
+  SVN_ERR(svn_fs_begin_txn2(&txn, repos->fs, rev,
                             SVN_FS_TXN_CHECK_LOCKS, pool));
-  SVN_ERR(svn_fs_txn_name(&txn_name, *txn_p, pool));
+  err = svn_fs_txn_name(&txn_name, txn, pool);
+  if (err)
+    return svn_error_compose_create(err, svn_fs_abort_txn(txn, pool));
 
   /* We pass the revision properties to the filesystem by adding them
      as properties on the txn.  Later, when we commit the txn, these
      properties will be copied into the newly created revision. */
   revprops = svn_prop_hash_to_array(revprop_table, pool);
-  SVN_ERR(svn_repos_fs_change_txn_props(*txn_p, revprops, pool));
+  err = svn_repos_fs_change_txn_props(txn, revprops, pool);
+  if (err)
+    return svn_error_compose_create(err, svn_fs_abort_txn(txn, pool));
 
   /* Run start-commit hooks. */
-  SVN_ERR(svn_repos__hooks_start_commit(repos, hooks_env,
-                                        author ? author->data : NULL,
-                                        repos->client_capabilities, txn_name,
-                                        pool));
+  err = svn_repos__hooks_start_commit(repos, hooks_env,
+                                      author ? author->data : NULL,
+                                      repos->client_capabilities, txn_name,
+                                      pool);
+  if (err)
+    return svn_error_compose_create(err, svn_fs_abort_txn(txn, pool));
+
+  /* We have API promise that *TXN_P is unaffected on faulure. */
+  *txn_p = txn;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/tests/cmdline/commit_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/commit_tests.py?rev=1583977&r1=1583976&r2=1583977&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/commit_tests.py Wed Apr  2 
11:45:06 2014
@@ -2545,6 +2545,16 @@ def start_commit_hook_test(sbox):
                                            'STDERR',
                                            expected_stderr, actual_stderr)
 
+  # Now list the txns in the repo. The list should be empty.
+  exit_code, output, errput = svntest.main.run_svnadmin('lstxns',
+                                                        sbox.repo_dir)
+  svntest.verify.compare_and_display_lines(
+    "Error running 'svnadmin lstxns'.",
+    'STDERR', [], errput)
+  svntest.verify.compare_and_display_lines(
+    "Output of 'svnadmin lstxns' is unexpected.",
+    'STDOUT', [], output)
+
 #----------------------------------------------------------------------
 @Issue(3553)
 def pre_commit_hook_test(sbox):


Reply via email to