diff --git a/hgext3rd/smartlog.py b/hgext3rd/smartlog.py --- a/hgext3rd/smartlog.py +++ b/hgext3rd/smartlog.py @@ -210,6 +210,12 @@ asnodes = list(modifysuccessors(ctx, 'histedit')) return templatekw.showlist('histeditsuccessor', asnodes, args) +@templatekeyword('undosuccessors') +def undosuccessors(repo, ctx, **args): + """Return all of the node's successors created as a result of undo""" + asnodes = list(modifysuccessors(ctx, 'undo')) + return templatekw.showlist('undosuccessor', asnodes, args) + def successormarkers(ctx): for data in ctx.repo().obsstore.successors.get(ctx.node(), ()): yield obsutil.marker(ctx.repo(), data) diff --git a/hgext3rd/undo.py b/hgext3rd/undo.py --- a/hgext3rd/undo.py +++ b/hgext3rd/undo.py @@ -17,6 +17,7 @@ hg, lock as lockmod, obsolete, + obsutil, registrar, revlog, revset, @@ -489,12 +490,11 @@ workingcopyparent = _readnode(repo, "workingparent.i", nodedict["workingparent"]) if not keep: - revealcommits(repo, workingcopyparent) + #revealcommits(repo, workingcopyparent) hg.updatetotally(ui, repo, workingcopyparent, workingcopyparent, clean=False, updatecheck='abort') else: # keeps working copy files - curctx = repo['.'] precnode = bin(workingcopyparent) precctx = repo[precnode] @@ -515,15 +515,13 @@ dirstate.add(filename) if data[1][0] is None: dirstate.remove(filename) - obsolete.createmarkers(repo, [(curctx, (precctx,))]) # visible changesets addedrevs = revsetlang.formatspec('olddraft(0) - olddraft(%d)', reverseindex) - hidecommits(repo, addedrevs) - removedrevs = revsetlang.formatspec('olddraft(%d) - olddraft(0)', reverseindex) + smarthide(repo, addedrevs, removedrevs) revealcommits(repo, removedrevs) def _computerelative(repo, reverseindex): @@ -540,12 +538,49 @@ return reverseindex # hide and reveal commits +def smarthide(repo, revhide, revshow): + '''hides changecontexts and reveals some commits -def hidecommits(repo, rev): - revr = scmutil.revrange(repo, [rev]) + tries to connect related hides and shows with obs marker + when reasonable and correct + ''' + revr = scmutil.revrange(repo, [revhide]) contexts = (repo[r] for r in revr) - for commit in contexts: - obsolete.createmarkers(repo, [[commit,[]]]) + revs = scmutil.revrange(repo, [revshow]) + shownodes = (repo[r] for r in revs) + for ctx in contexts: + unfi = repo.unfiltered() + related = [] + for i in obsutil.allprecursors(unfi.obsstore, [ctx.node()]): + related.append(i) + for i in obsutil.allsuccessors(unfi.obsstore, [ctx.node()]): + related.append(i) + destinations = [] + for x in shownodes: + if x.node() in related: + destinations.append(repo[x.node()]) + # two primary objectives: + # 1. correct divergence/nondivergence + # 2. correct visibility of changesets for the user + # secondary objectives: + # 3. usefull ui message in hg sl: "Undone to" + # Design choices: + # 1-to-1 correspondence is easy + # 1-to-many correspondence is hard: + # it's either divergent A to B, A to C + # or split A to B,C + # because of undo we don't know which + # without complex logic + # Solution: provide helpfull ui message for + # common and easy case (1 to 1), use simplest + # correct solution for complex edge case + if len(destinations) == 1: + hidecommits(repo, ctx, destinations) + else: + hidecommits(repo, ctx, []) + +def hidecommits(repo, curctx, precctxs): + obsolete.createmarkers(repo, [(curctx, precctxs)], operation='undo') def revealcommits(repo, rev): try: diff --git a/tests/test-smartlog.t b/tests/test-smartlog.t --- a/tests/test-smartlog.t +++ b/tests/test-smartlog.t @@ -506,3 +506,7 @@ successorssets Returns a string of sets of successors for a changectx + -- + undosuccessors + Return all of the node's successors created as a result of + undo diff --git a/tests/test-undo.t b/tests/test-undo.t --- a/tests/test-undo.t +++ b/tests/test-undo.t @@ -6,6 +6,8 @@ > _duringundologlock=1 > [experimental] > evolution=createmarkers + > [ui] + > interactive = true > EOF Build up a repo @@ -317,3 +319,87 @@ $ hg undo --keep $ hg st A kfl1 + $ hg commit --amend + +hg undo informative obsmarkers +check 1 to 1 undos have informative obsmarker +check 1 to many undos (generally a redo of split or divergence) do not connect +the changesets with obsmarkers as we do not differentiate between split and +divergence cases in undo. The original split/divergence obsmarkers suffice for +checking split/divergence. + $ cat >> $HGRCPATH < [extensions] + > smartlog = $TESTDIR/../hgext3rd/smartlog.py + > tweakdefaults = $TESTDIR/../hgext3rd/tweakdefaults.py + > fbamend = $TESTDIR/../hgext3rd/fbamend/ + > EOF + $ hg undo + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg sl --all --hidden -T "{if(undosuccessors, node)}\n{if(undosuccessors, label('sl.undo', '(Undone as {join(undosuccessors% \'{shortest(undosuccessor, 6)}\', ', ')})'))}" + x + | + | x + |/ + | x + |/ + | x + |/ + @ + : + : x c9476255bc2a68672c844021397838ff4eeefcda + :/ (Undone as 1dafc0) + : x + :/ + : o + :/ + : x + : | + : x + :/ + : o + :/ + o + | + ~ + $ echo "a" >> newa && echo "b" >> newb && hg add newa newb && hg ci -m "newfiles" + $ hg split --quiet << EOF + > y + > y + > n + > y + > EOF + diff --git a/newa b/newa + new file mode 100644 + examine changes to 'newa'? [Ynesfdaq?] y + + @@ -0,0 +1,1 @@ + +a + record change 1/2 to 'newa'? [Ynesfdaq?] y + + diff --git a/newb b/newb + new file mode 100644 + examine changes to 'newb'? [Ynesfdaq?] n + + Done splitting? [yN] y + $ hg debugobsolete | tail -5 + db3723da827c373768d500ab4e3a9c59a78314a6 0 {1dafc0b436123cab96f82a8e9e8d1d42c0301aaa} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + c9476255bc2a68672c844021397838ff4eeefcda 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa 0 (Thu Jan 01 00:00:04 1970 +0000) {'user': 'test'} + 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa c9476255bc2a68672c844021397838ff4eeefcda 0 (Thu Jan 01 00:00:05 1970 +0000) {'user': 'test'} + c9476255bc2a68672c844021397838ff4eeefcda 1dafc0b436123cab96f82a8e9e8d1d42c0301aaa 0 (Thu Jan 01 00:00:06 1970 +0000) {'operation': 'undo', 'user': 'test'} + f86734247df6db66a810e549cc938a72cd5c6d1a d0fdb9510dbf78c1a7e62c3e6628ff1f978f87ea 75f63379f12bf02d40fe7444587ad67be9ae81b8 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'split', 'user': 'test'} + $ hg undo + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg redo + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg debugobsolete | tail -5 + d0fdb9510dbf78c1a7e62c3e6628ff1f978f87ea f86734247df6db66a810e549cc938a72cd5c6d1a 0 (Thu Jan 01 00:00:01 1970 +0000) {'operation': 'undo', 'user': 'test'} + 75f63379f12bf02d40fe7444587ad67be9ae81b8 0 {d0fdb9510dbf78c1a7e62c3e6628ff1f978f87ea} (Thu Jan 01 00:00:01 1970 +0000) {'operation': 'undo', 'user': 'test'} + f86734247df6db66a810e549cc938a72cd5c6d1a 0 {1dafc0b436123cab96f82a8e9e8d1d42c0301aaa} (Thu Jan 01 00:00:02 1970 +0000) {'operation': 'undo', 'user': 'test'} + d0fdb9510dbf78c1a7e62c3e6628ff1f978f87ea d0fdb9510dbf78c1a7e62c3e6628ff1f978f87ea 0 (Thu Jan 01 00:00:01 1970 +0000) {'operation': 'revive', 'user': 'test'} + 75f63379f12bf02d40fe7444587ad67be9ae81b8 75f63379f12bf02d40fe7444587ad67be9ae81b8 0 (Thu Jan 01 00:00:01 1970 +0000) {'operation': 'revive', 'user': 'test'} + $ cat >> $HGRCPATH < [extensions] + > smartlog =! + > tweakdefaults =! + > fbamend =! + > EOF