Pierre-Yves David avatar Pierre-Yves David committed bd26eb9

obsolete: Detect conflicting changeset!

Comments (0)

Files changed (2)

hgext/obsolete.py

 
 context.changectx.latecomer = latecomer
 
+def conflicting(ctx):
+    """is the changeset conflicting (Try to succeed to public change)"""
+    if ctx.node() is None:
+        return False
+    return ctx.rev() in ctx._repo._conflictingset
+
+context.changectx.conflicting = conflicting
+
 
 ### revset
 #############################
     args = revset.getargs(x, 0, 0, 'latecomer takes no arguments')
     return [r for r in subset if r in repo._latecomerset]
 
+def revsetconflicting(repo, subset, x):
+    """conflicting, Try to succeed to public change"""
+    args = revset.getargs(x, 0, 0, 'conflicting takes no arguments')
+    return [r for r in subset if r in repo._conflictingset]
+
 def _precursors(repo, s):
     """Precursor of a changeset"""
     cs = set()
     revset.symbols["suspended"] = revsetsuspended
     revset.symbols["extinct"] = revsetextinct
     revset.symbols["latecomer"] = revsetlatecomer
+    revset.symbols["conflicting"] = revsetconflicting
     revset.symbols["obsparents"] = revsetprecursors  # DEPR
     revset.symbols["precursors"] = revsetprecursors
     revset.symbols["obsancestors"] = revsetallprecursors  # DEPR
         if ctx.latecomer():
             raise util.Abort(_("Trying to push latecomer changeset: %s!") % ctx,
                              hint=hint)
+        if ctx.conflicting():
+            raise util.Abort(_("Trying to push conflicting changeset: %s!") % ctx,
+                             hint=hint)
     ### patch remote branch map
     # do not read it this burn eyes
     try:
             query = 'allsuccessors(public()) - obsolete() - public()'
             return set(self.revs(query))
 
+        @util.propertycache
+        def _conflictingset(self):
+            """the set of rev trying to obsolete public revision"""
+            conflicting = set()
+            obsstore = self.obsstore
+            newermap = {}
+            for ctx in self.set('(not public()) - obsolete()'):
+                prec = obsstore.successors.get(ctx.node(), ())
+                toprocess = set(prec)
+                while toprocess:
+                    prec = toprocess.pop()[0]
+                    if prec not in newermap:
+                        newermap[prec] = newerversion(self, prec)
+                    newer = [n for n in newermap[prec] if n] # filter kill
+                    if len(newer) > 1:
+                        conflicting.add(ctx.rev())
+                        break
+                toprocess.update(obsstore.successors.get(prec, ()))
+            return conflicting
+
         def _clearobsoletecache(self):
             if '_obsoleteset' in vars(self):
                 del self._obsoleteset
                 del self._extinctset
             if '_latecomerset' in vars(self):
                 del self._latecomerset
+            if '_conflictingset' in vars(self):
+                del self._conflictingset
 
         def addobsolete(self, sub, obj):
             """Add a relation marking that node <sub> is a new version of <obj>"""

tests/test-obsolete.t

   9468a5f5d8b2 6db5e282cb91
   95de7fc6918d 909a0fb57e5d
   a7a6f2b5d8a5 95de7fc6918d
+
+Check conflict detection
+
+  $ hg up 9468a5f5d8b2 #  add obsol_d''
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit "obsolet_conflicting_d"
+  $ hg summary
+  parent: 14:50f11e5e3a63 tip
+   add obsolet_conflicting_d
+  branch: default
+  commit: (clean)
+  update: 9 new changesets, 9 branch heads (merge)
+  $ hg debugobsolete 50f11e5e3a63 a7a6f2b5d8a5
+  $ hg log -r 'conflicting()'
+  changeset:   14:50f11e5e3a63
+  tag:         tip
+  parent:      11:9468a5f5d8b2
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     add obsolet_conflicting_d
+  
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.