##// END OF EJS Templates
ui: log non-interactive default response to stdout when verbose...
Peter Arrenbrecht -
r7320:8dca507e default
parent child Browse files
Show More
@@ -1,484 +1,486 b''
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
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import errno, getpass, os, re, socket, sys, tempfile
10 10 import ConfigParser, traceback, util
11 11
12 12 def dupconfig(orig):
13 13 new = util.configparser(orig.defaults())
14 14 updateconfig(orig, new)
15 15 return new
16 16
17 17 def updateconfig(source, dest, sections=None):
18 18 if not sections:
19 19 sections = source.sections()
20 20 for section in sections:
21 21 if not dest.has_section(section):
22 22 dest.add_section(section)
23 23 for name, value in source.items(section, raw=True):
24 24 dest.set(section, name, value)
25 25
26 26 class ui(object):
27 27 _isatty = None
28 28
29 29 def __init__(self, verbose=False, debug=False, quiet=False,
30 30 interactive=True, traceback=False, report_untrusted=True,
31 31 parentui=None):
32 32 self.overlay = None
33 33 self.buffers = []
34 34 if parentui is None:
35 35 # this is the parent of all ui children
36 36 self.parentui = None
37 37 self.quiet = quiet
38 38 self.verbose = verbose
39 39 self.debugflag = debug
40 40 self.interactive = interactive
41 41 self.traceback = traceback
42 42 self.report_untrusted = report_untrusted
43 43 self.trusted_users = {}
44 44 self.trusted_groups = {}
45 45 # if ucdata is not None, its keys must be a superset of cdata's
46 46 self.cdata = util.configparser()
47 47 self.ucdata = None
48 48 # we always trust global config files
49 49 self.check_trusted = False
50 50 self.readconfig(util.rcpath())
51 51 self.check_trusted = True
52 52 self.updateopts(verbose, debug, quiet, interactive)
53 53 else:
54 54 # parentui may point to an ui object which is already a child
55 55 self.parentui = parentui.parentui or parentui
56 56 self.trusted_users = parentui.trusted_users.copy()
57 57 self.trusted_groups = parentui.trusted_groups.copy()
58 58 self.cdata = dupconfig(self.parentui.cdata)
59 59 if self.parentui.ucdata:
60 60 self.ucdata = dupconfig(self.parentui.ucdata)
61 61 if self.parentui.overlay:
62 62 self.overlay = dupconfig(self.parentui.overlay)
63 63 if self.parentui is not parentui and parentui.overlay is not None:
64 64 if self.overlay is None:
65 65 self.overlay = util.configparser()
66 66 updateconfig(parentui.overlay, self.overlay)
67 67 self.buffers = parentui.buffers
68 68
69 69 def __getattr__(self, key):
70 70 return getattr(self.parentui, key)
71 71
72 72 def isatty(self):
73 73 if ui._isatty is None:
74 74 ui._isatty = sys.stdin.isatty()
75 75 return ui._isatty
76 76
77 77 def updateopts(self, verbose=False, debug=False, quiet=False,
78 78 interactive=True, traceback=False, config=[]):
79 79 for section, name, value in config:
80 80 self.setconfig(section, name, value)
81 81
82 82 if quiet or verbose or debug:
83 83 self.setconfig('ui', 'quiet', str(bool(quiet)))
84 84 self.setconfig('ui', 'verbose', str(bool(verbose)))
85 85 self.setconfig('ui', 'debug', str(bool(debug)))
86 86
87 87 self.verbosity_constraints()
88 88
89 89 if not interactive:
90 90 self.setconfig('ui', 'interactive', 'False')
91 91 self.interactive = False
92 92
93 93 self.traceback = self.traceback or traceback
94 94
95 95 def verbosity_constraints(self):
96 96 self.quiet = self.configbool('ui', 'quiet')
97 97 self.verbose = self.configbool('ui', 'verbose')
98 98 self.debugflag = self.configbool('ui', 'debug')
99 99
100 100 if self.debugflag:
101 101 self.verbose = True
102 102 self.quiet = False
103 103 elif self.verbose and self.quiet:
104 104 self.quiet = self.verbose = False
105 105
106 106 def _is_trusted(self, fp, f, warn=True):
107 107 if not self.check_trusted:
108 108 return True
109 109 st = util.fstat(fp)
110 110 if util.isowner(fp, st):
111 111 return True
112 112 tusers = self.trusted_users
113 113 tgroups = self.trusted_groups
114 114 if not tusers:
115 115 user = util.username()
116 116 if user is not None:
117 117 self.trusted_users[user] = 1
118 118 self.fixconfig(section='trusted')
119 119 if (tusers or tgroups) and '*' not in tusers and '*' not in tgroups:
120 120 user = util.username(st.st_uid)
121 121 group = util.groupname(st.st_gid)
122 122 if user not in tusers and group not in tgroups:
123 123 if warn and self.report_untrusted:
124 124 self.warn(_('Not trusting file %s from untrusted '
125 125 'user %s, group %s\n') % (f, user, group))
126 126 return False
127 127 return True
128 128
129 129 def readconfig(self, fn, root=None):
130 130 if isinstance(fn, basestring):
131 131 fn = [fn]
132 132 for f in fn:
133 133 try:
134 134 fp = open(f)
135 135 except IOError:
136 136 continue
137 137 cdata = self.cdata
138 138 trusted = self._is_trusted(fp, f)
139 139 if not trusted:
140 140 if self.ucdata is None:
141 141 self.ucdata = dupconfig(self.cdata)
142 142 cdata = self.ucdata
143 143 elif self.ucdata is not None:
144 144 # use a separate configparser, so that we don't accidentally
145 145 # override ucdata settings later on.
146 146 cdata = util.configparser()
147 147
148 148 try:
149 149 cdata.readfp(fp, f)
150 150 except ConfigParser.ParsingError, inst:
151 151 msg = _("Failed to parse %s\n%s") % (f, inst)
152 152 if trusted:
153 153 raise util.Abort(msg)
154 154 self.warn(_("Ignored: %s\n") % msg)
155 155
156 156 if trusted:
157 157 if cdata != self.cdata:
158 158 updateconfig(cdata, self.cdata)
159 159 if self.ucdata is not None:
160 160 updateconfig(cdata, self.ucdata)
161 161 # override data from config files with data set with ui.setconfig
162 162 if self.overlay:
163 163 updateconfig(self.overlay, self.cdata)
164 164 if root is None:
165 165 root = os.path.expanduser('~')
166 166 self.fixconfig(root=root)
167 167
168 168 def readsections(self, filename, *sections):
169 169 """Read filename and add only the specified sections to the config data
170 170
171 171 The settings are added to the trusted config data.
172 172 """
173 173 if not sections:
174 174 return
175 175
176 176 cdata = util.configparser()
177 177 try:
178 178 try:
179 179 fp = open(filename)
180 180 except IOError, inst:
181 181 raise util.Abort(_("unable to open %s: %s") %
182 182 (filename, getattr(inst, "strerror", inst)))
183 183 try:
184 184 cdata.readfp(fp, filename)
185 185 finally:
186 186 fp.close()
187 187 except ConfigParser.ParsingError, inst:
188 188 raise util.Abort(_("failed to parse %s\n%s") % (filename, inst))
189 189
190 190 for section in sections:
191 191 if not cdata.has_section(section):
192 192 cdata.add_section(section)
193 193
194 194 updateconfig(cdata, self.cdata, sections)
195 195 if self.ucdata:
196 196 updateconfig(cdata, self.ucdata, sections)
197 197
198 198 def fixconfig(self, section=None, name=None, value=None, root=None):
199 199 # translate paths relative to root (or home) into absolute paths
200 200 if section is None or section == 'paths':
201 201 if root is None:
202 202 root = os.getcwd()
203 203 items = section and [(name, value)] or []
204 204 for cdata in self.cdata, self.ucdata, self.overlay:
205 205 if not cdata: continue
206 206 if not items and cdata.has_section('paths'):
207 207 pathsitems = cdata.items('paths')
208 208 else:
209 209 pathsitems = items
210 210 for n, path in pathsitems:
211 211 if path and "://" not in path and not os.path.isabs(path):
212 212 cdata.set("paths", n,
213 213 os.path.normpath(os.path.join(root, path)))
214 214
215 215 # update verbosity/interactive/report_untrusted settings
216 216 if section is None or section == 'ui':
217 217 if name is None or name in ('quiet', 'verbose', 'debug'):
218 218 self.verbosity_constraints()
219 219 if name is None or name == 'interactive':
220 220 interactive = self.configbool("ui", "interactive", None)
221 221 if interactive is None and self.interactive:
222 222 self.interactive = self.isatty()
223 223 else:
224 224 self.interactive = interactive
225 225 if name is None or name == 'report_untrusted':
226 226 self.report_untrusted = (
227 227 self.configbool("ui", "report_untrusted", True))
228 228
229 229 # update trust information
230 230 if (section is None or section == 'trusted') and self.trusted_users:
231 231 for user in self.configlist('trusted', 'users'):
232 232 self.trusted_users[user] = 1
233 233 for group in self.configlist('trusted', 'groups'):
234 234 self.trusted_groups[group] = 1
235 235
236 236 def setconfig(self, section, name, value):
237 237 if not self.overlay:
238 238 self.overlay = util.configparser()
239 239 for cdata in (self.overlay, self.cdata, self.ucdata):
240 240 if not cdata: continue
241 241 if not cdata.has_section(section):
242 242 cdata.add_section(section)
243 243 cdata.set(section, name, value)
244 244 self.fixconfig(section, name, value)
245 245
246 246 def _get_cdata(self, untrusted):
247 247 if untrusted and self.ucdata:
248 248 return self.ucdata
249 249 return self.cdata
250 250
251 251 def _config(self, section, name, default, funcname, untrusted, abort):
252 252 cdata = self._get_cdata(untrusted)
253 253 if cdata.has_option(section, name):
254 254 try:
255 255 func = getattr(cdata, funcname)
256 256 return func(section, name)
257 257 except (ConfigParser.InterpolationError, ValueError), inst:
258 258 msg = _("Error in configuration section [%s] "
259 259 "parameter '%s':\n%s") % (section, name, inst)
260 260 if abort:
261 261 raise util.Abort(msg)
262 262 self.warn(_("Ignored: %s\n") % msg)
263 263 return default
264 264
265 265 def _configcommon(self, section, name, default, funcname, untrusted):
266 266 value = self._config(section, name, default, funcname,
267 267 untrusted, abort=True)
268 268 if self.debugflag and not untrusted and self.ucdata:
269 269 uvalue = self._config(section, name, None, funcname,
270 270 untrusted=True, abort=False)
271 271 if uvalue is not None and uvalue != value:
272 272 self.warn(_("Ignoring untrusted configuration option "
273 273 "%s.%s = %s\n") % (section, name, uvalue))
274 274 return value
275 275
276 276 def config(self, section, name, default=None, untrusted=False):
277 277 return self._configcommon(section, name, default, 'get', untrusted)
278 278
279 279 def configbool(self, section, name, default=False, untrusted=False):
280 280 return self._configcommon(section, name, default, 'getboolean',
281 281 untrusted)
282 282
283 283 def configlist(self, section, name, default=None, untrusted=False):
284 284 """Return a list of comma/space separated strings"""
285 285 result = self.config(section, name, untrusted=untrusted)
286 286 if result is None:
287 287 result = default or []
288 288 if isinstance(result, basestring):
289 289 result = result.replace(",", " ").split()
290 290 return result
291 291
292 292 def has_section(self, section, untrusted=False):
293 293 '''tell whether section exists in config.'''
294 294 cdata = self._get_cdata(untrusted)
295 295 return cdata.has_section(section)
296 296
297 297 def _configitems(self, section, untrusted, abort):
298 298 items = {}
299 299 cdata = self._get_cdata(untrusted)
300 300 if cdata.has_section(section):
301 301 try:
302 302 items.update(dict(cdata.items(section)))
303 303 except ConfigParser.InterpolationError, inst:
304 304 msg = _("Error in configuration section [%s]:\n"
305 305 "%s") % (section, inst)
306 306 if abort:
307 307 raise util.Abort(msg)
308 308 self.warn(_("Ignored: %s\n") % msg)
309 309 return items
310 310
311 311 def configitems(self, section, untrusted=False):
312 312 items = self._configitems(section, untrusted=untrusted, abort=True)
313 313 if self.debugflag and not untrusted and self.ucdata:
314 314 uitems = self._configitems(section, untrusted=True, abort=False)
315 315 for k in util.sort(uitems):
316 316 if uitems[k] != items.get(k):
317 317 self.warn(_("Ignoring untrusted configuration option "
318 318 "%s.%s = %s\n") % (section, k, uitems[k]))
319 319 return util.sort(items.items())
320 320
321 321 def walkconfig(self, untrusted=False):
322 322 cdata = self._get_cdata(untrusted)
323 323 sections = cdata.sections()
324 324 sections.sort()
325 325 for section in sections:
326 326 for name, value in self.configitems(section, untrusted):
327 327 yield section, name, str(value).replace('\n', '\\n')
328 328
329 329 def username(self):
330 330 """Return default username to be used in commits.
331 331
332 332 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
333 333 and stop searching if one of these is set.
334 334 If not found and ui.askusername is True, ask the user, else use
335 335 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
336 336 """
337 337 user = os.environ.get("HGUSER")
338 338 if user is None:
339 339 user = self.config("ui", "username")
340 340 if user is None:
341 341 user = os.environ.get("EMAIL")
342 342 if user is None and self.configbool("ui", "askusername"):
343 343 user = self.prompt(_("Enter a commit username:"), default=None)
344 344 if user is None:
345 345 try:
346 346 user = '%s@%s' % (util.getuser(), socket.getfqdn())
347 347 self.warn(_("No username found, using '%s' instead\n") % user)
348 348 except KeyError:
349 349 pass
350 350 if not user:
351 351 raise util.Abort(_("Please specify a username."))
352 352 if "\n" in user:
353 353 raise util.Abort(_("username %s contains a newline\n") % `user`)
354 354 return user
355 355
356 356 def shortuser(self, user):
357 357 """Return a short representation of a user name or email address."""
358 358 if not self.verbose: user = util.shortuser(user)
359 359 return user
360 360
361 361 def expandpath(self, loc, default=None):
362 362 """Return repository location relative to cwd or from [paths]"""
363 363 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
364 364 return loc
365 365
366 366 path = self.config("paths", loc)
367 367 if not path and default is not None:
368 368 path = self.config("paths", default)
369 369 return path or loc
370 370
371 371 def pushbuffer(self):
372 372 self.buffers.append([])
373 373
374 374 def popbuffer(self):
375 375 return "".join(self.buffers.pop())
376 376
377 377 def write(self, *args):
378 378 if self.buffers:
379 379 self.buffers[-1].extend([str(a) for a in args])
380 380 else:
381 381 for a in args:
382 382 sys.stdout.write(str(a))
383 383
384 384 def write_err(self, *args):
385 385 try:
386 386 if not sys.stdout.closed: sys.stdout.flush()
387 387 for a in args:
388 388 sys.stderr.write(str(a))
389 389 # stderr may be buffered under win32 when redirected to files,
390 390 # including stdout.
391 391 if not sys.stderr.closed: sys.stderr.flush()
392 392 except IOError, inst:
393 393 if inst.errno != errno.EPIPE:
394 394 raise
395 395
396 396 def flush(self):
397 397 try: sys.stdout.flush()
398 398 except: pass
399 399 try: sys.stderr.flush()
400 400 except: pass
401 401
402 402 def _readline(self, prompt=''):
403 403 if self.isatty():
404 404 try:
405 405 # magically add command line editing support, where
406 406 # available
407 407 import readline
408 408 # force demandimport to really load the module
409 409 readline.read_history_file
410 410 except ImportError:
411 411 pass
412 412 line = raw_input(prompt)
413 413 # When stdin is in binary mode on Windows, it can cause
414 414 # raw_input() to emit an extra trailing carriage return
415 415 if os.linesep == '\r\n' and line and line[-1] == '\r':
416 416 line = line[:-1]
417 417 return line
418 418
419 419 def prompt(self, msg, pat=None, default="y"):
420 420 """Prompt user with msg, read response, and ensure it matches pat
421 421
422 422 If not interactive -- the default is returned
423 423 """
424 if not self.interactive: return default
424 if not self.interactive:
425 self.note(msg, ' ', default, "\n")
426 return default
425 427 while True:
426 428 try:
427 429 r = self._readline(msg + ' ')
428 430 if not r:
429 431 return default
430 432 if not pat or re.match(pat, r):
431 433 return r
432 434 else:
433 435 self.write(_("unrecognized response\n"))
434 436 except EOFError:
435 437 raise util.Abort(_('response expected'))
436 438
437 439 def getpass(self, prompt=None, default=None):
438 440 if not self.interactive: return default
439 441 return getpass.getpass(prompt or _('password: '))
440 442 def status(self, *msg):
441 443 if not self.quiet: self.write(*msg)
442 444 def warn(self, *msg):
443 445 self.write_err(*msg)
444 446 def note(self, *msg):
445 447 if self.verbose: self.write(*msg)
446 448 def debug(self, *msg):
447 449 if self.debugflag: self.write(*msg)
448 450 def edit(self, text, user):
449 451 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
450 452 text=True)
451 453 try:
452 454 f = os.fdopen(fd, "w")
453 455 f.write(text)
454 456 f.close()
455 457
456 458 editor = self.geteditor()
457 459
458 460 util.system("%s \"%s\"" % (editor, name),
459 461 environ={'HGUSER': user},
460 462 onerr=util.Abort, errprefix=_("edit failed"))
461 463
462 464 f = open(name)
463 465 t = f.read()
464 466 f.close()
465 467 t = re.sub("(?m)^HG:.*\n", "", t)
466 468 finally:
467 469 os.unlink(name)
468 470
469 471 return t
470 472
471 473 def print_exc(self):
472 474 '''print exception traceback if traceback printing enabled.
473 475 only to call in exception handler. returns true if traceback
474 476 printed.'''
475 477 if self.traceback:
476 478 traceback.print_exc()
477 479 return self.traceback
478 480
479 481 def geteditor(self):
480 482 '''return editor to use'''
481 483 return (os.environ.get("HGEDITOR") or
482 484 self.config("ui", "editor") or
483 485 os.environ.get("VISUAL") or
484 486 os.environ.get("EDITOR", "vi"))
@@ -1,23 +1,27 b''
1 1 adding a
2 2 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 3 created new head
4 4 resolving manifests
5 5 overwrite None partial False
6 6 ancestor c334dc3be0da local 521a1e40188f+ remote 3574f3e69b1c
7 7 searching for copies back to rev 1
8 conflicting flags for a
9 (n)one, e(x)ec or sym(l)ink? n
8 10 a: update permissions -> e
9 11 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 12 (branch merge, don't forget to commit)
11 13 % symlink is local parent, executable is other
12 14 a has no flags (default for conflicts)
13 15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 16 resolving manifests
15 17 overwrite None partial False
16 18 ancestor c334dc3be0da local 3574f3e69b1c+ remote 521a1e40188f
17 19 searching for copies back to rev 1
20 conflicting flags for a
21 (n)one, e(x)ec or sym(l)ink? n
18 22 a: remote is newer -> g
19 23 getting a
20 24 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 25 (branch merge, don't forget to commit)
22 26 % symlink is other parent, executable is local
23 27 a has no flags (default for conflicts)
@@ -1,596 +1,600 b''
1 1 created new head
2 2 --------------
3 3 test L:up a R:nc a b W: - 1 get local a to b
4 4 --------------
5 5 resolving manifests
6 6 overwrite None partial False
7 7 ancestor 924404dff337 local e300d1c794ec+ remote 735846fee2d7
8 8 searching for copies back to rev 1
9 9 unmatched files in other:
10 10 b
11 11 all copies found (* = to merge, ! = divergent):
12 12 b -> a *
13 13 checking for directory renames
14 14 rev: versions differ -> m
15 15 a: remote copied to b -> m
16 16 preserving a for resolve of b
17 17 preserving rev for resolve of rev
18 18 picked tool 'python ../merge' for b (binary False symlink False)
19 19 merging a and b to b
20 20 my b@e300d1c794ec+ other b@735846fee2d7 ancestor a@924404dff337
21 21 premerge successful
22 22 picked tool 'python ../merge' for rev (binary False symlink False)
23 23 merging rev
24 24 my rev@e300d1c794ec+ other rev@735846fee2d7 ancestor rev@924404dff337
25 25 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
26 26 (branch merge, don't forget to commit)
27 27 --------------
28 28 M b
29 29 a
30 30 C a
31 31 --------------
32 32
33 33 created new head
34 34 --------------
35 35 test L:nc a b R:up a W: - 2 get rem change to a and b
36 36 --------------
37 37 resolving manifests
38 38 overwrite None partial False
39 39 ancestor 924404dff337 local ac809aeed39a+ remote f4db7e329e71
40 40 searching for copies back to rev 1
41 41 unmatched files in local:
42 42 b
43 43 all copies found (* = to merge, ! = divergent):
44 44 b -> a *
45 45 checking for directory renames
46 46 a: remote is newer -> g
47 47 b: local copied to a -> m
48 48 rev: versions differ -> m
49 49 preserving b for resolve of b
50 50 preserving rev for resolve of rev
51 51 getting a
52 52 picked tool 'python ../merge' for b (binary False symlink False)
53 53 merging b and a to b
54 54 my b@ac809aeed39a+ other a@f4db7e329e71 ancestor a@924404dff337
55 55 premerge successful
56 56 picked tool 'python ../merge' for rev (binary False symlink False)
57 57 merging rev
58 58 my rev@ac809aeed39a+ other rev@f4db7e329e71 ancestor rev@924404dff337
59 59 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
60 60 (branch merge, don't forget to commit)
61 61 --------------
62 62 M a
63 63 M b
64 64 a
65 65 --------------
66 66
67 67 created new head
68 68 --------------
69 69 test L:up a R:nm a b W: - 3 get local a change to b, remove a
70 70 --------------
71 71 resolving manifests
72 72 overwrite None partial False
73 73 ancestor 924404dff337 local e300d1c794ec+ remote e03727d2d66b
74 74 searching for copies back to rev 1
75 75 unmatched files in other:
76 76 b
77 77 all copies found (* = to merge, ! = divergent):
78 78 b -> a *
79 79 checking for directory renames
80 80 rev: versions differ -> m
81 81 a: remote moved to b -> m
82 82 preserving a for resolve of b
83 83 preserving rev for resolve of rev
84 84 removing a
85 85 picked tool 'python ../merge' for b (binary False symlink False)
86 86 merging a and b to b
87 87 my b@e300d1c794ec+ other b@e03727d2d66b ancestor a@924404dff337
88 88 premerge successful
89 89 picked tool 'python ../merge' for rev (binary False symlink False)
90 90 merging rev
91 91 my rev@e300d1c794ec+ other rev@e03727d2d66b ancestor rev@924404dff337
92 92 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
93 93 (branch merge, don't forget to commit)
94 94 --------------
95 95 M b
96 96 a
97 97 --------------
98 98
99 99 created new head
100 100 --------------
101 101 test L:nm a b R:up a W: - 4 get remote change to b
102 102 --------------
103 103 resolving manifests
104 104 overwrite None partial False
105 105 ancestor 924404dff337 local ecf3cb2a4219+ remote f4db7e329e71
106 106 searching for copies back to rev 1
107 107 unmatched files in local:
108 108 b
109 109 all copies found (* = to merge, ! = divergent):
110 110 b -> a *
111 111 checking for directory renames
112 112 b: local moved to a -> m
113 113 rev: versions differ -> m
114 114 preserving b for resolve of b
115 115 preserving rev for resolve of rev
116 116 picked tool 'python ../merge' for b (binary False symlink False)
117 117 merging b and a to b
118 118 my b@ecf3cb2a4219+ other a@f4db7e329e71 ancestor a@924404dff337
119 119 premerge successful
120 120 picked tool 'python ../merge' for rev (binary False symlink False)
121 121 merging rev
122 122 my rev@ecf3cb2a4219+ other rev@f4db7e329e71 ancestor rev@924404dff337
123 123 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
124 124 (branch merge, don't forget to commit)
125 125 --------------
126 126 M b
127 127 a
128 128 --------------
129 129
130 130 created new head
131 131 --------------
132 132 test L: R:nc a b W: - 5 get b
133 133 --------------
134 134 resolving manifests
135 135 overwrite None partial False
136 136 ancestor 924404dff337 local 94b33a1b7f2d+ remote 735846fee2d7
137 137 searching for copies back to rev 1
138 138 unmatched files in other:
139 139 b
140 140 all copies found (* = to merge, ! = divergent):
141 141 b -> a
142 142 checking for directory renames
143 143 rev: versions differ -> m
144 144 b: remote created -> g
145 145 preserving rev for resolve of rev
146 146 getting b
147 147 picked tool 'python ../merge' for rev (binary False symlink False)
148 148 merging rev
149 149 my rev@94b33a1b7f2d+ other rev@735846fee2d7 ancestor rev@924404dff337
150 150 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 151 (branch merge, don't forget to commit)
152 152 --------------
153 153 M b
154 154 C a
155 155 --------------
156 156
157 157 created new head
158 158 --------------
159 159 test L:nc a b R: W: - 6 nothing
160 160 --------------
161 161 resolving manifests
162 162 overwrite None partial False
163 163 ancestor 924404dff337 local ac809aeed39a+ remote 97c705ade336
164 164 searching for copies back to rev 1
165 165 unmatched files in local:
166 166 b
167 167 all copies found (* = to merge, ! = divergent):
168 168 b -> a
169 169 checking for directory renames
170 170 rev: versions differ -> m
171 171 preserving rev for resolve of rev
172 172 picked tool 'python ../merge' for rev (binary False symlink False)
173 173 merging rev
174 174 my rev@ac809aeed39a+ other rev@97c705ade336 ancestor rev@924404dff337
175 175 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
176 176 (branch merge, don't forget to commit)
177 177 --------------
178 178 C a
179 179 C b
180 180 --------------
181 181
182 182 created new head
183 183 --------------
184 184 test L: R:nm a b W: - 7 get b
185 185 --------------
186 186 resolving manifests
187 187 overwrite None partial False
188 188 ancestor 924404dff337 local 94b33a1b7f2d+ remote e03727d2d66b
189 189 searching for copies back to rev 1
190 190 unmatched files in other:
191 191 b
192 192 all copies found (* = to merge, ! = divergent):
193 193 b -> a
194 194 checking for directory renames
195 195 a: other deleted -> r
196 196 rev: versions differ -> m
197 197 b: remote created -> g
198 198 preserving rev for resolve of rev
199 199 removing a
200 200 getting b
201 201 picked tool 'python ../merge' for rev (binary False symlink False)
202 202 merging rev
203 203 my rev@94b33a1b7f2d+ other rev@e03727d2d66b ancestor rev@924404dff337
204 204 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
205 205 (branch merge, don't forget to commit)
206 206 --------------
207 207 M b
208 208 --------------
209 209
210 210 created new head
211 211 --------------
212 212 test L:nm a b R: W: - 8 nothing
213 213 --------------
214 214 resolving manifests
215 215 overwrite None partial False
216 216 ancestor 924404dff337 local ecf3cb2a4219+ remote 97c705ade336
217 217 searching for copies back to rev 1
218 218 unmatched files in local:
219 219 b
220 220 all copies found (* = to merge, ! = divergent):
221 221 b -> a
222 222 checking for directory renames
223 223 rev: versions differ -> m
224 224 preserving rev for resolve of rev
225 225 picked tool 'python ../merge' for rev (binary False symlink False)
226 226 merging rev
227 227 my rev@ecf3cb2a4219+ other rev@97c705ade336 ancestor rev@924404dff337
228 228 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
229 229 (branch merge, don't forget to commit)
230 230 --------------
231 231 C b
232 232 --------------
233 233
234 234 created new head
235 235 --------------
236 236 test L:um a b R:um a b W: - 9 do merge with ancestor in a
237 237 --------------
238 238 resolving manifests
239 239 overwrite None partial False
240 240 ancestor 924404dff337 local ec03c2ca8642+ remote 79cc6877a3b7
241 241 searching for copies back to rev 1
242 242 b: versions differ -> m
243 243 rev: versions differ -> m
244 244 preserving b for resolve of b
245 245 preserving rev for resolve of rev
246 246 picked tool 'python ../merge' for b (binary False symlink False)
247 247 merging b
248 248 my b@ec03c2ca8642+ other b@79cc6877a3b7 ancestor a@924404dff337
249 249 picked tool 'python ../merge' for rev (binary False symlink False)
250 250 merging rev
251 251 my rev@ec03c2ca8642+ other rev@79cc6877a3b7 ancestor rev@924404dff337
252 252 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
253 253 (branch merge, don't forget to commit)
254 254 --------------
255 255 M b
256 256 --------------
257 257
258 258 created new head
259 259 --------------
260 260 test L:nm a b R:nm a c W: - 11 get c, keep b
261 261 --------------
262 262 resolving manifests
263 263 overwrite None partial False
264 264 ancestor 924404dff337 local ecf3cb2a4219+ remote e6abcc1a30c2
265 265 searching for copies back to rev 1
266 266 unmatched files in local:
267 267 b
268 268 unmatched files in other:
269 269 c
270 270 all copies found (* = to merge, ! = divergent):
271 271 c -> a !
272 272 b -> a !
273 273 checking for directory renames
274 274 a: divergent renames -> dr
275 275 rev: versions differ -> m
276 276 c: remote created -> g
277 277 preserving rev for resolve of rev
278 278 warning: detected divergent renames of a to:
279 279 b
280 280 c
281 281 getting c
282 282 picked tool 'python ../merge' for rev (binary False symlink False)
283 283 merging rev
284 284 my rev@ecf3cb2a4219+ other rev@e6abcc1a30c2 ancestor rev@924404dff337
285 285 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
286 286 (branch merge, don't forget to commit)
287 287 --------------
288 288 M c
289 289 C b
290 290 --------------
291 291
292 292 created new head
293 293 --------------
294 294 test L:nc a b R:up b W: - 12 merge b no ancestor
295 295 --------------
296 296 resolving manifests
297 297 overwrite None partial False
298 298 ancestor 924404dff337 local ac809aeed39a+ remote af30c7647fc7
299 299 searching for copies back to rev 1
300 300 b: versions differ -> m
301 301 rev: versions differ -> m
302 302 preserving b for resolve of b
303 303 preserving rev for resolve of rev
304 304 picked tool 'python ../merge' for b (binary False symlink False)
305 305 merging b
306 306 my b@ac809aeed39a+ other b@af30c7647fc7 ancestor b@000000000000
307 307 picked tool 'python ../merge' for rev (binary False symlink False)
308 308 merging rev
309 309 my rev@ac809aeed39a+ other rev@af30c7647fc7 ancestor rev@924404dff337
310 310 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
311 311 (branch merge, don't forget to commit)
312 312 --------------
313 313 M b
314 314 C a
315 315 --------------
316 316
317 317 created new head
318 318 --------------
319 319 test L:up b R:nm a b W: - 13 merge b no ancestor
320 320 --------------
321 321 resolving manifests
322 322 overwrite None partial False
323 323 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
324 324 searching for copies back to rev 1
325 325 a: other deleted -> r
326 326 b: versions differ -> m
327 327 rev: versions differ -> m
328 328 preserving b for resolve of b
329 329 preserving rev for resolve of rev
330 330 removing a
331 331 picked tool 'python ../merge' for b (binary False symlink False)
332 332 merging b
333 333 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
334 334 picked tool 'python ../merge' for rev (binary False symlink False)
335 335 merging rev
336 336 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
337 337 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
338 338 (branch merge, don't forget to commit)
339 339 --------------
340 340 M b
341 341 --------------
342 342
343 343 created new head
344 344 --------------
345 345 test L:nc a b R:up a b W: - 14 merge b no ancestor
346 346 --------------
347 347 resolving manifests
348 348 overwrite None partial False
349 349 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
350 350 searching for copies back to rev 1
351 351 a: remote is newer -> g
352 352 b: versions differ -> m
353 353 rev: versions differ -> m
354 354 preserving b for resolve of b
355 355 preserving rev for resolve of rev
356 356 getting a
357 357 picked tool 'python ../merge' for b (binary False symlink False)
358 358 merging b
359 359 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
360 360 picked tool 'python ../merge' for rev (binary False symlink False)
361 361 merging rev
362 362 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
363 363 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
364 364 (branch merge, don't forget to commit)
365 365 --------------
366 366 M a
367 367 M b
368 368 --------------
369 369
370 370 created new head
371 371 --------------
372 372 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
373 373 --------------
374 374 resolving manifests
375 375 overwrite None partial False
376 376 ancestor 924404dff337 local 59318016310c+ remote e03727d2d66b
377 377 searching for copies back to rev 1
378 378 a: other deleted -> r
379 379 b: versions differ -> m
380 380 rev: versions differ -> m
381 381 preserving b for resolve of b
382 382 preserving rev for resolve of rev
383 383 removing a
384 384 picked tool 'python ../merge' for b (binary False symlink False)
385 385 merging b
386 386 my b@59318016310c+ other b@e03727d2d66b ancestor b@000000000000
387 387 picked tool 'python ../merge' for rev (binary False symlink False)
388 388 merging rev
389 389 my rev@59318016310c+ other rev@e03727d2d66b ancestor rev@924404dff337
390 390 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
391 391 (branch merge, don't forget to commit)
392 392 --------------
393 393 M b
394 394 --------------
395 395
396 396 created new head
397 397 --------------
398 398 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
399 399 --------------
400 400 resolving manifests
401 401 overwrite None partial False
402 402 ancestor 924404dff337 local ac809aeed39a+ remote 8dbce441892a
403 403 searching for copies back to rev 1
404 404 a: remote is newer -> g
405 405 b: versions differ -> m
406 406 rev: versions differ -> m
407 407 preserving b for resolve of b
408 408 preserving rev for resolve of rev
409 409 getting a
410 410 picked tool 'python ../merge' for b (binary False symlink False)
411 411 merging b
412 412 my b@ac809aeed39a+ other b@8dbce441892a ancestor b@000000000000
413 413 picked tool 'python ../merge' for rev (binary False symlink False)
414 414 merging rev
415 415 my rev@ac809aeed39a+ other rev@8dbce441892a ancestor rev@924404dff337
416 416 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
417 417 (branch merge, don't forget to commit)
418 418 --------------
419 419 M a
420 420 M b
421 421 --------------
422 422
423 423 created new head
424 424 --------------
425 425 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
426 426 --------------
427 427 resolving manifests
428 428 overwrite None partial False
429 429 ancestor 924404dff337 local 0b76e65c8289+ remote 735846fee2d7
430 430 searching for copies back to rev 1
431 431 b: versions differ -> m
432 432 rev: versions differ -> m
433 433 preserving b for resolve of b
434 434 preserving rev for resolve of rev
435 435 picked tool 'python ../merge' for b (binary False symlink False)
436 436 merging b
437 437 my b@0b76e65c8289+ other b@735846fee2d7 ancestor b@000000000000
438 438 picked tool 'python ../merge' for rev (binary False symlink False)
439 439 merging rev
440 440 my rev@0b76e65c8289+ other rev@735846fee2d7 ancestor rev@924404dff337
441 441 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
442 442 (branch merge, don't forget to commit)
443 443 --------------
444 444 M b
445 445 C a
446 446 --------------
447 447
448 448 created new head
449 449 --------------
450 450 test L:nm a b R:up a b W: - 18 merge b no ancestor
451 451 --------------
452 452 resolving manifests
453 453 overwrite None partial False
454 454 ancestor 924404dff337 local ecf3cb2a4219+ remote 8dbce441892a
455 455 searching for copies back to rev 1
456 456 b: versions differ -> m
457 457 rev: versions differ -> m
458 remote changed a which local deleted
459 use (c)hanged version or leave (d)eleted? c
458 460 a: prompt recreating -> g
459 461 preserving b for resolve of b
460 462 preserving rev for resolve of rev
461 463 getting a
462 464 picked tool 'python ../merge' for b (binary False symlink False)
463 465 merging b
464 466 my b@ecf3cb2a4219+ other b@8dbce441892a ancestor b@000000000000
465 467 picked tool 'python ../merge' for rev (binary False symlink False)
466 468 merging rev
467 469 my rev@ecf3cb2a4219+ other rev@8dbce441892a ancestor rev@924404dff337
468 470 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
469 471 (branch merge, don't forget to commit)
470 472 --------------
471 473 M a
472 474 M b
473 475 --------------
474 476
475 477 created new head
476 478 --------------
477 479 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
478 480 --------------
479 481 resolving manifests
480 482 overwrite None partial False
481 483 ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
482 484 searching for copies back to rev 1
485 local changed a which remote deleted
486 use (c)hanged version or (d)elete? c
483 487 b: versions differ -> m
484 488 rev: versions differ -> m
485 489 preserving b for resolve of b
486 490 preserving rev for resolve of rev
487 491 picked tool 'python ../merge' for b (binary False symlink False)
488 492 merging b
489 493 my b@0b76e65c8289+ other b@e03727d2d66b ancestor b@000000000000
490 494 picked tool 'python ../merge' for rev (binary False symlink False)
491 495 merging rev
492 496 my rev@0b76e65c8289+ other rev@e03727d2d66b ancestor rev@924404dff337
493 497 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
494 498 (branch merge, don't forget to commit)
495 499 --------------
496 500 M b
497 501 C a
498 502 --------------
499 503
500 504 created new head
501 505 --------------
502 506 test L:up a R:um a b W: - 20 merge a and b to b, remove a
503 507 --------------
504 508 resolving manifests
505 509 overwrite None partial False
506 510 ancestor 924404dff337 local e300d1c794ec+ remote 79cc6877a3b7
507 511 searching for copies back to rev 1
508 512 unmatched files in other:
509 513 b
510 514 all copies found (* = to merge, ! = divergent):
511 515 b -> a *
512 516 checking for directory renames
513 517 rev: versions differ -> m
514 518 a: remote moved to b -> m
515 519 preserving a for resolve of b
516 520 preserving rev for resolve of rev
517 521 removing a
518 522 picked tool 'python ../merge' for b (binary False symlink False)
519 523 merging a and b to b
520 524 my b@e300d1c794ec+ other b@79cc6877a3b7 ancestor a@924404dff337
521 525 picked tool 'python ../merge' for rev (binary False symlink False)
522 526 merging rev
523 527 my rev@e300d1c794ec+ other rev@79cc6877a3b7 ancestor rev@924404dff337
524 528 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
525 529 (branch merge, don't forget to commit)
526 530 --------------
527 531 M b
528 532 a
529 533 --------------
530 534
531 535 created new head
532 536 --------------
533 537 test L:um a b R:up a W: - 21 merge a and b to b
534 538 --------------
535 539 resolving manifests
536 540 overwrite None partial False
537 541 ancestor 924404dff337 local ec03c2ca8642+ remote f4db7e329e71
538 542 searching for copies back to rev 1
539 543 unmatched files in local:
540 544 b
541 545 all copies found (* = to merge, ! = divergent):
542 546 b -> a *
543 547 checking for directory renames
544 548 b: local moved to a -> m
545 549 rev: versions differ -> m
546 550 preserving b for resolve of b
547 551 preserving rev for resolve of rev
548 552 picked tool 'python ../merge' for b (binary False symlink False)
549 553 merging b and a to b
550 554 my b@ec03c2ca8642+ other a@f4db7e329e71 ancestor a@924404dff337
551 555 picked tool 'python ../merge' for rev (binary False symlink False)
552 556 merging rev
553 557 my rev@ec03c2ca8642+ other rev@f4db7e329e71 ancestor rev@924404dff337
554 558 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
555 559 (branch merge, don't forget to commit)
556 560 --------------
557 561 M b
558 562 a
559 563 --------------
560 564
561 565 created new head
562 566 --------------
563 567 test L:nm a b R:up a c W: - 23 get c, keep b
564 568 --------------
565 569 resolving manifests
566 570 overwrite None partial False
567 571 ancestor 924404dff337 local ecf3cb2a4219+ remote 2b958612230f
568 572 searching for copies back to rev 1
569 573 unmatched files in local:
570 574 b
571 575 unmatched files in other:
572 576 c
573 577 all copies found (* = to merge, ! = divergent):
574 578 b -> a *
575 579 checking for directory renames
576 580 b: local moved to a -> m
577 581 rev: versions differ -> m
578 582 c: remote created -> g
579 583 preserving b for resolve of b
580 584 preserving rev for resolve of rev
581 585 picked tool 'python ../merge' for b (binary False symlink False)
582 586 merging b and a to b
583 587 my b@ecf3cb2a4219+ other a@2b958612230f ancestor a@924404dff337
584 588 premerge successful
585 589 getting c
586 590 picked tool 'python ../merge' for rev (binary False symlink False)
587 591 merging rev
588 592 my rev@ecf3cb2a4219+ other rev@2b958612230f ancestor rev@924404dff337
589 593 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
590 594 (branch merge, don't forget to commit)
591 595 --------------
592 596 M b
593 597 a
594 598 M c
595 599 --------------
596 600
General Comments 0
You need to be logged in to leave comments. Login now