##// END OF EJS Templates
ui: fix extra space in username abort
Matt Mackall -
r20580:b75a23ee default
parent child Browse files
Show More
@@ -1,829 +1,829
1 1 # ui.py - user interface bits for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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 i18n import _
9 9 import errno, getpass, os, socket, sys, tempfile, traceback
10 10 import config, scmutil, util, error, formatter
11 11
12 12 class ui(object):
13 13 def __init__(self, src=None):
14 14 self._buffers = []
15 15 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
16 16 self._reportuntrusted = True
17 17 self._ocfg = config.config() # overlay
18 18 self._tcfg = config.config() # trusted
19 19 self._ucfg = config.config() # untrusted
20 20 self._trustusers = set()
21 21 self._trustgroups = set()
22 22 self.callhooks = True
23 23
24 24 if src:
25 25 self.fout = src.fout
26 26 self.ferr = src.ferr
27 27 self.fin = src.fin
28 28
29 29 self._tcfg = src._tcfg.copy()
30 30 self._ucfg = src._ucfg.copy()
31 31 self._ocfg = src._ocfg.copy()
32 32 self._trustusers = src._trustusers.copy()
33 33 self._trustgroups = src._trustgroups.copy()
34 34 self.environ = src.environ
35 35 self.callhooks = src.callhooks
36 36 self.fixconfig()
37 37 else:
38 38 self.fout = sys.stdout
39 39 self.ferr = sys.stderr
40 40 self.fin = sys.stdin
41 41
42 42 # shared read-only environment
43 43 self.environ = os.environ
44 44 # we always trust global config files
45 45 for f in scmutil.rcpath():
46 46 self.readconfig(f, trust=True)
47 47
48 48 def copy(self):
49 49 return self.__class__(self)
50 50
51 51 def formatter(self, topic, opts):
52 52 return formatter.formatter(self, topic, opts)
53 53
54 54 def _trusted(self, fp, f):
55 55 st = util.fstat(fp)
56 56 if util.isowner(st):
57 57 return True
58 58
59 59 tusers, tgroups = self._trustusers, self._trustgroups
60 60 if '*' in tusers or '*' in tgroups:
61 61 return True
62 62
63 63 user = util.username(st.st_uid)
64 64 group = util.groupname(st.st_gid)
65 65 if user in tusers or group in tgroups or user == util.username():
66 66 return True
67 67
68 68 if self._reportuntrusted:
69 69 self.warn(_('not trusting file %s from untrusted '
70 70 'user %s, group %s\n') % (f, user, group))
71 71 return False
72 72
73 73 def readconfig(self, filename, root=None, trust=False,
74 74 sections=None, remap=None):
75 75 try:
76 76 fp = open(filename)
77 77 except IOError:
78 78 if not sections: # ignore unless we were looking for something
79 79 return
80 80 raise
81 81
82 82 cfg = config.config()
83 83 trusted = sections or trust or self._trusted(fp, filename)
84 84
85 85 try:
86 86 cfg.read(filename, fp, sections=sections, remap=remap)
87 87 fp.close()
88 88 except error.ConfigError, inst:
89 89 if trusted:
90 90 raise
91 91 self.warn(_("ignored: %s\n") % str(inst))
92 92
93 93 if self.plain():
94 94 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
95 95 'logtemplate', 'style',
96 96 'traceback', 'verbose'):
97 97 if k in cfg['ui']:
98 98 del cfg['ui'][k]
99 99 for k, v in cfg.items('defaults'):
100 100 del cfg['defaults'][k]
101 101 # Don't remove aliases from the configuration if in the exceptionlist
102 102 if self.plain('alias'):
103 103 for k, v in cfg.items('alias'):
104 104 del cfg['alias'][k]
105 105
106 106 if trusted:
107 107 self._tcfg.update(cfg)
108 108 self._tcfg.update(self._ocfg)
109 109 self._ucfg.update(cfg)
110 110 self._ucfg.update(self._ocfg)
111 111
112 112 if root is None:
113 113 root = os.path.expanduser('~')
114 114 self.fixconfig(root=root)
115 115
116 116 def fixconfig(self, root=None, section=None):
117 117 if section in (None, 'paths'):
118 118 # expand vars and ~
119 119 # translate paths relative to root (or home) into absolute paths
120 120 root = root or os.getcwd()
121 121 for c in self._tcfg, self._ucfg, self._ocfg:
122 122 for n, p in c.items('paths'):
123 123 if not p:
124 124 continue
125 125 if '%%' in p:
126 126 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
127 127 % (n, p, self.configsource('paths', n)))
128 128 p = p.replace('%%', '%')
129 129 p = util.expandpath(p)
130 130 if not util.hasscheme(p) and not os.path.isabs(p):
131 131 p = os.path.normpath(os.path.join(root, p))
132 132 c.set("paths", n, p)
133 133
134 134 if section in (None, 'ui'):
135 135 # update ui options
136 136 self.debugflag = self.configbool('ui', 'debug')
137 137 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
138 138 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
139 139 if self.verbose and self.quiet:
140 140 self.quiet = self.verbose = False
141 141 self._reportuntrusted = self.debugflag or self.configbool("ui",
142 142 "report_untrusted", True)
143 143 self.tracebackflag = self.configbool('ui', 'traceback', False)
144 144
145 145 if section in (None, 'trusted'):
146 146 # update trust information
147 147 self._trustusers.update(self.configlist('trusted', 'users'))
148 148 self._trustgroups.update(self.configlist('trusted', 'groups'))
149 149
150 150 def backupconfig(self, section, item):
151 151 return (self._ocfg.backup(section, item),
152 152 self._tcfg.backup(section, item),
153 153 self._ucfg.backup(section, item),)
154 154 def restoreconfig(self, data):
155 155 self._ocfg.restore(data[0])
156 156 self._tcfg.restore(data[1])
157 157 self._ucfg.restore(data[2])
158 158
159 159 def setconfig(self, section, name, value, overlay=True):
160 160 if overlay:
161 161 self._ocfg.set(section, name, value)
162 162 self._tcfg.set(section, name, value)
163 163 self._ucfg.set(section, name, value)
164 164 self.fixconfig(section=section)
165 165
166 166 def _data(self, untrusted):
167 167 return untrusted and self._ucfg or self._tcfg
168 168
169 169 def configsource(self, section, name, untrusted=False):
170 170 return self._data(untrusted).source(section, name) or 'none'
171 171
172 172 def config(self, section, name, default=None, untrusted=False):
173 173 if isinstance(name, list):
174 174 alternates = name
175 175 else:
176 176 alternates = [name]
177 177
178 178 for n in alternates:
179 179 value = self._data(untrusted).get(section, n, None)
180 180 if value is not None:
181 181 name = n
182 182 break
183 183 else:
184 184 value = default
185 185
186 186 if self.debugflag and not untrusted and self._reportuntrusted:
187 187 for n in alternates:
188 188 uvalue = self._ucfg.get(section, n)
189 189 if uvalue is not None and uvalue != value:
190 190 self.debug("ignoring untrusted configuration option "
191 191 "%s.%s = %s\n" % (section, n, uvalue))
192 192 return value
193 193
194 194 def configpath(self, section, name, default=None, untrusted=False):
195 195 'get a path config item, expanded relative to repo root or config file'
196 196 v = self.config(section, name, default, untrusted)
197 197 if v is None:
198 198 return None
199 199 if not os.path.isabs(v) or "://" not in v:
200 200 src = self.configsource(section, name, untrusted)
201 201 if ':' in src:
202 202 base = os.path.dirname(src.rsplit(':')[0])
203 203 v = os.path.join(base, os.path.expanduser(v))
204 204 return v
205 205
206 206 def configbool(self, section, name, default=False, untrusted=False):
207 207 """parse a configuration element as a boolean
208 208
209 209 >>> u = ui(); s = 'foo'
210 210 >>> u.setconfig(s, 'true', 'yes')
211 211 >>> u.configbool(s, 'true')
212 212 True
213 213 >>> u.setconfig(s, 'false', 'no')
214 214 >>> u.configbool(s, 'false')
215 215 False
216 216 >>> u.configbool(s, 'unknown')
217 217 False
218 218 >>> u.configbool(s, 'unknown', True)
219 219 True
220 220 >>> u.setconfig(s, 'invalid', 'somevalue')
221 221 >>> u.configbool(s, 'invalid')
222 222 Traceback (most recent call last):
223 223 ...
224 224 ConfigError: foo.invalid is not a boolean ('somevalue')
225 225 """
226 226
227 227 v = self.config(section, name, None, untrusted)
228 228 if v is None:
229 229 return default
230 230 if isinstance(v, bool):
231 231 return v
232 232 b = util.parsebool(v)
233 233 if b is None:
234 234 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
235 235 % (section, name, v))
236 236 return b
237 237
238 238 def configint(self, section, name, default=None, untrusted=False):
239 239 """parse a configuration element as an integer
240 240
241 241 >>> u = ui(); s = 'foo'
242 242 >>> u.setconfig(s, 'int1', '42')
243 243 >>> u.configint(s, 'int1')
244 244 42
245 245 >>> u.setconfig(s, 'int2', '-42')
246 246 >>> u.configint(s, 'int2')
247 247 -42
248 248 >>> u.configint(s, 'unknown', 7)
249 249 7
250 250 >>> u.setconfig(s, 'invalid', 'somevalue')
251 251 >>> u.configint(s, 'invalid')
252 252 Traceback (most recent call last):
253 253 ...
254 254 ConfigError: foo.invalid is not an integer ('somevalue')
255 255 """
256 256
257 257 v = self.config(section, name, None, untrusted)
258 258 if v is None:
259 259 return default
260 260 try:
261 261 return int(v)
262 262 except ValueError:
263 263 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
264 264 % (section, name, v))
265 265
266 266 def configbytes(self, section, name, default=0, untrusted=False):
267 267 """parse a configuration element as a quantity in bytes
268 268
269 269 Units can be specified as b (bytes), k or kb (kilobytes), m or
270 270 mb (megabytes), g or gb (gigabytes).
271 271
272 272 >>> u = ui(); s = 'foo'
273 273 >>> u.setconfig(s, 'val1', '42')
274 274 >>> u.configbytes(s, 'val1')
275 275 42
276 276 >>> u.setconfig(s, 'val2', '42.5 kb')
277 277 >>> u.configbytes(s, 'val2')
278 278 43520
279 279 >>> u.configbytes(s, 'unknown', '7 MB')
280 280 7340032
281 281 >>> u.setconfig(s, 'invalid', 'somevalue')
282 282 >>> u.configbytes(s, 'invalid')
283 283 Traceback (most recent call last):
284 284 ...
285 285 ConfigError: foo.invalid is not a byte quantity ('somevalue')
286 286 """
287 287
288 288 value = self.config(section, name)
289 289 if value is None:
290 290 if not isinstance(default, str):
291 291 return default
292 292 value = default
293 293 try:
294 294 return util.sizetoint(value)
295 295 except error.ParseError:
296 296 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
297 297 % (section, name, value))
298 298
299 299 def configlist(self, section, name, default=None, untrusted=False):
300 300 """parse a configuration element as a list of comma/space separated
301 301 strings
302 302
303 303 >>> u = ui(); s = 'foo'
304 304 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
305 305 >>> u.configlist(s, 'list1')
306 306 ['this', 'is', 'a small', 'test']
307 307 """
308 308
309 309 def _parse_plain(parts, s, offset):
310 310 whitespace = False
311 311 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
312 312 whitespace = True
313 313 offset += 1
314 314 if offset >= len(s):
315 315 return None, parts, offset
316 316 if whitespace:
317 317 parts.append('')
318 318 if s[offset] == '"' and not parts[-1]:
319 319 return _parse_quote, parts, offset + 1
320 320 elif s[offset] == '"' and parts[-1][-1] == '\\':
321 321 parts[-1] = parts[-1][:-1] + s[offset]
322 322 return _parse_plain, parts, offset + 1
323 323 parts[-1] += s[offset]
324 324 return _parse_plain, parts, offset + 1
325 325
326 326 def _parse_quote(parts, s, offset):
327 327 if offset < len(s) and s[offset] == '"': # ""
328 328 parts.append('')
329 329 offset += 1
330 330 while offset < len(s) and (s[offset].isspace() or
331 331 s[offset] == ','):
332 332 offset += 1
333 333 return _parse_plain, parts, offset
334 334
335 335 while offset < len(s) and s[offset] != '"':
336 336 if (s[offset] == '\\' and offset + 1 < len(s)
337 337 and s[offset + 1] == '"'):
338 338 offset += 1
339 339 parts[-1] += '"'
340 340 else:
341 341 parts[-1] += s[offset]
342 342 offset += 1
343 343
344 344 if offset >= len(s):
345 345 real_parts = _configlist(parts[-1])
346 346 if not real_parts:
347 347 parts[-1] = '"'
348 348 else:
349 349 real_parts[0] = '"' + real_parts[0]
350 350 parts = parts[:-1]
351 351 parts.extend(real_parts)
352 352 return None, parts, offset
353 353
354 354 offset += 1
355 355 while offset < len(s) and s[offset] in [' ', ',']:
356 356 offset += 1
357 357
358 358 if offset < len(s):
359 359 if offset + 1 == len(s) and s[offset] == '"':
360 360 parts[-1] += '"'
361 361 offset += 1
362 362 else:
363 363 parts.append('')
364 364 else:
365 365 return None, parts, offset
366 366
367 367 return _parse_plain, parts, offset
368 368
369 369 def _configlist(s):
370 370 s = s.rstrip(' ,')
371 371 if not s:
372 372 return []
373 373 parser, parts, offset = _parse_plain, [''], 0
374 374 while parser:
375 375 parser, parts, offset = parser(parts, s, offset)
376 376 return parts
377 377
378 378 result = self.config(section, name, untrusted=untrusted)
379 379 if result is None:
380 380 result = default or []
381 381 if isinstance(result, basestring):
382 382 result = _configlist(result.lstrip(' ,\n'))
383 383 if result is None:
384 384 result = default or []
385 385 return result
386 386
387 387 def has_section(self, section, untrusted=False):
388 388 '''tell whether section exists in config.'''
389 389 return section in self._data(untrusted)
390 390
391 391 def configitems(self, section, untrusted=False):
392 392 items = self._data(untrusted).items(section)
393 393 if self.debugflag and not untrusted and self._reportuntrusted:
394 394 for k, v in self._ucfg.items(section):
395 395 if self._tcfg.get(section, k) != v:
396 396 self.debug("ignoring untrusted configuration option "
397 397 "%s.%s = %s\n" % (section, k, v))
398 398 return items
399 399
400 400 def walkconfig(self, untrusted=False):
401 401 cfg = self._data(untrusted)
402 402 for section in cfg.sections():
403 403 for name, value in self.configitems(section, untrusted):
404 404 yield section, name, value
405 405
406 406 def plain(self, feature=None):
407 407 '''is plain mode active?
408 408
409 409 Plain mode means that all configuration variables which affect
410 410 the behavior and output of Mercurial should be
411 411 ignored. Additionally, the output should be stable,
412 412 reproducible and suitable for use in scripts or applications.
413 413
414 414 The only way to trigger plain mode is by setting either the
415 415 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
416 416
417 417 The return value can either be
418 418 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
419 419 - True otherwise
420 420 '''
421 421 if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
422 422 return False
423 423 exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
424 424 if feature and exceptions:
425 425 return feature not in exceptions
426 426 return True
427 427
428 428 def username(self):
429 429 """Return default username to be used in commits.
430 430
431 431 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
432 432 and stop searching if one of these is set.
433 433 If not found and ui.askusername is True, ask the user, else use
434 434 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
435 435 """
436 436 user = os.environ.get("HGUSER")
437 437 if user is None:
438 438 user = self.config("ui", "username")
439 439 if user is not None:
440 440 user = os.path.expandvars(user)
441 441 if user is None:
442 442 user = os.environ.get("EMAIL")
443 443 if user is None and self.configbool("ui", "askusername"):
444 444 user = self.prompt(_("enter a commit username:"), default=None)
445 445 if user is None and not self.interactive():
446 446 try:
447 447 user = '%s@%s' % (util.getuser(), socket.getfqdn())
448 448 self.warn(_("no username found, using '%s' instead\n") % user)
449 449 except KeyError:
450 450 pass
451 451 if not user:
452 452 raise util.Abort(_('no username supplied'),
453 453 hint=_('use "hg config --edit" '
454 ' to set your username'))
454 'to set your username'))
455 455 if "\n" in user:
456 456 raise util.Abort(_("username %s contains a newline\n") % repr(user))
457 457 return user
458 458
459 459 def shortuser(self, user):
460 460 """Return a short representation of a user name or email address."""
461 461 if not self.verbose:
462 462 user = util.shortuser(user)
463 463 return user
464 464
465 465 def expandpath(self, loc, default=None):
466 466 """Return repository location relative to cwd or from [paths]"""
467 467 if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
468 468 return loc
469 469
470 470 path = self.config('paths', loc)
471 471 if not path and default is not None:
472 472 path = self.config('paths', default)
473 473 return path or loc
474 474
475 475 def pushbuffer(self):
476 476 self._buffers.append([])
477 477
478 478 def popbuffer(self, labeled=False):
479 479 '''pop the last buffer and return the buffered output
480 480
481 481 If labeled is True, any labels associated with buffered
482 482 output will be handled. By default, this has no effect
483 483 on the output returned, but extensions and GUI tools may
484 484 handle this argument and returned styled output. If output
485 485 is being buffered so it can be captured and parsed or
486 486 processed, labeled should not be set to True.
487 487 '''
488 488 return "".join(self._buffers.pop())
489 489
490 490 def write(self, *args, **opts):
491 491 '''write args to output
492 492
493 493 By default, this method simply writes to the buffer or stdout,
494 494 but extensions or GUI tools may override this method,
495 495 write_err(), popbuffer(), and label() to style output from
496 496 various parts of hg.
497 497
498 498 An optional keyword argument, "label", can be passed in.
499 499 This should be a string containing label names separated by
500 500 space. Label names take the form of "topic.type". For example,
501 501 ui.debug() issues a label of "ui.debug".
502 502
503 503 When labeling output for a specific command, a label of
504 504 "cmdname.type" is recommended. For example, status issues
505 505 a label of "status.modified" for modified files.
506 506 '''
507 507 if self._buffers:
508 508 self._buffers[-1].extend([str(a) for a in args])
509 509 else:
510 510 for a in args:
511 511 self.fout.write(str(a))
512 512
513 513 def write_err(self, *args, **opts):
514 514 try:
515 515 if not getattr(self.fout, 'closed', False):
516 516 self.fout.flush()
517 517 for a in args:
518 518 self.ferr.write(str(a))
519 519 # stderr may be buffered under win32 when redirected to files,
520 520 # including stdout.
521 521 if not getattr(self.ferr, 'closed', False):
522 522 self.ferr.flush()
523 523 except IOError, inst:
524 524 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
525 525 raise
526 526
527 527 def flush(self):
528 528 try: self.fout.flush()
529 529 except (IOError, ValueError): pass
530 530 try: self.ferr.flush()
531 531 except (IOError, ValueError): pass
532 532
533 533 def _isatty(self, fh):
534 534 if self.configbool('ui', 'nontty', False):
535 535 return False
536 536 return util.isatty(fh)
537 537
538 538 def interactive(self):
539 539 '''is interactive input allowed?
540 540
541 541 An interactive session is a session where input can be reasonably read
542 542 from `sys.stdin'. If this function returns false, any attempt to read
543 543 from stdin should fail with an error, unless a sensible default has been
544 544 specified.
545 545
546 546 Interactiveness is triggered by the value of the `ui.interactive'
547 547 configuration variable or - if it is unset - when `sys.stdin' points
548 548 to a terminal device.
549 549
550 550 This function refers to input only; for output, see `ui.formatted()'.
551 551 '''
552 552 i = self.configbool("ui", "interactive", None)
553 553 if i is None:
554 554 # some environments replace stdin without implementing isatty
555 555 # usually those are non-interactive
556 556 return self._isatty(self.fin)
557 557
558 558 return i
559 559
560 560 def termwidth(self):
561 561 '''how wide is the terminal in columns?
562 562 '''
563 563 if 'COLUMNS' in os.environ:
564 564 try:
565 565 return int(os.environ['COLUMNS'])
566 566 except ValueError:
567 567 pass
568 568 return util.termwidth()
569 569
570 570 def formatted(self):
571 571 '''should formatted output be used?
572 572
573 573 It is often desirable to format the output to suite the output medium.
574 574 Examples of this are truncating long lines or colorizing messages.
575 575 However, this is not often not desirable when piping output into other
576 576 utilities, e.g. `grep'.
577 577
578 578 Formatted output is triggered by the value of the `ui.formatted'
579 579 configuration variable or - if it is unset - when `sys.stdout' points
580 580 to a terminal device. Please note that `ui.formatted' should be
581 581 considered an implementation detail; it is not intended for use outside
582 582 Mercurial or its extensions.
583 583
584 584 This function refers to output only; for input, see `ui.interactive()'.
585 585 This function always returns false when in plain mode, see `ui.plain()'.
586 586 '''
587 587 if self.plain():
588 588 return False
589 589
590 590 i = self.configbool("ui", "formatted", None)
591 591 if i is None:
592 592 # some environments replace stdout without implementing isatty
593 593 # usually those are non-interactive
594 594 return self._isatty(self.fout)
595 595
596 596 return i
597 597
598 598 def _readline(self, prompt=''):
599 599 if self._isatty(self.fin):
600 600 try:
601 601 # magically add command line editing support, where
602 602 # available
603 603 import readline
604 604 # force demandimport to really load the module
605 605 readline.read_history_file
606 606 # windows sometimes raises something other than ImportError
607 607 except Exception:
608 608 pass
609 609
610 610 # call write() so output goes through subclassed implementation
611 611 # e.g. color extension on Windows
612 612 self.write(prompt)
613 613
614 614 # instead of trying to emulate raw_input, swap (self.fin,
615 615 # self.fout) with (sys.stdin, sys.stdout)
616 616 oldin = sys.stdin
617 617 oldout = sys.stdout
618 618 sys.stdin = self.fin
619 619 sys.stdout = self.fout
620 620 line = raw_input(' ')
621 621 sys.stdin = oldin
622 622 sys.stdout = oldout
623 623
624 624 # When stdin is in binary mode on Windows, it can cause
625 625 # raw_input() to emit an extra trailing carriage return
626 626 if os.linesep == '\r\n' and line and line[-1] == '\r':
627 627 line = line[:-1]
628 628 return line
629 629
630 630 def prompt(self, msg, default="y"):
631 631 """Prompt user with msg, read response.
632 632 If ui is not interactive, the default is returned.
633 633 """
634 634 if not self.interactive():
635 635 self.write(msg, ' ', default, "\n")
636 636 return default
637 637 try:
638 638 r = self._readline(self.label(msg, 'ui.prompt'))
639 639 if not r:
640 640 return default
641 641 return r
642 642 except EOFError:
643 643 raise util.Abort(_('response expected'))
644 644
645 645 @staticmethod
646 646 def extractchoices(prompt):
647 647 """Extract prompt message and list of choices from specified prompt.
648 648
649 649 This returns tuple "(message, choices)", and "choices" is the
650 650 list of tuple "(response character, text without &)".
651 651 """
652 652 parts = prompt.split('$$')
653 653 msg = parts[0].rstrip(' ')
654 654 choices = [p.strip(' ') for p in parts[1:]]
655 655 return (msg,
656 656 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
657 657 for s in choices])
658 658
659 659 def promptchoice(self, prompt, default=0):
660 660 """Prompt user with a message, read response, and ensure it matches
661 661 one of the provided choices. The prompt is formatted as follows:
662 662
663 663 "would you like fries with that (Yn)? $$ &Yes $$ &No"
664 664
665 665 The index of the choice is returned. Responses are case
666 666 insensitive. If ui is not interactive, the default is
667 667 returned.
668 668 """
669 669
670 670 msg, choices = self.extractchoices(prompt)
671 671 resps = [r for r, t in choices]
672 672 while True:
673 673 r = self.prompt(msg, resps[default])
674 674 if r.lower() in resps:
675 675 return resps.index(r.lower())
676 676 self.write(_("unrecognized response\n"))
677 677
678 678 def getpass(self, prompt=None, default=None):
679 679 if not self.interactive():
680 680 return default
681 681 try:
682 682 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
683 683 return getpass.getpass('')
684 684 except EOFError:
685 685 raise util.Abort(_('response expected'))
686 686 def status(self, *msg, **opts):
687 687 '''write status message to output (if ui.quiet is False)
688 688
689 689 This adds an output label of "ui.status".
690 690 '''
691 691 if not self.quiet:
692 692 opts['label'] = opts.get('label', '') + ' ui.status'
693 693 self.write(*msg, **opts)
694 694 def warn(self, *msg, **opts):
695 695 '''write warning message to output (stderr)
696 696
697 697 This adds an output label of "ui.warning".
698 698 '''
699 699 opts['label'] = opts.get('label', '') + ' ui.warning'
700 700 self.write_err(*msg, **opts)
701 701 def note(self, *msg, **opts):
702 702 '''write note to output (if ui.verbose is True)
703 703
704 704 This adds an output label of "ui.note".
705 705 '''
706 706 if self.verbose:
707 707 opts['label'] = opts.get('label', '') + ' ui.note'
708 708 self.write(*msg, **opts)
709 709 def debug(self, *msg, **opts):
710 710 '''write debug message to output (if ui.debugflag is True)
711 711
712 712 This adds an output label of "ui.debug".
713 713 '''
714 714 if self.debugflag:
715 715 opts['label'] = opts.get('label', '') + ' ui.debug'
716 716 self.write(*msg, **opts)
717 717 def edit(self, text, user):
718 718 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
719 719 text=True)
720 720 try:
721 721 f = os.fdopen(fd, "w")
722 722 f.write(text)
723 723 f.close()
724 724
725 725 editor = self.geteditor()
726 726
727 727 util.system("%s \"%s\"" % (editor, name),
728 728 environ={'HGUSER': user},
729 729 onerr=util.Abort, errprefix=_("edit failed"),
730 730 out=self.fout)
731 731
732 732 f = open(name)
733 733 t = f.read()
734 734 f.close()
735 735 finally:
736 736 os.unlink(name)
737 737
738 738 return t
739 739
740 740 def traceback(self, exc=None, force=False):
741 741 '''print exception traceback if traceback printing enabled or forced.
742 742 only to call in exception handler. returns true if traceback
743 743 printed.'''
744 744 if self.tracebackflag or force:
745 745 if exc is None:
746 746 exc = sys.exc_info()
747 747 cause = getattr(exc[1], 'cause', None)
748 748
749 749 if cause is not None:
750 750 causetb = traceback.format_tb(cause[2])
751 751 exctb = traceback.format_tb(exc[2])
752 752 exconly = traceback.format_exception_only(cause[0], cause[1])
753 753
754 754 # exclude frame where 'exc' was chained and rethrown from exctb
755 755 self.write_err('Traceback (most recent call last):\n',
756 756 ''.join(exctb[:-1]),
757 757 ''.join(causetb),
758 758 ''.join(exconly))
759 759 else:
760 760 traceback.print_exception(exc[0], exc[1], exc[2],
761 761 file=self.ferr)
762 762 return self.tracebackflag or force
763 763
764 764 def geteditor(self):
765 765 '''return editor to use'''
766 766 if sys.platform == 'plan9':
767 767 # vi is the MIPS instruction simulator on Plan 9. We
768 768 # instead default to E to plumb commit messages to
769 769 # avoid confusion.
770 770 editor = 'E'
771 771 else:
772 772 editor = 'vi'
773 773 return (os.environ.get("HGEDITOR") or
774 774 self.config("ui", "editor") or
775 775 os.environ.get("VISUAL") or
776 776 os.environ.get("EDITOR", editor))
777 777
778 778 def progress(self, topic, pos, item="", unit="", total=None):
779 779 '''show a progress message
780 780
781 781 With stock hg, this is simply a debug message that is hidden
782 782 by default, but with extensions or GUI tools it may be
783 783 visible. 'topic' is the current operation, 'item' is a
784 784 non-numeric marker of the current position (i.e. the currently
785 785 in-process file), 'pos' is the current numeric position (i.e.
786 786 revision, bytes, etc.), unit is a corresponding unit label,
787 787 and total is the highest expected pos.
788 788
789 789 Multiple nested topics may be active at a time.
790 790
791 791 All topics should be marked closed by setting pos to None at
792 792 termination.
793 793 '''
794 794
795 795 if pos is None or not self.debugflag:
796 796 return
797 797
798 798 if unit:
799 799 unit = ' ' + unit
800 800 if item:
801 801 item = ' ' + item
802 802
803 803 if total:
804 804 pct = 100.0 * pos / total
805 805 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
806 806 % (topic, item, pos, total, unit, pct))
807 807 else:
808 808 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
809 809
810 810 def log(self, service, *msg, **opts):
811 811 '''hook for logging facility extensions
812 812
813 813 service should be a readily-identifiable subsystem, which will
814 814 allow filtering.
815 815 message should be a newline-terminated string to log.
816 816 '''
817 817 pass
818 818
819 819 def label(self, msg, label):
820 820 '''style msg based on supplied label
821 821
822 822 Like ui.write(), this just returns msg unchanged, but extensions
823 823 and GUI tools can override it to allow styling output without
824 824 writing it.
825 825
826 826 ui.write(s, 'label') is equivalent to
827 827 ui.write(ui.label(s, 'label')).
828 828 '''
829 829 return msg
@@ -1,66 +1,66
1 1 $ unset HGUSER
2 2 $ EMAIL="My Name <myname@example.com>"
3 3 $ export EMAIL
4 4
5 5 $ hg init test
6 6 $ cd test
7 7 $ touch asdf
8 8 $ hg add asdf
9 9 $ hg commit -m commit-1
10 10 $ hg tip
11 11 changeset: 0:53f268a58230
12 12 tag: tip
13 13 user: My Name <myname@example.com>
14 14 date: Thu Jan 01 00:00:00 1970 +0000
15 15 summary: commit-1
16 16
17 17
18 18 $ unset EMAIL
19 19 $ echo 1234 > asdf
20 20 $ hg commit -u "foo@bar.com" -m commit-1
21 21 $ hg tip
22 22 changeset: 1:3871b2a9e9bf
23 23 tag: tip
24 24 user: foo@bar.com
25 25 date: Thu Jan 01 00:00:00 1970 +0000
26 26 summary: commit-1
27 27
28 28 $ echo "[ui]" >> .hg/hgrc
29 29 $ echo "username = foobar <foo@bar.com>" >> .hg/hgrc
30 30 $ echo 12 > asdf
31 31 $ hg commit -m commit-1
32 32 $ hg tip
33 33 changeset: 2:8eeac6695c1c
34 34 tag: tip
35 35 user: foobar <foo@bar.com>
36 36 date: Thu Jan 01 00:00:00 1970 +0000
37 37 summary: commit-1
38 38
39 39 $ echo 1 > asdf
40 40 $ hg commit -u "foo@bar.com" -m commit-1
41 41 $ hg tip
42 42 changeset: 3:957606a725e4
43 43 tag: tip
44 44 user: foo@bar.com
45 45 date: Thu Jan 01 00:00:00 1970 +0000
46 46 summary: commit-1
47 47
48 48 $ echo 123 > asdf
49 49 $ echo "[ui]" > .hg/hgrc
50 50 $ echo "username = " >> .hg/hgrc
51 51 $ hg commit -m commit-1
52 52 abort: no username supplied
53 (use "hg config --edit" to set your username)
53 (use "hg config --edit" to set your username)
54 54 [255]
55 55 $ rm .hg/hgrc
56 56 $ hg commit -m commit-1 2>&1
57 57 no username found, using '[^']*' instead (re)
58 58
59 59 $ echo space > asdf
60 60 $ hg commit -u ' ' -m commit-1
61 61 transaction abort!
62 62 rollback completed
63 63 abort: empty username!
64 64 [255]
65 65
66 66 $ cd ..
@@ -1,1302 +1,1302
1 1 Set up a repo
2 2
3 3 $ echo "[ui]" >> $HGRCPATH
4 4 $ echo "interactive=true" >> $HGRCPATH
5 5 $ echo "[extensions]" >> $HGRCPATH
6 6 $ echo "record=" >> $HGRCPATH
7 7
8 8 $ hg init a
9 9 $ cd a
10 10
11 11 Select no files
12 12
13 13 $ touch empty-rw
14 14 $ hg add empty-rw
15 15
16 16 $ hg record empty-rw<<EOF
17 17 > n
18 18 > EOF
19 19 diff --git a/empty-rw b/empty-rw
20 20 new file mode 100644
21 21 examine changes to 'empty-rw'? [Ynesfdaq?]
22 22 no changes to record
23 23
24 24 $ hg tip -p
25 25 changeset: -1:000000000000
26 26 tag: tip
27 27 user:
28 28 date: Thu Jan 01 00:00:00 1970 +0000
29 29
30 30
31 31
32 32 Select files but no hunks
33 33
34 34 $ hg record empty-rw<<EOF
35 35 > y
36 36 > n
37 37 > EOF
38 38 diff --git a/empty-rw b/empty-rw
39 39 new file mode 100644
40 40 examine changes to 'empty-rw'? [Ynesfdaq?]
41 41 abort: empty commit message
42 42 [255]
43 43
44 44 $ hg tip -p
45 45 changeset: -1:000000000000
46 46 tag: tip
47 47 user:
48 48 date: Thu Jan 01 00:00:00 1970 +0000
49 49
50 50
51 51
52 52 Record empty file
53 53
54 54 $ hg record -d '0 0' -m empty empty-rw<<EOF
55 55 > y
56 56 > y
57 57 > EOF
58 58 diff --git a/empty-rw b/empty-rw
59 59 new file mode 100644
60 60 examine changes to 'empty-rw'? [Ynesfdaq?]
61 61
62 62 $ hg tip -p
63 63 changeset: 0:c0708cf4e46e
64 64 tag: tip
65 65 user: test
66 66 date: Thu Jan 01 00:00:00 1970 +0000
67 67 summary: empty
68 68
69 69
70 70
71 71 Summary shows we updated to the new cset
72 72
73 73 $ hg summary
74 74 parent: 0:c0708cf4e46e tip
75 75 empty
76 76 branch: default
77 77 commit: (clean)
78 78 update: (current)
79 79
80 80 Rename empty file
81 81
82 82 $ hg mv empty-rw empty-rename
83 83 $ hg record -d '1 0' -m rename<<EOF
84 84 > y
85 85 > EOF
86 86 diff --git a/empty-rw b/empty-rename
87 87 rename from empty-rw
88 88 rename to empty-rename
89 89 examine changes to 'empty-rw' and 'empty-rename'? [Ynesfdaq?]
90 90
91 91 $ hg tip -p
92 92 changeset: 1:d695e8dcb197
93 93 tag: tip
94 94 user: test
95 95 date: Thu Jan 01 00:00:01 1970 +0000
96 96 summary: rename
97 97
98 98
99 99
100 100 Copy empty file
101 101
102 102 $ hg cp empty-rename empty-copy
103 103 $ hg record -d '2 0' -m copy<<EOF
104 104 > y
105 105 > EOF
106 106 diff --git a/empty-rename b/empty-copy
107 107 copy from empty-rename
108 108 copy to empty-copy
109 109 examine changes to 'empty-rename' and 'empty-copy'? [Ynesfdaq?]
110 110
111 111 $ hg tip -p
112 112 changeset: 2:1d4b90bea524
113 113 tag: tip
114 114 user: test
115 115 date: Thu Jan 01 00:00:02 1970 +0000
116 116 summary: copy
117 117
118 118
119 119
120 120 Delete empty file
121 121
122 122 $ hg rm empty-copy
123 123 $ hg record -d '3 0' -m delete<<EOF
124 124 > y
125 125 > EOF
126 126 diff --git a/empty-copy b/empty-copy
127 127 deleted file mode 100644
128 128 examine changes to 'empty-copy'? [Ynesfdaq?]
129 129
130 130 $ hg tip -p
131 131 changeset: 3:b39a238f01a1
132 132 tag: tip
133 133 user: test
134 134 date: Thu Jan 01 00:00:03 1970 +0000
135 135 summary: delete
136 136
137 137
138 138
139 139 Add binary file
140 140
141 141 $ hg bundle --base -2 tip.bundle
142 142 1 changesets found
143 143 $ hg add tip.bundle
144 144 $ hg record -d '4 0' -m binary<<EOF
145 145 > y
146 146 > EOF
147 147 diff --git a/tip.bundle b/tip.bundle
148 148 new file mode 100644
149 149 this is a binary file
150 150 examine changes to 'tip.bundle'? [Ynesfdaq?]
151 151
152 152 $ hg tip -p
153 153 changeset: 4:ad816da3711e
154 154 tag: tip
155 155 user: test
156 156 date: Thu Jan 01 00:00:04 1970 +0000
157 157 summary: binary
158 158
159 159 diff -r b39a238f01a1 -r ad816da3711e tip.bundle
160 160 Binary file tip.bundle has changed
161 161
162 162
163 163 Change binary file
164 164
165 165 $ hg bundle --base -2 tip.bundle
166 166 1 changesets found
167 167 $ hg record -d '5 0' -m binary-change<<EOF
168 168 > y
169 169 > EOF
170 170 diff --git a/tip.bundle b/tip.bundle
171 171 this modifies a binary file (all or nothing)
172 172 examine changes to 'tip.bundle'? [Ynesfdaq?]
173 173
174 174 $ hg tip -p
175 175 changeset: 5:dccd6f3eb485
176 176 tag: tip
177 177 user: test
178 178 date: Thu Jan 01 00:00:05 1970 +0000
179 179 summary: binary-change
180 180
181 181 diff -r ad816da3711e -r dccd6f3eb485 tip.bundle
182 182 Binary file tip.bundle has changed
183 183
184 184
185 185 Rename and change binary file
186 186
187 187 $ hg mv tip.bundle top.bundle
188 188 $ hg bundle --base -2 top.bundle
189 189 1 changesets found
190 190 $ hg record -d '6 0' -m binary-change-rename<<EOF
191 191 > y
192 192 > EOF
193 193 diff --git a/tip.bundle b/top.bundle
194 194 rename from tip.bundle
195 195 rename to top.bundle
196 196 this modifies a binary file (all or nothing)
197 197 examine changes to 'tip.bundle' and 'top.bundle'? [Ynesfdaq?]
198 198
199 199 $ hg tip -p
200 200 changeset: 6:7fa44105f5b3
201 201 tag: tip
202 202 user: test
203 203 date: Thu Jan 01 00:00:06 1970 +0000
204 204 summary: binary-change-rename
205 205
206 206 diff -r dccd6f3eb485 -r 7fa44105f5b3 tip.bundle
207 207 Binary file tip.bundle has changed
208 208 diff -r dccd6f3eb485 -r 7fa44105f5b3 top.bundle
209 209 Binary file top.bundle has changed
210 210
211 211
212 212 Add plain file
213 213
214 214 $ for i in 1 2 3 4 5 6 7 8 9 10; do
215 215 > echo $i >> plain
216 216 > done
217 217
218 218 $ hg add plain
219 219 $ hg record -d '7 0' -m plain plain<<EOF
220 220 > y
221 221 > y
222 222 > EOF
223 223 diff --git a/plain b/plain
224 224 new file mode 100644
225 225 examine changes to 'plain'? [Ynesfdaq?]
226 226
227 227 $ hg tip -p
228 228 changeset: 7:11fb457c1be4
229 229 tag: tip
230 230 user: test
231 231 date: Thu Jan 01 00:00:07 1970 +0000
232 232 summary: plain
233 233
234 234 diff -r 7fa44105f5b3 -r 11fb457c1be4 plain
235 235 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
236 236 +++ b/plain Thu Jan 01 00:00:07 1970 +0000
237 237 @@ -0,0 +1,10 @@
238 238 +1
239 239 +2
240 240 +3
241 241 +4
242 242 +5
243 243 +6
244 244 +7
245 245 +8
246 246 +9
247 247 +10
248 248
249 249 Modify end of plain file with username unset
250 250
251 251 $ echo 11 >> plain
252 252 $ unset HGUSER
253 253 $ hg record --config ui.username= -d '8 0' -m end plain
254 254 abort: no username supplied
255 (use "hg config --edit" to set your username)
255 (use "hg config --edit" to set your username)
256 256 [255]
257 257
258 258
259 259 Modify end of plain file, also test that diffopts are accounted for
260 260
261 261 $ HGUSER="test"
262 262 $ export HGUSER
263 263 $ hg record --config diff.showfunc=true -d '8 0' -m end plain <<EOF
264 264 > y
265 265 > y
266 266 > EOF
267 267 diff --git a/plain b/plain
268 268 1 hunks, 1 lines changed
269 269 examine changes to 'plain'? [Ynesfdaq?]
270 270 @@ -8,3 +8,4 @@ 7
271 271 8
272 272 9
273 273 10
274 274 +11
275 275 record this change to 'plain'? [Ynesfdaq?]
276 276
277 277 Modify end of plain file, no EOL
278 278
279 279 $ hg tip --template '{node}' >> plain
280 280 $ hg record -d '9 0' -m noeol plain <<EOF
281 281 > y
282 282 > y
283 283 > EOF
284 284 diff --git a/plain b/plain
285 285 1 hunks, 1 lines changed
286 286 examine changes to 'plain'? [Ynesfdaq?]
287 287 @@ -9,3 +9,4 @@
288 288 9
289 289 10
290 290 11
291 291 +7264f99c5f5ff3261504828afa4fb4d406c3af54
292 292 \ No newline at end of file
293 293 record this change to 'plain'? [Ynesfdaq?]
294 294
295 295 Modify end of plain file, add EOL
296 296
297 297 $ echo >> plain
298 298 $ echo 1 > plain2
299 299 $ hg add plain2
300 300 $ hg record -d '10 0' -m eol plain plain2 <<EOF
301 301 > y
302 302 > y
303 303 > y
304 304 > EOF
305 305 diff --git a/plain b/plain
306 306 1 hunks, 1 lines changed
307 307 examine changes to 'plain'? [Ynesfdaq?]
308 308 @@ -9,4 +9,4 @@
309 309 9
310 310 10
311 311 11
312 312 -7264f99c5f5ff3261504828afa4fb4d406c3af54
313 313 \ No newline at end of file
314 314 +7264f99c5f5ff3261504828afa4fb4d406c3af54
315 315 record change 1/2 to 'plain'? [Ynesfdaq?]
316 316 diff --git a/plain2 b/plain2
317 317 new file mode 100644
318 318 examine changes to 'plain2'? [Ynesfdaq?]
319 319
320 320 Modify beginning, trim end, record both, add another file to test
321 321 changes numbering
322 322
323 323 $ rm plain
324 324 $ for i in 2 2 3 4 5 6 7 8 9 10; do
325 325 > echo $i >> plain
326 326 > done
327 327 $ echo 2 >> plain2
328 328
329 329 $ hg record -d '10 0' -m begin-and-end plain plain2 <<EOF
330 330 > y
331 331 > y
332 332 > y
333 333 > y
334 334 > y
335 335 > EOF
336 336 diff --git a/plain b/plain
337 337 2 hunks, 3 lines changed
338 338 examine changes to 'plain'? [Ynesfdaq?]
339 339 @@ -1,4 +1,4 @@
340 340 -1
341 341 +2
342 342 2
343 343 3
344 344 4
345 345 record change 1/3 to 'plain'? [Ynesfdaq?]
346 346 @@ -8,5 +8,3 @@
347 347 8
348 348 9
349 349 10
350 350 -11
351 351 -7264f99c5f5ff3261504828afa4fb4d406c3af54
352 352 record change 2/3 to 'plain'? [Ynesfdaq?]
353 353 diff --git a/plain2 b/plain2
354 354 1 hunks, 1 lines changed
355 355 examine changes to 'plain2'? [Ynesfdaq?]
356 356 @@ -1,1 +1,2 @@
357 357 1
358 358 +2
359 359 record change 3/3 to 'plain2'? [Ynesfdaq?]
360 360
361 361 $ hg tip -p
362 362 changeset: 11:21df83db12b8
363 363 tag: tip
364 364 user: test
365 365 date: Thu Jan 01 00:00:10 1970 +0000
366 366 summary: begin-and-end
367 367
368 368 diff -r ddb8b281c3ff -r 21df83db12b8 plain
369 369 --- a/plain Thu Jan 01 00:00:10 1970 +0000
370 370 +++ b/plain Thu Jan 01 00:00:10 1970 +0000
371 371 @@ -1,4 +1,4 @@
372 372 -1
373 373 +2
374 374 2
375 375 3
376 376 4
377 377 @@ -8,5 +8,3 @@
378 378 8
379 379 9
380 380 10
381 381 -11
382 382 -7264f99c5f5ff3261504828afa4fb4d406c3af54
383 383 diff -r ddb8b281c3ff -r 21df83db12b8 plain2
384 384 --- a/plain2 Thu Jan 01 00:00:10 1970 +0000
385 385 +++ b/plain2 Thu Jan 01 00:00:10 1970 +0000
386 386 @@ -1,1 +1,2 @@
387 387 1
388 388 +2
389 389
390 390
391 391 Trim beginning, modify end
392 392
393 393 $ rm plain
394 394 > for i in 4 5 6 7 8 9 10.new; do
395 395 > echo $i >> plain
396 396 > done
397 397
398 398 Record end
399 399
400 400 $ hg record -d '11 0' -m end-only plain <<EOF
401 401 > y
402 402 > n
403 403 > y
404 404 > EOF
405 405 diff --git a/plain b/plain
406 406 2 hunks, 4 lines changed
407 407 examine changes to 'plain'? [Ynesfdaq?]
408 408 @@ -1,9 +1,6 @@
409 409 -2
410 410 -2
411 411 -3
412 412 4
413 413 5
414 414 6
415 415 7
416 416 8
417 417 9
418 418 record change 1/2 to 'plain'? [Ynesfdaq?]
419 419 @@ -4,7 +1,7 @@
420 420 4
421 421 5
422 422 6
423 423 7
424 424 8
425 425 9
426 426 -10
427 427 +10.new
428 428 record change 2/2 to 'plain'? [Ynesfdaq?]
429 429
430 430 $ hg tip -p
431 431 changeset: 12:99337501826f
432 432 tag: tip
433 433 user: test
434 434 date: Thu Jan 01 00:00:11 1970 +0000
435 435 summary: end-only
436 436
437 437 diff -r 21df83db12b8 -r 99337501826f plain
438 438 --- a/plain Thu Jan 01 00:00:10 1970 +0000
439 439 +++ b/plain Thu Jan 01 00:00:11 1970 +0000
440 440 @@ -7,4 +7,4 @@
441 441 7
442 442 8
443 443 9
444 444 -10
445 445 +10.new
446 446
447 447
448 448 Record beginning
449 449
450 450 $ hg record -d '12 0' -m begin-only plain <<EOF
451 451 > y
452 452 > y
453 453 > EOF
454 454 diff --git a/plain b/plain
455 455 1 hunks, 3 lines changed
456 456 examine changes to 'plain'? [Ynesfdaq?]
457 457 @@ -1,6 +1,3 @@
458 458 -2
459 459 -2
460 460 -3
461 461 4
462 462 5
463 463 6
464 464 record this change to 'plain'? [Ynesfdaq?]
465 465
466 466 $ hg tip -p
467 467 changeset: 13:bbd45465d540
468 468 tag: tip
469 469 user: test
470 470 date: Thu Jan 01 00:00:12 1970 +0000
471 471 summary: begin-only
472 472
473 473 diff -r 99337501826f -r bbd45465d540 plain
474 474 --- a/plain Thu Jan 01 00:00:11 1970 +0000
475 475 +++ b/plain Thu Jan 01 00:00:12 1970 +0000
476 476 @@ -1,6 +1,3 @@
477 477 -2
478 478 -2
479 479 -3
480 480 4
481 481 5
482 482 6
483 483
484 484
485 485 Add to beginning, trim from end
486 486
487 487 $ rm plain
488 488 $ for i in 1 2 3 4 5 6 7 8 9; do
489 489 > echo $i >> plain
490 490 > done
491 491
492 492 Record end
493 493
494 494 $ hg record --traceback -d '13 0' -m end-again plain<<EOF
495 495 > y
496 496 > n
497 497 > y
498 498 > EOF
499 499 diff --git a/plain b/plain
500 500 2 hunks, 4 lines changed
501 501 examine changes to 'plain'? [Ynesfdaq?]
502 502 @@ -1,6 +1,9 @@
503 503 +1
504 504 +2
505 505 +3
506 506 4
507 507 5
508 508 6
509 509 7
510 510 8
511 511 9
512 512 record change 1/2 to 'plain'? [Ynesfdaq?]
513 513 @@ -1,7 +4,6 @@
514 514 4
515 515 5
516 516 6
517 517 7
518 518 8
519 519 9
520 520 -10.new
521 521 record change 2/2 to 'plain'? [Ynesfdaq?]
522 522
523 523 Add to beginning, middle, end
524 524
525 525 $ rm plain
526 526 $ for i in 1 2 3 4 5 5.new 5.reallynew 6 7 8 9 10 11; do
527 527 > echo $i >> plain
528 528 > done
529 529
530 530 Record beginning, middle
531 531
532 532 $ hg record -d '14 0' -m middle-only plain <<EOF
533 533 > y
534 534 > y
535 535 > y
536 536 > n
537 537 > EOF
538 538 diff --git a/plain b/plain
539 539 3 hunks, 7 lines changed
540 540 examine changes to 'plain'? [Ynesfdaq?]
541 541 @@ -1,2 +1,5 @@
542 542 +1
543 543 +2
544 544 +3
545 545 4
546 546 5
547 547 record change 1/3 to 'plain'? [Ynesfdaq?]
548 548 @@ -1,6 +4,8 @@
549 549 4
550 550 5
551 551 +5.new
552 552 +5.reallynew
553 553 6
554 554 7
555 555 8
556 556 9
557 557 record change 2/3 to 'plain'? [Ynesfdaq?]
558 558 @@ -3,4 +8,6 @@
559 559 6
560 560 7
561 561 8
562 562 9
563 563 +10
564 564 +11
565 565 record change 3/3 to 'plain'? [Ynesfdaq?]
566 566
567 567 $ hg tip -p
568 568 changeset: 15:f34a7937ec33
569 569 tag: tip
570 570 user: test
571 571 date: Thu Jan 01 00:00:14 1970 +0000
572 572 summary: middle-only
573 573
574 574 diff -r 82c065d0b850 -r f34a7937ec33 plain
575 575 --- a/plain Thu Jan 01 00:00:13 1970 +0000
576 576 +++ b/plain Thu Jan 01 00:00:14 1970 +0000
577 577 @@ -1,5 +1,10 @@
578 578 +1
579 579 +2
580 580 +3
581 581 4
582 582 5
583 583 +5.new
584 584 +5.reallynew
585 585 6
586 586 7
587 587 8
588 588
589 589
590 590 Record end
591 591
592 592 $ hg record -d '15 0' -m end-only plain <<EOF
593 593 > y
594 594 > y
595 595 > EOF
596 596 diff --git a/plain b/plain
597 597 1 hunks, 2 lines changed
598 598 examine changes to 'plain'? [Ynesfdaq?]
599 599 @@ -9,3 +9,5 @@
600 600 7
601 601 8
602 602 9
603 603 +10
604 604 +11
605 605 record this change to 'plain'? [Ynesfdaq?]
606 606
607 607 $ hg tip -p
608 608 changeset: 16:f9900b71a04c
609 609 tag: tip
610 610 user: test
611 611 date: Thu Jan 01 00:00:15 1970 +0000
612 612 summary: end-only
613 613
614 614 diff -r f34a7937ec33 -r f9900b71a04c plain
615 615 --- a/plain Thu Jan 01 00:00:14 1970 +0000
616 616 +++ b/plain Thu Jan 01 00:00:15 1970 +0000
617 617 @@ -9,3 +9,5 @@
618 618 7
619 619 8
620 620 9
621 621 +10
622 622 +11
623 623
624 624
625 625 $ mkdir subdir
626 626 $ cd subdir
627 627 $ echo a > a
628 628 $ hg ci -d '16 0' -Amsubdir
629 629 adding subdir/a
630 630
631 631 $ echo a >> a
632 632 $ hg record -d '16 0' -m subdir-change a <<EOF
633 633 > y
634 634 > y
635 635 > EOF
636 636 diff --git a/subdir/a b/subdir/a
637 637 1 hunks, 1 lines changed
638 638 examine changes to 'subdir/a'? [Ynesfdaq?]
639 639 @@ -1,1 +1,2 @@
640 640 a
641 641 +a
642 642 record this change to 'subdir/a'? [Ynesfdaq?]
643 643
644 644 $ hg tip -p
645 645 changeset: 18:61be427a9deb
646 646 tag: tip
647 647 user: test
648 648 date: Thu Jan 01 00:00:16 1970 +0000
649 649 summary: subdir-change
650 650
651 651 diff -r a7ffae4d61cb -r 61be427a9deb subdir/a
652 652 --- a/subdir/a Thu Jan 01 00:00:16 1970 +0000
653 653 +++ b/subdir/a Thu Jan 01 00:00:16 1970 +0000
654 654 @@ -1,1 +1,2 @@
655 655 a
656 656 +a
657 657
658 658
659 659 $ echo a > f1
660 660 $ echo b > f2
661 661 $ hg add f1 f2
662 662
663 663 $ hg ci -mz -d '17 0'
664 664
665 665 $ echo a >> f1
666 666 $ echo b >> f2
667 667
668 668 Help, quit
669 669
670 670 $ hg record <<EOF
671 671 > ?
672 672 > q
673 673 > EOF
674 674 diff --git a/subdir/f1 b/subdir/f1
675 675 1 hunks, 1 lines changed
676 676 examine changes to 'subdir/f1'? [Ynesfdaq?]
677 677 y - yes, record this change
678 678 n - no, skip this change
679 679 e - edit this change manually
680 680 s - skip remaining changes to this file
681 681 f - record remaining changes to this file
682 682 d - done, skip remaining changes and files
683 683 a - record all changes to all remaining files
684 684 q - quit, recording no changes
685 685 ? - ? (display help)
686 686 examine changes to 'subdir/f1'? [Ynesfdaq?]
687 687 abort: user quit
688 688 [255]
689 689
690 690 Skip
691 691
692 692 $ hg record <<EOF
693 693 > s
694 694 > EOF
695 695 diff --git a/subdir/f1 b/subdir/f1
696 696 1 hunks, 1 lines changed
697 697 examine changes to 'subdir/f1'? [Ynesfdaq?]
698 698 diff --git a/subdir/f2 b/subdir/f2
699 699 1 hunks, 1 lines changed
700 700 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
701 701 [255]
702 702
703 703 No
704 704
705 705 $ hg record <<EOF
706 706 > n
707 707 > EOF
708 708 diff --git a/subdir/f1 b/subdir/f1
709 709 1 hunks, 1 lines changed
710 710 examine changes to 'subdir/f1'? [Ynesfdaq?]
711 711 diff --git a/subdir/f2 b/subdir/f2
712 712 1 hunks, 1 lines changed
713 713 examine changes to 'subdir/f2'? [Ynesfdaq?] abort: response expected
714 714 [255]
715 715
716 716 f, quit
717 717
718 718 $ hg record <<EOF
719 719 > f
720 720 > q
721 721 > EOF
722 722 diff --git a/subdir/f1 b/subdir/f1
723 723 1 hunks, 1 lines changed
724 724 examine changes to 'subdir/f1'? [Ynesfdaq?]
725 725 diff --git a/subdir/f2 b/subdir/f2
726 726 1 hunks, 1 lines changed
727 727 examine changes to 'subdir/f2'? [Ynesfdaq?]
728 728 abort: user quit
729 729 [255]
730 730
731 731 s, all
732 732
733 733 $ hg record -d '18 0' -mx <<EOF
734 734 > s
735 735 > a
736 736 > EOF
737 737 diff --git a/subdir/f1 b/subdir/f1
738 738 1 hunks, 1 lines changed
739 739 examine changes to 'subdir/f1'? [Ynesfdaq?]
740 740 diff --git a/subdir/f2 b/subdir/f2
741 741 1 hunks, 1 lines changed
742 742 examine changes to 'subdir/f2'? [Ynesfdaq?]
743 743
744 744 $ hg tip -p
745 745 changeset: 20:b3df3dda369a
746 746 tag: tip
747 747 user: test
748 748 date: Thu Jan 01 00:00:18 1970 +0000
749 749 summary: x
750 750
751 751 diff -r 6e02d6c9906d -r b3df3dda369a subdir/f2
752 752 --- a/subdir/f2 Thu Jan 01 00:00:17 1970 +0000
753 753 +++ b/subdir/f2 Thu Jan 01 00:00:18 1970 +0000
754 754 @@ -1,1 +1,2 @@
755 755 b
756 756 +b
757 757
758 758
759 759 f
760 760
761 761 $ hg record -d '19 0' -my <<EOF
762 762 > f
763 763 > EOF
764 764 diff --git a/subdir/f1 b/subdir/f1
765 765 1 hunks, 1 lines changed
766 766 examine changes to 'subdir/f1'? [Ynesfdaq?]
767 767
768 768 $ hg tip -p
769 769 changeset: 21:38ec577f126b
770 770 tag: tip
771 771 user: test
772 772 date: Thu Jan 01 00:00:19 1970 +0000
773 773 summary: y
774 774
775 775 diff -r b3df3dda369a -r 38ec577f126b subdir/f1
776 776 --- a/subdir/f1 Thu Jan 01 00:00:18 1970 +0000
777 777 +++ b/subdir/f1 Thu Jan 01 00:00:19 1970 +0000
778 778 @@ -1,1 +1,2 @@
779 779 a
780 780 +a
781 781
782 782
783 783 #if execbit
784 784
785 785 Preserve chmod +x
786 786
787 787 $ chmod +x f1
788 788 $ echo a >> f1
789 789 $ hg record -d '20 0' -mz <<EOF
790 790 > y
791 791 > y
792 792 > y
793 793 > EOF
794 794 diff --git a/subdir/f1 b/subdir/f1
795 795 old mode 100644
796 796 new mode 100755
797 797 1 hunks, 1 lines changed
798 798 examine changes to 'subdir/f1'? [Ynesfdaq?]
799 799 @@ -1,2 +1,3 @@
800 800 a
801 801 a
802 802 +a
803 803 record this change to 'subdir/f1'? [Ynesfdaq?]
804 804
805 805 $ hg tip --config diff.git=True -p
806 806 changeset: 22:3261adceb075
807 807 tag: tip
808 808 user: test
809 809 date: Thu Jan 01 00:00:20 1970 +0000
810 810 summary: z
811 811
812 812 diff --git a/subdir/f1 b/subdir/f1
813 813 old mode 100644
814 814 new mode 100755
815 815 --- a/subdir/f1
816 816 +++ b/subdir/f1
817 817 @@ -1,2 +1,3 @@
818 818 a
819 819 a
820 820 +a
821 821
822 822
823 823 Preserve execute permission on original
824 824
825 825 $ echo b >> f1
826 826 $ hg record -d '21 0' -maa <<EOF
827 827 > y
828 828 > y
829 829 > y
830 830 > EOF
831 831 diff --git a/subdir/f1 b/subdir/f1
832 832 1 hunks, 1 lines changed
833 833 examine changes to 'subdir/f1'? [Ynesfdaq?]
834 834 @@ -1,3 +1,4 @@
835 835 a
836 836 a
837 837 a
838 838 +b
839 839 record this change to 'subdir/f1'? [Ynesfdaq?]
840 840
841 841 $ hg tip --config diff.git=True -p
842 842 changeset: 23:b429867550db
843 843 tag: tip
844 844 user: test
845 845 date: Thu Jan 01 00:00:21 1970 +0000
846 846 summary: aa
847 847
848 848 diff --git a/subdir/f1 b/subdir/f1
849 849 --- a/subdir/f1
850 850 +++ b/subdir/f1
851 851 @@ -1,3 +1,4 @@
852 852 a
853 853 a
854 854 a
855 855 +b
856 856
857 857
858 858 Preserve chmod -x
859 859
860 860 $ chmod -x f1
861 861 $ echo c >> f1
862 862 $ hg record -d '22 0' -mab <<EOF
863 863 > y
864 864 > y
865 865 > y
866 866 > EOF
867 867 diff --git a/subdir/f1 b/subdir/f1
868 868 old mode 100755
869 869 new mode 100644
870 870 1 hunks, 1 lines changed
871 871 examine changes to 'subdir/f1'? [Ynesfdaq?]
872 872 @@ -2,3 +2,4 @@
873 873 a
874 874 a
875 875 b
876 876 +c
877 877 record this change to 'subdir/f1'? [Ynesfdaq?]
878 878
879 879 $ hg tip --config diff.git=True -p
880 880 changeset: 24:0b082130c20a
881 881 tag: tip
882 882 user: test
883 883 date: Thu Jan 01 00:00:22 1970 +0000
884 884 summary: ab
885 885
886 886 diff --git a/subdir/f1 b/subdir/f1
887 887 old mode 100755
888 888 new mode 100644
889 889 --- a/subdir/f1
890 890 +++ b/subdir/f1
891 891 @@ -2,3 +2,4 @@
892 892 a
893 893 a
894 894 b
895 895 +c
896 896
897 897
898 898 #else
899 899
900 900 Slightly bogus tests to get almost same repo structure as when x bit is used
901 901 - but with different hashes.
902 902
903 903 Mock "Preserve chmod +x"
904 904
905 905 $ echo a >> f1
906 906 $ hg record -d '20 0' -mz <<EOF
907 907 > y
908 908 > y
909 909 > y
910 910 > EOF
911 911 diff --git a/subdir/f1 b/subdir/f1
912 912 1 hunks, 1 lines changed
913 913 examine changes to 'subdir/f1'? [Ynesfdaq?]
914 914 @@ -1,2 +1,3 @@
915 915 a
916 916 a
917 917 +a
918 918 record this change to 'subdir/f1'? [Ynesfdaq?]
919 919
920 920 $ hg tip --config diff.git=True -p
921 921 changeset: 22:0d463bd428f5
922 922 tag: tip
923 923 user: test
924 924 date: Thu Jan 01 00:00:20 1970 +0000
925 925 summary: z
926 926
927 927 diff --git a/subdir/f1 b/subdir/f1
928 928 --- a/subdir/f1
929 929 +++ b/subdir/f1
930 930 @@ -1,2 +1,3 @@
931 931 a
932 932 a
933 933 +a
934 934
935 935
936 936 Mock "Preserve execute permission on original"
937 937
938 938 $ echo b >> f1
939 939 $ hg record -d '21 0' -maa <<EOF
940 940 > y
941 941 > y
942 942 > y
943 943 > EOF
944 944 diff --git a/subdir/f1 b/subdir/f1
945 945 1 hunks, 1 lines changed
946 946 examine changes to 'subdir/f1'? [Ynesfdaq?]
947 947 @@ -1,3 +1,4 @@
948 948 a
949 949 a
950 950 a
951 951 +b
952 952 record this change to 'subdir/f1'? [Ynesfdaq?]
953 953
954 954 $ hg tip --config diff.git=True -p
955 955 changeset: 23:0eab41a3e524
956 956 tag: tip
957 957 user: test
958 958 date: Thu Jan 01 00:00:21 1970 +0000
959 959 summary: aa
960 960
961 961 diff --git a/subdir/f1 b/subdir/f1
962 962 --- a/subdir/f1
963 963 +++ b/subdir/f1
964 964 @@ -1,3 +1,4 @@
965 965 a
966 966 a
967 967 a
968 968 +b
969 969
970 970
971 971 Mock "Preserve chmod -x"
972 972
973 973 $ chmod -x f1
974 974 $ echo c >> f1
975 975 $ hg record -d '22 0' -mab <<EOF
976 976 > y
977 977 > y
978 978 > y
979 979 > EOF
980 980 diff --git a/subdir/f1 b/subdir/f1
981 981 1 hunks, 1 lines changed
982 982 examine changes to 'subdir/f1'? [Ynesfdaq?]
983 983 @@ -2,3 +2,4 @@
984 984 a
985 985 a
986 986 b
987 987 +c
988 988 record this change to 'subdir/f1'? [Ynesfdaq?]
989 989
990 990 $ hg tip --config diff.git=True -p
991 991 changeset: 24:f4f718f27b7c
992 992 tag: tip
993 993 user: test
994 994 date: Thu Jan 01 00:00:22 1970 +0000
995 995 summary: ab
996 996
997 997 diff --git a/subdir/f1 b/subdir/f1
998 998 --- a/subdir/f1
999 999 +++ b/subdir/f1
1000 1000 @@ -2,3 +2,4 @@
1001 1001 a
1002 1002 a
1003 1003 b
1004 1004 +c
1005 1005
1006 1006
1007 1007 #endif
1008 1008
1009 1009 $ cd ..
1010 1010
1011 1011
1012 1012 Abort early when a merge is in progress
1013 1013
1014 1014 $ hg up 4
1015 1015 1 files updated, 0 files merged, 6 files removed, 0 files unresolved
1016 1016
1017 1017 $ touch iwillmergethat
1018 1018 $ hg add iwillmergethat
1019 1019
1020 1020 $ hg branch thatbranch
1021 1021 marked working directory as branch thatbranch
1022 1022 (branches are permanent and global, did you want a bookmark?)
1023 1023
1024 1024 $ hg ci -m'new head'
1025 1025
1026 1026 $ hg up default
1027 1027 6 files updated, 0 files merged, 2 files removed, 0 files unresolved
1028 1028
1029 1029 $ hg merge thatbranch
1030 1030 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1031 1031 (branch merge, don't forget to commit)
1032 1032
1033 1033 $ hg record -m'will abort'
1034 1034 abort: cannot partially commit a merge (use "hg commit" instead)
1035 1035 [255]
1036 1036
1037 1037 $ hg up -C
1038 1038 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1039 1039
1040 1040 Editing patch (and ignoring trailing text)
1041 1041
1042 1042 $ cat > editor.sh << '__EOF__'
1043 1043 > sed -e 7d -e '5s/^-/ /' -e '/^# ---/i\
1044 1044 > trailing\nditto' "$1" > tmp
1045 1045 > mv tmp "$1"
1046 1046 > __EOF__
1047 1047 $ cat > editedfile << '__EOF__'
1048 1048 > This is the first line
1049 1049 > This is the second line
1050 1050 > This is the third line
1051 1051 > __EOF__
1052 1052 $ hg add editedfile
1053 1053 $ hg commit -medit-patch-1
1054 1054 $ cat > editedfile << '__EOF__'
1055 1055 > This line has changed
1056 1056 > This change will be committed
1057 1057 > This is the third line
1058 1058 > __EOF__
1059 1059 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg record -d '23 0' -medit-patch-2 <<EOF
1060 1060 > y
1061 1061 > e
1062 1062 > EOF
1063 1063 diff --git a/editedfile b/editedfile
1064 1064 1 hunks, 2 lines changed
1065 1065 examine changes to 'editedfile'? [Ynesfdaq?]
1066 1066 @@ -1,3 +1,3 @@
1067 1067 -This is the first line
1068 1068 -This is the second line
1069 1069 +This line has changed
1070 1070 +This change will be committed
1071 1071 This is the third line
1072 1072 record this change to 'editedfile'? [Ynesfdaq?]
1073 1073 $ cat editedfile
1074 1074 This line has changed
1075 1075 This change will be committed
1076 1076 This is the third line
1077 1077 $ hg cat -r tip editedfile
1078 1078 This is the first line
1079 1079 This change will be committed
1080 1080 This is the third line
1081 1081 $ hg revert editedfile
1082 1082
1083 1083 Trying to edit patch for whole file
1084 1084
1085 1085 $ echo "This is the fourth line" >> editedfile
1086 1086 $ hg record <<EOF
1087 1087 > e
1088 1088 > q
1089 1089 > EOF
1090 1090 diff --git a/editedfile b/editedfile
1091 1091 1 hunks, 1 lines changed
1092 1092 examine changes to 'editedfile'? [Ynesfdaq?]
1093 1093 cannot edit patch for whole file
1094 1094 examine changes to 'editedfile'? [Ynesfdaq?]
1095 1095 abort: user quit
1096 1096 [255]
1097 1097 $ hg revert editedfile
1098 1098
1099 1099 Removing changes from patch
1100 1100
1101 1101 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1102 1102 $ mv tmp editedfile
1103 1103 $ echo "This line has been added" >> editedfile
1104 1104 $ cat > editor.sh << '__EOF__'
1105 1105 > sed -e 's/^[-+]/ /' "$1" > tmp
1106 1106 > mv tmp "$1"
1107 1107 > __EOF__
1108 1108 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg record <<EOF
1109 1109 > y
1110 1110 > e
1111 1111 > EOF
1112 1112 diff --git a/editedfile b/editedfile
1113 1113 1 hunks, 3 lines changed
1114 1114 examine changes to 'editedfile'? [Ynesfdaq?]
1115 1115 @@ -1,3 +1,3 @@
1116 1116 -This is the first line
1117 1117 -This change will be committed
1118 1118 -This is the third line
1119 1119 +This change will not be committed
1120 1120 +This is the second line
1121 1121 +This line has been added
1122 1122 record this change to 'editedfile'? [Ynesfdaq?]
1123 1123 no changes to record
1124 1124 $ cat editedfile
1125 1125 This change will not be committed
1126 1126 This is the second line
1127 1127 This line has been added
1128 1128 $ hg cat -r tip editedfile
1129 1129 This is the first line
1130 1130 This change will be committed
1131 1131 This is the third line
1132 1132 $ hg revert editedfile
1133 1133
1134 1134 Invalid patch
1135 1135
1136 1136 $ sed -e '3s/third/second/' -e '2s/will/will not/' -e 1d editedfile > tmp
1137 1137 $ mv tmp editedfile
1138 1138 $ echo "This line has been added" >> editedfile
1139 1139 $ cat > editor.sh << '__EOF__'
1140 1140 > sed s/This/That/ "$1" > tmp
1141 1141 > mv tmp "$1"
1142 1142 > __EOF__
1143 1143 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg record <<EOF
1144 1144 > y
1145 1145 > e
1146 1146 > EOF
1147 1147 diff --git a/editedfile b/editedfile
1148 1148 1 hunks, 3 lines changed
1149 1149 examine changes to 'editedfile'? [Ynesfdaq?]
1150 1150 @@ -1,3 +1,3 @@
1151 1151 -This is the first line
1152 1152 -This change will be committed
1153 1153 -This is the third line
1154 1154 +This change will not be committed
1155 1155 +This is the second line
1156 1156 +This line has been added
1157 1157 record this change to 'editedfile'? [Ynesfdaq?]
1158 1158 patching file editedfile
1159 1159 Hunk #1 FAILED at 0
1160 1160 1 out of 1 hunks FAILED -- saving rejects to file editedfile.rej
1161 1161 abort: patch failed to apply
1162 1162 [255]
1163 1163 $ cat editedfile
1164 1164 This change will not be committed
1165 1165 This is the second line
1166 1166 This line has been added
1167 1167 $ hg cat -r tip editedfile
1168 1168 This is the first line
1169 1169 This change will be committed
1170 1170 This is the third line
1171 1171 $ cat editedfile.rej
1172 1172 --- editedfile
1173 1173 +++ editedfile
1174 1174 @@ -1,3 +1,3 @@
1175 1175 -That is the first line
1176 1176 -That change will be committed
1177 1177 -That is the third line
1178 1178 +That change will not be committed
1179 1179 +That is the second line
1180 1180 +That line has been added
1181 1181
1182 1182 Malformed patch - error handling
1183 1183
1184 1184 $ cat > editor.sh << '__EOF__'
1185 1185 > sed -e '/^@/p' "$1" > tmp
1186 1186 > mv tmp "$1"
1187 1187 > __EOF__
1188 1188 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg record <<EOF
1189 1189 > y
1190 1190 > e
1191 1191 > EOF
1192 1192 diff --git a/editedfile b/editedfile
1193 1193 1 hunks, 3 lines changed
1194 1194 examine changes to 'editedfile'? [Ynesfdaq?]
1195 1195 @@ -1,3 +1,3 @@
1196 1196 -This is the first line
1197 1197 -This change will be committed
1198 1198 -This is the third line
1199 1199 +This change will not be committed
1200 1200 +This is the second line
1201 1201 +This line has been added
1202 1202 record this change to 'editedfile'? [Ynesfdaq?]
1203 1203 abort: error parsing patch: unhandled transition: range -> range
1204 1204 [255]
1205 1205
1206 1206 random text in random positions is still an error
1207 1207
1208 1208 $ cat > editor.sh << '__EOF__'
1209 1209 > sed -e '/^@/i\
1210 1210 > other' "$1" > tmp
1211 1211 > mv tmp "$1"
1212 1212 > __EOF__
1213 1213 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg record <<EOF
1214 1214 > y
1215 1215 > e
1216 1216 > EOF
1217 1217 diff --git a/editedfile b/editedfile
1218 1218 1 hunks, 3 lines changed
1219 1219 examine changes to 'editedfile'? [Ynesfdaq?]
1220 1220 @@ -1,3 +1,3 @@
1221 1221 -This is the first line
1222 1222 -This change will be committed
1223 1223 -This is the third line
1224 1224 +This change will not be committed
1225 1225 +This is the second line
1226 1226 +This line has been added
1227 1227 record this change to 'editedfile'? [Ynesfdaq?]
1228 1228 abort: error parsing patch: unhandled transition: file -> other
1229 1229 [255]
1230 1230
1231 1231 $ hg up -C
1232 1232 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1233 1233
1234 1234 With win32text
1235 1235
1236 1236 $ echo '[extensions]' >> .hg/hgrc
1237 1237 $ echo 'win32text = ' >> .hg/hgrc
1238 1238 $ echo '[decode]' >> .hg/hgrc
1239 1239 $ echo '** = cleverdecode:' >> .hg/hgrc
1240 1240 $ echo '[encode]' >> .hg/hgrc
1241 1241 $ echo '** = cleverencode:' >> .hg/hgrc
1242 1242 $ echo '[patch]' >> .hg/hgrc
1243 1243 $ echo 'eol = crlf' >> .hg/hgrc
1244 1244
1245 1245 Ignore win32text deprecation warning for now:
1246 1246
1247 1247 $ echo '[win32text]' >> .hg/hgrc
1248 1248 $ echo 'warn = no' >> .hg/hgrc
1249 1249
1250 1250 $ echo d >> subdir/f1
1251 1251 $ hg record -d '24 0' -mw1 <<EOF
1252 1252 > y
1253 1253 > y
1254 1254 > EOF
1255 1255 diff --git a/subdir/f1 b/subdir/f1
1256 1256 1 hunks, 1 lines changed
1257 1257 examine changes to 'subdir/f1'? [Ynesfdaq?]
1258 1258 @@ -3,3 +3,4 @@
1259 1259 a
1260 1260 b
1261 1261 c
1262 1262 +d
1263 1263 record this change to 'subdir/f1'? [Ynesfdaq?]
1264 1264
1265 1265 $ hg tip -p
1266 1266 changeset: 28:* (glob)
1267 1267 tag: tip
1268 1268 user: test
1269 1269 date: Thu Jan 01 00:00:24 1970 +0000
1270 1270 summary: w1
1271 1271
1272 1272 diff -r ???????????? -r ???????????? subdir/f1 (glob)
1273 1273 --- a/subdir/f1 Thu Jan 01 00:00:23 1970 +0000
1274 1274 +++ b/subdir/f1 Thu Jan 01 00:00:24 1970 +0000
1275 1275 @@ -3,3 +3,4 @@
1276 1276 a
1277 1277 b
1278 1278 c
1279 1279 +d
1280 1280
1281 1281 Test --user when ui.username not set
1282 1282 $ unset HGUSER
1283 1283 $ echo e >> subdir/f1
1284 1284 $ hg record --config ui.username= -d '8 0' --user xyz -m "user flag" <<EOF
1285 1285 > y
1286 1286 > y
1287 1287 > EOF
1288 1288 diff --git a/subdir/f1 b/subdir/f1
1289 1289 1 hunks, 1 lines changed
1290 1290 examine changes to 'subdir/f1'? [Ynesfdaq?]
1291 1291 @@ -4,3 +4,4 @@
1292 1292 b
1293 1293 c
1294 1294 d
1295 1295 +e
1296 1296 record this change to 'subdir/f1'? [Ynesfdaq?]
1297 1297 $ hg log --template '{author}\n' -l 1
1298 1298 xyz
1299 1299 $ HGUSER="test"
1300 1300 $ export HGUSER
1301 1301
1302 1302 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now