Patchwork purge: add options for deleting only files or only directories

login
register
mail settings
Submitter Ben Kehoe
Date July 10, 2014, 10:20 p.m.
Message ID <359c67cbc748a6e3c68f.1405030836@surgical5>
Download mbox | patch
Permalink /patch/5140/
State Accepted
Commit 8127b9e798b1ef79fe22cca671261cacbb36e72d
Headers show

Comments

Ben Kehoe - July 10, 2014, 10:20 p.m.
# HG changeset patch
# User Ben Kehoe <benk@berkeley.edu>
# Date 1383873854 28800
#      Thu Nov 07 17:24:14 2013 -0800
# Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
# Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
purge: add options for deleting only files or only directories
Ben Kehoe - July 10, 2014, 10:23 p.m.
On Thu, Jul 10, 2014 at 3:20 PM, Ben Kehoe <benk@berkeley.edu> wrote:

> # HG changeset patch
> # User Ben Kehoe <benk@berkeley.edu>
> # Date 1383873854 28800
> #      Thu Nov 07 17:24:14 2013 -0800
> # Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
> # Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
> purge: add options for deleting only files or only directories
>
> diff -r 3b97a93dc137 -r 359c67cbc748 hgext/purge.py
> --- a/hgext/purge.py    Wed Jul 09 12:30:12 2014 -0500
> +++ b/hgext/purge.py    Thu Nov 07 17:24:14 2013 -0800
> @@ -35,6 +35,8 @@
>  @command('purge|clean',
>      [('a', 'abort-on-err', None, _('abort if an error occurs')),
>      ('',  'all', None, _('purge ignored files too')),
> +    ('',  'dirs', None, _('purge empty directories')),
> +    ('',  'files', None, _('purge files')),
>      ('p', 'print', None, _('print filenames instead of deleting them')),
>      ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
>                              ' (implies -p/--print)')),
> @@ -46,7 +48,7 @@
>      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:
> +    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
> @@ -58,6 +60,10 @@
>      - Ignored files (unless --all is specified)
>      - New files added to the repository (with :hg:`add`)
>
> +    The --files and --dirs options can be use 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.
>
> @@ -71,6 +77,11 @@
>      if opts['print0']:
>          eol = '\0'
>          act = False # --print0 implies --print
> +    removefiles = opts['files']
> +    removedirs = opts['dirs']
> +    if not removefiles and not removedirs:
> +        removefiles = True
> +        removedirs = True
>
>      def remove(remove_func, name):
>          if act:
> @@ -100,13 +111,15 @@
>      match.explicitdir = match.traversedir = directories.append
>      status = repo.status(match=match, ignored=opts['all'], unknown=True)
>
> -    for f in sorted(status[4] + status[5]):
> -        if act:
> -            ui.note(_('removing file %s\n') % f)
> -        remove(removefile, f)
> +    if removefiles:
> +        for f in sorted(status[4] + status[5]):
> +            if act:
> +                ui.note(_('removing file %s\n') % f)
> +            remove(removefile, f)
>
> -    for f in sorted(directories, reverse=True):
> -        if match(f) and not os.listdir(repo.wjoin(f)):
> -            if act:
> -                ui.note(_('removing directory %s\n') % f)
> -            remove(os.rmdir, f)
> +    if removedirs:
> +        for f in sorted(directories, reverse=True):
> +            if match(f) and not os.listdir(repo.wjoin(f)):
> +                if act:
> +                    ui.note(_('removing directory %s\n') % f)
> +                remove(os.rmdir, f)
> diff -r 3b97a93dc137 -r 359c67cbc748 tests/test-purge.t
> --- a/tests/test-purge.t        Wed Jul 09 12:30:12 2014 -0500
> +++ b/tests/test-purge.t        Thu Nov 07 17:24:14 2013 -0800
> @@ -215,4 +215,50 @@
>    $ hg purge -p -X .svn -X '*/.svn'
>    $ hg purge -p -X re:.*.svn
>
> +  $ rm -R .svn directory r1
> +
> +only remove files
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --files
> +  dir/untracked_file
> +  untracked_file
> +  $ hg purge -v --files
> +  removing file dir/untracked_file
> +  removing file untracked_file
> +  $ ls
> +  dir
> +  empty_dir
> +  $ ls dir
> +
> +only remove dirs
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --dirs
> +  empty_dir
> +  $ hg purge -v --dirs
> +  removing directory empty_dir
> +  $ ls
> +  dir
> +  untracked_file
> +  $ ls dir
> +  untracked_file
> +
> +remove both files and dirs
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --files --dirs
> +  dir/untracked_file
> +  untracked_file
> +  empty_dir
> +  $ hg purge -v --files --dirs
> +  removing file dir/untracked_file
> +  removing file untracked_file
> +  removing directory empty_dir
> +  removing directory dir
> +  $ ls
> +
>    $ cd ..
>

Please ignore the patch sent earlier. I went back and read Kevin's email
asking for me to rebase & resubmit the patch and saw he requested an update
to the --dir option help text.

Thanks,
Ben
Augie Fackler - July 11, 2014, 5:10 p.m.
On Thu, Jul 10, 2014 at 03:23:02PM -0700, Ben Kehoe wrote:
> On Thu, Jul 10, 2014 at 3:20 PM, Ben Kehoe <benk@berkeley.edu> wrote:
>
> > # HG changeset patch
> > # User Ben Kehoe <benk@berkeley.edu>
> > # Date 1383873854 28800
> > #      Thu Nov 07 17:24:14 2013 -0800
> > # Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
> > # Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
> > purge: add options for deleting only files or only directories
> >
> > diff -r 3b97a93dc137 -r 359c67cbc748 hgext/purge.py
> > --- a/hgext/purge.py    Wed Jul 09 12:30:12 2014 -0500
> > +++ b/hgext/purge.py    Thu Nov 07 17:24:14 2013 -0800
> > @@ -35,6 +35,8 @@
> >  @command('purge|clean',
> >      [('a', 'abort-on-err', None, _('abort if an error occurs')),
> >      ('',  'all', None, _('purge ignored files too')),
> > +    ('',  'dirs', None, _('purge empty directories')),
> > +    ('',  'files', None, _('purge files')),
> >      ('p', 'print', None, _('print filenames instead of deleting them')),
> >      ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
> >                              ' (implies -p/--print)')),
> > @@ -46,7 +48,7 @@
> >      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:
> > +    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
> > @@ -58,6 +60,10 @@
> >      - Ignored files (unless --all is specified)
> >      - New files added to the repository (with :hg:`add`)
> >
> > +    The --files and --dirs options can be use 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.
> >
> > @@ -71,6 +77,11 @@
> >      if opts['print0']:
> >          eol = '\0'
> >          act = False # --print0 implies --print
> > +    removefiles = opts['files']
> > +    removedirs = opts['dirs']
> > +    if not removefiles and not removedirs:
> > +        removefiles = True
> > +        removedirs = True
> >
> >      def remove(remove_func, name):
> >          if act:
> > @@ -100,13 +111,15 @@
> >      match.explicitdir = match.traversedir = directories.append
> >      status = repo.status(match=match, ignored=opts['all'], unknown=True)
> >
> > -    for f in sorted(status[4] + status[5]):
> > -        if act:
> > -            ui.note(_('removing file %s\n') % f)
> > -        remove(removefile, f)
> > +    if removefiles:
> > +        for f in sorted(status[4] + status[5]):
> > +            if act:
> > +                ui.note(_('removing file %s\n') % f)
> > +            remove(removefile, f)
> >
> > -    for f in sorted(directories, reverse=True):
> > -        if match(f) and not os.listdir(repo.wjoin(f)):
> > -            if act:
> > -                ui.note(_('removing directory %s\n') % f)
> > -            remove(os.rmdir, f)
> > +    if removedirs:
> > +        for f in sorted(directories, reverse=True):
> > +            if match(f) and not os.listdir(repo.wjoin(f)):
> > +                if act:
> > +                    ui.note(_('removing directory %s\n') % f)
> > +                remove(os.rmdir, f)
> > diff -r 3b97a93dc137 -r 359c67cbc748 tests/test-purge.t
> > --- a/tests/test-purge.t        Wed Jul 09 12:30:12 2014 -0500
> > +++ b/tests/test-purge.t        Thu Nov 07 17:24:14 2013 -0800
> > @@ -215,4 +215,50 @@
> >    $ hg purge -p -X .svn -X '*/.svn'
> >    $ hg purge -p -X re:.*.svn
> >
> > +  $ rm -R .svn directory r1
> > +
> > +only remove files
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --files
> > +  dir/untracked_file
> > +  untracked_file
> > +  $ hg purge -v --files
> > +  removing file dir/untracked_file
> > +  removing file untracked_file
> > +  $ ls
> > +  dir
> > +  empty_dir
> > +  $ ls dir
> > +
> > +only remove dirs
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --dirs
> > +  empty_dir
> > +  $ hg purge -v --dirs
> > +  removing directory empty_dir
> > +  $ ls
> > +  dir
> > +  untracked_file
> > +  $ ls dir
> > +  untracked_file
> > +
> > +remove both files and dirs
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --files --dirs
> > +  dir/untracked_file
> > +  untracked_file
> > +  empty_dir
> > +  $ hg purge -v --files --dirs
> > +  removing file dir/untracked_file
> > +  removing file untracked_file
> > +  removing directory empty_dir
> > +  removing directory dir
> > +  $ ls
> > +
> >    $ cd ..
> >
>
> Please ignore the patch sent earlier. I went back and read Kevin's email
> asking for me to rebase & resubmit the patch and saw he requested an update
> to the --dir option help text.

Are you saying to ignore the message that you just replied to?

If so, when you resend can you use --flag v2 so it's more obviously a
resend? Thanks!

>
> Thanks,
> Ben

> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Augie Fackler - July 11, 2014, 5:12 p.m.
On Thu, Jul 10, 2014 at 03:23:02PM -0700, Ben Kehoe wrote:
> On Thu, Jul 10, 2014 at 3:20 PM, Ben Kehoe <benk@berkeley.edu> wrote:
>
> > # HG changeset patch
> > # User Ben Kehoe <benk@berkeley.edu>
> > # Date 1383873854 28800
> > #      Thu Nov 07 17:24:14 2013 -0800
> > # Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
> > # Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
> > purge: add options for deleting only files or only directories
> >
> > diff -r 3b97a93dc137 -r 359c67cbc748 hgext/purge.py
> > --- a/hgext/purge.py    Wed Jul 09 12:30:12 2014 -0500
> > +++ b/hgext/purge.py    Thu Nov 07 17:24:14 2013 -0800
> > @@ -35,6 +35,8 @@
> >  @command('purge|clean',
> >      [('a', 'abort-on-err', None, _('abort if an error occurs')),
> >      ('',  'all', None, _('purge ignored files too')),
> > +    ('',  'dirs', None, _('purge empty directories')),
> > +    ('',  'files', None, _('purge files')),
> >      ('p', 'print', None, _('print filenames instead of deleting them')),
> >      ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
> >                              ' (implies -p/--print)')),
> > @@ -46,7 +48,7 @@
> >      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:
> > +    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
> > @@ -58,6 +60,10 @@
> >      - Ignored files (unless --all is specified)
> >      - New files added to the repository (with :hg:`add`)
> >
> > +    The --files and --dirs options can be use 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.
> >
> > @@ -71,6 +77,11 @@
> >      if opts['print0']:
> >          eol = '\0'
> >          act = False # --print0 implies --print
> > +    removefiles = opts['files']
> > +    removedirs = opts['dirs']
> > +    if not removefiles and not removedirs:
> > +        removefiles = True
> > +        removedirs = True
> >
> >      def remove(remove_func, name):
> >          if act:
> > @@ -100,13 +111,15 @@
> >      match.explicitdir = match.traversedir = directories.append
> >      status = repo.status(match=match, ignored=opts['all'], unknown=True)
> >
> > -    for f in sorted(status[4] + status[5]):
> > -        if act:
> > -            ui.note(_('removing file %s\n') % f)
> > -        remove(removefile, f)
> > +    if removefiles:
> > +        for f in sorted(status[4] + status[5]):
> > +            if act:
> > +                ui.note(_('removing file %s\n') % f)
> > +            remove(removefile, f)
> >
> > -    for f in sorted(directories, reverse=True):
> > -        if match(f) and not os.listdir(repo.wjoin(f)):
> > -            if act:
> > -                ui.note(_('removing directory %s\n') % f)
> > -            remove(os.rmdir, f)
> > +    if removedirs:
> > +        for f in sorted(directories, reverse=True):
> > +            if match(f) and not os.listdir(repo.wjoin(f)):
> > +                if act:
> > +                    ui.note(_('removing directory %s\n') % f)
> > +                remove(os.rmdir, f)
> > diff -r 3b97a93dc137 -r 359c67cbc748 tests/test-purge.t
> > --- a/tests/test-purge.t        Wed Jul 09 12:30:12 2014 -0500
> > +++ b/tests/test-purge.t        Thu Nov 07 17:24:14 2013 -0800
> > @@ -215,4 +215,50 @@
> >    $ hg purge -p -X .svn -X '*/.svn'
> >    $ hg purge -p -X re:.*.svn
> >
> > +  $ rm -R .svn directory r1
> > +
> > +only remove files
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --files
> > +  dir/untracked_file
> > +  untracked_file
> > +  $ hg purge -v --files
> > +  removing file dir/untracked_file
> > +  removing file untracked_file
> > +  $ ls
> > +  dir
> > +  empty_dir
> > +  $ ls dir
> > +
> > +only remove dirs
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --dirs
> > +  empty_dir
> > +  $ hg purge -v --dirs
> > +  removing directory empty_dir
> > +  $ ls
> > +  dir
> > +  untracked_file
> > +  $ ls dir
> > +  untracked_file
> > +
> > +remove both files and dirs
> > +
> > +  $ mkdir -p empty_dir dir
> > +  $ touch untracked_file dir/untracked_file
> > +  $ hg purge -p --files --dirs
> > +  dir/untracked_file
> > +  untracked_file
> > +  empty_dir
> > +  $ hg purge -v --files --dirs
> > +  removing file dir/untracked_file
> > +  removing file untracked_file
> > +  removing directory empty_dir
> > +  removing directory dir
> > +  $ ls
> > +
> >    $ cd ..
> >
>
> Please ignore the patch sent earlier. I went back and read Kevin's email
> asking for me to rebase & resubmit the patch and saw he requested an update
> to the --dir option help text.

Nevermind, figured out what you meant. Sorry for the noise.

>
> Thanks,
> Ben

> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Augie Fackler - July 11, 2014, 5:14 p.m.
On Thu, Jul 10, 2014 at 03:20:36PM -0700, Ben Kehoe wrote:
> # HG changeset patch
> # User Ben Kehoe <benk@berkeley.edu>
> # Date 1383873854 28800
> #      Thu Nov 07 17:24:14 2013 -0800
> # Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
> # Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
> purge: add options for deleting only files or only directories

Looks reasonable to me, Kevin? You did the last round on this one I
think, do you have anything else you want to check?

>
> diff -r 3b97a93dc137 -r 359c67cbc748 hgext/purge.py
> --- a/hgext/purge.py	Wed Jul 09 12:30:12 2014 -0500
> +++ b/hgext/purge.py	Thu Nov 07 17:24:14 2013 -0800
> @@ -35,6 +35,8 @@
>  @command('purge|clean',
>      [('a', 'abort-on-err', None, _('abort if an error occurs')),
>      ('',  'all', None, _('purge ignored files too')),
> +    ('',  'dirs', None, _('purge empty directories')),
> +    ('',  'files', None, _('purge files')),
>      ('p', 'print', None, _('print filenames instead of deleting them')),
>      ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
>                              ' (implies -p/--print)')),
> @@ -46,7 +48,7 @@
>      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:
> +    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
> @@ -58,6 +60,10 @@
>      - Ignored files (unless --all is specified)
>      - New files added to the repository (with :hg:`add`)
>
> +    The --files and --dirs options can be use 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.
>
> @@ -71,6 +77,11 @@
>      if opts['print0']:
>          eol = '\0'
>          act = False # --print0 implies --print
> +    removefiles = opts['files']
> +    removedirs = opts['dirs']
> +    if not removefiles and not removedirs:
> +        removefiles = True
> +        removedirs = True
>
>      def remove(remove_func, name):
>          if act:
> @@ -100,13 +111,15 @@
>      match.explicitdir = match.traversedir = directories.append
>      status = repo.status(match=match, ignored=opts['all'], unknown=True)
>
> -    for f in sorted(status[4] + status[5]):
> -        if act:
> -            ui.note(_('removing file %s\n') % f)
> -        remove(removefile, f)
> +    if removefiles:
> +        for f in sorted(status[4] + status[5]):
> +            if act:
> +                ui.note(_('removing file %s\n') % f)
> +            remove(removefile, f)
>
> -    for f in sorted(directories, reverse=True):
> -        if match(f) and not os.listdir(repo.wjoin(f)):
> -            if act:
> -                ui.note(_('removing directory %s\n') % f)
> -            remove(os.rmdir, f)
> +    if removedirs:
> +        for f in sorted(directories, reverse=True):
> +            if match(f) and not os.listdir(repo.wjoin(f)):
> +                if act:
> +                    ui.note(_('removing directory %s\n') % f)
> +                remove(os.rmdir, f)
> diff -r 3b97a93dc137 -r 359c67cbc748 tests/test-purge.t
> --- a/tests/test-purge.t	Wed Jul 09 12:30:12 2014 -0500
> +++ b/tests/test-purge.t	Thu Nov 07 17:24:14 2013 -0800
> @@ -215,4 +215,50 @@
>    $ hg purge -p -X .svn -X '*/.svn'
>    $ hg purge -p -X re:.*.svn
>
> +  $ rm -R .svn directory r1
> +
> +only remove files
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --files
> +  dir/untracked_file
> +  untracked_file
> +  $ hg purge -v --files
> +  removing file dir/untracked_file
> +  removing file untracked_file
> +  $ ls
> +  dir
> +  empty_dir
> +  $ ls dir
> +
> +only remove dirs
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --dirs
> +  empty_dir
> +  $ hg purge -v --dirs
> +  removing directory empty_dir
> +  $ ls
> +  dir
> +  untracked_file
> +  $ ls dir
> +  untracked_file
> +
> +remove both files and dirs
> +
> +  $ mkdir -p empty_dir dir
> +  $ touch untracked_file dir/untracked_file
> +  $ hg purge -p --files --dirs
> +  dir/untracked_file
> +  untracked_file
> +  empty_dir
> +  $ hg purge -v --files --dirs
> +  removing file dir/untracked_file
> +  removing file untracked_file
> +  removing directory empty_dir
> +  removing directory dir
> +  $ ls
> +
>    $ cd ..
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Matt Mackall - July 11, 2014, 10:22 p.m.
On Thu, 2014-07-10 at 15:20 -0700, Ben Kehoe wrote:
> # HG changeset patch
> # User Ben Kehoe <benk@berkeley.edu>
> # Date 1383873854 28800
> #      Thu Nov 07 17:24:14 2013 -0800
> # Node ID 359c67cbc748a6e3c68fbca552aab9303cfddc69
> # Parent  3b97a93dc1374b6e660eedce86252fce016a2fae
> purge: add options for deleting only files or only directories

Queued for default, thanks (with minor doc typo fixed). This looks like
your first patch, congrats and welcome.

Patch

diff -r 3b97a93dc137 -r 359c67cbc748 hgext/purge.py
--- a/hgext/purge.py	Wed Jul 09 12:30:12 2014 -0500
+++ b/hgext/purge.py	Thu Nov 07 17:24:14 2013 -0800
@@ -35,6 +35,8 @@ 
 @command('purge|clean',
     [('a', 'abort-on-err', None, _('abort if an error occurs')),
     ('',  'all', None, _('purge ignored files too')),
+    ('',  'dirs', None, _('purge empty directories')),
+    ('',  'files', None, _('purge files')),
     ('p', 'print', None, _('print filenames instead of deleting them')),
     ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
                             ' (implies -p/--print)')),
@@ -46,7 +48,7 @@ 
     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:
+    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
@@ -58,6 +60,10 @@ 
     - Ignored files (unless --all is specified)
     - New files added to the repository (with :hg:`add`)
 
+    The --files and --dirs options can be use 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.
 
@@ -71,6 +77,11 @@ 
     if opts['print0']:
         eol = '\0'
         act = False # --print0 implies --print
+    removefiles = opts['files']
+    removedirs = opts['dirs']
+    if not removefiles and not removedirs:
+        removefiles = True
+        removedirs = True
 
     def remove(remove_func, name):
         if act:
@@ -100,13 +111,15 @@ 
     match.explicitdir = match.traversedir = directories.append
     status = repo.status(match=match, ignored=opts['all'], unknown=True)
 
-    for f in sorted(status[4] + status[5]):
-        if act:
-            ui.note(_('removing file %s\n') % f)
-        remove(removefile, f)
+    if removefiles:
+        for f in sorted(status[4] + status[5]):
+            if act:
+                ui.note(_('removing file %s\n') % f)
+            remove(removefile, f)
 
-    for f in sorted(directories, reverse=True):
-        if match(f) and not os.listdir(repo.wjoin(f)):
-            if act:
-                ui.note(_('removing directory %s\n') % f)
-            remove(os.rmdir, f)
+    if removedirs:
+        for f in sorted(directories, reverse=True):
+            if match(f) and not os.listdir(repo.wjoin(f)):
+                if act:
+                    ui.note(_('removing directory %s\n') % f)
+                remove(os.rmdir, f)
diff -r 3b97a93dc137 -r 359c67cbc748 tests/test-purge.t
--- a/tests/test-purge.t	Wed Jul 09 12:30:12 2014 -0500
+++ b/tests/test-purge.t	Thu Nov 07 17:24:14 2013 -0800
@@ -215,4 +215,50 @@ 
   $ hg purge -p -X .svn -X '*/.svn'
   $ hg purge -p -X re:.*.svn
 
+  $ rm -R .svn directory r1
+
+only remove files
+
+  $ mkdir -p empty_dir dir
+  $ touch untracked_file dir/untracked_file
+  $ hg purge -p --files
+  dir/untracked_file
+  untracked_file
+  $ hg purge -v --files
+  removing file dir/untracked_file
+  removing file untracked_file
+  $ ls
+  dir
+  empty_dir
+  $ ls dir
+
+only remove dirs
+
+  $ mkdir -p empty_dir dir
+  $ touch untracked_file dir/untracked_file
+  $ hg purge -p --dirs
+  empty_dir
+  $ hg purge -v --dirs
+  removing directory empty_dir
+  $ ls
+  dir
+  untracked_file
+  $ ls dir
+  untracked_file
+
+remove both files and dirs
+
+  $ mkdir -p empty_dir dir
+  $ touch untracked_file dir/untracked_file
+  $ hg purge -p --files --dirs
+  dir/untracked_file
+  untracked_file
+  empty_dir
+  $ hg purge -v --files --dirs
+  removing file dir/untracked_file
+  removing file untracked_file
+  removing directory empty_dir
+  removing directory dir
+  $ ls
+
   $ cd ..