Index: subversion/include/svn_repos.h =================================================================== --- subversion/include/svn_repos.h (revision 22620) +++ subversion/include/svn_repos.h (working copy) @@ -336,6 +336,18 @@ const char *svn_repos_post_revprop_change_hook(svn_repos_t *repos, apr_pool_t *pool); +/** Return the path to @a repos's hook execution helper, allocated in + * @a pool. + */ +const char *svn_repos_hook_helper_path(svn_repos_t *repos, apr_pool_t *pool); + +/** Set the path to @a repos's hook execution helper, allocated in + * @a pool. + */ +void svn_repos_set_hook_helper_path(svn_repos_t *repos, + const char *hook_helper_path, + apr_pool_t *pool); + /** @defgroup svn_repos_lock_hooks paths to lock hooks * @{ Index: subversion/mod_dav_svn/mod_dav_svn.c =================================================================== --- subversion/mod_dav_svn/mod_dav_svn.c (revision 22620) +++ subversion/mod_dav_svn/mod_dav_svn.c (working copy) @@ -67,6 +67,7 @@ enum conf_flag list_parentpath; /* whether to allow GET of parentpath */ const char *root_dir; /* our top-level directory */ const char *master_uri; /* URI to the master SVN repos */ + const char *hook_helper_path; /* path to hook helper */ } dir_conf_t; @@ -162,6 +163,7 @@ newconf->autoversioning = INHERIT_VALUE(parent, child, autoversioning); newconf->do_path_authz = INHERIT_VALUE(parent, child, do_path_authz); newconf->list_parentpath = INHERIT_VALUE(parent, child, list_parentpath); + newconf->hook_helper_path = INHERIT_VALUE(parent, child, hook_helper_path); /* Prefer our parent's value over our new one - hence the swap. */ newconf->root_dir = INHERIT_VALUE(child, parent, root_dir); @@ -306,6 +308,17 @@ } +static const char * +SVNHookHelperPath_cmd(cmd_parms *cmd, void *config, const char *arg1) +{ + dir_conf_t *conf = config; + + conf->hook_helper_path = apr_pstrdup(cmd->pool, arg1); + + return NULL; +} + + /** Accessor functions for the module's configuration state **/ const char * @@ -454,6 +467,16 @@ } +const char * +dav_svn__get_hook_helper_path(request_rec *r) +{ + dir_conf_t *conf; + + conf = ap_get_module_config(r->per_dir_config, &dav_svn_module); + return conf->hook_helper_path; +} + + static void merge_xml_filter_insert(request_rec *r) { @@ -619,6 +642,10 @@ AP_INIT_TAKE1("SVNMasterURI", SVNMasterURI_cmd, NULL, ACCESS_CONF, "specifies a URI to access a master Subversion repository"), + /* per directory/location */ + AP_INIT_TAKE1("SVNHookHelperPath", SVNHookHelperPath_cmd, NULL, ACCESS_CONF, + "specify the path to a hook execution helper"), + { NULL } }; Index: subversion/mod_dav_svn/dav_svn.h =================================================================== --- subversion/mod_dav_svn/dav_svn.h (revision 22620) +++ subversion/mod_dav_svn/dav_svn.h (working copy) @@ -93,6 +93,9 @@ /* The URI of the XSL transform for directory indexes */ const char *xslt_uri; + /* The path to the hook helper */ + const char *hook_helper_path; + /* Whether autoversioning is active for this repository. */ svn_boolean_t autoversioning; @@ -298,6 +301,9 @@ /* Return the root directory */ const char * dav_svn__get_root_dir(request_rec *r); +/* Return the hook helper path */ +const char * dav_svn__get_hook_helper_path(request_rec *r); + /*** activity.c ***/ /* activity functions for looking up, storing, and deleting Index: subversion/mod_dav_svn/repos.c =================================================================== --- subversion/mod_dav_svn/repos.c (revision 22620) +++ subversion/mod_dav_svn/repos.c (working copy) @@ -1221,6 +1221,7 @@ comb->priv.repos = repos; repos->pool = r->pool; repos->xslt_uri = dav_svn__get_xslt_uri(r); + repos->hook_helper_path = dav_svn__get_hook_helper_path(r); repos->autoversioning = dav_svn__get_autoversioning_flag(r); repos->base_url = ap_construct_url(r->pool, "", r); repos->special_uri = dav_svn__get_special_uri(r); @@ -1434,6 +1435,7 @@ const char *fs_path; const char *repo_name; const char *xslt_uri; + const char *hook_helper_path; const char *fs_parent_path; dav_resource_combined *comb; dav_svn_repos *repos; @@ -1452,6 +1454,7 @@ repo_name = dav_svn__get_repo_name(r); xslt_uri = dav_svn__get_xslt_uri(r); + hook_helper_path = dav_svn__get_hook_helper_path(r); fs_parent_path = dav_svn__get_fs_parent_path(r); /* Special case: detect and build the SVNParentPath as a unique type @@ -1569,6 +1572,9 @@ /* An XSL transformation */ repos->xslt_uri = xslt_uri; + /* Path to hook execution helper */ + repos->hook_helper_path = hook_helper_path; + /* Is autoversioning active in this repos? */ repos->autoversioning = dav_svn__get_autoversioning_flag(r); @@ -1605,6 +1611,15 @@ HTTP_INTERNAL_SERVER_ERROR, r); } + /* Set the hook helper path for later use. */ + if (repos->hook_helper_path != NULL && + repos->hook_helper_path[0] != '\0') + { + svn_repos_set_hook_helper_path(repos->repos, + repos->hook_helper_path, + r->connection->pool); + } + /* Cache the open repos for the next request on this connection */ apr_pool_userdata_set(repos->repos, repos_key, NULL, r->connection->pool); Index: subversion/libsvn_repos/hooks.c =================================================================== --- subversion/libsvn_repos/hooks.c (revision 22620) +++ subversion/libsvn_repos/hooks.c (working copy) @@ -153,6 +153,7 @@ static svn_error_t * run_hook_cmd(const char *name, const char *cmd, + const char *hook_helper_path, const char **args, apr_file_t *stdin_handle, apr_pool_t *pool) @@ -162,6 +163,35 @@ apr_status_t apr_err; svn_error_t *err; apr_proc_t cmd_proc; + apr_size_t args_arr_size = 0, i; + const char **new_args; + + if (hook_helper_path) + { + /* Find number of elements in args array. */ + while (args[args_arr_size] != NULL) + args_arr_size++; + + /* Allocate memory for the new_args string array plus one for the hook + * helper, plus one for the ending null element. */ + new_args = apr_palloc(pool, (sizeof(char *) * args_arr_size + 2)); + + new_args[0] = hook_helper_path; + + for (i = 0; args[i] != NULL; i++) + { + new_args[i+1] = args[i]; + } + + /* Make the last element in the array a NULL pointer as required + * by spawn. */ + new_args[i] = NULL; + } + else + { + /* Pass args through unchanged */ + new_args = args; + } /* Create a pipe to access stderr of the child. */ apr_err = apr_file_pipe_create(&read_errhandle, &write_errhandle, pool); @@ -240,7 +270,7 @@ int fd_map[3], stderr_pipe[2], exitcode; svn_stringbuf_t *script_output = svn_stringbuf_create("", pool); pid_t child_pid, wait_rv; - apr_size_t args_arr_size = 0, i; + apr_size_t args_arr_size = 0, i, j; struct inheritance xmp_inherit = {0}; #pragma convert(0) /* Despite the UTF support in V5R4 a few functions still require @@ -253,21 +283,30 @@ while (args[args_arr_size] != NULL) args_arr_size++; - /* Allocate memory for the native_args string array plus one for - * the ending null element. */ - native_args = apr_palloc(pool, sizeof(char *) * args_arr_size + 1); + /* Allocate memory for the native_args string array plus one for the hook + * helper if appropriate, plus one for the ending null element. */ + native_args = apr_palloc(pool, (sizeof(char *) * args_arr_size + + (hook_helper_path!=NULL ? 1 : 0) + 1)); /* Convert UTF-8 args to EBCDIC for use by spawn(). */ - for (i = 0; args[i] != NULL; i++) + j = 0; + if (hook_helper_path) { + SVN_ERR(svn_utf_cstring_from_utf8_ex2((const char**)(&(native_args[j])), + hook_helper_path, (const char *)0, + pool)); + j++; + } + + for (i = 0; args[i] != NULL; i++, j++) { - SVN_ERR(svn_utf_cstring_from_utf8_ex2((const char**)(&(native_args[i])), + SVN_ERR(svn_utf_cstring_from_utf8_ex2((const char**)(&(native_args[j])), args[i], (const char *)0, pool)); } /* Make the last element in the array a NULL pointer as required * by spawn. */ - native_args[args_arr_size] = NULL; + native_args[j] = NULL; /* Map stdin. */ if (stdin_handle) @@ -528,7 +567,8 @@ args[2] = user ? user : ""; args[3] = NULL; - SVN_ERR(run_hook_cmd("start-commit", hook, args, NULL, pool)); + SVN_ERR(run_hook_cmd("start-commit", hook, repos->hook_helper_path, + args, NULL, pool)); } return SVN_NO_ERROR; @@ -556,7 +596,8 @@ args[2] = txn_name; args[3] = NULL; - SVN_ERR(run_hook_cmd("pre-commit", hook, args, NULL, pool)); + SVN_ERR(run_hook_cmd("pre-commit", hook, repos->hook_helper_path, + args, NULL, pool)); } return SVN_NO_ERROR; @@ -584,7 +625,8 @@ args[2] = apr_psprintf(pool, "%ld", rev); args[3] = NULL; - SVN_ERR(run_hook_cmd("post-commit", hook, args, NULL, pool)); + SVN_ERR(run_hook_cmd("post-commit", hook, repos->hook_helper_path, + args, NULL, pool)); } return SVN_NO_ERROR; @@ -631,8 +673,8 @@ args[5] = action_string; args[6] = NULL; - SVN_ERR(run_hook_cmd("pre-revprop-change", hook, args, stdin_handle, - pool)); + SVN_ERR(run_hook_cmd("pre-revprop-change", hook, repos->hook_helper_path, + args, stdin_handle, pool)); SVN_ERR(svn_io_file_close(stdin_handle, pool)); } @@ -693,8 +735,8 @@ args[5] = action_string; args[6] = NULL; - SVN_ERR(run_hook_cmd("post-revprop-change", hook, args, stdin_handle, - pool)); + SVN_ERR(run_hook_cmd("post-revprop-change", hook, repos->hook_helper_path, + args, stdin_handle, pool)); SVN_ERR(svn_io_file_close(stdin_handle, pool)); } @@ -727,7 +769,8 @@ args[3] = username; args[4] = NULL; - SVN_ERR(run_hook_cmd("pre-lock", hook, args, NULL, pool)); + SVN_ERR(run_hook_cmd("pre-lock", hook, repos->hook_helper_path, + args, NULL, pool)); } return SVN_NO_ERROR; @@ -763,7 +806,8 @@ args[3] = NULL; args[4] = NULL; - SVN_ERR(run_hook_cmd("post-lock", hook, args, stdin_handle, pool)); + SVN_ERR(run_hook_cmd("post-lock", hook, repos->hook_helper_path, + args, stdin_handle, pool)); SVN_ERR(svn_io_file_close(stdin_handle, pool)); } @@ -795,7 +839,8 @@ args[3] = username ? username : ""; args[4] = NULL; - SVN_ERR(run_hook_cmd("pre-unlock", hook, args, NULL, pool)); + SVN_ERR(run_hook_cmd("pre-unlock", hook, repos->hook_helper_path, + args, NULL, pool)); } return SVN_NO_ERROR; @@ -831,7 +876,8 @@ args[3] = NULL; args[4] = NULL; - SVN_ERR(run_hook_cmd("post-unlock", hook, args, stdin_handle, pool)); + SVN_ERR(run_hook_cmd("post-unlock", hook, repos->hook_helper_path, + args, stdin_handle, pool)); SVN_ERR(svn_io_file_close(stdin_handle, pool)); } Index: subversion/libsvn_repos/repos.c =================================================================== --- subversion/libsvn_repos/repos.c (revision 22620) +++ subversion/libsvn_repos/repos.c (working copy) @@ -154,6 +154,19 @@ pool); } +const char * +svn_repos_hook_helper_path(svn_repos_t *repos, apr_pool_t *pool) +{ + return apr_pstrdup(pool, repos->hook_helper_path); +} + +void +svn_repos_set_hook_helper_path(svn_repos_t *repos, const char *hook_helper_path, + apr_pool_t *pool) +{ + repos->hook_helper_path = apr_pstrdup(pool, hook_helper_path); +} + static svn_error_t * create_repos_dir(const char *path, apr_pool_t *pool) @@ -1559,7 +1572,7 @@ /* Allocate and return a new svn_repos_t * object, initializing the directory pathname members based on PATH. The members FS, FORMAT, and FS_TYPE are *not* initialized (they are null), - and it it the caller's responsibility to fill them in if needed. */ + and it is the caller's responsibility to fill them in if needed. */ static svn_repos_t * create_svn_repos_t(const char *path, apr_pool_t *pool) { @@ -1571,6 +1584,7 @@ repos->conf_path = svn_path_join(path, SVN_REPOS__CONF_DIR, pool); repos->hook_path = svn_path_join(path, SVN_REPOS__HOOK_DIR, pool); repos->lock_path = svn_path_join(path, SVN_REPOS__LOCK_DIR, pool); + /* repos->hook_helper_path = NULL; */ return repos; } Index: subversion/libsvn_repos/repos.h =================================================================== --- subversion/libsvn_repos/repos.h (revision 22620) +++ subversion/libsvn_repos/repos.h (working copy) @@ -115,6 +115,9 @@ /* The path to the Berkeley DB filesystem environment. */ char *db_path; + /* The path to the hook execution helper. */ + char *hook_helper_path; + /* The format number of this repository. */ int format;