# HG changeset patch # User Nicolas Dumazet # Date 1279295226 -32400 # Node ID e2bce1c717fa4506a99437d5bff9e8dad9361859 # Parent b3de1438028d590c68d36cd00bbcdfc06088c31a strip: support multiple revisions diff -r b3de1438028d -r e2bce1c717fa hgext/mq.py --- a/hgext/mq.py Thu Aug 12 16:35:34 2010 +0900 +++ b/hgext/mq.py Sat Jul 17 00:47:06 2010 +0900 @@ -513,7 +513,7 @@ # apply failed, strip away that rev and merge. hg.clean(repo, head) - self.strip(repo, n, update=False, backup='strip') + self.strip(repo, [n], update=False, backup='strip') ctx = repo[rev] ret = hg.merge(repo, rev) @@ -895,7 +895,7 @@ finally: release(wlock) - def strip(self, repo, rev, update=True, backup="all", force=None): + def strip(self, repo, revs, update=True, backup="all", force=None): wlock = lock = None try: wlock = repo.wlock() @@ -903,12 +903,13 @@ if update: self.check_localchanges(repo, force=force, refresh=False) - urev = self.qparents(repo, rev) + urev = self.qparents(repo, revs[0]) hg.clean(repo, urev) repo.dirstate.write() self.removeundo(repo) - repair.strip(self.ui, repo, rev, backup) + for rev in revs: + repair.strip(self.ui, repo, rev, backup) # strip may have unbundled a set of backed up revisions after # the actual strip self.removeundo(repo) @@ -1197,7 +1198,7 @@ for patch in reversed(self.applied[start:end]): self.ui.status(_("popping %s\n") % patch.name) del self.applied[start:end] - self.strip(repo, rev, update=False, backup='strip') + self.strip(repo, [rev], update=False, backup='strip') if self.applied: self.ui.write(_("now at: %s\n") % self.applied[-1].name) else: @@ -1377,7 +1378,7 @@ repo.dirstate.setparents(*cparents) self.applied.pop() self.applied_dirty = 1 - self.strip(repo, top, update=False, + self.strip(repo, [top], update=False, backup='strip') except: repo.dirstate.invalidate() @@ -1532,7 +1533,7 @@ update = True else: update = False - self.strip(repo, rev, update=update, backup='strip') + self.strip(repo, [rev], update=update, backup='strip') if qpp: self.ui.warn(_("saved queue repository parents: %s %s\n") % (short(qpp[0]), short(qpp[1]))) @@ -1934,7 +1935,7 @@ if qbase: ui.note(_('stripping applied patches from destination ' 'repository\n')) - dr.mq.strip(dr, qbase, update=False, backup=None) + dr.mq.strip(dr, [qbase], update=False, backup=None) if not opts['noupdate']: ui.note(_('updating destination repository\n')) hg.update(dr, dr.changelog.tip()) @@ -2396,14 +2397,12 @@ pass return 0 -def strip(ui, repo, rev, **opts): - """strip a changeset and all its descendants from the repository - - The strip command removes all changesets whose local revision - number is greater than or equal to REV, and then restores any - changesets that are not descendants of REV. If the working - directory has uncommitted changes, the operation is aborted unless - the --force flag is supplied. +def strip(ui, repo, *revs, **opts): + """strip changesets and all their descendants from the repository + + The strip command removes the specified changesets and all their + descendants. If the working directory has uncommitted changes, + the operation is aborted unless the --force flag is supplied. If a parent of the working directory is stripped, then the working directory will automatically be updated to the most recent @@ -2426,30 +2425,42 @@ elif opts['nobackup']: backup = 'none' - rev = repo.lookup(rev) - p = repo.dirstate.parents() cl = repo.changelog - update = True - if p[0] == nullid: - update = False - elif p[1] == nullid and rev != cl.ancestor(p[0], rev): - update = False - elif rev not in (cl.ancestor(p[0], rev), cl.ancestor(p[1], rev)): - update = False + revs = set(cl.rev(repo.lookup(r)) for r in revs) + + descendants = set(cl.descendants(*revs)) + strippedrevs = revs.union(descendants) + roots = revs.difference(descendants) + + update = False + # if one of the wdir parent is stripped we'll need + # to update away to an earlier revision + for p in repo.dirstate.parents(): + if p != nullid and cl.rev(p) in strippedrevs: + update = True + break + + rootnodes = set(cl.node(r) for r in roots) q = repo.mq if q.applied: - if rev == cl.ancestor(repo.lookup('qtip'), rev): + # refresh queue state if we're about to strip + # applied patches + if cl.rev(repo.lookup('qtip')) in strippedrevs: q.applied_dirty = True start = 0 end = len(q.applied) - applied_list = [i.node for i in q.applied] - if rev in applied_list: - start = applied_list.index(rev) + for i, statusentry in enumerate(q.applied): + if statusentry.node in rootnodes: + # if one of the stripped roots is an applied + # patch, only part of the queue is stripped + start = i + break del q.applied[start:end] q.save_dirty() - repo.mq.strip(repo, rev, backup=backup, update=update, force=opts['force']) + repo.mq.strip(repo, list(rootnodes), backup=backup, update=update, + force=opts['force']) return 0 def select(ui, repo, *args, **opts): @@ -3008,7 +3019,7 @@ ' number greater than REV which are not' ' descendants of REV (DEPRECATED)')), ('n', 'nobackup', None, _('no backups'))], - _('hg strip [-f] [-n] REV')), + _('hg strip [-f] [-n] REV...')), "qtop": (top, [] + seriesopts, _('hg qtop [-s]')), "qunapplied": (unapplied, diff -r b3de1438028d -r e2bce1c717fa tests/test-mq-strip --- a/tests/test-mq-strip Thu Aug 12 16:35:34 2010 +0900 +++ b/tests/test-mq-strip Sat Jul 17 00:47:06 2010 +0900 @@ -4,16 +4,20 @@ echo "[extensions]" >> $HGRCPATH echo "mq=" >> $HGRCPATH +echo "graphlog=" >> $HGRCPATH +restore() { + hg unbundle -q .hg/strip-backup/* + rm .hg/strip-backup/* +} teststrip() { hg up -C $1 echo % before update $1, strip $2 hg parents - hg strip $2 | hidebackup + hg --traceback strip $2 | hidebackup echo % after update $1, strip $2 hg parents - hg unbundle -q .hg/strip-backup/* - rm .hg/strip-backup/* + restore } hg init test @@ -53,6 +57,25 @@ hg strip 4 2>&1 | hidebackup echo % after strip of merge parent hg parents +restore + +hg up +hg glog +echo % 2 is parent of 3, only one strip should happen +hg strip 2 3 | hidebackup +hg glog +restore +hg glog +echo % 2 different branches: 2 strips +hg strip 2 4 | hidebackup +hg glog +restore +echo % 2 different branches and a common ancestor: 1 strip +hg strip 1 2 4 | hidebackup +restore + +# remove branchy history for qimport tests +hg strip 3 | hidebackup #strip of applied mq should cleanup status file hg up -C 3 diff -r b3de1438028d -r e2bce1c717fa tests/test-mq-strip.out --- a/tests/test-mq-strip.out Thu Aug 12 16:35:34 2010 +0900 +++ b/tests/test-mq-strip.out Sat Jul 17 00:47:06 2010 +0900 @@ -166,6 +166,103 @@ summary: b 1 files updated, 0 files merged, 0 files removed, 0 files unresolved +@ changeset: 4:264128213d29 +| tag: tip +| parent: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: c +| +| o changeset: 3:443431ffac4f +| | user: test +| | date: Thu Jan 01 00:00:00 1970 +0000 +| | summary: e +| | +| o changeset: 2:65bd5f99a4a3 +|/ user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: d +| +o changeset: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: b +| +o changeset: 0:9ab35a2d17cb + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +% 2 is parent of 3, only one strip should happen +saved backup bundle to +@ changeset: 2:264128213d29 +| tag: tip +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: c +| +o changeset: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: b +| +o changeset: 0:9ab35a2d17cb + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +o changeset: 4:443431ffac4f +| tag: tip +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: e +| +o changeset: 3:65bd5f99a4a3 +| parent: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: d +| +| @ changeset: 2:264128213d29 +|/ user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: c +| +o changeset: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: b +| +o changeset: 0:9ab35a2d17cb + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +% 2 different branches: 2 strips +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +saved backup bundle to +saved backup bundle to +@ changeset: 2:65bd5f99a4a3 +| tag: tip +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: d +| +o changeset: 1:ef3a871183d7 +| user: test +| date: Thu Jan 01 00:00:00 1970 +0000 +| summary: b +| +o changeset: 0:9ab35a2d17cb + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +% 2 different branches and a common ancestor: 1 strip +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +saved backup bundle to +saved backup bundle to +1 files updated, 0 files merged, 0 files removed, 0 files unresolved % applied patches before strip 2.diff 3.diff diff -r b3de1438028d -r e2bce1c717fa tests/test-mq.out --- a/tests/test-mq.out Thu Aug 12 16:35:34 2010 +0900 +++ b/tests/test-mq.out Sat Jul 17 00:47:06 2010 +0900 @@ -59,7 +59,7 @@ qseries print the entire series file qtop print the name of the current patch qunapplied print the patches not yet applied - strip strip a changeset and all its descendants from the repository + strip strip changesets and all their descendants from the repository use "hg -v help mq" to show aliases and global options adding a