##// END OF EJS Templates
errors: raise InputError in fancyopts...
Martin von Zweigbergk -
r46441:2eb8ad89 default
parent child Browse files
Show More
@@ -1,391 +1,391 b''
1 1 # fancyopts.py - better command line parsing
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import abc
11 11 import functools
12 12
13 13 from .i18n import _
14 14 from . import (
15 15 error,
16 16 pycompat,
17 17 )
18 18
19 19 # Set of flags to not apply boolean negation logic on
20 20 nevernegate = {
21 21 # avoid --no-noninteractive
22 22 b'noninteractive',
23 23 # These two flags are special because they cause hg to do one
24 24 # thing and then exit, and so aren't suitable for use in things
25 25 # like aliases anyway.
26 26 b'help',
27 27 b'version',
28 28 }
29 29
30 30
31 31 def _earlyoptarg(arg, shortlist, namelist):
32 32 """Check if the given arg is a valid unabbreviated option
33 33
34 34 Returns (flag_str, has_embedded_value?, embedded_value, takes_value?)
35 35
36 36 >>> def opt(arg):
37 37 ... return _earlyoptarg(arg, b'R:q', [b'cwd=', b'debugger'])
38 38
39 39 long form:
40 40
41 41 >>> opt(b'--cwd')
42 42 ('--cwd', False, '', True)
43 43 >>> opt(b'--cwd=')
44 44 ('--cwd', True, '', True)
45 45 >>> opt(b'--cwd=foo')
46 46 ('--cwd', True, 'foo', True)
47 47 >>> opt(b'--debugger')
48 48 ('--debugger', False, '', False)
49 49 >>> opt(b'--debugger=') # invalid but parsable
50 50 ('--debugger', True, '', False)
51 51
52 52 short form:
53 53
54 54 >>> opt(b'-R')
55 55 ('-R', False, '', True)
56 56 >>> opt(b'-Rfoo')
57 57 ('-R', True, 'foo', True)
58 58 >>> opt(b'-q')
59 59 ('-q', False, '', False)
60 60 >>> opt(b'-qfoo') # invalid but parsable
61 61 ('-q', True, 'foo', False)
62 62
63 63 unknown or invalid:
64 64
65 65 >>> opt(b'--unknown')
66 66 ('', False, '', False)
67 67 >>> opt(b'-u')
68 68 ('', False, '', False)
69 69 >>> opt(b'-ufoo')
70 70 ('', False, '', False)
71 71 >>> opt(b'--')
72 72 ('', False, '', False)
73 73 >>> opt(b'-')
74 74 ('', False, '', False)
75 75 >>> opt(b'-:')
76 76 ('', False, '', False)
77 77 >>> opt(b'-:foo')
78 78 ('', False, '', False)
79 79 """
80 80 if arg.startswith(b'--'):
81 81 flag, eq, val = arg.partition(b'=')
82 82 if flag[2:] in namelist:
83 83 return flag, bool(eq), val, False
84 84 if flag[2:] + b'=' in namelist:
85 85 return flag, bool(eq), val, True
86 86 elif arg.startswith(b'-') and arg != b'-' and not arg.startswith(b'-:'):
87 87 flag, val = arg[:2], arg[2:]
88 88 i = shortlist.find(flag[1:])
89 89 if i >= 0:
90 90 return flag, bool(val), val, shortlist.startswith(b':', i + 1)
91 91 return b'', False, b'', False
92 92
93 93
94 94 def earlygetopt(args, shortlist, namelist, gnu=False, keepsep=False):
95 95 """Parse options like getopt, but ignores unknown options and abbreviated
96 96 forms
97 97
98 98 If gnu=False, this stops processing options as soon as a non/unknown-option
99 99 argument is encountered. Otherwise, option and non-option arguments may be
100 100 intermixed, and unknown-option arguments are taken as non-option.
101 101
102 102 If keepsep=True, '--' won't be removed from the list of arguments left.
103 103 This is useful for stripping early options from a full command arguments.
104 104
105 105 >>> def get(args, gnu=False, keepsep=False):
106 106 ... return earlygetopt(args, b'R:q', [b'cwd=', b'debugger'],
107 107 ... gnu=gnu, keepsep=keepsep)
108 108
109 109 default parsing rules for early options:
110 110
111 111 >>> get([b'x', b'--cwd', b'foo', b'-Rbar', b'-q', b'y'], gnu=True)
112 112 ([('--cwd', 'foo'), ('-R', 'bar'), ('-q', '')], ['x', 'y'])
113 113 >>> get([b'x', b'--cwd=foo', b'y', b'-R', b'bar', b'--debugger'], gnu=True)
114 114 ([('--cwd', 'foo'), ('-R', 'bar'), ('--debugger', '')], ['x', 'y'])
115 115 >>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=True)
116 116 ([('--cwd', 'foo')], ['--unknown', '--debugger'])
117 117
118 118 restricted parsing rules (early options must come first):
119 119
120 120 >>> get([b'--cwd', b'foo', b'-Rbar', b'x', b'-q', b'y'], gnu=False)
121 121 ([('--cwd', 'foo'), ('-R', 'bar')], ['x', '-q', 'y'])
122 122 >>> get([b'--cwd=foo', b'x', b'y', b'-R', b'bar', b'--debugger'], gnu=False)
123 123 ([('--cwd', 'foo')], ['x', 'y', '-R', 'bar', '--debugger'])
124 124 >>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=False)
125 125 ([], ['--unknown', '--cwd=foo', '--', '--debugger'])
126 126
127 127 stripping early options (without loosing '--'):
128 128
129 129 >>> get([b'x', b'-Rbar', b'--', '--debugger'], gnu=True, keepsep=True)[1]
130 130 ['x', '--', '--debugger']
131 131
132 132 last argument:
133 133
134 134 >>> get([b'--cwd'])
135 135 ([], ['--cwd'])
136 136 >>> get([b'--cwd=foo'])
137 137 ([('--cwd', 'foo')], [])
138 138 >>> get([b'-R'])
139 139 ([], ['-R'])
140 140 >>> get([b'-Rbar'])
141 141 ([('-R', 'bar')], [])
142 142 >>> get([b'-q'])
143 143 ([('-q', '')], [])
144 144 >>> get([b'-q', b'--'])
145 145 ([('-q', '')], [])
146 146
147 147 '--' may be a value:
148 148
149 149 >>> get([b'-R', b'--', b'x'])
150 150 ([('-R', '--')], ['x'])
151 151 >>> get([b'--cwd', b'--', b'x'])
152 152 ([('--cwd', '--')], ['x'])
153 153
154 154 value passed to bool options:
155 155
156 156 >>> get([b'--debugger=foo', b'x'])
157 157 ([], ['--debugger=foo', 'x'])
158 158 >>> get([b'-qfoo', b'x'])
159 159 ([], ['-qfoo', 'x'])
160 160
161 161 short option isn't separated with '=':
162 162
163 163 >>> get([b'-R=bar'])
164 164 ([('-R', '=bar')], [])
165 165
166 166 ':' may be in shortlist, but shouldn't be taken as an option letter:
167 167
168 168 >>> get([b'-:', b'y'])
169 169 ([], ['-:', 'y'])
170 170
171 171 '-' is a valid non-option argument:
172 172
173 173 >>> get([b'-', b'y'])
174 174 ([], ['-', 'y'])
175 175 """
176 176 parsedopts = []
177 177 parsedargs = []
178 178 pos = 0
179 179 while pos < len(args):
180 180 arg = args[pos]
181 181 if arg == b'--':
182 182 pos += not keepsep
183 183 break
184 184 flag, hasval, val, takeval = _earlyoptarg(arg, shortlist, namelist)
185 185 if not hasval and takeval and pos + 1 >= len(args):
186 186 # missing last argument
187 187 break
188 188 if not flag or hasval and not takeval:
189 189 # non-option argument or -b/--bool=INVALID_VALUE
190 190 if gnu:
191 191 parsedargs.append(arg)
192 192 pos += 1
193 193 else:
194 194 break
195 195 elif hasval == takeval:
196 196 # -b/--bool or -s/--str=VALUE
197 197 parsedopts.append((flag, val))
198 198 pos += 1
199 199 else:
200 200 # -s/--str VALUE
201 201 parsedopts.append((flag, args[pos + 1]))
202 202 pos += 2
203 203
204 204 parsedargs.extend(args[pos:])
205 205 return parsedopts, parsedargs
206 206
207 207
208 208 class customopt(object): # pytype: disable=ignored-metaclass
209 209 """Manage defaults and mutations for any type of opt."""
210 210
211 211 __metaclass__ = abc.ABCMeta
212 212
213 213 def __init__(self, defaultvalue):
214 214 self._defaultvalue = defaultvalue
215 215
216 216 def _isboolopt(self):
217 217 return False
218 218
219 219 def getdefaultvalue(self):
220 220 """Returns the default value for this opt.
221 221
222 222 Subclasses should override this to return a new value if the value type
223 223 is mutable."""
224 224 return self._defaultvalue
225 225
226 226 @abc.abstractmethod
227 227 def newstate(self, oldstate, newparam, abort):
228 228 """Adds newparam to oldstate and returns the new state.
229 229
230 230 On failure, abort can be called with a string error message."""
231 231
232 232
233 233 class _simpleopt(customopt):
234 234 def _isboolopt(self):
235 235 return isinstance(self._defaultvalue, (bool, type(None)))
236 236
237 237 def newstate(self, oldstate, newparam, abort):
238 238 return newparam
239 239
240 240
241 241 class _callableopt(customopt):
242 242 def __init__(self, callablefn):
243 243 self.callablefn = callablefn
244 244 super(_callableopt, self).__init__(None)
245 245
246 246 def newstate(self, oldstate, newparam, abort):
247 247 return self.callablefn(newparam)
248 248
249 249
250 250 class _listopt(customopt):
251 251 def getdefaultvalue(self):
252 252 return self._defaultvalue[:]
253 253
254 254 def newstate(self, oldstate, newparam, abort):
255 255 oldstate.append(newparam)
256 256 return oldstate
257 257
258 258
259 259 class _intopt(customopt):
260 260 def newstate(self, oldstate, newparam, abort):
261 261 try:
262 262 return int(newparam)
263 263 except ValueError:
264 264 abort(_(b'expected int'))
265 265
266 266
267 267 def _defaultopt(default):
268 268 """Returns a default opt implementation, given a default value."""
269 269
270 270 if isinstance(default, customopt):
271 271 return default
272 272 elif callable(default):
273 273 return _callableopt(default)
274 274 elif isinstance(default, list):
275 275 return _listopt(default[:])
276 276 elif type(default) is type(1):
277 277 return _intopt(default)
278 278 else:
279 279 return _simpleopt(default)
280 280
281 281
282 282 def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
283 283 """
284 284 read args, parse options, and store options in state
285 285
286 286 each option is a tuple of:
287 287
288 288 short option or ''
289 289 long option
290 290 default value
291 291 description
292 292 option value label(optional)
293 293
294 294 option types include:
295 295
296 296 boolean or none - option sets variable in state to true
297 297 string - parameter string is stored in state
298 298 list - parameter string is added to a list
299 299 integer - parameter strings is stored as int
300 300 function - call function with parameter
301 301 customopt - subclass of 'customopt'
302 302
303 303 optaliases is a mapping from a canonical option name to a list of
304 304 additional long options. This exists for preserving backward compatibility
305 305 of early options. If we want to use it extensively, please consider moving
306 306 the functionality to the options table (e.g separate long options by '|'.)
307 307
308 308 non-option args are returned
309 309 """
310 310 if optaliases is None:
311 311 optaliases = {}
312 312 namelist = []
313 313 shortlist = b''
314 314 argmap = {}
315 315 defmap = {}
316 316 negations = {}
317 317 alllong = {o[1] for o in options}
318 318
319 319 for option in options:
320 320 if len(option) == 5:
321 321 short, name, default, comment, dummy = option
322 322 else:
323 323 short, name, default, comment = option
324 324 # convert opts to getopt format
325 325 onames = [name]
326 326 onames.extend(optaliases.get(name, []))
327 327 name = name.replace(b'-', b'_')
328 328
329 329 argmap[b'-' + short] = name
330 330 for n in onames:
331 331 argmap[b'--' + n] = name
332 332 defmap[name] = _defaultopt(default)
333 333
334 334 # copy defaults to state
335 335 state[name] = defmap[name].getdefaultvalue()
336 336
337 337 # does it take a parameter?
338 338 if not defmap[name]._isboolopt():
339 339 if short:
340 340 short += b':'
341 341 onames = [n + b'=' for n in onames]
342 342 elif name not in nevernegate:
343 343 for n in onames:
344 344 if n.startswith(b'no-'):
345 345 insert = n[3:]
346 346 else:
347 347 insert = b'no-' + n
348 348 # backout (as a practical example) has both --commit and
349 349 # --no-commit options, so we don't want to allow the
350 350 # negations of those flags.
351 351 if insert not in alllong:
352 352 assert (b'--' + n) not in negations
353 353 negations[b'--' + insert] = b'--' + n
354 354 namelist.append(insert)
355 355 if short:
356 356 shortlist += short
357 357 if name:
358 358 namelist.extend(onames)
359 359
360 360 # parse arguments
361 361 if early:
362 362 parse = functools.partial(earlygetopt, gnu=gnu)
363 363 elif gnu:
364 364 parse = pycompat.gnugetoptb
365 365 else:
366 366 parse = pycompat.getoptb
367 367 opts, args = parse(args, shortlist, namelist)
368 368
369 369 # transfer result to state
370 370 for opt, val in opts:
371 371 boolval = True
372 372 negation = negations.get(opt, False)
373 373 if negation:
374 374 opt = negation
375 375 boolval = False
376 376 name = argmap[opt]
377 377 obj = defmap[name]
378 378 if obj._isboolopt():
379 379 state[name] = boolval
380 380 else:
381 381
382 382 def abort(s):
383 raise error.Abort(
383 raise error.InputError(
384 384 _(b'invalid value %r for option %s, %s')
385 385 % (pycompat.maybebytestr(val), opt, s)
386 386 )
387 387
388 388 state[name] = defmap[name].newstate(state[name], val, abort)
389 389
390 390 # return unparsed args
391 391 return args
@@ -1,2090 +1,2090 b''
1 1 $ hg init a
2 2 $ mkdir a/d1
3 3 $ mkdir a/d1/d2
4 4 $ echo line 1 > a/a
5 5 $ echo line 1 > a/d1/d2/a
6 6 $ hg --cwd a ci -Ama
7 7 adding a
8 8 adding d1/d2/a
9 9
10 10 $ echo line 2 >> a/a
11 11 $ hg --cwd a ci -u someone -d '1 0' -m'second change'
12 12
13 13 import with no args:
14 14
15 15 $ hg --cwd a import
16 16 abort: need at least one patch to import
17 17 [10]
18 18
19 19 generate patches for the test
20 20
21 21 $ hg --cwd a export tip > exported-tip.patch
22 22 $ hg --cwd a diff -r0:1 > diffed-tip.patch
23 23
24 24
25 25 import exported patch
26 26 (this also tests that editor is not invoked, if the patch contains the
27 27 commit message and '--edit' is not specified)
28 28
29 29 $ hg clone -r0 a b
30 30 adding changesets
31 31 adding manifests
32 32 adding file changes
33 33 added 1 changesets with 2 changes to 2 files
34 34 new changesets 80971e65b431
35 35 updating to branch default
36 36 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 37 $ HGEDITOR=cat hg --cwd b import --debug ../exported-tip.patch
38 38 applying ../exported-tip.patch
39 39 Subject:
40 40
41 41 Content-Type: text/plain
42 42 found patch at byte 202
43 43 patch generated by hg export
44 44 From: someone
45 45 Date: 1 0
46 46 Node ID: 1d4bd90af0e43687763d158dfa83ff2a4b6c0c32
47 47 message:
48 48 second change
49 49 patching file a
50 50 committing files:
51 51 a
52 52 committing manifest
53 53 committing changelog
54 54 created 1d4bd90af0e4
55 55 updating the branch cache
56 56
57 57 message and committer and date should be same
58 58
59 59 $ hg --cwd b tip
60 60 changeset: 1:1d4bd90af0e4
61 61 tag: tip
62 62 user: someone
63 63 date: Thu Jan 01 00:00:01 1970 +0000
64 64 summary: second change
65 65
66 66 $ rm -r b
67 67
68 68
69 69 import exported patch with external patcher
70 70 (this also tests that editor is invoked, if the '--edit' is specified,
71 71 regardless of the commit message in the patch)
72 72
73 73 $ cat > dummypatch.py <<EOF
74 74 > from __future__ import print_function
75 75 > print('patching file a')
76 76 > open('a', 'wb').write(b'line2\n')
77 77 > EOF
78 78 $ hg clone -r0 a b
79 79 adding changesets
80 80 adding manifests
81 81 adding file changes
82 82 added 1 changesets with 2 changes to 2 files
83 83 new changesets 80971e65b431
84 84 updating to branch default
85 85 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 86 $ HGEDITOR=cat hg --config ui.patch="\"$PYTHON\" ../dummypatch.py" --cwd b import --edit ../exported-tip.patch
87 87 applying ../exported-tip.patch
88 88 second change
89 89
90 90
91 91 HG: Enter commit message. Lines beginning with 'HG:' are removed.
92 92 HG: Leave message empty to abort commit.
93 93 HG: --
94 94 HG: user: someone
95 95 HG: branch 'default'
96 96 HG: changed a
97 97 $ cat b/a
98 98 line2
99 99 $ rm -r b
100 100
101 101
102 102 import of plain diff should fail without message
103 103 (this also tests that editor is invoked, if the patch doesn't contain
104 104 the commit message, regardless of '--edit')
105 105
106 106 $ hg clone -r0 a b
107 107 adding changesets
108 108 adding manifests
109 109 adding file changes
110 110 added 1 changesets with 2 changes to 2 files
111 111 new changesets 80971e65b431
112 112 updating to branch default
113 113 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
114 114 $ cat > $TESTTMP/editor.sh <<EOF
115 115 > env | grep HGEDITFORM
116 116 > cat \$1
117 117 > EOF
118 118 $ HGEDITOR="sh $TESTTMP/editor.sh" hg --cwd b import ../diffed-tip.patch
119 119 applying ../diffed-tip.patch
120 120 HGEDITFORM=import.normal.normal
121 121
122 122
123 123 HG: Enter commit message. Lines beginning with 'HG:' are removed.
124 124 HG: Leave message empty to abort commit.
125 125 HG: --
126 126 HG: user: test
127 127 HG: branch 'default'
128 128 HG: changed a
129 129 abort: empty commit message
130 130 [10]
131 131
132 132 Test avoiding editor invocation at applying the patch with --exact,
133 133 even if commit message is empty
134 134
135 135 $ echo a >> b/a
136 136 $ hg --cwd b commit -m ' '
137 137 $ hg --cwd b tip -T "{node}\n"
138 138 d8804f3f5396d800812f579c8452796a5993bdb2
139 139 $ hg --cwd b export -o ../empty-log.diff .
140 140 $ hg --cwd b update -q -C ".^1"
141 141 $ hg --cwd b --config extensions.strip= strip -q tip
142 142 $ HGEDITOR=cat hg --cwd b import --exact ../empty-log.diff
143 143 applying ../empty-log.diff
144 144 $ hg --cwd b tip -T "{node}\n"
145 145 d8804f3f5396d800812f579c8452796a5993bdb2
146 146
147 147 $ rm -r b
148 148
149 149
150 150 import of plain diff should be ok with message
151 151
152 152 $ hg clone -r0 a b
153 153 adding changesets
154 154 adding manifests
155 155 adding file changes
156 156 added 1 changesets with 2 changes to 2 files
157 157 new changesets 80971e65b431
158 158 updating to branch default
159 159 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 160 $ hg --cwd b import -mpatch ../diffed-tip.patch
161 161 applying ../diffed-tip.patch
162 162 $ rm -r b
163 163
164 164
165 165 import of plain diff with specific date and user
166 166 (this also tests that editor is not invoked, if
167 167 '--message'/'--logfile' is specified and '--edit' is not)
168 168
169 169 $ hg clone -r0 a b
170 170 adding changesets
171 171 adding manifests
172 172 adding file changes
173 173 added 1 changesets with 2 changes to 2 files
174 174 new changesets 80971e65b431
175 175 updating to branch default
176 176 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 177 $ hg --cwd b import -mpatch -d '1 0' -u 'user@nowhere.net' ../diffed-tip.patch
178 178 applying ../diffed-tip.patch
179 179 $ hg -R b tip -pv
180 180 changeset: 1:ca68f19f3a40
181 181 tag: tip
182 182 user: user@nowhere.net
183 183 date: Thu Jan 01 00:00:01 1970 +0000
184 184 files: a
185 185 description:
186 186 patch
187 187
188 188
189 189 diff -r 80971e65b431 -r ca68f19f3a40 a
190 190 --- a/a Thu Jan 01 00:00:00 1970 +0000
191 191 +++ b/a Thu Jan 01 00:00:01 1970 +0000
192 192 @@ -1,1 +1,2 @@
193 193 line 1
194 194 +line 2
195 195
196 196 $ rm -r b
197 197
198 198
199 199 import of plain diff should be ok with --no-commit
200 200 (this also tests that editor is not invoked, if '--no-commit' is
201 201 specified, regardless of '--edit')
202 202
203 203 $ hg clone -r0 a b
204 204 adding changesets
205 205 adding manifests
206 206 adding file changes
207 207 added 1 changesets with 2 changes to 2 files
208 208 new changesets 80971e65b431
209 209 updating to branch default
210 210 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 211 $ HGEDITOR=cat hg --cwd b import --no-commit --edit ../diffed-tip.patch
212 212 applying ../diffed-tip.patch
213 213 $ hg --cwd b diff --nodates
214 214 diff -r 80971e65b431 a
215 215 --- a/a
216 216 +++ b/a
217 217 @@ -1,1 +1,2 @@
218 218 line 1
219 219 +line 2
220 220 $ rm -r b
221 221
222 222
223 223 import of malformed plain diff should fail
224 224
225 225 $ hg clone -r0 a b
226 226 adding changesets
227 227 adding manifests
228 228 adding file changes
229 229 added 1 changesets with 2 changes to 2 files
230 230 new changesets 80971e65b431
231 231 updating to branch default
232 232 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 233 $ sed 's/1,1/foo/' < diffed-tip.patch > broken.patch
234 234 $ hg --cwd b import -mpatch ../broken.patch
235 235 applying ../broken.patch
236 236 abort: bad hunk #1
237 237 [255]
238 238 $ rm -r b
239 239
240 240 hg -R repo import
241 241 put the clone in a subdir - having a directory named "a"
242 242 used to hide a bug.
243 243
244 244 $ mkdir dir
245 245 $ hg clone -r0 a dir/b
246 246 adding changesets
247 247 adding manifests
248 248 adding file changes
249 249 added 1 changesets with 2 changes to 2 files
250 250 new changesets 80971e65b431
251 251 updating to branch default
252 252 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 253 $ cd dir
254 254 $ hg -R b import ../exported-tip.patch
255 255 applying ../exported-tip.patch
256 256 $ cd ..
257 257 $ rm -r dir
258 258
259 259
260 260 import from stdin
261 261
262 262 $ hg clone -r0 a b
263 263 adding changesets
264 264 adding manifests
265 265 adding file changes
266 266 added 1 changesets with 2 changes to 2 files
267 267 new changesets 80971e65b431
268 268 updating to branch default
269 269 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
270 270 $ hg --cwd b import - < exported-tip.patch
271 271 applying patch from stdin
272 272 $ rm -r b
273 273
274 274
275 275 import two patches in one stream
276 276
277 277 $ hg init b
278 278 $ hg --cwd a export 0:tip | hg --cwd b import -
279 279 applying patch from stdin
280 280 $ hg --cwd a id
281 281 1d4bd90af0e4 tip
282 282 $ hg --cwd b id
283 283 1d4bd90af0e4 tip
284 284 $ rm -r b
285 285
286 286
287 287 override commit message
288 288
289 289 $ hg clone -r0 a b
290 290 adding changesets
291 291 adding manifests
292 292 adding file changes
293 293 added 1 changesets with 2 changes to 2 files
294 294 new changesets 80971e65b431
295 295 updating to branch default
296 296 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 297 $ hg --cwd b import -m 'override' - < exported-tip.patch
298 298 applying patch from stdin
299 299 $ hg --cwd b tip | grep override
300 300 summary: override
301 301 $ rm -r b
302 302
303 303 $ cat > mkmsg.py <<EOF
304 304 > import email.message
305 305 > import sys
306 306 > msg = email.message.Message()
307 307 > patch = open(sys.argv[1], 'rb').read()
308 308 > msg.set_payload(b'email commit message\n' + patch)
309 309 > msg['Subject'] = 'email patch'
310 310 > msg['From'] = 'email patcher'
311 311 > open(sys.argv[2], 'wb').write(bytes(msg))
312 312 > EOF
313 313
314 314
315 315 plain diff in email, subject, message body
316 316
317 317 $ hg clone -r0 a b
318 318 adding changesets
319 319 adding manifests
320 320 adding file changes
321 321 added 1 changesets with 2 changes to 2 files
322 322 new changesets 80971e65b431
323 323 updating to branch default
324 324 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
325 325 $ "$PYTHON" mkmsg.py diffed-tip.patch msg.patch
326 326 $ hg --cwd b import ../msg.patch
327 327 applying ../msg.patch
328 328 $ hg --cwd b tip | grep email
329 329 user: email patcher
330 330 summary: email patch
331 331 $ rm -r b
332 332
333 333
334 334 plain diff in email, no subject, message body
335 335
336 336 $ hg clone -r0 a b
337 337 adding changesets
338 338 adding manifests
339 339 adding file changes
340 340 added 1 changesets with 2 changes to 2 files
341 341 new changesets 80971e65b431
342 342 updating to branch default
343 343 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
344 344 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
345 345 applying patch from stdin
346 346 $ rm -r b
347 347
348 348
349 349 plain diff in email, subject, no message body
350 350
351 351 $ hg clone -r0 a b
352 352 adding changesets
353 353 adding manifests
354 354 adding file changes
355 355 added 1 changesets with 2 changes to 2 files
356 356 new changesets 80971e65b431
357 357 updating to branch default
358 358 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 359 $ grep -v '^email ' msg.patch | hg --cwd b import -
360 360 applying patch from stdin
361 361 $ rm -r b
362 362
363 363
364 364 plain diff in email, no subject, no message body, should fail
365 365
366 366 $ hg clone -r0 a b
367 367 adding changesets
368 368 adding manifests
369 369 adding file changes
370 370 added 1 changesets with 2 changes to 2 files
371 371 new changesets 80971e65b431
372 372 updating to branch default
373 373 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 374 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
375 375 applying patch from stdin
376 376 abort: empty commit message
377 377 [10]
378 378 $ rm -r b
379 379
380 380
381 381 hg export in email, should use patch header
382 382
383 383 $ hg clone -r0 a b
384 384 adding changesets
385 385 adding manifests
386 386 adding file changes
387 387 added 1 changesets with 2 changes to 2 files
388 388 new changesets 80971e65b431
389 389 updating to branch default
390 390 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 391 $ "$PYTHON" mkmsg.py exported-tip.patch msg.patch
392 392 $ cat msg.patch | hg --cwd b import -
393 393 applying patch from stdin
394 394 $ hg --cwd b tip | grep second
395 395 summary: second change
396 396 $ rm -r b
397 397
398 398 hg email --plain, should read X-Mercurial-Node header
399 399
400 400 $ cat >> a/.hg/hgrc << EOF
401 401 > [extensions]
402 402 > patchbomb =
403 403 > [email]
404 404 > from = foo
405 405 > cc = foo
406 406 > to = bar
407 407 > EOF
408 408 $ hg --cwd a email -m ../tip-plain.mbox --plain --date '1970-1-1 0:1' tip
409 409 this patch series consists of 1 patches.
410 410
411 411
412 412 sending [PATCH] second change ...
413 413
414 414 $ hg clone -r0 a b -q
415 415 $ hg --cwd b import --debug ../tip-plain.mbox
416 416 applying ../tip-plain.mbox
417 417 Node ID: 1d4bd90af0e43687763d158dfa83ff2a4b6c0c32
418 418 Subject: second change
419 419 From: foo
420 420 Content-Type: text/plain
421 421 found patch at byte 0
422 422 message:
423 423 second change
424 424 patching file a
425 425 committing files:
426 426 a
427 427 committing manifest
428 428 committing changelog
429 429 created de620f6fe949
430 430 updating the branch cache
431 431 $ hg --cwd b tip
432 432 changeset: 1:de620f6fe949
433 433 tag: tip
434 434 user: foo
435 435 date: Thu Jan 01 00:00:00 1970 +0000
436 436 summary: second change
437 437
438 438 $ hg --cwd b phase tip
439 439 1: draft
440 440 $ rm -r b
441 441
442 442
443 443 hg import --secret
444 444
445 445 $ hg clone -r0 a b -q
446 446 $ hg --cwd b import --no-commit --secret ../exported-tip.patch
447 447 abort: cannot specify both --no-commit and --secret
448 448 [10]
449 449 $ hg --cwd b import --secret ../exported-tip.patch
450 450 applying ../exported-tip.patch
451 451 $ hg --cwd b diff -c . --nodates
452 452 diff -r 80971e65b431 -r 1d4bd90af0e4 a
453 453 --- a/a
454 454 +++ b/a
455 455 @@ -1,1 +1,2 @@
456 456 line 1
457 457 +line 2
458 458 $ hg --cwd b phase
459 459 1: secret
460 460 $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
461 461 $ HGEDITOR=cat hg --cwd b import --secret --edit ../exported-tip.patch
462 462 applying ../exported-tip.patch
463 463 second change
464 464
465 465
466 466 HG: Enter commit message. Lines beginning with 'HG:' are removed.
467 467 HG: Leave message empty to abort commit.
468 468 HG: --
469 469 HG: user: someone
470 470 HG: branch 'default'
471 471 HG: changed a
472 472 $ hg --cwd b diff -c . --nodates
473 473 diff -r 80971e65b431 -r 1d4bd90af0e4 a
474 474 --- a/a
475 475 +++ b/a
476 476 @@ -1,1 +1,2 @@
477 477 line 1
478 478 +line 2
479 479 $ hg --cwd b phase
480 480 1: secret
481 481 $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
482 482 $ hg --cwd b import --bypass --secret ../exported-tip.patch
483 483 applying ../exported-tip.patch
484 484 $ hg --cwd b phase -r tip
485 485 1: secret
486 486 $ hg --cwd b --config extensions.strip= strip 1 --no-backup --quiet
487 487 $ rm -r b
488 488
489 489
490 490 subject: duplicate detection, removal of [PATCH]
491 491 The '---' tests the gitsendmail handling without proper mail headers
492 492
493 493 $ cat > mkmsg2.py <<EOF
494 494 > import email.message
495 495 > import sys
496 496 > msg = email.message.Message()
497 497 > patch = open(sys.argv[1], 'rb').read()
498 498 > msg.set_payload(b'email patch\n\nnext line\n---\n' + patch)
499 499 > msg['Subject'] = '[PATCH] email patch'
500 500 > msg['From'] = 'email patcher'
501 501 > open(sys.argv[2], 'wb').write(bytes(msg))
502 502 > EOF
503 503
504 504
505 505 plain diff in email, [PATCH] subject, message body with subject
506 506
507 507 $ hg clone -r0 a b
508 508 adding changesets
509 509 adding manifests
510 510 adding file changes
511 511 added 1 changesets with 2 changes to 2 files
512 512 new changesets 80971e65b431
513 513 updating to branch default
514 514 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
515 515 $ "$PYTHON" mkmsg2.py diffed-tip.patch msg.patch
516 516 $ cat msg.patch | hg --cwd b import -
517 517 applying patch from stdin
518 518 $ hg --cwd b tip --template '{desc}\n'
519 519 email patch
520 520
521 521 next line
522 522 $ rm -r b
523 523
524 524
525 525 Issue963: Parent of working dir incorrect after import of multiple
526 526 patches and rollback
527 527
528 528 We weren't backing up the correct dirstate file when importing many
529 529 patches: import patch1 patch2; rollback
530 530
531 531 $ echo line 3 >> a/a
532 532 $ hg --cwd a ci -m'third change'
533 533 $ hg --cwd a export -o '../patch%R' 1 2
534 534 $ hg clone -qr0 a b
535 535 $ hg --cwd b parents --template 'parent: {rev}\n'
536 536 parent: 0
537 537 $ hg --cwd b import -v ../patch1 ../patch2
538 538 applying ../patch1
539 539 patching file a
540 540 committing files:
541 541 a
542 542 committing manifest
543 543 committing changelog
544 544 created 1d4bd90af0e4
545 545 applying ../patch2
546 546 patching file a
547 547 committing files:
548 548 a
549 549 committing manifest
550 550 committing changelog
551 551 created 6d019af21222
552 552 $ hg --cwd b rollback
553 553 repository tip rolled back to revision 0 (undo import)
554 554 working directory now based on revision 0
555 555 $ hg --cwd b parents --template 'parent: {rev}\n'
556 556 parent: 0
557 557
558 558 Test that "hg rollback" doesn't restore dirstate to one at the
559 559 beginning of the rolled back transaction in not-"parent-gone" case.
560 560
561 561 invoking pretxncommit hook will cause marking '.hg/dirstate' as a file
562 562 to be restored when rolling back, after DirstateTransactionPlan (see wiki
563 563 page for detail).
564 564
565 565 $ hg --cwd b branch -q foobar
566 566 $ hg --cwd b commit -m foobar
567 567 $ hg --cwd b update 0 -q
568 568 $ hg --cwd b import ../patch1 ../patch2 --config hooks.pretxncommit=true
569 569 applying ../patch1
570 570 applying ../patch2
571 571 $ hg --cwd b update -q 1
572 572 $ hg --cwd b rollback -q
573 573 $ hg --cwd b parents --template 'parent: {rev}\n'
574 574 parent: 1
575 575
576 576 $ hg --cwd b update -q -C 0
577 577 $ hg --cwd b --config extensions.strip= strip -q 1
578 578
579 579 Test visibility of in-memory dirstate changes inside transaction to
580 580 external process
581 581
582 582 $ echo foo > a/foo
583 583 $ hg --cwd a commit -A -m 'adding foo' foo
584 584 $ hg --cwd a export -o '../patch%R' 3
585 585
586 586 $ cat > $TESTTMP/checkvisibility.sh <<EOF
587 587 > echo "===="
588 588 > hg parents --template "VISIBLE {rev}:{node|short}\n"
589 589 > hg status -amr
590 590 > # test that pending changes are hidden
591 591 > unset HG_PENDING
592 592 > hg parents --template "ACTUAL {rev}:{node|short}\n"
593 593 > hg status -amr
594 594 > echo "===="
595 595 > EOF
596 596
597 597 == test visibility to external editor
598 598
599 599 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
600 600 ====
601 601 VISIBLE 0:80971e65b431
602 602 ACTUAL 0:80971e65b431
603 603 ====
604 604
605 605 $ HGEDITOR="sh $TESTTMP/checkvisibility.sh" hg --cwd b import -v --edit ../patch1 ../patch2 ../patch3
606 606 applying ../patch1
607 607 patching file a
608 608 ====
609 609 VISIBLE 0:80971e65b431
610 610 M a
611 611 ACTUAL 0:80971e65b431
612 612 M a
613 613 ====
614 614 committing files:
615 615 a
616 616 committing manifest
617 617 committing changelog
618 618 created 1d4bd90af0e4
619 619 applying ../patch2
620 620 patching file a
621 621 ====
622 622 VISIBLE 1:1d4bd90af0e4
623 623 M a
624 624 ACTUAL 0:80971e65b431
625 625 M a
626 626 ====
627 627 committing files:
628 628 a
629 629 committing manifest
630 630 committing changelog
631 631 created 6d019af21222
632 632 applying ../patch3
633 633 patching file foo
634 634 adding foo
635 635 ====
636 636 VISIBLE 2:6d019af21222
637 637 A foo
638 638 ACTUAL 0:80971e65b431
639 639 M a
640 640 ====
641 641 committing files:
642 642 foo
643 643 committing manifest
644 644 committing changelog
645 645 created 55e3f75b2378
646 646
647 647 $ hg --cwd b rollback -q
648 648
649 649 (content of file "a" is already changed and it should be recognized as
650 650 "M", even though dirstate is restored to one before "hg import")
651 651
652 652 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
653 653 ====
654 654 VISIBLE 0:80971e65b431
655 655 M a
656 656 ACTUAL 0:80971e65b431
657 657 M a
658 658 ====
659 659 $ hg --cwd b revert --no-backup a
660 660 $ rm -f b/foo
661 661
662 662 == test visibility to precommit external hook
663 663
664 664 $ cat >> b/.hg/hgrc <<EOF
665 665 > [hooks]
666 666 > precommit.visibility = sh $TESTTMP/checkvisibility.sh
667 667 > EOF
668 668
669 669 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
670 670 ====
671 671 VISIBLE 0:80971e65b431
672 672 ACTUAL 0:80971e65b431
673 673 ====
674 674
675 675 $ hg --cwd b import ../patch1 ../patch2 ../patch3
676 676 applying ../patch1
677 677 ====
678 678 VISIBLE 0:80971e65b431
679 679 M a
680 680 ACTUAL 0:80971e65b431
681 681 M a
682 682 ====
683 683 applying ../patch2
684 684 ====
685 685 VISIBLE 1:1d4bd90af0e4
686 686 M a
687 687 ACTUAL 0:80971e65b431
688 688 M a
689 689 ====
690 690 applying ../patch3
691 691 ====
692 692 VISIBLE 2:6d019af21222
693 693 A foo
694 694 ACTUAL 0:80971e65b431
695 695 M a
696 696 ====
697 697
698 698 $ hg --cwd b rollback -q
699 699 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
700 700 ====
701 701 VISIBLE 0:80971e65b431
702 702 M a
703 703 ACTUAL 0:80971e65b431
704 704 M a
705 705 ====
706 706 $ hg --cwd b revert --no-backup a
707 707 $ rm -f b/foo
708 708
709 709 $ cat >> b/.hg/hgrc <<EOF
710 710 > [hooks]
711 711 > precommit.visibility =
712 712 > EOF
713 713
714 714 == test visibility to pretxncommit external hook
715 715
716 716 $ cat >> b/.hg/hgrc <<EOF
717 717 > [hooks]
718 718 > pretxncommit.visibility = sh $TESTTMP/checkvisibility.sh
719 719 > EOF
720 720
721 721 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
722 722 ====
723 723 VISIBLE 0:80971e65b431
724 724 ACTUAL 0:80971e65b431
725 725 ====
726 726
727 727 $ hg --cwd b import ../patch1 ../patch2 ../patch3
728 728 applying ../patch1
729 729 ====
730 730 VISIBLE 0:80971e65b431
731 731 M a
732 732 ACTUAL 0:80971e65b431
733 733 M a
734 734 ====
735 735 applying ../patch2
736 736 ====
737 737 VISIBLE 1:1d4bd90af0e4
738 738 M a
739 739 ACTUAL 0:80971e65b431
740 740 M a
741 741 ====
742 742 applying ../patch3
743 743 ====
744 744 VISIBLE 2:6d019af21222
745 745 A foo
746 746 ACTUAL 0:80971e65b431
747 747 M a
748 748 ====
749 749
750 750 $ hg --cwd b rollback -q
751 751 $ (cd b && sh "$TESTTMP/checkvisibility.sh")
752 752 ====
753 753 VISIBLE 0:80971e65b431
754 754 M a
755 755 ACTUAL 0:80971e65b431
756 756 M a
757 757 ====
758 758 $ hg --cwd b revert --no-backup a
759 759 $ rm -f b/foo
760 760
761 761 $ cat >> b/.hg/hgrc <<EOF
762 762 > [hooks]
763 763 > pretxncommit.visibility =
764 764 > EOF
765 765
766 766 $ rm -r b
767 767
768 768
769 769 importing a patch in a subdirectory failed at the commit stage
770 770
771 771 $ echo line 2 >> a/d1/d2/a
772 772 $ hg --cwd a ci -u someoneelse -d '1 0' -m'subdir change'
773 773
774 774 hg import in a subdirectory
775 775
776 776 $ hg clone -r0 a b
777 777 adding changesets
778 778 adding manifests
779 779 adding file changes
780 780 added 1 changesets with 2 changes to 2 files
781 781 new changesets 80971e65b431
782 782 updating to branch default
783 783 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
784 784 $ hg --cwd a export tip > tmp
785 785 $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
786 786 $ dir=`pwd`
787 787 $ cd b/d1/d2 2>&1 > /dev/null
788 788 $ hg import ../../../subdir-tip.patch
789 789 applying ../../../subdir-tip.patch
790 790 $ cd "$dir"
791 791
792 792 message should be 'subdir change'
793 793 committer should be 'someoneelse'
794 794
795 795 $ hg --cwd b tip
796 796 changeset: 1:3577f5aea227
797 797 tag: tip
798 798 user: someoneelse
799 799 date: Thu Jan 01 00:00:01 1970 +0000
800 800 summary: subdir change
801 801
802 802
803 803 should be empty
804 804
805 805 $ hg --cwd b status
806 806
807 807
808 808 Test fuzziness (ambiguous patch location, fuzz=2)
809 809
810 810 $ hg init fuzzy
811 811 $ cd fuzzy
812 812 $ echo line1 > a
813 813 $ echo line0 >> a
814 814 $ echo line3 >> a
815 815 $ hg ci -Am adda
816 816 adding a
817 817 $ echo line1 > a
818 818 $ echo line2 >> a
819 819 $ echo line0 >> a
820 820 $ echo line3 >> a
821 821 $ hg ci -m change a
822 822 $ hg export tip > fuzzy-tip.patch
823 823 $ hg up -C 0
824 824 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
825 825 $ echo line1 > a
826 826 $ echo line0 >> a
827 827 $ echo line1 >> a
828 828 $ echo line0 >> a
829 829 $ hg ci -m brancha
830 830 created new head
831 831 $ hg import --config patch.fuzz=0 -v fuzzy-tip.patch
832 832 applying fuzzy-tip.patch
833 833 patching file a
834 834 Hunk #1 FAILED at 0
835 835 1 out of 1 hunks FAILED -- saving rejects to file a.rej
836 836 abort: patch failed to apply
837 837 [255]
838 838 $ hg import --no-commit -v fuzzy-tip.patch
839 839 applying fuzzy-tip.patch
840 840 patching file a
841 841 Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
842 842 applied to working directory
843 843 $ hg revert -a
844 844 reverting a
845 845
846 846 Test --exact failure
847 847
848 848 $ sed 's/^# Parent .*/# Parent '"`hg log -r. -T '{node}'`"'/' \
849 849 > < fuzzy-tip.patch > fuzzy-reparent.patch
850 850 $ hg import --config patch.fuzz=0 --exact fuzzy-reparent.patch
851 851 applying fuzzy-reparent.patch
852 852 patching file a
853 853 Hunk #1 FAILED at 0
854 854 1 out of 1 hunks FAILED -- saving rejects to file a.rej
855 855 abort: patch failed to apply
856 856 [255]
857 857 $ hg up -qC
858 858 $ hg import --config patch.fuzz=2 --exact fuzzy-reparent.patch
859 859 applying fuzzy-reparent.patch
860 860 patching file a
861 861 Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
862 862 transaction abort!
863 863 rollback completed
864 864 abort: patch is damaged or loses information
865 865 [255]
866 866 $ hg up -qC
867 867
868 868 $ grep '^#' fuzzy-tip.patch > empty.patch
869 869 $ cat <<'EOF' >> empty.patch
870 870 > change
871 871 >
872 872 > diff -r bb90ef1daa38 -r 0e9b883378d4 a
873 873 > --- a/a Thu Jan 01 00:00:00 1970 +0000
874 874 > --- b/a Thu Jan 01 00:00:00 1970 +0000
875 875 > EOF
876 876 $ hg import --exact empty.patch
877 877 applying empty.patch
878 878 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
879 879 abort: patch is damaged or loses information
880 880 [255]
881 881 $ hg up -qC
882 882
883 883 import with --no-commit should have written .hg/last-message.txt
884 884
885 885 $ cat .hg/last-message.txt
886 886 change (no-eol)
887 887
888 888
889 889 test fuzziness with eol=auto
890 890
891 891 $ hg --config patch.eol=auto import --no-commit -v fuzzy-tip.patch
892 892 applying fuzzy-tip.patch
893 893 patching file a
894 894 Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
895 895 applied to working directory
896 896 $ cd ..
897 897
898 898
899 899 Test hunk touching empty files (issue906)
900 900
901 901 $ hg init empty
902 902 $ cd empty
903 903 $ touch a
904 904 $ touch b1
905 905 $ touch c1
906 906 $ echo d > d
907 907 $ hg ci -Am init
908 908 adding a
909 909 adding b1
910 910 adding c1
911 911 adding d
912 912 $ echo a > a
913 913 $ echo b > b1
914 914 $ hg mv b1 b2
915 915 $ echo c > c1
916 916 $ hg copy c1 c2
917 917 $ rm d
918 918 $ touch d
919 919 $ hg diff --git
920 920 diff --git a/a b/a
921 921 --- a/a
922 922 +++ b/a
923 923 @@ -0,0 +1,1 @@
924 924 +a
925 925 diff --git a/b1 b/b2
926 926 rename from b1
927 927 rename to b2
928 928 --- a/b1
929 929 +++ b/b2
930 930 @@ -0,0 +1,1 @@
931 931 +b
932 932 diff --git a/c1 b/c1
933 933 --- a/c1
934 934 +++ b/c1
935 935 @@ -0,0 +1,1 @@
936 936 +c
937 937 diff --git a/c1 b/c2
938 938 copy from c1
939 939 copy to c2
940 940 --- a/c1
941 941 +++ b/c2
942 942 @@ -0,0 +1,1 @@
943 943 +c
944 944 diff --git a/d b/d
945 945 --- a/d
946 946 +++ b/d
947 947 @@ -1,1 +0,0 @@
948 948 -d
949 949 $ hg ci -m empty
950 950 $ hg export --git tip > empty.diff
951 951 $ hg up -C 0
952 952 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
953 953 $ hg import empty.diff
954 954 applying empty.diff
955 955 $ for name in a b1 b2 c1 c2 d; do
956 956 > echo % $name file
957 957 > test -f $name && cat $name
958 958 > done
959 959 % a file
960 960 a
961 961 % b1 file
962 962 % b2 file
963 963 b
964 964 % c1 file
965 965 c
966 966 % c2 file
967 967 c
968 968 % d file
969 969 $ cd ..
970 970
971 971
972 972 Test importing a patch ending with a binary file removal
973 973
974 974 $ hg init binaryremoval
975 975 $ cd binaryremoval
976 976 $ echo a > a
977 977 $ "$PYTHON" -c "open('b', 'wb').write(b'a\x00b')"
978 978 $ hg ci -Am addall
979 979 adding a
980 980 adding b
981 981 $ hg rm a
982 982 $ hg rm b
983 983 $ hg st
984 984 R a
985 985 R b
986 986 $ hg ci -m remove
987 987 $ hg export --git . > remove.diff
988 988 $ cat remove.diff | grep git
989 989 diff --git a/a b/a
990 990 diff --git a/b b/b
991 991 $ hg up -C 0
992 992 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
993 993 $ hg import remove.diff
994 994 applying remove.diff
995 995 $ hg manifest
996 996 $ cd ..
997 997
998 998
999 999 Issue927: test update+rename with common name
1000 1000
1001 1001 $ hg init t
1002 1002 $ cd t
1003 1003 $ touch a
1004 1004 $ hg ci -Am t
1005 1005 adding a
1006 1006 $ echo a > a
1007 1007
1008 1008 Here, bfile.startswith(afile)
1009 1009
1010 1010 $ hg copy a a2
1011 1011 $ hg ci -m copya
1012 1012 $ hg export --git tip > copy.diff
1013 1013 $ hg up -C 0
1014 1014 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1015 1015 $ hg import copy.diff
1016 1016 applying copy.diff
1017 1017
1018 1018 a should contain an 'a'
1019 1019
1020 1020 $ cat a
1021 1021 a
1022 1022
1023 1023 and a2 should have duplicated it
1024 1024
1025 1025 $ cat a2
1026 1026 a
1027 1027 $ cd ..
1028 1028
1029 1029
1030 1030 test -p0
1031 1031
1032 1032 $ hg init p0
1033 1033 $ cd p0
1034 1034 $ echo a > a
1035 1035 $ hg ci -Am t
1036 1036 adding a
1037 1037 $ hg import -p foo
1038 1038 abort: invalid value 'foo' for option -p, expected int
1039 [255]
1039 [10]
1040 1040 $ hg import -p0 - << EOF
1041 1041 > foobar
1042 1042 > --- a Sat Apr 12 22:43:58 2008 -0400
1043 1043 > +++ a Sat Apr 12 22:44:05 2008 -0400
1044 1044 > @@ -1,1 +1,1 @@
1045 1045 > -a
1046 1046 > +bb
1047 1047 > EOF
1048 1048 applying patch from stdin
1049 1049 $ hg status
1050 1050 $ cat a
1051 1051 bb
1052 1052
1053 1053 test --prefix
1054 1054
1055 1055 $ mkdir -p dir/dir2
1056 1056 $ echo b > dir/dir2/b
1057 1057 $ hg ci -Am b
1058 1058 adding dir/dir2/b
1059 1059 $ hg import -p2 --prefix dir - << EOF
1060 1060 > foobar
1061 1061 > --- drop1/drop2/dir2/b
1062 1062 > +++ drop1/drop2/dir2/b
1063 1063 > @@ -1,1 +1,1 @@
1064 1064 > -b
1065 1065 > +cc
1066 1066 > EOF
1067 1067 applying patch from stdin
1068 1068 $ hg status
1069 1069 $ cat dir/dir2/b
1070 1070 cc
1071 1071 $ cd ..
1072 1072
1073 1073
1074 1074 test paths outside repo root
1075 1075
1076 1076 $ mkdir outside
1077 1077 $ touch outside/foo
1078 1078 $ hg init inside
1079 1079 $ cd inside
1080 1080 $ hg import - <<EOF
1081 1081 > diff --git a/a b/b
1082 1082 > rename from ../outside/foo
1083 1083 > rename to bar
1084 1084 > EOF
1085 1085 applying patch from stdin
1086 1086 abort: path contains illegal component: ../outside/foo
1087 1087 [255]
1088 1088 $ cd ..
1089 1089
1090 1090
1091 1091 test import with similarity and git and strip (issue295 et al.)
1092 1092
1093 1093 $ hg init sim
1094 1094 $ cd sim
1095 1095 $ echo 'this is a test' > a
1096 1096 $ hg ci -Ama
1097 1097 adding a
1098 1098 $ cat > ../rename.diff <<EOF
1099 1099 > diff --git a/foo/a b/foo/a
1100 1100 > deleted file mode 100644
1101 1101 > --- a/foo/a
1102 1102 > +++ /dev/null
1103 1103 > @@ -1,1 +0,0 @@
1104 1104 > -this is a test
1105 1105 > diff --git a/foo/b b/foo/b
1106 1106 > new file mode 100644
1107 1107 > --- /dev/null
1108 1108 > +++ b/foo/b
1109 1109 > @@ -0,0 +1,2 @@
1110 1110 > +this is a test
1111 1111 > +foo
1112 1112 > EOF
1113 1113 $ hg import --no-commit -v -s 1 ../rename.diff -p2
1114 1114 applying ../rename.diff
1115 1115 patching file a
1116 1116 patching file b
1117 1117 adding b
1118 1118 recording removal of a as rename to b (88% similar)
1119 1119 applied to working directory
1120 1120 $ echo 'mod b' > b
1121 1121 $ hg st -C
1122 1122 A b
1123 1123 a
1124 1124 R a
1125 1125 $ hg revert -a
1126 1126 forgetting b
1127 1127 undeleting a
1128 1128 $ cat b
1129 1129 mod b
1130 1130 $ rm b
1131 1131 $ hg import --no-commit -v -s 100 ../rename.diff -p2
1132 1132 applying ../rename.diff
1133 1133 patching file a
1134 1134 patching file b
1135 1135 adding b
1136 1136 applied to working directory
1137 1137 $ hg st -C
1138 1138 A b
1139 1139 R a
1140 1140 $ cd ..
1141 1141
1142 1142
1143 1143 Issue1495: add empty file from the end of patch
1144 1144
1145 1145 $ hg init addemptyend
1146 1146 $ cd addemptyend
1147 1147 $ touch a
1148 1148 $ hg addremove
1149 1149 adding a
1150 1150 $ hg ci -m "commit"
1151 1151 $ cat > a.patch <<EOF
1152 1152 > add a, b
1153 1153 > diff --git a/a b/a
1154 1154 > --- a/a
1155 1155 > +++ b/a
1156 1156 > @@ -0,0 +1,1 @@
1157 1157 > +a
1158 1158 > diff --git a/b b/b
1159 1159 > new file mode 100644
1160 1160 > EOF
1161 1161 $ hg import --no-commit a.patch
1162 1162 applying a.patch
1163 1163
1164 1164 apply a good patch followed by an empty patch (mainly to ensure
1165 1165 that dirstate is *not* updated when import crashes)
1166 1166 $ hg update -q -C .
1167 1167 $ rm b
1168 1168 $ touch empty.patch
1169 1169 $ hg import a.patch empty.patch
1170 1170 applying a.patch
1171 1171 applying empty.patch
1172 1172 transaction abort!
1173 1173 rollback completed
1174 1174 abort: empty.patch: no diffs found
1175 1175 [10]
1176 1176 $ hg tip --template '{rev} {desc|firstline}\n'
1177 1177 0 commit
1178 1178 $ hg -q status
1179 1179 M a
1180 1180 $ cd ..
1181 1181
1182 1182 create file when source is not /dev/null
1183 1183
1184 1184 $ cat > create.patch <<EOF
1185 1185 > diff -Naur proj-orig/foo proj-new/foo
1186 1186 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
1187 1187 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
1188 1188 > @@ -0,0 +1,1 @@
1189 1189 > +a
1190 1190 > EOF
1191 1191
1192 1192 some people have patches like the following too
1193 1193
1194 1194 $ cat > create2.patch <<EOF
1195 1195 > diff -Naur proj-orig/foo proj-new/foo
1196 1196 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
1197 1197 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
1198 1198 > @@ -0,0 +1,1 @@
1199 1199 > +a
1200 1200 > EOF
1201 1201 $ hg init oddcreate
1202 1202 $ cd oddcreate
1203 1203 $ hg import --no-commit ../create.patch
1204 1204 applying ../create.patch
1205 1205 $ cat foo
1206 1206 a
1207 1207 $ rm foo
1208 1208 $ hg revert foo
1209 1209 $ hg import --no-commit ../create2.patch
1210 1210 applying ../create2.patch
1211 1211 $ cat foo
1212 1212 a
1213 1213
1214 1214 $ cd ..
1215 1215
1216 1216 Issue1859: first line mistaken for email headers
1217 1217
1218 1218 $ hg init emailconfusion
1219 1219 $ cd emailconfusion
1220 1220 $ cat > a.patch <<EOF
1221 1221 > module: summary
1222 1222 >
1223 1223 > description
1224 1224 >
1225 1225 >
1226 1226 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
1227 1227 > --- /dev/null
1228 1228 > +++ b/a
1229 1229 > @@ -0,0 +1,1 @@
1230 1230 > +a
1231 1231 > EOF
1232 1232 $ hg import -d '0 0' a.patch
1233 1233 applying a.patch
1234 1234 $ hg parents -v
1235 1235 changeset: 0:5a681217c0ad
1236 1236 tag: tip
1237 1237 user: test
1238 1238 date: Thu Jan 01 00:00:00 1970 +0000
1239 1239 files: a
1240 1240 description:
1241 1241 module: summary
1242 1242
1243 1243 description
1244 1244
1245 1245
1246 1246 $ cd ..
1247 1247
1248 1248
1249 1249 in commit message
1250 1250
1251 1251 $ hg init commitconfusion
1252 1252 $ cd commitconfusion
1253 1253 $ cat > a.patch <<EOF
1254 1254 > module: summary
1255 1255 >
1256 1256 > --- description
1257 1257 >
1258 1258 > diff --git a/a b/a
1259 1259 > new file mode 100644
1260 1260 > --- /dev/null
1261 1261 > +++ b/a
1262 1262 > @@ -0,0 +1,1 @@
1263 1263 > +a
1264 1264 > EOF
1265 1265 > hg import -d '0 0' a.patch
1266 1266 > hg parents -v
1267 1267 > cd ..
1268 1268 >
1269 1269 > echo '% tricky header splitting'
1270 1270 > cat > trickyheaders.patch <<EOF
1271 1271 > From: User A <user@a>
1272 1272 > Subject: [PATCH] from: tricky!
1273 1273 >
1274 1274 > # HG changeset patch
1275 1275 > # User User B
1276 1276 > # Date 1266264441 18000
1277 1277 > # Branch stable
1278 1278 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
1279 1279 > # Parent 0000000000000000000000000000000000000000
1280 1280 > from: tricky!
1281 1281 >
1282 1282 > That is not a header.
1283 1283 >
1284 1284 > diff -r 000000000000 -r f2be6a1170ac foo
1285 1285 > --- /dev/null
1286 1286 > +++ b/foo
1287 1287 > @@ -0,0 +1,1 @@
1288 1288 > +foo
1289 1289 > EOF
1290 1290 applying a.patch
1291 1291 changeset: 0:f34d9187897d
1292 1292 tag: tip
1293 1293 user: test
1294 1294 date: Thu Jan 01 00:00:00 1970 +0000
1295 1295 files: a
1296 1296 description:
1297 1297 module: summary
1298 1298
1299 1299
1300 1300 % tricky header splitting
1301 1301
1302 1302 $ hg init trickyheaders
1303 1303 $ cd trickyheaders
1304 1304 $ hg import -d '0 0' ../trickyheaders.patch
1305 1305 applying ../trickyheaders.patch
1306 1306 $ hg export --git tip
1307 1307 # HG changeset patch
1308 1308 # User User B
1309 1309 # Date 0 0
1310 1310 # Thu Jan 01 00:00:00 1970 +0000
1311 1311 # Node ID eb56ab91903632294ac504838508cb370c0901d2
1312 1312 # Parent 0000000000000000000000000000000000000000
1313 1313 from: tricky!
1314 1314
1315 1315 That is not a header.
1316 1316
1317 1317 diff --git a/foo b/foo
1318 1318 new file mode 100644
1319 1319 --- /dev/null
1320 1320 +++ b/foo
1321 1321 @@ -0,0 +1,1 @@
1322 1322 +foo
1323 1323 $ cd ..
1324 1324
1325 1325
1326 1326 Issue2102: hg export and hg import speak different languages
1327 1327
1328 1328 $ hg init issue2102
1329 1329 $ cd issue2102
1330 1330 $ mkdir -p src/cmd/gc
1331 1331 $ touch src/cmd/gc/mksys.bash
1332 1332 $ hg ci -Am init
1333 1333 adding src/cmd/gc/mksys.bash
1334 1334 $ hg import - <<EOF
1335 1335 > # HG changeset patch
1336 1336 > # User Rob Pike
1337 1337 > # Date 1216685449 25200
1338 1338 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
1339 1339 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
1340 1340 > help management of empty pkg and lib directories in perforce
1341 1341 >
1342 1342 > R=gri
1343 1343 > DELTA=4 (4 added, 0 deleted, 0 changed)
1344 1344 > OCL=13328
1345 1345 > CL=13328
1346 1346 >
1347 1347 > diff --git a/lib/place-holder b/lib/place-holder
1348 1348 > new file mode 100644
1349 1349 > --- /dev/null
1350 1350 > +++ b/lib/place-holder
1351 1351 > @@ -0,0 +1,2 @@
1352 1352 > +perforce does not maintain empty directories.
1353 1353 > +this file helps.
1354 1354 > diff --git a/pkg/place-holder b/pkg/place-holder
1355 1355 > new file mode 100644
1356 1356 > --- /dev/null
1357 1357 > +++ b/pkg/place-holder
1358 1358 > @@ -0,0 +1,2 @@
1359 1359 > +perforce does not maintain empty directories.
1360 1360 > +this file helps.
1361 1361 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
1362 1362 > old mode 100644
1363 1363 > new mode 100755
1364 1364 > EOF
1365 1365 applying patch from stdin
1366 1366
1367 1367 #if execbit
1368 1368
1369 1369 $ hg sum
1370 1370 parent: 1:d59915696727 tip
1371 1371 help management of empty pkg and lib directories in perforce
1372 1372 branch: default
1373 1373 commit: (clean)
1374 1374 update: (current)
1375 1375 phases: 2 draft
1376 1376
1377 1377 $ hg diff --git -c tip
1378 1378 diff --git a/lib/place-holder b/lib/place-holder
1379 1379 new file mode 100644
1380 1380 --- /dev/null
1381 1381 +++ b/lib/place-holder
1382 1382 @@ -0,0 +1,2 @@
1383 1383 +perforce does not maintain empty directories.
1384 1384 +this file helps.
1385 1385 diff --git a/pkg/place-holder b/pkg/place-holder
1386 1386 new file mode 100644
1387 1387 --- /dev/null
1388 1388 +++ b/pkg/place-holder
1389 1389 @@ -0,0 +1,2 @@
1390 1390 +perforce does not maintain empty directories.
1391 1391 +this file helps.
1392 1392 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
1393 1393 old mode 100644
1394 1394 new mode 100755
1395 1395
1396 1396 #else
1397 1397
1398 1398 $ hg sum
1399 1399 parent: 1:28f089cc9ccc tip
1400 1400 help management of empty pkg and lib directories in perforce
1401 1401 branch: default
1402 1402 commit: (clean)
1403 1403 update: (current)
1404 1404 phases: 2 draft
1405 1405
1406 1406 $ hg diff --git -c tip
1407 1407 diff --git a/lib/place-holder b/lib/place-holder
1408 1408 new file mode 100644
1409 1409 --- /dev/null
1410 1410 +++ b/lib/place-holder
1411 1411 @@ -0,0 +1,2 @@
1412 1412 +perforce does not maintain empty directories.
1413 1413 +this file helps.
1414 1414 diff --git a/pkg/place-holder b/pkg/place-holder
1415 1415 new file mode 100644
1416 1416 --- /dev/null
1417 1417 +++ b/pkg/place-holder
1418 1418 @@ -0,0 +1,2 @@
1419 1419 +perforce does not maintain empty directories.
1420 1420 +this file helps.
1421 1421
1422 1422 /* The mode change for mksys.bash is missing here, because on platforms */
1423 1423 /* that don't support execbits, mode changes in patches are ignored when */
1424 1424 /* they are imported. This is obviously also the reason for why the hash */
1425 1425 /* in the created changeset is different to the one you see above the */
1426 1426 /* #else clause */
1427 1427
1428 1428 #endif
1429 1429 $ cd ..
1430 1430
1431 1431
1432 1432 diff lines looking like headers
1433 1433
1434 1434 $ hg init difflineslikeheaders
1435 1435 $ cd difflineslikeheaders
1436 1436 $ echo a >a
1437 1437 $ echo b >b
1438 1438 $ echo c >c
1439 1439 $ hg ci -Am1
1440 1440 adding a
1441 1441 adding b
1442 1442 adding c
1443 1443
1444 1444 $ echo "key: value" >>a
1445 1445 $ echo "key: value" >>b
1446 1446 $ echo "foo" >>c
1447 1447 $ hg ci -m2
1448 1448
1449 1449 $ hg up -C 0
1450 1450 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1451 1451 $ hg diff --git -c1 >want
1452 1452 $ hg diff -c1 | hg import --no-commit -
1453 1453 applying patch from stdin
1454 1454 $ hg diff --git >have
1455 1455 $ diff want have
1456 1456 $ cd ..
1457 1457
1458 1458 import a unified diff with no lines of context (diff -U0)
1459 1459
1460 1460 $ hg init diffzero
1461 1461 $ cd diffzero
1462 1462 $ cat > f << EOF
1463 1463 > c2
1464 1464 > c4
1465 1465 > c5
1466 1466 > EOF
1467 1467 $ hg commit -Am0
1468 1468 adding f
1469 1469
1470 1470 $ hg import --no-commit - << EOF
1471 1471 > # HG changeset patch
1472 1472 > # User test
1473 1473 > # Date 0 0
1474 1474 > # Node ID f4974ab632f3dee767567b0576c0ec9a4508575c
1475 1475 > # Parent 8679a12a975b819fae5f7ad3853a2886d143d794
1476 1476 > 1
1477 1477 > diff -r 8679a12a975b -r f4974ab632f3 f
1478 1478 > --- a/f Thu Jan 01 00:00:00 1970 +0000
1479 1479 > +++ b/f Thu Jan 01 00:00:00 1970 +0000
1480 1480 > @@ -0,0 +1,1 @@
1481 1481 > +c1
1482 1482 > @@ -1,0 +3,1 @@
1483 1483 > +c3
1484 1484 > @@ -3,1 +4,0 @@
1485 1485 > -c5
1486 1486 > EOF
1487 1487 applying patch from stdin
1488 1488
1489 1489 $ cat f
1490 1490 c1
1491 1491 c2
1492 1492 c3
1493 1493 c4
1494 1494
1495 1495 $ cd ..
1496 1496
1497 1497 commit message that looks like a diff header (issue1879)
1498 1498
1499 1499 $ hg init headerlikemsg
1500 1500 $ cd headerlikemsg
1501 1501 $ touch empty
1502 1502 $ echo nonempty >> nonempty
1503 1503 $ hg ci -qAl - <<EOF
1504 1504 > blah blah
1505 1505 > diff blah
1506 1506 > blah blah
1507 1507 > EOF
1508 1508 $ hg --config diff.git=1 log -pv
1509 1509 changeset: 0:c6ef204ef767
1510 1510 tag: tip
1511 1511 user: test
1512 1512 date: Thu Jan 01 00:00:00 1970 +0000
1513 1513 files: empty nonempty
1514 1514 description:
1515 1515 blah blah
1516 1516 diff blah
1517 1517 blah blah
1518 1518
1519 1519
1520 1520 diff --git a/empty b/empty
1521 1521 new file mode 100644
1522 1522 diff --git a/nonempty b/nonempty
1523 1523 new file mode 100644
1524 1524 --- /dev/null
1525 1525 +++ b/nonempty
1526 1526 @@ -0,0 +1,1 @@
1527 1527 +nonempty
1528 1528
1529 1529
1530 1530 (without --git, empty file is lost, but commit message should be preserved)
1531 1531
1532 1532 $ hg init plain
1533 1533 $ hg export 0 | hg -R plain import -
1534 1534 applying patch from stdin
1535 1535 $ hg --config diff.git=1 -R plain log -pv
1536 1536 changeset: 0:60a2d231e71f
1537 1537 tag: tip
1538 1538 user: test
1539 1539 date: Thu Jan 01 00:00:00 1970 +0000
1540 1540 files: nonempty
1541 1541 description:
1542 1542 blah blah
1543 1543 diff blah
1544 1544 blah blah
1545 1545
1546 1546
1547 1547 diff --git a/nonempty b/nonempty
1548 1548 new file mode 100644
1549 1549 --- /dev/null
1550 1550 +++ b/nonempty
1551 1551 @@ -0,0 +1,1 @@
1552 1552 +nonempty
1553 1553
1554 1554
1555 1555 (with --git, patch contents should be fully preserved)
1556 1556
1557 1557 $ hg init git
1558 1558 $ hg --config diff.git=1 export 0 | hg -R git import -
1559 1559 applying patch from stdin
1560 1560 $ hg --config diff.git=1 -R git log -pv
1561 1561 changeset: 0:c6ef204ef767
1562 1562 tag: tip
1563 1563 user: test
1564 1564 date: Thu Jan 01 00:00:00 1970 +0000
1565 1565 files: empty nonempty
1566 1566 description:
1567 1567 blah blah
1568 1568 diff blah
1569 1569 blah blah
1570 1570
1571 1571
1572 1572 diff --git a/empty b/empty
1573 1573 new file mode 100644
1574 1574 diff --git a/nonempty b/nonempty
1575 1575 new file mode 100644
1576 1576 --- /dev/null
1577 1577 +++ b/nonempty
1578 1578 @@ -0,0 +1,1 @@
1579 1579 +nonempty
1580 1580
1581 1581
1582 1582 $ cd ..
1583 1583
1584 1584 no segfault while importing a unified diff which start line is zero but chunk
1585 1585 size is non-zero
1586 1586
1587 1587 $ hg init startlinezero
1588 1588 $ cd startlinezero
1589 1589 $ echo foo > foo
1590 1590 $ hg commit -Amfoo
1591 1591 adding foo
1592 1592
1593 1593 $ hg import --no-commit - << EOF
1594 1594 > diff a/foo b/foo
1595 1595 > --- a/foo
1596 1596 > +++ b/foo
1597 1597 > @@ -0,1 +0,1 @@
1598 1598 > foo
1599 1599 > EOF
1600 1600 applying patch from stdin
1601 1601
1602 1602 $ cd ..
1603 1603
1604 1604 Test corner case involving fuzz and skew
1605 1605
1606 1606 $ hg init morecornercases
1607 1607 $ cd morecornercases
1608 1608
1609 1609 $ cat > 01-no-context-beginning-of-file.diff <<EOF
1610 1610 > diff --git a/a b/a
1611 1611 > --- a/a
1612 1612 > +++ b/a
1613 1613 > @@ -1,0 +1,1 @@
1614 1614 > +line
1615 1615 > EOF
1616 1616
1617 1617 $ cat > 02-no-context-middle-of-file.diff <<EOF
1618 1618 > diff --git a/a b/a
1619 1619 > --- a/a
1620 1620 > +++ b/a
1621 1621 > @@ -1,1 +1,1 @@
1622 1622 > -2
1623 1623 > +add some skew
1624 1624 > @@ -2,0 +2,1 @@
1625 1625 > +line
1626 1626 > EOF
1627 1627
1628 1628 $ cat > 03-no-context-end-of-file.diff <<EOF
1629 1629 > diff --git a/a b/a
1630 1630 > --- a/a
1631 1631 > +++ b/a
1632 1632 > @@ -10,0 +10,1 @@
1633 1633 > +line
1634 1634 > EOF
1635 1635
1636 1636 $ cat > 04-middle-of-file-completely-fuzzed.diff <<EOF
1637 1637 > diff --git a/a b/a
1638 1638 > --- a/a
1639 1639 > +++ b/a
1640 1640 > @@ -1,1 +1,1 @@
1641 1641 > -2
1642 1642 > +add some skew
1643 1643 > @@ -2,2 +2,3 @@
1644 1644 > not matching, should fuzz
1645 1645 > ... a bit
1646 1646 > +line
1647 1647 > EOF
1648 1648
1649 1649 $ cat > a <<EOF
1650 1650 > 1
1651 1651 > 2
1652 1652 > 3
1653 1653 > 4
1654 1654 > EOF
1655 1655 $ hg ci -Am adda a
1656 1656 $ for p in *.diff; do
1657 1657 > hg import -v --no-commit $p
1658 1658 > cat a
1659 1659 > hg revert -aqC a
1660 1660 > # patch -p1 < $p
1661 1661 > # cat a
1662 1662 > # hg revert -aC a
1663 1663 > done
1664 1664 applying 01-no-context-beginning-of-file.diff
1665 1665 patching file a
1666 1666 applied to working directory
1667 1667 1
1668 1668 line
1669 1669 2
1670 1670 3
1671 1671 4
1672 1672 applying 02-no-context-middle-of-file.diff
1673 1673 patching file a
1674 1674 Hunk #1 succeeded at 2 (offset 1 lines).
1675 1675 Hunk #2 succeeded at 4 (offset 1 lines).
1676 1676 applied to working directory
1677 1677 1
1678 1678 add some skew
1679 1679 3
1680 1680 line
1681 1681 4
1682 1682 applying 03-no-context-end-of-file.diff
1683 1683 patching file a
1684 1684 Hunk #1 succeeded at 5 (offset -6 lines).
1685 1685 applied to working directory
1686 1686 1
1687 1687 2
1688 1688 3
1689 1689 4
1690 1690 line
1691 1691 applying 04-middle-of-file-completely-fuzzed.diff
1692 1692 patching file a
1693 1693 Hunk #1 succeeded at 2 (offset 1 lines).
1694 1694 Hunk #2 succeeded at 5 with fuzz 2 (offset 1 lines).
1695 1695 applied to working directory
1696 1696 1
1697 1697 add some skew
1698 1698 3
1699 1699 4
1700 1700 line
1701 1701 $ cd ..
1702 1702
1703 1703 Test partial application
1704 1704 ------------------------
1705 1705
1706 1706 prepare a stack of patches depending on each other
1707 1707
1708 1708 $ hg init partial
1709 1709 $ cd partial
1710 1710 $ cat << EOF > a
1711 1711 > one
1712 1712 > two
1713 1713 > three
1714 1714 > four
1715 1715 > five
1716 1716 > six
1717 1717 > seven
1718 1718 > EOF
1719 1719 $ hg add a
1720 1720 $ echo 'b' > b
1721 1721 $ hg add b
1722 1722 $ hg commit -m 'initial' -u Babar
1723 1723 $ cat << EOF > a
1724 1724 > one
1725 1725 > two
1726 1726 > 3
1727 1727 > four
1728 1728 > five
1729 1729 > six
1730 1730 > seven
1731 1731 > EOF
1732 1732 $ hg commit -m 'three' -u Celeste
1733 1733 $ cat << EOF > a
1734 1734 > one
1735 1735 > two
1736 1736 > 3
1737 1737 > 4
1738 1738 > five
1739 1739 > six
1740 1740 > seven
1741 1741 > EOF
1742 1742 $ hg commit -m 'four' -u Rataxes
1743 1743 $ cat << EOF > a
1744 1744 > one
1745 1745 > two
1746 1746 > 3
1747 1747 > 4
1748 1748 > 5
1749 1749 > six
1750 1750 > seven
1751 1751 > EOF
1752 1752 $ echo bb >> b
1753 1753 $ hg commit -m 'five' -u Arthur
1754 1754 $ echo 'Babar' > jungle
1755 1755 $ hg add jungle
1756 1756 $ hg ci -m 'jungle' -u Zephir
1757 1757 $ echo 'Celeste' >> jungle
1758 1758 $ hg ci -m 'extended jungle' -u Cornelius
1759 1759 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1760 1760 @ extended jungle [Cornelius] 1: +1/-0
1761 1761 |
1762 1762 o jungle [Zephir] 1: +1/-0
1763 1763 |
1764 1764 o five [Arthur] 2: +2/-1
1765 1765 |
1766 1766 o four [Rataxes] 1: +1/-1
1767 1767 |
1768 1768 o three [Celeste] 1: +1/-1
1769 1769 |
1770 1770 o initial [Babar] 2: +8/-0
1771 1771
1772 1772 Adding those config options should not change the output of diffstat. Bugfix #4755.
1773 1773
1774 1774 $ hg log -r . --template '{diffstat}\n'
1775 1775 1: +1/-0
1776 1776 $ hg log -r . --template '{diffstat}\n' --config diff.git=1 \
1777 1777 > --config diff.noprefix=1
1778 1778 1: +1/-0
1779 1779
1780 1780 Importing with some success and some errors:
1781 1781
1782 1782 $ hg update --rev 'desc(initial)'
1783 1783 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1784 1784 $ hg export --rev 'desc(five)' | hg import --partial -
1785 1785 applying patch from stdin
1786 1786 patching file a
1787 1787 Hunk #1 FAILED at 1
1788 1788 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1789 1789 patch applied partially
1790 1790 (fix the .rej files and run `hg commit --amend`)
1791 1791 [1]
1792 1792
1793 1793 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1794 1794 @ five [Arthur] 1: +1/-0
1795 1795 |
1796 1796 | o extended jungle [Cornelius] 1: +1/-0
1797 1797 | |
1798 1798 | o jungle [Zephir] 1: +1/-0
1799 1799 | |
1800 1800 | o five [Arthur] 2: +2/-1
1801 1801 | |
1802 1802 | o four [Rataxes] 1: +1/-1
1803 1803 | |
1804 1804 | o three [Celeste] 1: +1/-1
1805 1805 |/
1806 1806 o initial [Babar] 2: +8/-0
1807 1807
1808 1808 $ hg export
1809 1809 # HG changeset patch
1810 1810 # User Arthur
1811 1811 # Date 0 0
1812 1812 # Thu Jan 01 00:00:00 1970 +0000
1813 1813 # Node ID 26e6446bb2526e2be1037935f5fca2b2706f1509
1814 1814 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1815 1815 five
1816 1816
1817 1817 diff -r 8e4f0351909e -r 26e6446bb252 b
1818 1818 --- a/b Thu Jan 01 00:00:00 1970 +0000
1819 1819 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1820 1820 @@ -1,1 +1,2 @@
1821 1821 b
1822 1822 +bb
1823 1823 $ hg status -c .
1824 1824 C a
1825 1825 C b
1826 1826 $ ls -A
1827 1827 .hg
1828 1828 a
1829 1829 a.rej
1830 1830 b
1831 1831
1832 1832 Importing with zero success:
1833 1833
1834 1834 $ hg update --rev 'desc(initial)'
1835 1835 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1836 1836 $ hg export --rev 'desc(four)' | hg import --partial -
1837 1837 applying patch from stdin
1838 1838 patching file a
1839 1839 Hunk #1 FAILED at 0
1840 1840 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1841 1841 patch applied partially
1842 1842 (fix the .rej files and run `hg commit --amend`)
1843 1843 [1]
1844 1844
1845 1845 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1846 1846 @ four [Rataxes] 0: +0/-0
1847 1847 |
1848 1848 | o five [Arthur] 1: +1/-0
1849 1849 |/
1850 1850 | o extended jungle [Cornelius] 1: +1/-0
1851 1851 | |
1852 1852 | o jungle [Zephir] 1: +1/-0
1853 1853 | |
1854 1854 | o five [Arthur] 2: +2/-1
1855 1855 | |
1856 1856 | o four [Rataxes] 1: +1/-1
1857 1857 | |
1858 1858 | o three [Celeste] 1: +1/-1
1859 1859 |/
1860 1860 o initial [Babar] 2: +8/-0
1861 1861
1862 1862 $ hg export
1863 1863 # HG changeset patch
1864 1864 # User Rataxes
1865 1865 # Date 0 0
1866 1866 # Thu Jan 01 00:00:00 1970 +0000
1867 1867 # Node ID cb9b1847a74d9ad52e93becaf14b98dbcc274e1e
1868 1868 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1869 1869 four
1870 1870
1871 1871 $ hg status -c .
1872 1872 C a
1873 1873 C b
1874 1874 $ ls -A
1875 1875 .hg
1876 1876 a
1877 1877 a.rej
1878 1878 b
1879 1879
1880 1880 Importing with unknown file:
1881 1881
1882 1882 $ hg update --rev 'desc(initial)'
1883 1883 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1884 1884 $ hg export --rev 'desc("extended jungle")' | hg import --partial -
1885 1885 applying patch from stdin
1886 1886 unable to find 'jungle' for patching
1887 1887 (use '--prefix' to apply patch relative to the current directory)
1888 1888 1 out of 1 hunks FAILED -- saving rejects to file jungle.rej
1889 1889 patch applied partially
1890 1890 (fix the .rej files and run `hg commit --amend`)
1891 1891 [1]
1892 1892
1893 1893 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1894 1894 @ extended jungle [Cornelius] 0: +0/-0
1895 1895 |
1896 1896 | o four [Rataxes] 0: +0/-0
1897 1897 |/
1898 1898 | o five [Arthur] 1: +1/-0
1899 1899 |/
1900 1900 | o extended jungle [Cornelius] 1: +1/-0
1901 1901 | |
1902 1902 | o jungle [Zephir] 1: +1/-0
1903 1903 | |
1904 1904 | o five [Arthur] 2: +2/-1
1905 1905 | |
1906 1906 | o four [Rataxes] 1: +1/-1
1907 1907 | |
1908 1908 | o three [Celeste] 1: +1/-1
1909 1909 |/
1910 1910 o initial [Babar] 2: +8/-0
1911 1911
1912 1912 $ hg export
1913 1913 # HG changeset patch
1914 1914 # User Cornelius
1915 1915 # Date 0 0
1916 1916 # Thu Jan 01 00:00:00 1970 +0000
1917 1917 # Node ID 1fb1f86bef43c5a75918178f8d23c29fb0a7398d
1918 1918 # Parent 8e4f0351909eae6b9cf68c2c076cb54c42b54b2e
1919 1919 extended jungle
1920 1920
1921 1921 $ hg status -c .
1922 1922 C a
1923 1923 C b
1924 1924 $ ls -A
1925 1925 .hg
1926 1926 a
1927 1927 a.rej
1928 1928 b
1929 1929 jungle.rej
1930 1930
1931 1931 Importing multiple failing patches:
1932 1932
1933 1933 $ hg update --rev 'desc(initial)'
1934 1934 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1935 1935 $ echo 'B' > b # just to make another commit
1936 1936 $ hg commit -m "a new base"
1937 1937 created new head
1938 1938 $ hg export --rev 'desc("four") + desc("extended jungle")' | hg import --partial -
1939 1939 applying patch from stdin
1940 1940 patching file a
1941 1941 Hunk #1 FAILED at 0
1942 1942 1 out of 1 hunks FAILED -- saving rejects to file a.rej
1943 1943 patch applied partially
1944 1944 (fix the .rej files and run `hg commit --amend`)
1945 1945 [1]
1946 1946 $ hg log -G --template '{desc|firstline} [{author}] {diffstat}\n'
1947 1947 @ four [Rataxes] 0: +0/-0
1948 1948 |
1949 1949 o a new base [test] 1: +1/-1
1950 1950 |
1951 1951 | o extended jungle [Cornelius] 0: +0/-0
1952 1952 |/
1953 1953 | o four [Rataxes] 0: +0/-0
1954 1954 |/
1955 1955 | o five [Arthur] 1: +1/-0
1956 1956 |/
1957 1957 | o extended jungle [Cornelius] 1: +1/-0
1958 1958 | |
1959 1959 | o jungle [Zephir] 1: +1/-0
1960 1960 | |
1961 1961 | o five [Arthur] 2: +2/-1
1962 1962 | |
1963 1963 | o four [Rataxes] 1: +1/-1
1964 1964 | |
1965 1965 | o three [Celeste] 1: +1/-1
1966 1966 |/
1967 1967 o initial [Babar] 2: +8/-0
1968 1968
1969 1969 $ hg export
1970 1970 # HG changeset patch
1971 1971 # User Rataxes
1972 1972 # Date 0 0
1973 1973 # Thu Jan 01 00:00:00 1970 +0000
1974 1974 # Node ID a9d7b6d0ffbb4eb12b7d5939250fcd42e8930a1d
1975 1975 # Parent f59f8d2e95a8ca5b1b4ca64320140da85f3b44fd
1976 1976 four
1977 1977
1978 1978 $ hg status -c .
1979 1979 C a
1980 1980 C b
1981 1981
1982 1982 Importing some extra header
1983 1983 ===========================
1984 1984
1985 1985 $ cat > $TESTTMP/parseextra.py <<EOF
1986 1986 > import mercurial.cmdutil
1987 1987 > import mercurial.patch
1988 1988 >
1989 1989 > def processfoo(repo, data, extra, opts):
1990 1990 > if b'foo' in data:
1991 1991 > extra[b'foo'] = data[b'foo']
1992 1992 > def postimport(ctx):
1993 1993 > if b'foo' in ctx.extra():
1994 1994 > ctx.repo().ui.write(b'imported-foo: %s\n' % ctx.extra()[b'foo'])
1995 1995 >
1996 1996 > mercurial.patch.patchheadermap.append((b'Foo', b'foo'))
1997 1997 > mercurial.cmdutil.extrapreimport.append(b'foo')
1998 1998 > mercurial.cmdutil.extrapreimportmap[b'foo'] = processfoo
1999 1999 > mercurial.cmdutil.extrapostimport.append(b'foo')
2000 2000 > mercurial.cmdutil.extrapostimportmap[b'foo'] = postimport
2001 2001 > EOF
2002 2002 $ cat >> $HGRCPATH <<EOF
2003 2003 > [extensions]
2004 2004 > parseextra=$TESTTMP/parseextra.py
2005 2005 > EOF
2006 2006 $ hg up -C tip
2007 2007 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2008 2008 $ cat > $TESTTMP/foo.patch <<EOF
2009 2009 > # HG changeset patch
2010 2010 > # User Rataxes
2011 2011 > # Date 0 0
2012 2012 > # Thu Jan 01 00:00:00 1970 +0000
2013 2013 > # Foo bar
2014 2014 > height
2015 2015 >
2016 2016 > --- a/a Thu Jan 01 00:00:00 1970 +0000
2017 2017 > +++ b/a Wed Oct 07 09:17:44 2015 +0000
2018 2018 > @@ -5,3 +5,4 @@
2019 2019 > five
2020 2020 > six
2021 2021 > seven
2022 2022 > +heigt
2023 2023 > EOF
2024 2024 $ hg import $TESTTMP/foo.patch
2025 2025 applying $TESTTMP/foo.patch
2026 2026 imported-foo: bar
2027 2027 $ hg log --debug -r . | grep extra
2028 2028 extra: branch=default
2029 2029 extra: foo=bar
2030 2030
2031 2031 Warn the user that paths are relative to the root of
2032 2032 repository when file not found for patching
2033 2033
2034 2034 $ mkdir filedir
2035 2035 $ echo "file1" >> filedir/file1
2036 2036 $ hg add filedir/file1
2037 2037 $ hg commit -m "file1"
2038 2038 $ cd filedir
2039 2039 $ hg import -p 2 - <<EOF
2040 2040 > # HG changeset patch
2041 2041 > # User test
2042 2042 > # Date 0 0
2043 2043 > file2
2044 2044 >
2045 2045 > diff --git a/filedir/file1 b/filedir/file1
2046 2046 > --- a/filedir/file1
2047 2047 > +++ b/filedir/file1
2048 2048 > @@ -1,1 +1,2 @@
2049 2049 > file1
2050 2050 > +file2
2051 2051 > EOF
2052 2052 applying patch from stdin
2053 2053 unable to find 'file1' for patching
2054 2054 (use '--prefix' to apply patch relative to the current directory)
2055 2055 1 out of 1 hunks FAILED -- saving rejects to file file1.rej
2056 2056 abort: patch failed to apply
2057 2057 [255]
2058 2058
2059 2059 test import crash (issue5375)
2060 2060 $ cd ..
2061 2061 $ hg init repo
2062 2062 $ cd repo
2063 2063 $ printf "diff --git a/a b/b\nrename from a\nrename to b" | hg import -
2064 2064 applying patch from stdin
2065 2065 a not tracked!
2066 2066 abort: source file 'a' does not exist
2067 2067 [255]
2068 2068
2069 2069 test immature end of hunk
2070 2070
2071 2071 $ hg import - <<'EOF'
2072 2072 > diff --git a/foo b/foo
2073 2073 > --- a/foo
2074 2074 > --- b/foo
2075 2075 > @@ -0,0 +1,1 @@
2076 2076 > EOF
2077 2077 applying patch from stdin
2078 2078 abort: bad hunk #1: incomplete hunk
2079 2079 [255]
2080 2080
2081 2081 $ hg import - <<'EOF'
2082 2082 > diff --git a/foo b/foo
2083 2083 > --- a/foo
2084 2084 > --- b/foo
2085 2085 > @@ -0,0 +1,1 @@
2086 2086 > \ No newline at end of file
2087 2087 > EOF
2088 2088 applying patch from stdin
2089 2089 abort: bad hunk #1: incomplete hunk
2090 2090 [255]
General Comments 0
You need to be logged in to leave comments. Login now