##// END OF EJS Templates
rollback: improve message
Matt Mackall -
r10893:468876bc default
parent child Browse files
Show More
@@ -1,2228 +1,2229 b''
1 1 # localrepo.py - read/write repository class 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 node import bin, hex, nullid, nullrev, short
9 9 from i18n import _
10 10 import repo, changegroup, subrepo
11 11 import changelog, dirstate, filelog, manifest, context
12 12 import lock, transaction, store, encoding
13 13 import util, extensions, hook, error
14 14 import match as matchmod
15 15 import merge as mergemod
16 16 import tags as tagsmod
17 17 import url as urlmod
18 18 from lock import release
19 19 import weakref, stat, errno, os, time, inspect
20 20 propertycache = util.propertycache
21 21
22 22 class localrepository(repo.repository):
23 23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap'))
24 24 supported = set('revlogv1 store fncache shared'.split())
25 25
26 26 def __init__(self, baseui, path=None, create=0):
27 27 repo.repository.__init__(self)
28 28 self.root = os.path.realpath(path)
29 29 self.path = os.path.join(self.root, ".hg")
30 30 self.origroot = path
31 31 self.opener = util.opener(self.path)
32 32 self.wopener = util.opener(self.root)
33 33 self.baseui = baseui
34 34 self.ui = baseui.copy()
35 35
36 36 try:
37 37 self.ui.readconfig(self.join("hgrc"), self.root)
38 38 extensions.loadall(self.ui)
39 39 except IOError:
40 40 pass
41 41
42 42 if not os.path.isdir(self.path):
43 43 if create:
44 44 if not os.path.exists(path):
45 45 os.mkdir(path)
46 46 os.mkdir(self.path)
47 47 requirements = ["revlogv1"]
48 48 if self.ui.configbool('format', 'usestore', True):
49 49 os.mkdir(os.path.join(self.path, "store"))
50 50 requirements.append("store")
51 51 if self.ui.configbool('format', 'usefncache', True):
52 52 requirements.append("fncache")
53 53 # create an invalid changelog
54 54 self.opener("00changelog.i", "a").write(
55 55 '\0\0\0\2' # represents revlogv2
56 56 ' dummy changelog to prevent using the old repo layout'
57 57 )
58 58 reqfile = self.opener("requires", "w")
59 59 for r in requirements:
60 60 reqfile.write("%s\n" % r)
61 61 reqfile.close()
62 62 else:
63 63 raise error.RepoError(_("repository %s not found") % path)
64 64 elif create:
65 65 raise error.RepoError(_("repository %s already exists") % path)
66 66 else:
67 67 # find requirements
68 68 requirements = set()
69 69 try:
70 70 requirements = set(self.opener("requires").read().splitlines())
71 71 except IOError, inst:
72 72 if inst.errno != errno.ENOENT:
73 73 raise
74 74 for r in requirements - self.supported:
75 75 raise error.RepoError(_("requirement '%s' not supported") % r)
76 76
77 77 self.sharedpath = self.path
78 78 try:
79 79 s = os.path.realpath(self.opener("sharedpath").read())
80 80 if not os.path.exists(s):
81 81 raise error.RepoError(
82 82 _('.hg/sharedpath points to nonexistent directory %s') % s)
83 83 self.sharedpath = s
84 84 except IOError, inst:
85 85 if inst.errno != errno.ENOENT:
86 86 raise
87 87
88 88 self.store = store.store(requirements, self.sharedpath, util.opener)
89 89 self.spath = self.store.path
90 90 self.sopener = self.store.opener
91 91 self.sjoin = self.store.join
92 92 self.opener.createmode = self.store.createmode
93 93 self.sopener.options = {}
94 94
95 95 # These two define the set of tags for this repository. _tags
96 96 # maps tag name to node; _tagtypes maps tag name to 'global' or
97 97 # 'local'. (Global tags are defined by .hgtags across all
98 98 # heads, and local tags are defined in .hg/localtags.) They
99 99 # constitute the in-memory cache of tags.
100 100 self._tags = None
101 101 self._tagtypes = None
102 102
103 103 self._branchcache = None # in UTF-8
104 104 self._branchcachetip = None
105 105 self.nodetagscache = None
106 106 self.filterpats = {}
107 107 self._datafilters = {}
108 108 self._transref = self._lockref = self._wlockref = None
109 109
110 110 @propertycache
111 111 def changelog(self):
112 112 c = changelog.changelog(self.sopener)
113 113 if 'HG_PENDING' in os.environ:
114 114 p = os.environ['HG_PENDING']
115 115 if p.startswith(self.root):
116 116 c.readpending('00changelog.i.a')
117 117 self.sopener.options['defversion'] = c.version
118 118 return c
119 119
120 120 @propertycache
121 121 def manifest(self):
122 122 return manifest.manifest(self.sopener)
123 123
124 124 @propertycache
125 125 def dirstate(self):
126 126 return dirstate.dirstate(self.opener, self.ui, self.root)
127 127
128 128 def __getitem__(self, changeid):
129 129 if changeid is None:
130 130 return context.workingctx(self)
131 131 return context.changectx(self, changeid)
132 132
133 133 def __contains__(self, changeid):
134 134 try:
135 135 return bool(self.lookup(changeid))
136 136 except error.RepoLookupError:
137 137 return False
138 138
139 139 def __nonzero__(self):
140 140 return True
141 141
142 142 def __len__(self):
143 143 return len(self.changelog)
144 144
145 145 def __iter__(self):
146 146 for i in xrange(len(self)):
147 147 yield i
148 148
149 149 def url(self):
150 150 return 'file:' + self.root
151 151
152 152 def hook(self, name, throw=False, **args):
153 153 return hook.hook(self.ui, self, name, throw, **args)
154 154
155 155 tag_disallowed = ':\r\n'
156 156
157 157 def _tag(self, names, node, message, local, user, date, extra={}):
158 158 if isinstance(names, str):
159 159 allchars = names
160 160 names = (names,)
161 161 else:
162 162 allchars = ''.join(names)
163 163 for c in self.tag_disallowed:
164 164 if c in allchars:
165 165 raise util.Abort(_('%r cannot be used in a tag name') % c)
166 166
167 167 for name in names:
168 168 self.hook('pretag', throw=True, node=hex(node), tag=name,
169 169 local=local)
170 170
171 171 def writetags(fp, names, munge, prevtags):
172 172 fp.seek(0, 2)
173 173 if prevtags and prevtags[-1] != '\n':
174 174 fp.write('\n')
175 175 for name in names:
176 176 m = munge and munge(name) or name
177 177 if self._tagtypes and name in self._tagtypes:
178 178 old = self._tags.get(name, nullid)
179 179 fp.write('%s %s\n' % (hex(old), m))
180 180 fp.write('%s %s\n' % (hex(node), m))
181 181 fp.close()
182 182
183 183 prevtags = ''
184 184 if local:
185 185 try:
186 186 fp = self.opener('localtags', 'r+')
187 187 except IOError:
188 188 fp = self.opener('localtags', 'a')
189 189 else:
190 190 prevtags = fp.read()
191 191
192 192 # local tags are stored in the current charset
193 193 writetags(fp, names, None, prevtags)
194 194 for name in names:
195 195 self.hook('tag', node=hex(node), tag=name, local=local)
196 196 return
197 197
198 198 try:
199 199 fp = self.wfile('.hgtags', 'rb+')
200 200 except IOError:
201 201 fp = self.wfile('.hgtags', 'ab')
202 202 else:
203 203 prevtags = fp.read()
204 204
205 205 # committed tags are stored in UTF-8
206 206 writetags(fp, names, encoding.fromlocal, prevtags)
207 207
208 208 if '.hgtags' not in self.dirstate:
209 209 self.add(['.hgtags'])
210 210
211 211 m = matchmod.exact(self.root, '', ['.hgtags'])
212 212 tagnode = self.commit(message, user, date, extra=extra, match=m)
213 213
214 214 for name in names:
215 215 self.hook('tag', node=hex(node), tag=name, local=local)
216 216
217 217 return tagnode
218 218
219 219 def tag(self, names, node, message, local, user, date):
220 220 '''tag a revision with one or more symbolic names.
221 221
222 222 names is a list of strings or, when adding a single tag, names may be a
223 223 string.
224 224
225 225 if local is True, the tags are stored in a per-repository file.
226 226 otherwise, they are stored in the .hgtags file, and a new
227 227 changeset is committed with the change.
228 228
229 229 keyword arguments:
230 230
231 231 local: whether to store tags in non-version-controlled file
232 232 (default False)
233 233
234 234 message: commit message to use if committing
235 235
236 236 user: name of user to use if committing
237 237
238 238 date: date tuple to use if committing'''
239 239
240 240 for x in self.status()[:5]:
241 241 if '.hgtags' in x:
242 242 raise util.Abort(_('working copy of .hgtags is changed '
243 243 '(please commit .hgtags manually)'))
244 244
245 245 self.tags() # instantiate the cache
246 246 self._tag(names, node, message, local, user, date)
247 247
248 248 def tags(self):
249 249 '''return a mapping of tag to node'''
250 250 if self._tags is None:
251 251 (self._tags, self._tagtypes) = self._findtags()
252 252
253 253 return self._tags
254 254
255 255 def _findtags(self):
256 256 '''Do the hard work of finding tags. Return a pair of dicts
257 257 (tags, tagtypes) where tags maps tag name to node, and tagtypes
258 258 maps tag name to a string like \'global\' or \'local\'.
259 259 Subclasses or extensions are free to add their own tags, but
260 260 should be aware that the returned dicts will be retained for the
261 261 duration of the localrepo object.'''
262 262
263 263 # XXX what tagtype should subclasses/extensions use? Currently
264 264 # mq and bookmarks add tags, but do not set the tagtype at all.
265 265 # Should each extension invent its own tag type? Should there
266 266 # be one tagtype for all such "virtual" tags? Or is the status
267 267 # quo fine?
268 268
269 269 alltags = {} # map tag name to (node, hist)
270 270 tagtypes = {}
271 271
272 272 tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
273 273 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
274 274
275 275 # Build the return dicts. Have to re-encode tag names because
276 276 # the tags module always uses UTF-8 (in order not to lose info
277 277 # writing to the cache), but the rest of Mercurial wants them in
278 278 # local encoding.
279 279 tags = {}
280 280 for (name, (node, hist)) in alltags.iteritems():
281 281 if node != nullid:
282 282 tags[encoding.tolocal(name)] = node
283 283 tags['tip'] = self.changelog.tip()
284 284 tagtypes = dict([(encoding.tolocal(name), value)
285 285 for (name, value) in tagtypes.iteritems()])
286 286 return (tags, tagtypes)
287 287
288 288 def tagtype(self, tagname):
289 289 '''
290 290 return the type of the given tag. result can be:
291 291
292 292 'local' : a local tag
293 293 'global' : a global tag
294 294 None : tag does not exist
295 295 '''
296 296
297 297 self.tags()
298 298
299 299 return self._tagtypes.get(tagname)
300 300
301 301 def tagslist(self):
302 302 '''return a list of tags ordered by revision'''
303 303 l = []
304 304 for t, n in self.tags().iteritems():
305 305 try:
306 306 r = self.changelog.rev(n)
307 307 except:
308 308 r = -2 # sort to the beginning of the list if unknown
309 309 l.append((r, t, n))
310 310 return [(t, n) for r, t, n in sorted(l)]
311 311
312 312 def nodetags(self, node):
313 313 '''return the tags associated with a node'''
314 314 if not self.nodetagscache:
315 315 self.nodetagscache = {}
316 316 for t, n in self.tags().iteritems():
317 317 self.nodetagscache.setdefault(n, []).append(t)
318 318 return self.nodetagscache.get(node, [])
319 319
320 320 def _branchtags(self, partial, lrev):
321 321 # TODO: rename this function?
322 322 tiprev = len(self) - 1
323 323 if lrev != tiprev:
324 324 ctxgen = (self[r] for r in xrange(lrev + 1, tiprev + 1))
325 325 self._updatebranchcache(partial, ctxgen)
326 326 self._writebranchcache(partial, self.changelog.tip(), tiprev)
327 327
328 328 return partial
329 329
330 330 def branchmap(self):
331 331 '''returns a dictionary {branch: [branchheads]}'''
332 332 tip = self.changelog.tip()
333 333 if self._branchcache is not None and self._branchcachetip == tip:
334 334 return self._branchcache
335 335
336 336 oldtip = self._branchcachetip
337 337 self._branchcachetip = tip
338 338 if oldtip is None or oldtip not in self.changelog.nodemap:
339 339 partial, last, lrev = self._readbranchcache()
340 340 else:
341 341 lrev = self.changelog.rev(oldtip)
342 342 partial = self._branchcache
343 343
344 344 self._branchtags(partial, lrev)
345 345 # this private cache holds all heads (not just tips)
346 346 self._branchcache = partial
347 347
348 348 return self._branchcache
349 349
350 350 def branchtags(self):
351 351 '''return a dict where branch names map to the tipmost head of
352 352 the branch, open heads come before closed'''
353 353 bt = {}
354 354 for bn, heads in self.branchmap().iteritems():
355 355 tip = heads[-1]
356 356 for h in reversed(heads):
357 357 if 'close' not in self.changelog.read(h)[5]:
358 358 tip = h
359 359 break
360 360 bt[bn] = tip
361 361 return bt
362 362
363 363
364 364 def _readbranchcache(self):
365 365 partial = {}
366 366 try:
367 367 f = self.opener("branchheads.cache")
368 368 lines = f.read().split('\n')
369 369 f.close()
370 370 except (IOError, OSError):
371 371 return {}, nullid, nullrev
372 372
373 373 try:
374 374 last, lrev = lines.pop(0).split(" ", 1)
375 375 last, lrev = bin(last), int(lrev)
376 376 if lrev >= len(self) or self[lrev].node() != last:
377 377 # invalidate the cache
378 378 raise ValueError('invalidating branch cache (tip differs)')
379 379 for l in lines:
380 380 if not l:
381 381 continue
382 382 node, label = l.split(" ", 1)
383 383 partial.setdefault(label.strip(), []).append(bin(node))
384 384 except KeyboardInterrupt:
385 385 raise
386 386 except Exception, inst:
387 387 if self.ui.debugflag:
388 388 self.ui.warn(str(inst), '\n')
389 389 partial, last, lrev = {}, nullid, nullrev
390 390 return partial, last, lrev
391 391
392 392 def _writebranchcache(self, branches, tip, tiprev):
393 393 try:
394 394 f = self.opener("branchheads.cache", "w", atomictemp=True)
395 395 f.write("%s %s\n" % (hex(tip), tiprev))
396 396 for label, nodes in branches.iteritems():
397 397 for node in nodes:
398 398 f.write("%s %s\n" % (hex(node), label))
399 399 f.rename()
400 400 except (IOError, OSError):
401 401 pass
402 402
403 403 def _updatebranchcache(self, partial, ctxgen):
404 404 # collect new branch entries
405 405 newbranches = {}
406 406 for c in ctxgen:
407 407 newbranches.setdefault(c.branch(), []).append(c.node())
408 408 # if older branchheads are reachable from new ones, they aren't
409 409 # really branchheads. Note checking parents is insufficient:
410 410 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
411 411 for branch, newnodes in newbranches.iteritems():
412 412 bheads = partial.setdefault(branch, [])
413 413 bheads.extend(newnodes)
414 414 if len(bheads) < 2:
415 415 continue
416 416 newbheads = []
417 417 # starting from tip means fewer passes over reachable
418 418 while newnodes:
419 419 latest = newnodes.pop()
420 420 if latest not in bheads:
421 421 continue
422 422 minbhrev = self[min([self[bh].rev() for bh in bheads])].node()
423 423 reachable = self.changelog.reachable(latest, minbhrev)
424 424 bheads = [b for b in bheads if b not in reachable]
425 425 newbheads.insert(0, latest)
426 426 bheads.extend(newbheads)
427 427 partial[branch] = bheads
428 428
429 429 def lookup(self, key):
430 430 if isinstance(key, int):
431 431 return self.changelog.node(key)
432 432 elif key == '.':
433 433 return self.dirstate.parents()[0]
434 434 elif key == 'null':
435 435 return nullid
436 436 elif key == 'tip':
437 437 return self.changelog.tip()
438 438 n = self.changelog._match(key)
439 439 if n:
440 440 return n
441 441 if key in self.tags():
442 442 return self.tags()[key]
443 443 if key in self.branchtags():
444 444 return self.branchtags()[key]
445 445 n = self.changelog._partialmatch(key)
446 446 if n:
447 447 return n
448 448
449 449 # can't find key, check if it might have come from damaged dirstate
450 450 if key in self.dirstate.parents():
451 451 raise error.Abort(_("working directory has unknown parent '%s'!")
452 452 % short(key))
453 453 try:
454 454 if len(key) == 20:
455 455 key = hex(key)
456 456 except:
457 457 pass
458 458 raise error.RepoLookupError(_("unknown revision '%s'") % key)
459 459
460 460 def local(self):
461 461 return True
462 462
463 463 def join(self, f):
464 464 return os.path.join(self.path, f)
465 465
466 466 def wjoin(self, f):
467 467 return os.path.join(self.root, f)
468 468
469 469 def rjoin(self, f):
470 470 return os.path.join(self.root, util.pconvert(f))
471 471
472 472 def file(self, f):
473 473 if f[0] == '/':
474 474 f = f[1:]
475 475 return filelog.filelog(self.sopener, f)
476 476
477 477 def changectx(self, changeid):
478 478 return self[changeid]
479 479
480 480 def parents(self, changeid=None):
481 481 '''get list of changectxs for parents of changeid'''
482 482 return self[changeid].parents()
483 483
484 484 def filectx(self, path, changeid=None, fileid=None):
485 485 """changeid can be a changeset revision, node, or tag.
486 486 fileid can be a file revision or node."""
487 487 return context.filectx(self, path, changeid, fileid)
488 488
489 489 def getcwd(self):
490 490 return self.dirstate.getcwd()
491 491
492 492 def pathto(self, f, cwd=None):
493 493 return self.dirstate.pathto(f, cwd)
494 494
495 495 def wfile(self, f, mode='r'):
496 496 return self.wopener(f, mode)
497 497
498 498 def _link(self, f):
499 499 return os.path.islink(self.wjoin(f))
500 500
501 501 def _filter(self, filter, filename, data):
502 502 if filter not in self.filterpats:
503 503 l = []
504 504 for pat, cmd in self.ui.configitems(filter):
505 505 if cmd == '!':
506 506 continue
507 507 mf = matchmod.match(self.root, '', [pat])
508 508 fn = None
509 509 params = cmd
510 510 for name, filterfn in self._datafilters.iteritems():
511 511 if cmd.startswith(name):
512 512 fn = filterfn
513 513 params = cmd[len(name):].lstrip()
514 514 break
515 515 if not fn:
516 516 fn = lambda s, c, **kwargs: util.filter(s, c)
517 517 # Wrap old filters not supporting keyword arguments
518 518 if not inspect.getargspec(fn)[2]:
519 519 oldfn = fn
520 520 fn = lambda s, c, **kwargs: oldfn(s, c)
521 521 l.append((mf, fn, params))
522 522 self.filterpats[filter] = l
523 523
524 524 for mf, fn, cmd in self.filterpats[filter]:
525 525 if mf(filename):
526 526 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
527 527 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
528 528 break
529 529
530 530 return data
531 531
532 532 def adddatafilter(self, name, filter):
533 533 self._datafilters[name] = filter
534 534
535 535 def wread(self, filename):
536 536 if self._link(filename):
537 537 data = os.readlink(self.wjoin(filename))
538 538 else:
539 539 data = self.wopener(filename, 'r').read()
540 540 return self._filter("encode", filename, data)
541 541
542 542 def wwrite(self, filename, data, flags):
543 543 data = self._filter("decode", filename, data)
544 544 try:
545 545 os.unlink(self.wjoin(filename))
546 546 except OSError:
547 547 pass
548 548 if 'l' in flags:
549 549 self.wopener.symlink(data, filename)
550 550 else:
551 551 self.wopener(filename, 'w').write(data)
552 552 if 'x' in flags:
553 553 util.set_flags(self.wjoin(filename), False, True)
554 554
555 555 def wwritedata(self, filename, data):
556 556 return self._filter("decode", filename, data)
557 557
558 558 def transaction(self, desc):
559 559 tr = self._transref and self._transref() or None
560 560 if tr and tr.running():
561 561 return tr.nest()
562 562
563 563 # abort here if the journal already exists
564 564 if os.path.exists(self.sjoin("journal")):
565 565 raise error.RepoError(
566 566 _("abandoned transaction found - run hg recover"))
567 567
568 568 # save dirstate for rollback
569 569 try:
570 570 ds = self.opener("dirstate").read()
571 571 except IOError:
572 572 ds = ""
573 573 self.opener("journal.dirstate", "w").write(ds)
574 574 self.opener("journal.branch", "w").write(self.dirstate.branch())
575 575 self.opener("journal.desc", "w").write("%d\n%s\n" % (len(self), desc))
576 576
577 577 renames = [(self.sjoin("journal"), self.sjoin("undo")),
578 578 (self.join("journal.dirstate"), self.join("undo.dirstate")),
579 579 (self.join("journal.branch"), self.join("undo.branch")),
580 580 (self.join("journal.desc"), self.join("undo.desc"))]
581 581 tr = transaction.transaction(self.ui.warn, self.sopener,
582 582 self.sjoin("journal"),
583 583 aftertrans(renames),
584 584 self.store.createmode)
585 585 self._transref = weakref.ref(tr)
586 586 return tr
587 587
588 588 def recover(self):
589 589 lock = self.lock()
590 590 try:
591 591 if os.path.exists(self.sjoin("journal")):
592 592 self.ui.status(_("rolling back interrupted transaction\n"))
593 593 transaction.rollback(self.sopener, self.sjoin("journal"),
594 594 self.ui.warn)
595 595 self.invalidate()
596 596 return True
597 597 else:
598 598 self.ui.warn(_("no interrupted transaction available\n"))
599 599 return False
600 600 finally:
601 601 lock.release()
602 602
603 603 def rollback(self, dryrun=False):
604 604 wlock = lock = None
605 605 try:
606 606 wlock = self.wlock()
607 607 lock = self.lock()
608 608 if os.path.exists(self.sjoin("undo")):
609 609 try:
610 610 args = self.opener("undo.desc", "r").read().splitlines()
611 611 if len(args) >= 3 and self.ui.verbose:
612 desc = _("rolling back %s (%s) to revision %s\n") % (
613 args[1], args[2], args[0])
612 desc = _("rolling back to revision %s"
613 " (undo %s: %s)\n") % (
614 args[0], args[1], args[2])
614 615 elif len(args) >= 2:
615 desc = _("rolling back %s to revision %s\n") % (
616 args[1], args[0])
616 desc = _("rolling back to revision %s (undo %s)\n") % (
617 args[0], args[1])
617 618 except IOError:
618 619 desc = _("rolling back unknown transaction\n")
619 620 self.ui.status(desc)
620 621 if dryrun:
621 622 return
622 623 transaction.rollback(self.sopener, self.sjoin("undo"),
623 624 self.ui.warn)
624 625 util.rename(self.join("undo.dirstate"), self.join("dirstate"))
625 626 try:
626 627 branch = self.opener("undo.branch").read()
627 628 self.dirstate.setbranch(branch)
628 629 except IOError:
629 630 self.ui.warn(_("Named branch could not be reset, "
630 631 "current branch still is: %s\n")
631 632 % encoding.tolocal(self.dirstate.branch()))
632 633 self.invalidate()
633 634 self.dirstate.invalidate()
634 635 self.destroyed()
635 636 else:
636 637 self.ui.warn(_("no rollback information available\n"))
637 638 finally:
638 639 release(lock, wlock)
639 640
640 641 def invalidatecaches(self):
641 642 self._tags = None
642 643 self._tagtypes = None
643 644 self.nodetagscache = None
644 645 self._branchcache = None # in UTF-8
645 646 self._branchcachetip = None
646 647
647 648 def invalidate(self):
648 649 for a in "changelog manifest".split():
649 650 if a in self.__dict__:
650 651 delattr(self, a)
651 652 self.invalidatecaches()
652 653
653 654 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
654 655 try:
655 656 l = lock.lock(lockname, 0, releasefn, desc=desc)
656 657 except error.LockHeld, inst:
657 658 if not wait:
658 659 raise
659 660 self.ui.warn(_("waiting for lock on %s held by %r\n") %
660 661 (desc, inst.locker))
661 662 # default to 600 seconds timeout
662 663 l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
663 664 releasefn, desc=desc)
664 665 if acquirefn:
665 666 acquirefn()
666 667 return l
667 668
668 669 def lock(self, wait=True):
669 670 '''Lock the repository store (.hg/store) and return a weak reference
670 671 to the lock. Use this before modifying the store (e.g. committing or
671 672 stripping). If you are opening a transaction, get a lock as well.)'''
672 673 l = self._lockref and self._lockref()
673 674 if l is not None and l.held:
674 675 l.lock()
675 676 return l
676 677
677 678 l = self._lock(self.sjoin("lock"), wait, None, self.invalidate,
678 679 _('repository %s') % self.origroot)
679 680 self._lockref = weakref.ref(l)
680 681 return l
681 682
682 683 def wlock(self, wait=True):
683 684 '''Lock the non-store parts of the repository (everything under
684 685 .hg except .hg/store) and return a weak reference to the lock.
685 686 Use this before modifying files in .hg.'''
686 687 l = self._wlockref and self._wlockref()
687 688 if l is not None and l.held:
688 689 l.lock()
689 690 return l
690 691
691 692 l = self._lock(self.join("wlock"), wait, self.dirstate.write,
692 693 self.dirstate.invalidate, _('working directory of %s') %
693 694 self.origroot)
694 695 self._wlockref = weakref.ref(l)
695 696 return l
696 697
697 698 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
698 699 """
699 700 commit an individual file as part of a larger transaction
700 701 """
701 702
702 703 fname = fctx.path()
703 704 text = fctx.data()
704 705 flog = self.file(fname)
705 706 fparent1 = manifest1.get(fname, nullid)
706 707 fparent2 = fparent2o = manifest2.get(fname, nullid)
707 708
708 709 meta = {}
709 710 copy = fctx.renamed()
710 711 if copy and copy[0] != fname:
711 712 # Mark the new revision of this file as a copy of another
712 713 # file. This copy data will effectively act as a parent
713 714 # of this new revision. If this is a merge, the first
714 715 # parent will be the nullid (meaning "look up the copy data")
715 716 # and the second one will be the other parent. For example:
716 717 #
717 718 # 0 --- 1 --- 3 rev1 changes file foo
718 719 # \ / rev2 renames foo to bar and changes it
719 720 # \- 2 -/ rev3 should have bar with all changes and
720 721 # should record that bar descends from
721 722 # bar in rev2 and foo in rev1
722 723 #
723 724 # this allows this merge to succeed:
724 725 #
725 726 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
726 727 # \ / merging rev3 and rev4 should use bar@rev2
727 728 # \- 2 --- 4 as the merge base
728 729 #
729 730
730 731 cfname = copy[0]
731 732 crev = manifest1.get(cfname)
732 733 newfparent = fparent2
733 734
734 735 if manifest2: # branch merge
735 736 if fparent2 == nullid or crev is None: # copied on remote side
736 737 if cfname in manifest2:
737 738 crev = manifest2[cfname]
738 739 newfparent = fparent1
739 740
740 741 # find source in nearest ancestor if we've lost track
741 742 if not crev:
742 743 self.ui.debug(" %s: searching for copy revision for %s\n" %
743 744 (fname, cfname))
744 745 for ancestor in self['.'].ancestors():
745 746 if cfname in ancestor:
746 747 crev = ancestor[cfname].filenode()
747 748 break
748 749
749 750 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
750 751 meta["copy"] = cfname
751 752 meta["copyrev"] = hex(crev)
752 753 fparent1, fparent2 = nullid, newfparent
753 754 elif fparent2 != nullid:
754 755 # is one parent an ancestor of the other?
755 756 fparentancestor = flog.ancestor(fparent1, fparent2)
756 757 if fparentancestor == fparent1:
757 758 fparent1, fparent2 = fparent2, nullid
758 759 elif fparentancestor == fparent2:
759 760 fparent2 = nullid
760 761
761 762 # is the file changed?
762 763 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
763 764 changelist.append(fname)
764 765 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
765 766
766 767 # are just the flags changed during merge?
767 768 if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
768 769 changelist.append(fname)
769 770
770 771 return fparent1
771 772
772 773 def commit(self, text="", user=None, date=None, match=None, force=False,
773 774 editor=False, extra={}):
774 775 """Add a new revision to current repository.
775 776
776 777 Revision information is gathered from the working directory,
777 778 match can be used to filter the committed files. If editor is
778 779 supplied, it is called to get a commit message.
779 780 """
780 781
781 782 def fail(f, msg):
782 783 raise util.Abort('%s: %s' % (f, msg))
783 784
784 785 if not match:
785 786 match = matchmod.always(self.root, '')
786 787
787 788 if not force:
788 789 vdirs = []
789 790 match.dir = vdirs.append
790 791 match.bad = fail
791 792
792 793 wlock = self.wlock()
793 794 try:
794 795 p1, p2 = self.dirstate.parents()
795 796 wctx = self[None]
796 797
797 798 if (not force and p2 != nullid and match and
798 799 (match.files() or match.anypats())):
799 800 raise util.Abort(_('cannot partially commit a merge '
800 801 '(do not specify files or patterns)'))
801 802
802 803 changes = self.status(match=match, clean=force)
803 804 if force:
804 805 changes[0].extend(changes[6]) # mq may commit unchanged files
805 806
806 807 # check subrepos
807 808 subs = []
808 809 removedsubs = set()
809 810 for p in wctx.parents():
810 811 removedsubs.update(s for s in p.substate if match(s))
811 812 for s in wctx.substate:
812 813 removedsubs.discard(s)
813 814 if match(s) and wctx.sub(s).dirty():
814 815 subs.append(s)
815 816 if (subs or removedsubs) and '.hgsubstate' not in changes[0]:
816 817 changes[0].insert(0, '.hgsubstate')
817 818
818 819 # make sure all explicit patterns are matched
819 820 if not force and match.files():
820 821 matched = set(changes[0] + changes[1] + changes[2])
821 822
822 823 for f in match.files():
823 824 if f == '.' or f in matched or f in wctx.substate:
824 825 continue
825 826 if f in changes[3]: # missing
826 827 fail(f, _('file not found!'))
827 828 if f in vdirs: # visited directory
828 829 d = f + '/'
829 830 for mf in matched:
830 831 if mf.startswith(d):
831 832 break
832 833 else:
833 834 fail(f, _("no match under directory!"))
834 835 elif f not in self.dirstate:
835 836 fail(f, _("file not tracked!"))
836 837
837 838 if (not force and not extra.get("close") and p2 == nullid
838 839 and not (changes[0] or changes[1] or changes[2])
839 840 and self[None].branch() == self['.'].branch()):
840 841 return None
841 842
842 843 ms = mergemod.mergestate(self)
843 844 for f in changes[0]:
844 845 if f in ms and ms[f] == 'u':
845 846 raise util.Abort(_("unresolved merge conflicts "
846 847 "(see hg resolve)"))
847 848
848 849 cctx = context.workingctx(self, (p1, p2), text, user, date,
849 850 extra, changes)
850 851 if editor:
851 852 cctx._text = editor(self, cctx, subs)
852 853 edited = (text != cctx._text)
853 854
854 855 # commit subs
855 856 if subs or removedsubs:
856 857 state = wctx.substate.copy()
857 858 for s in subs:
858 859 self.ui.status(_('committing subrepository %s\n') % s)
859 860 sr = wctx.sub(s).commit(cctx._text, user, date)
860 861 state[s] = (state[s][0], sr)
861 862 subrepo.writestate(self, state)
862 863
863 864 # Save commit message in case this transaction gets rolled back
864 865 # (e.g. by a pretxncommit hook). Leave the content alone on
865 866 # the assumption that the user will use the same editor again.
866 867 msgfile = self.opener('last-message.txt', 'wb')
867 868 msgfile.write(cctx._text)
868 869 msgfile.close()
869 870
870 871 try:
871 872 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
872 873 self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
873 874 ret = self.commitctx(cctx, True)
874 875 except:
875 876 if edited:
876 877 msgfn = self.pathto(msgfile.name[len(self.root)+1:])
877 878 self.ui.write(
878 879 _('note: commit message saved in %s\n') % msgfn)
879 880 raise
880 881
881 882 # update dirstate and mergestate
882 883 for f in changes[0] + changes[1]:
883 884 self.dirstate.normal(f)
884 885 for f in changes[2]:
885 886 self.dirstate.forget(f)
886 887 self.dirstate.setparents(ret)
887 888 ms.reset()
888 889 finally:
889 890 wlock.release()
890 891
891 892 self.hook("commit", node=hex(ret), parent1=hookp1, parent2=hookp2)
892 893 return ret
893 894
894 895 def commitctx(self, ctx, error=False):
895 896 """Add a new revision to current repository.
896 897 Revision information is passed via the context argument.
897 898 """
898 899
899 900 tr = lock = None
900 901 removed = ctx.removed()
901 902 p1, p2 = ctx.p1(), ctx.p2()
902 903 m1 = p1.manifest().copy()
903 904 m2 = p2.manifest()
904 905 user = ctx.user()
905 906
906 907 lock = self.lock()
907 908 try:
908 909 tr = self.transaction("commit")
909 910 trp = weakref.proxy(tr)
910 911
911 912 # check in files
912 913 new = {}
913 914 changed = []
914 915 linkrev = len(self)
915 916 for f in sorted(ctx.modified() + ctx.added()):
916 917 self.ui.note(f + "\n")
917 918 try:
918 919 fctx = ctx[f]
919 920 new[f] = self._filecommit(fctx, m1, m2, linkrev, trp,
920 921 changed)
921 922 m1.set(f, fctx.flags())
922 923 except OSError, inst:
923 924 self.ui.warn(_("trouble committing %s!\n") % f)
924 925 raise
925 926 except IOError, inst:
926 927 errcode = getattr(inst, 'errno', errno.ENOENT)
927 928 if error or errcode and errcode != errno.ENOENT:
928 929 self.ui.warn(_("trouble committing %s!\n") % f)
929 930 raise
930 931 else:
931 932 removed.append(f)
932 933
933 934 # update manifest
934 935 m1.update(new)
935 936 removed = [f for f in sorted(removed) if f in m1 or f in m2]
936 937 drop = [f for f in removed if f in m1]
937 938 for f in drop:
938 939 del m1[f]
939 940 mn = self.manifest.add(m1, trp, linkrev, p1.manifestnode(),
940 941 p2.manifestnode(), (new, drop))
941 942
942 943 # update changelog
943 944 self.changelog.delayupdate()
944 945 n = self.changelog.add(mn, changed + removed, ctx.description(),
945 946 trp, p1.node(), p2.node(),
946 947 user, ctx.date(), ctx.extra().copy())
947 948 p = lambda: self.changelog.writepending() and self.root or ""
948 949 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
949 950 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
950 951 parent2=xp2, pending=p)
951 952 self.changelog.finalize(trp)
952 953 tr.close()
953 954
954 955 if self._branchcache:
955 956 self.branchtags()
956 957 return n
957 958 finally:
958 959 del tr
959 960 lock.release()
960 961
961 962 def destroyed(self):
962 963 '''Inform the repository that nodes have been destroyed.
963 964 Intended for use by strip and rollback, so there's a common
964 965 place for anything that has to be done after destroying history.'''
965 966 # XXX it might be nice if we could take the list of destroyed
966 967 # nodes, but I don't see an easy way for rollback() to do that
967 968
968 969 # Ensure the persistent tag cache is updated. Doing it now
969 970 # means that the tag cache only has to worry about destroyed
970 971 # heads immediately after a strip/rollback. That in turn
971 972 # guarantees that "cachetip == currenttip" (comparing both rev
972 973 # and node) always means no nodes have been added or destroyed.
973 974
974 975 # XXX this is suboptimal when qrefresh'ing: we strip the current
975 976 # head, refresh the tag cache, then immediately add a new head.
976 977 # But I think doing it this way is necessary for the "instant
977 978 # tag cache retrieval" case to work.
978 979 self.invalidatecaches()
979 980
980 981 def walk(self, match, node=None):
981 982 '''
982 983 walk recursively through the directory tree or a given
983 984 changeset, finding all files matched by the match
984 985 function
985 986 '''
986 987 return self[node].walk(match)
987 988
988 989 def status(self, node1='.', node2=None, match=None,
989 990 ignored=False, clean=False, unknown=False):
990 991 """return status of files between two nodes or node and working directory
991 992
992 993 If node1 is None, use the first dirstate parent instead.
993 994 If node2 is None, compare node1 with working directory.
994 995 """
995 996
996 997 def mfmatches(ctx):
997 998 mf = ctx.manifest().copy()
998 999 for fn in mf.keys():
999 1000 if not match(fn):
1000 1001 del mf[fn]
1001 1002 return mf
1002 1003
1003 1004 if isinstance(node1, context.changectx):
1004 1005 ctx1 = node1
1005 1006 else:
1006 1007 ctx1 = self[node1]
1007 1008 if isinstance(node2, context.changectx):
1008 1009 ctx2 = node2
1009 1010 else:
1010 1011 ctx2 = self[node2]
1011 1012
1012 1013 working = ctx2.rev() is None
1013 1014 parentworking = working and ctx1 == self['.']
1014 1015 match = match or matchmod.always(self.root, self.getcwd())
1015 1016 listignored, listclean, listunknown = ignored, clean, unknown
1016 1017
1017 1018 # load earliest manifest first for caching reasons
1018 1019 if not working and ctx2.rev() < ctx1.rev():
1019 1020 ctx2.manifest()
1020 1021
1021 1022 if not parentworking:
1022 1023 def bad(f, msg):
1023 1024 if f not in ctx1:
1024 1025 self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg))
1025 1026 match.bad = bad
1026 1027
1027 1028 if working: # we need to scan the working dir
1028 1029 subrepos = ctx1.substate.keys()
1029 1030 s = self.dirstate.status(match, subrepos, listignored,
1030 1031 listclean, listunknown)
1031 1032 cmp, modified, added, removed, deleted, unknown, ignored, clean = s
1032 1033
1033 1034 # check for any possibly clean files
1034 1035 if parentworking and cmp:
1035 1036 fixup = []
1036 1037 # do a full compare of any files that might have changed
1037 1038 for f in sorted(cmp):
1038 1039 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
1039 1040 or ctx1[f].cmp(ctx2[f].data())):
1040 1041 modified.append(f)
1041 1042 else:
1042 1043 fixup.append(f)
1043 1044
1044 1045 if listclean:
1045 1046 clean += fixup
1046 1047
1047 1048 # update dirstate for files that are actually clean
1048 1049 if fixup:
1049 1050 try:
1050 1051 # updating the dirstate is optional
1051 1052 # so we don't wait on the lock
1052 1053 wlock = self.wlock(False)
1053 1054 try:
1054 1055 for f in fixup:
1055 1056 self.dirstate.normal(f)
1056 1057 finally:
1057 1058 wlock.release()
1058 1059 except error.LockError:
1059 1060 pass
1060 1061
1061 1062 if not parentworking:
1062 1063 mf1 = mfmatches(ctx1)
1063 1064 if working:
1064 1065 # we are comparing working dir against non-parent
1065 1066 # generate a pseudo-manifest for the working dir
1066 1067 mf2 = mfmatches(self['.'])
1067 1068 for f in cmp + modified + added:
1068 1069 mf2[f] = None
1069 1070 mf2.set(f, ctx2.flags(f))
1070 1071 for f in removed:
1071 1072 if f in mf2:
1072 1073 del mf2[f]
1073 1074 else:
1074 1075 # we are comparing two revisions
1075 1076 deleted, unknown, ignored = [], [], []
1076 1077 mf2 = mfmatches(ctx2)
1077 1078
1078 1079 modified, added, clean = [], [], []
1079 1080 for fn in mf2:
1080 1081 if fn in mf1:
1081 1082 if (mf1.flags(fn) != mf2.flags(fn) or
1082 1083 (mf1[fn] != mf2[fn] and
1083 1084 (mf2[fn] or ctx1[fn].cmp(ctx2[fn].data())))):
1084 1085 modified.append(fn)
1085 1086 elif listclean:
1086 1087 clean.append(fn)
1087 1088 del mf1[fn]
1088 1089 else:
1089 1090 added.append(fn)
1090 1091 removed = mf1.keys()
1091 1092
1092 1093 r = modified, added, removed, deleted, unknown, ignored, clean
1093 1094 [l.sort() for l in r]
1094 1095 return r
1095 1096
1096 1097 def add(self, list):
1097 1098 wlock = self.wlock()
1098 1099 try:
1099 1100 rejected = []
1100 1101 for f in list:
1101 1102 p = self.wjoin(f)
1102 1103 try:
1103 1104 st = os.lstat(p)
1104 1105 except:
1105 1106 self.ui.warn(_("%s does not exist!\n") % f)
1106 1107 rejected.append(f)
1107 1108 continue
1108 1109 if st.st_size > 10000000:
1109 1110 self.ui.warn(_("%s: up to %d MB of RAM may be required "
1110 1111 "to manage this file\n"
1111 1112 "(use 'hg revert %s' to cancel the "
1112 1113 "pending addition)\n")
1113 1114 % (f, 3 * st.st_size // 1000000, f))
1114 1115 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
1115 1116 self.ui.warn(_("%s not added: only files and symlinks "
1116 1117 "supported currently\n") % f)
1117 1118 rejected.append(p)
1118 1119 elif self.dirstate[f] in 'amn':
1119 1120 self.ui.warn(_("%s already tracked!\n") % f)
1120 1121 elif self.dirstate[f] == 'r':
1121 1122 self.dirstate.normallookup(f)
1122 1123 else:
1123 1124 self.dirstate.add(f)
1124 1125 return rejected
1125 1126 finally:
1126 1127 wlock.release()
1127 1128
1128 1129 def forget(self, list):
1129 1130 wlock = self.wlock()
1130 1131 try:
1131 1132 for f in list:
1132 1133 if self.dirstate[f] != 'a':
1133 1134 self.ui.warn(_("%s not added!\n") % f)
1134 1135 else:
1135 1136 self.dirstate.forget(f)
1136 1137 finally:
1137 1138 wlock.release()
1138 1139
1139 1140 def remove(self, list, unlink=False):
1140 1141 if unlink:
1141 1142 for f in list:
1142 1143 try:
1143 1144 util.unlink(self.wjoin(f))
1144 1145 except OSError, inst:
1145 1146 if inst.errno != errno.ENOENT:
1146 1147 raise
1147 1148 wlock = self.wlock()
1148 1149 try:
1149 1150 for f in list:
1150 1151 if unlink and os.path.exists(self.wjoin(f)):
1151 1152 self.ui.warn(_("%s still exists!\n") % f)
1152 1153 elif self.dirstate[f] == 'a':
1153 1154 self.dirstate.forget(f)
1154 1155 elif f not in self.dirstate:
1155 1156 self.ui.warn(_("%s not tracked!\n") % f)
1156 1157 else:
1157 1158 self.dirstate.remove(f)
1158 1159 finally:
1159 1160 wlock.release()
1160 1161
1161 1162 def undelete(self, list):
1162 1163 manifests = [self.manifest.read(self.changelog.read(p)[0])
1163 1164 for p in self.dirstate.parents() if p != nullid]
1164 1165 wlock = self.wlock()
1165 1166 try:
1166 1167 for f in list:
1167 1168 if self.dirstate[f] != 'r':
1168 1169 self.ui.warn(_("%s not removed!\n") % f)
1169 1170 else:
1170 1171 m = f in manifests[0] and manifests[0] or manifests[1]
1171 1172 t = self.file(f).read(m[f])
1172 1173 self.wwrite(f, t, m.flags(f))
1173 1174 self.dirstate.normal(f)
1174 1175 finally:
1175 1176 wlock.release()
1176 1177
1177 1178 def copy(self, source, dest):
1178 1179 p = self.wjoin(dest)
1179 1180 if not (os.path.exists(p) or os.path.islink(p)):
1180 1181 self.ui.warn(_("%s does not exist!\n") % dest)
1181 1182 elif not (os.path.isfile(p) or os.path.islink(p)):
1182 1183 self.ui.warn(_("copy failed: %s is not a file or a "
1183 1184 "symbolic link\n") % dest)
1184 1185 else:
1185 1186 wlock = self.wlock()
1186 1187 try:
1187 1188 if self.dirstate[dest] in '?r':
1188 1189 self.dirstate.add(dest)
1189 1190 self.dirstate.copy(source, dest)
1190 1191 finally:
1191 1192 wlock.release()
1192 1193
1193 1194 def heads(self, start=None):
1194 1195 heads = self.changelog.heads(start)
1195 1196 # sort the output in rev descending order
1196 1197 heads = [(-self.changelog.rev(h), h) for h in heads]
1197 1198 return [n for (r, n) in sorted(heads)]
1198 1199
1199 1200 def branchheads(self, branch=None, start=None, closed=False):
1200 1201 '''return a (possibly filtered) list of heads for the given branch
1201 1202
1202 1203 Heads are returned in topological order, from newest to oldest.
1203 1204 If branch is None, use the dirstate branch.
1204 1205 If start is not None, return only heads reachable from start.
1205 1206 If closed is True, return heads that are marked as closed as well.
1206 1207 '''
1207 1208 if branch is None:
1208 1209 branch = self[None].branch()
1209 1210 branches = self.branchmap()
1210 1211 if branch not in branches:
1211 1212 return []
1212 1213 # the cache returns heads ordered lowest to highest
1213 1214 bheads = list(reversed(branches[branch]))
1214 1215 if start is not None:
1215 1216 # filter out the heads that cannot be reached from startrev
1216 1217 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
1217 1218 bheads = [h for h in bheads if h in fbheads]
1218 1219 if not closed:
1219 1220 bheads = [h for h in bheads if
1220 1221 ('close' not in self.changelog.read(h)[5])]
1221 1222 return bheads
1222 1223
1223 1224 def branches(self, nodes):
1224 1225 if not nodes:
1225 1226 nodes = [self.changelog.tip()]
1226 1227 b = []
1227 1228 for n in nodes:
1228 1229 t = n
1229 1230 while 1:
1230 1231 p = self.changelog.parents(n)
1231 1232 if p[1] != nullid or p[0] == nullid:
1232 1233 b.append((t, n, p[0], p[1]))
1233 1234 break
1234 1235 n = p[0]
1235 1236 return b
1236 1237
1237 1238 def between(self, pairs):
1238 1239 r = []
1239 1240
1240 1241 for top, bottom in pairs:
1241 1242 n, l, i = top, [], 0
1242 1243 f = 1
1243 1244
1244 1245 while n != bottom and n != nullid:
1245 1246 p = self.changelog.parents(n)[0]
1246 1247 if i == f:
1247 1248 l.append(n)
1248 1249 f = f * 2
1249 1250 n = p
1250 1251 i += 1
1251 1252
1252 1253 r.append(l)
1253 1254
1254 1255 return r
1255 1256
1256 1257 def findincoming(self, remote, base=None, heads=None, force=False):
1257 1258 """Return list of roots of the subsets of missing nodes from remote
1258 1259
1259 1260 If base dict is specified, assume that these nodes and their parents
1260 1261 exist on the remote side and that no child of a node of base exists
1261 1262 in both remote and self.
1262 1263 Furthermore base will be updated to include the nodes that exists
1263 1264 in self and remote but no children exists in self and remote.
1264 1265 If a list of heads is specified, return only nodes which are heads
1265 1266 or ancestors of these heads.
1266 1267
1267 1268 All the ancestors of base are in self and in remote.
1268 1269 All the descendants of the list returned are missing in self.
1269 1270 (and so we know that the rest of the nodes are missing in remote, see
1270 1271 outgoing)
1271 1272 """
1272 1273 return self.findcommonincoming(remote, base, heads, force)[1]
1273 1274
1274 1275 def findcommonincoming(self, remote, base=None, heads=None, force=False):
1275 1276 """Return a tuple (common, missing roots, heads) used to identify
1276 1277 missing nodes from remote.
1277 1278
1278 1279 If base dict is specified, assume that these nodes and their parents
1279 1280 exist on the remote side and that no child of a node of base exists
1280 1281 in both remote and self.
1281 1282 Furthermore base will be updated to include the nodes that exists
1282 1283 in self and remote but no children exists in self and remote.
1283 1284 If a list of heads is specified, return only nodes which are heads
1284 1285 or ancestors of these heads.
1285 1286
1286 1287 All the ancestors of base are in self and in remote.
1287 1288 """
1288 1289 m = self.changelog.nodemap
1289 1290 search = []
1290 1291 fetch = set()
1291 1292 seen = set()
1292 1293 seenbranch = set()
1293 1294 if base is None:
1294 1295 base = {}
1295 1296
1296 1297 if not heads:
1297 1298 heads = remote.heads()
1298 1299
1299 1300 if self.changelog.tip() == nullid:
1300 1301 base[nullid] = 1
1301 1302 if heads != [nullid]:
1302 1303 return [nullid], [nullid], list(heads)
1303 1304 return [nullid], [], []
1304 1305
1305 1306 # assume we're closer to the tip than the root
1306 1307 # and start by examining the heads
1307 1308 self.ui.status(_("searching for changes\n"))
1308 1309
1309 1310 unknown = []
1310 1311 for h in heads:
1311 1312 if h not in m:
1312 1313 unknown.append(h)
1313 1314 else:
1314 1315 base[h] = 1
1315 1316
1316 1317 heads = unknown
1317 1318 if not unknown:
1318 1319 return base.keys(), [], []
1319 1320
1320 1321 req = set(unknown)
1321 1322 reqcnt = 0
1322 1323
1323 1324 # search through remote branches
1324 1325 # a 'branch' here is a linear segment of history, with four parts:
1325 1326 # head, root, first parent, second parent
1326 1327 # (a branch always has two parents (or none) by definition)
1327 1328 unknown = remote.branches(unknown)
1328 1329 while unknown:
1329 1330 r = []
1330 1331 while unknown:
1331 1332 n = unknown.pop(0)
1332 1333 if n[0] in seen:
1333 1334 continue
1334 1335
1335 1336 self.ui.debug("examining %s:%s\n"
1336 1337 % (short(n[0]), short(n[1])))
1337 1338 if n[0] == nullid: # found the end of the branch
1338 1339 pass
1339 1340 elif n in seenbranch:
1340 1341 self.ui.debug("branch already found\n")
1341 1342 continue
1342 1343 elif n[1] and n[1] in m: # do we know the base?
1343 1344 self.ui.debug("found incomplete branch %s:%s\n"
1344 1345 % (short(n[0]), short(n[1])))
1345 1346 search.append(n[0:2]) # schedule branch range for scanning
1346 1347 seenbranch.add(n)
1347 1348 else:
1348 1349 if n[1] not in seen and n[1] not in fetch:
1349 1350 if n[2] in m and n[3] in m:
1350 1351 self.ui.debug("found new changeset %s\n" %
1351 1352 short(n[1]))
1352 1353 fetch.add(n[1]) # earliest unknown
1353 1354 for p in n[2:4]:
1354 1355 if p in m:
1355 1356 base[p] = 1 # latest known
1356 1357
1357 1358 for p in n[2:4]:
1358 1359 if p not in req and p not in m:
1359 1360 r.append(p)
1360 1361 req.add(p)
1361 1362 seen.add(n[0])
1362 1363
1363 1364 if r:
1364 1365 reqcnt += 1
1365 1366 self.ui.progress(_('searching'), reqcnt, unit=_('queries'))
1366 1367 self.ui.debug("request %d: %s\n" %
1367 1368 (reqcnt, " ".join(map(short, r))))
1368 1369 for p in xrange(0, len(r), 10):
1369 1370 for b in remote.branches(r[p:p + 10]):
1370 1371 self.ui.debug("received %s:%s\n" %
1371 1372 (short(b[0]), short(b[1])))
1372 1373 unknown.append(b)
1373 1374
1374 1375 # do binary search on the branches we found
1375 1376 while search:
1376 1377 newsearch = []
1377 1378 reqcnt += 1
1378 1379 self.ui.progress(_('searching'), reqcnt, unit=_('queries'))
1379 1380 for n, l in zip(search, remote.between(search)):
1380 1381 l.append(n[1])
1381 1382 p = n[0]
1382 1383 f = 1
1383 1384 for i in l:
1384 1385 self.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i)))
1385 1386 if i in m:
1386 1387 if f <= 2:
1387 1388 self.ui.debug("found new branch changeset %s\n" %
1388 1389 short(p))
1389 1390 fetch.add(p)
1390 1391 base[i] = 1
1391 1392 else:
1392 1393 self.ui.debug("narrowed branch search to %s:%s\n"
1393 1394 % (short(p), short(i)))
1394 1395 newsearch.append((p, i))
1395 1396 break
1396 1397 p, f = i, f * 2
1397 1398 search = newsearch
1398 1399
1399 1400 # sanity check our fetch list
1400 1401 for f in fetch:
1401 1402 if f in m:
1402 1403 raise error.RepoError(_("already have changeset ")
1403 1404 + short(f[:4]))
1404 1405
1405 1406 if base.keys() == [nullid]:
1406 1407 if force:
1407 1408 self.ui.warn(_("warning: repository is unrelated\n"))
1408 1409 else:
1409 1410 raise util.Abort(_("repository is unrelated"))
1410 1411
1411 1412 self.ui.debug("found new changesets starting at " +
1412 1413 " ".join([short(f) for f in fetch]) + "\n")
1413 1414
1414 1415 self.ui.progress(_('searching'), None)
1415 1416 self.ui.debug("%d total queries\n" % reqcnt)
1416 1417
1417 1418 return base.keys(), list(fetch), heads
1418 1419
1419 1420 def findoutgoing(self, remote, base=None, heads=None, force=False):
1420 1421 """Return list of nodes that are roots of subsets not in remote
1421 1422
1422 1423 If base dict is specified, assume that these nodes and their parents
1423 1424 exist on the remote side.
1424 1425 If a list of heads is specified, return only nodes which are heads
1425 1426 or ancestors of these heads, and return a second element which
1426 1427 contains all remote heads which get new children.
1427 1428 """
1428 1429 if base is None:
1429 1430 base = {}
1430 1431 self.findincoming(remote, base, heads, force=force)
1431 1432
1432 1433 self.ui.debug("common changesets up to "
1433 1434 + " ".join(map(short, base.keys())) + "\n")
1434 1435
1435 1436 remain = set(self.changelog.nodemap)
1436 1437
1437 1438 # prune everything remote has from the tree
1438 1439 remain.remove(nullid)
1439 1440 remove = base.keys()
1440 1441 while remove:
1441 1442 n = remove.pop(0)
1442 1443 if n in remain:
1443 1444 remain.remove(n)
1444 1445 for p in self.changelog.parents(n):
1445 1446 remove.append(p)
1446 1447
1447 1448 # find every node whose parents have been pruned
1448 1449 subset = []
1449 1450 # find every remote head that will get new children
1450 1451 updated_heads = set()
1451 1452 for n in remain:
1452 1453 p1, p2 = self.changelog.parents(n)
1453 1454 if p1 not in remain and p2 not in remain:
1454 1455 subset.append(n)
1455 1456 if heads:
1456 1457 if p1 in heads:
1457 1458 updated_heads.add(p1)
1458 1459 if p2 in heads:
1459 1460 updated_heads.add(p2)
1460 1461
1461 1462 # this is the set of all roots we have to push
1462 1463 if heads:
1463 1464 return subset, list(updated_heads)
1464 1465 else:
1465 1466 return subset
1466 1467
1467 1468 def pull(self, remote, heads=None, force=False):
1468 1469 lock = self.lock()
1469 1470 try:
1470 1471 common, fetch, rheads = self.findcommonincoming(remote, heads=heads,
1471 1472 force=force)
1472 1473 if not fetch:
1473 1474 self.ui.status(_("no changes found\n"))
1474 1475 return 0
1475 1476
1476 1477 if fetch == [nullid]:
1477 1478 self.ui.status(_("requesting all changes\n"))
1478 1479 elif heads is None and remote.capable('changegroupsubset'):
1479 1480 # issue1320, avoid a race if remote changed after discovery
1480 1481 heads = rheads
1481 1482
1482 1483 if heads is None:
1483 1484 cg = remote.changegroup(fetch, 'pull')
1484 1485 else:
1485 1486 if not remote.capable('changegroupsubset'):
1486 1487 raise util.Abort(_("Partial pull cannot be done because "
1487 1488 "other repository doesn't support "
1488 1489 "changegroupsubset."))
1489 1490 cg = remote.changegroupsubset(fetch, heads, 'pull')
1490 1491 return self.addchangegroup(cg, 'pull', remote.url())
1491 1492 finally:
1492 1493 lock.release()
1493 1494
1494 1495 def push(self, remote, force=False, revs=None):
1495 1496 # there are two ways to push to remote repo:
1496 1497 #
1497 1498 # addchangegroup assumes local user can lock remote
1498 1499 # repo (local filesystem, old ssh servers).
1499 1500 #
1500 1501 # unbundle assumes local user cannot lock remote repo (new ssh
1501 1502 # servers, http servers).
1502 1503
1503 1504 if remote.capable('unbundle'):
1504 1505 return self.push_unbundle(remote, force, revs)
1505 1506 return self.push_addchangegroup(remote, force, revs)
1506 1507
1507 1508 def prepush(self, remote, force, revs):
1508 1509 '''Analyze the local and remote repositories and determine which
1509 1510 changesets need to be pushed to the remote. Return a tuple
1510 1511 (changegroup, remoteheads). changegroup is a readable file-like
1511 1512 object whose read() returns successive changegroup chunks ready to
1512 1513 be sent over the wire. remoteheads is the list of remote heads.
1513 1514 '''
1514 1515 common = {}
1515 1516 remote_heads = remote.heads()
1516 1517 inc = self.findincoming(remote, common, remote_heads, force=force)
1517 1518
1518 1519 cl = self.changelog
1519 1520 update, updated_heads = self.findoutgoing(remote, common, remote_heads)
1520 1521 msng_cl, bases, heads = cl.nodesbetween(update, revs)
1521 1522
1522 1523 outgoingnodeset = set(msng_cl)
1523 1524 # compute set of nodes which, if they were a head before, no longer are
1524 1525 nolongeraheadnodeset = set(p for n in msng_cl for p in cl.parents(n))
1525 1526
1526 1527 def checkbranch(lheads, rheads, branchname=None):
1527 1528 '''
1528 1529 check whether there are more local heads than remote heads on
1529 1530 a specific branch.
1530 1531
1531 1532 lheads: local branch heads
1532 1533 rheads: remote branch heads
1533 1534 '''
1534 1535 newlheads = [n for n in lheads if n in outgoingnodeset]
1535 1536 formerrheads = [n for n in rheads if n in nolongeraheadnodeset]
1536 1537 if len(newlheads) > len(formerrheads):
1537 1538 # we add more new heads than we demote former heads to non-head
1538 1539 if branchname is not None:
1539 1540 msg = _("abort: push creates new remote heads"
1540 1541 " on branch '%s'!\n") % branchname
1541 1542 else:
1542 1543 msg = _("abort: push creates new remote heads!\n")
1543 1544 self.ui.warn(msg)
1544 1545 if len(lheads) > len(rheads):
1545 1546 self.ui.status(_("(did you forget to merge?"
1546 1547 " use push -f to force)\n"))
1547 1548 else:
1548 1549 self.ui.status(_("(you should pull and merge or"
1549 1550 " use push -f to force)\n"))
1550 1551 return False
1551 1552 return True
1552 1553
1553 1554 if not bases:
1554 1555 self.ui.status(_("no changes found\n"))
1555 1556 return None, 1
1556 1557 elif not force:
1557 1558 # Check for each named branch if we're creating new remote heads.
1558 1559 # To be a remote head after push, node must be either:
1559 1560 # - unknown locally
1560 1561 # - a local outgoing head descended from update
1561 1562 # - a remote head that's known locally and not
1562 1563 # ancestral to an outgoing head
1563 1564 #
1564 1565 # New named branches cannot be created without --force.
1565 1566
1566 1567 if remote_heads != [nullid]:
1567 1568 if remote.capable('branchmap'):
1568 1569 remotebrheads = remote.branchmap()
1569 1570
1570 1571 if not revs:
1571 1572 localbrheads = self.branchmap()
1572 1573 else:
1573 1574 localbrheads = {}
1574 1575 ctxgen = (self[n] for n in msng_cl)
1575 1576 self._updatebranchcache(localbrheads, ctxgen)
1576 1577
1577 1578 newbranches = list(set(localbrheads) - set(remotebrheads))
1578 1579 if newbranches: # new branch requires --force
1579 1580 branchnames = ', '.join("%s" % b for b in newbranches)
1580 1581 self.ui.warn(_("abort: push creates "
1581 1582 "new remote branches: %s!\n")
1582 1583 % branchnames)
1583 1584 # propose 'push -b .' in the msg too?
1584 1585 self.ui.status(_("(use 'hg push -f' to force)\n"))
1585 1586 return None, 0
1586 1587 for branch, lheads in localbrheads.iteritems():
1587 1588 if branch in remotebrheads:
1588 1589 rheads = remotebrheads[branch]
1589 1590 if not checkbranch(lheads, rheads, branch):
1590 1591 return None, 0
1591 1592 else:
1592 1593 if not checkbranch(heads, remote_heads):
1593 1594 return None, 0
1594 1595
1595 1596 if inc:
1596 1597 self.ui.warn(_("note: unsynced remote changes!\n"))
1597 1598
1598 1599
1599 1600 if revs is None:
1600 1601 # use the fast path, no race possible on push
1601 1602 nodes = cl.findmissing(common.keys())
1602 1603 cg = self._changegroup(nodes, 'push')
1603 1604 else:
1604 1605 cg = self.changegroupsubset(update, revs, 'push')
1605 1606 return cg, remote_heads
1606 1607
1607 1608 def push_addchangegroup(self, remote, force, revs):
1608 1609 lock = remote.lock()
1609 1610 try:
1610 1611 ret = self.prepush(remote, force, revs)
1611 1612 if ret[0] is not None:
1612 1613 cg, remote_heads = ret
1613 1614 return remote.addchangegroup(cg, 'push', self.url())
1614 1615 return ret[1]
1615 1616 finally:
1616 1617 lock.release()
1617 1618
1618 1619 def push_unbundle(self, remote, force, revs):
1619 1620 # local repo finds heads on server, finds out what revs it
1620 1621 # must push. once revs transferred, if server finds it has
1621 1622 # different heads (someone else won commit/push race), server
1622 1623 # aborts.
1623 1624
1624 1625 ret = self.prepush(remote, force, revs)
1625 1626 if ret[0] is not None:
1626 1627 cg, remote_heads = ret
1627 1628 if force:
1628 1629 remote_heads = ['force']
1629 1630 return remote.unbundle(cg, remote_heads, 'push')
1630 1631 return ret[1]
1631 1632
1632 1633 def changegroupinfo(self, nodes, source):
1633 1634 if self.ui.verbose or source == 'bundle':
1634 1635 self.ui.status(_("%d changesets found\n") % len(nodes))
1635 1636 if self.ui.debugflag:
1636 1637 self.ui.debug("list of changesets:\n")
1637 1638 for node in nodes:
1638 1639 self.ui.debug("%s\n" % hex(node))
1639 1640
1640 1641 def changegroupsubset(self, bases, heads, source, extranodes=None):
1641 1642 """Compute a changegroup consisting of all the nodes that are
1642 1643 descendents of any of the bases and ancestors of any of the heads.
1643 1644 Return a chunkbuffer object whose read() method will return
1644 1645 successive changegroup chunks.
1645 1646
1646 1647 It is fairly complex as determining which filenodes and which
1647 1648 manifest nodes need to be included for the changeset to be complete
1648 1649 is non-trivial.
1649 1650
1650 1651 Another wrinkle is doing the reverse, figuring out which changeset in
1651 1652 the changegroup a particular filenode or manifestnode belongs to.
1652 1653
1653 1654 The caller can specify some nodes that must be included in the
1654 1655 changegroup using the extranodes argument. It should be a dict
1655 1656 where the keys are the filenames (or 1 for the manifest), and the
1656 1657 values are lists of (node, linknode) tuples, where node is a wanted
1657 1658 node and linknode is the changelog node that should be transmitted as
1658 1659 the linkrev.
1659 1660 """
1660 1661
1661 1662 # Set up some initial variables
1662 1663 # Make it easy to refer to self.changelog
1663 1664 cl = self.changelog
1664 1665 # msng is short for missing - compute the list of changesets in this
1665 1666 # changegroup.
1666 1667 if not bases:
1667 1668 bases = [nullid]
1668 1669 msng_cl_lst, bases, heads = cl.nodesbetween(bases, heads)
1669 1670
1670 1671 if extranodes is None:
1671 1672 # can we go through the fast path ?
1672 1673 heads.sort()
1673 1674 allheads = self.heads()
1674 1675 allheads.sort()
1675 1676 if heads == allheads:
1676 1677 return self._changegroup(msng_cl_lst, source)
1677 1678
1678 1679 # slow path
1679 1680 self.hook('preoutgoing', throw=True, source=source)
1680 1681
1681 1682 self.changegroupinfo(msng_cl_lst, source)
1682 1683 # Some bases may turn out to be superfluous, and some heads may be
1683 1684 # too. nodesbetween will return the minimal set of bases and heads
1684 1685 # necessary to re-create the changegroup.
1685 1686
1686 1687 # Known heads are the list of heads that it is assumed the recipient
1687 1688 # of this changegroup will know about.
1688 1689 knownheads = set()
1689 1690 # We assume that all parents of bases are known heads.
1690 1691 for n in bases:
1691 1692 knownheads.update(cl.parents(n))
1692 1693 knownheads.discard(nullid)
1693 1694 knownheads = list(knownheads)
1694 1695 if knownheads:
1695 1696 # Now that we know what heads are known, we can compute which
1696 1697 # changesets are known. The recipient must know about all
1697 1698 # changesets required to reach the known heads from the null
1698 1699 # changeset.
1699 1700 has_cl_set, junk, junk = cl.nodesbetween(None, knownheads)
1700 1701 junk = None
1701 1702 # Transform the list into a set.
1702 1703 has_cl_set = set(has_cl_set)
1703 1704 else:
1704 1705 # If there were no known heads, the recipient cannot be assumed to
1705 1706 # know about any changesets.
1706 1707 has_cl_set = set()
1707 1708
1708 1709 # Make it easy to refer to self.manifest
1709 1710 mnfst = self.manifest
1710 1711 # We don't know which manifests are missing yet
1711 1712 msng_mnfst_set = {}
1712 1713 # Nor do we know which filenodes are missing.
1713 1714 msng_filenode_set = {}
1714 1715
1715 1716 junk = mnfst.index[len(mnfst) - 1] # Get around a bug in lazyindex
1716 1717 junk = None
1717 1718
1718 1719 # A changeset always belongs to itself, so the changenode lookup
1719 1720 # function for a changenode is identity.
1720 1721 def identity(x):
1721 1722 return x
1722 1723
1723 1724 # If we determine that a particular file or manifest node must be a
1724 1725 # node that the recipient of the changegroup will already have, we can
1725 1726 # also assume the recipient will have all the parents. This function
1726 1727 # prunes them from the set of missing nodes.
1727 1728 def prune_parents(revlog, hasset, msngset):
1728 1729 for r in revlog.ancestors(*[revlog.rev(n) for n in hasset]):
1729 1730 msngset.pop(revlog.node(r), None)
1730 1731
1731 1732 # Use the information collected in collect_manifests_and_files to say
1732 1733 # which changenode any manifestnode belongs to.
1733 1734 def lookup_manifest_link(mnfstnode):
1734 1735 return msng_mnfst_set[mnfstnode]
1735 1736
1736 1737 # A function generating function that sets up the initial environment
1737 1738 # the inner function.
1738 1739 def filenode_collector(changedfiles):
1739 1740 # This gathers information from each manifestnode included in the
1740 1741 # changegroup about which filenodes the manifest node references
1741 1742 # so we can include those in the changegroup too.
1742 1743 #
1743 1744 # It also remembers which changenode each filenode belongs to. It
1744 1745 # does this by assuming the a filenode belongs to the changenode
1745 1746 # the first manifest that references it belongs to.
1746 1747 def collect_msng_filenodes(mnfstnode):
1747 1748 r = mnfst.rev(mnfstnode)
1748 1749 if r - 1 in mnfst.parentrevs(r):
1749 1750 # If the previous rev is one of the parents,
1750 1751 # we only need to see a diff.
1751 1752 deltamf = mnfst.readdelta(mnfstnode)
1752 1753 # For each line in the delta
1753 1754 for f, fnode in deltamf.iteritems():
1754 1755 f = changedfiles.get(f, None)
1755 1756 # And if the file is in the list of files we care
1756 1757 # about.
1757 1758 if f is not None:
1758 1759 # Get the changenode this manifest belongs to
1759 1760 clnode = msng_mnfst_set[mnfstnode]
1760 1761 # Create the set of filenodes for the file if
1761 1762 # there isn't one already.
1762 1763 ndset = msng_filenode_set.setdefault(f, {})
1763 1764 # And set the filenode's changelog node to the
1764 1765 # manifest's if it hasn't been set already.
1765 1766 ndset.setdefault(fnode, clnode)
1766 1767 else:
1767 1768 # Otherwise we need a full manifest.
1768 1769 m = mnfst.read(mnfstnode)
1769 1770 # For every file in we care about.
1770 1771 for f in changedfiles:
1771 1772 fnode = m.get(f, None)
1772 1773 # If it's in the manifest
1773 1774 if fnode is not None:
1774 1775 # See comments above.
1775 1776 clnode = msng_mnfst_set[mnfstnode]
1776 1777 ndset = msng_filenode_set.setdefault(f, {})
1777 1778 ndset.setdefault(fnode, clnode)
1778 1779 return collect_msng_filenodes
1779 1780
1780 1781 # We have a list of filenodes we think we need for a file, lets remove
1781 1782 # all those we know the recipient must have.
1782 1783 def prune_filenodes(f, filerevlog):
1783 1784 msngset = msng_filenode_set[f]
1784 1785 hasset = set()
1785 1786 # If a 'missing' filenode thinks it belongs to a changenode we
1786 1787 # assume the recipient must have, then the recipient must have
1787 1788 # that filenode.
1788 1789 for n in msngset:
1789 1790 clnode = cl.node(filerevlog.linkrev(filerevlog.rev(n)))
1790 1791 if clnode in has_cl_set:
1791 1792 hasset.add(n)
1792 1793 prune_parents(filerevlog, hasset, msngset)
1793 1794
1794 1795 # A function generator function that sets up the a context for the
1795 1796 # inner function.
1796 1797 def lookup_filenode_link_func(fname):
1797 1798 msngset = msng_filenode_set[fname]
1798 1799 # Lookup the changenode the filenode belongs to.
1799 1800 def lookup_filenode_link(fnode):
1800 1801 return msngset[fnode]
1801 1802 return lookup_filenode_link
1802 1803
1803 1804 # Add the nodes that were explicitly requested.
1804 1805 def add_extra_nodes(name, nodes):
1805 1806 if not extranodes or name not in extranodes:
1806 1807 return
1807 1808
1808 1809 for node, linknode in extranodes[name]:
1809 1810 if node not in nodes:
1810 1811 nodes[node] = linknode
1811 1812
1812 1813 # Now that we have all theses utility functions to help out and
1813 1814 # logically divide up the task, generate the group.
1814 1815 def gengroup():
1815 1816 # The set of changed files starts empty.
1816 1817 changedfiles = {}
1817 1818 collect = changegroup.collector(cl, msng_mnfst_set, changedfiles)
1818 1819
1819 1820 # Create a changenode group generator that will call our functions
1820 1821 # back to lookup the owning changenode and collect information.
1821 1822 group = cl.group(msng_cl_lst, identity, collect)
1822 1823 cnt = 0
1823 1824 for chnk in group:
1824 1825 yield chnk
1825 1826 self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
1826 1827 cnt += 1
1827 1828 self.ui.progress(_('bundling changes'), None)
1828 1829
1829 1830
1830 1831 # Figure out which manifest nodes (of the ones we think might be
1831 1832 # part of the changegroup) the recipient must know about and
1832 1833 # remove them from the changegroup.
1833 1834 has_mnfst_set = set()
1834 1835 for n in msng_mnfst_set:
1835 1836 # If a 'missing' manifest thinks it belongs to a changenode
1836 1837 # the recipient is assumed to have, obviously the recipient
1837 1838 # must have that manifest.
1838 1839 linknode = cl.node(mnfst.linkrev(mnfst.rev(n)))
1839 1840 if linknode in has_cl_set:
1840 1841 has_mnfst_set.add(n)
1841 1842 prune_parents(mnfst, has_mnfst_set, msng_mnfst_set)
1842 1843 add_extra_nodes(1, msng_mnfst_set)
1843 1844 msng_mnfst_lst = msng_mnfst_set.keys()
1844 1845 # Sort the manifestnodes by revision number.
1845 1846 msng_mnfst_lst.sort(key=mnfst.rev)
1846 1847 # Create a generator for the manifestnodes that calls our lookup
1847 1848 # and data collection functions back.
1848 1849 group = mnfst.group(msng_mnfst_lst, lookup_manifest_link,
1849 1850 filenode_collector(changedfiles))
1850 1851 cnt = 0
1851 1852 for chnk in group:
1852 1853 yield chnk
1853 1854 self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
1854 1855 cnt += 1
1855 1856 self.ui.progress(_('bundling manifests'), None)
1856 1857
1857 1858 # These are no longer needed, dereference and toss the memory for
1858 1859 # them.
1859 1860 msng_mnfst_lst = None
1860 1861 msng_mnfst_set.clear()
1861 1862
1862 1863 if extranodes:
1863 1864 for fname in extranodes:
1864 1865 if isinstance(fname, int):
1865 1866 continue
1866 1867 msng_filenode_set.setdefault(fname, {})
1867 1868 changedfiles[fname] = 1
1868 1869 # Go through all our files in order sorted by name.
1869 1870 cnt = 0
1870 1871 for fname in sorted(changedfiles):
1871 1872 filerevlog = self.file(fname)
1872 1873 if not len(filerevlog):
1873 1874 raise util.Abort(_("empty or missing revlog for %s") % fname)
1874 1875 # Toss out the filenodes that the recipient isn't really
1875 1876 # missing.
1876 1877 if fname in msng_filenode_set:
1877 1878 prune_filenodes(fname, filerevlog)
1878 1879 add_extra_nodes(fname, msng_filenode_set[fname])
1879 1880 msng_filenode_lst = msng_filenode_set[fname].keys()
1880 1881 else:
1881 1882 msng_filenode_lst = []
1882 1883 # If any filenodes are left, generate the group for them,
1883 1884 # otherwise don't bother.
1884 1885 if len(msng_filenode_lst) > 0:
1885 1886 yield changegroup.chunkheader(len(fname))
1886 1887 yield fname
1887 1888 # Sort the filenodes by their revision #
1888 1889 msng_filenode_lst.sort(key=filerevlog.rev)
1889 1890 # Create a group generator and only pass in a changenode
1890 1891 # lookup function as we need to collect no information
1891 1892 # from filenodes.
1892 1893 group = filerevlog.group(msng_filenode_lst,
1893 1894 lookup_filenode_link_func(fname))
1894 1895 for chnk in group:
1895 1896 self.ui.progress(
1896 1897 _('bundling files'), cnt, item=fname, unit=_('chunks'))
1897 1898 cnt += 1
1898 1899 yield chnk
1899 1900 if fname in msng_filenode_set:
1900 1901 # Don't need this anymore, toss it to free memory.
1901 1902 del msng_filenode_set[fname]
1902 1903 # Signal that no more groups are left.
1903 1904 yield changegroup.closechunk()
1904 1905 self.ui.progress(_('bundling files'), None)
1905 1906
1906 1907 if msng_cl_lst:
1907 1908 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1908 1909
1909 1910 return util.chunkbuffer(gengroup())
1910 1911
1911 1912 def changegroup(self, basenodes, source):
1912 1913 # to avoid a race we use changegroupsubset() (issue1320)
1913 1914 return self.changegroupsubset(basenodes, self.heads(), source)
1914 1915
1915 1916 def _changegroup(self, nodes, source):
1916 1917 """Compute the changegroup of all nodes that we have that a recipient
1917 1918 doesn't. Return a chunkbuffer object whose read() method will return
1918 1919 successive changegroup chunks.
1919 1920
1920 1921 This is much easier than the previous function as we can assume that
1921 1922 the recipient has any changenode we aren't sending them.
1922 1923
1923 1924 nodes is the set of nodes to send"""
1924 1925
1925 1926 self.hook('preoutgoing', throw=True, source=source)
1926 1927
1927 1928 cl = self.changelog
1928 1929 revset = set([cl.rev(n) for n in nodes])
1929 1930 self.changegroupinfo(nodes, source)
1930 1931
1931 1932 def identity(x):
1932 1933 return x
1933 1934
1934 1935 def gennodelst(log):
1935 1936 for r in log:
1936 1937 if log.linkrev(r) in revset:
1937 1938 yield log.node(r)
1938 1939
1939 1940 def lookuprevlink_func(revlog):
1940 1941 def lookuprevlink(n):
1941 1942 return cl.node(revlog.linkrev(revlog.rev(n)))
1942 1943 return lookuprevlink
1943 1944
1944 1945 def gengroup():
1945 1946 '''yield a sequence of changegroup chunks (strings)'''
1946 1947 # construct a list of all changed files
1947 1948 changedfiles = {}
1948 1949 mmfs = {}
1949 1950 collect = changegroup.collector(cl, mmfs, changedfiles)
1950 1951
1951 1952 cnt = 0
1952 1953 for chnk in cl.group(nodes, identity, collect):
1953 1954 self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
1954 1955 cnt += 1
1955 1956 yield chnk
1956 1957 self.ui.progress(_('bundling changes'), None)
1957 1958
1958 1959 mnfst = self.manifest
1959 1960 nodeiter = gennodelst(mnfst)
1960 1961 cnt = 0
1961 1962 for chnk in mnfst.group(nodeiter, lookuprevlink_func(mnfst)):
1962 1963 self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
1963 1964 cnt += 1
1964 1965 yield chnk
1965 1966 self.ui.progress(_('bundling manifests'), None)
1966 1967
1967 1968 cnt = 0
1968 1969 for fname in sorted(changedfiles):
1969 1970 filerevlog = self.file(fname)
1970 1971 if not len(filerevlog):
1971 1972 raise util.Abort(_("empty or missing revlog for %s") % fname)
1972 1973 nodeiter = gennodelst(filerevlog)
1973 1974 nodeiter = list(nodeiter)
1974 1975 if nodeiter:
1975 1976 yield changegroup.chunkheader(len(fname))
1976 1977 yield fname
1977 1978 lookup = lookuprevlink_func(filerevlog)
1978 1979 for chnk in filerevlog.group(nodeiter, lookup):
1979 1980 self.ui.progress(
1980 1981 _('bundling files'), cnt, item=fname, unit=_('chunks'))
1981 1982 cnt += 1
1982 1983 yield chnk
1983 1984 self.ui.progress(_('bundling files'), None)
1984 1985
1985 1986 yield changegroup.closechunk()
1986 1987
1987 1988 if nodes:
1988 1989 self.hook('outgoing', node=hex(nodes[0]), source=source)
1989 1990
1990 1991 return util.chunkbuffer(gengroup())
1991 1992
1992 1993 def addchangegroup(self, source, srctype, url, emptyok=False):
1993 1994 """add changegroup to repo.
1994 1995
1995 1996 return values:
1996 1997 - nothing changed or no source: 0
1997 1998 - more heads than before: 1+added heads (2..n)
1998 1999 - less heads than before: -1-removed heads (-2..-n)
1999 2000 - number of heads stays the same: 1
2000 2001 """
2001 2002 def csmap(x):
2002 2003 self.ui.debug("add changeset %s\n" % short(x))
2003 2004 return len(cl)
2004 2005
2005 2006 def revmap(x):
2006 2007 return cl.rev(x)
2007 2008
2008 2009 if not source:
2009 2010 return 0
2010 2011
2011 2012 self.hook('prechangegroup', throw=True, source=srctype, url=url)
2012 2013
2013 2014 changesets = files = revisions = 0
2014 2015 efiles = set()
2015 2016
2016 2017 # write changelog data to temp files so concurrent readers will not see
2017 2018 # inconsistent view
2018 2019 cl = self.changelog
2019 2020 cl.delayupdate()
2020 2021 oldheads = len(cl.heads())
2021 2022
2022 2023 tr = self.transaction("\n".join([srctype, urlmod.hidepassword(url)]))
2023 2024 try:
2024 2025 trp = weakref.proxy(tr)
2025 2026 # pull off the changeset group
2026 2027 self.ui.status(_("adding changesets\n"))
2027 2028 clstart = len(cl)
2028 2029 class prog(object):
2029 2030 step = _('changesets')
2030 2031 count = 1
2031 2032 ui = self.ui
2032 2033 total = None
2033 2034 def __call__(self):
2034 2035 self.ui.progress(self.step, self.count, unit=_('chunks'),
2035 2036 total=self.total)
2036 2037 self.count += 1
2037 2038 pr = prog()
2038 2039 chunkiter = changegroup.chunkiter(source, progress=pr)
2039 2040 if cl.addgroup(chunkiter, csmap, trp) is None and not emptyok:
2040 2041 raise util.Abort(_("received changelog group is empty"))
2041 2042 clend = len(cl)
2042 2043 changesets = clend - clstart
2043 2044 for c in xrange(clstart, clend):
2044 2045 efiles.update(self[c].files())
2045 2046 efiles = len(efiles)
2046 2047 self.ui.progress(_('changesets'), None)
2047 2048
2048 2049 # pull off the manifest group
2049 2050 self.ui.status(_("adding manifests\n"))
2050 2051 pr.step = _('manifests')
2051 2052 pr.count = 1
2052 2053 pr.total = changesets # manifests <= changesets
2053 2054 chunkiter = changegroup.chunkiter(source, progress=pr)
2054 2055 # no need to check for empty manifest group here:
2055 2056 # if the result of the merge of 1 and 2 is the same in 3 and 4,
2056 2057 # no new manifest will be created and the manifest group will
2057 2058 # be empty during the pull
2058 2059 self.manifest.addgroup(chunkiter, revmap, trp)
2059 2060 self.ui.progress(_('manifests'), None)
2060 2061
2061 2062 needfiles = {}
2062 2063 if self.ui.configbool('server', 'validate', default=False):
2063 2064 # validate incoming csets have their manifests
2064 2065 for cset in xrange(clstart, clend):
2065 2066 mfest = self.changelog.read(self.changelog.node(cset))[0]
2066 2067 mfest = self.manifest.readdelta(mfest)
2067 2068 # store file nodes we must see
2068 2069 for f, n in mfest.iteritems():
2069 2070 needfiles.setdefault(f, set()).add(n)
2070 2071
2071 2072 # process the files
2072 2073 self.ui.status(_("adding file changes\n"))
2073 2074 pr.step = 'files'
2074 2075 pr.count = 1
2075 2076 pr.total = efiles
2076 2077 while 1:
2077 2078 f = changegroup.getchunk(source)
2078 2079 if not f:
2079 2080 break
2080 2081 self.ui.debug("adding %s revisions\n" % f)
2081 2082 pr()
2082 2083 fl = self.file(f)
2083 2084 o = len(fl)
2084 2085 chunkiter = changegroup.chunkiter(source)
2085 2086 if fl.addgroup(chunkiter, revmap, trp) is None:
2086 2087 raise util.Abort(_("received file revlog group is empty"))
2087 2088 revisions += len(fl) - o
2088 2089 files += 1
2089 2090 if f in needfiles:
2090 2091 needs = needfiles[f]
2091 2092 for new in xrange(o, len(fl)):
2092 2093 n = fl.node(new)
2093 2094 if n in needs:
2094 2095 needs.remove(n)
2095 2096 if not needs:
2096 2097 del needfiles[f]
2097 2098 self.ui.progress(_('files'), None)
2098 2099
2099 2100 for f, needs in needfiles.iteritems():
2100 2101 fl = self.file(f)
2101 2102 for n in needs:
2102 2103 try:
2103 2104 fl.rev(n)
2104 2105 except error.LookupError:
2105 2106 raise util.Abort(
2106 2107 _('missing file data for %s:%s - run hg verify') %
2107 2108 (f, hex(n)))
2108 2109
2109 2110 newheads = len(cl.heads())
2110 2111 heads = ""
2111 2112 if oldheads and newheads != oldheads:
2112 2113 heads = _(" (%+d heads)") % (newheads - oldheads)
2113 2114
2114 2115 self.ui.status(_("added %d changesets"
2115 2116 " with %d changes to %d files%s\n")
2116 2117 % (changesets, revisions, files, heads))
2117 2118
2118 2119 if changesets > 0:
2119 2120 p = lambda: cl.writepending() and self.root or ""
2120 2121 self.hook('pretxnchangegroup', throw=True,
2121 2122 node=hex(cl.node(clstart)), source=srctype,
2122 2123 url=url, pending=p)
2123 2124
2124 2125 # make changelog see real files again
2125 2126 cl.finalize(trp)
2126 2127
2127 2128 tr.close()
2128 2129 finally:
2129 2130 del tr
2130 2131
2131 2132 if changesets > 0:
2132 2133 # forcefully update the on-disk branch cache
2133 2134 self.ui.debug("updating the branch cache\n")
2134 2135 self.branchtags()
2135 2136 self.hook("changegroup", node=hex(cl.node(clstart)),
2136 2137 source=srctype, url=url)
2137 2138
2138 2139 for i in xrange(clstart, clend):
2139 2140 self.hook("incoming", node=hex(cl.node(i)),
2140 2141 source=srctype, url=url)
2141 2142
2142 2143 # never return 0 here:
2143 2144 if newheads < oldheads:
2144 2145 return newheads - oldheads - 1
2145 2146 else:
2146 2147 return newheads - oldheads + 1
2147 2148
2148 2149
2149 2150 def stream_in(self, remote):
2150 2151 fp = remote.stream_out()
2151 2152 l = fp.readline()
2152 2153 try:
2153 2154 resp = int(l)
2154 2155 except ValueError:
2155 2156 raise error.ResponseError(
2156 2157 _('Unexpected response from remote server:'), l)
2157 2158 if resp == 1:
2158 2159 raise util.Abort(_('operation forbidden by server'))
2159 2160 elif resp == 2:
2160 2161 raise util.Abort(_('locking the remote repository failed'))
2161 2162 elif resp != 0:
2162 2163 raise util.Abort(_('the server sent an unknown error code'))
2163 2164 self.ui.status(_('streaming all changes\n'))
2164 2165 l = fp.readline()
2165 2166 try:
2166 2167 total_files, total_bytes = map(int, l.split(' ', 1))
2167 2168 except (ValueError, TypeError):
2168 2169 raise error.ResponseError(
2169 2170 _('Unexpected response from remote server:'), l)
2170 2171 self.ui.status(_('%d files to transfer, %s of data\n') %
2171 2172 (total_files, util.bytecount(total_bytes)))
2172 2173 start = time.time()
2173 2174 for i in xrange(total_files):
2174 2175 # XXX doesn't support '\n' or '\r' in filenames
2175 2176 l = fp.readline()
2176 2177 try:
2177 2178 name, size = l.split('\0', 1)
2178 2179 size = int(size)
2179 2180 except (ValueError, TypeError):
2180 2181 raise error.ResponseError(
2181 2182 _('Unexpected response from remote server:'), l)
2182 2183 self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size)))
2183 2184 # for backwards compat, name was partially encoded
2184 2185 ofp = self.sopener(store.decodedir(name), 'w')
2185 2186 for chunk in util.filechunkiter(fp, limit=size):
2186 2187 ofp.write(chunk)
2187 2188 ofp.close()
2188 2189 elapsed = time.time() - start
2189 2190 if elapsed <= 0:
2190 2191 elapsed = 0.001
2191 2192 self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
2192 2193 (util.bytecount(total_bytes), elapsed,
2193 2194 util.bytecount(total_bytes / elapsed)))
2194 2195 self.invalidate()
2195 2196 return len(self.heads()) + 1
2196 2197
2197 2198 def clone(self, remote, heads=[], stream=False):
2198 2199 '''clone remote repository.
2199 2200
2200 2201 keyword arguments:
2201 2202 heads: list of revs to clone (forces use of pull)
2202 2203 stream: use streaming clone if possible'''
2203 2204
2204 2205 # now, all clients that can request uncompressed clones can
2205 2206 # read repo formats supported by all servers that can serve
2206 2207 # them.
2207 2208
2208 2209 # if revlog format changes, client will have to check version
2209 2210 # and format flags on "stream" capability, and use
2210 2211 # uncompressed only if compatible.
2211 2212
2212 2213 if stream and not heads and remote.capable('stream'):
2213 2214 return self.stream_in(remote)
2214 2215 return self.pull(remote, heads)
2215 2216
2216 2217 # used to avoid circular references so destructors work
2217 2218 def aftertrans(files):
2218 2219 renamefiles = [tuple(t) for t in files]
2219 2220 def a():
2220 2221 for src, dest in renamefiles:
2221 2222 util.rename(src, dest)
2222 2223 return a
2223 2224
2224 2225 def instance(ui, path, create):
2225 2226 return localrepository(ui, util.drop_scheme('file', path), create)
2226 2227
2227 2228 def islocal(path):
2228 2229 return True
@@ -1,1165 +1,1165 b''
1 1 3:911600dab2ae
2 2 requesting all changes
3 3 adding changesets
4 4 adding manifests
5 5 adding file changes
6 6 added 1 changesets with 3 changes to 3 files
7 7 updating to branch default
8 8 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
9 9
10 10 Extension disabled for lack of a hook
11 11 Pushing as user fred
12 12 hgrc = """
13 13 """
14 14 pushing to ../b
15 15 searching for changes
16 16 common changesets up to 6675d58eff77
17 17 3 changesets found
18 18 list of changesets:
19 19 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
20 20 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
21 21 911600dab2ae7a9baff75958b84fe606851ce955
22 22 adding changesets
23 23 bundling changes: 0 chunks
24 24 bundling changes: 1 chunks
25 25 bundling changes: 2 chunks
26 26 bundling changes: 3 chunks
27 27 bundling changes: 4 chunks
28 28 bundling changes: 5 chunks
29 29 bundling changes: 6 chunks
30 30 bundling changes: 7 chunks
31 31 bundling changes: 8 chunks
32 32 bundling changes: 9 chunks
33 33 bundling manifests: 0 chunks
34 34 bundling manifests: 1 chunks
35 35 bundling manifests: 2 chunks
36 36 bundling manifests: 3 chunks
37 37 bundling manifests: 4 chunks
38 38 bundling manifests: 5 chunks
39 39 bundling manifests: 6 chunks
40 40 bundling manifests: 7 chunks
41 41 bundling manifests: 8 chunks
42 42 bundling manifests: 9 chunks
43 43 bundling files: foo/Bar/file.txt 0 chunks
44 44 bundling files: foo/Bar/file.txt 1 chunks
45 45 bundling files: foo/Bar/file.txt 2 chunks
46 46 bundling files: foo/Bar/file.txt 3 chunks
47 47 bundling files: foo/file.txt 4 chunks
48 48 bundling files: foo/file.txt 5 chunks
49 49 bundling files: foo/file.txt 6 chunks
50 50 bundling files: foo/file.txt 7 chunks
51 51 bundling files: quux/file.py 8 chunks
52 52 bundling files: quux/file.py 9 chunks
53 53 bundling files: quux/file.py 10 chunks
54 54 bundling files: quux/file.py 11 chunks
55 55 changesets: 1 chunks
56 56 add changeset ef1ea85a6374
57 57 changesets: 2 chunks
58 58 add changeset f9cafe1212c8
59 59 changesets: 3 chunks
60 60 add changeset 911600dab2ae
61 61 adding manifests
62 62 manifests: 1/3 chunks (33.33%)
63 63 manifests: 2/3 chunks (66.67%)
64 64 manifests: 3/3 chunks (100.00%)
65 65 adding file changes
66 66 adding foo/Bar/file.txt revisions
67 67 files: 1/3 chunks (33.33%)
68 68 adding foo/file.txt revisions
69 69 files: 2/3 chunks (66.67%)
70 70 adding quux/file.py revisions
71 71 files: 3/3 chunks (100.00%)
72 72 added 3 changesets with 3 changes to 3 files
73 73 updating the branch cache
74 rolling back push to revision 1
74 rolling back to revision 1 (undo push)
75 75 0:6675d58eff77
76 76
77 77 Extension disabled for lack of acl.sources
78 78 Pushing as user fred
79 79 hgrc = """
80 80 [hooks]
81 81 pretxnchangegroup.acl = python:hgext.acl.hook
82 82 """
83 83 pushing to ../b
84 84 searching for changes
85 85 common changesets up to 6675d58eff77
86 86 invalidating branch cache (tip differs)
87 87 3 changesets found
88 88 list of changesets:
89 89 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
90 90 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
91 91 911600dab2ae7a9baff75958b84fe606851ce955
92 92 adding changesets
93 93 bundling changes: 0 chunks
94 94 bundling changes: 1 chunks
95 95 bundling changes: 2 chunks
96 96 bundling changes: 3 chunks
97 97 bundling changes: 4 chunks
98 98 bundling changes: 5 chunks
99 99 bundling changes: 6 chunks
100 100 bundling changes: 7 chunks
101 101 bundling changes: 8 chunks
102 102 bundling changes: 9 chunks
103 103 bundling manifests: 0 chunks
104 104 bundling manifests: 1 chunks
105 105 bundling manifests: 2 chunks
106 106 bundling manifests: 3 chunks
107 107 bundling manifests: 4 chunks
108 108 bundling manifests: 5 chunks
109 109 bundling manifests: 6 chunks
110 110 bundling manifests: 7 chunks
111 111 bundling manifests: 8 chunks
112 112 bundling manifests: 9 chunks
113 113 bundling files: foo/Bar/file.txt 0 chunks
114 114 bundling files: foo/Bar/file.txt 1 chunks
115 115 bundling files: foo/Bar/file.txt 2 chunks
116 116 bundling files: foo/Bar/file.txt 3 chunks
117 117 bundling files: foo/file.txt 4 chunks
118 118 bundling files: foo/file.txt 5 chunks
119 119 bundling files: foo/file.txt 6 chunks
120 120 bundling files: foo/file.txt 7 chunks
121 121 bundling files: quux/file.py 8 chunks
122 122 bundling files: quux/file.py 9 chunks
123 123 bundling files: quux/file.py 10 chunks
124 124 bundling files: quux/file.py 11 chunks
125 125 changesets: 1 chunks
126 126 add changeset ef1ea85a6374
127 127 changesets: 2 chunks
128 128 add changeset f9cafe1212c8
129 129 changesets: 3 chunks
130 130 add changeset 911600dab2ae
131 131 adding manifests
132 132 manifests: 1/3 chunks (33.33%)
133 133 manifests: 2/3 chunks (66.67%)
134 134 manifests: 3/3 chunks (100.00%)
135 135 adding file changes
136 136 adding foo/Bar/file.txt revisions
137 137 files: 1/3 chunks (33.33%)
138 138 adding foo/file.txt revisions
139 139 files: 2/3 chunks (66.67%)
140 140 adding quux/file.py revisions
141 141 files: 3/3 chunks (100.00%)
142 142 added 3 changesets with 3 changes to 3 files
143 143 calling hook pretxnchangegroup.acl: hgext.acl.hook
144 144 acl: changes have source "push" - skipping
145 145 updating the branch cache
146 rolling back push to revision 1
146 rolling back to revision 1 (undo push)
147 147 0:6675d58eff77
148 148
149 149 No [acl.allow]/[acl.deny]
150 150 Pushing as user fred
151 151 hgrc = """
152 152 [hooks]
153 153 pretxnchangegroup.acl = python:hgext.acl.hook
154 154 [acl]
155 155 sources = push
156 156 """
157 157 pushing to ../b
158 158 searching for changes
159 159 common changesets up to 6675d58eff77
160 160 invalidating branch cache (tip differs)
161 161 3 changesets found
162 162 list of changesets:
163 163 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
164 164 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
165 165 911600dab2ae7a9baff75958b84fe606851ce955
166 166 adding changesets
167 167 bundling changes: 0 chunks
168 168 bundling changes: 1 chunks
169 169 bundling changes: 2 chunks
170 170 bundling changes: 3 chunks
171 171 bundling changes: 4 chunks
172 172 bundling changes: 5 chunks
173 173 bundling changes: 6 chunks
174 174 bundling changes: 7 chunks
175 175 bundling changes: 8 chunks
176 176 bundling changes: 9 chunks
177 177 bundling manifests: 0 chunks
178 178 bundling manifests: 1 chunks
179 179 bundling manifests: 2 chunks
180 180 bundling manifests: 3 chunks
181 181 bundling manifests: 4 chunks
182 182 bundling manifests: 5 chunks
183 183 bundling manifests: 6 chunks
184 184 bundling manifests: 7 chunks
185 185 bundling manifests: 8 chunks
186 186 bundling manifests: 9 chunks
187 187 bundling files: foo/Bar/file.txt 0 chunks
188 188 bundling files: foo/Bar/file.txt 1 chunks
189 189 bundling files: foo/Bar/file.txt 2 chunks
190 190 bundling files: foo/Bar/file.txt 3 chunks
191 191 bundling files: foo/file.txt 4 chunks
192 192 bundling files: foo/file.txt 5 chunks
193 193 bundling files: foo/file.txt 6 chunks
194 194 bundling files: foo/file.txt 7 chunks
195 195 bundling files: quux/file.py 8 chunks
196 196 bundling files: quux/file.py 9 chunks
197 197 bundling files: quux/file.py 10 chunks
198 198 bundling files: quux/file.py 11 chunks
199 199 changesets: 1 chunks
200 200 add changeset ef1ea85a6374
201 201 changesets: 2 chunks
202 202 add changeset f9cafe1212c8
203 203 changesets: 3 chunks
204 204 add changeset 911600dab2ae
205 205 adding manifests
206 206 manifests: 1/3 chunks (33.33%)
207 207 manifests: 2/3 chunks (66.67%)
208 208 manifests: 3/3 chunks (100.00%)
209 209 adding file changes
210 210 adding foo/Bar/file.txt revisions
211 211 files: 1/3 chunks (33.33%)
212 212 adding foo/file.txt revisions
213 213 files: 2/3 chunks (66.67%)
214 214 adding quux/file.py revisions
215 215 files: 3/3 chunks (100.00%)
216 216 added 3 changesets with 3 changes to 3 files
217 217 calling hook pretxnchangegroup.acl: hgext.acl.hook
218 218 acl: acl.allow not enabled
219 219 acl: acl.deny not enabled
220 220 acl: allowing changeset ef1ea85a6374
221 221 acl: allowing changeset f9cafe1212c8
222 222 acl: allowing changeset 911600dab2ae
223 223 updating the branch cache
224 rolling back push to revision 1
224 rolling back to revision 1 (undo push)
225 225 0:6675d58eff77
226 226
227 227 Empty [acl.allow]
228 228 Pushing as user fred
229 229 hgrc = """
230 230 [hooks]
231 231 pretxnchangegroup.acl = python:hgext.acl.hook
232 232 [acl]
233 233 sources = push
234 234 [acl.allow]
235 235 """
236 236 pushing to ../b
237 237 searching for changes
238 238 common changesets up to 6675d58eff77
239 239 invalidating branch cache (tip differs)
240 240 3 changesets found
241 241 list of changesets:
242 242 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
243 243 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
244 244 911600dab2ae7a9baff75958b84fe606851ce955
245 245 adding changesets
246 246 bundling changes: 0 chunks
247 247 bundling changes: 1 chunks
248 248 bundling changes: 2 chunks
249 249 bundling changes: 3 chunks
250 250 bundling changes: 4 chunks
251 251 bundling changes: 5 chunks
252 252 bundling changes: 6 chunks
253 253 bundling changes: 7 chunks
254 254 bundling changes: 8 chunks
255 255 bundling changes: 9 chunks
256 256 bundling manifests: 0 chunks
257 257 bundling manifests: 1 chunks
258 258 bundling manifests: 2 chunks
259 259 bundling manifests: 3 chunks
260 260 bundling manifests: 4 chunks
261 261 bundling manifests: 5 chunks
262 262 bundling manifests: 6 chunks
263 263 bundling manifests: 7 chunks
264 264 bundling manifests: 8 chunks
265 265 bundling manifests: 9 chunks
266 266 bundling files: foo/Bar/file.txt 0 chunks
267 267 bundling files: foo/Bar/file.txt 1 chunks
268 268 bundling files: foo/Bar/file.txt 2 chunks
269 269 bundling files: foo/Bar/file.txt 3 chunks
270 270 bundling files: foo/file.txt 4 chunks
271 271 bundling files: foo/file.txt 5 chunks
272 272 bundling files: foo/file.txt 6 chunks
273 273 bundling files: foo/file.txt 7 chunks
274 274 bundling files: quux/file.py 8 chunks
275 275 bundling files: quux/file.py 9 chunks
276 276 bundling files: quux/file.py 10 chunks
277 277 bundling files: quux/file.py 11 chunks
278 278 changesets: 1 chunks
279 279 add changeset ef1ea85a6374
280 280 changesets: 2 chunks
281 281 add changeset f9cafe1212c8
282 282 changesets: 3 chunks
283 283 add changeset 911600dab2ae
284 284 adding manifests
285 285 manifests: 1/3 chunks (33.33%)
286 286 manifests: 2/3 chunks (66.67%)
287 287 manifests: 3/3 chunks (100.00%)
288 288 adding file changes
289 289 adding foo/Bar/file.txt revisions
290 290 files: 1/3 chunks (33.33%)
291 291 adding foo/file.txt revisions
292 292 files: 2/3 chunks (66.67%)
293 293 adding quux/file.py revisions
294 294 files: 3/3 chunks (100.00%)
295 295 added 3 changesets with 3 changes to 3 files
296 296 calling hook pretxnchangegroup.acl: hgext.acl.hook
297 297 acl: acl.allow enabled, 0 entries for user fred
298 298 acl: acl.deny not enabled
299 299 acl: user fred not allowed on foo/file.txt
300 300 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
301 301 transaction abort!
302 302 rollback completed
303 303 abort: acl: access denied for changeset ef1ea85a6374
304 304 no rollback information available
305 305 0:6675d58eff77
306 306
307 307 fred is allowed inside foo/
308 308 Pushing as user fred
309 309 hgrc = """
310 310 [hooks]
311 311 pretxnchangegroup.acl = python:hgext.acl.hook
312 312 [acl]
313 313 sources = push
314 314 [acl.allow]
315 315 foo/** = fred
316 316 """
317 317 pushing to ../b
318 318 searching for changes
319 319 common changesets up to 6675d58eff77
320 320 3 changesets found
321 321 list of changesets:
322 322 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
323 323 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
324 324 911600dab2ae7a9baff75958b84fe606851ce955
325 325 adding changesets
326 326 bundling changes: 0 chunks
327 327 bundling changes: 1 chunks
328 328 bundling changes: 2 chunks
329 329 bundling changes: 3 chunks
330 330 bundling changes: 4 chunks
331 331 bundling changes: 5 chunks
332 332 bundling changes: 6 chunks
333 333 bundling changes: 7 chunks
334 334 bundling changes: 8 chunks
335 335 bundling changes: 9 chunks
336 336 bundling manifests: 0 chunks
337 337 bundling manifests: 1 chunks
338 338 bundling manifests: 2 chunks
339 339 bundling manifests: 3 chunks
340 340 bundling manifests: 4 chunks
341 341 bundling manifests: 5 chunks
342 342 bundling manifests: 6 chunks
343 343 bundling manifests: 7 chunks
344 344 bundling manifests: 8 chunks
345 345 bundling manifests: 9 chunks
346 346 bundling files: foo/Bar/file.txt 0 chunks
347 347 bundling files: foo/Bar/file.txt 1 chunks
348 348 bundling files: foo/Bar/file.txt 2 chunks
349 349 bundling files: foo/Bar/file.txt 3 chunks
350 350 bundling files: foo/file.txt 4 chunks
351 351 bundling files: foo/file.txt 5 chunks
352 352 bundling files: foo/file.txt 6 chunks
353 353 bundling files: foo/file.txt 7 chunks
354 354 bundling files: quux/file.py 8 chunks
355 355 bundling files: quux/file.py 9 chunks
356 356 bundling files: quux/file.py 10 chunks
357 357 bundling files: quux/file.py 11 chunks
358 358 changesets: 1 chunks
359 359 add changeset ef1ea85a6374
360 360 changesets: 2 chunks
361 361 add changeset f9cafe1212c8
362 362 changesets: 3 chunks
363 363 add changeset 911600dab2ae
364 364 adding manifests
365 365 manifests: 1/3 chunks (33.33%)
366 366 manifests: 2/3 chunks (66.67%)
367 367 manifests: 3/3 chunks (100.00%)
368 368 adding file changes
369 369 adding foo/Bar/file.txt revisions
370 370 files: 1/3 chunks (33.33%)
371 371 adding foo/file.txt revisions
372 372 files: 2/3 chunks (66.67%)
373 373 adding quux/file.py revisions
374 374 files: 3/3 chunks (100.00%)
375 375 added 3 changesets with 3 changes to 3 files
376 376 calling hook pretxnchangegroup.acl: hgext.acl.hook
377 377 acl: acl.allow enabled, 1 entries for user fred
378 378 acl: acl.deny not enabled
379 379 acl: allowing changeset ef1ea85a6374
380 380 acl: allowing changeset f9cafe1212c8
381 381 acl: user fred not allowed on quux/file.py
382 382 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
383 383 transaction abort!
384 384 rollback completed
385 385 abort: acl: access denied for changeset 911600dab2ae
386 386 no rollback information available
387 387 0:6675d58eff77
388 388
389 389 Empty [acl.deny]
390 390 Pushing as user barney
391 391 hgrc = """
392 392 [hooks]
393 393 pretxnchangegroup.acl = python:hgext.acl.hook
394 394 [acl]
395 395 sources = push
396 396 [acl.allow]
397 397 foo/** = fred
398 398 [acl.deny]
399 399 """
400 400 pushing to ../b
401 401 searching for changes
402 402 common changesets up to 6675d58eff77
403 403 3 changesets found
404 404 list of changesets:
405 405 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
406 406 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
407 407 911600dab2ae7a9baff75958b84fe606851ce955
408 408 adding changesets
409 409 bundling changes: 0 chunks
410 410 bundling changes: 1 chunks
411 411 bundling changes: 2 chunks
412 412 bundling changes: 3 chunks
413 413 bundling changes: 4 chunks
414 414 bundling changes: 5 chunks
415 415 bundling changes: 6 chunks
416 416 bundling changes: 7 chunks
417 417 bundling changes: 8 chunks
418 418 bundling changes: 9 chunks
419 419 bundling manifests: 0 chunks
420 420 bundling manifests: 1 chunks
421 421 bundling manifests: 2 chunks
422 422 bundling manifests: 3 chunks
423 423 bundling manifests: 4 chunks
424 424 bundling manifests: 5 chunks
425 425 bundling manifests: 6 chunks
426 426 bundling manifests: 7 chunks
427 427 bundling manifests: 8 chunks
428 428 bundling manifests: 9 chunks
429 429 bundling files: foo/Bar/file.txt 0 chunks
430 430 bundling files: foo/Bar/file.txt 1 chunks
431 431 bundling files: foo/Bar/file.txt 2 chunks
432 432 bundling files: foo/Bar/file.txt 3 chunks
433 433 bundling files: foo/file.txt 4 chunks
434 434 bundling files: foo/file.txt 5 chunks
435 435 bundling files: foo/file.txt 6 chunks
436 436 bundling files: foo/file.txt 7 chunks
437 437 bundling files: quux/file.py 8 chunks
438 438 bundling files: quux/file.py 9 chunks
439 439 bundling files: quux/file.py 10 chunks
440 440 bundling files: quux/file.py 11 chunks
441 441 changesets: 1 chunks
442 442 add changeset ef1ea85a6374
443 443 changesets: 2 chunks
444 444 add changeset f9cafe1212c8
445 445 changesets: 3 chunks
446 446 add changeset 911600dab2ae
447 447 adding manifests
448 448 manifests: 1/3 chunks (33.33%)
449 449 manifests: 2/3 chunks (66.67%)
450 450 manifests: 3/3 chunks (100.00%)
451 451 adding file changes
452 452 adding foo/Bar/file.txt revisions
453 453 files: 1/3 chunks (33.33%)
454 454 adding foo/file.txt revisions
455 455 files: 2/3 chunks (66.67%)
456 456 adding quux/file.py revisions
457 457 files: 3/3 chunks (100.00%)
458 458 added 3 changesets with 3 changes to 3 files
459 459 calling hook pretxnchangegroup.acl: hgext.acl.hook
460 460 acl: acl.allow enabled, 0 entries for user barney
461 461 acl: acl.deny enabled, 0 entries for user barney
462 462 acl: user barney not allowed on foo/file.txt
463 463 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
464 464 transaction abort!
465 465 rollback completed
466 466 abort: acl: access denied for changeset ef1ea85a6374
467 467 no rollback information available
468 468 0:6675d58eff77
469 469
470 470 fred is allowed inside foo/, but not foo/bar/ (case matters)
471 471 Pushing as user fred
472 472 hgrc = """
473 473 [hooks]
474 474 pretxnchangegroup.acl = python:hgext.acl.hook
475 475 [acl]
476 476 sources = push
477 477 [acl.allow]
478 478 foo/** = fred
479 479 [acl.deny]
480 480 foo/bar/** = fred
481 481 """
482 482 pushing to ../b
483 483 searching for changes
484 484 common changesets up to 6675d58eff77
485 485 3 changesets found
486 486 list of changesets:
487 487 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
488 488 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
489 489 911600dab2ae7a9baff75958b84fe606851ce955
490 490 adding changesets
491 491 bundling changes: 0 chunks
492 492 bundling changes: 1 chunks
493 493 bundling changes: 2 chunks
494 494 bundling changes: 3 chunks
495 495 bundling changes: 4 chunks
496 496 bundling changes: 5 chunks
497 497 bundling changes: 6 chunks
498 498 bundling changes: 7 chunks
499 499 bundling changes: 8 chunks
500 500 bundling changes: 9 chunks
501 501 bundling manifests: 0 chunks
502 502 bundling manifests: 1 chunks
503 503 bundling manifests: 2 chunks
504 504 bundling manifests: 3 chunks
505 505 bundling manifests: 4 chunks
506 506 bundling manifests: 5 chunks
507 507 bundling manifests: 6 chunks
508 508 bundling manifests: 7 chunks
509 509 bundling manifests: 8 chunks
510 510 bundling manifests: 9 chunks
511 511 bundling files: foo/Bar/file.txt 0 chunks
512 512 bundling files: foo/Bar/file.txt 1 chunks
513 513 bundling files: foo/Bar/file.txt 2 chunks
514 514 bundling files: foo/Bar/file.txt 3 chunks
515 515 bundling files: foo/file.txt 4 chunks
516 516 bundling files: foo/file.txt 5 chunks
517 517 bundling files: foo/file.txt 6 chunks
518 518 bundling files: foo/file.txt 7 chunks
519 519 bundling files: quux/file.py 8 chunks
520 520 bundling files: quux/file.py 9 chunks
521 521 bundling files: quux/file.py 10 chunks
522 522 bundling files: quux/file.py 11 chunks
523 523 changesets: 1 chunks
524 524 add changeset ef1ea85a6374
525 525 changesets: 2 chunks
526 526 add changeset f9cafe1212c8
527 527 changesets: 3 chunks
528 528 add changeset 911600dab2ae
529 529 adding manifests
530 530 manifests: 1/3 chunks (33.33%)
531 531 manifests: 2/3 chunks (66.67%)
532 532 manifests: 3/3 chunks (100.00%)
533 533 adding file changes
534 534 adding foo/Bar/file.txt revisions
535 535 files: 1/3 chunks (33.33%)
536 536 adding foo/file.txt revisions
537 537 files: 2/3 chunks (66.67%)
538 538 adding quux/file.py revisions
539 539 files: 3/3 chunks (100.00%)
540 540 added 3 changesets with 3 changes to 3 files
541 541 calling hook pretxnchangegroup.acl: hgext.acl.hook
542 542 acl: acl.allow enabled, 1 entries for user fred
543 543 acl: acl.deny enabled, 1 entries for user fred
544 544 acl: allowing changeset ef1ea85a6374
545 545 acl: allowing changeset f9cafe1212c8
546 546 acl: user fred not allowed on quux/file.py
547 547 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
548 548 transaction abort!
549 549 rollback completed
550 550 abort: acl: access denied for changeset 911600dab2ae
551 551 no rollback information available
552 552 0:6675d58eff77
553 553
554 554 fred is allowed inside foo/, but not foo/Bar/
555 555 Pushing as user fred
556 556 hgrc = """
557 557 [hooks]
558 558 pretxnchangegroup.acl = python:hgext.acl.hook
559 559 [acl]
560 560 sources = push
561 561 [acl.allow]
562 562 foo/** = fred
563 563 [acl.deny]
564 564 foo/bar/** = fred
565 565 foo/Bar/** = fred
566 566 """
567 567 pushing to ../b
568 568 searching for changes
569 569 common changesets up to 6675d58eff77
570 570 3 changesets found
571 571 list of changesets:
572 572 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
573 573 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
574 574 911600dab2ae7a9baff75958b84fe606851ce955
575 575 adding changesets
576 576 bundling changes: 0 chunks
577 577 bundling changes: 1 chunks
578 578 bundling changes: 2 chunks
579 579 bundling changes: 3 chunks
580 580 bundling changes: 4 chunks
581 581 bundling changes: 5 chunks
582 582 bundling changes: 6 chunks
583 583 bundling changes: 7 chunks
584 584 bundling changes: 8 chunks
585 585 bundling changes: 9 chunks
586 586 bundling manifests: 0 chunks
587 587 bundling manifests: 1 chunks
588 588 bundling manifests: 2 chunks
589 589 bundling manifests: 3 chunks
590 590 bundling manifests: 4 chunks
591 591 bundling manifests: 5 chunks
592 592 bundling manifests: 6 chunks
593 593 bundling manifests: 7 chunks
594 594 bundling manifests: 8 chunks
595 595 bundling manifests: 9 chunks
596 596 bundling files: foo/Bar/file.txt 0 chunks
597 597 bundling files: foo/Bar/file.txt 1 chunks
598 598 bundling files: foo/Bar/file.txt 2 chunks
599 599 bundling files: foo/Bar/file.txt 3 chunks
600 600 bundling files: foo/file.txt 4 chunks
601 601 bundling files: foo/file.txt 5 chunks
602 602 bundling files: foo/file.txt 6 chunks
603 603 bundling files: foo/file.txt 7 chunks
604 604 bundling files: quux/file.py 8 chunks
605 605 bundling files: quux/file.py 9 chunks
606 606 bundling files: quux/file.py 10 chunks
607 607 bundling files: quux/file.py 11 chunks
608 608 changesets: 1 chunks
609 609 add changeset ef1ea85a6374
610 610 changesets: 2 chunks
611 611 add changeset f9cafe1212c8
612 612 changesets: 3 chunks
613 613 add changeset 911600dab2ae
614 614 adding manifests
615 615 manifests: 1/3 chunks (33.33%)
616 616 manifests: 2/3 chunks (66.67%)
617 617 manifests: 3/3 chunks (100.00%)
618 618 adding file changes
619 619 adding foo/Bar/file.txt revisions
620 620 files: 1/3 chunks (33.33%)
621 621 adding foo/file.txt revisions
622 622 files: 2/3 chunks (66.67%)
623 623 adding quux/file.py revisions
624 624 files: 3/3 chunks (100.00%)
625 625 added 3 changesets with 3 changes to 3 files
626 626 calling hook pretxnchangegroup.acl: hgext.acl.hook
627 627 acl: acl.allow enabled, 1 entries for user fred
628 628 acl: acl.deny enabled, 2 entries for user fred
629 629 acl: allowing changeset ef1ea85a6374
630 630 acl: user fred denied on foo/Bar/file.txt
631 631 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
632 632 transaction abort!
633 633 rollback completed
634 634 abort: acl: access denied for changeset f9cafe1212c8
635 635 no rollback information available
636 636 0:6675d58eff77
637 637
638 638 barney is not mentioned => not allowed anywhere
639 639 Pushing as user barney
640 640 hgrc = """
641 641 [hooks]
642 642 pretxnchangegroup.acl = python:hgext.acl.hook
643 643 [acl]
644 644 sources = push
645 645 [acl.allow]
646 646 foo/** = fred
647 647 [acl.deny]
648 648 foo/bar/** = fred
649 649 foo/Bar/** = fred
650 650 """
651 651 pushing to ../b
652 652 searching for changes
653 653 common changesets up to 6675d58eff77
654 654 3 changesets found
655 655 list of changesets:
656 656 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
657 657 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
658 658 911600dab2ae7a9baff75958b84fe606851ce955
659 659 adding changesets
660 660 bundling changes: 0 chunks
661 661 bundling changes: 1 chunks
662 662 bundling changes: 2 chunks
663 663 bundling changes: 3 chunks
664 664 bundling changes: 4 chunks
665 665 bundling changes: 5 chunks
666 666 bundling changes: 6 chunks
667 667 bundling changes: 7 chunks
668 668 bundling changes: 8 chunks
669 669 bundling changes: 9 chunks
670 670 bundling manifests: 0 chunks
671 671 bundling manifests: 1 chunks
672 672 bundling manifests: 2 chunks
673 673 bundling manifests: 3 chunks
674 674 bundling manifests: 4 chunks
675 675 bundling manifests: 5 chunks
676 676 bundling manifests: 6 chunks
677 677 bundling manifests: 7 chunks
678 678 bundling manifests: 8 chunks
679 679 bundling manifests: 9 chunks
680 680 bundling files: foo/Bar/file.txt 0 chunks
681 681 bundling files: foo/Bar/file.txt 1 chunks
682 682 bundling files: foo/Bar/file.txt 2 chunks
683 683 bundling files: foo/Bar/file.txt 3 chunks
684 684 bundling files: foo/file.txt 4 chunks
685 685 bundling files: foo/file.txt 5 chunks
686 686 bundling files: foo/file.txt 6 chunks
687 687 bundling files: foo/file.txt 7 chunks
688 688 bundling files: quux/file.py 8 chunks
689 689 bundling files: quux/file.py 9 chunks
690 690 bundling files: quux/file.py 10 chunks
691 691 bundling files: quux/file.py 11 chunks
692 692 changesets: 1 chunks
693 693 add changeset ef1ea85a6374
694 694 changesets: 2 chunks
695 695 add changeset f9cafe1212c8
696 696 changesets: 3 chunks
697 697 add changeset 911600dab2ae
698 698 adding manifests
699 699 manifests: 1/3 chunks (33.33%)
700 700 manifests: 2/3 chunks (66.67%)
701 701 manifests: 3/3 chunks (100.00%)
702 702 adding file changes
703 703 adding foo/Bar/file.txt revisions
704 704 files: 1/3 chunks (33.33%)
705 705 adding foo/file.txt revisions
706 706 files: 2/3 chunks (66.67%)
707 707 adding quux/file.py revisions
708 708 files: 3/3 chunks (100.00%)
709 709 added 3 changesets with 3 changes to 3 files
710 710 calling hook pretxnchangegroup.acl: hgext.acl.hook
711 711 acl: acl.allow enabled, 0 entries for user barney
712 712 acl: acl.deny enabled, 0 entries for user barney
713 713 acl: user barney not allowed on foo/file.txt
714 714 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
715 715 transaction abort!
716 716 rollback completed
717 717 abort: acl: access denied for changeset ef1ea85a6374
718 718 no rollback information available
719 719 0:6675d58eff77
720 720
721 721 barney is allowed everywhere
722 722 Pushing as user barney
723 723 hgrc = """
724 724 [hooks]
725 725 pretxnchangegroup.acl = python:hgext.acl.hook
726 726 [acl]
727 727 sources = push
728 728 [acl.allow]
729 729 foo/** = fred
730 730 [acl.deny]
731 731 foo/bar/** = fred
732 732 foo/Bar/** = fred
733 733 [acl.allow]
734 734 ** = barney
735 735 """
736 736 pushing to ../b
737 737 searching for changes
738 738 common changesets up to 6675d58eff77
739 739 3 changesets found
740 740 list of changesets:
741 741 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
742 742 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
743 743 911600dab2ae7a9baff75958b84fe606851ce955
744 744 adding changesets
745 745 bundling changes: 0 chunks
746 746 bundling changes: 1 chunks
747 747 bundling changes: 2 chunks
748 748 bundling changes: 3 chunks
749 749 bundling changes: 4 chunks
750 750 bundling changes: 5 chunks
751 751 bundling changes: 6 chunks
752 752 bundling changes: 7 chunks
753 753 bundling changes: 8 chunks
754 754 bundling changes: 9 chunks
755 755 bundling manifests: 0 chunks
756 756 bundling manifests: 1 chunks
757 757 bundling manifests: 2 chunks
758 758 bundling manifests: 3 chunks
759 759 bundling manifests: 4 chunks
760 760 bundling manifests: 5 chunks
761 761 bundling manifests: 6 chunks
762 762 bundling manifests: 7 chunks
763 763 bundling manifests: 8 chunks
764 764 bundling manifests: 9 chunks
765 765 bundling files: foo/Bar/file.txt 0 chunks
766 766 bundling files: foo/Bar/file.txt 1 chunks
767 767 bundling files: foo/Bar/file.txt 2 chunks
768 768 bundling files: foo/Bar/file.txt 3 chunks
769 769 bundling files: foo/file.txt 4 chunks
770 770 bundling files: foo/file.txt 5 chunks
771 771 bundling files: foo/file.txt 6 chunks
772 772 bundling files: foo/file.txt 7 chunks
773 773 bundling files: quux/file.py 8 chunks
774 774 bundling files: quux/file.py 9 chunks
775 775 bundling files: quux/file.py 10 chunks
776 776 bundling files: quux/file.py 11 chunks
777 777 changesets: 1 chunks
778 778 add changeset ef1ea85a6374
779 779 changesets: 2 chunks
780 780 add changeset f9cafe1212c8
781 781 changesets: 3 chunks
782 782 add changeset 911600dab2ae
783 783 adding manifests
784 784 manifests: 1/3 chunks (33.33%)
785 785 manifests: 2/3 chunks (66.67%)
786 786 manifests: 3/3 chunks (100.00%)
787 787 adding file changes
788 788 adding foo/Bar/file.txt revisions
789 789 files: 1/3 chunks (33.33%)
790 790 adding foo/file.txt revisions
791 791 files: 2/3 chunks (66.67%)
792 792 adding quux/file.py revisions
793 793 files: 3/3 chunks (100.00%)
794 794 added 3 changesets with 3 changes to 3 files
795 795 calling hook pretxnchangegroup.acl: hgext.acl.hook
796 796 acl: acl.allow enabled, 1 entries for user barney
797 797 acl: acl.deny enabled, 0 entries for user barney
798 798 acl: allowing changeset ef1ea85a6374
799 799 acl: allowing changeset f9cafe1212c8
800 800 acl: allowing changeset 911600dab2ae
801 801 updating the branch cache
802 rolling back push to revision 1
802 rolling back to revision 1 (undo push)
803 803 0:6675d58eff77
804 804
805 805 wilma can change files with a .txt extension
806 806 Pushing as user wilma
807 807 hgrc = """
808 808 [hooks]
809 809 pretxnchangegroup.acl = python:hgext.acl.hook
810 810 [acl]
811 811 sources = push
812 812 [acl.allow]
813 813 foo/** = fred
814 814 [acl.deny]
815 815 foo/bar/** = fred
816 816 foo/Bar/** = fred
817 817 [acl.allow]
818 818 ** = barney
819 819 **/*.txt = wilma
820 820 """
821 821 pushing to ../b
822 822 searching for changes
823 823 common changesets up to 6675d58eff77
824 824 invalidating branch cache (tip differs)
825 825 3 changesets found
826 826 list of changesets:
827 827 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
828 828 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
829 829 911600dab2ae7a9baff75958b84fe606851ce955
830 830 adding changesets
831 831 bundling changes: 0 chunks
832 832 bundling changes: 1 chunks
833 833 bundling changes: 2 chunks
834 834 bundling changes: 3 chunks
835 835 bundling changes: 4 chunks
836 836 bundling changes: 5 chunks
837 837 bundling changes: 6 chunks
838 838 bundling changes: 7 chunks
839 839 bundling changes: 8 chunks
840 840 bundling changes: 9 chunks
841 841 bundling manifests: 0 chunks
842 842 bundling manifests: 1 chunks
843 843 bundling manifests: 2 chunks
844 844 bundling manifests: 3 chunks
845 845 bundling manifests: 4 chunks
846 846 bundling manifests: 5 chunks
847 847 bundling manifests: 6 chunks
848 848 bundling manifests: 7 chunks
849 849 bundling manifests: 8 chunks
850 850 bundling manifests: 9 chunks
851 851 bundling files: foo/Bar/file.txt 0 chunks
852 852 bundling files: foo/Bar/file.txt 1 chunks
853 853 bundling files: foo/Bar/file.txt 2 chunks
854 854 bundling files: foo/Bar/file.txt 3 chunks
855 855 bundling files: foo/file.txt 4 chunks
856 856 bundling files: foo/file.txt 5 chunks
857 857 bundling files: foo/file.txt 6 chunks
858 858 bundling files: foo/file.txt 7 chunks
859 859 bundling files: quux/file.py 8 chunks
860 860 bundling files: quux/file.py 9 chunks
861 861 bundling files: quux/file.py 10 chunks
862 862 bundling files: quux/file.py 11 chunks
863 863 changesets: 1 chunks
864 864 add changeset ef1ea85a6374
865 865 changesets: 2 chunks
866 866 add changeset f9cafe1212c8
867 867 changesets: 3 chunks
868 868 add changeset 911600dab2ae
869 869 adding manifests
870 870 manifests: 1/3 chunks (33.33%)
871 871 manifests: 2/3 chunks (66.67%)
872 872 manifests: 3/3 chunks (100.00%)
873 873 adding file changes
874 874 adding foo/Bar/file.txt revisions
875 875 files: 1/3 chunks (33.33%)
876 876 adding foo/file.txt revisions
877 877 files: 2/3 chunks (66.67%)
878 878 adding quux/file.py revisions
879 879 files: 3/3 chunks (100.00%)
880 880 added 3 changesets with 3 changes to 3 files
881 881 calling hook pretxnchangegroup.acl: hgext.acl.hook
882 882 acl: acl.allow enabled, 1 entries for user wilma
883 883 acl: acl.deny enabled, 0 entries for user wilma
884 884 acl: allowing changeset ef1ea85a6374
885 885 acl: allowing changeset f9cafe1212c8
886 886 acl: user wilma not allowed on quux/file.py
887 887 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
888 888 transaction abort!
889 889 rollback completed
890 890 abort: acl: access denied for changeset 911600dab2ae
891 891 no rollback information available
892 892 0:6675d58eff77
893 893
894 894 file specified by acl.config does not exist
895 895 Pushing as user barney
896 896 hgrc = """
897 897 [hooks]
898 898 pretxnchangegroup.acl = python:hgext.acl.hook
899 899 [acl]
900 900 sources = push
901 901 [acl.allow]
902 902 foo/** = fred
903 903 [acl.deny]
904 904 foo/bar/** = fred
905 905 foo/Bar/** = fred
906 906 [acl.allow]
907 907 ** = barney
908 908 **/*.txt = wilma
909 909 [acl]
910 910 config = ../acl.config
911 911 """
912 912 pushing to ../b
913 913 searching for changes
914 914 common changesets up to 6675d58eff77
915 915 3 changesets found
916 916 list of changesets:
917 917 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
918 918 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
919 919 911600dab2ae7a9baff75958b84fe606851ce955
920 920 adding changesets
921 921 bundling changes: 0 chunks
922 922 bundling changes: 1 chunks
923 923 bundling changes: 2 chunks
924 924 bundling changes: 3 chunks
925 925 bundling changes: 4 chunks
926 926 bundling changes: 5 chunks
927 927 bundling changes: 6 chunks
928 928 bundling changes: 7 chunks
929 929 bundling changes: 8 chunks
930 930 bundling changes: 9 chunks
931 931 bundling manifests: 0 chunks
932 932 bundling manifests: 1 chunks
933 933 bundling manifests: 2 chunks
934 934 bundling manifests: 3 chunks
935 935 bundling manifests: 4 chunks
936 936 bundling manifests: 5 chunks
937 937 bundling manifests: 6 chunks
938 938 bundling manifests: 7 chunks
939 939 bundling manifests: 8 chunks
940 940 bundling manifests: 9 chunks
941 941 bundling files: foo/Bar/file.txt 0 chunks
942 942 bundling files: foo/Bar/file.txt 1 chunks
943 943 bundling files: foo/Bar/file.txt 2 chunks
944 944 bundling files: foo/Bar/file.txt 3 chunks
945 945 bundling files: foo/file.txt 4 chunks
946 946 bundling files: foo/file.txt 5 chunks
947 947 bundling files: foo/file.txt 6 chunks
948 948 bundling files: foo/file.txt 7 chunks
949 949 bundling files: quux/file.py 8 chunks
950 950 bundling files: quux/file.py 9 chunks
951 951 bundling files: quux/file.py 10 chunks
952 952 bundling files: quux/file.py 11 chunks
953 953 changesets: 1 chunks
954 954 add changeset ef1ea85a6374
955 955 changesets: 2 chunks
956 956 add changeset f9cafe1212c8
957 957 changesets: 3 chunks
958 958 add changeset 911600dab2ae
959 959 adding manifests
960 960 manifests: 1/3 chunks (33.33%)
961 961 manifests: 2/3 chunks (66.67%)
962 962 manifests: 3/3 chunks (100.00%)
963 963 adding file changes
964 964 adding foo/Bar/file.txt revisions
965 965 files: 1/3 chunks (33.33%)
966 966 adding foo/file.txt revisions
967 967 files: 2/3 chunks (66.67%)
968 968 adding quux/file.py revisions
969 969 files: 3/3 chunks (100.00%)
970 970 added 3 changesets with 3 changes to 3 files
971 971 calling hook pretxnchangegroup.acl: hgext.acl.hook
972 972 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
973 973 transaction abort!
974 974 rollback completed
975 975 abort: No such file or directory: ../acl.config
976 976 no rollback information available
977 977 0:6675d58eff77
978 978
979 979 betty is allowed inside foo/ by a acl.config file
980 980 Pushing as user betty
981 981 hgrc = """
982 982 [hooks]
983 983 pretxnchangegroup.acl = python:hgext.acl.hook
984 984 [acl]
985 985 sources = push
986 986 [acl.allow]
987 987 foo/** = fred
988 988 [acl.deny]
989 989 foo/bar/** = fred
990 990 foo/Bar/** = fred
991 991 [acl.allow]
992 992 ** = barney
993 993 **/*.txt = wilma
994 994 [acl]
995 995 config = ../acl.config
996 996 """
997 997 acl.config = """
998 998 [acl.allow]
999 999 foo/** = betty
1000 1000 """
1001 1001 pushing to ../b
1002 1002 searching for changes
1003 1003 common changesets up to 6675d58eff77
1004 1004 3 changesets found
1005 1005 list of changesets:
1006 1006 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1007 1007 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1008 1008 911600dab2ae7a9baff75958b84fe606851ce955
1009 1009 adding changesets
1010 1010 bundling changes: 0 chunks
1011 1011 bundling changes: 1 chunks
1012 1012 bundling changes: 2 chunks
1013 1013 bundling changes: 3 chunks
1014 1014 bundling changes: 4 chunks
1015 1015 bundling changes: 5 chunks
1016 1016 bundling changes: 6 chunks
1017 1017 bundling changes: 7 chunks
1018 1018 bundling changes: 8 chunks
1019 1019 bundling changes: 9 chunks
1020 1020 bundling manifests: 0 chunks
1021 1021 bundling manifests: 1 chunks
1022 1022 bundling manifests: 2 chunks
1023 1023 bundling manifests: 3 chunks
1024 1024 bundling manifests: 4 chunks
1025 1025 bundling manifests: 5 chunks
1026 1026 bundling manifests: 6 chunks
1027 1027 bundling manifests: 7 chunks
1028 1028 bundling manifests: 8 chunks
1029 1029 bundling manifests: 9 chunks
1030 1030 bundling files: foo/Bar/file.txt 0 chunks
1031 1031 bundling files: foo/Bar/file.txt 1 chunks
1032 1032 bundling files: foo/Bar/file.txt 2 chunks
1033 1033 bundling files: foo/Bar/file.txt 3 chunks
1034 1034 bundling files: foo/file.txt 4 chunks
1035 1035 bundling files: foo/file.txt 5 chunks
1036 1036 bundling files: foo/file.txt 6 chunks
1037 1037 bundling files: foo/file.txt 7 chunks
1038 1038 bundling files: quux/file.py 8 chunks
1039 1039 bundling files: quux/file.py 9 chunks
1040 1040 bundling files: quux/file.py 10 chunks
1041 1041 bundling files: quux/file.py 11 chunks
1042 1042 changesets: 1 chunks
1043 1043 add changeset ef1ea85a6374
1044 1044 changesets: 2 chunks
1045 1045 add changeset f9cafe1212c8
1046 1046 changesets: 3 chunks
1047 1047 add changeset 911600dab2ae
1048 1048 adding manifests
1049 1049 manifests: 1/3 chunks (33.33%)
1050 1050 manifests: 2/3 chunks (66.67%)
1051 1051 manifests: 3/3 chunks (100.00%)
1052 1052 adding file changes
1053 1053 adding foo/Bar/file.txt revisions
1054 1054 files: 1/3 chunks (33.33%)
1055 1055 adding foo/file.txt revisions
1056 1056 files: 2/3 chunks (66.67%)
1057 1057 adding quux/file.py revisions
1058 1058 files: 3/3 chunks (100.00%)
1059 1059 added 3 changesets with 3 changes to 3 files
1060 1060 calling hook pretxnchangegroup.acl: hgext.acl.hook
1061 1061 acl: acl.allow enabled, 1 entries for user betty
1062 1062 acl: acl.deny enabled, 0 entries for user betty
1063 1063 acl: allowing changeset ef1ea85a6374
1064 1064 acl: allowing changeset f9cafe1212c8
1065 1065 acl: user betty not allowed on quux/file.py
1066 1066 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
1067 1067 transaction abort!
1068 1068 rollback completed
1069 1069 abort: acl: access denied for changeset 911600dab2ae
1070 1070 no rollback information available
1071 1071 0:6675d58eff77
1072 1072
1073 1073 acl.config can set only [acl.allow]/[acl.deny]
1074 1074 Pushing as user barney
1075 1075 hgrc = """
1076 1076 [hooks]
1077 1077 pretxnchangegroup.acl = python:hgext.acl.hook
1078 1078 [acl]
1079 1079 sources = push
1080 1080 [acl.allow]
1081 1081 foo/** = fred
1082 1082 [acl.deny]
1083 1083 foo/bar/** = fred
1084 1084 foo/Bar/** = fred
1085 1085 [acl.allow]
1086 1086 ** = barney
1087 1087 **/*.txt = wilma
1088 1088 [acl]
1089 1089 config = ../acl.config
1090 1090 """
1091 1091 acl.config = """
1092 1092 [acl.allow]
1093 1093 foo/** = betty
1094 1094 [hooks]
1095 1095 changegroup.acl = false
1096 1096 """
1097 1097 pushing to ../b
1098 1098 searching for changes
1099 1099 common changesets up to 6675d58eff77
1100 1100 3 changesets found
1101 1101 list of changesets:
1102 1102 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1103 1103 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1104 1104 911600dab2ae7a9baff75958b84fe606851ce955
1105 1105 adding changesets
1106 1106 bundling changes: 0 chunks
1107 1107 bundling changes: 1 chunks
1108 1108 bundling changes: 2 chunks
1109 1109 bundling changes: 3 chunks
1110 1110 bundling changes: 4 chunks
1111 1111 bundling changes: 5 chunks
1112 1112 bundling changes: 6 chunks
1113 1113 bundling changes: 7 chunks
1114 1114 bundling changes: 8 chunks
1115 1115 bundling changes: 9 chunks
1116 1116 bundling manifests: 0 chunks
1117 1117 bundling manifests: 1 chunks
1118 1118 bundling manifests: 2 chunks
1119 1119 bundling manifests: 3 chunks
1120 1120 bundling manifests: 4 chunks
1121 1121 bundling manifests: 5 chunks
1122 1122 bundling manifests: 6 chunks
1123 1123 bundling manifests: 7 chunks
1124 1124 bundling manifests: 8 chunks
1125 1125 bundling manifests: 9 chunks
1126 1126 bundling files: foo/Bar/file.txt 0 chunks
1127 1127 bundling files: foo/Bar/file.txt 1 chunks
1128 1128 bundling files: foo/Bar/file.txt 2 chunks
1129 1129 bundling files: foo/Bar/file.txt 3 chunks
1130 1130 bundling files: foo/file.txt 4 chunks
1131 1131 bundling files: foo/file.txt 5 chunks
1132 1132 bundling files: foo/file.txt 6 chunks
1133 1133 bundling files: foo/file.txt 7 chunks
1134 1134 bundling files: quux/file.py 8 chunks
1135 1135 bundling files: quux/file.py 9 chunks
1136 1136 bundling files: quux/file.py 10 chunks
1137 1137 bundling files: quux/file.py 11 chunks
1138 1138 changesets: 1 chunks
1139 1139 add changeset ef1ea85a6374
1140 1140 changesets: 2 chunks
1141 1141 add changeset f9cafe1212c8
1142 1142 changesets: 3 chunks
1143 1143 add changeset 911600dab2ae
1144 1144 adding manifests
1145 1145 manifests: 1/3 chunks (33.33%)
1146 1146 manifests: 2/3 chunks (66.67%)
1147 1147 manifests: 3/3 chunks (100.00%)
1148 1148 adding file changes
1149 1149 adding foo/Bar/file.txt revisions
1150 1150 files: 1/3 chunks (33.33%)
1151 1151 adding foo/file.txt revisions
1152 1152 files: 2/3 chunks (66.67%)
1153 1153 adding quux/file.py revisions
1154 1154 files: 3/3 chunks (100.00%)
1155 1155 added 3 changesets with 3 changes to 3 files
1156 1156 calling hook pretxnchangegroup.acl: hgext.acl.hook
1157 1157 acl: acl.allow enabled, 1 entries for user barney
1158 1158 acl: acl.deny enabled, 0 entries for user barney
1159 1159 acl: allowing changeset ef1ea85a6374
1160 1160 acl: allowing changeset f9cafe1212c8
1161 1161 acl: allowing changeset 911600dab2ae
1162 1162 updating the branch cache
1163 rolling back push to revision 1
1163 rolling back to revision 1 (undo push)
1164 1164 0:6675d58eff77
1165 1165
@@ -1,95 +1,95 b''
1 1 # should complain
2 2 abort: please specify a revision to backout
3 3 abort: please specify just one revision
4 4 # basic operation
5 5 adding a
6 6 reverting a
7 7 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
8 8 a
9 9 # file that was removed is recreated
10 10 adding a
11 11 adding a
12 12 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
13 13 content
14 14 # backout of backout is as if nothing happened
15 15 removing a
16 16 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
17 17 cat: a: No such file or directory
18 18 # across branch
19 19 adding a
20 20 adding b
21 21 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 22 abort: cannot backout change on a different branch
23 23 adding c
24 24 created new head
25 25 abort: cannot backout change on a different branch
26 26 # backout with merge
27 27 adding a
28 28 reverting a
29 29 created new head
30 30 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
31 31 merging with changeset 3:26b8ccb9ad91
32 32 merging a
33 33 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
34 34 (branch merge, don't forget to commit)
35 35 line 1
36 36 line 2
37 37 line 3
38 38 # backout should not back out subsequent changesets
39 39 adding a
40 40 adding b
41 41 reverting a
42 42 created new head
43 43 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
44 44 the backout changeset is a new head - do not forget to merge
45 45 (use "backout --merge" if you want to auto-merge)
46 46 b
47 47 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 48 adding a
49 49 adding b
50 50 adding c
51 51 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
52 52 adding d
53 53 created new head
54 54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 55 (branch merge, don't forget to commit)
56 56 # backout of merge should fail
57 57 abort: cannot backout a merge changeset without --parent
58 58 # backout of merge with bad parent should fail
59 59 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
60 60 # backout of non-merge with parent should fail
61 61 abort: cannot use --parent on non-merge changeset
62 62 # backout with valid parent should be ok
63 63 removing d
64 64 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
65 rolling back commit to revision 5
65 rolling back to revision 5 (undo commit)
66 66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67 removing c
68 68 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
69 69 # named branches
70 70 adding default
71 71 marked working directory as branch branch1
72 72 adding file1
73 73 marked working directory as branch branch2
74 74 adding file2
75 75 removing file1
76 76 created new head
77 77 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
78 78 the backout changeset is a new head - do not forget to merge
79 79 (use "backout --merge" if you want to auto-merge)
80 80 % on branch2 with branch1 not merged, so file1 should still exist:
81 81 45bbcd363bf0 (branch2)
82 82 C default
83 83 C file1
84 84 C file2
85 85 % on branch2 with branch1 merged, so file1 should be gone:
86 86 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
87 87 (branch merge, don't forget to commit)
88 88 22149cdde76d (branch2) tip
89 89 C default
90 90 C file2
91 91 % on branch1, so no file1 and file2:
92 92 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
93 93 bf1602f437f3 (branch1)
94 94 C default
95 95 C file1
@@ -1,250 +1,250 b''
1 1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 2 created new head
3 3 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
4 4 rev offset length base linkrev nodeid p1 p2
5 5 0 0 3 0 0 362fef284ce2 000000000000 000000000000
6 6 1 3 5 1 1 125144f7e028 362fef284ce2 000000000000
7 7 2 8 7 2 2 4c982badb186 125144f7e028 000000000000
8 8 3 15 9 3 3 19b1fc555737 4c982badb186 000000000000
9 9 rev offset length base linkrev nodeid p1 p2
10 10 0 0 75 0 7 2565f3199a74 000000000000 000000000000
11 11 rev offset length base linkrev nodeid p1 p2
12 12 0 0 75 0 8 2565f3199a74 000000000000 000000000000
13 13 rev offset length base linkrev nodeid p1 p2
14 14 0 0 8 0 6 12ab3bcc5ea4 000000000000 000000000000
15 15 rev offset length base linkrev nodeid p1 p2
16 16 0 0 48 0 0 43eadb1d2d06 000000000000 000000000000
17 17 1 48 48 1 1 8b89697eba2c 43eadb1d2d06 000000000000
18 18 2 96 48 2 2 626a32663c2f 8b89697eba2c 000000000000
19 19 3 144 48 3 3 f54c32f13478 626a32663c2f 000000000000
20 20 4 192 58 3 6 de68e904d169 626a32663c2f 000000000000
21 21 5 250 68 3 7 09bb521d218d de68e904d169 000000000000
22 22 6 318 54 6 8 1fde233dfb0f f54c32f13478 000000000000
23 23 checking changesets
24 24 checking manifests
25 25 crosschecking files in changesets and manifests
26 26 checking files
27 27 4 files, 9 changesets, 7 total revisions
28 28 searching for changes
29 29 1 changesets found
30 30 adding changesets
31 31 adding manifests
32 32 adding file changes
33 33 added 1 changesets with 1 changes to 1 files
34 34 (run 'hg update' to get a working copy)
35 35 checking changesets
36 36 checking manifests
37 37 crosschecking files in changesets and manifests
38 38 checking files
39 39 1 files, 1 changesets, 1 total revisions
40 40 0:5649c9d34dd8
41 41 searching for changes
42 42 2 changesets found
43 43 adding changesets
44 44 adding manifests
45 45 adding file changes
46 46 added 2 changesets with 2 changes to 1 files
47 47 (run 'hg update' to get a working copy)
48 48 checking changesets
49 49 checking manifests
50 50 crosschecking files in changesets and manifests
51 51 checking files
52 52 1 files, 2 changesets, 2 total revisions
53 53 1:10b2180f755b
54 54 searching for changes
55 55 3 changesets found
56 56 adding changesets
57 57 adding manifests
58 58 adding file changes
59 59 added 3 changesets with 3 changes to 1 files
60 60 (run 'hg update' to get a working copy)
61 61 checking changesets
62 62 checking manifests
63 63 crosschecking files in changesets and manifests
64 64 checking files
65 65 1 files, 3 changesets, 3 total revisions
66 66 2:d62976ca1e50
67 67 searching for changes
68 68 4 changesets found
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 4 changesets with 4 changes to 1 files
73 73 (run 'hg update' to get a working copy)
74 74 checking changesets
75 75 checking manifests
76 76 crosschecking files in changesets and manifests
77 77 checking files
78 78 1 files, 4 changesets, 4 total revisions
79 79 3:ac69c658229d
80 80 searching for changes
81 81 2 changesets found
82 82 adding changesets
83 83 adding manifests
84 84 adding file changes
85 85 added 2 changesets with 2 changes to 1 files
86 86 (run 'hg update' to get a working copy)
87 87 checking changesets
88 88 checking manifests
89 89 crosschecking files in changesets and manifests
90 90 checking files
91 91 1 files, 2 changesets, 2 total revisions
92 92 1:5f4f3ceb285e
93 93 searching for changes
94 94 3 changesets found
95 95 adding changesets
96 96 adding manifests
97 97 adding file changes
98 98 added 3 changesets with 3 changes to 1 files
99 99 (run 'hg update' to get a working copy)
100 100 checking changesets
101 101 checking manifests
102 102 crosschecking files in changesets and manifests
103 103 checking files
104 104 1 files, 3 changesets, 3 total revisions
105 105 2:024e4e7df376
106 106 searching for changes
107 107 4 changesets found
108 108 adding changesets
109 109 adding manifests
110 110 adding file changes
111 111 added 4 changesets with 5 changes to 2 files
112 112 (run 'hg update' to get a working copy)
113 113 checking changesets
114 114 checking manifests
115 115 crosschecking files in changesets and manifests
116 116 checking files
117 117 2 files, 4 changesets, 5 total revisions
118 118 3:1e3f6b843bd6
119 119 searching for changes
120 120 5 changesets found
121 121 adding changesets
122 122 adding manifests
123 123 adding file changes
124 124 added 5 changesets with 6 changes to 3 files
125 125 (run 'hg update' to get a working copy)
126 126 checking changesets
127 127 checking manifests
128 128 crosschecking files in changesets and manifests
129 129 checking files
130 130 3 files, 5 changesets, 6 total revisions
131 131 4:27f57c869697
132 132 searching for changes
133 133 5 changesets found
134 134 adding changesets
135 135 adding manifests
136 136 adding file changes
137 137 added 5 changesets with 5 changes to 2 files
138 138 (run 'hg update' to get a working copy)
139 139 checking changesets
140 140 checking manifests
141 141 crosschecking files in changesets and manifests
142 142 checking files
143 143 2 files, 5 changesets, 5 total revisions
144 144 4:088ff9d6e1e1
145 145 pulling from ../test-7
146 146 searching for changes
147 147 adding changesets
148 148 adding manifests
149 149 adding file changes
150 150 added 4 changesets with 2 changes to 3 files (+1 heads)
151 151 (run 'hg heads' to see heads, 'hg merge' to merge)
152 152 checking changesets
153 153 checking manifests
154 154 crosschecking files in changesets and manifests
155 155 checking files
156 156 4 files, 9 changesets, 7 total revisions
157 rolling back pull to revision 5
157 rolling back to revision 5 (undo pull)
158 158 % should fail
159 159 abort: --base is incompatible with specifying a destination
160 160 abort: repository default-push not found!
161 161 2 changesets found
162 162 4 changesets found
163 163 6 changesets found
164 164 1 changesets found
165 165 no changes found
166 166 1 changesets found
167 167 4 changesets found
168 168 updating to branch default
169 169 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 170 % 2
171 171 2:d62976ca1e50
172 172 adding changesets
173 173 transaction abort!
174 174 rollback completed
175 175 abort: 00changelog.i@ac69c658229d: unknown parent!
176 176 % 2
177 177 2:d62976ca1e50
178 178 adding changesets
179 179 adding manifests
180 180 adding file changes
181 181 added 6 changesets with 4 changes to 4 files (+1 heads)
182 182 (run 'hg heads' to see heads, 'hg merge' to merge)
183 183 % 8
184 184 8:088ff9d6e1e1
185 185 checking changesets
186 186 checking manifests
187 187 crosschecking files in changesets and manifests
188 188 checking files
189 189 4 files, 9 changesets, 7 total revisions
190 rolling back unbundle to revision 3
190 rolling back to revision 3 (undo unbundle)
191 191 % 2
192 192 2:d62976ca1e50
193 193 adding changesets
194 194 adding manifests
195 195 adding file changes
196 196 added 2 changesets with 2 changes to 2 files
197 197 (run 'hg update' to get a working copy)
198 198 % 4
199 199 4:088ff9d6e1e1
200 200 checking changesets
201 201 checking manifests
202 202 crosschecking files in changesets and manifests
203 203 checking files
204 204 2 files, 5 changesets, 5 total revisions
205 rolling back unbundle to revision 3
205 rolling back to revision 3 (undo unbundle)
206 206 adding changesets
207 207 adding manifests
208 208 adding file changes
209 209 added 4 changesets with 3 changes to 3 files (+1 heads)
210 210 (run 'hg heads' to see heads, 'hg merge' to merge)
211 211 % 6
212 212 6:27f57c869697
213 213 checking changesets
214 214 checking manifests
215 215 crosschecking files in changesets and manifests
216 216 checking files
217 217 3 files, 7 changesets, 6 total revisions
218 rolling back unbundle to revision 3
218 rolling back to revision 3 (undo unbundle)
219 219 adding changesets
220 220 adding manifests
221 221 adding file changes
222 222 added 2 changesets with 2 changes to 2 files
223 223 (run 'hg update' to get a working copy)
224 224 % 4
225 225 4:088ff9d6e1e1
226 226 checking changesets
227 227 checking manifests
228 228 crosschecking files in changesets and manifests
229 229 checking files
230 230 2 files, 5 changesets, 5 total revisions
231 231 warning: detected divergent renames of afile to:
232 232 anotherfile
233 233 adifferentfile
234 234 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 235 (branch merge, don't forget to commit)
236 236 7 changesets found
237 237 updating to branch default
238 238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 239 adding changesets
240 240 adding manifests
241 241 adding file changes
242 242 added 7 changesets with 4 changes to 4 files
243 243 (run 'hg update' to get a working copy)
244 244 % 9
245 245 9:e3061ea42e4c
246 246 checking changesets
247 247 checking manifests
248 248 crosschecking files in changesets and manifests
249 249 checking files
250 250 4 files, 10 changesets, 7 total revisions
@@ -1,365 +1,365 b''
1 1 ====== Setting up test
2 2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 3 created new head
4 4 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
5 5 checking changesets
6 6 checking manifests
7 7 crosschecking files in changesets and manifests
8 8 checking files
9 9 4 files, 9 changesets, 7 total revisions
10 10 ====== Bundle --all
11 11 9 changesets found
12 12 ====== Bundle test to full.hg
13 13 searching for changes
14 14 9 changesets found
15 15 ====== Unbundle full.hg in test
16 16 adding changesets
17 17 adding manifests
18 18 adding file changes
19 19 added 0 changesets with 0 changes to 4 files
20 20 (run 'hg update' to get a working copy)
21 21 ====== Verify empty
22 22 checking changesets
23 23 checking manifests
24 24 crosschecking files in changesets and manifests
25 25 checking files
26 26 0 files, 0 changesets, 0 total revisions
27 27 ====== Pull full.hg into test (using --cwd)
28 28 pulling from ../full.hg
29 29 searching for changes
30 30 no changes found
31 31 ====== Pull full.hg into empty (using --cwd)
32 32 pulling from ../full.hg
33 33 requesting all changes
34 34 adding changesets
35 35 adding manifests
36 36 adding file changes
37 37 added 9 changesets with 7 changes to 4 files (+1 heads)
38 38 (run 'hg heads' to see heads, 'hg merge' to merge)
39 39 ====== Rollback empty
40 rolling back pull to revision 0
40 rolling back to revision 0 (undo pull)
41 41 ====== Pull full.hg into empty again (using --cwd)
42 42 pulling from ../full.hg
43 43 requesting all changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 9 changesets with 7 changes to 4 files (+1 heads)
48 48 (run 'hg heads' to see heads, 'hg merge' to merge)
49 49 ====== Pull full.hg into test (using -R)
50 50 pulling from full.hg
51 51 searching for changes
52 52 no changes found
53 53 ====== Pull full.hg into empty (using -R)
54 54 pulling from full.hg
55 55 searching for changes
56 56 no changes found
57 57 ====== Rollback empty
58 rolling back pull to revision 0
58 rolling back to revision 0 (undo pull)
59 59 ====== Pull full.hg into empty again (using -R)
60 60 pulling from full.hg
61 61 requesting all changes
62 62 adding changesets
63 63 adding manifests
64 64 adding file changes
65 65 added 9 changesets with 7 changes to 4 files (+1 heads)
66 66 (run 'hg heads' to see heads, 'hg merge' to merge)
67 67 ====== Log -R full.hg in fresh empty
68 68 changeset: 8:088ff9d6e1e1
69 69 tag: tip
70 70 parent: 3:ac69c658229d
71 71 user: test
72 72 date: Mon Jan 12 13:46:40 1970 +0000
73 73 summary: 0.3m
74 74
75 75 changeset: 7:27f57c869697
76 76 user: test
77 77 date: Mon Jan 12 13:46:40 1970 +0000
78 78 summary: 1.3m
79 79
80 80 changeset: 6:1e3f6b843bd6
81 81 user: test
82 82 date: Mon Jan 12 13:46:40 1970 +0000
83 83 summary: 1.3
84 84
85 85 changeset: 5:024e4e7df376
86 86 user: test
87 87 date: Mon Jan 12 13:46:40 1970 +0000
88 88 summary: 1.2
89 89
90 90 changeset: 4:5f4f3ceb285e
91 91 parent: 0:5649c9d34dd8
92 92 user: test
93 93 date: Mon Jan 12 13:46:40 1970 +0000
94 94 summary: 1.1
95 95
96 96 changeset: 3:ac69c658229d
97 97 user: test
98 98 date: Mon Jan 12 13:46:40 1970 +0000
99 99 summary: 0.3
100 100
101 101 changeset: 2:d62976ca1e50
102 102 user: test
103 103 date: Mon Jan 12 13:46:40 1970 +0000
104 104 summary: 0.2
105 105
106 106 changeset: 1:10b2180f755b
107 107 user: test
108 108 date: Mon Jan 12 13:46:40 1970 +0000
109 109 summary: 0.1
110 110
111 111 changeset: 0:5649c9d34dd8
112 112 user: test
113 113 date: Mon Jan 12 13:46:40 1970 +0000
114 114 summary: 0.0
115 115
116 116 ====== Pull ../full.hg into empty (with hook)
117 117 changegroup hook: HG_NODE=5649c9d34dd87d0ecb5fd39672128376e83b22e1 HG_SOURCE=pull HG_URL=bundle:../full.hg
118 118 pulling from bundle://../full.hg
119 119 requesting all changes
120 120 adding changesets
121 121 adding manifests
122 122 adding file changes
123 123 added 9 changesets with 7 changes to 4 files (+1 heads)
124 124 (run 'hg heads' to see heads, 'hg merge' to merge)
125 125 ====== Rollback empty
126 rolling back pull to revision 0
126 rolling back to revision 0 (undo pull)
127 127 ====== Log -R bundle:empty+full.hg
128 128 8 7 6 5 4 3 2 1 0
129 129 ====== Pull full.hg into empty again (using -R; with hook)
130 130 changegroup hook: HG_NODE=5649c9d34dd87d0ecb5fd39672128376e83b22e1 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
131 131 pulling from full.hg
132 132 requesting all changes
133 133 adding changesets
134 134 adding manifests
135 135 adding file changes
136 136 added 9 changesets with 7 changes to 4 files (+1 heads)
137 137 (run 'hg heads' to see heads, 'hg merge' to merge)
138 138 ====== Create partial clones
139 139 requesting all changes
140 140 adding changesets
141 141 adding manifests
142 142 adding file changes
143 143 added 4 changesets with 4 changes to 1 files
144 144 updating to branch default
145 145 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 146 updating to branch default
147 147 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
148 148 ====== Log -R full.hg in partial
149 149 changeset: 8:088ff9d6e1e1
150 150 tag: tip
151 151 parent: 3:ac69c658229d
152 152 user: test
153 153 date: Mon Jan 12 13:46:40 1970 +0000
154 154 summary: 0.3m
155 155
156 156 changeset: 7:27f57c869697
157 157 user: test
158 158 date: Mon Jan 12 13:46:40 1970 +0000
159 159 summary: 1.3m
160 160
161 161 changeset: 6:1e3f6b843bd6
162 162 user: test
163 163 date: Mon Jan 12 13:46:40 1970 +0000
164 164 summary: 1.3
165 165
166 166 changeset: 5:024e4e7df376
167 167 user: test
168 168 date: Mon Jan 12 13:46:40 1970 +0000
169 169 summary: 1.2
170 170
171 171 changeset: 4:5f4f3ceb285e
172 172 parent: 0:5649c9d34dd8
173 173 user: test
174 174 date: Mon Jan 12 13:46:40 1970 +0000
175 175 summary: 1.1
176 176
177 177 changeset: 3:ac69c658229d
178 178 user: test
179 179 date: Mon Jan 12 13:46:40 1970 +0000
180 180 summary: 0.3
181 181
182 182 changeset: 2:d62976ca1e50
183 183 user: test
184 184 date: Mon Jan 12 13:46:40 1970 +0000
185 185 summary: 0.2
186 186
187 187 changeset: 1:10b2180f755b
188 188 user: test
189 189 date: Mon Jan 12 13:46:40 1970 +0000
190 190 summary: 0.1
191 191
192 192 changeset: 0:5649c9d34dd8
193 193 user: test
194 194 date: Mon Jan 12 13:46:40 1970 +0000
195 195 summary: 0.0
196 196
197 197 ====== Incoming full.hg in partial
198 198 comparing with bundle://../full.hg
199 199 searching for changes
200 200 changeset: 4:5f4f3ceb285e
201 201 parent: 0:5649c9d34dd8
202 202 user: test
203 203 date: Mon Jan 12 13:46:40 1970 +0000
204 204 summary: 1.1
205 205
206 206 changeset: 5:024e4e7df376
207 207 user: test
208 208 date: Mon Jan 12 13:46:40 1970 +0000
209 209 summary: 1.2
210 210
211 211 changeset: 6:1e3f6b843bd6
212 212 user: test
213 213 date: Mon Jan 12 13:46:40 1970 +0000
214 214 summary: 1.3
215 215
216 216 changeset: 7:27f57c869697
217 217 user: test
218 218 date: Mon Jan 12 13:46:40 1970 +0000
219 219 summary: 1.3m
220 220
221 221 changeset: 8:088ff9d6e1e1
222 222 tag: tip
223 223 parent: 3:ac69c658229d
224 224 user: test
225 225 date: Mon Jan 12 13:46:40 1970 +0000
226 226 summary: 0.3m
227 227
228 228 ====== Outgoing -R full.hg vs partial2 in partial
229 229 comparing with ../partial2
230 230 searching for changes
231 231 changeset: 4:5f4f3ceb285e
232 232 parent: 0:5649c9d34dd8
233 233 user: test
234 234 date: Mon Jan 12 13:46:40 1970 +0000
235 235 summary: 1.1
236 236
237 237 changeset: 5:024e4e7df376
238 238 user: test
239 239 date: Mon Jan 12 13:46:40 1970 +0000
240 240 summary: 1.2
241 241
242 242 changeset: 6:1e3f6b843bd6
243 243 user: test
244 244 date: Mon Jan 12 13:46:40 1970 +0000
245 245 summary: 1.3
246 246
247 247 changeset: 7:27f57c869697
248 248 user: test
249 249 date: Mon Jan 12 13:46:40 1970 +0000
250 250 summary: 1.3m
251 251
252 252 changeset: 8:088ff9d6e1e1
253 253 tag: tip
254 254 parent: 3:ac69c658229d
255 255 user: test
256 256 date: Mon Jan 12 13:46:40 1970 +0000
257 257 summary: 0.3m
258 258
259 259 ====== Outgoing -R does-not-exist.hg vs partial2 in partial
260 260 abort: No such file or directory: ../does-not-exist.hg
261 261 ====== Direct clone from bundle (all-history)
262 262 requesting all changes
263 263 adding changesets
264 264 adding manifests
265 265 adding file changes
266 266 added 9 changesets with 7 changes to 4 files (+1 heads)
267 267 updating to branch default
268 268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 269 changeset: 8:088ff9d6e1e1
270 270 tag: tip
271 271 parent: 3:ac69c658229d
272 272 user: test
273 273 date: Mon Jan 12 13:46:40 1970 +0000
274 274 summary: 0.3m
275 275
276 276 changeset: 7:27f57c869697
277 277 user: test
278 278 date: Mon Jan 12 13:46:40 1970 +0000
279 279 summary: 1.3m
280 280
281 281 ====== Unbundle incremental bundles into fresh empty in one go
282 282 1 changesets found
283 283 1 changesets found
284 284 adding changesets
285 285 adding manifests
286 286 adding file changes
287 287 added 1 changesets with 1 changes to 1 files
288 288 adding changesets
289 289 adding manifests
290 290 adding file changes
291 291 added 1 changesets with 1 changes to 1 files
292 292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
293 293 ====== test for 540d1059c802
294 294 updating to branch default
295 295 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
296 296 searching for changes
297 297 1 changesets found
298 298 comparing with ../bundle.hg
299 299 searching for changes
300 300 changeset: 2:ed1b79f46b9a
301 301 tag: tip
302 302 parent: 0:bbd179dfa0a7
303 303 user: test
304 304 date: Thu Jan 01 00:00:00 1970 +0000
305 305 summary: change foo
306 306
307 307 ===== test that verify bundle does not traceback
308 308 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
309 309 abort: cannot verify bundle or remote repos
310 310 checking changesets
311 311 checking manifests
312 312 crosschecking files in changesets and manifests
313 313 checking files
314 314 2 files, 2 changesets, 2 total revisions
315 315 ====== diff against bundle
316 316 diff -r 088ff9d6e1e1 anotherfile
317 317 --- a/anotherfile Mon Jan 12 13:46:40 1970 +0000
318 318 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
319 319 @@ -1,4 +0,0 @@
320 320 -0
321 321 -1
322 322 -2
323 323 -3
324 324 ====== bundle single branch
325 325 adding a
326 326 adding b
327 327 adding b1
328 328 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
329 329 adding c
330 330 created new head
331 331 adding c1
332 332 == bundling via incoming
333 333 comparing with .
334 334 searching for changes
335 335 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
336 336 5ece8e77363e2b5269e27c66828b72da29e4341a
337 337 == bundling
338 338 searching for changes
339 339 common changesets up to c0025332f9ed
340 340 2 changesets found
341 341 list of changesets:
342 342 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
343 343 5ece8e77363e2b5269e27c66828b72da29e4341a
344 344 bundling changes: 0 chunks
345 345 bundling changes: 1 chunks
346 346 bundling changes: 2 chunks
347 347 bundling changes: 3 chunks
348 348 bundling changes: 4 chunks
349 349 bundling changes: 5 chunks
350 350 bundling changes: 6 chunks
351 351 bundling manifests: 0 chunks
352 352 bundling manifests: 1 chunks
353 353 bundling manifests: 2 chunks
354 354 bundling manifests: 3 chunks
355 355 bundling manifests: 4 chunks
356 356 bundling manifests: 5 chunks
357 357 bundling manifests: 6 chunks
358 358 bundling files: b 0 chunks
359 359 bundling files: b 1 chunks
360 360 bundling files: b 2 chunks
361 361 bundling files: b 3 chunks
362 362 bundling files: b1 4 chunks
363 363 bundling files: b1 5 chunks
364 364 bundling files: b1 6 chunks
365 365 bundling files: b1 7 chunks
@@ -1,288 +1,288 b''
1 1 % create cvs repository
2 2 % create source directory
3 3 % import source directory
4 4 N src/a
5 5 N src/b/c
6 6
7 7 No conflicts created by this import
8 8
9 9 % checkout source directory
10 10 U src/a
11 11 U src/b/c
12 12 % commit a new revision changing b/c
13 13 checking in src/b/c,v
14 14 % convert fresh repo
15 15 initializing destination src-hg repository
16 16 connecting to cvsrepo
17 17 scanning source...
18 18 collecting CVS rlog
19 19 5 log entries
20 20 cvslog hook: 5 entries
21 21 creating changesets
22 22 3 changeset entries
23 23 cvschangesets hook: 3 changesets
24 24 sorting...
25 25 converting...
26 26 2 Initial revision
27 27 1 import
28 28 0 ci0
29 29 updating tags
30 30 a
31 31 c
32 32 c
33 33 % convert fresh repo with --filemap
34 34 initializing destination src-filemap repository
35 35 connecting to cvsrepo
36 36 scanning source...
37 37 collecting CVS rlog
38 38 5 log entries
39 39 cvslog hook: 5 entries
40 40 creating changesets
41 41 3 changeset entries
42 42 cvschangesets hook: 3 changesets
43 43 sorting...
44 44 converting...
45 45 2 Initial revision
46 46 1 import
47 47 filtering out empty revision
48 rolling back commit to revision 1
48 rolling back to revision 1 (undo commit)
49 49 0 ci0
50 50 updating tags
51 51 c
52 52 c
53 53 2 update tags files: .hgtags
54 54 1 ci0 files: b/c
55 55 0 Initial revision files: b/c
56 56 % convert full repository (issue1649)
57 57 U srcfull/src/a
58 58 U srcfull/src/b/c
59 59 CVS
60 60 CVSROOT
61 61 src
62 62 initializing destination srcfull-hg repository
63 63 connecting to cvsrepo
64 64 scanning source...
65 65 collecting CVS rlog
66 66 creating changesets
67 67 4 changeset entries
68 68 sorting...
69 69 converting...
70 70 updating tags
71 71 a
72 72 c
73 73 c
74 74 % commit new file revisions
75 75 checking in src/a,v
76 76 checking in src/b/c,v
77 77 % convert again
78 78 connecting to cvsrepo
79 79 scanning source...
80 80 collecting CVS rlog
81 81 7 log entries
82 82 cvslog hook: 7 entries
83 83 creating changesets
84 84 4 changeset entries
85 85 cvschangesets hook: 4 changesets
86 86 sorting...
87 87 converting...
88 88 0 ci1
89 89 a
90 90 a
91 91 c
92 92 c
93 93 c
94 94 % convert again with --filemap
95 95 connecting to cvsrepo
96 96 scanning source...
97 97 collecting CVS rlog
98 98 7 log entries
99 99 cvslog hook: 7 entries
100 100 creating changesets
101 101 4 changeset entries
102 102 cvschangesets hook: 4 changesets
103 103 sorting...
104 104 converting...
105 105 0 ci1
106 106 c
107 107 c
108 108 c
109 109 3 ci1 files: b/c
110 110 2 update tags files: .hgtags
111 111 1 ci0 files: b/c
112 112 0 Initial revision files: b/c
113 113 % commit branch
114 114 U b/c
115 115 T a
116 116 T b/c
117 117 checking in src/b/c,v
118 118 % convert again
119 119 connecting to cvsrepo
120 120 scanning source...
121 121 collecting CVS rlog
122 122 8 log entries
123 123 cvslog hook: 8 entries
124 124 creating changesets
125 125 5 changeset entries
126 126 cvschangesets hook: 5 changesets
127 127 sorting...
128 128 converting...
129 129 0 ci2
130 130 c
131 131 d
132 132 % convert again with --filemap
133 133 connecting to cvsrepo
134 134 scanning source...
135 135 collecting CVS rlog
136 136 8 log entries
137 137 cvslog hook: 8 entries
138 138 creating changesets
139 139 5 changeset entries
140 140 cvschangesets hook: 5 changesets
141 141 sorting...
142 142 converting...
143 143 0 ci2
144 144 c
145 145 d
146 146 4 ci2 files: b/c
147 147 3 ci1 files: b/c
148 148 2 update tags files: .hgtags
149 149 1 ci0 files: b/c
150 150 0 Initial revision files: b/c
151 151 % commit a new revision with funny log message
152 152 checking in src/a,v
153 153 % convert again
154 154 connecting to cvsrepo
155 155 scanning source...
156 156 collecting CVS rlog
157 157 9 log entries
158 158 cvslog hook: 9 entries
159 159 creating changesets
160 160 6 changeset entries
161 161 cvschangesets hook: 6 changesets
162 162 sorting...
163 163 converting...
164 164 0 funny
165 165 o 6 (branch) funny
166 166 | ----------------------------
167 167 | log message files: a
168 168 o 5 (branch) ci2 files: b/c
169 169
170 170 o 4 () ci1 files: a b/c
171 171 |
172 172 o 3 () update tags files: .hgtags
173 173 |
174 174 o 2 () ci0 files: b/c
175 175 |
176 176 | o 1 (INITIAL) import files:
177 177 |/
178 178 o 0 () Initial revision files: a b/c
179 179
180 180 % testing debugcvsps
181 181 collecting CVS rlog
182 182 9 log entries
183 183 cvslog hook: 9 entries
184 184 creating changesets
185 185 8 changeset entries
186 186 cvschangesets hook: 8 changesets
187 187 ---------------------
188 188 PatchSet 1
189 189 Date:
190 190 Author:
191 191 Branch: HEAD
192 192 Tag: (none)
193 193 Branchpoints: INITIAL
194 194 Log:
195 195 Initial revision
196 196
197 197 Members:
198 198 a:INITIAL->1.1
199 199
200 200 ---------------------
201 201 PatchSet 2
202 202 Date:
203 203 Author:
204 204 Branch: HEAD
205 205 Tag: (none)
206 206 Branchpoints: INITIAL, branch
207 207 Log:
208 208 Initial revision
209 209
210 210 Members:
211 211 b/c:INITIAL->1.1
212 212
213 213 ---------------------
214 214 PatchSet 3
215 215 Date:
216 216 Author:
217 217 Branch: INITIAL
218 218 Tag: start
219 219 Log:
220 220 import
221 221
222 222 Members:
223 223 a:1.1->1.1.1.1
224 224 b/c:1.1->1.1.1.1
225 225
226 226 ---------------------
227 227 PatchSet 4
228 228 Date:
229 229 Author:
230 230 Branch: HEAD
231 231 Tag: (none)
232 232 Log:
233 233 ci0
234 234
235 235 Members:
236 236 b/c:1.1->1.2
237 237
238 238 ---------------------
239 239 PatchSet 5
240 240 Date:
241 241 Author:
242 242 Branch: HEAD
243 243 Tag: (none)
244 244 Branchpoints: branch
245 245 Log:
246 246 ci1
247 247
248 248 Members:
249 249 a:1.1->1.2
250 250
251 251 ---------------------
252 252 PatchSet 6
253 253 Date:
254 254 Author:
255 255 Branch: HEAD
256 256 Tag: (none)
257 257 Log:
258 258 ci1
259 259
260 260 Members:
261 261 b/c:1.2->1.3
262 262
263 263 ---------------------
264 264 PatchSet 7
265 265 Date:
266 266 Author:
267 267 Branch: branch
268 268 Tag: (none)
269 269 Log:
270 270 ci2
271 271
272 272 Members:
273 273 b/c:1.1->1.1.2.1
274 274
275 275 ---------------------
276 276 PatchSet 8
277 277 Date:
278 278 Author:
279 279 Branch: branch
280 280 Tag: (none)
281 281 Log:
282 282 funny
283 283 ----------------------------
284 284 log message
285 285
286 286 Members:
287 287 a:1.2->1.2.2.1
288 288
@@ -1,63 +1,63 b''
1 1 adding a
2 2 % default context
3 3 diff -r cf9f4ba66af2 a
4 4 --- a/a
5 5 +++ b/a
6 6 @@ -2,7 +2,7 @@
7 7 c
8 8 a
9 9 a
10 10 -b
11 11 +dd
12 12 a
13 13 a
14 14 c
15 15 % --unified=2
16 16 diff -r cf9f4ba66af2 a
17 17 --- a/a
18 18 +++ b/a
19 19 @@ -3,5 +3,5 @@
20 20 a
21 21 a
22 22 -b
23 23 +dd
24 24 a
25 25 a
26 26 % diffstat
27 27 a | 2 +-
28 28 1 files changed, 1 insertions(+), 1 deletions(-)
29 29 % record
30 30 diff --git a/a b/a
31 31 old mode 100644
32 32 new mode 100755
33 33 1 hunks, 2 lines changed
34 34 examine changes to 'a'? [Ynsfdaq?]
35 35 @@ -2,7 +2,7 @@
36 36 c
37 37 a
38 38 a
39 39 -b
40 40 +dd
41 41 a
42 42 a
43 43 c
44 44 record this change to 'a'? [Ynsfdaq?]
45 45
46 rolling back commit to revision 1
46 rolling back to revision 1 (undo commit)
47 47 % qrecord
48 48 diff --git a/a b/a
49 49 old mode 100644
50 50 new mode 100755
51 51 1 hunks, 2 lines changed
52 52 examine changes to 'a'? [Ynsfdaq?]
53 53 @@ -2,7 +2,7 @@
54 54 c
55 55 a
56 56 a
57 57 -b
58 58 +dd
59 59 a
60 60 a
61 61 c
62 62 record this change to 'a'? [Ynsfdaq?]
63 63
@@ -1,177 +1,177 b''
1 1 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
2 2 pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$HGTMP/test-hook/a
3 3 0:29b62aeb769f
4 4 commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
5 5 commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
6 6 updating to branch default
7 7 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 8 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
9 9 pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
10 10 1:b702efe96888
11 11 commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
12 12 commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
13 13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
15 15 pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
16 16 2:1324a5531bac
17 17 commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
18 18 commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
19 19 created new head
20 20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 21 (branch merge, don't forget to commit)
22 22 precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
23 23 pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=$HGTMP/test-hook/a
24 24 3:4c52fb2e4022
25 25 commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
26 26 commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
27 27 pre-identify hook: HG_ARGS=id
28 28 warning: pre-identify hook exited with status 1
29 29 pre-cat hook: HG_ARGS=cat b
30 30 post-cat hook: HG_ARGS=cat b HG_RESULT=0
31 31 b
32 32 prechangegroup hook: HG_SOURCE=pull HG_URL=file:
33 33 changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
34 34 incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
35 35 incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
36 36 incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
37 37 pulling from ../a
38 38 searching for changes
39 39 adding changesets
40 40 adding manifests
41 41 adding file changes
42 42 added 3 changesets with 2 changes to 2 files
43 43 (run 'hg update' to get a working copy)
44 44 pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
45 45 precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
46 46 pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=$HGTMP/test-hook/a
47 47 4:8ea2ef7ad3e8
48 48 commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
49 49 commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
50 50 tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
51 51 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
52 52 tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
53 53 pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
54 54 pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
55 55 abort: pretag.forbid hook exited with status 1
56 56 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
57 57 pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
58 58 abort: pretag.forbid hook exited with status 1
59 59 4:8ea2ef7ad3e8
60 60 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
61 61 pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
62 62 5:fad284daf8c0
63 63 5:fad284daf8c0
64 64 pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
65 65 transaction abort!
66 66 rollback completed
67 67 abort: pretxncommit.forbid1 hook exited with status 1
68 68 4:8ea2ef7ad3e8
69 69 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
70 70 precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
71 71 abort: precommit.forbid hook exited with status 1
72 72 4:8ea2ef7ad3e8
73 73 preupdate hook: HG_PARENT1=b702efe96888
74 74 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
75 75 preupdate hook: HG_PARENT1=8ea2ef7ad3e8
76 76 update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
77 77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 78 3:4c52fb2e4022
79 79 prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
80 80 pulling from ../a
81 81 searching for changes
82 82 abort: prechangegroup.forbid hook exited with status 1
83 83 4:8ea2ef7ad3e8
84 84 pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/b HG_SOURCE=pull HG_URL=file:
85 85 pulling from ../a
86 86 searching for changes
87 87 adding changesets
88 88 adding manifests
89 89 adding file changes
90 90 added 1 changesets with 1 changes to 1 files
91 91 transaction abort!
92 92 rollback completed
93 93 abort: pretxnchangegroup.forbid1 hook exited with status 1
94 94 3:4c52fb2e4022
95 95 preoutgoing hook: HG_SOURCE=pull
96 96 outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
97 97 pulling from ../a
98 98 searching for changes
99 99 adding changesets
100 100 adding manifests
101 101 adding file changes
102 102 added 1 changesets with 1 changes to 1 files
103 103 (run 'hg update' to get a working copy)
104 rolling back pull to revision 4
104 rolling back to revision 4 (undo pull)
105 105 preoutgoing hook: HG_SOURCE=pull
106 106 preoutgoing.forbid hook: HG_SOURCE=pull
107 107 pulling from ../a
108 108 searching for changes
109 109 abort: preoutgoing.forbid hook exited with status 1
110 110 preoutgoing hook: HG_SOURCE=clone
111 111 outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
112 112 updating to branch default
113 113 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
114 114 preoutgoing hook: HG_SOURCE=clone
115 115 preoutgoing.forbid hook: HG_SOURCE=clone
116 116 abort: preoutgoing.forbid hook exited with status 1
117 117 # test python hooks
118 118 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
119 119 error: preoutgoing.raise hook raised an exception: exception from hook
120 120 pulling from ../a
121 121 searching for changes
122 122 error: preoutgoing.abort hook failed: raise abort from hook
123 123 abort: raise abort from hook
124 124 pulling from ../a
125 125 searching for changes
126 126 hook args:
127 127 hooktype preoutgoing
128 128 source pull
129 129 abort: preoutgoing.fail hook failed
130 130 pulling from ../a
131 131 searching for changes
132 132 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
133 133 pulling from ../a
134 134 searching for changes
135 135 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
136 136 pulling from ../a
137 137 searching for changes
138 138 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
139 139 pulling from ../a
140 140 searching for changes
141 141 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
142 142 pulling from ../a
143 143 searching for changes
144 144 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
145 145 pulling from ../a
146 146 searching for changes
147 147 hook args:
148 148 hooktype preoutgoing
149 149 source pull
150 150 adding changesets
151 151 adding manifests
152 152 adding file changes
153 153 added 1 changesets with 1 changes to 1 files
154 154 (run 'hg update' to get a working copy)
155 155 # make sure --traceback works
156 156 Traceback (most recent call last):
157 157 Automatically installed hook
158 158 foo
159 159 calling hook commit.auto: <function autohook>
160 160 Automatically installed hook
161 161 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
162 162 hooks.commit.auto=<function autohook>
163 163 # test python hook configured with python:[file]:[hook] syntax
164 164 hook works
165 165 nothing changed
166 166 # make sure --traceback works on hook import failure
167 167 exception from first failed import attempt:
168 168 Traceback (most recent call last):
169 169 ImportError: No module named somebogusmodule
170 170 exception from second failed import attempt:
171 171 Traceback (most recent call last):
172 172 ImportError: No module named hgext_importfail
173 173 Traceback (most recent call last):
174 174 # commit and update hooks should run after command completion (issue 1827)
175 175 8da618c33484 tip
176 176 29b62aeb769f
177 177 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1,381 +1,381 b''
1 1 adding a
2 2 adding d1/d2/a
3 3 % import exported patch
4 4 requesting all changes
5 5 adding changesets
6 6 adding manifests
7 7 adding file changes
8 8 added 1 changesets with 2 changes to 2 files
9 9 updating to branch default
10 10 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 11 applying ../tip.patch
12 12 % message should be same
13 13 summary: second change
14 14 % committer should be same
15 15 user: someone
16 16 % import exported patch with external patcher
17 17 requesting all changes
18 18 adding changesets
19 19 adding manifests
20 20 adding file changes
21 21 added 1 changesets with 2 changes to 2 files
22 22 updating to branch default
23 23 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 applying ../tip.patch
25 25 line2
26 26 % import of plain diff should fail without message
27 27 requesting all changes
28 28 adding changesets
29 29 adding manifests
30 30 adding file changes
31 31 added 1 changesets with 2 changes to 2 files
32 32 updating to branch default
33 33 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 applying ../tip.patch
35 35 abort: empty commit message
36 36 % import of plain diff should be ok with message
37 37 requesting all changes
38 38 adding changesets
39 39 adding manifests
40 40 adding file changes
41 41 added 1 changesets with 2 changes to 2 files
42 42 updating to branch default
43 43 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 applying ../tip.patch
45 45 % import of plain diff with specific date and user
46 46 requesting all changes
47 47 adding changesets
48 48 adding manifests
49 49 adding file changes
50 50 added 1 changesets with 2 changes to 2 files
51 51 updating to branch default
52 52 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 53 applying ../tip.patch
54 54 changeset: 1:ca68f19f3a40
55 55 tag: tip
56 56 user: user@nowhere.net
57 57 date: Thu Jan 01 00:00:01 1970 +0000
58 58 files: a
59 59 description:
60 60 patch
61 61
62 62
63 63 diff -r 80971e65b431 -r ca68f19f3a40 a
64 64 --- a/a Thu Jan 01 00:00:00 1970 +0000
65 65 +++ b/a Thu Jan 01 00:00:01 1970 +0000
66 66 @@ -1,1 +1,2 @@
67 67 line 1
68 68 +line 2
69 69
70 70 % import of plain diff should be ok with --no-commit
71 71 requesting all changes
72 72 adding changesets
73 73 adding manifests
74 74 adding file changes
75 75 added 1 changesets with 2 changes to 2 files
76 76 updating to branch default
77 77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 78 applying ../tip.patch
79 79 diff -r 80971e65b431 a
80 80 --- a/a
81 81 +++ b/a
82 82 @@ -1,1 +1,2 @@
83 83 line 1
84 84 +line 2
85 85 % hg -R repo import
86 86 requesting all changes
87 87 adding changesets
88 88 adding manifests
89 89 adding file changes
90 90 added 1 changesets with 2 changes to 2 files
91 91 updating to branch default
92 92 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 93 applying tip.patch
94 94 % import from stdin
95 95 requesting all changes
96 96 adding changesets
97 97 adding manifests
98 98 adding file changes
99 99 added 1 changesets with 2 changes to 2 files
100 100 updating to branch default
101 101 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 102 applying patch from stdin
103 103 % import two patches in one stream
104 104 applying patch from stdin
105 105 applied 80971e65b431
106 106 1d4bd90af0e4 tip
107 107 1d4bd90af0e4 tip
108 108 % override commit message
109 109 requesting all changes
110 110 adding changesets
111 111 adding manifests
112 112 adding file changes
113 113 added 1 changesets with 2 changes to 2 files
114 114 updating to branch default
115 115 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 116 applying patch from stdin
117 117 summary: override
118 118 % plain diff in email, subject, message body
119 119 requesting all changes
120 120 adding changesets
121 121 adding manifests
122 122 adding file changes
123 123 added 1 changesets with 2 changes to 2 files
124 124 updating to branch default
125 125 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 126 applying ../msg.patch
127 127 user: email patcher
128 128 summary: email patch
129 129 % plain diff in email, no subject, message body
130 130 requesting all changes
131 131 adding changesets
132 132 adding manifests
133 133 adding file changes
134 134 added 1 changesets with 2 changes to 2 files
135 135 updating to branch default
136 136 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137 applying patch from stdin
138 138 % plain diff in email, subject, no message body
139 139 requesting all changes
140 140 adding changesets
141 141 adding manifests
142 142 adding file changes
143 143 added 1 changesets with 2 changes to 2 files
144 144 updating to branch default
145 145 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 146 applying patch from stdin
147 147 % plain diff in email, no subject, no message body, should fail
148 148 requesting all changes
149 149 adding changesets
150 150 adding manifests
151 151 adding file changes
152 152 added 1 changesets with 2 changes to 2 files
153 153 updating to branch default
154 154 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 155 applying patch from stdin
156 156 abort: empty commit message
157 157 % hg export in email, should use patch header
158 158 requesting all changes
159 159 adding changesets
160 160 adding manifests
161 161 adding file changes
162 162 added 1 changesets with 2 changes to 2 files
163 163 updating to branch default
164 164 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 165 applying patch from stdin
166 166 summary: second change
167 167 % plain diff in email, [PATCH] subject, message body with subject
168 168 requesting all changes
169 169 adding changesets
170 170 adding manifests
171 171 adding file changes
172 172 added 1 changesets with 2 changes to 2 files
173 173 updating to branch default
174 174 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 175 applying patch from stdin
176 176 email patch
177 177
178 178 next line
179 179 ---
180 180 % import patch1 patch2; rollback
181 181 parent: 0
182 182 applying ../patch1
183 183 applying ../patch2
184 184 applied 1d4bd90af0e4
185 rolling back commit to revision 2
185 rolling back to revision 2 (undo commit)
186 186 parent: 1
187 187 % hg import in a subdirectory
188 188 requesting all changes
189 189 adding changesets
190 190 adding manifests
191 191 adding file changes
192 192 added 1 changesets with 2 changes to 2 files
193 193 updating to branch default
194 194 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 195 applying ../../../tip.patch
196 196 % message should be 'subdir change'
197 197 summary: subdir change
198 198 % committer should be 'someoneelse'
199 199 user: someoneelse
200 200 % should be empty
201 201 % test fuzziness
202 202 adding a
203 203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 204 created new head
205 205 applying tip.patch
206 206 patching file a
207 207 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
208 208 reverting a
209 209 % test fuzziness with eol=auto
210 210 applying tip.patch
211 211 patching file a
212 212 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
213 213 adding a
214 214 adding b1
215 215 adding c1
216 216 adding d
217 217 diff --git a/a b/a
218 218 --- a/a
219 219 +++ b/a
220 220 @@ -0,0 +1,1 @@
221 221 +a
222 222 diff --git a/b1 b/b2
223 223 rename from b1
224 224 rename to b2
225 225 --- a/b1
226 226 +++ b/b2
227 227 @@ -0,0 +1,1 @@
228 228 +b
229 229 diff --git a/c1 b/c1
230 230 --- a/c1
231 231 +++ b/c1
232 232 @@ -0,0 +1,1 @@
233 233 +c
234 234 diff --git a/c1 b/c2
235 235 copy from c1
236 236 copy to c2
237 237 --- a/c1
238 238 +++ b/c2
239 239 @@ -0,0 +1,1 @@
240 240 +c
241 241 diff --git a/d b/d
242 242 --- a/d
243 243 +++ b/d
244 244 @@ -1,1 +0,0 @@
245 245 -d
246 246 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
247 247 applying empty.diff
248 248 % a file
249 249 a
250 250 % b1 file
251 251 % b2 file
252 252 b
253 253 % c1 file
254 254 c
255 255 % c2 file
256 256 c
257 257 % d file
258 258 % test trailing binary removal
259 259 adding a
260 260 adding b
261 261 R a
262 262 R b
263 263 diff --git a/a b/a
264 264 diff --git a/b b/b
265 265 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 266 applying remove.diff
267 267 % test update+rename with common name (issue 927)
268 268 adding a
269 269 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
270 270 applying copy.diff
271 271 % view a
272 272 a
273 273 % view a2
274 274 a
275 275 % test -p0
276 276 adding a
277 277 applying patch from stdin
278 278 bb
279 279 % test paths outside repo root
280 280 applying patch from stdin
281 281 abort: ../outside/foo not under root
282 282 % test import with similarity (issue295)
283 283 adding a
284 284 applying ../rename.diff
285 285 patching file a
286 286 patching file b
287 287 removing a
288 288 adding b
289 289 recording removal of a as rename to b (88% similar)
290 290 A b
291 291 a
292 292 R a
293 293 undeleting a
294 294 forgetting b
295 295 applying ../rename.diff
296 296 patching file a
297 297 patching file b
298 298 removing a
299 299 adding b
300 300 A b
301 301 R a
302 302 % add empty file from the end of patch (issue 1495)
303 303 adding a
304 304 applying a.patch
305 305 % create file when source is not /dev/null
306 306 applying ../create.patch
307 307 a
308 308 applying ../create2.patch
309 309 a
310 310 % first line mistaken for email headers (issue 1859)
311 311 applying a.patch
312 312 changeset: 0:5a681217c0ad
313 313 tag: tip
314 314 user: test
315 315 date: Thu Jan 01 00:00:00 1970 +0000
316 316 files: a
317 317 description:
318 318 module: summary
319 319
320 320 description
321 321
322 322
323 323 % --- in commit message
324 324 applying a.patch
325 325 changeset: 0:f34d9187897d
326 326 tag: tip
327 327 user: test
328 328 date: Thu Jan 01 00:00:00 1970 +0000
329 329 files: a
330 330 description:
331 331 module: summary
332 332
333 333
334 334 % tricky header splitting
335 335 applying ../trickyheaders.patch
336 336 # HG changeset patch
337 337 # User User B
338 338 # Date 0 0
339 339 # Node ID eb56ab91903632294ac504838508cb370c0901d2
340 340 # Parent 0000000000000000000000000000000000000000
341 341 from: tricky!
342 342
343 343 That is not a header.
344 344
345 345 diff --git a/foo b/foo
346 346 new file mode 100644
347 347 --- /dev/null
348 348 +++ b/foo
349 349 @@ -0,0 +1,1 @@
350 350 +foo
351 351 % issue2102
352 352 adding src/cmd/gc/mksys.bash
353 353 applying patch from stdin
354 354 parent: 1:d59915696727 tip
355 355 help management of empty pkg and lib directories in perforce
356 356 branch: default
357 357 commit: (clean)
358 358 update: (current)
359 359 diff --git a/lib/place-holder b/lib/place-holder
360 360 new file mode 100644
361 361 --- /dev/null
362 362 +++ b/lib/place-holder
363 363 @@ -0,0 +1,2 @@
364 364 +perforce does not maintain empty directories.
365 365 +this file helps.
366 366 diff --git a/pkg/place-holder b/pkg/place-holder
367 367 new file mode 100644
368 368 --- /dev/null
369 369 +++ b/pkg/place-holder
370 370 @@ -0,0 +1,2 @@
371 371 +perforce does not maintain empty directories.
372 372 +this file helps.
373 373 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
374 374 old mode 100644
375 375 new mode 100755
376 376 % diff lines looking like headers
377 377 adding a
378 378 adding b
379 379 adding c
380 380 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 381 applying patch from stdin
@@ -1,480 +1,480 b''
1 1 % hg kwdemo
2 2 [extensions]
3 3 keyword =
4 4 [keyword]
5 5 demo.txt =
6 6 [keywordmaps]
7 7 Author = {author|user}
8 8 Date = {date|utcdate}
9 9 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
10 10 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
11 11 RCSFile = {file|basename},v
12 12 RCSfile = {file|basename},v
13 13 Revision = {node|short}
14 14 Source = {root}/{file},v
15 15 $Author: test $
16 16 $Date: 2000/00/00 00:00:00 $
17 17 $Header: /TMP/demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
18 18 $Id: demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
19 19 $RCSFile: demo.txt,v $
20 20 $RCSfile: demo.txt,v $
21 21 $Revision: xxxxxxxxxxxx $
22 22 $Source: /TMP/demo.txt,v $
23 23 [extensions]
24 24 keyword =
25 25 [keyword]
26 26 demo.txt =
27 27 [keywordmaps]
28 28 Branch = {branches}
29 29 $Branch: demobranch $
30 30 % kwshrink should exit silently in empty/invalid repo
31 31 pulling from test-keyword.hg
32 32 requesting all changes
33 33 adding changesets
34 34 adding manifests
35 35 adding file changes
36 36 added 1 changesets with 1 changes to 1 files
37 37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 38 % cat
39 39 expand $Id$
40 40 do not process $Id:
41 41 xxx $
42 42 ignore $Id$
43 43 % no kwfiles
44 44 % untracked candidates
45 45 k a
46 46 % addremove
47 47 adding a
48 48 adding b
49 49 % status
50 50 A a
51 51 A b
52 52 % default keyword expansion including commit hook
53 53 % interrupted commit should not change state or run commit hook
54 54 abort: empty commit message
55 55 % status
56 56 A a
57 57 A b
58 58 % commit
59 59 a
60 60 b
61 61 overwriting a expanding keywords
62 62 running hook commit.test: cp a hooktest
63 63 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
64 64 % status
65 65 ? hooktest
66 66 % identify
67 67 ef63ca68695b
68 68 % cat
69 69 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
70 70 do not process $Id:
71 71 xxx $
72 72 ignore $Id$
73 73 % hg cat
74 74 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
75 75 do not process $Id:
76 76 xxx $
77 77 ignore $Id$
78 78 a
79 79 % diff a hooktest
80 80 % removing commit hook from config
81 81 % bundle
82 82 2 changesets found
83 83 % notify on pull to check whether keywords stay as is in email
84 84 % ie. if patch.diff wrapper acts as it should
85 85 % pull from bundle
86 86 pulling from ../kw.hg
87 87 requesting all changes
88 88 adding changesets
89 89 adding manifests
90 90 adding file changes
91 91 added 2 changesets with 3 changes to 3 files
92 92
93 93 diff -r 000000000000 -r a2392c293916 sym
94 94 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95 95 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
96 96 @@ -0,0 +1,1 @@
97 97 +a
98 98 \ No newline at end of file
99 99
100 100 diff -r a2392c293916 -r ef63ca68695b a
101 101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102 102 +++ b/a Thu Jan 01 00:00:00 1970 +0000
103 103 @@ -0,0 +1,3 @@
104 104 +expand $Id$
105 105 +do not process $Id:
106 106 +xxx $
107 107 diff -r a2392c293916 -r ef63ca68695b b
108 108 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109 109 +++ b/b Thu Jan 01 00:00:00 1970 +0000
110 110 @@ -0,0 +1,1 @@
111 111 +ignore $Id$
112 112 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 113 % remove notify config
114 114 % touch
115 115 % status
116 116 % update
117 117 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 118 % cat
119 119 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
120 120 do not process $Id:
121 121 xxx $
122 122 ignore $Id$
123 123 % check whether expansion is filewise
124 124 % commit c
125 125 adding c
126 126 % force expansion
127 127 overwriting a expanding keywords
128 128 overwriting c expanding keywords
129 129 % compare changenodes in a c
130 130 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
131 131 do not process $Id:
132 132 xxx $
133 133 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
134 134 tests for different changenodes
135 135 % qinit -c
136 136 % qimport
137 137 % qcommit
138 138 % keywords should not be expanded in patch
139 139 # HG changeset patch
140 140 # User User Name <user@example.com>
141 141 # Date 1 0
142 142 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
143 143 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
144 144 cndiff
145 145
146 146 diff -r ef63ca68695b -r 40a904bbbe4c c
147 147 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
148 148 +++ b/c Thu Jan 01 00:00:01 1970 +0000
149 149 @@ -0,0 +1,2 @@
150 150 +$Id$
151 151 +tests for different changenodes
152 152 % qpop
153 153 popping mqtest.diff
154 154 patch queue now empty
155 155 % qgoto - should imply qpush
156 156 applying mqtest.diff
157 157 now at: mqtest.diff
158 158 % cat
159 159 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
160 160 tests for different changenodes
161 161 % qpop and move on
162 162 popping mqtest.diff
163 163 patch queue now empty
164 164 % copy
165 165 % kwfiles added
166 166 a
167 167 c
168 168 % commit
169 169 c
170 170 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
171 171 overwriting c expanding keywords
172 172 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
173 173 % cat a c
174 174 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
175 175 do not process $Id:
176 176 xxx $
177 177 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
178 178 do not process $Id:
179 179 xxx $
180 180 % touch copied c
181 181 % status
182 182 % kwfiles
183 183 a
184 184 c
185 185 % ignored files
186 186 I b
187 187 I sym
188 188 % all files
189 189 K a
190 190 K c
191 191 I b
192 192 I sym
193 193 % diff --rev
194 194 diff -r ef63ca68695b c
195 195 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
196 196 @@ -0,0 +1,3 @@
197 197 +expand $Id$
198 198 +do not process $Id:
199 199 +xxx $
200 200 % rollback
201 rolling back commit to revision 2
201 rolling back to revision 2 (undo commit)
202 202 % status
203 203 A c
204 204 % update -C
205 205 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 206 % custom keyword expansion
207 207 % try with kwdemo
208 208 [extensions]
209 209 keyword =
210 210 [keyword]
211 211 * =
212 212 b = ignore
213 213 demo.txt =
214 214 [keywordmaps]
215 215 Xinfo = {author}: {desc}
216 216 $Xinfo: test: hg keyword configuration and expansion example $
217 217 % cat
218 218 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
219 219 do not process $Id:
220 220 xxx $
221 221 ignore $Id$
222 222 % hg cat
223 223 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
224 224 do not process $Id:
225 225 xxx $
226 226 ignore $Id$
227 227 a
228 228 % interrupted commit should not change state
229 229 abort: empty commit message
230 230 % status
231 231 M a
232 232 ? c
233 233 ? log
234 234 % commit
235 235 a
236 236 overwriting a expanding keywords
237 237 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
238 238 % status
239 239 ? c
240 240 % verify
241 241 checking changesets
242 242 checking manifests
243 243 crosschecking files in changesets and manifests
244 244 checking files
245 245 3 files, 3 changesets, 4 total revisions
246 246 % cat
247 247 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
248 248 do not process $Id:
249 249 xxx $
250 250 $Xinfo: User Name <user@example.com>: firstline $
251 251 ignore $Id$
252 252 % hg cat
253 253 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
254 254 do not process $Id:
255 255 xxx $
256 256 $Xinfo: User Name <user@example.com>: firstline $
257 257 ignore $Id$
258 258 a
259 259 % annotate
260 260 1: expand $Id$
261 261 1: do not process $Id:
262 262 1: xxx $
263 263 2: $Xinfo$
264 264 % remove
265 265 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
266 266 % status
267 267 ? c
268 268 % rollback
269 rolling back commit to revision 3
269 rolling back to revision 3 (undo commit)
270 270 % status
271 271 R a
272 272 ? c
273 273 % revert a
274 274 % cat a
275 275 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
276 276 do not process $Id:
277 277 xxx $
278 278 $Xinfo: User Name <user@example.com>: firstline $
279 279 % clone to test incoming
280 280 requesting all changes
281 281 adding changesets
282 282 adding manifests
283 283 adding file changes
284 284 added 2 changesets with 3 changes to 3 files
285 285 updating to branch default
286 286 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 287 % incoming
288 288 comparing with test-keyword/Test
289 289 searching for changes
290 290 changeset: 2:bb948857c743
291 291 tag: tip
292 292 user: User Name <user@example.com>
293 293 date: Thu Jan 01 00:00:02 1970 +0000
294 294 summary: firstline
295 295
296 296 % commit rejecttest
297 297 a
298 298 overwriting a expanding keywords
299 299 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
300 300 % export
301 301 % import
302 302 applying ../rejecttest.diff
303 303 % cat
304 304 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
305 305 do not process $Id: rejecttest
306 306 xxx $
307 307 $Xinfo: User Name <user@example.com>: rejects? $
308 308 ignore $Id$
309 309
310 310 % rollback
311 rolling back commit to revision 3
311 rolling back to revision 3 (undo commit)
312 312 % clean update
313 313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 314 % kwexpand/kwshrink on selected files
315 315 % copy a x/a
316 316 % kwexpand a
317 317 overwriting a expanding keywords
318 318 % kwexpand x/a should abort
319 319 abort: outstanding uncommitted changes
320 320 x/a
321 321 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
322 322 overwriting x/a expanding keywords
323 323 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
324 324 % cat a
325 325 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
326 326 do not process $Id:
327 327 xxx $
328 328 $Xinfo: User Name <user@example.com>: xa $
329 329 % kwshrink a inside directory x
330 330 overwriting x/a shrinking keywords
331 331 % cat a
332 332 expand $Id$
333 333 do not process $Id:
334 334 xxx $
335 335 $Xinfo$
336 336 % kwexpand nonexistent
337 337 nonexistent:
338 338 % hg serve
339 339 % expansion
340 340 % hgweb file
341 341 200 Script output follows
342 342
343 343 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
344 344 do not process $Id:
345 345 xxx $
346 346 $Xinfo: User Name <user@example.com>: firstline $
347 347 % no expansion
348 348 % hgweb annotate
349 349 200 Script output follows
350 350
351 351
352 352 user@1: expand $Id$
353 353 user@1: do not process $Id:
354 354 user@1: xxx $
355 355 user@2: $Xinfo$
356 356
357 357
358 358
359 359
360 360 % hgweb changeset
361 361 200 Script output follows
362 362
363 363
364 364 # HG changeset patch
365 365 # User User Name <user@example.com>
366 366 # Date 3 0
367 367 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
368 368 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
369 369 xa
370 370
371 371 diff -r bb948857c743 -r b4560182a3f9 x/a
372 372 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
373 373 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
374 374 @@ -0,0 +1,4 @@
375 375 +expand $Id$
376 376 +do not process $Id:
377 377 +xxx $
378 378 +$Xinfo$
379 379
380 380 % hgweb filediff
381 381 200 Script output follows
382 382
383 383
384 384 diff -r ef63ca68695b -r bb948857c743 a
385 385 --- a/a Thu Jan 01 00:00:00 1970 +0000
386 386 +++ b/a Thu Jan 01 00:00:02 1970 +0000
387 387 @@ -1,3 +1,4 @@
388 388 expand $Id$
389 389 do not process $Id:
390 390 xxx $
391 391 +$Xinfo$
392 392
393 393
394 394
395 395
396 396 % errors encountered
397 397 % merge/resolve
398 398 % simplemerge
399 399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 400 created new head
401 401 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 402 (branch merge, don't forget to commit)
403 403 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
404 404 foo
405 405 % conflict
406 406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 407 created new head
408 408 merging m
409 409 warning: conflicts during merge.
410 410 merging m failed!
411 411 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
412 412 use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon
413 413 % keyword stays outside conflict zone
414 414 $Id$
415 415 <<<<<<< local
416 416 bar
417 417 =======
418 418 foo
419 419 >>>>>>> other
420 420 % resolve to local
421 421 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
422 422 bar
423 423 % test restricted mode with transplant -b
424 424 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 425 marked working directory as branch foo
426 426 created new head
427 427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 428 applying 4aa30d025d50
429 429 4aa30d025d50 transplanted to 5a4da427c162
430 430 % no expansion in changeset
431 431 changeset: 11:5a4da427c162
432 432 tag: tip
433 433 parent: 9:41efa6d38e9b
434 434 user: test
435 435 date: Thu Jan 01 00:00:00 1970 +0000
436 436 summary: 9foobranch
437 437
438 438 diff -r 41efa6d38e9b -r 5a4da427c162 a
439 439 --- a/a Thu Jan 01 00:00:00 1970 +0000
440 440 +++ b/a Thu Jan 01 00:00:00 1970 +0000
441 441 @@ -1,3 +1,4 @@
442 442 +foobranch
443 443 expand $Id$
444 444 do not process $Id:
445 445 xxx $
446 446
447 447 % expansion in file
448 448 foobranch
449 449 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
450 450 % switch off expansion
451 451 % kwshrink with unknown file u
452 452 overwriting a shrinking keywords
453 453 overwriting m shrinking keywords
454 454 overwriting x/a shrinking keywords
455 455 % cat
456 456 expand $Id$
457 457 do not process $Id:
458 458 xxx $
459 459 $Xinfo$
460 460 ignore $Id$
461 461 % hg cat
462 462 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
463 463 do not process $Id:
464 464 xxx $
465 465 $Xinfo: User Name <user@example.com>: firstline $
466 466 ignore $Id$
467 467 a
468 468 % cat
469 469 expand $Id$
470 470 do not process $Id:
471 471 xxx $
472 472 $Xinfo$
473 473 ignore $Id$
474 474 % hg cat
475 475 expand $Id$
476 476 do not process $Id:
477 477 xxx $
478 478 $Xinfo$
479 479 ignore $Id$
480 480 a
@@ -1,181 +1,181 b''
1 1 marked working directory as branch foo
2 2 foo
3 3 marked working directory as branch bar
4 4 % branch shadowing
5 5 abort: a branch of the same name already exists (use 'hg update' to switch to it)
6 6 marked working directory as branch default
7 7 % there should be only one default branch head
8 8 changeset: 3:bf1bc2f45e83
9 9 tag: tip
10 10 user: test
11 11 date: Mon Jan 12 13:46:40 1970 +0000
12 12 summary: clear branch name
13 13
14 14 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15 foo
16 16 created new head
17 17 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 18 (branch merge, don't forget to commit)
19 19 foo
20 20 changeset: 5:5f8fb06e083e
21 21 branch: foo
22 22 tag: tip
23 23 parent: 4:4909a3732169
24 24 parent: 3:bf1bc2f45e83
25 25 user: test
26 26 date: Mon Jan 12 13:46:40 1970 +0000
27 27 summary: merge
28 28
29 29 changeset: 4:4909a3732169
30 30 branch: foo
31 31 parent: 1:b699b1cec9c2
32 32 user: test
33 33 date: Mon Jan 12 13:46:40 1970 +0000
34 34 summary: modify a branch
35 35
36 36 changeset: 3:bf1bc2f45e83
37 37 user: test
38 38 date: Mon Jan 12 13:46:40 1970 +0000
39 39 summary: clear branch name
40 40
41 41 changeset: 2:67ec16bde7f1
42 42 branch: bar
43 43 user: test
44 44 date: Mon Jan 12 13:46:40 1970 +0000
45 45 summary: change branch name
46 46
47 47 changeset: 1:b699b1cec9c2
48 48 branch: foo
49 49 user: test
50 50 date: Mon Jan 12 13:46:40 1970 +0000
51 51 summary: add branch name
52 52
53 53 changeset: 0:be8523e69bf8
54 54 user: test
55 55 date: Mon Jan 12 13:46:40 1970 +0000
56 56 summary: initial
57 57
58 58 foo 5:5f8fb06e083e
59 59 default 3:bf1bc2f45e83 (inactive)
60 60 bar 2:67ec16bde7f1 (inactive)
61 61 foo
62 62 default
63 63 bar
64 64 % test for invalid branch cache
65 rolling back commit to revision 5
65 rolling back to revision 5 (undo commit)
66 66 changeset: 4:4909a3732169
67 67 branch: foo
68 68 tag: tip
69 69 parent: 1:b699b1cec9c2
70 70 user: test
71 71 date: Mon Jan 12 13:46:40 1970 +0000
72 72 summary: modify a branch
73 73
74 74 invalidating branch cache (tip differs)
75 75 changeset: 4:4909a3732169c0c20011c4f4b8fdff4e3d89b23f
76 76 branch: foo
77 77 tag: tip
78 78 parent: 1:b699b1cec9c2966b3700de4fef0dc123cd754c31
79 79 parent: -1:0000000000000000000000000000000000000000
80 80 manifest: 4:d01b250baaa05909152f7ae07d7a649deea0df9a
81 81 user: test
82 82 date: Mon Jan 12 13:46:40 1970 +0000
83 83 files: a
84 84 extra: branch=foo
85 85 description:
86 86 modify a branch
87 87
88 88
89 89 4:4909a3732169
90 90 4909a3732169c0c20011c4f4b8fdff4e3d89b23f 4
91 91 bf1bc2f45e834c75404d0ddab57d53beab56e2f8 default
92 92 4909a3732169c0c20011c4f4b8fdff4e3d89b23f foo
93 93 67ec16bde7f1575d523313b9bca000f6a6f12dca bar
94 94 % push should update the branch cache
95 95 % pushing just rev 0
96 96 be8523e69bf892e25817fc97187516b3c0804ae4 0
97 97 be8523e69bf892e25817fc97187516b3c0804ae4 default
98 98 % pushing everything
99 99 4909a3732169c0c20011c4f4b8fdff4e3d89b23f 4
100 100 bf1bc2f45e834c75404d0ddab57d53beab56e2f8 default
101 101 4909a3732169c0c20011c4f4b8fdff4e3d89b23f foo
102 102 67ec16bde7f1575d523313b9bca000f6a6f12dca bar
103 103 % update with no arguments: tipmost revision of the current branch
104 104 bf1bc2f45e83
105 105 4909a3732169 (foo) tip
106 106 marked working directory as branch foobar
107 107 abort: branch foobar not found
108 108 % fastforward merge
109 109 marked working directory as branch ff
110 110 adding ff
111 111 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
112 112 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 113 (branch merge, don't forget to commit)
114 114 foo
115 115 changeset: 6:f0c74f92a385
116 116 branch: foo
117 117 tag: tip
118 118 parent: 4:4909a3732169
119 119 parent: 5:c420d2121b71
120 120 user: test
121 121 date: Mon Jan 12 13:46:40 1970 +0000
122 122 summary: Merge ff into foo
123 123
124 124 a
125 125 ff
126 126 % test merging, add 3 default heads and one test head
127 127 adding a
128 128 adding b
129 129 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
130 130 adding c
131 131 created new head
132 132 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 133 adding d
134 134 created new head
135 135 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
136 136 marked working directory as branch test
137 137 adding e
138 138 created new head
139 139 changeset: 4:3a1e01ed1df4
140 140 branch: test
141 141 tag: tip
142 142 parent: 0:cb9a9f314b8b
143 143 user: test
144 144 date: Thu Jan 01 00:00:00 1970 +0000
145 145 summary: e
146 146
147 147 changeset: 3:980f7dc84c29
148 148 parent: 0:cb9a9f314b8b
149 149 user: test
150 150 date: Thu Jan 01 00:00:00 1970 +0000
151 151 summary: d
152 152
153 153 changeset: 2:d36c0562f908
154 154 parent: 0:cb9a9f314b8b
155 155 user: test
156 156 date: Thu Jan 01 00:00:00 1970 +0000
157 157 summary: c
158 158
159 159 changeset: 1:d2ae7f538514
160 160 user: test
161 161 date: Thu Jan 01 00:00:00 1970 +0000
162 162 summary: b
163 163
164 164 changeset: 0:cb9a9f314b8b
165 165 user: test
166 166 date: Thu Jan 01 00:00:00 1970 +0000
167 167 summary: a
168 168
169 169 % implicit merge with test branch as parent
170 170 abort: branch 'test' has one head - please merge with an explicit rev
171 171 (run 'hg heads' to see all heads)
172 172 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
173 173 % implicit merge with default branch as parent
174 174 abort: branch 'default' has 3 heads - please merge with an explicit rev
175 175 (run 'hg heads .' to see heads)
176 176 % 3 branch heads, explicit merge required
177 177 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 178 (branch merge, don't forget to commit)
179 179 % 2 branch heads, implicit merge works
180 180 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
181 181 (branch merge, don't forget to commit)
@@ -1,219 +1,219 b''
1 1 notify extension - hooks for sending email notifications at commit/push time
2 2
3 3 Subscriptions can be managed through a hgrc file. Default mode is to print
4 4 messages to stdout, for testing and configuring.
5 5
6 6 To use, configure the notify extension and enable it in hgrc like this:
7 7
8 8 [extensions]
9 9 notify =
10 10
11 11 [hooks]
12 12 # one email for each incoming changeset
13 13 incoming.notify = python:hgext.notify.hook
14 14 # batch emails when many changesets incoming at one time
15 15 changegroup.notify = python:hgext.notify.hook
16 16
17 17 [notify]
18 18 # config items go here
19 19
20 20 Required configuration items:
21 21
22 22 config = /path/to/file # file containing subscriptions
23 23
24 24 Optional configuration items:
25 25
26 26 test = True # print messages to stdout for testing
27 27 strip = 3 # number of slashes to strip for url paths
28 28 domain = example.com # domain to use if committer missing domain
29 29 style = ... # style file to use when formatting email
30 30 template = ... # template to use when formatting email
31 31 incoming = ... # template to use when run as incoming hook
32 32 changegroup = ... # template when run as changegroup hook
33 33 maxdiff = 300 # max lines of diffs to include (0=none, -1=all)
34 34 maxsubject = 67 # truncate subject line longer than this
35 35 diffstat = True # add a diffstat before the diff content
36 36 sources = serve # notify if source of incoming changes in this list
37 37 # (serve == ssh or http, push, pull, bundle)
38 38 merge = False # send notification for merges (default True)
39 39 [email]
40 40 from = user@host.com # email address to send as if none given
41 41 [web]
42 42 baseurl = http://hgserver/... # root of hg web site for browsing commits
43 43
44 44 The notify config file has same format as a regular hgrc file. It has two
45 45 sections so you can express subscriptions in whatever way is handier for you.
46 46
47 47 [usersubs]
48 48 # key is subscriber email, value is ","-separated list of glob patterns
49 49 user@host = pattern
50 50
51 51 [reposubs]
52 52 # key is glob pattern, value is ","-separated list of subscriber emails
53 53 pattern = user@host
54 54
55 55 Glob patterns are matched against path to repository root.
56 56
57 57 If you like, you can put notify config file in repository that users can push
58 58 changes to, they can manage their own subscriptions.
59 59
60 60 no commands defined
61 61 % commit
62 62 adding a
63 63 % clone
64 64 updating to branch default
65 65 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 66 % commit
67 67 % pull (minimal config)
68 68 pulling from ../a
69 69 searching for changes
70 70 adding changesets
71 71 adding manifests
72 72 adding file changes
73 73 added 1 changesets with 1 changes to 1 files
74 74 Content-Type: text/plain; charset="us-ascii"
75 75 MIME-Version: 1.0
76 76 Content-Transfer-Encoding: 7bit
77 77 Date:
78 78 Subject: changeset in test-notify/b: b
79 79 From: test
80 80 X-Hg-Notification: changeset 0647d048b600
81 81 Message-Id:
82 82 To: baz, foo@bar
83 83
84 84 changeset 0647d048b600 in test-notify/b
85 85 details: test-notify/b?cmd=changeset;node=0647d048b600
86 86 description: b
87 87
88 88 diffs (6 lines):
89 89
90 90 diff -r cb9a9f314b8b -r 0647d048b600 a
91 91 --- a/a Thu Jan 01 00:00:00 1970 +0000
92 92 +++ b/a Thu Jan 01 00:00:01 1970 +0000
93 93 @@ -1,1 +1,2 @@
94 94 a
95 95 +a
96 96 (run 'hg update' to get a working copy)
97 97 % fail for config file is missing
98 rolling back pull to revision 1
98 rolling back to revision 1 (undo pull)
99 99 pull failed
100 100 % pull
101 rolling back pull to revision 1
101 rolling back to revision 1 (undo pull)
102 102 pulling from ../a
103 103 searching for changes
104 104 adding changesets
105 105 adding manifests
106 106 adding file changes
107 107 added 1 changesets with 1 changes to 1 files
108 108 Content-Type: text/plain; charset="us-ascii"
109 109 MIME-Version: 1.0
110 110 Content-Transfer-Encoding: 7bit
111 111 X-Test: foo
112 112 Date:
113 113 Subject: b
114 114 From: test@test.com
115 115 X-Hg-Notification: changeset 0647d048b600
116 116 Message-Id:
117 117 To: baz@test.com, foo@bar
118 118
119 119 changeset 0647d048b600
120 120 description:
121 121 b
122 122 diffs (6 lines):
123 123
124 124 diff -r cb9a9f314b8b -r 0647d048b600 a
125 125 --- a/a Thu Jan 01 00:00:00 1970 +0000
126 126 +++ b/a Thu Jan 01 00:00:01 1970 +0000
127 127 @@ -1,1 +1,2 @@
128 128 a
129 129 +a
130 130 (run 'hg update' to get a working copy)
131 131 % pull
132 rolling back pull to revision 1
132 rolling back to revision 1 (undo pull)
133 133 pulling from ../a
134 134 searching for changes
135 135 adding changesets
136 136 adding manifests
137 137 adding file changes
138 138 added 1 changesets with 1 changes to 1 files
139 139 Content-Type: text/plain; charset="us-ascii"
140 140 MIME-Version: 1.0
141 141 Content-Transfer-Encoding: 7bit
142 142 X-Test: foo
143 143 Date:
144 144 Subject: b
145 145 From: test@test.com
146 146 X-Hg-Notification: changeset 0647d048b600
147 147 Message-Id:
148 148 To: baz@test.com, foo@bar
149 149
150 150 changeset 0647d048b600
151 151 description:
152 152 b
153 153 diffstat:
154 154
155 155 a | 1 +
156 156 1 files changed, 1 insertions(+), 0 deletions(-)
157 157
158 158 diffs (6 lines):
159 159
160 160 diff -r cb9a9f314b8b -r 0647d048b600 a
161 161 --- a/a Thu Jan 01 00:00:00 1970 +0000
162 162 +++ b/a Thu Jan 01 00:00:01 1970 +0000
163 163 @@ -1,1 +1,2 @@
164 164 a
165 165 +a
166 166 (run 'hg update' to get a working copy)
167 167 % test merge
168 168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 169 created new head
170 170 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 171 (branch merge, don't forget to commit)
172 172 pulling from ../a
173 173 searching for changes
174 174 adding changesets
175 175 adding manifests
176 176 adding file changes
177 177 added 2 changesets with 0 changes to 0 files
178 178 Content-Type: text/plain; charset="us-ascii"
179 179 MIME-Version: 1.0
180 180 Content-Transfer-Encoding: 7bit
181 181 X-Test: foo
182 182 Date:
183 183 Subject: adda2
184 184 From: test@test.com
185 185 X-Hg-Notification: changeset 0a184ce6067f
186 186 Message-Id:
187 187 To: baz@test.com, foo@bar
188 188
189 189 changeset 0a184ce6067f
190 190 description:
191 191 adda2
192 192 diffstat:
193 193
194 194 a | 1 +
195 195 1 files changed, 1 insertions(+), 0 deletions(-)
196 196
197 197 diffs (6 lines):
198 198
199 199 diff -r cb9a9f314b8b -r 0a184ce6067f a
200 200 --- a/a Thu Jan 01 00:00:00 1970 +0000
201 201 +++ b/a Thu Jan 01 00:00:02 1970 +0000
202 202 @@ -1,1 +1,2 @@
203 203 a
204 204 +a
205 205 Content-Type: text/plain; charset="us-ascii"
206 206 MIME-Version: 1.0
207 207 Content-Transfer-Encoding: 7bit
208 208 X-Test: foo
209 209 Date:
210 210 Subject: merge
211 211 From: test@test.com
212 212 X-Hg-Notification: changeset 22c88b85aa27
213 213 Message-Id:
214 214 To: baz@test.com, foo@bar
215 215
216 216 changeset 22c88b85aa27
217 217 description:
218 218 merge
219 219 (run 'hg update' to get a working copy)
@@ -1,42 +1,42 b''
1 1 changeset: 2:effea6de0384
2 2 tag: tip
3 3 parent: 0:bbd179dfa0a7
4 4 user: test
5 5 date: Thu Jan 01 00:00:00 1970 +0000
6 6 summary: add bar
7 7
8 8 changeset: 1:ed1b79f46b9a
9 9 user: test
10 10 date: Thu Jan 01 00:00:00 1970 +0000
11 11 summary: change foo
12 12
13 13 changeset: 0:bbd179dfa0a7
14 14 user: test
15 15 date: Thu Jan 01 00:00:00 1970 +0000
16 16 summary: add foo
17 17
18 18 % pull a missing revision
19 19 abort: unknown revision 'missing'!
20 20 % pull multiple revisions with update
21 21 0:bbd179dfa0a7
22 rolling back pull to revision 0
22 rolling back to revision 0 (undo pull)
23 23 % pull -r 0
24 24 changeset: 0:bbd179dfa0a7
25 25 tag: tip
26 26 user: test
27 27 date: Thu Jan 01 00:00:00 1970 +0000
28 28 summary: add foo
29 29
30 30 % pull -r 1
31 31 changeset: 1:ed1b79f46b9a
32 32 tag: tip
33 33 user: test
34 34 date: Thu Jan 01 00:00:00 1970 +0000
35 35 summary: change foo
36 36
37 37 changeset: 0:bbd179dfa0a7
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: add foo
41 41
42 42 % pull -r 1 again
@@ -1,38 +1,38 b''
1 1 adding a
2 2 updating to branch default
3 3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 4 % expect ssl error
5 5 pushing to http://localhost:$HGPORT/
6 6 searching for changes
7 7 remote: ssl required
8 8 % serve errors
9 9 % expect authorization error
10 10 abort: authorization failed
11 11 pushing to http://localhost:$HGPORT/
12 12 searching for changes
13 13 % serve errors
14 14 % expect authorization error: must have authorized user
15 15 abort: authorization failed
16 16 pushing to http://localhost:$HGPORT/
17 17 searching for changes
18 18 % serve errors
19 19 % expect success
20 20 pushing to http://localhost:$HGPORT/
21 21 searching for changes
22 22 remote: adding changesets
23 23 remote: adding manifests
24 24 remote: adding file changes
25 25 remote: added 1 changesets with 1 changes to 1 files
26 26 % serve errors
27 27 changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_URL=remote:http
28 rolling back serve to revision 1
28 rolling back to revision 1 (undo serve)
29 29 % expect authorization error: all users denied
30 30 abort: authorization failed
31 31 pushing to http://localhost:$HGPORT/
32 32 searching for changes
33 33 % serve errors
34 34 % expect authorization error: some users denied, users must be authenticated
35 35 abort: authorization failed
36 36 pushing to http://localhost:$HGPORT/
37 37 searching for changes
38 38 % serve errors
@@ -1,43 +1,43 b''
1 1 % create source repository
2 2 adding a
3 3 % fork source repository
4 4 updating to branch default
5 5 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
6 6 adding b
7 7 % update source repository
8 8 % merge repositories
9 9 pulling from ../t2
10 10 searching for changes
11 11 adding changesets
12 12 adding manifests
13 13 adding file changes
14 14 added 1 changesets with 1 changes to 1 files (+1 heads)
15 15 (run 'hg heads' to see heads, 'hg merge' to merge)
16 16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 17 (branch merge, don't forget to commit)
18 18 M b
19 19 % rename b as c
20 20 A c
21 21 R b
22 22 % rename back c as b
23 23 M b
24 24 % test issue 1476
25 25 adding a
26 26 adding b1
27 27 adding b2
28 28 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
29 29 adding c1
30 30 adding c2
31 31 created new head
32 32 % merge heads
33 33 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 (branch merge, don't forget to commit)
35 35 % commit issue 1476
36 36 copies: c2 (c1)
37 rolling back commit to revision 3
37 rolling back to revision 3 (undo commit)
38 38 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
39 39 % merge heads again
40 40 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 41 (branch merge, don't forget to commit)
42 42 % commit issue 1476 with a rename on the other side
43 43 copies: b2 (b1)
@@ -1,43 +1,43 b''
1 1 checking changesets
2 2 checking manifests
3 3 crosschecking files in changesets and manifests
4 4 checking files
5 5 1 files, 1 changesets, 1 total revisions
6 6 changeset: 0:0acdaf898367
7 7 tag: tip
8 8 user: test
9 9 date: Mon Jan 12 13:46:40 1970 +0000
10 10 summary: test
11 11
12 rolling back commit to revision 0
12 rolling back to revision 0 (undo commit)
13 13 checking changesets
14 14 checking manifests
15 15 crosschecking files in changesets and manifests
16 16 checking files
17 17 0 files, 0 changesets, 0 total revisions
18 18 A a
19 19 % Test issue 902
20 20 marked working directory as branch test
21 rolling back commit to revision 0
21 rolling back to revision 0 (undo commit)
22 22 default
23 23 % Test issue 1635 (commit message saved)
24 24 .hg/last-message.txt:
25 25 test2
26 26 % Test rollback of hg before issue 902 was fixed
27 27 marked working directory as branch test
28 rolling back commit to revision 0
28 rolling back to revision 0 (undo commit)
29 29 Named branch could not be reset, current branch still is: test
30 30 test
31 31 % rollback by pretxncommit saves commit message (issue 1635)
32 32 transaction abort!
33 33 rollback completed
34 34 abort: pretxncommit hook exited ...
35 35 .hg/last-message.txt:
36 36 precious commit message
37 37 % same thing, but run $EDITOR
38 38 transaction abort!
39 39 rollback completed
40 40 note: commit message saved in .hg/last-message.txt
41 41 abort: pretxncommit hook exited ...
42 42 .hg/last-message.txt:
43 43 another precious commit message
@@ -1,153 +1,153 b''
1 1 % setup
2 2 no tag cache
3 3 000000000000 tip
4 4 no tag cache
5 5 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
6 6 acb14030fe0a tip
7 7 tag cache exists
8 8 % create local tag with long name
9 9 tip 0:acb14030fe0a
10 10 This is a local tag with a really long name! 0:acb14030fe0a
11 11 % create a tag behind hg's back
12 12 acb14030fe0a21b60322c440ad2d20cf7685a376 first
13 13 tip 1:b9154636be93
14 14 first 0:acb14030fe0a
15 15 b9154636be93 tip
16 16 % identify with cold cache
17 17 b9154636be93 tip
18 18 % identify with unwritable cache
19 19 b9154636be93 tip
20 20 % create a branch
21 21 M a
22 22 b9154636be93+ tip
23 23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 24 acb14030fe0a+ first
25 25 acb14030fe0a+ first
26 26 M a
27 27 created new head
28 28 c8edf04160c7 tip
29 29 % merge the two heads
30 30 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 31 (branch merge, don't forget to commit)
32 32 c8edf04160c7+b9154636be93+ tip
33 33 M .hgtags
34 34 % create fake head, make sure tag not visible afterwards
35 35 tip 6:35ff301afafe
36 36 first 0:acb14030fe0a
37 37 % add invalid tags
38 38 committing .hgtags:
39 39 acb14030fe0a21b60322c440ad2d20cf7685a376 first
40 40 spam
41 41
42 42 foo bar
43 43 % report tag parse error on other head
44 44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 created new head
46 46 .hgtags@75d9f02dfe28, line 2: cannot parse entry
47 47 .hgtags@75d9f02dfe28, line 4: node 'foo' is not well formed
48 48 .hgtags@c4be69a18c11, line 2: node 'x' is not well formed
49 49 tip 8:c4be69a18c11
50 50 first 0:acb14030fe0a
51 51 changeset: 8:c4be69a18c11
52 52 tag: tip
53 53 parent: 3:ac5e980c4dc0
54 54 user: test
55 55 date: Thu Jan 01 00:00:00 1970 +0000
56 56 summary: head
57 57
58 58 % test tag precedence rules
59 59 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 60 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 61 created new head
62 62 tip 4:0c192d7d5e6b
63 63 bar 1:78391a272241
64 64 tip 4:0c192d7d5e6b
65 65 bar 1:78391a272241
66 66 % detailed dump of tag info
67 67 heads:
68 68 4:0c192d7d5e6b
69 69 3:6fa450212aeb
70 70 2:7a94127795a3
71 71 rev 2: .hgtags:
72 72 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
73 73 rev 3: .hgtags:
74 74 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
75 75 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
76 76 78391a272241d70354aa14c874552cad6b51bb42 bar
77 77 rev 4: .hgtags:
78 78 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
79 79 .hg/tags.cache:
80 80 4 0c192d7d5e6b78a714de54a2e9627952a877e25a 0c04f2a8af31de17fab7422878ee5a2dadbc943d
81 81 3 6fa450212aeb2a21ed616a54aea39a4a27894cd7 7d3b718c964ef37b89e550ebdafd5789e76ce1b0
82 82 2 7a94127795a33c10a370c93f731fd9fea0b79af6 0c04f2a8af31de17fab7422878ee5a2dadbc943d
83 83
84 84 78391a272241d70354aa14c874552cad6b51bb42 bar
85 85 % test tag removal
86 86 changeset: 5:5f6e8655b1c7
87 87 tag: tip
88 88 user: test
89 89 date: Thu Jan 01 00:00:00 1970 +0000
90 90 files: .hgtags
91 91 description:
92 92 Removed tag bar
93 93
94 94
95 95 diff -r 0c192d7d5e6b -r 5f6e8655b1c7 .hgtags
96 96 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
97 97 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
98 98 @@ -1,1 +1,3 @@
99 99 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
100 100 +78391a272241d70354aa14c874552cad6b51bb42 bar
101 101 +0000000000000000000000000000000000000000 bar
102 102
103 103 tip 5:5f6e8655b1c7
104 104 tip 5:5f6e8655b1c7
105 105 % remove nonexistent tag
106 106 abort: tag 'foobar' does not exist
107 107 changeset: 5:5f6e8655b1c7
108 108 tag: tip
109 109 user: test
110 110 date: Thu Jan 01 00:00:00 1970 +0000
111 111 summary: Removed tag bar
112 112
113 113 % rollback undoes tag operation
114 rolling back commit to revision 5
114 rolling back to revision 5 (undo commit)
115 115 tip 4:0c192d7d5e6b
116 116 bar 1:78391a272241
117 117 tip 4:0c192d7d5e6b
118 118 bar 1:78391a272241
119 119 % test tag rank
120 120 tip 5:85f05169d91d
121 121 bar 0:bbd179dfa0a7
122 122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 123 created new head
124 124 tip 6:735c3ca72986
125 125 bar 0:bbd179dfa0a7
126 126 % don't allow moving tag without -f
127 127 abort: tag 'bar' already exists (use -f to force)
128 128 tip 6:735c3ca72986
129 129 bar 0:bbd179dfa0a7
130 130 % strip 1: expose an old head
131 131 tip 5:735c3ca72986
132 132 bar 1:78391a272241
133 133 tip 5:735c3ca72986
134 134 bar 1:78391a272241
135 135 % strip 2: destroy whole branch, no old head exposed
136 136 tip 4:735c3ca72986
137 137 bar 0:bbd179dfa0a7
138 138 tip 4:735c3ca72986
139 139 bar 0:bbd179dfa0a7
140 140 % test tag rank with 3 heads
141 141 adding foo
142 142 tip 3:197c21bbbf2c
143 143 bar 2:6fa450212aeb
144 144 % bar should still point to rev 2
145 145 tip 4:3b4b14ed0202
146 146 bar 2:6fa450212aeb
147 147 % remove local as global and global as local
148 148 adding foo
149 149 abort: tag 'localtag' is not a global tag
150 150 abort: tag 'globaltag' is not a local tag
151 151 tip 1:a0b6fe111088
152 152 localtag 0:bbd179dfa0a7 local
153 153 globaltag 0:bbd179dfa0a7
@@ -1,148 +1,148 b''
1 1 marked working directory as branch foo
2 2 % clone repo#foo
3 3 requesting all changes
4 4 adding changesets
5 5 adding manifests
6 6 adding file changes
7 7 added 2 changesets with 2 changes to 1 files
8 8 updating to branch foo
9 9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 10 % heads
11 11 changeset: 1:cd2a86ecc814
12 12 branch: foo
13 13 tag: tip
14 14 user: test
15 15 date: Thu Jan 01 00:00:00 1970 +0000
16 16 summary: change a
17 17
18 18 changeset: 0:1f0dee641bb7
19 19 user: test
20 20 date: Thu Jan 01 00:00:00 1970 +0000
21 21 summary: add a
22 22
23 23 % parents
24 24 changeset: 1:cd2a86ecc814
25 25 branch: foo
26 26 tag: tip
27 27 user: test
28 28 date: Thu Jan 01 00:00:00 1970 +0000
29 29 summary: change a
30 30
31 31 [paths]
32 32 default = #foo
33 33
34 34 % changing original repo
35 35 changeset: 3:4cd725637392
36 36 tag: tip
37 37 parent: 0:1f0dee641bb7
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: add bar
41 41
42 42 changeset: 2:faba9097cad4
43 43 branch: foo
44 44 user: test
45 45 date: Thu Jan 01 00:00:00 1970 +0000
46 46 summary: new head of branch foo
47 47
48 48 changeset: 1:cd2a86ecc814
49 49 branch: foo
50 50 user: test
51 51 date: Thu Jan 01 00:00:00 1970 +0000
52 52 summary: change a
53 53
54 54 changeset: 0:1f0dee641bb7
55 55 user: test
56 56 date: Thu Jan 01 00:00:00 1970 +0000
57 57 summary: add a
58 58
59 59
60 60 % outgoing
61 61 2:faba9097cad4
62 62
63 63 % push
64 64 changeset: 2:faba9097cad4
65 65 branch: foo
66 66 tag: tip
67 67 user: test
68 68 date: Thu Jan 01 00:00:00 1970 +0000
69 69 summary: new head of branch foo
70 70
71 71 changeset: 0:1f0dee641bb7
72 72 user: test
73 73 date: Thu Jan 01 00:00:00 1970 +0000
74 74 summary: add a
75 75
76 76
77 77 % rolling back
78 rolling back push to revision 2
78 rolling back to revision 2 (undo push)
79 79 % incoming
80 80 2:faba9097cad4
81 81 % pull
82 82 changeset: 2:faba9097cad4
83 83 branch: foo
84 84 tag: tip
85 85 user: test
86 86 date: Thu Jan 01 00:00:00 1970 +0000
87 87 summary: new head of branch foo
88 88
89 89 changeset: 0:1f0dee641bb7
90 90 user: test
91 91 date: Thu Jan 01 00:00:00 1970 +0000
92 92 summary: add a
93 93
94 94
95 95 % pull should not have updated
96 96 1:cd2a86ecc814
97 97 % going back to the default branch
98 98 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 99 changeset: 0:1f0dee641bb7
100 100 user: test
101 101 date: Thu Jan 01 00:00:00 1970 +0000
102 102 summary: add a
103 103
104 104 % no new revs, no update
105 105 0:1f0dee641bb7
106 106 % rollback
107 rolling back pull to revision 2
107 rolling back to revision 2 (undo pull)
108 108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 0:1f0dee641bb7
110 110 % pull -u takes us back to branch foo
111 111 changeset: 2:faba9097cad4
112 112 branch: foo
113 113 tag: tip
114 114 user: test
115 115 date: Thu Jan 01 00:00:00 1970 +0000
116 116 summary: new head of branch foo
117 117
118 118 % rollback
119 rolling back pull to revision 2
119 rolling back to revision 2 (undo pull)
120 120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 121 % parents
122 122 0:1f0dee641bb7
123 123 % heads
124 124 1:cd2a86ecc814
125 125 0:1f0dee641bb7
126 126 % pull -u -r otherrev url#rev updates to rev
127 127 % parents
128 128 changeset: 3:4cd725637392
129 129 tag: tip
130 130 parent: 0:1f0dee641bb7
131 131 user: test
132 132 date: Thu Jan 01 00:00:00 1970 +0000
133 133 summary: add bar
134 134
135 135 % heads
136 136 changeset: 3:4cd725637392
137 137 tag: tip
138 138 parent: 0:1f0dee641bb7
139 139 user: test
140 140 date: Thu Jan 01 00:00:00 1970 +0000
141 141 summary: add bar
142 142
143 143 changeset: 2:faba9097cad4
144 144 branch: foo
145 145 user: test
146 146 date: Thu Jan 01 00:00:00 1970 +0000
147 147 summary: new head of branch foo
148 148
General Comments 0
You need to be logged in to leave comments. Login now