Merge with crew
authorBryan O'Sullivan <bos@serpentine.com>
Wed, 20 Feb 2008 13:38:16 -0800
changeset 6151 8bc4fe428103
parent 6150 aafdea37f796 (current diff)
parent 6149 b023915aa1bc (diff)
child 6152 c050548307a4
Merge with crew
--- a/mercurial/cmdutil.py	Fri Jan 25 04:11:32 2008 -0500
+++ b/mercurial/cmdutil.py	Wed Feb 20 13:38:16 2008 -0800
@@ -967,7 +967,7 @@
     if follow:
         defrange = '%s:0' % repo.changectx().rev()
     else:
-        defrange = 'tip:0'
+        defrange = '-1:0'
     revs = revrange(repo, opts['rev'] or [defrange])
     wanted = {}
     slowpath = anypats or opts.get('removed')
--- a/mercurial/commands.py	Fri Jan 25 04:11:32 2008 -0500
+++ b/mercurial/commands.py	Wed Feb 20 13:38:16 2008 -0800
@@ -1072,19 +1072,19 @@
         if st == 'window':
             matches.clear()
         elif st == 'add':
-            mf = repo.changectx(rev).manifest()
+            ctx = repo.changectx(rev)
             matches[rev] = {}
             for fn in fns:
                 if fn in skip:
                     continue
                 try:
-                    grepbody(fn, rev, getfile(fn).read(mf[fn]))
+                    grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
                     fstate.setdefault(fn, [])
                     if follow:
-                        copied = getfile(fn).renamed(mf[fn])
+                        copied = getfile(fn).renamed(ctx.filenode(fn))
                         if copied:
                             copies.setdefault(rev, {})[fn] = copied[0]
-                except KeyError:
+                except revlog.LookupError:
                     pass
         elif st == 'iter':
             states = matches[rev].items()
--- a/mercurial/hgweb/hgweb_mod.py	Fri Jan 25 04:11:32 2008 -0500
+++ b/mercurial/hgweb/hgweb_mod.py	Wed Feb 20 13:38:16 2008 -0800
@@ -199,35 +199,38 @@
                         req.form['node'] = [fn[:-len(ext)]]
                         req.form['type'] = [type_]
 
-        # actually process the request
+        # process this if it's a protocol request
+
+        cmd = req.form.get('cmd', [''])[0]
+        if cmd in protocol.__all__:
+            method = getattr(protocol, cmd)
+            method(self, req)
+            return
+
+        # process the web interface request
 
         try:
 
-            cmd = req.form.get('cmd', [''])[0]
-            if cmd in protocol.__all__:
-                method = getattr(protocol, cmd)
-                method(self, req)
-            else:
-                tmpl = self.templater(req)
-                ctype = tmpl('mimetype', encoding=self.encoding)
-                ctype = templater.stringify(ctype)
-                
-                if cmd == '':
-                    req.form['cmd'] = [tmpl.cache['default']]
-                    cmd = req.form['cmd'][0]
+            tmpl = self.templater(req)
+            ctype = tmpl('mimetype', encoding=self.encoding)
+            ctype = templater.stringify(ctype)
+
+            if cmd == '':
+                req.form['cmd'] = [tmpl.cache['default']]
+                cmd = req.form['cmd'][0]
 
-                if cmd not in webcommands.__all__:
-                    msg = 'No such method: %s' % cmd
-                    raise ErrorResponse(HTTP_BAD_REQUEST, msg)
-                elif cmd == 'file' and 'raw' in req.form.get('style', []):
-                    self.ctype = ctype
-                    content = webcommands.rawfile(self, req, tmpl)
-                else:
-                    content = getattr(webcommands, cmd)(self, req, tmpl)
-                    req.respond(HTTP_OK, ctype)
+            if cmd not in webcommands.__all__:
+                msg = 'No such method: %s' % cmd
+                raise ErrorResponse(HTTP_BAD_REQUEST, msg)
+            elif cmd == 'file' and 'raw' in req.form.get('style', []):
+                self.ctype = ctype
+                content = webcommands.rawfile(self, req, tmpl)
+            else:
+                content = getattr(webcommands, cmd)(self, req, tmpl)
+                req.respond(HTTP_OK, ctype)
 
-                req.write(content)
-                del tmpl
+            req.write(content)
+            del tmpl
 
         except revlog.LookupError, err:
             req.respond(HTTP_NOT_FOUND, ctype)
--- a/mercurial/repair.py	Fri Jan 25 04:11:32 2008 -0500
+++ b/mercurial/repair.py	Wed Feb 20 13:38:16 2008 -0800
@@ -9,18 +9,6 @@
 import changegroup, os
 from node import *
 
-def _limitheads(cl, stoprev):
-    """return the list of all revs >= stoprev that have no children"""
-    seen = {}
-    heads = []
-
-    for r in xrange(cl.count() - 1, stoprev - 1, -1):
-        if r not in seen:
-            heads.append(r)
-        for p in cl.parentrevs(r):
-            seen[p] = 1
-    return heads
-
 def _bundle(repo, bases, heads, node, suffix, extranodes=None):
     """create a bundle with the specified revisions as a backup"""
     cg = repo.changegroupsubset(bases, heads, 'strip', extranodes)
@@ -87,42 +75,39 @@
     pp = cl.parents(node)
     striprev = cl.rev(node)
 
-    # save is a list of all the branches we are truncating away
-    # that we actually want to keep.  changegroup will be used
-    # to preserve them and add them back after the truncate
-    saveheads = []
-    savebases = {}
-
-    heads = [cl.node(r) for r in _limitheads(cl, striprev)]
-    seen = {}
+    # Some revisions with rev > striprev may not be descendants of striprev.
+    # We have to find these revisions and put them in a bundle, so that
+    # we can restore them after the truncations.
+    # To create the bundle we use repo.changegroupsubset which requires
+    # the list of heads and bases of the set of interesting revisions.
+    # (head = revision in the set that has no descendant in the set;
+    #  base = revision in the set that has no ancestor in the set)
+    tostrip = {striprev: 1}
+    saveheads = {}
+    savebases = []
+    for r in xrange(striprev + 1, cl.count()):
+        parents = cl.parentrevs(r)
+        if parents[0] in tostrip or parents[1] in tostrip:
+            # r is a descendant of striprev
+            tostrip[r] = 1
+            # if this is a merge and one of the parents does not descend
+            # from striprev, mark that parent as a savehead.
+            if parents[1] != nullrev:
+                for p in parents:
+                    if p not in tostrip and p > striprev:
+                        saveheads[p] = 1
+        else:
+            # if no parents of this revision will be stripped, mark it as
+            # a savebase
+            if parents[0] < striprev and parents[1] < striprev:
+                savebases.append(cl.node(r))
 
-    # search through all the heads, finding those where the revision
-    # we want to strip away is an ancestor.  Also look for merges
-    # that might be turned into new heads by the strip.
-    while heads:
-        h = heads.pop()
-        n = h
-        while True:
-            seen[n] = 1
-            pp = cl.parents(n)
-            if pp[1] != nullid:
-                for p in pp:
-                    if cl.rev(p) > striprev and p not in seen:
-                        heads.append(p)
-            if pp[0] == nullid:
-                break
-            if cl.rev(pp[0]) < striprev:
-                break
-            n = pp[0]
-            if n == node:
-                break
-        r = cl.reachable(h, node)
-        if node not in r:
-            saveheads.append(h)
-            for x in r:
-                if cl.rev(x) > striprev:
-                    savebases[x] = 1
+            for p in parents:
+                if p in saveheads:
+                    del saveheads[p]
+            saveheads[r] = 1
 
+    saveheads = [cl.node(r) for r in saveheads]
     files = _collectfiles(repo, striprev)
 
     extranodes = _collectextranodes(repo, files, striprev)
@@ -131,7 +116,7 @@
     if backup == "all":
         _bundle(repo, [node], cl.heads(), node, 'backup')
     if saveheads or extranodes:
-        chgrpfile = _bundle(repo, savebases.keys(), saveheads, node, 'temp',
+        chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
                             extranodes)
 
     cl.strip(striprev)
--- a/mercurial/revlog.py	Fri Jan 25 04:11:32 2008 -0500
+++ b/mercurial/revlog.py	Wed Feb 20 13:38:16 2008 -0800
@@ -933,19 +933,19 @@
             raise RevlogError(_('incompatible revision flag %x') %
                               (self.index[rev][0] & 0xFFFF))
 
-        if self._inline:
-            # we probably have the whole chunk cached
-            df = None
-        else:
-            df = self.opener(self.datafile)
+        df = None
 
         # do we have useful data cached?
         if self._cache and self._cache[1] >= base and self._cache[1] < rev:
             base = self._cache[1]
             text = str(self._cache[2])
             self._loadindex(base, rev + 1)
+            if not self._inline and rev > base + 1:
+                df = self.opener(self.datafile)
         else:
             self._loadindex(base, rev + 1)
+            if not self._inline and rev > base:
+                df = self.opener(self.datafile)
             text = self.chunk(base, df=df)
 
         bins = [self.chunk(r, df) for r in xrange(base + 1, rev + 1)]
--- a/tests/test-convert.out	Fri Jan 25 04:11:32 2008 -0500
+++ b/tests/test-convert.out	Wed Feb 20 13:38:16 2008 -0800
@@ -56,6 +56,17 @@
     subdirectory into the root of the repository, use '.' as the path to
     rename to.
 
+    The splicemap is a file that allows insertion of synthetic
+    history, letting you specify the parents of a revision.  This is
+    useful if you want to e.g. give a Subversion merge two parents, or
+    graft two disconnected series of history together.  Each entry
+    contains a key, followed by a space, followed by one or two
+    values, separated by spaces.  The key is the revision ID in the
+    source revision control system whose parents should be modified
+    (same format as a key in .hg/shamap).  The values are the revision
+    IDs (in either the source or destination revision control system)
+    that should be used as the new parents for that node.
+
     Back end options:
 
     --config convert.hg.clonebranches=False   (boolean)
@@ -81,6 +92,7 @@
     --filemap      remap file names using contents of file
  -r --rev          import up to target revision REV
  -s --source-type  source repository type
+    --splicemap    splice synthesized history into place
     --datesort     try to sort changesets by date
 
 use "hg -v help convert" to show global options