##// END OF EJS Templates
rollback: clarifies the message about the reverted state (issue2628)...
Gilles Moris -
r13446:1e497df5 stable
parent child Browse files
Show More
@@ -1,2025 +1,2029 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, discovery, pushkey
11 11 import changelog, dirstate, filelog, manifest, context, bookmarks
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, errno, os, time, inspect
20 20 propertycache = util.propertycache
21 21
22 22 class localrepository(repo.repository):
23 23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey'))
24 24 supportedformats = set(('revlogv1', 'parentdelta'))
25 25 supported = supportedformats | set(('store', 'fncache', 'shared',
26 26 'dotencode'))
27 27
28 28 def __init__(self, baseui, path=None, create=0):
29 29 repo.repository.__init__(self)
30 30 self.root = os.path.realpath(util.expandpath(path))
31 31 self.path = os.path.join(self.root, ".hg")
32 32 self.origroot = path
33 33 self.auditor = util.path_auditor(self.root, self._checknested)
34 34 self.opener = util.opener(self.path)
35 35 self.wopener = util.opener(self.root)
36 36 self.baseui = baseui
37 37 self.ui = baseui.copy()
38 38
39 39 try:
40 40 self.ui.readconfig(self.join("hgrc"), self.root)
41 41 extensions.loadall(self.ui)
42 42 except IOError:
43 43 pass
44 44
45 45 if not os.path.isdir(self.path):
46 46 if create:
47 47 if not os.path.exists(path):
48 48 util.makedirs(path)
49 49 os.mkdir(self.path)
50 50 requirements = ["revlogv1"]
51 51 if self.ui.configbool('format', 'usestore', True):
52 52 os.mkdir(os.path.join(self.path, "store"))
53 53 requirements.append("store")
54 54 if self.ui.configbool('format', 'usefncache', True):
55 55 requirements.append("fncache")
56 56 if self.ui.configbool('format', 'dotencode', True):
57 57 requirements.append('dotencode')
58 58 # create an invalid changelog
59 59 self.opener("00changelog.i", "a").write(
60 60 '\0\0\0\2' # represents revlogv2
61 61 ' dummy changelog to prevent using the old repo layout'
62 62 )
63 63 if self.ui.configbool('format', 'parentdelta', False):
64 64 requirements.append("parentdelta")
65 65 else:
66 66 raise error.RepoError(_("repository %s not found") % path)
67 67 elif create:
68 68 raise error.RepoError(_("repository %s already exists") % path)
69 69 else:
70 70 # find requirements
71 71 requirements = set()
72 72 try:
73 73 requirements = set(self.opener("requires").read().splitlines())
74 74 except IOError, inst:
75 75 if inst.errno != errno.ENOENT:
76 76 raise
77 77 for r in requirements - self.supported:
78 78 raise error.RepoError(_("requirement '%s' not supported") % r)
79 79
80 80 self.sharedpath = self.path
81 81 try:
82 82 s = os.path.realpath(self.opener("sharedpath").read())
83 83 if not os.path.exists(s):
84 84 raise error.RepoError(
85 85 _('.hg/sharedpath points to nonexistent directory %s') % s)
86 86 self.sharedpath = s
87 87 except IOError, inst:
88 88 if inst.errno != errno.ENOENT:
89 89 raise
90 90
91 91 self.store = store.store(requirements, self.sharedpath, util.opener)
92 92 self.spath = self.store.path
93 93 self.sopener = self.store.opener
94 94 self.sjoin = self.store.join
95 95 self.opener.createmode = self.store.createmode
96 96 self._applyrequirements(requirements)
97 97 if create:
98 98 self._writerequirements()
99 99
100 100 # These two define the set of tags for this repository. _tags
101 101 # maps tag name to node; _tagtypes maps tag name to 'global' or
102 102 # 'local'. (Global tags are defined by .hgtags across all
103 103 # heads, and local tags are defined in .hg/localtags.) They
104 104 # constitute the in-memory cache of tags.
105 105 self._tags = None
106 106 self._tagtypes = None
107 107
108 108 self._branchcache = None
109 109 self._branchcachetip = None
110 110 self.nodetagscache = None
111 111 self.filterpats = {}
112 112 self._datafilters = {}
113 113 self._transref = self._lockref = self._wlockref = None
114 114
115 115 def _applyrequirements(self, requirements):
116 116 self.requirements = requirements
117 117 self.sopener.options = {}
118 118 if 'parentdelta' in requirements:
119 119 self.sopener.options['parentdelta'] = 1
120 120
121 121 def _writerequirements(self):
122 122 reqfile = self.opener("requires", "w")
123 123 for r in self.requirements:
124 124 reqfile.write("%s\n" % r)
125 125 reqfile.close()
126 126
127 127 def _checknested(self, path):
128 128 """Determine if path is a legal nested repository."""
129 129 if not path.startswith(self.root):
130 130 return False
131 131 subpath = path[len(self.root) + 1:]
132 132
133 133 # XXX: Checking against the current working copy is wrong in
134 134 # the sense that it can reject things like
135 135 #
136 136 # $ hg cat -r 10 sub/x.txt
137 137 #
138 138 # if sub/ is no longer a subrepository in the working copy
139 139 # parent revision.
140 140 #
141 141 # However, it can of course also allow things that would have
142 142 # been rejected before, such as the above cat command if sub/
143 143 # is a subrepository now, but was a normal directory before.
144 144 # The old path auditor would have rejected by mistake since it
145 145 # panics when it sees sub/.hg/.
146 146 #
147 147 # All in all, checking against the working copy seems sensible
148 148 # since we want to prevent access to nested repositories on
149 149 # the filesystem *now*.
150 150 ctx = self[None]
151 151 parts = util.splitpath(subpath)
152 152 while parts:
153 153 prefix = os.sep.join(parts)
154 154 if prefix in ctx.substate:
155 155 if prefix == subpath:
156 156 return True
157 157 else:
158 158 sub = ctx.sub(prefix)
159 159 return sub.checknested(subpath[len(prefix) + 1:])
160 160 else:
161 161 parts.pop()
162 162 return False
163 163
164 164 @util.propertycache
165 165 def _bookmarks(self):
166 166 return bookmarks.read(self)
167 167
168 168 @util.propertycache
169 169 def _bookmarkcurrent(self):
170 170 return bookmarks.readcurrent(self)
171 171
172 172 @propertycache
173 173 def changelog(self):
174 174 c = changelog.changelog(self.sopener)
175 175 if 'HG_PENDING' in os.environ:
176 176 p = os.environ['HG_PENDING']
177 177 if p.startswith(self.root):
178 178 c.readpending('00changelog.i.a')
179 179 self.sopener.options['defversion'] = c.version
180 180 return c
181 181
182 182 @propertycache
183 183 def manifest(self):
184 184 return manifest.manifest(self.sopener)
185 185
186 186 @propertycache
187 187 def dirstate(self):
188 188 warned = [0]
189 189 def validate(node):
190 190 try:
191 191 r = self.changelog.rev(node)
192 192 return node
193 193 except error.LookupError:
194 194 if not warned[0]:
195 195 warned[0] = True
196 196 self.ui.warn(_("warning: ignoring unknown"
197 197 " working parent %s!\n") % short(node))
198 198 return nullid
199 199
200 200 return dirstate.dirstate(self.opener, self.ui, self.root, validate)
201 201
202 202 def __getitem__(self, changeid):
203 203 if changeid is None:
204 204 return context.workingctx(self)
205 205 return context.changectx(self, changeid)
206 206
207 207 def __contains__(self, changeid):
208 208 try:
209 209 return bool(self.lookup(changeid))
210 210 except error.RepoLookupError:
211 211 return False
212 212
213 213 def __nonzero__(self):
214 214 return True
215 215
216 216 def __len__(self):
217 217 return len(self.changelog)
218 218
219 219 def __iter__(self):
220 220 for i in xrange(len(self)):
221 221 yield i
222 222
223 223 def url(self):
224 224 return 'file:' + self.root
225 225
226 226 def hook(self, name, throw=False, **args):
227 227 return hook.hook(self.ui, self, name, throw, **args)
228 228
229 229 tag_disallowed = ':\r\n'
230 230
231 231 def _tag(self, names, node, message, local, user, date, extra={}):
232 232 if isinstance(names, str):
233 233 allchars = names
234 234 names = (names,)
235 235 else:
236 236 allchars = ''.join(names)
237 237 for c in self.tag_disallowed:
238 238 if c in allchars:
239 239 raise util.Abort(_('%r cannot be used in a tag name') % c)
240 240
241 241 branches = self.branchmap()
242 242 for name in names:
243 243 self.hook('pretag', throw=True, node=hex(node), tag=name,
244 244 local=local)
245 245 if name in branches:
246 246 self.ui.warn(_("warning: tag %s conflicts with existing"
247 247 " branch name\n") % name)
248 248
249 249 def writetags(fp, names, munge, prevtags):
250 250 fp.seek(0, 2)
251 251 if prevtags and prevtags[-1] != '\n':
252 252 fp.write('\n')
253 253 for name in names:
254 254 m = munge and munge(name) or name
255 255 if self._tagtypes and name in self._tagtypes:
256 256 old = self._tags.get(name, nullid)
257 257 fp.write('%s %s\n' % (hex(old), m))
258 258 fp.write('%s %s\n' % (hex(node), m))
259 259 fp.close()
260 260
261 261 prevtags = ''
262 262 if local:
263 263 try:
264 264 fp = self.opener('localtags', 'r+')
265 265 except IOError:
266 266 fp = self.opener('localtags', 'a')
267 267 else:
268 268 prevtags = fp.read()
269 269
270 270 # local tags are stored in the current charset
271 271 writetags(fp, names, None, prevtags)
272 272 for name in names:
273 273 self.hook('tag', node=hex(node), tag=name, local=local)
274 274 return
275 275
276 276 try:
277 277 fp = self.wfile('.hgtags', 'rb+')
278 278 except IOError:
279 279 fp = self.wfile('.hgtags', 'ab')
280 280 else:
281 281 prevtags = fp.read()
282 282
283 283 # committed tags are stored in UTF-8
284 284 writetags(fp, names, encoding.fromlocal, prevtags)
285 285
286 286 fp.close()
287 287
288 288 if '.hgtags' not in self.dirstate:
289 289 self[None].add(['.hgtags'])
290 290
291 291 m = matchmod.exact(self.root, '', ['.hgtags'])
292 292 tagnode = self.commit(message, user, date, extra=extra, match=m)
293 293
294 294 for name in names:
295 295 self.hook('tag', node=hex(node), tag=name, local=local)
296 296
297 297 return tagnode
298 298
299 299 def tag(self, names, node, message, local, user, date):
300 300 '''tag a revision with one or more symbolic names.
301 301
302 302 names is a list of strings or, when adding a single tag, names may be a
303 303 string.
304 304
305 305 if local is True, the tags are stored in a per-repository file.
306 306 otherwise, they are stored in the .hgtags file, and a new
307 307 changeset is committed with the change.
308 308
309 309 keyword arguments:
310 310
311 311 local: whether to store tags in non-version-controlled file
312 312 (default False)
313 313
314 314 message: commit message to use if committing
315 315
316 316 user: name of user to use if committing
317 317
318 318 date: date tuple to use if committing'''
319 319
320 320 if not local:
321 321 for x in self.status()[:5]:
322 322 if '.hgtags' in x:
323 323 raise util.Abort(_('working copy of .hgtags is changed '
324 324 '(please commit .hgtags manually)'))
325 325
326 326 self.tags() # instantiate the cache
327 327 self._tag(names, node, message, local, user, date)
328 328
329 329 def tags(self):
330 330 '''return a mapping of tag to node'''
331 331 if self._tags is None:
332 332 (self._tags, self._tagtypes) = self._findtags()
333 333
334 334 return self._tags
335 335
336 336 def _findtags(self):
337 337 '''Do the hard work of finding tags. Return a pair of dicts
338 338 (tags, tagtypes) where tags maps tag name to node, and tagtypes
339 339 maps tag name to a string like \'global\' or \'local\'.
340 340 Subclasses or extensions are free to add their own tags, but
341 341 should be aware that the returned dicts will be retained for the
342 342 duration of the localrepo object.'''
343 343
344 344 # XXX what tagtype should subclasses/extensions use? Currently
345 345 # mq and bookmarks add tags, but do not set the tagtype at all.
346 346 # Should each extension invent its own tag type? Should there
347 347 # be one tagtype for all such "virtual" tags? Or is the status
348 348 # quo fine?
349 349
350 350 alltags = {} # map tag name to (node, hist)
351 351 tagtypes = {}
352 352
353 353 tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
354 354 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
355 355
356 356 # Build the return dicts. Have to re-encode tag names because
357 357 # the tags module always uses UTF-8 (in order not to lose info
358 358 # writing to the cache), but the rest of Mercurial wants them in
359 359 # local encoding.
360 360 tags = {}
361 361 for (name, (node, hist)) in alltags.iteritems():
362 362 if node != nullid:
363 363 tags[encoding.tolocal(name)] = node
364 364 tags['tip'] = self.changelog.tip()
365 365 tagtypes = dict([(encoding.tolocal(name), value)
366 366 for (name, value) in tagtypes.iteritems()])
367 367 return (tags, tagtypes)
368 368
369 369 def tagtype(self, tagname):
370 370 '''
371 371 return the type of the given tag. result can be:
372 372
373 373 'local' : a local tag
374 374 'global' : a global tag
375 375 None : tag does not exist
376 376 '''
377 377
378 378 self.tags()
379 379
380 380 return self._tagtypes.get(tagname)
381 381
382 382 def tagslist(self):
383 383 '''return a list of tags ordered by revision'''
384 384 l = []
385 385 for t, n in self.tags().iteritems():
386 386 try:
387 387 r = self.changelog.rev(n)
388 388 except:
389 389 r = -2 # sort to the beginning of the list if unknown
390 390 l.append((r, t, n))
391 391 return [(t, n) for r, t, n in sorted(l)]
392 392
393 393 def nodetags(self, node):
394 394 '''return the tags associated with a node'''
395 395 if not self.nodetagscache:
396 396 self.nodetagscache = {}
397 397 for t, n in self.tags().iteritems():
398 398 self.nodetagscache.setdefault(n, []).append(t)
399 399 for tags in self.nodetagscache.itervalues():
400 400 tags.sort()
401 401 return self.nodetagscache.get(node, [])
402 402
403 403 def nodebookmarks(self, node):
404 404 marks = []
405 405 for bookmark, n in self._bookmarks.iteritems():
406 406 if n == node:
407 407 marks.append(bookmark)
408 408 return sorted(marks)
409 409
410 410 def _branchtags(self, partial, lrev):
411 411 # TODO: rename this function?
412 412 tiprev = len(self) - 1
413 413 if lrev != tiprev:
414 414 ctxgen = (self[r] for r in xrange(lrev + 1, tiprev + 1))
415 415 self._updatebranchcache(partial, ctxgen)
416 416 self._writebranchcache(partial, self.changelog.tip(), tiprev)
417 417
418 418 return partial
419 419
420 420 def updatebranchcache(self):
421 421 tip = self.changelog.tip()
422 422 if self._branchcache is not None and self._branchcachetip == tip:
423 423 return self._branchcache
424 424
425 425 oldtip = self._branchcachetip
426 426 self._branchcachetip = tip
427 427 if oldtip is None or oldtip not in self.changelog.nodemap:
428 428 partial, last, lrev = self._readbranchcache()
429 429 else:
430 430 lrev = self.changelog.rev(oldtip)
431 431 partial = self._branchcache
432 432
433 433 self._branchtags(partial, lrev)
434 434 # this private cache holds all heads (not just tips)
435 435 self._branchcache = partial
436 436
437 437 def branchmap(self):
438 438 '''returns a dictionary {branch: [branchheads]}'''
439 439 self.updatebranchcache()
440 440 return self._branchcache
441 441
442 442 def branchtags(self):
443 443 '''return a dict where branch names map to the tipmost head of
444 444 the branch, open heads come before closed'''
445 445 bt = {}
446 446 for bn, heads in self.branchmap().iteritems():
447 447 tip = heads[-1]
448 448 for h in reversed(heads):
449 449 if 'close' not in self.changelog.read(h)[5]:
450 450 tip = h
451 451 break
452 452 bt[bn] = tip
453 453 return bt
454 454
455 455 def _readbranchcache(self):
456 456 partial = {}
457 457 try:
458 458 f = self.opener("cache/branchheads")
459 459 lines = f.read().split('\n')
460 460 f.close()
461 461 except (IOError, OSError):
462 462 return {}, nullid, nullrev
463 463
464 464 try:
465 465 last, lrev = lines.pop(0).split(" ", 1)
466 466 last, lrev = bin(last), int(lrev)
467 467 if lrev >= len(self) or self[lrev].node() != last:
468 468 # invalidate the cache
469 469 raise ValueError('invalidating branch cache (tip differs)')
470 470 for l in lines:
471 471 if not l:
472 472 continue
473 473 node, label = l.split(" ", 1)
474 474 label = encoding.tolocal(label.strip())
475 475 partial.setdefault(label, []).append(bin(node))
476 476 except KeyboardInterrupt:
477 477 raise
478 478 except Exception, inst:
479 479 if self.ui.debugflag:
480 480 self.ui.warn(str(inst), '\n')
481 481 partial, last, lrev = {}, nullid, nullrev
482 482 return partial, last, lrev
483 483
484 484 def _writebranchcache(self, branches, tip, tiprev):
485 485 try:
486 486 f = self.opener("cache/branchheads", "w", atomictemp=True)
487 487 f.write("%s %s\n" % (hex(tip), tiprev))
488 488 for label, nodes in branches.iteritems():
489 489 for node in nodes:
490 490 f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
491 491 f.rename()
492 492 except (IOError, OSError):
493 493 pass
494 494
495 495 def _updatebranchcache(self, partial, ctxgen):
496 496 # collect new branch entries
497 497 newbranches = {}
498 498 for c in ctxgen:
499 499 newbranches.setdefault(c.branch(), []).append(c.node())
500 500 # if older branchheads are reachable from new ones, they aren't
501 501 # really branchheads. Note checking parents is insufficient:
502 502 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
503 503 for branch, newnodes in newbranches.iteritems():
504 504 bheads = partial.setdefault(branch, [])
505 505 bheads.extend(newnodes)
506 506 if len(bheads) <= 1:
507 507 continue
508 508 # starting from tip means fewer passes over reachable
509 509 while newnodes:
510 510 latest = newnodes.pop()
511 511 if latest not in bheads:
512 512 continue
513 513 minbhrev = self[min([self[bh].rev() for bh in bheads])].node()
514 514 reachable = self.changelog.reachable(latest, minbhrev)
515 515 reachable.remove(latest)
516 516 bheads = [b for b in bheads if b not in reachable]
517 517 partial[branch] = bheads
518 518
519 519 def lookup(self, key):
520 520 if isinstance(key, int):
521 521 return self.changelog.node(key)
522 522 elif key == '.':
523 523 return self.dirstate.parents()[0]
524 524 elif key == 'null':
525 525 return nullid
526 526 elif key == 'tip':
527 527 return self.changelog.tip()
528 528 n = self.changelog._match(key)
529 529 if n:
530 530 return n
531 531 if key in self._bookmarks:
532 532 return self._bookmarks[key]
533 533 if key in self.tags():
534 534 return self.tags()[key]
535 535 if key in self.branchtags():
536 536 return self.branchtags()[key]
537 537 n = self.changelog._partialmatch(key)
538 538 if n:
539 539 return n
540 540
541 541 # can't find key, check if it might have come from damaged dirstate
542 542 if key in self.dirstate.parents():
543 543 raise error.Abort(_("working directory has unknown parent '%s'!")
544 544 % short(key))
545 545 try:
546 546 if len(key) == 20:
547 547 key = hex(key)
548 548 except:
549 549 pass
550 550 raise error.RepoLookupError(_("unknown revision '%s'") % key)
551 551
552 552 def lookupbranch(self, key, remote=None):
553 553 repo = remote or self
554 554 if key in repo.branchmap():
555 555 return key
556 556
557 557 repo = (remote and remote.local()) and remote or self
558 558 return repo[key].branch()
559 559
560 560 def local(self):
561 561 return True
562 562
563 563 def join(self, f):
564 564 return os.path.join(self.path, f)
565 565
566 566 def wjoin(self, f):
567 567 return os.path.join(self.root, f)
568 568
569 569 def file(self, f):
570 570 if f[0] == '/':
571 571 f = f[1:]
572 572 return filelog.filelog(self.sopener, f)
573 573
574 574 def changectx(self, changeid):
575 575 return self[changeid]
576 576
577 577 def parents(self, changeid=None):
578 578 '''get list of changectxs for parents of changeid'''
579 579 return self[changeid].parents()
580 580
581 581 def filectx(self, path, changeid=None, fileid=None):
582 582 """changeid can be a changeset revision, node, or tag.
583 583 fileid can be a file revision or node."""
584 584 return context.filectx(self, path, changeid, fileid)
585 585
586 586 def getcwd(self):
587 587 return self.dirstate.getcwd()
588 588
589 589 def pathto(self, f, cwd=None):
590 590 return self.dirstate.pathto(f, cwd)
591 591
592 592 def wfile(self, f, mode='r'):
593 593 return self.wopener(f, mode)
594 594
595 595 def _link(self, f):
596 596 return os.path.islink(self.wjoin(f))
597 597
598 598 def _loadfilter(self, filter):
599 599 if filter not in self.filterpats:
600 600 l = []
601 601 for pat, cmd in self.ui.configitems(filter):
602 602 if cmd == '!':
603 603 continue
604 604 mf = matchmod.match(self.root, '', [pat])
605 605 fn = None
606 606 params = cmd
607 607 for name, filterfn in self._datafilters.iteritems():
608 608 if cmd.startswith(name):
609 609 fn = filterfn
610 610 params = cmd[len(name):].lstrip()
611 611 break
612 612 if not fn:
613 613 fn = lambda s, c, **kwargs: util.filter(s, c)
614 614 # Wrap old filters not supporting keyword arguments
615 615 if not inspect.getargspec(fn)[2]:
616 616 oldfn = fn
617 617 fn = lambda s, c, **kwargs: oldfn(s, c)
618 618 l.append((mf, fn, params))
619 619 self.filterpats[filter] = l
620 620 return self.filterpats[filter]
621 621
622 622 def _filter(self, filterpats, filename, data):
623 623 for mf, fn, cmd in filterpats:
624 624 if mf(filename):
625 625 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
626 626 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
627 627 break
628 628
629 629 return data
630 630
631 631 @propertycache
632 632 def _encodefilterpats(self):
633 633 return self._loadfilter('encode')
634 634
635 635 @propertycache
636 636 def _decodefilterpats(self):
637 637 return self._loadfilter('decode')
638 638
639 639 def adddatafilter(self, name, filter):
640 640 self._datafilters[name] = filter
641 641
642 642 def wread(self, filename):
643 643 if self._link(filename):
644 644 data = os.readlink(self.wjoin(filename))
645 645 else:
646 646 data = self.wopener(filename, 'r').read()
647 647 return self._filter(self._encodefilterpats, filename, data)
648 648
649 649 def wwrite(self, filename, data, flags):
650 650 data = self._filter(self._decodefilterpats, filename, data)
651 651 if 'l' in flags:
652 652 self.wopener.symlink(data, filename)
653 653 else:
654 654 self.wopener(filename, 'w').write(data)
655 655 if 'x' in flags:
656 656 util.set_flags(self.wjoin(filename), False, True)
657 657
658 658 def wwritedata(self, filename, data):
659 659 return self._filter(self._decodefilterpats, filename, data)
660 660
661 661 def transaction(self, desc):
662 662 tr = self._transref and self._transref() or None
663 663 if tr and tr.running():
664 664 return tr.nest()
665 665
666 666 # abort here if the journal already exists
667 667 if os.path.exists(self.sjoin("journal")):
668 668 raise error.RepoError(
669 669 _("abandoned transaction found - run hg recover"))
670 670
671 671 # save dirstate for rollback
672 672 try:
673 673 ds = self.opener("dirstate").read()
674 674 except IOError:
675 675 ds = ""
676 676 self.opener("journal.dirstate", "w").write(ds)
677 677 self.opener("journal.branch", "w").write(
678 678 encoding.fromlocal(self.dirstate.branch()))
679 679 self.opener("journal.desc", "w").write("%d\n%s\n" % (len(self), desc))
680 680
681 681 renames = [(self.sjoin("journal"), self.sjoin("undo")),
682 682 (self.join("journal.dirstate"), self.join("undo.dirstate")),
683 683 (self.join("journal.branch"), self.join("undo.branch")),
684 684 (self.join("journal.desc"), self.join("undo.desc"))]
685 685 tr = transaction.transaction(self.ui.warn, self.sopener,
686 686 self.sjoin("journal"),
687 687 aftertrans(renames),
688 688 self.store.createmode)
689 689 self._transref = weakref.ref(tr)
690 690 return tr
691 691
692 692 def recover(self):
693 693 lock = self.lock()
694 694 try:
695 695 if os.path.exists(self.sjoin("journal")):
696 696 self.ui.status(_("rolling back interrupted transaction\n"))
697 697 transaction.rollback(self.sopener, self.sjoin("journal"),
698 698 self.ui.warn)
699 699 self.invalidate()
700 700 return True
701 701 else:
702 702 self.ui.warn(_("no interrupted transaction available\n"))
703 703 return False
704 704 finally:
705 705 lock.release()
706 706
707 707 def rollback(self, dryrun=False):
708 708 wlock = lock = None
709 709 try:
710 710 wlock = self.wlock()
711 711 lock = self.lock()
712 712 if os.path.exists(self.sjoin("undo")):
713 713 try:
714 714 args = self.opener("undo.desc", "r").read().splitlines()
715 715 if len(args) >= 3 and self.ui.verbose:
716 desc = _("rolling back to revision %s"
716 desc = _("repository tip rolled back to revision %s"
717 717 " (undo %s: %s)\n") % (
718 718 int(args[0]) - 1, args[1], args[2])
719 719 elif len(args) >= 2:
720 desc = _("rolling back to revision %s (undo %s)\n") % (
720 desc = _("repository tip rolled back to revision %s"
721 " (undo %s)\n") % (
721 722 int(args[0]) - 1, args[1])
722 723 except IOError:
723 724 desc = _("rolling back unknown transaction\n")
724 725 self.ui.status(desc)
725 726 if dryrun:
726 727 return
727 728 transaction.rollback(self.sopener, self.sjoin("undo"),
728 729 self.ui.warn)
729 730 util.rename(self.join("undo.dirstate"), self.join("dirstate"))
730 731 if os.path.exists(self.join('undo.bookmarks')):
731 732 util.rename(self.join('undo.bookmarks'),
732 733 self.join('bookmarks'))
733 734 try:
734 735 branch = self.opener("undo.branch").read()
735 736 self.dirstate.setbranch(branch)
736 737 except IOError:
737 738 self.ui.warn(_("Named branch could not be reset, "
738 739 "current branch still is: %s\n")
739 740 % self.dirstate.branch())
740 741 self.invalidate()
741 742 self.dirstate.invalidate()
742 743 self.destroyed()
744 self.ui.status(_("working directory now based on "
745 "revision %s\n") % (
746 _(' and ').join(str(p.rev()) for p in self.parents())))
743 747 else:
744 748 self.ui.warn(_("no rollback information available\n"))
745 749 return 1
746 750 finally:
747 751 release(lock, wlock)
748 752
749 753 def invalidatecaches(self):
750 754 self._tags = None
751 755 self._tagtypes = None
752 756 self.nodetagscache = None
753 757 self._branchcache = None # in UTF-8
754 758 self._branchcachetip = None
755 759
756 760 def invalidate(self):
757 761 for a in ("changelog", "manifest", "_bookmarks", "_bookmarkscurrent"):
758 762 if a in self.__dict__:
759 763 delattr(self, a)
760 764 self.invalidatecaches()
761 765
762 766 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
763 767 try:
764 768 l = lock.lock(lockname, 0, releasefn, desc=desc)
765 769 except error.LockHeld, inst:
766 770 if not wait:
767 771 raise
768 772 self.ui.warn(_("waiting for lock on %s held by %r\n") %
769 773 (desc, inst.locker))
770 774 # default to 600 seconds timeout
771 775 l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
772 776 releasefn, desc=desc)
773 777 if acquirefn:
774 778 acquirefn()
775 779 return l
776 780
777 781 def lock(self, wait=True):
778 782 '''Lock the repository store (.hg/store) and return a weak reference
779 783 to the lock. Use this before modifying the store (e.g. committing or
780 784 stripping). If you are opening a transaction, get a lock as well.)'''
781 785 l = self._lockref and self._lockref()
782 786 if l is not None and l.held:
783 787 l.lock()
784 788 return l
785 789
786 790 l = self._lock(self.sjoin("lock"), wait, self.store.write,
787 791 self.invalidate, _('repository %s') % self.origroot)
788 792 self._lockref = weakref.ref(l)
789 793 return l
790 794
791 795 def wlock(self, wait=True):
792 796 '''Lock the non-store parts of the repository (everything under
793 797 .hg except .hg/store) and return a weak reference to the lock.
794 798 Use this before modifying files in .hg.'''
795 799 l = self._wlockref and self._wlockref()
796 800 if l is not None and l.held:
797 801 l.lock()
798 802 return l
799 803
800 804 l = self._lock(self.join("wlock"), wait, self.dirstate.write,
801 805 self.dirstate.invalidate, _('working directory of %s') %
802 806 self.origroot)
803 807 self._wlockref = weakref.ref(l)
804 808 return l
805 809
806 810 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
807 811 """
808 812 commit an individual file as part of a larger transaction
809 813 """
810 814
811 815 fname = fctx.path()
812 816 text = fctx.data()
813 817 flog = self.file(fname)
814 818 fparent1 = manifest1.get(fname, nullid)
815 819 fparent2 = fparent2o = manifest2.get(fname, nullid)
816 820
817 821 meta = {}
818 822 copy = fctx.renamed()
819 823 if copy and copy[0] != fname:
820 824 # Mark the new revision of this file as a copy of another
821 825 # file. This copy data will effectively act as a parent
822 826 # of this new revision. If this is a merge, the first
823 827 # parent will be the nullid (meaning "look up the copy data")
824 828 # and the second one will be the other parent. For example:
825 829 #
826 830 # 0 --- 1 --- 3 rev1 changes file foo
827 831 # \ / rev2 renames foo to bar and changes it
828 832 # \- 2 -/ rev3 should have bar with all changes and
829 833 # should record that bar descends from
830 834 # bar in rev2 and foo in rev1
831 835 #
832 836 # this allows this merge to succeed:
833 837 #
834 838 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
835 839 # \ / merging rev3 and rev4 should use bar@rev2
836 840 # \- 2 --- 4 as the merge base
837 841 #
838 842
839 843 cfname = copy[0]
840 844 crev = manifest1.get(cfname)
841 845 newfparent = fparent2
842 846
843 847 if manifest2: # branch merge
844 848 if fparent2 == nullid or crev is None: # copied on remote side
845 849 if cfname in manifest2:
846 850 crev = manifest2[cfname]
847 851 newfparent = fparent1
848 852
849 853 # find source in nearest ancestor if we've lost track
850 854 if not crev:
851 855 self.ui.debug(" %s: searching for copy revision for %s\n" %
852 856 (fname, cfname))
853 857 for ancestor in self[None].ancestors():
854 858 if cfname in ancestor:
855 859 crev = ancestor[cfname].filenode()
856 860 break
857 861
858 862 if crev:
859 863 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
860 864 meta["copy"] = cfname
861 865 meta["copyrev"] = hex(crev)
862 866 fparent1, fparent2 = nullid, newfparent
863 867 else:
864 868 self.ui.warn(_("warning: can't find ancestor for '%s' "
865 869 "copied from '%s'!\n") % (fname, cfname))
866 870
867 871 elif fparent2 != nullid:
868 872 # is one parent an ancestor of the other?
869 873 fparentancestor = flog.ancestor(fparent1, fparent2)
870 874 if fparentancestor == fparent1:
871 875 fparent1, fparent2 = fparent2, nullid
872 876 elif fparentancestor == fparent2:
873 877 fparent2 = nullid
874 878
875 879 # is the file changed?
876 880 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
877 881 changelist.append(fname)
878 882 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
879 883
880 884 # are just the flags changed during merge?
881 885 if fparent1 != fparent2o and manifest1.flags(fname) != fctx.flags():
882 886 changelist.append(fname)
883 887
884 888 return fparent1
885 889
886 890 def commit(self, text="", user=None, date=None, match=None, force=False,
887 891 editor=False, extra={}):
888 892 """Add a new revision to current repository.
889 893
890 894 Revision information is gathered from the working directory,
891 895 match can be used to filter the committed files. If editor is
892 896 supplied, it is called to get a commit message.
893 897 """
894 898
895 899 def fail(f, msg):
896 900 raise util.Abort('%s: %s' % (f, msg))
897 901
898 902 if not match:
899 903 match = matchmod.always(self.root, '')
900 904
901 905 if not force:
902 906 vdirs = []
903 907 match.dir = vdirs.append
904 908 match.bad = fail
905 909
906 910 wlock = self.wlock()
907 911 try:
908 912 wctx = self[None]
909 913 merge = len(wctx.parents()) > 1
910 914
911 915 if (not force and merge and match and
912 916 (match.files() or match.anypats())):
913 917 raise util.Abort(_('cannot partially commit a merge '
914 918 '(do not specify files or patterns)'))
915 919
916 920 changes = self.status(match=match, clean=force)
917 921 if force:
918 922 changes[0].extend(changes[6]) # mq may commit unchanged files
919 923
920 924 # check subrepos
921 925 subs = []
922 926 removedsubs = set()
923 927 for p in wctx.parents():
924 928 removedsubs.update(s for s in p.substate if match(s))
925 929 for s in wctx.substate:
926 930 removedsubs.discard(s)
927 931 if match(s) and wctx.sub(s).dirty():
928 932 subs.append(s)
929 933 if (subs or removedsubs):
930 934 if (not match('.hgsub') and
931 935 '.hgsub' in (wctx.modified() + wctx.added())):
932 936 raise util.Abort(_("can't commit subrepos without .hgsub"))
933 937 if '.hgsubstate' not in changes[0]:
934 938 changes[0].insert(0, '.hgsubstate')
935 939
936 940 if subs and not self.ui.configbool('ui', 'commitsubrepos', True):
937 941 changedsubs = [s for s in subs if wctx.sub(s).dirty(True)]
938 942 if changedsubs:
939 943 raise util.Abort(_("uncommitted changes in subrepo %s")
940 944 % changedsubs[0])
941 945
942 946 # make sure all explicit patterns are matched
943 947 if not force and match.files():
944 948 matched = set(changes[0] + changes[1] + changes[2])
945 949
946 950 for f in match.files():
947 951 if f == '.' or f in matched or f in wctx.substate:
948 952 continue
949 953 if f in changes[3]: # missing
950 954 fail(f, _('file not found!'))
951 955 if f in vdirs: # visited directory
952 956 d = f + '/'
953 957 for mf in matched:
954 958 if mf.startswith(d):
955 959 break
956 960 else:
957 961 fail(f, _("no match under directory!"))
958 962 elif f not in self.dirstate:
959 963 fail(f, _("file not tracked!"))
960 964
961 965 if (not force and not extra.get("close") and not merge
962 966 and not (changes[0] or changes[1] or changes[2])
963 967 and wctx.branch() == wctx.p1().branch()):
964 968 return None
965 969
966 970 ms = mergemod.mergestate(self)
967 971 for f in changes[0]:
968 972 if f in ms and ms[f] == 'u':
969 973 raise util.Abort(_("unresolved merge conflicts "
970 974 "(see hg resolve)"))
971 975
972 976 cctx = context.workingctx(self, text, user, date, extra, changes)
973 977 if editor:
974 978 cctx._text = editor(self, cctx, subs)
975 979 edited = (text != cctx._text)
976 980
977 981 # commit subs
978 982 if subs or removedsubs:
979 983 state = wctx.substate.copy()
980 984 for s in sorted(subs):
981 985 sub = wctx.sub(s)
982 986 self.ui.status(_('committing subrepository %s\n') %
983 987 subrepo.subrelpath(sub))
984 988 sr = sub.commit(cctx._text, user, date)
985 989 state[s] = (state[s][0], sr)
986 990 subrepo.writestate(self, state)
987 991
988 992 # Save commit message in case this transaction gets rolled back
989 993 # (e.g. by a pretxncommit hook). Leave the content alone on
990 994 # the assumption that the user will use the same editor again.
991 995 msgfile = self.opener('last-message.txt', 'wb')
992 996 msgfile.write(cctx._text)
993 997 msgfile.close()
994 998
995 999 p1, p2 = self.dirstate.parents()
996 1000 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
997 1001 try:
998 1002 self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
999 1003 ret = self.commitctx(cctx, True)
1000 1004 except:
1001 1005 if edited:
1002 1006 msgfn = self.pathto(msgfile.name[len(self.root)+1:])
1003 1007 self.ui.write(
1004 1008 _('note: commit message saved in %s\n') % msgfn)
1005 1009 raise
1006 1010
1007 1011 # update bookmarks, dirstate and mergestate
1008 1012 parents = (p1, p2)
1009 1013 if p2 == nullid:
1010 1014 parents = (p1,)
1011 1015 bookmarks.update(self, parents, ret)
1012 1016 for f in changes[0] + changes[1]:
1013 1017 self.dirstate.normal(f)
1014 1018 for f in changes[2]:
1015 1019 self.dirstate.forget(f)
1016 1020 self.dirstate.setparents(ret)
1017 1021 ms.reset()
1018 1022 finally:
1019 1023 wlock.release()
1020 1024
1021 1025 self.hook("commit", node=hex(ret), parent1=hookp1, parent2=hookp2)
1022 1026 return ret
1023 1027
1024 1028 def commitctx(self, ctx, error=False):
1025 1029 """Add a new revision to current repository.
1026 1030 Revision information is passed via the context argument.
1027 1031 """
1028 1032
1029 1033 tr = lock = None
1030 1034 removed = list(ctx.removed())
1031 1035 p1, p2 = ctx.p1(), ctx.p2()
1032 1036 m1 = p1.manifest().copy()
1033 1037 m2 = p2.manifest()
1034 1038 user = ctx.user()
1035 1039
1036 1040 lock = self.lock()
1037 1041 try:
1038 1042 tr = self.transaction("commit")
1039 1043 trp = weakref.proxy(tr)
1040 1044
1041 1045 # check in files
1042 1046 new = {}
1043 1047 changed = []
1044 1048 linkrev = len(self)
1045 1049 for f in sorted(ctx.modified() + ctx.added()):
1046 1050 self.ui.note(f + "\n")
1047 1051 try:
1048 1052 fctx = ctx[f]
1049 1053 new[f] = self._filecommit(fctx, m1, m2, linkrev, trp,
1050 1054 changed)
1051 1055 m1.set(f, fctx.flags())
1052 1056 except OSError, inst:
1053 1057 self.ui.warn(_("trouble committing %s!\n") % f)
1054 1058 raise
1055 1059 except IOError, inst:
1056 1060 errcode = getattr(inst, 'errno', errno.ENOENT)
1057 1061 if error or errcode and errcode != errno.ENOENT:
1058 1062 self.ui.warn(_("trouble committing %s!\n") % f)
1059 1063 raise
1060 1064 else:
1061 1065 removed.append(f)
1062 1066
1063 1067 # update manifest
1064 1068 m1.update(new)
1065 1069 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1066 1070 drop = [f for f in removed if f in m1]
1067 1071 for f in drop:
1068 1072 del m1[f]
1069 1073 mn = self.manifest.add(m1, trp, linkrev, p1.manifestnode(),
1070 1074 p2.manifestnode(), (new, drop))
1071 1075
1072 1076 # update changelog
1073 1077 self.changelog.delayupdate()
1074 1078 n = self.changelog.add(mn, changed + removed, ctx.description(),
1075 1079 trp, p1.node(), p2.node(),
1076 1080 user, ctx.date(), ctx.extra().copy())
1077 1081 p = lambda: self.changelog.writepending() and self.root or ""
1078 1082 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
1079 1083 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
1080 1084 parent2=xp2, pending=p)
1081 1085 self.changelog.finalize(trp)
1082 1086 tr.close()
1083 1087
1084 1088 if self._branchcache:
1085 1089 self.updatebranchcache()
1086 1090 return n
1087 1091 finally:
1088 1092 if tr:
1089 1093 tr.release()
1090 1094 lock.release()
1091 1095
1092 1096 def destroyed(self):
1093 1097 '''Inform the repository that nodes have been destroyed.
1094 1098 Intended for use by strip and rollback, so there's a common
1095 1099 place for anything that has to be done after destroying history.'''
1096 1100 # XXX it might be nice if we could take the list of destroyed
1097 1101 # nodes, but I don't see an easy way for rollback() to do that
1098 1102
1099 1103 # Ensure the persistent tag cache is updated. Doing it now
1100 1104 # means that the tag cache only has to worry about destroyed
1101 1105 # heads immediately after a strip/rollback. That in turn
1102 1106 # guarantees that "cachetip == currenttip" (comparing both rev
1103 1107 # and node) always means no nodes have been added or destroyed.
1104 1108
1105 1109 # XXX this is suboptimal when qrefresh'ing: we strip the current
1106 1110 # head, refresh the tag cache, then immediately add a new head.
1107 1111 # But I think doing it this way is necessary for the "instant
1108 1112 # tag cache retrieval" case to work.
1109 1113 self.invalidatecaches()
1110 1114
1111 1115 def walk(self, match, node=None):
1112 1116 '''
1113 1117 walk recursively through the directory tree or a given
1114 1118 changeset, finding all files matched by the match
1115 1119 function
1116 1120 '''
1117 1121 return self[node].walk(match)
1118 1122
1119 1123 def status(self, node1='.', node2=None, match=None,
1120 1124 ignored=False, clean=False, unknown=False,
1121 1125 listsubrepos=False):
1122 1126 """return status of files between two nodes or node and working directory
1123 1127
1124 1128 If node1 is None, use the first dirstate parent instead.
1125 1129 If node2 is None, compare node1 with working directory.
1126 1130 """
1127 1131
1128 1132 def mfmatches(ctx):
1129 1133 mf = ctx.manifest().copy()
1130 1134 for fn in mf.keys():
1131 1135 if not match(fn):
1132 1136 del mf[fn]
1133 1137 return mf
1134 1138
1135 1139 if isinstance(node1, context.changectx):
1136 1140 ctx1 = node1
1137 1141 else:
1138 1142 ctx1 = self[node1]
1139 1143 if isinstance(node2, context.changectx):
1140 1144 ctx2 = node2
1141 1145 else:
1142 1146 ctx2 = self[node2]
1143 1147
1144 1148 working = ctx2.rev() is None
1145 1149 parentworking = working and ctx1 == self['.']
1146 1150 match = match or matchmod.always(self.root, self.getcwd())
1147 1151 listignored, listclean, listunknown = ignored, clean, unknown
1148 1152
1149 1153 # load earliest manifest first for caching reasons
1150 1154 if not working and ctx2.rev() < ctx1.rev():
1151 1155 ctx2.manifest()
1152 1156
1153 1157 if not parentworking:
1154 1158 def bad(f, msg):
1155 1159 if f not in ctx1:
1156 1160 self.ui.warn('%s: %s\n' % (self.dirstate.pathto(f), msg))
1157 1161 match.bad = bad
1158 1162
1159 1163 if working: # we need to scan the working dir
1160 1164 subrepos = []
1161 1165 if '.hgsub' in self.dirstate:
1162 1166 subrepos = ctx1.substate.keys()
1163 1167 s = self.dirstate.status(match, subrepos, listignored,
1164 1168 listclean, listunknown)
1165 1169 cmp, modified, added, removed, deleted, unknown, ignored, clean = s
1166 1170
1167 1171 # check for any possibly clean files
1168 1172 if parentworking and cmp:
1169 1173 fixup = []
1170 1174 # do a full compare of any files that might have changed
1171 1175 for f in sorted(cmp):
1172 1176 if (f not in ctx1 or ctx2.flags(f) != ctx1.flags(f)
1173 1177 or ctx1[f].cmp(ctx2[f])):
1174 1178 modified.append(f)
1175 1179 else:
1176 1180 fixup.append(f)
1177 1181
1178 1182 # update dirstate for files that are actually clean
1179 1183 if fixup:
1180 1184 if listclean:
1181 1185 clean += fixup
1182 1186
1183 1187 try:
1184 1188 # updating the dirstate is optional
1185 1189 # so we don't wait on the lock
1186 1190 wlock = self.wlock(False)
1187 1191 try:
1188 1192 for f in fixup:
1189 1193 self.dirstate.normal(f)
1190 1194 finally:
1191 1195 wlock.release()
1192 1196 except error.LockError:
1193 1197 pass
1194 1198
1195 1199 if not parentworking:
1196 1200 mf1 = mfmatches(ctx1)
1197 1201 if working:
1198 1202 # we are comparing working dir against non-parent
1199 1203 # generate a pseudo-manifest for the working dir
1200 1204 mf2 = mfmatches(self['.'])
1201 1205 for f in cmp + modified + added:
1202 1206 mf2[f] = None
1203 1207 mf2.set(f, ctx2.flags(f))
1204 1208 for f in removed:
1205 1209 if f in mf2:
1206 1210 del mf2[f]
1207 1211 else:
1208 1212 # we are comparing two revisions
1209 1213 deleted, unknown, ignored = [], [], []
1210 1214 mf2 = mfmatches(ctx2)
1211 1215
1212 1216 modified, added, clean = [], [], []
1213 1217 for fn in mf2:
1214 1218 if fn in mf1:
1215 1219 if (mf1.flags(fn) != mf2.flags(fn) or
1216 1220 (mf1[fn] != mf2[fn] and
1217 1221 (mf2[fn] or ctx1[fn].cmp(ctx2[fn])))):
1218 1222 modified.append(fn)
1219 1223 elif listclean:
1220 1224 clean.append(fn)
1221 1225 del mf1[fn]
1222 1226 else:
1223 1227 added.append(fn)
1224 1228 removed = mf1.keys()
1225 1229
1226 1230 r = modified, added, removed, deleted, unknown, ignored, clean
1227 1231
1228 1232 if listsubrepos:
1229 1233 for subpath, sub in subrepo.itersubrepos(ctx1, ctx2):
1230 1234 if working:
1231 1235 rev2 = None
1232 1236 else:
1233 1237 rev2 = ctx2.substate[subpath][1]
1234 1238 try:
1235 1239 submatch = matchmod.narrowmatcher(subpath, match)
1236 1240 s = sub.status(rev2, match=submatch, ignored=listignored,
1237 1241 clean=listclean, unknown=listunknown,
1238 1242 listsubrepos=True)
1239 1243 for rfiles, sfiles in zip(r, s):
1240 1244 rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
1241 1245 except error.LookupError:
1242 1246 self.ui.status(_("skipping missing subrepository: %s\n")
1243 1247 % subpath)
1244 1248
1245 1249 for l in r:
1246 1250 l.sort()
1247 1251 return r
1248 1252
1249 1253 def heads(self, start=None):
1250 1254 heads = self.changelog.heads(start)
1251 1255 # sort the output in rev descending order
1252 1256 return sorted(heads, key=self.changelog.rev, reverse=True)
1253 1257
1254 1258 def branchheads(self, branch=None, start=None, closed=False):
1255 1259 '''return a (possibly filtered) list of heads for the given branch
1256 1260
1257 1261 Heads are returned in topological order, from newest to oldest.
1258 1262 If branch is None, use the dirstate branch.
1259 1263 If start is not None, return only heads reachable from start.
1260 1264 If closed is True, return heads that are marked as closed as well.
1261 1265 '''
1262 1266 if branch is None:
1263 1267 branch = self[None].branch()
1264 1268 branches = self.branchmap()
1265 1269 if branch not in branches:
1266 1270 return []
1267 1271 # the cache returns heads ordered lowest to highest
1268 1272 bheads = list(reversed(branches[branch]))
1269 1273 if start is not None:
1270 1274 # filter out the heads that cannot be reached from startrev
1271 1275 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
1272 1276 bheads = [h for h in bheads if h in fbheads]
1273 1277 if not closed:
1274 1278 bheads = [h for h in bheads if
1275 1279 ('close' not in self.changelog.read(h)[5])]
1276 1280 return bheads
1277 1281
1278 1282 def branches(self, nodes):
1279 1283 if not nodes:
1280 1284 nodes = [self.changelog.tip()]
1281 1285 b = []
1282 1286 for n in nodes:
1283 1287 t = n
1284 1288 while 1:
1285 1289 p = self.changelog.parents(n)
1286 1290 if p[1] != nullid or p[0] == nullid:
1287 1291 b.append((t, n, p[0], p[1]))
1288 1292 break
1289 1293 n = p[0]
1290 1294 return b
1291 1295
1292 1296 def between(self, pairs):
1293 1297 r = []
1294 1298
1295 1299 for top, bottom in pairs:
1296 1300 n, l, i = top, [], 0
1297 1301 f = 1
1298 1302
1299 1303 while n != bottom and n != nullid:
1300 1304 p = self.changelog.parents(n)[0]
1301 1305 if i == f:
1302 1306 l.append(n)
1303 1307 f = f * 2
1304 1308 n = p
1305 1309 i += 1
1306 1310
1307 1311 r.append(l)
1308 1312
1309 1313 return r
1310 1314
1311 1315 def pull(self, remote, heads=None, force=False):
1312 1316 lock = self.lock()
1313 1317 try:
1314 1318 tmp = discovery.findcommonincoming(self, remote, heads=heads,
1315 1319 force=force)
1316 1320 common, fetch, rheads = tmp
1317 1321 if not fetch:
1318 1322 self.ui.status(_("no changes found\n"))
1319 1323 result = 0
1320 1324 else:
1321 1325 if heads is None and fetch == [nullid]:
1322 1326 self.ui.status(_("requesting all changes\n"))
1323 1327 elif heads is None and remote.capable('changegroupsubset'):
1324 1328 # issue1320, avoid a race if remote changed after discovery
1325 1329 heads = rheads
1326 1330
1327 1331 if heads is None:
1328 1332 cg = remote.changegroup(fetch, 'pull')
1329 1333 elif not remote.capable('changegroupsubset'):
1330 1334 raise util.Abort(_("partial pull cannot be done because "
1331 1335 "other repository doesn't support "
1332 1336 "changegroupsubset."))
1333 1337 else:
1334 1338 cg = remote.changegroupsubset(fetch, heads, 'pull')
1335 1339 result = self.addchangegroup(cg, 'pull', remote.url(),
1336 1340 lock=lock)
1337 1341 finally:
1338 1342 lock.release()
1339 1343
1340 1344 self.ui.debug("checking for updated bookmarks\n")
1341 1345 rb = remote.listkeys('bookmarks')
1342 1346 changed = False
1343 1347 for k in rb.keys():
1344 1348 if k in self._bookmarks:
1345 1349 nr, nl = rb[k], self._bookmarks[k]
1346 1350 if nr in self:
1347 1351 cr = self[nr]
1348 1352 cl = self[nl]
1349 1353 if cl.rev() >= cr.rev():
1350 1354 continue
1351 1355 if cr in cl.descendants():
1352 1356 self._bookmarks[k] = cr.node()
1353 1357 changed = True
1354 1358 self.ui.status(_("updating bookmark %s\n") % k)
1355 1359 else:
1356 1360 self.ui.warn(_("not updating divergent"
1357 1361 " bookmark %s\n") % k)
1358 1362 if changed:
1359 1363 bookmarks.write(self)
1360 1364
1361 1365 return result
1362 1366
1363 1367 def checkpush(self, force, revs):
1364 1368 """Extensions can override this function if additional checks have
1365 1369 to be performed before pushing, or call it if they override push
1366 1370 command.
1367 1371 """
1368 1372 pass
1369 1373
1370 1374 def push(self, remote, force=False, revs=None, newbranch=False):
1371 1375 '''Push outgoing changesets (limited by revs) from the current
1372 1376 repository to remote. Return an integer:
1373 1377 - 0 means HTTP error *or* nothing to push
1374 1378 - 1 means we pushed and remote head count is unchanged *or*
1375 1379 we have outgoing changesets but refused to push
1376 1380 - other values as described by addchangegroup()
1377 1381 '''
1378 1382 # there are two ways to push to remote repo:
1379 1383 #
1380 1384 # addchangegroup assumes local user can lock remote
1381 1385 # repo (local filesystem, old ssh servers).
1382 1386 #
1383 1387 # unbundle assumes local user cannot lock remote repo (new ssh
1384 1388 # servers, http servers).
1385 1389
1386 1390 self.checkpush(force, revs)
1387 1391 lock = None
1388 1392 unbundle = remote.capable('unbundle')
1389 1393 if not unbundle:
1390 1394 lock = remote.lock()
1391 1395 try:
1392 1396 cg, remote_heads = discovery.prepush(self, remote, force, revs,
1393 1397 newbranch)
1394 1398 ret = remote_heads
1395 1399 if cg is not None:
1396 1400 if unbundle:
1397 1401 # local repo finds heads on server, finds out what
1398 1402 # revs it must push. once revs transferred, if server
1399 1403 # finds it has different heads (someone else won
1400 1404 # commit/push race), server aborts.
1401 1405 if force:
1402 1406 remote_heads = ['force']
1403 1407 # ssh: return remote's addchangegroup()
1404 1408 # http: return remote's addchangegroup() or 0 for error
1405 1409 ret = remote.unbundle(cg, remote_heads, 'push')
1406 1410 else:
1407 1411 # we return an integer indicating remote head count change
1408 1412 ret = remote.addchangegroup(cg, 'push', self.url(),
1409 1413 lock=lock)
1410 1414 finally:
1411 1415 if lock is not None:
1412 1416 lock.release()
1413 1417
1414 1418 self.ui.debug("checking for updated bookmarks\n")
1415 1419 rb = remote.listkeys('bookmarks')
1416 1420 for k in rb.keys():
1417 1421 if k in self._bookmarks:
1418 1422 nr, nl = rb[k], hex(self._bookmarks[k])
1419 1423 if nr in self:
1420 1424 cr = self[nr]
1421 1425 cl = self[nl]
1422 1426 if cl in cr.descendants():
1423 1427 r = remote.pushkey('bookmarks', k, nr, nl)
1424 1428 if r:
1425 1429 self.ui.status(_("updating bookmark %s\n") % k)
1426 1430 else:
1427 1431 self.ui.warn(_('updating bookmark %s'
1428 1432 ' failed!\n') % k)
1429 1433
1430 1434 return ret
1431 1435
1432 1436 def changegroupinfo(self, nodes, source):
1433 1437 if self.ui.verbose or source == 'bundle':
1434 1438 self.ui.status(_("%d changesets found\n") % len(nodes))
1435 1439 if self.ui.debugflag:
1436 1440 self.ui.debug("list of changesets:\n")
1437 1441 for node in nodes:
1438 1442 self.ui.debug("%s\n" % hex(node))
1439 1443
1440 1444 def changegroupsubset(self, bases, heads, source, extranodes=None):
1441 1445 """Compute a changegroup consisting of all the nodes that are
1442 1446 descendents of any of the bases and ancestors of any of the heads.
1443 1447 Return a chunkbuffer object whose read() method will return
1444 1448 successive changegroup chunks.
1445 1449
1446 1450 It is fairly complex as determining which filenodes and which
1447 1451 manifest nodes need to be included for the changeset to be complete
1448 1452 is non-trivial.
1449 1453
1450 1454 Another wrinkle is doing the reverse, figuring out which changeset in
1451 1455 the changegroup a particular filenode or manifestnode belongs to.
1452 1456
1453 1457 The caller can specify some nodes that must be included in the
1454 1458 changegroup using the extranodes argument. It should be a dict
1455 1459 where the keys are the filenames (or 1 for the manifest), and the
1456 1460 values are lists of (node, linknode) tuples, where node is a wanted
1457 1461 node and linknode is the changelog node that should be transmitted as
1458 1462 the linkrev.
1459 1463 """
1460 1464
1461 1465 # Set up some initial variables
1462 1466 # Make it easy to refer to self.changelog
1463 1467 cl = self.changelog
1464 1468 # Compute the list of changesets in this changegroup.
1465 1469 # Some bases may turn out to be superfluous, and some heads may be
1466 1470 # too. nodesbetween will return the minimal set of bases and heads
1467 1471 # necessary to re-create the changegroup.
1468 1472 if not bases:
1469 1473 bases = [nullid]
1470 1474 msng_cl_lst, bases, heads = cl.nodesbetween(bases, heads)
1471 1475
1472 1476 if extranodes is None:
1473 1477 # can we go through the fast path ?
1474 1478 heads.sort()
1475 1479 allheads = self.heads()
1476 1480 allheads.sort()
1477 1481 if heads == allheads:
1478 1482 return self._changegroup(msng_cl_lst, source)
1479 1483
1480 1484 # slow path
1481 1485 self.hook('preoutgoing', throw=True, source=source)
1482 1486
1483 1487 self.changegroupinfo(msng_cl_lst, source)
1484 1488
1485 1489 # We assume that all ancestors of bases are known
1486 1490 commonrevs = set(cl.ancestors(*[cl.rev(n) for n in bases]))
1487 1491
1488 1492 # Make it easy to refer to self.manifest
1489 1493 mnfst = self.manifest
1490 1494 # We don't know which manifests are missing yet
1491 1495 msng_mnfst_set = {}
1492 1496 # Nor do we know which filenodes are missing.
1493 1497 msng_filenode_set = {}
1494 1498
1495 1499 # A changeset always belongs to itself, so the changenode lookup
1496 1500 # function for a changenode is identity.
1497 1501 def identity(x):
1498 1502 return x
1499 1503
1500 1504 # A function generating function that sets up the initial environment
1501 1505 # the inner function.
1502 1506 def filenode_collector(changedfiles):
1503 1507 # This gathers information from each manifestnode included in the
1504 1508 # changegroup about which filenodes the manifest node references
1505 1509 # so we can include those in the changegroup too.
1506 1510 #
1507 1511 # It also remembers which changenode each filenode belongs to. It
1508 1512 # does this by assuming the a filenode belongs to the changenode
1509 1513 # the first manifest that references it belongs to.
1510 1514 def collect_msng_filenodes(mnfstnode):
1511 1515 r = mnfst.rev(mnfstnode)
1512 1516 if mnfst.deltaparent(r) in mnfst.parentrevs(r):
1513 1517 # If the previous rev is one of the parents,
1514 1518 # we only need to see a diff.
1515 1519 deltamf = mnfst.readdelta(mnfstnode)
1516 1520 # For each line in the delta
1517 1521 for f, fnode in deltamf.iteritems():
1518 1522 # And if the file is in the list of files we care
1519 1523 # about.
1520 1524 if f in changedfiles:
1521 1525 # Get the changenode this manifest belongs to
1522 1526 clnode = msng_mnfst_set[mnfstnode]
1523 1527 # Create the set of filenodes for the file if
1524 1528 # there isn't one already.
1525 1529 ndset = msng_filenode_set.setdefault(f, {})
1526 1530 # And set the filenode's changelog node to the
1527 1531 # manifest's if it hasn't been set already.
1528 1532 ndset.setdefault(fnode, clnode)
1529 1533 else:
1530 1534 # Otherwise we need a full manifest.
1531 1535 m = mnfst.read(mnfstnode)
1532 1536 # For every file in we care about.
1533 1537 for f in changedfiles:
1534 1538 fnode = m.get(f, None)
1535 1539 # If it's in the manifest
1536 1540 if fnode is not None:
1537 1541 # See comments above.
1538 1542 clnode = msng_mnfst_set[mnfstnode]
1539 1543 ndset = msng_filenode_set.setdefault(f, {})
1540 1544 ndset.setdefault(fnode, clnode)
1541 1545 return collect_msng_filenodes
1542 1546
1543 1547 # If we determine that a particular file or manifest node must be a
1544 1548 # node that the recipient of the changegroup will already have, we can
1545 1549 # also assume the recipient will have all the parents. This function
1546 1550 # prunes them from the set of missing nodes.
1547 1551 def prune(revlog, missingnodes):
1548 1552 hasset = set()
1549 1553 # If a 'missing' filenode thinks it belongs to a changenode we
1550 1554 # assume the recipient must have, then the recipient must have
1551 1555 # that filenode.
1552 1556 for n in missingnodes:
1553 1557 clrev = revlog.linkrev(revlog.rev(n))
1554 1558 if clrev in commonrevs:
1555 1559 hasset.add(n)
1556 1560 for n in hasset:
1557 1561 missingnodes.pop(n, None)
1558 1562 for r in revlog.ancestors(*[revlog.rev(n) for n in hasset]):
1559 1563 missingnodes.pop(revlog.node(r), None)
1560 1564
1561 1565 # Add the nodes that were explicitly requested.
1562 1566 def add_extra_nodes(name, nodes):
1563 1567 if not extranodes or name not in extranodes:
1564 1568 return
1565 1569
1566 1570 for node, linknode in extranodes[name]:
1567 1571 if node not in nodes:
1568 1572 nodes[node] = linknode
1569 1573
1570 1574 # Now that we have all theses utility functions to help out and
1571 1575 # logically divide up the task, generate the group.
1572 1576 def gengroup():
1573 1577 # The set of changed files starts empty.
1574 1578 changedfiles = set()
1575 1579 collect = changegroup.collector(cl, msng_mnfst_set, changedfiles)
1576 1580
1577 1581 # Create a changenode group generator that will call our functions
1578 1582 # back to lookup the owning changenode and collect information.
1579 1583 group = cl.group(msng_cl_lst, identity, collect)
1580 1584 for cnt, chnk in enumerate(group):
1581 1585 yield chnk
1582 1586 # revlog.group yields three entries per node, so
1583 1587 # dividing by 3 gives an approximation of how many
1584 1588 # nodes have been processed.
1585 1589 self.ui.progress(_('bundling'), cnt / 3,
1586 1590 unit=_('changesets'))
1587 1591 changecount = cnt / 3
1588 1592 self.ui.progress(_('bundling'), None)
1589 1593
1590 1594 prune(mnfst, msng_mnfst_set)
1591 1595 add_extra_nodes(1, msng_mnfst_set)
1592 1596 msng_mnfst_lst = msng_mnfst_set.keys()
1593 1597 # Sort the manifestnodes by revision number.
1594 1598 msng_mnfst_lst.sort(key=mnfst.rev)
1595 1599 # Create a generator for the manifestnodes that calls our lookup
1596 1600 # and data collection functions back.
1597 1601 group = mnfst.group(msng_mnfst_lst,
1598 1602 lambda mnode: msng_mnfst_set[mnode],
1599 1603 filenode_collector(changedfiles))
1600 1604 efiles = {}
1601 1605 for cnt, chnk in enumerate(group):
1602 1606 if cnt % 3 == 1:
1603 1607 mnode = chnk[:20]
1604 1608 efiles.update(mnfst.readdelta(mnode))
1605 1609 yield chnk
1606 1610 # see above comment for why we divide by 3
1607 1611 self.ui.progress(_('bundling'), cnt / 3,
1608 1612 unit=_('manifests'), total=changecount)
1609 1613 self.ui.progress(_('bundling'), None)
1610 1614 efiles = len(efiles)
1611 1615
1612 1616 # These are no longer needed, dereference and toss the memory for
1613 1617 # them.
1614 1618 msng_mnfst_lst = None
1615 1619 msng_mnfst_set.clear()
1616 1620
1617 1621 if extranodes:
1618 1622 for fname in extranodes:
1619 1623 if isinstance(fname, int):
1620 1624 continue
1621 1625 msng_filenode_set.setdefault(fname, {})
1622 1626 changedfiles.add(fname)
1623 1627 # Go through all our files in order sorted by name.
1624 1628 for idx, fname in enumerate(sorted(changedfiles)):
1625 1629 filerevlog = self.file(fname)
1626 1630 if not len(filerevlog):
1627 1631 raise util.Abort(_("empty or missing revlog for %s") % fname)
1628 1632 # Toss out the filenodes that the recipient isn't really
1629 1633 # missing.
1630 1634 missingfnodes = msng_filenode_set.pop(fname, {})
1631 1635 prune(filerevlog, missingfnodes)
1632 1636 add_extra_nodes(fname, missingfnodes)
1633 1637 # If any filenodes are left, generate the group for them,
1634 1638 # otherwise don't bother.
1635 1639 if missingfnodes:
1636 1640 yield changegroup.chunkheader(len(fname))
1637 1641 yield fname
1638 1642 # Sort the filenodes by their revision # (topological order)
1639 1643 nodeiter = list(missingfnodes)
1640 1644 nodeiter.sort(key=filerevlog.rev)
1641 1645 # Create a group generator and only pass in a changenode
1642 1646 # lookup function as we need to collect no information
1643 1647 # from filenodes.
1644 1648 group = filerevlog.group(nodeiter,
1645 1649 lambda fnode: missingfnodes[fnode])
1646 1650 for chnk in group:
1647 1651 # even though we print the same progress on
1648 1652 # most loop iterations, put the progress call
1649 1653 # here so that time estimates (if any) can be updated
1650 1654 self.ui.progress(
1651 1655 _('bundling'), idx, item=fname,
1652 1656 unit=_('files'), total=efiles)
1653 1657 yield chnk
1654 1658 # Signal that no more groups are left.
1655 1659 yield changegroup.closechunk()
1656 1660 self.ui.progress(_('bundling'), None)
1657 1661
1658 1662 if msng_cl_lst:
1659 1663 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
1660 1664
1661 1665 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
1662 1666
1663 1667 def changegroup(self, basenodes, source):
1664 1668 # to avoid a race we use changegroupsubset() (issue1320)
1665 1669 return self.changegroupsubset(basenodes, self.heads(), source)
1666 1670
1667 1671 def _changegroup(self, nodes, source):
1668 1672 """Compute the changegroup of all nodes that we have that a recipient
1669 1673 doesn't. Return a chunkbuffer object whose read() method will return
1670 1674 successive changegroup chunks.
1671 1675
1672 1676 This is much easier than the previous function as we can assume that
1673 1677 the recipient has any changenode we aren't sending them.
1674 1678
1675 1679 nodes is the set of nodes to send"""
1676 1680
1677 1681 self.hook('preoutgoing', throw=True, source=source)
1678 1682
1679 1683 cl = self.changelog
1680 1684 revset = set([cl.rev(n) for n in nodes])
1681 1685 self.changegroupinfo(nodes, source)
1682 1686
1683 1687 def identity(x):
1684 1688 return x
1685 1689
1686 1690 def gennodelst(log):
1687 1691 for r in log:
1688 1692 if log.linkrev(r) in revset:
1689 1693 yield log.node(r)
1690 1694
1691 1695 def lookuplinkrev_func(revlog):
1692 1696 def lookuplinkrev(n):
1693 1697 return cl.node(revlog.linkrev(revlog.rev(n)))
1694 1698 return lookuplinkrev
1695 1699
1696 1700 def gengroup():
1697 1701 '''yield a sequence of changegroup chunks (strings)'''
1698 1702 # construct a list of all changed files
1699 1703 changedfiles = set()
1700 1704 mmfs = {}
1701 1705 collect = changegroup.collector(cl, mmfs, changedfiles)
1702 1706
1703 1707 for cnt, chnk in enumerate(cl.group(nodes, identity, collect)):
1704 1708 # revlog.group yields three entries per node, so
1705 1709 # dividing by 3 gives an approximation of how many
1706 1710 # nodes have been processed.
1707 1711 self.ui.progress(_('bundling'), cnt / 3, unit=_('changesets'))
1708 1712 yield chnk
1709 1713 changecount = cnt / 3
1710 1714 self.ui.progress(_('bundling'), None)
1711 1715
1712 1716 mnfst = self.manifest
1713 1717 nodeiter = gennodelst(mnfst)
1714 1718 efiles = {}
1715 1719 for cnt, chnk in enumerate(mnfst.group(nodeiter,
1716 1720 lookuplinkrev_func(mnfst))):
1717 1721 if cnt % 3 == 1:
1718 1722 mnode = chnk[:20]
1719 1723 efiles.update(mnfst.readdelta(mnode))
1720 1724 # see above comment for why we divide by 3
1721 1725 self.ui.progress(_('bundling'), cnt / 3,
1722 1726 unit=_('manifests'), total=changecount)
1723 1727 yield chnk
1724 1728 efiles = len(efiles)
1725 1729 self.ui.progress(_('bundling'), None)
1726 1730
1727 1731 for idx, fname in enumerate(sorted(changedfiles)):
1728 1732 filerevlog = self.file(fname)
1729 1733 if not len(filerevlog):
1730 1734 raise util.Abort(_("empty or missing revlog for %s") % fname)
1731 1735 nodeiter = gennodelst(filerevlog)
1732 1736 nodeiter = list(nodeiter)
1733 1737 if nodeiter:
1734 1738 yield changegroup.chunkheader(len(fname))
1735 1739 yield fname
1736 1740 lookup = lookuplinkrev_func(filerevlog)
1737 1741 for chnk in filerevlog.group(nodeiter, lookup):
1738 1742 self.ui.progress(
1739 1743 _('bundling'), idx, item=fname,
1740 1744 total=efiles, unit=_('files'))
1741 1745 yield chnk
1742 1746 self.ui.progress(_('bundling'), None)
1743 1747
1744 1748 yield changegroup.closechunk()
1745 1749
1746 1750 if nodes:
1747 1751 self.hook('outgoing', node=hex(nodes[0]), source=source)
1748 1752
1749 1753 return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
1750 1754
1751 1755 def addchangegroup(self, source, srctype, url, emptyok=False, lock=None):
1752 1756 """Add the changegroup returned by source.read() to this repo.
1753 1757 srctype is a string like 'push', 'pull', or 'unbundle'. url is
1754 1758 the URL of the repo where this changegroup is coming from.
1755 1759 If lock is not None, the function takes ownership of the lock
1756 1760 and releases it after the changegroup is added.
1757 1761
1758 1762 Return an integer summarizing the change to this repo:
1759 1763 - nothing changed or no source: 0
1760 1764 - more heads than before: 1+added heads (2..n)
1761 1765 - fewer heads than before: -1-removed heads (-2..-n)
1762 1766 - number of heads stays the same: 1
1763 1767 """
1764 1768 def csmap(x):
1765 1769 self.ui.debug("add changeset %s\n" % short(x))
1766 1770 return len(cl)
1767 1771
1768 1772 def revmap(x):
1769 1773 return cl.rev(x)
1770 1774
1771 1775 if not source:
1772 1776 return 0
1773 1777
1774 1778 self.hook('prechangegroup', throw=True, source=srctype, url=url)
1775 1779
1776 1780 changesets = files = revisions = 0
1777 1781 efiles = set()
1778 1782
1779 1783 # write changelog data to temp files so concurrent readers will not see
1780 1784 # inconsistent view
1781 1785 cl = self.changelog
1782 1786 cl.delayupdate()
1783 1787 oldheads = len(cl.heads())
1784 1788
1785 1789 tr = self.transaction("\n".join([srctype, urlmod.hidepassword(url)]))
1786 1790 try:
1787 1791 trp = weakref.proxy(tr)
1788 1792 # pull off the changeset group
1789 1793 self.ui.status(_("adding changesets\n"))
1790 1794 clstart = len(cl)
1791 1795 class prog(object):
1792 1796 step = _('changesets')
1793 1797 count = 1
1794 1798 ui = self.ui
1795 1799 total = None
1796 1800 def __call__(self):
1797 1801 self.ui.progress(self.step, self.count, unit=_('chunks'),
1798 1802 total=self.total)
1799 1803 self.count += 1
1800 1804 pr = prog()
1801 1805 source.callback = pr
1802 1806
1803 1807 if (cl.addgroup(source, csmap, trp) is None
1804 1808 and not emptyok):
1805 1809 raise util.Abort(_("received changelog group is empty"))
1806 1810 clend = len(cl)
1807 1811 changesets = clend - clstart
1808 1812 for c in xrange(clstart, clend):
1809 1813 efiles.update(self[c].files())
1810 1814 efiles = len(efiles)
1811 1815 self.ui.progress(_('changesets'), None)
1812 1816
1813 1817 # pull off the manifest group
1814 1818 self.ui.status(_("adding manifests\n"))
1815 1819 pr.step = _('manifests')
1816 1820 pr.count = 1
1817 1821 pr.total = changesets # manifests <= changesets
1818 1822 # no need to check for empty manifest group here:
1819 1823 # if the result of the merge of 1 and 2 is the same in 3 and 4,
1820 1824 # no new manifest will be created and the manifest group will
1821 1825 # be empty during the pull
1822 1826 self.manifest.addgroup(source, revmap, trp)
1823 1827 self.ui.progress(_('manifests'), None)
1824 1828
1825 1829 needfiles = {}
1826 1830 if self.ui.configbool('server', 'validate', default=False):
1827 1831 # validate incoming csets have their manifests
1828 1832 for cset in xrange(clstart, clend):
1829 1833 mfest = self.changelog.read(self.changelog.node(cset))[0]
1830 1834 mfest = self.manifest.readdelta(mfest)
1831 1835 # store file nodes we must see
1832 1836 for f, n in mfest.iteritems():
1833 1837 needfiles.setdefault(f, set()).add(n)
1834 1838
1835 1839 # process the files
1836 1840 self.ui.status(_("adding file changes\n"))
1837 1841 pr.step = 'files'
1838 1842 pr.count = 1
1839 1843 pr.total = efiles
1840 1844 source.callback = None
1841 1845
1842 1846 while 1:
1843 1847 f = source.chunk()
1844 1848 if not f:
1845 1849 break
1846 1850 self.ui.debug("adding %s revisions\n" % f)
1847 1851 pr()
1848 1852 fl = self.file(f)
1849 1853 o = len(fl)
1850 1854 if fl.addgroup(source, revmap, trp) is None:
1851 1855 raise util.Abort(_("received file revlog group is empty"))
1852 1856 revisions += len(fl) - o
1853 1857 files += 1
1854 1858 if f in needfiles:
1855 1859 needs = needfiles[f]
1856 1860 for new in xrange(o, len(fl)):
1857 1861 n = fl.node(new)
1858 1862 if n in needs:
1859 1863 needs.remove(n)
1860 1864 if not needs:
1861 1865 del needfiles[f]
1862 1866 self.ui.progress(_('files'), None)
1863 1867
1864 1868 for f, needs in needfiles.iteritems():
1865 1869 fl = self.file(f)
1866 1870 for n in needs:
1867 1871 try:
1868 1872 fl.rev(n)
1869 1873 except error.LookupError:
1870 1874 raise util.Abort(
1871 1875 _('missing file data for %s:%s - run hg verify') %
1872 1876 (f, hex(n)))
1873 1877
1874 1878 newheads = len(cl.heads())
1875 1879 heads = ""
1876 1880 if oldheads and newheads != oldheads:
1877 1881 heads = _(" (%+d heads)") % (newheads - oldheads)
1878 1882
1879 1883 self.ui.status(_("added %d changesets"
1880 1884 " with %d changes to %d files%s\n")
1881 1885 % (changesets, revisions, files, heads))
1882 1886
1883 1887 if changesets > 0:
1884 1888 p = lambda: cl.writepending() and self.root or ""
1885 1889 self.hook('pretxnchangegroup', throw=True,
1886 1890 node=hex(cl.node(clstart)), source=srctype,
1887 1891 url=url, pending=p)
1888 1892
1889 1893 # make changelog see real files again
1890 1894 cl.finalize(trp)
1891 1895
1892 1896 tr.close()
1893 1897 finally:
1894 1898 tr.release()
1895 1899 if lock:
1896 1900 lock.release()
1897 1901
1898 1902 if changesets > 0:
1899 1903 # forcefully update the on-disk branch cache
1900 1904 self.ui.debug("updating the branch cache\n")
1901 1905 self.updatebranchcache()
1902 1906 self.hook("changegroup", node=hex(cl.node(clstart)),
1903 1907 source=srctype, url=url)
1904 1908
1905 1909 for i in xrange(clstart, clend):
1906 1910 self.hook("incoming", node=hex(cl.node(i)),
1907 1911 source=srctype, url=url)
1908 1912
1909 1913 # FIXME - why does this care about tip?
1910 1914 if newheads == oldheads:
1911 1915 bookmarks.update(self, self.dirstate.parents(), self['tip'].node())
1912 1916
1913 1917 # never return 0 here:
1914 1918 if newheads < oldheads:
1915 1919 return newheads - oldheads - 1
1916 1920 else:
1917 1921 return newheads - oldheads + 1
1918 1922
1919 1923
1920 1924 def stream_in(self, remote, requirements):
1921 1925 lock = self.lock()
1922 1926 try:
1923 1927 fp = remote.stream_out()
1924 1928 l = fp.readline()
1925 1929 try:
1926 1930 resp = int(l)
1927 1931 except ValueError:
1928 1932 raise error.ResponseError(
1929 1933 _('Unexpected response from remote server:'), l)
1930 1934 if resp == 1:
1931 1935 raise util.Abort(_('operation forbidden by server'))
1932 1936 elif resp == 2:
1933 1937 raise util.Abort(_('locking the remote repository failed'))
1934 1938 elif resp != 0:
1935 1939 raise util.Abort(_('the server sent an unknown error code'))
1936 1940 self.ui.status(_('streaming all changes\n'))
1937 1941 l = fp.readline()
1938 1942 try:
1939 1943 total_files, total_bytes = map(int, l.split(' ', 1))
1940 1944 except (ValueError, TypeError):
1941 1945 raise error.ResponseError(
1942 1946 _('Unexpected response from remote server:'), l)
1943 1947 self.ui.status(_('%d files to transfer, %s of data\n') %
1944 1948 (total_files, util.bytecount(total_bytes)))
1945 1949 start = time.time()
1946 1950 for i in xrange(total_files):
1947 1951 # XXX doesn't support '\n' or '\r' in filenames
1948 1952 l = fp.readline()
1949 1953 try:
1950 1954 name, size = l.split('\0', 1)
1951 1955 size = int(size)
1952 1956 except (ValueError, TypeError):
1953 1957 raise error.ResponseError(
1954 1958 _('Unexpected response from remote server:'), l)
1955 1959 self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size)))
1956 1960 # for backwards compat, name was partially encoded
1957 1961 ofp = self.sopener(store.decodedir(name), 'w')
1958 1962 for chunk in util.filechunkiter(fp, limit=size):
1959 1963 ofp.write(chunk)
1960 1964 ofp.close()
1961 1965 elapsed = time.time() - start
1962 1966 if elapsed <= 0:
1963 1967 elapsed = 0.001
1964 1968 self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
1965 1969 (util.bytecount(total_bytes), elapsed,
1966 1970 util.bytecount(total_bytes / elapsed)))
1967 1971
1968 1972 # new requirements = old non-format requirements + new format-related
1969 1973 # requirements from the streamed-in repository
1970 1974 requirements.update(set(self.requirements) - self.supportedformats)
1971 1975 self._applyrequirements(requirements)
1972 1976 self._writerequirements()
1973 1977
1974 1978 self.invalidate()
1975 1979 return len(self.heads()) + 1
1976 1980 finally:
1977 1981 lock.release()
1978 1982
1979 1983 def clone(self, remote, heads=[], stream=False):
1980 1984 '''clone remote repository.
1981 1985
1982 1986 keyword arguments:
1983 1987 heads: list of revs to clone (forces use of pull)
1984 1988 stream: use streaming clone if possible'''
1985 1989
1986 1990 # now, all clients that can request uncompressed clones can
1987 1991 # read repo formats supported by all servers that can serve
1988 1992 # them.
1989 1993
1990 1994 # if revlog format changes, client will have to check version
1991 1995 # and format flags on "stream" capability, and use
1992 1996 # uncompressed only if compatible.
1993 1997
1994 1998 if stream and not heads:
1995 1999 # 'stream' means remote revlog format is revlogv1 only
1996 2000 if remote.capable('stream'):
1997 2001 return self.stream_in(remote, set(('revlogv1',)))
1998 2002 # otherwise, 'streamreqs' contains the remote revlog format
1999 2003 streamreqs = remote.capable('streamreqs')
2000 2004 if streamreqs:
2001 2005 streamreqs = set(streamreqs.split(','))
2002 2006 # if we support it, stream in and adjust our requirements
2003 2007 if not streamreqs - self.supportedformats:
2004 2008 return self.stream_in(remote, streamreqs)
2005 2009 return self.pull(remote, heads)
2006 2010
2007 2011 def pushkey(self, namespace, key, old, new):
2008 2012 return pushkey.push(self, namespace, key, old, new)
2009 2013
2010 2014 def listkeys(self, namespace):
2011 2015 return pushkey.list(self, namespace)
2012 2016
2013 2017 # used to avoid circular references so destructors work
2014 2018 def aftertrans(files):
2015 2019 renamefiles = [tuple(t) for t in files]
2016 2020 def a():
2017 2021 for src, dest in renamefiles:
2018 2022 util.rename(src, dest)
2019 2023 return a
2020 2024
2021 2025 def instance(ui, path, create):
2022 2026 return localrepository(ui, util.drop_scheme('file', path), create)
2023 2027
2024 2028 def islocal(path):
2025 2029 return True
@@ -1,1742 +1,1749 b''
1 1 > do_push()
2 2 > {
3 3 > user=$1
4 4 > shift
5 5 > echo "Pushing as user $user"
6 6 > echo 'hgrc = """'
7 7 > sed -e 1,2d b/.hg/hgrc | grep -v fakegroups.py
8 8 > echo '"""'
9 9 > if test -f acl.config; then
10 10 > echo 'acl.config = """'
11 11 > cat acl.config
12 12 > echo '"""'
13 13 > fi
14 14 > # On AIX /etc/profile sets LOGNAME read-only. So
15 15 > # LOGNAME=$user hg --cws a --debug push ../b
16 16 > # fails with "This variable is read only."
17 17 > # Use env to work around this.
18 18 > env LOGNAME=$user hg --cwd a --debug push ../b
19 19 > hg --cwd b rollback
20 20 > hg --cwd b --quiet tip
21 21 > echo
22 22 > }
23 23
24 24 > init_config()
25 25 > {
26 26 > cat > fakegroups.py <<EOF
27 27 > from hgext import acl
28 28 > def fakegetusers(ui, group):
29 29 > try:
30 30 > return acl._getusersorig(ui, group)
31 31 > except:
32 32 > return ["fred", "betty"]
33 33 > acl._getusersorig = acl._getusers
34 34 > acl._getusers = fakegetusers
35 35 > EOF
36 36 > rm -f acl.config
37 37 > cat > $config <<EOF
38 38 > [hooks]
39 39 > pretxnchangegroup.acl = python:hgext.acl.hook
40 40 > [acl]
41 41 > sources = push
42 42 > [extensions]
43 43 > f=`pwd`/fakegroups.py
44 44 > EOF
45 45 > }
46 46
47 47 $ hg init a
48 48 $ cd a
49 49 $ mkdir foo foo/Bar quux
50 50 $ echo 'in foo' > foo/file.txt
51 51 $ echo 'in foo/Bar' > foo/Bar/file.txt
52 52 $ echo 'in quux' > quux/file.py
53 53 $ hg add -q
54 54 $ hg ci -m 'add files' -d '1000000 0'
55 55 $ echo >> foo/file.txt
56 56 $ hg ci -m 'change foo/file' -d '1000001 0'
57 57 $ echo >> foo/Bar/file.txt
58 58 $ hg ci -m 'change foo/Bar/file' -d '1000002 0'
59 59 $ echo >> quux/file.py
60 60 $ hg ci -m 'change quux/file' -d '1000003 0'
61 61 $ hg tip --quiet
62 62 3:911600dab2ae
63 63
64 64 $ cd ..
65 65 $ hg clone -r 0 a b
66 66 adding changesets
67 67 adding manifests
68 68 adding file changes
69 69 added 1 changesets with 3 changes to 3 files
70 70 updating to branch default
71 71 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 72
73 73 $ echo '[extensions]' >> $HGRCPATH
74 74 $ echo 'acl =' >> $HGRCPATH
75 75
76 76 $ config=b/.hg/hgrc
77 77
78 78 Extension disabled for lack of a hook
79 79
80 80 $ do_push fred
81 81 Pushing as user fred
82 82 hgrc = """
83 83 """
84 84 pushing to ../b
85 85 searching for changes
86 86 common changesets up to 6675d58eff77
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: 0 changesets
94 94 bundling: 0 changesets
95 95 bundling: 0 changesets
96 96 bundling: 1 changesets
97 97 bundling: 1 changesets
98 98 bundling: 1 changesets
99 99 bundling: 2 changesets
100 100 bundling: 2 changesets
101 101 bundling: 2 changesets
102 102 bundling: 3 changesets
103 103 bundling: 0/3 manifests (0.00%)
104 104 bundling: 0/3 manifests (0.00%)
105 105 bundling: 0/3 manifests (0.00%)
106 106 bundling: 1/3 manifests (33.33%)
107 107 bundling: 1/3 manifests (33.33%)
108 108 bundling: 1/3 manifests (33.33%)
109 109 bundling: 2/3 manifests (66.67%)
110 110 bundling: 2/3 manifests (66.67%)
111 111 bundling: 2/3 manifests (66.67%)
112 112 bundling: 3/3 manifests (100.00%)
113 113 bundling: foo/Bar/file.txt 0/3 files (0.00%)
114 114 bundling: foo/Bar/file.txt 0/3 files (0.00%)
115 115 bundling: foo/Bar/file.txt 0/3 files (0.00%)
116 116 bundling: foo/Bar/file.txt 0/3 files (0.00%)
117 117 bundling: foo/file.txt 1/3 files (33.33%)
118 118 bundling: foo/file.txt 1/3 files (33.33%)
119 119 bundling: foo/file.txt 1/3 files (33.33%)
120 120 bundling: foo/file.txt 1/3 files (33.33%)
121 121 bundling: quux/file.py 2/3 files (66.67%)
122 122 bundling: quux/file.py 2/3 files (66.67%)
123 123 bundling: quux/file.py 2/3 files (66.67%)
124 124 bundling: quux/file.py 2/3 files (66.67%)
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 updating the branch cache
144 144 checking for updated bookmarks
145 rolling back to revision 0 (undo push)
145 repository tip rolled back to revision 0 (undo push)
146 working directory now based on revision 0
146 147 0:6675d58eff77
147 148
148 149
149 150 $ echo '[hooks]' >> $config
150 151 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
151 152
152 153 Extension disabled for lack of acl.sources
153 154
154 155 $ do_push fred
155 156 Pushing as user fred
156 157 hgrc = """
157 158 [hooks]
158 159 pretxnchangegroup.acl = python:hgext.acl.hook
159 160 """
160 161 pushing to ../b
161 162 searching for changes
162 163 common changesets up to 6675d58eff77
163 164 invalidating branch cache (tip differs)
164 165 3 changesets found
165 166 list of changesets:
166 167 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
167 168 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
168 169 911600dab2ae7a9baff75958b84fe606851ce955
169 170 adding changesets
170 171 bundling: 0 changesets
171 172 bundling: 0 changesets
172 173 bundling: 0 changesets
173 174 bundling: 1 changesets
174 175 bundling: 1 changesets
175 176 bundling: 1 changesets
176 177 bundling: 2 changesets
177 178 bundling: 2 changesets
178 179 bundling: 2 changesets
179 180 bundling: 3 changesets
180 181 bundling: 0/3 manifests (0.00%)
181 182 bundling: 0/3 manifests (0.00%)
182 183 bundling: 0/3 manifests (0.00%)
183 184 bundling: 1/3 manifests (33.33%)
184 185 bundling: 1/3 manifests (33.33%)
185 186 bundling: 1/3 manifests (33.33%)
186 187 bundling: 2/3 manifests (66.67%)
187 188 bundling: 2/3 manifests (66.67%)
188 189 bundling: 2/3 manifests (66.67%)
189 190 bundling: 3/3 manifests (100.00%)
190 191 bundling: foo/Bar/file.txt 0/3 files (0.00%)
191 192 bundling: foo/Bar/file.txt 0/3 files (0.00%)
192 193 bundling: foo/Bar/file.txt 0/3 files (0.00%)
193 194 bundling: foo/Bar/file.txt 0/3 files (0.00%)
194 195 bundling: foo/file.txt 1/3 files (33.33%)
195 196 bundling: foo/file.txt 1/3 files (33.33%)
196 197 bundling: foo/file.txt 1/3 files (33.33%)
197 198 bundling: foo/file.txt 1/3 files (33.33%)
198 199 bundling: quux/file.py 2/3 files (66.67%)
199 200 bundling: quux/file.py 2/3 files (66.67%)
200 201 bundling: quux/file.py 2/3 files (66.67%)
201 202 bundling: quux/file.py 2/3 files (66.67%)
202 203 changesets: 1 chunks
203 204 add changeset ef1ea85a6374
204 205 changesets: 2 chunks
205 206 add changeset f9cafe1212c8
206 207 changesets: 3 chunks
207 208 add changeset 911600dab2ae
208 209 adding manifests
209 210 manifests: 1/3 chunks (33.33%)
210 211 manifests: 2/3 chunks (66.67%)
211 212 manifests: 3/3 chunks (100.00%)
212 213 adding file changes
213 214 adding foo/Bar/file.txt revisions
214 215 files: 1/3 chunks (33.33%)
215 216 adding foo/file.txt revisions
216 217 files: 2/3 chunks (66.67%)
217 218 adding quux/file.py revisions
218 219 files: 3/3 chunks (100.00%)
219 220 added 3 changesets with 3 changes to 3 files
220 221 calling hook pretxnchangegroup.acl: hgext.acl.hook
221 222 acl: changes have source "push" - skipping
222 223 updating the branch cache
223 224 checking for updated bookmarks
224 rolling back to revision 0 (undo push)
225 repository tip rolled back to revision 0 (undo push)
226 working directory now based on revision 0
225 227 0:6675d58eff77
226 228
227 229
228 230 No [acl.allow]/[acl.deny]
229 231
230 232 $ echo '[acl]' >> $config
231 233 $ echo 'sources = push' >> $config
232 234 $ do_push fred
233 235 Pushing as user fred
234 236 hgrc = """
235 237 [hooks]
236 238 pretxnchangegroup.acl = python:hgext.acl.hook
237 239 [acl]
238 240 sources = push
239 241 """
240 242 pushing to ../b
241 243 searching for changes
242 244 common changesets up to 6675d58eff77
243 245 invalidating branch cache (tip differs)
244 246 3 changesets found
245 247 list of changesets:
246 248 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
247 249 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
248 250 911600dab2ae7a9baff75958b84fe606851ce955
249 251 adding changesets
250 252 bundling: 0 changesets
251 253 bundling: 0 changesets
252 254 bundling: 0 changesets
253 255 bundling: 1 changesets
254 256 bundling: 1 changesets
255 257 bundling: 1 changesets
256 258 bundling: 2 changesets
257 259 bundling: 2 changesets
258 260 bundling: 2 changesets
259 261 bundling: 3 changesets
260 262 bundling: 0/3 manifests (0.00%)
261 263 bundling: 0/3 manifests (0.00%)
262 264 bundling: 0/3 manifests (0.00%)
263 265 bundling: 1/3 manifests (33.33%)
264 266 bundling: 1/3 manifests (33.33%)
265 267 bundling: 1/3 manifests (33.33%)
266 268 bundling: 2/3 manifests (66.67%)
267 269 bundling: 2/3 manifests (66.67%)
268 270 bundling: 2/3 manifests (66.67%)
269 271 bundling: 3/3 manifests (100.00%)
270 272 bundling: foo/Bar/file.txt 0/3 files (0.00%)
271 273 bundling: foo/Bar/file.txt 0/3 files (0.00%)
272 274 bundling: foo/Bar/file.txt 0/3 files (0.00%)
273 275 bundling: foo/Bar/file.txt 0/3 files (0.00%)
274 276 bundling: foo/file.txt 1/3 files (33.33%)
275 277 bundling: foo/file.txt 1/3 files (33.33%)
276 278 bundling: foo/file.txt 1/3 files (33.33%)
277 279 bundling: foo/file.txt 1/3 files (33.33%)
278 280 bundling: quux/file.py 2/3 files (66.67%)
279 281 bundling: quux/file.py 2/3 files (66.67%)
280 282 bundling: quux/file.py 2/3 files (66.67%)
281 283 bundling: quux/file.py 2/3 files (66.67%)
282 284 changesets: 1 chunks
283 285 add changeset ef1ea85a6374
284 286 changesets: 2 chunks
285 287 add changeset f9cafe1212c8
286 288 changesets: 3 chunks
287 289 add changeset 911600dab2ae
288 290 adding manifests
289 291 manifests: 1/3 chunks (33.33%)
290 292 manifests: 2/3 chunks (66.67%)
291 293 manifests: 3/3 chunks (100.00%)
292 294 adding file changes
293 295 adding foo/Bar/file.txt revisions
294 296 files: 1/3 chunks (33.33%)
295 297 adding foo/file.txt revisions
296 298 files: 2/3 chunks (66.67%)
297 299 adding quux/file.py revisions
298 300 files: 3/3 chunks (100.00%)
299 301 added 3 changesets with 3 changes to 3 files
300 302 calling hook pretxnchangegroup.acl: hgext.acl.hook
301 303 acl: acl.allow.branches not enabled
302 304 acl: acl.deny.branches not enabled
303 305 acl: acl.allow not enabled
304 306 acl: acl.deny not enabled
305 307 acl: branch access granted: "ef1ea85a6374" on branch "default"
306 308 acl: allowing changeset ef1ea85a6374
307 309 acl: branch access granted: "f9cafe1212c8" on branch "default"
308 310 acl: allowing changeset f9cafe1212c8
309 311 acl: branch access granted: "911600dab2ae" on branch "default"
310 312 acl: allowing changeset 911600dab2ae
311 313 updating the branch cache
312 314 checking for updated bookmarks
313 rolling back to revision 0 (undo push)
315 repository tip rolled back to revision 0 (undo push)
316 working directory now based on revision 0
314 317 0:6675d58eff77
315 318
316 319
317 320 Empty [acl.allow]
318 321
319 322 $ echo '[acl.allow]' >> $config
320 323 $ do_push fred
321 324 Pushing as user fred
322 325 hgrc = """
323 326 [hooks]
324 327 pretxnchangegroup.acl = python:hgext.acl.hook
325 328 [acl]
326 329 sources = push
327 330 [acl.allow]
328 331 """
329 332 pushing to ../b
330 333 searching for changes
331 334 common changesets up to 6675d58eff77
332 335 invalidating branch cache (tip differs)
333 336 3 changesets found
334 337 list of changesets:
335 338 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
336 339 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
337 340 911600dab2ae7a9baff75958b84fe606851ce955
338 341 adding changesets
339 342 bundling: 0 changesets
340 343 bundling: 0 changesets
341 344 bundling: 0 changesets
342 345 bundling: 1 changesets
343 346 bundling: 1 changesets
344 347 bundling: 1 changesets
345 348 bundling: 2 changesets
346 349 bundling: 2 changesets
347 350 bundling: 2 changesets
348 351 bundling: 3 changesets
349 352 bundling: 0/3 manifests (0.00%)
350 353 bundling: 0/3 manifests (0.00%)
351 354 bundling: 0/3 manifests (0.00%)
352 355 bundling: 1/3 manifests (33.33%)
353 356 bundling: 1/3 manifests (33.33%)
354 357 bundling: 1/3 manifests (33.33%)
355 358 bundling: 2/3 manifests (66.67%)
356 359 bundling: 2/3 manifests (66.67%)
357 360 bundling: 2/3 manifests (66.67%)
358 361 bundling: 3/3 manifests (100.00%)
359 362 bundling: foo/Bar/file.txt 0/3 files (0.00%)
360 363 bundling: foo/Bar/file.txt 0/3 files (0.00%)
361 364 bundling: foo/Bar/file.txt 0/3 files (0.00%)
362 365 bundling: foo/Bar/file.txt 0/3 files (0.00%)
363 366 bundling: foo/file.txt 1/3 files (33.33%)
364 367 bundling: foo/file.txt 1/3 files (33.33%)
365 368 bundling: foo/file.txt 1/3 files (33.33%)
366 369 bundling: foo/file.txt 1/3 files (33.33%)
367 370 bundling: quux/file.py 2/3 files (66.67%)
368 371 bundling: quux/file.py 2/3 files (66.67%)
369 372 bundling: quux/file.py 2/3 files (66.67%)
370 373 bundling: quux/file.py 2/3 files (66.67%)
371 374 changesets: 1 chunks
372 375 add changeset ef1ea85a6374
373 376 changesets: 2 chunks
374 377 add changeset f9cafe1212c8
375 378 changesets: 3 chunks
376 379 add changeset 911600dab2ae
377 380 adding manifests
378 381 manifests: 1/3 chunks (33.33%)
379 382 manifests: 2/3 chunks (66.67%)
380 383 manifests: 3/3 chunks (100.00%)
381 384 adding file changes
382 385 adding foo/Bar/file.txt revisions
383 386 files: 1/3 chunks (33.33%)
384 387 adding foo/file.txt revisions
385 388 files: 2/3 chunks (66.67%)
386 389 adding quux/file.py revisions
387 390 files: 3/3 chunks (100.00%)
388 391 added 3 changesets with 3 changes to 3 files
389 392 calling hook pretxnchangegroup.acl: hgext.acl.hook
390 393 acl: acl.allow.branches not enabled
391 394 acl: acl.deny.branches not enabled
392 395 acl: acl.allow enabled, 0 entries for user fred
393 396 acl: acl.deny not enabled
394 397 acl: branch access granted: "ef1ea85a6374" on branch "default"
395 398 acl: user fred not allowed on foo/file.txt
396 399 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
397 400 transaction abort!
398 401 rollback completed
399 402 abort: acl: access denied for changeset ef1ea85a6374
400 403 no rollback information available
401 404 0:6675d58eff77
402 405
403 406
404 407 fred is allowed inside foo/
405 408
406 409 $ echo 'foo/** = fred' >> $config
407 410 $ do_push fred
408 411 Pushing as user fred
409 412 hgrc = """
410 413 [hooks]
411 414 pretxnchangegroup.acl = python:hgext.acl.hook
412 415 [acl]
413 416 sources = push
414 417 [acl.allow]
415 418 foo/** = fred
416 419 """
417 420 pushing to ../b
418 421 searching for changes
419 422 common changesets up to 6675d58eff77
420 423 3 changesets found
421 424 list of changesets:
422 425 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
423 426 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
424 427 911600dab2ae7a9baff75958b84fe606851ce955
425 428 adding changesets
426 429 bundling: 0 changesets
427 430 bundling: 0 changesets
428 431 bundling: 0 changesets
429 432 bundling: 1 changesets
430 433 bundling: 1 changesets
431 434 bundling: 1 changesets
432 435 bundling: 2 changesets
433 436 bundling: 2 changesets
434 437 bundling: 2 changesets
435 438 bundling: 3 changesets
436 439 bundling: 0/3 manifests (0.00%)
437 440 bundling: 0/3 manifests (0.00%)
438 441 bundling: 0/3 manifests (0.00%)
439 442 bundling: 1/3 manifests (33.33%)
440 443 bundling: 1/3 manifests (33.33%)
441 444 bundling: 1/3 manifests (33.33%)
442 445 bundling: 2/3 manifests (66.67%)
443 446 bundling: 2/3 manifests (66.67%)
444 447 bundling: 2/3 manifests (66.67%)
445 448 bundling: 3/3 manifests (100.00%)
446 449 bundling: foo/Bar/file.txt 0/3 files (0.00%)
447 450 bundling: foo/Bar/file.txt 0/3 files (0.00%)
448 451 bundling: foo/Bar/file.txt 0/3 files (0.00%)
449 452 bundling: foo/Bar/file.txt 0/3 files (0.00%)
450 453 bundling: foo/file.txt 1/3 files (33.33%)
451 454 bundling: foo/file.txt 1/3 files (33.33%)
452 455 bundling: foo/file.txt 1/3 files (33.33%)
453 456 bundling: foo/file.txt 1/3 files (33.33%)
454 457 bundling: quux/file.py 2/3 files (66.67%)
455 458 bundling: quux/file.py 2/3 files (66.67%)
456 459 bundling: quux/file.py 2/3 files (66.67%)
457 460 bundling: quux/file.py 2/3 files (66.67%)
458 461 changesets: 1 chunks
459 462 add changeset ef1ea85a6374
460 463 changesets: 2 chunks
461 464 add changeset f9cafe1212c8
462 465 changesets: 3 chunks
463 466 add changeset 911600dab2ae
464 467 adding manifests
465 468 manifests: 1/3 chunks (33.33%)
466 469 manifests: 2/3 chunks (66.67%)
467 470 manifests: 3/3 chunks (100.00%)
468 471 adding file changes
469 472 adding foo/Bar/file.txt revisions
470 473 files: 1/3 chunks (33.33%)
471 474 adding foo/file.txt revisions
472 475 files: 2/3 chunks (66.67%)
473 476 adding quux/file.py revisions
474 477 files: 3/3 chunks (100.00%)
475 478 added 3 changesets with 3 changes to 3 files
476 479 calling hook pretxnchangegroup.acl: hgext.acl.hook
477 480 acl: acl.allow.branches not enabled
478 481 acl: acl.deny.branches not enabled
479 482 acl: acl.allow enabled, 1 entries for user fred
480 483 acl: acl.deny not enabled
481 484 acl: branch access granted: "ef1ea85a6374" on branch "default"
482 485 acl: allowing changeset ef1ea85a6374
483 486 acl: branch access granted: "f9cafe1212c8" on branch "default"
484 487 acl: allowing changeset f9cafe1212c8
485 488 acl: branch access granted: "911600dab2ae" on branch "default"
486 489 acl: user fred not allowed on quux/file.py
487 490 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
488 491 transaction abort!
489 492 rollback completed
490 493 abort: acl: access denied for changeset 911600dab2ae
491 494 no rollback information available
492 495 0:6675d58eff77
493 496
494 497
495 498 Empty [acl.deny]
496 499
497 500 $ echo '[acl.deny]' >> $config
498 501 $ do_push barney
499 502 Pushing as user barney
500 503 hgrc = """
501 504 [hooks]
502 505 pretxnchangegroup.acl = python:hgext.acl.hook
503 506 [acl]
504 507 sources = push
505 508 [acl.allow]
506 509 foo/** = fred
507 510 [acl.deny]
508 511 """
509 512 pushing to ../b
510 513 searching for changes
511 514 common changesets up to 6675d58eff77
512 515 3 changesets found
513 516 list of changesets:
514 517 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
515 518 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
516 519 911600dab2ae7a9baff75958b84fe606851ce955
517 520 adding changesets
518 521 bundling: 0 changesets
519 522 bundling: 0 changesets
520 523 bundling: 0 changesets
521 524 bundling: 1 changesets
522 525 bundling: 1 changesets
523 526 bundling: 1 changesets
524 527 bundling: 2 changesets
525 528 bundling: 2 changesets
526 529 bundling: 2 changesets
527 530 bundling: 3 changesets
528 531 bundling: 0/3 manifests (0.00%)
529 532 bundling: 0/3 manifests (0.00%)
530 533 bundling: 0/3 manifests (0.00%)
531 534 bundling: 1/3 manifests (33.33%)
532 535 bundling: 1/3 manifests (33.33%)
533 536 bundling: 1/3 manifests (33.33%)
534 537 bundling: 2/3 manifests (66.67%)
535 538 bundling: 2/3 manifests (66.67%)
536 539 bundling: 2/3 manifests (66.67%)
537 540 bundling: 3/3 manifests (100.00%)
538 541 bundling: foo/Bar/file.txt 0/3 files (0.00%)
539 542 bundling: foo/Bar/file.txt 0/3 files (0.00%)
540 543 bundling: foo/Bar/file.txt 0/3 files (0.00%)
541 544 bundling: foo/Bar/file.txt 0/3 files (0.00%)
542 545 bundling: foo/file.txt 1/3 files (33.33%)
543 546 bundling: foo/file.txt 1/3 files (33.33%)
544 547 bundling: foo/file.txt 1/3 files (33.33%)
545 548 bundling: foo/file.txt 1/3 files (33.33%)
546 549 bundling: quux/file.py 2/3 files (66.67%)
547 550 bundling: quux/file.py 2/3 files (66.67%)
548 551 bundling: quux/file.py 2/3 files (66.67%)
549 552 bundling: quux/file.py 2/3 files (66.67%)
550 553 changesets: 1 chunks
551 554 add changeset ef1ea85a6374
552 555 changesets: 2 chunks
553 556 add changeset f9cafe1212c8
554 557 changesets: 3 chunks
555 558 add changeset 911600dab2ae
556 559 adding manifests
557 560 manifests: 1/3 chunks (33.33%)
558 561 manifests: 2/3 chunks (66.67%)
559 562 manifests: 3/3 chunks (100.00%)
560 563 adding file changes
561 564 adding foo/Bar/file.txt revisions
562 565 files: 1/3 chunks (33.33%)
563 566 adding foo/file.txt revisions
564 567 files: 2/3 chunks (66.67%)
565 568 adding quux/file.py revisions
566 569 files: 3/3 chunks (100.00%)
567 570 added 3 changesets with 3 changes to 3 files
568 571 calling hook pretxnchangegroup.acl: hgext.acl.hook
569 572 acl: acl.allow.branches not enabled
570 573 acl: acl.deny.branches not enabled
571 574 acl: acl.allow enabled, 0 entries for user barney
572 575 acl: acl.deny enabled, 0 entries for user barney
573 576 acl: branch access granted: "ef1ea85a6374" on branch "default"
574 577 acl: user barney not allowed on foo/file.txt
575 578 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
576 579 transaction abort!
577 580 rollback completed
578 581 abort: acl: access denied for changeset ef1ea85a6374
579 582 no rollback information available
580 583 0:6675d58eff77
581 584
582 585
583 586 fred is allowed inside foo/, but not foo/bar/ (case matters)
584 587
585 588 $ echo 'foo/bar/** = fred' >> $config
586 589 $ do_push fred
587 590 Pushing as user fred
588 591 hgrc = """
589 592 [hooks]
590 593 pretxnchangegroup.acl = python:hgext.acl.hook
591 594 [acl]
592 595 sources = push
593 596 [acl.allow]
594 597 foo/** = fred
595 598 [acl.deny]
596 599 foo/bar/** = fred
597 600 """
598 601 pushing to ../b
599 602 searching for changes
600 603 common changesets up to 6675d58eff77
601 604 3 changesets found
602 605 list of changesets:
603 606 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
604 607 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
605 608 911600dab2ae7a9baff75958b84fe606851ce955
606 609 adding changesets
607 610 bundling: 0 changesets
608 611 bundling: 0 changesets
609 612 bundling: 0 changesets
610 613 bundling: 1 changesets
611 614 bundling: 1 changesets
612 615 bundling: 1 changesets
613 616 bundling: 2 changesets
614 617 bundling: 2 changesets
615 618 bundling: 2 changesets
616 619 bundling: 3 changesets
617 620 bundling: 0/3 manifests (0.00%)
618 621 bundling: 0/3 manifests (0.00%)
619 622 bundling: 0/3 manifests (0.00%)
620 623 bundling: 1/3 manifests (33.33%)
621 624 bundling: 1/3 manifests (33.33%)
622 625 bundling: 1/3 manifests (33.33%)
623 626 bundling: 2/3 manifests (66.67%)
624 627 bundling: 2/3 manifests (66.67%)
625 628 bundling: 2/3 manifests (66.67%)
626 629 bundling: 3/3 manifests (100.00%)
627 630 bundling: foo/Bar/file.txt 0/3 files (0.00%)
628 631 bundling: foo/Bar/file.txt 0/3 files (0.00%)
629 632 bundling: foo/Bar/file.txt 0/3 files (0.00%)
630 633 bundling: foo/Bar/file.txt 0/3 files (0.00%)
631 634 bundling: foo/file.txt 1/3 files (33.33%)
632 635 bundling: foo/file.txt 1/3 files (33.33%)
633 636 bundling: foo/file.txt 1/3 files (33.33%)
634 637 bundling: foo/file.txt 1/3 files (33.33%)
635 638 bundling: quux/file.py 2/3 files (66.67%)
636 639 bundling: quux/file.py 2/3 files (66.67%)
637 640 bundling: quux/file.py 2/3 files (66.67%)
638 641 bundling: quux/file.py 2/3 files (66.67%)
639 642 changesets: 1 chunks
640 643 add changeset ef1ea85a6374
641 644 changesets: 2 chunks
642 645 add changeset f9cafe1212c8
643 646 changesets: 3 chunks
644 647 add changeset 911600dab2ae
645 648 adding manifests
646 649 manifests: 1/3 chunks (33.33%)
647 650 manifests: 2/3 chunks (66.67%)
648 651 manifests: 3/3 chunks (100.00%)
649 652 adding file changes
650 653 adding foo/Bar/file.txt revisions
651 654 files: 1/3 chunks (33.33%)
652 655 adding foo/file.txt revisions
653 656 files: 2/3 chunks (66.67%)
654 657 adding quux/file.py revisions
655 658 files: 3/3 chunks (100.00%)
656 659 added 3 changesets with 3 changes to 3 files
657 660 calling hook pretxnchangegroup.acl: hgext.acl.hook
658 661 acl: acl.allow.branches not enabled
659 662 acl: acl.deny.branches not enabled
660 663 acl: acl.allow enabled, 1 entries for user fred
661 664 acl: acl.deny enabled, 1 entries for user fred
662 665 acl: branch access granted: "ef1ea85a6374" on branch "default"
663 666 acl: allowing changeset ef1ea85a6374
664 667 acl: branch access granted: "f9cafe1212c8" on branch "default"
665 668 acl: allowing changeset f9cafe1212c8
666 669 acl: branch access granted: "911600dab2ae" on branch "default"
667 670 acl: user fred not allowed on quux/file.py
668 671 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
669 672 transaction abort!
670 673 rollback completed
671 674 abort: acl: access denied for changeset 911600dab2ae
672 675 no rollback information available
673 676 0:6675d58eff77
674 677
675 678
676 679 fred is allowed inside foo/, but not foo/Bar/
677 680
678 681 $ echo 'foo/Bar/** = fred' >> $config
679 682 $ do_push fred
680 683 Pushing as user fred
681 684 hgrc = """
682 685 [hooks]
683 686 pretxnchangegroup.acl = python:hgext.acl.hook
684 687 [acl]
685 688 sources = push
686 689 [acl.allow]
687 690 foo/** = fred
688 691 [acl.deny]
689 692 foo/bar/** = fred
690 693 foo/Bar/** = fred
691 694 """
692 695 pushing to ../b
693 696 searching for changes
694 697 common changesets up to 6675d58eff77
695 698 3 changesets found
696 699 list of changesets:
697 700 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
698 701 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
699 702 911600dab2ae7a9baff75958b84fe606851ce955
700 703 adding changesets
701 704 bundling: 0 changesets
702 705 bundling: 0 changesets
703 706 bundling: 0 changesets
704 707 bundling: 1 changesets
705 708 bundling: 1 changesets
706 709 bundling: 1 changesets
707 710 bundling: 2 changesets
708 711 bundling: 2 changesets
709 712 bundling: 2 changesets
710 713 bundling: 3 changesets
711 714 bundling: 0/3 manifests (0.00%)
712 715 bundling: 0/3 manifests (0.00%)
713 716 bundling: 0/3 manifests (0.00%)
714 717 bundling: 1/3 manifests (33.33%)
715 718 bundling: 1/3 manifests (33.33%)
716 719 bundling: 1/3 manifests (33.33%)
717 720 bundling: 2/3 manifests (66.67%)
718 721 bundling: 2/3 manifests (66.67%)
719 722 bundling: 2/3 manifests (66.67%)
720 723 bundling: 3/3 manifests (100.00%)
721 724 bundling: foo/Bar/file.txt 0/3 files (0.00%)
722 725 bundling: foo/Bar/file.txt 0/3 files (0.00%)
723 726 bundling: foo/Bar/file.txt 0/3 files (0.00%)
724 727 bundling: foo/Bar/file.txt 0/3 files (0.00%)
725 728 bundling: foo/file.txt 1/3 files (33.33%)
726 729 bundling: foo/file.txt 1/3 files (33.33%)
727 730 bundling: foo/file.txt 1/3 files (33.33%)
728 731 bundling: foo/file.txt 1/3 files (33.33%)
729 732 bundling: quux/file.py 2/3 files (66.67%)
730 733 bundling: quux/file.py 2/3 files (66.67%)
731 734 bundling: quux/file.py 2/3 files (66.67%)
732 735 bundling: quux/file.py 2/3 files (66.67%)
733 736 changesets: 1 chunks
734 737 add changeset ef1ea85a6374
735 738 changesets: 2 chunks
736 739 add changeset f9cafe1212c8
737 740 changesets: 3 chunks
738 741 add changeset 911600dab2ae
739 742 adding manifests
740 743 manifests: 1/3 chunks (33.33%)
741 744 manifests: 2/3 chunks (66.67%)
742 745 manifests: 3/3 chunks (100.00%)
743 746 adding file changes
744 747 adding foo/Bar/file.txt revisions
745 748 files: 1/3 chunks (33.33%)
746 749 adding foo/file.txt revisions
747 750 files: 2/3 chunks (66.67%)
748 751 adding quux/file.py revisions
749 752 files: 3/3 chunks (100.00%)
750 753 added 3 changesets with 3 changes to 3 files
751 754 calling hook pretxnchangegroup.acl: hgext.acl.hook
752 755 acl: acl.allow.branches not enabled
753 756 acl: acl.deny.branches not enabled
754 757 acl: acl.allow enabled, 1 entries for user fred
755 758 acl: acl.deny enabled, 2 entries for user fred
756 759 acl: branch access granted: "ef1ea85a6374" on branch "default"
757 760 acl: allowing changeset ef1ea85a6374
758 761 acl: branch access granted: "f9cafe1212c8" on branch "default"
759 762 acl: user fred denied on foo/Bar/file.txt
760 763 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
761 764 transaction abort!
762 765 rollback completed
763 766 abort: acl: access denied for changeset f9cafe1212c8
764 767 no rollback information available
765 768 0:6675d58eff77
766 769
767 770
768 771 $ echo 'barney is not mentioned => not allowed anywhere'
769 772 barney is not mentioned => not allowed anywhere
770 773 $ do_push barney
771 774 Pushing as user barney
772 775 hgrc = """
773 776 [hooks]
774 777 pretxnchangegroup.acl = python:hgext.acl.hook
775 778 [acl]
776 779 sources = push
777 780 [acl.allow]
778 781 foo/** = fred
779 782 [acl.deny]
780 783 foo/bar/** = fred
781 784 foo/Bar/** = fred
782 785 """
783 786 pushing to ../b
784 787 searching for changes
785 788 common changesets up to 6675d58eff77
786 789 3 changesets found
787 790 list of changesets:
788 791 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
789 792 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
790 793 911600dab2ae7a9baff75958b84fe606851ce955
791 794 adding changesets
792 795 bundling: 0 changesets
793 796 bundling: 0 changesets
794 797 bundling: 0 changesets
795 798 bundling: 1 changesets
796 799 bundling: 1 changesets
797 800 bundling: 1 changesets
798 801 bundling: 2 changesets
799 802 bundling: 2 changesets
800 803 bundling: 2 changesets
801 804 bundling: 3 changesets
802 805 bundling: 0/3 manifests (0.00%)
803 806 bundling: 0/3 manifests (0.00%)
804 807 bundling: 0/3 manifests (0.00%)
805 808 bundling: 1/3 manifests (33.33%)
806 809 bundling: 1/3 manifests (33.33%)
807 810 bundling: 1/3 manifests (33.33%)
808 811 bundling: 2/3 manifests (66.67%)
809 812 bundling: 2/3 manifests (66.67%)
810 813 bundling: 2/3 manifests (66.67%)
811 814 bundling: 3/3 manifests (100.00%)
812 815 bundling: foo/Bar/file.txt 0/3 files (0.00%)
813 816 bundling: foo/Bar/file.txt 0/3 files (0.00%)
814 817 bundling: foo/Bar/file.txt 0/3 files (0.00%)
815 818 bundling: foo/Bar/file.txt 0/3 files (0.00%)
816 819 bundling: foo/file.txt 1/3 files (33.33%)
817 820 bundling: foo/file.txt 1/3 files (33.33%)
818 821 bundling: foo/file.txt 1/3 files (33.33%)
819 822 bundling: foo/file.txt 1/3 files (33.33%)
820 823 bundling: quux/file.py 2/3 files (66.67%)
821 824 bundling: quux/file.py 2/3 files (66.67%)
822 825 bundling: quux/file.py 2/3 files (66.67%)
823 826 bundling: quux/file.py 2/3 files (66.67%)
824 827 changesets: 1 chunks
825 828 add changeset ef1ea85a6374
826 829 changesets: 2 chunks
827 830 add changeset f9cafe1212c8
828 831 changesets: 3 chunks
829 832 add changeset 911600dab2ae
830 833 adding manifests
831 834 manifests: 1/3 chunks (33.33%)
832 835 manifests: 2/3 chunks (66.67%)
833 836 manifests: 3/3 chunks (100.00%)
834 837 adding file changes
835 838 adding foo/Bar/file.txt revisions
836 839 files: 1/3 chunks (33.33%)
837 840 adding foo/file.txt revisions
838 841 files: 2/3 chunks (66.67%)
839 842 adding quux/file.py revisions
840 843 files: 3/3 chunks (100.00%)
841 844 added 3 changesets with 3 changes to 3 files
842 845 calling hook pretxnchangegroup.acl: hgext.acl.hook
843 846 acl: acl.allow.branches not enabled
844 847 acl: acl.deny.branches not enabled
845 848 acl: acl.allow enabled, 0 entries for user barney
846 849 acl: acl.deny enabled, 0 entries for user barney
847 850 acl: branch access granted: "ef1ea85a6374" on branch "default"
848 851 acl: user barney not allowed on foo/file.txt
849 852 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
850 853 transaction abort!
851 854 rollback completed
852 855 abort: acl: access denied for changeset ef1ea85a6374
853 856 no rollback information available
854 857 0:6675d58eff77
855 858
856 859
857 860 barney is allowed everywhere
858 861
859 862 $ echo '[acl.allow]' >> $config
860 863 $ echo '** = barney' >> $config
861 864 $ do_push barney
862 865 Pushing as user barney
863 866 hgrc = """
864 867 [hooks]
865 868 pretxnchangegroup.acl = python:hgext.acl.hook
866 869 [acl]
867 870 sources = push
868 871 [acl.allow]
869 872 foo/** = fred
870 873 [acl.deny]
871 874 foo/bar/** = fred
872 875 foo/Bar/** = fred
873 876 [acl.allow]
874 877 ** = barney
875 878 """
876 879 pushing to ../b
877 880 searching for changes
878 881 common changesets up to 6675d58eff77
879 882 3 changesets found
880 883 list of changesets:
881 884 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
882 885 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
883 886 911600dab2ae7a9baff75958b84fe606851ce955
884 887 adding changesets
885 888 bundling: 0 changesets
886 889 bundling: 0 changesets
887 890 bundling: 0 changesets
888 891 bundling: 1 changesets
889 892 bundling: 1 changesets
890 893 bundling: 1 changesets
891 894 bundling: 2 changesets
892 895 bundling: 2 changesets
893 896 bundling: 2 changesets
894 897 bundling: 3 changesets
895 898 bundling: 0/3 manifests (0.00%)
896 899 bundling: 0/3 manifests (0.00%)
897 900 bundling: 0/3 manifests (0.00%)
898 901 bundling: 1/3 manifests (33.33%)
899 902 bundling: 1/3 manifests (33.33%)
900 903 bundling: 1/3 manifests (33.33%)
901 904 bundling: 2/3 manifests (66.67%)
902 905 bundling: 2/3 manifests (66.67%)
903 906 bundling: 2/3 manifests (66.67%)
904 907 bundling: 3/3 manifests (100.00%)
905 908 bundling: foo/Bar/file.txt 0/3 files (0.00%)
906 909 bundling: foo/Bar/file.txt 0/3 files (0.00%)
907 910 bundling: foo/Bar/file.txt 0/3 files (0.00%)
908 911 bundling: foo/Bar/file.txt 0/3 files (0.00%)
909 912 bundling: foo/file.txt 1/3 files (33.33%)
910 913 bundling: foo/file.txt 1/3 files (33.33%)
911 914 bundling: foo/file.txt 1/3 files (33.33%)
912 915 bundling: foo/file.txt 1/3 files (33.33%)
913 916 bundling: quux/file.py 2/3 files (66.67%)
914 917 bundling: quux/file.py 2/3 files (66.67%)
915 918 bundling: quux/file.py 2/3 files (66.67%)
916 919 bundling: quux/file.py 2/3 files (66.67%)
917 920 changesets: 1 chunks
918 921 add changeset ef1ea85a6374
919 922 changesets: 2 chunks
920 923 add changeset f9cafe1212c8
921 924 changesets: 3 chunks
922 925 add changeset 911600dab2ae
923 926 adding manifests
924 927 manifests: 1/3 chunks (33.33%)
925 928 manifests: 2/3 chunks (66.67%)
926 929 manifests: 3/3 chunks (100.00%)
927 930 adding file changes
928 931 adding foo/Bar/file.txt revisions
929 932 files: 1/3 chunks (33.33%)
930 933 adding foo/file.txt revisions
931 934 files: 2/3 chunks (66.67%)
932 935 adding quux/file.py revisions
933 936 files: 3/3 chunks (100.00%)
934 937 added 3 changesets with 3 changes to 3 files
935 938 calling hook pretxnchangegroup.acl: hgext.acl.hook
936 939 acl: acl.allow.branches not enabled
937 940 acl: acl.deny.branches not enabled
938 941 acl: acl.allow enabled, 1 entries for user barney
939 942 acl: acl.deny enabled, 0 entries for user barney
940 943 acl: branch access granted: "ef1ea85a6374" on branch "default"
941 944 acl: allowing changeset ef1ea85a6374
942 945 acl: branch access granted: "f9cafe1212c8" on branch "default"
943 946 acl: allowing changeset f9cafe1212c8
944 947 acl: branch access granted: "911600dab2ae" on branch "default"
945 948 acl: allowing changeset 911600dab2ae
946 949 updating the branch cache
947 950 checking for updated bookmarks
948 rolling back to revision 0 (undo push)
951 repository tip rolled back to revision 0 (undo push)
952 working directory now based on revision 0
949 953 0:6675d58eff77
950 954
951 955
952 956 wilma can change files with a .txt extension
953 957
954 958 $ echo '**/*.txt = wilma' >> $config
955 959 $ do_push wilma
956 960 Pushing as user wilma
957 961 hgrc = """
958 962 [hooks]
959 963 pretxnchangegroup.acl = python:hgext.acl.hook
960 964 [acl]
961 965 sources = push
962 966 [acl.allow]
963 967 foo/** = fred
964 968 [acl.deny]
965 969 foo/bar/** = fred
966 970 foo/Bar/** = fred
967 971 [acl.allow]
968 972 ** = barney
969 973 **/*.txt = wilma
970 974 """
971 975 pushing to ../b
972 976 searching for changes
973 977 common changesets up to 6675d58eff77
974 978 invalidating branch cache (tip differs)
975 979 3 changesets found
976 980 list of changesets:
977 981 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
978 982 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
979 983 911600dab2ae7a9baff75958b84fe606851ce955
980 984 adding changesets
981 985 bundling: 0 changesets
982 986 bundling: 0 changesets
983 987 bundling: 0 changesets
984 988 bundling: 1 changesets
985 989 bundling: 1 changesets
986 990 bundling: 1 changesets
987 991 bundling: 2 changesets
988 992 bundling: 2 changesets
989 993 bundling: 2 changesets
990 994 bundling: 3 changesets
991 995 bundling: 0/3 manifests (0.00%)
992 996 bundling: 0/3 manifests (0.00%)
993 997 bundling: 0/3 manifests (0.00%)
994 998 bundling: 1/3 manifests (33.33%)
995 999 bundling: 1/3 manifests (33.33%)
996 1000 bundling: 1/3 manifests (33.33%)
997 1001 bundling: 2/3 manifests (66.67%)
998 1002 bundling: 2/3 manifests (66.67%)
999 1003 bundling: 2/3 manifests (66.67%)
1000 1004 bundling: 3/3 manifests (100.00%)
1001 1005 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1002 1006 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1003 1007 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1004 1008 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1005 1009 bundling: foo/file.txt 1/3 files (33.33%)
1006 1010 bundling: foo/file.txt 1/3 files (33.33%)
1007 1011 bundling: foo/file.txt 1/3 files (33.33%)
1008 1012 bundling: foo/file.txt 1/3 files (33.33%)
1009 1013 bundling: quux/file.py 2/3 files (66.67%)
1010 1014 bundling: quux/file.py 2/3 files (66.67%)
1011 1015 bundling: quux/file.py 2/3 files (66.67%)
1012 1016 bundling: quux/file.py 2/3 files (66.67%)
1013 1017 changesets: 1 chunks
1014 1018 add changeset ef1ea85a6374
1015 1019 changesets: 2 chunks
1016 1020 add changeset f9cafe1212c8
1017 1021 changesets: 3 chunks
1018 1022 add changeset 911600dab2ae
1019 1023 adding manifests
1020 1024 manifests: 1/3 chunks (33.33%)
1021 1025 manifests: 2/3 chunks (66.67%)
1022 1026 manifests: 3/3 chunks (100.00%)
1023 1027 adding file changes
1024 1028 adding foo/Bar/file.txt revisions
1025 1029 files: 1/3 chunks (33.33%)
1026 1030 adding foo/file.txt revisions
1027 1031 files: 2/3 chunks (66.67%)
1028 1032 adding quux/file.py revisions
1029 1033 files: 3/3 chunks (100.00%)
1030 1034 added 3 changesets with 3 changes to 3 files
1031 1035 calling hook pretxnchangegroup.acl: hgext.acl.hook
1032 1036 acl: acl.allow.branches not enabled
1033 1037 acl: acl.deny.branches not enabled
1034 1038 acl: acl.allow enabled, 1 entries for user wilma
1035 1039 acl: acl.deny enabled, 0 entries for user wilma
1036 1040 acl: branch access granted: "ef1ea85a6374" on branch "default"
1037 1041 acl: allowing changeset ef1ea85a6374
1038 1042 acl: branch access granted: "f9cafe1212c8" on branch "default"
1039 1043 acl: allowing changeset f9cafe1212c8
1040 1044 acl: branch access granted: "911600dab2ae" on branch "default"
1041 1045 acl: user wilma not allowed on quux/file.py
1042 1046 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
1043 1047 transaction abort!
1044 1048 rollback completed
1045 1049 abort: acl: access denied for changeset 911600dab2ae
1046 1050 no rollback information available
1047 1051 0:6675d58eff77
1048 1052
1049 1053
1050 1054 file specified by acl.config does not exist
1051 1055
1052 1056 $ echo '[acl]' >> $config
1053 1057 $ echo 'config = ../acl.config' >> $config
1054 1058 $ do_push barney
1055 1059 Pushing as user barney
1056 1060 hgrc = """
1057 1061 [hooks]
1058 1062 pretxnchangegroup.acl = python:hgext.acl.hook
1059 1063 [acl]
1060 1064 sources = push
1061 1065 [acl.allow]
1062 1066 foo/** = fred
1063 1067 [acl.deny]
1064 1068 foo/bar/** = fred
1065 1069 foo/Bar/** = fred
1066 1070 [acl.allow]
1067 1071 ** = barney
1068 1072 **/*.txt = wilma
1069 1073 [acl]
1070 1074 config = ../acl.config
1071 1075 """
1072 1076 pushing to ../b
1073 1077 searching for changes
1074 1078 common changesets up to 6675d58eff77
1075 1079 3 changesets found
1076 1080 list of changesets:
1077 1081 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1078 1082 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1079 1083 911600dab2ae7a9baff75958b84fe606851ce955
1080 1084 adding changesets
1081 1085 bundling: 0 changesets
1082 1086 bundling: 0 changesets
1083 1087 bundling: 0 changesets
1084 1088 bundling: 1 changesets
1085 1089 bundling: 1 changesets
1086 1090 bundling: 1 changesets
1087 1091 bundling: 2 changesets
1088 1092 bundling: 2 changesets
1089 1093 bundling: 2 changesets
1090 1094 bundling: 3 changesets
1091 1095 bundling: 0/3 manifests (0.00%)
1092 1096 bundling: 0/3 manifests (0.00%)
1093 1097 bundling: 0/3 manifests (0.00%)
1094 1098 bundling: 1/3 manifests (33.33%)
1095 1099 bundling: 1/3 manifests (33.33%)
1096 1100 bundling: 1/3 manifests (33.33%)
1097 1101 bundling: 2/3 manifests (66.67%)
1098 1102 bundling: 2/3 manifests (66.67%)
1099 1103 bundling: 2/3 manifests (66.67%)
1100 1104 bundling: 3/3 manifests (100.00%)
1101 1105 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1102 1106 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1103 1107 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1104 1108 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1105 1109 bundling: foo/file.txt 1/3 files (33.33%)
1106 1110 bundling: foo/file.txt 1/3 files (33.33%)
1107 1111 bundling: foo/file.txt 1/3 files (33.33%)
1108 1112 bundling: foo/file.txt 1/3 files (33.33%)
1109 1113 bundling: quux/file.py 2/3 files (66.67%)
1110 1114 bundling: quux/file.py 2/3 files (66.67%)
1111 1115 bundling: quux/file.py 2/3 files (66.67%)
1112 1116 bundling: quux/file.py 2/3 files (66.67%)
1113 1117 changesets: 1 chunks
1114 1118 add changeset ef1ea85a6374
1115 1119 changesets: 2 chunks
1116 1120 add changeset f9cafe1212c8
1117 1121 changesets: 3 chunks
1118 1122 add changeset 911600dab2ae
1119 1123 adding manifests
1120 1124 manifests: 1/3 chunks (33.33%)
1121 1125 manifests: 2/3 chunks (66.67%)
1122 1126 manifests: 3/3 chunks (100.00%)
1123 1127 adding file changes
1124 1128 adding foo/Bar/file.txt revisions
1125 1129 files: 1/3 chunks (33.33%)
1126 1130 adding foo/file.txt revisions
1127 1131 files: 2/3 chunks (66.67%)
1128 1132 adding quux/file.py revisions
1129 1133 files: 3/3 chunks (100.00%)
1130 1134 added 3 changesets with 3 changes to 3 files
1131 1135 calling hook pretxnchangegroup.acl: hgext.acl.hook
1132 1136 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
1133 1137 transaction abort!
1134 1138 rollback completed
1135 1139 abort: No such file or directory: ../acl.config
1136 1140 no rollback information available
1137 1141 0:6675d58eff77
1138 1142
1139 1143
1140 1144 betty is allowed inside foo/ by a acl.config file
1141 1145
1142 1146 $ echo '[acl.allow]' >> acl.config
1143 1147 $ echo 'foo/** = betty' >> acl.config
1144 1148 $ do_push betty
1145 1149 Pushing as user betty
1146 1150 hgrc = """
1147 1151 [hooks]
1148 1152 pretxnchangegroup.acl = python:hgext.acl.hook
1149 1153 [acl]
1150 1154 sources = push
1151 1155 [acl.allow]
1152 1156 foo/** = fred
1153 1157 [acl.deny]
1154 1158 foo/bar/** = fred
1155 1159 foo/Bar/** = fred
1156 1160 [acl.allow]
1157 1161 ** = barney
1158 1162 **/*.txt = wilma
1159 1163 [acl]
1160 1164 config = ../acl.config
1161 1165 """
1162 1166 acl.config = """
1163 1167 [acl.allow]
1164 1168 foo/** = betty
1165 1169 """
1166 1170 pushing to ../b
1167 1171 searching for changes
1168 1172 common changesets up to 6675d58eff77
1169 1173 3 changesets found
1170 1174 list of changesets:
1171 1175 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1172 1176 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1173 1177 911600dab2ae7a9baff75958b84fe606851ce955
1174 1178 adding changesets
1175 1179 bundling: 0 changesets
1176 1180 bundling: 0 changesets
1177 1181 bundling: 0 changesets
1178 1182 bundling: 1 changesets
1179 1183 bundling: 1 changesets
1180 1184 bundling: 1 changesets
1181 1185 bundling: 2 changesets
1182 1186 bundling: 2 changesets
1183 1187 bundling: 2 changesets
1184 1188 bundling: 3 changesets
1185 1189 bundling: 0/3 manifests (0.00%)
1186 1190 bundling: 0/3 manifests (0.00%)
1187 1191 bundling: 0/3 manifests (0.00%)
1188 1192 bundling: 1/3 manifests (33.33%)
1189 1193 bundling: 1/3 manifests (33.33%)
1190 1194 bundling: 1/3 manifests (33.33%)
1191 1195 bundling: 2/3 manifests (66.67%)
1192 1196 bundling: 2/3 manifests (66.67%)
1193 1197 bundling: 2/3 manifests (66.67%)
1194 1198 bundling: 3/3 manifests (100.00%)
1195 1199 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1196 1200 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1197 1201 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1198 1202 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1199 1203 bundling: foo/file.txt 1/3 files (33.33%)
1200 1204 bundling: foo/file.txt 1/3 files (33.33%)
1201 1205 bundling: foo/file.txt 1/3 files (33.33%)
1202 1206 bundling: foo/file.txt 1/3 files (33.33%)
1203 1207 bundling: quux/file.py 2/3 files (66.67%)
1204 1208 bundling: quux/file.py 2/3 files (66.67%)
1205 1209 bundling: quux/file.py 2/3 files (66.67%)
1206 1210 bundling: quux/file.py 2/3 files (66.67%)
1207 1211 changesets: 1 chunks
1208 1212 add changeset ef1ea85a6374
1209 1213 changesets: 2 chunks
1210 1214 add changeset f9cafe1212c8
1211 1215 changesets: 3 chunks
1212 1216 add changeset 911600dab2ae
1213 1217 adding manifests
1214 1218 manifests: 1/3 chunks (33.33%)
1215 1219 manifests: 2/3 chunks (66.67%)
1216 1220 manifests: 3/3 chunks (100.00%)
1217 1221 adding file changes
1218 1222 adding foo/Bar/file.txt revisions
1219 1223 files: 1/3 chunks (33.33%)
1220 1224 adding foo/file.txt revisions
1221 1225 files: 2/3 chunks (66.67%)
1222 1226 adding quux/file.py revisions
1223 1227 files: 3/3 chunks (100.00%)
1224 1228 added 3 changesets with 3 changes to 3 files
1225 1229 calling hook pretxnchangegroup.acl: hgext.acl.hook
1226 1230 acl: acl.allow.branches not enabled
1227 1231 acl: acl.deny.branches not enabled
1228 1232 acl: acl.allow enabled, 1 entries for user betty
1229 1233 acl: acl.deny enabled, 0 entries for user betty
1230 1234 acl: branch access granted: "ef1ea85a6374" on branch "default"
1231 1235 acl: allowing changeset ef1ea85a6374
1232 1236 acl: branch access granted: "f9cafe1212c8" on branch "default"
1233 1237 acl: allowing changeset f9cafe1212c8
1234 1238 acl: branch access granted: "911600dab2ae" on branch "default"
1235 1239 acl: user betty not allowed on quux/file.py
1236 1240 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
1237 1241 transaction abort!
1238 1242 rollback completed
1239 1243 abort: acl: access denied for changeset 911600dab2ae
1240 1244 no rollback information available
1241 1245 0:6675d58eff77
1242 1246
1243 1247
1244 1248 acl.config can set only [acl.allow]/[acl.deny]
1245 1249
1246 1250 $ echo '[hooks]' >> acl.config
1247 1251 $ echo 'changegroup.acl = false' >> acl.config
1248 1252 $ do_push barney
1249 1253 Pushing as user barney
1250 1254 hgrc = """
1251 1255 [hooks]
1252 1256 pretxnchangegroup.acl = python:hgext.acl.hook
1253 1257 [acl]
1254 1258 sources = push
1255 1259 [acl.allow]
1256 1260 foo/** = fred
1257 1261 [acl.deny]
1258 1262 foo/bar/** = fred
1259 1263 foo/Bar/** = fred
1260 1264 [acl.allow]
1261 1265 ** = barney
1262 1266 **/*.txt = wilma
1263 1267 [acl]
1264 1268 config = ../acl.config
1265 1269 """
1266 1270 acl.config = """
1267 1271 [acl.allow]
1268 1272 foo/** = betty
1269 1273 [hooks]
1270 1274 changegroup.acl = false
1271 1275 """
1272 1276 pushing to ../b
1273 1277 searching for changes
1274 1278 common changesets up to 6675d58eff77
1275 1279 3 changesets found
1276 1280 list of changesets:
1277 1281 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1278 1282 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1279 1283 911600dab2ae7a9baff75958b84fe606851ce955
1280 1284 adding changesets
1281 1285 bundling: 0 changesets
1282 1286 bundling: 0 changesets
1283 1287 bundling: 0 changesets
1284 1288 bundling: 1 changesets
1285 1289 bundling: 1 changesets
1286 1290 bundling: 1 changesets
1287 1291 bundling: 2 changesets
1288 1292 bundling: 2 changesets
1289 1293 bundling: 2 changesets
1290 1294 bundling: 3 changesets
1291 1295 bundling: 0/3 manifests (0.00%)
1292 1296 bundling: 0/3 manifests (0.00%)
1293 1297 bundling: 0/3 manifests (0.00%)
1294 1298 bundling: 1/3 manifests (33.33%)
1295 1299 bundling: 1/3 manifests (33.33%)
1296 1300 bundling: 1/3 manifests (33.33%)
1297 1301 bundling: 2/3 manifests (66.67%)
1298 1302 bundling: 2/3 manifests (66.67%)
1299 1303 bundling: 2/3 manifests (66.67%)
1300 1304 bundling: 3/3 manifests (100.00%)
1301 1305 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1302 1306 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1303 1307 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1304 1308 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1305 1309 bundling: foo/file.txt 1/3 files (33.33%)
1306 1310 bundling: foo/file.txt 1/3 files (33.33%)
1307 1311 bundling: foo/file.txt 1/3 files (33.33%)
1308 1312 bundling: foo/file.txt 1/3 files (33.33%)
1309 1313 bundling: quux/file.py 2/3 files (66.67%)
1310 1314 bundling: quux/file.py 2/3 files (66.67%)
1311 1315 bundling: quux/file.py 2/3 files (66.67%)
1312 1316 bundling: quux/file.py 2/3 files (66.67%)
1313 1317 changesets: 1 chunks
1314 1318 add changeset ef1ea85a6374
1315 1319 changesets: 2 chunks
1316 1320 add changeset f9cafe1212c8
1317 1321 changesets: 3 chunks
1318 1322 add changeset 911600dab2ae
1319 1323 adding manifests
1320 1324 manifests: 1/3 chunks (33.33%)
1321 1325 manifests: 2/3 chunks (66.67%)
1322 1326 manifests: 3/3 chunks (100.00%)
1323 1327 adding file changes
1324 1328 adding foo/Bar/file.txt revisions
1325 1329 files: 1/3 chunks (33.33%)
1326 1330 adding foo/file.txt revisions
1327 1331 files: 2/3 chunks (66.67%)
1328 1332 adding quux/file.py revisions
1329 1333 files: 3/3 chunks (100.00%)
1330 1334 added 3 changesets with 3 changes to 3 files
1331 1335 calling hook pretxnchangegroup.acl: hgext.acl.hook
1332 1336 acl: acl.allow.branches not enabled
1333 1337 acl: acl.deny.branches not enabled
1334 1338 acl: acl.allow enabled, 1 entries for user barney
1335 1339 acl: acl.deny enabled, 0 entries for user barney
1336 1340 acl: branch access granted: "ef1ea85a6374" on branch "default"
1337 1341 acl: allowing changeset ef1ea85a6374
1338 1342 acl: branch access granted: "f9cafe1212c8" on branch "default"
1339 1343 acl: allowing changeset f9cafe1212c8
1340 1344 acl: branch access granted: "911600dab2ae" on branch "default"
1341 1345 acl: allowing changeset 911600dab2ae
1342 1346 updating the branch cache
1343 1347 checking for updated bookmarks
1344 rolling back to revision 0 (undo push)
1348 repository tip rolled back to revision 0 (undo push)
1349 working directory now based on revision 0
1345 1350 0:6675d58eff77
1346 1351
1347 1352
1348 1353 asterisk
1349 1354
1350 1355 $ init_config
1351 1356
1352 1357 asterisk test
1353 1358
1354 1359 $ echo '[acl.allow]' >> $config
1355 1360 $ echo "** = fred" >> $config
1356 1361
1357 1362 fred is always allowed
1358 1363
1359 1364 $ do_push fred
1360 1365 Pushing as user fred
1361 1366 hgrc = """
1362 1367 [acl]
1363 1368 sources = push
1364 1369 [extensions]
1365 1370 [acl.allow]
1366 1371 ** = fred
1367 1372 """
1368 1373 pushing to ../b
1369 1374 searching for changes
1370 1375 common changesets up to 6675d58eff77
1371 1376 invalidating branch cache (tip differs)
1372 1377 3 changesets found
1373 1378 list of changesets:
1374 1379 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1375 1380 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1376 1381 911600dab2ae7a9baff75958b84fe606851ce955
1377 1382 adding changesets
1378 1383 bundling: 0 changesets
1379 1384 bundling: 0 changesets
1380 1385 bundling: 0 changesets
1381 1386 bundling: 1 changesets
1382 1387 bundling: 1 changesets
1383 1388 bundling: 1 changesets
1384 1389 bundling: 2 changesets
1385 1390 bundling: 2 changesets
1386 1391 bundling: 2 changesets
1387 1392 bundling: 3 changesets
1388 1393 bundling: 0/3 manifests (0.00%)
1389 1394 bundling: 0/3 manifests (0.00%)
1390 1395 bundling: 0/3 manifests (0.00%)
1391 1396 bundling: 1/3 manifests (33.33%)
1392 1397 bundling: 1/3 manifests (33.33%)
1393 1398 bundling: 1/3 manifests (33.33%)
1394 1399 bundling: 2/3 manifests (66.67%)
1395 1400 bundling: 2/3 manifests (66.67%)
1396 1401 bundling: 2/3 manifests (66.67%)
1397 1402 bundling: 3/3 manifests (100.00%)
1398 1403 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1399 1404 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1400 1405 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1401 1406 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1402 1407 bundling: foo/file.txt 1/3 files (33.33%)
1403 1408 bundling: foo/file.txt 1/3 files (33.33%)
1404 1409 bundling: foo/file.txt 1/3 files (33.33%)
1405 1410 bundling: foo/file.txt 1/3 files (33.33%)
1406 1411 bundling: quux/file.py 2/3 files (66.67%)
1407 1412 bundling: quux/file.py 2/3 files (66.67%)
1408 1413 bundling: quux/file.py 2/3 files (66.67%)
1409 1414 bundling: quux/file.py 2/3 files (66.67%)
1410 1415 changesets: 1 chunks
1411 1416 add changeset ef1ea85a6374
1412 1417 changesets: 2 chunks
1413 1418 add changeset f9cafe1212c8
1414 1419 changesets: 3 chunks
1415 1420 add changeset 911600dab2ae
1416 1421 adding manifests
1417 1422 manifests: 1/3 chunks (33.33%)
1418 1423 manifests: 2/3 chunks (66.67%)
1419 1424 manifests: 3/3 chunks (100.00%)
1420 1425 adding file changes
1421 1426 adding foo/Bar/file.txt revisions
1422 1427 files: 1/3 chunks (33.33%)
1423 1428 adding foo/file.txt revisions
1424 1429 files: 2/3 chunks (66.67%)
1425 1430 adding quux/file.py revisions
1426 1431 files: 3/3 chunks (100.00%)
1427 1432 added 3 changesets with 3 changes to 3 files
1428 1433 calling hook pretxnchangegroup.acl: hgext.acl.hook
1429 1434 acl: acl.allow.branches not enabled
1430 1435 acl: acl.deny.branches not enabled
1431 1436 acl: acl.allow enabled, 1 entries for user fred
1432 1437 acl: acl.deny not enabled
1433 1438 acl: branch access granted: "ef1ea85a6374" on branch "default"
1434 1439 acl: allowing changeset ef1ea85a6374
1435 1440 acl: branch access granted: "f9cafe1212c8" on branch "default"
1436 1441 acl: allowing changeset f9cafe1212c8
1437 1442 acl: branch access granted: "911600dab2ae" on branch "default"
1438 1443 acl: allowing changeset 911600dab2ae
1439 1444 updating the branch cache
1440 1445 checking for updated bookmarks
1441 rolling back to revision 0 (undo push)
1446 repository tip rolled back to revision 0 (undo push)
1447 working directory now based on revision 0
1442 1448 0:6675d58eff77
1443 1449
1444 1450
1445 1451 $ echo '[acl.deny]' >> $config
1446 1452 $ echo "foo/Bar/** = *" >> $config
1447 1453
1448 1454 no one is allowed inside foo/Bar/
1449 1455
1450 1456 $ do_push fred
1451 1457 Pushing as user fred
1452 1458 hgrc = """
1453 1459 [acl]
1454 1460 sources = push
1455 1461 [extensions]
1456 1462 [acl.allow]
1457 1463 ** = fred
1458 1464 [acl.deny]
1459 1465 foo/Bar/** = *
1460 1466 """
1461 1467 pushing to ../b
1462 1468 searching for changes
1463 1469 common changesets up to 6675d58eff77
1464 1470 invalidating branch cache (tip differs)
1465 1471 3 changesets found
1466 1472 list of changesets:
1467 1473 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1468 1474 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1469 1475 911600dab2ae7a9baff75958b84fe606851ce955
1470 1476 adding changesets
1471 1477 bundling: 0 changesets
1472 1478 bundling: 0 changesets
1473 1479 bundling: 0 changesets
1474 1480 bundling: 1 changesets
1475 1481 bundling: 1 changesets
1476 1482 bundling: 1 changesets
1477 1483 bundling: 2 changesets
1478 1484 bundling: 2 changesets
1479 1485 bundling: 2 changesets
1480 1486 bundling: 3 changesets
1481 1487 bundling: 0/3 manifests (0.00%)
1482 1488 bundling: 0/3 manifests (0.00%)
1483 1489 bundling: 0/3 manifests (0.00%)
1484 1490 bundling: 1/3 manifests (33.33%)
1485 1491 bundling: 1/3 manifests (33.33%)
1486 1492 bundling: 1/3 manifests (33.33%)
1487 1493 bundling: 2/3 manifests (66.67%)
1488 1494 bundling: 2/3 manifests (66.67%)
1489 1495 bundling: 2/3 manifests (66.67%)
1490 1496 bundling: 3/3 manifests (100.00%)
1491 1497 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1492 1498 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1493 1499 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1494 1500 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1495 1501 bundling: foo/file.txt 1/3 files (33.33%)
1496 1502 bundling: foo/file.txt 1/3 files (33.33%)
1497 1503 bundling: foo/file.txt 1/3 files (33.33%)
1498 1504 bundling: foo/file.txt 1/3 files (33.33%)
1499 1505 bundling: quux/file.py 2/3 files (66.67%)
1500 1506 bundling: quux/file.py 2/3 files (66.67%)
1501 1507 bundling: quux/file.py 2/3 files (66.67%)
1502 1508 bundling: quux/file.py 2/3 files (66.67%)
1503 1509 changesets: 1 chunks
1504 1510 add changeset ef1ea85a6374
1505 1511 changesets: 2 chunks
1506 1512 add changeset f9cafe1212c8
1507 1513 changesets: 3 chunks
1508 1514 add changeset 911600dab2ae
1509 1515 adding manifests
1510 1516 manifests: 1/3 chunks (33.33%)
1511 1517 manifests: 2/3 chunks (66.67%)
1512 1518 manifests: 3/3 chunks (100.00%)
1513 1519 adding file changes
1514 1520 adding foo/Bar/file.txt revisions
1515 1521 files: 1/3 chunks (33.33%)
1516 1522 adding foo/file.txt revisions
1517 1523 files: 2/3 chunks (66.67%)
1518 1524 adding quux/file.py revisions
1519 1525 files: 3/3 chunks (100.00%)
1520 1526 added 3 changesets with 3 changes to 3 files
1521 1527 calling hook pretxnchangegroup.acl: hgext.acl.hook
1522 1528 acl: acl.allow.branches not enabled
1523 1529 acl: acl.deny.branches not enabled
1524 1530 acl: acl.allow enabled, 1 entries for user fred
1525 1531 acl: acl.deny enabled, 1 entries for user fred
1526 1532 acl: branch access granted: "ef1ea85a6374" on branch "default"
1527 1533 acl: allowing changeset ef1ea85a6374
1528 1534 acl: branch access granted: "f9cafe1212c8" on branch "default"
1529 1535 acl: user fred denied on foo/Bar/file.txt
1530 1536 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
1531 1537 transaction abort!
1532 1538 rollback completed
1533 1539 abort: acl: access denied for changeset f9cafe1212c8
1534 1540 no rollback information available
1535 1541 0:6675d58eff77
1536 1542
1537 1543
1538 1544 Groups
1539 1545
1540 1546 $ init_config
1541 1547
1542 1548 OS-level groups
1543 1549
1544 1550 $ echo '[acl.allow]' >> $config
1545 1551 $ echo "** = @group1" >> $config
1546 1552
1547 1553 @group1 is always allowed
1548 1554
1549 1555 $ do_push fred
1550 1556 Pushing as user fred
1551 1557 hgrc = """
1552 1558 [acl]
1553 1559 sources = push
1554 1560 [extensions]
1555 1561 [acl.allow]
1556 1562 ** = @group1
1557 1563 """
1558 1564 pushing to ../b
1559 1565 searching for changes
1560 1566 common changesets up to 6675d58eff77
1561 1567 3 changesets found
1562 1568 list of changesets:
1563 1569 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1564 1570 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1565 1571 911600dab2ae7a9baff75958b84fe606851ce955
1566 1572 adding changesets
1567 1573 bundling: 0 changesets
1568 1574 bundling: 0 changesets
1569 1575 bundling: 0 changesets
1570 1576 bundling: 1 changesets
1571 1577 bundling: 1 changesets
1572 1578 bundling: 1 changesets
1573 1579 bundling: 2 changesets
1574 1580 bundling: 2 changesets
1575 1581 bundling: 2 changesets
1576 1582 bundling: 3 changesets
1577 1583 bundling: 0/3 manifests (0.00%)
1578 1584 bundling: 0/3 manifests (0.00%)
1579 1585 bundling: 0/3 manifests (0.00%)
1580 1586 bundling: 1/3 manifests (33.33%)
1581 1587 bundling: 1/3 manifests (33.33%)
1582 1588 bundling: 1/3 manifests (33.33%)
1583 1589 bundling: 2/3 manifests (66.67%)
1584 1590 bundling: 2/3 manifests (66.67%)
1585 1591 bundling: 2/3 manifests (66.67%)
1586 1592 bundling: 3/3 manifests (100.00%)
1587 1593 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1588 1594 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1589 1595 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1590 1596 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1591 1597 bundling: foo/file.txt 1/3 files (33.33%)
1592 1598 bundling: foo/file.txt 1/3 files (33.33%)
1593 1599 bundling: foo/file.txt 1/3 files (33.33%)
1594 1600 bundling: foo/file.txt 1/3 files (33.33%)
1595 1601 bundling: quux/file.py 2/3 files (66.67%)
1596 1602 bundling: quux/file.py 2/3 files (66.67%)
1597 1603 bundling: quux/file.py 2/3 files (66.67%)
1598 1604 bundling: quux/file.py 2/3 files (66.67%)
1599 1605 changesets: 1 chunks
1600 1606 add changeset ef1ea85a6374
1601 1607 changesets: 2 chunks
1602 1608 add changeset f9cafe1212c8
1603 1609 changesets: 3 chunks
1604 1610 add changeset 911600dab2ae
1605 1611 adding manifests
1606 1612 manifests: 1/3 chunks (33.33%)
1607 1613 manifests: 2/3 chunks (66.67%)
1608 1614 manifests: 3/3 chunks (100.00%)
1609 1615 adding file changes
1610 1616 adding foo/Bar/file.txt revisions
1611 1617 files: 1/3 chunks (33.33%)
1612 1618 adding foo/file.txt revisions
1613 1619 files: 2/3 chunks (66.67%)
1614 1620 adding quux/file.py revisions
1615 1621 files: 3/3 chunks (100.00%)
1616 1622 added 3 changesets with 3 changes to 3 files
1617 1623 calling hook pretxnchangegroup.acl: hgext.acl.hook
1618 1624 acl: acl.allow.branches not enabled
1619 1625 acl: acl.deny.branches not enabled
1620 1626 acl: "group1" not defined in [acl.groups]
1621 1627 acl: acl.allow enabled, 1 entries for user fred
1622 1628 acl: acl.deny not enabled
1623 1629 acl: branch access granted: "ef1ea85a6374" on branch "default"
1624 1630 acl: allowing changeset ef1ea85a6374
1625 1631 acl: branch access granted: "f9cafe1212c8" on branch "default"
1626 1632 acl: allowing changeset f9cafe1212c8
1627 1633 acl: branch access granted: "911600dab2ae" on branch "default"
1628 1634 acl: allowing changeset 911600dab2ae
1629 1635 updating the branch cache
1630 1636 checking for updated bookmarks
1631 rolling back to revision 0 (undo push)
1637 repository tip rolled back to revision 0 (undo push)
1638 working directory now based on revision 0
1632 1639 0:6675d58eff77
1633 1640
1634 1641
1635 1642 $ echo '[acl.deny]' >> $config
1636 1643 $ echo "foo/Bar/** = @group1" >> $config
1637 1644
1638 1645 @group is allowed inside anything but foo/Bar/
1639 1646
1640 1647 $ do_push fred
1641 1648 Pushing as user fred
1642 1649 hgrc = """
1643 1650 [acl]
1644 1651 sources = push
1645 1652 [extensions]
1646 1653 [acl.allow]
1647 1654 ** = @group1
1648 1655 [acl.deny]
1649 1656 foo/Bar/** = @group1
1650 1657 """
1651 1658 pushing to ../b
1652 1659 searching for changes
1653 1660 common changesets up to 6675d58eff77
1654 1661 invalidating branch cache (tip differs)
1655 1662 3 changesets found
1656 1663 list of changesets:
1657 1664 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1658 1665 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1659 1666 911600dab2ae7a9baff75958b84fe606851ce955
1660 1667 adding changesets
1661 1668 bundling: 0 changesets
1662 1669 bundling: 0 changesets
1663 1670 bundling: 0 changesets
1664 1671 bundling: 1 changesets
1665 1672 bundling: 1 changesets
1666 1673 bundling: 1 changesets
1667 1674 bundling: 2 changesets
1668 1675 bundling: 2 changesets
1669 1676 bundling: 2 changesets
1670 1677 bundling: 3 changesets
1671 1678 bundling: 0/3 manifests (0.00%)
1672 1679 bundling: 0/3 manifests (0.00%)
1673 1680 bundling: 0/3 manifests (0.00%)
1674 1681 bundling: 1/3 manifests (33.33%)
1675 1682 bundling: 1/3 manifests (33.33%)
1676 1683 bundling: 1/3 manifests (33.33%)
1677 1684 bundling: 2/3 manifests (66.67%)
1678 1685 bundling: 2/3 manifests (66.67%)
1679 1686 bundling: 2/3 manifests (66.67%)
1680 1687 bundling: 3/3 manifests (100.00%)
1681 1688 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1682 1689 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1683 1690 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1684 1691 bundling: foo/Bar/file.txt 0/3 files (0.00%)
1685 1692 bundling: foo/file.txt 1/3 files (33.33%)
1686 1693 bundling: foo/file.txt 1/3 files (33.33%)
1687 1694 bundling: foo/file.txt 1/3 files (33.33%)
1688 1695 bundling: foo/file.txt 1/3 files (33.33%)
1689 1696 bundling: quux/file.py 2/3 files (66.67%)
1690 1697 bundling: quux/file.py 2/3 files (66.67%)
1691 1698 bundling: quux/file.py 2/3 files (66.67%)
1692 1699 bundling: quux/file.py 2/3 files (66.67%)
1693 1700 changesets: 1 chunks
1694 1701 add changeset ef1ea85a6374
1695 1702 changesets: 2 chunks
1696 1703 add changeset f9cafe1212c8
1697 1704 changesets: 3 chunks
1698 1705 add changeset 911600dab2ae
1699 1706 adding manifests
1700 1707 manifests: 1/3 chunks (33.33%)
1701 1708 manifests: 2/3 chunks (66.67%)
1702 1709 manifests: 3/3 chunks (100.00%)
1703 1710 adding file changes
1704 1711 adding foo/Bar/file.txt revisions
1705 1712 files: 1/3 chunks (33.33%)
1706 1713 adding foo/file.txt revisions
1707 1714 files: 2/3 chunks (66.67%)
1708 1715 adding quux/file.py revisions
1709 1716 files: 3/3 chunks (100.00%)
1710 1717 added 3 changesets with 3 changes to 3 files
1711 1718 calling hook pretxnchangegroup.acl: hgext.acl.hook
1712 1719 acl: acl.allow.branches not enabled
1713 1720 acl: acl.deny.branches not enabled
1714 1721 acl: "group1" not defined in [acl.groups]
1715 1722 acl: acl.allow enabled, 1 entries for user fred
1716 1723 acl: "group1" not defined in [acl.groups]
1717 1724 acl: acl.deny enabled, 1 entries for user fred
1718 1725 acl: branch access granted: "ef1ea85a6374" on branch "default"
1719 1726 acl: allowing changeset ef1ea85a6374
1720 1727 acl: branch access granted: "f9cafe1212c8" on branch "default"
1721 1728 acl: user fred denied on foo/Bar/file.txt
1722 1729 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
1723 1730 transaction abort!
1724 1731 rollback completed
1725 1732 abort: acl: access denied for changeset f9cafe1212c8
1726 1733 no rollback information available
1727 1734 0:6675d58eff77
1728 1735
1729 1736
1730 1737 Invalid group
1731 1738
1732 1739 Disable the fakegroups trick to get real failures
1733 1740
1734 1741 $ grep -v fakegroups $config > config.tmp
1735 1742 $ mv config.tmp $config
1736 1743 $ echo '[acl.allow]' >> $config
1737 1744 $ echo "** = @unlikelytoexist" >> $config
1738 1745 $ do_push fred 2>&1 | grep unlikelytoexist
1739 1746 ** = @unlikelytoexist
1740 1747 acl: "unlikelytoexist" not defined in [acl.groups]
1741 1748 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1742 1749 abort: group 'unlikelytoexist' is undefined
@@ -1,287 +1,288 b''
1 1 $ hg init basic
2 2 $ cd basic
3 3
4 4 should complain
5 5
6 6 $ hg backout
7 7 abort: please specify a revision to backout
8 8 [255]
9 9 $ hg backout -r 0 0
10 10 abort: please specify just one revision
11 11 [255]
12 12
13 13 basic operation
14 14
15 15 $ echo a > a
16 16 $ hg commit -d '0 0' -A -m a
17 17 adding a
18 18 $ echo b >> a
19 19 $ hg commit -d '1 0' -m b
20 20
21 21 $ hg backout -d '2 0' tip --tool=true
22 22 reverting a
23 23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
24 24 $ cat a
25 25 a
26 26
27 27 file that was removed is recreated
28 28
29 29 $ cd ..
30 30 $ hg init remove
31 31 $ cd remove
32 32
33 33 $ echo content > a
34 34 $ hg commit -d '0 0' -A -m a
35 35 adding a
36 36
37 37 $ hg rm a
38 38 $ hg commit -d '1 0' -m b
39 39
40 40 $ hg backout -d '2 0' tip --tool=true
41 41 adding a
42 42 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
43 43 $ cat a
44 44 content
45 45
46 46 backout of backout is as if nothing happened
47 47
48 48 $ hg backout -d '3 0' --merge tip --tool=true
49 49 removing a
50 50 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
51 51 $ cat a 2>/dev/null || echo cat: a: No such file or directory
52 52 cat: a: No such file or directory
53 53
54 54 across branch
55 55
56 56 $ cd ..
57 57 $ hg init branch
58 58 $ cd branch
59 59 $ echo a > a
60 60 $ hg ci -Am0
61 61 adding a
62 62 $ echo b > b
63 63 $ hg ci -Am1
64 64 adding b
65 65 $ hg co -C 0
66 66 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
67 67
68 68 should fail
69 69
70 70 $ hg backout 1
71 71 abort: cannot backout change on a different branch
72 72 [255]
73 73 $ echo c > c
74 74 $ hg ci -Am2
75 75 adding c
76 76 created new head
77 77
78 78 should fail
79 79
80 80 $ hg backout 1
81 81 abort: cannot backout change on a different branch
82 82 [255]
83 83
84 84 backout with merge
85 85
86 86 $ cd ..
87 87 $ hg init merge
88 88 $ cd merge
89 89
90 90 $ echo line 1 > a
91 91 $ echo line 2 >> a
92 92 $ hg commit -d '0 0' -A -m a
93 93 adding a
94 94
95 95 remove line 1
96 96
97 97 $ echo line 2 > a
98 98 $ hg commit -d '1 0' -m b
99 99
100 100 $ echo line 3 >> a
101 101 $ hg commit -d '2 0' -m c
102 102
103 103 $ hg backout --merge -d '3 0' 1 --tool=true
104 104 reverting a
105 105 created new head
106 106 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
107 107 merging with changeset 3:26b8ccb9ad91
108 108 merging a
109 109 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
110 110 (branch merge, don't forget to commit)
111 111 $ hg commit -d '4 0' -m d
112 112
113 113 check line 1 is back
114 114
115 115 $ cat a
116 116 line 1
117 117 line 2
118 118 line 3
119 119
120 120 backout should not back out subsequent changesets
121 121
122 122 $ hg init onecs
123 123 $ cd onecs
124 124 $ echo 1 > a
125 125 $ hg commit -d '0 0' -A -m a
126 126 adding a
127 127 $ echo 2 >> a
128 128 $ hg commit -d '1 0' -m b
129 129 $ echo 1 > b
130 130 $ hg commit -d '2 0' -A -m c
131 131 adding b
132 132
133 133 without --merge
134 134 $ hg backout -d '3 0' 1 --tool=true
135 135 reverting a
136 136 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137 $ hg locate b
138 138 b
139 139 $ hg update -C tip
140 140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 141 $ hg locate b
142 142 b
143 143
144 144 with --merge
145 145 $ hg backout --merge -d '3 0' 1 --tool=true
146 146 reverting a
147 147 created new head
148 148 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
149 149 merging with changeset 3:3202beb76721
150 150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 (branch merge, don't forget to commit)
152 152 $ hg locate b
153 153 b
154 154 $ hg update -C tip
155 155 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
156 156 $ hg locate b
157 157 [1]
158 158
159 159 $ cd ..
160 160 $ hg init m
161 161 $ cd m
162 162 $ echo a > a
163 163 $ hg commit -d '0 0' -A -m a
164 164 adding a
165 165 $ echo b > b
166 166 $ hg commit -d '1 0' -A -m b
167 167 adding b
168 168 $ echo c > c
169 169 $ hg commit -d '2 0' -A -m b
170 170 adding c
171 171 $ hg update 1
172 172 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
173 173 $ echo d > d
174 174 $ hg commit -d '3 0' -A -m c
175 175 adding d
176 176 created new head
177 177 $ hg merge 2
178 178 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 179 (branch merge, don't forget to commit)
180 180 $ hg commit -d '4 0' -A -m d
181 181
182 182 backout of merge should fail
183 183
184 184 $ hg backout 4
185 185 abort: cannot backout a merge changeset without --parent
186 186 [255]
187 187
188 188 backout of merge with bad parent should fail
189 189
190 190 $ hg backout --parent 0 4
191 191 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
192 192 [255]
193 193
194 194 backout of non-merge with parent should fail
195 195
196 196 $ hg backout --parent 0 3
197 197 abort: cannot use --parent on non-merge changeset
198 198 [255]
199 199
200 200 backout with valid parent should be ok
201 201
202 202 $ hg backout -d '5 0' --parent 2 4 --tool=true
203 203 removing d
204 204 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
205 205
206 206 $ hg rollback
207 rolling back to revision 4 (undo commit)
207 repository tip rolled back to revision 4 (undo commit)
208 working directory now based on revision 4
208 209 $ hg update -C
209 210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 211
211 212 $ hg backout -d '6 0' --parent 3 4 --tool=true
212 213 removing c
213 214 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
214 215
215 216 $ cd ..
216 217
217 218 named branches
218 219
219 220 $ hg init named_branches
220 221 $ cd named_branches
221 222
222 223 $ echo default > default
223 224 $ hg ci -d '0 0' -Am default
224 225 adding default
225 226 $ hg branch branch1
226 227 marked working directory as branch branch1
227 228 $ echo branch1 > file1
228 229 $ hg ci -d '1 0' -Am file1
229 230 adding file1
230 231 $ hg branch branch2
231 232 marked working directory as branch branch2
232 233 $ echo branch2 > file2
233 234 $ hg ci -d '2 0' -Am file2
234 235 adding file2
235 236
236 237 without --merge
237 238 $ hg backout -r 1 --tool=true
238 239 removing file1
239 240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 241 $ hg branch
241 242 branch2
242 243 $ hg status -A
243 244 R file1
244 245 C default
245 246 C file2
246 247
247 248 with --merge
248 249 $ hg update -qC
249 250 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
250 251 removing file1
251 252 created new head
252 253 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
253 254 merging with changeset 3:d4e8f6db59fb
254 255 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
255 256 (branch merge, don't forget to commit)
256 257 $ hg update -q -C 2
257 258
258 259 on branch2 with branch1 not merged, so file1 should still exist:
259 260
260 261 $ hg id
261 262 45bbcd363bf0 (branch2)
262 263 $ hg st -A
263 264 C default
264 265 C file1
265 266 C file2
266 267
267 268 on branch2 with branch1 merged, so file1 should be gone:
268 269
269 270 $ hg merge
270 271 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
271 272 (branch merge, don't forget to commit)
272 273 $ hg ci -d '4 0' -m 'merge backout of branch1'
273 274 $ hg id
274 275 22149cdde76d (branch2) tip
275 276 $ hg st -A
276 277 C default
277 278 C file2
278 279
279 280 on branch1, so no file1 and file2:
280 281
281 282 $ hg co -C branch1
282 283 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
283 284 $ hg id
284 285 bf1602f437f3 (branch1)
285 286 $ hg st -A
286 287 C default
287 288 C file1
@@ -1,102 +1,103 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "bookmarks=" >> $HGRCPATH
3 3 $ echo "mq=" >> $HGRCPATH
4 4
5 5 $ hg init
6 6
7 7 $ echo qqq>qqq.txt
8 8
9 9 rollback dry run without rollback information
10 10
11 11 $ hg rollback
12 12 no rollback information available
13 13 [1]
14 14
15 15 add file
16 16
17 17 $ hg add
18 18 adding qqq.txt
19 19
20 20 commit first revision
21 21
22 22 $ hg ci -m 1
23 23
24 24 set bookmark
25 25
26 26 $ hg book test
27 27
28 28 $ echo www>>qqq.txt
29 29
30 30 commit second revision
31 31
32 32 $ hg ci -m 2
33 33
34 34 set bookmark
35 35
36 36 $ hg book test2
37 37
38 38 update to -2
39 39
40 40 $ hg update -r -2
41 41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42
43 43 $ echo eee>>qqq.txt
44 44
45 45 commit new head
46 46
47 47 $ hg ci -m 3
48 48 created new head
49 49
50 50 bookmarks updated?
51 51
52 52 $ hg book
53 53 test 1:25e1ee7a0081
54 54 test2 1:25e1ee7a0081
55 55
56 56 strip to revision 1
57 57
58 58 $ hg strip 1
59 59 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
60 60
61 61 list bookmarks
62 62
63 63 $ hg book
64 64 test 1:8cf31af87a2b
65 65 * test2 1:8cf31af87a2b
66 66
67 67 immediate rollback and reentrancy issue
68 68
69 69 $ echo "mq=!" >> $HGRCPATH
70 70 $ hg init repo
71 71 $ cd repo
72 72 $ echo a > a
73 73 $ hg ci -Am adda
74 74 adding a
75 75 $ echo b > b
76 76 $ hg ci -Am addb
77 77 adding b
78 78 $ hg bookmarks markb
79 79 $ hg rollback
80 rolling back to revision 0 (undo commit)
80 repository tip rolled back to revision 0 (undo commit)
81 working directory now based on revision 0
81 82
82 83 are you there?
83 84
84 85 $ hg bookmarks
85 86 no bookmarks set
86 87
87 88 can you be added again?
88 89
89 90 $ hg bookmarks markb
90 91 $ hg bookmarks
91 92 * markb 0:07f494440405
92 93
93 94 rollback dry run with rollback information
94 95
95 96 $ hg rollback -n
96 97 no rollback information available
97 98 [1]
98 99 $ hg bookmarks
99 100 * markb 0:07f494440405
100 101
101 102 $ cd ..
102 103
@@ -1,372 +1,376 b''
1 1 $ hg init test
2 2 $ cd test
3 3 $ echo "0" >> afile
4 4 $ hg add afile
5 5 $ hg commit -m "0.0"
6 6 $ echo "1" >> afile
7 7 $ hg commit -m "0.1"
8 8 $ echo "2" >> afile
9 9 $ hg commit -m "0.2"
10 10 $ echo "3" >> afile
11 11 $ hg commit -m "0.3"
12 12 $ hg update -C 0
13 13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14 $ echo "1" >> afile
15 15 $ hg commit -m "1.1"
16 16 created new head
17 17 $ echo "2" >> afile
18 18 $ hg commit -m "1.2"
19 19 $ echo "a line" > fred
20 20 $ echo "3" >> afile
21 21 $ hg add fred
22 22 $ hg commit -m "1.3"
23 23 $ hg mv afile adifferentfile
24 24 $ hg commit -m "1.3m"
25 25 $ hg update -C 3
26 26 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
27 27 $ hg mv afile anotherfile
28 28 $ hg commit -m "0.3m"
29 29 $ hg debugindex .hg/store/data/afile.i
30 30 rev offset length base linkrev nodeid p1 p2
31 31 0 0 3 0 0 362fef284ce2 000000000000 000000000000
32 32 1 3 5 1 1 125144f7e028 362fef284ce2 000000000000
33 33 2 8 7 2 2 4c982badb186 125144f7e028 000000000000
34 34 3 15 9 3 3 19b1fc555737 4c982badb186 000000000000
35 35 $ hg debugindex .hg/store/data/adifferentfile.i
36 36 rev offset length base linkrev nodeid p1 p2
37 37 0 0 75 0 7 2565f3199a74 000000000000 000000000000
38 38 $ hg debugindex .hg/store/data/anotherfile.i
39 39 rev offset length base linkrev nodeid p1 p2
40 40 0 0 75 0 8 2565f3199a74 000000000000 000000000000
41 41 $ hg debugindex .hg/store/data/fred.i
42 42 rev offset length base linkrev nodeid p1 p2
43 43 0 0 8 0 6 12ab3bcc5ea4 000000000000 000000000000
44 44 $ hg debugindex .hg/store/00manifest.i
45 45 rev offset length base linkrev nodeid p1 p2
46 46 0 0 48 0 0 43eadb1d2d06 000000000000 000000000000
47 47 1 48 48 1 1 8b89697eba2c 43eadb1d2d06 000000000000
48 48 2 96 48 2 2 626a32663c2f 8b89697eba2c 000000000000
49 49 3 144 48 3 3 f54c32f13478 626a32663c2f 000000000000
50 50 4 192 58 3 6 de68e904d169 626a32663c2f 000000000000
51 51 5 250 68 3 7 09bb521d218d de68e904d169 000000000000
52 52 6 318 54 6 8 1fde233dfb0f f54c32f13478 000000000000
53 53 $ hg verify
54 54 checking changesets
55 55 checking manifests
56 56 crosschecking files in changesets and manifests
57 57 checking files
58 58 4 files, 9 changesets, 7 total revisions
59 59 $ cd ..
60 60 $ for i in 0 1 2 3 4 5 6 7 8; do
61 61 > mkdir test-"$i"
62 62 > hg --cwd test-"$i" init
63 63 > hg -R test bundle -r "$i" test-"$i".hg test-"$i"
64 64 > cd test-"$i"
65 65 > hg unbundle ../test-"$i".hg
66 66 > hg verify
67 67 > hg tip -q
68 68 > cd ..
69 69 > done
70 70 searching for changes
71 71 1 changesets found
72 72 adding changesets
73 73 adding manifests
74 74 adding file changes
75 75 added 1 changesets with 1 changes to 1 files
76 76 (run 'hg update' to get a working copy)
77 77 checking changesets
78 78 checking manifests
79 79 crosschecking files in changesets and manifests
80 80 checking files
81 81 1 files, 1 changesets, 1 total revisions
82 82 0:f9ee2f85a263
83 83 searching for changes
84 84 2 changesets found
85 85 adding changesets
86 86 adding manifests
87 87 adding file changes
88 88 added 2 changesets with 2 changes to 1 files
89 89 (run 'hg update' to get a working copy)
90 90 checking changesets
91 91 checking manifests
92 92 crosschecking files in changesets and manifests
93 93 checking files
94 94 1 files, 2 changesets, 2 total revisions
95 95 1:34c2bf6b0626
96 96 searching for changes
97 97 3 changesets found
98 98 adding changesets
99 99 adding manifests
100 100 adding file changes
101 101 added 3 changesets with 3 changes to 1 files
102 102 (run 'hg update' to get a working copy)
103 103 checking changesets
104 104 checking manifests
105 105 crosschecking files in changesets and manifests
106 106 checking files
107 107 1 files, 3 changesets, 3 total revisions
108 108 2:e38ba6f5b7e0
109 109 searching for changes
110 110 4 changesets found
111 111 adding changesets
112 112 adding manifests
113 113 adding file changes
114 114 added 4 changesets with 4 changes to 1 files
115 115 (run 'hg update' to get a working copy)
116 116 checking changesets
117 117 checking manifests
118 118 crosschecking files in changesets and manifests
119 119 checking files
120 120 1 files, 4 changesets, 4 total revisions
121 121 3:eebf5a27f8ca
122 122 searching for changes
123 123 2 changesets found
124 124 adding changesets
125 125 adding manifests
126 126 adding file changes
127 127 added 2 changesets with 2 changes to 1 files
128 128 (run 'hg update' to get a working copy)
129 129 checking changesets
130 130 checking manifests
131 131 crosschecking files in changesets and manifests
132 132 checking files
133 133 1 files, 2 changesets, 2 total revisions
134 134 1:095197eb4973
135 135 searching for changes
136 136 3 changesets found
137 137 adding changesets
138 138 adding manifests
139 139 adding file changes
140 140 added 3 changesets with 3 changes to 1 files
141 141 (run 'hg update' to get a working copy)
142 142 checking changesets
143 143 checking manifests
144 144 crosschecking files in changesets and manifests
145 145 checking files
146 146 1 files, 3 changesets, 3 total revisions
147 147 2:1bb50a9436a7
148 148 searching for changes
149 149 4 changesets found
150 150 adding changesets
151 151 adding manifests
152 152 adding file changes
153 153 added 4 changesets with 5 changes to 2 files
154 154 (run 'hg update' to get a working copy)
155 155 checking changesets
156 156 checking manifests
157 157 crosschecking files in changesets and manifests
158 158 checking files
159 159 2 files, 4 changesets, 5 total revisions
160 160 3:7373c1169842
161 161 searching for changes
162 162 5 changesets found
163 163 adding changesets
164 164 adding manifests
165 165 adding file changes
166 166 added 5 changesets with 6 changes to 3 files
167 167 (run 'hg update' to get a working copy)
168 168 checking changesets
169 169 checking manifests
170 170 crosschecking files in changesets and manifests
171 171 checking files
172 172 3 files, 5 changesets, 6 total revisions
173 173 4:a6a34bfa0076
174 174 searching for changes
175 175 5 changesets found
176 176 adding changesets
177 177 adding manifests
178 178 adding file changes
179 179 added 5 changesets with 5 changes to 2 files
180 180 (run 'hg update' to get a working copy)
181 181 checking changesets
182 182 checking manifests
183 183 crosschecking files in changesets and manifests
184 184 checking files
185 185 2 files, 5 changesets, 5 total revisions
186 186 4:aa35859c02ea
187 187 $ cd test-8
188 188 $ hg pull ../test-7
189 189 pulling from ../test-7
190 190 searching for changes
191 191 adding changesets
192 192 adding manifests
193 193 adding file changes
194 194 added 4 changesets with 2 changes to 3 files (+1 heads)
195 195 (run 'hg heads' to see heads, 'hg merge' to merge)
196 196 $ hg verify
197 197 checking changesets
198 198 checking manifests
199 199 crosschecking files in changesets and manifests
200 200 checking files
201 201 4 files, 9 changesets, 7 total revisions
202 202 $ hg rollback
203 rolling back to revision 4 (undo pull)
203 repository tip rolled back to revision 4 (undo pull)
204 working directory now based on revision -1
204 205 $ cd ..
205 206
206 207 should fail
207 208
208 209 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3
209 210 abort: --base is incompatible with specifying a destination
210 211 [255]
211 212 $ hg -R test bundle -r tip test-bundle-branch1.hg
212 213 abort: repository default-push not found!
213 214 [255]
214 215
215 216 $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg
216 217 2 changesets found
217 218 $ hg -R test bundle --base 2 -r 7 test-bundle-branch2.hg
218 219 4 changesets found
219 220 $ hg -R test bundle --base 2 test-bundle-all.hg
220 221 6 changesets found
221 222 $ hg -R test bundle --base 3 -r tip test-bundle-should-fail.hg
222 223 1 changesets found
223 224
224 225 empty bundle
225 226
226 227 $ hg -R test bundle --base 7 --base 8 test-bundle-empty.hg
227 228 no changes found
228 229 [1]
229 230
230 231 issue76 msg2163
231 232
232 233 $ hg -R test bundle --base 3 -r 3 -r 3 test-bundle-cset-3.hg
233 234 1 changesets found
234 235
235 236 Issue1910: 'hg bundle --base $head' does not exclude $head from
236 237 result
237 238
238 239 $ hg -R test bundle --base 7 test-bundle-cset-7.hg
239 240 4 changesets found
240 241
241 242 $ hg clone test-2 test-9
242 243 updating to branch default
243 244 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
244 245 $ cd test-9
245 246
246 247 revision 2
247 248
248 249 $ hg tip -q
249 250 2:e38ba6f5b7e0
250 251 $ hg unbundle ../test-bundle-should-fail.hg
251 252 adding changesets
252 253 transaction abort!
253 254 rollback completed
254 255 abort: 00changelog.i@eebf5a27f8ca: unknown parent!
255 256 [255]
256 257
257 258 revision 2
258 259
259 260 $ hg tip -q
260 261 2:e38ba6f5b7e0
261 262 $ hg unbundle ../test-bundle-all.hg
262 263 adding changesets
263 264 adding manifests
264 265 adding file changes
265 266 added 6 changesets with 4 changes to 4 files (+1 heads)
266 267 (run 'hg heads' to see heads, 'hg merge' to merge)
267 268
268 269 revision 8
269 270
270 271 $ hg tip -q
271 272 8:aa35859c02ea
272 273 $ hg verify
273 274 checking changesets
274 275 checking manifests
275 276 crosschecking files in changesets and manifests
276 277 checking files
277 278 4 files, 9 changesets, 7 total revisions
278 279 $ hg rollback
279 rolling back to revision 2 (undo unbundle)
280 repository tip rolled back to revision 2 (undo unbundle)
281 working directory now based on revision 2
280 282
281 283 revision 2
282 284
283 285 $ hg tip -q
284 286 2:e38ba6f5b7e0
285 287 $ hg unbundle ../test-bundle-branch1.hg
286 288 adding changesets
287 289 adding manifests
288 290 adding file changes
289 291 added 2 changesets with 2 changes to 2 files
290 292 (run 'hg update' to get a working copy)
291 293
292 294 revision 4
293 295
294 296 $ hg tip -q
295 297 4:aa35859c02ea
296 298 $ hg verify
297 299 checking changesets
298 300 checking manifests
299 301 crosschecking files in changesets and manifests
300 302 checking files
301 303 2 files, 5 changesets, 5 total revisions
302 304 $ hg rollback
303 rolling back to revision 2 (undo unbundle)
305 repository tip rolled back to revision 2 (undo unbundle)
306 working directory now based on revision 2
304 307 $ hg unbundle ../test-bundle-branch2.hg
305 308 adding changesets
306 309 adding manifests
307 310 adding file changes
308 311 added 4 changesets with 3 changes to 3 files (+1 heads)
309 312 (run 'hg heads' to see heads, 'hg merge' to merge)
310 313
311 314 revision 6
312 315
313 316 $ hg tip -q
314 317 6:a6a34bfa0076
315 318 $ hg verify
316 319 checking changesets
317 320 checking manifests
318 321 crosschecking files in changesets and manifests
319 322 checking files
320 323 3 files, 7 changesets, 6 total revisions
321 324 $ hg rollback
322 rolling back to revision 2 (undo unbundle)
325 repository tip rolled back to revision 2 (undo unbundle)
326 working directory now based on revision 2
323 327 $ hg unbundle ../test-bundle-cset-7.hg
324 328 adding changesets
325 329 adding manifests
326 330 adding file changes
327 331 added 2 changesets with 2 changes to 2 files
328 332 (run 'hg update' to get a working copy)
329 333
330 334 revision 4
331 335
332 336 $ hg tip -q
333 337 4:aa35859c02ea
334 338 $ hg verify
335 339 checking changesets
336 340 checking manifests
337 341 crosschecking files in changesets and manifests
338 342 checking files
339 343 2 files, 5 changesets, 5 total revisions
340 344
341 345 $ cd ../test
342 346 $ hg merge 7
343 347 note: possible conflict - afile was renamed multiple times to:
344 348 anotherfile
345 349 adifferentfile
346 350 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 351 (branch merge, don't forget to commit)
348 352 $ hg ci -m merge
349 353 $ cd ..
350 354 $ hg -R test bundle --base 2 test-bundle-head.hg
351 355 7 changesets found
352 356 $ hg clone test-2 test-10
353 357 updating to branch default
354 358 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
355 359 $ cd test-10
356 360 $ hg unbundle ../test-bundle-head.hg
357 361 adding changesets
358 362 adding manifests
359 363 adding file changes
360 364 added 7 changesets with 4 changes to 4 files
361 365 (run 'hg update' to get a working copy)
362 366
363 367 revision 9
364 368
365 369 $ hg tip -q
366 370 9:905597b0d5d4
367 371 $ hg verify
368 372 checking changesets
369 373 checking manifests
370 374 crosschecking files in changesets and manifests
371 375 checking files
372 376 4 files, 10 changesets, 7 total revisions
@@ -1,573 +1,576 b''
1 1 Setting up test
2 2
3 3 $ hg init test
4 4 $ cd test
5 5 $ echo 0 > afile
6 6 $ hg add afile
7 7 $ hg commit -m "0.0"
8 8 $ echo 1 >> afile
9 9 $ hg commit -m "0.1"
10 10 $ echo 2 >> afile
11 11 $ hg commit -m "0.2"
12 12 $ echo 3 >> afile
13 13 $ hg commit -m "0.3"
14 14 $ hg update -C 0
15 15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 16 $ echo 1 >> afile
17 17 $ hg commit -m "1.1"
18 18 created new head
19 19 $ echo 2 >> afile
20 20 $ hg commit -m "1.2"
21 21 $ echo "a line" > fred
22 22 $ echo 3 >> afile
23 23 $ hg add fred
24 24 $ hg commit -m "1.3"
25 25 $ hg mv afile adifferentfile
26 26 $ hg commit -m "1.3m"
27 27 $ hg update -C 3
28 28 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
29 29 $ hg mv afile anotherfile
30 30 $ hg commit -m "0.3m"
31 31 $ hg verify
32 32 checking changesets
33 33 checking manifests
34 34 crosschecking files in changesets and manifests
35 35 checking files
36 36 4 files, 9 changesets, 7 total revisions
37 37 $ cd ..
38 38 $ hg init empty
39 39
40 40 Bundle --all
41 41
42 42 $ hg -R test bundle --all all.hg
43 43 9 changesets found
44 44
45 45 Bundle test to full.hg
46 46
47 47 $ hg -R test bundle full.hg empty
48 48 searching for changes
49 49 9 changesets found
50 50
51 51 Unbundle full.hg in test
52 52
53 53 $ hg -R test unbundle full.hg
54 54 adding changesets
55 55 adding manifests
56 56 adding file changes
57 57 added 0 changesets with 0 changes to 4 files
58 58 (run 'hg update' to get a working copy)
59 59
60 60 Verify empty
61 61
62 62 $ hg -R empty heads
63 63 [1]
64 64 $ hg -R empty verify
65 65 checking changesets
66 66 checking manifests
67 67 crosschecking files in changesets and manifests
68 68 checking files
69 69 0 files, 0 changesets, 0 total revisions
70 70
71 71 Pull full.hg into test (using --cwd)
72 72
73 73 $ hg --cwd test pull ../full.hg
74 74 pulling from ../full.hg
75 75 searching for changes
76 76 no changes found
77 77
78 78 Pull full.hg into empty (using --cwd)
79 79
80 80 $ hg --cwd empty pull ../full.hg
81 81 pulling from ../full.hg
82 82 requesting all changes
83 83 adding changesets
84 84 adding manifests
85 85 adding file changes
86 86 added 9 changesets with 7 changes to 4 files (+1 heads)
87 87 (run 'hg heads' to see heads, 'hg merge' to merge)
88 88
89 89 Rollback empty
90 90
91 91 $ hg -R empty rollback
92 rolling back to revision -1 (undo pull)
92 repository tip rolled back to revision -1 (undo pull)
93 working directory now based on revision -1
93 94
94 95 Pull full.hg into empty again (using --cwd)
95 96
96 97 $ hg --cwd empty pull ../full.hg
97 98 pulling from ../full.hg
98 99 requesting all changes
99 100 adding changesets
100 101 adding manifests
101 102 adding file changes
102 103 added 9 changesets with 7 changes to 4 files (+1 heads)
103 104 (run 'hg heads' to see heads, 'hg merge' to merge)
104 105
105 106 Pull full.hg into test (using -R)
106 107
107 108 $ hg -R test pull full.hg
108 109 pulling from full.hg
109 110 searching for changes
110 111 no changes found
111 112
112 113 Pull full.hg into empty (using -R)
113 114
114 115 $ hg -R empty pull full.hg
115 116 pulling from full.hg
116 117 searching for changes
117 118 no changes found
118 119
119 120 Rollback empty
120 121
121 122 $ hg -R empty rollback
122 rolling back to revision -1 (undo pull)
123 repository tip rolled back to revision -1 (undo pull)
124 working directory now based on revision -1
123 125
124 126 Pull full.hg into empty again (using -R)
125 127
126 128 $ hg -R empty pull full.hg
127 129 pulling from full.hg
128 130 requesting all changes
129 131 adding changesets
130 132 adding manifests
131 133 adding file changes
132 134 added 9 changesets with 7 changes to 4 files (+1 heads)
133 135 (run 'hg heads' to see heads, 'hg merge' to merge)
134 136
135 137 Log -R full.hg in fresh empty
136 138
137 139 $ rm -r empty
138 140 $ hg init empty
139 141 $ cd empty
140 142 $ hg -R bundle://../full.hg log
141 143 changeset: 8:aa35859c02ea
142 144 tag: tip
143 145 parent: 3:eebf5a27f8ca
144 146 user: test
145 147 date: Thu Jan 01 00:00:00 1970 +0000
146 148 summary: 0.3m
147 149
148 150 changeset: 7:a6a34bfa0076
149 151 user: test
150 152 date: Thu Jan 01 00:00:00 1970 +0000
151 153 summary: 1.3m
152 154
153 155 changeset: 6:7373c1169842
154 156 user: test
155 157 date: Thu Jan 01 00:00:00 1970 +0000
156 158 summary: 1.3
157 159
158 160 changeset: 5:1bb50a9436a7
159 161 user: test
160 162 date: Thu Jan 01 00:00:00 1970 +0000
161 163 summary: 1.2
162 164
163 165 changeset: 4:095197eb4973
164 166 parent: 0:f9ee2f85a263
165 167 user: test
166 168 date: Thu Jan 01 00:00:00 1970 +0000
167 169 summary: 1.1
168 170
169 171 changeset: 3:eebf5a27f8ca
170 172 user: test
171 173 date: Thu Jan 01 00:00:00 1970 +0000
172 174 summary: 0.3
173 175
174 176 changeset: 2:e38ba6f5b7e0
175 177 user: test
176 178 date: Thu Jan 01 00:00:00 1970 +0000
177 179 summary: 0.2
178 180
179 181 changeset: 1:34c2bf6b0626
180 182 user: test
181 183 date: Thu Jan 01 00:00:00 1970 +0000
182 184 summary: 0.1
183 185
184 186 changeset: 0:f9ee2f85a263
185 187 user: test
186 188 date: Thu Jan 01 00:00:00 1970 +0000
187 189 summary: 0.0
188 190
189 191 Make sure bundlerepo doesn't leak tempfiles (issue2491)
190 192
191 193 $ ls .hg
192 194 00changelog.i
193 195 cache
194 196 requires
195 197 store
196 198
197 199 Pull ../full.hg into empty (with hook)
198 200
199 201 $ echo '[hooks]' >> .hg/hgrc
200 202 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
201 203
202 204 doesn't work (yet ?)
203 205
204 206 hg -R bundle://../full.hg verify
205 207
206 208 $ hg pull bundle://../full.hg
207 209 pulling from bundle://../full.hg
208 210 requesting all changes
209 211 adding changesets
210 212 adding manifests
211 213 adding file changes
212 214 added 9 changesets with 7 changes to 4 files (+1 heads)
213 215 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:../full.hg
214 216 (run 'hg heads' to see heads, 'hg merge' to merge)
215 217
216 218 Rollback empty
217 219
218 220 $ hg rollback
219 rolling back to revision -1 (undo pull)
221 repository tip rolled back to revision -1 (undo pull)
222 working directory now based on revision -1
220 223 $ cd ..
221 224
222 225 Log -R bundle:empty+full.hg
223 226
224 227 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
225 228 8 7 6 5 4 3 2 1 0
226 229
227 230 Pull full.hg into empty again (using -R; with hook)
228 231
229 232 $ hg -R empty pull full.hg
230 233 pulling from full.hg
231 234 requesting all changes
232 235 adding changesets
233 236 adding manifests
234 237 adding file changes
235 238 added 9 changesets with 7 changes to 4 files (+1 heads)
236 239 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
237 240 (run 'hg heads' to see heads, 'hg merge' to merge)
238 241
239 242 Create partial clones
240 243
241 244 $ rm -r empty
242 245 $ hg init empty
243 246 $ hg clone -r 3 test partial
244 247 adding changesets
245 248 adding manifests
246 249 adding file changes
247 250 added 4 changesets with 4 changes to 1 files
248 251 updating to branch default
249 252 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
250 253 $ hg clone partial partial2
251 254 updating to branch default
252 255 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 256 $ cd partial
254 257
255 258 Log -R full.hg in partial
256 259
257 260 $ hg -R bundle://../full.hg log
258 261 changeset: 8:aa35859c02ea
259 262 tag: tip
260 263 parent: 3:eebf5a27f8ca
261 264 user: test
262 265 date: Thu Jan 01 00:00:00 1970 +0000
263 266 summary: 0.3m
264 267
265 268 changeset: 7:a6a34bfa0076
266 269 user: test
267 270 date: Thu Jan 01 00:00:00 1970 +0000
268 271 summary: 1.3m
269 272
270 273 changeset: 6:7373c1169842
271 274 user: test
272 275 date: Thu Jan 01 00:00:00 1970 +0000
273 276 summary: 1.3
274 277
275 278 changeset: 5:1bb50a9436a7
276 279 user: test
277 280 date: Thu Jan 01 00:00:00 1970 +0000
278 281 summary: 1.2
279 282
280 283 changeset: 4:095197eb4973
281 284 parent: 0:f9ee2f85a263
282 285 user: test
283 286 date: Thu Jan 01 00:00:00 1970 +0000
284 287 summary: 1.1
285 288
286 289 changeset: 3:eebf5a27f8ca
287 290 user: test
288 291 date: Thu Jan 01 00:00:00 1970 +0000
289 292 summary: 0.3
290 293
291 294 changeset: 2:e38ba6f5b7e0
292 295 user: test
293 296 date: Thu Jan 01 00:00:00 1970 +0000
294 297 summary: 0.2
295 298
296 299 changeset: 1:34c2bf6b0626
297 300 user: test
298 301 date: Thu Jan 01 00:00:00 1970 +0000
299 302 summary: 0.1
300 303
301 304 changeset: 0:f9ee2f85a263
302 305 user: test
303 306 date: Thu Jan 01 00:00:00 1970 +0000
304 307 summary: 0.0
305 308
306 309
307 310 Incoming full.hg in partial
308 311
309 312 $ hg incoming bundle://../full.hg
310 313 comparing with bundle://../full.hg
311 314 searching for changes
312 315 changeset: 4:095197eb4973
313 316 parent: 0:f9ee2f85a263
314 317 user: test
315 318 date: Thu Jan 01 00:00:00 1970 +0000
316 319 summary: 1.1
317 320
318 321 changeset: 5:1bb50a9436a7
319 322 user: test
320 323 date: Thu Jan 01 00:00:00 1970 +0000
321 324 summary: 1.2
322 325
323 326 changeset: 6:7373c1169842
324 327 user: test
325 328 date: Thu Jan 01 00:00:00 1970 +0000
326 329 summary: 1.3
327 330
328 331 changeset: 7:a6a34bfa0076
329 332 user: test
330 333 date: Thu Jan 01 00:00:00 1970 +0000
331 334 summary: 1.3m
332 335
333 336 changeset: 8:aa35859c02ea
334 337 tag: tip
335 338 parent: 3:eebf5a27f8ca
336 339 user: test
337 340 date: Thu Jan 01 00:00:00 1970 +0000
338 341 summary: 0.3m
339 342
340 343
341 344 Outgoing -R full.hg vs partial2 in partial
342 345
343 346 $ hg -R bundle://../full.hg outgoing ../partial2
344 347 comparing with ../partial2
345 348 searching for changes
346 349 changeset: 4:095197eb4973
347 350 parent: 0:f9ee2f85a263
348 351 user: test
349 352 date: Thu Jan 01 00:00:00 1970 +0000
350 353 summary: 1.1
351 354
352 355 changeset: 5:1bb50a9436a7
353 356 user: test
354 357 date: Thu Jan 01 00:00:00 1970 +0000
355 358 summary: 1.2
356 359
357 360 changeset: 6:7373c1169842
358 361 user: test
359 362 date: Thu Jan 01 00:00:00 1970 +0000
360 363 summary: 1.3
361 364
362 365 changeset: 7:a6a34bfa0076
363 366 user: test
364 367 date: Thu Jan 01 00:00:00 1970 +0000
365 368 summary: 1.3m
366 369
367 370 changeset: 8:aa35859c02ea
368 371 tag: tip
369 372 parent: 3:eebf5a27f8ca
370 373 user: test
371 374 date: Thu Jan 01 00:00:00 1970 +0000
372 375 summary: 0.3m
373 376
374 377
375 378 Outgoing -R does-not-exist.hg vs partial2 in partial
376 379
377 380 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
378 381 abort: No such file or directory: ../does-not-exist.hg
379 382 [255]
380 383 $ cd ..
381 384
382 385 Direct clone from bundle (all-history)
383 386
384 387 $ hg clone full.hg full-clone
385 388 requesting all changes
386 389 adding changesets
387 390 adding manifests
388 391 adding file changes
389 392 added 9 changesets with 7 changes to 4 files (+1 heads)
390 393 updating to branch default
391 394 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 395 $ hg -R full-clone heads
393 396 changeset: 8:aa35859c02ea
394 397 tag: tip
395 398 parent: 3:eebf5a27f8ca
396 399 user: test
397 400 date: Thu Jan 01 00:00:00 1970 +0000
398 401 summary: 0.3m
399 402
400 403 changeset: 7:a6a34bfa0076
401 404 user: test
402 405 date: Thu Jan 01 00:00:00 1970 +0000
403 406 summary: 1.3m
404 407
405 408 $ rm -r full-clone
406 409
407 410 When cloning from a non-copiable repository into '', do not
408 411 recurse infinitely (issue 2528)
409 412
410 413 $ hg clone full.hg ''
411 414 abort: No such file or directory
412 415 [255]
413 416
414 417 test for http://mercurial.selenic.com/bts/issue216
415 418
416 419 Unbundle incremental bundles into fresh empty in one go
417 420
418 421 $ rm -r empty
419 422 $ hg init empty
420 423 $ hg -R test bundle --base null -r 0 ../0.hg
421 424 1 changesets found
422 425 $ hg -R test bundle --base 0 -r 1 ../1.hg
423 426 1 changesets found
424 427 $ hg -R empty unbundle -u ../0.hg ../1.hg
425 428 adding changesets
426 429 adding manifests
427 430 adding file changes
428 431 added 1 changesets with 1 changes to 1 files
429 432 adding changesets
430 433 adding manifests
431 434 adding file changes
432 435 added 1 changesets with 1 changes to 1 files
433 436 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
434 437
435 438 test for 540d1059c802
436 439
437 440 test for 540d1059c802
438 441
439 442 $ hg init orig
440 443 $ cd orig
441 444 $ echo foo > foo
442 445 $ hg add foo
443 446 $ hg ci -m 'add foo'
444 447
445 448 $ hg clone . ../copy
446 449 updating to branch default
447 450 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 451 $ hg tag foo
449 452
450 453 $ cd ../copy
451 454 $ echo >> foo
452 455 $ hg ci -m 'change foo'
453 456 $ hg bundle ../bundle.hg ../orig
454 457 searching for changes
455 458 1 changesets found
456 459
457 460 $ cd ../orig
458 461 $ hg incoming ../bundle.hg
459 462 comparing with ../bundle.hg
460 463 searching for changes
461 464 changeset: 2:ed1b79f46b9a
462 465 tag: tip
463 466 parent: 0:bbd179dfa0a7
464 467 user: test
465 468 date: Thu Jan 01 00:00:00 1970 +0000
466 469 summary: change foo
467 470
468 471 $ cd ..
469 472
470 473 test for http://mercurial.selenic.com/bts/issue1144
471 474
472 475 test that verify bundle does not traceback
473 476
474 477 partial history bundle, fails w/ unkown parent
475 478
476 479 $ hg -R bundle.hg verify
477 480 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
478 481 [255]
479 482
480 483 full history bundle, refuses to verify non-local repo
481 484
482 485 $ hg -R all.hg verify
483 486 abort: cannot verify bundle or remote repos
484 487 [255]
485 488
486 489 but, regular verify must continue to work
487 490
488 491 $ hg -R orig verify
489 492 checking changesets
490 493 checking manifests
491 494 crosschecking files in changesets and manifests
492 495 checking files
493 496 2 files, 2 changesets, 2 total revisions
494 497
495 498 diff against bundle
496 499
497 500 $ hg init b
498 501 $ cd b
499 502 $ hg -R ../all.hg diff -r tip
500 503 diff -r aa35859c02ea anotherfile
501 504 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
502 505 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
503 506 @@ -1,4 +0,0 @@
504 507 -0
505 508 -1
506 509 -2
507 510 -3
508 511 $ cd ..
509 512
510 513 bundle single branch
511 514
512 515 $ hg init branchy
513 516 $ cd branchy
514 517 $ echo a >a
515 518 $ hg ci -Ama
516 519 adding a
517 520 $ echo b >b
518 521 $ hg ci -Amb
519 522 adding b
520 523 $ echo b1 >b1
521 524 $ hg ci -Amb1
522 525 adding b1
523 526 $ hg up 0
524 527 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
525 528 $ echo c >c
526 529 $ hg ci -Amc
527 530 adding c
528 531 created new head
529 532 $ echo c1 >c1
530 533 $ hg ci -Amc1
531 534 adding c1
532 535 $ hg clone -q .#tip part
533 536
534 537 == bundling via incoming
535 538
536 539 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
537 540 comparing with .
538 541 searching for changes
539 542 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
540 543 5ece8e77363e2b5269e27c66828b72da29e4341a
541 544
542 545 == bundling
543 546
544 547 $ hg bundle bundle.hg part --debug
545 548 searching for changes
546 549 common changesets up to c0025332f9ed
547 550 2 changesets found
548 551 list of changesets:
549 552 d2ae7f538514cd87c17547b0de4cea71fe1af9fb
550 553 5ece8e77363e2b5269e27c66828b72da29e4341a
551 554 bundling: 0 changesets
552 555 bundling: 0 changesets
553 556 bundling: 0 changesets
554 557 bundling: 1 changesets
555 558 bundling: 1 changesets
556 559 bundling: 1 changesets
557 560 bundling: 2 changesets
558 561 bundling: 0/2 manifests (0.00%)
559 562 bundling: 0/2 manifests (0.00%)
560 563 bundling: 0/2 manifests (0.00%)
561 564 bundling: 1/2 manifests (50.00%)
562 565 bundling: 1/2 manifests (50.00%)
563 566 bundling: 1/2 manifests (50.00%)
564 567 bundling: 2/2 manifests (100.00%)
565 568 bundling: b 0/2 files (0.00%)
566 569 bundling: b 0/2 files (0.00%)
567 570 bundling: b 0/2 files (0.00%)
568 571 bundling: b 0/2 files (0.00%)
569 572 bundling: b1 1/2 files (50.00%)
570 573 bundling: b1 1/2 files (50.00%)
571 574 bundling: b1 1/2 files (50.00%)
572 575 bundling: b1 1/2 files (50.00%)
573 576
@@ -1,460 +1,461 b''
1 1
2 2 $ "$TESTDIR/hghave" cvs || exit 80
3 3 $ cvscall()
4 4 > {
5 5 > cvs -f "$@"
6 6 > }
7 7 $ hgcat()
8 8 > {
9 9 > hg --cwd src-hg cat -r tip "$1"
10 10 > }
11 11 $ echo "[extensions]" >> $HGRCPATH
12 12 $ echo "convert = " >> $HGRCPATH
13 13 $ echo "graphlog = " >> $HGRCPATH
14 14 $ cat > cvshooks.py <<EOF
15 15 > def cvslog(ui,repo,hooktype,log):
16 16 > print "%s hook: %d entries"%(hooktype,len(log))
17 17 >
18 18 > def cvschangesets(ui,repo,hooktype,changesets):
19 19 > print "%s hook: %d changesets"%(hooktype,len(changesets))
20 20 > EOF
21 21 $ hookpath=`pwd`
22 22 $ echo "[hooks]" >> $HGRCPATH
23 23 $ echo "cvslog=python:$hookpath/cvshooks.py:cvslog" >> $HGRCPATH
24 24 $ echo "cvschangesets=python:$hookpath/cvshooks.py:cvschangesets" >> $HGRCPATH
25 25
26 26 create cvs repository
27 27
28 28 $ mkdir cvsrepo
29 29 $ cd cvsrepo
30 30 $ CVSROOT=`pwd`
31 31 $ export CVSROOT
32 32 $ CVS_OPTIONS=-f
33 33 $ export CVS_OPTIONS
34 34 $ cd ..
35 35 $ cvscall -q -d "$CVSROOT" init
36 36
37 37 create source directory
38 38
39 39 $ mkdir src-temp
40 40 $ cd src-temp
41 41 $ echo a > a
42 42 $ mkdir b
43 43 $ cd b
44 44 $ echo c > c
45 45 $ cd ..
46 46
47 47 import source directory
48 48
49 49 $ cvscall -q import -m import src INITIAL start
50 50 N src/a
51 51 N src/b/c
52 52
53 53 No conflicts created by this import
54 54
55 55 $ cd ..
56 56
57 57 checkout source directory
58 58
59 59 $ cvscall -q checkout src
60 60 U src/a
61 61 U src/b/c
62 62
63 63 commit a new revision changing b/c
64 64
65 65 $ cd src
66 66 $ sleep 1
67 67 $ echo c >> b/c
68 68 $ cvscall -q commit -mci0 . | grep '<--'
69 69 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
70 70 $ cd ..
71 71
72 72 convert fresh repo
73 73
74 74 $ hg convert src src-hg
75 75 initializing destination src-hg repository
76 76 connecting to $TESTTMP/cvsrepo
77 77 scanning source...
78 78 collecting CVS rlog
79 79 5 log entries
80 80 cvslog hook: 5 entries
81 81 creating changesets
82 82 3 changeset entries
83 83 cvschangesets hook: 3 changesets
84 84 sorting...
85 85 converting...
86 86 2 Initial revision
87 87 1 import
88 88 0 ci0
89 89 updating tags
90 90 $ hgcat a
91 91 a
92 92 $ hgcat b/c
93 93 c
94 94 c
95 95
96 96 convert fresh repo with --filemap
97 97
98 98 $ echo include b/c > filemap
99 99 $ hg convert --filemap filemap src src-filemap
100 100 initializing destination src-filemap repository
101 101 connecting to $TESTTMP/cvsrepo
102 102 scanning source...
103 103 collecting CVS rlog
104 104 5 log entries
105 105 cvslog hook: 5 entries
106 106 creating changesets
107 107 3 changeset entries
108 108 cvschangesets hook: 3 changesets
109 109 sorting...
110 110 converting...
111 111 2 Initial revision
112 112 1 import
113 113 filtering out empty revision
114 rolling back to revision 0 (undo commit)
114 repository tip rolled back to revision 0 (undo commit)
115 working directory now based on revision -1
115 116 0 ci0
116 117 updating tags
117 118 $ hgcat b/c
118 119 c
119 120 c
120 121 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
121 122 2 update tags files: .hgtags
122 123 1 ci0 files: b/c
123 124 0 Initial revision files: b/c
124 125
125 126 convert full repository (issue1649)
126 127
127 128 $ cvscall -q -d "$CVSROOT" checkout -d srcfull "." | grep -v CVSROOT
128 129 U srcfull/src/a
129 130 U srcfull/src/b/c
130 131 $ ls srcfull
131 132 CVS
132 133 CVSROOT
133 134 src
134 135 $ hg convert srcfull srcfull-hg \
135 136 > | grep -v 'log entries' | grep -v 'hook:' \
136 137 > | grep -v '^[0-3] .*' # filter instable changeset order
137 138 initializing destination srcfull-hg repository
138 139 connecting to $TESTTMP/cvsrepo
139 140 scanning source...
140 141 collecting CVS rlog
141 142 creating changesets
142 143 4 changeset entries
143 144 sorting...
144 145 converting...
145 146 updating tags
146 147 $ hg cat -r tip srcfull-hg/src/a
147 148 a
148 149 $ hg cat -r tip srcfull-hg/src/b/c
149 150 c
150 151 c
151 152
152 153 commit new file revisions
153 154
154 155 $ cd src
155 156 $ echo a >> a
156 157 $ echo c >> b/c
157 158 $ cvscall -q commit -mci1 . | grep '<--'
158 159 $TESTTMP/cvsrepo/src/a,v <-- a
159 160 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
160 161 $ cd ..
161 162
162 163 convert again
163 164
164 165 $ hg convert src src-hg
165 166 connecting to $TESTTMP/cvsrepo
166 167 scanning source...
167 168 collecting CVS rlog
168 169 7 log entries
169 170 cvslog hook: 7 entries
170 171 creating changesets
171 172 4 changeset entries
172 173 cvschangesets hook: 4 changesets
173 174 sorting...
174 175 converting...
175 176 0 ci1
176 177 $ hgcat a
177 178 a
178 179 a
179 180 $ hgcat b/c
180 181 c
181 182 c
182 183 c
183 184
184 185 convert again with --filemap
185 186
186 187 $ hg convert --filemap filemap src src-filemap
187 188 connecting to $TESTTMP/cvsrepo
188 189 scanning source...
189 190 collecting CVS rlog
190 191 7 log entries
191 192 cvslog hook: 7 entries
192 193 creating changesets
193 194 4 changeset entries
194 195 cvschangesets hook: 4 changesets
195 196 sorting...
196 197 converting...
197 198 0 ci1
198 199 $ hgcat b/c
199 200 c
200 201 c
201 202 c
202 203 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
203 204 3 ci1 files: b/c
204 205 2 update tags files: .hgtags
205 206 1 ci0 files: b/c
206 207 0 Initial revision files: b/c
207 208
208 209 commit branch
209 210
210 211 $ cd src
211 212 $ cvs -q update -r1.1 b/c
212 213 U b/c
213 214 $ cvs -q tag -b branch
214 215 T a
215 216 T b/c
216 217 $ cvs -q update -r branch > /dev/null
217 218 $ echo d >> b/c
218 219 $ cvs -q commit -mci2 . | grep '<--'
219 220 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
220 221 $ cd ..
221 222
222 223 convert again
223 224
224 225 $ hg convert src src-hg
225 226 connecting to $TESTTMP/cvsrepo
226 227 scanning source...
227 228 collecting CVS rlog
228 229 8 log entries
229 230 cvslog hook: 8 entries
230 231 creating changesets
231 232 5 changeset entries
232 233 cvschangesets hook: 5 changesets
233 234 sorting...
234 235 converting...
235 236 0 ci2
236 237 $ hgcat b/c
237 238 c
238 239 d
239 240
240 241 convert again with --filemap
241 242
242 243 $ hg convert --filemap filemap src src-filemap
243 244 connecting to $TESTTMP/cvsrepo
244 245 scanning source...
245 246 collecting CVS rlog
246 247 8 log entries
247 248 cvslog hook: 8 entries
248 249 creating changesets
249 250 5 changeset entries
250 251 cvschangesets hook: 5 changesets
251 252 sorting...
252 253 converting...
253 254 0 ci2
254 255 $ hgcat b/c
255 256 c
256 257 d
257 258 $ hg -R src-filemap log --template '{rev} {desc} files: {files}\n'
258 259 4 ci2 files: b/c
259 260 3 ci1 files: b/c
260 261 2 update tags files: .hgtags
261 262 1 ci0 files: b/c
262 263 0 Initial revision files: b/c
263 264
264 265 commit a new revision with funny log message
265 266
266 267 $ cd src
267 268 $ sleep 1
268 269 $ echo e >> a
269 270 $ cvscall -q commit -m'funny
270 271 > ----------------------------
271 272 > log message' . | grep '<--' |\
272 273 > sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
273 274 checking in src/a,v
274 275
275 276 commit new file revisions with some fuzz
276 277
277 278 $ sleep 1
278 279 $ echo f >> a
279 280 $ cvscall -q commit -mfuzzy . | grep '<--'
280 281 $TESTTMP/cvsrepo/src/a,v <-- a
281 282 $ sleep 4 # the two changes will be split if fuzz < 4
282 283 $ echo g >> b/c
283 284 $ cvscall -q commit -mfuzzy . | grep '<--'
284 285 $TESTTMP/cvsrepo/src/b/c,v <-- *c (glob)
285 286 $ cd ..
286 287
287 288 convert again
288 289
289 290 $ hg convert --config convert.cvsps.fuzz=2 src src-hg
290 291 connecting to $TESTTMP/cvsrepo
291 292 scanning source...
292 293 collecting CVS rlog
293 294 11 log entries
294 295 cvslog hook: 11 entries
295 296 creating changesets
296 297 8 changeset entries
297 298 cvschangesets hook: 8 changesets
298 299 sorting...
299 300 converting...
300 301 2 funny
301 302 1 fuzzy
302 303 0 fuzzy
303 304 $ hg -R src-hg glog --template '{rev} ({branches}) {desc} files: {files}\n'
304 305 o 8 (branch) fuzzy files: b/c
305 306 |
306 307 o 7 (branch) fuzzy files: a
307 308 |
308 309 o 6 (branch) funny
309 310 | ----------------------------
310 311 | log message files: a
311 312 o 5 (branch) ci2 files: b/c
312 313
313 314 o 4 () ci1 files: a b/c
314 315 |
315 316 o 3 () update tags files: .hgtags
316 317 |
317 318 o 2 () ci0 files: b/c
318 319 |
319 320 | o 1 (INITIAL) import files:
320 321 |/
321 322 o 0 () Initial revision files: a b/c
322 323
323 324
324 325 testing debugcvsps
325 326
326 327 $ cd src
327 328 $ hg debugcvsps --fuzz=2
328 329 collecting CVS rlog
329 330 11 log entries
330 331 cvslog hook: 11 entries
331 332 creating changesets
332 333 10 changeset entries
333 334 cvschangesets hook: 10 changesets
334 335 ---------------------
335 336 PatchSet 1
336 337 Date: * (glob)
337 338 Author: * (glob)
338 339 Branch: HEAD
339 340 Tag: (none)
340 341 Branchpoints: INITIAL
341 342 Log:
342 343 Initial revision
343 344
344 345 Members:
345 346 a:INITIAL->1.1
346 347
347 348 ---------------------
348 349 PatchSet 2
349 350 Date: * (glob)
350 351 Author: * (glob)
351 352 Branch: HEAD
352 353 Tag: (none)
353 354 Branchpoints: INITIAL, branch
354 355 Log:
355 356 Initial revision
356 357
357 358 Members:
358 359 b/c:INITIAL->1.1
359 360
360 361 ---------------------
361 362 PatchSet 3
362 363 Date: * (glob)
363 364 Author: * (glob)
364 365 Branch: INITIAL
365 366 Tag: start
366 367 Log:
367 368 import
368 369
369 370 Members:
370 371 a:1.1->1.1.1.1
371 372 b/c:1.1->1.1.1.1
372 373
373 374 ---------------------
374 375 PatchSet 4
375 376 Date: * (glob)
376 377 Author: * (glob)
377 378 Branch: HEAD
378 379 Tag: (none)
379 380 Log:
380 381 ci0
381 382
382 383 Members:
383 384 b/c:1.1->1.2
384 385
385 386 ---------------------
386 387 PatchSet 5
387 388 Date: * (glob)
388 389 Author: * (glob)
389 390 Branch: HEAD
390 391 Tag: (none)
391 392 Branchpoints: branch
392 393 Log:
393 394 ci1
394 395
395 396 Members:
396 397 a:1.1->1.2
397 398
398 399 ---------------------
399 400 PatchSet 6
400 401 Date: * (glob)
401 402 Author: * (glob)
402 403 Branch: HEAD
403 404 Tag: (none)
404 405 Log:
405 406 ci1
406 407
407 408 Members:
408 409 b/c:1.2->1.3
409 410
410 411 ---------------------
411 412 PatchSet 7
412 413 Date: * (glob)
413 414 Author: * (glob)
414 415 Branch: branch
415 416 Tag: (none)
416 417 Log:
417 418 ci2
418 419
419 420 Members:
420 421 b/c:1.1->1.1.2.1
421 422
422 423 ---------------------
423 424 PatchSet 8
424 425 Date: * (glob)
425 426 Author: * (glob)
426 427 Branch: branch
427 428 Tag: (none)
428 429 Log:
429 430 funny
430 431 ----------------------------
431 432 log message
432 433
433 434 Members:
434 435 a:1.2->1.2.2.1
435 436
436 437 ---------------------
437 438 PatchSet 9
438 439 Date: * (glob)
439 440 Author: * (glob)
440 441 Branch: branch
441 442 Tag: (none)
442 443 Log:
443 444 fuzzy
444 445
445 446 Members:
446 447 a:1.2.2.1->1.2.2.2
447 448
448 449 ---------------------
449 450 PatchSet 10
450 451 Date: * (glob)
451 452 Author: * (glob)
452 453 Branch: branch
453 454 Tag: (none)
454 455 Log:
455 456 fuzzy
456 457
457 458 Members:
458 459 b/c:1.1.2.1->1.1.2.2
459 460
460 461
@@ -1,124 +1,125 b''
1 1 Setup
2 2
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "color=" >> $HGRCPATH
5 5 $ hg init repo
6 6 $ cd repo
7 7 $ cat > a <<EOF
8 8 > c
9 9 > c
10 10 > a
11 11 > a
12 12 > b
13 13 > a
14 14 > a
15 15 > c
16 16 > c
17 17 > EOF
18 18 $ hg ci -Am adda
19 19 adding a
20 20 $ cat > a <<EOF
21 21 > c
22 22 > c
23 23 > a
24 24 > a
25 25 > dd
26 26 > a
27 27 > a
28 28 > c
29 29 > c
30 30 > EOF
31 31
32 32 default context
33 33
34 34 $ hg diff --nodates --color=always
35 35 \x1b[0;1mdiff -r cf9f4ba66af2 a\x1b[0m (esc)
36 36 \x1b[0;31;1m--- a/a\x1b[0m (esc)
37 37 \x1b[0;32;1m+++ b/a\x1b[0m (esc)
38 38 \x1b[0;35m@@ -2,7 +2,7 @@\x1b[0m (esc)
39 39 c
40 40 a
41 41 a
42 42 \x1b[0;31m-b\x1b[0m (esc)
43 43 \x1b[0;32m+dd\x1b[0m (esc)
44 44 a
45 45 a
46 46 c
47 47
48 48 --unified=2
49 49
50 50 $ hg diff --nodates -U 2 --color=always
51 51 \x1b[0;1mdiff -r cf9f4ba66af2 a\x1b[0m (esc)
52 52 \x1b[0;31;1m--- a/a\x1b[0m (esc)
53 53 \x1b[0;32;1m+++ b/a\x1b[0m (esc)
54 54 \x1b[0;35m@@ -3,5 +3,5 @@\x1b[0m (esc)
55 55 a
56 56 a
57 57 \x1b[0;31m-b\x1b[0m (esc)
58 58 \x1b[0;32m+dd\x1b[0m (esc)
59 59 a
60 60 a
61 61
62 62 diffstat
63 63
64 64 $ hg diff --stat --color=always
65 65 a | 2 \x1b[0;32m+\x1b[0m\x1b[0;31m-\x1b[0m (esc)
66 66 1 files changed, 1 insertions(+), 1 deletions(-)
67 67 $ echo "record=" >> $HGRCPATH
68 68 $ echo "[ui]" >> $HGRCPATH
69 69 $ echo "interactive=true" >> $HGRCPATH
70 70 $ echo "[diff]" >> $HGRCPATH
71 71 $ echo "git=True" >> $HGRCPATH
72 72
73 73 record
74 74
75 75 $ chmod 0755 a
76 76 $ hg record --color=always -m moda a <<EOF
77 77 > y
78 78 > y
79 79 > EOF
80 80 \x1b[0;1mdiff --git a/a b/a\x1b[0m (esc)
81 81 \x1b[0;36;1mold mode 100644\x1b[0m (esc)
82 82 \x1b[0;36;1mnew mode 100755\x1b[0m (esc)
83 83 1 hunks, 1 lines changed
84 84 examine changes to 'a'? [Ynsfdaq?]
85 85 \x1b[0;35m@@ -2,7 +2,7 @@\x1b[0m (esc)
86 86 c
87 87 a
88 88 a
89 89 \x1b[0;31m-b\x1b[0m (esc)
90 90 \x1b[0;32m+dd\x1b[0m (esc)
91 91 a
92 92 a
93 93 c
94 94 record this change to 'a'? [Ynsfdaq?]
95 95 $ echo
96 96
97 97 $ echo "[extensions]" >> $HGRCPATH
98 98 $ echo "mq=" >> $HGRCPATH
99 99 $ hg rollback
100 rolling back to revision 0 (undo commit)
100 repository tip rolled back to revision 0 (undo commit)
101 working directory now based on revision 0
101 102
102 103 qrecord
103 104
104 105 $ hg qrecord --color=always -m moda patch <<EOF
105 106 > y
106 107 > y
107 108 > EOF
108 109 \x1b[0;1mdiff --git a/a b/a\x1b[0m (esc)
109 110 \x1b[0;36;1mold mode 100644\x1b[0m (esc)
110 111 \x1b[0;36;1mnew mode 100755\x1b[0m (esc)
111 112 1 hunks, 1 lines changed
112 113 examine changes to 'a'? [Ynsfdaq?]
113 114 \x1b[0;35m@@ -2,7 +2,7 @@\x1b[0m (esc)
114 115 c
115 116 a
116 117 a
117 118 \x1b[0;31m-b\x1b[0m (esc)
118 119 \x1b[0;32m+dd\x1b[0m (esc)
119 120 a
120 121 a
121 122 c
122 123 record this change to 'a'? [Ynsfdaq?]
123 124 $ echo
124 125
@@ -1,481 +1,482 b''
1 1 commit hooks can see env vars
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo "[hooks]" > .hg/hgrc
6 6 $ echo 'commit = unset HG_LOCAL HG_TAG; python "$TESTDIR"/printenv.py commit' >> .hg/hgrc
7 7 $ echo 'commit.b = unset HG_LOCAL HG_TAG; python "$TESTDIR"/printenv.py commit.b' >> .hg/hgrc
8 8 $ echo 'precommit = unset HG_LOCAL HG_NODE HG_TAG; python "$TESTDIR"/printenv.py precommit' >> .hg/hgrc
9 9 $ echo 'pretxncommit = unset HG_LOCAL HG_TAG; python "$TESTDIR"/printenv.py pretxncommit' >> .hg/hgrc
10 10 $ echo 'pretxncommit.tip = hg -q tip' >> .hg/hgrc
11 11 $ echo 'pre-identify = python "$TESTDIR"/printenv.py pre-identify 1' >> .hg/hgrc
12 12 $ echo 'pre-cat = python "$TESTDIR"/printenv.py pre-cat' >> .hg/hgrc
13 13 $ echo 'post-cat = python "$TESTDIR"/printenv.py post-cat' >> .hg/hgrc
14 14 $ echo a > a
15 15 $ hg add a
16 16 $ hg commit -m a
17 17 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
18 18 pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
19 19 0:cb9a9f314b8b
20 20 commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
21 21 commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
22 22
23 23 $ hg clone . ../b
24 24 updating to branch default
25 25 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 26 $ cd ../b
27 27
28 28 changegroup hooks can see env vars
29 29
30 30 $ echo '[hooks]' > .hg/hgrc
31 31 $ echo 'prechangegroup = python "$TESTDIR"/printenv.py prechangegroup' >> .hg/hgrc
32 32 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup' >> .hg/hgrc
33 33 $ echo 'incoming = python "$TESTDIR"/printenv.py incoming' >> .hg/hgrc
34 34
35 35 pretxncommit and commit hooks can see both parents of merge
36 36
37 37 $ cd ../a
38 38 $ echo b >> a
39 39 $ hg commit -m a1 -d "1 0"
40 40 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
41 41 pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
42 42 1:ab228980c14d
43 43 commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
44 44 commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
45 45 $ hg update -C 0
46 46 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 47 $ echo b > b
48 48 $ hg add b
49 49 $ hg commit -m b -d '1 0'
50 50 precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
51 51 pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
52 52 2:ee9deb46ab31
53 53 commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
54 54 commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
55 55 created new head
56 56 $ hg merge 1
57 57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58 (branch merge, don't forget to commit)
59 59 $ hg commit -m merge -d '2 0'
60 60 precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
61 61 pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
62 62 3:07f3376c1e65
63 63 commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
64 64 commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
65 65
66 66 test generic hooks
67 67
68 68 $ hg id
69 69 pre-identify hook: HG_ARGS=id HG_OPTS={'branch': None, 'id': None, 'num': None, 'rev': '', 'tags': None} HG_PATS=[]
70 70 warning: pre-identify hook exited with status 1
71 71 [1]
72 72 $ hg cat b
73 73 pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
74 74 b
75 75 post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
76 76
77 77 $ cd ../b
78 78 $ hg pull ../a
79 79 pulling from ../a
80 80 searching for changes
81 81 prechangegroup hook: HG_SOURCE=pull HG_URL=file:$TESTTMP/a
82 82 adding changesets
83 83 adding manifests
84 84 adding file changes
85 85 added 3 changesets with 2 changes to 2 files
86 86 changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_URL=file:$TESTTMP/a
87 87 incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_URL=file:$TESTTMP/a
88 88 incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_URL=file:$TESTTMP/a
89 89 incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_URL=file:$TESTTMP/a
90 90 (run 'hg update' to get a working copy)
91 91
92 92 tag hooks can see env vars
93 93
94 94 $ cd ../a
95 95 $ echo 'pretag = python "$TESTDIR"/printenv.py pretag' >> .hg/hgrc
96 96 $ echo 'tag = unset HG_PARENT1 HG_PARENT2; python "$TESTDIR"/printenv.py tag' >> .hg/hgrc
97 97 $ hg tag -d '3 0' a
98 98 pretag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
99 99 precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
100 100 pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
101 101 4:539e4b31b6dc
102 102 commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
103 103 commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
104 104 tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
105 105 $ hg tag -l la
106 106 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
107 107 tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
108 108
109 109 pretag hook can forbid tagging
110 110
111 111 $ echo 'pretag.forbid = python "$TESTDIR"/printenv.py pretag.forbid 1' >> .hg/hgrc
112 112 $ hg tag -d '4 0' fa
113 113 pretag hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
114 114 pretag.forbid hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
115 115 abort: pretag.forbid hook exited with status 1
116 116 [255]
117 117 $ hg tag -l fla
118 118 pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
119 119 pretag.forbid hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
120 120 abort: pretag.forbid hook exited with status 1
121 121 [255]
122 122
123 123 pretxncommit hook can see changeset, can roll back txn, changeset no
124 124 more there after
125 125
126 126 $ echo 'pretxncommit.forbid0 = hg tip -q' >> .hg/hgrc
127 127 $ echo 'pretxncommit.forbid1 = python "$TESTDIR"/printenv.py pretxncommit.forbid 1' >> .hg/hgrc
128 128 $ echo z > z
129 129 $ hg add z
130 130 $ hg -q tip
131 131 4:539e4b31b6dc
132 132 $ hg commit -m 'fail' -d '4 0'
133 133 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
134 134 pretxncommit hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
135 135 5:6f611f8018c1
136 136 5:6f611f8018c1
137 137 pretxncommit.forbid hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
138 138 transaction abort!
139 139 rollback completed
140 140 abort: pretxncommit.forbid1 hook exited with status 1
141 141 [255]
142 142 $ hg -q tip
143 143 4:539e4b31b6dc
144 144
145 145 precommit hook can prevent commit
146 146
147 147 $ echo 'precommit.forbid = python "$TESTDIR"/printenv.py precommit.forbid 1' >> .hg/hgrc
148 148 $ hg commit -m 'fail' -d '4 0'
149 149 precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
150 150 precommit.forbid hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
151 151 abort: precommit.forbid hook exited with status 1
152 152 [255]
153 153 $ hg -q tip
154 154 4:539e4b31b6dc
155 155
156 156 preupdate hook can prevent update
157 157
158 158 $ echo 'preupdate = python "$TESTDIR"/printenv.py preupdate' >> .hg/hgrc
159 159 $ hg update 1
160 160 preupdate hook: HG_PARENT1=ab228980c14d
161 161 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
162 162
163 163 update hook
164 164
165 165 $ echo 'update = python "$TESTDIR"/printenv.py update' >> .hg/hgrc
166 166 $ hg update
167 167 preupdate hook: HG_PARENT1=539e4b31b6dc
168 168 update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc
169 169 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 170
171 171 prechangegroup hook can prevent incoming changes
172 172
173 173 $ cd ../b
174 174 $ hg -q tip
175 175 3:07f3376c1e65
176 176 $ echo '[hooks]' > .hg/hgrc
177 177 $ echo 'prechangegroup.forbid = python "$TESTDIR"/printenv.py prechangegroup.forbid 1' >> .hg/hgrc
178 178 $ hg pull ../a
179 179 pulling from ../a
180 180 searching for changes
181 181 prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:$TESTTMP/a
182 182 abort: prechangegroup.forbid hook exited with status 1
183 183 [255]
184 184
185 185 pretxnchangegroup hook can see incoming changes, can roll back txn,
186 186 incoming changes no longer there after
187 187
188 188 $ echo '[hooks]' > .hg/hgrc
189 189 $ echo 'pretxnchangegroup.forbid0 = hg tip -q' >> .hg/hgrc
190 190 $ echo 'pretxnchangegroup.forbid1 = python "$TESTDIR"/printenv.py pretxnchangegroup.forbid 1' >> .hg/hgrc
191 191 $ hg pull ../a
192 192 pulling from ../a
193 193 searching for changes
194 194 adding changesets
195 195 adding manifests
196 196 adding file changes
197 197 added 1 changesets with 1 changes to 1 files
198 198 4:539e4b31b6dc
199 199 pretxnchangegroup.forbid hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_URL=file:$TESTTMP/a
200 200 transaction abort!
201 201 rollback completed
202 202 abort: pretxnchangegroup.forbid1 hook exited with status 1
203 203 [255]
204 204 $ hg -q tip
205 205 3:07f3376c1e65
206 206
207 207 outgoing hooks can see env vars
208 208
209 209 $ rm .hg/hgrc
210 210 $ echo '[hooks]' > ../a/.hg/hgrc
211 211 $ echo 'preoutgoing = python "$TESTDIR"/printenv.py preoutgoing' >> ../a/.hg/hgrc
212 212 $ echo 'outgoing = python "$TESTDIR"/printenv.py outgoing' >> ../a/.hg/hgrc
213 213 $ hg pull ../a
214 214 pulling from ../a
215 215 searching for changes
216 216 preoutgoing hook: HG_SOURCE=pull
217 217 adding changesets
218 218 outgoing hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull
219 219 adding manifests
220 220 adding file changes
221 221 added 1 changesets with 1 changes to 1 files
222 222 (run 'hg update' to get a working copy)
223 223 $ hg rollback
224 rolling back to revision 3 (undo pull)
224 repository tip rolled back to revision 3 (undo pull)
225 working directory now based on revision 0
225 226
226 227 preoutgoing hook can prevent outgoing changes
227 228
228 229 $ echo 'preoutgoing.forbid = python "$TESTDIR"/printenv.py preoutgoing.forbid 1' >> ../a/.hg/hgrc
229 230 $ hg pull ../a
230 231 pulling from ../a
231 232 searching for changes
232 233 preoutgoing hook: HG_SOURCE=pull
233 234 preoutgoing.forbid hook: HG_SOURCE=pull
234 235 abort: preoutgoing.forbid hook exited with status 1
235 236 [255]
236 237
237 238 outgoing hooks work for local clones
238 239
239 240 $ cd ..
240 241 $ echo '[hooks]' > a/.hg/hgrc
241 242 $ echo 'preoutgoing = python "$TESTDIR"/printenv.py preoutgoing' >> a/.hg/hgrc
242 243 $ echo 'outgoing = python "$TESTDIR"/printenv.py outgoing' >> a/.hg/hgrc
243 244 $ hg clone a c
244 245 preoutgoing hook: HG_SOURCE=clone
245 246 outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
246 247 updating to branch default
247 248 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
248 249 $ rm -rf c
249 250
250 251 preoutgoing hook can prevent outgoing changes for local clones
251 252
252 253 $ echo 'preoutgoing.forbid = python "$TESTDIR"/printenv.py preoutgoing.forbid 1' >> a/.hg/hgrc
253 254 $ hg clone a zzz
254 255 preoutgoing hook: HG_SOURCE=clone
255 256 preoutgoing.forbid hook: HG_SOURCE=clone
256 257 abort: preoutgoing.forbid hook exited with status 1
257 258 [255]
258 259 $ cd b
259 260
260 261 $ cat > hooktests.py <<EOF
261 262 > from mercurial import util
262 263 >
263 264 > uncallable = 0
264 265 >
265 266 > def printargs(args):
266 267 > args.pop('ui', None)
267 268 > args.pop('repo', None)
268 269 > a = list(args.items())
269 270 > a.sort()
270 271 > print 'hook args:'
271 272 > for k, v in a:
272 273 > print ' ', k, v
273 274 >
274 275 > def passhook(**args):
275 276 > printargs(args)
276 277 >
277 278 > def failhook(**args):
278 279 > printargs(args)
279 280 > return True
280 281 >
281 282 > class LocalException(Exception):
282 283 > pass
283 284 >
284 285 > def raisehook(**args):
285 286 > raise LocalException('exception from hook')
286 287 >
287 288 > def aborthook(**args):
288 289 > raise util.Abort('raise abort from hook')
289 290 >
290 291 > def brokenhook(**args):
291 292 > return 1 + {}
292 293 >
293 294 > class container:
294 295 > unreachable = 1
295 296 > EOF
296 297
297 298 test python hooks
298 299
299 300 $ PYTHONPATH="`pwd`:$PYTHONPATH"
300 301 $ export PYTHONPATH
301 302
302 303 $ echo '[hooks]' > ../a/.hg/hgrc
303 304 $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
304 305 $ hg pull ../a 2>&1 | grep 'raised an exception'
305 306 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
306 307
307 308 $ echo '[hooks]' > ../a/.hg/hgrc
308 309 $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
309 310 $ hg pull ../a 2>&1 | grep 'raised an exception'
310 311 error: preoutgoing.raise hook raised an exception: exception from hook
311 312
312 313 $ echo '[hooks]' > ../a/.hg/hgrc
313 314 $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
314 315 $ hg pull ../a
315 316 pulling from ../a
316 317 searching for changes
317 318 error: preoutgoing.abort hook failed: raise abort from hook
318 319 abort: raise abort from hook
319 320 [255]
320 321
321 322 $ echo '[hooks]' > ../a/.hg/hgrc
322 323 $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
323 324 $ hg pull ../a
324 325 pulling from ../a
325 326 searching for changes
326 327 hook args:
327 328 hooktype preoutgoing
328 329 source pull
329 330 abort: preoutgoing.fail hook failed
330 331 [255]
331 332
332 333 $ echo '[hooks]' > ../a/.hg/hgrc
333 334 $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
334 335 $ hg pull ../a
335 336 pulling from ../a
336 337 searching for changes
337 338 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
338 339 [255]
339 340
340 341 $ echo '[hooks]' > ../a/.hg/hgrc
341 342 $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
342 343 $ hg pull ../a
343 344 pulling from ../a
344 345 searching for changes
345 346 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
346 347 [255]
347 348
348 349 $ echo '[hooks]' > ../a/.hg/hgrc
349 350 $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
350 351 $ hg pull ../a
351 352 pulling from ../a
352 353 searching for changes
353 354 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
354 355 [255]
355 356
356 357 $ echo '[hooks]' > ../a/.hg/hgrc
357 358 $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
358 359 $ hg pull ../a
359 360 pulling from ../a
360 361 searching for changes
361 362 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
362 363 [255]
363 364
364 365 $ echo '[hooks]' > ../a/.hg/hgrc
365 366 $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
366 367 $ hg pull ../a
367 368 pulling from ../a
368 369 searching for changes
369 370 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
370 371 [255]
371 372
372 373 $ echo '[hooks]' > ../a/.hg/hgrc
373 374 $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
374 375 $ hg pull ../a
375 376 pulling from ../a
376 377 searching for changes
377 378 hook args:
378 379 hooktype preoutgoing
379 380 source pull
380 381 adding changesets
381 382 adding manifests
382 383 adding file changes
383 384 added 1 changesets with 1 changes to 1 files
384 385 (run 'hg update' to get a working copy)
385 386
386 387 make sure --traceback works
387 388
388 389 $ echo '[hooks]' > .hg/hgrc
389 390 $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
390 391
391 392 $ echo aa > a
392 393 $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
393 394 Traceback (most recent call last):
394 395
395 396 $ cd ..
396 397 $ hg init c
397 398 $ cd c
398 399
399 400 $ cat > hookext.py <<EOF
400 401 > def autohook(**args):
401 402 > print "Automatically installed hook"
402 403 >
403 404 > def reposetup(ui, repo):
404 405 > repo.ui.setconfig("hooks", "commit.auto", autohook)
405 406 > EOF
406 407 $ echo '[extensions]' >> .hg/hgrc
407 408 $ echo 'hookext = hookext.py' >> .hg/hgrc
408 409
409 410 $ touch foo
410 411 $ hg add foo
411 412 $ hg ci -d '0 0' -m 'add foo'
412 413 Automatically installed hook
413 414 $ echo >> foo
414 415 $ hg ci --debug -d '0 0' -m 'change foo'
415 416 foo
416 417 calling hook commit.auto: <function autohook at *> (glob)
417 418 Automatically installed hook
418 419 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
419 420
420 421 $ hg showconfig hooks
421 422 hooks.commit.auto=<function autohook at *> (glob)
422 423
423 424 test python hook configured with python:[file]:[hook] syntax
424 425
425 426 $ cd ..
426 427 $ mkdir d
427 428 $ cd d
428 429 $ hg init repo
429 430 $ mkdir hooks
430 431
431 432 $ cd hooks
432 433 $ cat > testhooks.py <<EOF
433 434 > def testhook(**args):
434 435 > print 'hook works'
435 436 > EOF
436 437 $ echo '[hooks]' > ../repo/.hg/hgrc
437 438 $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
438 439
439 440 $ cd ../repo
440 441 $ hg commit -d '0 0'
441 442 hook works
442 443 nothing changed
443 444 [1]
444 445
445 446 $ cd ../../b
446 447
447 448 make sure --traceback works on hook import failure
448 449
449 450 $ cat > importfail.py <<EOF
450 451 > import somebogusmodule
451 452 > # dereference something in the module to force demandimport to load it
452 453 > somebogusmodule.whatever
453 454 > EOF
454 455
455 456 $ echo '[hooks]' > .hg/hgrc
456 457 $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
457 458
458 459 $ echo a >> a
459 460 $ hg --traceback commit -ma 2>&1 | egrep '^(exception|Traceback|ImportError)'
460 461 exception from first failed import attempt:
461 462 Traceback (most recent call last):
462 463 ImportError: No module named somebogusmodule
463 464 exception from second failed import attempt:
464 465 Traceback (most recent call last):
465 466 ImportError: No module named hgext_importfail
466 467 Traceback (most recent call last):
467 468
468 469 Issue1827: Hooks Update & Commit not completely post operation
469 470
470 471 commit and update hooks should run after command completion
471 472
472 473 $ echo '[hooks]' > .hg/hgrc
473 474 $ echo 'commit = hg id' >> .hg/hgrc
474 475 $ echo 'update = hg id' >> .hg/hgrc
475 476 $ echo bb > a
476 477 $ hg ci -ma
477 478 223eafe2750c tip
478 479 $ hg up 0
479 480 cb9a9f314b8b
480 481 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
481 482
@@ -1,931 +1,932 b''
1 1 $ hg init a
2 2 $ mkdir a/d1
3 3 $ mkdir a/d1/d2
4 4 $ echo line 1 > a/a
5 5 $ echo line 1 > a/d1/d2/a
6 6 $ hg --cwd a ci -Ama
7 7 adding a
8 8 adding d1/d2/a
9 9
10 10 $ echo line 2 >> a/a
11 11 $ hg --cwd a ci -u someone -d '1 0' -m'second change'
12 12
13 13
14 14 import exported patch
15 15
16 16 $ hg clone -r0 a b
17 17 adding changesets
18 18 adding manifests
19 19 adding file changes
20 20 added 1 changesets with 2 changes to 2 files
21 21 updating to branch default
22 22 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 23 $ hg --cwd a export tip > tip.patch
24 24 $ hg --cwd b import ../tip.patch
25 25 applying ../tip.patch
26 26
27 27 message should be same
28 28
29 29 $ hg --cwd b tip | grep 'second change'
30 30 summary: second change
31 31
32 32 committer should be same
33 33
34 34 $ hg --cwd b tip | grep someone
35 35 user: someone
36 36 $ rm -r b
37 37
38 38
39 39 import exported patch with external patcher
40 40
41 41 $ cat > dummypatch.py <<EOF
42 42 > print 'patching file a'
43 43 > file('a', 'wb').write('line2\n')
44 44 > EOF
45 45 $ chmod +x dummypatch.py
46 46 $ hg clone -r0 a b
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 $ hg --cwd a export tip > tip.patch
54 54 $ hg --config ui.patch='python ../dummypatch.py' --cwd b import ../tip.patch
55 55 applying ../tip.patch
56 56 $ cat b/a
57 57 line2
58 58 $ rm -r b
59 59
60 60
61 61 import of plain diff should fail without message
62 62
63 63 $ hg clone -r0 a b
64 64 adding changesets
65 65 adding manifests
66 66 adding file changes
67 67 added 1 changesets with 2 changes to 2 files
68 68 updating to branch default
69 69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 $ hg --cwd a diff -r0:1 > tip.patch
71 71 $ hg --cwd b import ../tip.patch
72 72 applying ../tip.patch
73 73 abort: empty commit message
74 74 [255]
75 75 $ rm -r b
76 76
77 77
78 78 import of plain diff should be ok with message
79 79
80 80 $ hg clone -r0 a b
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 1 changesets with 2 changes to 2 files
85 85 updating to branch default
86 86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 87 $ hg --cwd a diff -r0:1 > tip.patch
88 88 $ hg --cwd b import -mpatch ../tip.patch
89 89 applying ../tip.patch
90 90 $ rm -r b
91 91
92 92
93 93 import of plain diff with specific date and user
94 94
95 95 $ hg clone -r0 a b
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 $ hg --cwd a diff -r0:1 > tip.patch
103 103 $ hg --cwd b import -mpatch -d '1 0' -u 'user@nowhere.net' ../tip.patch
104 104 applying ../tip.patch
105 105 $ hg -R b tip -pv
106 106 changeset: 1:ca68f19f3a40
107 107 tag: tip
108 108 user: user@nowhere.net
109 109 date: Thu Jan 01 00:00:01 1970 +0000
110 110 files: a
111 111 description:
112 112 patch
113 113
114 114
115 115 diff -r 80971e65b431 -r ca68f19f3a40 a
116 116 --- a/a Thu Jan 01 00:00:00 1970 +0000
117 117 +++ b/a Thu Jan 01 00:00:01 1970 +0000
118 118 @@ -1,1 +1,2 @@
119 119 line 1
120 120 +line 2
121 121
122 122 $ rm -r b
123 123
124 124
125 125 import of plain diff should be ok with --no-commit
126 126
127 127 $ hg clone -r0 a b
128 128 adding changesets
129 129 adding manifests
130 130 adding file changes
131 131 added 1 changesets with 2 changes to 2 files
132 132 updating to branch default
133 133 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
134 134 $ hg --cwd a diff -r0:1 > tip.patch
135 135 $ hg --cwd b import --no-commit ../tip.patch
136 136 applying ../tip.patch
137 137 $ hg --cwd b diff --nodates
138 138 diff -r 80971e65b431 a
139 139 --- a/a
140 140 +++ b/a
141 141 @@ -1,1 +1,2 @@
142 142 line 1
143 143 +line 2
144 144 $ rm -r b
145 145
146 146
147 147 import of malformed plain diff should fail
148 148
149 149 $ hg clone -r0 a b
150 150 adding changesets
151 151 adding manifests
152 152 adding file changes
153 153 added 1 changesets with 2 changes to 2 files
154 154 updating to branch default
155 155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 156 $ hg --cwd a diff -r0:1 > tip.patch
157 157 $ sed 's/1,1/foo/' < tip.patch > broken.patch
158 158 $ hg --cwd b import -mpatch ../broken.patch
159 159 applying ../broken.patch
160 160 abort: bad hunk #1
161 161 [255]
162 162 $ rm -r b
163 163
164 164
165 165 hg -R repo import
166 166 put the clone in a subdir - having a directory named "a"
167 167 used to hide a bug.
168 168
169 169 $ mkdir dir
170 170 $ hg clone -r0 a dir/b
171 171 adding changesets
172 172 adding manifests
173 173 adding file changes
174 174 added 1 changesets with 2 changes to 2 files
175 175 updating to branch default
176 176 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 177 $ hg --cwd a export tip > dir/tip.patch
178 178 $ cd dir
179 179 $ hg -R b import tip.patch
180 180 applying tip.patch
181 181 $ cd ..
182 182 $ rm -r dir
183 183
184 184
185 185 import from stdin
186 186
187 187 $ hg clone -r0 a b
188 188 adding changesets
189 189 adding manifests
190 190 adding file changes
191 191 added 1 changesets with 2 changes to 2 files
192 192 updating to branch default
193 193 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
194 194 $ hg --cwd a export tip | hg --cwd b import -
195 195 applying patch from stdin
196 196 $ rm -r b
197 197
198 198
199 199 import two patches in one stream
200 200
201 201 $ hg init b
202 202 $ hg --cwd a export 0:tip | hg --cwd b import -
203 203 applying patch from stdin
204 204 applied 80971e65b431
205 205 $ hg --cwd a id
206 206 1d4bd90af0e4 tip
207 207 $ hg --cwd b id
208 208 1d4bd90af0e4 tip
209 209 $ rm -r b
210 210
211 211
212 212 override commit message
213 213
214 214 $ hg clone -r0 a b
215 215 adding changesets
216 216 adding manifests
217 217 adding file changes
218 218 added 1 changesets with 2 changes to 2 files
219 219 updating to branch default
220 220 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 221 $ hg --cwd a export tip | hg --cwd b import -m 'override' -
222 222 applying patch from stdin
223 223 $ hg --cwd b tip | grep override
224 224 summary: override
225 225 $ rm -r b
226 226
227 227 $ cat > mkmsg.py <<EOF
228 228 > import email.Message, sys
229 229 > msg = email.Message.Message()
230 230 > msg.set_payload('email commit message\n' + open('tip.patch', 'rb').read())
231 231 > msg['Subject'] = 'email patch'
232 232 > msg['From'] = 'email patcher'
233 233 > sys.stdout.write(msg.as_string())
234 234 > EOF
235 235
236 236
237 237 plain diff in email, subject, message body
238 238
239 239 $ hg clone -r0 a b
240 240 adding changesets
241 241 adding manifests
242 242 adding file changes
243 243 added 1 changesets with 2 changes to 2 files
244 244 updating to branch default
245 245 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 246 $ hg --cwd a diff -r0:1 > tip.patch
247 247 $ python mkmsg.py > msg.patch
248 248 $ hg --cwd b import ../msg.patch
249 249 applying ../msg.patch
250 250 $ hg --cwd b tip | grep email
251 251 user: email patcher
252 252 summary: email patch
253 253 $ rm -r b
254 254
255 255
256 256 plain diff in email, no subject, message body
257 257
258 258 $ hg clone -r0 a b
259 259 adding changesets
260 260 adding manifests
261 261 adding file changes
262 262 added 1 changesets with 2 changes to 2 files
263 263 updating to branch default
264 264 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 265 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
266 266 applying patch from stdin
267 267 $ rm -r b
268 268
269 269
270 270 plain diff in email, subject, no message body
271 271
272 272 $ hg clone -r0 a b
273 273 adding changesets
274 274 adding manifests
275 275 adding file changes
276 276 added 1 changesets with 2 changes to 2 files
277 277 updating to branch default
278 278 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 279 $ grep -v '^email ' msg.patch | hg --cwd b import -
280 280 applying patch from stdin
281 281 $ rm -r b
282 282
283 283
284 284 plain diff in email, no subject, no message body, should fail
285 285
286 286 $ hg clone -r0 a b
287 287 adding changesets
288 288 adding manifests
289 289 adding file changes
290 290 added 1 changesets with 2 changes to 2 files
291 291 updating to branch default
292 292 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
293 293 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
294 294 applying patch from stdin
295 295 abort: empty commit message
296 296 [255]
297 297 $ rm -r b
298 298
299 299
300 300 hg export in email, should use patch header
301 301
302 302 $ hg clone -r0 a b
303 303 adding changesets
304 304 adding manifests
305 305 adding file changes
306 306 added 1 changesets with 2 changes to 2 files
307 307 updating to branch default
308 308 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 309 $ hg --cwd a export tip > tip.patch
310 310 $ python mkmsg.py | hg --cwd b import -
311 311 applying patch from stdin
312 312 $ hg --cwd b tip | grep second
313 313 summary: second change
314 314 $ rm -r b
315 315
316 316
317 317 subject: duplicate detection, removal of [PATCH]
318 318 The '---' tests the gitsendmail handling without proper mail headers
319 319
320 320 $ cat > mkmsg2.py <<EOF
321 321 > import email.Message, sys
322 322 > msg = email.Message.Message()
323 323 > msg.set_payload('email patch\n\nnext line\n---\n' + open('tip.patch').read())
324 324 > msg['Subject'] = '[PATCH] email patch'
325 325 > msg['From'] = 'email patcher'
326 326 > sys.stdout.write(msg.as_string())
327 327 > EOF
328 328
329 329
330 330 plain diff in email, [PATCH] subject, message body with subject
331 331
332 332 $ hg clone -r0 a b
333 333 adding changesets
334 334 adding manifests
335 335 adding file changes
336 336 added 1 changesets with 2 changes to 2 files
337 337 updating to branch default
338 338 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
339 339 $ hg --cwd a diff -r0:1 > tip.patch
340 340 $ python mkmsg2.py | hg --cwd b import -
341 341 applying patch from stdin
342 342 $ hg --cwd b tip --template '{desc}\n'
343 343 email patch
344 344
345 345 next line
346 346 ---
347 347 $ rm -r b
348 348
349 349
350 350 Issue963: Parent of working dir incorrect after import of multiple
351 351 patches and rollback
352 352
353 353 We weren't backing up the correct dirstate file when importing many
354 354 patches: import patch1 patch2; rollback
355 355
356 356 $ echo line 3 >> a/a
357 357 $ hg --cwd a ci -m'third change'
358 358 $ hg --cwd a export -o '../patch%R' 1 2
359 359 $ hg clone -qr0 a b
360 360 $ hg --cwd b parents --template 'parent: {rev}\n'
361 361 parent: 0
362 362 $ hg --cwd b import ../patch1 ../patch2
363 363 applying ../patch1
364 364 applying ../patch2
365 365 applied 1d4bd90af0e4
366 366 $ hg --cwd b rollback
367 rolling back to revision 1 (undo commit)
367 repository tip rolled back to revision 1 (undo commit)
368 working directory now based on revision 1
368 369 $ hg --cwd b parents --template 'parent: {rev}\n'
369 370 parent: 1
370 371 $ rm -r b
371 372
372 373
373 374 importing a patch in a subdirectory failed at the commit stage
374 375
375 376 $ echo line 2 >> a/d1/d2/a
376 377 $ hg --cwd a ci -u someoneelse -d '1 0' -m'subdir change'
377 378
378 379 hg import in a subdirectory
379 380
380 381 $ hg clone -r0 a b
381 382 adding changesets
382 383 adding manifests
383 384 adding file changes
384 385 added 1 changesets with 2 changes to 2 files
385 386 updating to branch default
386 387 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
387 388 $ hg --cwd a export tip > tmp
388 389 $ sed -e 's/d1\/d2\///' < tmp > tip.patch
389 390 $ dir=`pwd`
390 391 $ cd b/d1/d2 2>&1 > /dev/null
391 392 $ hg import ../../../tip.patch
392 393 applying ../../../tip.patch
393 394 $ cd "$dir"
394 395
395 396 message should be 'subdir change'
396 397
397 398 $ hg --cwd b tip | grep 'subdir change'
398 399 summary: subdir change
399 400
400 401 committer should be 'someoneelse'
401 402
402 403 $ hg --cwd b tip | grep someoneelse
403 404 user: someoneelse
404 405
405 406 should be empty
406 407
407 408 $ hg --cwd b status
408 409
409 410
410 411 Test fuzziness (ambiguous patch location, fuzz=2)
411 412
412 413 $ hg init fuzzy
413 414 $ cd fuzzy
414 415 $ echo line1 > a
415 416 $ echo line0 >> a
416 417 $ echo line3 >> a
417 418 $ hg ci -Am adda
418 419 adding a
419 420 $ echo line1 > a
420 421 $ echo line2 >> a
421 422 $ echo line0 >> a
422 423 $ echo line3 >> a
423 424 $ hg ci -m change a
424 425 $ hg export tip > tip.patch
425 426 $ hg up -C 0
426 427 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 428 $ echo line1 > a
428 429 $ echo line0 >> a
429 430 $ echo line1 >> a
430 431 $ echo line0 >> a
431 432 $ hg ci -m brancha
432 433 created new head
433 434 $ hg import --no-commit -v tip.patch
434 435 applying tip.patch
435 436 patching file a
436 437 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
437 438 $ hg revert -a
438 439 reverting a
439 440
440 441
441 442 import with --no-commit should have written .hg/last-message.txt
442 443
443 444 $ cat .hg/last-message.txt
444 445 change (no-eol)
445 446
446 447
447 448 test fuzziness with eol=auto
448 449
449 450 $ hg --config patch.eol=auto import --no-commit -v tip.patch
450 451 applying tip.patch
451 452 patching file a
452 453 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
453 454 $ cd ..
454 455
455 456
456 457 Test hunk touching empty files (issue906)
457 458
458 459 $ hg init empty
459 460 $ cd empty
460 461 $ touch a
461 462 $ touch b1
462 463 $ touch c1
463 464 $ echo d > d
464 465 $ hg ci -Am init
465 466 adding a
466 467 adding b1
467 468 adding c1
468 469 adding d
469 470 $ echo a > a
470 471 $ echo b > b1
471 472 $ hg mv b1 b2
472 473 $ echo c > c1
473 474 $ hg copy c1 c2
474 475 $ rm d
475 476 $ touch d
476 477 $ hg diff --git
477 478 diff --git a/a b/a
478 479 --- a/a
479 480 +++ b/a
480 481 @@ -0,0 +1,1 @@
481 482 +a
482 483 diff --git a/b1 b/b2
483 484 rename from b1
484 485 rename to b2
485 486 --- a/b1
486 487 +++ b/b2
487 488 @@ -0,0 +1,1 @@
488 489 +b
489 490 diff --git a/c1 b/c1
490 491 --- a/c1
491 492 +++ b/c1
492 493 @@ -0,0 +1,1 @@
493 494 +c
494 495 diff --git a/c1 b/c2
495 496 copy from c1
496 497 copy to c2
497 498 --- a/c1
498 499 +++ b/c2
499 500 @@ -0,0 +1,1 @@
500 501 +c
501 502 diff --git a/d b/d
502 503 --- a/d
503 504 +++ b/d
504 505 @@ -1,1 +0,0 @@
505 506 -d
506 507 $ hg ci -m empty
507 508 $ hg export --git tip > empty.diff
508 509 $ hg up -C 0
509 510 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
510 511 $ hg import empty.diff
511 512 applying empty.diff
512 513 $ for name in a b1 b2 c1 c2 d; do
513 514 > echo % $name file
514 515 > test -f $name && cat $name
515 516 > done
516 517 % a file
517 518 a
518 519 % b1 file
519 520 % b2 file
520 521 b
521 522 % c1 file
522 523 c
523 524 % c2 file
524 525 c
525 526 % d file
526 527 $ cd ..
527 528
528 529
529 530 Test importing a patch ending with a binary file removal
530 531
531 532 $ hg init binaryremoval
532 533 $ cd binaryremoval
533 534 $ echo a > a
534 535 $ python -c "file('b', 'wb').write('a\x00b')"
535 536 $ hg ci -Am addall
536 537 adding a
537 538 adding b
538 539 $ hg rm a
539 540 $ hg rm b
540 541 $ hg st
541 542 R a
542 543 R b
543 544 $ hg ci -m remove
544 545 $ hg export --git . > remove.diff
545 546 $ cat remove.diff | grep git
546 547 diff --git a/a b/a
547 548 diff --git a/b b/b
548 549 $ hg up -C 0
549 550 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
550 551 $ hg import remove.diff
551 552 applying remove.diff
552 553 $ hg manifest
553 554 $ cd ..
554 555
555 556
556 557 Issue927: test update+rename with common name
557 558
558 559 $ hg init t
559 560 $ cd t
560 561 $ touch a
561 562 $ hg ci -Am t
562 563 adding a
563 564 $ echo a > a
564 565
565 566 Here, bfile.startswith(afile)
566 567
567 568 $ hg copy a a2
568 569 $ hg ci -m copya
569 570 $ hg export --git tip > copy.diff
570 571 $ hg up -C 0
571 572 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
572 573 $ hg import copy.diff
573 574 applying copy.diff
574 575
575 576 a should contain an 'a'
576 577
577 578 $ cat a
578 579 a
579 580
580 581 and a2 should have duplicated it
581 582
582 583 $ cat a2
583 584 a
584 585 $ cd ..
585 586
586 587
587 588 test -p0
588 589
589 590 $ hg init p0
590 591 $ cd p0
591 592 $ echo a > a
592 593 $ hg ci -Am t
593 594 adding a
594 595 $ hg import -p0 - << EOF
595 596 > foobar
596 597 > --- a Sat Apr 12 22:43:58 2008 -0400
597 598 > +++ a Sat Apr 12 22:44:05 2008 -0400
598 599 > @@ -1,1 +1,1 @@
599 600 > -a
600 601 > +bb
601 602 > EOF
602 603 applying patch from stdin
603 604 $ hg status
604 605 $ cat a
605 606 bb
606 607 $ cd ..
607 608
608 609
609 610 test paths outside repo root
610 611
611 612 $ mkdir outside
612 613 $ touch outside/foo
613 614 $ hg init inside
614 615 $ cd inside
615 616 $ hg import - <<EOF
616 617 > diff --git a/a b/b
617 618 > rename from ../outside/foo
618 619 > rename to bar
619 620 > EOF
620 621 applying patch from stdin
621 622 abort: ../outside/foo not under root
622 623 [255]
623 624 $ cd ..
624 625
625 626
626 627 test import with similarity and git and strip (issue295 et al.)
627 628
628 629 $ hg init sim
629 630 $ cd sim
630 631 $ echo 'this is a test' > a
631 632 $ hg ci -Ama
632 633 adding a
633 634 $ cat > ../rename.diff <<EOF
634 635 > diff --git a/foo/a b/foo/a
635 636 > deleted file mode 100644
636 637 > --- a/foo/a
637 638 > +++ /dev/null
638 639 > @@ -1,1 +0,0 @@
639 640 > -this is a test
640 641 > diff --git a/foo/b b/foo/b
641 642 > new file mode 100644
642 643 > --- /dev/null
643 644 > +++ b/foo/b
644 645 > @@ -0,0 +1,2 @@
645 646 > +this is a test
646 647 > +foo
647 648 > EOF
648 649 $ hg import --no-commit -v -s 1 ../rename.diff -p2
649 650 applying ../rename.diff
650 651 patching file a
651 652 patching file b
652 653 removing a
653 654 adding b
654 655 recording removal of a as rename to b (88% similar)
655 656 $ hg st -C
656 657 A b
657 658 a
658 659 R a
659 660 $ hg revert -a
660 661 undeleting a
661 662 forgetting b
662 663 $ rm b
663 664 $ hg import --no-commit -v -s 100 ../rename.diff -p2
664 665 applying ../rename.diff
665 666 patching file a
666 667 patching file b
667 668 removing a
668 669 adding b
669 670 $ hg st -C
670 671 A b
671 672 R a
672 673 $ cd ..
673 674
674 675
675 676 Issue1495: add empty file from the end of patch
676 677
677 678 $ hg init addemptyend
678 679 $ cd addemptyend
679 680 $ touch a
680 681 $ hg addremove
681 682 adding a
682 683 $ hg ci -m "commit"
683 684 $ cat > a.patch <<EOF
684 685 > diff --git a/a b/a
685 686 > --- a/a
686 687 > +++ b/a
687 688 > @@ -0,0 +1,1 @@
688 689 > +a
689 690 > diff --git a/b b/b
690 691 > new file mode 100644
691 692 > EOF
692 693 $ hg import --no-commit a.patch
693 694 applying a.patch
694 695 $ cd ..
695 696
696 697
697 698 create file when source is not /dev/null
698 699
699 700 $ cat > create.patch <<EOF
700 701 > diff -Naur proj-orig/foo proj-new/foo
701 702 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
702 703 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
703 704 > @@ -0,0 +1,1 @@
704 705 > +a
705 706 > EOF
706 707
707 708 some people have patches like the following too
708 709
709 710 $ cat > create2.patch <<EOF
710 711 > diff -Naur proj-orig/foo proj-new/foo
711 712 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
712 713 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
713 714 > @@ -0,0 +1,1 @@
714 715 > +a
715 716 > EOF
716 717 $ hg init oddcreate
717 718 $ cd oddcreate
718 719 $ hg import --no-commit ../create.patch
719 720 applying ../create.patch
720 721 $ cat foo
721 722 a
722 723 $ rm foo
723 724 $ hg revert foo
724 725 $ hg import --no-commit ../create2.patch
725 726 applying ../create2.patch
726 727 $ cat foo
727 728 a
728 729
729 730
730 731 Issue1859: first line mistaken for email headers
731 732
732 733 $ hg init emailconfusion
733 734 $ cd emailconfusion
734 735 $ cat > a.patch <<EOF
735 736 > module: summary
736 737 >
737 738 > description
738 739 >
739 740 >
740 741 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
741 742 > --- /dev/null
742 743 > +++ b/a
743 744 > @@ -0,0 +1,1 @@
744 745 > +a
745 746 > EOF
746 747 $ hg import -d '0 0' a.patch
747 748 applying a.patch
748 749 $ hg parents -v
749 750 changeset: 0:5a681217c0ad
750 751 tag: tip
751 752 user: test
752 753 date: Thu Jan 01 00:00:00 1970 +0000
753 754 files: a
754 755 description:
755 756 module: summary
756 757
757 758 description
758 759
759 760
760 761 $ cd ..
761 762
762 763
763 764 --- in commit message
764 765
765 766 $ hg init commitconfusion
766 767 $ cd commitconfusion
767 768 $ cat > a.patch <<EOF
768 769 > module: summary
769 770 >
770 771 > --- description
771 772 >
772 773 > diff --git a/a b/a
773 774 > new file mode 100644
774 775 > --- /dev/null
775 776 > +++ b/a
776 777 > @@ -0,0 +1,1 @@
777 778 > +a
778 779 > EOF
779 780 > hg import -d '0 0' a.patch
780 781 > hg parents -v
781 782 > cd ..
782 783 >
783 784 > echo '% tricky header splitting'
784 785 > cat > trickyheaders.patch <<EOF
785 786 > From: User A <user@a>
786 787 > Subject: [PATCH] from: tricky!
787 788 >
788 789 > # HG changeset patch
789 790 > # User User B
790 791 > # Date 1266264441 18000
791 792 > # Branch stable
792 793 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
793 794 > # Parent 0000000000000000000000000000000000000000
794 795 > from: tricky!
795 796 >
796 797 > That is not a header.
797 798 >
798 799 > diff -r 000000000000 -r f2be6a1170ac foo
799 800 > --- /dev/null
800 801 > +++ b/foo
801 802 > @@ -0,0 +1,1 @@
802 803 > +foo
803 804 > EOF
804 805 applying a.patch
805 806 changeset: 0:f34d9187897d
806 807 tag: tip
807 808 user: test
808 809 date: Thu Jan 01 00:00:00 1970 +0000
809 810 files: a
810 811 description:
811 812 module: summary
812 813
813 814
814 815 % tricky header splitting
815 816
816 817 $ hg init trickyheaders
817 818 $ cd trickyheaders
818 819 $ hg import -d '0 0' ../trickyheaders.patch
819 820 applying ../trickyheaders.patch
820 821 $ hg export --git tip
821 822 # HG changeset patch
822 823 # User User B
823 824 # Date 0 0
824 825 # Node ID eb56ab91903632294ac504838508cb370c0901d2
825 826 # Parent 0000000000000000000000000000000000000000
826 827 from: tricky!
827 828
828 829 That is not a header.
829 830
830 831 diff --git a/foo b/foo
831 832 new file mode 100644
832 833 --- /dev/null
833 834 +++ b/foo
834 835 @@ -0,0 +1,1 @@
835 836 +foo
836 837 $ cd ..
837 838
838 839
839 840 Issue2102: hg export and hg import speak different languages
840 841
841 842 $ hg init issue2102
842 843 $ cd issue2102
843 844 $ mkdir -p src/cmd/gc
844 845 $ touch src/cmd/gc/mksys.bash
845 846 $ hg ci -Am init
846 847 adding src/cmd/gc/mksys.bash
847 848 $ hg import - <<EOF
848 849 > # HG changeset patch
849 850 > # User Rob Pike
850 851 > # Date 1216685449 25200
851 852 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
852 853 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
853 854 > help management of empty pkg and lib directories in perforce
854 855 >
855 856 > R=gri
856 857 > DELTA=4 (4 added, 0 deleted, 0 changed)
857 858 > OCL=13328
858 859 > CL=13328
859 860 >
860 861 > diff --git a/lib/place-holder b/lib/place-holder
861 862 > new file mode 100644
862 863 > --- /dev/null
863 864 > +++ b/lib/place-holder
864 865 > @@ -0,0 +1,2 @@
865 866 > +perforce does not maintain empty directories.
866 867 > +this file helps.
867 868 > diff --git a/pkg/place-holder b/pkg/place-holder
868 869 > new file mode 100644
869 870 > --- /dev/null
870 871 > +++ b/pkg/place-holder
871 872 > @@ -0,0 +1,2 @@
872 873 > +perforce does not maintain empty directories.
873 874 > +this file helps.
874 875 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
875 876 > old mode 100644
876 877 > new mode 100755
877 878 > EOF
878 879 applying patch from stdin
879 880 $ hg sum
880 881 parent: 1:d59915696727 tip
881 882 help management of empty pkg and lib directories in perforce
882 883 branch: default
883 884 commit: (clean)
884 885 update: (current)
885 886 $ hg diff --git -c tip
886 887 diff --git a/lib/place-holder b/lib/place-holder
887 888 new file mode 100644
888 889 --- /dev/null
889 890 +++ b/lib/place-holder
890 891 @@ -0,0 +1,2 @@
891 892 +perforce does not maintain empty directories.
892 893 +this file helps.
893 894 diff --git a/pkg/place-holder b/pkg/place-holder
894 895 new file mode 100644
895 896 --- /dev/null
896 897 +++ b/pkg/place-holder
897 898 @@ -0,0 +1,2 @@
898 899 +perforce does not maintain empty directories.
899 900 +this file helps.
900 901 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
901 902 old mode 100644
902 903 new mode 100755
903 904 $ cd ..
904 905
905 906
906 907 diff lines looking like headers
907 908
908 909 $ hg init difflineslikeheaders
909 910 $ cd difflineslikeheaders
910 911 $ echo a >a
911 912 $ echo b >b
912 913 $ echo c >c
913 914 $ hg ci -Am1
914 915 adding a
915 916 adding b
916 917 adding c
917 918
918 919 $ echo "key: value" >>a
919 920 $ echo "key: value" >>b
920 921 $ echo "foo" >>c
921 922 $ hg ci -m2
922 923
923 924 $ hg up -C 0
924 925 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
925 926 $ hg diff --git -c1 >want
926 927 $ hg diff -c1 | hg import --no-commit -
927 928 applying patch from stdin
928 929 $ hg diff --git >have
929 930 $ diff want have
930 931 $ cd ..
931 932
@@ -1,1066 +1,1074 b''
1 1 $ cat <<EOF >> $HGRCPATH
2 2 > [extensions]
3 3 > keyword =
4 4 > mq =
5 5 > notify =
6 6 > record =
7 7 > transplant =
8 8 > [ui]
9 9 > interactive = true
10 10 > EOF
11 11
12 12 Run kwdemo before [keyword] files are set up
13 13 as it would succeed without uisetup otherwise
14 14
15 15 $ hg --quiet kwdemo
16 16 [extensions]
17 17 keyword =
18 18 [keyword]
19 19 demo.txt =
20 20 [keywordset]
21 21 svn = False
22 22 [keywordmaps]
23 23 Author = {author|user}
24 24 Date = {date|utcdate}
25 25 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
26 26 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
27 27 RCSFile = {file|basename},v
28 28 RCSfile = {file|basename},v
29 29 Revision = {node|short}
30 30 Source = {root}/{file},v
31 31 $Author: test $
32 32 $Date: ????/??/?? ??:??:?? $ (glob)
33 33 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
34 34 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
35 35 $RCSFile: demo.txt,v $
36 36 $RCSfile: demo.txt,v $
37 37 $Revision: ???????????? $ (glob)
38 38 $Source: */demo.txt,v $ (glob)
39 39
40 40 $ hg --quiet kwdemo "Branch = {branches}"
41 41 [extensions]
42 42 keyword =
43 43 [keyword]
44 44 demo.txt =
45 45 [keywordset]
46 46 svn = False
47 47 [keywordmaps]
48 48 Branch = {branches}
49 49 $Branch: demobranch $
50 50
51 51 $ cat <<EOF >> $HGRCPATH
52 52 > [keyword]
53 53 > ** =
54 54 > b = ignore
55 55 > i = ignore
56 56 > [hooks]
57 57 > EOF
58 58 $ cp $HGRCPATH $HGRCPATH.nohooks
59 59 > cat <<EOF >> $HGRCPATH
60 60 > commit=
61 61 > commit.test=cp a hooktest
62 62 > EOF
63 63
64 64 $ hg init Test-bndl
65 65 $ cd Test-bndl
66 66
67 67 kwshrink should exit silently in empty/invalid repo
68 68
69 69 $ hg kwshrink
70 70
71 71 Symlinks cannot be created on Windows.
72 72 A bundle to test this was made with:
73 73 hg init t
74 74 cd t
75 75 echo a > a
76 76 ln -s a sym
77 77 hg add sym
78 78 hg ci -m addsym -u mercurial
79 79 hg bundle --base null ../test-keyword.hg
80 80
81 81 $ hg pull -u "$TESTDIR"/test-keyword.hg
82 82 pulling from *test-keyword.hg (glob)
83 83 requesting all changes
84 84 adding changesets
85 85 adding manifests
86 86 adding file changes
87 87 added 1 changesets with 1 changes to 1 files
88 88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 89
90 90 $ echo 'expand $Id$' > a
91 91 $ echo 'do not process $Id:' >> a
92 92 $ echo 'xxx $' >> a
93 93 $ echo 'ignore $Id$' > b
94 94
95 95 Output files as they were created
96 96
97 97 $ cat a b
98 98 expand $Id$
99 99 do not process $Id:
100 100 xxx $
101 101 ignore $Id$
102 102
103 103 no kwfiles
104 104
105 105 $ hg kwfiles
106 106
107 107 untracked candidates
108 108
109 109 $ hg -v kwfiles --unknown
110 110 k a
111 111
112 112 Add files and check status
113 113
114 114 $ hg addremove
115 115 adding a
116 116 adding b
117 117 $ hg status
118 118 A a
119 119 A b
120 120
121 121
122 122 Default keyword expansion including commit hook
123 123 Interrupted commit should not change state or run commit hook
124 124
125 125 $ hg --debug commit
126 126 abort: empty commit message
127 127 [255]
128 128 $ hg status
129 129 A a
130 130 A b
131 131
132 132 Commit with several checks
133 133
134 134 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
135 135 a
136 136 b
137 137 overwriting a expanding keywords
138 138 running hook commit.test: cp a hooktest
139 139 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
140 140 $ hg status
141 141 ? hooktest
142 142 $ hg debugrebuildstate
143 143 $ hg --quiet identify
144 144 ef63ca68695b
145 145
146 146 cat files in working directory with keywords expanded
147 147
148 148 $ cat a b
149 149 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
150 150 do not process $Id:
151 151 xxx $
152 152 ignore $Id$
153 153
154 154 hg cat files and symlink, no expansion
155 155
156 156 $ hg cat sym a b && echo
157 157 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
158 158 do not process $Id:
159 159 xxx $
160 160 ignore $Id$
161 161 a
162 162
163 163 Test hook execution
164 164
165 165 $ diff a hooktest
166 166
167 167 $ cp $HGRCPATH.nohooks $HGRCPATH
168 168 $ rm hooktest
169 169
170 170 bundle
171 171
172 172 $ hg bundle --base null ../kw.hg
173 173 2 changesets found
174 174 $ cd ..
175 175 $ hg init Test
176 176 $ cd Test
177 177
178 178 Notify on pull to check whether keywords stay as is in email
179 179 ie. if patch.diff wrapper acts as it should
180 180
181 181 $ cat <<EOF >> $HGRCPATH
182 182 > [hooks]
183 183 > incoming.notify = python:hgext.notify.hook
184 184 > [notify]
185 185 > sources = pull
186 186 > diffstat = False
187 187 > maxsubject = 15
188 188 > [reposubs]
189 189 > * = Test
190 190 > EOF
191 191
192 192 Pull from bundle and trigger notify
193 193
194 194 $ hg pull -u ../kw.hg
195 195 pulling from ../kw.hg
196 196 requesting all changes
197 197 adding changesets
198 198 adding manifests
199 199 adding file changes
200 200 added 2 changesets with 3 changes to 3 files
201 201 Content-Type: text/plain; charset="us-ascii"
202 202 MIME-Version: 1.0
203 203 Content-Transfer-Encoding: 7bit
204 204 Date: * (glob)
205 205 Subject: changeset in...
206 206 From: mercurial
207 207 X-Hg-Notification: changeset a2392c293916
208 208 Message-Id: <hg.a2392c293916*> (glob)
209 209 To: Test
210 210
211 211 changeset a2392c293916 in $TESTTMP/Test
212 212 details: *cmd=changeset;node=a2392c293916 (glob)
213 213 description:
214 214 addsym
215 215
216 216 diffs (6 lines):
217 217
218 218 diff -r 000000000000 -r a2392c293916 sym
219 219 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
220 220 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
221 221 @@ -0,0 +1,1 @@
222 222 +a
223 223 \ No newline at end of file
224 224 Content-Type: text/plain; charset="us-ascii"
225 225 MIME-Version: 1.0
226 226 Content-Transfer-Encoding: 7bit
227 227 Date:* (glob)
228 228 Subject: changeset in...
229 229 From: User Name <user@example.com>
230 230 X-Hg-Notification: changeset ef63ca68695b
231 231 Message-Id: <hg.ef63ca68695b*> (glob)
232 232 To: Test
233 233
234 234 changeset ef63ca68695b in $TESTTMP/Test
235 235 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
236 236 description:
237 237 absym
238 238
239 239 diffs (12 lines):
240 240
241 241 diff -r a2392c293916 -r ef63ca68695b a
242 242 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
243 243 +++ b/a Thu Jan 01 00:00:00 1970 +0000
244 244 @@ -0,0 +1,3 @@
245 245 +expand $Id$
246 246 +do not process $Id:
247 247 +xxx $
248 248 diff -r a2392c293916 -r ef63ca68695b b
249 249 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250 250 +++ b/b Thu Jan 01 00:00:00 1970 +0000
251 251 @@ -0,0 +1,1 @@
252 252 +ignore $Id$
253 253 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 254
255 255 $ cp $HGRCPATH.nohooks $HGRCPATH
256 256
257 257 Touch files and check with status
258 258
259 259 $ touch a b
260 260 $ hg status
261 261
262 262 Update and expand
263 263
264 264 $ rm sym a b
265 265 $ hg update -C
266 266 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 267 $ cat a b
268 268 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
269 269 do not process $Id:
270 270 xxx $
271 271 ignore $Id$
272 272
273 273 Check whether expansion is filewise
274 274
275 275 $ echo '$Id$' > c
276 276 $ echo 'tests for different changenodes' >> c
277 277
278 278 commit file c
279 279
280 280 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
281 281 adding c
282 282
283 283 force expansion
284 284
285 285 $ hg -v kwexpand
286 286 overwriting a expanding keywords
287 287 overwriting c expanding keywords
288 288
289 289 compare changenodes in a and c
290 290
291 291 $ cat a c
292 292 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
293 293 do not process $Id:
294 294 xxx $
295 295 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
296 296 tests for different changenodes
297 297
298 298 record
299 299
300 300 $ echo '$Id$' > r
301 301 $ hg add r
302 302
303 303 record chunk
304 304
305 305 $ python -c \
306 306 > 'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
307 307 $ hg record -d '1 10' -m rectest a<<EOF
308 308 > y
309 309 > y
310 310 > n
311 311 > EOF
312 312 diff --git a/a b/a
313 313 2 hunks, 2 lines changed
314 314 examine changes to 'a'? [Ynsfdaq?]
315 315 @@ -1,3 +1,4 @@
316 316 expand $Id$
317 317 +foo
318 318 do not process $Id:
319 319 xxx $
320 320 record change 1/2 to 'a'? [Ynsfdaq?]
321 321 @@ -2,2 +3,3 @@
322 322 do not process $Id:
323 323 xxx $
324 324 +bar
325 325 record change 2/2 to 'a'? [Ynsfdaq?]
326 326
327 327 $ hg identify
328 328 d17e03c92c97+ tip
329 329 $ hg status
330 330 M a
331 331 A r
332 332
333 333 Cat modified file a
334 334
335 335 $ cat a
336 336 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
337 337 foo
338 338 do not process $Id:
339 339 xxx $
340 340 bar
341 341
342 342 Diff remaining chunk
343 343
344 344 $ hg diff a
345 345 diff -r d17e03c92c97 a
346 346 --- a/a Wed Dec 31 23:59:51 1969 -0000
347 347 +++ b/a * (glob)
348 348 @@ -2,3 +2,4 @@
349 349 foo
350 350 do not process $Id:
351 351 xxx $
352 352 +bar
353 353
354 354 $ hg rollback
355 rolling back to revision 2 (undo commit)
355 repository tip rolled back to revision 2 (undo commit)
356 working directory now based on revision 2
356 357
357 358 Record all chunks in file a
358 359
359 360 $ echo foo > msg
360 361
361 362 - do not use "hg record -m" here!
362 363
363 364 $ hg record -l msg -d '1 11' a<<EOF
364 365 > y
365 366 > y
366 367 > y
367 368 > EOF
368 369 diff --git a/a b/a
369 370 2 hunks, 2 lines changed
370 371 examine changes to 'a'? [Ynsfdaq?]
371 372 @@ -1,3 +1,4 @@
372 373 expand $Id$
373 374 +foo
374 375 do not process $Id:
375 376 xxx $
376 377 record change 1/2 to 'a'? [Ynsfdaq?]
377 378 @@ -2,2 +3,3 @@
378 379 do not process $Id:
379 380 xxx $
380 381 +bar
381 382 record change 2/2 to 'a'? [Ynsfdaq?]
382 383
383 384 File a should be clean
384 385
385 386 $ hg status -A a
386 387 C a
387 388
388 389 rollback and revert expansion
389 390
390 391 $ cat a
391 392 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
392 393 foo
393 394 do not process $Id:
394 395 xxx $
395 396 bar
396 397 $ hg --verbose rollback
397 rolling back to revision 2 (undo commit)
398 repository tip rolled back to revision 2 (undo commit)
399 working directory now based on revision 2
398 400 overwriting a expanding keywords
399 401 $ hg status a
400 402 M a
401 403 $ cat a
402 404 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
403 405 foo
404 406 do not process $Id:
405 407 xxx $
406 408 bar
407 409 $ echo '$Id$' > y
408 410 $ echo '$Id$' > z
409 411 $ hg add y
410 412 $ hg commit -Am "rollback only" z
411 413 $ cat z
412 414 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
413 415 $ hg --verbose rollback
414 rolling back to revision 2 (undo commit)
416 repository tip rolled back to revision 2 (undo commit)
417 working directory now based on revision 2
415 418 overwriting z shrinking keywords
416 419
417 420 Only z should be overwritten
418 421
419 422 $ hg status a y z
420 423 M a
421 424 A y
422 425 A z
423 426 $ cat z
424 427 $Id$
425 428 $ hg forget y z
426 429 $ rm y z
427 430
428 431 record added file alone
429 432
430 433 $ hg -v record -l msg -d '1 12' r<<EOF
431 434 > y
432 435 > EOF
433 436 diff --git a/r b/r
434 437 new file mode 100644
435 438 examine changes to 'r'? [Ynsfdaq?]
436 439 r
437 440 committed changeset 3:899491280810
438 441 overwriting r expanding keywords
439 442 $ hg --verbose rollback
440 rolling back to revision 2 (undo commit)
443 repository tip rolled back to revision 2 (undo commit)
444 working directory now based on revision 2
441 445 overwriting r shrinking keywords
442 446 $ hg forget r
443 447 $ rm msg r
444 448 $ hg update -C
445 449 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
446 450
447 451 record added keyword ignored file
448 452
449 453 $ echo '$Id$' > i
450 454 $ hg add i
451 455 $ hg --verbose record -d '1 13' -m recignored<<EOF
452 456 > y
453 457 > EOF
454 458 diff --git a/i b/i
455 459 new file mode 100644
456 460 examine changes to 'i'? [Ynsfdaq?]
457 461 i
458 462 committed changeset 3:5f40fe93bbdc
459 463 $ cat i
460 464 $Id$
461 465 $ hg -q rollback
462 466 $ hg forget i
463 467 $ rm i
464 468
465 469 Test patch queue repo
466 470
467 471 $ hg init --mq
468 472 $ hg qimport -r tip -n mqtest.diff
469 473 $ hg commit --mq -m mqtest
470 474
471 475 Keywords should not be expanded in patch
472 476
473 477 $ cat .hg/patches/mqtest.diff
474 478 # HG changeset patch
475 479 # User User Name <user@example.com>
476 480 # Date 1 0
477 481 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
478 482 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
479 483 cndiff
480 484
481 485 diff -r ef63ca68695b -r 40a904bbbe4c c
482 486 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
483 487 +++ b/c Thu Jan 01 00:00:01 1970 +0000
484 488 @@ -0,0 +1,2 @@
485 489 +$Id$
486 490 +tests for different changenodes
487 491
488 492 $ hg qpop
489 493 popping mqtest.diff
490 494 patch queue now empty
491 495
492 496 qgoto, implying qpush, should expand
493 497
494 498 $ hg qgoto mqtest.diff
495 499 applying mqtest.diff
496 500 now at: mqtest.diff
497 501 $ cat c
498 502 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
499 503 tests for different changenodes
500 504 $ hg cat c
501 505 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
502 506 tests for different changenodes
503 507
504 508 Keywords should not be expanded in filelog
505 509
506 510 $ hg --config 'extensions.keyword=!' cat c
507 511 $Id$
508 512 tests for different changenodes
509 513
510 514 qpop and move on
511 515
512 516 $ hg qpop
513 517 popping mqtest.diff
514 518 patch queue now empty
515 519
516 520 Copy and show added kwfiles
517 521
518 522 $ hg cp a c
519 523 $ hg kwfiles
520 524 a
521 525 c
522 526
523 527 Commit and show expansion in original and copy
524 528
525 529 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
526 530 c
527 531 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
528 532 overwriting c expanding keywords
529 533 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
530 534 $ cat a c
531 535 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
532 536 do not process $Id:
533 537 xxx $
534 538 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
535 539 do not process $Id:
536 540 xxx $
537 541
538 542 Touch copied c and check its status
539 543
540 544 $ touch c
541 545 $ hg status
542 546
543 547 Copy kwfile to keyword ignored file unexpanding keywords
544 548
545 549 $ hg --verbose copy a i
546 550 copying a to i
547 551 overwriting i shrinking keywords
548 552 $ head -n 1 i
549 553 expand $Id$
550 554 $ hg forget i
551 555 $ rm i
552 556
553 557 Copy ignored file to ignored file: no overwriting
554 558
555 559 $ hg --verbose copy b i
556 560 copying b to i
557 561 $ hg forget i
558 562 $ rm i
559 563
560 564 cp symlink file; hg cp -A symlink file (part1)
561 565 - copied symlink points to kwfile: overwrite
562 566
563 567 $ cp sym i
564 568 $ ls -l i
565 569 -rw-r--r--* (glob)
566 570 $ head -1 i
567 571 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
568 572 $ hg copy --after --verbose sym i
569 573 copying sym to i
570 574 overwriting i shrinking keywords
571 575 $ head -1 i
572 576 expand $Id$
573 577 $ hg forget i
574 578 $ rm i
575 579
576 580 Test different options of hg kwfiles
577 581
578 582 $ hg kwfiles
579 583 a
580 584 c
581 585 $ hg -v kwfiles --ignore
582 586 I b
583 587 I sym
584 588 $ hg kwfiles --all
585 589 K a
586 590 K c
587 591 I b
588 592 I sym
589 593
590 594 Diff specific revision
591 595
592 596 $ hg diff --rev 1
593 597 diff -r ef63ca68695b c
594 598 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
595 599 +++ b/c * (glob)
596 600 @@ -0,0 +1,3 @@
597 601 +expand $Id$
598 602 +do not process $Id:
599 603 +xxx $
600 604
601 605 Status after rollback:
602 606
603 607 $ hg rollback
604 rolling back to revision 1 (undo commit)
608 repository tip rolled back to revision 1 (undo commit)
609 working directory now based on revision 1
605 610 $ hg status
606 611 A c
607 612 $ hg update --clean
608 613 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
609 614
610 615 cp symlink file; hg cp -A symlink file (part2)
611 616 - copied symlink points to kw ignored file: do not overwrite
612 617
613 618 $ cat a > i
614 619 $ ln -s i symignored
615 620 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
616 621 $ cp symignored x
617 622 $ hg copy --after --verbose symignored x
618 623 copying symignored to x
619 624 $ head -n 1 x
620 625 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
621 626 $ hg forget x
622 627 $ rm x
623 628
624 629 $ hg rollback
625 rolling back to revision 1 (undo commit)
630 repository tip rolled back to revision 1 (undo commit)
631 working directory now based on revision 1
626 632 $ hg update --clean
627 633 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 634 $ rm i symignored
629 635
630 636 Custom keywordmaps as argument to kwdemo
631 637
632 638 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
633 639 [extensions]
634 640 keyword =
635 641 [keyword]
636 642 ** =
637 643 b = ignore
638 644 demo.txt =
639 645 i = ignore
640 646 [keywordset]
641 647 svn = False
642 648 [keywordmaps]
643 649 Xinfo = {author}: {desc}
644 650 $Xinfo: test: hg keyword configuration and expansion example $
645 651
646 652 Configure custom keywordmaps
647 653
648 654 $ cat <<EOF >>$HGRCPATH
649 655 > [keywordmaps]
650 656 > Id = {file} {node|short} {date|rfc822date} {author|user}
651 657 > Xinfo = {author}: {desc}
652 658 > EOF
653 659
654 660 Cat and hg cat files before custom expansion
655 661
656 662 $ cat a b
657 663 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
658 664 do not process $Id:
659 665 xxx $
660 666 ignore $Id$
661 667 $ hg cat sym a b && echo
662 668 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
663 669 do not process $Id:
664 670 xxx $
665 671 ignore $Id$
666 672 a
667 673
668 674 Write custom keyword and prepare multiline commit message
669 675
670 676 $ echo '$Xinfo$' >> a
671 677 $ cat <<EOF >> log
672 678 > firstline
673 679 > secondline
674 680 > EOF
675 681
676 682 Interrupted commit should not change state
677 683
678 684 $ hg commit
679 685 abort: empty commit message
680 686 [255]
681 687 $ hg status
682 688 M a
683 689 ? c
684 690 ? log
685 691
686 692 Commit with multiline message and custom expansion
687 693
688 694 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
689 695 a
690 696 overwriting a expanding keywords
691 697 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
692 698 $ rm log
693 699
694 700 Stat, verify and show custom expansion (firstline)
695 701
696 702 $ hg status
697 703 ? c
698 704 $ hg verify
699 705 checking changesets
700 706 checking manifests
701 707 crosschecking files in changesets and manifests
702 708 checking files
703 709 3 files, 3 changesets, 4 total revisions
704 710 $ cat a b
705 711 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
706 712 do not process $Id:
707 713 xxx $
708 714 $Xinfo: User Name <user@example.com>: firstline $
709 715 ignore $Id$
710 716 $ hg cat sym a b && echo
711 717 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
712 718 do not process $Id:
713 719 xxx $
714 720 $Xinfo: User Name <user@example.com>: firstline $
715 721 ignore $Id$
716 722 a
717 723
718 724 annotate
719 725
720 726 $ hg annotate a
721 727 1: expand $Id$
722 728 1: do not process $Id:
723 729 1: xxx $
724 730 2: $Xinfo$
725 731
726 732 remove with status checks
727 733
728 734 $ hg debugrebuildstate
729 735 $ hg remove a
730 736 $ hg --debug commit -m rma
731 737 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
732 738 $ hg status
733 739 ? c
734 740
735 741 Rollback, revert, and check expansion
736 742
737 743 $ hg rollback
738 rolling back to revision 2 (undo commit)
744 repository tip rolled back to revision 2 (undo commit)
745 working directory now based on revision 2
739 746 $ hg status
740 747 R a
741 748 ? c
742 749 $ hg revert --no-backup --rev tip a
743 750 $ cat a
744 751 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
745 752 do not process $Id:
746 753 xxx $
747 754 $Xinfo: User Name <user@example.com>: firstline $
748 755
749 756 Clone to test global and local configurations
750 757
751 758 $ cd ..
752 759
753 760 Expansion in destinaton with global configuration
754 761
755 762 $ hg --quiet clone Test globalconf
756 763 $ cat globalconf/a
757 764 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
758 765 do not process $Id:
759 766 xxx $
760 767 $Xinfo: User Name <user@example.com>: firstline $
761 768
762 769 No expansion in destination with local configuration in origin only
763 770
764 771 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
765 772 $ cat localconf/a
766 773 expand $Id$
767 774 do not process $Id:
768 775 xxx $
769 776 $Xinfo$
770 777
771 778 Clone to test incoming
772 779
773 780 $ hg clone -r1 Test Test-a
774 781 adding changesets
775 782 adding manifests
776 783 adding file changes
777 784 added 2 changesets with 3 changes to 3 files
778 785 updating to branch default
779 786 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
780 787 $ cd Test-a
781 788 $ cat <<EOF >> .hg/hgrc
782 789 > [paths]
783 790 > default = ../Test
784 791 > EOF
785 792 $ hg incoming
786 793 comparing with $TESTTMP/Test
787 794 searching for changes
788 795 changeset: 2:bb948857c743
789 796 tag: tip
790 797 user: User Name <user@example.com>
791 798 date: Thu Jan 01 00:00:02 1970 +0000
792 799 summary: firstline
793 800
794 801 Imported patch should not be rejected
795 802
796 803 $ python -c \
797 804 > 'import re; s=re.sub("(Id.*)","\\1 rejecttest",open("a").read()); open("a","wb").write(s);'
798 805 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
799 806 a
800 807 overwriting a expanding keywords
801 808 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
802 809 $ hg export -o ../rejecttest.diff tip
803 810 $ cd ../Test
804 811 $ hg import ../rejecttest.diff
805 812 applying ../rejecttest.diff
806 813 $ cat a b
807 814 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
808 815 do not process $Id: rejecttest
809 816 xxx $
810 817 $Xinfo: User Name <user@example.com>: rejects? $
811 818 ignore $Id$
812 819
813 820 $ hg rollback
814 rolling back to revision 2 (undo commit)
821 repository tip rolled back to revision 2 (undo commit)
822 working directory now based on revision 2
815 823 $ hg update --clean
816 824 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
817 825
818 826 kwexpand/kwshrink on selected files
819 827
820 828 $ mkdir x
821 829 $ hg copy a x/a
822 830 $ hg --verbose kwshrink a
823 831 overwriting a shrinking keywords
824 832 $ hg status a
825 833 $ hg --verbose kwexpand a
826 834 overwriting a expanding keywords
827 835 $ hg status a
828 836
829 837 kwexpand x/a should abort
830 838
831 839 $ hg --verbose kwexpand x/a
832 840 abort: outstanding uncommitted changes
833 841 [255]
834 842 $ cd x
835 843 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
836 844 x/a
837 845 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
838 846 overwriting x/a expanding keywords
839 847 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
840 848 $ cat a
841 849 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
842 850 do not process $Id:
843 851 xxx $
844 852 $Xinfo: User Name <user@example.com>: xa $
845 853
846 854 kwshrink a inside directory x
847 855
848 856 $ hg --verbose kwshrink a
849 857 overwriting x/a shrinking keywords
850 858 $ cat a
851 859 expand $Id$
852 860 do not process $Id:
853 861 xxx $
854 862 $Xinfo$
855 863 $ cd ..
856 864
857 865 kwexpand nonexistent
858 866
859 867 $ hg kwexpand nonexistent
860 868 nonexistent:* (glob)
861 869
862 870
863 871 hg serve
864 872 - expand with hgweb file
865 873 - no expansion with hgweb annotate/changeset/filediff
866 874 - check errors
867 875
868 876 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
869 877 $ cat hg.pid >> $DAEMON_PIDS
870 878 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
871 879 200 Script output follows
872 880
873 881 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
874 882 do not process $Id:
875 883 xxx $
876 884 $Xinfo: User Name <user@example.com>: firstline $
877 885 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
878 886 200 Script output follows
879 887
880 888
881 889 user@1: expand $Id$
882 890 user@1: do not process $Id:
883 891 user@1: xxx $
884 892 user@2: $Xinfo$
885 893
886 894
887 895
888 896
889 897 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
890 898 200 Script output follows
891 899
892 900
893 901 # HG changeset patch
894 902 # User User Name <user@example.com>
895 903 # Date 3 0
896 904 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
897 905 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
898 906 xa
899 907
900 908 diff -r bb948857c743 -r b4560182a3f9 x/a
901 909 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
902 910 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
903 911 @@ -0,0 +1,4 @@
904 912 +expand $Id$
905 913 +do not process $Id:
906 914 +xxx $
907 915 +$Xinfo$
908 916
909 917 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
910 918 200 Script output follows
911 919
912 920
913 921 diff -r ef63ca68695b -r bb948857c743 a
914 922 --- a/a Thu Jan 01 00:00:00 1970 +0000
915 923 +++ b/a Thu Jan 01 00:00:02 1970 +0000
916 924 @@ -1,3 +1,4 @@
917 925 expand $Id$
918 926 do not process $Id:
919 927 xxx $
920 928 +$Xinfo$
921 929
922 930
923 931
924 932
925 933 $ cat errors.log
926 934
927 935 Prepare merge and resolve tests
928 936
929 937 $ echo '$Id$' > m
930 938 $ hg add m
931 939 $ hg commit -m 4kw
932 940 $ echo foo >> m
933 941 $ hg commit -m 5foo
934 942
935 943 simplemerge
936 944
937 945 $ hg update 4
938 946 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
939 947 $ echo foo >> m
940 948 $ hg commit -m 6foo
941 949 created new head
942 950 $ hg merge
943 951 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 952 (branch merge, don't forget to commit)
945 953 $ hg commit -m simplemerge
946 954 $ cat m
947 955 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
948 956 foo
949 957
950 958 conflict: keyword should stay outside conflict zone
951 959
952 960 $ hg update 4
953 961 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
954 962 $ echo bar >> m
955 963 $ hg commit -m 8bar
956 964 created new head
957 965 $ hg merge
958 966 merging m
959 967 warning: conflicts during merge.
960 968 merging m failed!
961 969 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
962 970 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
963 971 [1]
964 972 $ cat m
965 973 $Id$
966 974 <<<<<<< local
967 975 bar
968 976 =======
969 977 foo
970 978 >>>>>>> other
971 979
972 980 resolve to local
973 981
974 982 $ HGMERGE=internal:local hg resolve -a
975 983 $ hg commit -m localresolve
976 984 $ cat m
977 985 $Id: m 41efa6d38e9b Thu, 01 Jan 1970 00:00:00 +0000 test $
978 986 bar
979 987
980 988 Test restricted mode with transplant -b
981 989
982 990 $ hg update 6
983 991 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
984 992 $ hg branch foo
985 993 marked working directory as branch foo
986 994 $ mv a a.bak
987 995 $ echo foobranch > a
988 996 $ cat a.bak >> a
989 997 $ rm a.bak
990 998 $ hg commit -m 9foobranch
991 999 $ hg update default
992 1000 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
993 1001 $ hg -y transplant -b foo tip
994 1002 applying 4aa30d025d50
995 1003 4aa30d025d50 transplanted to 5a4da427c162
996 1004
997 1005 Expansion in changeset but not in file
998 1006
999 1007 $ hg tip -p
1000 1008 changeset: 11:5a4da427c162
1001 1009 tag: tip
1002 1010 parent: 9:41efa6d38e9b
1003 1011 user: test
1004 1012 date: Thu Jan 01 00:00:00 1970 +0000
1005 1013 summary: 9foobranch
1006 1014
1007 1015 diff -r 41efa6d38e9b -r 5a4da427c162 a
1008 1016 --- a/a Thu Jan 01 00:00:00 1970 +0000
1009 1017 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1010 1018 @@ -1,3 +1,4 @@
1011 1019 +foobranch
1012 1020 expand $Id$
1013 1021 do not process $Id:
1014 1022 xxx $
1015 1023
1016 1024 $ head -n 2 a
1017 1025 foobranch
1018 1026 expand $Id: a 5a4da427c162 Thu, 01 Jan 1970 00:00:00 +0000 test $
1019 1027
1020 1028 Turn off expansion
1021 1029
1022 1030 $ hg -q rollback
1023 1031 $ hg -q update -C
1024 1032
1025 1033 kwshrink with unknown file u
1026 1034
1027 1035 $ cp a u
1028 1036 $ hg --verbose kwshrink
1029 1037 overwriting a shrinking keywords
1030 1038 overwriting m shrinking keywords
1031 1039 overwriting x/a shrinking keywords
1032 1040
1033 1041 Keywords shrunk in working directory, but not yet disabled
1034 1042 - cat shows unexpanded keywords
1035 1043 - hg cat shows expanded keywords
1036 1044
1037 1045 $ cat a b
1038 1046 expand $Id$
1039 1047 do not process $Id:
1040 1048 xxx $
1041 1049 $Xinfo$
1042 1050 ignore $Id$
1043 1051 $ hg cat sym a b && echo
1044 1052 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1045 1053 do not process $Id:
1046 1054 xxx $
1047 1055 $Xinfo: User Name <user@example.com>: firstline $
1048 1056 ignore $Id$
1049 1057 a
1050 1058
1051 1059 Now disable keyword expansion
1052 1060
1053 1061 $ rm "$HGRCPATH"
1054 1062 $ cat a b
1055 1063 expand $Id$
1056 1064 do not process $Id:
1057 1065 xxx $
1058 1066 $Xinfo$
1059 1067 ignore $Id$
1060 1068 $ hg cat sym a b && echo
1061 1069 expand $Id$
1062 1070 do not process $Id:
1063 1071 xxx $
1064 1072 $Xinfo$
1065 1073 ignore $Id$
1066 1074 a
@@ -1,319 +1,320 b''
1 1 $ branchcache=.hg/cache/branchheads
2 2
3 3 $ hg init t
4 4 $ cd t
5 5
6 6 $ hg branches
7 7 $ echo foo > a
8 8 $ hg add a
9 9 $ hg ci -m "initial"
10 10 $ hg branch foo
11 11 marked working directory as branch foo
12 12 $ hg branch
13 13 foo
14 14 $ hg ci -m "add branch name"
15 15 $ hg branch bar
16 16 marked working directory as branch bar
17 17 $ hg ci -m "change branch name"
18 18
19 19 Branch shadowing:
20 20
21 21 $ hg branch default
22 22 abort: a branch of the same name already exists (use 'hg update' to switch to it)
23 23 [255]
24 24
25 25 $ hg branch -f default
26 26 marked working directory as branch default
27 27
28 28 $ hg ci -m "clear branch name"
29 29 created new head
30 30
31 31 There should be only one default branch head
32 32
33 33 $ hg heads .
34 34 changeset: 3:9d567d0b51f9
35 35 tag: tip
36 36 user: test
37 37 date: Thu Jan 01 00:00:00 1970 +0000
38 38 summary: clear branch name
39 39
40 40
41 41 $ hg co foo
42 42 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ hg branch
44 44 foo
45 45 $ echo bleah > a
46 46 $ hg ci -m "modify a branch"
47 47
48 48 $ hg merge default
49 49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 50 (branch merge, don't forget to commit)
51 51
52 52 $ hg branch
53 53 foo
54 54 $ hg ci -m "merge"
55 55
56 56 $ hg log
57 57 changeset: 5:dc140083783b
58 58 branch: foo
59 59 tag: tip
60 60 parent: 4:98d14f698afe
61 61 parent: 3:9d567d0b51f9
62 62 user: test
63 63 date: Thu Jan 01 00:00:00 1970 +0000
64 64 summary: merge
65 65
66 66 changeset: 4:98d14f698afe
67 67 branch: foo
68 68 parent: 1:0079f24813e2
69 69 user: test
70 70 date: Thu Jan 01 00:00:00 1970 +0000
71 71 summary: modify a branch
72 72
73 73 changeset: 3:9d567d0b51f9
74 74 user: test
75 75 date: Thu Jan 01 00:00:00 1970 +0000
76 76 summary: clear branch name
77 77
78 78 changeset: 2:ed2bbf4e0102
79 79 branch: bar
80 80 user: test
81 81 date: Thu Jan 01 00:00:00 1970 +0000
82 82 summary: change branch name
83 83
84 84 changeset: 1:0079f24813e2
85 85 branch: foo
86 86 user: test
87 87 date: Thu Jan 01 00:00:00 1970 +0000
88 88 summary: add branch name
89 89
90 90 changeset: 0:db01e8ea3388
91 91 user: test
92 92 date: Thu Jan 01 00:00:00 1970 +0000
93 93 summary: initial
94 94
95 95 $ hg branches
96 96 foo 5:dc140083783b
97 97 default 3:9d567d0b51f9 (inactive)
98 98 bar 2:ed2bbf4e0102 (inactive)
99 99
100 100 $ hg branches -q
101 101 foo
102 102 default
103 103 bar
104 104
105 105 Test for invalid branch cache:
106 106
107 107 $ hg rollback
108 rolling back to revision 4 (undo commit)
108 repository tip rolled back to revision 4 (undo commit)
109 working directory now based on revision 4 and 3
109 110
110 111 $ cp $branchcache .hg/bc-invalid
111 112
112 113 $ hg log -r foo
113 114 changeset: 4:98d14f698afe
114 115 branch: foo
115 116 tag: tip
116 117 parent: 1:0079f24813e2
117 118 user: test
118 119 date: Thu Jan 01 00:00:00 1970 +0000
119 120 summary: modify a branch
120 121
121 122 $ cp .hg/bc-invalid $branchcache
122 123
123 124 $ hg --debug log -r foo
124 125 invalidating branch cache (tip differs)
125 126 changeset: 4:98d14f698afeaff8cb612dcf215ce95e639effc3
126 127 branch: foo
127 128 tag: tip
128 129 parent: 1:0079f24813e2b73a891577c243684c5066347bc8
129 130 parent: -1:0000000000000000000000000000000000000000
130 131 manifest: 4:d01b250baaa05909152f7ae07d7a649deea0df9a
131 132 user: test
132 133 date: Thu Jan 01 00:00:00 1970 +0000
133 134 files: a
134 135 extra: branch=foo
135 136 description:
136 137 modify a branch
137 138
138 139
139 140 $ rm $branchcache
140 141 $ echo corrupted > $branchcache
141 142
142 143 $ hg log -qr foo
143 144 4:98d14f698afe
144 145
145 146 $ cat $branchcache
146 147 98d14f698afeaff8cb612dcf215ce95e639effc3 4
147 148 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
148 149 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
149 150 ed2bbf4e01029020711be82ca905283e883f0e11 bar
150 151
151 152 Push should update the branch cache:
152 153
153 154 $ hg init ../target
154 155
155 156 Pushing just rev 0:
156 157
157 158 $ hg push -qr 0 ../target
158 159
159 160 $ cat ../target/$branchcache
160 161 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
161 162 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
162 163
163 164 Pushing everything:
164 165
165 166 $ hg push -qf ../target
166 167
167 168 $ cat ../target/$branchcache
168 169 98d14f698afeaff8cb612dcf215ce95e639effc3 4
169 170 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
170 171 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
171 172 ed2bbf4e01029020711be82ca905283e883f0e11 bar
172 173
173 174 Update with no arguments: tipmost revision of the current branch:
174 175
175 176 $ hg up -q -C 0
176 177 $ hg up -q
177 178 $ hg id
178 179 9d567d0b51f9
179 180
180 181 $ hg up -q 1
181 182 $ hg up -q
182 183 $ hg id
183 184 98d14f698afe (foo) tip
184 185
185 186 $ hg branch foobar
186 187 marked working directory as branch foobar
187 188
188 189 $ hg up
189 190 abort: branch foobar not found
190 191 [255]
191 192
192 193 Fastforward merge:
193 194
194 195 $ hg branch ff
195 196 marked working directory as branch ff
196 197
197 198 $ echo ff > ff
198 199 $ hg ci -Am'fast forward'
199 200 adding ff
200 201
201 202 $ hg up foo
202 203 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
203 204
204 205 $ hg merge ff
205 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 207 (branch merge, don't forget to commit)
207 208
208 209 $ hg branch
209 210 foo
210 211 $ hg commit -m'Merge ff into foo'
211 212 created new head
212 213 $ hg parents
213 214 changeset: 6:6af8030670c9
214 215 branch: foo
215 216 tag: tip
216 217 user: test
217 218 date: Thu Jan 01 00:00:00 1970 +0000
218 219 summary: Merge ff into foo
219 220
220 221 $ hg manifest
221 222 a
222 223 ff
223 224
224 225
225 226 Test merging, add 3 default heads and one test head:
226 227
227 228 $ cd ..
228 229 $ hg init merges
229 230 $ cd merges
230 231 $ echo a > a
231 232 $ hg ci -Ama
232 233 adding a
233 234
234 235 $ echo b > b
235 236 $ hg ci -Amb
236 237 adding b
237 238
238 239 $ hg up 0
239 240 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
240 241 $ echo c > c
241 242 $ hg ci -Amc
242 243 adding c
243 244 created new head
244 245
245 246 $ hg up 0
246 247 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
247 248 $ echo d > d
248 249 $ hg ci -Amd
249 250 adding d
250 251 created new head
251 252
252 253 $ hg up 0
253 254 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
254 255 $ hg branch test
255 256 marked working directory as branch test
256 257 $ echo e >> e
257 258 $ hg ci -Ame
258 259 adding e
259 260
260 261 $ hg log
261 262 changeset: 4:3a1e01ed1df4
262 263 branch: test
263 264 tag: tip
264 265 parent: 0:cb9a9f314b8b
265 266 user: test
266 267 date: Thu Jan 01 00:00:00 1970 +0000
267 268 summary: e
268 269
269 270 changeset: 3:980f7dc84c29
270 271 parent: 0:cb9a9f314b8b
271 272 user: test
272 273 date: Thu Jan 01 00:00:00 1970 +0000
273 274 summary: d
274 275
275 276 changeset: 2:d36c0562f908
276 277 parent: 0:cb9a9f314b8b
277 278 user: test
278 279 date: Thu Jan 01 00:00:00 1970 +0000
279 280 summary: c
280 281
281 282 changeset: 1:d2ae7f538514
282 283 user: test
283 284 date: Thu Jan 01 00:00:00 1970 +0000
284 285 summary: b
285 286
286 287 changeset: 0:cb9a9f314b8b
287 288 user: test
288 289 date: Thu Jan 01 00:00:00 1970 +0000
289 290 summary: a
290 291
291 292 Implicit merge with test branch as parent:
292 293
293 294 $ hg merge
294 295 abort: branch 'test' has one head - please merge with an explicit rev
295 296 (run 'hg heads' to see all heads)
296 297 [255]
297 298 $ hg up -C default
298 299 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
299 300
300 301 Implicit merge with default branch as parent:
301 302
302 303 $ hg merge
303 304 abort: branch 'default' has 3 heads - please merge with an explicit rev
304 305 (run 'hg heads .' to see heads)
305 306 [255]
306 307
307 308 3 branch heads, explicit merge required:
308 309
309 310 $ hg merge 2
310 311 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 312 (branch merge, don't forget to commit)
312 313 $ hg ci -m merge
313 314
314 315 2 branch heads, implicit merge works:
315 316
316 317 $ hg merge
317 318 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 319 (branch merge, don't forget to commit)
319 320
@@ -1,350 +1,353 b''
1 1
2 2 $ cat <<EOF >> $HGRCPATH
3 3 > [extensions]
4 4 > notify=
5 5 >
6 6 > [hooks]
7 7 > incoming.notify = python:hgext.notify.hook
8 8 >
9 9 > [notify]
10 10 > sources = pull
11 11 > diffstat = False
12 12 >
13 13 > [usersubs]
14 14 > foo@bar = *
15 15 >
16 16 > [reposubs]
17 17 > * = baz
18 18 > EOF
19 19 $ hg help notify
20 20 notify extension - hooks for sending email notifications at commit/push time
21 21
22 22 Subscriptions can be managed through a hgrc file. Default mode is to print
23 23 messages to stdout, for testing and configuring.
24 24
25 25 To use, configure the notify extension and enable it in hgrc like this:
26 26
27 27 [extensions]
28 28 notify =
29 29
30 30 [hooks]
31 31 # one email for each incoming changeset
32 32 incoming.notify = python:hgext.notify.hook
33 33 # batch emails when many changesets incoming at one time
34 34 changegroup.notify = python:hgext.notify.hook
35 35
36 36 [notify]
37 37 # config items go here
38 38
39 39 Required configuration items:
40 40
41 41 config = /path/to/file # file containing subscriptions
42 42
43 43 Optional configuration items:
44 44
45 45 test = True # print messages to stdout for testing
46 46 strip = 3 # number of slashes to strip for url paths
47 47 domain = example.com # domain to use if committer missing domain
48 48 style = ... # style file to use when formatting email
49 49 template = ... # template to use when formatting email
50 50 incoming = ... # template to use when run as incoming hook
51 51 changegroup = ... # template when run as changegroup hook
52 52 maxdiff = 300 # max lines of diffs to include (0=none, -1=all)
53 53 maxsubject = 67 # truncate subject line longer than this
54 54 diffstat = True # add a diffstat before the diff content
55 55 sources = serve # notify if source of incoming changes in this list
56 56 # (serve == ssh or http, push, pull, bundle)
57 57 merge = False # send notification for merges (default True)
58 58 [email]
59 59 from = user@host.com # email address to send as if none given
60 60 [web]
61 61 baseurl = http://hgserver/... # root of hg web site for browsing commits
62 62
63 63 The notify config file has same format as a regular hgrc file. It has two
64 64 sections so you can express subscriptions in whatever way is handier for you.
65 65
66 66 [usersubs]
67 67 # key is subscriber email, value is ","-separated list of glob patterns
68 68 user@host = pattern
69 69
70 70 [reposubs]
71 71 # key is glob pattern, value is ","-separated list of subscriber emails
72 72 pattern = user@host
73 73
74 74 Glob patterns are matched against path to repository root.
75 75
76 76 If you like, you can put notify config file in repository that users can push
77 77 changes to, they can manage their own subscriptions.
78 78
79 79 no commands defined
80 80 $ hg init a
81 81 $ echo a > a/a
82 82
83 83 commit
84 84
85 85 $ hg --cwd a commit -Ama -d '0 0'
86 86 adding a
87 87
88 88
89 89 clone
90 90
91 91 $ hg --traceback clone a b
92 92 updating to branch default
93 93 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 94 $ echo a >> a/a
95 95
96 96 commit
97 97
98 98 $ hg --traceback --cwd a commit -Amb -d '1 0'
99 99
100 100 on Mac OS X 10.5 the tmp path is very long so would get stripped in the subject line
101 101
102 102 $ cat <<EOF >> $HGRCPATH
103 103 > [notify]
104 104 > maxsubject = 200
105 105 > EOF
106 106
107 107 the python call below wraps continuation lines, which appear on Mac OS X 10.5 because
108 108 of the very long subject line
109 109 pull (minimal config)
110 110
111 111 $ hg --traceback --cwd b pull ../a | \
112 112 > python -c 'import sys,re; print re.sub("\n[\t ]", " ", sys.stdin.read()),'
113 113 pulling from ../a
114 114 searching for changes
115 115 adding changesets
116 116 adding manifests
117 117 adding file changes
118 118 added 1 changesets with 1 changes to 1 files
119 119 Content-Type: text/plain; charset="us-ascii"
120 120 MIME-Version: 1.0
121 121 Content-Transfer-Encoding: 7bit
122 122 Date: * (glob)
123 123 Subject: changeset in $TESTTMP/b: b
124 124 From: test
125 125 X-Hg-Notification: changeset 0647d048b600
126 126 Message-Id: <*> (glob)
127 127 To: baz, foo@bar
128 128
129 129 changeset 0647d048b600 in $TESTTMP/b
130 130 details: $TESTTMP/b?cmd=changeset;node=0647d048b600
131 131 description: b
132 132
133 133 diffs (6 lines):
134 134
135 135 diff -r cb9a9f314b8b -r 0647d048b600 a
136 136 --- a/a Thu Jan 01 00:00:00 1970 +0000
137 137 +++ b/a Thu Jan 01 00:00:01 1970 +0000
138 138 @@ -1,1 +1,2 @@ a
139 139 +a
140 140 (run 'hg update' to get a working copy)
141 141 $ cat <<EOF >> $HGRCPATH
142 142 > [notify]
143 143 > config = `pwd`/.notify.conf
144 144 > domain = test.com
145 145 > strip = 42
146 146 > template = Subject: {desc|firstline|strip}\nFrom: {author}\nX-Test: foo\n\nchangeset {node|short} in {webroot}\ndescription:\n\t{desc|tabindent|strip}
147 147 >
148 148 > [web]
149 149 > baseurl = http://test/
150 150 > EOF
151 151
152 152 fail for config file is missing
153 153
154 154 $ hg --cwd b rollback
155 rolling back to revision 0 (undo pull)
155 repository tip rolled back to revision 0 (undo pull)
156 working directory now based on revision 0
156 157 $ hg --cwd b pull ../a 2>&1 | grep 'error.*\.notify\.conf' > /dev/null && echo pull failed
157 158 pull failed
158 159 $ touch ".notify.conf"
159 160
160 161 pull
161 162
162 163 $ hg --cwd b rollback
163 rolling back to revision 0 (undo pull)
164 repository tip rolled back to revision 0 (undo pull)
165 working directory now based on revision 0
164 166 $ hg --traceback --cwd b pull ../a | \
165 167 > python -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),'
166 168 pulling from ../a
167 169 searching for changes
168 170 adding changesets
169 171 adding manifests
170 172 adding file changes
171 173 added 1 changesets with 1 changes to 1 files
172 174 Content-Type: text/plain; charset="us-ascii"
173 175 MIME-Version: 1.0
174 176 Content-Transfer-Encoding: 7bit
175 177 X-Test: foo
176 178 Date: * (glob)
177 179 Subject: b
178 180 From: test@test.com
179 181 X-Hg-Notification: changeset 0647d048b600
180 182 Message-Id: <*> (glob)
181 183 To: baz@test.com, foo@bar
182 184
183 185 changeset 0647d048b600 in b
184 186 description: b
185 187 diffs (6 lines):
186 188
187 189 diff -r cb9a9f314b8b -r 0647d048b600 a
188 190 --- a/a Thu Jan 01 00:00:00 1970 +0000
189 191 +++ b/a Thu Jan 01 00:00:01 1970 +0000
190 192 @@ -1,1 +1,2 @@
191 193 a
192 194 +a
193 195 (run 'hg update' to get a working copy)
194 196
195 197 $ cat << EOF >> $HGRCPATH
196 198 > [hooks]
197 199 > incoming.notify = python:hgext.notify.hook
198 200 >
199 201 > [notify]
200 202 > sources = pull
201 203 > diffstat = True
202 204 > EOF
203 205
204 206 pull
205 207
206 208 $ hg --cwd b rollback
207 rolling back to revision 0 (undo pull)
209 repository tip rolled back to revision 0 (undo pull)
210 working directory now based on revision 0
208 211 $ hg --traceback --cwd b pull ../a | \
209 212 > python -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),'
210 213 pulling from ../a
211 214 searching for changes
212 215 adding changesets
213 216 adding manifests
214 217 adding file changes
215 218 added 1 changesets with 1 changes to 1 files
216 219 Content-Type: text/plain; charset="us-ascii"
217 220 MIME-Version: 1.0
218 221 Content-Transfer-Encoding: 7bit
219 222 X-Test: foo
220 223 Date: * (glob)
221 224 Subject: b
222 225 From: test@test.com
223 226 X-Hg-Notification: changeset 0647d048b600
224 227 Message-Id: <*> (glob)
225 228 To: baz@test.com, foo@bar
226 229
227 230 changeset 0647d048b600 in b
228 231 description: b
229 232 diffstat:
230 233
231 234 a | 1 +
232 235 1 files changed, 1 insertions(+), 0 deletions(-)
233 236
234 237 diffs (6 lines):
235 238
236 239 diff -r cb9a9f314b8b -r 0647d048b600 a
237 240 --- a/a Thu Jan 01 00:00:00 1970 +0000
238 241 +++ b/a Thu Jan 01 00:00:01 1970 +0000
239 242 @@ -1,1 +1,2 @@
240 243 a
241 244 +a
242 245 (run 'hg update' to get a working copy)
243 246
244 247 test merge
245 248
246 249 $ cd a
247 250 $ hg up -C 0
248 251 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 252 $ echo a >> a
250 253 $ hg ci -Am adda2 -d '2 0'
251 254 created new head
252 255 $ hg merge
253 256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 257 (branch merge, don't forget to commit)
255 258 $ hg ci -m merge -d '3 0'
256 259 $ cd ..
257 260 $ hg --traceback --cwd b pull ../a | \
258 261 > python -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),'
259 262 pulling from ../a
260 263 searching for changes
261 264 adding changesets
262 265 adding manifests
263 266 adding file changes
264 267 added 2 changesets with 0 changes to 0 files
265 268 Content-Type: text/plain; charset="us-ascii"
266 269 MIME-Version: 1.0
267 270 Content-Transfer-Encoding: 7bit
268 271 X-Test: foo
269 272 Date: * (glob)
270 273 Subject: adda2
271 274 From: test@test.com
272 275 X-Hg-Notification: changeset 0a184ce6067f
273 276 Message-Id: <*> (glob)
274 277 To: baz@test.com, foo@bar
275 278
276 279 changeset 0a184ce6067f in b
277 280 description: adda2
278 281 diffstat:
279 282
280 283 a | 1 +
281 284 1 files changed, 1 insertions(+), 0 deletions(-)
282 285
283 286 diffs (6 lines):
284 287
285 288 diff -r cb9a9f314b8b -r 0a184ce6067f a
286 289 --- a/a Thu Jan 01 00:00:00 1970 +0000
287 290 +++ b/a Thu Jan 01 00:00:02 1970 +0000
288 291 @@ -1,1 +1,2 @@
289 292 a
290 293 +a
291 294 Content-Type: text/plain; charset="us-ascii"
292 295 MIME-Version: 1.0
293 296 Content-Transfer-Encoding: 7bit
294 297 X-Test: foo
295 298 Date: * (glob)
296 299 Subject: merge
297 300 From: test@test.com
298 301 X-Hg-Notification: changeset 22c88b85aa27
299 302 Message-Id: <*> (glob)
300 303 To: baz@test.com, foo@bar
301 304
302 305 changeset 22c88b85aa27 in b
303 306 description: merge
304 307 (run 'hg update' to get a working copy)
305 308
306 309 truncate multi-byte subject
307 310
308 311 $ cat <<EOF >> $HGRCPATH
309 312 > [notify]
310 313 > maxsubject = 4
311 314 > EOF
312 315 $ echo a >> a/a
313 316 $ hg --cwd a --encoding utf-8 commit -A -d '0 0' \
314 317 > -m `python -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'`
315 318 $ hg --traceback --cwd b --encoding utf-8 pull ../a | \
316 319 > python -c 'import sys,re; print re.sub("\n\t", " ", sys.stdin.read()),'
317 320 pulling from ../a
318 321 searching for changes
319 322 adding changesets
320 323 adding manifests
321 324 adding file changes
322 325 added 1 changesets with 1 changes to 1 files
323 326 Content-Type: text/plain; charset="us-ascii"
324 327 MIME-Version: 1.0
325 328 Content-Transfer-Encoding: 8bit
326 329 X-Test: foo
327 330 Date: * (glob)
328 331 Subject: \xc3\xa0... (esc)
329 332 From: test@test.com
330 333 X-Hg-Notification: changeset 4a47f01c1356
331 334 Message-Id: <*> (glob)
332 335 To: baz@test.com, foo@bar
333 336
334 337 changeset 4a47f01c1356 in b
335 338 description: \xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4 (esc)
336 339 diffstat:
337 340
338 341 a | 1 +
339 342 1 files changed, 1 insertions(+), 0 deletions(-)
340 343
341 344 diffs (7 lines):
342 345
343 346 diff -r 22c88b85aa27 -r 4a47f01c1356 a
344 347 --- a/a Thu Jan 01 00:00:03 1970 +0000
345 348 +++ b/a Thu Jan 01 00:00:00 1970 +0000
346 349 @@ -1,2 +1,3 @@
347 350 a
348 351 a
349 352 +a
350 353 (run 'hg update' to get a working copy)
@@ -1,72 +1,73 b''
1 1 $ hg init repo
2 2 $ cd repo
3 3 $ echo foo > foo
4 4 $ hg ci -qAm 'add foo'
5 5 $ echo >> foo
6 6 $ hg ci -m 'change foo'
7 7 $ hg up -qC 0
8 8 $ echo bar > bar
9 9 $ hg ci -qAm 'add bar'
10 10
11 11 $ hg log
12 12 changeset: 2:effea6de0384
13 13 tag: tip
14 14 parent: 0:bbd179dfa0a7
15 15 user: test
16 16 date: Thu Jan 01 00:00:00 1970 +0000
17 17 summary: add bar
18 18
19 19 changeset: 1:ed1b79f46b9a
20 20 user: test
21 21 date: Thu Jan 01 00:00:00 1970 +0000
22 22 summary: change foo
23 23
24 24 changeset: 0:bbd179dfa0a7
25 25 user: test
26 26 date: Thu Jan 01 00:00:00 1970 +0000
27 27 summary: add foo
28 28
29 29 $ cd ..
30 30 $ hg init copy
31 31 $ cd copy
32 32
33 33 Pull a missing revision:
34 34
35 35 $ hg pull -qr missing ../repo
36 36 abort: unknown revision 'missing'!
37 37 [255]
38 38
39 39 Pull multiple revisions with update:
40 40
41 41 $ hg pull -qu -r 0 -r 1 ../repo
42 42 $ hg -q parents
43 43 0:bbd179dfa0a7
44 44 $ hg rollback
45 rolling back to revision -1 (undo pull)
45 repository tip rolled back to revision -1 (undo pull)
46 working directory now based on revision -1
46 47
47 48 $ hg pull -qr 0 ../repo
48 49 $ hg log
49 50 changeset: 0:bbd179dfa0a7
50 51 tag: tip
51 52 user: test
52 53 date: Thu Jan 01 00:00:00 1970 +0000
53 54 summary: add foo
54 55
55 56 $ hg pull -qr 1 ../repo
56 57 $ hg log
57 58 changeset: 1:ed1b79f46b9a
58 59 tag: tip
59 60 user: test
60 61 date: Thu Jan 01 00:00:00 1970 +0000
61 62 summary: change foo
62 63
63 64 changeset: 0:bbd179dfa0a7
64 65 user: test
65 66 date: Thu Jan 01 00:00:00 1970 +0000
66 67 summary: add foo
67 68
68 69
69 70 This used to abort: received changelog group is empty:
70 71
71 72 $ hg pull -qr 1 ../repo
72 73
@@ -1,81 +1,81 b''
1 1 $ mkdir test
2 2 $ cd test
3 3
4 4 $ echo foo>foo
5 5 $ hg init
6 6 $ hg addremove
7 7 adding foo
8 8 $ hg commit -m 1
9 9
10 10 $ hg verify
11 11 checking changesets
12 12 checking manifests
13 13 crosschecking files in changesets and manifests
14 14 checking files
15 15 1 files, 1 changesets, 1 total revisions
16 16
17 17 $ hg serve -p $HGPORT -d --pid-file=hg.pid
18 18 $ cat hg.pid >> $DAEMON_PIDS
19 19 $ cd ..
20 20
21 21 $ hg clone --pull http://foo:bar@localhost:$HGPORT/ copy
22 22 requesting all changes
23 23 adding changesets
24 24 adding manifests
25 25 adding file changes
26 26 added 1 changesets with 1 changes to 1 files
27 27 updating to branch default
28 28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 29
30 30 $ cd copy
31 31 $ hg verify
32 32 checking changesets
33 33 checking manifests
34 34 crosschecking files in changesets and manifests
35 35 checking files
36 36 1 files, 1 changesets, 1 total revisions
37 37
38 38 $ hg co
39 39 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 40 $ cat foo
41 41 foo
42 42
43 43 $ hg manifest --debug
44 44 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
45 45
46 46 $ hg pull
47 47 pulling from http://foo:***@localhost:$HGPORT/
48 48 searching for changes
49 49 no changes found
50 50
51 51 $ hg rollback --dry-run --verbose
52 rolling back to revision -1 (undo pull: http://foo:***@localhost:$HGPORT/)
52 repository tip rolled back to revision -1 (undo pull: http://foo:***@localhost:$HGPORT/)
53 53
54 54 Issue622: hg init && hg pull -u URL doesn't checkout default branch
55 55
56 56 $ cd ..
57 57 $ hg init empty
58 58 $ cd empty
59 59 $ hg pull -u ../test
60 60 pulling from ../test
61 61 requesting all changes
62 62 adding changesets
63 63 adding manifests
64 64 adding file changes
65 65 added 1 changesets with 1 changes to 1 files
66 66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67
68 68 Test 'file:' uri handling:
69 69
70 70 $ hg pull -q file://../test-doesnt-exist
71 71 abort: repository /test-doesnt-exist not found!
72 72 [255]
73 73
74 74 $ hg pull -q file:../test
75 75
76 76 It's tricky to make file:// URLs working on every platform with
77 77 regular shell commands.
78 78
79 79 $ URL=`python -c "import os; print 'file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test'"`
80 80 $ hg pull -q "$URL"
81 81
@@ -1,86 +1,87 b''
1 1
2 2 $ hg init test
3 3 $ cd test
4 4 $ echo a > a
5 5 $ hg ci -Ama
6 6 adding a
7 7 $ cd ..
8 8 $ hg clone test test2
9 9 updating to branch default
10 10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 11 $ cd test2
12 12 $ echo a >> a
13 13 $ hg ci -mb
14 14 $ req() {
15 15 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
16 16 > cat hg.pid >> $DAEMON_PIDS
17 17 > hg --cwd ../test2 push http://localhost:$HGPORT/
18 18 > kill `cat hg.pid`
19 19 > echo % serve errors
20 20 > cat errors.log
21 21 > }
22 22 $ cd ../test
23 23
24 24 expect ssl error
25 25
26 26 $ req
27 27 pushing to http://localhost:$HGPORT/
28 28 searching for changes
29 29 remote: ssl required
30 30 % serve errors
31 31
32 32 expect authorization error
33 33
34 34 $ echo '[web]' > .hg/hgrc
35 35 $ echo 'push_ssl = false' >> .hg/hgrc
36 36 $ req
37 37 pushing to http://localhost:$HGPORT/
38 38 searching for changes
39 39 abort: authorization failed
40 40 % serve errors
41 41
42 42 expect authorization error: must have authorized user
43 43
44 44 $ echo 'allow_push = unperson' >> .hg/hgrc
45 45 $ req
46 46 pushing to http://localhost:$HGPORT/
47 47 searching for changes
48 48 abort: authorization failed
49 49 % serve errors
50 50
51 51 expect success
52 52
53 53 $ echo 'allow_push = *' >> .hg/hgrc
54 54 $ echo '[hooks]' >> .hg/hgrc
55 55 $ echo 'changegroup = python "$TESTDIR"/printenv.py changegroup 0' >> .hg/hgrc
56 56 $ req
57 57 pushing to http://localhost:$HGPORT/
58 58 searching for changes
59 59 remote: adding changesets
60 60 remote: adding manifests
61 61 remote: adding file changes
62 62 remote: added 1 changesets with 1 changes to 1 files
63 63 remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_URL=remote:http:*: (glob)
64 64 % serve errors
65 65 $ hg rollback
66 rolling back to revision 0 (undo serve)
66 repository tip rolled back to revision 0 (undo serve)
67 working directory now based on revision 0
67 68
68 69 expect authorization error: all users denied
69 70
70 71 $ echo '[web]' > .hg/hgrc
71 72 $ echo 'push_ssl = false' >> .hg/hgrc
72 73 $ echo 'deny_push = *' >> .hg/hgrc
73 74 $ req
74 75 pushing to http://localhost:$HGPORT/
75 76 searching for changes
76 77 abort: authorization failed
77 78 % serve errors
78 79
79 80 expect authorization error: some users denied, users must be authenticated
80 81
81 82 $ echo 'deny_push = unperson' >> .hg/hgrc
82 83 $ req
83 84 pushing to http://localhost:$HGPORT/
84 85 searching for changes
85 86 abort: authorization failed
86 87 % serve errors
@@ -1,119 +1,120 b''
1 1 Issue746: renaming files brought by the second parent of a merge was
2 2 broken.
3 3
4 4 Create source repository:
5 5
6 6 $ hg init t
7 7 $ cd t
8 8 $ echo a > a
9 9 $ hg ci -Am a
10 10 adding a
11 11 $ cd ..
12 12
13 13 Fork source repository:
14 14
15 15 $ hg clone t t2
16 16 updating to branch default
17 17 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 18 $ cd t2
19 19 $ echo b > b
20 20 $ hg ci -Am b
21 21 adding b
22 22
23 23 Update source repository:
24 24
25 25 $ cd ../t
26 26 $ echo a >> a
27 27 $ hg ci -m a2
28 28
29 29 Merge repositories:
30 30
31 31 $ hg pull ../t2
32 32 pulling from ../t2
33 33 searching for changes
34 34 adding changesets
35 35 adding manifests
36 36 adding file changes
37 37 added 1 changesets with 1 changes to 1 files (+1 heads)
38 38 (run 'hg heads' to see heads, 'hg merge' to merge)
39 39
40 40 $ hg merge
41 41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 (branch merge, don't forget to commit)
43 43
44 44 $ hg st
45 45 M b
46 46
47 47 Rename b as c:
48 48
49 49 $ hg mv b c
50 50 $ hg st
51 51 A c
52 52 R b
53 53
54 54 Rename back c as b:
55 55
56 56 $ hg mv c b
57 57 $ hg st
58 58 M b
59 59
60 60 $ cd ..
61 61
62 62 Issue 1476: renaming a first parent file into another first parent
63 63 file while none of them belong to the second parent was broken
64 64
65 65 $ hg init repo1476
66 66 $ cd repo1476
67 67 $ echo a > a
68 68 $ hg ci -Am adda
69 69 adding a
70 70 $ echo b1 > b1
71 71 $ echo b2 > b2
72 72 $ hg ci -Am changea
73 73 adding b1
74 74 adding b2
75 75 $ hg up -C 0
76 76 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
77 77 $ echo c1 > c1
78 78 $ echo c2 > c2
79 79 $ hg ci -Am addcandd
80 80 adding c1
81 81 adding c2
82 82 created new head
83 83
84 84 Merge heads:
85 85
86 86 $ hg merge
87 87 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 88 (branch merge, don't forget to commit)
89 89
90 90 $ hg mv -Af c1 c2
91 91
92 92 Commit issue 1476:
93 93
94 94 $ hg ci -m merge
95 95
96 96 $ hg log -r tip -C -v | grep copies
97 97 copies: c2 (c1)
98 98
99 99 $ hg rollback
100 rolling back to revision 2 (undo commit)
100 repository tip rolled back to revision 2 (undo commit)
101 working directory now based on revision 2 and 1
101 102
102 103 $ hg up -C .
103 104 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
104 105
105 106 Merge heads again:
106 107
107 108 $ hg merge
108 109 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 110 (branch merge, don't forget to commit)
110 111
111 112 $ hg mv -Af b1 b2
112 113
113 114 Commit issue 1476 with a rename on the other side:
114 115
115 116 $ hg ci -m merge
116 117
117 118 $ hg log -r tip -C -v | grep copies
118 119 copies: b2 (b1)
119 120
@@ -1,91 +1,94 b''
1 1
2 2 $ mkdir t
3 3 $ cd t
4 4 $ hg init
5 5 $ echo a > a
6 6 $ hg add a
7 7 $ hg commit -m "test"
8 8 $ hg verify
9 9 checking changesets
10 10 checking manifests
11 11 crosschecking files in changesets and manifests
12 12 checking files
13 13 1 files, 1 changesets, 1 total revisions
14 14 $ hg parents
15 15 changeset: 0:acb14030fe0a
16 16 tag: tip
17 17 user: test
18 18 date: Thu Jan 01 00:00:00 1970 +0000
19 19 summary: test
20 20
21 21 $ hg status
22 22 $ hg rollback
23 rolling back to revision -1 (undo commit)
23 repository tip rolled back to revision -1 (undo commit)
24 working directory now based on revision -1
24 25 $ hg verify
25 26 checking changesets
26 27 checking manifests
27 28 crosschecking files in changesets and manifests
28 29 checking files
29 30 0 files, 0 changesets, 0 total revisions
30 31 $ hg parents
31 32 $ hg status
32 33 A a
33 34
34 35 Test issue 902
35 36
36 37 $ hg commit -m "test2"
37 38 $ hg branch test
38 39 marked working directory as branch test
39 40 $ hg rollback
40 rolling back to revision -1 (undo commit)
41 repository tip rolled back to revision -1 (undo commit)
42 working directory now based on revision -1
41 43 $ hg branch
42 44 default
43 45
44 46 Test issue 1635 (commit message saved)
45 47 .hg/last-message.txt:
46 48
47 49 $ cat .hg/last-message.txt ; echo
48 50 test2
49 51
50 52 Test rollback of hg before issue 902 was fixed
51 53
52 54 $ hg commit -m "test3"
53 55 $ hg branch test
54 56 marked working directory as branch test
55 57 $ rm .hg/undo.branch
56 58 $ hg rollback
57 rolling back to revision -1 (undo commit)
59 repository tip rolled back to revision -1 (undo commit)
58 60 Named branch could not be reset, current branch still is: test
61 working directory now based on revision -1
59 62 $ hg branch
60 63 test
61 64
62 65 rollback by pretxncommit saves commit message (issue 1635)
63 66
64 67 $ echo a >> a
65 68 $ hg --config hooks.pretxncommit=false commit -m"precious commit message"
66 69 transaction abort!
67 70 rollback completed
68 71 abort: pretxncommit hook exited with status * (glob)
69 72 [255]
70 73
71 74 .hg/last-message.txt:
72 75
73 76 $ cat .hg/last-message.txt ; echo
74 77 precious commit message
75 78
76 79 same thing, but run $EDITOR
77 80
78 81 $ cat > editor << '__EOF__'
79 82 > #!/bin/sh
80 83 > echo "another precious commit message" > "$1"
81 84 > __EOF__
82 85 $ chmod +x editor
83 86 $ HGEDITOR="'`pwd`'"/editor hg --config hooks.pretxncommit=false commit 2>&1
84 87 transaction abort!
85 88 rollback completed
86 89 note: commit message saved in .hg/last-message.txt
87 90 abort: pretxncommit hook exited with status * (glob)
88 91 [255]
89 92 $ cat .hg/last-message.txt
90 93 another precious commit message
91 94
@@ -1,297 +1,298 b''
1 1 $ hg init test
2 2 $ cd test
3 3
4 4 $ echo a > a
5 5 $ hg add a
6 6 $ hg commit -m "test"
7 7 $ hg history
8 8 changeset: 0:acb14030fe0a
9 9 tag: tip
10 10 user: test
11 11 date: Thu Jan 01 00:00:00 1970 +0000
12 12 summary: test
13 13
14 14
15 15 $ hg tag ' '
16 16 abort: tag names cannot consist entirely of whitespace
17 17 [255]
18 18
19 19 $ hg tag "bleah"
20 20 $ hg history
21 21 changeset: 1:d4f0d2909abc
22 22 tag: tip
23 23 user: test
24 24 date: Thu Jan 01 00:00:00 1970 +0000
25 25 summary: Added tag bleah for changeset acb14030fe0a
26 26
27 27 changeset: 0:acb14030fe0a
28 28 tag: bleah
29 29 user: test
30 30 date: Thu Jan 01 00:00:00 1970 +0000
31 31 summary: test
32 32
33 33
34 34 $ echo foo >> .hgtags
35 35 $ hg tag "bleah2"
36 36 abort: working copy of .hgtags is changed (please commit .hgtags manually)
37 37 [255]
38 38
39 39 $ hg revert .hgtags
40 40 $ hg tag -r 0 x y z y y z
41 41 abort: tag names must be unique
42 42 [255]
43 43 $ hg tag tap nada dot tip null .
44 44 abort: the name 'tip' is reserved
45 45 [255]
46 46 $ hg tag "bleah"
47 47 abort: tag 'bleah' already exists (use -f to force)
48 48 [255]
49 49 $ hg tag "blecch" "bleah"
50 50 abort: tag 'bleah' already exists (use -f to force)
51 51 [255]
52 52
53 53 $ hg tag --remove "blecch"
54 54 abort: tag 'blecch' does not exist
55 55 [255]
56 56 $ hg tag --remove "bleah" "blecch" "blough"
57 57 abort: tag 'blecch' does not exist
58 58 [255]
59 59
60 60 $ hg tag -r 0 "bleah0"
61 61 $ hg tag -l -r 1 "bleah1"
62 62 $ hg tag gack gawk gorp
63 63 $ hg tag -f gack
64 64 $ hg tag --remove gack gorp
65 65
66 66 $ hg tag "bleah "
67 67 abort: tag 'bleah' already exists (use -f to force)
68 68 [255]
69 69 $ hg tag " bleah"
70 70 abort: tag 'bleah' already exists (use -f to force)
71 71 [255]
72 72 $ hg tag " bleah"
73 73 abort: tag 'bleah' already exists (use -f to force)
74 74 [255]
75 75 $ hg tag -r 0 " bleahbleah "
76 76 $ hg tag -r 0 " bleah bleah "
77 77
78 78 $ cat .hgtags
79 79 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
80 80 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
81 81 336fccc858a4eb69609a291105009e484a6b6b8d gack
82 82 336fccc858a4eb69609a291105009e484a6b6b8d gawk
83 83 336fccc858a4eb69609a291105009e484a6b6b8d gorp
84 84 336fccc858a4eb69609a291105009e484a6b6b8d gack
85 85 799667b6f2d9b957f73fa644a918c2df22bab58f gack
86 86 799667b6f2d9b957f73fa644a918c2df22bab58f gack
87 87 0000000000000000000000000000000000000000 gack
88 88 336fccc858a4eb69609a291105009e484a6b6b8d gorp
89 89 0000000000000000000000000000000000000000 gorp
90 90 acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah
91 91 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah bleah
92 92
93 93 $ cat .hg/localtags
94 94 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
95 95
96 96 tagging on a non-head revision
97 97
98 98 $ hg update 0
99 99 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
100 100 $ hg tag -l localblah
101 101 $ hg tag "foobar"
102 102 abort: not at a branch head (use -f to force)
103 103 [255]
104 104 $ hg tag -f "foobar"
105 105 $ cat .hgtags
106 106 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
107 107 $ cat .hg/localtags
108 108 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
109 109 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
110 110
111 111 $ hg tag -l 'xx
112 112 > newline'
113 113 abort: '\n' cannot be used in a tag name
114 114 [255]
115 115 $ hg tag -l 'xx:xx'
116 116 abort: ':' cannot be used in a tag name
117 117 [255]
118 118
119 119 cloning local tags
120 120
121 121 $ cd ..
122 122 $ hg -R test log -r0:5
123 123 changeset: 0:acb14030fe0a
124 124 tag: bleah
125 125 tag: bleah bleah
126 126 tag: bleah0
127 127 tag: bleahbleah
128 128 tag: foobar
129 129 tag: localblah
130 130 user: test
131 131 date: Thu Jan 01 00:00:00 1970 +0000
132 132 summary: test
133 133
134 134 changeset: 1:d4f0d2909abc
135 135 tag: bleah1
136 136 user: test
137 137 date: Thu Jan 01 00:00:00 1970 +0000
138 138 summary: Added tag bleah for changeset acb14030fe0a
139 139
140 140 changeset: 2:336fccc858a4
141 141 tag: gawk
142 142 user: test
143 143 date: Thu Jan 01 00:00:00 1970 +0000
144 144 summary: Added tag bleah0 for changeset acb14030fe0a
145 145
146 146 changeset: 3:799667b6f2d9
147 147 user: test
148 148 date: Thu Jan 01 00:00:00 1970 +0000
149 149 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
150 150
151 151 changeset: 4:154eeb7c0138
152 152 user: test
153 153 date: Thu Jan 01 00:00:00 1970 +0000
154 154 summary: Added tag gack for changeset 799667b6f2d9
155 155
156 156 changeset: 5:b4bb47aaff09
157 157 user: test
158 158 date: Thu Jan 01 00:00:00 1970 +0000
159 159 summary: Removed tag gack, gorp
160 160
161 161 $ hg clone -q -rbleah1 test test1
162 162 $ hg -R test1 parents --style=compact
163 163 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
164 164 Added tag bleah for changeset acb14030fe0a
165 165
166 166 $ hg clone -q -r5 test#bleah1 test2
167 167 $ hg -R test2 parents --style=compact
168 168 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
169 169 Removed tag gack, gorp
170 170
171 171 $ hg clone -q -U test#bleah1 test3
172 172 $ hg -R test3 parents --style=compact
173 173
174 174 $ cd test
175 175
176 176 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
177 177 doesn't end with EOL
178 178
179 179 $ python << EOF
180 180 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
181 181 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
182 182 > EOF
183 183 $ cat .hg/localtags; echo
184 184 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
185 185 $ hg tag -l localnewline
186 186 $ cat .hg/localtags; echo
187 187 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
188 188 c2899151f4e76890c602a2597a650a72666681bf localnewline
189 189
190 190
191 191 $ python << EOF
192 192 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
193 193 > f = file('.hgtags', 'w'); f.write(last); f.close()
194 194 > EOF
195 195 $ hg ci -m'broken manual edit of .hgtags'
196 196 $ cat .hgtags; echo
197 197 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
198 198 $ hg tag newline
199 199 $ cat .hgtags; echo
200 200 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
201 201 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
202 202
203 203
204 204 tag and branch using same name
205 205
206 206 $ hg branch tag-and-branch-same-name
207 207 marked working directory as branch tag-and-branch-same-name
208 208 $ hg ci -m"discouraged"
209 209 $ hg tag tag-and-branch-same-name
210 210 warning: tag tag-and-branch-same-name conflicts with existing branch name
211 211
212 212 test custom commit messages
213 213
214 214 $ cat > editor << '__EOF__'
215 215 > #!/bin/sh
216 216 > echo "custom tag message" > "$1"
217 217 > echo "second line" >> "$1"
218 218 > __EOF__
219 219 $ chmod +x editor
220 220 $ HGEDITOR="'`pwd`'"/editor hg tag custom-tag -e
221 221 $ hg log -l1 --template "{desc}\n"
222 222 custom tag message
223 223 second line
224 224
225 225
226 226 local tag with .hgtags modified
227 227
228 228 $ hg tag hgtags-modified
229 229 $ hg rollback
230 rolling back to revision 13 (undo commit)
230 repository tip rolled back to revision 13 (undo commit)
231 working directory now based on revision 13
231 232 $ hg st
232 233 M .hgtags
233 234 ? .hgtags.orig
234 235 ? editor
235 236 $ hg tag --local baz
236 237 $ hg revert --no-backup .hgtags
237 238
238 239
239 240 tagging when at named-branch-head that's not a topo-head
240 241
241 242 $ hg up default
242 243 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
243 244 $ hg merge -t internal:local
244 245 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
245 246 (branch merge, don't forget to commit)
246 247 $ hg ci -m 'merge named branch'
247 248 $ hg up 13
248 249 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
249 250 $ hg tag new-topo-head
250 251
251 252
252 253 tagging on null rev
253 254
254 255 $ hg up null
255 256 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
256 257 $ hg tag nullrev
257 258 abort: not at a branch head (use -f to force)
258 259 [255]
259 260
260 261 $ hg init empty
261 262 $ hg tag -R empty nullrev
262 263
263 264 $ cd ..
264 265
265 266 tagging on an uncommitted merge (issue2542)
266 267
267 268 $ hg init repo-tag-uncommitted-merge
268 269 $ cd repo-tag-uncommitted-merge
269 270 $ echo c1 > f1
270 271 $ hg ci -Am0
271 272 adding f1
272 273 $ echo c2 > f2
273 274 $ hg ci -Am1
274 275 adding f2
275 276 $ hg co -q 0
276 277 $ hg branch b1
277 278 marked working directory as branch b1
278 279 $ hg ci -m2
279 280 $ hg up default
280 281 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 282 $ hg merge b1
282 283 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 284 (branch merge, don't forget to commit)
284 285
285 286 $ hg tag t1
286 287 abort: uncommitted merge
287 288 [255]
288 289 $ hg status
289 290 $ hg tag --rev 1 t2
290 291 abort: uncommitted merge
291 292 [255]
292 293 $ hg tag --rev 1 --local t3
293 294 $ hg tags -v
294 295 tip 2:8a8f787d0d5c
295 296 t3 1:c3adabd1a5f4 local
296 297
297 298 $ cd ..
@@ -1,381 +1,382 b''
1 1 Helper functions:
2 2
3 3 $ cacheexists() {
4 4 > [ -f .hg/cache/tags ] && echo "tag cache exists" || echo "no tag cache"
5 5 > }
6 6
7 7 $ dumptags() {
8 8 > rev=$1
9 9 > echo "rev $rev: .hgtags:"
10 10 > hg cat -r$rev .hgtags
11 11 > }
12 12
13 13 # XXX need to test that the tag cache works when we strip an old head
14 14 # and add a new one rooted off non-tip: i.e. node and rev of tip are the
15 15 # same, but stuff has changed behind tip.
16 16
17 17 Setup:
18 18
19 19 $ hg init t
20 20 $ cd t
21 21 $ cacheexists
22 22 no tag cache
23 23 $ hg id
24 24 000000000000 tip
25 25 $ cacheexists
26 26 no tag cache
27 27 $ echo a > a
28 28 $ hg add a
29 29 $ hg commit -m "test"
30 30 $ hg co
31 31 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 32 $ hg identify
33 33 acb14030fe0a tip
34 34 $ cacheexists
35 35 tag cache exists
36 36
37 37 Try corrupting the cache
38 38
39 39 $ printf 'a b' > .hg/cache/tags
40 40 $ hg identify
41 41 .hg/cache/tags is corrupt, rebuilding it
42 42 acb14030fe0a tip
43 43 $ cacheexists
44 44 tag cache exists
45 45 $ hg identify
46 46 acb14030fe0a tip
47 47
48 48 Create local tag with long name:
49 49
50 50 $ T=`hg identify --debug --id`
51 51 $ hg tag -l "This is a local tag with a really long name!"
52 52 $ hg tags
53 53 tip 0:acb14030fe0a
54 54 This is a local tag with a really long name! 0:acb14030fe0a
55 55 $ rm .hg/localtags
56 56
57 57 Create a tag behind hg's back:
58 58
59 59 $ echo "$T first" > .hgtags
60 60 $ cat .hgtags
61 61 acb14030fe0a21b60322c440ad2d20cf7685a376 first
62 62 $ hg add .hgtags
63 63 $ hg commit -m "add tags"
64 64 $ hg tags
65 65 tip 1:b9154636be93
66 66 first 0:acb14030fe0a
67 67 $ hg identify
68 68 b9154636be93 tip
69 69
70 70 Repeat with cold tag cache:
71 71
72 72 $ rm -f .hg/cache/tags
73 73 $ hg identify
74 74 b9154636be93 tip
75 75
76 76 And again, but now unable to write tag cache:
77 77
78 78 $ rm -f .hg/cache/tags
79 79 $ chmod 555 .hg
80 80 $ hg identify
81 81 b9154636be93 tip
82 82 $ chmod 755 .hg
83 83
84 84 Create a branch:
85 85
86 86 $ echo bb > a
87 87 $ hg status
88 88 M a
89 89 $ hg identify
90 90 b9154636be93+ tip
91 91 $ hg co first
92 92 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
93 93 $ hg id
94 94 acb14030fe0a+ first
95 95 $ hg -v id
96 96 acb14030fe0a+ first
97 97 $ hg status
98 98 M a
99 99 $ echo 1 > b
100 100 $ hg add b
101 101 $ hg commit -m "branch"
102 102 created new head
103 103 $ hg id
104 104 c8edf04160c7 tip
105 105
106 106 Merge the two heads:
107 107
108 108 $ hg merge 1
109 109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 110 (branch merge, don't forget to commit)
111 111 $ hg id
112 112 c8edf04160c7+b9154636be93+ tip
113 113 $ hg status
114 114 M .hgtags
115 115 $ hg commit -m "merge"
116 116
117 117 Create a fake head, make sure tag not visible afterwards:
118 118
119 119 $ cp .hgtags tags
120 120 $ hg tag last
121 121 $ hg rm .hgtags
122 122 $ hg commit -m "remove"
123 123
124 124 $ mv tags .hgtags
125 125 $ hg add .hgtags
126 126 $ hg commit -m "readd"
127 127 $
128 128 $ hg tags
129 129 tip 6:35ff301afafe
130 130 first 0:acb14030fe0a
131 131
132 132 Add invalid tags:
133 133
134 134 $ echo "spam" >> .hgtags
135 135 $ echo >> .hgtags
136 136 $ echo "foo bar" >> .hgtags
137 137 $ echo "a5a5 invalid" >> .hg/localtags
138 138 $ echo "committing .hgtags:"
139 139 committing .hgtags:
140 140 $ cat .hgtags
141 141 acb14030fe0a21b60322c440ad2d20cf7685a376 first
142 142 spam
143 143
144 144 foo bar
145 145 $ hg commit -m "tags"
146 146
147 147 Report tag parse error on other head:
148 148
149 149 $ hg up 3
150 150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 $ echo 'x y' >> .hgtags
152 152 $ hg commit -m "head"
153 153 created new head
154 154
155 155 $ hg tags
156 156 .hgtags@75d9f02dfe28, line 2: cannot parse entry
157 157 .hgtags@75d9f02dfe28, line 4: node 'foo' is not well formed
158 158 .hgtags@c4be69a18c11, line 2: node 'x' is not well formed
159 159 tip 8:c4be69a18c11
160 160 first 0:acb14030fe0a
161 161 $ hg tip
162 162 changeset: 8:c4be69a18c11
163 163 tag: tip
164 164 parent: 3:ac5e980c4dc0
165 165 user: test
166 166 date: Thu Jan 01 00:00:00 1970 +0000
167 167 summary: head
168 168
169 169
170 170 Test tag precedence rules:
171 171
172 172 $ cd ..
173 173 $ hg init t2
174 174 $ cd t2
175 175 $ echo foo > foo
176 176 $ hg add foo
177 177 $ hg ci -m 'add foo' # rev 0
178 178 $ hg tag bar # rev 1
179 179 $ echo >> foo
180 180 $ hg ci -m 'change foo 1' # rev 2
181 181 $ hg up -C 1
182 182 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
183 183 $ hg tag -r 1 -f bar # rev 3
184 184 $ hg up -C 1
185 185 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 186 $ echo >> foo
187 187 $ hg ci -m 'change foo 2' # rev 4
188 188 created new head
189 189 $ hg tags
190 190 tip 4:0c192d7d5e6b
191 191 bar 1:78391a272241
192 192
193 193 Repeat in case of cache effects:
194 194
195 195 $ hg tags
196 196 tip 4:0c192d7d5e6b
197 197 bar 1:78391a272241
198 198
199 199 Detailed dump of tag info:
200 200
201 201 $ hg heads -q # expect 4, 3, 2
202 202 4:0c192d7d5e6b
203 203 3:6fa450212aeb
204 204 2:7a94127795a3
205 205 $ dumptags 2
206 206 rev 2: .hgtags:
207 207 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
208 208 $ dumptags 3
209 209 rev 3: .hgtags:
210 210 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
211 211 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
212 212 78391a272241d70354aa14c874552cad6b51bb42 bar
213 213 $ dumptags 4
214 214 rev 4: .hgtags:
215 215 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
216 216
217 217 Dump cache:
218 218
219 219 $ cat .hg/cache/tags
220 220 4 0c192d7d5e6b78a714de54a2e9627952a877e25a 0c04f2a8af31de17fab7422878ee5a2dadbc943d
221 221 3 6fa450212aeb2a21ed616a54aea39a4a27894cd7 7d3b718c964ef37b89e550ebdafd5789e76ce1b0
222 222 2 7a94127795a33c10a370c93f731fd9fea0b79af6 0c04f2a8af31de17fab7422878ee5a2dadbc943d
223 223
224 224 78391a272241d70354aa14c874552cad6b51bb42 bar
225 225
226 226 Test tag removal:
227 227
228 228 $ hg tag --remove bar # rev 5
229 229 $ hg tip -vp
230 230 changeset: 5:5f6e8655b1c7
231 231 tag: tip
232 232 user: test
233 233 date: Thu Jan 01 00:00:00 1970 +0000
234 234 files: .hgtags
235 235 description:
236 236 Removed tag bar
237 237
238 238
239 239 diff -r 0c192d7d5e6b -r 5f6e8655b1c7 .hgtags
240 240 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
241 241 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
242 242 @@ -1,1 +1,3 @@
243 243 bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
244 244 +78391a272241d70354aa14c874552cad6b51bb42 bar
245 245 +0000000000000000000000000000000000000000 bar
246 246
247 247 $ hg tags
248 248 tip 5:5f6e8655b1c7
249 249 $ hg tags # again, try to expose cache bugs
250 250 tip 5:5f6e8655b1c7
251 251
252 252 Remove nonexistent tag:
253 253
254 254 $ hg tag --remove foobar
255 255 abort: tag 'foobar' does not exist
256 256 [255]
257 257 $ hg tip
258 258 changeset: 5:5f6e8655b1c7
259 259 tag: tip
260 260 user: test
261 261 date: Thu Jan 01 00:00:00 1970 +0000
262 262 summary: Removed tag bar
263 263
264 264
265 265 Undo a tag with rollback:
266 266
267 267 $ hg rollback # destroy rev 5 (restore bar)
268 rolling back to revision 4 (undo commit)
268 repository tip rolled back to revision 4 (undo commit)
269 working directory now based on revision 4
269 270 $ hg tags
270 271 tip 4:0c192d7d5e6b
271 272 bar 1:78391a272241
272 273 $ hg tags
273 274 tip 4:0c192d7d5e6b
274 275 bar 1:78391a272241
275 276
276 277 Test tag rank:
277 278
278 279 $ cd ..
279 280 $ hg init t3
280 281 $ cd t3
281 282 $ echo foo > foo
282 283 $ hg add foo
283 284 $ hg ci -m 'add foo' # rev 0
284 285 $ hg tag -f bar # rev 1 bar -> 0
285 286 $ hg tag -f bar # rev 2 bar -> 1
286 287 $ hg tag -fr 0 bar # rev 3 bar -> 0
287 288 $ hg tag -fr 1 bar # rev 4 bar -> 1
288 289 $ hg tag -fr 0 bar # rev 5 bar -> 0
289 290 $ hg tags
290 291 tip 5:85f05169d91d
291 292 bar 0:bbd179dfa0a7
292 293 $ hg co 3
293 294 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
294 295 $ echo barbar > foo
295 296 $ hg ci -m 'change foo' # rev 6
296 297 created new head
297 298 $ hg tags
298 299 tip 6:735c3ca72986
299 300 bar 0:bbd179dfa0a7
300 301
301 302 Don't allow moving tag without -f:
302 303
303 304 $ hg tag -r 3 bar
304 305 abort: tag 'bar' already exists (use -f to force)
305 306 [255]
306 307 $ hg tags
307 308 tip 6:735c3ca72986
308 309 bar 0:bbd179dfa0a7
309 310
310 311 Strip 1: expose an old head:
311 312
312 313 $ hg --config extensions.mq= strip 5
313 314 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
314 315 $ hg tags # partly stale cache
315 316 tip 5:735c3ca72986
316 317 bar 1:78391a272241
317 318 $ hg tags # up-to-date cache
318 319 tip 5:735c3ca72986
319 320 bar 1:78391a272241
320 321
321 322 Strip 2: destroy whole branch, no old head exposed
322 323
323 324 $ hg --config extensions.mq= strip 4
324 325 saved backup bundle to $TESTTMP/t3/.hg/strip-backup/*-backup.hg (glob)
325 326 $ hg tags # partly stale
326 327 tip 4:735c3ca72986
327 328 bar 0:bbd179dfa0a7
328 329 $ rm -f .hg/cache/tags
329 330 $ hg tags # cold cache
330 331 tip 4:735c3ca72986
331 332 bar 0:bbd179dfa0a7
332 333
333 334 Test tag rank with 3 heads:
334 335
335 336 $ cd ..
336 337 $ hg init t4
337 338 $ cd t4
338 339 $ echo foo > foo
339 340 $ hg add
340 341 adding foo
341 342 $ hg ci -m 'add foo' # rev 0
342 343 $ hg tag bar # rev 1 bar -> 0
343 344 $ hg tag -f bar # rev 2 bar -> 1
344 345 $ hg up -qC 0
345 346 $ hg tag -fr 2 bar # rev 3 bar -> 2
346 347 $ hg tags
347 348 tip 3:197c21bbbf2c
348 349 bar 2:6fa450212aeb
349 350 $ hg up -qC 0
350 351 $ hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
351 352
352 353 Bar should still point to rev 2:
353 354
354 355 $ hg tags
355 356 tip 4:3b4b14ed0202
356 357 bar 2:6fa450212aeb
357 358
358 359 Test that removing global/local tags does not get confused when trying
359 360 to remove a tag of type X which actually only exists as a type Y:
360 361
361 362 $ cd ..
362 363 $ hg init t5
363 364 $ cd t5
364 365 $ echo foo > foo
365 366 $ hg add
366 367 adding foo
367 368 $ hg ci -m 'add foo' # rev 0
368 369
369 370 $ hg tag -r 0 -l localtag
370 371 $ hg tag --remove localtag
371 372 abort: tag 'localtag' is not a global tag
372 373 [255]
373 374 $
374 375 $ hg tag -r 0 globaltag
375 376 $ hg tag --remove -l globaltag
376 377 abort: tag 'globaltag' is not a local tag
377 378 [255]
378 379 $ hg tags -v
379 380 tip 1:a0b6fe111088
380 381 localtag 0:bbd179dfa0a7 local
381 382 globaltag 0:bbd179dfa0a7
@@ -1,205 +1,208 b''
1 1 Test basic functionality of url#rev syntax
2 2
3 3 $ hg init repo
4 4 $ cd repo
5 5 $ echo a > a
6 6 $ hg ci -qAm 'add a'
7 7 $ hg branch foo
8 8 marked working directory as branch foo
9 9 $ echo >> a
10 10 $ hg ci -m 'change a'
11 11 $ cd ..
12 12
13 13 $ hg clone 'repo#foo' clone
14 14 adding changesets
15 15 adding manifests
16 16 adding file changes
17 17 added 2 changesets with 2 changes to 1 files
18 18 updating to branch foo
19 19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20
21 21 $ hg --cwd clone heads
22 22 changeset: 1:cd2a86ecc814
23 23 branch: foo
24 24 tag: tip
25 25 user: test
26 26 date: Thu Jan 01 00:00:00 1970 +0000
27 27 summary: change a
28 28
29 29 changeset: 0:1f0dee641bb7
30 30 user: test
31 31 date: Thu Jan 01 00:00:00 1970 +0000
32 32 summary: add a
33 33
34 34 $ hg --cwd clone parents
35 35 changeset: 1:cd2a86ecc814
36 36 branch: foo
37 37 tag: tip
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: change a
41 41
42 42 $ cat clone/.hg/hgrc
43 43 [paths]
44 44 default = $TESTTMP/repo#foo
45 45
46 46 Changing original repo:
47 47
48 48 $ cd repo
49 49
50 50 $ echo >> a
51 51 $ hg ci -m 'new head of branch foo'
52 52
53 53 $ hg up -qC default
54 54 $ echo bar > bar
55 55 $ hg ci -qAm 'add bar'
56 56
57 57 $ hg log
58 58 changeset: 3:4cd725637392
59 59 tag: tip
60 60 parent: 0:1f0dee641bb7
61 61 user: test
62 62 date: Thu Jan 01 00:00:00 1970 +0000
63 63 summary: add bar
64 64
65 65 changeset: 2:faba9097cad4
66 66 branch: foo
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: 1:cd2a86ecc814
72 72 branch: foo
73 73 user: test
74 74 date: Thu Jan 01 00:00:00 1970 +0000
75 75 summary: change a
76 76
77 77 changeset: 0:1f0dee641bb7
78 78 user: test
79 79 date: Thu Jan 01 00:00:00 1970 +0000
80 80 summary: add a
81 81
82 82 $ hg -q outgoing '../clone#foo'
83 83 2:faba9097cad4
84 84
85 85 $ hg -q push '../clone#foo'
86 86
87 87 $ hg --cwd ../clone heads
88 88 changeset: 2:faba9097cad4
89 89 branch: foo
90 90 tag: tip
91 91 user: test
92 92 date: Thu Jan 01 00:00:00 1970 +0000
93 93 summary: new head of branch foo
94 94
95 95 changeset: 0:1f0dee641bb7
96 96 user: test
97 97 date: Thu Jan 01 00:00:00 1970 +0000
98 98 summary: add a
99 99
100 100 $ cd ..
101 101
102 102 $ cd clone
103 103 $ hg rollback
104 rolling back to revision 1 (undo push)
104 repository tip rolled back to revision 1 (undo push)
105 working directory now based on revision 1
105 106
106 107 $ hg -q incoming
107 108 2:faba9097cad4
108 109
109 110 $ hg -q pull
110 111
111 112 $ hg heads
112 113 changeset: 2:faba9097cad4
113 114 branch: foo
114 115 tag: tip
115 116 user: test
116 117 date: Thu Jan 01 00:00:00 1970 +0000
117 118 summary: new head of branch foo
118 119
119 120 changeset: 0:1f0dee641bb7
120 121 user: test
121 122 date: Thu Jan 01 00:00:00 1970 +0000
122 123 summary: add a
123 124
124 125 Pull should not have updated:
125 126
126 127 $ hg parents -q
127 128 1:cd2a86ecc814
128 129
129 130 Going back to the default branch:
130 131
131 132 $ hg up -C 0
132 133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
133 134
134 135 $ hg parents
135 136 changeset: 0:1f0dee641bb7
136 137 user: test
137 138 date: Thu Jan 01 00:00:00 1970 +0000
138 139 summary: add a
139 140
140 141 No new revs, no update:
141 142
142 143 $ hg pull -qu
143 144
144 145 $ hg parents -q
145 146 0:1f0dee641bb7
146 147
147 148 $ hg rollback
148 rolling back to revision 1 (undo pull)
149 repository tip rolled back to revision 1 (undo pull)
150 working directory now based on revision 1
149 151
150 152 $ hg up -C 0
151 153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
152 154
153 155 $ hg parents -q
154 156 0:1f0dee641bb7
155 157
156 158 Pull -u takes us back to branch foo:
157 159
158 160 $ hg pull -qu
159 161
160 162 $ hg parents
161 163 changeset: 2:faba9097cad4
162 164 branch: foo
163 165 tag: tip
164 166 user: test
165 167 date: Thu Jan 01 00:00:00 1970 +0000
166 168 summary: new head of branch foo
167 169
168 170 $ hg rollback
169 rolling back to revision 1 (undo pull)
171 repository tip rolled back to revision 1 (undo pull)
172 working directory now based on revision 0
170 173
171 174 $ hg up -C 0
172 175 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 176
174 177 $ hg parents -q
175 178 0:1f0dee641bb7
176 179
177 180 $ hg heads -q
178 181 1:cd2a86ecc814
179 182 0:1f0dee641bb7
180 183
181 184 $ hg pull -qur default default
182 185
183 186 $ hg parents
184 187 changeset: 3:4cd725637392
185 188 tag: tip
186 189 parent: 0:1f0dee641bb7
187 190 user: test
188 191 date: Thu Jan 01 00:00:00 1970 +0000
189 192 summary: add bar
190 193
191 194 $ hg heads
192 195 changeset: 3:4cd725637392
193 196 tag: tip
194 197 parent: 0:1f0dee641bb7
195 198 user: test
196 199 date: Thu Jan 01 00:00:00 1970 +0000
197 200 summary: add bar
198 201
199 202 changeset: 2:faba9097cad4
200 203 branch: foo
201 204 user: test
202 205 date: Thu Jan 01 00:00:00 1970 +0000
203 206 summary: new head of branch foo
204 207
205 208
General Comments 0
You need to be logged in to leave comments. Login now