Submitter | David Soria Parra |
---|---|
Date | Sept. 17, 2014, 12:58 a.m. |
Message ID | <b37ac883fe2d267fdbff.1410915520@davidsp-mbp.local> |
Download | mbox | patch |
Permalink | /patch/5837/ |
State | Changes Requested |
Headers | show |
Comments
On 09/16/2014 05:58 PM, David Soria Parra wrote: > # HG changeset patch > # User David Soria Parra <davidsp@fb.com> > # Date 1410900110 25200 > # Tue Sep 16 13:41:50 2014 -0700 > # Node ID b37ac883fe2d267fdbff2fbfc72477738493531c > # Parent d4e975e2707a0ea606c22ed472d56fab4fda7ae2 > histedit: add 'x'/'exec' verb > > Add the 'x'/'exec' verb to execute a command. As exec lives in it's own line > and doesn't have a changeset attached to but applies to the previous changeset, > we have add some special handling. In particular when we restore we don't want > to execute the command again. This new action needs to be added to the histedit documentation. > > diff --git a/hgext/histedit.py b/hgext/histedit.py > --- a/hgext/histedit.py > +++ b/hgext/histedit.py > @@ -429,7 +429,11 @@ > raise error.InterventionRequired( > _('Working copy dirty, please check the files listed above.\n' > 'When you are finished, run hg histedit --continue to resume.')) > - return ctx, [] > + > + newctx = repo['.'] > + if ctx.node() != newctx.node(): > + return newctx, [(ctx.node(), (newctx.node(),))] > + return newctx, [] > > def message(ui, repo, ctx, ha, opts): > oldctx = repo[ha] > @@ -486,6 +490,8 @@ > 'drop': drop, > 'm': message, > 'mess': message, > + 'x': execute, > + 'exec': execute, > } > > @command('histedit', > @@ -707,7 +713,14 @@ > > def bootstrapcontinue(ui, repo, parentctx, rules, opts): > action, currentnode = rules.pop(0) > - ctx = repo[currentnode] > + if action in ['x', 'exec']: > + action, currentnode = rules.pop(0) > + # ensure we jump to the next node after an exec > + if action not in ['x', 'exec']: micro nits: could be ('x', 'exec') instead of ['x, 'exec'] > + ctx = repo[currentnode] > + hg.update(repo, ctx.node()) > + else: > + ctx = repo[currentnode] > > newchildren = gatherchildren(repo, parentctx) > > @@ -825,20 +838,23 @@ > if ' ' not in r: > raise util.Abort(_('malformed line "%s"') % r) > action, rest = r.split(' ', 1) > - ha = rest.strip().split(' ', 1)[0] > - try: > - ha = str(repo[ha]) # ensure its a short hash > - except error.RepoError: > - raise util.Abort(_('unknown changeset %s listed') % ha) > - if ha not in expected: > - raise util.Abort( > - _('may not use changesets other than the ones listed')) > - if ha in seen: > - raise util.Abort(_('duplicated command for changeset %s') % ha) > - seen.add(ha) > - if action not in actiontable: > - raise util.Abort(_('unknown action "%s"') % action) > - parsed.append([action, ha]) > + if action in ['x', 'exec']: > + parsed.append([action, rest]) You want to add a comment here so that future reader understand what is going on. > + else: > + ha = rest.strip().split(' ', 1)[0] > + try: > + ha = str(repo[ha]) # ensure its a short hash > + except error.RepoError: > + raise util.Abort(_('unknown changeset %s listed') % ha) > + if ha not in expected: > + raise util.Abort( > + _('may not use changesets other than the ones listed')) > + if ha in seen: > + raise util.Abort(_('duplicated command for changeset %s') % ha) > + seen.add(ha) > + if action not in actiontable: > + raise util.Abort(_('unknown action "%s"') % action) > + parsed.append([action, ha]) > missing = sorted(expected - seen) # sort to stabilize output > if missing: > raise util.Abort(_('missing rules for changeset %s') % missing[0], > diff --git a/tests/test-histedit-exec.t b/tests/test-histedit-exec.t > new file mode 100644 > --- /dev/null > +++ b/tests/test-histedit-exec.t > @@ -0,0 +1,191 @@ > + $ . "$TESTDIR/histedit-helpers.sh" > + > + $ cat >> $HGRCPATH <<EOF > + > [extensions] > + > histedit= > + > EOF > + > + $ initrepo () > + > { > + > hg init r > + > cd r > + > for x in a b c d e f ; do > + > echo $x > $x > + > hg add $x > + > hg ci -m $x > + > done > + > } > + > + $ initrepo > + > +log before edit > + > + $ hg log --graph > + @ changeset: 5:652413bf663e > + | tag: tip > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: f > + | > + o changeset: 4:e860deea161a > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: e > + | > + o changeset: 3:055a42cdd887 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: d > + | > + o changeset: 2:177f92b77385 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: c > + | > + o changeset: 1:d2ae7f538514 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: b > + | > + o changeset: 0:cb9a9f314b8b > + user: test > + date: Thu Jan 01 00:00:00 1970 +0000 > + summary: a > + > + > +exec & continue should preserve hashes > + > + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > + > pick 177f92b77385 c > + > pick 055a42cdd887 d > + > pick e860deea161a e > + > exec echo "this should be printed to stdout" > + > exec echo "this should be printed to stderr" >&2 > + > pick 652413bf663e f > + > EOF > + this should be printed to stdout > + this should be printed to stderr > + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved > + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved > + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved > + > + $ hg log --graph > + @ changeset: 5:652413bf663e > + | tag: tip > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: f > + | > + o changeset: 4:e860deea161a > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: e > + | > + o changeset: 3:055a42cdd887 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: d > + | > + o changeset: 2:177f92b77385 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: c > + | > + o changeset: 1:d2ae7f538514 > + | user: test > + | date: Thu Jan 01 00:00:00 1970 +0000 > + | summary: b > + | > + o changeset: 0:cb9a9f314b8b > + user: test > + date: Thu Jan 01 00:00:00 1970 +0000 > + summary: a > + > +ensure we are properly executed in a shell > + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > + > pick 177f92b77385 c > + > pick 055a42cdd887 d > + > pick e860deea161a e > + > exec echo "foo" >/dev/null && exit 0 > + > pick 652413bf663e f > + > EOF > + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved > + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved I can we get a test testing that something actually happend during exec (before redirecting this something to /dev/null) > +a failing command should drop us into the shell > + > + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > + > pick 177f92b77385 c > + > pick 055a42cdd887 d > + > pick e860deea161a e > + > exec exit 1 > + > pick 652413bf663e f > + > EOF > + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved > + Command 'exit 1' failed with exit status 1. > + > +continue should work > + > + $ hg histedit --continue > + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved > + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved > + > + $ hg log --template '{node|short} {desc}' --graph > + @ 652413bf663e f > + | > + o e860deea161a e > + | > + o 055a42cdd887 d > + | > + o 177f92b77385 c > + | > + o d2ae7f538514 b > + | > + o cb9a9f314b8b a > + > + > +abort should work > + > + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > + > pick 177f92b77385 c > + > pick 055a42cdd887 d > + > pick e860deea161a e > + > exec exit 1 > + > pick 652413bf663e f > + > EOF > + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved > + Command 'exit 1' failed with exit status 1. > + > + $ hg histedit --abort > + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved > + > + $ hg log --template '{node|short} {desc}' --graph > + @ 652413bf663e f > + | > + o e860deea161a e > + | > + o 055a42cdd887 d > + | > + o 177f92b77385 c > + | > + o d2ae7f538514 b > + | > + o cb9a9f314b8b a > + > + > +abort on a failing command, e.g when we have children > + > + > + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle > + > pick 177f92b77385 c > + > pick 055a42cdd887 d > + > pick e860deea161a e > + > exec echo 'added' > added && hg addremove && hg commit --amend > + > pick 652413bf663e f > + > EOF > + abort: cannot amend changeset with children > + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved > + > + $ hg id -r . -i > + e860deea161a Can we get a test for: 1. rewriting history 2. appending history 3. leaving uncommited change (from clean exec run and from --continue) 4. some combination of the above ?
Patch
diff --git a/hgext/histedit.py b/hgext/histedit.py --- a/hgext/histedit.py +++ b/hgext/histedit.py @@ -429,7 +429,11 @@ raise error.InterventionRequired( _('Working copy dirty, please check the files listed above.\n' 'When you are finished, run hg histedit --continue to resume.')) - return ctx, [] + + newctx = repo['.'] + if ctx.node() != newctx.node(): + return newctx, [(ctx.node(), (newctx.node(),))] + return newctx, [] def message(ui, repo, ctx, ha, opts): oldctx = repo[ha] @@ -486,6 +490,8 @@ 'drop': drop, 'm': message, 'mess': message, + 'x': execute, + 'exec': execute, } @command('histedit', @@ -707,7 +713,14 @@ def bootstrapcontinue(ui, repo, parentctx, rules, opts): action, currentnode = rules.pop(0) - ctx = repo[currentnode] + if action in ['x', 'exec']: + action, currentnode = rules.pop(0) + # ensure we jump to the next node after an exec + if action not in ['x', 'exec']: + ctx = repo[currentnode] + hg.update(repo, ctx.node()) + else: + ctx = repo[currentnode] newchildren = gatherchildren(repo, parentctx) @@ -825,20 +838,23 @@ if ' ' not in r: raise util.Abort(_('malformed line "%s"') % r) action, rest = r.split(' ', 1) - ha = rest.strip().split(' ', 1)[0] - try: - ha = str(repo[ha]) # ensure its a short hash - except error.RepoError: - raise util.Abort(_('unknown changeset %s listed') % ha) - if ha not in expected: - raise util.Abort( - _('may not use changesets other than the ones listed')) - if ha in seen: - raise util.Abort(_('duplicated command for changeset %s') % ha) - seen.add(ha) - if action not in actiontable: - raise util.Abort(_('unknown action "%s"') % action) - parsed.append([action, ha]) + if action in ['x', 'exec']: + parsed.append([action, rest]) + else: + ha = rest.strip().split(' ', 1)[0] + try: + ha = str(repo[ha]) # ensure its a short hash + except error.RepoError: + raise util.Abort(_('unknown changeset %s listed') % ha) + if ha not in expected: + raise util.Abort( + _('may not use changesets other than the ones listed')) + if ha in seen: + raise util.Abort(_('duplicated command for changeset %s') % ha) + seen.add(ha) + if action not in actiontable: + raise util.Abort(_('unknown action "%s"') % action) + parsed.append([action, ha]) missing = sorted(expected - seen) # sort to stabilize output if missing: raise util.Abort(_('missing rules for changeset %s') % missing[0], diff --git a/tests/test-histedit-exec.t b/tests/test-histedit-exec.t new file mode 100644 --- /dev/null +++ b/tests/test-histedit-exec.t @@ -0,0 +1,191 @@ + $ . "$TESTDIR/histedit-helpers.sh" + + $ cat >> $HGRCPATH <<EOF + > [extensions] + > histedit= + > EOF + + $ initrepo () + > { + > hg init r + > cd r + > for x in a b c d e f ; do + > echo $x > $x + > hg add $x + > hg ci -m $x + > done + > } + + $ initrepo + +log before edit + + $ hg log --graph + @ changeset: 5:652413bf663e + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: f + | + o changeset: 4:e860deea161a + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: e + | + o changeset: 3:055a42cdd887 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: d + | + o changeset: 2:177f92b77385 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c + | + o changeset: 1:d2ae7f538514 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: b + | + o changeset: 0:cb9a9f314b8b + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + + +exec & continue should preserve hashes + + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle + > pick 177f92b77385 c + > pick 055a42cdd887 d + > pick e860deea161a e + > exec echo "this should be printed to stdout" + > exec echo "this should be printed to stderr" >&2 + > pick 652413bf663e f + > EOF + this should be printed to stdout + this should be printed to stderr + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg log --graph + @ changeset: 5:652413bf663e + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: f + | + o changeset: 4:e860deea161a + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: e + | + o changeset: 3:055a42cdd887 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: d + | + o changeset: 2:177f92b77385 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c + | + o changeset: 1:d2ae7f538514 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: b + | + o changeset: 0:cb9a9f314b8b + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: a + +ensure we are properly executed in a shell + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle + > pick 177f92b77385 c + > pick 055a42cdd887 d + > pick e860deea161a e + > exec echo "foo" >/dev/null && exit 0 + > pick 652413bf663e f + > EOF + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +a failing command should drop us into the shell + + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle + > pick 177f92b77385 c + > pick 055a42cdd887 d + > pick e860deea161a e + > exec exit 1 + > pick 652413bf663e f + > EOF + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + Command 'exit 1' failed with exit status 1. + +continue should work + + $ hg histedit --continue + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg log --template '{node|short} {desc}' --graph + @ 652413bf663e f + | + o e860deea161a e + | + o 055a42cdd887 d + | + o 177f92b77385 c + | + o d2ae7f538514 b + | + o cb9a9f314b8b a + + +abort should work + + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle + > pick 177f92b77385 c + > pick 055a42cdd887 d + > pick e860deea161a e + > exec exit 1 + > pick 652413bf663e f + > EOF + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + Command 'exit 1' failed with exit status 1. + + $ hg histedit --abort + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg log --template '{node|short} {desc}' --graph + @ 652413bf663e f + | + o e860deea161a e + | + o 055a42cdd887 d + | + o 177f92b77385 c + | + o d2ae7f538514 b + | + o cb9a9f314b8b a + + +abort on a failing command, e.g when we have children + + + $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle + > pick 177f92b77385 c + > pick 055a42cdd887 d + > pick e860deea161a e + > exec echo 'added' > added && hg addremove && hg commit --amend + > pick 652413bf663e f + > EOF + abort: cannot amend changeset with children + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg id -r . -i + e860deea161a +