[PATCH 9 of 9] convert/gnuarch: follow continuation-of revisions

Edouard Gomez ed.gomez at free.fr
Sat Jan 3 19:37:18 CST 2009


# HG changeset patch
# User Edouard Gomez <ed.gomez at free.fr>
# Date 1231033008 -3600
# Node ID fbcfe50615014d960374450e92cd30128815b795
# Parent  3489a79dc5267e8b6f0e65d82e4054ff38609327
convert/gnuarch: follow continuation-of revisions

Built on top of previous patches:
 - continuation-of parsing
 - registered archives retrieval
 - use of fully qualified revisions

This allows the converter scanning for more source revisions
following the tree versions 'leaked' through the continuation-of
informations. Coupled with the registered archives retrieval, this
makes possible to decide to follow such a hint or stop scanning for
more revisions.

This also implies some changes in the retrieval of some base-0
revisions when they're continuation-of other revisions, in that
case a 'replay' will work where a simple 'get' fails because the
dir exists already. I found the code dealing with 'replay' quite
good as it has already a fallback to 'get' in the error path.

diff --git a/hgext/convert/gnuarch.py b/hgext/convert/gnuarch.py
--- a/hgext/convert/gnuarch.py
+++ b/hgext/convert/gnuarch.py
@@ -63,32 +63,59 @@
             output = self.run0('tree-version', '-d', self.path)
         self.treeversion = output.strip()
 
-        self.ui.status(_('analyzing tree version %s...\n') % self.treeversion)
-
         # Get name of temporary directory
         version = self.treeversion.split('/')
         self.tmppath = os.path.join(tempfile.gettempdir(),
                                     'hg-%s' % version[1])
 
         # Generate parents dictionary
-        child = []
-        output, status = self.runlines('revisions', '-f', self.treeversion)
-        self.checkexit(status, 'archive registered?')
-        for l in output:
-            rev = l.strip()
-            self.changes[rev] = self.gnuarch_rev(rev)
+        self.parents[None] = []
+        treeversion = self.treeversion
+        child = None
+        while treeversion:
+            self.ui.status(_('analyzing tree version %s...\n') % treeversion)
 
-            # Read author, date and summary
-            catlog, status = self.run('cat-log', '-d', self.path, rev)
-            if status:
-                catlog = self.run0('cat-archive-log', rev)
-            self._parsecatlog(catlog, rev)
+            archive = treeversion.split('/')[0]
+            if archive not in self.archives:
+                self.ui.status(_('tree analysis stopped because it points to an unregistered archive %s...\n') % archive)
+                break
 
-            self.parents[rev] = child
-            child = [rev]
-            if rev == self.rev:
-                break
-        self.parents[None] = child
+            # Get the complete list of revisions for that tree version
+            output, status = self.runlines('revisions', '-r', '-f', treeversion)
+            self.checkexit(status, 'failed retrieveing revisions for %s' % treeversion)
+
+            # No new iteration unless a revision has a continuation-of header
+            treeversion = None
+
+            for l in output:
+                rev = l.strip()
+                self.changes[rev] = self.gnuarch_rev(rev)
+                self.parents[rev] = []
+
+                # Read author, date and summary
+                catlog, status = self.run('cat-log', '-d', self.path, rev)
+                if status:
+                    catlog  = self.run0('cat-archive-log', rev)
+                self._parsecatlog(catlog, rev)
+
+                # Populate the parents map
+                self.parents[child].append(rev)
+
+                # Keep track of the current revision as the child of the next
+                # revision scanned
+                child = rev
+
+                # Check if we have to follow the usual incremental history
+                # or if we have to 'jump' to a different treeversion given
+                # by the continuation-of header.
+                if self.changes[rev].continuationof:
+                    treeversion = '--'.join(self.changes[rev].continuationof.split('--')[:-1])
+                    break
+
+                # If we reached a base-0 revision w/o any continuation-of
+                # header, it means the tree history ends here.
+                if rev[-6:] == 'base-0':
+                    break
 
     def after(self):
         self.ui.debug(_('cleaning up %s\n') % self.tmppath)
@@ -162,23 +189,19 @@
         return os.system(cmdline)
 
     def _update(self, rev):
-        if rev[-6:] == 'base-0':
-            # Initialise 'base-0' revision
+        self.ui.debug(_('applying revision %s...\n') % rev)
+        changeset, status = self.runlines('replay', '-d', self.tmppath,
+                                              rev)
+        if status:
+            # Something went wrong while merging (baz or tla
+            # issue?), get latest revision and try from there
+            shutil.rmtree(self.tmppath, ignore_errors=True)
             self._obtainrevision(rev)
         else:
-            self.ui.debug(_('applying revision %s...\n') % rev)
-            changeset, status = self.runlines('replay', '-d', self.tmppath,
-                                              rev)
-            if status:
-                # Something went wrong while merging (baz or tla
-                # issue?), get latest revision and try from there
-                shutil.rmtree(self.tmppath, ignore_errors=True)
-                self._obtainrevision(rev)
-            else:
-                old_rev = self.parents[rev][0]
-                self.ui.debug(_('computing changeset between %s and %s...\n')
-                              % (old_rev, rev))
-                self._parsechangeset(changeset, rev)
+            old_rev = self.parents[rev][0]
+            self.ui.debug(_('computing changeset between %s and %s...\n')
+                          % (old_rev, rev))
+            self._parsechangeset(changeset, rev)
 
     def _getfile(self, name, rev):
         mode = os.lstat(os.path.join(self.tmppath, name)).st_mode


More information about the Mercurial-devel mailing list