purge: move extension into core mercurial
The motivation is simple: it's nicer to avoid gating basic
functionality.
To reduce the risk of people shooting themselves in the feet, `--confirm` is now
the default, unless the extensions is loaded..
For review of the body of the purge command, use this instead of what
hg/phabricator will show (the block of code is modified, not just
moved):
Differential Revision: https://phab.mercurial-scm.org/D9820
--- a/hgext/largefiles/overrides.py Mon Jan 18 10:24:11 2021 +0100
+++ b/hgext/largefiles/overrides.py Mon Jan 18 10:24:20 2021 +0100
@@ -1567,7 +1567,7 @@
# Calling purge with --all will cause the largefiles to be deleted.
# Override repo.status to prevent this from happening.
-@eh.wrapcommand(b'purge', extension=b'purge')
+@eh.wrapcommand(b'purge')
def overridepurge(orig, ui, repo, *dirs, **opts):
# XXX Monkey patching a repoview will not work. The assigned attribute will
# be set on the unfiltered repo, but we will only lookup attributes in the
--- a/hgext/purge.py Mon Jan 18 10:24:11 2021 +0100
+++ b/hgext/purge.py Mon Jan 18 10:24:20 2021 +0100
@@ -22,118 +22,11 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
-'''command to delete untracked files from the working directory'''
-from __future__ import absolute_import
-
-from mercurial.i18n import _
-from mercurial import (
- cmdutil,
- merge as mergemod,
- pycompat,
- registrar,
- scmutil,
-)
-
-cmdtable = {}
-command = registrar.command(cmdtable)
-# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
-# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
-# be specifying the version(s) of Mercurial they are tested with, or
-# leave the attribute unspecified.
-testedwith = b'ships-with-hg-core'
-
-
-@command(
- b'purge|clean',
- [
- (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
- (b'', b'all', None, _(b'purge ignored files too')),
- (b'i', b'ignored', None, _(b'purge only ignored files')),
- (b'', b'dirs', None, _(b'purge empty directories')),
- (b'', b'files', None, _(b'purge files')),
- (b'p', b'print', None, _(b'print filenames instead of deleting them')),
- (
- b'0',
- b'print0',
- None,
- _(
- b'end filenames with NUL, for use with xargs'
- b' (implies -p/--print)'
- ),
- ),
- (b'', b'confirm', None, _(b'ask before permanently deleting files')),
- ]
- + cmdutil.walkopts,
- _(b'hg purge [OPTION]... [DIR]...'),
- helpcategory=command.CATEGORY_WORKING_DIRECTORY,
-)
-def purge(ui, repo, *dirs, **opts):
- """removes files not tracked by Mercurial
-
- Delete files not known to Mercurial. This is useful to test local
- and uncommitted changes in an otherwise-clean source tree.
-
- This means that purge will delete the following by default:
-
- - Unknown files: files marked with "?" by :hg:`status`
- - Empty directories: in fact Mercurial ignores directories unless
- they contain files under source control management
+'''command to delete untracked files from the working directory (DEPRECATED)
- But it will leave untouched:
-
- - Modified and unmodified tracked files
- - Ignored files (unless -i or --all is specified)
- - New files added to the repository (with :hg:`add`)
-
- The --files and --dirs options can be used to direct purge to delete
- only files, only directories, or both. If neither option is given,
- both will be deleted.
-
- If directories are given on the command line, only files in these
- directories are considered.
-
- Be careful with purge, as you could irreversibly delete some files
- you forgot to add to the repository. If you only want to print the
- list of files that this program would delete, use the --print
- option.
- """
- opts = pycompat.byteskwargs(opts)
- cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
+The functionality of this extension has been included in core Mercurial since
+version 5.7. Please use :hg:`purge ...` instead. :hg:`purge --confirm` is now the default, unless the extension is enabled for backward compatibility.
+'''
- act = not opts.get(b'print')
- eol = b'\n'
- if opts.get(b'print0'):
- eol = b'\0'
- act = False # --print0 implies --print
- if opts.get(b'all', False):
- ignored = True
- unknown = True
- else:
- ignored = opts.get(b'ignored', False)
- unknown = not ignored
-
- removefiles = opts.get(b'files')
- removedirs = opts.get(b'dirs')
- confirm = opts.get(b'confirm')
-
- if not removefiles and not removedirs:
- removefiles = True
- removedirs = True
-
- match = scmutil.match(repo[None], dirs, opts)
-
- paths = mergemod.purge(
- repo,
- match,
- unknown=unknown,
- ignored=ignored,
- removeemptydirs=removedirs,
- removefiles=removefiles,
- abortonerror=opts.get(b'abort_on_err'),
- noop=not act,
- confirm=confirm,
- )
-
- for path in paths:
- if not act:
- ui.write(b'%s%s' % (path, eol))
+# This empty extension looks pointless, but core mercurial checks if it's loaded
+# to implement the slightly different behavior documented above.
--- a/mercurial/commands.py Mon Jan 18 10:24:11 2021 +0100
+++ b/mercurial/commands.py Mon Jan 18 10:24:20 2021 +0100
@@ -5447,6 +5447,108 @@
@command(
+ b'purge|clean',
+ [
+ (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
+ (b'', b'all', None, _(b'purge ignored files too')),
+ (b'i', b'ignored', None, _(b'purge only ignored files')),
+ (b'', b'dirs', None, _(b'purge empty directories')),
+ (b'', b'files', None, _(b'purge files')),
+ (b'p', b'print', None, _(b'print filenames instead of deleting them')),
+ (
+ b'0',
+ b'print0',
+ None,
+ _(
+ b'end filenames with NUL, for use with xargs'
+ b' (implies -p/--print)'
+ ),
+ ),
+ (b'', b'confirm', None, _(b'ask before permanently deleting files')),
+ ]
+ + cmdutil.walkopts,
+ _(b'hg purge [OPTION]... [DIR]...'),
+ helpcategory=command.CATEGORY_WORKING_DIRECTORY,
+)
+def purge(ui, repo, *dirs, **opts):
+ """removes files not tracked by Mercurial
+
+ Delete files not known to Mercurial. This is useful to test local
+ and uncommitted changes in an otherwise-clean source tree.
+
+ This means that purge will delete the following by default:
+
+ - Unknown files: files marked with "?" by :hg:`status`
+ - Empty directories: in fact Mercurial ignores directories unless
+ they contain files under source control management
+
+ But it will leave untouched:
+
+ - Modified and unmodified tracked files
+ - Ignored files (unless -i or --all is specified)
+ - New files added to the repository (with :hg:`add`)
+
+ The --files and --dirs options can be used to direct purge to delete
+ only files, only directories, or both. If neither option is given,
+ both will be deleted.
+
+ If directories are given on the command line, only files in these
+ directories are considered.
+
+ Be careful with purge, as you could irreversibly delete some files
+ you forgot to add to the repository. If you only want to print the
+ list of files that this program would delete, use the --print
+ option.
+ """
+ opts = pycompat.byteskwargs(opts)
+ cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
+
+ act = not opts.get(b'print')
+ eol = b'\n'
+ if opts.get(b'print0'):
+ eol = b'\0'
+ act = False # --print0 implies --print
+ if opts.get(b'all', False):
+ ignored = True
+ unknown = True
+ else:
+ ignored = opts.get(b'ignored', False)
+ unknown = not ignored
+
+ removefiles = opts.get(b'files')
+ removedirs = opts.get(b'dirs')
+ confirm = opts.get(b'confirm')
+ if confirm is None:
+ try:
+ extensions.find(b'purge')
+ confirm = False
+ except KeyError:
+ confirm = True
+
+ if not removefiles and not removedirs:
+ removefiles = True
+ removedirs = True
+
+ match = scmutil.match(repo[None], dirs, opts)
+
+ paths = mergemod.purge(
+ repo,
+ match,
+ unknown=unknown,
+ ignored=ignored,
+ removeemptydirs=removedirs,
+ removefiles=removefiles,
+ abortonerror=opts.get(b'abort_on_err'),
+ noop=not act,
+ confirm=confirm,
+ )
+
+ for path in paths:
+ if not act:
+ ui.write(b'%s%s' % (path, eol))
+
+
+@command(
b'push',
[
(b'f', b'force', None, _(b'force push')),
--- a/relnotes/next Mon Jan 18 10:24:11 2021 +0100
+++ b/relnotes/next Mon Jan 18 10:24:20 2021 +0100
@@ -17,6 +17,8 @@
can be e.g. `rebase`. As part of this effort, the default format
from `hg rebase` was reorganized a bit.
+ * `hg purge` is now a core command using `--confirm` by default.
+
* `hg strip`, from the strip extension, is now a core command, `hg
debugstrip`. The extension remains for compatibility.
--- a/tests/test-completion.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-completion.t Mon Jan 18 10:24:20 2021 +0100
@@ -38,6 +38,7 @@
paths
phase
pull
+ purge
push
recover
remove
@@ -354,6 +355,7 @@
paths: template
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
recover: verify
remove: after, force, subrepos, include, exclude, dry-run
--- a/tests/test-globalopts.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-globalopts.t Mon Jan 18 10:24:20 2021 +0100
@@ -351,6 +351,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
@@ -483,6 +484,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
--- a/tests/test-help-hide.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-help-hide.t Mon Jan 18 10:24:20 2021 +0100
@@ -55,6 +55,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
@@ -191,6 +192,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
--- a/tests/test-help.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-help.t Mon Jan 18 10:24:20 2021 +0100
@@ -107,6 +107,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
@@ -235,6 +236,7 @@
addremove add all new files, delete all missing files
files list tracked files
forget forget the specified files on the next commit
+ purge removes files not tracked by Mercurial
remove remove the specified files on the next commit
rename rename files; equivalent of copy + remove
resolve redo merges or set/view the merge status of files
@@ -375,8 +377,6 @@
mq manage a stack of patches
notify hooks for sending email push notifications
patchbomb command to send changesets as (a series of) patch emails
- purge command to delete untracked files from the working
- directory
relink recreates hardlinks between repository clones
schemes extend schemes with shortcuts to repository swarms
share share a common history between several working directories
@@ -2720,6 +2720,13 @@
set or show the current phase name
</td></tr>
<tr><td>
+ <a href="/help/purge">
+ purge
+ </a>
+ </td><td>
+ removes files not tracked by Mercurial
+ </td></tr>
+ <tr><td>
<a href="/help/recover">
recover
</a>
--- a/tests/test-hgweb-json.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-hgweb-json.t Mon Jan 18 10:24:20 2021 +0100
@@ -2190,6 +2190,10 @@
"topic": "phase"
},
{
+ "summary": "removes files not tracked by Mercurial",
+ "topic": "purge"
+ },
+ {
"summary": "roll back an interrupted transaction",
"topic": "recover"
},
--- a/tests/test-purge.t Mon Jan 18 10:24:11 2021 +0100
+++ b/tests/test-purge.t Mon Jan 18 10:24:20 2021 +0100
@@ -1,8 +1,3 @@
- $ cat <<EOF >> $HGRCPATH
- > [extensions]
- > purge =
- > EOF
-
init
$ hg init t
@@ -18,6 +13,26 @@
$ echo 'ignored' > .hgignore
$ hg ci -qAmr3 -d'2 0'
+purge without the extension
+
+ $ hg st
+ $ touch foo
+ $ hg purge
+ permanently delete 1 unkown files? (yN) n
+ abort: removal cancelled
+ [250]
+ $ hg st
+ ? foo
+ $ hg purge --no-confirm
+ $ hg st
+
+now enabling the extension
+
+ $ cat <<EOF >> $HGRCPATH
+ > [extensions]
+ > purge =
+ > EOF
+
delete an empty directory
$ mkdir empty_dir