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