Commits

Anonymous committed ce5ea6f Merge

merge with doc fix

Comments (0)

Files changed (6)

 d3f20770b86a31dba56ae7b252089e12b34702da 0.2.0
 c046b083a5e0b21af69027f31cee141800cf894b 0.3.0
 9bbcd274689829d9239978236e16610688978233 0.4.0
+4ecbaec1d664b1e6f8ebc78292e1ced77a8e69c0 0.4.1
     return map(repo.changelog.node,
                scmutil.revrange(repo, revsets))
 
-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()'))
-    #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
-        #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)
-
 ### changeset rewriting logic
 #############################
 
         rebase = None
         raise error.Abort(_('evolution extension require rebase extension.'))
 
+    for cmd in ['amend', 'kill', 'uncommit']:
+        entry = extensions.wrapcommand(cmdtable, cmd,
+                                       obsolete.warnobserrors)
+
     entry = extensions.wrapcommand(commands.table, 'commit', commitwrapper)
     entry[1].append(('o', 'obsolete', [],
                      _("make commit obsolete this revision")))
     entry[1].append(('O', 'old-obsolete', False,
                      _("make graft obsoletes its source")))
 
-    # warning about more obsolete
-    for cmd in ['commit', 'push', 'pull', 'graft', 'phase', 'unbundle']:
-        entry = extensions.wrapcommand(commands.table, cmd, warnobserrors)
-    for cmd in ['amend', 'kill', 'uncommit']:
-        entry = extensions.wrapcommand(cmdtable, cmd, warnobserrors)
-
-    if rebase is not None:
-        entry = extensions.wrapcommand(rebase.cmdtable, 'rebase', warnobserrors)

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
 
     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)
         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:
                 del oldmark['id']  # dropped for now
                 del oldmark['reason']  # unused until then
                 oldobject = str(oldmark.pop('object'))
-                oldsubjects = [str(s) for s in oldmark.pop('subjects')]
+                oldsubjects = [str(s) for s in oldmark.pop('subjects', [])]
                 LOOKUP_ERRORS = (error.RepoLookupError, error.LookupError)
                 if len(oldobject) != 40:
                     try:
                 meta = dict((k.encode('utf-8'), v.encode('utf-8'))
                              for k, v in oldmark.iteritems())
                 try:
-                    store.create(bin(oldobject), [bin(n) for n in oldsubjects],
+                    succs = [bin(n) for n in oldsubjects]
+                    succs = [n for n in succs if n != nullid]
+                    store.create(bin(oldobject), succs,
                                  0, meta)
                     cnt += 1
                 except ValueError:
         ui.warn(_('Working directory parent is obsolete\n'))
     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)
     while toproceed:
         current = toproceed.pop()
         assert len(current) <= 1, 'splitting not handled yet. %r' % current
+        current = [n for n in current if n != nullid]
         if current:
             n, = current
             if n in objectrels:
             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

   $ hg up 3 -q
   Working directory parent is obsolete
   $ mkcommit d # 5 (on 3)
+  1 new unstables changesets
   $ qlog -r 'obsolete()'
   3
   - 0d3f46688ccc
   Working directory parent is obsolete
   $ mkcommit obsol_d # 6
   created new head
+  1 new unstables changesets
   $ hg debugobsolete 6 5
   $ qlog
   6
   Working directory parent is obsolete
   $ mkcommit "obsol_d'" # 7
   created new head
+  1 new unstables changesets
   $ hg debugobsolete 7 6
   $ hg pull -R ../other-new .
   pulling from .
   Working directory parent is obsolete
   $ mkcommit "obsol_d''"
   created new head
+  1 new unstables changesets
   $ hg debugobsolete 8 7
   $ cd ../other-new
   $ hg up -q 3
 
   $ cd local
   $ hg phase --public 11
+  1 new latecomers changesets
   $ hg --config extensions.graphlog=glog glog --template='{rev} - ({phase}) {node|short} {desc}\n'
   @  12 - (draft) 6db5e282cb91 add obsol_d'''
   |
   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
+  

tests/test-oldconvert.t

   >     }, 
   >     {
   >         "reason": "import from older format.", 
-  >         "subjects": [
-  >             "a37154106de358121a32a3dd6ba0281931550515"
-  >         ], 
   >         "user": "Pierre-Yves David <pierre-yves.david@logilab.fr>", 
   >         "date": [
   >             1336557472.7875929, 
   >     {
   >         "reason": "import from older format.", 
   >         "subjects": [
-  >             "dc8d8aa6e8ac490fcafd074d570df0787ee0ee69"
+  >             "0000000000000000000000000000000000000000"
   >         ], 
   >         "user": "Pierre-Yves David <pierre-yves.david@logilab.fr>", 
   >         "date": [
   $ hg debugconvertobsolete --traceback
   3 obsolete marker converted
   $ hg debugsuccessors
-  2c3784e102bb dc8d8aa6e8ac
+  2c3784e102bb
   3e03d82708d4 3218406b50ed
-  5c722672795c a37154106de3
+  5c722672795c
   7c3bad9141dc d67cd0334eee

tests/test-uncommit.t

   Working directory parent is obsolete
   $ hg --config extensions.purge= purge
   $ hg uncommit -I 'set:added() and e'
+  2 new conflictings changesets
   $ hg st --copies
   A e
   $ hg st --copies --change .
   Working directory parent is obsolete
   $ hg --config extensions.purge= purge
   $ hg uncommit --all -X e
+  1 new conflictings changesets
   $ hg st --copies
   M b
   M d