hgext/obsolete.py
changeset 359 43f79983f638
parent 353 8feb73f733cb
parent 356 56d4c6207ef9
child 360 6390ab3aea93
--- a/hgext/obsolete.py	Tue Jul 10 16:14:29 2012 +0200
+++ b/hgext/obsolete.py	Wed Jul 11 15:20:22 2012 +0200
@@ -151,6 +151,14 @@
 
 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
 #############################
@@ -192,6 +200,11 @@
     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()
@@ -390,6 +403,7 @@
     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
@@ -399,9 +413,13 @@
 
     templatekw.keywords['obsolete'] = obsoletekw
 
+    # warning about more obsolete
+    for cmd in ['commit', 'push', 'pull', 'graft', 'phase', 'unbundle']:
+        entry = extensions.wrapcommand(commands.table, cmd, warnobserrors)
     try:
         rebase = extensions.find('rebase')
         if rebase:
+            entry = extensions.wrapcommand(rebase.cmdtable, 'rebase', warnobserrors)
             extensions.wrapfunction(rebase, 'buildstate', buildstate)
             extensions.wrapfunction(rebase, 'defineparents', defineparents)
             extensions.wrapfunction(rebase, 'concludenode', concludenode)
@@ -454,6 +472,9 @@
         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:
@@ -640,6 +661,28 @@
         lock.release()
     return res
 
+def warnobserrors(orig, ui, repo, *args, **kwargs):
+    """display warning is the command resulted in more instable changeset"""
+    priorunstables = len(repo.revs('unstable()'))
+    priorlatecomers = len(repo.revs('latecomer()'))
+    priorconflictings = len(repo.revs('conflicting()'))
+    #print orig, priorunstables
+    #print len(repo.revs('secret() - obsolete()'))
+    try:
+        return orig(ui, repo, *args, **kwargs)
+    finally:
+        newunstables = len(repo.revs('unstable()')) - priorunstables
+        newlatecomers = len(repo.revs('latecomer()')) - priorlatecomers
+        newconflictings = len(repo.revs('conflicting()')) - priorconflictings
+        #print orig, newunstables
+        #print len(repo.revs('secret() - obsolete()'))
+        if newunstables > 0:
+            ui.warn(_('%i new unstables changesets\n') % newunstables)
+        if newlatecomers > 0:
+            ui.warn(_('%i new latecomers changesets\n') % newlatecomers)
+        if newconflictings > 0:
+            ui.warn(_('%i new conflictings changesets\n') % newconflictings)
+
 def noextinctsvisibleheads(orig, repo):
     repo._turn_extinct_secret()
     return orig(repo)
@@ -806,6 +849,26 @@
             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
@@ -824,6 +887,8 @@
                 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>"""