[PATCH 1 of 9 PoC] mq2: proof of concept for improving mq - starting point and tests

Gregory Szorc gregory.szorc at gmail.com
Tue Sep 9 13:17:14 CDT 2014


As much as I personally dislike many aspects of mq, there are people 
(especially at Mozilla) that cling to it and this patch series offers 
some ideas that would go a long way towards making the mq workflow more 
compatible with Mozilla's wants.

Namely:

1) Our new code review tool is obsolescence aware. When creating reviews 
of commits that have obsolescence data, the workflow is vastly simpler 
since we can get the commit mapping from history rewriting from 
obsolescence. Maintaining this from mq is slightly more difficult since 
it requires storing patch names. Patch names are neither versioned nor 
consistent, so things break down when people collaborate on reviews. 
(We're trying to avoid writing heuristic-based commit mapping for as 
long as possible.)

2) Merge handling. One of Mozilla's top complaints about Mercurial is 
merge handling. I suspect most of the complainers are people using mq 
and not getting the superior merge tool experience. I'd love to see mq 
play nicer with merging and not produce .rej files.

I also think that bridging the gap between evolve and mq is a worthy 
goal. Some people just like thinking about mq-style heads as separate 
from the "core" repo data. It seems to be easier for them to grok.

I feel that a lot of people at Mozilla will cling to mq despite advances 
in bookmarks workflows, etc. I would prefer to support these users with 
mq++ over mq-current. I therefore support this patch series.

On 8/29/14 1:59 AM, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski at unity3d.com>
> # Date 1409301979 -7200
> #      Fri Aug 29 10:46:19 2014 +0200
> # Node ID e426af93a42f11fb187793904b743b5b4341af6e
> # Parent  926bc0d3b595caf37c5d70833a347eb43285de2f
> mq2: proof of concept for improving mq - starting point and tests
>
> These days it is trendy to bash mq and try to kill it. Instead, let's create
> something better and let the winner win and let the loser go somewhere else and
> die a quiet death.
>
> Let's try to evolve and improve mq and give people the choice of using the tool
> they prefer.
>
> I kind of see mq as a tool for efficiently locally working on a number of
> patches, while I more more see evolve as a tool modifying history under my
> feet.
>
> Problems/design goals to address:
>   * Improve mq and try to remain backwards compatible.
>   * Use merge and merge tools instead of patches and .rej files.
>   * Better meta history without using tracked queues.
>   * Consider evolve and the mindset that comes with it, be compatible or
>     bridge the gab to it.
>
> The basic ideas are:
>   * Keep "stripped" (especially qpopped) changesets around instead of stripping
>     them.
>   * If possible, use these changesets for grafting when "qpushing".
>   * Update patch files with reference to the last changeset it was qpushed as.
>   * Get "rid" of qpopped changesets when they no longer are referenced -
>     currently by using obsolete, could also strip them at that point.
>
> Current issues:
>   * Needs real testing.
>   * Needs better error handling.
>   * Better handling of the 'qpush failed with .rej files' scenario.
>   ** It will now use merge - which is nice but requires test updates.
>   ** How to represent that state (use nullid or a commit of something random?).
>   ** How to continue from that state (qrefresh should pick it up).
>   * Collision with already obsoleted changesets. Is that because obsolete markers
>     are a bad solution to the problem ... or solving the wrong problem?
>   * Some .unfiltered() has been added in various places. Is it just because
>     this filtered hack is a *** hack or is there something wrong?
>
> These changes are done incrementally in code, causing some test churn that mostly
> ends up going away again. That is mostly because we start keeping "stripped"
> changesets before we start hiding them.
>
> diff --git a/tests/test-mq2.t b/tests/test-mq2.t
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-mq2.t
> @@ -0,0 +1,153 @@
> +  $ checkundo()
> +  > {
> +  >     if [ -f .hg/store/undo ]; then
> +  >     echo ".hg/store/undo still exists after $1"
> +  >     fi
> +  > }
> +
> +  $ echo "[extensions]" >> $HGRCPATH
> +  $ echo "mq=" >> $HGRCPATH
> +
> +  $ echo "[mq]" >> $HGRCPATH
> +  $ echo "plain=false" >> $HGRCPATH
> +
> +  $ echo "[diff]" >> $HGRCPATH
> +  $ echo "git=true" >> $HGRCPATH
> +
> +  $ hg init a
> +  $ cd a
> +  $ echo a > a
> +  $ hg ci -Ama
> +  adding a
> +
> +  $ hg qnew b -d '314159265 0'
> +  $ echo b > b
> +  $ hg add b
> +  $ cat .hg/patches/b
> +  # HG changeset patch
> +  # Parent cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
> +  # Date 314159265 0
> +
> +  $ hg qref -m b -d '47 0'
> +  $ cat .hg/patches/b
> +  # HG changeset patch
> +  # Parent cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
> +  # Date 47 0
> +  b
> +
> +  diff --git a/b b/b
> +  new file mode 100644
> +  --- /dev/null
> +  +++ b/b
> +  @@ -0,0 +1,1 @@
> +  +b
> +
> +  $ echo a2 >> a
> +  $ hg qnew a2 -m a2 -d '117 0'
> +
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  2 757e6e08e7eb draft a2
> +  |
> +  o  1 3506c28d72aa draft b
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> +
> +  $ hg qpop
> +  popping a2
> +  now at: b
> +
> +  $ cat .hg/patches/status
> +  3506c28d72aa3a31f8ce50ca4cfcb812af131450:b
> +
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  1 3506c28d72aa draft b
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> +
> +  $ hg qpush
> +  applying a2
> +  now at: a2
> +
> +  $ cat .hg/patches/status
> +  3506c28d72aa3a31f8ce50ca4cfcb812af131450:b
> +  757e6e08e7eb6b956e2d583ff4d7450d392f8a13:a2
> +
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  2 757e6e08e7eb draft a2
> +  |
> +  o  1 3506c28d72aa draft b
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> +
> +  $ hg qpop -a
> +  popping a2
> +  popping b
> +  patch queue now empty
> +  $ sed -i 1iyada a
> +  $ hg ci -m yada
> +
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  1 dfa6dafa9c6c draft yada
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> +
> +  $ cat .hg/patches/b
> +  # HG changeset patch
> +  # Parent cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
> +  # Date 47 0
> +  b
> +
> +  diff --git a/b b/b
> +  new file mode 100644
> +  --- /dev/null
> +  +++ b/b
> +  @@ -0,0 +1,1 @@
> +  +b
> +  $ hg qpush
> +  applying b
> +  now at: b
> +  $ cat .hg/patches/b
> +  # HG changeset patch
> +  # Parent cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
> +  # Date 47 0
> +  b
> +
> +  diff --git a/b b/b
> +  new file mode 100644
> +  --- /dev/null
> +  +++ b/b
> +  @@ -0,0 +1,1 @@
> +  +b
> +
> +  $ hg qpush
> +  applying a2
> +  now at: a2
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  3 cd192c2f0104 draft a2
> +  |
> +  o  2 c27d00b1f47f draft b
> +  |
> +  o  1 dfa6dafa9c6c draft yada
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> +
> +  $ hg qap
> +  b
> +  a2
> +  $ hg qpop -a
> +  popping a2
> +  popping b
> +  patch queue now empty
> +  $ hg qrm b
> +  $ hg qrm a2
> +(should also have stripped b that couldn't be stripped before)
> +  $ hg log -G --template "{rev} {node|short} {phase} {desc|firstline}\n"
> +  @  1 dfa6dafa9c6c draft yada
> +  |
> +  o  0 cb9a9f314b8b draft a
> +
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>



More information about the Mercurial-devel mailing list