[PATCH 1 of 8] commands: add abandon command

Matt Mackall mpm at selenic.com
Wed Jun 1 12:22:28 CDT 2011


On Wed, 2011-06-01 at 18:42 +0200, Martin Geisler wrote:
> # HG changeset patch
> # User Martin Geisler <mg at lazybytes.net>
> # Date 1306919141 -7200
> # Node ID 9b14fa930acae9dc802d7cec87780ba1a3a9aa8b
> # Parent  1ffeeb91c55d0b00445ceabde14a0d0faf906a33
> commands: add abandon command

Going to need a more complete doc string, of course.

> 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
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel


-- 
Mathematics is the supreme nostalgia of our time.




More information about the Mercurial-devel mailing list