--- subversion/libsvn_repos/fs-wrap.c	(revision 32149)
+++ subversion/libsvn_repos/fs-wrap.c	(local)
@@ -447,7 +447,7 @@ svn_repos_fs_lock(svn_lock_t **lock,
 {
   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,8 +467,9 @@ svn_repos_fs_lock(svn_lock_t **lock,
 
   /* Run pre-lock hook.  This could throw error, preventing
      svn_fs_lock() from happening. */
-  SVN_ERR(svn_repos__hooks_pre_lock(repos, path, username, pool));
-
+  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));
@@ -511,7 +512,8 @@ svn_repos_fs_unlock(svn_repos_t *repos,
 
   /* Run pre-unlock hook.  This could throw error, preventing
      svn_fs_unlock() from happening. */
-  SVN_ERR(svn_repos__hooks_pre_unlock(repos, path, username, pool));
+  SVN_ERR(svn_repos__hooks_pre_unlock(repos, path, username, token,
+                                      break_lock, pool));
 
   /* Unlock. */
   SVN_ERR(svn_fs_unlock(repos->fs, path, token, break_lock, pool));
--- subversion/libsvn_repos/hooks.c	(revision 32149)
+++ subversion/libsvn_repos/hooks.c	(local)
@@ -165,15 +165,18 @@ check_hook_result(const char *name, cons
 
    If STDIN_HANDLE is non-null, pass it as the hook's stdin, else pass
    no stdin to the hook. */
+
 static svn_error_t *
-run_hook_cmd(const char *name,
-             const char *cmd,
-             const char **args,
-             apr_file_t *stdin_handle,
-             apr_pool_t *pool)
+run_hook_cmd2(const char **result,
+              const char *name,
+              const char *cmd,
+              const char **args,
+              apr_file_t *stdin_handle,
+              apr_pool_t *pool)
 #ifndef AS400
 {
   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;
@@ -203,16 +206,37 @@ run_hook_cmd(const char *name,
       (apr_err, _("Can't make pipe write handle non-inherited 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);
+  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);
+
+    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
@@ -223,6 +247,13 @@ run_hook_cmd(const char *name,
     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
@@ -245,6 +276,17 @@ run_hook_cmd(const char *name,
   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;
+  }
+
   return err;
 }
 #else /* Run hooks with spawn() on OS400. */
@@ -464,6 +506,15 @@ run_hook_cmd(const char *name,
 }
 #endif /* AS400 */
 
+static svn_error_t *
+run_hook_cmd(const char *name,
+             const char *cmd,
+             const char **args,
+             apr_file_t *stdin_handle,
+             apr_pool_t *pool)
+{
+  return run_hook_cmd2(NULL, name, cmd, args, stdin_handle, pool);
+}
 
 /* Create a temporary file F that will automatically be deleted when it is
    closed.  Fill it with VALUE, and leave it open and rewound, ready to be
@@ -766,8 +817,11 @@ svn_repos__hooks_post_revprop_change(svn
 
 svn_error_t  *
 svn_repos__hooks_pre_lock(svn_repos_t *repos,
+                          const char **token,
                           const char *path,
                           const char *username,
+                          const char *comment,
+                          svn_boolean_t steal_lock,
                           apr_pool_t *pool)
 {
   const char *hook = svn_repos_pre_lock_hook(repos, pool);
@@ -779,15 +833,17 @@ svn_repos__hooks_pre_lock(svn_repos_t *r
     }
   else if (hook)
     {
-      const char *args[5];
+      const char *args[7];
 
       args[0] = hook;
       args[1] = svn_path_local_style(svn_repos_path(repos, pool), pool);
       args[2] = path;
       args[3] = username;
-      args[4] = NULL;
+      args[4] = comment ? comment : "";
+      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_cmd2(token, SVN_REPOS__HOOK_PRE_LOCK, hook, args, NULL, pool));
     }
 
   return SVN_NO_ERROR;
@@ -837,6 +893,8 @@ svn_error_t  *
 svn_repos__hooks_pre_unlock(svn_repos_t *repos,
                             const char *path,
                             const char *username,
+                            const char *token,
+                            svn_boolean_t break_lock,
                             apr_pool_t *pool)
 {
   const char *hook = svn_repos_pre_unlock_hook(repos, pool);
@@ -848,13 +906,15 @@ svn_repos__hooks_pre_unlock(svn_repos_t 
     }
   else if (hook)
     {
-      const char *args[5];
+      const char *args[7];
 
       args[0] = hook;
       args[1] = svn_path_local_style(svn_repos_path(repos, pool), pool);
       args[2] = path;
       args[3] = username ? username : "";
-      args[4] = NULL;
+      args[4] = token ? token : "";
+      args[5] = break_lock ? "1" : "0";
+      args[6] = NULL;
 
       SVN_ERR(run_hook_cmd(SVN_REPOS__HOOK_PRE_UNLOCK, hook, args, NULL,
                            pool));
--- subversion/libsvn_repos/repos.c	(revision 32149)
+++ subversion/libsvn_repos/repos.c	(local)
@@ -537,6 +537,11 @@ PREWRITTEN_HOOKS_TEXT
 "#   [1] REPOS-PATH   (the path to this repository)"                         NL
 "#   [2] PATH         (the path in the repository about to be locked)"       NL
 "#   [3] USER         (the user creating the lock)"                          NL
+"#   [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"                        NL
 "#"                                                                          NL
 "# The default working directory for the invocation is undefined, so"        NL
 "# the program should set one explicitly if it cares."                       NL
@@ -618,6 +623,8 @@ PREWRITTEN_HOOKS_TEXT
 "#   [1] REPOS-PATH   (the path to this repository)"                         NL
 "#   [2] PATH         (the path in the repository about to be unlocked)"     NL
 "#   [3] USER         (the user destroying the lock)"                        NL
+"#   [4] TOKEN        (the lock token to be destoryed)"                      NL
+"#   [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0)"          NL
 "#"                                                                          NL
 "# The default working directory for the invocation is undefined, so"        NL
 "# the program should set one explicitly if it cares."                       NL
--- subversion/libsvn_repos/repos.h	(revision 32149)
+++ subversion/libsvn_repos/repos.h	(local)
@@ -220,11 +220,16 @@ svn_repos__hooks_post_revprop_change(svn
 /* Run the pre-lock hook for REPOS.  Use POOL for any temporary
    allocations.  If the hook fails, return SVN_ERR_REPOS_HOOK_FAILURE.
 
-   PATH is the path being locked, USERNAME is the person doing it.  */
+   PATH is the path being locked, USERNAME is the person doing it,
+   COMMENT is the comment of the lock, and STEAL-LOCK is a flag if the
+   user is stealing the 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,
+                          svn_boolean_t steal_lock,
                           apr_pool_t *pool);
 
 /* Run the post-lock hook for REPOS.  Use POOL for any temporary
@@ -241,11 +246,15 @@ svn_repos__hooks_post_lock(svn_repos_t *
 /* Run the pre-unlock hook for REPOS.  Use POOL for any temporary
    allocations.  If the hook fails, return SVN_ERR_REPOS_HOOK_FAILURE.
 
-   PATH is the path being unlocked, USERNAME is the person doing it.  */
+   PATH is the path being unlocked, USERNAME is the person doing it,
+   TOKEN is the lock token to be unlocked, and BREAK-LOCK is a flag if
+   the user is breaking the lock.  */
 svn_error_t *
 svn_repos__hooks_pre_unlock(svn_repos_t *repos,
                             const char *path,
                             const char *username,
+                            const char *token,
+                            svn_boolean_t break_lock,
                             apr_pool_t *pool);
 
 /* Run the post-unlock hook for REPOS.  Use POOL for any temporary
