diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -26,6 +26,7 @@ bundle2, changegroup, cmdutil, + context, copies, debugcommands as debugcommandsmod, destutil, @@ -1468,6 +1469,55 @@ return r is None +@command('close-branch', commitopts + commitopts2, + _('[OPTION]... [REV]...'), inferrepo=True) +def close_branch(ui, repo, *revs, **opts): + """close the given head revisions + + This is equivalent to checking out each revision in a clean tree and running + ``hg commit --close-branch``, except that it doesn't change the working + directory. + + The commit message must be specified with -l or -m. + """ + def docommit(rev): + cctx = context.memctx(repo, parents=[rev, None], text=message, + files=[], filectxfn=None, user=opts.get('user'), + date=opts.get('date'), extra=extra) + tr = repo.transaction('commit') + ret = repo.commitctx(cctx, True) + bookmarks.update(repo, [rev, None], ret) + cctx.markcommitted(ret) + tr.close() + + if not revs: + raise error.Abort(_('no revisions specified')) + + revs = scmutil.revrange(repo, revs) + + heads = [] + for branch in repo.branchmap(): + heads.extend(repo.branchheads(branch)) + heads = set(repo[h].rev() for h in heads) + for rev in revs: + if rev not in heads: + raise error.Abort(_('revision is not an open head: %s') % rev) + + message = cmdutil.logmessage(ui, opts) + if not message: + raise error.Abort(_("No commit message specified with -l or -m")) + extra = { 'close': '1' } + + wlock = lock = None + try: + wlock = repo.wlock() + lock = repo.lock() + for rev in revs: + docommit(rev) + finally: + release(lock, wlock) + return 0 + @command('^commit|ci', [('A', 'addremove', None, _('mark new/missing files as added/removed before committing')), diff --git a/tests/test-close-branch.t b/tests/test-close-branch.t new file mode 100644 --- /dev/null +++ b/tests/test-close-branch.t @@ -0,0 +1,41 @@ + $ hg init + $ hg debugbuilddag '+2*2*3*4' + $ hg log -G --template '{rev}:{node|short}' + o 4:e7bd5218ca15 + | + | o 3:6100d3090acf + |/ + | o 2:fa942426a6fd + |/ + | o 1:66f7d451a68b + |/ + o 0:1ea73414a91b + + $ hg close-branch -m 'Close old heads' 1 2 + $ hg heads + changeset: 4:e7bd5218ca15 + parent: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:04 1970 +0000 + summary: r4 + + changeset: 3:6100d3090acf + parent: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:03 1970 +0000 + summary: r3 + + $ hg close-branch -m 'Close more old heads' 4 + $ hg heads + changeset: 3:6100d3090acf + parent: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:03 1970 +0000 + summary: r3 + + $ hg close-branch -m 'Not a head' 0 + abort: revision is not an open head: 0 + [255] + $ hg close-branch -m 'Already closed head' 1 + abort: revision is not an open head: 1 + [255] diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -12,6 +12,7 @@ bundle cat clone + close-branch commit config copy @@ -252,6 +253,7 @@ branches: active, closed, template bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure cat: output, rev, decode, include, exclude, template + close-branch: message, logfile, date, user config: untrusted, edit, local, global, template copy: after, force, include, exclude, dry-run debugancestor: diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t --- a/tests/test-globalopts.t +++ b/tests/test-globalopts.t @@ -308,6 +308,7 @@ bundle create a bundle file cat output the current or given revision of files clone make a copy of an existing repository + close-branch close the given head revisions commit commit the specified files or all outstanding changes config show combined config settings from all hgrc files copy mark files as copied for the next commit @@ -391,6 +392,7 @@ bundle create a bundle file cat output the current or given revision of files clone make a copy of an existing repository + close-branch close the given head revisions commit commit the specified files or all outstanding changes config show combined config settings from all hgrc files copy mark files as copied for the next commit diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -65,6 +65,7 @@ bundle create a bundle file cat output the current or given revision of files clone make a copy of an existing repository + close-branch close the given head revisions commit commit the specified files or all outstanding changes config show combined config settings from all hgrc files copy mark files as copied for the next commit @@ -144,6 +145,7 @@ bundle create a bundle file cat output the current or given revision of files clone make a copy of an existing repository + close-branch close the given head revisions commit commit the specified files or all outstanding changes config show combined config settings from all hgrc files copy mark files as copied for the next commit @@ -840,6 +842,7 @@ bundle create a bundle file cat output the current or given revision of files clone make a copy of an existing repository + close-branch close the given head revisions commit commit the specified files or all outstanding changes config show combined config settings from all hgrc files copy mark files as copied for the next commit @@ -2356,6 +2359,13 @@ output the current or given revision of files + + close-branch + + + close the given head revisions + + config diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t --- a/tests/test-hgweb-json.t +++ b/tests/test-hgweb-json.t @@ -1800,6 +1800,10 @@ "topic": "cat" }, { + "summary": "close the given head revisions", + "topic": "close-branch" + }, + { "summary": "show combined config settings from all hgrc files", "topic": "config" },