In the command-line client, forbid
[svn.git] / subversion / tests / cmdline / history_tests.py
blob6b57d96f7ab87e64010d9469aa3abbb68ee47d8d
1 #!/usr/bin/env python
3 # history_tests.py: testing history-tracing code
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-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 os
22 # Our testing module
23 import svntest
24 from svntest import wc
26 # (abbreviation)
27 Skip = svntest.testcase.Skip
28 XFail = svntest.testcase.XFail
29 Item = wc.StateItem
31 ######################################################################
32 # Tests
34 # Each test must return on success or raise on failure.
36 #----------------------------------------------------------------------
38 def cat_traces_renames(sbox):
39 "verify that 'svn cat' traces renames"
41 sbox.build()
42 wc_dir = sbox.wc_dir
43 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
44 pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
45 bloo_path = os.path.join(wc_dir, 'A', 'D', 'G', 'bloo')
47 # rename rho to bloo. commit r2.
48 svntest.main.run_svn(None, 'mv', rho_path, bloo_path)
50 expected_output = svntest.wc.State(wc_dir, {
51 'A/D/G/rho' : Item(verb='Deleting'),
52 'A/D/G/bloo' : Item(verb='Adding')
54 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
55 expected_status.remove('A/D/G/rho');
56 expected_status.add({ 'A/D/G/bloo' :
57 Item(wc_rev=2, status=' ') })
59 svntest.actions.run_and_verify_commit(wc_dir,
60 expected_output,
61 expected_status,
62 None,
63 None, None,
64 None, None,
65 wc_dir)
67 # rename pi to rho. commit r3.
68 svntest.main.run_svn(None, 'mv', pi_path, rho_path)
70 # svn cat -r1 rho --> should show pi's contents.
71 svntest.actions.run_and_verify_svn(None,
72 [ "This is the file 'pi'.\n"], [],
73 'cat', '-r', '1', rho_path)
75 expected_output = svntest.wc.State(wc_dir, {
76 'A/D/G/pi' : Item(verb='Deleting'),
77 'A/D/G/rho' : Item(verb='Adding')
79 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
80 expected_status.remove('A/D/G/pi');
81 expected_status.tweak('A/D/G/rho', wc_rev=3)
82 expected_status.add({ 'A/D/G/bloo' :
83 Item(wc_rev=2, status=' ') })
85 svntest.actions.run_and_verify_commit(wc_dir,
86 expected_output,
87 expected_status,
88 None,
89 None, None,
90 None, None,
91 wc_dir)
93 # update whole wc to HEAD
94 expected_output = svntest.wc.State(wc_dir, { }) # no output
95 expected_status.tweak(wc_rev=3)
96 expected_disk = svntest.main.greek_state.copy()
97 expected_disk.remove('A/D/G/pi', 'A/D/G/rho')
98 expected_disk.add({
99 'A/D/G/rho' : Item("This is the file 'pi'.\n"),
101 expected_disk.add({
102 'A/D/G/bloo' : Item("This is the file 'rho'.\n"),
104 svntest.actions.run_and_verify_update(wc_dir,
105 expected_output,
106 expected_disk,
107 expected_status)
109 # 'svn cat bloo' --> should show rho's contents.
110 svntest.actions.run_and_verify_svn(None,
111 [ "This is the file 'rho'.\n"], [],
112 'cat', bloo_path)
114 # svn cat -r1 bloo --> should still show rho's contents.
115 svntest.actions.run_and_verify_svn(None,
116 [ "This is the file 'rho'.\n"], [],
117 'cat', '-r', '1', bloo_path)
119 # svn cat -r1 rho --> should show pi's contents.
120 svntest.actions.run_and_verify_svn(None,
121 [ "This is the file 'pi'.\n"], [],
122 'cat', '-r', '1', rho_path)
124 # svn up -r1
125 svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r', '1', wc_dir)
126 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
127 svntest.actions.run_and_verify_status(wc_dir, expected_status)
129 # svn cat -rHEAD rho --> should see 'unrelated object' error.
130 svntest.actions.run_and_verify_svn("unrelated object",
131 None, svntest.verify.AnyOutput,
132 'cat', '-r', 'HEAD', rho_path)
134 def cat_avoids_false_identities(sbox):
135 "verify that 'svn cat' avoids false identities"
137 sbox.build()
138 wc_dir = sbox.wc_dir
140 # Issue #1970
142 # Highlight a bug in the client side use of the repository's
143 # location searching algorithm.
145 # The buggy history-following algorithm determines the paths that a
146 # line of history would be *expected to be* found in a given revision,
147 # but doesn't treat copies as gaps in the historical sequence. If
148 # some other object fills those gaps at the same expected path, the
149 # client will find the wrong object.
151 # In the recipe below, iota gets created in r1. In r2, it is
152 # deleted and replaced with an unrelated object at the same path.
153 # In r3, the interloper is deleted. In r4, the original iota is
154 # resurrected via a copy from r1.
156 # ,- - - - - - --.
157 # o---| o---| o o----->
159 # | | | |
160 # r1 r2 r3 r4
162 # In a working copy at r4, running
164 # $ svn cat -r2 iota
166 # should result in an error, but with the bug it instead cats the r2
167 # interloper.
169 # To reassure yourself that that's wrong, recall that the above
170 # command is equivalent to
172 # $ svn cat -r2 iota@4
174 # Now do you see the evil that lies within us?
176 iota_path = os.path.join(wc_dir, 'iota')
177 iota_url = sbox.repo_url + '/iota'
179 # r2
180 svntest.main.run_svn(None, 'del', iota_path)
181 svntest.main.file_append(iota_path, "YOU SHOULD NOT SEE THIS\n")
182 svntest.main.run_svn(None, 'add', iota_path)
183 svntest.main.run_svn(None, 'ci', '-m', 'log msg',
184 wc_dir)
185 svntest.main.run_svn(None, 'up', wc_dir)
187 # r3
188 svntest.main.run_svn(None, 'del', iota_path)
189 svntest.main.run_svn(None, 'ci', '-m', 'log msg',
190 wc_dir)
191 svntest.main.run_svn(None, 'up', wc_dir)
193 # r4
194 svntest.main.run_svn(None, 'cp', iota_url + '@1', wc_dir)
195 svntest.main.run_svn(None, 'ci', '-m', 'log msg',
196 wc_dir)
197 svntest.main.run_svn(None, 'up', wc_dir)
199 # 'svn cat -r2 iota' should error, because the line of history
200 # currently identified by /iota did not exist in r2, even though a
201 # totally unrelated file of the same name did.
202 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
203 'cat', '-r', '2', iota_path)
206 ########################################################################
207 # Run the tests
209 # list all tests here, starting with None:
210 test_list = [ None,
211 cat_traces_renames,
212 cat_avoids_false_identities,
215 if __name__ == '__main__':
216 svntest.main.run_tests(test_list)
217 # NOTREACHED
220 ### End of file.