diff --git a/mercurial/context.py b/mercurial/context.py --- a/mercurial/context.py +++ b/mercurial/context.py @@ -36,6 +36,7 @@ match as matchmod, mdiff, obsolete as obsmod, + obsutil, patch, pathutil, phases, @@ -433,8 +434,21 @@ This is extracted in a function to help extensions (eg: evolve) to experiment with various message variants.""" if repo.filtername.startswith('visible'): - msg = _("hidden revision '%s'") % changeid + + # Check if the changeset is obsolete + unfilteredrepo = repo.unfiltered() + ctx = unfilteredrepo[changeid] + + # If the changeset is obsolete, enrich the hint with the reason that + # made this changeset not visible + if ctx.obsolete(): + reason = obsutil._getfilteredreason(unfilteredrepo, ctx) + msg = _("hidden revision '%s' %s") % (changeid, reason) + else: + msg = _("hidden revision '%s'") % changeid + hint = _('use --hidden to access hidden revisions') + return error.FilteredRepoLookupError(msg, hint=hint) msg = _("filtered revision '%s' (not in '%s' subset)") msg %= (changeid, repo.filtername) diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py --- a/mercurial/obsutil.py +++ b/mercurial/obsutil.py @@ -9,9 +9,11 @@ import re +from .i18n import _ from . import ( + node as nodemod, phases, - util + util, ) class marker(object): @@ -751,6 +753,32 @@ return values +def _getobsfate(successorssets): + """ Compute a changeset obsolescence fate based on its successorssets. + Successors can be the tipmost ones or the immediate ones. This function + return values are not meant to be shown directly to users, it is meant to + be used by internal functions only. + Returns one fate from the following values: + - pruned + - diverged + - superseed + - superseed_split + """ + + if len(successorssets) == 0: + # The commit has been pruned + return 'pruned' + elif len(successorssets) > 1: + return 'diverged' + else: + # No divergence, only one set of successors + successors = successorssets[0] + + if len(successors) == 1: + return 'superseed' + else: + return 'superseed_split' + def obsfateverb(successorset, markers): """ Return the verb summarizing the successorset and potentially using information from the markers @@ -836,3 +864,34 @@ line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date)) return "".join(line) + +def _getfilteredreason(unfilteredrepo, ctx): + """return a human-friendly string on why a obsolete changeset is hidden + """ + successors = successorssets(unfilteredrepo, ctx.node()) + fate = _getobsfate(successors) + + # Be more precise in case the revision is superseed + if fate == 'pruned': + reason = _('is pruned') + elif fate == 'diverged': + reason = _('has diverged') + elif fate == 'superseed': + reason = _("was rewritten as: %s") % nodemod.short(successors[0][0]) + elif fate == 'superseed_split': + + succs = [] + for node_id in successors[0]: + succs.append(nodemod.short(node_id)) + + if len(succs) <= 2: + reason = _("was split as: %s") % ", ".join(succs) + else: + firstsuccessors = ", ".join(succs[:2]) + remainingnumber = len(succs) - 2 + + args = (firstsuccessors, remainingnumber) + successorsmsg = _("%s and %d more") % args + reason = _("was split as: %s") % successorsmsg + + return reason diff --git a/tests/test-log.t b/tests/test-log.t --- a/tests/test-log.t +++ b/tests/test-log.t @@ -1817,7 +1817,7 @@ 1:a765632148dc55d38c35c4f247c618701886cb2f 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05 $ hg log -r a - abort: hidden revision 'a'! + abort: hidden revision 'a' is pruned! (use --hidden to access hidden revisions) [255] @@ -1874,7 +1874,7 @@ 2:94375ec45bddd2a824535fc04855bd058c926ec0 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e $ hg log -T'{rev}:{node}\n' -r:0 - abort: hidden revision '0'! + abort: hidden revision '0' is pruned! (use --hidden to access hidden revisions) [255] $ hg log -T'{rev}:{node}\n' -f diff --git a/tests/test-obshistory.t b/tests/test-obshistory.t new file mode 100644 --- /dev/null +++ b/tests/test-obshistory.t @@ -0,0 +1,541 @@ +This test file test the various messages when accessing obsolete +revisions. + +Global setup +============ + + $ . $TESTDIR/testlib/obsmarker-common.sh + $ cat >> $HGRCPATH < [ui] + > interactive = true + > [phases] + > publish=False + > [experimental] + > evolution.createmarkers = yes + > evolution.effect-flags = yes + > EOF + +Test output on amended commit +============================= + +Test setup +---------- + + $ hg init $TESTTMP/local-amend + $ cd $TESTTMP/local-amend + $ mkcommit ROOT + $ mkcommit A0 + $ echo 42 >> A0 + $ hg commit --amend -m "A1 + > + > Better commit message" + $ hg log --hidden -G + @ changeset: 2:4ae3a4151de9 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A1 + | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten using amend as 2:4ae3a4151de9 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + $ hg update 471f378eab4c + abort: hidden revision '471f378eab4c' was rewritten as: 4ae3a4151de9! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden "desc(A0)" + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with pruned commit +============================== + +Test setup +---------- + + $ hg init $TESTTMP/local-prune + $ cd $TESTTMP/local-prune + $ mkcommit ROOT + $ mkcommit A0 # 0 + $ mkcommit B0 # 1 + $ hg log --hidden -G + @ changeset: 2:0dec01379d3b + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B0 + | + o changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg debugobsolete --record-parents `getid 'desc(B0)'` + obsoleted 1 changesets + + $ hg log --hidden -G + @ changeset: 2:0dec01379d3b + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: pruned + | summary: B0 + | + o changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + +Actual test +----------- + $ hg up 1 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg up 0dec01379d3b + abort: hidden revision '0dec01379d3b' is pruned! + (use --hidden to access hidden revisions) + [255] + $ hg up --hidden -r 'desc(B0)' + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with splitted commit +================================ + +Test setup +---------- + + $ hg init $TESTTMP/local-split + $ cd $TESTTMP/local-split + $ mkcommit ROOT + $ echo 42 >> a + $ echo 43 >> b + $ hg commit -A -m "A0" + adding a + adding b + $ hg log --hidden -G + @ changeset: 1:471597cad322 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +# Simulate a split + $ hg up 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + + $ echo 42 >> a + $ hg commit -A -m "A0" + adding a + created new head + + $ echo 43 >> b + $ hg commit -A -m "A0" + adding b + + $ hg debugobsolete `getid '1'` `getid '2'` `getid '3'` + obsoleted 1 changesets + + $ hg log --hidden -G + @ changeset: 3:f257fde29c7a + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 2:337fec4d2edc + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + | x changeset: 1:471597cad322 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + $ hg update 471597cad322 + abort: hidden revision '471597cad322' was split as: 337fec4d2edc, f257fde29c7a! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'min(desc(A0))' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with lots of splitted commit +======================================== + +Test setup +---------- + + $ hg init $TESTTMP/local-lots-split + $ cd $TESTTMP/local-lots-split + $ mkcommit ROOT + $ echo 42 >> a + $ echo 43 >> b + $ echo 44 >> c + $ echo 45 >> d + $ hg commit -A -m "A0" + adding a + adding b + adding c + adding d + $ hg log --hidden -G + @ changeset: 1:de7290d8b885 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +# Simulate a split + $ hg up 0 + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + + $ echo 42 >> a + $ hg commit -A -m "A0" + adding a + created new head + + $ echo 43 >> b + $ hg commit -A -m "A0" + adding b + + $ echo 44 >> c + $ hg commit -A -m "A0" + adding c + + $ echo 45 >> d + $ hg commit -A -m "A0" + adding d + + $ hg debugobsolete `getid '1'` `getid '2'` `getid '3'` `getid '4'` `getid '5'` + obsoleted 1 changesets + + $ hg log --hidden -G + @ changeset: 5:c7f044602e9b + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 4:1ae8bc733a14 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 3:f257fde29c7a + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 2:337fec4d2edc + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + | x changeset: 1:de7290d8b885 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a, 4:1ae8bc733a14, 5:c7f044602e9b + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + $ hg update de7290d8b885 + abort: hidden revision 'de7290d8b885' was split as: 337fec4d2edc, f257fde29c7a and 2 more! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'min(desc(A0))' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with folded commit +============================== + +Test setup +---------- + + $ hg init $TESTTMP/local-fold + $ cd $TESTTMP/local-fold + $ mkcommit ROOT + $ mkcommit A0 + $ mkcommit B0 + $ hg log --hidden -G + @ changeset: 2:0dec01379d3b + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B0 + | + o changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +# Simulate a fold + $ hg up 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo "A0" > A0 + $ echo "B0" > B0 + $ hg add A0 B0 + $ hg commit -m "C0" + created new head + + $ hg debugobsolete `getid 'desc(A0)'` `getid 'desc(C0)'` + obsoleted 1 changesets + $ hg debugobsolete `getid 'desc(B0)'` `getid 'desc(C0)'` + obsoleted 1 changesets + + $ hg log --hidden -G + @ changeset: 3:eb5a0daa2192 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + | x changeset: 2:0dec01379d3b + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | obsolete: rewritten as 3:eb5a0daa2192 + | | summary: B0 + | | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten as 3:eb5a0daa2192 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + Actual test + ----------- + $ hg update 471f378eab4c + abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'desc(A0)' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg update 0dec01379d3b + abort: hidden revision '0dec01379d3b' was rewritten as: eb5a0daa2192! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'desc(B0)' + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with divergence +=========================== + +Test setup +---------- + + $ hg init $TESTTMP/local-divergence + $ cd $TESTTMP/local-divergence + $ mkcommit ROOT + $ mkcommit A0 + $ hg commit --amend -m "A1" + $ hg log --hidden -G + @ changeset: 2:fdf9bde5129a + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A1 + | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten using amend as 2:fdf9bde5129a + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg update --hidden 'desc(A0)' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg commit --amend -m "A2" + $ hg log --hidden -G + @ changeset: 3:65b757b745b9 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: A2 + | + | o changeset: 2:fdf9bde5129a + |/ parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | instability: content-divergent + | summary: A1 + | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten using amend as 2:fdf9bde5129a + | obsolete: rewritten using amend as 3:65b757b745b9 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + $ hg update 471f378eab4c + abort: hidden revision '471f378eab4c' has diverged! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'desc(A0)' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test output with amended + folded commit +======================================== + +Test setup +---------- + + $ hg init $TESTTMP/local-amend-fold + $ cd $TESTTMP/local-amend-fold + $ mkcommit ROOT + $ mkcommit A0 + $ mkcommit B0 + $ hg commit --amend -m "B1" + $ hg log --hidden -G + @ changeset: 3:b7ea6d14e664 + | tag: tip + | parent: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B1 + | + | x changeset: 2:0dec01379d3b + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten using amend as 3:b7ea6d14e664 + | summary: B0 + | + o changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + +# Simulate a fold + $ hg up 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo "A0" > A0 + $ echo "B0" > B0 + $ hg add A0 B0 + $ hg commit -m "C0" + created new head + + $ hg debugobsolete `getid 'desc(A0)'` `getid 'desc(C0)'` + obsoleted 1 changesets + $ hg debugobsolete `getid 'desc(B1)'` `getid 'desc(C0)'` + obsoleted 1 changesets + + $ hg log --hidden -G + @ changeset: 4:eb5a0daa2192 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + | x changeset: 3:b7ea6d14e664 + | | parent: 1:471f378eab4c + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | obsolete: rewritten as 4:eb5a0daa2192 + | | summary: B1 + | | + | | x changeset: 2:0dec01379d3b + | |/ user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | obsolete: rewritten using amend as 3:b7ea6d14e664 + | | summary: B0 + | | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: rewritten as 4:eb5a0daa2192 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + Actual test + ----------- + $ hg update 471f378eab4c + abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'desc(A0)' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg update --hidden 0dec01379d3b + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg update 0dec01379d3b + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg update --hidden 'desc(B0)' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t --- a/tests/test-obsolete.t +++ b/tests/test-obsolete.t @@ -196,7 +196,7 @@ abort: unknown revision '6'! [255] $ hg log -r 4 - abort: hidden revision '4'! + abort: hidden revision '4' was rewritten as: 5601fb93a350! (use --hidden to access hidden revisions) [255] $ hg debugrevspec 'rev(6)' @@ -1324,7 +1324,7 @@ 4:13bedc178fce (draft *obsolete*) [ bookb] add b [rewritten using amend as 5:a9b1f8652753] $ hg book -d bookb $ hg log -r 13bedc178fce - abort: hidden revision '13bedc178fce'! + abort: hidden revision '13bedc178fce' was rewritten as: a9b1f8652753! (use --hidden to access hidden revisions) [255]