[PATCH 1 of 8] commands: add abandon command
Martin Geisler
mg at lazybytes.net
Wed Jun 1 16:42:47 UTC 2011
# HG changeset patch
# User Martin Geisler <mg at lazybytes.net>
# Date 1306919141 -7200
# Node ID 9b14fa930acae9dc802d7cec87780ba1a3a9aa8b
# Parent 1ffeeb91c55d0b00445ceabde14a0d0faf906a33
commands: add abandon command
Abandoned changesets are hidden from 'hg log' by default.
diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -48,6 +48,9 @@
def perfheads(ui, repo):
timer(lambda: len(repo.changelog.heads()))
+def perfabandoned(ui, repo):
+ timer(lambda: repo.changelog.abandoned(0))
+
def perftags(ui, repo):
import mercurial.changelog, mercurial.manifest
def t():
@@ -153,6 +156,7 @@
'perfmanifest': (perfmanifest, []),
'perfindex': (perfindex, []),
'perfheads': (perfheads, []),
+ 'perfabandoned': (perfabandoned, []),
'perftags': (perftags, []),
'perfdirstate': (perfdirstate, []),
'perfdirstatedirs': (perfdirstate, []),
diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -240,3 +240,24 @@
l = [hex(manifest), user, parseddate] + sorted(files) + ["", desc]
text = "\n".join(l)
return self.addrevision(text, transaction, len(self), p1, p2)
+
+ def abandoned(self, node):
+ # TODO: need cache
+ abandoned = set()
+
+ for head in self.heads():
+ extra = self.read(head)[5]
+ if 'abandon' in extra:
+ abandoned.update(map(bin, extra['abandon'].split(' ')))
+ abandoned.add(head)
+
+ if node in abandoned:
+ for head in self.heads():
+ if head not in abandoned and self.ancestor(head, node) == node:
+ return None
+
+ return [h for h in self.heads() if
+ hex(node) in self.read(h)[5].get('abandon', '').split(' ')
+ or node == h][0]
+
+ return None
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -130,6 +130,18 @@
# Commands start here, listed alphabetically
+ at command('abandon', commitopts2, _('REV'))
+def abandon(ui, repo, rev, **opts):
+ """abandon specified changeset and its descendents"""
+ root = scmutil.revsingle(repo, rev)
+ abandoned = repo.changelog.descendants(root.rev())
+ revlist = root.hex() + " ".join(a.hex() for a in abandoned)
+ ctx = context.memctx(repo, [root.rev(), None], "abandoned",
+ [], None, user=opts.get('user'),
+ date=opts.get('date'),
+ extra=dict(abandon=revlist))
+ ctx.commit()
+
@command('^add',
walkopts + subrepoopts + dryrunopts,
_('[OPTION]... [FILE]...'))
@@ -3281,6 +3293,7 @@
_('show changesets within the given named branch'), _('BRANCH')),
('P', 'prune', [],
_('do not display revision or any of its ancestors'), _('REV')),
+ ('', 'abandoned', False, _('show abandoned changesets')),
] + logopts + walkopts,
_('[OPTION]... [FILE]'))
def log(ui, repo, *pats, **opts):
@@ -3336,6 +3349,8 @@
rev = ctx.rev()
parents = [p for p in repo.changelog.parentrevs(rev)
if p != nullrev]
+ if not opts.get('abandoned') and ctx.abandoned():
+ return
if opts.get('no_merges') and len(parents) == 2:
return
if opts.get('only_merges') and len(parents) != 2:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -110,6 +110,8 @@
return self._changeset[4]
def branch(self):
return encoding.tolocal(self._changeset[5].get("branch"))
+ def abandoned(self):
+ return self._repo.abandoned(self._node)
def extra(self):
return self._changeset[5]
def tags(self):
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -517,6 +517,9 @@
bheads = [b for b in bheads if b not in reachable]
partial[branch] = bheads
+ def abandoned(self, rev):
+ return self.changelog.abandoned(self[rev].node())
+
def lookup(self, key):
if isinstance(key, int):
return self.changelog.node(key)
diff --git a/tests/test-abandoned.t b/tests/test-abandoned.t
new file mode 100644
--- /dev/null
+++ b/tests/test-abandoned.t
@@ -0,0 +1,45 @@
+setting up
+
+ $ cat >> $HGRCPATH <<EOF
+ > [ui]
+ > logtemplate = '{rev} {node|short} {desc|firstline|strip}\n'
+ > [defaults]
+ > abandon = -d "0 0"
+ > [extensions]
+ > graphlog =
+ > EOF
+
+ $ hg init repo
+ $ cd repo
+ $ touch i x
+ $ hg commit -A -m init i
+ $ hg commit -A -m x x
+ $ hg glog
+ @ 1 0b00c28422ee x
+ |
+ o 0 54dbcd775ef0 init
+
+ $ hg init ../empty
+ $ hg clone -q -r 0 . ../base-i
+ $ hg clone -q -r 1 . ../base-x
+
+abandon x
+
+ $ hg abandon 1
+ $ hg glog
+ o 2 339976ff5010 abandoned
+ |
+ @ 1 0b00c28422ee x
+ |
+ o 0 54dbcd775ef0 init
+
+
+abandoned changeset is hidden in log
+
+ $ hg log
+ 0 54dbcd775ef0 init
+
+ $ hg log --abandoned
+ 2 339976ff5010 abandoned
+ 1 0b00c28422ee x
+ 0 54dbcd775ef0 init
diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t
--- a/tests/test-debugcomplete.t
+++ b/tests/test-debugcomplete.t
@@ -1,5 +1,6 @@
Show all commands except debug commands
$ hg debugcomplete
+ abandon
add
addremove
annotate
@@ -54,6 +55,7 @@
Show all commands that start with "a"
$ hg debugcomplete a
+ abandon
add
addremove
annotate
@@ -193,7 +195,7 @@
export: output, switch-parent, rev, text, git, nodates
forget: include, exclude
init: ssh, remotecmd, insecure
- log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
+ log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, abandoned, patch, git, limit, no-merges, stat, style, template, include, exclude
merge: force, tool, rev, preview
pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
@@ -202,6 +204,7 @@
status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
summary: remote
update: clean, check, date, rev
+ abandon: date, user
addremove: similarity, include, exclude, dry-run
archive: no-decode, prefix, rev, type, subrepos, include, exclude
backout: merge, parent, tool, rev, include, exclude, message, logfile, date, user
diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t
--- a/tests/test-globalopts.t
+++ b/tests/test-globalopts.t
@@ -279,6 +279,7 @@
list of commands:
+ abandon abandon specified changeset and its descendents
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information by line for each file
@@ -359,6 +360,7 @@
list of commands:
+ abandon abandon specified changeset and its descendents
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information by line for each file
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -49,6 +49,7 @@
list of commands:
+ abandon abandon specified changeset and its descendents
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information by line for each file
@@ -123,6 +124,7 @@
use "hg -v help" to show builtin aliases and global options
$ hg -q help
+ abandon abandon specified changeset and its descendents
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information by line for each file
@@ -636,6 +638,7 @@
list of commands:
+ abandon abandon specified changeset and its descendents
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information by line for each file
More information about the Mercurial-devel
mailing list