In the command-line client, forbid
[svn.git] / subversion / tests / cmdline / svnlook_tests.py
blobe4cc9c0156b894c39f4fd90308b023a0ba301317
1 #!/usr/bin/env python
3 # svnlook_tests.py: testing the 'svnlook' tool.
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2004, 2007 CollabNet. All rights reserved.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at http://subversion.tigris.org/license-1.html.
14 # If newer versions of this license are posted there, you may use a
15 # newer version instead, at your option.
17 ######################################################################
19 # General modules
20 import re, os
22 # Our testing module
23 import svntest
26 # (abbreviation)
27 Skip = svntest.testcase.Skip
28 XFail = svntest.testcase.XFail
29 Item = svntest.wc.StateItem
32 #----------------------------------------------------------------------
34 # Convenience functions to make writing more tests easier
36 def run_svnlook(*varargs):
37 """Run svnlook with VARARGS, returns stdout as list of lines.
38 Raises Failure if any stderr messages."""
39 output, dummy_errput = svntest.main.run_command(svntest.main.svnlook_binary,
40 0, 0, *varargs)
41 return output
44 def expect(tag, expected, got):
45 if expected != got:
46 print "When testing: %s" % tag
47 print "Expected: %s" % expected
48 print " Got: %s" % got
49 raise svntest.Failure
52 # Tests
54 def test_misc(sbox):
55 "test miscellaneous svnlook features"
57 sbox.build()
58 wc_dir = sbox.wc_dir
59 repo_dir = sbox.repo_dir
61 # Make a couple of local mods to files
62 mu_path = os.path.join(wc_dir, 'A', 'mu')
63 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
64 svntest.main.file_append(mu_path, 'appended mu text')
65 svntest.main.file_append(rho_path, 'new appended text for rho')
67 # Created expected output tree for 'svn ci'
68 expected_output = svntest.wc.State(wc_dir, {
69 'A/mu' : Item(verb='Sending'),
70 'A/D/G/rho' : Item(verb='Sending'),
73 # Create expected status tree; all local revisions should be at 1,
74 # but mu and rho should be at revision 2.
75 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
76 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
78 svntest.actions.run_and_verify_commit(wc_dir,
79 expected_output,
80 expected_status,
81 None,
82 None, None,
83 None, None,
84 wc_dir)
86 # give the repo a new UUID
87 uuid = "01234567-89ab-cdef-89ab-cdef01234567"
88 svntest.main.run_command_stdin(svntest.main.svnadmin_binary, None, 1,
89 ["SVN-fs-dump-format-version: 2\n",
90 "\n",
91 "UUID: ", uuid, "\n",
93 'load', '--force-uuid', repo_dir)
95 expect('youngest', [ '2\n' ], run_svnlook('youngest', repo_dir))
97 expect('uuid', [ uuid + '\n' ], run_svnlook('uuid', repo_dir))
99 # it would be nice to test the author too, but the current test framework
100 # does not pull a username when testing over ra_neon or ra_svn,
101 # so the commits have an empty author.
103 expect('log', [ 'log msg\n' ], run_svnlook('log', repo_dir))
105 # check if the 'svnlook tree' output can be expanded to
106 # the 'svnlook tree --full-paths' output if demanding the whole repository
107 treelist = run_svnlook('tree', repo_dir)
108 treelistfull = run_svnlook('tree', '--full-paths', repo_dir)
109 path = ''
110 n = 0
111 for entry in treelist:
112 len1 = len(entry)
113 len2 = len(entry.lstrip())
114 path = path[0:2*(len1-len2)-1] + entry.strip()
115 test = treelistfull[n].rstrip()
116 if n != 0:
117 test = "/" + test
118 if not path == test:
119 print "Unexpected result from tree with --full-paths:"
120 print " entry : %s" % entry.rstrip()
121 print " with --full-paths: %s" % treelistfull[n].rstrip()
122 raise svntest.Failure
123 n = n + 1
125 # check if the 'svnlook tree' output is the ending of
126 # the 'svnlook tree --full-paths' output if demanding
127 # any part of the repository
128 n = 0
129 treelist = run_svnlook('tree', repo_dir, '/A/B')
130 treelistfull = run_svnlook('tree', '--full-paths', repo_dir, '/A/B')
131 for entry in treelist:
132 if not treelistfull[n].endswith(entry.lstrip()):
133 print "Unexpected result from tree with --full-paths:"
134 print " entry : %s" % entry.rstrip()
135 print " with --full-paths: %s" % treelistfull[n].rstrip()
136 raise svntest.Failure
137 n = n + 1
139 treelist = run_svnlook('tree', repo_dir, '/')
140 if treelist[0] != '/\n':
141 raise svntest.Failure
143 expect('propget svn:log', [ 'log msg' ],
144 run_svnlook('propget', '--revprop', repo_dir, 'svn:log'))
147 proplist = run_svnlook('proplist', '--revprop', repo_dir)
148 proplist = [prop.strip() for prop in proplist]
149 proplist.sort()
151 # We cannot rely on svn:author's presence. ra_svn doesn't set it.
152 if not (proplist == [ 'svn:author', 'svn:date', 'svn:log' ]
153 or proplist == [ 'svn:date', 'svn:log' ]):
154 print "Unexpected result from proplist: %s" % proplist
155 raise svntest.Failure
157 prop_name = 'foo:bar-baz-quux'
158 output, errput = svntest.main.run_svnlook('propget', '--revprop', repo_dir,
159 prop_name)
161 expected_err = "Property '%s' not found on revision " % prop_name
162 for line in errput:
163 if line.find(expected_err) != -1:
164 break
165 else:
166 raise svntest.main.SVNUnmatchedError
168 output, errput = svntest.main.run_svnlook('propget', '-r1', repo_dir,
169 prop_name, '/')
171 expected_err = "Property '%s' not found on path '/' in revision " % prop_name
172 for line in errput:
173 if line.find(expected_err) != -1:
174 break
175 else:
176 raise svntest.main.SVNUnmatchedError
178 #----------------------------------------------------------------------
179 # Issue 1089
180 def delete_file_in_moved_dir(sbox):
181 "delete file in moved dir"
183 sbox.build()
184 wc_dir = sbox.wc_dir
185 repo_dir = sbox.repo_dir
187 # move E to E2 and delete E2/alpha
188 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
189 E2_path = os.path.join(wc_dir, 'A', 'B', 'E2')
190 svntest.actions.run_and_verify_svn(None, None, [], 'mv', E_path, E2_path)
191 alpha_path = os.path.join(E2_path, 'alpha')
192 svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
194 # commit
195 expected_output = svntest.wc.State(wc_dir, {
196 'A/B/E' : Item(verb='Deleting'),
197 'A/B/E2' : Item(verb='Adding'),
198 'A/B/E2/alpha' : Item(verb='Deleting'),
200 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
201 expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
202 expected_status.add({
203 'A/B/E2' : Item(status=' ', wc_rev=2),
204 'A/B/E2/beta' : Item(status=' ', wc_rev=2),
206 svntest.actions.run_and_verify_commit(wc_dir,
207 expected_output,
208 expected_status,
209 None,
210 None, None,
211 None, None,
212 wc_dir)
214 output, errput = svntest.main.run_svnlook("dirs-changed", repo_dir)
215 if errput:
216 raise svntest.Failure
218 # Okay. No failure, but did we get the right output?
219 if len(output) != 2:
220 raise svntest.Failure
221 if not ((output[0].strip() == 'A/B/')
222 and (output[1].strip() == 'A/B/E2/')):
223 raise svntest.Failure
226 #----------------------------------------------------------------------
227 # Issue 1241
228 def test_print_property_diffs(sbox):
229 "test the printing of property diffs"
231 sbox.build()
232 wc_dir = sbox.wc_dir
233 repo_dir = sbox.repo_dir
235 # Add a bogus property to iota
236 iota_path = os.path.join(wc_dir, 'iota')
237 svntest.actions.run_and_verify_svn(None, None, [], 'propset',
238 'bogus_prop', 'bogus_val', iota_path)
240 # commit the change
241 svntest.actions.run_and_verify_svn(None, None, [],
242 'ci', '-m', 'log msg', iota_path)
244 # Grab the diff
245 expected_output, err = svntest.actions.run_and_verify_svn(None, None, [],
246 'diff',
247 '-r', 'PREV',
248 iota_path)
250 output, errput = svntest.main.run_svnlook("diff", repo_dir)
251 if errput:
252 raise svntest.Failure
254 # Okay. No failure, but did we get the right output?
255 if len(output) != len(expected_output):
256 raise svntest.Failure
258 # replace wcdir/iota with iota in expected_output
259 for i in xrange(len(expected_output)):
260 expected_output[i] = expected_output[i].replace(iota_path, 'iota')
262 svntest.verify.compare_and_display_lines('', '', expected_output, output)
264 #----------------------------------------------------------------------
265 # Check that svnlook info repairs allows inconsistent line endings in logs.
267 def info_bad_newlines(sbox):
268 "svnlook info must allow inconsistent newlines"
270 dump_str = """SVN-fs-dump-format-version: 2
272 UUID: dc40867b-38f6-0310-9f5f-f81aa277e06e
274 Revision-number: 0
275 Prop-content-length: 56
276 Content-length: 56
279 svn:date
280 V 27
281 2005-05-03T19:09:41.129900Z
282 PROPS-END
284 Revision-number: 1
285 Prop-content-length: 99
286 Content-length: 99
289 svn:log
291 \n\r\n
292 K 10
293 svn:author
297 svn:date
298 V 27
299 2005-05-03T19:10:19.975578Z
300 PROPS-END
302 Node-path: file
303 Node-kind: file
304 Node-action: add
305 Prop-content-length: 10
306 Text-content-length: 5
307 Text-content-md5: e1cbb0c3879af8347246f12c559a86b5
308 Content-length: 15
310 PROPS-END
311 text
316 # load dumpfile with inconsistent newlines into repos.
317 svntest.actions.load_repo(sbox, dump_str=dump_str)
319 output, errput = svntest.main.run_svnlook("info", sbox.repo_dir, "-r1")
320 if errput:
321 raise svntest.Failure
323 def changed_copy_info(sbox):
324 "test --copy-info flag on the changed command"
325 sbox.build()
326 wc_dir = sbox.wc_dir
327 repo_dir = sbox.repo_dir
329 # Copy alpha to /A/alpha2.
330 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
331 alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
332 alpha2_path = os.path.join(wc_dir, 'A', 'alpha2')
333 svntest.actions.run_and_verify_svn(None, None, [], 'cp', alpha_path,
334 alpha2_path)
336 # commit
337 expected_output = svntest.wc.State(wc_dir, {
338 'A/alpha2' : Item(verb='Adding'),
340 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
341 expected_status.add({
342 'A/alpha2' : Item(status=' ', wc_rev=2),
344 svntest.actions.run_and_verify_commit(wc_dir,
345 expected_output,
346 expected_status,
347 None,
348 None, None,
349 None, None,
350 wc_dir)
352 output, errput = svntest.main.run_svnlook("changed", repo_dir)
353 if errput:
354 raise svntest.Failure
356 expect("changed without --copy-info", ["A A/alpha2\n"], output)
358 output, errput = svntest.main.run_svnlook("changed", repo_dir, "--copy-info")
359 if errput:
360 raise svntest.Failure
362 expect("changed with --copy-info",
363 ["A + A/alpha2\n",
364 " (from A/B/E/alpha:r1)\n"],
365 output)
367 #----------------------------------------------------------------------
368 # Issue 2663
369 def tree_non_recursive(sbox):
370 "test 'svnlook tree --non-recursive'"
372 sbox.build()
373 repo_dir = sbox.repo_dir
375 expected_results_root = ('/', ' iota', ' A/')
376 expected_results_deep = ('B/', ' lambda', ' E/', ' F/')
378 # check the output of svnlook --non-recursive on the
379 # root of the repository
380 treelist = run_svnlook('tree', '--non-recursive', repo_dir)
381 for entry in treelist:
382 if not entry.rstrip() in expected_results_root:
383 print "Unexpected result from tree with --non-recursive:"
384 print " entry : %s" % entry.rstrip()
385 raise svntest.Failure
386 if len(treelist) != len(expected_results_root):
387 print "Expected %i output entries, found %i" \
388 % (len(expected_results_root), len(treelist))
389 raise svntest.Failure
391 # check the output of svnlook --non-recursive on a
392 # subdirectory of the repository
393 treelist = run_svnlook('tree', '--non-recursive', repo_dir, '/A/B')
394 for entry in treelist:
395 if not entry.rstrip() in expected_results_deep:
396 print "Unexpected result from tree with --non-recursive:"
397 print " entry : %s" % entry.rstrip()
398 raise svntest.Failure
399 if len(treelist) != len(expected_results_deep):
400 print "Expected %i output entries, found %i" \
401 % (len(expected_results_deep), len(treelist))
402 raise svntest.Failure
404 #----------------------------------------------------------------------
405 def limit_history(sbox):
406 "history --limit"
407 sbox.build(create_wc=False)
408 repo_url = sbox.repo_url
409 svntest.actions.run_and_verify_svn(None, None, [],
410 'mv', '-m', 'log msg',
411 repo_url + "/iota", repo_url + "/iota2")
412 svntest.actions.run_and_verify_svn(None, None, [],
413 'mv', '-m', 'log msg',
414 repo_url + "/A/mu", repo_url + "/iota")
415 history = run_svnlook("history", "--limit=1", sbox.repo_dir)
416 # Ignore the two lines of header, and verify expected number of items.
417 if len(history[2:]) != 1:
418 raise svntest.Failure("Output not limited to expected number of items")
420 #----------------------------------------------------------------------
421 def diff_ignore_whitespace(sbox):
422 "test 'svnlook diff -x -b' and 'svnlook diff -x -w'"
424 sbox.build()
425 repo_dir = sbox.repo_dir
426 wc_dir = sbox.wc_dir
428 # Make whitespace-only changes to mu
429 mu_path = os.path.join(wc_dir, 'A', 'mu')
430 svntest.main.file_write(mu_path, "This is the file 'mu'.\n", "wb")
432 # Created expected output tree for 'svn ci'
433 expected_output = svntest.wc.State(wc_dir, {
434 'A/mu' : Item(verb='Sending'),
437 # Create expected status tree; all local revisions should be at 1,
438 # but mu should be at revision 2.
439 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
440 expected_status.tweak('A/mu', wc_rev=2)
442 svntest.actions.run_and_verify_commit(wc_dir,
443 expected_output,
444 expected_status,
445 None,
446 None, None,
447 None, None,
448 wc_dir)
450 # Check the output of 'svnlook diff -x --ignore-space-change' on mu.
451 # It should not print anything.
452 output = run_svnlook('diff', '-r2', '-x', '--ignore-space-change',
453 repo_dir, '/A/mu')
454 if output != []:
455 raise svntest.Failure
457 # Check the output of 'svnlook diff -x --ignore-all-space' on mu.
458 # It should not print anything.
459 output = run_svnlook('diff', '-r2', '-x', '--ignore-all-space',
460 repo_dir, '/A/mu')
461 if output != []:
462 raise svntest.Failure
464 #----------------------------------------------------------------------
465 def diff_ignore_eolstyle(sbox):
466 "test 'svnlook diff -x --ignore-eol-style'"
468 sbox.build()
469 repo_dir = sbox.repo_dir
470 wc_dir = sbox.wc_dir
472 if os.name == 'nt':
473 crlf = '\n'
474 else:
475 crlf = '\r\n'
477 mu_path = os.path.join(wc_dir, 'A', 'mu')
479 rev = 1
480 # do the --ignore-eol-style test for each eol-style
481 for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'],
482 [crlf, '\015', '\n', '\012']):
483 # rewrite file mu and set the eol-style property.
484 svntest.main.file_write(mu_path, "This is the file 'mu'." + eolchar, 'wb')
485 svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path)
487 # Created expected output tree for 'svn ci'
488 expected_output = svntest.wc.State(wc_dir, {
489 'A/mu' : Item(verb='Sending'),
492 # Create expected status tree; all local revisions should be at
493 # revision 1, but mu should be at revision rev + 1.
494 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
495 expected_status.tweak('A/mu', wc_rev=rev + 1)
497 svntest.actions.run_and_verify_commit(wc_dir,
498 expected_output,
499 expected_status,
500 None,
501 None, None,
502 None, None,
503 wc_dir)
505 # Grab the diff
506 expected_output, err = \
507 svntest.actions.run_and_verify_svn(None, None, [], 'diff',
508 '-r', 'PREV', '-x',
509 '--ignore-eol-style', mu_path)
511 output = run_svnlook('diff', '-r', str(rev + 1), '-x',
512 '--ignore-eol-style', repo_dir, '/A/mu')
513 rev += 1
515 # replace wcdir/A/mu with A/mu in expected_output
516 for i in xrange(len(expected_output)):
517 expected_output[i] = expected_output[i].replace(mu_path, 'A/mu')
519 svntest.verify.compare_and_display_lines('', '', expected_output, output)
522 ########################################################################
523 # Run the tests
526 # list all tests here, starting with None:
527 test_list = [ None,
528 test_misc,
529 delete_file_in_moved_dir,
530 test_print_property_diffs,
531 info_bad_newlines,
532 changed_copy_info,
533 tree_non_recursive,
534 limit_history,
535 diff_ignore_whitespace,
536 diff_ignore_eolstyle,
539 if __name__ == '__main__':
540 svntest.main.run_tests(test_list)
541 # NOTREACHED
544 ### End of file.