Patchwork D9820: purge: move extension into core mercurial

login
register
mail settings
Submitter phabricator
Date Jan. 18, 2021, 9:28 a.m.
Message ID <differential-rev-PHID-DREV-teorrrmn3xv53tkph334-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48131/
State Superseded
Headers show

Comments

phabricator - Jan. 18, 2021, 9:28 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  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):

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9820

AFFECTED FILES
  hgext/largefiles/overrides.py
  hgext/purge.py
  mercurial/commands.py
  relnotes/next
  tests/test-completion.t
  tests/test-globalopts.t
  tests/test-help-hide.t
  tests/test-help.t
  tests/test-hgweb-json.t
  tests/test-purge.t

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

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 <<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
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-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
@@ -2718,6 +2718,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>
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-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-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
@@ -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
diff --git a/relnotes/next b/relnotes/next
--- a/relnotes/next
+++ b/relnotes/next
@@ -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.
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -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')),
diff --git a/hgext/purge.py b/hgext/purge.py
--- a/hgext/purge.py
+++ b/hgext/purge.py
@@ -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.
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -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