diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1552,7 +1552,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
diff --git a/hgext/purge.py b/hgext/purge.py
--- a/hgext/purge.py
+++ b/hgext/purge.py
@@ -22,115 +22,14 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
-'''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)'
- ),
- ),
- ]
- + 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. However it is not exactly
+equivalent: without the extension, one of -i, -u or --all must be specified.
+With the extension, -u is assumed if none of these flags are specified.
- 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')
+'''
- 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,
- )
-
- 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.
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -5382,6 +5382,112 @@
other.close()
return ret
+@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'u', b'unknown', None, _(b'purge only unknown 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)'
+ ),
+ ),
+ ]
+ + 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.
+
+ purge can delete:
+
+ - Unknown files: files marked with "?" by :hg:`status`
+ - Ignored files
+ - Empty directories: in fact Mercurial ignores directories unless
+ they contain files under source control management
+
+ Unknown files are selected with -u, ignored files with -i, and
+ both with --all. At least one such flag must be provided. Empty
+ directories are deleted by default.
+
+ But it will leave untouched:
+
+ - Modified and unmodified tracked files
+ - 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')
+ cmdutil.check_at_most_one_arg(opts, b'all', b'unknown')
+
+ 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 = opts.get(b'unknown', False)
+ if not unknown and not ignored:
+ # If the extension is loaded, we clean unknown files for compatibility.
+ # If it is not loaded, we refuse to work to reduce the risk of mistakes.
+ try:
+ extensions.find(b'purge')
+ unknown = True
+ except KeyError:
+ raise error.Abort(_(b"please specify what to purge with -i, -u or --all"))
+
+ removefiles = opts.get(b'files')
+ removedirs = opts.get(b'dirs')
+
+ 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,
+ )
+
+ for path in paths:
+ if not act:
+ ui.write(b'%s%s' % (path, eol))
+
@command(
b'push',
diff --git a/relnotes/next b/relnotes/next
--- a/relnotes/next
+++ b/relnotes/next
@@ -4,6 +4,9 @@
* The memory footprint per changeset and per file during pull/unbundle
operations has been significantly reduced.
+ * `hg purge` is now a core command. See `hg help -e purge` for how it
+ compares to the behavior of `hg purge` when the purge extension is
+ loaded.
== New Experimental Features ==
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -38,6 +38,7 @@
paths
phase
pull
+ purge
push
recover
remove
@@ -352,6 +353,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, unknown, dirs, files, print, print0, 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
diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t
--- a/tests/test-globalopts.t
+++ b/tests/test-globalopts.t
@@ -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
diff --git a/tests/test-help-hide.t b/tests/test-help-hide.t
--- a/tests/test-help-hide.t
+++ b/tests/test-help-hide.t
@@ -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
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -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
@@ -2703,6 +2703,13 @@
set or show the current phase name
+
+ purge
+
+ |
+ removes files not tracked by Mercurial
+ |
+
recover
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
@@ -2190,6 +2190,10 @@
"topic": "phase"
},
{
+ "summary": "removes files not tracked by Mercurial",
+ "topic": "purge"
+ },
+ {
"summary": "roll back an interrupted transaction",
"topic": "recover"
},
diff --git a/tests/test-purge.t b/tests/test-purge.t
--- a/tests/test-purge.t
+++ b/tests/test-purge.t
@@ -1,8 +1,3 @@
- $ cat <> $HGRCPATH
- > [extensions]
- > purge =
- > EOF
-
init
$ hg init t
@@ -18,6 +13,25 @@
$ echo 'ignored' > .hgignore
$ hg ci -qAmr3 -d'2 0'
+purge without the extension
+
+ $ hg st
+ $ touch foo
+ $ hg purge
+ abort: please specify what to purge with -i, -u or --all
+ [255]
+ $ hg st
+ ? foo
+ $ hg purge -u
+ $ hg st
+
+now enabling the extension
+
+ $ cat <> $HGRCPATH
+ > [extensions]
+ > purge =
+ > EOF
+
delete an empty directory
$ mkdir empty_dir
|