Start work on issue #1601: to do deltification unconditionally as part
of the commit, but in the background when possible, so the user
doesn't wait.

This change prepares code paths for RA layers to choose which style of
deltification is most appropriate.  The actual deltification
(backgrounded or foregrounded) is not implemented yet.  In other
words, don't merge this to trunk yet :-).

* subversion/include/svn_repos.h
  (enum svn_repos_deltification_style): New enum.
  (svn_repos_fs_commit_txn, svn_repos_get_commit_editor): Take new
    deltify_how enum parameter.

* subversion/libsvn_repos/fs-wrap.c
  (svn_repos_fs_commit_txn): Take new deltify_how enum, leave comment
    about actually using it.

* subversion/libsvn_repos/commit.c
  (struct edit_baton): New field deltify_how.
  (svn_repos_get_commit_editor): Take new deltify_how parameter, store
    it in the edit baton.
  (close_edit): Pass eb->deltify_how to svn_repos_fs_commit_txn.

* subversion/libsvn_ra_local/ra_plugin.c
  (svn_ra_local__get_commit_editor): Pass svn_repos_deltify_foreground
    to svn_repos_get_commit_editor.

* subversion/svnserve/serve.c
  (commit): Pass svn_repos_deltify_foreground to
    svn_repos_get_commit_editor, for now, and leave comment about
    conditionalizing based on daemon mode.

* subversion/mod_dav_svn/version.c
  (dav_svn_checkin, dav_svn_merge): Pass svn_repos_deltify_background
    to svn_repos_fs_commit_txn.

* subversion/tests/libsvn_repos/repos-test.c
  (dir_deltas, node_tree_delete_under_copy): Pass
    svn_repos_deltify_foreground to svn_repos_fs_commit_txn.

* subversion/libsvn_repos/repos.c
  (create_hooks): Remove call to 'svnadmin deltify' from the
    post-commit hook template.

* subversion/include/svn_types.h
  (svn_commit_callback_t): Document that this is invoked only after
    the post-commit hook has completed.


git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/issue-1601-dev@848048 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subversion/include/svn_repos.h b/subversion/include/svn_repos.h
index d7940f2..0a02ad8 100644
--- a/subversion/include/svn_repos.h
+++ b/subversion/include/svn_repos.h
@@ -434,6 +434,21 @@
 
 /* Making commits. */
 
+/* This specifies whether and how deltification of the previous
+   revision tree is to be done.  If none, then do no deltification; if
+   foreground, then perform deltification in the same line of
+   execution and don't return from the commit until deltification is
+   completed; if background, then if possible, fork/spawn a separate
+   deltification process and return from the commit immediately, else
+   fall back to the foreground behavior. */
+enum svn_repos_deltify_how
+{
+  svn_repos_deltify_none,
+  svn_repos_deltify_foreground,
+  svn_repos_deltify_background
+};
+
+
 /** Return an @a editor and @a edit_baton to commit changes to @a session->fs,
  * beginning at location 'rev:@a base_path', where "rev" is the argument
  * given to @c open_root().  Store @a user as the author of the commit and
@@ -450,6 +465,9 @@
  * error will be returned from @c close_edit, otherwise if there was a
  * post-commit hook failure, then that error will be returned and will
  * have code SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED.
+ *
+ * @a deltify_how says how to deltify the previous revision, if at
+ * all; see the type's documentation for more. 
  */
 svn_error_t *svn_repos_get_commit_editor (const svn_delta_editor_t **editor,
                                           void **edit_baton,
@@ -460,6 +478,7 @@
                                           const char *log_msg,
                                           svn_commit_callback_t callback,
                                           void *callback_baton,
+                                          enum svn_repos_deltify_how deltify_how,
                                           apr_pool_t *pool);
 
 
@@ -614,11 +633,15 @@
  * error, it knows that the commit succeeded anyway.
  *
  * @a conflict_p, @a new_rev, and @a txn are as in @c svn_fs_commit_txn().
+ *
+ * @a deltify_how says how to deltify the previous revision, if at
+ * all; see the type's documentation for more. 
  */
 svn_error_t *svn_repos_fs_commit_txn (const char **conflict_p,
                                       svn_repos_t *repos,
                                       svn_revnum_t *new_rev,
                                       svn_fs_txn_t *txn,
+                                      enum svn_repos_deltify_how deltify_how,
                                       apr_pool_t *pool);
 
 /** Like @c svn_fs_begin_txn(), but use @a author and @a log_msg to set the
diff --git a/subversion/include/svn_types.h b/subversion/include/svn_types.h
index 196a86c..18b5f86 100644
--- a/subversion/include/svn_types.h
+++ b/subversion/include/svn_types.h
@@ -301,9 +301,9 @@
 
 /** Callback function type for commits.
  *
- * When a commit succeeds, an instance of this is invoked on the @a
- * new_revision, @a date, and @a author of the commit, along with the
- * @a baton closure.
+ * When a commit succeeds (and the post-commit hook has exited), an
+ * instance of this is invoked on the @a new_revision, @a date, and
+ * @a author of the commit, along with the @a baton closure.
  */
 typedef svn_error_t * (*svn_commit_callback_t) (
     svn_revnum_t new_revision,
diff --git a/subversion/libsvn_ra_local/ra_plugin.c b/subversion/libsvn_ra_local/ra_plugin.c
index 43f122a..d70ef73 100644
--- a/subversion/libsvn_ra_local/ra_plugin.c
+++ b/subversion/libsvn_ra_local/ra_plugin.c
@@ -322,7 +322,8 @@
   SVN_ERR (svn_repos_get_commit_editor (editor, edit_baton, sess->repos,
                                         sess->repos_url, sess->fs_path,
                                         sess->username, log_msg,
-                                        callback, callback_baton, pool));
+                                        callback, callback_baton,
+                                        svn_repos_deltify_foreground, pool));
 
   return SVN_NO_ERROR;
 }
diff --git a/subversion/libsvn_repos/commit.c b/subversion/libsvn_repos/commit.c
index 58312f7..1397578 100644
--- a/subversion/libsvn_repos/commit.c
+++ b/subversion/libsvn_repos/commit.c
@@ -80,6 +80,9 @@
   /* The new revision created by this commit. */
   svn_revnum_t *new_rev;
 
+  /* Whether and how to deltify the result of this commit. */
+  enum svn_repos_deltify_how deltify_how;
+
   /* The date (according to the repository) of this commit. */
   const char **committed_date;
 
@@ -528,7 +531,8 @@
 
   /* Commit. */
   err = svn_repos_fs_commit_txn (&conflict, eb->repos, 
-                                 &new_revision, eb->txn, pool);
+                                 &new_revision, eb->txn,
+                                 eb->deltify_how, pool);
 
   /* We want to abort the transaction *unless* the error code tells us
      the commit succeeded and something just went wrong in post-commit. */
@@ -612,6 +616,7 @@
                              const char *log_msg,
                              svn_commit_callback_t callback,
                              void *callback_baton,
+                             enum svn_repos_deltify_how deltify_how,
                              apr_pool_t *pool)
 {
   svn_delta_editor_t *e = svn_delta_default_editor (pool);
@@ -643,6 +648,7 @@
   eb->repos_url = repos_url;
   eb->fs = svn_repos_fs (repos);
   eb->txn = NULL;
+  eb->deltify_how = deltify_how;
 
   *edit_baton = eb;
   *editor = e;
diff --git a/subversion/libsvn_repos/fs-wrap.c b/subversion/libsvn_repos/fs-wrap.c
index 99df352..0b6cb7c 100644
--- a/subversion/libsvn_repos/fs-wrap.c
+++ b/subversion/libsvn_repos/fs-wrap.c
@@ -33,6 +33,7 @@
                          svn_repos_t *repos,
                          svn_revnum_t *new_rev,
                          svn_fs_txn_t *txn,
+                         enum svn_repos_deltify_how deltify_how,
                          apr_pool_t *pool)
 {
   svn_error_t *err;
@@ -53,6 +54,8 @@
       (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
        "Commit succeeded, but post-commit hook failed.");
 
+  /* ### issue-1601-todo: use deltify_how parameter here. */
+
   return SVN_NO_ERROR;
 }
 
diff --git a/subversion/libsvn_repos/repos.c b/subversion/libsvn_repos/repos.c
index bc8b13f..e58847b 100644
--- a/subversion/libsvn_repos/repos.c
+++ b/subversion/libsvn_repos/repos.c
@@ -637,11 +637,6 @@
       "REV=\"$2\""
       APR_EOL_STR
       APR_EOL_STR
-      "# Deltify predecessors of things changed in this revision."
-      APR_EOL_STR
-      "nice -2 svnadmin deltify \"$REPOS\" -r \"$REV\" &"
-      APR_EOL_STR
-      APR_EOL_STR
       "commit-email.pl \"$REPOS\" \"$REV\" commit-watchers@example.org"
       APR_EOL_STR
       "log-commit.py --repository \"$REPOS\" --revision \"$REV\""
diff --git a/subversion/mod_dav_svn/version.c b/subversion/mod_dav_svn/version.c
index 42179a7..d8e759a 100644
--- a/subversion/mod_dav_svn/version.c
+++ b/subversion/mod_dav_svn/version.c
@@ -633,6 +633,7 @@
                                          resource->info->repos->repos,
                                          &new_rev, 
                                          resource->info->root.txn,
+                                         svn_repos_deltify_background,
                                          resource->pool);
           if (serr != NULL)
             {
@@ -880,7 +881,8 @@
 
   /* all righty... commit the bugger. */
   serr = svn_repos_fs_commit_txn(&conflict, source->info->repos->repos,
-                                 &new_rev, txn, pool);
+                                 &new_rev, txn, svn_repos_deltify_background,
+                                 pool);
   if (serr != NULL)
     {
       const char *msg;
diff --git a/subversion/svnserve/serve.c b/subversion/svnserve/serve.c
index 79dde31..6eed997 100644
--- a/subversion/svnserve/serve.c
+++ b/subversion/svnserve/serve.c
@@ -539,9 +539,13 @@
   ccb.new_rev = &new_rev;
   ccb.date = &date;
   ccb.author = &author;
+  /* ### issue-1601-todo: For now, pass svn_repos_deltify_foreground
+     as that's safe in all modes.  The next step is for daemon mode to
+     deltify in the background. */
   SVN_CMD_ERR(svn_repos_get_commit_editor(&editor, &edit_baton, b->repos,
                                           b->repos_url, b->fs_path, b->user,
-                                          log_msg, commit_done, &ccb, pool));
+                                          log_msg, commit_done, &ccb,
+                                          svn_repos_deltify_foreground, pool));
   SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
   SVN_ERR(svn_ra_svn_drive_editor(conn, pool, editor, edit_baton, &aborted));
   if (!aborted)
diff --git a/subversion/tests/libsvn_repos/repos-test.c b/subversion/tests/libsvn_repos/repos-test.c
index 68835ab..221362a 100644
--- a/subversion/tests/libsvn_repos/repos-test.c
+++ b/subversion/tests/libsvn_repos/repos-test.c
@@ -76,7 +76,8 @@
   SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, subpool));
   SVN_ERR (svn_fs_txn_root (&txn_root, txn, subpool));
   SVN_ERR (svn_test__create_greek_tree (txn_root, subpool));
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, subpool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, subpool));
 
   /***********************************************************************/
   /* REVISION 1 */
@@ -137,7 +138,8 @@
     SVN_ERR (svn_test__txn_script_exec (txn_root, script_entries, 10, 
                                         subpool));
   }
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, subpool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, subpool));
 
   /***********************************************************************/
   /* REVISION 2 */
@@ -191,7 +193,8 @@
     };
     SVN_ERR (svn_test__txn_script_exec (txn_root, script_entries, 4, subpool));
   }
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, subpool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, subpool));
 
   /***********************************************************************/
   /* REVISION 3 */
@@ -244,7 +247,8 @@
   SVN_ERR (svn_fs_copy (revision_root, "A/epsilon",
                         txn_root, "A/B/epsilon",
                         subpool));
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, subpool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, subpool));
 
   /***********************************************************************/
   /* REVISION 4 */
@@ -381,7 +385,8 @@
 
   /* Create and commit the greek tree. */
   SVN_ERR (svn_test__create_greek_tree (txn_root, pool));
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, pool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, pool));
 
   /* Now, commit again, this time after copying a directory, and then
      deleting some paths under that directory. */
@@ -391,7 +396,8 @@
   SVN_ERR (svn_fs_copy (revision_root, "A", txn_root, "Z", pool));
   SVN_ERR (svn_fs_delete (txn_root, "Z/D/G/rho", pool));
   SVN_ERR (svn_fs_delete (txn_root, "Z/D/H", pool));
-  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn, pool));
+  SVN_ERR (svn_repos_fs_commit_txn (NULL, repos, &youngest_rev, txn,
+                                    svn_repos_deltify_foreground, pool));
 
   /* Now, we run the node_tree editor code, and see that a) it doesn't
      bomb out, and b) that our nodes are all good. */