[PATCH 9 of 9] template: use template-engine for obsfate

Boris Feld boris.feld at octobus.net
Thu Jul 13 06:32:39 EDT 2017


I think there was a misunderstanding about obsfate that I will try to
clarify, this email is a bit long, sorry.

TL;DR:
- hg log is a changeset-centric command
- obsfate template summarize the obs-history between a changeset and
its successors, history that can span several obs-markers
- hg obslog from evolve extensions is a obs-marker centric command that
could gain support for operation

Given this repository:

  @  changeset:   2:256782ab8caa
  |  tag:         tip
  |  parent:      0:ea207398892e
  |  user:        test
  |  date:        Thu Jan 01 00:00:00 1970 +0000
  |  summary:     B
  |
  | o  changeset:   1:2a34000d3544
  |/   user:        test
  |    date:        Thu Jan 01 00:00:00 1970 +0000
  |    summary:     A
  |
  o  changeset:   0:ea207398892e
     user:        test
     date:        Thu Jan 01 00:00:00 1970 +0000
     summary:     ROOT

If you rebase 1 on top of 2, amend it a first time, then amend it a
second time, you will get:


  @  changeset:   5:022e174ded42
  |  tag:         tip
  |  parent:      2:256782ab8caa
  |  user:        test2
  |  date:        Thu Jan 01 00:00:00 1970 +0000
  |  summary:     A"
  |
  o  changeset:   2:256782ab8caa
  |  parent:      0:ea207398892e
  |  user:        test
  |  date:        Thu Jan 01 00:00:00 1970 +0000
  |  summary:     B
  |
  o  changeset:   0:ea207398892e
     user:        test
     date:        Thu Jan 01 00:00:00 1970 +0000
     summary:     ROOT

Now for any reason if changeset 1 should be shown (if it's the current
repository parent for example), the output would be:


  o  changeset:   5:022e174ded42
  |  tag:         tip
  |  parent:      2:256782ab8caa
  |  user:        test2
  |  date:        Thu Jan 01 00:00:00 1970 +0000
  |  files:       A
  |  description:
  |  A"
  |
  |
  o  changeset:   2:256782ab8caa
  |  parent:      0:ea207398892e
  |  user:        test
  |  date:        Thu Jan 01 00:00:00 1970 +0000
  |  files:       B
  |  description:
  |  B
  |
  |
  | @  changeset:   1:2a34000d3544
  |/   user:        test
  |    date:        Thu Jan 01 00:00:00 1970 +0000
  |    obsolete:    rewritten by test as 022e174ded42 (at 1970-01-01
00:00 +0000)
  |    files:       A
  |    description:
  |    A
  |
  |
  o  changeset:   0:ea207398892e
     user:        test
     date:        Thu Jan 01 00:00:00 1970 +0000
     files:       ROOT
     description:
     ROOT

Obsfate was designed to summarize the obsolescence history for users.
As 'hg log' is a changeset centric command, obsfate tries to output
informations about visible changesets only. That's why obsfate for
2a34000d3544 is "rewritten as 022e174ded42". We have intermediary
changesets but they are not visible here so it would be disturbing to
say to the user "rewritten as 1737d8285b4d".

One side-effect of this summarization is that obsfate needs to
aggregate all the obs-markers from 2a34000d3544 to 022e174ded42, which
in this case is "1->3" (from the rebase), "3->4" (from the first amend)
and "4->5" (from the second amend). Here the range of obs-markers is
short but it could be much more big. That's why obsfate aggregate a
couple of fields to show a human-redable summary of the obs-history:

- Remove users duplicate.
- Compute the range of date, the smaller date of the obs-marker range
and the bigger one.
- Try to compute a verb based on the markers.

All theses computations are quite naive for the moment but the code has
been designed to be easily updated, wrapped by a command or extended.

This example is also quite simple but a real-life example:

  obsolete:    split by Boris Feld <boris.feld at octobus.net>,Matthieu
Laneuville <matthieu.laneuville at octobus.net> as 008f7cd1fcbe,
b6e50897b94e (between 2017-06-26 17:17 +0200 and 2017-07-02 15:08
+0200)

In this case, obsfate is summarizing 19 obs-markers.


Correct me if I'm wrong, but it looks like you're thinking about a more
obs-marker centric way of displaying history. We have a command like
that in the evolve extension: "obslog": while hg log shows changesets
and parents/descendants, hg obslog shows changesets and
successors/predecessors.

For example, this would be the output of "hg obslog -r 5":

  @  022e174ded42 (5) A"
  |
  x  15900262089a (4) A"
  |    rewritten(user) by test (Thu Jan 01 00:00:00 1970 +0000) as
022e174ded42
  |
  x  1737d8285b4d (3) A
  |    rewritten(description) by test (Thu Jan 01 00:00:00 1970 +0000)
as 15900262089a
  |
  x  2a34000d3544 (1) A
       rewritten(parent) by test (Thu Jan 01 00:00:00 1970 +0000) as
1737d8285b4d

With this command, one marker is displayed by line, not an aggregate so
it would make sense to add support for operation there. It would be a
nice improvement to use the operation metadata to display a more
accurate verb in this function.

On Wed, 2017-07-12 at 09:28 -0700, Jun Wu wrote:
> As previously discussed in the "operation" thread [1]. I think we
> want to
> use "operation" metadata instead of introducing flags, "obsfate"
> and/or
> "verb" as new concepts. Practically "rebased as X" / "histedited as
> X" is
> more friendly to end-user than just "rewritten as X".
> 
> With "operation" concept available, template could be just raw fields
> of an
> obsmarker like user, data, successors, operation etc without needing
> another
> layer of indirection (obsfate). I think that's simpler for users to
> understand.
> 
> [1]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-May
> /097678.html
> 
> Excerpts from Boris Feld's message of 2017-07-12 15:44:13 +0200:
> > On Wed, 2017-07-12 at 00:06 +0900, Yuya Nishihara wrote:
> > > On Tue, 11 Jul 2017 11:16:03 +0200, Boris Feld wrote:
> > > > Obsfate has a difficult task: summarize the obsolescence
> > > > history
> > > > (potentially spanning multiple obs-markers), aggregating the
> > > > different
> > > > values and all of this in multiple dimensions when there's a
> > > > divergence.
> > > > 
> > > > This template seems quite complex, it felt complex during
> > > > implementation using templates. I tried finding an existing
> > > > template
> > > > that was close to this complexity, successorssets was close but
> > > > obsfate
> > > > adds one more layer of nesting, so I didn't find a good example
> > > > to
> > > > mimic.
> > > > 
> > > > I'm pretty sure that implementing obsfate cleanly with the
> > > > template
> > > > engine can be done, but after spending several days, I'm afraid
> > > > I
> > > > won't
> > > > be able to do it on my own. For example, I wasn't able to
> > > > successfully
> > > > format the users list using templates, I tried doing this:
> > > >     
> > > >     hg log -G -T '{obsfate % "obsolete: {get(obsfate, "verb")}
> > > > by
> > > > {join(get(obsfate, "users"), ', ')}\n"}'
> > > > 
> > > > Lately, I was thinking about sending a V2 that, instead of
> > > > returning
> > > > the formatted string, would returns an _hybrid object:
> > > >     
> > > > -    return _obsfateprinter(values, repo, repo.ui)
> > > > +    gen = _obsfateprinter(values, repo, repo.ui)
> > > > +    return _hybrid(gen, values, None, None)
> > > > 
> > > > This way people would be able to start customizing it (with
> > > > template
> > > > function "get") and we would be able to improve the
> > > > implementation
> > > > with
> > > > potential syntactic sugar addition in the template engine.
> > > 
> > > Well, I don't have expertise in the obsolete thingy, though I'm
> > > (unfortunately)
> > > a template expert.
> > > 
> > > Guessing from the PATCH 4, which has the following functions,
> > > 
> > >   obsfatedata: ctx => [succs, ...] => [(succs, markers), ...]
> > > 
> > > maybe we'll want a template function which converts 'succs' to
> > > 'markers' ?
> > > Let's call it 'relatedmarkers' here.
> > > 
> > >   relatedmarkers: succs => [marker, ...]  (where marker is a
> > > _hybrid
> > > dict)
> > > 
> > > Then, a part of {obsfate} could probably be written as:
> > > 
> > >   {successorsets % "{relatedmarkers(successorset)
> > >                      % "{get(marker, "verb")} ..."}"}
> > 
> > I hadn't thought about splitting the template into several
> > templates
> > functions, it's a good idea!.
> > 
> > One small, but important detail: the verb, users list and dates are
> > computed from the markers list. Something like this might work,
> > what do
> > you think?
> > 
> >     {successorsets % "{obsfateverb(successorset)} by
> > {obsfateusers(successorset)} as {join(get(successorset,
> > 'successors'),
> > ', ')}"}
> > 
> > Would it be possible to keep the current {obsfate} template? It is
> > easy
> > to use for users who are OK with the default obsfate output format
> > (which could be updated of course).
> > 
> > Also I've almost successfully reproduce the obsfate output "by
> > hand"
> > with:
> > 
> > $ hg log -r 34177 --hidden -v -T "{obsfate}"
> > rewritten by Boris Feld <boris.feld at octobus.net> as e18d8e61b726
> > (at
> > 2017-07-06 23:47 +0200)
> > 
> > $ hg log -r 34177 --hidden -T '{obsfate % "{get(obsfate, "verb")}
> > by
> > {join(get(obsfate, "users"), ", ")} as {get(obsfate, "successors")}
> > (at
> > {get(obsfate, "min_date")|isodate})\n"}'
> > rewritten by Boris Feld <boris.feld at octobus.net> as e18d8e61b726
> > (at
> > 2017-07-06 23:47 +0200)
> > > 
> > > I think that's similar to what Jun suggested.


More information about the Mercurial-devel mailing list