Author: rhuijben
Date: Fri Jan 25 23:38:05 2013
New Revision: 1438767
URL: http://svn.apache.org/viewvc?rev=1438767&view=rev
Log:
Resolve issue #3405, by making the merge code properly install pristine
properties for directories added by the merge. Before this patch the pristine
properties list of such a directory would be empty while the repository would
assume it had the list like before the 'copy'. The commit would then just
commit the property changes as if the directory was really changed.
* subversion/include/private/svn_wc_private.h
(svn_wc__complete_directory_add): New function.
* subversion/libsvn_client/merge.c
(merge_dir_props_changed): For an added directory the properties should be
installed, not processed as incomming property changes.
* subversion/libsvn_wc/update_editor.c
(svn_wc__complete_directory_add): New function. Using the infrastructure
also used by the update editor and svn_wc_add_repos_file4() to process
entry properties in what the wc_db api expects.
* subversion/tests/cmdline/merge_tests.py
(no_self_referential_filtering_on_added_path,
merge_with_added_subtrees_with_mergeinfo ): Mark now Failing tests as
work in progress, until the needed changes are carefully reviewed.
(merge_properties_on_adds): Remove XFail marker.
Modified:
subversion/trunk/subversion/include/private/svn_wc_private.h
subversion/trunk/subversion/libsvn_client/merge.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/tests/cmdline/merge_tests.py
Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1438767&r1=1438766&r2=1438767&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Fri Jan 25
23:38:05 2013
@@ -1834,6 +1834,26 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
void *notify_baton,
apr_pool_t *scratch_pool);
+
+/* During merge when we encounter added directories, we add them using
+ svn_wc_add4(), recording its original location, etc. But at that time
+ we don't have its original properties. This function allows updating the
+ BASE properties of such a special added node, but only before it receives
+ other changes.
+
+ NEW_ORIGINAL_PROPS is a new set of properties, including entry props that
+ will be applied to LOCAL_ABSPATH as pristine properties.
+
+ The copyfrom_* arguments are used to verify (some of) the assumptions of
+ this function */
+svn_error_t *
+svn_wc__complete_directory_add(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_hash_t *new_original_props,
+ const char *copyfrom_url,
+ svn_revnum_t copyfrom_rev,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1438767&r1=1438766&r2=1438767&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Fri Jan 25 23:38:05 2013
@@ -1461,6 +1461,62 @@ merge_dir_props_changed(svn_wc_notify_st
return SVN_NO_ERROR; /* We can't do a real prop merge for added dirs */
}
+ if (dir_was_added && merge_b->same_repos)
+ {
+ /* When the directory was added in merge_dir_added() we didn't update its
+ pristine properties. Instead we receive the property changes later and
+ apply them in this function.
+
+ If we would apply them as changes (such as before fixing issue #3405),
+ we would see the unmodified properties as local changes, and the
+ pristine properties would be out of sync with what the repository
+ expects for this directory.
+
+ Instead of doing that we now simply set the properties as the pristine
+ properties via a private libsvn_wc api.
+ */
+
+ const char *copyfrom_url;
+ svn_revnum_t copyfrom_rev;
+ const char *parent_abspath;
+ const char *child;
+
+ /* Creating a hash containing regular and entry props */
+ apr_hash_t *new_pristine_props = svn_prop__patch(original_props,
propchanges,
+ scratch_pool);
+
+ parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ child = svn_dirent_is_child(merge_b->target->abspath, local_abspath,
NULL);
+ SVN_ERR_ASSERT(child != NULL);
+
+ copyfrom_url =
svn_path_url_add_component2(merge_b->merge_source.loc2->url,
+ child, scratch_pool);
+ copyfrom_rev = merge_b->merge_source.loc2->rev;
+
+ SVN_ERR(check_repos_match(merge_b->target, parent_abspath, copyfrom_url,
+ scratch_pool));
+
+ if (!merge_b->dry_run)
+ {
+ SVN_ERR(svn_wc__complete_directory_add(merge_b->ctx->wc_ctx,
+ local_abspath,
+ new_pristine_props,
+ copyfrom_url, copyfrom_rev,
+ scratch_pool));
+ }
+ *state = svn_wc_notify_state_changed; /* same as merge_props did */
+
+ /* Until issue #3405 was fixed the code for changed directories was
+ used for directory deletions, which made use apply svn:mergeinfo as if
+ additional changes were applied by the merge, which really weren't.
+
+ ### I wouldn't be surprised if we somehow relied on these for correct
+ ### merges, but in this case the fix added here should also be applied
+ ### for added files! */
+
+ return SVN_NO_ERROR;
+ }
+
SVN_ERR(prepare_merge_props_changed(&props, local_abspath, propchanges,
merge_b, scratch_pool, scratch_pool));
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1438767&r1=1438766&r2=1438767&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Jan 25 23:38:05
2013
@@ -5278,3 +5278,90 @@ svn_wc_add_repos_file4(svn_wc_context_t
cancel_func, cancel_baton,
pool));
}
+
+svn_error_t *
+svn_wc__complete_directory_add(svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_hash_t *new_original_props,
+ const char *copyfrom_url,
+ svn_revnum_t copyfrom_rev,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_status_t status;
+ svn_kind_t kind;
+ const char *original_repos_relpath;
+ const char *original_root_url;
+ const char *original_uuid;
+ svn_boolean_t had_props;
+ svn_boolean_t props_mod;
+
+ svn_revnum_t original_revision;
+ svn_revnum_t changed_rev;
+ apr_time_t changed_date;
+ const char *changed_author;
+
+ SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ &original_repos_relpath, &original_root_url,
+ &original_uuid, &original_revision, NULL, NULL,
+ NULL, NULL, NULL, NULL, &had_props, &props_mod,
+ NULL, NULL, NULL,
+ wc_ctx->db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ if (status != svn_wc__db_status_added
+ || kind != svn_kind_dir
+ || had_props
+ || props_mod
+ || !original_repos_relpath)
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+ _("'%s' is not an unmodified copied directory"),
+ svn_dirent_local_style(local_abspath, scratch_pool));
+ }
+ if (original_revision != copyfrom_rev
+ || strcmp(copyfrom_url,
+ svn_path_url_add_component2(original_root_url,
+ original_repos_relpath,
+ scratch_pool)))
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_COPYFROM_PATH_NOT_FOUND, NULL,
+ _("Copyfrom '%s' doesn't match original location of '%s'"),
+ copyfrom_url,
+ svn_dirent_local_style(local_abspath, scratch_pool));
+ }
+
+ {
+ apr_array_header_t *regular_props;
+ apr_array_header_t *entry_props;
+
+ SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(new_original_props,
+ scratch_pool),
+ &entry_props, NULL, ®ular_props,
+ scratch_pool));
+
+ /* Put regular props back into a hash table. */
+ new_original_props = svn_prop_array_to_hash(regular_props, scratch_pool);
+
+ /* Get the change_* info from the entry props. */
+ SVN_ERR(accumulate_last_change(&changed_rev,
+ &changed_date,
+ &changed_author,
+ entry_props, scratch_pool, scratch_pool));
+ }
+
+ return svn_error_trace(
+ svn_wc__db_op_copy_dir(wc_ctx->db, local_abspath,
+ new_original_props,
+ changed_rev, changed_date, changed_author,
+ original_repos_relpath, original_root_url,
+ original_uuid, original_revision,
+ NULL /* children */,
+ FALSE /* is_move */,
+ svn_depth_infinity,
+ NULL /* conflict */,
+ NULL /* work_items */,
+ scratch_pool));
+}
Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=1438767&r1=1438766&r2=1438767&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Fri Jan 25
23:38:05 2013
@@ -13888,6 +13888,7 @@ def subtree_gets_changes_even_if_ultimat
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
+@Wimp("Needs review after issue #3405 fix")
def no_self_referential_filtering_on_added_path(sbox):
"no self referential filtering on added path"
@@ -17654,6 +17655,7 @@ def merge_adds_then_deletes_subtree(sbox
# cause spurious subtree mergeinfo'.
@SkipUnless(server_has_mergeinfo)
@Issue(4169)
+@Wimp("Needs review after issue #3405 fix")
def merge_with_added_subtrees_with_mergeinfo(sbox):
"merge with added subtrees with mergeinfo"
@@ -18098,7 +18100,7 @@ def merge_target_selection(sbox):
svntest.actions.run_and_verify_svn(None, expected_output, [],
'merge', '^/dir', '-c', '4',
'binary-file')
-@XFail()
+@Issue(3405)
def merge_properties_on_adds(sbox):
"merged directory properties are added"