changeset 16728:99f369f5a8db

merge with crew
author Matt Mackall <mpm@selenic.com>
date Tue, 15 May 2012 07:01:35 +0200
parents 3e24ce3de5f1 (diff) b0fb4f57d076 (current diff)
children 46c15dff3497
files
diffstat 20 files changed, 320 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/fetch.py	Sun May 13 12:07:49 2012 +0200
+++ b/hgext/fetch.py	Tue May 15 07:01:35 2012 +0200
@@ -38,7 +38,10 @@
 
     parent, p2 = repo.dirstate.parents()
     branch = repo.dirstate.branch()
-    branchnode = repo.branchtags().get(branch)
+    try:
+        branchnode = repo.branchtip(branch)
+    except error.RepoLookupError:
+        branchnode = None
     if parent != branchnode:
         raise util.Abort(_('working dir not at branch tip '
                            '(use "hg update" to check out branch tip)'))
--- a/hgext/largefiles/lfcommands.py	Sun May 13 12:07:49 2012 +0200
+++ b/hgext/largefiles/lfcommands.py	Tue May 15 07:01:35 2012 +0200
@@ -14,6 +14,7 @@
 from mercurial import util, match as match_, hg, node, context, error, \
     cmdutil, scmutil
 from mercurial.i18n import _
+from mercurial.lock import release
 
 import lfutil
 import basestore
@@ -55,10 +56,12 @@
     rdst = hg.repository(ui, dest, create=True)
 
     success = False
+    dstwlock = dstlock = None
     try:
         # Lock destination to prevent modification while it is converted to.
         # Don't need to lock src because we are just reading from its history
         # which can't change.
+        dstwlock = rdst.wlock()
         dstlock = rdst.lock()
 
         # Get a list of all changesets in the source.  The easy way to do this
@@ -111,10 +114,11 @@
             ui.progress(_('converting revisions'), None)
         success = True
     finally:
+        rdst.dirstate.clear()
+        release(dstlock, dstwlock)
         if not success:
             # we failed, remove the new directory
             shutil.rmtree(rdst.root)
-        dstlock.release()
 
 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
  # Convert src parents to dst parents
--- a/hgext/largefiles/overrides.py	Sun May 13 12:07:49 2012 +0200
+++ b/hgext/largefiles/overrides.py	Tue May 15 07:01:35 2012 +0200
@@ -704,6 +704,12 @@
     return result
 
 def overrideclone(orig, ui, source, dest=None, **opts):
+    if dest is None:
+        dest = defaultdest(source)
+    if opts.get('all_largefiles') and not hg.islocal(dest):
+            raise util.Abort(_(
+            '--all-largefiles is incompatible with non-local destination %s' %
+            dest))
     result = hg.clone(ui, opts, source, dest,
                       pull=opts.get('pull'),
                       stream=opts.get('uncompressed'),
--- a/hgext/mq.py	Sun May 13 12:07:49 2012 +0200
+++ b/hgext/mq.py	Tue May 15 07:01:35 2012 +0200
@@ -2890,8 +2890,10 @@
           ('', 'no-backup', None, _('no backups')),
           ('', 'nobackup', None, _('no backups (DEPRECATED)')),
           ('n', '', None, _('ignored  (DEPRECATED)')),
-          ('k', 'keep', None, _("do not modify working copy during strip"))],
-          _('hg strip [-k] [-f] [-n] REV...'))
+          ('k', 'keep', None, _("do not modify working copy during strip")),
+          ('B', 'bookmark', '', _("remove revs only reachable from given"
+                                  " bookmark"))],
+          _('hg strip [-k] [-f] [-n] [-B bookmark] REV...'))
 def strip(ui, repo, *revs, **opts):
     """strip changesets and all their descendants from the repository
 
@@ -2926,6 +2928,32 @@
     cl = repo.changelog
     revs = list(revs) + opts.get('rev')
     revs = set(scmutil.revrange(repo, revs))
+
+    if opts.get('bookmark'):
+        mark = opts.get('bookmark')
+        marks = repo._bookmarks
+        if mark not in marks:
+            raise util.Abort(_("bookmark '%s' not found") % mark)
+
+        # If the requested bookmark is not the only one pointing to a
+        # a revision we have to only delete the bookmark and not strip
+        # anything. revsets cannot detect that case.
+        uniquebm = True
+        for m, n in marks.iteritems():
+            if m != mark and n == repo[mark].node():
+                uniquebm = False
+                break
+        if uniquebm:
+            rsrevs = repo.revs("ancestors(bookmark(%s)) - "
+                               "ancestors(head() and not bookmark(%s)) - "
+                               "ancestors(bookmark() and not bookmark(%s))",
+                               mark, mark, mark)
+            revs.update(set(rsrevs))
+        if not revs:
+            del marks[mark]
+            repo._writebookmarks(mark)
+            ui.write(_("bookmark '%s' deleted\n") % mark)
+
     if not revs:
         raise util.Abort(_('empty revision set'))
 
@@ -2973,6 +3001,12 @@
 
     repo.mq.strip(repo, revs, backup=backup, update=update,
                   force=opts.get('force'))
+
+    if opts.get('bookmark'):
+        del marks[mark]
+        repo._writebookmarks(marks)
+        ui.write(_("bookmark '%s' deleted\n") % mark)
+
     return 0
 
 @command("qselect",
--- a/mercurial/bookmarks.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/bookmarks.py	Tue May 15 07:01:35 2012 +0200
@@ -7,7 +7,7 @@
 
 from mercurial.i18n import _
 from mercurial.node import hex
-from mercurial import encoding, util
+from mercurial import encoding, error, util
 import errno, os
 
 def valid(mark):
@@ -140,8 +140,8 @@
 
 def updatecurrentbookmark(repo, oldnode, curbranch):
     try:
-        return update(repo, oldnode, repo.branchtags()[curbranch])
-    except KeyError:
+        return update(repo, oldnode, repo.branchtip(curbranch))
+    except error.RepoLookupError:
         if curbranch == "default": # no default branch!
             return update(repo, oldnode, repo.lookup("tip"))
         else:
--- a/mercurial/commands.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/commands.py	Tue May 15 07:01:35 2012 +0200
@@ -827,7 +827,7 @@
         if mark in marks and not force:
             raise util.Abort(_("bookmark '%s' already exists "
                                "(use -f to force)") % mark)
-        if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
+        if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
             and not force):
             raise util.Abort(
                 _("a bookmark cannot have the name of an existing branch"))
@@ -903,7 +903,7 @@
             repo.dirstate.setbranch(label)
             ui.status(_('reset working directory to branch %s\n') % label)
         elif label:
-            if not opts.get('force') and label in repo.branchtags():
+            if not opts.get('force') and label in repo.branchmap():
                 if label not in [p.branch() for p in repo.parents()]:
                     raise util.Abort(_('a branch of the same name already'
                                        ' exists'),
@@ -936,22 +936,29 @@
     """
 
     hexfunc = ui.debugflag and hex or short
-    activebranches = [repo[n].branch() for n in repo.heads()]
-    def testactive(tag, node):
-        realhead = tag in activebranches
-        open = node in repo.branchheads(tag, closed=False)
-        return realhead and open
-    branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
-                          for tag, node in repo.branchtags().items()],
-                      reverse=True)
-
-    for isactive, node, tag in branches:
+
+    activebranches = set([repo[n].branch() for n in repo.heads()])
+    branches = []
+    for tag, heads in repo.branchmap().iteritems():
+        for h in reversed(heads):
+            ctx = repo[h]
+            isopen = not ctx.closesbranch()
+            if isopen:
+                tip = ctx
+                break
+        else:
+            tip = repo[heads[-1]]
+        isactive = tag in activebranches and isopen
+        branches.append((tip, isactive, isopen))
+    branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
+                  reverse=True)
+
+    for ctx, isactive, isopen in branches:
         if (not active) or isactive:
-            hn = repo.lookup(node)
             if isactive:
                 label = 'branches.active'
                 notice = ''
-            elif hn not in repo.branchheads(tag, closed=False):
+            elif not isopen:
                 if not closed:
                     continue
                 label = 'branches.closed'
@@ -959,11 +966,12 @@
             else:
                 label = 'branches.inactive'
                 notice = _(' (inactive)')
-            if tag == repo.dirstate.branch():
+            if ctx.branch() == repo.dirstate.branch():
                 label = 'branches.current'
-            rev = str(node).rjust(31 - encoding.colwidth(tag))
-            rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
-            tag = ui.label(tag, label)
+            rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
+            rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
+                           'log.changeset')
+            tag = ui.label(ctx.branch(), label)
             if ui.quiet:
                 ui.write("%s\n" % tag)
             else:
@@ -1349,7 +1357,7 @@
 
     if not opts.get('close_branch'):
         for r in parents:
-            if r.extra().get('close') and r.branch() == branch:
+            if r.closesbranch() and r.branch() == branch:
                 ui.status(_('reopening closed branch head %d\n') % r)
 
     if ui.debugflag:
@@ -4443,25 +4451,23 @@
                 phases.retractboundary(repo, targetphase, nodes)
         finally:
             lock.release()
-        if olddata is not None:
-            changes = 0
-            newdata = repo._phasecache.getphaserevs(repo)
-            changes = sum(o != newdata[i] for i, o in enumerate(olddata))
-            rejected = [n for n in nodes
-                        if newdata[repo[n].rev()] < targetphase]
-            if rejected:
-                ui.warn(_('cannot move %i changesets to a more permissive '
-                          'phase, use --force\n') % len(rejected))
-                ret = 1
-            if changes:
-                msg = _('phase changed for %i changesets\n') % changes
-                if ret:
-                    ui.status(msg)
-                else:
-                    ui.note(msg)
+        newdata = repo._phasecache.getphaserevs(repo)
+        changes = sum(o != newdata[i] for i, o in enumerate(olddata))
+        rejected = [n for n in nodes
+                    if newdata[repo[n].rev()] < targetphase]
+        if rejected:
+            ui.warn(_('cannot move %i changesets to a more permissive '
+                      'phase, use --force\n') % len(rejected))
+            ret = 1
+        if changes:
+            msg = _('phase changed for %i changesets\n') % changes
+            if ret:
+                ui.status(msg)
             else:
-                ui.warn(_('no phases changed\n'))
-                ret = 1
+                ui.note(msg)
+        else:
+            ui.warn(_('no phases changed\n'))
+            ret = 1
     return ret
 
 def postincoming(ui, repo, modheads, optupdate, checkout):
@@ -5416,7 +5422,7 @@
         t += _(' (merge)')
     elif branch != parents[0].branch():
         t += _(' (new branch)')
-    elif (parents[0].extra().get('close') and
+    elif (parents[0].closesbranch() and
           pnode in repo.branchheads(branch, closed=True)):
         t += _(' (head closed)')
     elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
--- a/mercurial/context.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/context.py	Tue May 15 07:01:35 2012 +0200
@@ -78,10 +78,12 @@
             self._node = repo._tagscache.tags[changeid]
             self._rev = repo.changelog.rev(self._node)
             return
-        if changeid in repo.branchtags():
-            self._node = repo.branchtags()[changeid]
+        try:
+            self._node = repo.branchtip(changeid)
             self._rev = repo.changelog.rev(self._node)
             return
+        except error.RepoLookupError:
+            pass
 
         self._node = repo.changelog._partialmatch(changeid)
         if self._node is not None:
@@ -184,6 +186,8 @@
         return self._changeset[4]
     def branch(self):
         return encoding.tolocal(self._changeset[5].get("branch"))
+    def closesbranch(self):
+        return 'close' in self._changeset[5]
     def extra(self):
         return self._changeset[5]
     def tags(self):
@@ -893,6 +897,8 @@
         return self._clean
     def branch(self):
         return encoding.tolocal(self._extra['branch'])
+    def closesbranch(self):
+        return 'close' in self._extra
     def extra(self):
         return self._extra
 
--- a/mercurial/hgweb/webcommands.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/hgweb/webcommands.py	Tue May 15 07:01:35 2012 +0200
@@ -441,7 +441,7 @@
     tips = (web.repo[n] for t, n in web.repo.branchtags().iteritems())
     heads = web.repo.heads()
     parity = paritygen(web.stripecount)
-    sortkey = lambda ctx: ('close' not in ctx.extra(), ctx.rev())
+    sortkey = lambda ctx: (not ctx.closesbranch(), ctx.rev())
 
     def entries(limit, **map):
         count = 0
@@ -558,6 +558,7 @@
     if fctx is not None:
         n = fctx.node()
         path = fctx.path()
+        ctx = fctx.changectx()
     else:
         n = ctx.node()
         # path already defined in except clause
@@ -567,7 +568,7 @@
     if 'style' in req.form:
         style = req.form['style'][0]
 
-    diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
+    diffs = webutil.diffs(web.repo, tmpl, ctx, [path], parity, style)
     rename = fctx and webutil.renamelink(fctx) or []
     ctx = fctx and fctx or ctx
     return tmpl("filediff",
@@ -794,7 +795,11 @@
         desc = cgi.escape(templatefilters.nonempty(desc))
         user = cgi.escape(templatefilters.person(ctx.user()))
         branch = ctx.branch()
-        branch = branch, web.repo.branchtags().get(branch) == ctx.node()
+        try:
+            branchnode = web.repo.branchtip(branch)
+        except error.RepoLookupError:
+            branchnode = None
+        branch = branch, branchnode == ctx.node()
         data.append((node, vtx, edges, desc, user, age, branch, ctx.tags(),
                      ctx.bookmarks()))
 
--- a/mercurial/hgweb/webutil.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/hgweb/webutil.py	Tue May 15 07:01:35 2012 +0200
@@ -98,16 +98,23 @@
     branches = []
     branch = ctx.branch()
     # If this is an empty repo, ctx.node() == nullid,
-    # ctx.branch() == 'default', but branchtags() is
-    # an empty dict. Using dict.get avoids a traceback.
-    if repo.branchtags().get(branch) == ctx.node():
+    # ctx.branch() == 'default'.
+    try:
+        branchnode = repo.branchtip(branch)
+    except error.RepoLookupError:
+        branchnode = None
+    if branchnode == ctx.node():
         branches.append({"name": branch})
     return branches
 
 def nodeinbranch(repo, ctx):
     branches = []
     branch = ctx.branch()
-    if branch != 'default' and repo.branchtags().get(branch) != ctx.node():
+    try:
+        branchnode = repo.branchtip(branch)
+    except error.RepoLookupError:
+        branchnode = None
+    if branch != 'default' and branchnode != ctx.node():
         branches.append({"name": branch})
     return branches
 
--- a/mercurial/localrepo.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/localrepo.py	Tue May 15 07:01:35 2012 +0200
@@ -507,17 +507,27 @@
         self.updatebranchcache()
         return self._branchcache
 
+    def _branchtip(self, heads):
+        '''return the tipmost branch head in heads'''
+        tip = heads[-1]
+        for h in reversed(heads):
+            if not self[h].closesbranch():
+                tip = h
+                break
+        return tip
+
+    def branchtip(self, branch):
+        '''return the tip node for a given branch'''
+        if branch not in self.branchmap():
+            raise error.RepoLookupError(_("unknown branch '%s'") % branch)
+        return self._branchtip(self.branchmap()[branch])
+
     def branchtags(self):
         '''return a dict where branch names map to the tipmost head of
         the branch, open heads come before closed'''
         bt = {}
         for bn, heads in self.branchmap().iteritems():
-            tip = heads[-1]
-            for h in reversed(heads):
-                if 'close' not in self.changelog.read(h)[5]:
-                    tip = h
-                    break
-            bt[bn] = tip
+            bt[bn] = self._branchtip(heads)
         return bt
 
     def _readbranchcache(self):
@@ -540,6 +550,9 @@
                     continue
                 node, label = l.split(" ", 1)
                 label = encoding.tolocal(label.strip())
+                if not node in self:
+                    raise ValueError('invalidating branch cache because node '+
+                                     '%s does not exist' % node)
                 partial.setdefault(label, []).append(bin(node))
         except KeyboardInterrupt:
             raise
@@ -561,6 +574,10 @@
             pass
 
     def _updatebranchcache(self, partial, ctxgen):
+        """Given a branchhead cache, partial, that may have extra nodes or be
+        missing heads, and a generator of nodes that are at least a superset of
+        heads missing, this function updates partial to be correct.
+        """
         # collect new branch entries
         newbranches = {}
         for c in ctxgen:
@@ -571,21 +588,42 @@
         for branch, newnodes in newbranches.iteritems():
             bheads = partial.setdefault(branch, [])
             bheads.extend(newnodes)
-            if len(bheads) <= 1:
-                continue
-            bheads = sorted(bheads, key=lambda x: self[x].rev())
-            # starting from tip means fewer passes over reachable
-            while newnodes:
-                latest = newnodes.pop()
-                if latest not in bheads:
-                    continue
-                minbhnode = self[bheads[0]].node()
-                reachable = self.changelog.reachable(latest, minbhnode)
-                reachable.remove(latest)
-                if reachable:
-                    bheads = [b for b in bheads if b not in reachable]
+            # Remove duplicates - nodes that are in newnodes and are already in
+            # bheads.  This can happen if you strip a node and its parent was
+            # already a head (because they're on different branches).
+            bheads = set(bheads)
+
+            # Remove candidate heads that no longer are in the repo (e.g., as
+            # the result of a strip that just happened).
+            # avoid using 'bhead in self' here because that dives down into
+            # branchcache code somewhat recrusively.
+            bheads = [bhead for bhead in bheads \
+                          if self.changelog.hasnode(bhead)]
+            if len(bheads) > 1:
+                bheads = sorted(bheads, key=lambda x: self[x].rev())
+                # starting from tip means fewer passes over reachable
+                while newnodes:
+                    latest = newnodes.pop()
+                    if latest not in bheads:
+                        continue
+                    minbhnode = self[bheads[0]].node()
+                    reachable = self.changelog.reachable(latest, minbhnode)
+                    reachable.remove(latest)
+                    if reachable:
+                        bheads = [b for b in bheads if b not in reachable]
             partial[branch] = bheads
 
+        # There may be branches that cease to exist when the last commit in the
+        # branch was stripped.  This code filters them out.  Note that the
+        # branch that ceased to exist may not be in newbranches because
+        # newbranches is the set of candidate heads, which when you strip the
+        # last commit in a branch will be the parent branch.
+        for branch in partial.keys():
+            nodes = [head for head in partial[branch] \
+                         if self.changelog.hasnode(head)]
+            if len(nodes) < 1:
+                del partial[branch]
+
     def lookup(self, key):
         return self[key].node()
 
@@ -848,6 +886,9 @@
             else:
                 ui.status(_('working directory now based on '
                             'revision %d\n') % parents)
+        # TODO: if we know which new heads may result from this rollback, pass
+        # them to destroy(), which will prevent the branchhead cache from being
+        # invalidated.
         self.destroyed()
         return 0
 
@@ -1291,12 +1332,27 @@
                 tr.release()
             lock.release()
 
-    def destroyed(self):
+    def destroyed(self, newheadrevs=None):
         '''Inform the repository that nodes have been destroyed.
         Intended for use by strip and rollback, so there's a common
-        place for anything that has to be done after destroying history.'''
-        # XXX it might be nice if we could take the list of destroyed
-        # nodes, but I don't see an easy way for rollback() to do that
+        place for anything that has to be done after destroying history.
+
+        If you know the branchheadcache was uptodate before nodes were removed
+        and you also know the set of candidate set of new heads that may have
+        resulted from the destruction, you can set newheadrevs.  This will
+        enable the code to update the branchheads cache, rather than having
+        future code decide it's invalid and regenrating it.
+        '''
+        if newheadrevs:
+            tiprev = len(self) - 1
+            ctxgen = (self[rev] for rev in newheadrevs)
+            self._updatebranchcache(self._branchcache, ctxgen)
+            self._writebranchcache(self._branchcache, self.changelog.tip(),
+                                   tiprev)
+        else:
+            # No info to update the cache.  If nodes were destroyed, the cache
+            # is stale and this will be caught the next time it is read.
+            pass
 
         # Ensure the persistent tag cache is updated.  Doing it now
         # means that the tag cache only has to worry about destroyed
@@ -1499,8 +1555,7 @@
             fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
             bheads = [h for h in bheads if h in fbheads]
         if not closed:
-            bheads = [h for h in bheads if
-                      ('close' not in self.changelog.read(h)[5])]
+            bheads = [h for h in bheads if not self[h].closesbranch()]
         return bheads
 
     def branches(self, nodes):
@@ -2150,7 +2205,7 @@
                 heads = cl.heads()
                 dh = len(heads) - len(oldheads)
                 for h in heads:
-                    if h not in oldheads and 'close' in self[h].extra():
+                    if h not in oldheads and self[h].closesbranch():
                         dh -= 1
             htext = ""
             if dh:
--- a/mercurial/merge.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/merge.py	Tue May 15 07:01:35 2012 +0200
@@ -7,7 +7,7 @@
 
 from node import nullid, nullrev, hex, bin
 from i18n import _
-import scmutil, util, filemerge, copies, subrepo
+import error, scmutil, util, filemerge, copies, subrepo
 import errno, os, shutil
 
 class mergestate(object):
@@ -529,8 +529,8 @@
         if node is None:
             # tip of current branch
             try:
-                node = repo.branchtags()[wc.branch()]
-            except KeyError:
+                node = repo.branchtip(wc.branch())
+            except error.RepoLookupError:
                 if wc.branch() == "default": # no default branch!
                     node = repo.lookup("tip") # update to tip
                 else:
--- a/mercurial/posix.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/posix.py	Tue May 15 07:01:35 2012 +0200
@@ -409,10 +409,13 @@
                     continue
                 if not os.isatty(fd):
                     continue
-                arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
-                width = array.array('h', arri)[1]
-                if width > 0:
-                    return width
+                try:
+                    arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
+                    width = array.array('h', arri)[1]
+                    if width > 0:
+                        return width
+                except AttributeError:
+                    pass
             except ValueError:
                 pass
             except IOError, e:
--- a/mercurial/repair.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/repair.py	Tue May 15 07:01:35 2012 +0200
@@ -56,6 +56,11 @@
     return s
 
 def strip(ui, repo, nodelist, backup="all", topic='backup'):
+    # It simplifies the logic around updating the branchheads cache if we only
+    # have to consider the effect of the stripped revisions and not revisions
+    # missing because the cache is out-of-date.
+    repo.updatebranchcache()
+
     cl = repo.changelog
     # TODO handle undo of merge sets
     if isinstance(nodelist, str):
@@ -63,6 +68,14 @@
     striplist = [cl.rev(node) for node in nodelist]
     striprev = min(striplist)
 
+    # Set of potential new heads resulting from the strip.  The parents of any
+    # node removed could be a new head because the node to be removed could have
+    # been the only child of the parent.
+    # Do a list->set->list conversion to remove duplicates.
+    stringstriplist = [str(rev) for rev in striplist]
+    newheadrevs = set(repo.revs("parents(%lr::) - %lr::", stringstriplist,
+                                stringstriplist))
+
     keeppartialbundle = backup == 'strip'
 
     # Some revisions with rev > striprev may not be descendants of striprev.
@@ -169,4 +182,4 @@
                     % chgrpfile)
         raise
 
-    repo.destroyed()
+    repo.destroyed(newheadrevs)
--- a/mercurial/revset.py	Sun May 13 12:07:49 2012 +0200
+++ b/mercurial/revset.py	Tue May 15 07:01:35 2012 +0200
@@ -395,7 +395,7 @@
     """
     # i18n: "closed" is a keyword
     getargs(x, 0, 0, _("closed takes no arguments"))
-    return [r for r in subset if repo[r].extra().get('close')]
+    return [r for r in subset if repo[r].closesbranch()]
 
 def contains(repo, subset, x):
     """``contains(pattern)``
--- a/tests/test-commit-amend.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-commit-amend.t	Tue May 15 07:01:35 2012 +0200
@@ -247,6 +247,7 @@
 
   $ echo b >> b
   $ hg ci -m 'reopen branch'
+  created new head
   reopening closed branch head 4
   $ echo b >> b
   $ hg ci --amend --close-branch
--- a/tests/test-hgweb-commands.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-hgweb-commands.t	Tue May 15 07:01:35 2012 +0200
@@ -663,15 +663,24 @@
   </body>
   </html>
   
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/0/foo/?style=raw'
+  200 Script output follows
+  
+  
+  diff -r 000000000000 -r 2ef0ac749a14 foo
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +foo
+  
+  
+  
+  
+
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
   200 Script output follows
   
   
-  diff -r 000000000000 -r a4f92ed23982 foo
-  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
-  @@ -0,0 +1,1 @@
-  +foo
   
   
   
--- a/tests/test-hgweb-diffs.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-hgweb-diffs.t	Tue May 15 07:01:35 2012 +0200
@@ -13,6 +13,7 @@
 change permissions for git diffs
 
   $ chmod +x a
+  $ hg rm b
   $ hg ci -Amb
 
 set up hgweb
@@ -90,7 +91,7 @@
   </tr>
   <tr>
    <th class="author">children</th>
-   <td class="author"> <a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+   <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
   </tr>
   <tr>
    <th class="files">files</th>
@@ -177,7 +178,7 @@
 
 diff removed file
 
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/b'
   200 Script output follows
   
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -188,7 +189,7 @@
   <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
   <script type="text/javascript" src="/static/mercurial.js"></script>
   
-  <title>test: a diff</title>
+  <title>test: b diff</title>
   </head>
   <body>
   
@@ -199,23 +200,23 @@
   <img src="/static/hglogo.png" alt="mercurial" /></a>
   </div>
   <ul>
-  <li><a href="/shortlog/78e4ebad7cdf">log</a></li>
-  <li><a href="/graph/78e4ebad7cdf">graph</a></li>
+  <li><a href="/shortlog/559edbd9ed20">log</a></li>
+  <li><a href="/graph/559edbd9ed20">graph</a></li>
   <li><a href="/tags">tags</a></li>
   <li><a href="/bookmarks">bookmarks</a></li>
   <li><a href="/branches">branches</a></li>
   </ul>
   <ul>
-  <li><a href="/rev/78e4ebad7cdf">changeset</a></li>
-  <li><a href="/file/78e4ebad7cdf">browse</a></li>
+  <li><a href="/rev/559edbd9ed20">changeset</a></li>
+  <li><a href="/file/559edbd9ed20">browse</a></li>
   </ul>
   <ul>
-  <li><a href="/file/78e4ebad7cdf/a">file</a></li>
-  <li><a href="/file/tip/a">latest</a></li>
+  <li><a href="/file/559edbd9ed20/b">file</a></li>
+  <li><a href="/file/tip/b">latest</a></li>
   <li class="active">diff</li>
-  <li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
-  <li><a href="/log/78e4ebad7cdf/a">file log</a></li>
-  <li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+  <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
+  <li><a href="/log/559edbd9ed20/b">file log</a></li>
+  <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
   </ul>
   <ul>
   <li><a href="/help">help</a></li>
@@ -224,7 +225,7 @@
   
   <div class="main">
   <h2><a href="/">test</a></h2>
-  <h3>diff a @ 1:78e4ebad7cdf</h3>
+  <h3>diff b @ 1:559edbd9ed20</h3>
   
   <form class="search" action="/log">
   <p></p>
@@ -246,7 +247,7 @@
   </tr>
   <tr>
    <th>parents</th>
-   <td></td>
+   <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
   </tr>
   <tr>
    <th>children</th>
@@ -258,10 +259,10 @@
   <div class="overflow">
   <div class="sourcefirst">   line diff</div>
   
-  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  </span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ b/a	Thu Jan 01 00:00:00 1970 +0000
-  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -0,0 +1,1 @@
-  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="plusline">+a
+  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- a/b	Thu Jan 01 00:00:00 1970 +0000
+  </span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -1,1 +0,0 @@
+  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="minusline">-b
   </span></pre></div>
   </div>
   </div>
@@ -350,7 +351,7 @@
   </tr>
   <tr>
    <th class="author">children</th>
-   <td class="author"> <a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+   <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
   </tr>
   <tr>
    <th class="files">files</th>
@@ -463,23 +464,23 @@
   <img src="/static/hglogo.png" alt="mercurial" /></a>
   </div>
   <ul>
-  <li><a href="/shortlog/78e4ebad7cdf">log</a></li>
-  <li><a href="/graph/78e4ebad7cdf">graph</a></li>
+  <li><a href="/shortlog/559edbd9ed20">log</a></li>
+  <li><a href="/graph/559edbd9ed20">graph</a></li>
   <li><a href="/tags">tags</a></li>
   <li><a href="/bookmarks">bookmarks</a></li>
   <li><a href="/branches">branches</a></li>
   </ul>
   <ul>
-  <li><a href="/rev/78e4ebad7cdf">changeset</a></li>
-  <li><a href="/file/78e4ebad7cdf">browse</a></li>
+  <li><a href="/rev/559edbd9ed20">changeset</a></li>
+  <li><a href="/file/559edbd9ed20">browse</a></li>
   </ul>
   <ul>
-  <li><a href="/file/78e4ebad7cdf/a">file</a></li>
+  <li><a href="/file/559edbd9ed20/a">file</a></li>
   <li><a href="/file/tip/a">latest</a></li>
   <li class="active">diff</li>
-  <li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
-  <li><a href="/log/78e4ebad7cdf/a">file log</a></li>
-  <li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+  <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
+  <li><a href="/log/559edbd9ed20/a">file log</a></li>
+  <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
   </ul>
   <ul>
   <li><a href="/help">help</a></li>
@@ -488,7 +489,7 @@
   
   <div class="main">
   <h2><a href="/">test</a></h2>
-  <h3>diff a @ 1:78e4ebad7cdf</h3>
+  <h3>diff a @ 1:559edbd9ed20</h3>
   
   <form class="search" action="/log">
   <p></p>
@@ -522,12 +523,9 @@
   <div class="overflow">
   <div class="sourcefirst">   line diff</div>
   
-  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> new file mode 100755
-  <a href="#l1.2" id="l1.2">     1.2</a> <span class="minusline">--- /dev/null
-  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="plusline">+++ b/a
-  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="atline">@@ -0,0 +1,1 @@
-  </span><a href="#l1.5" id="l1.5">     1.5</a> <span class="plusline">+a
-  </span></pre></div>
+  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> old mode 100644
+  <a href="#l1.2" id="l1.2">     1.2</a> new mode 100755
+  </pre></div>
   </div>
   </div>
   </div>
--- a/tests/test-largefiles.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-largefiles.t	Tue May 15 07:01:35 2012 +0200
@@ -444,6 +444,10 @@
   3 largefiles updated, 0 removed
   8 additional largefiles cached
 
+  $ hg clone --all-largefiles a ssh://localhost/a
+  abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
+  [255]
+
 Test pulling with --all-largefiles flag
 
   $ rm -Rf a-backup
--- a/tests/test-mq-caches.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-mq-caches.t	Tue May 15 07:01:35 2012 +0200
@@ -36,7 +36,8 @@
   $ hg qrefresh -m 'patch 1'
   $ show_branch_cache
   tip: 0
-  No branch cache
+  d986d5caac23a7d44a46efc0ddaf5eb9665844cf 0
+  d986d5caac23a7d44a46efc0ddaf5eb9665844cf default
 
 some regular revisions
 
@@ -75,8 +76,8 @@
   $ hg qrefresh -m 'patch 2'
   $ show_branch_cache 1
   tip: 3
-  c229711f16da3d7591f89b1b8d963b79bda22714 1
-  c229711f16da3d7591f89b1b8d963b79bda22714 bar
+  982611f6955f9c48d3365decea203217c945ef0d 2
+  982611f6955f9c48d3365decea203217c945ef0d bar
   dc25e3827021582e979f600811852e36cbe57341 foo
   branch foo: 3
   branch bar: 2
--- a/tests/test-mq-strip.t	Sun May 13 12:07:49 2012 +0200
+++ b/tests/test-mq-strip.t	Tue May 15 07:01:35 2012 +0200
@@ -430,3 +430,37 @@
   $ hg strip 'not ancestors(x)'
   saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
 
+test hg strip -B bookmark
+
+  $ cd ..
+  $ hg init bookmarks
+  $ cd bookmarks
+  $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
+  $ hg bookmark -r 'a' 'todelete'
+  $ hg bookmark -r 'b' 'B'
+  $ hg bookmark -r 'b' 'nostrip'
+  $ hg bookmark -r 'c' 'delete'
+  $ hg up -C todelete
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg strip -B nostrip
+  bookmark 'nostrip' deleted
+  abort: empty revision set
+  [255]
+  $ hg strip -B todelete
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+  bookmark 'todelete' deleted
+  $ hg id -ir dcbb326fdec2
+  abort: unknown revision 'dcbb326fdec2'!
+  [255]
+  $ hg id -ir d62d843c9a01
+  d62d843c9a01
+  $ hg bookmarks
+     B                         9:ff43616e5d0f
+     delete                    6:2702dd0c91e7
+  $ hg strip -B delete
+  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+  bookmark 'delete' deleted
+  $ hg id -ir 6:2702dd0c91e7
+  abort: unknown revision '2702dd0c91e7'!
+  [255]