Commits

Peter Arrenbrecht committed 79a77e2

auto-detect the set of managed revs, implement evolve along parent chain

Comments (0)

Files changed (2)

hgext/evolution.py

 '''
 
 from mercurial import commands, context, bookmarks, error, revset
-from mercurial import scmutil, cmdutil, extensions, util, hg
+from mercurial import scmutil, cmdutil, extensions, util, hg, dagutil
 from mercurial.commands import command, walkopts, commitopts, commitopts2, logopts
 from mercurial.i18n import _
-from mercurial.node import nullid, hex, bin
+from mercurial.node import nullid, nullrev, hex, bin
 import os
 import errno
 
         self.repo = repo
         self._supercedes = {}
         self._replacedby = {}
+        self._managedrevs = set()
         self._readmeta()
         self._bookmarktargets = dict((id, name) for name, id
                                      in repo._bookmarks.iteritems())
 
     def _readmeta(self):
+        managedrevs = set()
         cl = self.repo.changelog
         try:
             srcrev = None
                     try:
                         srcrev = cl.rev(bin(stripped))
                         tgts = self._supercedes.setdefault(srcrev, [])
+                        managedrevs.add(srcrev)
                     except error.RepoLookupError:
                         tgts = None
                 elif tgts is not None:
                         # TODO what if someone updates back to a replaced node and amends again?
                         if type == REPLACES:
                             self._replacedby[tgtrev] = srcrev
+                        managedrevs.add(tgtrev)
                     except error.RepoLookupError:
                         pass
+            self._updaterevs(managedrevs)
         except IOError, inst:
             if inst.errno != errno.ENOENT:
                 raise
 
+    def _updaterevs(self, newrevs):
+        dag = dagutil.revlogdag(self.repo.changelog)
+        self._managedrevs = dag.descendantset(self._managedrevs.union(set(newrevs)))
+
     def writemeta(self):
         cl = self.repo.changelog
         wlock = self.repo.wlock()
         self._supercedes.setdefault(srcrev, []).append((type, tgtrev,))
         if type == REPLACES:
             self._replacedby[tgtrev] = srcrev
+        # TODO might want to defer this until writemeta for speed
+        self._updaterevs([srcrev, tgtrev])
 
     def supercedes(self, srcrev):
         return self._supercedes.get(srcrev)
         if not printfn:
             def printfn(s):
                 pass
-        replrev = self.replacedby(cset.rev())
-        if replrev:
-            printfn(_('rev %s has been replaced by rev %s\n')
-                    % (cset.rev(), replrev))
-            return False
+        while cset.rev() in self._managedrevs:
+            replrev = self.replacedby(cset.rev())
+            if replrev:
+                printfn(_('rev %s has been replaced by rev %s\n')
+                        % (cset.rev(), replrev))
+                return False
 
-        sup = self.supercedes(cset.rev())
-        if sup:
-            for type, tgtrev in sup:
-                if type == UPDATES:
-                    replrev = self.replacedby(tgtrev) or '?'
-                    printfn(_('rev %s is an update of rev %s, which was replaced by rev %s\n')
-                            % (cset.rev(), tgtrev, replrev))
-                    return False
+            sup = self.supercedes(cset.rev())
+            if sup:
+                for type, tgtrev in sup:
+                    if type == UPDATES:
+                        replrev = self.replacedby(tgtrev) or '?'
+                        printfn(_('rev %s is an update of rev %s, which was replaced by rev %s\n')
+                                % (cset.rev(), tgtrev, replrev))
+                        return False
 
-        replrev = self.replacedby(cset.p1().rev())
-        if replrev:
-            printfn(_('rev %s needs rebase on rev %s, which replaces rev %s\n')
-                    % (cset.rev(), replrev, cset.p1().rev()))
-            return True
+            replrev = self.replacedby(cset.p1().rev())
+            if replrev:
+                printfn(_('rev %s needs rebase on rev %s, which replaces rev %s\n')
+                        % (cset.rev(), replrev, cset.p1().rev()))
+                return True
+
+            cset = cset.p1()
 
         return False
 
 
     def evolveupto(self, old, commitopts):
         # scan back to earliest parent possibly needing evolve
-        csets = [old]
-        while True:
+        repo = self.repo
+        res = old.node()
+        csets = []
+        while old.rev() in self._managedrevs:
+            # TODO this probably wants to evolve the entire graph below
+            newestrev = self.replacedby(old.rev(), transitive=True)
+            csets.append(newestrev and repo[newestrev] or old)
             old = old.p1()
-            if not self.checkstatus(old):
-                break
-            csets.append(old)
         # evolve them, parents first
         for old in reversed(csets):
             res = self.evolveontonewest(old, commitopts)

tut/src/simple.rextile

 	$ hg clone . ../evolve-in-one-go
 	updating to branch default
 	3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+	$ cp .hg/hiddenrevs .hg/evolution ../evolve-in-one-go/.hg/
 
 h5. hg update
 
 
 	$ hg update patchC
 	4 files updated, 0 files merged, 0 files removed, 0 files unresolved
+	WARNING: rev 4 needs rebase on rev 7, which replaces rev 1
+	use 'hg evolve'
 
 	$ hg evolve
 	rebasing rev 4 onto 7
-	0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+	updating to rev 4
+	1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+	merging with rev 6
 	1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 	(branch merge, don't forget to commit)
+	committing new version
 	rebasing rev 5 onto 9
+	updating to rev 5
 	3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+	merging with rev 8
 	1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 	(branch merge, don't forget to commit)
+	committing new version
 	1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Again, the details:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.