Author: rhuijben
Date: Sun Apr 20 14:46:42 2014
New Revision: 1588772
URL: http://svn.apache.org/r1588772
Log:
Implement an initial fix for issue #4480. As noted in the code this patch
might make this code report out of date in a few cases where we should allow
a commit, but this is much safer than not reporting out of date where we
should.
As far as I can tell this check matches how we do things in the repos/fs
commit api, so I hope somebody with more knowledge of these apis can
confirm that this is the right fix to close issue #4480.
* subversion/mod_dav_svn/repos.c
(do_out_of_date_check): Implement an additional out of date check for
directory changes to catch the issue #4480 problem.
* subversion/tests/cmdline/commit_tests.py
(commit_mergeinfo_ood): Remove XFail marker.
Modified:
subversion/trunk/subversion/mod_dav_svn/repos.c
subversion/trunk/subversion/tests/cmdline/commit_tests.py
Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1588772&r1=1588771&r2=1588772&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Sun Apr 20 14:46:42 2014
@@ -1791,18 +1791,113 @@ do_out_of_date_check(dav_resource_combin
"Could not get created rev of "
"resource", r->pool);
- if (comb->priv.version_name < created_rev)
+ if (SVN_IS_VALID_REVNUM(created_rev))
{
- serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL,
- comb->res.collection
- ? "Directory '%s' is out of date"
- : (comb->res.exists
- ? "File '%s' is out of date"
- : "'%s' is out of date"),
- comb->priv.repos_path);
- return dav_svn__convert_err(serr, HTTP_CONFLICT,
- "Attempting to modify out-of-date resource.",
+ if (comb->priv.version_name < created_rev)
+ {
+ serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL,
+ comb->res.collection
+ ? "Directory '%s' is out of date"
+ : (comb->res.exists
+ ? "File '%s' is out of date"
+ : "'%s' is out of date"),
+ comb->priv.repos_path);
+ return dav_svn__convert_err(serr, HTTP_CONFLICT,
+ "Attempting to modify out-of-date
resource.",
+ r->pool);
+ }
+ }
+ else if (SVN_IS_VALID_REVNUM(comb->priv.version_name)
+ && comb->res.collection)
+ {
+ /* Issue #4480: With HTTPv2 we can receive the first change for a
+ directory after it has been made mutable, because one of its
+ descendants was changed before changing the directory.
+
+ We have to check if whatever the node is in HEAD is equivalent
+ to what it was in the provided BASE revision.
+
+ If the node was copied, we would process it before its decendants
+ and we already performed quite a few checks when making it mutable
+ via its descendant, so what we should really check here is if the
+ properties changed since the BASE version.
+
+ ### I think svn_fs_node_relation() checks for more changes than we
+ should check for here. Needs further review. But it looks like\
+ this check matches the checks in the libsvn_fs commit editor.
+
+ For now I would say reporting out of date in a few too many
+ cases is safer than not reporting out of date when we should.
+ */
+ svn_revnum_t youngest;
+ svn_fs_root_t *youngest_root;
+ svn_fs_root_t *rev_root;
+ svn_fs_node_relation_t node_relation;
+
+ serr = svn_fs_youngest_rev(&youngest, comb->res.info->repos->fs,
+ r->pool);
+ if (serr != NULL)
+ {
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Could not determine the youngest "
+ "revision for verification against "
+ "the baseline being checked out",
+ r->pool);
+ }
+
+ if (comb->priv.version_name == youngest)
+ return NULL; /* Easy out: we commit against HEAD */
+
+ serr = svn_fs_revision_root(&youngest_root, comb->res.info->repos->fs,
+ youngest, r->pool);
+
+ if (serr != NULL)
+ {
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Could not open youngest revision root "
+ "for verification against the base "
+ "revision", r->pool);
+ }
+
+ serr = svn_fs_revision_root(&rev_root, comb->res.info->repos->fs,
+ comb->priv.version_name, r->pool);
+
+ if (serr != NULL)
+ {
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Could not open the base revision"
+ "for verification against the youngest "
+ "revision", r->pool);
+ }
+
+ serr = svn_fs_node_relation(&node_relation, rev_root,
+ comb->priv.repos_path,
+ youngest_root,
+ comb->priv.repos_path,
r->pool);
+
+ svn_fs_close_root(rev_root);
+ svn_fs_close_root(youngest_root);
+
+ if (serr != NULL)
+ {
+ /* ### correct HTTP error? */
+ return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+ "Unable to fetch the node revision id "
+ "of the version resource within the "
+ "revision",
+ r->pool);
+ }
+
+ if (node_relation != svn_fs_node_same)
+ {
+ serr = svn_error_createf(SVN_ERR_RA_OUT_OF_DATE, NULL,
+ "Directory '%s' is out of date",
+ comb->priv.repos_path);
+ return dav_svn__convert_err(serr, HTTP_CONFLICT,
+ "Attempting to modify out-of-date
resource.",
+ r->pool);
+ }
}
return NULL;
Modified: subversion/trunk/subversion/tests/cmdline/commit_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/commit_tests.py?rev=1588772&r1=1588771&r2=1588772&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/commit_tests.py Sun Apr 20
14:46:42 2014
@@ -3072,7 +3072,6 @@ def commit_deep_deleted(sbox):
sbox.ospath('A'))
@Issue(4480)
-@XFail(svntest.main.is_ra_type_dav)
def commit_mergeinfo_ood(sbox):
"commit of mergeinfo that should cause out of date"