=== subversion/libsvn_repos/fs-wrap.c
==================================================================
--- subversion/libsvn_repos/fs-wrap.c	(revision 32395)
+++ subversion/libsvn_repos/fs-wrap.c	(local)
@@ -447,7 +447,7 @@
 {
   svn_error_t *err;
   svn_fs_access_t *access_ctx = NULL;
-  const char *username = NULL;
+  const char *username = NULL, *new_token = NULL;
   apr_array_header_t *paths;
 
   /* Setup an array of paths in anticipation of the ra layers handling
@@ -467,9 +467,9 @@
 
   /* Run pre-lock hook.  This could throw error, preventing
      svn_fs_lock() from happening. */
-  SVN_ERR(svn_repos__hooks_pre_lock(repos, path, username, comment,
+  SVN_ERR(svn_repos__hooks_pre_lock(repos, &new_token, path, username, comment,
                                     steal_lock, pool));
-
+  token = (new_token && *new_token) ? new_token : token;
   /* Lock. */
   SVN_ERR(svn_fs_lock(lock, repos->fs, path, token, comment, is_dav_comment,
                       expiration_date, current_rev, steal_lock, pool));
=== subversion/libsvn_repos/hooks.c
==================================================================
--- subversion/libsvn_repos/hooks.c	(revision 32395)
+++ subversion/libsvn_repos/hooks.c	(local)
@@ -156,15 +156,20 @@
    the returned error.
 
    If STDIN_HANDLE is non-null, pass it as the hook's stdin, else pass
-   no stdin to the hook. */
+   no stdin to the hook.
+
+   If RESULT is non-null, capture the stdout of the hook and return it.
+*/
 static svn_error_t *
-run_hook_cmd(const char *name,
+run_hook_cmd(const char **result,
+             const char *name,
              const char *cmd,
              const char **args,
              apr_file_t *stdin_handle,
              apr_pool_t *pool)
 {
   apr_file_t *read_errhandle, *write_errhandle, *null_handle;
+  apr_file_t *read_outhandle, *write_outhandle;  
   apr_status_t apr_err;
   svn_error_t *err;
   apr_proc_t cmd_proc;
@@ -194,16 +199,39 @@
       (apr_err, _("Can't make pipe write handle non-inherited for hook '%s'"),
        cmd);
 
+  if (result)
+    {
+      /* Create a pipe to access stdout of the child. */
+      apr_err = apr_file_pipe_create(&read_outhandle, &write_outhandle, pool);
+      if (apr_err)
+        return svn_error_wrap_apr
+          (apr_err, _("Can't create pipe for hook '%s'"), cmd);
 
-  /* Redirect stdout to the null device */
-  apr_err = apr_file_open(&null_handle, SVN_NULL_DEVICE_NAME, APR_WRITE,
-                          APR_OS_DEFAULT, pool);
-  if (apr_err)
-    return svn_error_wrap_apr
-      (apr_err, _("Can't create null stdout for hook '%s'"), cmd);
+      apr_err = apr_file_inherit_unset(read_outhandle);
+      if (apr_err)
+        return svn_error_wrap_apr
+          (apr_err,
+           _("Can't make pipe read handle non-inherited for hook '%s'"), cmd);
 
+      apr_err = apr_file_inherit_unset(write_outhandle);
+      if (apr_err)
+        return svn_error_wrap_apr
+          (apr_err,
+           _("Can't make pipe write handle non-inherited for hook '%s'"), cmd);
+    }
+  else
+    {
+      /* Redirect stdout to the null device */
+        apr_err = apr_file_open(&null_handle, SVN_NULL_DEVICE_NAME, APR_WRITE,
+                                APR_OS_DEFAULT, pool);
+        if (apr_err)
+          return svn_error_wrap_apr
+            (apr_err, _("Can't create null stdout for hook '%s'"), cmd);
+    }
+
   err = svn_io_start_cmd(&cmd_proc, ".", cmd, args, FALSE,
-                         stdin_handle, null_handle, write_errhandle, pool);
+                         stdin_handle, result ? write_outhandle : null_handle,
+                         write_errhandle, pool);
 
   /* This seems to be done automatically if we pass the third parameter of
      apr_procattr_child_in/out_set(), but svn_io_run_cmd()'s interface does
@@ -214,6 +242,14 @@
     return svn_error_wrap_apr
       (apr_err, _("Error closing write end of stderr pipe"));
 
+  if (result)
+    {
+      apr_err = apr_file_close(write_outhandle);
+      if (!err && apr_err)
+        return svn_error_wrap_apr
+          (apr_err, _("Error closing write end of stderr pipe"));
+    }
+
   if (err)
     {
       err = svn_error_createf
@@ -232,10 +268,24 @@
     return svn_error_wrap_apr
       (apr_err, _("Error closing read end of stderr pipe"));
 
-  apr_err = apr_file_close(null_handle);
-  if (!err && apr_err)
-    return svn_error_wrap_apr(apr_err, _("Error closing null file"));
+  if (result)
+    {
+      svn_stringbuf_t *native_stdout;
+      SVN_ERR(svn_stringbuf_from_aprfile(&native_stdout, read_outhandle, pool));
+      apr_err = apr_file_close(read_outhandle);
+      if (!err && apr_err)
+        return svn_error_wrap_apr
+          (apr_err, _("Error closing read end of stderr pipe"));
 
+      *result = (svn_string_create_from_buf(native_stdout, pool))->data;
+    }
+  else
+    {
+      apr_err = apr_file_close(null_handle);
+      if (!err && apr_err)
+        return svn_error_wrap_apr(apr_err, _("Error closing null file"));
+    }
+
   return err;
 }
 
@@ -258,7 +308,6 @@
   return SVN_NO_ERROR;
 }
 
-
 /* Check if the HOOK program exists and is a file or a symbolic link, using
    POOL for temporary allocations.
 
@@ -360,7 +409,7 @@
       args[3] = capabilities_string;
       args[4] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_START_COMMIT, hook, args, NULL,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_START_COMMIT, hook, args, NULL,
                            pool));
     }
 
@@ -389,7 +438,7 @@
       args[2] = txn_name;
       args[3] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_COMMIT, hook, args, NULL,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_COMMIT, hook, args, NULL,
                            pool));
     }
 
@@ -418,14 +467,13 @@
       args[2] = apr_psprintf(pool, "%ld", rev);
       args[3] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_POST_COMMIT, hook, args, NULL,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_COMMIT, hook, args, NULL,
                            pool));
     }
 
   return SVN_NO_ERROR;
 }
 
-
 svn_error_t  *
 svn_repos__hooks_pre_revprop_change(svn_repos_t *repos,
                                     svn_revnum_t rev,
@@ -466,7 +514,7 @@
       args[5] = action_string;
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_REVPROP_CHANGE, hook, args,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_REVPROP_CHANGE, hook, args,
                            stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
@@ -528,8 +576,8 @@
       args[5] = action_string;
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_POST_REVPROP_CHANGE, hook, args,
-                           stdin_handle, pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_REVPROP_CHANGE, hook,
+                           args, stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }
@@ -541,6 +589,7 @@
 
 svn_error_t  *
 svn_repos__hooks_pre_lock(svn_repos_t *repos,
+                          const char **token,
                           const char *path,
                           const char *username,
                           const char *comment,
@@ -566,7 +615,8 @@
       args[5] = steal_lock ? "1" : "0";
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_LOCK, hook, args, NULL, pool));
+      SVN_ERR(run_hook_cmd(token, SVN_REPOS__HOOK_PRE_LOCK, hook, args, NULL,
+                           pool));
     }
 
   return SVN_NO_ERROR;
@@ -602,8 +652,8 @@
       args[3] = NULL;
       args[4] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_POST_LOCK, hook, args, stdin_handle,
-                           pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_LOCK, hook, args,
+                           stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }
@@ -639,7 +689,7 @@
       args[5] = break_lock ? "1" : "0";
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_UNLOCK, hook, args, NULL,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_UNLOCK, hook, args, NULL,
                            pool));
     }
 
@@ -676,7 +726,7 @@
       args[3] = NULL;
       args[4] = NULL;
 
-      SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_POST_UNLOCK, hook, args,
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_UNLOCK, hook, args,
                            stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
=== subversion/libsvn_repos/repos.c
==================================================================
--- subversion/libsvn_repos/repos.c	(revision 32395)
+++ subversion/libsvn_repos/repos.c	(local)
@@ -540,6 +540,11 @@
 "#   [4] COMMENT      (the comment of the lock)"                             NL
 "#   [5] STEAL-LOCK   (1 if the user is trying to steal the lock, else 0)"   NL
 "#"                                                                          NL
+"# If the hook program outputs anything in stdout, the output string will"   NL
+"# be used as the lock token for this lock operation.  If you choose to use" NL
+"# this feature, you must guarantee the tokens generated are unique each."   NL
+"# time."                                                                    NL
+"#"                                                                          NL
 "# The default working directory for the invocation is undefined, so"        NL
 "# the program should set one explicitly if it cares."                       NL
 "#"                                                                          NL
=== subversion/libsvn_repos/repos.h
==================================================================
--- subversion/libsvn_repos/repos.h	(revision 32395)
+++ subversion/libsvn_repos/repos.h	(local)
@@ -223,10 +223,12 @@
    PATH is the path being locked, USERNAME is the person doing it,
    COMMENT is the comment of the lock, and is treated as an empty
    string when NULL is given.  STEAL-LOCK is a flag if the user is
-   stealing the lock.  */
+   stealing the lock.  If TOKEN is returned by the hook, it will be
+   used as the token for this lock. */
 
 svn_error_t *
 svn_repos__hooks_pre_lock(svn_repos_t *repos,
+                          const char **token,
                           const char *path,
                           const char *username,
                           const char *comment,
