Show More
@@ -1,575 +1,577 b'' | |||
|
1 | 1 | #!/usr/bin/env python |
|
2 | 2 | # |
|
3 | 3 | # check-code - a style and portability checker for Mercurial |
|
4 | 4 | # |
|
5 | 5 | # Copyright 2010 Matt Mackall <mpm@selenic.com> |
|
6 | 6 | # |
|
7 | 7 | # This software may be used and distributed according to the terms of the |
|
8 | 8 | # GNU General Public License version 2 or any later version. |
|
9 | 9 | |
|
10 | 10 | """style and portability checker for Mercurial |
|
11 | 11 | |
|
12 | 12 | when a rule triggers wrong, do one of the following (prefer one from top): |
|
13 | 13 | * do the work-around the rule suggests |
|
14 | 14 | * doublecheck that it is a false match |
|
15 | 15 | * improve the rule pattern |
|
16 | 16 | * add an ignore pattern to the rule (3rd arg) which matches your good line |
|
17 | 17 | (you can append a short comment and match this, like: #re-raises, # no-py24) |
|
18 | 18 | * change the pattern to a warning and list the exception in test-check-code-hg |
|
19 | 19 | * ONLY use no--check-code for skipping entire files from external sources |
|
20 | 20 | """ |
|
21 | 21 | |
|
22 | 22 | import re, glob, os, sys |
|
23 | 23 | import keyword |
|
24 | 24 | import optparse |
|
25 | 25 | try: |
|
26 | 26 | import re2 |
|
27 | 27 | except ImportError: |
|
28 | 28 | re2 = None |
|
29 | 29 | |
|
30 | 30 | def compilere(pat, multiline=False): |
|
31 | 31 | if multiline: |
|
32 | 32 | pat = '(?m)' + pat |
|
33 | 33 | if re2: |
|
34 | 34 | try: |
|
35 | 35 | return re2.compile(pat) |
|
36 | 36 | except re2.error: |
|
37 | 37 | pass |
|
38 | 38 | return re.compile(pat) |
|
39 | 39 | |
|
40 | 40 | def repquote(m): |
|
41 | 41 | fromc = '.:' |
|
42 | 42 | tochr = 'pq' |
|
43 | 43 | def encodechr(i): |
|
44 | 44 | if i > 255: |
|
45 | 45 | return 'u' |
|
46 | 46 | c = chr(i) |
|
47 | 47 | if c in ' \n': |
|
48 | 48 | return c |
|
49 | 49 | if c.isalpha(): |
|
50 | 50 | return 'x' |
|
51 | 51 | if c.isdigit(): |
|
52 | 52 | return 'n' |
|
53 | 53 | try: |
|
54 | 54 | return tochr[fromc.find(c)] |
|
55 | 55 | except (ValueError, IndexError): |
|
56 | 56 | return 'o' |
|
57 | 57 | t = m.group('text') |
|
58 | 58 | tt = ''.join(encodechr(i) for i in xrange(256)) |
|
59 | 59 | t = t.translate(tt) |
|
60 | 60 | return m.group('quote') + t + m.group('quote') |
|
61 | 61 | |
|
62 | 62 | def reppython(m): |
|
63 | 63 | comment = m.group('comment') |
|
64 | 64 | if comment: |
|
65 | 65 | l = len(comment.rstrip()) |
|
66 | 66 | return "#" * l + comment[l:] |
|
67 | 67 | return repquote(m) |
|
68 | 68 | |
|
69 | 69 | def repcomment(m): |
|
70 | 70 | return m.group(1) + "#" * len(m.group(2)) |
|
71 | 71 | |
|
72 | 72 | def repccomment(m): |
|
73 | 73 | t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) |
|
74 | 74 | return m.group(1) + t + "*/" |
|
75 | 75 | |
|
76 | 76 | def repcallspaces(m): |
|
77 | 77 | t = re.sub(r"\n\s+", "\n", m.group(2)) |
|
78 | 78 | return m.group(1) + t |
|
79 | 79 | |
|
80 | 80 | def repinclude(m): |
|
81 | 81 | return m.group(1) + "<foo>" |
|
82 | 82 | |
|
83 | 83 | def rephere(m): |
|
84 | 84 | t = re.sub(r"\S", "x", m.group(2)) |
|
85 | 85 | return m.group(1) + t |
|
86 | 86 | |
|
87 | 87 | |
|
88 | 88 | testpats = [ |
|
89 | 89 | [ |
|
90 | 90 | (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"), |
|
91 | 91 | (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), |
|
92 | 92 | (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
|
93 | 93 | (r'(?<!hg )grep.*-a', "don't use 'grep -a', use in-line python"), |
|
94 | 94 | (r'sed.*-i', "don't use 'sed -i', use a temporary file"), |
|
95 | 95 | (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), |
|
96 | 96 | (r'echo -n', "don't use 'echo -n', use printf"), |
|
97 | 97 | (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"), |
|
98 | 98 | (r'head -c', "don't use 'head -c', use 'dd'"), |
|
99 | 99 | (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), |
|
100 | 100 | (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), |
|
101 | 101 | (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), |
|
102 | 102 | (r'printf.*[^\\]\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"), |
|
103 | 103 | (r'printf.*[^\\]\\x', "don't use printf \\x, use Python"), |
|
104 | 104 | (r'\$\(.*\)', "don't use $(expr), use `expr`"), |
|
105 | 105 | (r'rm -rf \*', "don't use naked rm -rf, target a directory"), |
|
106 | 106 | (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', |
|
107 | 107 | "use egrep for extended grep syntax"), |
|
108 | 108 | (r'/bin/', "don't use explicit paths for tools"), |
|
109 | 109 | (r'[^\n]\Z', "no trailing newline"), |
|
110 | 110 | (r'export.*=', "don't export and assign at once"), |
|
111 | 111 | (r'^source\b', "don't use 'source', use '.'"), |
|
112 | 112 | (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
|
113 | 113 | (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"), |
|
114 | 114 | (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
|
115 | 115 | (r'^stop\(\)', "don't use 'stop' as a shell function name"), |
|
116 | 116 | (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"), |
|
117 | 117 | (r'^alias\b.*=', "don't use alias, use a function"), |
|
118 | 118 | (r'if\s*!', "don't use '!' to negate exit status"), |
|
119 | 119 | (r'/dev/u?random', "don't use entropy, use /dev/zero"), |
|
120 | 120 | (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"), |
|
121 | 121 | (r'^( *)\t', "don't use tabs to indent"), |
|
122 | 122 | (r'sed (-e )?\'(\d+|/[^/]*/)i(?!\\\n)', |
|
123 | 123 | "put a backslash-escaped newline after sed 'i' command"), |
|
124 | 124 | (r'^diff *-\w*u.*$\n(^ \$ |^$)', "prefix diff -u with cmp"), |
|
125 | 125 | ], |
|
126 | 126 | # warnings |
|
127 | 127 | [ |
|
128 | 128 | (r'^function', "don't use 'function', use old style"), |
|
129 | 129 | (r'^diff.*-\w*N', "don't use 'diff -N'"), |
|
130 | 130 | (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"), |
|
131 | 131 | (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"), |
|
132 | 132 | (r'kill (`|\$\()', "don't use kill, use killdaemons.py") |
|
133 | 133 | ] |
|
134 | 134 | ] |
|
135 | 135 | |
|
136 | 136 | testfilters = [ |
|
137 | 137 | (r"( *)(#([^\n]*\S)?)", repcomment), |
|
138 | 138 | (r"<<(\S+)((.|\n)*?\n\1)", rephere), |
|
139 | 139 | ] |
|
140 | 140 | |
|
141 | 141 | winglobmsg = "use (glob) to match Windows paths too" |
|
142 | 142 | uprefix = r"^ \$ " |
|
143 | 143 | utestpats = [ |
|
144 | 144 | [ |
|
145 | 145 | (r'^(\S.*|| [$>] .*)[ \t]\n', "trailing whitespace on non-output"), |
|
146 | 146 | (uprefix + r'.*\|\s*sed[^|>\n]*\n', |
|
147 | 147 | "use regex test output patterns instead of sed"), |
|
148 | 148 | (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
|
149 | 149 | (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"), |
|
150 | 150 | (uprefix + r'.*\|\| echo.*(fail|error)', |
|
151 | 151 | "explicit exit code checks unnecessary"), |
|
152 | 152 | (uprefix + r'set -e', "don't use set -e"), |
|
153 | 153 | (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"), |
|
154 | 154 | (uprefix + r'.*:\.\S*/', "x:.y in a path does not work on msys, rewrite " |
|
155 | 155 | "as x://.y, or see `hg log -k msys` for alternatives", r'-\S+:\.|' #-Rxxx |
|
156 | 156 | 'hg pull -q file:../test'), # in test-pull.t which is skipped on windows |
|
157 | 157 | (r'^ saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg), |
|
158 | 158 | (r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$', |
|
159 | 159 | winglobmsg), |
|
160 | 160 | (r'^ pulling from \$TESTTMP/.*[^)]$', winglobmsg, |
|
161 | 161 | '\$TESTTMP/unix-repo$'), # in test-issue1802.t which skipped on windows |
|
162 | 162 | (r'^ reverting .*/.*[^)]$', winglobmsg), |
|
163 | 163 | (r'^ cloning subrepo \S+/.*[^)]$', winglobmsg), |
|
164 | 164 | (r'^ pushing to \$TESTTMP/.*[^)]$', winglobmsg), |
|
165 | 165 | (r'^ pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg), |
|
166 | 166 | (r'^ moving \S+/.*[^)]$', winglobmsg), |
|
167 | 167 | (r'^ no changes made to subrepo since.*/.*[^)]$', winglobmsg), |
|
168 | 168 | (r'^ .*: largefile \S+ not available from file:.*/.*[^)]$', winglobmsg), |
|
169 | 169 | (r'^ .*file://\$TESTTMP', |
|
170 | 170 | 'write "file:/*/$TESTTMP" + (glob) to match on windows too'), |
|
171 | (r'^ (cat|find): .*: No such file or directory', | |
|
172 | 'use test -f to test for file existence'), | |
|
171 | 173 | ], |
|
172 | 174 | # warnings |
|
173 | 175 | [ |
|
174 | 176 | (r'^ [^*?/\n]* \(glob\)$', |
|
175 | 177 | "glob match with no glob character (?*/)"), |
|
176 | 178 | ] |
|
177 | 179 | ] |
|
178 | 180 | |
|
179 | 181 | for i in [0, 1]: |
|
180 | 182 | for p, m in testpats[i]: |
|
181 | 183 | if p.startswith(r'^'): |
|
182 | 184 | p = r"^ [$>] (%s)" % p[1:] |
|
183 | 185 | else: |
|
184 | 186 | p = r"^ [$>] .*(%s)" % p |
|
185 | 187 | utestpats[i].append((p, m)) |
|
186 | 188 | |
|
187 | 189 | utestfilters = [ |
|
188 | 190 | (r"<<(\S+)((.|\n)*?\n > \1)", rephere), |
|
189 | 191 | (r"( *)(#([^\n]*\S)?)", repcomment), |
|
190 | 192 | ] |
|
191 | 193 | |
|
192 | 194 | pypats = [ |
|
193 | 195 | [ |
|
194 | 196 | (r'\([^)]*\*\w[^()]+\w+=', "can't pass varargs with keyword in Py2.5"), |
|
195 | 197 | (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
|
196 | 198 | "tuple parameter unpacking not available in Python 3+"), |
|
197 | 199 | (r'lambda\s*\(.*,.*\)', |
|
198 | 200 | "tuple parameter unpacking not available in Python 3+"), |
|
199 | 201 | (r'import (.+,[^.]+\.[^.]+|[^.]+\.[^.]+,)', |
|
200 | 202 | '2to3 can\'t always rewrite "import qux, foo.bar", ' |
|
201 | 203 | 'use "import foo.bar" on its own line instead.'), |
|
202 | 204 | (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
|
203 | 205 | (r'\breduce\s*\(.*', "reduce is not available in Python 3+"), |
|
204 | 206 | (r'dict\(.*=', 'dict() is different in Py2 and 3 and is slower than {}', |
|
205 | 207 | 'dict-from-generator'), |
|
206 | 208 | (r'\.has_key\b', "dict.has_key is not available in Python 3+"), |
|
207 | 209 | (r'\s<>\s', '<> operator is not available in Python 3+, use !='), |
|
208 | 210 | (r'^\s*\t', "don't use tabs"), |
|
209 | 211 | (r'\S;\s*\n', "semicolon"), |
|
210 | 212 | (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"), |
|
211 | 213 | (r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"), |
|
212 | 214 | (r'(\w|\)),\w', "missing whitespace after ,"), |
|
213 | 215 | (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"), |
|
214 | 216 | (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"), |
|
215 | 217 | (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n' |
|
216 | 218 | r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Python 2.4'), |
|
217 | 219 | (r'(?<!def)(\s+|^|\()next\(.+\)', |
|
218 | 220 | 'no next(foo) in Python 2.4 and 2.5, use foo.next() instead'), |
|
219 | 221 | (r'(\s+)try:\n((?:\n|\1\s.*\n)*?)\1\s*yield\b.*?' |
|
220 | 222 | r'((?:\n|\1\s.*\n)+?)\1finally:', |
|
221 | 223 | 'no yield inside try/finally in Python 2.4'), |
|
222 | 224 | (r'.{81}', "line too long"), |
|
223 | 225 | (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'), |
|
224 | 226 | (r'[^\n]\Z', "no trailing newline"), |
|
225 | 227 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
|
226 | 228 | # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', |
|
227 | 229 | # "don't use underbars in identifiers"), |
|
228 | 230 | (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ', |
|
229 | 231 | "don't use camelcase in identifiers"), |
|
230 | 232 | (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', |
|
231 | 233 | "linebreak after :"), |
|
232 | 234 | (r'class\s[^( \n]+:', "old-style class, use class foo(object)"), |
|
233 | 235 | (r'class\s[^( \n]+\(\):', |
|
234 | 236 | "class foo() not available in Python 2.4, use class foo(object)"), |
|
235 | 237 | (r'\b(%s)\(' % '|'.join(keyword.kwlist), |
|
236 | 238 | "Python keyword is not a function"), |
|
237 | 239 | (r',]', "unneeded trailing ',' in list"), |
|
238 | 240 | # (r'class\s[A-Z][^\(]*\((?!Exception)', |
|
239 | 241 | # "don't capitalize non-exception classes"), |
|
240 | 242 | # (r'in range\(', "use xrange"), |
|
241 | 243 | # (r'^\s*print\s+', "avoid using print in core and extensions"), |
|
242 | 244 | (r'[\x80-\xff]', "non-ASCII character literal"), |
|
243 | 245 | (r'("\')\.format\(', "str.format() not available in Python 2.4"), |
|
244 | 246 | (r'^\s*with\s+', "with not available in Python 2.4"), |
|
245 | 247 | (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"), |
|
246 | 248 | (r'^\s*except.* as .*:', "except as not available in Python 2.4"), |
|
247 | 249 | (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"), |
|
248 | 250 | (r'(?<!def)\s+(any|all|format)\(', |
|
249 | 251 | "any/all/format not available in Python 2.4", 'no-py24'), |
|
250 | 252 | (r'if\s.*\selse', "if ... else form not available in Python 2.4"), |
|
251 | 253 | (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), |
|
252 | 254 | "gratuitous whitespace after Python keyword"), |
|
253 | 255 | (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), |
|
254 | 256 | # (r'\s\s=', "gratuitous whitespace before ="), |
|
255 | 257 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', |
|
256 | 258 | "missing whitespace around operator"), |
|
257 | 259 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s', |
|
258 | 260 | "missing whitespace around operator"), |
|
259 | 261 | (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', |
|
260 | 262 | "missing whitespace around operator"), |
|
261 | 263 | (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]', |
|
262 | 264 | "wrong whitespace around ="), |
|
263 | 265 | (r'\([^()]*( =[^=]|[^<>!=]= )', |
|
264 | 266 | "no whitespace around = for named parameters"), |
|
265 | 267 | (r'raise Exception', "don't raise generic exceptions"), |
|
266 | 268 | (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$', |
|
267 | 269 | "don't use old-style two-argument raise, use Exception(message)"), |
|
268 | 270 | (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
|
269 | 271 | (r' [=!]=\s+(True|False|None)', |
|
270 | 272 | "comparison with singleton, use 'is' or 'is not' instead"), |
|
271 | 273 | (r'^\s*(while|if) [01]:', |
|
272 | 274 | "use True/False for constant Boolean expression"), |
|
273 | 275 | (r'(?:(?<!def)\s+|\()hasattr', |
|
274 | 276 | 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), |
|
275 | 277 | (r'opener\([^)]*\).read\(', |
|
276 | 278 | "use opener.read() instead"), |
|
277 | 279 | (r'BaseException', 'not in Python 2.4, use Exception'), |
|
278 | 280 | (r'os\.path\.relpath', 'os.path.relpath is not in Python 2.5'), |
|
279 | 281 | (r'opener\([^)]*\).write\(', |
|
280 | 282 | "use opener.write() instead"), |
|
281 | 283 | (r'[\s\(](open|file)\([^)]*\)\.read\(', |
|
282 | 284 | "use util.readfile() instead"), |
|
283 | 285 | (r'[\s\(](open|file)\([^)]*\)\.write\(', |
|
284 | 286 | "use util.writefile() instead"), |
|
285 | 287 | (r'^[\s\(]*(open(er)?|file)\([^)]*\)', |
|
286 | 288 | "always assign an opened file to a variable, and close it afterwards"), |
|
287 | 289 | (r'[\s\(](open|file)\([^)]*\)\.', |
|
288 | 290 | "always assign an opened file to a variable, and close it afterwards"), |
|
289 | 291 | (r'(?i)descendent', "the proper spelling is descendAnt"), |
|
290 | 292 | (r'\.debug\(\_', "don't mark debug messages for translation"), |
|
291 | 293 | (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"), |
|
292 | 294 | (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'), |
|
293 | 295 | (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"), |
|
294 | 296 | (r'ui\.(status|progress|write|note|warn)\([\'\"]x', |
|
295 | 297 | "missing _() in ui message (use () to hide false-positives)"), |
|
296 | 298 | (r'release\(.*wlock, .*lock\)', "wrong lock release order"), |
|
297 | 299 | ], |
|
298 | 300 | # warnings |
|
299 | 301 | [ |
|
300 | 302 | (r'(^| )pp +xxxxqq[ \n][^\n]', "add two newlines after '.. note::'"), |
|
301 | 303 | ] |
|
302 | 304 | ] |
|
303 | 305 | |
|
304 | 306 | pyfilters = [ |
|
305 | 307 | (r"""(?msx)(?P<comment>\#.*?$)| |
|
306 | 308 | ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
|
307 | 309 | (?P<text>(([^\\]|\\.)*?)) |
|
308 | 310 | (?P=quote))""", reppython), |
|
309 | 311 | ] |
|
310 | 312 | |
|
311 | 313 | txtfilters = [] |
|
312 | 314 | |
|
313 | 315 | txtpats = [ |
|
314 | 316 | [ |
|
315 | 317 | ('\s$', 'trailing whitespace'), |
|
316 | 318 | ('.. note::[ \n][^\n]', 'add two newlines after note::') |
|
317 | 319 | ], |
|
318 | 320 | [] |
|
319 | 321 | ] |
|
320 | 322 | |
|
321 | 323 | cpats = [ |
|
322 | 324 | [ |
|
323 | 325 | (r'//', "don't use //-style comments"), |
|
324 | 326 | (r'^ ', "don't use spaces to indent"), |
|
325 | 327 | (r'\S\t', "don't use tabs except for indent"), |
|
326 | 328 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
|
327 | 329 | (r'.{81}', "line too long"), |
|
328 | 330 | (r'(while|if|do|for)\(', "use space after while/if/do/for"), |
|
329 | 331 | (r'return\(', "return is not a function"), |
|
330 | 332 | (r' ;', "no space before ;"), |
|
331 | 333 | (r'[)][{]', "space between ) and {"), |
|
332 | 334 | (r'\w+\* \w+', "use int *foo, not int* foo"), |
|
333 | 335 | (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"), |
|
334 | 336 | (r'\w+ (\+\+|--)', "use foo++, not foo ++"), |
|
335 | 337 | (r'\w,\w', "missing whitespace after ,"), |
|
336 | 338 | (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
|
337 | 339 | (r'^#\s+\w', "use #foo, not # foo"), |
|
338 | 340 | (r'[^\n]\Z', "no trailing newline"), |
|
339 | 341 | (r'^\s*#import\b', "use only #include in standard C code"), |
|
340 | 342 | ], |
|
341 | 343 | # warnings |
|
342 | 344 | [] |
|
343 | 345 | ] |
|
344 | 346 | |
|
345 | 347 | cfilters = [ |
|
346 | 348 | (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), |
|
347 | 349 | (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
|
348 | 350 | (r'''(#\s*include\s+<)([^>]+)>''', repinclude), |
|
349 | 351 | (r'(\()([^)]+\))', repcallspaces), |
|
350 | 352 | ] |
|
351 | 353 | |
|
352 | 354 | inutilpats = [ |
|
353 | 355 | [ |
|
354 | 356 | (r'\bui\.', "don't use ui in util"), |
|
355 | 357 | ], |
|
356 | 358 | # warnings |
|
357 | 359 | [] |
|
358 | 360 | ] |
|
359 | 361 | |
|
360 | 362 | inrevlogpats = [ |
|
361 | 363 | [ |
|
362 | 364 | (r'\brepo\.', "don't use repo in revlog"), |
|
363 | 365 | ], |
|
364 | 366 | # warnings |
|
365 | 367 | [] |
|
366 | 368 | ] |
|
367 | 369 | |
|
368 | 370 | webtemplatefilters = [] |
|
369 | 371 | |
|
370 | 372 | webtemplatepats = [ |
|
371 | 373 | [], |
|
372 | 374 | [ |
|
373 | 375 | (r'{desc(\|(?!websub|firstline)[^\|]*)+}', |
|
374 | 376 | 'follow desc keyword with either firstline or websub'), |
|
375 | 377 | ] |
|
376 | 378 | ] |
|
377 | 379 | |
|
378 | 380 | checks = [ |
|
379 | 381 | ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats), |
|
380 | 382 | ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats), |
|
381 | 383 | ('c', r'.*\.[ch]$', '', cfilters, cpats), |
|
382 | 384 | ('unified test', r'.*\.t$', '', utestfilters, utestpats), |
|
383 | 385 | ('layering violation repo in revlog', r'mercurial/revlog\.py', '', |
|
384 | 386 | pyfilters, inrevlogpats), |
|
385 | 387 | ('layering violation ui in util', r'mercurial/util\.py', '', pyfilters, |
|
386 | 388 | inutilpats), |
|
387 | 389 | ('txt', r'.*\.txt$', '', txtfilters, txtpats), |
|
388 | 390 | ('web template', r'mercurial/templates/.*\.tmpl', '', |
|
389 | 391 | webtemplatefilters, webtemplatepats), |
|
390 | 392 | ] |
|
391 | 393 | |
|
392 | 394 | def _preparepats(): |
|
393 | 395 | for c in checks: |
|
394 | 396 | failandwarn = c[-1] |
|
395 | 397 | for pats in failandwarn: |
|
396 | 398 | for i, pseq in enumerate(pats): |
|
397 | 399 | # fix-up regexes for multi-line searches |
|
398 | 400 | p = pseq[0] |
|
399 | 401 | # \s doesn't match \n |
|
400 | 402 | p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p) |
|
401 | 403 | # [^...] doesn't match newline |
|
402 | 404 | p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) |
|
403 | 405 | |
|
404 | 406 | pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:] |
|
405 | 407 | filters = c[3] |
|
406 | 408 | for i, flt in enumerate(filters): |
|
407 | 409 | filters[i] = re.compile(flt[0]), flt[1] |
|
408 | 410 | _preparepats() |
|
409 | 411 | |
|
410 | 412 | class norepeatlogger(object): |
|
411 | 413 | def __init__(self): |
|
412 | 414 | self._lastseen = None |
|
413 | 415 | |
|
414 | 416 | def log(self, fname, lineno, line, msg, blame): |
|
415 | 417 | """print error related a to given line of a given file. |
|
416 | 418 | |
|
417 | 419 | The faulty line will also be printed but only once in the case |
|
418 | 420 | of multiple errors. |
|
419 | 421 | |
|
420 | 422 | :fname: filename |
|
421 | 423 | :lineno: line number |
|
422 | 424 | :line: actual content of the line |
|
423 | 425 | :msg: error message |
|
424 | 426 | """ |
|
425 | 427 | msgid = fname, lineno, line |
|
426 | 428 | if msgid != self._lastseen: |
|
427 | 429 | if blame: |
|
428 | 430 | print "%s:%d (%s):" % (fname, lineno, blame) |
|
429 | 431 | else: |
|
430 | 432 | print "%s:%d:" % (fname, lineno) |
|
431 | 433 | print " > %s" % line |
|
432 | 434 | self._lastseen = msgid |
|
433 | 435 | print " " + msg |
|
434 | 436 | |
|
435 | 437 | _defaultlogger = norepeatlogger() |
|
436 | 438 | |
|
437 | 439 | def getblame(f): |
|
438 | 440 | lines = [] |
|
439 | 441 | for l in os.popen('hg annotate -un %s' % f): |
|
440 | 442 | start, line = l.split(':', 1) |
|
441 | 443 | user, rev = start.split() |
|
442 | 444 | lines.append((line[1:-1], user, rev)) |
|
443 | 445 | return lines |
|
444 | 446 | |
|
445 | 447 | def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, |
|
446 | 448 | blame=False, debug=False, lineno=True): |
|
447 | 449 | """checks style and portability of a given file |
|
448 | 450 | |
|
449 | 451 | :f: filepath |
|
450 | 452 | :logfunc: function used to report error |
|
451 | 453 | logfunc(filename, linenumber, linecontent, errormessage) |
|
452 | 454 | :maxerr: number of error to display before aborting. |
|
453 | 455 | Set to false (default) to report all errors |
|
454 | 456 | |
|
455 | 457 | return True if no error is found, False otherwise. |
|
456 | 458 | """ |
|
457 | 459 | blamecache = None |
|
458 | 460 | result = True |
|
459 | 461 | |
|
460 | 462 | try: |
|
461 | 463 | fp = open(f) |
|
462 | 464 | except IOError, e: |
|
463 | 465 | print "Skipping %s, %s" % (f, str(e).split(':', 1)[0]) |
|
464 | 466 | return result |
|
465 | 467 | pre = post = fp.read() |
|
466 | 468 | fp.close() |
|
467 | 469 | |
|
468 | 470 | for name, match, magic, filters, pats in checks: |
|
469 | 471 | if debug: |
|
470 | 472 | print name, f |
|
471 | 473 | fc = 0 |
|
472 | 474 | if not (re.match(match, f) or (magic and re.search(magic, f))): |
|
473 | 475 | if debug: |
|
474 | 476 | print "Skipping %s for %s it doesn't match %s" % ( |
|
475 | 477 | name, match, f) |
|
476 | 478 | continue |
|
477 | 479 | if "no-" "check-code" in pre: |
|
478 | 480 | print "Skipping %s it has no-" "check-code" % f |
|
479 | 481 | return "Skip" # skip checking this file |
|
480 | 482 | for p, r in filters: |
|
481 | 483 | post = re.sub(p, r, post) |
|
482 | 484 | nerrs = len(pats[0]) # nerr elements are errors |
|
483 | 485 | if warnings: |
|
484 | 486 | pats = pats[0] + pats[1] |
|
485 | 487 | else: |
|
486 | 488 | pats = pats[0] |
|
487 | 489 | # print post # uncomment to show filtered version |
|
488 | 490 | |
|
489 | 491 | if debug: |
|
490 | 492 | print "Checking %s for %s" % (name, f) |
|
491 | 493 | |
|
492 | 494 | prelines = None |
|
493 | 495 | errors = [] |
|
494 | 496 | for i, pat in enumerate(pats): |
|
495 | 497 | if len(pat) == 3: |
|
496 | 498 | p, msg, ignore = pat |
|
497 | 499 | else: |
|
498 | 500 | p, msg = pat |
|
499 | 501 | ignore = None |
|
500 | 502 | if i >= nerrs: |
|
501 | 503 | msg = "warning: " + msg |
|
502 | 504 | |
|
503 | 505 | pos = 0 |
|
504 | 506 | n = 0 |
|
505 | 507 | for m in p.finditer(post): |
|
506 | 508 | if prelines is None: |
|
507 | 509 | prelines = pre.splitlines() |
|
508 | 510 | postlines = post.splitlines(True) |
|
509 | 511 | |
|
510 | 512 | start = m.start() |
|
511 | 513 | while n < len(postlines): |
|
512 | 514 | step = len(postlines[n]) |
|
513 | 515 | if pos + step > start: |
|
514 | 516 | break |
|
515 | 517 | pos += step |
|
516 | 518 | n += 1 |
|
517 | 519 | l = prelines[n] |
|
518 | 520 | |
|
519 | 521 | if ignore and re.search(ignore, l, re.MULTILINE): |
|
520 | 522 | if debug: |
|
521 | 523 | print "Skipping %s for %s:%s (ignore pattern)" % ( |
|
522 | 524 | name, f, n) |
|
523 | 525 | continue |
|
524 | 526 | bd = "" |
|
525 | 527 | if blame: |
|
526 | 528 | bd = 'working directory' |
|
527 | 529 | if not blamecache: |
|
528 | 530 | blamecache = getblame(f) |
|
529 | 531 | if n < len(blamecache): |
|
530 | 532 | bl, bu, br = blamecache[n] |
|
531 | 533 | if bl == l: |
|
532 | 534 | bd = '%s@%s' % (bu, br) |
|
533 | 535 | |
|
534 | 536 | errors.append((f, lineno and n + 1, l, msg, bd)) |
|
535 | 537 | result = False |
|
536 | 538 | |
|
537 | 539 | errors.sort() |
|
538 | 540 | for e in errors: |
|
539 | 541 | logfunc(*e) |
|
540 | 542 | fc += 1 |
|
541 | 543 | if maxerr and fc >= maxerr: |
|
542 | 544 | print " (too many errors, giving up)" |
|
543 | 545 | break |
|
544 | 546 | |
|
545 | 547 | return result |
|
546 | 548 | |
|
547 | 549 | if __name__ == "__main__": |
|
548 | 550 | parser = optparse.OptionParser("%prog [options] [files]") |
|
549 | 551 | parser.add_option("-w", "--warnings", action="store_true", |
|
550 | 552 | help="include warning-level checks") |
|
551 | 553 | parser.add_option("-p", "--per-file", type="int", |
|
552 | 554 | help="max warnings per file") |
|
553 | 555 | parser.add_option("-b", "--blame", action="store_true", |
|
554 | 556 | help="use annotate to generate blame info") |
|
555 | 557 | parser.add_option("", "--debug", action="store_true", |
|
556 | 558 | help="show debug information") |
|
557 | 559 | parser.add_option("", "--nolineno", action="store_false", |
|
558 | 560 | dest='lineno', help="don't show line numbers") |
|
559 | 561 | |
|
560 | 562 | parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False, |
|
561 | 563 | lineno=True) |
|
562 | 564 | (options, args) = parser.parse_args() |
|
563 | 565 | |
|
564 | 566 | if len(args) == 0: |
|
565 | 567 | check = glob.glob("*") |
|
566 | 568 | else: |
|
567 | 569 | check = args |
|
568 | 570 | |
|
569 | 571 | ret = 0 |
|
570 | 572 | for f in check: |
|
571 | 573 | if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, |
|
572 | 574 | blame=options.blame, debug=options.debug, |
|
573 | 575 | lineno=options.lineno): |
|
574 | 576 | ret = 1 |
|
575 | 577 | sys.exit(ret) |
@@ -1,346 +1,345 b'' | |||
|
1 | 1 | $ . "$TESTDIR/histedit-helpers.sh" |
|
2 | 2 | |
|
3 | 3 | $ cat >> $HGRCPATH <<EOF |
|
4 | 4 | > [extensions] |
|
5 | 5 | > histedit= |
|
6 | 6 | > EOF |
|
7 | 7 | |
|
8 | 8 | $ initrepo () |
|
9 | 9 | > { |
|
10 | 10 | > hg init r |
|
11 | 11 | > cd r |
|
12 | 12 | > for x in a b c d e f ; do |
|
13 | 13 | > echo $x > $x |
|
14 | 14 | > hg add $x |
|
15 | 15 | > hg ci -m $x |
|
16 | 16 | > done |
|
17 | 17 | > } |
|
18 | 18 | |
|
19 | 19 | $ initrepo |
|
20 | 20 | |
|
21 | 21 | log before edit |
|
22 | 22 | $ hg log --graph |
|
23 | 23 | @ changeset: 5:652413bf663e |
|
24 | 24 | | tag: tip |
|
25 | 25 | | user: test |
|
26 | 26 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
27 | 27 | | summary: f |
|
28 | 28 | | |
|
29 | 29 | o changeset: 4:e860deea161a |
|
30 | 30 | | user: test |
|
31 | 31 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
32 | 32 | | summary: e |
|
33 | 33 | | |
|
34 | 34 | o changeset: 3:055a42cdd887 |
|
35 | 35 | | user: test |
|
36 | 36 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
37 | 37 | | summary: d |
|
38 | 38 | | |
|
39 | 39 | o changeset: 2:177f92b77385 |
|
40 | 40 | | user: test |
|
41 | 41 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
42 | 42 | | summary: c |
|
43 | 43 | | |
|
44 | 44 | o changeset: 1:d2ae7f538514 |
|
45 | 45 | | user: test |
|
46 | 46 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
47 | 47 | | summary: b |
|
48 | 48 | | |
|
49 | 49 | o changeset: 0:cb9a9f314b8b |
|
50 | 50 | user: test |
|
51 | 51 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
52 | 52 | summary: a |
|
53 | 53 | |
|
54 | 54 | |
|
55 | 55 | edit the history |
|
56 | 56 | $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle |
|
57 | 57 | > pick 177f92b77385 c |
|
58 | 58 | > pick 055a42cdd887 d |
|
59 | 59 | > edit e860deea161a e |
|
60 | 60 | > pick 652413bf663e f |
|
61 | 61 | > EOF |
|
62 | 62 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
63 | 63 | Make changes as needed, you may commit or record as needed now. |
|
64 | 64 | When you are finished, run hg histedit --continue to resume. |
|
65 | 65 | |
|
66 | 66 | Go at a random point and try to continue |
|
67 | 67 | |
|
68 | 68 | $ hg id -n |
|
69 | 69 | 3+ |
|
70 | 70 | $ hg up 0 |
|
71 | 71 | abort: histedit in progress |
|
72 | 72 | (use 'hg histedit --continue' or 'hg histedit --abort') |
|
73 | 73 | [255] |
|
74 | 74 | |
|
75 | 75 | commit, then edit the revision |
|
76 | 76 | $ hg ci -m 'wat' |
|
77 | 77 | created new head |
|
78 | 78 | $ echo a > e |
|
79 | 79 | $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle |
|
80 | 80 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
81 | 81 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
82 | 82 | |
|
83 | 83 | $ hg log --graph |
|
84 | 84 | @ changeset: 6:b5f70786f9b0 |
|
85 | 85 | | tag: tip |
|
86 | 86 | | user: test |
|
87 | 87 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
88 | 88 | | summary: f |
|
89 | 89 | | |
|
90 | 90 | o changeset: 5:a5e1ba2f7afb |
|
91 | 91 | | user: test |
|
92 | 92 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
93 | 93 | | summary: foobaz |
|
94 | 94 | | |
|
95 | 95 | o changeset: 4:1a60820cd1f6 |
|
96 | 96 | | user: test |
|
97 | 97 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
98 | 98 | | summary: wat |
|
99 | 99 | | |
|
100 | 100 | o changeset: 3:055a42cdd887 |
|
101 | 101 | | user: test |
|
102 | 102 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
103 | 103 | | summary: d |
|
104 | 104 | | |
|
105 | 105 | o changeset: 2:177f92b77385 |
|
106 | 106 | | user: test |
|
107 | 107 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
108 | 108 | | summary: c |
|
109 | 109 | | |
|
110 | 110 | o changeset: 1:d2ae7f538514 |
|
111 | 111 | | user: test |
|
112 | 112 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
113 | 113 | | summary: b |
|
114 | 114 | | |
|
115 | 115 | o changeset: 0:cb9a9f314b8b |
|
116 | 116 | user: test |
|
117 | 117 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
118 | 118 | summary: a |
|
119 | 119 | |
|
120 | 120 | |
|
121 | 121 | $ hg cat e |
|
122 | 122 | a |
|
123 | 123 | |
|
124 | 124 | check histedit_source |
|
125 | 125 | |
|
126 | 126 | $ hg log --debug --rev 5 |
|
127 | 127 | changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d |
|
128 | 128 | phase: draft |
|
129 | 129 | parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34 |
|
130 | 130 | parent: -1:0000000000000000000000000000000000000000 |
|
131 | 131 | manifest: 5:5ad3be8791f39117565557781f5464363b918a45 |
|
132 | 132 | user: test |
|
133 | 133 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
134 | 134 | files: e |
|
135 | 135 | extra: branch=default |
|
136 | 136 | extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae |
|
137 | 137 | description: |
|
138 | 138 | foobaz |
|
139 | 139 | |
|
140 | 140 | |
|
141 | 141 | |
|
142 | 142 | $ hg histedit tip --commands - 2>&1 <<EOF| fixbundle |
|
143 | 143 | > edit b5f70786f9b0 f |
|
144 | 144 | > EOF |
|
145 | 145 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
146 | 146 | Make changes as needed, you may commit or record as needed now. |
|
147 | 147 | When you are finished, run hg histedit --continue to resume. |
|
148 | 148 | $ hg status |
|
149 | 149 | A f |
|
150 | 150 | |
|
151 | 151 | $ hg summary |
|
152 | 152 | parent: 5:a5e1ba2f7afb |
|
153 | 153 | foobaz |
|
154 | 154 | branch: default |
|
155 | 155 | commit: 1 added (new branch head) |
|
156 | 156 | update: 1 new changesets (update) |
|
157 | 157 | hist: 1 remaining (histedit --continue) |
|
158 | 158 | |
|
159 | 159 | (test also that editor is invoked if histedit is continued for |
|
160 | 160 | "edit" action) |
|
161 | 161 | |
|
162 | 162 | $ HGEDITOR='cat' hg histedit --continue |
|
163 | 163 | f |
|
164 | 164 | |
|
165 | 165 | |
|
166 | 166 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
167 | 167 | HG: Leave message empty to abort commit. |
|
168 | 168 | HG: -- |
|
169 | 169 | HG: user: test |
|
170 | 170 | HG: branch 'default' |
|
171 | 171 | HG: added f |
|
172 | 172 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
173 | 173 | saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-backup.hg (glob) |
|
174 | 174 | |
|
175 | 175 | $ hg status |
|
176 | 176 | |
|
177 | 177 | log after edit |
|
178 | 178 | $ hg log --limit 1 |
|
179 | 179 | changeset: 6:a107ee126658 |
|
180 | 180 | tag: tip |
|
181 | 181 | user: test |
|
182 | 182 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
183 | 183 | summary: f |
|
184 | 184 | |
|
185 | 185 | |
|
186 | 186 | say we'll change the message, but don't. |
|
187 | 187 | $ cat > ../edit.sh <<EOF |
|
188 | 188 | > cat "\$1" | sed s/pick/mess/ > tmp |
|
189 | 189 | > mv tmp "\$1" |
|
190 | 190 | > EOF |
|
191 | 191 | $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle |
|
192 | 192 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
193 | 193 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
194 | 194 | $ hg status |
|
195 | 195 | $ hg log --limit 1 |
|
196 | 196 | changeset: 6:1fd3b2fe7754 |
|
197 | 197 | tag: tip |
|
198 | 198 | user: test |
|
199 | 199 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
200 | 200 | summary: f |
|
201 | 201 | |
|
202 | 202 | |
|
203 | 203 | modify the message |
|
204 | 204 | |
|
205 | 205 | check saving last-message.txt, at first |
|
206 | 206 | |
|
207 | 207 | $ cat > $TESTTMP/commitfailure.py <<EOF |
|
208 | 208 | > from mercurial import util |
|
209 | 209 | > def reposetup(ui, repo): |
|
210 | 210 | > class commitfailure(repo.__class__): |
|
211 | 211 | > def commit(self, *args, **kwargs): |
|
212 | 212 | > raise util.Abort('emulating unexpected abort') |
|
213 | 213 | > repo.__class__ = commitfailure |
|
214 | 214 | > EOF |
|
215 | 215 | $ cat >> .hg/hgrc <<EOF |
|
216 | 216 | > [extensions] |
|
217 | 217 | > # this failure occurs before editor invocation |
|
218 | 218 | > commitfailure = $TESTTMP/commitfailure.py |
|
219 | 219 | > EOF |
|
220 | 220 | |
|
221 | 221 | $ cat > $TESTTMP/editor.sh <<EOF |
|
222 | 222 | > echo "==== before editing" |
|
223 | 223 | > cat \$1 |
|
224 | 224 | > echo "====" |
|
225 | 225 | > echo "check saving last-message.txt" >> \$1 |
|
226 | 226 | > EOF |
|
227 | 227 | |
|
228 | 228 | (test that editor is not invoked before transaction starting) |
|
229 | 229 | |
|
230 | 230 | $ rm -f .hg/last-message.txt |
|
231 | 231 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF | fixbundle |
|
232 | 232 | > mess 1fd3b2fe7754 f |
|
233 | 233 | > EOF |
|
234 | 234 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
235 | 235 | abort: emulating unexpected abort |
|
236 |
$ |
|
|
237 | cat: .hg/last-message.txt: No such file or directory | |
|
236 | $ test -f .hg/last-message.txt | |
|
238 | 237 | [1] |
|
239 | 238 | |
|
240 | 239 | $ cat >> .hg/hgrc <<EOF |
|
241 | 240 | > [extensions] |
|
242 | 241 | > commitfailure = ! |
|
243 | 242 | > EOF |
|
244 | 243 | $ hg histedit --abort -q |
|
245 | 244 | |
|
246 | 245 | (test that editor is invoked and commit message is saved into |
|
247 | 246 | "last-message.txt") |
|
248 | 247 | |
|
249 | 248 | $ cat >> .hg/hgrc <<EOF |
|
250 | 249 | > [hooks] |
|
251 | 250 | > # this failure occurs after editor invocation |
|
252 | 251 | > pretxncommit.unexpectedabort = false |
|
253 | 252 | > EOF |
|
254 | 253 | |
|
255 | 254 | $ hg status --rev '1fd3b2fe7754^1' --rev 1fd3b2fe7754 |
|
256 | 255 | A f |
|
257 | 256 | |
|
258 | 257 | $ rm -f .hg/last-message.txt |
|
259 | 258 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF |
|
260 | 259 | > mess 1fd3b2fe7754 f |
|
261 | 260 | > EOF |
|
262 | 261 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
263 | 262 | adding f |
|
264 | 263 | ==== before editing |
|
265 | 264 | f |
|
266 | 265 | |
|
267 | 266 | |
|
268 | 267 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
269 | 268 | HG: Leave message empty to abort commit. |
|
270 | 269 | HG: -- |
|
271 | 270 | HG: user: test |
|
272 | 271 | HG: branch 'default' |
|
273 | 272 | HG: added f |
|
274 | 273 | ==== |
|
275 | 274 | transaction abort! |
|
276 | 275 | rollback completed |
|
277 | 276 | note: commit message saved in .hg/last-message.txt |
|
278 | 277 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
279 | 278 | [255] |
|
280 | 279 | $ cat .hg/last-message.txt |
|
281 | 280 | f |
|
282 | 281 | |
|
283 | 282 | |
|
284 | 283 | check saving last-message.txt |
|
285 | 284 | |
|
286 | 285 | (test also that editor is invoked if histedit is continued for "message" |
|
287 | 286 | action) |
|
288 | 287 | |
|
289 | 288 | $ HGEDITOR=cat hg histedit --continue |
|
290 | 289 | f |
|
291 | 290 | |
|
292 | 291 | |
|
293 | 292 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
294 | 293 | HG: Leave message empty to abort commit. |
|
295 | 294 | HG: -- |
|
296 | 295 | HG: user: test |
|
297 | 296 | HG: branch 'default' |
|
298 | 297 | HG: added f |
|
299 | 298 | transaction abort! |
|
300 | 299 | rollback completed |
|
301 | 300 | note: commit message saved in .hg/last-message.txt |
|
302 | 301 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
303 | 302 | [255] |
|
304 | 303 | |
|
305 | 304 | $ cat >> .hg/hgrc <<EOF |
|
306 | 305 | > [hooks] |
|
307 | 306 | > pretxncommit.unexpectedabort = |
|
308 | 307 | > EOF |
|
309 | 308 | $ hg histedit --abort -q |
|
310 | 309 | |
|
311 | 310 | then, check "modify the message" itself |
|
312 | 311 | |
|
313 | 312 | $ hg histedit tip --commands - 2>&1 << EOF | fixbundle |
|
314 | 313 | > mess 1fd3b2fe7754 f |
|
315 | 314 | > EOF |
|
316 | 315 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
317 | 316 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
318 | 317 | $ hg status |
|
319 | 318 | $ hg log --limit 1 |
|
320 | 319 | changeset: 6:62feedb1200e |
|
321 | 320 | tag: tip |
|
322 | 321 | user: test |
|
323 | 322 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
324 | 323 | summary: f |
|
325 | 324 | |
|
326 | 325 | |
|
327 | 326 | rollback should not work after a histedit |
|
328 | 327 | $ hg rollback |
|
329 | 328 | no rollback information available |
|
330 | 329 | [1] |
|
331 | 330 | |
|
332 | 331 | $ cd .. |
|
333 | 332 | $ hg clone -qr0 r r0 |
|
334 | 333 | $ cd r0 |
|
335 | 334 | $ hg phase -fdr0 |
|
336 | 335 | $ hg histedit --commands - 0 2>&1 << EOF |
|
337 | 336 | > edit cb9a9f314b8b a > $EDITED |
|
338 | 337 | > EOF |
|
339 | 338 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
340 | 339 | adding a |
|
341 | 340 | Make changes as needed, you may commit or record as needed now. |
|
342 | 341 | When you are finished, run hg histedit --continue to resume. |
|
343 | 342 | [1] |
|
344 | 343 | $ HGEDITOR=true hg histedit --continue |
|
345 | 344 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
346 | 345 | saved backup bundle to $TESTTMP/r0/.hg/strip-backup/cb9a9f314b8b-backup.hg (glob) |
@@ -1,370 +1,369 b'' | |||
|
1 | 1 | |
|
2 | 2 | $ echo "[extensions]" >> $HGRCPATH |
|
3 | 3 | $ echo "largefiles =" >> $HGRCPATH |
|
4 | 4 | |
|
5 | 5 | Create the repository outside $HOME since largefiles write to |
|
6 | 6 | $HOME/.cache/largefiles. |
|
7 | 7 | |
|
8 | 8 | $ hg init test |
|
9 | 9 | $ cd test |
|
10 | 10 | $ echo "root" > root |
|
11 | 11 | $ hg add root |
|
12 | 12 | $ hg commit -m "Root commit" |
|
13 | 13 | |
|
14 | 14 | $ echo "large" > foo |
|
15 | 15 | $ hg add --large foo |
|
16 | 16 | $ hg commit -m "Add foo as a largefile" |
|
17 | 17 | |
|
18 | 18 | $ hg update -r 0 |
|
19 | 19 | getting changed largefiles |
|
20 | 20 | 0 largefiles updated, 1 removed |
|
21 | 21 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
22 | 22 | |
|
23 | 23 | $ echo "normal" > foo |
|
24 | 24 | $ hg add foo |
|
25 | 25 | $ hg commit -m "Add foo as normal file" |
|
26 | 26 | created new head |
|
27 | 27 | |
|
28 | 28 | Normal file in the working copy, keeping the normal version: |
|
29 | 29 | |
|
30 | 30 | $ echo "n" | hg merge --config ui.interactive=Yes |
|
31 | 31 | remote turned local normal file foo into a largefile |
|
32 | 32 | use (l)argefile or keep (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
33 | 33 | (branch merge, don't forget to commit) |
|
34 | 34 | getting changed largefiles |
|
35 | 35 | 0 largefiles updated, 0 removed |
|
36 | 36 | |
|
37 | 37 | $ hg status |
|
38 | 38 | $ cat foo |
|
39 | 39 | normal |
|
40 | 40 | |
|
41 | 41 | Normal file in the working copy, keeping the largefile version: |
|
42 | 42 | |
|
43 | 43 | $ hg update -q -C |
|
44 | 44 | $ echo "l" | hg merge --config ui.interactive=Yes |
|
45 | 45 | remote turned local normal file foo into a largefile |
|
46 | 46 | use (l)argefile or keep (n)ormal file? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
47 | 47 | (branch merge, don't forget to commit) |
|
48 | 48 | getting changed largefiles |
|
49 | 49 | 1 largefiles updated, 0 removed |
|
50 | 50 | |
|
51 | 51 | $ hg status |
|
52 | 52 | M foo |
|
53 | 53 | |
|
54 | 54 | $ hg diff --nodates |
|
55 | 55 | diff -r fa129ab6b5a7 .hglf/foo |
|
56 | 56 | --- /dev/null |
|
57 | 57 | +++ b/.hglf/foo |
|
58 | 58 | @@ -0,0 +1,1 @@ |
|
59 | 59 | +7f7097b041ccf68cc5561e9600da4655d21c6d18 |
|
60 | 60 | diff -r fa129ab6b5a7 foo |
|
61 | 61 | --- a/foo |
|
62 | 62 | +++ /dev/null |
|
63 | 63 | @@ -1,1 +0,0 @@ |
|
64 | 64 | -normal |
|
65 | 65 | |
|
66 | 66 | $ cat foo |
|
67 | 67 | large |
|
68 | 68 | |
|
69 | 69 | Largefile in the working copy, keeping the normal version: |
|
70 | 70 | |
|
71 | 71 | $ hg update -q -C -r 1 |
|
72 | 72 | $ echo "n" | hg merge --config ui.interactive=Yes |
|
73 | 73 | remote turned local largefile foo into a normal file |
|
74 | 74 | keep (l)argefile or use (n)ormal file? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
75 | 75 | (branch merge, don't forget to commit) |
|
76 | 76 | getting changed largefiles |
|
77 | 77 | 0 largefiles updated, 0 removed |
|
78 | 78 | |
|
79 | 79 | $ hg status |
|
80 | 80 | M foo |
|
81 | 81 | |
|
82 | 82 | $ hg diff --nodates |
|
83 | 83 | diff -r ff521236428a .hglf/foo |
|
84 | 84 | --- a/.hglf/foo |
|
85 | 85 | +++ /dev/null |
|
86 | 86 | @@ -1,1 +0,0 @@ |
|
87 | 87 | -7f7097b041ccf68cc5561e9600da4655d21c6d18 |
|
88 | 88 | diff -r ff521236428a foo |
|
89 | 89 | --- /dev/null |
|
90 | 90 | +++ b/foo |
|
91 | 91 | @@ -0,0 +1,1 @@ |
|
92 | 92 | +normal |
|
93 | 93 | |
|
94 | 94 | $ cat foo |
|
95 | 95 | normal |
|
96 | 96 | |
|
97 | 97 | Largefile in the working copy, keeping the largefile version: |
|
98 | 98 | |
|
99 | 99 | $ hg update -q -C -r 1 |
|
100 | 100 | $ echo "l" | hg merge --config ui.interactive=Yes |
|
101 | 101 | remote turned local largefile foo into a normal file |
|
102 | 102 | keep (l)argefile or use (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
103 | 103 | (branch merge, don't forget to commit) |
|
104 | 104 | getting changed largefiles |
|
105 | 105 | 1 largefiles updated, 0 removed |
|
106 | 106 | |
|
107 | 107 | $ hg status |
|
108 | 108 | |
|
109 | 109 | $ cat foo |
|
110 | 110 | large |
|
111 | 111 | |
|
112 | 112 | Whatever ... commit something so we can invoke merge when updating |
|
113 | 113 | |
|
114 | 114 | $ hg commit -m '3: Merge' |
|
115 | 115 | |
|
116 | 116 | Updating from largefile to normal - no reason to prompt |
|
117 | 117 | |
|
118 | 118 | $ hg up -r 2 |
|
119 | 119 | getting changed largefiles |
|
120 | 120 | 0 largefiles updated, 0 removed |
|
121 | 121 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
122 | 122 | $ cat foo |
|
123 | 123 | normal |
|
124 | 124 | |
|
125 | 125 | (the update above used to leave the working dir in a very weird state - clean it |
|
126 | 126 | $ hg up -qr null |
|
127 | 127 | $ hg up -qr 2 |
|
128 | 128 | ) |
|
129 | 129 | |
|
130 | 130 | Updating from normal to largefile - no reason to prompt |
|
131 | 131 | |
|
132 | 132 | $ hg up -r 3 |
|
133 | 133 | getting changed largefiles |
|
134 | 134 | 1 largefiles updated, 0 removed |
|
135 | 135 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
136 | 136 | $ cat foo |
|
137 | 137 | large |
|
138 | 138 | |
|
139 | 139 | $ cd .. |
|
140 | 140 | |
|
141 | 141 | |
|
142 | 142 | Systematic testing of merges involving largefiles: |
|
143 | 143 | |
|
144 | 144 | Ancestor: normal Parent: normal= Parent: large result: large |
|
145 | 145 | Ancestor: normal Parent: normal2 Parent: large result: ? |
|
146 | 146 | Ancestor: large Parent: large= Parent: normal result: normal |
|
147 | 147 | Ancestor: large Parent: large2 Parent: normal result: ? |
|
148 | 148 | |
|
149 | 149 | All cases should try merging both ways. |
|
150 | 150 | "=" means same file content. |
|
151 | 151 | |
|
152 | 152 | Prepare test repo: |
|
153 | 153 | |
|
154 | 154 | $ hg init merges |
|
155 | 155 | $ cd merges |
|
156 | 156 | $ touch f1 |
|
157 | 157 | $ hg ci -Aqm "0-root" --config extensions.largefiles=! |
|
158 | 158 | |
|
159 | 159 | Ensure that .hg/largefiles isn't created before largefiles are added |
|
160 | 160 | #if unix-permissions |
|
161 | 161 | $ chmod 555 .hg |
|
162 | 162 | #endif |
|
163 | 163 | $ hg status |
|
164 | 164 | #if unix-permissions |
|
165 | 165 | $ chmod 755 .hg |
|
166 | 166 | #endif |
|
167 | 167 | |
|
168 |
$ f |
|
|
169 | find: `.hg/largefiles': No such file or directory | |
|
168 | $ test -f .hg/largefiles | |
|
170 | 169 | [1] |
|
171 | 170 | |
|
172 | 171 | ancestor is "normal": |
|
173 | 172 | $ echo normal > f |
|
174 | 173 | $ hg ci -Aqm "1-normal-ancestor" |
|
175 | 174 | $ touch f2 |
|
176 | 175 | $ hg ci -Aqm "2-normal-unchanged" |
|
177 | 176 | $ hg tag -l "normal=" |
|
178 | 177 | $ echo normal2 > f |
|
179 | 178 | $ hg ci -m "3-normal2" |
|
180 | 179 | $ hg tag -l "normal2" |
|
181 | 180 | $ hg up -qr 1 |
|
182 | 181 | $ hg rm f |
|
183 | 182 | $ echo large > f |
|
184 | 183 | $ hg add --large f |
|
185 | 184 | $ hg ci -qm "4-normal-to-large" |
|
186 | 185 | $ hg tag -l "large" |
|
187 | 186 | |
|
188 | 187 | $ hg up -qr null |
|
189 | 188 | |
|
190 | 189 | ancestor is "large": |
|
191 | 190 | $ echo large > f |
|
192 | 191 | $ hg add --large f |
|
193 | 192 | $ hg ci -qm "5-large-ancestor" |
|
194 | 193 | $ touch f2 |
|
195 | 194 | $ hg ci -Aqm "6-large-unchanged" |
|
196 | 195 | $ hg tag -l "large=" |
|
197 | 196 | $ echo large2 > f |
|
198 | 197 | $ hg ci -m "7-large2" |
|
199 | 198 | $ hg tag -l "large2" |
|
200 | 199 | $ hg up -qr 5 |
|
201 | 200 | $ hg rm f |
|
202 | 201 | $ echo normal > f |
|
203 | 202 | $ hg ci -qAm "8-large-to-normal" |
|
204 | 203 | $ hg tag -l "normal" |
|
205 | 204 | |
|
206 | 205 | Ancestor: normal Parent: normal= Parent: large result: large |
|
207 | 206 | |
|
208 | 207 | $ hg up -Cqr normal= |
|
209 | 208 | $ hg merge -r large |
|
210 | 209 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
211 | 210 |
|
|
212 | 211 | getting changed largefiles |
|
213 | 212 | 1 largefiles updated, 0 removed |
|
214 | 213 | $ cat f |
|
215 | 214 | large |
|
216 | 215 | |
|
217 | 216 | swap |
|
218 | 217 | |
|
219 | 218 | $ hg up -Cqr large |
|
220 | 219 | $ hg merge -r normal= |
|
221 | 220 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
222 | 221 | (branch merge, don't forget to commit) |
|
223 | 222 | getting changed largefiles |
|
224 | 223 | 0 largefiles updated, 0 removed |
|
225 | 224 | $ cat f |
|
226 | 225 | large |
|
227 | 226 | |
|
228 | 227 | Ancestor: normal Parent: normal2 Parent: large result: ? |
|
229 | 228 | (annoying extra prompt ... but it do not do any serious harm) |
|
230 | 229 | |
|
231 | 230 | $ hg up -Cqr normal2 |
|
232 | 231 | $ hg merge -r large |
|
233 | 232 | local changed f which remote deleted |
|
234 | 233 | use (c)hanged version or (d)elete? c |
|
235 | 234 | remote turned local normal file f into a largefile |
|
236 | 235 | use (l)argefile or keep (n)ormal file? l |
|
237 | 236 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
238 | 237 |
|
|
239 | 238 | getting changed largefiles |
|
240 | 239 | 1 largefiles updated, 0 removed |
|
241 | 240 | $ cat f |
|
242 | 241 | large |
|
243 | 242 | |
|
244 | 243 | $ hg up -Cqr normal2 |
|
245 | 244 | $ ( echo c; echo n ) | hg merge -r large --config ui.interactive=Yes |
|
246 | 245 | local changed f which remote deleted |
|
247 | 246 | use (c)hanged version or (d)elete? remote turned local normal file f into a largefile |
|
248 | 247 | use (l)argefile or keep (n)ormal file? 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
249 | 248 | (branch merge, don't forget to commit) |
|
250 | 249 | getting changed largefiles |
|
251 | 250 | 0 largefiles updated, 0 removed |
|
252 | 251 | $ cat f |
|
253 | 252 | normal2 |
|
254 | 253 | |
|
255 | 254 | $ hg up -Cqr normal2 |
|
256 | 255 | $ echo d | hg merge -r large --config ui.interactive=Yes |
|
257 | 256 | local changed f which remote deleted |
|
258 | 257 | use (c)hanged version or (d)elete? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
259 | 258 |
|
|
260 | 259 | getting changed largefiles |
|
261 | 260 | 1 largefiles updated, 0 removed |
|
262 | 261 | $ cat f |
|
263 | 262 | large |
|
264 | 263 | |
|
265 | 264 | swap |
|
266 | 265 | |
|
267 | 266 | $ hg up -Cqr large |
|
268 | 267 | $ hg merge -r normal2 |
|
269 | 268 | remote changed f which local deleted |
|
270 | 269 | use (c)hanged version or leave (d)eleted? c |
|
271 | 270 | remote turned local largefile f into a normal file |
|
272 | 271 | keep (l)argefile or use (n)ormal file? l |
|
273 | 272 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
274 | 273 | (branch merge, don't forget to commit) |
|
275 | 274 | getting changed largefiles |
|
276 | 275 | 1 largefiles updated, 0 removed |
|
277 | 276 | $ cat f |
|
278 | 277 | large |
|
279 | 278 | |
|
280 | 279 | $ hg up -Cqr large |
|
281 | 280 | $ ( echo c; echo n ) | hg merge -r normal2 --config ui.interactive=Yes |
|
282 | 281 | remote changed f which local deleted |
|
283 | 282 | use (c)hanged version or leave (d)eleted? remote turned local largefile f into a normal file |
|
284 | 283 | keep (l)argefile or use (n)ormal file? 2 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
285 | 284 |
|
|
286 | 285 | getting changed largefiles |
|
287 | 286 | 0 largefiles updated, 0 removed |
|
288 | 287 | $ cat f |
|
289 | 288 | normal2 |
|
290 | 289 | |
|
291 | 290 | $ hg up -Cqr large |
|
292 | 291 | $ echo d | hg merge -r normal2 --config ui.interactive=Yes |
|
293 | 292 | remote changed f which local deleted |
|
294 | 293 | use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
295 | 294 | (branch merge, don't forget to commit) |
|
296 | 295 | getting changed largefiles |
|
297 | 296 | 0 largefiles updated, 0 removed |
|
298 | 297 | $ cat f |
|
299 | 298 | large |
|
300 | 299 | |
|
301 | 300 | Ancestor: large Parent: large= Parent: normal result: normal |
|
302 | 301 | |
|
303 | 302 | $ hg up -Cqr large= |
|
304 | 303 | $ hg merge -r normal |
|
305 | 304 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
306 | 305 |
|
|
307 | 306 | getting changed largefiles |
|
308 | 307 | 0 largefiles updated, 0 removed |
|
309 | 308 | $ cat f |
|
310 | 309 | normal |
|
311 | 310 | |
|
312 | 311 | swap |
|
313 | 312 | |
|
314 | 313 | $ hg up -Cqr normal |
|
315 | 314 | $ hg merge -r large= |
|
316 | 315 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
317 | 316 | (branch merge, don't forget to commit) |
|
318 | 317 | $ cat f |
|
319 | 318 | normal |
|
320 | 319 | |
|
321 | 320 | Ancestor: large Parent: large2 Parent: normal result: ? |
|
322 | 321 | (annoying extra prompt ... but it do not do any serious harm) |
|
323 | 322 | |
|
324 | 323 | $ hg up -Cqr large2 |
|
325 | 324 | $ hg merge -r normal |
|
326 | 325 | local changed .hglf/f which remote deleted |
|
327 | 326 | use (c)hanged version or (d)elete? c |
|
328 | 327 | remote turned local largefile f into a normal file |
|
329 | 328 | keep (l)argefile or use (n)ormal file? l |
|
330 | 329 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
331 | 330 |
|
|
332 | 331 | getting changed largefiles |
|
333 | 332 | 1 largefiles updated, 0 removed |
|
334 | 333 | $ cat f |
|
335 | 334 | large2 |
|
336 | 335 | |
|
337 | 336 | $ hg up -Cqr large2 |
|
338 | 337 | $ echo d | hg merge -r normal --config ui.interactive=Yes |
|
339 | 338 | local changed .hglf/f which remote deleted |
|
340 | 339 | use (c)hanged version or (d)elete? 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
341 | 340 | (branch merge, don't forget to commit) |
|
342 | 341 | getting changed largefiles |
|
343 | 342 | 0 largefiles updated, 0 removed |
|
344 | 343 | $ cat f |
|
345 | 344 | normal |
|
346 | 345 | |
|
347 | 346 |
|
|
348 | 347 | |
|
349 | 348 | $ hg up -Cqr normal |
|
350 | 349 | $ hg merge -r large2 |
|
351 | 350 | remote changed .hglf/f which local deleted |
|
352 | 351 | use (c)hanged version or leave (d)eleted? c |
|
353 | 352 | remote turned local normal file f into a largefile |
|
354 | 353 | use (l)argefile or keep (n)ormal file? l |
|
355 | 354 | 2 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
356 | 355 |
|
|
357 | 356 | getting changed largefiles |
|
358 | 357 | 1 largefiles updated, 0 removed |
|
359 | 358 | $ cat f |
|
360 | 359 | large2 |
|
361 | 360 | |
|
362 | 361 | $ hg up -Cqr normal |
|
363 | 362 | $ echo d | hg merge -r large2 --config ui.interactive=Yes |
|
364 | 363 | remote changed .hglf/f which local deleted |
|
365 | 364 | use (c)hanged version or leave (d)eleted? 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
366 | 365 | (branch merge, don't forget to commit) |
|
367 | 366 | $ cat f |
|
368 | 367 | normal |
|
369 | 368 | |
|
370 | 369 | $ cd .. |
@@ -1,262 +1,261 b'' | |||
|
1 | 1 | $ echo "[extensions]" >> $HGRCPATH |
|
2 | 2 | $ echo "mq=" >> $HGRCPATH |
|
3 | 3 | $ echo "[mq]" >> $HGRCPATH |
|
4 | 4 | $ echo "git=keep" >> $HGRCPATH |
|
5 | 5 | $ echo "[diff]" >> $HGRCPATH |
|
6 | 6 | $ echo "nodates=1" >> $HGRCPATH |
|
7 | 7 | |
|
8 | 8 | init: |
|
9 | 9 | |
|
10 | 10 | $ hg init repo |
|
11 | 11 | $ cd repo |
|
12 | 12 | $ echo a > a |
|
13 | 13 | $ hg ci -Am adda |
|
14 | 14 | adding a |
|
15 | 15 | $ echo a >> a |
|
16 | 16 | $ hg qnew -f p1 |
|
17 | 17 | $ echo b >> a |
|
18 | 18 | $ hg qnew -f p2 |
|
19 | 19 | $ echo c >> a |
|
20 | 20 | $ hg qnew -f p3 |
|
21 | 21 | |
|
22 | 22 | Fold in the middle of the queue: |
|
23 | 23 | (this tests also that editor is not invoked if '--edit' is not |
|
24 | 24 | specified) |
|
25 | 25 | |
|
26 | 26 | $ hg qpop p1 |
|
27 | 27 | popping p3 |
|
28 | 28 | popping p2 |
|
29 | 29 | now at: p1 |
|
30 | 30 | |
|
31 | 31 | $ hg qdiff |
|
32 | 32 | diff -r 07f494440405 a |
|
33 | 33 | --- a/a |
|
34 | 34 | +++ b/a |
|
35 | 35 | @@ -1,1 +1,2 @@ |
|
36 | 36 | a |
|
37 | 37 | +a |
|
38 | 38 | |
|
39 | 39 | $ HGEDITOR=cat hg qfold p2 |
|
40 | 40 | $ grep git .hg/patches/p1 && echo 'git patch found!' |
|
41 | 41 | [1] |
|
42 | 42 | |
|
43 | 43 | $ hg qser |
|
44 | 44 | p1 |
|
45 | 45 | p3 |
|
46 | 46 | |
|
47 | 47 | $ hg qdiff |
|
48 | 48 | diff -r 07f494440405 a |
|
49 | 49 | --- a/a |
|
50 | 50 | +++ b/a |
|
51 | 51 | @@ -1,1 +1,3 @@ |
|
52 | 52 | a |
|
53 | 53 | +a |
|
54 | 54 | +b |
|
55 | 55 | |
|
56 | 56 | Fold with local changes: |
|
57 | 57 | |
|
58 | 58 | $ echo d >> a |
|
59 | 59 | $ hg qfold p3 |
|
60 | 60 | abort: local changes found, refresh first |
|
61 | 61 | [255] |
|
62 | 62 | |
|
63 | 63 | $ hg diff -c . |
|
64 | 64 | diff -r 07f494440405 -r ???????????? a (glob) |
|
65 | 65 | --- a/a |
|
66 | 66 | +++ b/a |
|
67 | 67 | @@ -1,1 +1,3 @@ |
|
68 | 68 | a |
|
69 | 69 | +a |
|
70 | 70 | +b |
|
71 | 71 | |
|
72 | 72 | $ hg revert -a --no-backup |
|
73 | 73 | reverting a |
|
74 | 74 | |
|
75 | 75 | Fold git patch into a regular patch, expect git patch: |
|
76 | 76 | |
|
77 | 77 | $ echo a >> a |
|
78 | 78 | $ hg qnew -f regular |
|
79 | 79 | $ hg cp a aa |
|
80 | 80 | $ hg qnew --git -f git |
|
81 | 81 | |
|
82 | 82 | $ hg qpop |
|
83 | 83 | popping git |
|
84 | 84 | now at: regular |
|
85 | 85 | |
|
86 | 86 | $ hg qfold git |
|
87 | 87 | |
|
88 | 88 | $ cat .hg/patches/regular |
|
89 | 89 | # HG changeset patch |
|
90 | 90 | # Parent ???????????????????????????????????????? (glob) |
|
91 | 91 | |
|
92 | 92 | diff --git a/a b/a |
|
93 | 93 | --- a/a |
|
94 | 94 | +++ b/a |
|
95 | 95 | @@ -1,3 +1,4 @@ |
|
96 | 96 | a |
|
97 | 97 | a |
|
98 | 98 | b |
|
99 | 99 | +a |
|
100 | 100 | diff --git a/a b/aa |
|
101 | 101 | copy from a |
|
102 | 102 | copy to aa |
|
103 | 103 | --- a/a |
|
104 | 104 | +++ b/aa |
|
105 | 105 | @@ -1,3 +1,4 @@ |
|
106 | 106 | a |
|
107 | 107 | a |
|
108 | 108 | b |
|
109 | 109 | +a |
|
110 | 110 | |
|
111 | 111 | $ hg qpop |
|
112 | 112 | popping regular |
|
113 | 113 | now at: p1 |
|
114 | 114 | |
|
115 | 115 | $ hg qdel regular |
|
116 | 116 | |
|
117 | 117 | Fold regular patch into a git patch, expect git patch: |
|
118 | 118 | |
|
119 | 119 | $ hg cp a aa |
|
120 | 120 | $ hg qnew --git -f git |
|
121 | 121 | $ echo b >> aa |
|
122 | 122 | $ hg qnew -f regular |
|
123 | 123 | |
|
124 | 124 | $ hg qpop |
|
125 | 125 | popping regular |
|
126 | 126 | now at: git |
|
127 | 127 | |
|
128 | 128 | $ hg qfold regular |
|
129 | 129 | |
|
130 | 130 | $ cat .hg/patches/git |
|
131 | 131 | # HG changeset patch |
|
132 | 132 | # Parent ???????????????????????????????????????? (glob) |
|
133 | 133 | |
|
134 | 134 | diff --git a/a b/aa |
|
135 | 135 | copy from a |
|
136 | 136 | copy to aa |
|
137 | 137 | --- a/a |
|
138 | 138 | +++ b/aa |
|
139 | 139 | @@ -1,3 +1,4 @@ |
|
140 | 140 | a |
|
141 | 141 | a |
|
142 | 142 | b |
|
143 | 143 | +b |
|
144 | 144 | |
|
145 | 145 | Test saving last-message.txt: |
|
146 | 146 | |
|
147 | 147 | $ hg qrefresh -m "original message" |
|
148 | 148 | |
|
149 | 149 | $ cat > $TESTTMP/commitfailure.py <<EOF |
|
150 | 150 | > from mercurial import util |
|
151 | 151 | > def reposetup(ui, repo): |
|
152 | 152 | > class commitfailure(repo.__class__): |
|
153 | 153 | > def commit(self, *args, **kwargs): |
|
154 | 154 | > raise util.Abort('emulating unexpected abort') |
|
155 | 155 | > repo.__class__ = commitfailure |
|
156 | 156 | > EOF |
|
157 | 157 | |
|
158 | 158 | $ cat >> .hg/hgrc <<EOF |
|
159 | 159 | > [extensions] |
|
160 | 160 | > # this failure occurs before editor invocation |
|
161 | 161 | > commitfailure = $TESTTMP/commitfailure.py |
|
162 | 162 | > EOF |
|
163 | 163 | |
|
164 | 164 | $ cat > $TESTTMP/editor.sh << EOF |
|
165 | 165 | > echo "==== before editing" |
|
166 | 166 | > cat \$1 |
|
167 | 167 | > echo "====" |
|
168 | 168 | > (echo; echo "test saving last-message.txt") >> \$1 |
|
169 | 169 | > EOF |
|
170 | 170 | |
|
171 | 171 | $ hg qapplied |
|
172 | 172 | p1 |
|
173 | 173 | git |
|
174 | 174 | $ hg tip --template "{files}\n" |
|
175 | 175 | aa |
|
176 | 176 | |
|
177 | 177 | (test that editor is not invoked before transaction starting, |
|
178 | 178 | and that combination of '--edit' and '--message' doesn't abort execution) |
|
179 | 179 | |
|
180 | 180 | $ rm -f .hg/last-message.txt |
|
181 | 181 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qfold -e -m MESSAGE p3 |
|
182 | 182 | refresh interrupted while patch was popped! (revert --all, qpush to recover) |
|
183 | 183 | abort: emulating unexpected abort |
|
184 | 184 | [255] |
|
185 |
$ |
|
|
186 | cat: .hg/last-message.txt: No such file or directory | |
|
185 | $ test -f .hg/last-message.txt | |
|
187 | 186 | [1] |
|
188 | 187 | |
|
189 | 188 | (reset applied patches and directory status) |
|
190 | 189 | |
|
191 | 190 | $ cat >> .hg/hgrc <<EOF |
|
192 | 191 | > [extensions] |
|
193 | 192 | > # this failure occurs after editor invocation |
|
194 | 193 | > commitfailure = ! |
|
195 | 194 | > EOF |
|
196 | 195 | |
|
197 | 196 | $ hg qapplied |
|
198 | 197 | p1 |
|
199 | 198 | $ hg status -A aa |
|
200 | 199 | ? aa |
|
201 | 200 | $ rm aa |
|
202 | 201 | $ hg status -m |
|
203 | 202 | M a |
|
204 | 203 | $ hg revert --no-backup -q a |
|
205 | 204 | $ hg qpush -q git |
|
206 | 205 | now at: git |
|
207 | 206 | |
|
208 | 207 | (test that editor is invoked and commit message is saved into |
|
209 | 208 | "last-message.txt") |
|
210 | 209 | |
|
211 | 210 | $ cat >> .hg/hgrc <<EOF |
|
212 | 211 | > [hooks] |
|
213 | 212 | > # this failure occurs after editor invocation |
|
214 | 213 | > pretxncommit.unexpectedabort = false |
|
215 | 214 | > EOF |
|
216 | 215 | |
|
217 | 216 | $ rm -f .hg/last-message.txt |
|
218 | 217 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qfold -e p3 |
|
219 | 218 | ==== before editing |
|
220 | 219 | original message |
|
221 | 220 | |
|
222 | 221 | |
|
223 | 222 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
224 | 223 | HG: Leave message empty to use default message. |
|
225 | 224 | HG: -- |
|
226 | 225 | HG: user: test |
|
227 | 226 | HG: branch 'default' |
|
228 | 227 | HG: added aa |
|
229 | 228 | HG: changed a |
|
230 | 229 | ==== |
|
231 | 230 | transaction abort! |
|
232 | 231 | rollback completed |
|
233 | 232 | note: commit message saved in .hg/last-message.txt |
|
234 | 233 | refresh interrupted while patch was popped! (revert --all, qpush to recover) |
|
235 | 234 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
236 | 235 | [255] |
|
237 | 236 | $ cat .hg/last-message.txt |
|
238 | 237 | original message |
|
239 | 238 | |
|
240 | 239 | |
|
241 | 240 | |
|
242 | 241 | test saving last-message.txt |
|
243 | 242 | |
|
244 | 243 | (confirm whether files listed up in the commit message editing are correct) |
|
245 | 244 | |
|
246 | 245 | $ cat >> .hg/hgrc <<EOF |
|
247 | 246 | > [hooks] |
|
248 | 247 | > pretxncommit.unexpectedabort = |
|
249 | 248 | > EOF |
|
250 | 249 | $ hg status -u | while read f; do rm ${f}; done |
|
251 | 250 | $ hg revert --no-backup -q --all |
|
252 | 251 | $ hg qpush -q git |
|
253 | 252 | now at: git |
|
254 | 253 | $ hg qpush -q --move p3 |
|
255 | 254 | now at: p3 |
|
256 | 255 | |
|
257 | 256 | $ hg status --rev "git^1" --rev . -arm |
|
258 | 257 | M a |
|
259 | 258 | A aa |
|
260 | 259 | |
|
261 | 260 | $ cd .. |
|
262 | 261 |
@@ -1,344 +1,343 b'' | |||
|
1 | 1 | |
|
2 | 2 | $ catpatch() { |
|
3 | 3 | > cat $1 | sed -e "s/^\(# Parent \).*/\1/" |
|
4 | 4 | > } |
|
5 | 5 | $ echo "[extensions]" >> $HGRCPATH |
|
6 | 6 | $ echo "mq=" >> $HGRCPATH |
|
7 | 7 | $ runtest() { |
|
8 | 8 | > hg init mq |
|
9 | 9 | > cd mq |
|
10 | 10 | > |
|
11 | 11 | > echo a > a |
|
12 | 12 | > hg ci -Ama |
|
13 | 13 | > |
|
14 | 14 | > echo '% qnew should refuse bad patch names' |
|
15 | 15 | > hg qnew series |
|
16 | 16 | > hg qnew status |
|
17 | 17 | > hg qnew guards |
|
18 | 18 | > hg qnew . |
|
19 | 19 | > hg qnew .. |
|
20 | 20 | > hg qnew .hgignore |
|
21 | 21 | > hg qnew .mqfoo |
|
22 | 22 | > hg qnew 'foo#bar' |
|
23 | 23 | > hg qnew 'foo:bar' |
|
24 | 24 | > |
|
25 | 25 | > hg qinit -c |
|
26 | 26 | > |
|
27 | 27 | > echo '% qnew with name containing slash' |
|
28 | 28 | > hg qnew foo/ |
|
29 | 29 | > hg qnew foo/bar.patch |
|
30 | 30 | > hg qnew foo |
|
31 | 31 | > hg qseries |
|
32 | 32 | > hg qpop |
|
33 | 33 | > hg qdelete foo/bar.patch |
|
34 | 34 | > |
|
35 | 35 | > echo '% qnew with uncommitted changes' |
|
36 | 36 | > echo a > somefile |
|
37 | 37 | > hg add somefile |
|
38 | 38 | > hg qnew uncommitted.patch |
|
39 | 39 | > hg st |
|
40 | 40 | > hg qseries |
|
41 | 41 | > |
|
42 | 42 | > echo '% qnew implies add' |
|
43 | 43 | > hg -R .hg/patches st |
|
44 | 44 | > |
|
45 | 45 | > echo '% qnew missing' |
|
46 | 46 | > hg qnew missing.patch missing |
|
47 | 47 | > |
|
48 | 48 | > echo '% qnew -m' |
|
49 | 49 | > hg qnew -m 'foo bar' mtest.patch |
|
50 | 50 | > catpatch .hg/patches/mtest.patch |
|
51 | 51 | > |
|
52 | 52 | > echo '% qnew twice' |
|
53 | 53 | > hg qnew first.patch |
|
54 | 54 | > hg qnew first.patch |
|
55 | 55 | > |
|
56 | 56 | > touch ../first.patch |
|
57 | 57 | > hg qimport ../first.patch |
|
58 | 58 | > |
|
59 | 59 | > echo '% qnew -f from a subdirectory' |
|
60 | 60 | > hg qpop -a |
|
61 | 61 | > mkdir d |
|
62 | 62 | > cd d |
|
63 | 63 | > echo b > b |
|
64 | 64 | > hg ci -Am t |
|
65 | 65 | > echo b >> b |
|
66 | 66 | > hg st |
|
67 | 67 | > hg qnew -g -f p |
|
68 | 68 | > catpatch ../.hg/patches/p |
|
69 | 69 | > |
|
70 | 70 | > echo '% qnew -u with no username configured' |
|
71 | 71 | > HGUSER= hg qnew -u blue red |
|
72 | 72 | > catpatch ../.hg/patches/red |
|
73 | 73 | > |
|
74 | 74 | > echo '% qnew -e -u with no username configured' |
|
75 | 75 | > HGUSER= hg qnew -e -u chartreuse fucsia |
|
76 | 76 | > catpatch ../.hg/patches/fucsia |
|
77 | 77 | > |
|
78 | 78 | > echo '% fail when trying to import a merge' |
|
79 | 79 | > hg init merge |
|
80 | 80 | > cd merge |
|
81 | 81 | > touch a |
|
82 | 82 | > hg ci -Am null |
|
83 | 83 | > echo a >> a |
|
84 | 84 | > hg ci -m a |
|
85 | 85 | > hg up -r 0 |
|
86 | 86 | > echo b >> a |
|
87 | 87 | > hg ci -m b |
|
88 | 88 | > hg merge -f 1 |
|
89 | 89 | > hg resolve --mark a |
|
90 | 90 | > hg qnew -f merge |
|
91 | 91 | > |
|
92 | 92 | > cd ../../.. |
|
93 | 93 | > rm -r mq |
|
94 | 94 | > } |
|
95 | 95 | |
|
96 | 96 | plain headers |
|
97 | 97 | |
|
98 | 98 | $ echo "[mq]" >> $HGRCPATH |
|
99 | 99 | $ echo "plain=true" >> $HGRCPATH |
|
100 | 100 | $ mkdir sandbox |
|
101 | 101 | $ (cd sandbox ; runtest) |
|
102 | 102 | adding a |
|
103 | 103 | % qnew should refuse bad patch names |
|
104 | 104 | abort: "series" cannot be used as the name of a patch |
|
105 | 105 | abort: "status" cannot be used as the name of a patch |
|
106 | 106 | abort: "guards" cannot be used as the name of a patch |
|
107 | 107 | abort: "." cannot be used as the name of a patch |
|
108 | 108 | abort: ".." cannot be used as the name of a patch |
|
109 | 109 | abort: patch name cannot begin with ".hg" |
|
110 | 110 | abort: patch name cannot begin with ".mq" |
|
111 | 111 | abort: "#" cannot be used in the name of a patch |
|
112 | 112 | abort: ":" cannot be used in the name of a patch |
|
113 | 113 | % qnew with name containing slash |
|
114 | 114 | abort: path ends in directory separator: foo/ (glob) |
|
115 | 115 | abort: "foo" already exists as a directory |
|
116 | 116 | foo/bar.patch |
|
117 | 117 | popping foo/bar.patch |
|
118 | 118 | patch queue now empty |
|
119 | 119 | % qnew with uncommitted changes |
|
120 | 120 | uncommitted.patch |
|
121 | 121 | % qnew implies add |
|
122 | 122 | A .hgignore |
|
123 | 123 | A series |
|
124 | 124 | A uncommitted.patch |
|
125 | 125 | % qnew missing |
|
126 | 126 | abort: missing: * (glob) |
|
127 | 127 | % qnew -m |
|
128 | 128 | foo bar |
|
129 | 129 | |
|
130 | 130 | % qnew twice |
|
131 | 131 | abort: patch "first.patch" already exists |
|
132 | 132 | abort: patch "first.patch" already exists |
|
133 | 133 | % qnew -f from a subdirectory |
|
134 | 134 | popping first.patch |
|
135 | 135 | popping mtest.patch |
|
136 | 136 | popping uncommitted.patch |
|
137 | 137 | patch queue now empty |
|
138 | 138 | adding d/b |
|
139 | 139 | M d/b |
|
140 | 140 | diff --git a/d/b b/d/b |
|
141 | 141 | --- a/d/b |
|
142 | 142 | +++ b/d/b |
|
143 | 143 | @@ -1,1 +1,2 @@ |
|
144 | 144 | b |
|
145 | 145 | +b |
|
146 | 146 | % qnew -u with no username configured |
|
147 | 147 | From: blue |
|
148 | 148 | |
|
149 | 149 | % qnew -e -u with no username configured |
|
150 | 150 | From: chartreuse |
|
151 | 151 | |
|
152 | 152 | % fail when trying to import a merge |
|
153 | 153 | adding a |
|
154 | 154 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
155 | 155 | created new head |
|
156 | 156 | merging a |
|
157 | 157 | warning: conflicts during merge. |
|
158 | 158 | merging a incomplete! (edit conflicts, then use 'hg resolve --mark') |
|
159 | 159 | 0 files updated, 0 files merged, 0 files removed, 1 files unresolved |
|
160 | 160 | use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon |
|
161 | 161 | no more unresolved files |
|
162 | 162 | abort: cannot manage merge changesets |
|
163 | 163 | $ rm -r sandbox |
|
164 | 164 | |
|
165 | 165 | hg headers |
|
166 | 166 | |
|
167 | 167 | $ echo "plain=false" >> $HGRCPATH |
|
168 | 168 | $ mkdir sandbox |
|
169 | 169 | $ (cd sandbox ; runtest) |
|
170 | 170 | adding a |
|
171 | 171 | % qnew should refuse bad patch names |
|
172 | 172 | abort: "series" cannot be used as the name of a patch |
|
173 | 173 | abort: "status" cannot be used as the name of a patch |
|
174 | 174 | abort: "guards" cannot be used as the name of a patch |
|
175 | 175 | abort: "." cannot be used as the name of a patch |
|
176 | 176 | abort: ".." cannot be used as the name of a patch |
|
177 | 177 | abort: patch name cannot begin with ".hg" |
|
178 | 178 | abort: patch name cannot begin with ".mq" |
|
179 | 179 | abort: "#" cannot be used in the name of a patch |
|
180 | 180 | abort: ":" cannot be used in the name of a patch |
|
181 | 181 | % qnew with name containing slash |
|
182 | 182 | abort: path ends in directory separator: foo/ (glob) |
|
183 | 183 | abort: "foo" already exists as a directory |
|
184 | 184 | foo/bar.patch |
|
185 | 185 | popping foo/bar.patch |
|
186 | 186 | patch queue now empty |
|
187 | 187 | % qnew with uncommitted changes |
|
188 | 188 | uncommitted.patch |
|
189 | 189 | % qnew implies add |
|
190 | 190 | A .hgignore |
|
191 | 191 | A series |
|
192 | 192 | A uncommitted.patch |
|
193 | 193 | % qnew missing |
|
194 | 194 | abort: missing: * (glob) |
|
195 | 195 | % qnew -m |
|
196 | 196 | # HG changeset patch |
|
197 | 197 | # Parent |
|
198 | 198 | foo bar |
|
199 | 199 | |
|
200 | 200 | % qnew twice |
|
201 | 201 | abort: patch "first.patch" already exists |
|
202 | 202 | abort: patch "first.patch" already exists |
|
203 | 203 | % qnew -f from a subdirectory |
|
204 | 204 | popping first.patch |
|
205 | 205 | popping mtest.patch |
|
206 | 206 | popping uncommitted.patch |
|
207 | 207 | patch queue now empty |
|
208 | 208 | adding d/b |
|
209 | 209 | M d/b |
|
210 | 210 | # HG changeset patch |
|
211 | 211 | # Parent |
|
212 | 212 | diff --git a/d/b b/d/b |
|
213 | 213 | --- a/d/b |
|
214 | 214 | +++ b/d/b |
|
215 | 215 | @@ -1,1 +1,2 @@ |
|
216 | 216 | b |
|
217 | 217 | +b |
|
218 | 218 | % qnew -u with no username configured |
|
219 | 219 | # HG changeset patch |
|
220 | 220 | # Parent |
|
221 | 221 | # User blue |
|
222 | 222 | % qnew -e -u with no username configured |
|
223 | 223 | # HG changeset patch |
|
224 | 224 | # Parent |
|
225 | 225 | # User chartreuse |
|
226 | 226 | % fail when trying to import a merge |
|
227 | 227 | adding a |
|
228 | 228 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
229 | 229 | created new head |
|
230 | 230 | merging a |
|
231 | 231 | warning: conflicts during merge. |
|
232 | 232 | merging a incomplete! (edit conflicts, then use 'hg resolve --mark') |
|
233 | 233 | 0 files updated, 0 files merged, 0 files removed, 1 files unresolved |
|
234 | 234 | use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon |
|
235 | 235 | no more unresolved files |
|
236 | 236 | abort: cannot manage merge changesets |
|
237 | 237 | $ rm -r sandbox |
|
238 | 238 | |
|
239 | 239 | Test saving last-message.txt |
|
240 | 240 | |
|
241 | 241 | $ hg init repo |
|
242 | 242 | $ cd repo |
|
243 | 243 | |
|
244 | 244 | $ cat > $TESTTMP/commitfailure.py <<EOF |
|
245 | 245 | > from mercurial import util |
|
246 | 246 | > def reposetup(ui, repo): |
|
247 | 247 | > class commitfailure(repo.__class__): |
|
248 | 248 | > def commit(self, *args, **kwargs): |
|
249 | 249 | > raise util.Abort('emulating unexpected abort') |
|
250 | 250 | > repo.__class__ = commitfailure |
|
251 | 251 | > EOF |
|
252 | 252 | $ cat >> .hg/hgrc <<EOF |
|
253 | 253 | > [extensions] |
|
254 | 254 | > # this failure occurs before editor invocation |
|
255 | 255 | > commitfailure = $TESTTMP/commitfailure.py |
|
256 | 256 | > EOF |
|
257 | 257 | |
|
258 | 258 | $ cat > $TESTTMP/editor.sh << EOF |
|
259 | 259 | > echo "==== before editing" |
|
260 | 260 | > cat \$1 |
|
261 | 261 | > echo "====" |
|
262 | 262 | > echo "test saving last-message.txt" >> \$1 |
|
263 | 263 | > EOF |
|
264 | 264 | |
|
265 | 265 | (test that editor is not invoked before transaction starting) |
|
266 | 266 | |
|
267 | 267 | $ rm -f .hg/last-message.txt |
|
268 | 268 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qnew -e patch |
|
269 | 269 | abort: emulating unexpected abort |
|
270 | 270 | [255] |
|
271 |
$ |
|
|
272 | cat: .hg/last-message.txt: No such file or directory | |
|
271 | $ test -f .hg/last-message.txt | |
|
273 | 272 | [1] |
|
274 | 273 | |
|
275 | 274 | (test that editor is invoked and commit message is saved into |
|
276 | 275 | "last-message.txt") |
|
277 | 276 | |
|
278 | 277 | $ cat >> .hg/hgrc <<EOF |
|
279 | 278 | > [extensions] |
|
280 | 279 | > commitfailure = ! |
|
281 | 280 | > [hooks] |
|
282 | 281 | > # this failure occurs after editor invocation |
|
283 | 282 | > pretxncommit.unexpectedabort = false |
|
284 | 283 | > EOF |
|
285 | 284 | |
|
286 | 285 | $ rm -f .hg/last-message.txt |
|
287 | 286 | $ hg status |
|
288 | 287 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qnew -e patch |
|
289 | 288 | ==== before editing |
|
290 | 289 | |
|
291 | 290 | |
|
292 | 291 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
293 | 292 | HG: Leave message empty to use default message. |
|
294 | 293 | HG: -- |
|
295 | 294 | HG: user: test |
|
296 | 295 | HG: branch 'default' |
|
297 | 296 | HG: no files changed |
|
298 | 297 | ==== |
|
299 | 298 | transaction abort! |
|
300 | 299 | rollback completed |
|
301 | 300 | note: commit message saved in .hg/last-message.txt |
|
302 | 301 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
303 | 302 | [255] |
|
304 | 303 | $ cat .hg/last-message.txt |
|
305 | 304 | |
|
306 | 305 | |
|
307 | 306 | test saving last-message.txt |
|
308 | 307 | |
|
309 | 308 | $ cat >> .hg/hgrc <<EOF |
|
310 | 309 | > [hooks] |
|
311 | 310 | > pretxncommit.unexpectedabort = |
|
312 | 311 | > EOF |
|
313 | 312 | |
|
314 | 313 | #if unix-permissions |
|
315 | 314 | |
|
316 | 315 | Test handling default message with the patch filename with tail whitespaces |
|
317 | 316 | |
|
318 | 317 | $ cat > $TESTTMP/editor.sh << EOF |
|
319 | 318 | > echo "==== before editing" |
|
320 | 319 | > cat \$1 |
|
321 | 320 | > echo "====" |
|
322 | 321 | > echo "[mq]: patch " > \$1 |
|
323 | 322 | > EOF |
|
324 | 323 | |
|
325 | 324 | $ rm -f .hg/last-message.txt |
|
326 | 325 | $ hg status |
|
327 | 326 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qnew -e "patch " |
|
328 | 327 | ==== before editing |
|
329 | 328 | |
|
330 | 329 | |
|
331 | 330 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
332 | 331 | HG: Leave message empty to use default message. |
|
333 | 332 | HG: -- |
|
334 | 333 | HG: user: test |
|
335 | 334 | HG: branch 'default' |
|
336 | 335 | HG: no files changed |
|
337 | 336 | ==== |
|
338 | 337 | $ cat ".hg/patches/patch " |
|
339 | 338 | # HG changeset patch |
|
340 | 339 | # Parent 0000000000000000000000000000000000000000 |
|
341 | 340 | |
|
342 | 341 | $ cd .. |
|
343 | 342 | |
|
344 | 343 | #endif |
@@ -1,192 +1,191 b'' | |||
|
1 | 1 | Environment setup for MQ |
|
2 | 2 | |
|
3 | 3 | $ echo "[extensions]" >> $HGRCPATH |
|
4 | 4 | $ echo "mq=" >> $HGRCPATH |
|
5 | 5 | $ hg init |
|
6 | 6 | $ hg qinit |
|
7 | 7 | |
|
8 | 8 | Should fail if no patches applied |
|
9 | 9 | (this tests also that editor is not invoked if '--edit' is not |
|
10 | 10 | specified) |
|
11 | 11 | |
|
12 | 12 | $ hg qrefresh |
|
13 | 13 | no patches applied |
|
14 | 14 | [1] |
|
15 | 15 | $ hg qrefresh -e |
|
16 | 16 | no patches applied |
|
17 | 17 | [1] |
|
18 | 18 | $ hg qnew -m "First commit message" first-patch |
|
19 | 19 | $ echo aaaa > file |
|
20 | 20 | $ hg add file |
|
21 | 21 | $ HGEDITOR=cat hg qrefresh |
|
22 | 22 | |
|
23 | 23 | Should display 'First commit message' |
|
24 | 24 | |
|
25 | 25 | $ hg log -l1 --template "{desc}\n" |
|
26 | 26 | First commit message |
|
27 | 27 | |
|
28 | 28 | Testing changing message with -m |
|
29 | 29 | (this tests also that '--edit' can be used with '--message', and |
|
30 | 30 | that '[committemplate] changeset' definition and commit log specific |
|
31 | 31 | template keyword 'extramsg' work well) |
|
32 | 32 | |
|
33 | 33 | $ cat >> .hg/hgrc <<EOF |
|
34 | 34 | > [committemplate] |
|
35 | 35 | > changeset = HG: this is customized commit template |
|
36 | 36 | > {desc}\n\n |
|
37 | 37 | > HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
38 | 38 | > HG: {extramsg} |
|
39 | 39 | > HG: -- |
|
40 | 40 | > HG: user: {author} |
|
41 | 41 | > HG: branch '{branch}'\n{file_adds % |
|
42 | 42 | > "HG: added {file}\n" }{file_mods % |
|
43 | 43 | > "HG: changed {file}\n" }{file_dels % |
|
44 | 44 | > "HG: removed {file}\n" }{if(files, "", |
|
45 | 45 | > "HG: no files changed\n")} |
|
46 | 46 | > EOF |
|
47 | 47 | |
|
48 | 48 | $ echo bbbb > file |
|
49 | 49 | $ HGEDITOR=cat hg qrefresh -m "Second commit message" -e |
|
50 | 50 | HG: this is customized commit template |
|
51 | 51 | Second commit message |
|
52 | 52 | |
|
53 | 53 | |
|
54 | 54 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
55 | 55 | HG: Leave message empty to use default message. |
|
56 | 56 | HG: -- |
|
57 | 57 | HG: user: test |
|
58 | 58 | HG: branch 'default' |
|
59 | 59 | HG: added file |
|
60 | 60 | |
|
61 | 61 | $ cat >> .hg/hgrc <<EOF |
|
62 | 62 | > # disable customizing for subsequent tests |
|
63 | 63 | > [committemplate] |
|
64 | 64 | > changeset = |
|
65 | 65 | > EOF |
|
66 | 66 | |
|
67 | 67 | Should display 'Second commit message' |
|
68 | 68 | |
|
69 | 69 | $ hg log -l1 --template "{desc}\n" |
|
70 | 70 | Second commit message |
|
71 | 71 | |
|
72 | 72 | Testing changing message with -l |
|
73 | 73 | |
|
74 | 74 | $ echo "Third commit message" > logfile |
|
75 | 75 | $ echo " This is the 3rd log message" >> logfile |
|
76 | 76 | $ echo bbbb > file |
|
77 | 77 | $ hg qrefresh -l logfile |
|
78 | 78 | |
|
79 | 79 | Should display 'Third commit message\\\n This is the 3rd log message' |
|
80 | 80 | |
|
81 | 81 | $ hg log -l1 --template "{desc}\n" |
|
82 | 82 | Third commit message |
|
83 | 83 | This is the 3rd log message |
|
84 | 84 | |
|
85 | 85 | Testing changing message with -l- |
|
86 | 86 | |
|
87 | 87 | $ hg qnew -m "First commit message" second-patch |
|
88 | 88 | $ echo aaaa > file2 |
|
89 | 89 | $ hg add file2 |
|
90 | 90 | $ echo bbbb > file2 |
|
91 | 91 | $ (echo "Fifth commit message"; echo " This is the 5th log message") | hg qrefresh -l- |
|
92 | 92 | |
|
93 | 93 | Should display 'Fifth commit message\\\n This is the 5th log message' |
|
94 | 94 | |
|
95 | 95 | $ hg log -l1 --template "{desc}\n" |
|
96 | 96 | Fifth commit message |
|
97 | 97 | This is the 5th log message |
|
98 | 98 | |
|
99 | 99 | Test saving last-message.txt: |
|
100 | 100 | |
|
101 | 101 | $ cat > $TESTTMP/editor.sh << EOF |
|
102 | 102 | > echo "==== before editing" |
|
103 | 103 | > cat \$1 |
|
104 | 104 | > echo "====" |
|
105 | 105 | > (echo; echo "test saving last-message.txt") >> \$1 |
|
106 | 106 | > EOF |
|
107 | 107 | |
|
108 | 108 | $ cat > $TESTTMP/commitfailure.py <<EOF |
|
109 | 109 | > from mercurial import util |
|
110 | 110 | > def reposetup(ui, repo): |
|
111 | 111 | > class commitfailure(repo.__class__): |
|
112 | 112 | > def commit(self, *args, **kwargs): |
|
113 | 113 | > raise util.Abort('emulating unexpected abort') |
|
114 | 114 | > repo.__class__ = commitfailure |
|
115 | 115 | > EOF |
|
116 | 116 | |
|
117 | 117 | $ cat >> .hg/hgrc <<EOF |
|
118 | 118 | > [extensions] |
|
119 | 119 | > # this failure occurs before editor invocation |
|
120 | 120 | > commitfailure = $TESTTMP/commitfailure.py |
|
121 | 121 | > EOF |
|
122 | 122 | |
|
123 | 123 | $ hg qapplied |
|
124 | 124 | first-patch |
|
125 | 125 | second-patch |
|
126 | 126 | $ hg tip --template "{files}\n" |
|
127 | 127 | file2 |
|
128 | 128 | |
|
129 | 129 | (test that editor is not invoked before transaction starting) |
|
130 | 130 | |
|
131 | 131 | $ rm -f .hg/last-message.txt |
|
132 | 132 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qrefresh -e |
|
133 | 133 | refresh interrupted while patch was popped! (revert --all, qpush to recover) |
|
134 | 134 | abort: emulating unexpected abort |
|
135 | 135 | [255] |
|
136 |
$ |
|
|
137 | cat: .hg/last-message.txt: No such file or directory | |
|
136 | $ test -f .hg/last-message.txt | |
|
138 | 137 | [1] |
|
139 | 138 | |
|
140 | 139 | (reset applied patches and directory status) |
|
141 | 140 | |
|
142 | 141 | $ cat >> .hg/hgrc <<EOF |
|
143 | 142 | > [extensions] |
|
144 | 143 | > commitfailure = ! |
|
145 | 144 | > EOF |
|
146 | 145 | |
|
147 | 146 | $ hg qapplied |
|
148 | 147 | first-patch |
|
149 | 148 | $ hg status -A file2 |
|
150 | 149 | ? file2 |
|
151 | 150 | $ rm file2 |
|
152 | 151 | $ hg qpush -q second-patch |
|
153 | 152 | now at: second-patch |
|
154 | 153 | |
|
155 | 154 | (test that editor is invoked and commit message is saved into |
|
156 | 155 | "last-message.txt") |
|
157 | 156 | |
|
158 | 157 | $ cat >> .hg/hgrc <<EOF |
|
159 | 158 | > [hooks] |
|
160 | 159 | > # this failure occurs after editor invocation |
|
161 | 160 | > pretxncommit.unexpectedabort = false |
|
162 | 161 | > EOF |
|
163 | 162 | |
|
164 | 163 | $ rm -f .hg/last-message.txt |
|
165 | 164 | $ hg status --rev "second-patch^1" -arm |
|
166 | 165 | A file2 |
|
167 | 166 | $ HGEDITOR="sh $TESTTMP/editor.sh" hg qrefresh -e |
|
168 | 167 | ==== before editing |
|
169 | 168 | Fifth commit message |
|
170 | 169 | This is the 5th log message |
|
171 | 170 | |
|
172 | 171 | |
|
173 | 172 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
174 | 173 | HG: Leave message empty to use default message. |
|
175 | 174 | HG: -- |
|
176 | 175 | HG: user: test |
|
177 | 176 | HG: branch 'default' |
|
178 | 177 | HG: added file2 |
|
179 | 178 | ==== |
|
180 | 179 | transaction abort! |
|
181 | 180 | rollback completed |
|
182 | 181 | note: commit message saved in .hg/last-message.txt |
|
183 | 182 | refresh interrupted while patch was popped! (revert --all, qpush to recover) |
|
184 | 183 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
185 | 184 | [255] |
|
186 | 185 | $ cat .hg/last-message.txt |
|
187 | 186 | Fifth commit message |
|
188 | 187 | This is the 5th log message |
|
189 | 188 | |
|
190 | 189 | |
|
191 | 190 | |
|
192 | 191 | test saving last-message.txt |
@@ -1,688 +1,686 b'' | |||
|
1 | 1 | $ "$TESTDIR/hghave" svn15 || exit 80 |
|
2 | 2 | |
|
3 | 3 | $ SVNREPOPATH=`pwd`/svn-repo |
|
4 | 4 | #if windows |
|
5 | 5 | $ SVNREPOURL=file:///`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"` |
|
6 | 6 | #else |
|
7 | 7 | $ SVNREPOURL=file://`python -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"` |
|
8 | 8 | #endif |
|
9 | 9 | |
|
10 | 10 | create subversion repo |
|
11 | 11 | |
|
12 | 12 | $ WCROOT="`pwd`/svn-wc" |
|
13 | 13 | $ svnadmin create svn-repo |
|
14 | 14 | $ svn co "$SVNREPOURL" svn-wc |
|
15 | 15 | Checked out revision 0. |
|
16 | 16 | $ cd svn-wc |
|
17 | 17 | $ mkdir src |
|
18 | 18 | $ echo alpha > src/alpha |
|
19 | 19 | $ svn add src |
|
20 | 20 | A src |
|
21 | 21 | A src/alpha (glob) |
|
22 | 22 | $ mkdir externals |
|
23 | 23 | $ echo other > externals/other |
|
24 | 24 | $ svn add externals |
|
25 | 25 | A externals |
|
26 | 26 | A externals/other (glob) |
|
27 | 27 | $ svn ci -m 'Add alpha' |
|
28 | 28 | Adding externals |
|
29 | 29 | Adding externals/other (glob) |
|
30 | 30 | Adding src |
|
31 | 31 | Adding src/alpha (glob) |
|
32 | 32 | Transmitting file data .. |
|
33 | 33 | Committed revision 1. |
|
34 | 34 | $ svn up -q |
|
35 | 35 | $ echo "externals -r1 $SVNREPOURL/externals" > extdef |
|
36 | 36 | $ svn propset -F extdef svn:externals src |
|
37 | 37 | property 'svn:externals' set on 'src' |
|
38 | 38 | $ svn ci -m 'Setting externals' |
|
39 | 39 | Sending src |
|
40 | 40 | |
|
41 | 41 | Committed revision 2. |
|
42 | 42 | $ cd .. |
|
43 | 43 | |
|
44 | 44 | create hg repo |
|
45 | 45 | |
|
46 | 46 | $ mkdir sub |
|
47 | 47 | $ cd sub |
|
48 | 48 | $ hg init t |
|
49 | 49 | $ cd t |
|
50 | 50 | |
|
51 | 51 | first revision, no sub |
|
52 | 52 | |
|
53 | 53 | $ echo a > a |
|
54 | 54 | $ hg ci -Am0 |
|
55 | 55 | adding a |
|
56 | 56 | |
|
57 | 57 | add first svn sub with leading whitespaces |
|
58 | 58 | |
|
59 | 59 | $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub |
|
60 | 60 | $ echo "subdir/s = [svn] $SVNREPOURL/src" >> .hgsub |
|
61 | 61 | $ svn co --quiet "$SVNREPOURL"/src s |
|
62 | 62 | $ mkdir subdir |
|
63 | 63 | $ svn co --quiet "$SVNREPOURL"/src subdir/s |
|
64 | 64 | $ hg add .hgsub |
|
65 | 65 | $ hg ci -m1 |
|
66 | 66 | |
|
67 | 67 | make sure we avoid empty commits (issue2445) |
|
68 | 68 | |
|
69 | 69 | $ hg sum |
|
70 | 70 | parent: 1:* tip (glob) |
|
71 | 71 | 1 |
|
72 | 72 | branch: default |
|
73 | 73 | commit: (clean) |
|
74 | 74 | update: (current) |
|
75 | 75 | $ hg ci -moops |
|
76 | 76 | nothing changed |
|
77 | 77 | [1] |
|
78 | 78 | |
|
79 | 79 | debugsub |
|
80 | 80 | |
|
81 | 81 | $ hg debugsub |
|
82 | 82 | path s |
|
83 | 83 | source file://*/svn-repo/src (glob) |
|
84 | 84 | revision 2 |
|
85 | 85 | path subdir/s |
|
86 | 86 | source file://*/svn-repo/src (glob) |
|
87 | 87 | revision 2 |
|
88 | 88 | |
|
89 | 89 | change file in svn and hg, commit |
|
90 | 90 | |
|
91 | 91 | $ echo a >> a |
|
92 | 92 | $ echo alpha >> s/alpha |
|
93 | 93 | $ hg sum |
|
94 | 94 | parent: 1:* tip (glob) |
|
95 | 95 | 1 |
|
96 | 96 | branch: default |
|
97 | 97 | commit: 1 modified, 1 subrepos |
|
98 | 98 | update: (current) |
|
99 | 99 | $ hg commit --subrepos -m 'Message!' | grep -v Updating |
|
100 | 100 | committing subrepository s |
|
101 | 101 | Sending*s/alpha (glob) |
|
102 | 102 | Transmitting file data . |
|
103 | 103 | Committed revision 3. |
|
104 | 104 | |
|
105 | 105 | Fetching external item into '*s/externals'* (glob) |
|
106 | 106 | External at revision 1. |
|
107 | 107 | |
|
108 | 108 | At revision 3. |
|
109 | 109 | $ hg debugsub |
|
110 | 110 | path s |
|
111 | 111 | source file://*/svn-repo/src (glob) |
|
112 | 112 | revision 3 |
|
113 | 113 | path subdir/s |
|
114 | 114 | source file://*/svn-repo/src (glob) |
|
115 | 115 | revision 2 |
|
116 | 116 | |
|
117 | 117 | missing svn file, commit should fail |
|
118 | 118 | |
|
119 | 119 | $ rm s/alpha |
|
120 | 120 | $ hg commit --subrepos -m 'abort on missing file' |
|
121 | 121 | committing subrepository s |
|
122 | 122 | abort: cannot commit missing svn entries (in subrepo s) |
|
123 | 123 | [255] |
|
124 | 124 | $ svn revert s/alpha > /dev/null |
|
125 | 125 | |
|
126 | 126 | add an unrelated revision in svn and update the subrepo to without |
|
127 | 127 | bringing any changes. |
|
128 | 128 | |
|
129 | 129 | $ svn mkdir "$SVNREPOURL/unrelated" -m 'create unrelated' |
|
130 | 130 | |
|
131 | 131 | Committed revision 4. |
|
132 | 132 | $ svn up -q s |
|
133 | 133 | $ hg sum |
|
134 | 134 | parent: 2:* tip (glob) |
|
135 | 135 | Message! |
|
136 | 136 | branch: default |
|
137 | 137 | commit: (clean) |
|
138 | 138 | update: (current) |
|
139 | 139 | |
|
140 | 140 | $ echo a > s/a |
|
141 | 141 | |
|
142 | 142 | should be empty despite change to s/a |
|
143 | 143 | |
|
144 | 144 | $ hg st |
|
145 | 145 | |
|
146 | 146 | add a commit from svn |
|
147 | 147 | |
|
148 | 148 | $ cd "$WCROOT/src" |
|
149 | 149 | $ svn up -q |
|
150 | 150 | $ echo xyz >> alpha |
|
151 | 151 | $ svn propset svn:mime-type 'text/xml' alpha |
|
152 | 152 | property 'svn:mime-type' set on 'alpha' |
|
153 | 153 | $ svn ci -m 'amend a from svn' |
|
154 | 154 | Sending *alpha (glob) |
|
155 | 155 | Transmitting file data . |
|
156 | 156 | Committed revision 5. |
|
157 | 157 | $ cd ../../sub/t |
|
158 | 158 | |
|
159 | 159 | this commit from hg will fail |
|
160 | 160 | |
|
161 | 161 | $ echo zzz >> s/alpha |
|
162 | 162 | $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date' |
|
163 | 163 | committing subrepository s |
|
164 | 164 | abort: svn:*Commit failed (details follow): (glob) |
|
165 | 165 | [255] |
|
166 | 166 | $ svn revert -q s/alpha |
|
167 | 167 | |
|
168 | 168 | this commit fails because of meta changes |
|
169 | 169 | |
|
170 | 170 | $ svn propset svn:mime-type 'text/html' s/alpha |
|
171 | 171 | property 'svn:mime-type' set on 's/alpha' (glob) |
|
172 | 172 | $ (hg ci --subrepos -m 'amend alpha from hg' 2>&1; echo "[$?]") | grep -vi 'out of date' |
|
173 | 173 | committing subrepository s |
|
174 | 174 | abort: svn:*Commit failed (details follow): (glob) |
|
175 | 175 | [255] |
|
176 | 176 | $ svn revert -q s/alpha |
|
177 | 177 | |
|
178 | 178 | this commit fails because of externals changes |
|
179 | 179 | |
|
180 | 180 | $ echo zzz > s/externals/other |
|
181 | 181 | $ hg ci --subrepos -m 'amend externals from hg' |
|
182 | 182 | committing subrepository s |
|
183 | 183 | abort: cannot commit svn externals (in subrepo s) |
|
184 | 184 | [255] |
|
185 | 185 | $ hg diff --subrepos -r 1:2 | grep -v diff |
|
186 | 186 | --- a/.hgsubstate Thu Jan 01 00:00:00 1970 +0000 |
|
187 | 187 | +++ b/.hgsubstate Thu Jan 01 00:00:00 1970 +0000 |
|
188 | 188 | @@ -1,2 +1,2 @@ |
|
189 | 189 | -2 s |
|
190 | 190 | +3 s |
|
191 | 191 | 2 subdir/s |
|
192 | 192 | --- a/a Thu Jan 01 00:00:00 1970 +0000 |
|
193 | 193 | +++ b/a Thu Jan 01 00:00:00 1970 +0000 |
|
194 | 194 | @@ -1,1 +1,2 @@ |
|
195 | 195 | a |
|
196 | 196 | +a |
|
197 | 197 | $ svn revert -q s/externals/other |
|
198 | 198 | |
|
199 | 199 | this commit fails because of externals meta changes |
|
200 | 200 | |
|
201 | 201 | $ svn propset svn:mime-type 'text/html' s/externals/other |
|
202 | 202 | property 'svn:mime-type' set on 's/externals/other' (glob) |
|
203 | 203 | $ hg ci --subrepos -m 'amend externals from hg' |
|
204 | 204 | committing subrepository s |
|
205 | 205 | abort: cannot commit svn externals (in subrepo s) |
|
206 | 206 | [255] |
|
207 | 207 | $ svn revert -q s/externals/other |
|
208 | 208 | |
|
209 | 209 | clone |
|
210 | 210 | |
|
211 | 211 | $ cd .. |
|
212 | 212 | $ hg clone t tc |
|
213 | 213 | updating to branch default |
|
214 | 214 | A tc/s/alpha (glob) |
|
215 | 215 | U tc/s (glob) |
|
216 | 216 | |
|
217 | 217 | Fetching external item into 'tc/s/externals'* (glob) |
|
218 | 218 | A tc/s/externals/other (glob) |
|
219 | 219 | Checked out external at revision 1. |
|
220 | 220 | |
|
221 | 221 | Checked out revision 3. |
|
222 | 222 | A tc/subdir/s/alpha (glob) |
|
223 | 223 | U tc/subdir/s (glob) |
|
224 | 224 | |
|
225 | 225 | Fetching external item into 'tc/subdir/s/externals'* (glob) |
|
226 | 226 | A tc/subdir/s/externals/other (glob) |
|
227 | 227 | Checked out external at revision 1. |
|
228 | 228 | |
|
229 | 229 | Checked out revision 2. |
|
230 | 230 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
231 | 231 | $ cd tc |
|
232 | 232 | |
|
233 | 233 | debugsub in clone |
|
234 | 234 | |
|
235 | 235 | $ hg debugsub |
|
236 | 236 | path s |
|
237 | 237 | source file://*/svn-repo/src (glob) |
|
238 | 238 | revision 3 |
|
239 | 239 | path subdir/s |
|
240 | 240 | source file://*/svn-repo/src (glob) |
|
241 | 241 | revision 2 |
|
242 | 242 | |
|
243 | 243 | verify subrepo is contained within the repo directory |
|
244 | 244 | |
|
245 | 245 | $ python -c "import os.path; print os.path.exists('s')" |
|
246 | 246 | True |
|
247 | 247 | |
|
248 | 248 | update to nullrev (must delete the subrepo) |
|
249 | 249 | |
|
250 | 250 | $ hg up null |
|
251 | 251 | 0 files updated, 0 files merged, 3 files removed, 0 files unresolved |
|
252 | 252 | $ ls |
|
253 | 253 | |
|
254 | 254 | Check hg update --clean |
|
255 | 255 | $ cd "$TESTTMP/sub/t" |
|
256 | 256 | $ cd s |
|
257 | 257 | $ echo c0 > alpha |
|
258 | 258 | $ echo c1 > f1 |
|
259 | 259 | $ echo c1 > f2 |
|
260 | 260 | $ svn add f1 -q |
|
261 | 261 | $ svn status | sort |
|
262 | 262 | |
|
263 | 263 | ? * a (glob) |
|
264 | 264 | ? * f2 (glob) |
|
265 | 265 | A * f1 (glob) |
|
266 | 266 | M * alpha (glob) |
|
267 | 267 | Performing status on external item at 'externals'* (glob) |
|
268 | 268 | X * externals (glob) |
|
269 | 269 | $ cd ../.. |
|
270 | 270 | $ hg -R t update -C |
|
271 | 271 | |
|
272 | 272 | Fetching external item into 't/s/externals'* (glob) |
|
273 | 273 | Checked out external at revision 1. |
|
274 | 274 | |
|
275 | 275 | Checked out revision 3. |
|
276 | 276 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
277 | 277 | $ cd t/s |
|
278 | 278 | $ svn status | sort |
|
279 | 279 | |
|
280 | 280 | ? * a (glob) |
|
281 | 281 | ? * f1 (glob) |
|
282 | 282 | ? * f2 (glob) |
|
283 | 283 | Performing status on external item at 'externals'* (glob) |
|
284 | 284 | X * externals (glob) |
|
285 | 285 | |
|
286 | 286 | Sticky subrepositories, no changes |
|
287 | 287 | $ cd "$TESTTMP/sub/t" |
|
288 | 288 | $ hg id -n |
|
289 | 289 | 2 |
|
290 | 290 | $ cd s |
|
291 | 291 | $ svnversion |
|
292 | 292 | 3 |
|
293 | 293 | $ cd .. |
|
294 | 294 | $ hg update 1 |
|
295 | 295 | U *s/alpha (glob) |
|
296 | 296 | |
|
297 | 297 | Fetching external item into '*s/externals'* (glob) |
|
298 | 298 | Checked out external at revision 1. |
|
299 | 299 | |
|
300 | 300 | Checked out revision 2. |
|
301 | 301 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
302 | 302 | $ hg id -n |
|
303 | 303 | 1 |
|
304 | 304 | $ cd s |
|
305 | 305 | $ svnversion |
|
306 | 306 | 2 |
|
307 | 307 | $ cd .. |
|
308 | 308 | |
|
309 | 309 | Sticky subrepositories, file changes |
|
310 | 310 | $ touch s/f1 |
|
311 | 311 | $ cd s |
|
312 | 312 | $ svn add f1 |
|
313 | 313 | A f1 |
|
314 | 314 | $ cd .. |
|
315 | 315 | $ hg id -n |
|
316 | 316 | 1+ |
|
317 | 317 | $ cd s |
|
318 | 318 | $ svnversion |
|
319 | 319 | 2M |
|
320 | 320 | $ cd .. |
|
321 | 321 | $ hg update tip |
|
322 | 322 | subrepository s diverged (local revision: 2, remote revision: 3) |
|
323 | 323 | (M)erge, keep (l)ocal or keep (r)emote? m |
|
324 | 324 | subrepository sources for s differ |
|
325 | 325 | use (l)ocal source (2) or (r)emote source (3)? |
|
326 | 326 | l |
|
327 | 327 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
328 | 328 | $ hg id -n |
|
329 | 329 | 2+ |
|
330 | 330 | $ cd s |
|
331 | 331 | $ svnversion |
|
332 | 332 | 2M |
|
333 | 333 | $ cd .. |
|
334 | 334 | $ hg update --clean tip |
|
335 | 335 | U *s/alpha (glob) |
|
336 | 336 | |
|
337 | 337 | Fetching external item into '*s/externals'* (glob) |
|
338 | 338 | Checked out external at revision 1. |
|
339 | 339 | |
|
340 | 340 | Checked out revision 3. |
|
341 | 341 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
342 | 342 | |
|
343 | 343 | Sticky subrepository, revision updates |
|
344 | 344 | $ hg id -n |
|
345 | 345 | 2 |
|
346 | 346 | $ cd s |
|
347 | 347 | $ svnversion |
|
348 | 348 | 3 |
|
349 | 349 | $ cd .. |
|
350 | 350 | $ cd s |
|
351 | 351 | $ svn update -qr 1 |
|
352 | 352 | $ cd .. |
|
353 | 353 | $ hg update 1 |
|
354 | 354 | subrepository s diverged (local revision: 3, remote revision: 2) |
|
355 | 355 | (M)erge, keep (l)ocal or keep (r)emote? m |
|
356 | 356 | subrepository sources for s differ (in checked out version) |
|
357 | 357 | use (l)ocal source (1) or (r)emote source (2)? |
|
358 | 358 | l |
|
359 | 359 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
360 | 360 | $ hg id -n |
|
361 | 361 | 1+ |
|
362 | 362 | $ cd s |
|
363 | 363 | $ svnversion |
|
364 | 364 | 1 |
|
365 | 365 | $ cd .. |
|
366 | 366 | |
|
367 | 367 | Sticky subrepository, file changes and revision updates |
|
368 | 368 | $ touch s/f1 |
|
369 | 369 | $ cd s |
|
370 | 370 | $ svn add f1 |
|
371 | 371 | A f1 |
|
372 | 372 | $ svnversion |
|
373 | 373 | 1M |
|
374 | 374 | $ cd .. |
|
375 | 375 | $ hg id -n |
|
376 | 376 | 1+ |
|
377 | 377 | $ hg update tip |
|
378 | 378 | subrepository s diverged (local revision: 3, remote revision: 3) |
|
379 | 379 | (M)erge, keep (l)ocal or keep (r)emote? m |
|
380 | 380 | subrepository sources for s differ |
|
381 | 381 | use (l)ocal source (1) or (r)emote source (3)? |
|
382 | 382 | l |
|
383 | 383 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
384 | 384 | $ hg id -n |
|
385 | 385 | 2+ |
|
386 | 386 | $ cd s |
|
387 | 387 | $ svnversion |
|
388 | 388 | 1M |
|
389 | 389 | $ cd .. |
|
390 | 390 | |
|
391 | 391 | Sticky repository, update --clean |
|
392 | 392 | $ hg update --clean tip | grep -v 's[/\]externals[/\]other' |
|
393 | 393 | U *s/alpha (glob) |
|
394 | 394 | U *s (glob) |
|
395 | 395 | |
|
396 | 396 | Fetching external item into '*s/externals'* (glob) |
|
397 | 397 | Checked out external at revision 1. |
|
398 | 398 | |
|
399 | 399 | Checked out revision 3. |
|
400 | 400 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
401 | 401 | $ hg id -n |
|
402 | 402 | 2 |
|
403 | 403 | $ cd s |
|
404 | 404 | $ svnversion |
|
405 | 405 | 3 |
|
406 | 406 | $ cd .. |
|
407 | 407 | |
|
408 | 408 | Test subrepo already at intended revision: |
|
409 | 409 | $ cd s |
|
410 | 410 | $ svn update -qr 2 |
|
411 | 411 | $ cd .. |
|
412 | 412 | $ hg update 1 |
|
413 | 413 | subrepository s diverged (local revision: 3, remote revision: 2) |
|
414 | 414 | (M)erge, keep (l)ocal or keep (r)emote? m |
|
415 | 415 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
416 | 416 | $ hg id -n |
|
417 | 417 | 1+ |
|
418 | 418 | $ cd s |
|
419 | 419 | $ svnversion |
|
420 | 420 | 2 |
|
421 | 421 | $ cd .. |
|
422 | 422 | |
|
423 | 423 | Test case where subversion would fail to update the subrepo because there |
|
424 | 424 | are unknown directories being replaced by tracked ones (happens with rebase). |
|
425 | 425 | |
|
426 | 426 | $ cd "$WCROOT/src" |
|
427 | 427 | $ mkdir dir |
|
428 | 428 | $ echo epsilon.py > dir/epsilon.py |
|
429 | 429 | $ svn add dir |
|
430 | 430 | A dir |
|
431 | 431 | A dir/epsilon.py (glob) |
|
432 | 432 | $ svn ci -m 'Add dir/epsilon.py' |
|
433 | 433 | Adding *dir (glob) |
|
434 | 434 | Adding *dir/epsilon.py (glob) |
|
435 | 435 | Transmitting file data . |
|
436 | 436 | Committed revision 6. |
|
437 | 437 | $ cd ../.. |
|
438 | 438 | $ hg init rebaserepo |
|
439 | 439 | $ cd rebaserepo |
|
440 | 440 | $ svn co -r5 --quiet "$SVNREPOURL"/src s |
|
441 | 441 | $ echo "s = [svn] $SVNREPOURL/src" >> .hgsub |
|
442 | 442 | $ hg add .hgsub |
|
443 | 443 | $ hg ci -m addsub |
|
444 | 444 | $ echo a > a |
|
445 | 445 | $ hg ci -Am adda |
|
446 | 446 | adding a |
|
447 | 447 | $ hg up 0 |
|
448 | 448 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
449 | 449 | $ svn up -qr6 s |
|
450 | 450 | $ hg ci -m updatesub |
|
451 | 451 | created new head |
|
452 | 452 | $ echo pyc > s/dir/epsilon.pyc |
|
453 | 453 | $ hg up 1 |
|
454 | 454 | D *s/dir (glob) |
|
455 | 455 | |
|
456 | 456 | Fetching external item into '*s/externals'* (glob) |
|
457 | 457 | Checked out external at revision 1. |
|
458 | 458 | |
|
459 | 459 | Checked out revision 5. |
|
460 | 460 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
461 | 461 | $ hg up -q 2 |
|
462 | 462 | |
|
463 | 463 | Modify one of the externals to point to a different path so we can |
|
464 | 464 | test having obstructions when switching branches on checkout: |
|
465 | 465 | $ hg checkout tip |
|
466 | 466 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
467 | 467 | $ echo "obstruct = [svn] $SVNREPOURL/externals" >> .hgsub |
|
468 | 468 | $ svn co -r5 --quiet "$SVNREPOURL"/externals obstruct |
|
469 | 469 | $ hg commit -m 'Start making obstructed working copy' |
|
470 | 470 | $ hg book other |
|
471 | 471 | $ hg co -r 'p1(tip)' |
|
472 | 472 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
473 | 473 | (leaving bookmark other) |
|
474 | 474 | $ echo "obstruct = [svn] $SVNREPOURL/src" >> .hgsub |
|
475 | 475 | $ svn co -r5 --quiet "$SVNREPOURL"/src obstruct |
|
476 | 476 | $ hg commit -m 'Other branch which will be obstructed' |
|
477 | 477 | created new head |
|
478 | 478 | |
|
479 | 479 | Switching back to the head where we have another path mapped to the |
|
480 | 480 | same subrepo should work if the subrepo is clean. |
|
481 | 481 | $ hg co other |
|
482 | 482 | A *obstruct/other (glob) |
|
483 | 483 | Checked out revision 1. |
|
484 | 484 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
485 | 485 | (activating bookmark other) |
|
486 | 486 | |
|
487 | 487 | This is surprising, but is also correct based on the current code: |
|
488 | 488 | $ echo "updating should (maybe) fail" > obstruct/other |
|
489 | 489 | $ hg co tip |
|
490 | 490 | abort: uncommitted changes |
|
491 | 491 | (commit or update --clean to discard changes) |
|
492 | 492 | [255] |
|
493 | 493 | |
|
494 | 494 | Point to a Subversion branch which has since been deleted and recreated |
|
495 | 495 | First, create that condition in the repository. |
|
496 | 496 | |
|
497 | 497 | $ hg ci --subrepos -m cleanup | grep -v Updating |
|
498 | 498 | committing subrepository obstruct |
|
499 | 499 | Sending obstruct/other (glob) |
|
500 | 500 | Transmitting file data . |
|
501 | 501 | Committed revision 7. |
|
502 | 502 | At revision 7. |
|
503 | 503 | $ svn mkdir -m "baseline" $SVNREPOURL/trunk |
|
504 | 504 | |
|
505 | 505 | Committed revision 8. |
|
506 | 506 | $ svn copy -m "initial branch" $SVNREPOURL/trunk $SVNREPOURL/branch |
|
507 | 507 | |
|
508 | 508 | Committed revision 9. |
|
509 | 509 | $ svn co --quiet "$SVNREPOURL"/branch tempwc |
|
510 | 510 | $ cd tempwc |
|
511 | 511 | $ echo "something old" > somethingold |
|
512 | 512 | $ svn add somethingold |
|
513 | 513 | A somethingold |
|
514 | 514 | $ svn ci -m 'Something old' |
|
515 | 515 | Adding somethingold |
|
516 | 516 | Transmitting file data . |
|
517 | 517 | Committed revision 10. |
|
518 | 518 | $ svn rm -m "remove branch" $SVNREPOURL/branch |
|
519 | 519 | |
|
520 | 520 | Committed revision 11. |
|
521 | 521 | $ svn copy -m "recreate branch" $SVNREPOURL/trunk $SVNREPOURL/branch |
|
522 | 522 | |
|
523 | 523 | Committed revision 12. |
|
524 | 524 | $ svn up -q |
|
525 | 525 | $ echo "something new" > somethingnew |
|
526 | 526 | $ svn add somethingnew |
|
527 | 527 | A somethingnew |
|
528 | 528 | $ svn ci -m 'Something new' |
|
529 | 529 | Adding somethingnew |
|
530 | 530 | Transmitting file data . |
|
531 | 531 | Committed revision 13. |
|
532 | 532 | $ cd .. |
|
533 | 533 | $ rm -rf tempwc |
|
534 | 534 | $ svn co "$SVNREPOURL/branch"@10 recreated |
|
535 | 535 | A recreated/somethingold (glob) |
|
536 | 536 | Checked out revision 10. |
|
537 | 537 | $ echo "recreated = [svn] $SVNREPOURL/branch" >> .hgsub |
|
538 | 538 | $ hg ci -m addsub |
|
539 | 539 | $ cd recreated |
|
540 | 540 | $ svn up -q |
|
541 | 541 | $ cd .. |
|
542 | 542 | $ hg ci -m updatesub |
|
543 | 543 | $ hg up -r-2 |
|
544 | 544 | D *recreated/somethingnew (glob) |
|
545 | 545 | A *recreated/somethingold (glob) |
|
546 | 546 | Checked out revision 10. |
|
547 | 547 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
548 | 548 | (leaving bookmark other) |
|
549 | 549 | $ test -f recreated/somethingold |
|
550 | 550 | |
|
551 | 551 | Test archive |
|
552 | 552 | |
|
553 | 553 | $ hg archive -S ../archive-all --debug |
|
554 | 554 | archiving: 0/2 files (0.00%) |
|
555 | 555 | archiving: .hgsub 1/2 files (50.00%) |
|
556 | 556 | archiving: .hgsubstate 2/2 files (100.00%) |
|
557 | 557 | archiving (obstruct): 0/1 files (0.00%) |
|
558 | 558 | archiving (obstruct): 1/1 files (100.00%) |
|
559 | 559 | archiving (recreated): 0/1 files (0.00%) |
|
560 | 560 | archiving (recreated): 1/1 files (100.00%) |
|
561 | 561 | archiving (s): 0/2 files (0.00%) |
|
562 | 562 | archiving (s): 1/2 files (50.00%) |
|
563 | 563 | archiving (s): 2/2 files (100.00%) |
|
564 | 564 | |
|
565 | 565 | $ hg archive -S ../archive-exclude --debug -X **old |
|
566 | 566 | archiving: 0/2 files (0.00%) |
|
567 | 567 | archiving: .hgsub 1/2 files (50.00%) |
|
568 | 568 | archiving: .hgsubstate 2/2 files (100.00%) |
|
569 | 569 | archiving (obstruct): 0/1 files (0.00%) |
|
570 | 570 | archiving (obstruct): 1/1 files (100.00%) |
|
571 | 571 | archiving (recreated): 0 files |
|
572 | 572 | archiving (s): 0/2 files (0.00%) |
|
573 | 573 | archiving (s): 1/2 files (50.00%) |
|
574 | 574 | archiving (s): 2/2 files (100.00%) |
|
575 | 575 | $ find ../archive-exclude | sort |
|
576 | 576 | ../archive-exclude |
|
577 | 577 | ../archive-exclude/.hg_archival.txt |
|
578 | 578 | ../archive-exclude/.hgsub |
|
579 | 579 | ../archive-exclude/.hgsubstate |
|
580 | 580 | ../archive-exclude/obstruct |
|
581 | 581 | ../archive-exclude/obstruct/other |
|
582 | 582 | ../archive-exclude/s |
|
583 | 583 | ../archive-exclude/s/alpha |
|
584 | 584 | ../archive-exclude/s/dir |
|
585 | 585 | ../archive-exclude/s/dir/epsilon.py |
|
586 | 586 | |
|
587 | 587 | Test forgetting files, not implemented in svn subrepo, used to |
|
588 | 588 | traceback |
|
589 | 589 | |
|
590 | 590 | #if no-windows |
|
591 | 591 | $ hg forget 'notafile*' |
|
592 | 592 | notafile*: No such file or directory |
|
593 | 593 | [1] |
|
594 | 594 | #else |
|
595 | 595 | $ hg forget 'notafile' |
|
596 | 596 | notafile: * (glob) |
|
597 | 597 | [1] |
|
598 | 598 | #endif |
|
599 | 599 | |
|
600 | 600 | Test a subrepo referencing a just moved svn path. Last commit rev will |
|
601 | 601 | be different from the revision, and the path will be different as |
|
602 | 602 | well. |
|
603 | 603 | |
|
604 | 604 | $ cd "$WCROOT" |
|
605 | 605 | $ svn up > /dev/null |
|
606 | 606 | $ mkdir trunk/subdir branches |
|
607 | 607 | $ echo a > trunk/subdir/a |
|
608 | 608 | $ svn add trunk/subdir branches |
|
609 | 609 | A trunk/subdir (glob) |
|
610 | 610 | A trunk/subdir/a (glob) |
|
611 | 611 | A branches |
|
612 | 612 | $ svn ci -m addsubdir |
|
613 | 613 | Adding branches |
|
614 | 614 | Adding trunk/subdir (glob) |
|
615 | 615 | Adding trunk/subdir/a (glob) |
|
616 | 616 | Transmitting file data . |
|
617 | 617 | Committed revision 14. |
|
618 | 618 | $ svn cp -m branchtrunk $SVNREPOURL/trunk $SVNREPOURL/branches/somebranch |
|
619 | 619 | |
|
620 | 620 | Committed revision 15. |
|
621 | 621 | $ cd .. |
|
622 | 622 | |
|
623 | 623 | $ hg init repo2 |
|
624 | 624 | $ cd repo2 |
|
625 | 625 | $ svn co $SVNREPOURL/branches/somebranch/subdir |
|
626 | 626 | A subdir/a (glob) |
|
627 | 627 | Checked out revision 15. |
|
628 | 628 | $ echo "subdir = [svn] $SVNREPOURL/branches/somebranch/subdir" > .hgsub |
|
629 | 629 | $ hg add .hgsub |
|
630 | 630 | $ hg ci -m addsub |
|
631 | 631 | $ hg up null |
|
632 | 632 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
633 | 633 | $ hg up |
|
634 | 634 | A *subdir/a (glob) |
|
635 | 635 | Checked out revision 15. |
|
636 | 636 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
637 | 637 | $ cd .. |
|
638 | 638 | |
|
639 | 639 | Test sanitizing ".hg/hgrc" in subrepo |
|
640 | 640 | |
|
641 | 641 | $ cd sub/t |
|
642 | 642 | $ hg update -q -C tip |
|
643 | 643 | $ cd s |
|
644 | 644 | $ mkdir .hg |
|
645 | 645 | $ echo '.hg/hgrc in svn repo' > .hg/hgrc |
|
646 | 646 | $ mkdir -p sub/.hg |
|
647 | 647 | $ echo 'sub/.hg/hgrc in svn repo' > sub/.hg/hgrc |
|
648 | 648 | $ svn add .hg sub |
|
649 | 649 | A .hg |
|
650 | 650 | A .hg/hgrc (glob) |
|
651 | 651 | A sub |
|
652 | 652 | A sub/.hg (glob) |
|
653 | 653 | A sub/.hg/hgrc (glob) |
|
654 | 654 | $ svn ci -m 'add .hg/hgrc to be sanitized at hg update' |
|
655 | 655 | Adding .hg |
|
656 | 656 | Adding .hg/hgrc (glob) |
|
657 | 657 | Adding sub |
|
658 | 658 | Adding sub/.hg (glob) |
|
659 | 659 | Adding sub/.hg/hgrc (glob) |
|
660 | 660 | Transmitting file data .. |
|
661 | 661 | Committed revision 16. |
|
662 | 662 | $ svn up -q |
|
663 | 663 | $ cd .. |
|
664 | 664 | $ hg commit -S -m 'commit with svn revision including .hg/hgrc' |
|
665 | 665 | $ grep ' s$' .hgsubstate |
|
666 | 666 | 16 s |
|
667 | 667 | $ cd .. |
|
668 | 668 | |
|
669 | 669 | $ hg -R tc pull -u -q 2>&1 | sort |
|
670 | 670 | warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/.hg' (glob) |
|
671 | 671 | warning: removing potentially hostile 'hgrc' in '$TESTTMP/sub/tc/s/sub/.hg' (glob) |
|
672 | 672 | $ cd tc |
|
673 | 673 | $ grep ' s$' .hgsubstate |
|
674 | 674 | 16 s |
|
675 |
$ |
|
|
676 | cat: s/.hg/hgrc: No such file or directory | |
|
675 | $ test -f s/.hg/hgrc | |
|
677 | 676 | [1] |
|
678 |
$ |
|
|
679 | cat: s/sub/.hg/hgrc: No such file or directory | |
|
677 | $ test -f s/sub/.hg/hgrc | |
|
680 | 678 | [1] |
|
681 | 679 | |
|
682 | 680 | Test that sanitizing is omitted in meta data area: |
|
683 | 681 | |
|
684 | 682 | $ mkdir s/.svn/.hg |
|
685 | 683 | $ echo '.hg/hgrc in svn metadata area' > s/.svn/.hg/hgrc |
|
686 | 684 | $ hg update -q -C '.^1' |
|
687 | 685 | |
|
688 | 686 | $ cd ../.. |
@@ -1,606 +1,605 b'' | |||
|
1 | 1 | $ hg init test |
|
2 | 2 | $ cd test |
|
3 | 3 | |
|
4 | 4 | $ echo a > a |
|
5 | 5 | $ hg add a |
|
6 | 6 | $ hg commit -m "test" |
|
7 | 7 | $ hg history |
|
8 | 8 | changeset: 0:acb14030fe0a |
|
9 | 9 | tag: tip |
|
10 | 10 | user: test |
|
11 | 11 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
12 | 12 | summary: test |
|
13 | 13 | |
|
14 | 14 | |
|
15 | 15 | $ hg tag ' ' |
|
16 | 16 | abort: tag names cannot consist entirely of whitespace |
|
17 | 17 | [255] |
|
18 | 18 | |
|
19 | 19 | (this tests also that editor is not invoked, if '--edit' is not |
|
20 | 20 | specified) |
|
21 | 21 | |
|
22 | 22 | $ HGEDITOR=cat hg tag "bleah" |
|
23 | 23 | $ hg history |
|
24 | 24 | changeset: 1:d4f0d2909abc |
|
25 | 25 | tag: tip |
|
26 | 26 | user: test |
|
27 | 27 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
28 | 28 | summary: Added tag bleah for changeset acb14030fe0a |
|
29 | 29 | |
|
30 | 30 | changeset: 0:acb14030fe0a |
|
31 | 31 | tag: bleah |
|
32 | 32 | user: test |
|
33 | 33 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
34 | 34 | summary: test |
|
35 | 35 | |
|
36 | 36 | |
|
37 | 37 | $ echo foo >> .hgtags |
|
38 | 38 | $ hg tag "bleah2" |
|
39 | 39 | abort: working copy of .hgtags is changed (please commit .hgtags manually) |
|
40 | 40 | [255] |
|
41 | 41 | |
|
42 | 42 | $ hg revert .hgtags |
|
43 | 43 | $ hg tag -r 0 x y z y y z |
|
44 | 44 | abort: tag names must be unique |
|
45 | 45 | [255] |
|
46 | 46 | $ hg tag tap nada dot tip |
|
47 | 47 | abort: the name 'tip' is reserved |
|
48 | 48 | [255] |
|
49 | 49 | $ hg tag . |
|
50 | 50 | abort: the name '.' is reserved |
|
51 | 51 | [255] |
|
52 | 52 | $ hg tag null |
|
53 | 53 | abort: the name 'null' is reserved |
|
54 | 54 | [255] |
|
55 | 55 | $ hg tag "bleah" |
|
56 | 56 | abort: tag 'bleah' already exists (use -f to force) |
|
57 | 57 | [255] |
|
58 | 58 | $ hg tag "blecch" "bleah" |
|
59 | 59 | abort: tag 'bleah' already exists (use -f to force) |
|
60 | 60 | [255] |
|
61 | 61 | |
|
62 | 62 | $ hg tag --remove "blecch" |
|
63 | 63 | abort: tag 'blecch' does not exist |
|
64 | 64 | [255] |
|
65 | 65 | $ hg tag --remove "bleah" "blecch" "blough" |
|
66 | 66 | abort: tag 'blecch' does not exist |
|
67 | 67 | [255] |
|
68 | 68 | |
|
69 | 69 | $ hg tag -r 0 "bleah0" |
|
70 | 70 | $ hg tag -l -r 1 "bleah1" |
|
71 | 71 | $ hg tag gack gawk gorp |
|
72 | 72 | $ hg tag -f gack |
|
73 | 73 | $ hg tag --remove gack gorp |
|
74 | 74 | |
|
75 | 75 | $ hg tag "bleah " |
|
76 | 76 | abort: tag 'bleah' already exists (use -f to force) |
|
77 | 77 | [255] |
|
78 | 78 | $ hg tag " bleah" |
|
79 | 79 | abort: tag 'bleah' already exists (use -f to force) |
|
80 | 80 | [255] |
|
81 | 81 | $ hg tag " bleah" |
|
82 | 82 | abort: tag 'bleah' already exists (use -f to force) |
|
83 | 83 | [255] |
|
84 | 84 | $ hg tag -r 0 " bleahbleah " |
|
85 | 85 | $ hg tag -r 0 " bleah bleah " |
|
86 | 86 | |
|
87 | 87 | $ cat .hgtags |
|
88 | 88 | acb14030fe0a21b60322c440ad2d20cf7685a376 bleah |
|
89 | 89 | acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0 |
|
90 | 90 | 336fccc858a4eb69609a291105009e484a6b6b8d gack |
|
91 | 91 | 336fccc858a4eb69609a291105009e484a6b6b8d gawk |
|
92 | 92 | 336fccc858a4eb69609a291105009e484a6b6b8d gorp |
|
93 | 93 | 336fccc858a4eb69609a291105009e484a6b6b8d gack |
|
94 | 94 | 799667b6f2d9b957f73fa644a918c2df22bab58f gack |
|
95 | 95 | 799667b6f2d9b957f73fa644a918c2df22bab58f gack |
|
96 | 96 | 0000000000000000000000000000000000000000 gack |
|
97 | 97 | 336fccc858a4eb69609a291105009e484a6b6b8d gorp |
|
98 | 98 | 0000000000000000000000000000000000000000 gorp |
|
99 | 99 | acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah |
|
100 | 100 | acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah |
|
101 | 101 | |
|
102 | 102 | $ cat .hg/localtags |
|
103 | 103 | d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1 |
|
104 | 104 | |
|
105 | 105 | tagging on a non-head revision |
|
106 | 106 | |
|
107 | 107 | $ hg update 0 |
|
108 | 108 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
109 | 109 | $ hg tag -l localblah |
|
110 | 110 | $ hg tag "foobar" |
|
111 | 111 | abort: not at a branch head (use -f to force) |
|
112 | 112 | [255] |
|
113 | 113 | $ hg tag -f "foobar" |
|
114 | 114 | $ cat .hgtags |
|
115 | 115 | acb14030fe0a21b60322c440ad2d20cf7685a376 foobar |
|
116 | 116 | $ cat .hg/localtags |
|
117 | 117 | d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1 |
|
118 | 118 | acb14030fe0a21b60322c440ad2d20cf7685a376 localblah |
|
119 | 119 | |
|
120 | 120 | $ hg tag -l 'xx |
|
121 | 121 | > newline' |
|
122 | 122 | abort: '\n' cannot be used in a name |
|
123 | 123 | [255] |
|
124 | 124 | $ hg tag -l 'xx:xx' |
|
125 | 125 | abort: ':' cannot be used in a name |
|
126 | 126 | [255] |
|
127 | 127 | |
|
128 | 128 | cloning local tags |
|
129 | 129 | |
|
130 | 130 | $ cd .. |
|
131 | 131 | $ hg -R test log -r0:5 |
|
132 | 132 | changeset: 0:acb14030fe0a |
|
133 | 133 | tag: bleah |
|
134 | 134 | tag: bleah bleah |
|
135 | 135 | tag: bleah0 |
|
136 | 136 | tag: bleahbleah |
|
137 | 137 | tag: foobar |
|
138 | 138 | tag: localblah |
|
139 | 139 | user: test |
|
140 | 140 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
141 | 141 | summary: test |
|
142 | 142 | |
|
143 | 143 | changeset: 1:d4f0d2909abc |
|
144 | 144 | tag: bleah1 |
|
145 | 145 | user: test |
|
146 | 146 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
147 | 147 | summary: Added tag bleah for changeset acb14030fe0a |
|
148 | 148 | |
|
149 | 149 | changeset: 2:336fccc858a4 |
|
150 | 150 | tag: gawk |
|
151 | 151 | user: test |
|
152 | 152 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
153 | 153 | summary: Added tag bleah0 for changeset acb14030fe0a |
|
154 | 154 | |
|
155 | 155 | changeset: 3:799667b6f2d9 |
|
156 | 156 | user: test |
|
157 | 157 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
158 | 158 | summary: Added tag gack, gawk, gorp for changeset 336fccc858a4 |
|
159 | 159 | |
|
160 | 160 | changeset: 4:154eeb7c0138 |
|
161 | 161 | user: test |
|
162 | 162 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
163 | 163 | summary: Added tag gack for changeset 799667b6f2d9 |
|
164 | 164 | |
|
165 | 165 | changeset: 5:b4bb47aaff09 |
|
166 | 166 | user: test |
|
167 | 167 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
168 | 168 | summary: Removed tag gack, gorp |
|
169 | 169 | |
|
170 | 170 | $ hg clone -q -rbleah1 test test1 |
|
171 | 171 | $ hg -R test1 parents --style=compact |
|
172 | 172 | 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test |
|
173 | 173 | Added tag bleah for changeset acb14030fe0a |
|
174 | 174 | |
|
175 | 175 | $ hg clone -q -r5 test#bleah1 test2 |
|
176 | 176 | $ hg -R test2 parents --style=compact |
|
177 | 177 | 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test |
|
178 | 178 | Removed tag gack, gorp |
|
179 | 179 | |
|
180 | 180 | $ hg clone -q -U test#bleah1 test3 |
|
181 | 181 | $ hg -R test3 parents --style=compact |
|
182 | 182 | |
|
183 | 183 | $ cd test |
|
184 | 184 | |
|
185 | 185 | Issue601: hg tag doesn't do the right thing if .hgtags or localtags |
|
186 | 186 | doesn't end with EOL |
|
187 | 187 | |
|
188 | 188 | $ python << EOF |
|
189 | 189 | > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close() |
|
190 | 190 | > f = file('.hg/localtags', 'w'); f.write(last); f.close() |
|
191 | 191 | > EOF |
|
192 | 192 | $ cat .hg/localtags; echo |
|
193 | 193 | acb14030fe0a21b60322c440ad2d20cf7685a376 localblah |
|
194 | 194 | $ hg tag -l localnewline |
|
195 | 195 | $ cat .hg/localtags; echo |
|
196 | 196 | acb14030fe0a21b60322c440ad2d20cf7685a376 localblah |
|
197 | 197 | c2899151f4e76890c602a2597a650a72666681bf localnewline |
|
198 | 198 | |
|
199 | 199 | |
|
200 | 200 | $ python << EOF |
|
201 | 201 | > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close() |
|
202 | 202 | > f = file('.hgtags', 'w'); f.write(last); f.close() |
|
203 | 203 | > EOF |
|
204 | 204 | $ hg ci -m'broken manual edit of .hgtags' |
|
205 | 205 | $ cat .hgtags; echo |
|
206 | 206 | acb14030fe0a21b60322c440ad2d20cf7685a376 foobar |
|
207 | 207 | $ hg tag newline |
|
208 | 208 | $ cat .hgtags; echo |
|
209 | 209 | acb14030fe0a21b60322c440ad2d20cf7685a376 foobar |
|
210 | 210 | a0eea09de1eeec777b46f2085260a373b2fbc293 newline |
|
211 | 211 | |
|
212 | 212 | |
|
213 | 213 | tag and branch using same name |
|
214 | 214 | |
|
215 | 215 | $ hg branch tag-and-branch-same-name |
|
216 | 216 | marked working directory as branch tag-and-branch-same-name |
|
217 | 217 | (branches are permanent and global, did you want a bookmark?) |
|
218 | 218 | $ hg ci -m"discouraged" |
|
219 | 219 | $ hg tag tag-and-branch-same-name |
|
220 | 220 | warning: tag tag-and-branch-same-name conflicts with existing branch name |
|
221 | 221 | |
|
222 | 222 | test custom commit messages |
|
223 | 223 | |
|
224 | 224 | $ cat > editor.sh << '__EOF__' |
|
225 | 225 | > echo "==== before editing" |
|
226 | 226 | > cat "$1" |
|
227 | 227 | > echo "====" |
|
228 | 228 | > echo "custom tag message" > "$1" |
|
229 | 229 | > echo "second line" >> "$1" |
|
230 | 230 | > __EOF__ |
|
231 | 231 | |
|
232 | 232 | at first, test saving last-message.txt |
|
233 | 233 | |
|
234 | 234 | (test that editor is not invoked before transaction starting) |
|
235 | 235 | |
|
236 | 236 | $ cat > .hg/hgrc << '__EOF__' |
|
237 | 237 | > [hooks] |
|
238 | 238 | > # this failure occurs before editor invocation |
|
239 | 239 | > pretag.test-saving-lastmessage = false |
|
240 | 240 | > __EOF__ |
|
241 | 241 | $ rm -f .hg/last-message.txt |
|
242 | 242 | $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e |
|
243 | 243 | abort: pretag.test-saving-lastmessage hook exited with status 1 |
|
244 | 244 | [255] |
|
245 |
$ |
|
|
246 | cat: .hg/last-message.txt: No such file or directory | |
|
245 | $ test -f .hg/last-message.txt | |
|
247 | 246 | [1] |
|
248 | 247 | |
|
249 | 248 | (test that editor is invoked and commit message is saved into |
|
250 | 249 | "last-message.txt") |
|
251 | 250 | |
|
252 | 251 | $ cat >> .hg/hgrc << '__EOF__' |
|
253 | 252 | > [hooks] |
|
254 | 253 | > pretag.test-saving-lastmessage = |
|
255 | 254 | > # this failure occurs after editor invocation |
|
256 | 255 | > pretxncommit.unexpectedabort = false |
|
257 | 256 | > __EOF__ |
|
258 | 257 | |
|
259 | 258 | (this tests also that editor is invoked, if '--edit' is specified, |
|
260 | 259 | regardless of '--message') |
|
261 | 260 | |
|
262 | 261 | $ rm -f .hg/last-message.txt |
|
263 | 262 | $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e -m "foo bar" |
|
264 | 263 | ==== before editing |
|
265 | 264 | foo bar |
|
266 | 265 | |
|
267 | 266 | |
|
268 | 267 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
269 | 268 | HG: Leave message empty to abort commit. |
|
270 | 269 | HG: -- |
|
271 | 270 | HG: user: test |
|
272 | 271 | HG: branch 'tag-and-branch-same-name' |
|
273 | 272 | HG: changed .hgtags |
|
274 | 273 | ==== |
|
275 | 274 | transaction abort! |
|
276 | 275 | rollback completed |
|
277 | 276 | note: commit message saved in .hg/last-message.txt |
|
278 | 277 | abort: pretxncommit.unexpectedabort hook exited with status 1 |
|
279 | 278 | [255] |
|
280 | 279 | $ cat .hg/last-message.txt |
|
281 | 280 | custom tag message |
|
282 | 281 | second line |
|
283 | 282 | |
|
284 | 283 | $ cat >> .hg/hgrc << '__EOF__' |
|
285 | 284 | > [hooks] |
|
286 | 285 | > pretxncommit.unexpectedabort = |
|
287 | 286 | > __EOF__ |
|
288 | 287 | $ hg status .hgtags |
|
289 | 288 | M .hgtags |
|
290 | 289 | $ hg revert --no-backup -q .hgtags |
|
291 | 290 | |
|
292 | 291 | then, test custom commit message itself |
|
293 | 292 | |
|
294 | 293 | $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg tag custom-tag -e |
|
295 | 294 | ==== before editing |
|
296 | 295 | Added tag custom-tag for changeset 75a534207be6 |
|
297 | 296 | |
|
298 | 297 | |
|
299 | 298 | HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
300 | 299 | HG: Leave message empty to abort commit. |
|
301 | 300 | HG: -- |
|
302 | 301 | HG: user: test |
|
303 | 302 | HG: branch 'tag-and-branch-same-name' |
|
304 | 303 | HG: changed .hgtags |
|
305 | 304 | ==== |
|
306 | 305 | $ hg log -l1 --template "{desc}\n" |
|
307 | 306 | custom tag message |
|
308 | 307 | second line |
|
309 | 308 | |
|
310 | 309 | |
|
311 | 310 | local tag with .hgtags modified |
|
312 | 311 | |
|
313 | 312 | $ hg tag hgtags-modified |
|
314 | 313 | $ hg rollback |
|
315 | 314 | repository tip rolled back to revision 13 (undo commit) |
|
316 | 315 | working directory now based on revision 13 |
|
317 | 316 | $ hg st |
|
318 | 317 | M .hgtags |
|
319 | 318 | ? .hgtags.orig |
|
320 | 319 | ? editor.sh |
|
321 | 320 | $ hg tag --local baz |
|
322 | 321 | $ hg revert --no-backup .hgtags |
|
323 | 322 | |
|
324 | 323 | |
|
325 | 324 | tagging when at named-branch-head that's not a topo-head |
|
326 | 325 | |
|
327 | 326 | $ hg up default |
|
328 | 327 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
329 | 328 | $ hg merge -t internal:local |
|
330 | 329 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
|
331 | 330 | (branch merge, don't forget to commit) |
|
332 | 331 | $ hg ci -m 'merge named branch' |
|
333 | 332 | $ hg up 13 |
|
334 | 333 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
335 | 334 | $ hg tag new-topo-head |
|
336 | 335 | |
|
337 | 336 | tagging on null rev |
|
338 | 337 | |
|
339 | 338 | $ hg up null |
|
340 | 339 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
341 | 340 | $ hg tag nullrev |
|
342 | 341 | abort: not at a branch head (use -f to force) |
|
343 | 342 | [255] |
|
344 | 343 | |
|
345 | 344 | $ hg init empty |
|
346 | 345 | $ hg tag -R empty nullrev |
|
347 | 346 | abort: cannot tag null revision |
|
348 | 347 | [255] |
|
349 | 348 | |
|
350 | 349 | $ hg tag -R empty -r 00000000000 -f nulltag |
|
351 | 350 | abort: cannot tag null revision |
|
352 | 351 | [255] |
|
353 | 352 | |
|
354 | 353 | $ cd .. |
|
355 | 354 | |
|
356 | 355 | tagging on an uncommitted merge (issue2542) |
|
357 | 356 | |
|
358 | 357 | $ hg init repo-tag-uncommitted-merge |
|
359 | 358 | $ cd repo-tag-uncommitted-merge |
|
360 | 359 | $ echo c1 > f1 |
|
361 | 360 | $ hg ci -Am0 |
|
362 | 361 | adding f1 |
|
363 | 362 | $ echo c2 > f2 |
|
364 | 363 | $ hg ci -Am1 |
|
365 | 364 | adding f2 |
|
366 | 365 | $ hg co -q 0 |
|
367 | 366 | $ hg branch b1 |
|
368 | 367 | marked working directory as branch b1 |
|
369 | 368 | (branches are permanent and global, did you want a bookmark?) |
|
370 | 369 | $ hg ci -m2 |
|
371 | 370 | $ hg up default |
|
372 | 371 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
373 | 372 | $ hg merge b1 |
|
374 | 373 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
375 | 374 | (branch merge, don't forget to commit) |
|
376 | 375 | |
|
377 | 376 | $ hg tag t1 |
|
378 | 377 | abort: uncommitted merge |
|
379 | 378 | [255] |
|
380 | 379 | $ hg status |
|
381 | 380 | $ hg tag --rev 1 t2 |
|
382 | 381 | abort: uncommitted merge |
|
383 | 382 | [255] |
|
384 | 383 | $ hg tag --rev 1 --local t3 |
|
385 | 384 | $ hg tags -v |
|
386 | 385 | tip 2:2a156e8887cc |
|
387 | 386 | t3 1:c3adabd1a5f4 local |
|
388 | 387 | |
|
389 | 388 | $ cd .. |
|
390 | 389 | |
|
391 | 390 | commit hook on tag used to be run without write lock - issue3344 |
|
392 | 391 | |
|
393 | 392 | $ hg init repo-tag |
|
394 | 393 | $ touch repo-tag/test |
|
395 | 394 | $ hg -R repo-tag commit -A -m "test" |
|
396 | 395 | adding test |
|
397 | 396 | $ hg init repo-tag-target |
|
398 | 397 | $ hg -R repo-tag --config hooks.commit="\"hg\" push \"`pwd`/repo-tag-target\"" tag tag |
|
399 | 398 | pushing to $TESTTMP/repo-tag-target (glob) |
|
400 | 399 | searching for changes |
|
401 | 400 | adding changesets |
|
402 | 401 | adding manifests |
|
403 | 402 | adding file changes |
|
404 | 403 | added 2 changesets with 2 changes to 2 files |
|
405 | 404 | |
|
406 | 405 | automatically merge resolvable tag conflicts (i.e. tags that differ in rank) |
|
407 | 406 | create two clones with some different tags as well as some common tags |
|
408 | 407 | check that we can merge tags that differ in rank |
|
409 | 408 | |
|
410 | 409 | $ hg init repo-automatic-tag-merge |
|
411 | 410 | $ cd repo-automatic-tag-merge |
|
412 | 411 | $ echo c0 > f0 |
|
413 | 412 | $ hg ci -A -m0 |
|
414 | 413 | adding f0 |
|
415 | 414 | $ hg tag tbase |
|
416 | 415 | $ cd .. |
|
417 | 416 | $ hg clone repo-automatic-tag-merge repo-automatic-tag-merge-clone |
|
418 | 417 | updating to branch default |
|
419 | 418 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
420 | 419 | $ cd repo-automatic-tag-merge-clone |
|
421 | 420 | $ echo c1 > f1 |
|
422 | 421 | $ hg ci -A -m1 |
|
423 | 422 | adding f1 |
|
424 | 423 | $ hg tag t1 t2 t3 |
|
425 | 424 | $ hg tag --remove t2 |
|
426 | 425 | $ hg tag t5 |
|
427 | 426 | $ echo c2 > f2 |
|
428 | 427 | $ hg ci -A -m2 |
|
429 | 428 | adding f2 |
|
430 | 429 | $ hg tag -f t3 |
|
431 | 430 | |
|
432 | 431 | $ cd ../repo-automatic-tag-merge |
|
433 | 432 | $ echo c3 > f3 |
|
434 | 433 | $ hg ci -A -m3 |
|
435 | 434 | adding f3 |
|
436 | 435 | $ hg tag -f t4 t5 t6 |
|
437 | 436 | $ hg tag --remove t5 |
|
438 | 437 | $ echo c4 > f4 |
|
439 | 438 | $ hg ci -A -m4 |
|
440 | 439 | adding f4 |
|
441 | 440 | $ hg tag t2 |
|
442 | 441 | $ hg tag -f t6 |
|
443 | 442 | |
|
444 | 443 | $ cd ../repo-automatic-tag-merge-clone |
|
445 | 444 | $ hg pull |
|
446 | 445 | pulling from $TESTTMP/repo-automatic-tag-merge (glob) |
|
447 | 446 | searching for changes |
|
448 | 447 | adding changesets |
|
449 | 448 | adding manifests |
|
450 | 449 | adding file changes |
|
451 | 450 | added 6 changesets with 6 changes to 3 files (+1 heads) |
|
452 | 451 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
453 | 452 | $ hg merge --tool internal:tagmerge |
|
454 | 453 | merging .hgtags |
|
455 | 454 | 2 files updated, 1 files merged, 0 files removed, 0 files unresolved |
|
456 | 455 | (branch merge, don't forget to commit) |
|
457 | 456 | $ hg status |
|
458 | 457 | M .hgtags |
|
459 | 458 | M f3 |
|
460 | 459 | M f4 |
|
461 | 460 | $ hg resolve -l |
|
462 | 461 | R .hgtags |
|
463 | 462 | $ cat .hgtags |
|
464 | 463 | 9aa4e1292a27a248f8d07339bed9931d54907be7 t4 |
|
465 | 464 | 9aa4e1292a27a248f8d07339bed9931d54907be7 t6 |
|
466 | 465 | 9aa4e1292a27a248f8d07339bed9931d54907be7 t6 |
|
467 | 466 | 09af2ce14077a94effef208b49a718f4836d4338 t6 |
|
468 | 467 | 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase |
|
469 | 468 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1 |
|
470 | 469 | 929bca7b18d067cbf3844c3896319a940059d748 t2 |
|
471 | 470 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
472 | 471 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
473 | 472 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
474 | 473 | 0000000000000000000000000000000000000000 t2 |
|
475 | 474 | 875517b4806a848f942811a315a5bce30804ae85 t5 |
|
476 | 475 | 9aa4e1292a27a248f8d07339bed9931d54907be7 t5 |
|
477 | 476 | 9aa4e1292a27a248f8d07339bed9931d54907be7 t5 |
|
478 | 477 | 0000000000000000000000000000000000000000 t5 |
|
479 | 478 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
480 | 479 | 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 |
|
481 | 480 | |
|
482 | 481 | check that the merge tried to minimize the diff witht he first merge parent |
|
483 | 482 | |
|
484 | 483 | $ hg diff --git -r 'p1()' .hgtags |
|
485 | 484 | diff --git a/.hgtags b/.hgtags |
|
486 | 485 | --- a/.hgtags |
|
487 | 486 | +++ b/.hgtags |
|
488 | 487 | @@ -1,9 +1,17 @@ |
|
489 | 488 | +9aa4e1292a27a248f8d07339bed9931d54907be7 t4 |
|
490 | 489 | +9aa4e1292a27a248f8d07339bed9931d54907be7 t6 |
|
491 | 490 | +9aa4e1292a27a248f8d07339bed9931d54907be7 t6 |
|
492 | 491 | +09af2ce14077a94effef208b49a718f4836d4338 t6 |
|
493 | 492 | 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase |
|
494 | 493 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1 |
|
495 | 494 | +929bca7b18d067cbf3844c3896319a940059d748 t2 |
|
496 | 495 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
497 | 496 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
498 | 497 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
499 | 498 | 0000000000000000000000000000000000000000 t2 |
|
500 | 499 | 875517b4806a848f942811a315a5bce30804ae85 t5 |
|
501 | 500 | +9aa4e1292a27a248f8d07339bed9931d54907be7 t5 |
|
502 | 501 | +9aa4e1292a27a248f8d07339bed9931d54907be7 t5 |
|
503 | 502 | +0000000000000000000000000000000000000000 t5 |
|
504 | 503 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
505 | 504 | 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 |
|
506 | 505 | |
|
507 | 506 | detect merge tag conflicts |
|
508 | 507 | |
|
509 | 508 | $ hg update -C -r tip |
|
510 | 509 | 3 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
511 | 510 | $ hg tag t7 |
|
512 | 511 | $ hg update -C -r 'first(sort(head()))' |
|
513 | 512 | 3 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
514 | 513 | $ printf "%s %s\n" `hg log -r . --template "{node} t7"` >> .hgtags |
|
515 | 514 | $ hg commit -m "manually add conflicting t7 tag" |
|
516 | 515 | $ hg merge --tool internal:tagmerge |
|
517 | 516 | merging .hgtags |
|
518 | 517 | automatic .hgtags merge failed |
|
519 | 518 | the following 1 tags are in conflict: t7 |
|
520 | 519 | automatic tag merging of .hgtags failed! (use 'hg resolve --tool internal:merge' or another merge tool of your choice) |
|
521 | 520 | 2 files updated, 0 files merged, 0 files removed, 1 files unresolved |
|
522 | 521 | use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon |
|
523 | 522 | [1] |
|
524 | 523 | $ hg resolve -l |
|
525 | 524 | U .hgtags |
|
526 | 525 | $ cat .hgtags |
|
527 | 526 | 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase |
|
528 | 527 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1 |
|
529 | 528 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
530 | 529 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
531 | 530 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
532 | 531 | 0000000000000000000000000000000000000000 t2 |
|
533 | 532 | 875517b4806a848f942811a315a5bce30804ae85 t5 |
|
534 | 533 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
535 | 534 | 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 |
|
536 | 535 | ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7 |
|
537 | 536 | |
|
538 | 537 | $ cd .. |
|
539 | 538 | |
|
540 | 539 | handle the loss of tags |
|
541 | 540 | |
|
542 | 541 | $ hg clone repo-automatic-tag-merge-clone repo-merge-lost-tags |
|
543 | 542 | updating to branch default |
|
544 | 543 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
545 | 544 | $ cd repo-merge-lost-tags |
|
546 | 545 | $ echo c5 > f5 |
|
547 | 546 | $ hg ci -A -m5 |
|
548 | 547 | adding f5 |
|
549 | 548 | $ hg tag -f t7 |
|
550 | 549 | $ hg update -r 'p1(t7)' |
|
551 | 550 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
552 | 551 | $ printf '' > .hgtags |
|
553 | 552 | $ hg commit -m 'delete all tags' |
|
554 | 553 | created new head |
|
555 | 554 | $ hg update -r 'max(t7::)' |
|
556 | 555 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
557 | 556 | $ hg merge -r tip --tool internal:tagmerge |
|
558 | 557 | merging .hgtags |
|
559 | 558 | 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
|
560 | 559 | (branch merge, don't forget to commit) |
|
561 | 560 | $ hg resolve -l |
|
562 | 561 | R .hgtags |
|
563 | 562 | $ cat .hgtags |
|
564 | 563 | 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase |
|
565 | 564 | 0000000000000000000000000000000000000000 tbase |
|
566 | 565 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1 |
|
567 | 566 | 0000000000000000000000000000000000000000 t1 |
|
568 | 567 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
569 | 568 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
570 | 569 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
571 | 570 | 0000000000000000000000000000000000000000 t2 |
|
572 | 571 | 875517b4806a848f942811a315a5bce30804ae85 t5 |
|
573 | 572 | 0000000000000000000000000000000000000000 t5 |
|
574 | 573 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
575 | 574 | 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 |
|
576 | 575 | 0000000000000000000000000000000000000000 t3 |
|
577 | 576 | ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7 |
|
578 | 577 | 0000000000000000000000000000000000000000 t7 |
|
579 | 578 | ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7 |
|
580 | 579 | fd3a9e394ce3afb354a496323bf68ac1755a30de t7 |
|
581 | 580 | |
|
582 | 581 | also check that we minimize the diff with the 1st merge parent |
|
583 | 582 | |
|
584 | 583 | $ hg diff --git -r 'p1()' .hgtags |
|
585 | 584 | diff --git a/.hgtags b/.hgtags |
|
586 | 585 | --- a/.hgtags |
|
587 | 586 | +++ b/.hgtags |
|
588 | 587 | @@ -1,12 +1,17 @@ |
|
589 | 588 | 6cee5c8f3e5b4ae1a3996d2f6489c3e08eb5aea7 tbase |
|
590 | 589 | +0000000000000000000000000000000000000000 tbase |
|
591 | 590 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t1 |
|
592 | 591 | +0000000000000000000000000000000000000000 t1 |
|
593 | 592 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
594 | 593 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
595 | 594 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t2 |
|
596 | 595 | 0000000000000000000000000000000000000000 t2 |
|
597 | 596 | 875517b4806a848f942811a315a5bce30804ae85 t5 |
|
598 | 597 | +0000000000000000000000000000000000000000 t5 |
|
599 | 598 | 4f3e9b90005b68b4d8a3f4355cedc302a8364f5c t3 |
|
600 | 599 | 79505d5360b07e3e79d1052e347e73c02b8afa5b t3 |
|
601 | 600 | +0000000000000000000000000000000000000000 t3 |
|
602 | 601 | ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7 |
|
603 | 602 | +0000000000000000000000000000000000000000 t7 |
|
604 | 603 | ea918d56be86a4afc5a95312e8b6750e1428d9d2 t7 |
|
605 | 604 | fd3a9e394ce3afb354a496323bf68ac1755a30de t7 |
|
606 | 605 |
General Comments 0
You need to be logged in to leave comments.
Login now