##// END OF EJS Templates
purge.py: fix invocation of statwalk
Alexis S. L. Carvalho -
r4155:4c714ed2 default
parent child Browse files
Show More
@@ -1,113 +1,114 b''
1 # Copyright (C) 2006 - Marco Barisione <marco@barisione.org>
1 # Copyright (C) 2006 - Marco Barisione <marco@barisione.org>
2 #
2 #
3 # This is a small extension for Mercurial (http://www.selenic.com/mercurial)
3 # This is a small extension for Mercurial (http://www.selenic.com/mercurial)
4 # that removes files not known to mercurial
4 # that removes files not known to mercurial
5 #
5 #
6 # This program was inspired by the "cvspurge" script contained in CVS utilities
6 # This program was inspired by the "cvspurge" script contained in CVS utilities
7 # (http://www.red-bean.com/cvsutils/).
7 # (http://www.red-bean.com/cvsutils/).
8 #
8 #
9 # To enable the "purge" extension put these lines in your ~/.hgrc:
9 # To enable the "purge" extension put these lines in your ~/.hgrc:
10 # [extensions]
10 # [extensions]
11 # purge = /path/to/purge.py
11 # purge = /path/to/purge.py
12 #
12 #
13 # For help on the usage of "hg purge" use:
13 # For help on the usage of "hg purge" use:
14 # hg help purge
14 # hg help purge
15 #
15 #
16 # This program is free software; you can redistribute it and/or modify
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
19 # (at your option) any later version.
20 #
20 #
21 # This program is distributed in the hope that it will be useful,
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 # GNU General Public License for more details.
24 # GNU General Public License for more details.
25 #
25 #
26 # You should have received a copy of the GNU General Public License
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
29
30 from mercurial import hg, util
30 from mercurial import hg, util
31 from mercurial.i18n import _
31 from mercurial.i18n import _
32 import os
32 import os
33
33
34 def dopurge(ui, repo, dirs=None, act=True, abort_on_err=False, eol='\n'):
34 def dopurge(ui, repo, dirs=None, act=True, abort_on_err=False, eol='\n'):
35 def error(msg):
35 def error(msg):
36 if abort_on_err:
36 if abort_on_err:
37 raise util.Abort(msg)
37 raise util.Abort(msg)
38 else:
38 else:
39 ui.warn(_('warning: %s\n') % msg)
39 ui.warn(_('warning: %s\n') % msg)
40
40
41 def remove(remove_func, name):
41 def remove(remove_func, name):
42 if act:
42 if act:
43 try:
43 try:
44 remove_func(os.path.join(repo.root, name))
44 remove_func(os.path.join(repo.root, name))
45 except OSError, e:
45 except OSError, e:
46 error(_('%s cannot be removed') % name)
46 error(_('%s cannot be removed') % name)
47 else:
47 else:
48 ui.write('%s%s' % (name, eol))
48 ui.write('%s%s' % (name, eol))
49
49
50 directories = []
50 directories = []
51 files = []
51 files = []
52 for src, f, st in repo.dirstate.statwalk(files=dirs, ignored=True,
52 roots, match, anypats = util.cmdmatcher(repo.root, repo.getcwd(), dirs)
53 directories=True):
53 for src, f, st in repo.dirstate.statwalk(files=roots, match=match,
54 if src == 'd':
54 ignored=True, directories=True):
55 if src == 'd':
55 directories.append(f)
56 directories.append(f)
56 elif src == 'f' and f not in repo.dirstate:
57 elif src == 'f' and f not in repo.dirstate:
57 files.append(f)
58 files.append(f)
58
59
59 directories.sort()
60 directories.sort()
60
61
61 for f in files:
62 for f in files:
62 if f not in repo.dirstate:
63 if f not in repo.dirstate:
63 ui.note(_('Removing file %s\n') % f)
64 ui.note(_('Removing file %s\n') % f)
64 remove(os.remove, f)
65 remove(os.remove, f)
65
66
66 for f in directories[::-1]:
67 for f in directories[::-1]:
67 if not os.listdir(repo.wjoin(f)):
68 if not os.listdir(repo.wjoin(f)):
68 ui.note(_('Removing directory %s\n') % f)
69 ui.note(_('Removing directory %s\n') % f)
69 remove(os.rmdir, f)
70 remove(os.rmdir, f)
70
71
71
72
72 def purge(ui, repo, *dirs, **opts):
73 def purge(ui, repo, *dirs, **opts):
73 '''removes files not tracked by mercurial
74 '''removes files not tracked by mercurial
74
75
75 Delete files not known to mercurial, this is useful to test local and
76 Delete files not known to mercurial, this is useful to test local and
76 uncommitted changes in the otherwise clean source tree.
77 uncommitted changes in the otherwise clean source tree.
77
78
78 This means that purge will delete:
79 This means that purge will delete:
79 - Unknown files: files marked with "?" by "hg status"
80 - Unknown files: files marked with "?" by "hg status"
80 - Ignored files: files usually ignored by Mercurial because they match
81 - Ignored files: files usually ignored by Mercurial because they match
81 a pattern in a ".hgignore" file
82 a pattern in a ".hgignore" file
82 - Empty directories: in fact Mercurial ignores directories unless they
83 - Empty directories: in fact Mercurial ignores directories unless they
83 contain files under source control managment
84 contain files under source control managment
84 But it will leave untouched:
85 But it will leave untouched:
85 - Unmodified tracked files
86 - Unmodified tracked files
86 - Modified tracked files
87 - Modified tracked files
87 - New files added to the repository (with "hg add")
88 - New files added to the repository (with "hg add")
88
89
89 If directories are given on the command line, only files in these
90 If directories are given on the command line, only files in these
90 directories are considered.
91 directories are considered.
91
92
92 Be careful with purge, you could irreversibly delete some files you
93 Be careful with purge, you could irreversibly delete some files you
93 forgot to add to the repository. If you only want to print the list of
94 forgot to add to the repository. If you only want to print the list of
94 files that this program would delete use the --print option.
95 files that this program would delete use the --print option.
95 '''
96 '''
96 act = not opts['print']
97 act = not opts['print']
97 abort_on_err = bool(opts['abort_on_err'])
98 abort_on_err = bool(opts['abort_on_err'])
98 eol = opts['print0'] and '\0' or '\n'
99 eol = opts['print0'] and '\0' or '\n'
99 if eol == '\0':
100 if eol == '\0':
100 # --print0 implies --print
101 # --print0 implies --print
101 act = False
102 act = False
102 dopurge(ui, repo, dirs, act, abort_on_err, eol)
103 dopurge(ui, repo, dirs, act, abort_on_err, eol)
103
104
104
105
105 cmdtable = {
106 cmdtable = {
106 'purge':
107 'purge':
107 (purge,
108 (purge,
108 [('a', 'abort-on-err', None, _('abort if an error occurs')),
109 [('a', 'abort-on-err', None, _('abort if an error occurs')),
109 ('p', 'print', None, _('print the file names instead of deleting them')),
110 ('p', 'print', None, _('print the file names instead of deleting them')),
110 ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
111 ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
111 ' (implies -p)'))],
112 ' (implies -p)'))],
112 _('hg purge [OPTION]... [DIR]...'))
113 _('hg purge [OPTION]... [DIR]...'))
113 }
114 }
@@ -1,57 +1,76 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat <<EOF >> $HGRCPATH
3 cat <<EOF >> $HGRCPATH
4 [extensions]
4 [extensions]
5 purge=${TESTDIR}/../contrib/purge/purge.py
5 purge=${TESTDIR}/../contrib/purge/purge.py
6 EOF
6 EOF
7
7
8 echo % init
8 echo % init
9 hg init t
9 hg init t
10 cd t
10 cd t
11
11
12 echo % setup
12 echo % setup
13 echo r1 > r1
13 echo r1 > r1
14 hg ci -qAmr1 -d'0 0'
14 hg ci -qAmr1 -d'0 0'
15 mkdir directory
15 mkdir directory
16 echo r2 > directory/r2
16 echo r2 > directory/r2
17 hg ci -qAmr2 -d'1 0'
17 hg ci -qAmr2 -d'1 0'
18 echo 'ignored' > .hgignore
18 echo 'ignored' > .hgignore
19 hg ci -qAmr3 -d'2 0'
19 hg ci -qAmr3 -d'2 0'
20
20
21 echo % delete an empty directory
21 echo % delete an empty directory
22 mkdir empty_dir
22 mkdir empty_dir
23 hg purge -p
23 hg purge -p
24 hg purge -v
24 hg purge -v
25 ls
25 ls
26
26
27 echo % delete an untracked directory
27 echo % delete an untracked directory
28 mkdir untracked_dir
28 mkdir untracked_dir
29 touch untracked_dir/untracked_file1
29 touch untracked_dir/untracked_file1
30 touch untracked_dir/untracked_file2
30 touch untracked_dir/untracked_file2
31 hg purge -p
31 hg purge -p
32 hg purge -v
32 hg purge -v
33 ls
33 ls
34
34
35 echo % delete an untracked file
35 echo % delete an untracked file
36 touch untracked_file
36 touch untracked_file
37 hg purge -p
37 hg purge -p
38 hg purge -v
38 hg purge -v
39 ls
39 ls
40
40
41 echo % delete an untracked file in a tracked directory
41 echo % delete an untracked file in a tracked directory
42 touch directory/untracked_file
42 touch directory/untracked_file
43 hg purge -p
43 hg purge -p
44 hg purge -v
44 hg purge -v
45 ls
45 ls
46
46
47 echo % delete nested directories
47 echo % delete nested directories
48 mkdir -p untracked_directory/nested_directory
48 mkdir -p untracked_directory/nested_directory
49 hg purge -p
49 hg purge -p
50 hg purge -v
50 hg purge -v
51 ls
51 ls
52
52
53 echo % delete nested directories from a subdir
54 mkdir -p untracked_directory/nested_directory
55 cd directory
56 hg purge -p
57 hg purge -v
58 cd ..
59 ls
60
61 echo % delete only part of the tree
62 mkdir -p untracked_directory/nested_directory
63 touch directory/untracked_file
64 cd directory
65 hg purge -p ../untracked_directory
66 hg purge -v ../untracked_directory
67 cd ..
68 ls
69 ls directory/untracked_file
70 rm directory/untracked_file
71
53 echo % delete ignored files
72 echo % delete ignored files
54 touch ignored
73 touch ignored
55 hg purge -p
74 hg purge -p
56 hg purge -v
75 hg purge -v
57 ls
76 ls
@@ -1,36 +1,49 b''
1 % init
1 % init
2 % setup
2 % setup
3 % delete an empty directory
3 % delete an empty directory
4 empty_dir
4 empty_dir
5 Removing directory empty_dir
5 Removing directory empty_dir
6 directory
6 directory
7 r1
7 r1
8 % delete an untracked directory
8 % delete an untracked directory
9 untracked_dir/untracked_file1
9 untracked_dir/untracked_file1
10 untracked_dir/untracked_file2
10 untracked_dir/untracked_file2
11 Removing file untracked_dir/untracked_file1
11 Removing file untracked_dir/untracked_file1
12 Removing file untracked_dir/untracked_file2
12 Removing file untracked_dir/untracked_file2
13 Removing directory untracked_dir
13 Removing directory untracked_dir
14 directory
14 directory
15 r1
15 r1
16 % delete an untracked file
16 % delete an untracked file
17 untracked_file
17 untracked_file
18 Removing file untracked_file
18 Removing file untracked_file
19 directory
19 directory
20 r1
20 r1
21 % delete an untracked file in a tracked directory
21 % delete an untracked file in a tracked directory
22 directory/untracked_file
22 directory/untracked_file
23 Removing file directory/untracked_file
23 Removing file directory/untracked_file
24 directory
24 directory
25 r1
25 r1
26 % delete nested directories
26 % delete nested directories
27 untracked_directory/nested_directory
27 untracked_directory/nested_directory
28 Removing directory untracked_directory/nested_directory
28 Removing directory untracked_directory/nested_directory
29 Removing directory untracked_directory
29 Removing directory untracked_directory
30 directory
30 directory
31 r1
31 r1
32 % delete nested directories from a subdir
33 untracked_directory/nested_directory
34 Removing directory untracked_directory/nested_directory
35 Removing directory untracked_directory
36 directory
37 r1
38 % delete only part of the tree
39 untracked_directory/nested_directory
40 Removing directory untracked_directory/nested_directory
41 Removing directory untracked_directory
42 directory
43 r1
44 directory/untracked_file
32 % delete ignored files
45 % delete ignored files
33 ignored
46 ignored
34 Removing file ignored
47 Removing file ignored
35 directory
48 directory
36 r1
49 r1
General Comments 0
You need to be logged in to leave comments. Login now