summaryrefslogtreecommitdiff
path: root/subversion/tests/cmdline/diff_tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/cmdline/diff_tests.py')
-rwxr-xr-xsubversion/tests/cmdline/diff_tests.py1617
1 files changed, 1306 insertions, 311 deletions
diff --git a/subversion/tests/cmdline/diff_tests.py b/subversion/tests/cmdline/diff_tests.py
index ac10557..aae8c46 100755
--- a/subversion/tests/cmdline/diff_tests.py
+++ b/subversion/tests/cmdline/diff_tests.py
@@ -26,11 +26,15 @@
######################################################################
# General modules
-import sys, re, os, time, shutil
+import sys, re, os, time, shutil, logging
+
+logger = logging.getLogger()
# Our testing module
import svntest
-from svntest import err
+from svntest import err, wc
+
+from prop_tests import binary_mime_type_on_text_file_warning
# (abbreviation)
Skip = svntest.testcase.Skip_deco
@@ -45,16 +49,28 @@ Item = svntest.wc.StateItem
######################################################################
# Generate expected output
-def make_diff_header(path, old_tag, new_tag):
+def make_diff_header(path, old_tag, new_tag, src_label=None, dst_label=None):
"""Generate the expected diff header for file PATH, with its old and new
- versions described in parentheses by OLD_TAG and NEW_TAG. Return the header
- as an array of newline-terminated strings."""
+ versions described in parentheses by OLD_TAG and NEW_TAG. SRC_LABEL and
+ DST_LABEL are paths or urls that are added to the diff labels if we're
+ diffing against the repository or diffing two arbitrary paths.
+ Return the header as an array of newline-terminated strings."""
+ if src_label:
+ src_label = src_label.replace('\\', '/')
+ src_label = '\t(.../' + src_label + ')'
+ else:
+ src_label = ''
+ if dst_label:
+ dst_label = dst_label.replace('\\', '/')
+ dst_label = '\t(.../' + dst_label + ')'
+ else:
+ dst_label = ''
path_as_shown = path.replace('\\', '/')
return [
"Index: " + path_as_shown + "\n",
"===================================================================\n",
- "--- " + path_as_shown + "\t(" + old_tag + ")\n",
- "+++ " + path_as_shown + "\t(" + new_tag + ")\n",
+ "--- " + path_as_shown + src_label + "\t(" + old_tag + ")\n",
+ "+++ " + path_as_shown + dst_label + "\t(" + new_tag + ")\n",
]
def make_no_diff_deleted_header(path, old_tag, new_tag):
@@ -70,7 +86,8 @@ def make_no_diff_deleted_header(path, old_tag, new_tag):
def make_git_diff_header(target_path, repos_relpath,
old_tag, new_tag, add=False, src_label=None,
dst_label=None, delete=False, text_changes=True,
- cp=False, mv=False, copyfrom_path=None):
+ cp=False, mv=False, copyfrom_path=None,
+ copyfrom_rev=None):
""" Generate the expected 'git diff' header for file TARGET_PATH.
REPOS_RELPATH is the location of the path relative to the repository root.
The old and new versions ("revision X", or "working copy") must be
@@ -93,64 +110,62 @@ def make_git_diff_header(target_path, repos_relpath,
else:
dst_label = ''
+ output = [
+ "Index: " + path_as_shown + "\n",
+ "===================================================================\n"
+ ]
if add:
- output = [
- "Index: " + path_as_shown + "\n",
- "===================================================================\n",
+ output.extend([
"diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
"new file mode 10644\n",
- ]
+ ])
if text_changes:
output.extend([
"--- /dev/null\t(" + old_tag + ")\n",
"+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n"
])
elif delete:
- output = [
- "Index: " + path_as_shown + "\n",
- "===================================================================\n",
+ output.extend([
"diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
"deleted file mode 10644\n",
- ]
+ ])
if text_changes:
output.extend([
"--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
"+++ /dev/null\t(" + new_tag + ")\n"
])
elif cp:
- output = [
- "Index: " + path_as_shown + "\n",
- "===================================================================\n",
+ if copyfrom_rev:
+ copyfrom_rev = '@' + copyfrom_rev
+ else:
+ copyfrom_rev = ''
+ output.extend([
"diff --git a/" + copyfrom_path + " b/" + repos_relpath + "\n",
- "copy from " + copyfrom_path + "\n",
+ "copy from " + copyfrom_path + copyfrom_rev + "\n",
"copy to " + repos_relpath + "\n",
- ]
+ ])
if text_changes:
output.extend([
"--- a/" + copyfrom_path + src_label + "\t(" + old_tag + ")\n",
"+++ b/" + repos_relpath + "\t(" + new_tag + ")\n"
])
elif mv:
- return [
- "Index: " + path_as_shown + "\n",
- "===================================================================\n",
+ output.extend([
"diff --git a/" + copyfrom_path + " b/" + path_as_shown + "\n",
"rename from " + copyfrom_path + "\n",
"rename to " + repos_relpath + "\n",
- ]
+ ])
if text_changes:
output.extend([
"--- a/" + copyfrom_path + src_label + "\t(" + old_tag + ")\n",
"+++ b/" + repos_relpath + "\t(" + new_tag + ")\n"
])
else:
- output = [
- "Index: " + path_as_shown + "\n",
- "===================================================================\n",
+ output.extend([
"diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
"--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
"+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n",
- ]
+ ])
return output
def make_diff_prop_header(path):
@@ -167,7 +182,7 @@ def make_diff_prop_val(plus_minus, pval):
if len(pval) > 0 and pval[-1] != '\n':
return [plus_minus + pval + "\n","\\ No newline at end of property\n"]
return [plus_minus + pval]
-
+
def make_diff_prop_deleted(pname, pval):
"""Return a property diff for deletion of property PNAME, old value PVAL.
PVAL is a single string with no embedded newlines. Return the result
@@ -188,8 +203,14 @@ def make_diff_prop_added(pname, pval):
def make_diff_prop_modified(pname, pval1, pval2):
"""Return a property diff for modification of property PNAME, old value
- PVAL1, new value PVAL2. PVAL is a single string with no embedded
- newlines. Return the result as a list of newline-terminated strings."""
+ PVAL1, new value PVAL2.
+
+ PVAL is a single string with no embedded newlines. A newline at the
+ end is significant: without it, we add an extra line saying '\ No
+ newline at end of property'.
+
+ Return the result as a list of newline-terminated strings.
+ """
return [
"Modified: " + pname + "\n",
"## -1 +1 ##\n",
@@ -274,8 +295,8 @@ def verify_excluded_output(diff_output, excluded):
"verify given line does not exist in diff output as diff line"
for line in diff_output:
if re.match("^(\\+|-)%s" % re.escape(excluded), line):
- print('Sought: %s' % excluded)
- print('Found: %s' % line)
+ logger.warn('Sought: %s' % excluded)
+ logger.warn('Found: %s' % line)
raise svntest.Failure
def extract_diff_path(line):
@@ -645,21 +666,21 @@ def diff_non_recursive(sbox):
# full diff has three changes
exit_code, diff_output, err_output = svntest.main.run_svn(
- None, 'diff', '-r', '1', os.path.join(wc_dir, 'A', 'D'))
+ None, 'diff', '-r', '1', sbox.ospath('A/D'))
if count_diff_output(diff_output) != 3:
raise svntest.Failure
# non-recursive has one change
exit_code, diff_output, err_output = svntest.main.run_svn(
- None, 'diff', '-r', '1', '-N', os.path.join(wc_dir, 'A', 'D'))
+ None, 'diff', '-r', '1', '-N', sbox.ospath('A/D'))
if count_diff_output(diff_output) != 1:
raise svntest.Failure
# diffing a directory doesn't pick up other diffs in the anchor
exit_code, diff_output, err_output = svntest.main.run_svn(
- None, 'diff', '-r', '1', os.path.join(wc_dir, 'A', 'D', 'G'))
+ None, 'diff', '-r', '1', sbox.ospath('A/D/G'))
if count_diff_output(diff_output) != 1:
raise svntest.Failure
@@ -698,10 +719,10 @@ def diff_non_version_controlled_file(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- svntest.main.file_append(os.path.join(wc_dir, 'A', 'D', 'foo'), "a new file")
+ svntest.main.file_append(sbox.ospath('A/D/foo'), "a new file")
exit_code, diff_output, err_output = svntest.main.run_svn(
- 1, 'diff', os.path.join(wc_dir, 'A', 'D', 'foo'))
+ 1, 'diff', sbox.ospath('A/D/foo'))
if count_diff_output(diff_output) != 0: raise svntest.Failure
@@ -842,7 +863,7 @@ def dont_diff_binary_file(sbox):
# Add a binary file to the project.
theta_contents = open(os.path.join(sys.path[0], "theta.bin"), 'rb').read()
# Write PNG file data into 'A/theta'.
- theta_path = os.path.join(wc_dir, 'A', 'theta')
+ theta_path = sbox.ospath('A/theta')
svntest.main.file_write(theta_path, theta_contents, 'wb')
svntest.main.run_svn(None, 'add', theta_path)
@@ -967,7 +988,7 @@ def diff_head_of_moved_file(sbox):
"diff against the head of a moved file"
sbox.build()
- mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
+ mu_path = sbox.ospath('A/mu')
new_mu_path = mu_path + '.new'
svntest.main.run_svn(None, 'mv', mu_path, new_mu_path)
@@ -975,7 +996,21 @@ def diff_head_of_moved_file(sbox):
# Modify the file to ensure that the diff is non-empty.
svntest.main.file_append(new_mu_path, "\nActually, it's a new mu.")
- svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ mu_new = sbox.ospath('A/mu.new').replace('\\','/')
+
+ expected_output = [
+ 'Index: %s\n' % mu_new,
+ '===================================================================\n',
+ '--- %s\t(.../mu)\t(revision 1)\n' % mu_new,
+ '+++ %s\t(.../mu.new)\t(working copy)\n' % mu_new,
+ '@@ -1 +1,3 @@\n',
+ ' This is the file \'mu\'.\n',
+ '+\n',
+ '+Actually, it\'s a new mu.\n',
+ '\ No newline at end of file\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
'diff', '-r', 'HEAD', new_mu_path)
@@ -991,9 +1026,9 @@ def diff_base_to_repos(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(sbox.wc_dir, 'iota')
- newfile_path = os.path.join(sbox.wc_dir, 'A', 'D', 'newfile')
- mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
+ iota_path = sbox.ospath('iota')
+ newfile_path = sbox.ospath('A/D/newfile')
+ mu_path = sbox.ospath('A/mu')
# Make changes to iota, commit r2, update to HEAD (r2).
svntest.main.file_append(iota_path, "some rev2 iota text.\n")
@@ -1191,8 +1226,8 @@ def diff_deleted_in_head(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- A_path = os.path.join(sbox.wc_dir, 'A')
- mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
+ A_path = sbox.ospath('A')
+ mu_path = sbox.ospath('A/mu')
# Make a change to mu, commit r2, update.
svntest.main.file_append(mu_path, "some rev2 mu text.\n")
@@ -1238,6 +1273,7 @@ def diff_deleted_in_head(sbox):
#----------------------------------------------------------------------
+@Issue(2873)
def diff_targets(sbox):
"select diff targets"
@@ -1322,8 +1358,8 @@ def diff_branches(sbox):
svntest.actions.run_and_verify_svn(None, None, [],
'up', sbox.wc_dir)
- A_alpha = os.path.join(sbox.wc_dir, 'A', 'B', 'E', 'alpha')
- A2_alpha = os.path.join(sbox.wc_dir, 'A2', 'B', 'E', 'alpha')
+ A_alpha = sbox.ospath('A/B/E/alpha')
+ A2_alpha = sbox.ospath('A2/B/E/alpha')
svntest.main.file_append(A_alpha, "\nfoo\n")
svntest.actions.run_and_verify_svn(None, None, [],
@@ -1388,8 +1424,8 @@ def diff_repos_and_wc(sbox):
svntest.actions.run_and_verify_svn(None, None, [],
'up', sbox.wc_dir)
- A_alpha = os.path.join(sbox.wc_dir, 'A', 'B', 'E', 'alpha')
- A2_alpha = os.path.join(sbox.wc_dir, 'A2', 'B', 'E', 'alpha')
+ A_alpha = sbox.ospath('A/B/E/alpha')
+ A2_alpha = sbox.ospath('A2/B/E/alpha')
svntest.main.file_append(A_alpha, "\nfoo\n")
svntest.actions.run_and_verify_svn(None, None, [],
@@ -1403,7 +1439,7 @@ def diff_repos_and_wc(sbox):
# Compare working file on one branch against repository file on
# another branch
- A_path = os.path.join(sbox.wc_dir, 'A')
+ A_path = sbox.ospath('A')
rel_path = os.path.join('B', 'E', 'alpha')
exit_code, diff_output, err = svntest.actions.run_and_verify_svn(
None, None, [],
@@ -1429,9 +1465,9 @@ def diff_file_urls(sbox):
sbox.build()
- iota_path = os.path.join(sbox.wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
iota_url = sbox.repo_url + '/iota'
- iota_copy_path = os.path.join(sbox.wc_dir, 'A', 'iota')
+ iota_copy_path = sbox.ospath('A/iota')
iota_copy_url = sbox.repo_url + '/A/iota'
iota_copy2_url = sbox.repo_url + '/A/iota2'
@@ -1488,7 +1524,7 @@ def diff_prop_change_local_edit(sbox):
sbox.build()
- iota_path = os.path.join(sbox.wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
iota_url = sbox.repo_url + '/iota'
# Change a property on iota, and commit.
@@ -1533,10 +1569,10 @@ def check_for_omitted_prefix_in_path_component(sbox):
sbox.build()
svntest.actions.do_sleep_for_timestamps()
- prefix_path = os.path.join(sbox.wc_dir, 'prefix_mydir')
+ prefix_path = sbox.ospath('prefix_mydir')
svntest.actions.run_and_verify_svn(None, None, [],
'mkdir', prefix_path)
- other_prefix_path = os.path.join(sbox.wc_dir, 'prefix_other')
+ other_prefix_path = sbox.ospath('prefix_other')
svntest.actions.run_and_verify_svn(None, None, [],
'mkdir', other_prefix_path)
@@ -1575,12 +1611,11 @@ def check_for_omitted_prefix_in_path_component(sbox):
good_dest = ".../prefix_other/mytag"
if ((src != good_src) or (dest != good_dest)):
- print("src is '%s' instead of '%s' and dest is '%s' instead of '%s'" %
+ logger.warn("src is '%s' instead of '%s' and dest is '%s' instead of '%s'" %
(src, good_src, dest, good_dest))
raise svntest.Failure
#----------------------------------------------------------------------
-@XFail()
def diff_renamed_file(sbox):
"diff a file that has been renamed"
@@ -1773,6 +1808,7 @@ def diff_prop_on_named_dir(sbox):
svntest.actions.run_and_verify_svn(None, None, [],
'propdel', 'p', 'A')
+
svntest.actions.run_and_verify_svn(None, None, [],
'ci', '-m', '')
@@ -1787,7 +1823,7 @@ def diff_keywords(sbox):
sbox.build()
- iota_path = os.path.join(sbox.wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
svntest.actions.run_and_verify_svn(None, None, [],
'ps',
@@ -1868,11 +1904,11 @@ def diff_force(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
# Append a line to iota and make it binary.
svntest.main.file_append(iota_path, "new line")
- svntest.main.run_svn(None,
+ svntest.main.run_svn(binary_mime_type_on_text_file_warning,
'propset', 'svn:mime-type',
'application/octet-stream', iota_path)
@@ -1950,7 +1986,7 @@ def diff_renamed_dir(sbox):
svntest.main.run_svn(None, 'mv', os.path.join('A', 'D', 'G'),
os.path.join('A', 'D', 'I'))
- # Check a repos->wc diff
+ # Check a wc->wc diff
exit_code, diff_output, err_output = svntest.main.run_svn(
None, 'diff', '--show-copies-as-adds', os.path.join('A', 'D'))
@@ -1963,6 +1999,23 @@ def diff_renamed_dir(sbox):
'A') :
raise svntest.Failure
+ # Check a repos->wc diff of the moved-here node before commit
+ exit_code, diff_output, err_output = svntest.main.run_svn(
+ None, 'diff', '-r', '1', '--show-copies-as-adds',
+ os.path.join('A', 'D', 'I'))
+ if check_diff_output(diff_output,
+ os.path.join('A', 'D', 'I', 'pi'),
+ 'A') :
+ raise svntest.Failure
+
+ # Check a repos->wc diff of the moved-away node before commit
+ exit_code, diff_output, err_output = svntest.main.run_svn(
+ None, 'diff', '-r', '1', os.path.join('A', 'D', 'G'))
+ if check_diff_output(diff_output,
+ os.path.join('A', 'D', 'G', 'pi'),
+ 'D') :
+ raise svntest.Failure
+
# Commit
svntest.actions.run_and_verify_svn(None, None, [],
'ci', '-m', 'log msg')
@@ -2058,45 +2111,36 @@ def diff_property_changes_to_base(sbox):
sbox.build()
wc_dir = sbox.wc_dir
-
- add_diff = \
- make_diff_prop_header("A") + \
- make_diff_prop_added("dirprop", "r2value") + \
- make_diff_prop_header("iota") + \
- make_diff_prop_added("fileprop", "r2value")
-
- del_diff = \
- make_diff_prop_header("A") + \
- make_diff_prop_deleted("dirprop", "r2value") + \
- make_diff_prop_header("iota") + \
- make_diff_prop_deleted("fileprop", "r2value")
-
-
- expected_output_r1_r2 = list(make_diff_header('A', 'revision 1', 'revision 2')
- + add_diff[:6]
- + make_diff_header('iota', 'revision 1',
- 'revision 2')
- + add_diff[7:])
-
- expected_output_r2_r1 = list(make_diff_header('A', 'revision 2',
- 'revision 1')
- + del_diff[:6]
- + make_diff_header('iota', 'revision 2',
- 'revision 1')
- + del_diff[7:])
-
- expected_output_r1 = list(make_diff_header('A', 'revision 1',
- 'working copy')
- + add_diff[:6]
- + make_diff_header('iota', 'revision 1',
- 'working copy')
- + add_diff[7:])
- expected_output_base_r1 = list(make_diff_header('A', 'working copy',
- 'revision 1')
- + del_diff[:6]
- + make_diff_header('iota', 'working copy',
- 'revision 1')
- + del_diff[7:])
+ # Each of these returns an expected diff as a list of lines.
+ def add_diff_A(r1, r2):
+ return (make_diff_header("A", r1, r2) +
+ make_diff_prop_header("A") +
+ make_diff_prop_added("dirprop", "r2value"))
+
+ def add_diff_iota(r1, r2):
+ return (make_diff_header("iota", r1, r2) +
+ make_diff_prop_header("iota") +
+ make_diff_prop_added("fileprop", "r2value"))
+
+ def del_diff_A(r1, r2):
+ return (make_diff_header("A", r1, r2) +
+ make_diff_prop_header("A") +
+ make_diff_prop_deleted("dirprop", "r2value"))
+
+ def del_diff_iota(r1, r2):
+ return (make_diff_header("iota", r1, r2) +
+ make_diff_prop_header("iota") +
+ make_diff_prop_deleted("fileprop", "r2value"))
+
+ # Each of these is an expected diff as a list of lines.
+ expected_output_r1_r2 = (add_diff_A('revision 1', 'revision 2') +
+ add_diff_iota('revision 1', 'revision 2'))
+ expected_output_r2_r1 = (del_diff_A('revision 2', 'revision 1') +
+ del_diff_iota('revision 2', 'revision 1'))
+ expected_output_r1 = (add_diff_A('revision 1', 'working copy') +
+ add_diff_iota('revision 1', 'working copy'))
+ expected_output_base_r1 = (del_diff_A('working copy', 'revision 1') +
+ del_diff_iota('working copy', 'revision 1'))
os.chdir(sbox.wc_dir)
@@ -2170,15 +2214,13 @@ def diff_schedule_delete(sbox):
expected_output_r2_base = make_diff_header("foo", "revision 2",
"working copy") + [
- "@@ -1 +1,2 @@\n",
- " xxx\n",
- "+yyy\n"
+ "@@ -1 +0,0 @@\n",
+ "-xxx\n",
]
- expected_output_base_r2 = make_diff_header("foo", "working copy",
+ expected_output_base_r2 = make_diff_header("foo", "revision 0",
"revision 2") + [
- "@@ -1,2 +1 @@\n",
- " xxx\n",
- "-yyy\n"
+ "@@ -0,0 +1 @@\n",
+ "+xxx\n",
]
expected_output_r1_base = make_diff_header("foo", "revision 0",
@@ -2272,8 +2314,9 @@ def diff_mime_type_changes(sbox):
'diff', '-r', 'BASE:1')
# Mark iota as a binary file in the working copy.
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset', 'svn:mime-type',
+ svntest.actions.run_and_verify_svn2(None, None,
+ binary_mime_type_on_text_file_warning, 0,
+ 'propset', 'svn:mime-type',
'application/octet-stream', 'iota')
# Check that the earlier diffs against BASE are unaffected by the
@@ -2387,9 +2430,9 @@ def diff_repos_wc_add_with_props(sbox):
] + make_diff_prop_header("X/bar") + \
make_diff_prop_added("propname", "propvalue")
- diff_X_r1_base = make_diff_header("X", "revision 1",
+ diff_X_r1_base = make_diff_header("X", "revision 0",
"working copy") + diff_X
- diff_X_base_r3 = make_diff_header("X", "working copy",
+ diff_X_base_r3 = make_diff_header("X", "revision 0",
"revision 3") + diff_X
diff_foo_r1_base = make_diff_header("foo", "revision 0",
"revision 3") + diff_foo
@@ -2488,7 +2531,7 @@ def diff_repos_working_added_dir(sbox):
"@@ -0,0 +1 @@\n",
"+content\n" ]
expected_output_r1_WORKING = make_diff_header("X/bar", "revision 0",
- "revision 2") + [
+ "working copy") + [
"@@ -0,0 +1,2 @@\n",
"+content\n",
"+more content\n" ]
@@ -2574,6 +2617,52 @@ def basic_diff_summarize(sbox):
wc_dir = sbox.wc_dir
p = sbox.ospath
+ # Diff summarize of a newly added file
+ expected_diff = svntest.wc.State(wc_dir, {
+ 'iota': Item(status='A '),
+ })
+ svntest.actions.run_and_verify_diff_summarize(expected_diff,
+ p('iota'), '-c1')
+
+ # Reverse summarize diff of a newly added file
+ expected_diff = svntest.wc.State(wc_dir, {
+ 'iota': Item(status='D '),
+ })
+ svntest.actions.run_and_verify_diff_summarize(expected_diff,
+ p('iota'), '-c-1')
+
+ # Diff summarize of a newly added directory
+ expected_diff = svntest.wc.State(wc_dir, {
+ 'A/D': Item(status='A '),
+ 'A/D/gamma': Item(status='A '),
+ 'A/D/H': Item(status='A '),
+ 'A/D/H/chi': Item(status='A '),
+ 'A/D/H/psi': Item(status='A '),
+ 'A/D/H/omega': Item(status='A '),
+ 'A/D/G': Item(status='A '),
+ 'A/D/G/pi': Item(status='A '),
+ 'A/D/G/rho': Item(status='A '),
+ 'A/D/G/tau': Item(status='A '),
+ })
+ svntest.actions.run_and_verify_diff_summarize(expected_diff,
+ p('A/D'), '-c1')
+
+ # Reverse summarize diff of a newly added directory
+ expected_diff = svntest.wc.State(wc_dir, {
+ 'A/D': Item(status='D '),
+ 'A/D/gamma': Item(status='D '),
+ 'A/D/H': Item(status='D '),
+ 'A/D/H/chi': Item(status='D '),
+ 'A/D/H/psi': Item(status='D '),
+ 'A/D/H/omega': Item(status='D '),
+ 'A/D/G': Item(status='D '),
+ 'A/D/G/pi': Item(status='D '),
+ 'A/D/G/rho': Item(status='D '),
+ 'A/D/G/tau': Item(status='D '),
+ })
+ svntest.actions.run_and_verify_diff_summarize(expected_diff,
+ p('A/D'), '-c-1')
+
# Add props to some items that will be deleted, and commit.
sbox.simple_propset('prop', 'val',
'A/C',
@@ -2685,7 +2774,7 @@ def diff_weird_author(sbox):
svntest.actions.enable_revprop_changes(sbox.repo_dir)
- svntest.main.file_write(os.path.join(sbox.wc_dir, 'A', 'mu'),
+ svntest.main.file_write(sbox.ospath('A/mu'),
"new content\n")
expected_output = svntest.wc.State(sbox.wc_dir, {
@@ -2811,8 +2900,8 @@ def diff_in_renamed_folder(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- C_path = os.path.join(wc_dir, "A", "C")
- D_path = os.path.join(wc_dir, "A", "D")
+ C_path = sbox.ospath('A/C')
+ D_path = sbox.ospath('A/D')
kappa_path = os.path.join(D_path, "C", "kappa")
# add a new file to a renamed (moved in this case) folder.
@@ -2857,146 +2946,117 @@ def diff_with_depth(sbox):
"test diffs at various depths"
sbox.build()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
B_path = os.path.join('A', 'B')
- diff = make_diff_prop_header(".") + \
- make_diff_prop_added("foo1", "bar1") + \
- make_diff_prop_header("iota") + \
- make_diff_prop_added("foo2", "bar2") + \
- make_diff_prop_header("A") + \
- make_diff_prop_added("foo3", "bar3") + \
- make_diff_prop_header("A/B") + \
- make_diff_prop_added("foo4", "bar4")
-
- dot_header = make_diff_header(".", "revision 1", "working copy")
- iota_header = make_diff_header('iota', "revision 1", "working copy")
- A_header = make_diff_header('A', "revision 1", "working copy")
- B_header = make_diff_header(B_path, "revision 1", "working copy")
-
- expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
- expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
- + iota_header + diff[8:14])
- expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
- + iota_header
- + diff[8:14]
- + A_header + diff[15:21])
- expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:7]
- + iota_header
- + diff[8:14]
- + A_header + diff[15:21]
- + B_header + diff[22:])
-
- os.chdir(sbox.wc_dir)
-
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo1', 'bar1', '.')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo2', 'bar2', 'iota')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo3', 'bar3', 'A')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo4', 'bar4', os.path.join('A', 'B'))
+ sbox.simple_propset('foo1', 'bar1', '.')
+ sbox.simple_propset('foo2', 'bar2', 'iota')
+ sbox.simple_propset('foo3', 'bar3', 'A')
+ sbox.simple_propset('foo4', 'bar4', 'A/B')
+
+ def create_expected_diffs(r1, r2):
+ diff_dot = \
+ make_diff_header(".", r1, r2) + \
+ make_diff_prop_header(".") + \
+ make_diff_prop_added("foo1", "bar1")
+ diff_iota = \
+ make_diff_header('iota', r1, r2) + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_added("foo2", "bar2")
+ diff_A = \
+ make_diff_header('A', r1, r2) + \
+ make_diff_prop_header("A") + \
+ make_diff_prop_added("foo3", "bar3")
+ diff_AB = \
+ make_diff_header(B_path, r1, r2) + \
+ make_diff_prop_header("A/B") + \
+ make_diff_prop_added("foo4", "bar4")
+
+ expected = {}
+ expected['empty'] = svntest.verify.UnorderedOutput(diff_dot)
+ expected['files'] = svntest.verify.UnorderedOutput(diff_dot +
+ diff_iota)
+ expected['immediates'] = svntest.verify.UnorderedOutput(diff_dot +
+ diff_iota +
+ diff_A)
+ expected['infinity'] = svntest.verify.UnorderedOutput(diff_dot +
+ diff_iota +
+ diff_A +
+ diff_AB)
+ return expected
# Test wc-wc diff.
- svntest.actions.run_and_verify_svn(None, expected_empty, [],
- 'diff', '--depth', 'empty')
- svntest.actions.run_and_verify_svn(None, expected_files, [],
- 'diff', '--depth', 'files')
- svntest.actions.run_and_verify_svn(None, expected_immediates, [],
- 'diff', '--depth', 'immediates')
- svntest.actions.run_and_verify_svn(None, expected_infinity, [],
- 'diff', '--depth', 'infinity')
+ expected_diffs = create_expected_diffs("revision 1", "working copy")
+ for depth in ['empty', 'files', 'immediates', 'infinity']:
+ svntest.actions.run_and_verify_svn(None, expected_diffs[depth], [],
+ 'diff', '--depth', depth)
# Commit the changes.
svntest.actions.run_and_verify_svn(None, None, [],
'ci', '-m', '')
- dot_header = make_diff_header(".", "revision 1", "revision 2")
- iota_header = make_diff_header('iota', "revision 1", "revision 2")
- A_header = make_diff_header('A', "revision 1", "revision 2")
- B_header = make_diff_header(B_path, "revision 1", "revision 2")
-
- expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
- expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
- + iota_header + diff[8:14])
- expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
- + iota_header
- + diff[8:14]
- + A_header + diff[15:21])
- expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6]
- + iota_header
- + diff[8:14]
- + A_header + diff[15:21]
- + B_header + diff[22:])
-
# Test repos-repos diff.
- svntest.actions.run_and_verify_svn(None, expected_empty, [],
- 'diff', '-c2', '--depth', 'empty')
- svntest.actions.run_and_verify_svn(None, expected_files, [],
- 'diff', '-c2', '--depth', 'files')
- svntest.actions.run_and_verify_svn(None, expected_immediates, [],
- 'diff', '-c2', '--depth', 'immediates')
- svntest.actions.run_and_verify_svn(None, expected_infinity, [],
- 'diff', '-c2', '--depth', 'infinity')
-
- diff_wc_repos = \
- make_diff_header("A/B", "revision 2", "working copy") + \
- make_diff_prop_header("A/B") + \
- make_diff_prop_modified("foo4", "bar4", "baz4") + \
- make_diff_header("A", "revision 2", "working copy") + \
- make_diff_prop_header("A") + \
- make_diff_prop_modified("foo3", "bar3", "baz3") + \
- make_diff_header("A/mu", "revision 1", "working copy") + [
- "@@ -1 +1,2 @@\n",
- " This is the file 'mu'.\n",
- "+new text\n",
- ] + make_diff_header("iota", "revision 2", "working copy") + [
- "@@ -1 +1,2 @@\n",
- " This is the file 'iota'.\n",
- "+new text\n",
- ] + make_diff_prop_header("iota") + \
- make_diff_prop_modified("foo2", "bar2", "baz2") + \
- make_diff_header(".", "revision 2", "working copy") + \
- make_diff_prop_header(".") + \
- make_diff_prop_modified("foo1", "bar1", "baz1")
-
- expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[49:])
- expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[33:])
- expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[13:26]
- +diff_wc_repos[33:])
- expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:])
+ expected_diffs = create_expected_diffs("revision 1", "revision 2")
+ for depth in ['empty', 'files', 'immediates', 'infinity']:
+ svntest.actions.run_and_verify_svn(None, expected_diffs[depth], [],
+ 'diff', '-c2', '--depth', depth)
+
+ def create_expected_repos_wc_diffs():
+ diff_AB = \
+ make_diff_header("A/B", "revision 2", "working copy") + \
+ make_diff_prop_header("A/B") + \
+ make_diff_prop_modified("foo4", "bar4", "baz4")
+ diff_A = \
+ make_diff_header("A", "revision 2", "working copy") + \
+ make_diff_prop_header("A") + \
+ make_diff_prop_modified("foo3", "bar3", "baz3")
+ diff_mu = \
+ make_diff_header("A/mu", "revision 2", "working copy") + [
+ "@@ -1 +1,2 @@\n",
+ " This is the file 'mu'.\n",
+ "+new text\n",]
+ diff_iota = \
+ make_diff_header("iota", "revision 2", "working copy") + [
+ "@@ -1 +1,2 @@\n",
+ " This is the file 'iota'.\n",
+ "+new text\n",
+ ] + make_diff_prop_header("iota") + \
+ make_diff_prop_modified("foo2", "bar2", "baz2")
+ diff_dot = \
+ make_diff_header(".", "revision 2", "working copy") + \
+ make_diff_prop_header(".") + \
+ make_diff_prop_modified("foo1", "bar1", "baz1")
+
+ expected = {}
+ expected['empty'] = svntest.verify.UnorderedOutput(diff_dot)
+ expected['files'] = svntest.verify.UnorderedOutput(diff_iota +
+ diff_dot)
+ expected['immediates'] = svntest.verify.UnorderedOutput(diff_A +
+ diff_iota +
+ diff_dot)
+ expected['infinity'] = svntest.verify.UnorderedOutput(diff_AB +
+ diff_A +
+ diff_mu +
+ diff_iota +
+ diff_dot)
+ return expected
svntest.actions.run_and_verify_svn(None, None, [],
'up', '-r1')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo1', 'baz1', '.')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo2', 'baz2', 'iota')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo3', 'baz3', 'A')
- svntest.actions.run_and_verify_svn(None, None, [],
- 'propset',
- 'foo4', 'baz4', os.path.join('A', 'B'))
+ sbox.simple_propset('foo1', 'baz1', '.')
+ sbox.simple_propset('foo2', 'baz2', 'iota')
+ sbox.simple_propset('foo3', 'baz3', 'A')
+ sbox.simple_propset('foo4', 'baz4', 'A/B')
svntest.main.file_append(os.path.join('A', 'mu'), "new text\n")
svntest.main.file_append('iota', "new text\n")
# Test wc-repos diff.
- svntest.actions.run_and_verify_svn(None, expected_empty, [],
- 'diff', '-rHEAD', '--depth', 'empty')
- svntest.actions.run_and_verify_svn(None, expected_files, [],
- 'diff', '-rHEAD', '--depth', 'files')
- svntest.actions.run_and_verify_svn(None, expected_immediates, [],
- 'diff', '-rHEAD', '--depth', 'immediates')
- svntest.actions.run_and_verify_svn(None, expected_infinity, [],
- 'diff', '-rHEAD', '--depth', 'infinity')
+ expected_diffs = create_expected_repos_wc_diffs()
+ for depth in ['empty', 'files', 'immediates', 'infinity']:
+ svntest.actions.run_and_verify_svn(None, expected_diffs[depth], [],
+ 'diff', '-rHEAD', '--depth', depth)
# test for issue 2920: ignore eol-style on empty lines
@Issue(2920)
@@ -3073,21 +3133,21 @@ def diff_summarize_xml(sbox):
wc_dir = sbox.wc_dir
# A content modification.
- svntest.main.file_append(os.path.join(wc_dir, "A", "mu"), "New mu content")
+ svntest.main.file_append(sbox.ospath('A/mu'), "New mu content")
# A prop modification.
svntest.main.run_svn(None,
"propset", "prop", "val",
- os.path.join(wc_dir, 'iota'))
+ sbox.ospath('iota'))
# Both content and prop mods.
- tau_path = os.path.join(wc_dir, "A", "D", "G", "tau")
+ tau_path = sbox.ospath('A/D/G/tau')
svntest.main.file_append(tau_path, "tautau")
svntest.main.run_svn(None,
"propset", "prop", "val", tau_path)
# A file addition.
- newfile_path = os.path.join(wc_dir, 'newfile')
+ newfile_path = sbox.ospath('newfile')
svntest.main.file_append(newfile_path, 'newfile')
svntest.main.run_svn(None, 'add', newfile_path)
@@ -3096,7 +3156,7 @@ def diff_summarize_xml(sbox):
'lambda'))
# A directory addition
- svntest.main.run_svn(None, "mkdir", os.path.join(wc_dir, 'newdir'))
+ svntest.main.run_svn(None, "mkdir", sbox.ospath('newdir'))
expected_output = svntest.wc.State(wc_dir, {
'A/mu': Item(verb='Sending'),
@@ -3115,6 +3175,16 @@ def diff_summarize_xml(sbox):
wc_rev=2)
expected_status.remove("A/B/lambda")
+ # 3) Test working copy summarize
+ paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
+ 'newdir',]
+ items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
+ kinds = ['file','file','file','file','file', 'dir',]
+ props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
+
+ svntest.actions.run_and_verify_diff_summarize_xml(
+ [], wc_dir, paths, items, props, kinds, wc_dir)
+
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
@@ -3128,38 +3198,21 @@ def diff_summarize_xml(sbox):
".*No such revision 5555555",
None, wc_dir, None, None, None, '-r0:5555555', wc_dir)
- # 3) Test working copy summarize
- svntest.actions.run_and_verify_diff_summarize_xml(
- ".*Summarizing diff can only compare repository to repository",
- None, wc_dir, None, None, wc_dir)
-
# 4) Test --summarize --xml on -c2
- paths = ['iota',]
- items = ['none',]
- kinds = ['file',]
- props = ['modified',]
+ paths_iota = ['iota',]
+ items_iota = ['none',]
+ kinds_iota = ['file',]
+ props_iota = ['modified',]
svntest.actions.run_and_verify_diff_summarize_xml(
- [], wc_dir, paths, items, props, kinds, '-c2',
- os.path.join(wc_dir, 'iota'))
+ [], wc_dir, paths_iota, items_iota, props_iota, kinds_iota, '-c2',
+ sbox.ospath('iota'))
# 5) Test --summarize --xml on -r1:2
- paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
- 'newdir',]
- items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
- kinds = ['file','file','file','file','file', 'dir',]
- props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
-
svntest.actions.run_and_verify_diff_summarize_xml(
[], wc_dir, paths, items, props, kinds, '-r1:2', wc_dir)
# 6) Same as test #5 but ran against a URL instead of a WC path
- paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
- 'newdir',]
- items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
- kinds = ['file','file','file','file','file', 'dir',]
- props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
-
svntest.actions.run_and_verify_diff_summarize_xml(
[], sbox.repo_url, paths, items, props, kinds, '-r1:2', sbox.repo_url)
@@ -3167,7 +3220,7 @@ def diff_file_depth_empty(sbox):
"svn diff --depth=empty FILE_WITH_LOCAL_MODS"
# The bug was that no diff output would be generated. Check that some is.
sbox.build()
- iota_path = os.path.join(sbox.wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
svntest.main.file_append(iota_path, "new text in iota")
exit_code, out, err = svntest.main.run_svn(None, 'diff',
'--depth', 'empty', iota_path)
@@ -3242,7 +3295,6 @@ def make_file_edit_del_add(dir):
svntest.main.run_svn(None, 'add', theta)
-@XFail()
@Issue(3295)
def diff_url_against_local_mods(sbox):
"diff URL against working copy with local mods"
@@ -3265,12 +3317,18 @@ def diff_url_against_local_mods(sbox):
'up')
# In A, add, remove and change a file, and commit.
- make_file_edit_del_add(A);
+ make_file_edit_del_add(A)
svntest.actions.run_and_verify_svn(None, None, [],
'ci', '-m', 'committing A')
# In A2, do the same changes but leave uncommitted.
- make_file_edit_del_add(A2);
+ make_file_edit_del_add(A2)
+
+ # Diff Path of A against working copy of A2.
+ # Output using arbritrary diff handling should be empty.
+ expected_output = []
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--old', A, '--new', A2)
# Diff URL of A against working copy of A2. Output should be empty.
expected_output = []
@@ -3281,7 +3339,6 @@ def diff_url_against_local_mods(sbox):
#----------------------------------------------------------------------
# Diff against old revision of the parent directory of a removed and
# locally re-added file.
-@XFail()
@Issue(3797)
def diff_preexisting_rev_against_local_add(sbox):
"diff -r1 of dir with removed-then-readded file"
@@ -3310,13 +3367,13 @@ def diff_git_format_wc_wc(sbox):
"create a diff in git unidiff format for wc-wc"
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
- mu_path = os.path.join(wc_dir, 'A', 'mu')
- new_path = os.path.join(wc_dir, 'new')
- lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda')
- lambda_copied_path = os.path.join(wc_dir, 'A', 'B', 'lambda_copied')
- alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
- alpha_copied_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha_copied')
+ iota_path = sbox.ospath('iota')
+ mu_path = sbox.ospath('A/mu')
+ new_path = sbox.ospath('new')
+ lambda_path = sbox.ospath('A/B/lambda')
+ lambda_copied_path = sbox.ospath('A/B/lambda_copied')
+ alpha_path = sbox.ospath('A/B/E/alpha')
+ alpha_copied_path = sbox.ospath('A/B/E/alpha_copied')
svntest.main.file_append(iota_path, "Changed 'iota'.\n")
svntest.main.file_append(new_path, "This is the file 'new'.\n")
@@ -3328,35 +3385,84 @@ def diff_git_format_wc_wc(sbox):
### We're not testing moved paths
- expected_output = make_git_diff_header(lambda_copied_path,
+ expected_output = make_git_diff_header(
+ alpha_copied_path, "A/B/E/alpha_copied",
+ "revision 0", "working copy",
+ copyfrom_path="A/B/E/alpha",
+ copyfrom_rev='1', cp=True,
+ text_changes=True) + [
+ "@@ -1 +1,2 @@\n",
+ " This is the file 'alpha'.\n",
+ "+This is a copy of 'alpha'.\n",
+ ] + make_git_diff_header(lambda_copied_path,
"A/B/lambda_copied",
"revision 1", "working copy",
- copyfrom_path="A/B/lambda", cp=True,
+ copyfrom_path="A/B/lambda",
+ copyfrom_rev='1', cp=True,
text_changes=False) \
+ make_git_diff_header(mu_path, "A/mu", "revision 1",
"working copy",
delete=True) + [
"@@ -1 +0,0 @@\n",
"-This is the file 'mu'.\n",
- ] + make_git_diff_header(alpha_copied_path, "A/B/E/alpha_copied",
- "revision 0", "working copy",
- copyfrom_path="A/B/E/alpha", cp=True,
- text_changes=True) + [
+ ] + make_git_diff_header(iota_path, "iota", "revision 1",
+ "working copy") + [
"@@ -1 +1,2 @@\n",
- " This is the file 'alpha'.\n",
- "+This is a copy of 'alpha'.\n",
+ " This is the file 'iota'.\n",
+ "+Changed 'iota'.\n",
] + make_git_diff_header(new_path, "new", "revision 0",
"working copy", add=True) + [
"@@ -0,0 +1 @@\n",
"+This is the file 'new'.\n",
- ] + make_git_diff_header(iota_path, "iota", "revision 1",
- "working copy") + [
- "@@ -1 +1,2 @@\n",
- " This is the file 'iota'.\n",
- "+Changed 'iota'.\n",
]
- expected = svntest.verify.UnorderedOutput(expected_output)
+ expected = expected_output
+
+ svntest.actions.run_and_verify_svn(None, expected, [], 'diff',
+ '--git', wc_dir)
+
+@Issue(4294)
+def diff_git_format_wc_wc_dir_mv(sbox):
+ "create a diff in git unidff format for wc dir mv"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ g_path = sbox.ospath('A/D/G')
+ g2_path = sbox.ospath('A/D/G2')
+ pi_path = sbox.ospath('A/D/G/pi')
+ rho_path = sbox.ospath('A/D/G/rho')
+ tau_path = sbox.ospath('A/D/G/tau')
+ new_pi_path = sbox.ospath('A/D/G2/pi')
+ new_rho_path = sbox.ospath('A/D/G2/rho')
+ new_tau_path = sbox.ospath('A/D/G2/tau')
+
+ svntest.main.run_svn(None, 'mv', g_path, g2_path)
+
+ expected_output = make_git_diff_header(pi_path, "A/D/G/pi",
+ "revision 1", "working copy",
+ delete=True) \
+ + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'pi'.\n"
+ ] + make_git_diff_header(rho_path, "A/D/G/rho",
+ "revision 1", "working copy",
+ delete=True) \
+ + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'rho'.\n"
+ ] + make_git_diff_header(tau_path, "A/D/G/tau",
+ "revision 1", "working copy",
+ delete=True) \
+ + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'tau'.\n"
+ ] + make_git_diff_header(new_pi_path, "A/D/G2/pi", None, None, cp=True,
+ copyfrom_path="A/D/G/pi", copyfrom_rev='1', text_changes=False) \
+ + make_git_diff_header(new_rho_path, "A/D/G2/rho", None, None, cp=True,
+ copyfrom_path="A/D/G/rho", copyfrom_rev='1', text_changes=False) \
+ + make_git_diff_header(new_tau_path, "A/D/G2/tau", None, None, cp=True,
+ copyfrom_path="A/D/G/tau", copyfrom_rev='1', text_changes=False)
+
+ expected = expected_output
svntest.actions.run_and_verify_svn(None, expected, [], 'diff',
'--git', wc_dir)
@@ -3366,9 +3472,9 @@ def diff_git_format_url_wc(sbox):
sbox.build()
wc_dir = sbox.wc_dir
repo_url = sbox.repo_url
- iota_path = os.path.join(wc_dir, 'iota')
- mu_path = os.path.join(wc_dir, 'A', 'mu')
- new_path = os.path.join(wc_dir, 'new')
+ iota_path = sbox.ospath('iota')
+ mu_path = sbox.ospath('A/mu')
+ new_path = sbox.ospath('new')
svntest.main.file_append(iota_path, "Changed 'iota'.\n")
svntest.main.file_append(new_path, "This is the file 'new'.\n")
svntest.main.run_svn(None, 'add', new_path)
@@ -3406,9 +3512,9 @@ def diff_git_format_url_url(sbox):
sbox.build()
wc_dir = sbox.wc_dir
repo_url = sbox.repo_url
- iota_path = os.path.join(wc_dir, 'iota')
- mu_path = os.path.join(wc_dir, 'A', 'mu')
- new_path = os.path.join(wc_dir, 'new')
+ iota_path = sbox.ospath('iota')
+ mu_path = sbox.ospath('A/mu')
+ new_path = sbox.ospath('new')
svntest.main.file_append(iota_path, "Changed 'iota'.\n")
svntest.main.file_append(new_path, "This is the file 'new'.\n")
svntest.main.run_svn(None, 'add', new_path)
@@ -3450,7 +3556,7 @@ def diff_prop_missing_context(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
prop_val = "".join([
"line 1\n",
"line 2\n",
@@ -3501,7 +3607,7 @@ def diff_prop_multiple_hunks(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
+ iota_path = sbox.ospath('iota')
prop_val = "".join([
"line 1\n",
"line 2\n",
@@ -3575,8 +3681,8 @@ def diff_git_empty_files(sbox):
"create a diff in git format for empty files"
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
- new_path = os.path.join(wc_dir, 'new')
+ iota_path = sbox.ospath('iota')
+ new_path = sbox.ospath('new')
svntest.main.file_write(iota_path, "")
# Now commit the local mod, creating rev 2.
@@ -3612,8 +3718,8 @@ def diff_git_with_props(sbox):
"create a diff in git format showing prop changes"
sbox.build()
wc_dir = sbox.wc_dir
- iota_path = os.path.join(wc_dir, 'iota')
- new_path = os.path.join(wc_dir, 'new')
+ iota_path = sbox.ospath('iota')
+ new_path = sbox.ospath('new')
svntest.main.file_write(iota_path, "")
# Now commit the local mod, creating rev 2.
@@ -3640,7 +3746,7 @@ def diff_git_with_props(sbox):
make_diff_prop_header("new") + \
make_diff_prop_added("svn:eol-style", "native") + \
make_git_diff_header(iota_path, "iota",
- "revision 1", "working copy",
+ "revision 2", "working copy",
text_changes=False) + \
make_diff_prop_header("iota") + \
make_diff_prop_added("svn:keywords", "Id")
@@ -3651,6 +3757,44 @@ def diff_git_with_props(sbox):
svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
'--git', wc_dir)
+@Issue(4010)
+def diff_correct_wc_base_revnum(sbox):
+ "diff WC-WC shows the correct base rev num"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ iota_path = sbox.ospath('iota')
+ svntest.main.file_write(iota_path, "")
+
+ # Commit a local mod, creating rev 2.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'iota' : Item(verb='Sending'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add({
+ 'iota' : Item(status=' ', wc_rev=2),
+ })
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+
+ # Child's base is now 2; parent's is still 1.
+ # Make a local mod.
+ svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Id', iota_path)
+
+ expected_output = make_git_diff_header(iota_path, "iota",
+ "revision 2", "working copy") + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_added("svn:keywords", "Id")
+
+ # Diff the parent.
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
+ '--git', wc_dir)
+
+ # The same again, but specifying the target explicity. This should
+ # give the same output.
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
+ '--git', iota_path)
+
def diff_git_with_props_on_dir(sbox):
"diff in git format showing prop changes on dir"
sbox.build()
@@ -3659,24 +3803,31 @@ def diff_git_with_props_on_dir(sbox):
# Now commit the local mod, creating rev 2.
expected_output = svntest.wc.State(wc_dir, {
'.' : Item(verb='Sending'),
+ 'A' : Item(verb='Sending'),
})
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
expected_status.add({
'' : Item(status=' ', wc_rev=2),
})
+ expected_status.tweak('A', wc_rev=2)
- svntest.main.run_svn(None, 'ps', 'a','b', wc_dir)
+ sbox.simple_propset('k','v', '', 'A')
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
was_cwd = os.getcwd()
os.chdir(wc_dir)
- expected_output = make_git_diff_header(".", "", "revision 1",
+ expected_output = make_git_diff_header("A", "A", "revision 1",
+ "revision 2",
+ add=False, text_changes=False) + \
+ make_diff_prop_header("A") + \
+ make_diff_prop_added("k", "v") + \
+ make_git_diff_header(".", "", "revision 1",
"revision 2",
add=False, text_changes=False) + \
make_diff_prop_header("") + \
- make_diff_prop_added("a", "b")
+ make_diff_prop_added("k", "v")
svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
'-c2', '--git')
@@ -3688,8 +3839,8 @@ def diff_abs_localpath_from_wc_folder(sbox):
sbox.build(read_only = True)
wc_dir = sbox.wc_dir
- A_path = os.path.join(wc_dir, 'A')
- B_abs_path = os.path.abspath(os.path.join(wc_dir, 'A', 'B'))
+ A_path = sbox.ospath('A')
+ B_abs_path = os.path.abspath(sbox.ospath('A/B'))
os.chdir(os.path.abspath(A_path))
svntest.actions.run_and_verify_svn(None, None, [], 'diff', B_abs_path)
@@ -3733,6 +3884,833 @@ def no_spurious_conflict(sbox):
expected_status.tweak('3449_spurious', status=' ')
svntest.actions.run_and_verify_status(wc_dir, expected_status)
+def diff_two_working_copies(sbox):
+ "diff between two working copies"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Create a pristine working copy that will remain mostly unchanged
+ wc_dir_old = sbox.add_wc_path('old')
+ svntest.main.run_svn(None, 'co', sbox.repo_url, wc_dir_old)
+ # Add a property to A/B/F in the pristine working copy
+ svntest.main.run_svn(None, 'propset', 'newprop', 'propval-old\n',
+ os.path.join(wc_dir_old, 'A', 'B', 'F'))
+
+ # Make changes to the first working copy:
+
+ # removed nodes
+ sbox.simple_rm('A/mu')
+ sbox.simple_rm('A/D/H')
+
+ # new nodes
+ sbox.simple_mkdir('newdir')
+ svntest.main.file_append(sbox.ospath('newdir/newfile'), 'new text\n')
+ sbox.simple_add('newdir/newfile')
+ sbox.simple_mkdir('newdir/newdir2') # should not show up in the diff
+
+ # modified nodes
+ sbox.simple_propset('newprop', 'propval', 'A/D')
+ sbox.simple_propset('newprop', 'propval', 'A/D/gamma')
+ svntest.main.file_append(sbox.ospath('A/B/lambda'), 'new text\n')
+
+ # replaced nodes (files vs. directories) with property mods
+ sbox.simple_rm('A/B/F')
+ svntest.main.file_append(sbox.ospath('A/B/F'), 'new text\n')
+ sbox.simple_add('A/B/F')
+ sbox.simple_propset('newprop', 'propval-new\n', 'A/B/F')
+ sbox.simple_rm('A/D/G/pi')
+ sbox.simple_mkdir('A/D/G/pi')
+ sbox.simple_propset('newprop', 'propval', 'A/D/G/pi')
+
+ src_label = os.path.basename(wc_dir_old)
+ dst_label = os.path.basename(wc_dir)
+ expected_output = make_diff_header('newdir/newfile', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -0,0 +1 @@\n",
+ "+new text\n",
+ ] + make_diff_header('A/mu', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'mu'.\n",
+ ] + make_diff_header('A/B/F', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -0,0 +1 @@\n",
+ "+new text\n",
+ ] + make_diff_prop_header('A/B/F') + \
+ make_diff_prop_modified("newprop", "propval-old\n",
+ "propval-new\n") + \
+ make_diff_header('A/B/lambda', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +1,2 @@\n",
+ " This is the file 'lambda'.\n",
+ "+new text\n",
+ ] + make_diff_header('A/D', 'working copy', 'working copy',
+ src_label, dst_label) + \
+ make_diff_prop_header('A/D') + \
+ make_diff_prop_added("newprop", "propval") + \
+ make_diff_header('A/D/gamma', 'working copy',
+ 'working copy',
+ src_label, dst_label) + \
+ make_diff_prop_header('A/D/gamma') + \
+ make_diff_prop_added("newprop", "propval") + \
+ make_diff_header('A/D/G/pi', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'pi'.\n",
+ ] + make_diff_header('A/D/G/pi', 'working copy',
+ 'working copy',
+ src_label, dst_label) + \
+ make_diff_prop_header('A/D/G/pi') + \
+ make_diff_prop_added("newprop", "propval") + \
+ make_diff_header('A/D/H/chi', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'chi'.\n",
+ ] + make_diff_header('A/D/H/omega', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'omega'.\n",
+ ] + make_diff_header('A/D/H/psi', 'working copy',
+ 'working copy',
+ src_label, dst_label) + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'psi'.\n",
+ ]
+
+ # Files in diff may be in any order.
+ expected_output = svntest.verify.UnorderedOutput(expected_output)
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--old', wc_dir_old,
+ '--new', wc_dir)
+
+def diff_deleted_url(sbox):
+ "diff -cN of URL deleted in rN"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # remove A/D/H in r2
+ sbox.simple_rm("A/D/H")
+ sbox.simple_commit()
+
+ # A diff of r2 with target A/D/H should show the removed children
+ expected_output = make_diff_header("chi", "revision 1", "revision 2") + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'chi'.\n",
+ ] + make_diff_header("omega", "revision 1",
+ "revision 2") + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'omega'.\n",
+ ] + make_diff_header("psi", "revision 1",
+ "revision 2") + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'psi'.\n",
+ ]
+
+ # Files in diff may be in any order.
+ expected_output = svntest.verify.UnorderedOutput(expected_output)
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '-c2',
+ sbox.repo_url + '/A/D/H')
+
+def diff_arbitrary_files_and_dirs(sbox):
+ "diff arbitrary files and dirs"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # diff iota with A/mu
+ expected_output = make_diff_header("iota", "working copy", "working copy",
+ "iota", "A/mu") + [
+ "@@ -1 +1 @@\n",
+ "-This is the file 'iota'.\n",
+ "+This is the file 'mu'.\n"
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--old', sbox.ospath('iota'),
+ '--new', sbox.ospath('A/mu'))
+
+ # diff A/B/E with A/D
+ expected_output = make_diff_header("G/pi", "working copy", "working copy",
+ "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'pi'.\n"
+ ] + make_diff_header("G/rho", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'rho'.\n"
+ ] + make_diff_header("G/tau", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'tau'.\n"
+ ] + make_diff_header("H/chi", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'chi'.\n"
+ ] + make_diff_header("H/omega", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'omega'.\n"
+ ] + make_diff_header("H/psi", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'psi'.\n"
+ ] + make_diff_header("alpha", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'alpha'.\n"
+ ] + make_diff_header("beta", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -1 +0,0 @@\n",
+ "-This is the file 'beta'.\n"
+ ] + make_diff_header("gamma", "working copy",
+ "working copy", "B/E", "D") + [
+ "@@ -0,0 +1 @@\n",
+ "+This is the file 'gamma'.\n"
+ ]
+
+ # Files in diff may be in any order.
+ expected_output = svntest.verify.UnorderedOutput(expected_output)
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--old', sbox.ospath('A/B/E'),
+ '--new', sbox.ospath('A/D'))
+
+def diff_properties_only(sbox):
+ "diff --properties-only"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ expected_output = \
+ make_diff_header("iota", "revision 1", "revision 2") + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_added("svn:eol-style", "native")
+
+ expected_reverse_output = \
+ make_diff_header("iota", "revision 2", "revision 1") + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_deleted("svn:eol-style", "native")
+
+ expected_rev1_output = \
+ make_diff_header("iota", "revision 1", "working copy") + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_added("svn:eol-style", "native")
+
+ # Make a property change and a content change to 'iota'
+ # Only the property change should be displayed by diff --properties-only
+ sbox.simple_propset('svn:eol-style', 'native', 'iota')
+ svntest.main.file_append(sbox.ospath('iota'), 'new text')
+
+ sbox.simple_commit() # r2
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--properties-only', '-r', '1:2',
+ sbox.repo_url + '/iota')
+
+ svntest.actions.run_and_verify_svn(None, expected_reverse_output, [],
+ 'diff', '--properties-only', '-r', '2:1',
+ sbox.repo_url + '/iota')
+
+ os.chdir(wc_dir)
+ svntest.actions.run_and_verify_svn(None, expected_rev1_output, [],
+ 'diff', '--properties-only', '-r', '1',
+ 'iota')
+
+ svntest.actions.run_and_verify_svn(None, expected_rev1_output, [],
+ 'diff', '--properties-only',
+ '-r', 'PREV', 'iota')
+
+def diff_properties_no_newline(sbox):
+ "diff props; check no-newline-at-end messages"
+
+ sbox.build()
+ old_cwd = os.getcwd()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+ no_nl = "\\ No newline at end of property\n"
+ propchange_header = "Modified: p.*\n"
+
+ subtests = [
+ ('p1', 'val1', 'val2' ),
+ ('p2', 'val1', 'val2\n'),
+ ('p3', 'val1\n', 'val2' ),
+ ('p4', 'val1\n', 'val2\n'),
+ ]
+
+ # The "before" state.
+ for pname, old_val, new_val in subtests:
+ sbox.simple_propset(pname, old_val, 'iota')
+ sbox.simple_commit() # r2
+
+ # Test one change at a time. (Because, with multiple changes, the order
+ # may not be predictable.)
+ for pname, old_val, new_val in subtests:
+ expected_output = \
+ make_diff_header("iota", "revision 2", "working copy") + \
+ make_diff_prop_header("iota") + \
+ make_diff_prop_modified(pname, old_val, new_val)
+
+ sbox.simple_propset(pname, new_val, 'iota')
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff')
+ svntest.actions.run_and_verify_svn(None, None, [], 'revert', 'iota')
+
+ os.chdir(old_cwd)
+
+def diff_arbitrary_same(sbox):
+ "diff arbitrary files and dirs but same"
+
+ sbox.build(read_only = True)
+
+ sbox.simple_propset('k', 'v', 'A', 'A/mu', 'A/D/G/pi')
+
+ svntest.main.file_write(sbox.ospath('A/mu'), "new mu")
+
+ sbox.simple_copy('A', 'A2')
+
+ svntest.actions.run_and_verify_svn(None, [], [],
+ 'diff',
+ '--old', sbox.ospath('A'),
+ '--new', sbox.ospath('A2'))
+
+ svntest.actions.run_and_verify_svn(None, [], [],
+ 'diff', '--summarize',
+ '--old', sbox.ospath('A'),
+ '--new', sbox.ospath('A2'))
+
+def simple_ancestry(sbox):
+ "diff some simple ancestry changes"
+
+ sbox.build()
+ sbox.simple_copy('A/B/E', 'A/B/E_copied')
+ sbox.simple_copy('A/D/G/pi', 'A/D/G/pi-2')
+ sbox.simple_copy('A/D/G/rho', 'A/D/G/rho-2')
+ sbox.simple_rm('A/B/F', 'A/B/E', 'A/D/G/rho', 'A/D/G/tau')
+ sbox.simple_add_text('new', 'new')
+
+ line = '===================================================================\n'
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Index: %s (added)\n' % sbox.path('new'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E_copied/beta'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E_copied/alpha'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/pi-2'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/rho'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/rho-2'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/tau'),
+ line,
+ ])
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', sbox.wc_dir,
+ '-r', '1',
+ '--notice-ancestry',
+ '--no-diff-deleted',
+ '--show-copies-as-adds',
+ '--no-diff-added')
+
+ # And try the same thing in reverse
+ sbox.simple_commit()
+ sbox.simple_update(revision=1)
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Index: %s (deleted)\n' % sbox.path('new'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E_copied/beta'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E_copied/alpha'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/pi-2'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/rho'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/rho-2'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/tau'),
+ line,
+ ])
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', sbox.wc_dir,
+ '-r', 'HEAD',
+ '--notice-ancestry',
+ '--no-diff-deleted',
+ '--show-copies-as-adds',
+ '--no-diff-added')
+
+ # Now introduce a replacements and some delete-deletes
+ sbox.simple_update()
+ sbox.simple_mkdir('A/B/E')
+ sbox.simple_add_text('New alpha', 'A/B/E/alpha')
+ sbox.simple_add_text('New beta', 'A/B/E/beta')
+ sbox.simple_add_text('New rho', 'A/D/G/rho')
+ sbox.simple_add_text('New tau', 'A/D/G/tau')
+ sbox.simple_rm('A/B/E_copied', 'A/D/G/pi-2', 'A/D/G/rho-2')
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Index: %s (added)\n' % sbox.path('new'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/rho'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/rho'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/D/G/tau'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/D/G/tau'),
+ line,
+ ])
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', sbox.wc_dir,
+ '-r', '1',
+ '--notice-ancestry',
+ '--no-diff-deleted',
+ '--show-copies-as-adds',
+ '--no-diff-added')
+
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', sbox.wc_dir,
+ '-r', '1',
+ '--notice-ancestry',
+ '--no-diff-deleted',
+ '--show-copies-as-adds',
+ '--no-diff-added')
+
+def local_tree_replace(sbox):
+ "diff a replaced tree"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_add_text('extra', 'A/B/F/extra')
+ sbox.simple_commit()
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', '--keep-local',
+ sbox.ospath('A/B'))
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'add', sbox.ospath('A/B'))
+
+ # And now check with ancestry
+
+ line = '===================================================================\n'
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'Index: %s (deleted)\n' % sbox.path('A/B/lambda'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (deleted)\n' % sbox.path('A/B/F/extra'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/lambda'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/alpha'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/E/beta'),
+ line,
+ 'Index: %s (added)\n' % sbox.path('A/B/F/extra'),
+ line,
+ ])
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', wc_dir,
+ '-r', '2',
+ '--notice-ancestry',
+ '--show-copies-as-adds',
+ '--no-diff-added',
+ '--no-diff-deleted')
+
+ # Now create patches to verify the tree ordering
+ patch = os.path.abspath(os.path.join(wc_dir, 'ancestry.patch'))
+
+ cwd = os.getcwd()
+ os.chdir(wc_dir)
+ _, out, _ = svntest.actions.run_and_verify_svn(None, None, [],
+ 'diff', '.',
+ '-r', '2',
+ '--notice-ancestry',
+ '--show-copies-as-adds')
+ svntest.main.file_append(patch, ''.join(out))
+ os.chdir(cwd)
+
+ # And try to apply it
+ svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
+
+ expected_output = svntest.verify.UnorderedOutput([
+ 'D %s\n' % sbox.ospath('A/B/F/extra'),
+ 'D %s\n' % sbox.ospath('A/B/F'),
+ 'D %s\n' % sbox.ospath('A/B/E/beta'),
+ 'D %s\n' % sbox.ospath('A/B/E/alpha'),
+ 'D %s\n' % sbox.ospath('A/B/E'),
+ 'D %s\n' % sbox.ospath('A/B/lambda'),
+ 'D %s\n' % sbox.ospath('A/B'),
+ 'A %s\n' % sbox.ospath('A/B'),
+ 'A %s\n' % sbox.ospath('A/B/lambda'),
+ 'A %s\n' % sbox.ospath('A/B/F'),
+ 'A %s\n' % sbox.ospath('A/B/F/extra'),
+ 'A %s\n' % sbox.ospath('A/B/E'),
+ 'A %s\n' % sbox.ospath('A/B/E/beta'),
+ 'A %s\n' % sbox.ospath('A/B/E/alpha'),
+ ])
+ # And this currently fails because the ordering is broken, but also
+ # because it hits an issue in 'svn patch'
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'patch', patch, wc_dir)
+
+def diff_dir_replaced_by_file(sbox):
+ "diff a directory replaced by a file"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_rm('A/B/E')
+ sbox.simple_add_text('text', 'A/B/E')
+
+ expected_output = [
+ 'Index: %s\n' % sbox.path('A/B/E/alpha'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/alpha'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/alpha'),
+ '@@ -1 +0,0 @@\n',
+ '-This is the file \'alpha\'.\n',
+ 'Index: %s\n' % sbox.path('A/B/E/beta'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/beta'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/beta'),
+ '@@ -1 +0,0 @@\n',
+ '-This is the file \'beta\'.\n',
+ 'Index: %s\n' % sbox.path('A/B/E'),
+ '===================================================================\n',
+ '--- %s\t(revision 0)\n' % sbox.path('A/B/E'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E'),
+ '@@ -0,0 +1 @@\n',
+ '+text\n',
+ '\ No newline at end of file\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', wc_dir)
+
+def diff_dir_replaced_by_dir(sbox):
+ "diff a directory replaced by a directory tree"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_rm('A/B/E')
+ sbox.simple_mkdir('A/B/E')
+ sbox.simple_propset('a', 'b\n', 'A/B/E')
+ sbox.simple_add_text('New beta\n', 'A/B/E/beta')
+
+ # First check with ancestry (Tree replace)
+
+ expected_output = [
+ 'Index: %s\n' % sbox.path('A/B/E/alpha'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/alpha'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/alpha'),
+ '@@ -1 +0,0 @@\n',
+ '-This is the file \'alpha\'.\n',
+ 'Index: %s\n' % sbox.path('A/B/E/beta'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/beta'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/beta'),
+ '@@ -1 +0,0 @@\n',
+ '-This is the file \'beta\'.\n',
+ 'Index: %s\n' % sbox.path('A/B/E/beta'),
+ '===================================================================\n',
+ '--- %s\t(revision 0)\n' % sbox.path('A/B/E/beta'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/beta'),
+ '@@ -0,0 +1 @@\n',
+ '+New beta\n',
+ 'Index: %s\n' % sbox.path('A/B/E'),
+ '===================================================================\n',
+ '--- %s\t(revision 0)\n' % sbox.path('A/B/E'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E'),
+ '\n',
+ 'Property changes on: %s\n' % sbox.path('A/B/E'),
+ '___________________________________________________________________\n',
+ 'Added: a\n',
+ '## -0,0 +1 ##\n',
+ '+b\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--notice-ancestry', wc_dir)
+
+ # And summarized. Currently produces directory adds after their children
+ expected_output = svntest.verify.UnorderedOutput([
+ 'D %s\n' % sbox.ospath('A/B/E/alpha'),
+ 'D %s\n' % sbox.ospath('A/B/E/beta'),
+ 'D %s\n' % sbox.ospath('A/B/E'),
+ 'A %s\n' % sbox.ospath('A/B/E'),
+ 'A %s\n' % sbox.ospath('A/B/E/beta'),
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--summarize', wc_dir,
+ '--notice-ancestry')
+
+ # And now without (file delete, change + properties)
+ expected_output = [
+ 'Index: %s\n' % sbox.path('A/B/E/alpha'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/alpha'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/alpha'),
+ '@@ -1 +0,0 @@\n',
+ '-This is the file \'alpha\'.\n',
+ 'Index: %s\n' % sbox.path('A/B/E/beta'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E/beta'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E/beta'),
+ '@@ -1 +1 @@\n',
+ '-This is the file \'beta\'.\n',
+ '+New beta\n',
+ 'Index: %s\n' % sbox.path('A/B/E'),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % sbox.path('A/B/E'),
+ '+++ %s\t(working copy)\n' % sbox.path('A/B/E'),
+ '\n',
+ 'Property changes on: %s\n' % sbox.path('A/B/E'),
+ '___________________________________________________________________\n',
+ 'Added: a\n',
+ '## -0,0 +1 ##\n',
+ '+b\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', wc_dir)
+
+ expected_output = [
+ 'D %s\n' % sbox.ospath('A/B/E/alpha'),
+ 'M %s\n' % sbox.ospath('A/B/E/beta'),
+ ' M %s\n' % sbox.ospath('A/B/E'),
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '--summarize', wc_dir)
+
+
+@Issue(4366)
+def diff_repos_empty_file_addition(sbox):
+ "repos diff of rev which adds empty file"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Add and commit an empty file.
+ svntest.main.file_append(sbox.ospath('newfile'), "")
+ svntest.main.run_svn(None, 'add', sbox.ospath('newfile'))
+ expected_output = svntest.wc.State(sbox.wc_dir, {
+ 'newfile': Item(verb='Adding'),
+ })
+ expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+ expected_status.add({
+ 'newfile' : Item(status=' ', wc_rev=2),
+ })
+ svntest.actions.run_and_verify_commit(sbox.wc_dir, expected_output,
+ expected_status, None, sbox.wc_dir)
+
+ # Now diff the revision that added the empty file.
+ expected_output = [
+ 'Index: newfile\n',
+ '===================================================================\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'diff', '-c', '2', sbox.repo_url)
+
+def diff_missing_tree_conflict_victim(sbox):
+ "diff with missing tree-conflict victim in wc"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Produce an 'incoming edit vs. local missing' tree conflict:
+ # r2: edit iota and commit the change
+ svntest.main.file_append(sbox.ospath('iota'), "This is a change to iota.\n")
+ sbox.simple_propset('k', 'v', 'A/C')
+ sbox.simple_commit()
+ # now remove iota
+ sbox.simple_rm('iota', 'A/C')
+ sbox.simple_commit()
+ # update to avoid mixed-rev wc warning
+ sbox.simple_update()
+ # merge r2 into wc and verify that a tree conflict is flagged on iota
+ expected_output = wc.State(wc_dir, {
+ 'iota' : Item(status=' ', treeconflict='C'),
+ 'A/C' : Item(status=' ', treeconflict='C')
+ })
+ expected_mergeinfo_output = wc.State(wc_dir, {})
+ expected_elision_output = wc.State(wc_dir, {})
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.remove('iota','A/C')
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+ expected_status.tweak('iota', 'A/C',
+ status='! ', treeconflict='C', wc_rev=None)
+ expected_skip = wc.State('', { })
+ svntest.actions.run_and_verify_merge(wc_dir, '1', '2',
+ sbox.repo_url, None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None, None, None,
+ False, '--ignore-ancestry', wc_dir)
+
+ # 'svn diff' should show no change for the working copy
+ # This currently fails because svn errors out with a 'node not found' error
+ expected_output = [ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', wc_dir)
+
+@Issue(4396)
+def diff_local_missing_obstruction(sbox):
+ "diff local missing and obstructed files"
+
+ sbox.build(read_only=True)
+ wc_dir = sbox.wc_dir
+
+ os.unlink(sbox.ospath('iota'))
+ os.unlink(sbox.ospath('A/mu'))
+ os.mkdir(sbox.ospath('A/mu'))
+
+ # Expect no output for missing and obstructed files
+ expected_output = [
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', wc_dir)
+
+ sbox.simple_propset('K', 'V', 'iota', 'A/mu')
+ sbox.simple_append('IotA', 'Content')
+
+ # But do expect a proper property diff
+ expected_output = [
+ 'Index: %s\n' % (sbox.path('A/mu'),),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % (sbox.path('A/mu'),),
+ '+++ %s\t(working copy)\n' % (sbox.path('A/mu'),),
+ '\n',
+ 'Property changes on: %s\n' % (sbox.path('A/mu'),),
+ '___________________________________________________________________\n',
+ 'Added: K\n',
+ '## -0,0 +1 ##\n',
+ '+V\n',
+ '\ No newline at end of property\n',
+ 'Index: %s\n' % (sbox.path('iota'),),
+ '===================================================================\n',
+ '--- %s\t(revision 1)\n' % (sbox.path('iota'),),
+ '+++ %s\t(working copy)\n' % (sbox.path('iota'),),
+ '\n',
+ 'Property changes on: %s\n' % (sbox.path('iota'),),
+ '___________________________________________________________________\n',
+ 'Added: K\n',
+ '## -0,0 +1 ##\n',
+ '+V\n',
+ '\ No newline at end of property\n',
+ ]
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', wc_dir)
+
+ # Create an external. This produces an error in 1.8.0.
+ sbox.simple_propset('svn:externals', 'AA/BB ' + sbox.repo_url + '/A', '.')
+ sbox.simple_update()
+
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'diff', wc_dir)
+
+
+@Issue(4444)
+def diff_move_inside_copy(sbox):
+ "diff copied-along child that contains a moved file"
+ sbox.build(read_only=True)
+ wc_dir = sbox.wc_dir
+
+ d_path = 'A/D'
+ d_copy = 'A/D-copy'
+ h_path = 'A/D-copy/H'
+ chi_path = '%s/chi' % h_path
+ chi_moved = '%s/chi-moved' % h_path
+
+ sbox.simple_copy(d_path, d_copy)
+ sbox.simple_move(chi_path, chi_moved)
+ sbox.simple_append(chi_moved, 'a new line')
+
+ # Bug: Diffing the copied-along parent directory asserts
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'diff', sbox.ospath(h_path))
+# Regression test for the fix in r1619380. Prior to this (and in releases
+# 1.8.0 through 1.8.10) a local diff incorrectly showed a copied dir's
+# properties as added, whereas it should show only the changes against the
+# copy-source.
+def diff_local_copied_dir(sbox):
+ "local WC diff of copied dir"
+
+ sbox.build()
+
+ was_cwd = os.getcwd()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+ try:
+ sbox.simple_propset('p1', 'v1', 'A/C')
+ sbox.simple_commit()
+
+ # dir with no prop changes
+ sbox.simple_copy('A/C', 'C2')
+ # dir with prop changes
+ sbox.simple_copy('A/C', 'C3')
+ sbox.simple_propset('p2', 'v2', 'C3')
+
+ expected_output_C2 = []
+ expected_output_C3 = [
+ 'Index: C3\n',
+ '===================================================================\n',
+ '--- C3 (revision 2)\n',
+ '+++ C3 (working copy)\n',
+ '\n',
+ 'Property changes on: C3\n',
+ '___________________________________________________________________\n',
+ 'Added: p2\n',
+ '## -0,0 +1 ##\n',
+ '+v2\n',
+ '\ No newline at end of property\n',
+ ]
+
+ svntest.actions.run_and_verify_svn(None, expected_output_C2, [],
+ 'diff', 'C2')
+ svntest.actions.run_and_verify_svn(None, expected_output_C3, [],
+ 'diff', 'C3')
+ finally:
+ os.chdir(was_cwd)
########################################################################
#Run the tests
@@ -3800,6 +4778,23 @@ test_list = [ None,
diff_git_with_props_on_dir,
diff_abs_localpath_from_wc_folder,
no_spurious_conflict,
+ diff_correct_wc_base_revnum,
+ diff_two_working_copies,
+ diff_deleted_url,
+ diff_arbitrary_files_and_dirs,
+ diff_properties_only,
+ diff_properties_no_newline,
+ diff_arbitrary_same,
+ diff_git_format_wc_wc_dir_mv,
+ simple_ancestry,
+ local_tree_replace,
+ diff_dir_replaced_by_file,
+ diff_dir_replaced_by_dir,
+ diff_repos_empty_file_addition,
+ diff_missing_tree_conflict_victim,
+ diff_local_missing_obstruction,
+ diff_move_inside_copy,
+ diff_local_copied_dir,
]
if __name__ == '__main__':