Reintegrate the 1.7.x-issue3976 branch to 1.7.x:
* r1161683, r1161721
Fix issue #3976 "record-only merges which add new subtree mergeinfo don't
record mergeinfo describing merge".
Justification:
Avoid repeat merges and possible spurious conflicts in merges subsequent
to a --record-only merge which adds mergeinfo to a subtree which had no
explicit mergeinfo prior to the merge. Ok, that's a mouthful, to put it
more succinctly: A --record-only merge of revision X should block future
merges of revision X, but that wasn't happening here.
Notes:
r1161683 is a new test for this issue and r1161721 is the fix.
Branch:
^/subversion/branches/1.7.x-issue3976
Votes:
+1: pburba, stsp, philip
git-svn-id: https://svn.apache.org/repos/asf/subversion/branches/1.7.x@1165398 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES b/CHANGES
index b8df254..5012b4d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -41,6 +41,7 @@
* make server-side network data compression rate configurable (r1072288)
* added support for auto-detecting mime-types with libmagic (r1131120)
* 'svn rm url1 url2 url3' uses single txn per repo (issue #1199)
+ * don't leave unversioned files when reverting copies (issue #3101)
- Client-side bugfixes:
* 'svn cp A B; svn mv B C' is equivalent to 'svn cp A C' (issue #756)
@@ -82,6 +83,9 @@
* 'svn delete --force' removes tree conflicts (issue #3805)
* don't throw an error when skipping tree conflicts in update (issue #3329)
* don't break commits of wc->wc copies with file externals (issue #3589)
+ * allow 'svn info' to work on symlinks to working copies (issue #2305)
+ * allow 'svn st --show-updates' to work across symlinks (issue #3117)
+ * 'svn revert' shouldn't loop on symlinks (issue #3972)
* fixed: wc-to-wc copy of a switch source (issue #1802)
* fixed: 'svn st' reports symlinks as obstructed items (issue #2284)
* fixed: 'cd e:\; svn up e:\' fails (issue #2556)
@@ -123,6 +127,9 @@
* fixed: spurious prop conflict with 'merge --reintegrate' (issue #3919)
* fixed: 'svn --version' fails with non-existant $HOME (issue #3947)
* fixed: unforced export silently overwites existing file (issue #3799)
+ * fixed: reverse merge which adds subtree mergeinfo fails (issue #3978)
+ * fixed: 'svn up -r{R>HEAD}' hangs client over ra_svn (issue #3963)
+ * fixed: 'svn up' updates file externals in target siblings (issue #3819)
* many other minor bugfixes, optimizations, plugs of memory leaks, etc
- Server-side bugfixes:
@@ -143,6 +150,7 @@
* svnserve can now force usernames to upper/lower case (issue #3726)
* reduce duplicate log messages in 'log -g' (issue #3650)
* don't crash on shutdown with SASL in inetd mode (issue #3664)
+ * disallow arbitrary HTTP headers from committers (issue #2872)
* many other minor bugfixes too numerous to list here
- Other tool improvements and bugfixes:
@@ -172,7 +180,9 @@
* notifications sent when mergeinfo changes (r877588)
* add information on text and property mods in log APIs (r877688)
* fixed: svn_ra_local__get_file() leaks file descriptors (issue #3290)
+ * svn_ra_neon__get_dir() returns correct dir set for URLs (issue #3093)
* swig-py: always set ChangedPath.path (issue #2630)
+ * improve conflict resolver API for a specific direction (issue #3049)
- Bindings:
* New JavaHL package: org.apache.subversion
diff --git a/STATUS b/STATUS
index 390046c..a35f282 100644
--- a/STATUS
+++ b/STATUS
@@ -40,6 +40,7 @@
Votes:
+1: arfrever
-0: stsp (we can backport these when we need to)
+ -0: gstein
* r1154278, r1154379, r1154382
Make 'svn ls' capable of listing Subversion 1.0-1.3 repositories using
@@ -58,12 +59,92 @@
Votes:
+1: rhuijben, cmpilato
- * r1159400
- Document a neat trick to better handle patch rejects in 'svn help patch'.
+ * r1147299, r1162974, r1162995
+ Fix issue #3867 'reintegrate merges create mergeinfo for non-existent
+ paths' and issue #3961 'reintegrate merge of replaced source produces
+ inaccurate mergeinfo'.
Justification:
- Might save a poor soul from lots of manual copy-paste/editing some day.
+ Avoid potential confusion which can occur when a reintegrate merge
+ sets mergeinfo (to describe the merge) which contains non-existent
+ path-revs, other lines of history, and/or valid path-revs which were
+ never merged.
+ Notes:
+ r1147299 and r1162995 is the addition and tweak of a test for
+ issue #3961. A test already existed for issue #3867 prior to branching
+ 1.7.x. r1162974 is the fix for both issues.
Votes:
- +1: stsp, rhuijben
+ +1: pburba, stsp
+
+ * r1163243, r1163383
+ Fix issue #3791 'svn mergeinfo shows natural history of added subtrees
+ as eligible'.
+ Justification:
+ The 'svn mergeinfo [ -R | --depth [ files | immediates | infinity ] ]'
+ subcommand gives incorrect answers in some use cases.
+ Notes:
+ r1163243 is a test for the issue, r1163383 is the fix.
+ Votes:
+ +1: pburba
+
+ * r1163557
+ Relax wcng consistency checks for file externals.
+ Justification:
+ Debug build claims wcng DB is inconsistent when it is OK.
+ Branch:
+ 1.7.x-r1163557
+ Votes:
+ +1: philip
+
+ * r1164386
+ Avoid an expensive database operation in 'svn info'.
+ Justification:
+ Improves performance of 'svn info' on a single unmodified node by 20-30%, by
+ moving an in most cases unneeded database call in the error handling.
+ Votes:
+ +1: rhuijben
+ +1: gstein (for 1.7.1)
+
+ * r1164426,r1164614
+ Fix STMT_SELECT_NODE_CHILDREN_WALKER_INFO for correctness and speed.
+ Justification:
+ Recursive info and propset don't scale well with large working copies
+ and may possibly act on the wrong nodes.
+ On a Linux machine with a Subversion trunk working copy on a local disk
+ running 'svn info --depth infinity' shows it to be 2 or 3 times faster.
+ On a larger working copy it's orders of magnitude faster.
+ Votes:
+ +1: philip
+ +0: peters, gstein (looks correct, but I didn't test, and while
+ performance should be better, I wonder if that's
+ been tested at all)
+
+ * r1164645
+ Fix issue #3999 'svn merge with bad option or target segfaults'.
+ Justification:
+ Command line merge with too many targets and/or a bad option
+ (no leading '-') results in a segfault without this fix.
+ Votes:
+ +1: pburba, philip
+
+ * branches/1.7.x-issue4000
+ Fix issue #4000 'WC-WC-copy of file external creates first-class file node'
+ and don't break file external state when committing a file external.
+ Justification:
+ Inconsistency. Can create collisions between externals definitions and
+ versioned nodes.
+ r1164027 is included since it inadvertently fixes the re-appearance of
+ issue #4000 on a file external that has been committed.
+ Notes:
+ Since r1164027 prevents the NODES table's FILE_EXTERNAL column from
+ being blanked out during commit bumping, it probably fixes a number of
+ other problems with committed file externals that I'm not aware of ATM.
+ Conflicts:
+ C externals_tests.py
+ branches/1.7.x-issue4000@ 1164785 1164786 1164792
+ are clean versions of trunk@ 1164027 1164760 1164765
+ and are the: corner case fix^ main fix^ ^test
+ Votes:
+ +1: neels
Veto-blocked changes:
=====================
diff --git a/subversion/libsvn_client/merge.c b/subversion/libsvn_client/merge.c
index efc5f42..513cbf9 100644
--- a/subversion/libsvn_client/merge.c
+++ b/subversion/libsvn_client/merge.c
@@ -7705,6 +7705,7 @@
&& (!merge_b->record_only || merge_b->reintegrate_merge)
&& (!is_rollback))
{
+ svn_error_t *err;
svn_opt_revision_t peg_revision;
svn_mergeinfo_t subtree_history_as_mergeinfo;
apr_array_header_t *child_merge_src_rangelist;
@@ -7727,26 +7728,40 @@
merge_b->ra_session2,
subtree_mergeinfo_url,
iterpool));
- SVN_ERR(svn_client__get_history_as_mergeinfo(
+ err = svn_client__get_history_as_mergeinfo(
&subtree_history_as_mergeinfo, NULL,
subtree_mergeinfo_url, &peg_revision,
MAX(merged_range->start, merged_range->end),
MIN(merged_range->start, merged_range->end),
- merge_b->ra_session2, merge_b->ctx, iterpool));
+ merge_b->ra_session2, merge_b->ctx, iterpool);
+
+ /* If CHILD is a subtree it may have been deleted prior to
+ MERGED_RANGE->END so the above call to get its history
+ will fail. */
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
+ return svn_error_trace(err);
+ svn_error_clear(err);
+ }
+ else
+ {
+ child_merge_src_rangelist = apr_hash_get(
+ subtree_history_as_mergeinfo,
+ child_merge_src_canon_path,
+ APR_HASH_KEY_STRING);
+ SVN_ERR(svn_rangelist_intersect(&child_merge_rangelist,
+ child_merge_rangelist,
+ child_merge_src_rangelist,
+ FALSE, iterpool));
+ if (!rangelist_inheritance)
+ svn_rangelist__set_inheritance(child_merge_rangelist,
+ FALSE);
+ }
if (old_session_url)
SVN_ERR(svn_ra_reparent(merge_b->ra_session2,
old_session_url, iterpool));
- child_merge_src_rangelist = apr_hash_get(
- subtree_history_as_mergeinfo,
- child_merge_src_canon_path,
- APR_HASH_KEY_STRING);
- SVN_ERR(svn_rangelist_intersect(&child_merge_rangelist,
- child_merge_rangelist,
- child_merge_src_rangelist,
- FALSE, iterpool));
- if (!rangelist_inheritance)
- svn_rangelist__set_inheritance(child_merge_rangelist, FALSE);
}
apr_hash_set(child_merges, child->abspath, APR_HASH_KEY_STRING,
diff --git a/subversion/libsvn_client/patch.c b/subversion/libsvn_client/patch.c
index 989caa6..445952d 100644
--- a/subversion/libsvn_client/patch.c
+++ b/subversion/libsvn_client/patch.c
@@ -2471,8 +2471,15 @@
target->added = TRUE;
}
- /* Attempt to set the property, and reject all hunks if this fails. */
- prop_val = svn_stringbuf__morph_into_string(prop_target->patched_value);
+ /* Attempt to set the property, and reject all hunks if this
+ fails. If the property had a non-empty value, but now has
+ an empty one, we'll just delete the property altogether. */
+ if (prop_target->value && prop_target->value->len
+ && prop_target->patched_value && !prop_target->patched_value->len)
+ prop_val = NULL;
+ else
+ prop_val = svn_stringbuf__morph_into_string(prop_target->patched_value);
+
if (dry_run)
{
const svn_string_t *canon_propval;
@@ -2891,7 +2898,7 @@
btn->ctx, btn->dry_run,
iterpool));
- if (target->has_prop_changes)
+ if (target->has_prop_changes && (!target->deleted))
SVN_ERR(install_patched_prop_targets(target, btn->ctx,
btn->dry_run,
iterpool));
diff --git a/subversion/libsvn_ra_serf/update.c b/subversion/libsvn_ra_serf/update.c
index 07c33f1..da1c71b 100644
--- a/subversion/libsvn_ra_serf/update.c
+++ b/subversion/libsvn_ra_serf/update.c
@@ -1604,9 +1604,11 @@
SVN_ERR(open_dir(info->dir));
- SVN_ERR(ctx->update_editor->absent_directory(file_name,
- info->dir->dir_baton,
- info->dir->pool));
+ SVN_ERR(ctx->update_editor->absent_directory(
+ svn_relpath_join(info->name, file_name,
+ info->dir->pool),
+ info->dir->dir_baton,
+ info->dir->pool));
}
else if ((state == OPEN_DIR || state == ADD_DIR) &&
strcmp(name.name, "absent-file") == 0)
@@ -1627,9 +1629,11 @@
SVN_ERR(open_dir(info->dir));
- SVN_ERR(ctx->update_editor->absent_file(file_name,
- info->dir->dir_baton,
- info->dir->pool));
+ SVN_ERR(ctx->update_editor->absent_file(
+ svn_relpath_join(info->name, file_name,
+ info->dir->pool),
+ info->dir->dir_baton,
+ info->dir->pool));
}
else if (state == OPEN_DIR || state == ADD_DIR)
{
diff --git a/subversion/libsvn_repos/dump.c b/subversion/libsvn_repos/dump.c
index f8b07ad..ca23809 100644
--- a/subversion/libsvn_repos/dump.c
+++ b/subversion/libsvn_repos/dump.c
@@ -385,7 +385,7 @@
pool,
_("Referencing data in revision %ld,"
" which is older than the oldest"
- " dumped revision (%ld). Loading this dump"
+ " dumped revision (r%ld). Loading this dump"
" into an empty repository"
" will fail."),
cmp_rev, eb->oldest_dumped_rev);
@@ -489,7 +489,7 @@
notify->warning_str = apr_psprintf(
pool,
_("Mergeinfo referencing revision(s) prior "
- "to the oldest dumped revision (%ld). "
+ "to the oldest dumped revision (r%ld). "
"Loading this dump may result in invalid "
"mergeinfo."),
eb->oldest_dumped_rev);
diff --git a/subversion/libsvn_wc/entries.c b/subversion/libsvn_wc/entries.c
index 1d842b0..9ef1ec1 100644
--- a/subversion/libsvn_wc/entries.c
+++ b/subversion/libsvn_wc/entries.c
@@ -892,12 +892,15 @@
switch (cd->kind)
{
case svn_wc_conflict_kind_text:
- entry->conflict_old = svn_dirent_basename(cd->base_abspath,
- result_pool);
- entry->conflict_new = svn_dirent_basename(cd->their_abspath,
- result_pool);
- entry->conflict_wrk = svn_dirent_basename(cd->my_abspath,
- result_pool);
+ if (cd->base_abspath)
+ entry->conflict_old = svn_dirent_basename(cd->base_abspath,
+ result_pool);
+ if (cd->their_abspath)
+ entry->conflict_new = svn_dirent_basename(cd->their_abspath,
+ result_pool);
+ if (cd->my_abspath)
+ entry->conflict_wrk = svn_dirent_basename(cd->my_abspath,
+ result_pool);
break;
case svn_wc_conflict_kind_property:
entry->prejfile = svn_dirent_basename(cd->their_abspath,
diff --git a/subversion/libsvn_wc/merge.c b/subversion/libsvn_wc/merge.c
index 17fb554..3f48896 100644
--- a/subversion/libsvn_wc/merge.c
+++ b/subversion/libsvn_wc/merge.c
@@ -1037,7 +1037,7 @@
}
if (*merge_outcome == svn_wc_merge_merged)
- return SVN_NO_ERROR;
+ goto done;
}
else if (contains_conflicts && dry_run)
*merge_outcome = svn_wc_merge_conflict;
@@ -1074,6 +1074,7 @@
*work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
}
+done:
/* Remove the tempfile after use */
SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
mt->db, result_target,
diff --git a/subversion/svn/info-cmd.c b/subversion/svn/info-cmd.c
index 263e09d..14d0db6 100644
--- a/subversion/svn/info-cmd.c
+++ b/subversion/svn/info-cmd.c
@@ -417,20 +417,26 @@
switch (conflict->kind)
{
case svn_wc_conflict_kind_text:
- SVN_ERR(svn_cmdline_printf(pool,
- _("Conflict Previous Base File: %s\n"),
- svn_dirent_local_style(conflict->base_abspath,
- pool)));
+ if (conflict->base_abspath)
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("Conflict Previous Base File: %s\n"),
+ svn_cl__local_style_skip_ancestor(
+ path_prefix, conflict->base_abspath,
+ pool)));
- SVN_ERR(svn_cmdline_printf(pool,
- _("Conflict Previous Working File: %s\n"),
- svn_dirent_local_style(conflict->my_abspath,
- pool)));
+ if (conflict->my_abspath)
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("Conflict Previous Working File: %s\n"),
+ svn_cl__local_style_skip_ancestor(
+ path_prefix, conflict->my_abspath,
+ pool)));
- SVN_ERR(svn_cmdline_printf(pool,
- _("Conflict Current Base File: %s\n"),
- svn_dirent_local_style(conflict->their_abspath,
- pool)));
+ if (conflict->their_abspath)
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("Conflict Current Base File: %s\n"),
+ svn_cl__local_style_skip_ancestor(
+ path_prefix, conflict->their_abspath,
+ pool)));
break;
case svn_wc_conflict_kind_property:
diff --git a/subversion/svn/main.c b/subversion/svn/main.c
index f1cc45a..c17240a 100644
--- a/subversion/svn/main.c
+++ b/subversion/svn/main.c
@@ -1006,6 +1006,13 @@
" for deletion. If the patch creates a new file, that file is scheduled\n"
" for addition. Use 'svn revert' to undo deletions and additions you\n"
" do not agree with.\n"
+ "\n"
+ " Hint: If the patch file was created with Subversion, it will contain\n"
+ " the number of a revision N the patch will cleanly apply to\n"
+ " (look for lines like \"--- foo/bar.txt (revision N)\").\n"
+ " To avoid rejects, first update to the revision N using \n"
+ " 'svn update -r N', apply the patch, and then update back to the\n"
+ " HEAD revision. This way, conflicts can be resolved interactively.\n"
),
{'q', opt_dry_run, opt_strip, opt_reverse_diff,
opt_ignore_whitespace} },
@@ -1384,7 +1391,7 @@
{ "upgrade", svn_cl__upgrade, {0}, N_
("Upgrade the metadata storage format for a working copy.\n"
- "usage: upgrade WCPATH...\n"
+ "usage: upgrade [WCPATH...]\n"
"\n"
" Local modifications are preserved.\n"),
{ 'q' } },
diff --git a/subversion/tests/cmdline/info_tests.py b/subversion/tests/cmdline/info_tests.py
index 86a56bb..aa1c924 100755
--- a/subversion/tests/cmdline/info_tests.py
+++ b/subversion/tests/cmdline/info_tests.py
@@ -482,6 +482,42 @@
'svn: E200009: Could not display info for all targets.*',
'info', iota)
+@Issue(3998)
+def binary_tree_conflict(sbox):
+ "svn info shouldn't crash on conflict"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_propset('svn:mime-type', 'binary/octet-stream', 'iota')
+ sbox.simple_commit()
+
+ iota = sbox.ospath('iota')
+
+ svntest.main.file_write(iota, 'something-else')
+ sbox.simple_commit()
+
+ svntest.main.file_write(iota, 'third')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(status='C '),
+ })
+ expected_status = svntest.wc.State(iota, {
+ '' : Item(status='C ', wc_rev='2')
+ })
+ svntest.actions.run_and_verify_update(iota,
+ expected_output, None, expected_status,
+ None, None, None, None, None, False,
+ iota, '-r', '2')
+
+ expected_info = [{
+ 'Path' : '%s' % re.escape(iota),
+ 'Conflict Previous Base File' : re.escape(iota + '.r3'),
+ 'Conflict Current Base File' : re.escape(iota + '.r2'),
+ }]
+ svntest.actions.run_and_verify_info(expected_info, iota)
+
+
+
########################################################################
# Run the tests
@@ -496,6 +532,7 @@
info_multiple_targets,
info_repos_root_url,
info_show_exclude,
+ binary_tree_conflict,
]
if __name__ == '__main__':
diff --git a/subversion/tests/cmdline/patch_tests.py b/subversion/tests/cmdline/patch_tests.py
index 2c9a588..29a4583 100755
--- a/subversion/tests/cmdline/patch_tests.py
+++ b/subversion/tests/cmdline/patch_tests.py
@@ -3485,6 +3485,193 @@
1) # dry-run
+@Issue(4003)
+def patch_deletes_prop(sbox):
+ "patch deletes prop, directly and via reversed add"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ patch_file_path = make_patch_path(sbox)
+ iota_path = os.path.join(wc_dir, 'iota')
+
+ svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+ iota_path)
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Sending'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('iota', wc_rev=2)
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+
+ # Apply patch
+ unidiff_patch = [
+ "Index: iota\n",
+ "===================================================================\n",
+ "--- iota\t(revision 1)\n",
+ "+++ iota\t(working copy)\n",
+ "\n",
+ "Property changes on: iota\n",
+ "___________________________________________________________________\n",
+ "Deleted: propname\n",
+ "## -1 +0,0 ##\n",
+ "-propvalue\n",
+ ]
+ svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+ # Expect the original state of the working copy in r1, exception
+ # that iota is at r2 now.
+ expected_disk = svntest.main.greek_state.copy()
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('iota', status=' M')
+ expected_status.tweak('iota', wc_rev=2)
+ expected_skip = wc.State('', { })
+ expected_output = [
+ ' U %s\n' % os.path.join(wc_dir, 'iota'),
+ ]
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, # expected err
+ 1, # check-props
+ 0) # dry-run
+
+ # Revert any local mods, then try to reverse-apply a patch which
+ # *adds* the property.
+ svntest.main.run_svn(None, 'revert', iota_path)
+
+ # Apply patch
+ unidiff_patch = [
+ "Index: iota\n",
+ "===================================================================\n",
+ "--- iota\t(revision 1)\n",
+ "+++ iota\t(working copy)\n",
+ "\n",
+ "Property changes on: iota\n",
+ "___________________________________________________________________\n",
+ "Added: propname\n",
+ "## -0,0 +1 ##\n",
+ "+propvalue\n",
+ ]
+ svntest.main.file_write(patch_file_path, ''.join(unidiff_patch))
+
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, # expected err
+ 1, # check-props
+ 0, # dry-run
+ '--reverse-diff')
+
+@Issue(4004)
+def patch_reversed_add_with_props(sbox):
+ "reverse patch new file+props atop uncommitted"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ patch_file_path = make_patch_path(sbox)
+
+ # Add a new file which also has props set on it.
+ newfile_path = os.path.join(wc_dir, 'newfile')
+ newfile_contents = ["This is the file 'newfile'.\n"]
+ svntest.main.file_write(newfile_path, ''.join(newfile_contents))
+ svntest.main.run_svn(None, 'add', newfile_path)
+ svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+ newfile_path)
+
+ # Generate a patch file from our current diff (rooted at the working
+ # copy root).
+ cwd = os.getcwd()
+ try:
+ os.chdir(wc_dir)
+ exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff')
+ finally:
+ os.chdir(cwd)
+ svntest.main.file_write(patch_file_path, ''.join(diff_output))
+
+ # Okay, now commit up.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'newfile' : Item(verb='Adding'),
+ })
+
+ # Now, we'll try to reverse-apply the very diff we just created. We
+ # expect the original state of the working copy in r1.
+ expected_disk = svntest.main.greek_state.copy()
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_skip = wc.State('', { })
+ expected_output = [
+ 'D %s\n' % newfile_path,
+ ]
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, # expected err
+ 1, # check-props
+ 0, # dry-run
+ '--reverse-diff')
+
+@Issue(4004)
+def patch_reversed_add_with_props2(sbox):
+ "reverse patch new file+props"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ patch_file_path = make_patch_path(sbox)
+
+ # Add a new file which also has props set on it.
+ newfile_path = os.path.join(wc_dir, 'newfile')
+ newfile_contents = ["This is the file 'newfile'.\n"]
+ svntest.main.file_write(newfile_path, ''.join(newfile_contents))
+ svntest.main.run_svn(None, 'add', newfile_path)
+ svntest.main.run_svn(None, 'propset', 'propname', 'propvalue',
+ newfile_path)
+
+ # Generate a patch file from our current diff (rooted at the working
+ # copy root).
+ cwd = os.getcwd()
+ try:
+ os.chdir(wc_dir)
+ exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff')
+ finally:
+ os.chdir(cwd)
+ svntest.main.file_write(patch_file_path, ''.join(diff_output))
+
+ # Okay, now commit up.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'newfile' : Item(verb='Adding'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({'newfile' : Item(wc_rev=2, status=' ')})
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+
+ # Now, we'll try to reverse-apply the very diff we just created. We
+ # expect the original state of the working copy in r1 plus 'newfile'
+ # scheduled for deletion.
+ expected_disk = svntest.main.greek_state.copy()
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({'newfile' : Item(status='D ', wc_rev=2)})
+ expected_skip = wc.State('', { })
+ expected_output = [
+ 'D %s\n' % newfile_path,
+ ]
+ svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path),
+ expected_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, # expected err
+ 1, # check-props
+ 0, # dry-run
+ '--reverse-diff')
+
########################################################################
#Run the tests
@@ -3520,6 +3707,9 @@
patch_strip_cwd,
patch_set_prop_no_eol,
patch_add_symlink,
+ patch_deletes_prop,
+ patch_reversed_add_with_props,
+ patch_reversed_add_with_props2,
]
if __name__ == '__main__':