| #!/usr/bin/env python |
| # |
| # svnlook_tests.py: testing the 'svnlook' tool. |
| # |
| # Subversion is a tool for revision control. |
| # See http://subversion.apache.org for more information. |
| # |
| # ==================================================================== |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| ###################################################################### |
| |
| # General modules |
| import re, os, logging |
| |
| logger = logging.getLogger() |
| |
| # Our testing module |
| import svntest |
| |
| from prop_tests import binary_mime_type_on_text_file_warning |
| |
| # (abbreviation) |
| Skip = svntest.testcase.Skip_deco |
| SkipUnless = svntest.testcase.SkipUnless_deco |
| XFail = svntest.testcase.XFail_deco |
| Issues = svntest.testcase.Issues_deco |
| Issue = svntest.testcase.Issue_deco |
| Wimp = svntest.testcase.Wimp_deco |
| Item = svntest.wc.StateItem |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Convenience functions to make writing more tests easier |
| |
| def run_svnlook(*varargs): |
| """Run svnlook with VARARGS, returns exit code as int; stdout, stderr as |
| list of lines (including line terminators). |
| Raises Failure if any stderr messages. |
| """ |
| exit_code, output, dummy_errput = svntest.main.run_command( |
| svntest.main.svnlook_binary, 0, False, *varargs) |
| |
| return output |
| |
| |
| def expect(tag, expected, got): |
| if expected != got: |
| logger.warn("When testing: %s", tag) |
| logger.warn("Expected: %s", expected) |
| logger.warn(" Got: %s", got) |
| raise svntest.Failure |
| |
| |
| # Tests |
| |
| def test_misc(sbox): |
| "test miscellaneous svnlook features" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| |
| # Make a couple of local mods to files |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| svntest.main.file_append(rho_path, 'new appended text for rho') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # give the repo a new UUID |
| uuid = b"01234567-89ab-cdef-89ab-cdef01234567" |
| svntest.main.run_command_stdin(svntest.main.svnadmin_binary, None, 0, True, |
| [b"SVN-fs-dump-format-version: 2\n", |
| b"\n", |
| b"UUID: ", uuid, b"\n", |
| ], |
| 'load', '--force-uuid', repo_dir) |
| |
| expect('youngest', [ '2\n' ], run_svnlook('youngest', repo_dir)) |
| |
| expect('uuid', [ uuid.decode() + '\n' ], run_svnlook('uuid', repo_dir)) |
| |
| # it would be nice to test the author too, but the current test framework |
| # does not pull a username when testing over ra_neon or ra_svn, |
| # so the commits have an empty author. |
| |
| expect('log', [ 'log msg\n' ], run_svnlook('log', repo_dir)) |
| |
| # check if the 'svnlook tree' output can be expanded to |
| # the 'svnlook tree --full-paths' output if demanding the whole repository |
| treelist = run_svnlook('tree', repo_dir) |
| treelistfull = run_svnlook('tree', '--full-paths', repo_dir) |
| |
| path = '' |
| treelistexpand = [] |
| for entry in treelist: |
| len1 = len(entry) |
| len2 = len(entry.lstrip()) |
| path = path[0:2*(len1-len2)-1] + entry.strip() + '\n' |
| if path == '/\n': |
| treelistexpand.append(path) |
| else: |
| treelistexpand.append(path[1:]) |
| |
| treelistexpand = svntest.verify.UnorderedOutput(treelistexpand) |
| svntest.verify.compare_and_display_lines('Unexpected result from tree', '', |
| treelistexpand, treelistfull) |
| |
| # check if the 'svnlook tree' output is the ending of |
| # the 'svnlook tree --full-paths' output if demanding |
| # any part of the repository |
| treelist = run_svnlook('tree', repo_dir, '/A/B') |
| treelistfull = run_svnlook('tree', '--full-paths', repo_dir, '/A/B') |
| |
| path = '' |
| treelistexpand = [] |
| for entry in treelist: |
| len1 = len(entry) |
| len2 = len(entry.lstrip()) |
| path = path[0:2*(len1-len2)] + entry.strip() + '\n' |
| treelistexpand.append('/A/' + path) |
| |
| treelistexpand = svntest.verify.UnorderedOutput(treelistexpand) |
| svntest.verify.compare_and_display_lines('Unexpected result from tree', '', |
| treelistexpand, treelistfull) |
| |
| treelist = run_svnlook('tree', repo_dir, '/') |
| if treelist[0] != '/\n': |
| raise svntest.Failure |
| |
| expect('propget svn:log', [ 'log msg' ], |
| run_svnlook('propget', '--revprop', repo_dir, 'svn:log')) |
| |
| |
| proplist = run_svnlook('proplist', '--revprop', repo_dir) |
| proplist = sorted([prop.strip() for prop in proplist]) |
| |
| # We cannot rely on svn:author's presence. ra_svn doesn't set it. |
| if not (proplist == [ 'svn:author', 'svn:date', 'svn:log' ] |
| or proplist == [ 'svn:date', 'svn:log' ]): |
| logger.warn("Unexpected result from proplist: %s", proplist) |
| raise svntest.Failure |
| |
| prop_name = 'foo:bar-baz-quux' |
| exit_code, output, errput = svntest.main.run_svnlook('propget', |
| '--revprop', repo_dir, |
| prop_name) |
| |
| expected_err = "Property '%s' not found on revision " % prop_name |
| for line in errput: |
| if line.find(expected_err) != -1: |
| break |
| else: |
| raise svntest.main.SVNUnmatchedError |
| |
| exit_code, output, errput = svntest.main.run_svnlook('propget', |
| '-r1', repo_dir, |
| prop_name, '/') |
| |
| expected_err = "Property '%s' not found on path '/' in revision " % prop_name |
| for line in errput: |
| if line.find(expected_err) != -1: |
| break |
| else: |
| raise svntest.main.SVNUnmatchedError |
| |
| #---------------------------------------------------------------------- |
| # Issue 1089 |
| @Issue(1089) |
| def delete_file_in_moved_dir(sbox): |
| "delete file in moved dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| |
| # move E to E2 and delete E2/alpha |
| E_path = os.path.join(wc_dir, 'A', 'B', 'E') |
| E2_path = os.path.join(wc_dir, 'A', 'B', 'E2') |
| svntest.actions.run_and_verify_svn(None, [], 'mv', E_path, E2_path) |
| alpha_path = os.path.join(E2_path, 'alpha') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', alpha_path) |
| |
| # commit |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E' : Item(verb='Deleting'), |
| 'A/B/E2' : Item(verb='Adding'), |
| 'A/B/E2/alpha' : Item(verb='Deleting'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta') |
| expected_status.add({ |
| 'A/B/E2' : Item(status=' ', wc_rev=2), |
| 'A/B/E2/beta' : Item(status=' ', wc_rev=2), |
| }) |
| ### this commit fails. the 'alpha' node is marked 'not-present' since it |
| ### is a deleted child of a move/copy. this is all well and proper. |
| ### however, during the commit, the parent node is committed down to just |
| ### the BASE node. at that point, 'alpha' has no parent in WORKING which |
| ### is a schema violation. there is a plan for committing in this kind of |
| ### situation, layed out in wc-ng-design. that needs to be implemented |
| ### in order to get this commit working again. |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| exit_code, output, errput = svntest.main.run_svnlook("dirs-changed", |
| repo_dir) |
| if errput: |
| raise svntest.Failure |
| |
| # Okay. No failure, but did we get the right output? |
| if len(output) != 2: |
| raise svntest.Failure |
| if not ((output[0].strip() == 'A/B/') |
| and (output[1].strip() == 'A/B/E2/')): |
| raise svntest.Failure |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue 1241 |
| @Issue(1241) |
| def test_print_property_diffs(sbox): |
| "test the printing of property diffs" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| |
| # Add a bogus property to iota |
| iota_path = os.path.join(wc_dir, 'iota') |
| svntest.actions.run_and_verify_svn(None, [], 'propset', |
| 'bogus_prop', 'bogus_val', iota_path) |
| |
| # commit the change |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', '-m', 'log msg', iota_path) |
| |
| # Grab the diff |
| exit_code, expected_output, err = svntest.actions.run_and_verify_svn( |
| None, [], 'diff', '-r', 'PREV', iota_path) |
| |
| exit_code, output, errput = svntest.main.run_svnlook("diff", repo_dir) |
| if errput: |
| raise svntest.Failure |
| |
| # Okay. No failure, but did we get the right output? |
| if len(output) != len(expected_output): |
| raise svntest.Failure |
| |
| canonical_iota_path = iota_path.replace(os.path.sep, '/') |
| |
| # replace wcdir/iota with iota in expected_output |
| for i in range(len(expected_output)): |
| expected_output[i] = expected_output[i].replace(canonical_iota_path, |
| 'iota') |
| |
| # Check that the header filenames match. |
| if expected_output[2].split()[1] != output[2].split()[1]: |
| raise svntest.Failure |
| if expected_output[3].split()[1] != output[3].split()[1]: |
| raise svntest.Failure |
| |
| svntest.verify.compare_and_display_lines('', '', |
| expected_output[4:], |
| output[4:]) |
| |
| #---------------------------------------------------------------------- |
| # Check that svnlook info repairs allows inconsistent line endings in logs. |
| |
| def info_bad_newlines(sbox): |
| "svnlook info must allow inconsistent newlines" |
| |
| dump_str = b"""SVN-fs-dump-format-version: 2 |
| |
| UUID: dc40867b-38f6-0310-9f5f-f81aa277e06e |
| |
| Revision-number: 0 |
| Prop-content-length: 56 |
| Content-length: 56 |
| |
| K 8 |
| svn:date |
| V 27 |
| 2005-05-03T19:09:41.129900Z |
| PROPS-END |
| |
| Revision-number: 1 |
| Prop-content-length: 99 |
| Content-length: 99 |
| |
| K 7 |
| svn:log |
| V 3 |
| \n\r\n |
| K 10 |
| svn:author |
| V 2 |
| pl |
| K 8 |
| svn:date |
| V 27 |
| 2005-05-03T19:10:19.975578Z |
| PROPS-END |
| |
| Node-path: file |
| Node-kind: file |
| Node-action: add |
| Prop-content-length: 10 |
| Text-content-length: 5 |
| Text-content-md5: e1cbb0c3879af8347246f12c559a86b5 |
| Content-length: 15 |
| |
| PROPS-END |
| text |
| |
| |
| """ |
| |
| # load dumpfile with inconsistent newlines into repos. |
| svntest.actions.load_repo(sbox, dump_str=dump_str, |
| bypass_prop_validation=True) |
| |
| exit_code, output, errput = svntest.main.run_svnlook("info", |
| sbox.repo_dir, "-r1") |
| if errput: |
| raise svntest.Failure |
| |
| def changed_copy_info(sbox): |
| "test --copy-info flag on the changed command" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| |
| # Copy alpha to /A/alpha2. |
| E_path = os.path.join(wc_dir, 'A', 'B', 'E') |
| alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha') |
| alpha2_path = os.path.join(wc_dir, 'A', 'alpha2') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', alpha_path, |
| alpha2_path) |
| |
| # commit |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/alpha2' : Item(verb='Adding'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/alpha2' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| exit_code, output, errput = svntest.main.run_svnlook("changed", repo_dir) |
| if errput: |
| raise svntest.Failure |
| |
| expect("changed without --copy-info", ["A A/alpha2\n"], output) |
| |
| exit_code, output, errput = svntest.main.run_svnlook("changed", |
| repo_dir, "--copy-info") |
| if errput: |
| raise svntest.Failure |
| |
| expect("changed with --copy-info", |
| ["A + A/alpha2\n", |
| " (from A/B/E/alpha:r1)\n"], |
| output) |
| |
| #---------------------------------------------------------------------- |
| # Issue 2663 |
| @Issue(2663) |
| def tree_non_recursive(sbox): |
| "test 'svnlook tree --non-recursive'" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| |
| expected_results_root = ('/', ' iota', ' A/') |
| expected_results_deep = ('B/', ' lambda', ' E/', ' F/') |
| |
| # check the output of svnlook --non-recursive on the |
| # root of the repository |
| treelist = run_svnlook('tree', '--non-recursive', repo_dir) |
| for entry in treelist: |
| if not entry.rstrip() in expected_results_root: |
| logger.warn("Unexpected result from tree with --non-recursive:") |
| logger.warn(" entry : %s", entry.rstrip()) |
| raise svntest.Failure |
| if len(treelist) != len(expected_results_root): |
| logger.warn("Expected %i output entries, found %i", |
| len(expected_results_root), len(treelist)) |
| raise svntest.Failure |
| |
| # check the output of svnlook --non-recursive on a |
| # subdirectory of the repository |
| treelist = run_svnlook('tree', '--non-recursive', repo_dir, '/A/B') |
| for entry in treelist: |
| if not entry.rstrip() in expected_results_deep: |
| logger.warn("Unexpected result from tree with --non-recursive:") |
| logger.warn(" entry : %s", entry.rstrip()) |
| raise svntest.Failure |
| if len(treelist) != len(expected_results_deep): |
| logger.warn("Expected %i output entries, found %i", |
| len(expected_results_deep), len(treelist)) |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| def limit_history(sbox): |
| "history --limit" |
| sbox.build(create_wc=False) |
| repo_url = sbox.repo_url |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', '-m', 'log msg', |
| repo_url + "/iota", repo_url + "/iota2") |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', '-m', 'log msg', |
| repo_url + "/A/mu", repo_url + "/iota") |
| history = run_svnlook("history", "--limit=1", sbox.repo_dir) |
| # Ignore the two lines of header, and verify expected number of items. |
| if len(history[2:]) != 1: |
| raise svntest.Failure("Output not limited to expected number of items") |
| |
| #---------------------------------------------------------------------- |
| def diff_ignore_whitespace(sbox): |
| "test 'svnlook diff -x -b' and 'svnlook diff -x -w'" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| |
| # Make whitespace-only changes to mu |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| svntest.main.file_write(mu_path, "This is the file 'mu'.\n", "wb") |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', wc_rev=2) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Check the output of 'svnlook diff -x --ignore-space-change' on mu. |
| # It should not print anything. |
| output = run_svnlook('diff', '-r2', '-x', '--ignore-space-change', |
| repo_dir) |
| if output != []: |
| raise svntest.Failure |
| |
| # Check the output of 'svnlook diff -x --ignore-all-space' on mu. |
| # It should not print anything. |
| output = run_svnlook('diff', '-r2', '-x', '--ignore-all-space', |
| repo_dir) |
| if output != []: |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| def diff_ignore_eolstyle(sbox): |
| "test 'svnlook diff -x --ignore-eol-style'" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| |
| # CRLF is a string that will match a CRLF sequence read from a text file. |
| # ### On Windows, we assume CRLF will be read as LF, so it's a poor test. |
| if os.name == 'nt': |
| crlf = '\n' |
| else: |
| crlf = '\r\n' |
| |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| |
| rev = 1 |
| # do the --ignore-eol-style test for each eol-style |
| for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'], |
| [crlf, '\015', '\n', '\012']): |
| # rewrite file mu and set the eol-style property. |
| svntest.main.file_write(mu_path, "This is the file 'mu'." + eolchar, 'wb') |
| svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path) |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at |
| # revision 1, but mu should be at revision rev + 1. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', wc_rev=rev + 1) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Grab the diff |
| exit_code, expected_output, err = svntest.actions.run_and_verify_svn( |
| None, [], |
| 'diff', '-r', 'PREV', '-x', '--ignore-eol-style', mu_path) |
| |
| |
| output = run_svnlook('diff', '-r', str(rev + 1), '-x', |
| '--ignore-eol-style', repo_dir) |
| rev += 1 |
| |
| canonical_mu_path = mu_path.replace(os.path.sep, '/') |
| |
| # replace wcdir/A/mu with A/mu in expected_output |
| for i in range(len(expected_output)): |
| expected_output[i] = expected_output[i].replace(canonical_mu_path, |
| 'A/mu') |
| |
| # Check that the header filenames match. |
| if expected_output[2].split()[1] != output[2].split()[1]: |
| raise svntest.Failure |
| if expected_output[3].split()[1] != output[3].split()[1]: |
| raise svntest.Failure |
| |
| svntest.verify.compare_and_display_lines('', '', |
| expected_output[4:], |
| output[4:]) |
| |
| |
| #---------------------------------------------------------------------- |
| def diff_binary(sbox): |
| "test 'svnlook diff' on binary files" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| |
| # Set A/mu to a binary mime-type, tweak its text, and commit. |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| svntest.main.file_append(mu_path, 'new appended text for mu') |
| svntest.main.run_svn(binary_mime_type_on_text_file_warning, |
| 'propset', 'svn:mime-type', |
| 'application/octet-stream', mu_path) |
| svntest.main.run_svn(None, 'ci', '-m', 'log msg', mu_path) |
| |
| # Now run 'svnlook diff' and look for the "Binary files differ" message. |
| output = run_svnlook('diff', repo_dir) |
| if not "(Binary files differ)\n" in output: |
| raise svntest.Failure("No 'Binary files differ' indication in " |
| "'svnlook diff' output.") |
| |
| #---------------------------------------------------------------------- |
| def test_filesize(sbox): |
| "test 'svnlook filesize'" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| |
| tree_output = run_svnlook('tree', '--full-paths', repo_dir) |
| for line in tree_output: |
| # Drop line endings |
| line = line.rstrip() |
| # Skip directories |
| if line[-1] == '/': |
| continue |
| # Run 'svnlook cat' and measure the size of the output. |
| cat_output = run_svnlook('cat', repo_dir, line) |
| cat_size = len("".join(cat_output)) |
| # Run 'svnlook filesize' and compare the results with the CAT_SIZE. |
| filesize_output = run_svnlook('filesize', repo_dir, line) |
| if len(filesize_output) != 1: |
| raise svntest.Failure("'svnlook filesize' printed something other than " |
| "a single line of output.") |
| filesize = int(filesize_output[0].strip()) |
| if filesize != cat_size: |
| raise svntest.Failure("'svnlook filesize' and the counted length of " |
| "'svnlook cat's output differ for the path " |
| "'%s'." % (line)) |
| |
| #---------------------------------------------------------------------- |
| def verify_logfile(logfilename, expected_data): |
| if os.path.exists(logfilename): |
| fp = open(logfilename) |
| else: |
| raise svntest.verify.SVNUnexpectedOutput("hook logfile %s not found"\ |
| % logfilename) |
| |
| actual_data = fp.readlines() |
| fp.close() |
| os.unlink(logfilename) |
| svntest.verify.compare_and_display_lines('wrong hook logfile content', |
| 'STDOUT', |
| expected_data, actual_data) |
| |
| def test_txn_flag(sbox): |
| "test 'svnlook * -t'" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| logfilepath = os.path.join(repo_dir, 'hooks.log') |
| |
| # List changed dirs and files in this transaction |
| hook_template = """import sys,os,subprocess |
| svnlook_bin=%s |
| |
| fp = open(os.path.join(sys.argv[1], 'hooks.log'), 'wb') |
| def output_command(fp, cmd, opt): |
| command = [svnlook_bin, cmd, '-t', sys.argv[2], sys.argv[1]] + opt |
| process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, bufsize=-1) |
| (output, errors) = process.communicate() |
| status = process.returncode |
| fp.write(output) |
| fp.write(errors) |
| return status |
| |
| for (svnlook_cmd, svnlook_opt) in %s: |
| output_command(fp, svnlook_cmd, svnlook_opt.split()) |
| fp.close()""" |
| pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir) |
| |
| # 1. svnlook 'changed' -t and 'dirs-changed' -t |
| hook_instance = hook_template % (repr(svntest.main.svnlook_binary), |
| repr([('changed', ''), |
| ('dirs-changed', '')])) |
| svntest.main.create_python_hook_script(pre_commit_hook, |
| hook_instance) |
| |
| # Change files mu and rho |
| A_path = os.path.join(wc_dir, 'A') |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| svntest.main.file_append(rho_path, 'new appended text for rho') |
| |
| # commit, and check the hook's logfile |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', '-m', 'log msg', wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'up', wc_dir) |
| |
| expected_data = [ 'U A/D/G/rho\n', 'U A/mu\n', 'A/\n', 'A/D/G/\n' ] |
| verify_logfile(logfilepath, expected_data) |
| |
| # 2. svnlook 'propget' -t, 'proplist' -t |
| # 2. Change a dir and revision property |
| hook_instance = hook_template % (repr(svntest.main.svnlook_binary), |
| repr([('propget', 'bogus_prop /A'), |
| ('propget', '--revprop bogus_rev_prop'), |
| ('proplist', '/A'), |
| ('proplist', '--revprop')])) |
| svntest.main.create_python_hook_script(pre_commit_hook, |
| hook_instance) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'propset', |
| 'bogus_prop', 'bogus_val\n', A_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', '-m', 'log msg', wc_dir, |
| '--with-revprop', 'bogus_rev_prop=bogus_rev_val\n') |
| # Now check the logfile |
| expected_data = [ 'bogus_val\n', |
| 'bogus_rev_val\n', |
| "Properties on '/A':\n", |
| ' bogus_prop\n', |
| ' svn:log\n', ' svn:author\n', |
| ' bogus_rev_prop\n', |
| ' svn:date\n', |
| ' svn:txn-client-compat-version\n', |
| ' svn:txn-user-agent\n', |
| ] |
| verify_logfile(logfilepath, svntest.verify.UnorderedOutput(expected_data)) |
| |
| # From r1293375 until fixed in r1303856, 'svnlook changed' and 'svnlook diff' |
| # produced no output on a property delete. |
| def property_delete(sbox): |
| "property delete" |
| |
| sbox.build() |
| repo_dir = sbox.repo_dir |
| |
| sbox.simple_propset('foo', 'bar', 'A/mu') |
| sbox.simple_commit() |
| sbox.simple_propdel('foo', 'A/mu') |
| sbox.simple_commit() |
| |
| svntest.actions.run_and_verify_svnlook(["_U A/mu\n"], [], |
| 'changed', repo_dir) |
| |
| |
| ######################################################################## |
| # Run the tests |
| |
| |
| # list all tests here, starting with None: |
| test_list = [ None, |
| test_misc, |
| delete_file_in_moved_dir, |
| test_print_property_diffs, |
| info_bad_newlines, |
| changed_copy_info, |
| tree_non_recursive, |
| limit_history, |
| diff_ignore_whitespace, |
| diff_ignore_eolstyle, |
| diff_binary, |
| test_filesize, |
| test_txn_flag, |
| property_delete, |
| ] |
| |
| if __name__ == '__main__': |
| svntest.main.run_tests(test_list) |
| # NOTREACHED |
| |
| |
| ### End of file. |