Patchwork [05,of,11,V2] templatekw: introduce obsfate keyword

login
register
mail settings
Submitter Boris Feld
Date Oct. 11, 2017, 12:09 p.m.
Message ID <34bb2af8638432dea305.1507723791@FB>
Download mbox | patch
Permalink /patch/24726/
State Accepted
Headers show

Comments

Boris Feld - Oct. 11, 2017, 12:09 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1507218176 -7200
#      Thu Oct 05 17:42:56 2017 +0200
# Node ID 34bb2af8638432dea3052eabd4b6eb12a1777e19
# Parent  8447ccc2c5c91520ca75e6bbdc57100af8d0e931
# EXP-Topic obsfatekeyword
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 34bb2af86384
templatekw: introduce obsfate keyword

Introduce an obsfate printer that uses all helpers functions defined in
obsutil to get all the obsfate-related data and format a string according to
the current format in test-obsmarker-template.t.

Then, introduce an obsfate templatekw that uses the obsfateprinter to return a
list of strings.

The goal is not to replace existing obsfate template functions but to propose
a default, good-enough and easily usable obsfate definition for end-users that
don't want to customize it. Such output would ultimately get included in the
default log output.

Here are some output examples for a commit amended:

rewritten using amend as 5:a9b1f8652753 by test (at 1970-01-01 00:00 +0000)

Next patches will make the output dependent on the verbosity.

Exemple of use-cases:

For having the obsfate on a single-line between brackets:

  {if(obsfate, " [{join(obsfate, "; ")}]")}

For having the obsfate in several lines:

  {if(obsfate, "{obsfate % "  Obsfate: {fate}\n"}")}
Yuya Nishihara - Oct. 11, 2017, 1:24 p.m.
On Wed, 11 Oct 2017 14:09:51 +0200, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld@octobus.net>
> # Date 1507218176 -7200
> #      Thu Oct 05 17:42:56 2017 +0200
> # Node ID 34bb2af8638432dea3052eabd4b6eb12a1777e19
> # Parent  8447ccc2c5c91520ca75e6bbdc57100af8d0e931
> # EXP-Topic obsfatekeyword
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 34bb2af86384
> templatekw: introduce obsfate keyword

> +def obsfateprinter(successors, markers, ui):
> +    """ Build a obsfate string for a single successorset using all obsfate
> +    related function defined in obsutil
> +    """
> +    line = []
> +
> +    # Verb
> +    line.append(successorsetverb(successors))
> +
> +    # Operations
> +    operations = markersoperations(markers)
> +    if operations:
> +        line.append(" using %s" % ", ".join(operations))
> +
> +    # Successors
> +    if successors:
> +        fmtsuccessors = [successors.joinfmt(succ) for succ in successors]
> +        line.append(" as %s" % ", ".join(fmtsuccessors))
> +
> +    # Users
> +    users = markersusers(markers)
> +
> +    if users:
> +        line.append(" by %s" % ", ".join(users))
> +
> +    # Date
> +    dates = markersdates(markers)
> +
> +    min_date = min(dates)
> +    max_date = max(dates)
> +
> +    if min_date == max_date:
> +        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
> +        line.append(" (at %s)" % fmtmin_date)
> +    else:
> +        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
> +        fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2')
> +        line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date))
> +
> +    return "".join(line)
> diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
> --- a/mercurial/templatekw.py
> +++ b/mercurial/templatekw.py
> @@ -580,6 +580,19 @@
>      # rev and node are completely different from changeset's.
>      return _mappable(f, f, lambda: {'rev': mrev, 'node': mhex})
>  
> +@templatekeyword('obsfate')
> +def showobsfate(**args):
> +    succsandmarkers = showsuccsandmarkers(**args)

Ugh, there's templatekw.defaulttempl which provides the default template
fragments to all stock/user templates. Maybe we can (ab)use it to define
the default '{obsfate}' template.

I'm so sorry I didn't mention it before. It totally slipped my mind.
Boris Feld - Oct. 12, 2017, 1:29 p.m.
On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> On Wed, 11 Oct 2017 14:09:51 +0200, Boris Feld wrote:
> > # HG changeset patch
> > # User Boris Feld <boris.feld@octobus.net>
> > # Date 1507218176 -7200
> > #      Thu Oct 05 17:42:56 2017 +0200
> > # Node ID 34bb2af8638432dea3052eabd4b6eb12a1777e19
> > # Parent  8447ccc2c5c91520ca75e6bbdc57100af8d0e931
> > # EXP-Topic obsfatekeyword
> > # Available At https://bitbucket.org/octobus/mercurial-devel/
> > #              hg pull https://bitbucket.org/octobus/mercurial-deve
> > l/ -r 34bb2af86384
> > templatekw: introduce obsfate keyword
> > +def obsfateprinter(successors, markers, ui):
> > +    """ Build a obsfate string for a single successorset using all
> > obsfate
> > +    related function defined in obsutil
> > +    """
> > +    line = []
> > +
> > +    # Verb
> > +    line.append(successorsetverb(successors))
> > +
> > +    # Operations
> > +    operations = markersoperations(markers)
> > +    if operations:
> > +        line.append(" using %s" % ", ".join(operations))
> > +
> > +    # Successors
> > +    if successors:
> > +        fmtsuccessors = [successors.joinfmt(succ) for succ in
> > successors]
> > +        line.append(" as %s" % ", ".join(fmtsuccessors))
> > +
> > +    # Users
> > +    users = markersusers(markers)
> > +
> > +    if users:
> > +        line.append(" by %s" % ", ".join(users))
> > +
> > +    # Date
> > +    dates = markersdates(markers)
> > +
> > +    min_date = min(dates)
> > +    max_date = max(dates)
> > +
> > +    if min_date == max_date:
> > +        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M
> > %1%2')
> > +        line.append(" (at %s)" % fmtmin_date)
> > +    else:
> > +        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M
> > %1%2')
> > +        fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M
> > %1%2')
> > +        line.append(" (between %s and %s)" % (fmtmin_date,
> > fmtmax_date))
> > +
> > +    return "".join(line)
> > diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
> > --- a/mercurial/templatekw.py
> > +++ b/mercurial/templatekw.py
> > @@ -580,6 +580,19 @@
> >      # rev and node are completely different from changeset's.
> >      return _mappable(f, f, lambda: {'rev': mrev, 'node': mhex})
> >  
> > +@templatekeyword('obsfate')
> > +def showobsfate(**args):
> > +    succsandmarkers = showsuccsandmarkers(**args)
> 
> Ugh, there's templatekw.defaulttempl which provides the default
> template
> fragments to all stock/user templates. Maybe we can (ab)use it to
> define
> the default '{obsfate}' template.
> 
> I'm so sorry I didn't mention it before. It totally slipped my mind.

I saw templatekw.defaulttempl when working in this series but it felt
like a big hack.

I tried to limit the number of places where obsfate is defined, this
series already adds two obsfate definitions/implementations, the
changeset_printer and lobsfate in the default mapfile. I thought adding
a third one in defaulttempl would complicate the potential update of
obsfate output format.

I'm not an expert in the template engine, what benefits do you see in
putting the obsfate definition in templatekw.defaulttempl?
Yuya Nishihara - Oct. 12, 2017, 1:51 p.m.
On Thu, 12 Oct 2017 15:29:31 +0200, Boris Feld wrote:
> On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> > Ugh, there's templatekw.defaulttempl which provides the default
> > template
> > fragments to all stock/user templates. Maybe we can (ab)use it to
> > define
> > the default '{obsfate}' template.
> > 
> > I'm so sorry I didn't mention it before. It totally slipped my mind.
> 
> I saw templatekw.defaulttempl when working in this series but it felt
> like a big hack.
> 
> I tried to limit the number of places where obsfate is defined, this
> series already adds two obsfate definitions/implementations, the
> changeset_printer and lobsfate in the default mapfile. I thought adding
> a third one in defaulttempl would complicate the potential update of
> obsfate output format.
> 
> I'm not an expert in the template engine, what benefits do you see in
> putting the obsfate definition in templatekw.defaulttempl?

That's more close to the end goal, right? We started off with a couple of
building blocks to define {obsfate} in user template, because we don't want
a monolithic {obsfate} keyword.

It would be nice if we could add "obsfate" to map-cmdline.default, which
is the right way to define log templates, but IIRC you said you also wanted
to reuse it in any user templates. So using defaulttempl seemed less bad.
Boris Feld - Oct. 13, 2017, 6 p.m.
On Thu, 2017-10-12 at 22:51 +0900, Yuya Nishihara wrote:
> On Thu, 12 Oct 2017 15:29:31 +0200, Boris Feld wrote:
> > On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> > > Ugh, there's templatekw.defaulttempl which provides the default
> > > template
> > > fragments to all stock/user templates. Maybe we can (ab)use it to
> > > define
> > > the default '{obsfate}' template.
> > > 
> > > I'm so sorry I didn't mention it before. It totally slipped my
> > > mind.
> > 
> > I saw templatekw.defaulttempl when working in this series but it
> > felt
> > like a big hack.
> > 
> > I tried to limit the number of places where obsfate is defined,
> > this
> > series already adds two obsfate definitions/implementations, the
> > changeset_printer and lobsfate in the default mapfile. I thought
> > adding
> > a third one in defaulttempl would complicate the potential update
> > of
> > obsfate output format.
> > 
> > I'm not an expert in the template engine, what benefits do you see
> > in
> > putting the obsfate definition in templatekw.defaulttempl?
> 
> That's more close to the end goal, right? We started off with a
> couple of
> building blocks to define {obsfate} in user template, because we
> don't want
> a monolithic {obsfate} keyword.
> 
> It would be nice if we could add "obsfate" to map-cmdline.default,
> which
> is the right way to define log templates, but IIRC you said you also
> wanted
> to reuse it in any user templates. So using defaulttempl seemed less
> bad.

I thought that keywords defined in map-cmdline.default were not
available in user-defined templates, I need to check that.

One thing that I would like is for the default obsfate templatekw to be
verbosity dependent, both in changing the fields that are shown (no
date except in verbose mode) and the content of the fields themselves
(if current user is the only one that touched a changeset and not in
verbose mode, don't show users).

Is it possible to have this verbosity dependent logic with templates?
Yuya Nishihara - Oct. 14, 2017, 5:58 a.m.
On Fri, 13 Oct 2017 20:00:32 +0200, Boris Feld wrote:
> On Thu, 2017-10-12 at 22:51 +0900, Yuya Nishihara wrote:
> > On Thu, 12 Oct 2017 15:29:31 +0200, Boris Feld wrote:
> > > On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> > > > Ugh, there's templatekw.defaulttempl which provides the default
> > > > template
> > > > fragments to all stock/user templates. Maybe we can (ab)use it to
> > > > define
> > > > the default '{obsfate}' template.
> > > > 
> > > > I'm so sorry I didn't mention it before. It totally slipped my
> > > > mind.
> > > 
> > > I saw templatekw.defaulttempl when working in this series but it
> > > felt
> > > like a big hack.
> > > 
> > > I tried to limit the number of places where obsfate is defined,
> > > this
> > > series already adds two obsfate definitions/implementations, the
> > > changeset_printer and lobsfate in the default mapfile. I thought
> > > adding
> > > a third one in defaulttempl would complicate the potential update
> > > of
> > > obsfate output format.
> > > 
> > > I'm not an expert in the template engine, what benefits do you see
> > > in
> > > putting the obsfate definition in templatekw.defaulttempl?
> > 
> > That's more close to the end goal, right? We started off with a
> > couple of
> > building blocks to define {obsfate} in user template, because we
> > don't want
> > a monolithic {obsfate} keyword.
> > 
> > It would be nice if we could add "obsfate" to map-cmdline.default,
> > which
> > is the right way to define log templates, but IIRC you said you also
> > wanted
> > to reuse it in any user templates. So using defaulttempl seemed less
> > bad.
> 
> I thought that keywords defined in map-cmdline.default were not
> available in user-defined templates, I need to check that.

map-cmdline.default is not, but defaulttempl is. You need to %include a
map file to share some bits.

> One thing that I would like is for the default obsfate templatekw to be
> verbosity dependent, both in changing the fields that are shown (no
> date except in verbose mode) and the content of the fields themselves
> (if current user is the only one that touched a changeset and not in
> verbose mode, don't show users).
> 
> Is it possible to have this verbosity dependent logic with templates?

Maybe we can add {verbosity} keyword which returns ''/quiet/verbose/debug.
Boris Feld - Oct. 16, 2017, 4:50 p.m.
On Sat, 2017-10-14 at 14:58 +0900, Yuya Nishihara wrote:
> On Fri, 13 Oct 2017 20:00:32 +0200, Boris Feld wrote:
> > On Thu, 2017-10-12 at 22:51 +0900, Yuya Nishihara wrote:
> > > On Thu, 12 Oct 2017 15:29:31 +0200, Boris Feld wrote:
> > > > On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> > > > > Ugh, there's templatekw.defaulttempl which provides the
> > > > > default
> > > > > template
> > > > > fragments to all stock/user templates. Maybe we can (ab)use
> > > > > it to
> > > > > define
> > > > > the default '{obsfate}' template.
> > > > > 
> > > > > I'm so sorry I didn't mention it before. It totally slipped
> > > > > my
> > > > > mind.
> > > > 
> > > > I saw templatekw.defaulttempl when working in this series but
> > > > it
> > > > felt
> > > > like a big hack.
> > > > 
> > > > I tried to limit the number of places where obsfate is defined,
> > > > this
> > > > series already adds two obsfate definitions/implementations,
> > > > the
> > > > changeset_printer and lobsfate in the default mapfile. I
> > > > thought
> > > > adding
> > > > a third one in defaulttempl would complicate the potential
> > > > update
> > > > of
> > > > obsfate output format.
> > > > 
> > > > I'm not an expert in the template engine, what benefits do you
> > > > see
> > > > in
> > > > putting the obsfate definition in templatekw.defaulttempl?
> > > 
> > > That's more close to the end goal, right? We started off with a
> > > couple of
> > > building blocks to define {obsfate} in user template, because we
> > > don't want
> > > a monolithic {obsfate} keyword.
> > > 
> > > It would be nice if we could add "obsfate" to map-
> > > cmdline.default,
> > > which
> > > is the right way to define log templates, but IIRC you said you
> > > also
> > > wanted
> > > to reuse it in any user templates. So using defaulttempl seemed
> > > less
> > > bad.
> > 
> > I thought that keywords defined in map-cmdline.default were not
> > available in user-defined templates, I need to check that.
> 
> map-cmdline.default is not, but defaulttempl is. You need to %include
> a
> map file to share some bits.
> 
> > One thing that I would like is for the default obsfate templatekw
> > to be
> > verbosity dependent, both in changing the fields that are shown (no
> > date except in verbose mode) and the content of the fields
> > themselves
> > (if current user is the only one that touched a changeset and not
> > in
> > verbose mode, don't show users).
> > 
> > Is it possible to have this verbosity dependent logic with
> > templates?
> 
> Maybe we can add {verbosity} keyword which returns
> ''/quiet/verbose/debug.

I think that a good idea. Could we queue obsfate in the current state
and I will send a series that defines verbosity keyword and update
obsfate templatekw to use it?
Yuya Nishihara - Oct. 17, 2017, 1:02 p.m.
On Mon, 16 Oct 2017 18:50:29 +0200, Boris Feld wrote:
> On Sat, 2017-10-14 at 14:58 +0900, Yuya Nishihara wrote:
> > On Fri, 13 Oct 2017 20:00:32 +0200, Boris Feld wrote:
> > > On Thu, 2017-10-12 at 22:51 +0900, Yuya Nishihara wrote:
> > > > On Thu, 12 Oct 2017 15:29:31 +0200, Boris Feld wrote:
> > > > > On Wed, 2017-10-11 at 22:24 +0900, Yuya Nishihara wrote:
> > > > > > Ugh, there's templatekw.defaulttempl which provides the
> > > > > > default
> > > > > > template
> > > > > > fragments to all stock/user templates. Maybe we can (ab)use
> > > > > > it to
> > > > > > define
> > > > > > the default '{obsfate}' template.
> > > > > > 
> > > > > > I'm so sorry I didn't mention it before. It totally slipped
> > > > > > my
> > > > > > mind.
> > > > > 
> > > > > I saw templatekw.defaulttempl when working in this series but
> > > > > it
> > > > > felt
> > > > > like a big hack.
> > > > > 
> > > > > I tried to limit the number of places where obsfate is defined,
> > > > > this
> > > > > series already adds two obsfate definitions/implementations,
> > > > > the
> > > > > changeset_printer and lobsfate in the default mapfile. I
> > > > > thought
> > > > > adding
> > > > > a third one in defaulttempl would complicate the potential
> > > > > update
> > > > > of
> > > > > obsfate output format.
> > > > > 
> > > > > I'm not an expert in the template engine, what benefits do you
> > > > > see
> > > > > in
> > > > > putting the obsfate definition in templatekw.defaulttempl?
> > > > 
> > > > That's more close to the end goal, right? We started off with a
> > > > couple of
> > > > building blocks to define {obsfate} in user template, because we
> > > > don't want
> > > > a monolithic {obsfate} keyword.
> > > > 
> > > > It would be nice if we could add "obsfate" to map-
> > > > cmdline.default,
> > > > which
> > > > is the right way to define log templates, but IIRC you said you
> > > > also
> > > > wanted
> > > > to reuse it in any user templates. So using defaulttempl seemed
> > > > less
> > > > bad.
> > > 
> > > I thought that keywords defined in map-cmdline.default were not
> > > available in user-defined templates, I need to check that.
> > 
> > map-cmdline.default is not, but defaulttempl is. You need to %include
> > a
> > map file to share some bits.
> > 
> > > One thing that I would like is for the default obsfate templatekw
> > > to be
> > > verbosity dependent, both in changing the fields that are shown (no
> > > date except in verbose mode) and the content of the fields
> > > themselves
> > > (if current user is the only one that touched a changeset and not
> > > in
> > > verbose mode, don't show users).
> > > 
> > > Is it possible to have this verbosity dependent logic with
> > > templates?
> > 
> > Maybe we can add {verbosity} keyword which returns
> > ''/quiet/verbose/debug.
> 
> I think that a good idea. Could we queue obsfate in the current state
> and I will send a series that defines verbosity keyword and update
> obsfate templatekw to use it?

I don't feel it's good idea to queue stuff that will be mostly rewritten
in near future. Let's revist it after the release.

Patch

diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py
--- a/mercurial/obsutil.py
+++ b/mercurial/obsutil.py
@@ -783,3 +783,44 @@ 
                      if meta.get('operation'))
 
     return sorted(operations)
+
+def obsfateprinter(successors, markers, ui):
+    """ Build a obsfate string for a single successorset using all obsfate
+    related function defined in obsutil
+    """
+    line = []
+
+    # Verb
+    line.append(successorsetverb(successors))
+
+    # Operations
+    operations = markersoperations(markers)
+    if operations:
+        line.append(" using %s" % ", ".join(operations))
+
+    # Successors
+    if successors:
+        fmtsuccessors = [successors.joinfmt(succ) for succ in successors]
+        line.append(" as %s" % ", ".join(fmtsuccessors))
+
+    # Users
+    users = markersusers(markers)
+
+    if users:
+        line.append(" by %s" % ", ".join(users))
+
+    # Date
+    dates = markersdates(markers)
+
+    min_date = min(dates)
+    max_date = max(dates)
+
+    if min_date == max_date:
+        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
+        line.append(" (at %s)" % fmtmin_date)
+    else:
+        fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2')
+        fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2')
+        line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date))
+
+    return "".join(line)
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -580,6 +580,19 @@ 
     # rev and node are completely different from changeset's.
     return _mappable(f, f, lambda: {'rev': mrev, 'node': mhex})
 
+@templatekeyword('obsfate')
+def showobsfate(**args):
+    succsandmarkers = showsuccsandmarkers(**args)
+
+    ui = args['ui']
+
+    values = []
+
+    for x in succsandmarkers:
+        values.append(obsutil.obsfateprinter(x['successors'], x['markers'], ui))
+
+    return showlist("fate", values, args)
+
 def shownames(namespace, **args):
     """helper method to generate a template keyword for a namespace"""
     args = pycompat.byteskwargs(args)
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -7,7 +7,7 @@ 
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > logtemplate = {rev}:{node|short} {desc}\n
+  > logtemplate = {rev}:{node|short} {desc}{if(obsfate, " [{join(obsfate, "; ")}]")}\n
   > [experimental]
   > stabilization=createmarkers
   > [extensions]
@@ -66,7 +66,7 @@ 
   |
   | o  2:82623d38b9ba A_1
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [rewritten as 2:82623d38b9ba by test (at 1970-01-01 00:00 +0000); rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   @  0:d20a80d4def3 base
   
@@ -127,11 +127,11 @@ 
   $ hg log -G --hidden
   @  4:01f36c5a8fda A_3
   |
-  | x  3:392fd25390da A_2
+  | x  3:392fd25390da A_2 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
   | o  2:82623d38b9ba A_1
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [rewritten as 2:82623d38b9ba by test (at 1970-01-01 00:00 +0000); rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   o  0:d20a80d4def3 base
   
@@ -185,7 +185,7 @@ 
   |
   | o  2:82623d38b9ba A_1
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [rewritten as 2:82623d38b9ba by test (at 1970-01-01 00:00 +0000); rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   @  0:d20a80d4def3 base
   
@@ -259,11 +259,11 @@ 
   $ hg log -G --hidden
   @  4:01f36c5a8fda A_3
   |
-  | x  3:392fd25390da A_2
+  | x  3:392fd25390da A_2 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  2:82623d38b9ba A_1
+  | x  2:82623d38b9ba A_1 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [rewritten as 2:82623d38b9ba by test (at 1970-01-01 00:00 +0000); rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   o  0:d20a80d4def3 base
   
@@ -309,7 +309,7 @@ 
   |
   | o  2:82623d38b9ba A_1
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [split as 2:82623d38b9ba, 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   @  0:d20a80d4def3 base
   
@@ -361,15 +361,15 @@ 
   $ hg log -G --hidden
   @  6:e442cfc57690 A_5
   |
-  | x  5:6a411f0d7a0a A_4
+  | x  5:6a411f0d7a0a A_4 [rewritten as 6:e442cfc57690 by test (at 1970-01-01 00:00 +0000)]
   |/
   | o  4:01f36c5a8fda A_3
   |/
-  | x  3:392fd25390da A_2
+  | x  3:392fd25390da A_2 [rewritten as 5:6a411f0d7a0a by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  2:82623d38b9ba A_1
+  | x  2:82623d38b9ba A_1 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [split as 2:82623d38b9ba, 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   o  0:d20a80d4def3 base
   
@@ -437,19 +437,19 @@ 
   |/
   | o  8:7ae126973a96 A_7
   |/
-  | x  7:3750ebee865d B_0
+  | x  7:3750ebee865d B_0 [rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   | |
-  | x  6:e442cfc57690 A_5
+  | x  6:e442cfc57690 A_5 [rewritten as 10:bed64f5d2f5a by test (at 1970-01-01 00:00 +0000); split as 8:7ae126973a96, 9:14608b260df8 by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  5:6a411f0d7a0a A_4
+  | x  5:6a411f0d7a0a A_4 [rewritten as 6:e442cfc57690 by test (at 1970-01-01 00:00 +0000)]
   |/
   | o  4:01f36c5a8fda A_3
   |/
-  | x  3:392fd25390da A_2
+  | x  3:392fd25390da A_2 [rewritten as 5:6a411f0d7a0a by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  2:82623d38b9ba A_1
+  | x  2:82623d38b9ba A_1 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [split as 2:82623d38b9ba, 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   @  0:d20a80d4def3 base
   
@@ -535,25 +535,25 @@ 
   $ hg log -G --hidden
   o  11:a139f71be9da A_A
   |
-  | x  10:bed64f5d2f5a A_9
+  | x  10:bed64f5d2f5a A_9 [rewritten as 11:a139f71be9da by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  9:14608b260df8 A_8
+  | x  9:14608b260df8 A_8 [rewritten as 11:a139f71be9da by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  8:7ae126973a96 A_7
+  | x  8:7ae126973a96 A_7 [rewritten as 11:a139f71be9da by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  7:3750ebee865d B_0
+  | x  7:3750ebee865d B_0 [rewritten as 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   | |
-  | x  6:e442cfc57690 A_5
+  | x  6:e442cfc57690 A_5 [rewritten as 10:bed64f5d2f5a by test (at 1970-01-01 00:00 +0000); split as 8:7ae126973a96, 9:14608b260df8 by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  5:6a411f0d7a0a A_4
+  | x  5:6a411f0d7a0a A_4 [rewritten as 6:e442cfc57690 by test (at 1970-01-01 00:00 +0000)]
   |/
   | o  4:01f36c5a8fda A_3
   |/
-  | x  3:392fd25390da A_2
+  | x  3:392fd25390da A_2 [rewritten as 5:6a411f0d7a0a by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  2:82623d38b9ba A_1
+  | x  2:82623d38b9ba A_1 [rewritten as 4:01f36c5a8fda by test (at 1970-01-01 00:00 +0000)]
   |/
-  | x  1:007dc284c1f8 A_0
+  | x  1:007dc284c1f8 A_0 [split as 2:82623d38b9ba, 3:392fd25390da by test (at 1970-01-01 00:00 +0000)]
   |/
   @  0:d20a80d4def3 base
   
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -3,7 +3,7 @@ 
   > # public changeset are not obsolete
   > publish=false
   > [ui]
-  > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}\n"
+  > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}{if(obsfate, " [{join(obsfate, "; ")}]")}\n"
   > EOF
   $ mkcommit() {
   >    echo "$1" > "$1"
@@ -159,9 +159,9 @@ 
   5:5601fb93a350 (draft) [tip ] add new_3_c
   $ hg heads --hidden
   5:5601fb93a350 (draft) [tip ] add new_3_c
-  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
-  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
-  2:245bde4270cd (draft *obsolete*) [ ] add original_c
+  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350 by test (between 1970-01-01 00:22 +0000 and 1970-01-01 00:22 +0000)]
+  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9 by test (at 1970-01-01 00:22 +0000)]
+  2:245bde4270cd (draft *obsolete*) [ ] add original_c [rewritten as 3:cdbce2fbb163 by test (at 1970-01-01 00:00 -0002)]
 
 
 check that summary does not report them
@@ -277,11 +277,11 @@ 
   $ hg log -G --hidden
   @  6:6f9641995072 (draft) [tip ] add n3w_3_c
   |
-  | x  5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
+  | x  5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072 by test (at 1970-01-01 00:22 +0000)]
   |/
-  | x  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
+  | x  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350 by test (between 1970-01-01 00:22 +0000 and 1970-01-01 00:22 +0000)]
   |/
-  | x  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
+  | x  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9 by test (at 1970-01-01 00:22 +0000)]
   |/
   | o  2:245bde4270cd (public) [ ] add original_c
   |/
@@ -434,11 +434,11 @@ 
   $ hg -R clone-dest log -G --hidden
   @  6:6f9641995072 (draft) [tip ] add n3w_3_c
   |
-  | x  5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
+  | x  5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072 by test (at 1970-01-01 00:22 +0000)]
   |/
-  | x  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
+  | x  4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350 by test (between 1970-01-01 00:22 +0000 and 1970-01-01 00:22 +0000)]
   |/
-  | x  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
+  | x  3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9 by test (at 1970-01-01 00:22 +0000)]
   |/
   | o  2:245bde4270cd (public) [ ] add original_c
   |/
@@ -518,7 +518,7 @@ 
   $ hg debugobsolete | grep `getid original_d`
   94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
   $ hg log -r 'obsolete()'
-  4:94b33453f93b (draft *obsolete*) [ ] add original_d
+  4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned by test (at 1970-01-01 00:00 +0000)]
   $ hg summary
   parent: 5:cda648ca50f5 tip (orphan)
    add original_e
@@ -530,7 +530,7 @@ 
   $ hg log -G -r '::orphan()'
   @  5:cda648ca50f5 (draft orphan) [tip ] add original_e
   |
-  x  4:94b33453f93b (draft *obsolete*) [ ] add original_d
+  x  4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned by test (at 1970-01-01 00:00 +0000)]
   |
   o  3:6f9641995072 (draft) [ ] add n3w_3_c
   |
@@ -569,7 +569,7 @@ 
   1:7c3bad9141dc (public) [ ] add b
   2:245bde4270cd (public) [ ] add original_c
   3:6f9641995072 (draft) [ ] add n3w_3_c
-  4:94b33453f93b (draft *obsolete*) [ ] add original_d
+  4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned by test (at 1970-01-01 00:00 +0000)]
   5:cda648ca50f5 (draft orphan) [tip ] add original_e
   $ hg push ../tmpf -f # -f because be push unstable too
   pushing to ../tmpf
@@ -593,7 +593,7 @@ 
   $ hg log -G
   @  5:cda648ca50f5 (draft orphan) [tip ] add original_e
   |
-  x  4:94b33453f93b (draft *obsolete*) [ ] add original_d
+  x  4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned by test (at 1970-01-01 00:00 +0000)]
   |
   o  3:6f9641995072 (draft) [ ] add n3w_3_c
   |
@@ -634,9 +634,9 @@ 
   $ hg log --hidden --graph
   @  6:3de5eca88c00 (draft) [tip ] add obsolete_e
   |
-  | x  5:cda648ca50f5 (draft *obsolete*) [ ] add original_e
+  | x  5:cda648ca50f5 (draft *obsolete*) [ ] add original_e [rewritten as 6:3de5eca88c00 by test <test@example.net> (at 1970-01-01 00:00 +0000)]
   | |
-  | x  4:94b33453f93b (draft *obsolete*) [ ] add original_d
+  | x  4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned by test (at 1970-01-01 00:00 +0000)]
   |/
   o  3:6f9641995072 (draft) [ ] add n3w_3_c
   |
@@ -925,7 +925,7 @@ 
 test the "obsolete" templatekw
 
   $ hg log -r 'obsolete()'
-  6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e
+  6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e [pruned by test (at 1970-01-01 00:00 +0000)]
 
 test the "troubles" templatekw
 
@@ -1095,7 +1095,7 @@ 
   $ hg log -G
   @  2:323a9c3ddd91 (draft) [tip ] A
   |
-  | x  1:29f0c6921ddd (draft *obsolete*) [visible ] A
+  | x  1:29f0c6921ddd (draft *obsolete*) [visible ] A [rewritten using amend as 2:323a9c3ddd91 by test (at 1970-01-01 00:00 +0000)]
   |/
   o  0:d20a80d4def3 (draft) [ ] base
   
@@ -1148,7 +1148,7 @@ 
   $ hg log -G --hidden
   @  2:b7d587542d40 (draft) [tip ] B+
   |
-  | x  1:44526ebb0f98 (draft *obsolete*) [ ] B
+  | x  1:44526ebb0f98 (draft *obsolete*) [ ] B [rewritten using amend as 2:b7d587542d40 by test (at 1970-01-01 00:00 +0000)]
   |/
   o  0:4b34ecfb0d56 (draft) [ ] A
   
@@ -1275,7 +1275,7 @@ 
   $ hg commit --amend -m "message"
   $ hg book bookb -r 13bedc178fce --hidden
   $ hg log -r 13bedc178fce
-  4:13bedc178fce (draft *obsolete*) [ bookb] add b
+  4:13bedc178fce (draft *obsolete*) [ bookb] add b [rewritten using amend as 5:a9b1f8652753 by test (at 1970-01-01 00:00 +0000)]
   $ hg book -d bookb
   $ hg log -r 13bedc178fce
   abort: hidden revision '13bedc178fce'!
@@ -1315,7 +1315,7 @@ 
   $ hg log -G --hidden
   @  3:b0551702f918 (draft) [tip ] 2
   |
-  | x  2:e008cf283490 (draft *obsolete*) [ ] 2
+  | x  2:e008cf283490 (draft *obsolete*) [ ] 2 [rewritten using amend as 3:b0551702f918 by test (at 1970-01-01 00:00 +0000)]
   |/
   o  1:e016b03fd86f (draft) [ ] 1
   |