http://subversion.tigris.org/issues/show_bug.cgi?id=3085
The issue is that when a pre-revprop-change hook fails mod_dav_svn
runs the hook a second time but with a different property change.
This means that the message returned to the user doesn't contain the
correct hook error output.
The reason for this is that mod_dav has a rollback mechanism. When a
reprop is changed mod_dav first calls mod_dav_svn to setup for
rollback, then it calls mod_dav_svn a second time to make the change,
and if the change fails it calls mod_dav_svn a third time to rollback
the change.
If I patch mod_dav_svn to make the rollback into a no-op then I get
the expected behaviour, the hook runs once and the change succeeds or
fails. It also fixes the problem that when a post-revprop-change
hook fails it reverts the successful change.
There is however one problem: the message returned to the client no
longer contains the hook output. This is because when mod_dav_svn
returns an the hook error to mod_dav then mod_dav creates it's own
generic PROPPATCH failed error and returns that to the user. Before I
made rollback a no-op the rollback could return an error that was
generated after mod_dav's generic PROPPATCH error and that gets
returned to thwe client.
I can be sneaky and work around this. When the hook fails mod_dav_svn
can cache the error, and then when rollback gets invoked the cached
error can be returned even though rollback is otherwise a no-op.
What do people think? I suppose the proper solution is to change
mod_dav to return Subversion's error but then users would need to
coordinate upgrades to both mod_dav_svn and mod_dav.
Proof of principle patch:
Index: subversion/mod_dav_svn/deadprops.c
===================================================================
--- subversion/mod_dav_svn/deadprops.c (revision 947740)
+++ subversion/mod_dav_svn/deadprops.c (working copy)
@@ -218,6 +218,8 @@
db->authz_read_func,
db->authz_read_baton,
resource->pool);
+ if (serr)
+ resource->info->revprop_error = svn_error_dup(serr);
/* Tell the logging subsystem about the revprop change. */
dav_svn__operational_log(resource->info,
@@ -681,12 +683,20 @@
static dav_error *
db_apply_rollback(dav_db *db, dav_deadprop_rollback *rollback)
{
+#if 0
if (rollback->value.data == NULL)
{
return db_remove(db, &rollback->name);
}
return save_value(db, &rollback->name, &rollback->value);
+#endif
+ db->props = NULL;
+ if (db->resource->info->revprop_error)
+ return dav_svn__convert_err(db->resource->info->revprop_error,
+ HTTP_INTERNAL_SERVER_ERROR, NULL,
+ db->resource->pool);
+ return NULL;
}
Index: subversion/mod_dav_svn/dav_svn.h
===================================================================
--- subversion/mod_dav_svn/dav_svn.h (revision 947740)
+++ subversion/mod_dav_svn/dav_svn.h (working copy)
@@ -271,6 +271,8 @@
interface (ie: /path/to/item?p=PEGREV]? */
svn_boolean_t pegged;
+ svn_error_t *revprop_error;
+
/* Pool to allocate temporary data from */
apr_pool_t *pool;
};
--
Philip
Received on 2010-05-24 22:37:26 CEST