Index: subversion/libsvn_subr/constructors.c
===================================================================
--- subversion/libsvn_subr/constructors.c (revision 16776)
+++ subversion/libsvn_subr/constructors.c (working copy)
@@ -47,6 +47,8 @@
dst_commit_info->author = src_commit_info->author
? apr_pstrdup (pool, src_commit_info->author) : NULL;
dst_commit_info->revision = src_commit_info->revision;
+ dst_commit_info->post_commit_err = src_commit_info->post_commit_err
+ ? apr_pstrdup (pool, src_commit_info->post_commit_err) : NULL;
return dst_commit_info;
}
Index: subversion/mod_dav_svn/merge.c
===================================================================
--- subversion/mod_dav_svn/merge.c (revision 16776)
+++ subversion/mod_dav_svn/merge.c (working copy)
@@ -29,6 +29,7 @@
#include "svn_props.h"
#include "dav_svn.h"
+#include "svn_xml.h"
/* #################################################################
@@ -200,6 +201,7 @@
dav_error * dav_svn__merge_response(ap_filter_t *output,
const dav_svn_repos *repos,
svn_revnum_t new_rev,
+ char *post_commit_err,
apr_xml_elem *prop_elem,
svn_boolean_t disable_merge_response,
apr_pool_t *pool)
@@ -210,6 +212,8 @@
const char *vcc;
const char *rev;
svn_string_t *creationdate, *creator_displayname;
+ const char *post_commit_err_elem = NULL,
+ *post_commit_header_info = NULL;
serr = svn_fs_revision_root(&root, repos->fs, new_rev, pool);
if (serr != NULL)
@@ -231,6 +235,24 @@
/* the version-name of the baseline is the revision number */
rev = apr_psprintf(pool, "%ld", new_rev);
+ /* get the post-commit hook stderr, if any */
+ if (post_commit_err)
+ {
+ post_commit_header_info = apr_psprintf (pool,
+ " xmlns:S=\"%s\"",
+ SVN_XML_NAMESPACE);
+ post_commit_err_elem = apr_psprintf (pool,
+ "%s"
+ "",
+ post_commit_err);
+ }
+ else
+ {
+ post_commit_header_info = "" ;
+ post_commit_err_elem = "" ;
+ }
+
+
/* get the creationdate and creator-displayname of the new revision, too. */
serr = svn_fs_revision_prop(&creationdate, repos->fs, new_rev,
SVN_PROP_REVISION_DATE, pool);
@@ -252,7 +274,9 @@
(void) ap_fputstrs(output, bb,
DAV_XML_HEADER DEBUG_CR
- "" DEBUG_CR
+ "" DEBUG_CR
"" DEBUG_CR
/* generate a response for the new baseline */
@@ -264,7 +288,8 @@
/* ### this is wrong. it's a VCC, not a baseline. but
### we need to tell the client to look at *this*
### resource for the version-name. */
- "" DEBUG_CR
+ "" DEBUG_CR,
+ post_commit_err_elem, DEBUG_CR
"", rev, "" DEBUG_CR,
NULL);
if (creationdate)
Index: subversion/mod_dav_svn/dav_svn.h
===================================================================
--- subversion/mod_dav_svn/dav_svn.h (revision 16776)
+++ subversion/mod_dav_svn/dav_svn.h (working copy)
@@ -507,6 +507,7 @@
dav_error * dav_svn__merge_response(ap_filter_t *output,
const dav_svn_repos *repos,
svn_revnum_t new_rev,
+ char *post_commit_err,
apr_xml_elem *prop_elem,
svn_boolean_t disable_merge_response,
apr_pool_t *pool);
Index: subversion/mod_dav_svn/version.c
===================================================================
--- subversion/mod_dav_svn/version.c (revision 16776)
+++ subversion/mod_dav_svn/version.c (working copy)
@@ -1614,6 +1614,7 @@
svn_fs_txn_t *txn;
const char *conflict;
svn_error_t *serr;
+ char *post_commit_err = NULL;
svn_revnum_t new_rev;
apr_hash_t *locks;
svn_boolean_t disable_merge_response = FALSE;
@@ -1694,7 +1695,11 @@
return dav_svn_convert_err(serr, HTTP_CONFLICT, msg, pool);
}
else if (serr)
- svn_error_clear(serr);
+ {
+ if (serr->child->message)
+ post_commit_err = apr_pstrdup (pool, serr->child->message);
+ svn_error_clear(serr);
+ }
/* Commit was successful, so schedule deltification. */
register_deltification_cleanup(source->info->repos->repos, new_rev,
@@ -1740,7 +1745,8 @@
/* process the response for the new revision. */
return dav_svn__merge_response(output, source->info->repos, new_rev,
- prop_elem, disable_merge_response, pool);
+ post_commit_err, prop_elem,
+ disable_merge_response, pool);
}
const dav_hooks_vsn dav_svn_hooks_vsn = {
Index: subversion/clients/cmdline/util.c
===================================================================
--- subversion/clients/cmdline/util.c (revision 16776)
+++ subversion/clients/cmdline/util.c (working copy)
@@ -53,10 +53,20 @@
svn_cl__print_commit_info (svn_commit_info_t *commit_info,
apr_pool_t *pool)
{
- if ((commit_info)
- && (SVN_IS_VALID_REVNUM (commit_info->revision)))
- SVN_ERR (svn_cmdline_printf (pool, _("\nCommitted revision %ld.\n"),
+ if (commit_info)
+ {
+ if (SVN_IS_VALID_REVNUM (commit_info->revision))
+ SVN_ERR (svn_cmdline_printf (pool, _("\nCommitted revision %ld.\n"),
commit_info->revision));
+
+ /* Writing to stdout, as there maybe systems that consider the
+ * presence of stderr as an indication of commit failure.
+ * OTOH, this is only of informational nature to the user as
+ * the commit has succeeded. */
+ if (commit_info->post_commit_err)
+ SVN_ERR (svn_cmdline_printf (pool, _("\nWarning:%s\n"),
+ commit_info->post_commit_err));
+ }
return SVN_NO_ERROR;
}
Index: subversion/tests/clients/cmdline/commit_tests.py
===================================================================
--- subversion/tests/clients/cmdline/commit_tests.py (revision 16776)
+++ subversion/tests/clients/cmdline/commit_tests.py (working copy)
@@ -1955,6 +1955,47 @@
os.path.join(wc_dir, 'A', 'yu'))
+#----------------------------------------------------------------------
+# Test if the post-commit error message is returned back to the svn
+# client and is displayed as a warning.
+#
+def post_commit_hook_test(sbox):
+ "post commit hook failure case testing"
+
+ sbox.build()
+
+ # Get paths to the working copy and repository
+ wc_dir = sbox.wc_dir
+ repo_dir = sbox.repo_dir
+
+ # Setup the hook configs to echo data back
+ post_commit_hook = svntest.main.get_post_commit_hook_path (repo_dir)
+ svntest.main.file_append (post_commit_hook,
+ """#!/bin/sh
+ echo "Post-commit Hook says nothing doing on stderr" > /dev/stderr
+ exit -1
+ """)
+ os.chmod (post_commit_hook, 0755)
+
+ # Modify iota just so there is something to commit.
+ iota_path = os.path.join (wc_dir, "iota")
+ svntest.main.file_append (iota_path, "lakalakalakalaka")
+
+ # Now, commit and examine the output (we happen to know that the
+ # filesystem will report an absolute path because that's the way the
+ # filesystem is created by this test suite.
+ expected_output = [ "Sending "+ iota_path + "\n",
+ "Transmitting file data .\n",
+ "Committed revision 2.\n",
+ "\n",
+ "Warning:'post-commit' hook failed with error output:\n",
+ "Post-commit Hook says nothing doing on stderr\n",
+ "\n"]
+
+ svntest.actions.run_and_verify_svn (None, expected_output, [],
+ 'ci', '-m', 'log msg', iota_path)
+
+
########################################################################
# Run the tests
@@ -1994,6 +2035,7 @@
mods_in_schedule_delete,
Skip(tab_test, (os.name != 'posix' or sys.platform == 'cygwin')),
local_mods_are_not_commits,
+ post_commit_hook_test
]
if __name__ == '__main__':
Index: subversion/libsvn_repos/hooks.c
===================================================================
--- subversion/libsvn_repos/hooks.c (revision 16776)
+++ subversion/libsvn_repos/hooks.c (working copy)
@@ -297,7 +297,7 @@
args[2] = apr_psprintf (pool, "%ld", rev);
args[3] = NULL;
- SVN_ERR (run_hook_cmd ("post-commit", hook, args, FALSE, NULL, pool));
+ SVN_ERR (run_hook_cmd ("post-commit", hook, args, TRUE, NULL, pool));
}
return SVN_NO_ERROR;
Index: subversion/libsvn_repos/commit.c
===================================================================
--- subversion/libsvn_repos/commit.c (revision 16776)
+++ subversion/libsvn_repos/commit.c (working copy)
@@ -664,6 +664,7 @@
svn_revnum_t new_revision = SVN_INVALID_REVNUM;
svn_error_t *err;
const char *conflict;
+ char *post_commit_err = NULL;
/* If no transaction has been created (ie. if open_root wasn't
called before close_edit), abort the operation here with an
@@ -702,12 +703,13 @@
}
else if (err)
{
- /* ### TODO: ra_local is the only RA layer that currently
- understands SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED. And as of
- at least r12960, svn_repos_fs_commit_txn() would never return
- that anyway. If someone who knows ra_svn better can add
- handling for this special case, this whole "else if" block
- can go away (again). */
+ /* Post-commit hook's failure output can be passed back to the
+ client. However, this cannot be a commit failure. Hence
+ passing back the post-commit error message as a string to
+ be displayed as a warning. */
+ if (err->child->message)
+ post_commit_err = apr_pstrdup (pool, err->child->message) ;
+
svn_error_clear(err);
err = SVN_NO_ERROR;
}
@@ -738,6 +740,7 @@
commit_info->revision = new_revision;
commit_info->date = date ? date->data : NULL;
commit_info->author = author ? author->data : NULL;
+ commit_info->post_commit_err = post_commit_err;
err2 = (*eb->commit_callback) (commit_info,
eb->commit_callback_baton,
pool);
Index: subversion/libsvn_ra_svn/client.c
===================================================================
--- subversion/libsvn_ra_svn/client.c (revision 16776)
+++ subversion/libsvn_ra_svn/client.c (working copy)
@@ -870,10 +870,12 @@
svn_commit_info_t *commit_info = svn_create_commit_info (ccb->pool);
SVN_ERR(handle_auth_request(ccb->sess_baton, ccb->pool));
- SVN_ERR(svn_ra_svn_read_tuple(ccb->sess_baton->conn, ccb->pool, "r(?c)(?c)",
- &(commit_info->revision),
- &(commit_info->date),
- &(commit_info->author)));
+ SVN_ERR(svn_ra_svn_read_tuple(ccb->sess_baton->conn, ccb->pool,
+ "r(?c)(?c)(?c)",
+ &(commit_info->revision),
+ &(commit_info->date),
+ &(commit_info->author),
+ &(commit_info->post_commit_err)));
return ccb->callback(commit_info, ccb->callback_baton, ccb->pool);
Index: subversion/libsvn_ra_dav/merge.c
===================================================================
--- subversion/libsvn_ra_dav/merge.c (revision 16776)
+++ subversion/libsvn_ra_dav/merge.c (working copy)
@@ -58,6 +58,8 @@
{ "DAV:", "collection", ELEM_collection, 0 },
{ "DAV:", "baseline", ELEM_baseline, 0 },
{ "DAV:", "version-name", ELEM_version_name, SVN_RA_DAV__XML_CDATA },
+ { SVN_XML_NAMESPACE, "post-commit-err",
+ ELEM_post_commit_err, SVN_RA_DAV__XML_CDATA },
{ "DAV:", "creationdate", ELEM_creationdate, SVN_RA_DAV__XML_CDATA },
{ "DAV:", "creator-displayname", ELEM_creator_displayname,
SVN_RA_DAV__XML_CDATA },
@@ -104,6 +106,8 @@
svn_stringbuf_t *committed_date; /* DAV:creationdate for this resource */
svn_stringbuf_t *last_author; /* DAV:creator-displayname for this
resource */
+ svn_stringbuf_t *post_commit_err;/* SVN_XML_NAMESPACE:post-commit hook's
+ stderr */
/* We only invoke set_prop() on targets listed in valid_targets.
Some entities (such as directories that have had changes
@@ -136,7 +140,6 @@
/* Easy check: if path itself is in the hash, then it's legit. */
if (apr_hash_get (valid_targets, path, APR_HASH_KEY_STRING))
return TRUE;
-
/* Otherwise, this path is bumpable IFF one of its parents is in the
hash and marked with a 'recursion' flag. */
parent_path = svn_stringbuf_create (path, pool);
@@ -341,6 +344,7 @@
|| child == ELEM_version_name
|| child == ELEM_creationdate
|| child == ELEM_creator_displayname
+ || child == ELEM_post_commit_err
/* other props */)
return SVN_RA_DAV__XML_VALID;
else
@@ -524,6 +528,10 @@
svn_stringbuf_set(mc->vsn_name, cdata);
break;
+ case ELEM_post_commit_err:
+ svn_stringbuf_set(mc->post_commit_err, cdata);
+ break;
+
case ELEM_creationdate:
svn_stringbuf_set(mc->committed_date, cdata);
break;
@@ -656,6 +664,7 @@
svn_revnum_t *new_rev,
const char **committed_date,
const char **committed_author,
+ const char **post_commit_err,
svn_ra_dav__session_t *ras,
const char *repos_url,
const char *activity_url,
@@ -686,6 +695,8 @@
mc.vsn_url = MAKE_BUFFER(pool);
mc.committed_date = MAKE_BUFFER(pool);
mc.last_author = MAKE_BUFFER(pool);
+ if (post_commit_err)
+ mc.post_commit_err = MAKE_BUFFER(pool);
if (disable_merge_response
|| (! keep_locks))
@@ -749,6 +760,9 @@
if (committed_author)
*committed_author = mc.last_author->len
? apr_pstrdup(pool, mc.last_author->data) : NULL;
+ if (post_commit_err)
+ *post_commit_err = mc.post_commit_err->len
+ ? apr_pstrdup(pool, mc.post_commit_err->data) : NULL;
svn_pool_destroy(mc.scratchpool);
Index: subversion/libsvn_ra_dav/ra_dav.h
===================================================================
--- subversion/libsvn_ra_dav/ra_dav.h (revision 16776)
+++ subversion/libsvn_ra_dav/ra_dav.h (working copy)
@@ -665,6 +665,7 @@
ELEM_updated_set,
ELEM_vcc,
ELEM_version_name,
+ ELEM_post_commit_err,
ELEM_error,
/* SVN elements */
@@ -719,6 +720,7 @@
svn_revnum_t *new_rev,
const char **committed_date,
const char **committed_author,
+ const char **post_commit_err,
svn_ra_dav__session_t *ras,
const char *repos_url,
const char *activity_url,
Index: subversion/libsvn_ra_dav/commit.c
===================================================================
--- subversion/libsvn_ra_dav/commit.c (revision 16776)
+++ subversion/libsvn_ra_dav/commit.c (working copy)
@@ -1465,6 +1465,7 @@
SVN_ERR( svn_ra_dav__merge_activity(&(commit_info->revision),
&(commit_info->date),
&(commit_info->author),
+ &(commit_info->post_commit_err),
cc->ras,
cc->ras->root.path,
cc->activity_url,
Index: subversion/svnserve/serve.c
===================================================================
--- subversion/svnserve/serve.c (revision 16776)
+++ subversion/svnserve/serve.c (working copy)
@@ -68,6 +68,7 @@
svn_revnum_t *new_rev;
const char **date;
const char **author;
+ const char **post_commit_err;
} commit_callback_baton_t;
typedef struct {
@@ -796,6 +797,8 @@
? apr_pstrdup(ccb->pool, commit_info->date): NULL;
*ccb->author = commit_info->author
? apr_pstrdup(ccb->pool, commit_info->author) : NULL;
+ *ccb->post_commit_err = commit_info->post_commit_err
+ ? apr_pstrdup(ccb->pool, commit_info->post_commit_err) : NULL;
return SVN_NO_ERROR;
}
@@ -899,7 +902,10 @@
apr_array_header_t *params, void *baton)
{
server_baton_t *b = baton;
- const char *log_msg, *date, *author;
+ const char *log_msg = NULL,
+ *date = NULL,
+ *author = NULL,
+ *post_commit_err = NULL;
apr_array_header_t *lock_tokens;
svn_boolean_t keep_locks;
const svn_delta_editor_t *editor;
@@ -936,6 +942,7 @@
ccb.new_rev = &new_rev;
ccb.date = &date;
ccb.author = &author;
+ ccb.post_commit_err = &post_commit_err;
/* ### Note that svn_repos_get_commit_editor actually wants a decoded URL. */
SVN_CMD_ERR(svn_repos_get_commit_editor4
(&editor, &edit_baton, b->repos, NULL,
@@ -961,8 +968,8 @@
if (! keep_locks && lock_tokens)
SVN_ERR(unlock_paths(lock_tokens, b, pool));
- SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "r(?c)(?c)",
- new_rev, date, author));
+ SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "r(?c)(?c)(?c)",
+ new_rev, date, author, post_commit_err));
if (! b->tunnel)
SVN_ERR(svn_fs_deltify_revision(b->fs, new_rev, pool));