overlay: change content checking in non-contiguous mode (bug 1375966); r?smacleod draft
authorGregory Szorc <gps@mozilla.com>
Fri, 23 Jun 2017 12:52:20 -0700
changeset 11315 1d252f7ffcdb26bea34bf89bd54b6acd7ee7e557
parent 11314 fc236ee0a7652e90cd5187bd96a1dfc2a4afac78
push id1718
push userbmo:gps@mozilla.com
push dateFri, 23 Jun 2017 19:52:33 +0000
reviewerssmacleod
bugs1375966
overlay: change content checking in non-contiguous mode (bug 1375966); r?smacleod Before this change, non-contiguous mode compared content against the last overlayed changeset. Since we're skipping changesets in non-contiguous mode, this check would almost certainly fail. The (current) goal in non-contiguous mode is to support backouts. The skipped changeset will be a backout. The first parent of the first changeset to be overlayed should be the backout. So, for non-contiguous mode, we change the content check to be against the first parent. This isn't a complete fix. If the first parent isn't the backout, then the content check will fail. But this is presumed to be true most of the time for the current Servo backout system. Perfect is the enemy of good. MozReview-Commit-ID: 79AHD6SYztA
hgext/overlay/__init__.py
hgext/overlay/tests/test-overlay-filtered-dag.t
--- a/hgext/overlay/__init__.py
+++ b/hgext/overlay/__init__.py
@@ -230,31 +230,42 @@ def _dooverlay(sourcerepo, sourceurl, so
     # We don't (yet) support overlaying merge commits.
     for rev in sourcerevs:
         ctx = sourcerepo[rev]
         if len(ctx.parents()) > 1:
             raise error.Abort(_('do not support overlaying merges: %s') %
                               short(ctx.node()))
 
     # If we previously performed an overlay, verify that changeset
-    # continuity is uninterrupted. We ensure the parent of the first source
-    # changeset matches the last imported changeset and that the state of
-    # files in the last imported changeset matches exactly the state of files
-    # in the destination changeset. If these conditions don't hold, the repos
-    # got out of sync. If we continued, the first overlayed changeset would
-    # have a diff that didn't match the source repository. In other words,
-    # the history wouldn't be accurate. So prevent that from happening.
+    # continuity is uninterrupted.
+    #
+    # For the default mode of contiguous importing, we verify the last overlayed
+    # changeset is the first parent of the first changeset to be overlayed. We
+    # also verify that files in the destination match the last overlayed
+    # changeset.
+    #
+    # For non-contiguous operation, we skip the parent check because it doesn't
+    # make sense. For file comparisons, we check against the parent of the first
+    # incoming changeset rather than the last overlayed changeset.
+    #
+    # The file content check ensures that repos don't get out of sync. They
+    # ensure that diffs from the source repository match diffs in the
+    # destination repository.
     if lastsourcectx:
-        if (not noncontiguous and
-                sourcerepo[sourcerevs[0]].p1() != lastsourcectx):
-            raise error.Abort(_('parent of initial source changeset does not '
-                                'match last overlayed changeset (%s)') %
-                              short(lastsourcectx.node()))
+        if not noncontiguous:
+            if sourcerepo[sourcerevs[0]].p1() != lastsourcectx:
+                raise error.Abort(_('parent of initial source changeset does '
+                                    'not match last overlayed changeset (%s)') %
+                                  short(lastsourcectx.node()))
 
-        _verifymanifestsequal(sourcerepo, lastsourcectx, destrepo, destctx,
+            comparectx = lastsourcectx
+        else:
+            comparectx = sourcerepo[sourcerevs[0]].p1()
+
+        _verifymanifestsequal(sourcerepo, comparectx, destrepo, destctx,
                               prefix)
 
     # All the validation is done. Proceed with the data conversion.
     with destrepo.lock():
         with destrepo.transaction('overlay'):
             for i, rev in enumerate(sourcerevs):
                 ui.progress(_('revisions'), i + 1, total=len(sourcerevs))
                 sourcectx = sourcerepo[rev]
--- a/hgext/overlay/tests/test-overlay-filtered-dag.t
+++ b/hgext/overlay/tests/test-overlay-filtered-dag.t
@@ -48,8 +48,38 @@ A non-contiguous dag range will fail to 
 
 Passing --noncontiguous should allow a non-contiguous dag range where some of
 the commits have been filtered.
   $ hg overlay http://localhost:$HGPORT1 'not keyword("FILTERED")' --into prefix --noncontiguous
   af1e0a150cd4 -> 8e52bf8e668a: initial
   eb87a779cc67 -> 452dcbcc9fb9: head 1 commit 1
   38627e51950d -> ccc09fef5c59: head 1 commit 2
   eebf284459b0 -> ed781cf9ab85: head 1 commit 4
+
+Incremental conversion with --noncontiguous works
+
+  $ cd ../repo0
+  $ echo 5 > foo
+  $ hg commit -m 'head 1 commit 5 FILTERED'
+  $ echo 6 > foo
+  $ hg commit -m 'head 1 commit 6'
+
+  $ cd ../dest
+
+  $ hg -q up tip
+
+  $ echo 5 > prefix/foo
+  $ hg commit -m 'out of band change simulating commit 5'
+
+  $ hg overlay http://localhost:$HGPORT1 'not desc("FILTERED")' --into prefix
+  pulling http://localhost:$HGPORT1 into $TESTTMP/dest/.hg/localhost~3a20123
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 1 files
+  abort: source revisions must be part of contiguous DAG range
+  [255]
+
+  $ hg overlay http://localhost:$HGPORT1 'not desc("FILTERED")' --into prefix --noncontiguous
+  eebf284459b0 already processed as ed781cf9ab85; skipping 4/5 revisions
+  8c4d7f24662e -> ee4ce23b43ca: head 1 commit 6
+