comparison hgext/purge.py @ 21853:8127b9e798b1

purge: add options for deleting only files or only directories
author Ben Kehoe <benk@berkeley.edu>
date Thu, 07 Nov 2013 17:24:14 -0800
parents f1c3ba167b0c
children 52d34d5415c9
comparison
equal deleted inserted replaced
21852:37a5decc6924 21853:8127b9e798b1
33 testedwith = 'internal' 33 testedwith = 'internal'
34 34
35 @command('purge|clean', 35 @command('purge|clean',
36 [('a', 'abort-on-err', None, _('abort if an error occurs')), 36 [('a', 'abort-on-err', None, _('abort if an error occurs')),
37 ('', 'all', None, _('purge ignored files too')), 37 ('', 'all', None, _('purge ignored files too')),
38 ('', 'dirs', None, _('purge empty directories')),
39 ('', 'files', None, _('purge files')),
38 ('p', 'print', None, _('print filenames instead of deleting them')), 40 ('p', 'print', None, _('print filenames instead of deleting them')),
39 ('0', 'print0', None, _('end filenames with NUL, for use with xargs' 41 ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
40 ' (implies -p/--print)')), 42 ' (implies -p/--print)')),
41 ] + commands.walkopts, 43 ] + commands.walkopts,
42 _('hg purge [OPTION]... [DIR]...')) 44 _('hg purge [OPTION]... [DIR]...'))
44 '''removes files not tracked by Mercurial 46 '''removes files not tracked by Mercurial
45 47
46 Delete files not known to Mercurial. This is useful to test local 48 Delete files not known to Mercurial. This is useful to test local
47 and uncommitted changes in an otherwise-clean source tree. 49 and uncommitted changes in an otherwise-clean source tree.
48 50
49 This means that purge will delete: 51 This means that purge will delete the following by default:
50 52
51 - Unknown files: files marked with "?" by :hg:`status` 53 - Unknown files: files marked with "?" by :hg:`status`
52 - Empty directories: in fact Mercurial ignores directories unless 54 - Empty directories: in fact Mercurial ignores directories unless
53 they contain files under source control management 55 they contain files under source control management
54 56
55 But it will leave untouched: 57 But it will leave untouched:
56 58
57 - Modified and unmodified tracked files 59 - Modified and unmodified tracked files
58 - Ignored files (unless --all is specified) 60 - Ignored files (unless --all is specified)
59 - New files added to the repository (with :hg:`add`) 61 - New files added to the repository (with :hg:`add`)
62
63 The --files and --dirs options can be used to direct purge to delete
64 only files, only directories, or both. If neither option is given,
65 both will be deleted.
60 66
61 If directories are given on the command line, only files in these 67 If directories are given on the command line, only files in these
62 directories are considered. 68 directories are considered.
63 69
64 Be careful with purge, as you could irreversibly delete some files 70 Be careful with purge, as you could irreversibly delete some files
69 act = not opts['print'] 75 act = not opts['print']
70 eol = '\n' 76 eol = '\n'
71 if opts['print0']: 77 if opts['print0']:
72 eol = '\0' 78 eol = '\0'
73 act = False # --print0 implies --print 79 act = False # --print0 implies --print
80 removefiles = opts['files']
81 removedirs = opts['dirs']
82 if not removefiles and not removedirs:
83 removefiles = True
84 removedirs = True
74 85
75 def remove(remove_func, name): 86 def remove(remove_func, name):
76 if act: 87 if act:
77 try: 88 try:
78 remove_func(repo.wjoin(name)) 89 remove_func(repo.wjoin(name))
98 directories = [] 109 directories = []
99 match = scmutil.match(repo[None], dirs, opts) 110 match = scmutil.match(repo[None], dirs, opts)
100 match.explicitdir = match.traversedir = directories.append 111 match.explicitdir = match.traversedir = directories.append
101 status = repo.status(match=match, ignored=opts['all'], unknown=True) 112 status = repo.status(match=match, ignored=opts['all'], unknown=True)
102 113
103 for f in sorted(status[4] + status[5]): 114 if removefiles:
104 if act: 115 for f in sorted(status[4] + status[5]):
105 ui.note(_('removing file %s\n') % f) 116 if act:
106 remove(removefile, f) 117 ui.note(_('removing file %s\n') % f)
118 remove(removefile, f)
107 119
108 for f in sorted(directories, reverse=True): 120 if removedirs:
109 if match(f) and not os.listdir(repo.wjoin(f)): 121 for f in sorted(directories, reverse=True):
110 if act: 122 if match(f) and not os.listdir(repo.wjoin(f)):
111 ui.note(_('removing directory %s\n') % f) 123 if act:
112 remove(os.rmdir, f) 124 ui.note(_('removing directory %s\n') % f)
125 remove(os.rmdir, f)