[PATCH 5 of 8] convert: track files and copies for revisions that were filtered out

Yury Sulsky yury.sulsky at gmail.com
Mon Nov 28 00:26:01 CST 2011


# HG changeset patch
# User Yury Sulsky <yury.sulsky at gmail.com>
# Date 1322459840 18000
# Node ID 2325d1fa02ac96bc8d4a31eab98ee736edc0f501
# Parent  ca6bd3a18621286746cc7a83f23f871d49c8ed62
convert: track files and copies for revisions that were filtered out

diff -r ca6bd3a18621 -r 2325d1fa02ac hgext/convert/filtermap.py
--- a/hgext/convert/filtermap.py	Mon Nov 28 00:51:10 2011 -0500
+++ b/hgext/convert/filtermap.py	Mon Nov 28 00:57:20 2011 -0500
@@ -23,7 +23,7 @@
         """Return True if we want to keep this revision"""
         return True
 
-    def __init__(self, ui, baseconverter):
+    def __init__(self, ui, baseconverter, trackchanges):
         super(filtermap_base, self).__init__(ui)
         self.base = baseconverter
         self.commits = {}
@@ -38,6 +38,8 @@
         self.origparents = {}
         self.children = {}
         self.seenchildren = {}
+        self.skippedchanges = {}
+        self.trackingchanges = trackchanges
 
     def before(self):
         self.base.before()
@@ -51,7 +53,7 @@
         # To avoid calling getcommit for every revision that has already
         # been converted, we rebuild only the parentmap, delaying the
         # rebuild of wantedancestors until we need it (i.e. until a
-        # merge).
+        # merge or if we are tracking changes).
         #
         # We assume the order argument lists the revisions in
         # topological order, so that we can infer which revisions were
@@ -83,6 +85,7 @@
         self.parentmap.clear()
         self.wantedancestors.clear()
         self.seenchildren.clear()
+        self.skippedchanges.clear()
         for rev, wanted, arg in self.convertedorder:
             if rev not in self.origparents:
                 self.origparents[rev] = self.getcommit(rev).parents
@@ -124,12 +127,40 @@
                 del self.wantedancestors[r]
                 del self.parentmap[r]
                 del self.seenchildren[r]
+                if self.trackingchanges:
+                    del self.skippedchanges[r]
                 if self._rebuilt:
                     del self.children[r]
 
+    def _trackedchanges(self, rev, parents):
+        changes = self.base.getchanges(rev)
+        if not self.trackingchanges or not parents:
+            return changes
+
+        files, copies = set(), {}
+        # The case of a convergent copy takes care of itself because
+        # the destination file should be present in the merge node's
+        # list of changed files
+        for p in parents:
+            pf, pc = self.skippedchanges[p]
+            copies.update(pc)
+            files.update([(f, rev) for (f, prev) in pf])
+
+        cf, cc = changes
+        copies.update(cc); files.update(cf)
+
+        for dest in copies:
+            if dest in files:
+                del copies[dest]
+
+        return files, copies
+
     def mark_not_wanted(self, rev, p):
         # Mark rev as not interesting and update data structures.
 
+        if self.trackingchanges:
+            self.skippedchanges[rev] = self._trackedchanges(rev, p and [p])
+
         if p is None:
             # A root revision. Use SKIPREV to indicate that it doesn't
             # map to any revision in the restricted graph.  Put SKIPREV
@@ -145,6 +176,9 @@
     def mark_wanted(self, rev, parents):
         # Mark rev ss wanted and update data structures.
 
+        if self.trackingchanges:
+            self.skippedchanges[rev] = [], {}
+
         # rev will be in the restricted graph, so children of rev in
         # the original graph should still have rev as a parent in the
         # restricted graph.
@@ -160,7 +194,7 @@
 
     def getchanges(self, rev):
         parents = self.commits[rev].parents
-        if len(parents) > 1:
+        if len(parents) > 1 or self.trackingchanges:
             self.rebuild()
 
         # To decide whether we're interested in rev we:
@@ -223,7 +257,7 @@
         self.mark_wanted(rev, parents)
         self.convertedorder.append((rev, True, None))
 
-        files, copies = self.base.getchanges(rev)
+        files, copies = self._trackedchanges(rev, parents)
 
         # Flatten copies if this is a root node
         if copies and not mparents:
@@ -266,7 +300,11 @@
 
 class filtermap_source(filtermap_base):
     def __init__(self, ui, base, filemap):
-        super(filtermap_source, self).__init__(ui, base)
+        # If we only filter by files, there's no need to track
+        # changes. Revisions are only removed if they don't touch
+        # files that we care about.
+        trackchanges = False
+        super(filtermap_source, self).__init__(ui, base, trackchanges)
         self.filemapper = filemapper(ui, filemap)
 
     def wanted(self, rev, i):


More information about the Mercurial-devel mailing list