[PATCH V2] show: implement "stack" view

Sean Farley sean at farley.io
Tue Jul 4 20:17:00 EDT 2017


Gregory Szorc <gregory.szorc at gmail.com> writes:

> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1498973922 25200
> #      Sat Jul 01 22:38:42 2017 -0700
> # Node ID eaf601d0ea04ad80ee3d763cb3274286a780f16d
> # Parent  6d678ab1b10d0fddc73003d21aa3c7ec43194e2e
> show: implement "stack" view
>
> People often want to know what they are working on *now*. As part of
> this, they also commonly want to know how that work is related to other
> changesets in the repo so they can perform common actions like rebase,
> histedit, and merge.
>
> `hg show work` made headway into this space. However, it is geared
> towards a complete repo view as opposed to just the current line of
> work. If you have a lot of in-flight work or the repo has many heads,
> the output can be overwhelming. The closest thing Mercurial has to
> "show me the current thing I'm working on" that doesn't require custom
> revsets is `hg qseries`. And this requires MQ, which completely changes
> workflows and repository behavior and has horrible performance on large
> repos. But as sub-optimal as MQ is, it does some things right, such as
> expose a model of the repo that is easy for people to reason about.
> This simplicity is why I think a lot of people prefer to use MQ, despite
> its shortcomings.
>
> One common development workflow is to author a series of linear
> changesets, using bookmarks, branches, anonymous heads, or even topics
> (3rd party extension). I'll call this a "stack." You periodically
> rewrite history in place (using `hg histedit`) and reparent the stack
> against newer changesets (using `hg rebase`). This workflow can be
> difficult because there is no obvious way to quickly see the current
> "stack" nor its relation to other changesets. Figuring out arguments to
> `hg rebase` can be difficult and may require highlighting and pasting
> multiple changeset nodes to construct a command.
>
> The goal of this commit is to make stack based workflows simpler
> by exposing a view of the current stack and its relationship to
> other releant changesets, notably the parent of the base changeset
> in the stack and newer heads that the stack could be rebased or merged
> into.
>
> Introduced is the `hg show stack` view. Essentially, it finds all
> mutable changesets from the working directory revision in both
> directions, stopping at a merge or branch point. This limits the
> revisions to a DAG linear range.
>
> The stack is rendered as a concise list of changesets. Alongside the
> stack is a visualization of the DAG, similar to `hg log -G`.
>
> Newer public heads from the branch point of the stack are rendered
> above the stack. The presence of these heads helps people understand
> the DAG model and the relationship between the stack and changes made
> since the branch point of that stack. If the "rebase" command is
> available, a `hg rebase` command is printed for each head so a user
> can perform a simple copy and paste to perform a rebase.
>
> This view is alpha quality. There are tons of TODOs documented
> inline. But I think it is good enough for a first iteration.
>
> diff --git a/hgext/show.py b/hgext/show.py
> --- a/hgext/show.py
> +++ b/hgext/show.py
> @@ -32,9 +32,11 @@ from mercurial.node import nullrev
>  from mercurial import (
>      cmdutil,
>      commands,
> +    destutil,
>      error,
>      formatter,
>      graphmod,
> +    phases,
>      pycompat,
>      registrar,
>      revset,
> @@ -171,6 +173,166 @@ def showbookmarks(ui, repo, fm):
>          fm.data(active=bm == active,
>                  longestbookmarklen=longestname)
>  
> + at showview('stack', csettopic='stack')
> +def showstack(ui, repo, displayer):
> +    """current line of work"""
> +    wdirctx = repo['.']
> +    if wdirctx.rev() == nullrev:
> +        raise error.Abort(_('stack view only available when there is a '
> +                            'working directory'))
> +
> +    if wdirctx.phase() == phases.public:
> +        ui.write(_('(empty stack; working directory is a published '
> +                   'changeset)\n'))
> +        return
> +
> +    # TODO extract "find stack" into a function to facilitate
> +    # customization and reuse.
> +
> +    baserev = destutil.stackbase(ui, repo)
> +    basectx = None
> +
> +    if baserev is None:
> +        baserev = wdirctx.rev()
> +        stackrevs = {wdirctx.rev()}
> +    else:
> +        stackrevs = set(repo.revs('%d::.', baserev))
> +
> +    ctx = repo[baserev]
> +    if ctx.p1().rev() != nullrev:
> +        basectx = ctx.p1()
> +
> +    # And relevant descendants.
> +    branchpointattip = False
> +    cl = repo.changelog
> +
> +    for rev in cl.descendants([wdirctx.rev()]):

I think for the first iteration of this, we could use the dead-simple:
'draft() and branch(.)' revset. Later we could try throwing in some
'only' revset logic (which would handle the branch point stuff) but my
gut feeling is to keep this simple (perhaps specify this revset as an
option?)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 800 bytes
Desc: not available
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20170704/b4bf33c3/attachment.sig>


More information about the Mercurial-devel mailing list