annotate purge.py @ 2364:f368a1c302d5

Initial commit
author demian@gaudron.lan
date Fri, 12 May 2006 20:26:19 +0200
parents
children 9da3dd62c827
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2364
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
1 #!/usr/bin/env python
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
2 #
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
3 # Copyright (C) 2006 - Marco Barisione <marco@barisione.org>
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
4 #
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
5 # This is a small extension for Mercurial (http://www.selenic.com/mercurial)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
6 # that removes files not known to mercurial
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
7 #
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
8 # This program is free software; you can redistribute it and/or modify
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
9 # it under the terms of the GNU General Public License as published by
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
10 # the Free Software Foundation; either version 2 of the License, or
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
11 # (at your option) any later version.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
12 #
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
13 # This program is distributed in the hope that it will be useful,
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
16 # GNU General Public License for more details.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
17 #
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
18 # You should have received a copy of the GNU General Public License
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
19 # along with this program; if not, write to the Free Software
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
20 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
21
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
22 from mercurial import hg, util
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
23 import os
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
24
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
25 class Purge(object):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
26 '''removes files not tracked by mercurial
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
27
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
28 Delete files not known to mercurial, this is useful to test local and
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
29 uncommitted changes in the otherwise clean source tree.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
30
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
31 This means that purge will delete:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
32 - Unknown files: files marked with "?" by "hg status"
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
33 - Ignored files: files usually ignored by Mercurial because they match a
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
34 pattern in a ".hgignore" file
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
35 - Empty directories: infact Mercurial ignores directories unless they
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
36 contain files under source control managment
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
37 But it will leave untouched:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
38 - Unmodified tracked files
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
39 - Modified tracked files
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
40 - New files added to the repository (with "hg add")
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
41
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
42 If names are given, only files matching the names are considered, else
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
43 all files in the repository directory are considered.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
44
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
45 Be careful with purge, you could irreversibly delete some files you
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
46 forgot to add to the repository. If you only want to print the list of
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
47 files that this program would delete use the -vn options.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
48 '''
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
49
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
50 def __init__(self, act=True, abort_on_err=False):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
51 self._repo = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
52 self._ui = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
53 self._hg_root = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
54 self._act = act
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
55 self._abort_on_err = abort_on_err
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
56
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
57 def purge(self, ui, repo, paths=None):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
58 self._repo = repo
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
59 self._ui = ui
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
60 self._hg_root = self._split_path(repo.root)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
61
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
62 if not paths:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
63 paths = [repo.root]
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
64
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
65 for path in paths:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
66 path = os.path.abspath(path)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
67 for root, dirs, files in os.walk(path, topdown=False):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
68 if '.hg' in self._split_path(root):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
69 # Skip files in the .hg directory.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
70 # Note that if the repository is in a directory
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
71 # called .hg this command does not work.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
72 continue
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
73 for name in files:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
74 self._remove_file(os.path.join(root, name))
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
75 if not os.listdir(root):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
76 # Remove this directory if it is empty.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
77 self._remove_dir(root)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
78
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
79 self._repo = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
80 self._ui = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
81 self._hg_root = None
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
82
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
83 def _error(self, msg):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
84 if self._abort_on_err:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
85 raise util.Abort(msg)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
86 else:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
87 ui.warn('warning: ' + msg + '\n')
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
88
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
89 def _remove_file(self, name):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
90 relative_name = self._relative_name(name)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
91 # dirstate.state() requires a path relative to the root
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
92 # directory.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
93 if self._repo.dirstate.state(relative_name) != '?':
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
94 return
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
95 if self._ui.verbose:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
96 self._ui.status(name + '\n')
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
97 if self._act:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
98 try:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
99 os.remove(name)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
100 except OSError, e:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
101 error('"%s" cannot be removed' % name)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
102
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
103 def _remove_dir(self, name):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
104 if self._ui.verbose:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
105 self._ui.status(name + '\n')
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
106 if self._act:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
107 try:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
108 os.rmdir(name)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
109 except OSError, e:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
110 error('"%s" cannot be removed' % name)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
111
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
112 def _relative_name(self, name):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
113 splitted_path = self._split_path(name)[len(self._hg_root):]
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
114 return self._join_path(splitted_path)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
115
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
116 def _split_path(self, path):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
117 ret = []
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
118 while True:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
119 head, tail = os.path.split(path)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
120 if tail:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
121 ret.append(tail)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
122 if head == path:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
123 ret.append(head)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
124 break
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
125 path = head
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
126 ret.reverse()
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
127 return ret
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
128
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
129 def _join_path(self, splitted_path):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
130 ret = ''
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
131 for part in splitted_path:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
132 if ret:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
133 ret = os.path.join(ret, part)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
134 else:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
135 ret = part
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
136 return ret
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
137
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
138 def from_command(ui, repo, *paths, **opts):
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
139 act = True
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
140 if opts['nothing']:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
141 act = False
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
142
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
143 abort_on_err = True
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
144 if not opts['abort_on_err']:
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
145 abort_on_err = False
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
146
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
147 p = Purge(act, abort_on_err)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
148 p.purge(ui, repo, paths)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
149
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
150 # The docstring of from_command() is used by hg to print the help
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
151 # of the command.
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
152 from_command.__doc__ = __doc__
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
153 from_command = staticmethod(from_command)
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
154
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
155
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
156 cmdtable = {
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
157 'purge': (Purge.from_command,
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
158 [('a', 'abort-on-err', None, 'abort if an error occurs'),
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
159 ('n', 'nothing', None, 'do nothing on files, useful with --verbose'),
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
160 ],
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
161 'hg purge [OPTIONS] [NAME]')
f368a1c302d5 Initial commit
demian@gaudron.lan
parents:
diff changeset
162 }