# HG changeset patch # User Pierre-Yves David # Date 1342003085 -7200 # Node ID bd26eb9714fbc13fe90e59ec115225a035b56cb8 # Parent de3edd3856c36f44bc24dab8aff2693d0214a61c obsolete: Detect conflicting changeset! diff -r de3edd3856c3 -r bd26eb9714fb hgext/obsolete.py --- a/hgext/obsolete.py Tue Jul 10 16:14:03 2012 +0200 +++ b/hgext/obsolete.py Wed Jul 11 12:38:05 2012 +0200 @@ -152,6 +152,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 ############################# @@ -193,6 +201,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() @@ -391,6 +404,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 @@ -483,6 +497,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: @@ -1031,6 +1048,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 @@ -1049,6 +1086,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 is a new version of """ diff -r de3edd3856c3 -r bd26eb9714fb tests/test-obsolete.t --- a/tests/test-obsolete.t Tue Jul 10 16:14:03 2012 +0200 +++ b/tests/test-obsolete.t Wed Jul 11 12:38:05 2012 +0200 @@ -578,3 +578,24 @@ 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 +