comparison hgext/mq.py @ 11789:e2bce1c717fa

strip: support multiple revisions
author Nicolas Dumazet <nicdumz.commits@gmail.com>
date Sat, 17 Jul 2010 00:47:06 +0900
parents 9b771b4ce2f3
children 1c00577b0298
comparison
equal deleted inserted replaced
11788:b3de1438028d 11789:e2bce1c717fa
511 511
512 self.ui.warn(_("patch didn't work out, merging %s\n") % patch) 512 self.ui.warn(_("patch didn't work out, merging %s\n") % patch)
513 513
514 # apply failed, strip away that rev and merge. 514 # apply failed, strip away that rev and merge.
515 hg.clean(repo, head) 515 hg.clean(repo, head)
516 self.strip(repo, n, update=False, backup='strip') 516 self.strip(repo, [n], update=False, backup='strip')
517 517
518 ctx = repo[rev] 518 ctx = repo[rev]
519 ret = hg.merge(repo, rev) 519 ret = hg.merge(repo, rev)
520 if ret: 520 if ret:
521 raise util.Abort(_("update returned %d") % ret) 521 raise util.Abort(_("update returned %d") % ret)
893 raise 893 raise
894 self.removeundo(repo) 894 self.removeundo(repo)
895 finally: 895 finally:
896 release(wlock) 896 release(wlock)
897 897
898 def strip(self, repo, rev, update=True, backup="all", force=None): 898 def strip(self, repo, revs, update=True, backup="all", force=None):
899 wlock = lock = None 899 wlock = lock = None
900 try: 900 try:
901 wlock = repo.wlock() 901 wlock = repo.wlock()
902 lock = repo.lock() 902 lock = repo.lock()
903 903
904 if update: 904 if update:
905 self.check_localchanges(repo, force=force, refresh=False) 905 self.check_localchanges(repo, force=force, refresh=False)
906 urev = self.qparents(repo, rev) 906 urev = self.qparents(repo, revs[0])
907 hg.clean(repo, urev) 907 hg.clean(repo, urev)
908 repo.dirstate.write() 908 repo.dirstate.write()
909 909
910 self.removeundo(repo) 910 self.removeundo(repo)
911 repair.strip(self.ui, repo, rev, backup) 911 for rev in revs:
912 repair.strip(self.ui, repo, rev, backup)
912 # strip may have unbundled a set of backed up revisions after 913 # strip may have unbundled a set of backed up revisions after
913 # the actual strip 914 # the actual strip
914 self.removeundo(repo) 915 self.removeundo(repo)
915 finally: 916 finally:
916 release(lock, wlock) 917 release(lock, wlock)
1195 repo.dirstate.normal(f) 1196 repo.dirstate.normal(f)
1196 repo.dirstate.setparents(qp, nullid) 1197 repo.dirstate.setparents(qp, nullid)
1197 for patch in reversed(self.applied[start:end]): 1198 for patch in reversed(self.applied[start:end]):
1198 self.ui.status(_("popping %s\n") % patch.name) 1199 self.ui.status(_("popping %s\n") % patch.name)
1199 del self.applied[start:end] 1200 del self.applied[start:end]
1200 self.strip(repo, rev, update=False, backup='strip') 1201 self.strip(repo, [rev], update=False, backup='strip')
1201 if self.applied: 1202 if self.applied:
1202 self.ui.write(_("now at: %s\n") % self.applied[-1].name) 1203 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
1203 else: 1204 else:
1204 self.ui.write(_("patch queue now empty\n")) 1205 self.ui.write(_("patch queue now empty\n"))
1205 finally: 1206 finally:
1375 1376
1376 # assumes strip can roll itself back if interrupted 1377 # assumes strip can roll itself back if interrupted
1377 repo.dirstate.setparents(*cparents) 1378 repo.dirstate.setparents(*cparents)
1378 self.applied.pop() 1379 self.applied.pop()
1379 self.applied_dirty = 1 1380 self.applied_dirty = 1
1380 self.strip(repo, top, update=False, 1381 self.strip(repo, [top], update=False,
1381 backup='strip') 1382 backup='strip')
1382 except: 1383 except:
1383 repo.dirstate.invalidate() 1384 repo.dirstate.invalidate()
1384 raise 1385 raise
1385 1386
1530 pp = repo.dirstate.parents() 1531 pp = repo.dirstate.parents()
1531 if rev in pp: 1532 if rev in pp:
1532 update = True 1533 update = True
1533 else: 1534 else:
1534 update = False 1535 update = False
1535 self.strip(repo, rev, update=update, backup='strip') 1536 self.strip(repo, [rev], update=update, backup='strip')
1536 if qpp: 1537 if qpp:
1537 self.ui.warn(_("saved queue repository parents: %s %s\n") % 1538 self.ui.warn(_("saved queue repository parents: %s %s\n") %
1538 (short(qpp[0]), short(qpp[1]))) 1539 (short(qpp[0]), short(qpp[1])))
1539 if qupdate: 1540 if qupdate:
1540 self.ui.status(_("queue directory updating\n")) 1541 self.ui.status(_("queue directory updating\n"))
1932 stream=opts['uncompressed']) 1933 stream=opts['uncompressed'])
1933 if dr.local(): 1934 if dr.local():
1934 if qbase: 1935 if qbase:
1935 ui.note(_('stripping applied patches from destination ' 1936 ui.note(_('stripping applied patches from destination '
1936 'repository\n')) 1937 'repository\n'))
1937 dr.mq.strip(dr, qbase, update=False, backup=None) 1938 dr.mq.strip(dr, [qbase], update=False, backup=None)
1938 if not opts['noupdate']: 1939 if not opts['noupdate']:
1939 ui.note(_('updating destination repository\n')) 1940 ui.note(_('updating destination repository\n'))
1940 hg.update(dr, dr.changelog.tip()) 1941 hg.update(dr, dr.changelog.tip())
1941 1942
1942 def commit(ui, repo, *pats, **opts): 1943 def commit(ui, repo, *pats, **opts):
2394 os.unlink(q.join(q.status_path)) 2395 os.unlink(q.join(q.status_path))
2395 except: 2396 except:
2396 pass 2397 pass
2397 return 0 2398 return 0
2398 2399
2399 def strip(ui, repo, rev, **opts): 2400 def strip(ui, repo, *revs, **opts):
2400 """strip a changeset and all its descendants from the repository 2401 """strip changesets and all their descendants from the repository
2401 2402
2402 The strip command removes all changesets whose local revision 2403 The strip command removes the specified changesets and all their
2403 number is greater than or equal to REV, and then restores any 2404 descendants. If the working directory has uncommitted changes,
2404 changesets that are not descendants of REV. If the working 2405 the operation is aborted unless the --force flag is supplied.
2405 directory has uncommitted changes, the operation is aborted unless
2406 the --force flag is supplied.
2407 2406
2408 If a parent of the working directory is stripped, then the working 2407 If a parent of the working directory is stripped, then the working
2409 directory will automatically be updated to the most recent 2408 directory will automatically be updated to the most recent
2410 available ancestor of the stripped parent after the operation 2409 available ancestor of the stripped parent after the operation
2411 completes. 2410 completes.
2424 if opts['backup']: 2423 if opts['backup']:
2425 backup = 'strip' 2424 backup = 'strip'
2426 elif opts['nobackup']: 2425 elif opts['nobackup']:
2427 backup = 'none' 2426 backup = 'none'
2428 2427
2429 rev = repo.lookup(rev)
2430 p = repo.dirstate.parents()
2431 cl = repo.changelog 2428 cl = repo.changelog
2432 update = True 2429 revs = set(cl.rev(repo.lookup(r)) for r in revs)
2433 if p[0] == nullid: 2430
2434 update = False 2431 descendants = set(cl.descendants(*revs))
2435 elif p[1] == nullid and rev != cl.ancestor(p[0], rev): 2432 strippedrevs = revs.union(descendants)
2436 update = False 2433 roots = revs.difference(descendants)
2437 elif rev not in (cl.ancestor(p[0], rev), cl.ancestor(p[1], rev)): 2434
2438 update = False 2435 update = False
2436 # if one of the wdir parent is stripped we'll need
2437 # to update away to an earlier revision
2438 for p in repo.dirstate.parents():
2439 if p != nullid and cl.rev(p) in strippedrevs:
2440 update = True
2441 break
2442
2443 rootnodes = set(cl.node(r) for r in roots)
2439 2444
2440 q = repo.mq 2445 q = repo.mq
2441 if q.applied: 2446 if q.applied:
2442 if rev == cl.ancestor(repo.lookup('qtip'), rev): 2447 # refresh queue state if we're about to strip
2448 # applied patches
2449 if cl.rev(repo.lookup('qtip')) in strippedrevs:
2443 q.applied_dirty = True 2450 q.applied_dirty = True
2444 start = 0 2451 start = 0
2445 end = len(q.applied) 2452 end = len(q.applied)
2446 applied_list = [i.node for i in q.applied] 2453 for i, statusentry in enumerate(q.applied):
2447 if rev in applied_list: 2454 if statusentry.node in rootnodes:
2448 start = applied_list.index(rev) 2455 # if one of the stripped roots is an applied
2456 # patch, only part of the queue is stripped
2457 start = i
2458 break
2449 del q.applied[start:end] 2459 del q.applied[start:end]
2450 q.save_dirty() 2460 q.save_dirty()
2451 2461
2452 repo.mq.strip(repo, rev, backup=backup, update=update, force=opts['force']) 2462 repo.mq.strip(repo, list(rootnodes), backup=backup, update=update,
2463 force=opts['force'])
2453 return 0 2464 return 0
2454 2465
2455 def select(ui, repo, *args, **opts): 2466 def select(ui, repo, *args, **opts):
2456 '''set or print guarded patches to push 2467 '''set or print guarded patches to push
2457 2468
3006 'working directory has uncommitted changes')), 3017 'working directory has uncommitted changes')),
3007 ('b', 'backup', None, _('bundle only changesets with local revision' 3018 ('b', 'backup', None, _('bundle only changesets with local revision'
3008 ' number greater than REV which are not' 3019 ' number greater than REV which are not'
3009 ' descendants of REV (DEPRECATED)')), 3020 ' descendants of REV (DEPRECATED)')),
3010 ('n', 'nobackup', None, _('no backups'))], 3021 ('n', 'nobackup', None, _('no backups'))],
3011 _('hg strip [-f] [-n] REV')), 3022 _('hg strip [-f] [-n] REV...')),
3012 "qtop": (top, [] + seriesopts, _('hg qtop [-s]')), 3023 "qtop": (top, [] + seriesopts, _('hg qtop [-s]')),
3013 "qunapplied": 3024 "qunapplied":
3014 (unapplied, 3025 (unapplied,
3015 [('1', 'first', None, _('show only the first patch'))] + seriesopts, 3026 [('1', 'first', None, _('show only the first patch'))] + seriesopts,
3016 _('hg qunapplied [-1] [-s] [PATCH]')), 3027 _('hg qunapplied [-1] [-s] [PATCH]')),