martinvonz created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches.
REVISION SUMMARY This patch adds a config option to make it an error to push the parent of the working copy when the working copy is dirty. We have had this feature enabled by default internally for a few years. I think most users have found it helpful. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D11680 AFFECTED FILES mercurial/cmdutil.py mercurial/commands.py mercurial/configitems.py tests/test-completion.t tests/test-push.t CHANGE DETAILS diff --git a/tests/test-push.t b/tests/test-push.t --- a/tests/test-push.t +++ b/tests/test-push.t @@ -400,3 +400,73 @@ searching for changes no changes found [1] + + +Test `push.on-dirty-working-copy` +--------------------------------- + + $ cat >> $HGRCPATH << EOF + > [extensions] + > drawdag=$TESTDIR/drawdag.py + > EOF + $ cd $TESTTMP + $ mkdir dirty-working-copy + $ cd dirty-working-copy + $ hg init source + $ cat >> source/.hg/hgrc << EOF + > [phases] + > publish=false + > EOF + $ hg clone source dest + updating to branch default + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd dest + $ hg debugdrawdag << 'EOF' + > D + > | + > F C + > | | + > E B + > |/ + > A + > EOF + $ cat >> .hg/hgrc << EOF + > [push] + > on-dirty-working-copy=abort + > EOF +# Push all commits just to make the output from further pushes consistently +# "no changes found". + $ hg push -q -r 'head()' + $ hg co C + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo modified >> A +# Cannot push the parent commit with a dirty working copy + $ hg push -q -r . + abort: won't push with dirty working directory + (maybe you meant to commit or amend the changes; if you want to push + anyway, use --allow-dirty, or set on-dirty-working-copy=ignore in + the [push] section of your ~/.hgrc) + [20] +# Cannot push a descendant either + $ hg push -q -r D + abort: won't push with dirty working directory + (maybe you meant to commit or amend the changes; if you want to push + anyway, use --allow-dirty, or set on-dirty-working-copy=ignore in + the [push] section of your ~/.hgrc) + [20] +# Typo in config value results in default behavior (which is to allow push) + $ hg push --config push.on-dirty-working-copy=abirt -q -r . + [1] +# Can override config + $ hg push -q -r . --allow-dirty + [1] +# Can push an ancestor + $ hg push -q -r B + [1] +# Can push a sibling + $ hg push -q -r F + [1] +# Can push descendant if the working copy parent is public + $ hg phase -p + $ hg push -q -r D + [1] diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -362,7 +362,7 @@ phase: public, draft, secret, force, rev pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude - push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure + push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, allow-dirty, ssh, remotecmd, insecure recover: verify remove: after, force, subrepos, include, exclude, dry-run rename: forget, after, at-rev, force, include, exclude, dry-run diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1869,6 +1869,12 @@ default=False, ) coreconfigitem( + b'push', + b'on-dirty-working-copy', + default=b"ignore", + experimental=True, +) +coreconfigitem( b'rewrite', b'backup-bundle', default=True, diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5633,6 +5633,15 @@ False, _(b'push the changeset as public (EXPERIMENTAL)'), ), + ( + b'', + b'allow-dirty', + False, + _( + b'allow pushing with a dirty working copy, overriding ' + b'push.on-dirty-working-copy=abort (EXPERIMENTAL)' + ), + ), ] + remoteopts, _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'), @@ -5735,8 +5744,10 @@ try: if revs: - revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)] - if not revs: + nodes = [ + repo[r].node() for r in logcmdutil.revrange(repo, revs) + ] + if not nodes: raise error.InputError( _(b"specified revisions evaluate to an empty set"), hint=_(b"use different revision arguments"), @@ -5746,8 +5757,8 @@ # to DAG heads to make discovery simpler. expr = revsetlang.formatspec(b'heads(%r)', path.pushrev) revs = scmutil.revrange(repo, [expr]) - revs = [repo[rev].node() for rev in revs] - if not revs: + nodes = [repo[rev].node() for rev in revs] + if not nodes: raise error.InputError( _( b'default push revset for path evaluates to an empty set' @@ -5758,6 +5769,10 @@ _(b'no revisions specified to push'), hint=_(b'did you mean "hg push -r ."?'), ) + else: + nodes = None + if nodes and not opts.get(b'allow_dirty'): + cmdutil.check_push_dirty_wc(repo, nodes) repo._subtoppath = dest try: @@ -5780,7 +5795,7 @@ repo, other, opts.get(b'force'), - revs=revs, + revs=nodes, newbranch=opts.get(b'new_branch'), bookmarks=opts.get(b'bookmark', ()), publish=opts.get(b'publish'), diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1112,6 +1112,26 @@ ctx.sub(s).bailifchanged(hint=hint) +def check_push_dirty_wc(repo, nodes): + """Checks that `.` is not being pushed if the working copy is dirty.""" + if repo.ui.config(b'push', b'on-dirty-working-copy') == b'abort': + # We assume that commits back to the public ancestors will be pushed. + if repo.revs('only(%ln, public()) & parents()', nodes): + # Covers both pending working directory state and merges. + try: + bailifchanged(repo) + except error.Abort: + hint = ( + b'maybe you meant to commit or amend the changes; if ' + b'you want to push\nanyway, use --allow-dirty, or set ' + b'on-dirty-working-copy=ignore in\nthe [push] section ' + b'of your ~/.hgrc' + ) + raise error.StateError( + b"won't push with dirty working directory", hint=_(hint) + ) + + def logmessage(ui, opts): """get the log message according to -m and -l option""" To: martinvonz, #hg-reviewers Cc: mercurial-patches, mercurial-devel _______________________________________________ Mercurial-devel mailing list [email protected] https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
