Mercurial > public > mercurial-scm > hg
annotate mercurial/dirstate.py @ 1183:d9e85a75dbda
Optimize dirstate walking
This generally cuts the time for hg status/diff in half, from 2s down to 1s.
The main parts I'm trying to optimize are:
1) os.walk stats every file. dirstate.changes then stats every file again.
2) os.walk yields every file and subdir to dirstate.traverse who yields every
file and everything in the dirstate map. dirstate.walk then
filters this mass and yields every file to the caller. There should be
fewer steps in here, and fewer duplicate strings yielded.
3) dirstate.walk runs util.unique on the results from dirstate.traverse,
even though it is also passing things through dirstate.seen to look for
duplicates.
I've turned os.walk into something hg specific that takes all the dirstate
ignore and matching rules into account. The new function also takes an
function arg (statmatch()) the caller supplies to help filter out
files it doesn't care about. dirstate.changes uses this to update state
for each file, avoiding the second stat call.
dirstate.walk is changed to turn the match function it is passed into
a statmatch function. The only real difference is that a statmatch
function takes the stat data as a second parameter. It now calls
dirstate.walkhelper, who requires a statmatch function to be passed.
This fails test-walk, but right now I think this is from a sorting error
fixed by this patch.
Index: crew/mercurial/dirstate.py
===================================================================
author | mason@suse.com |
---|---|
date | Thu, 01 Sep 2005 07:34:53 -0700 |
parents | 30ab5b8ee8ec |
children | cc61d366bc3b |
rev | line source |
---|---|
1089 | 1 """ |
2 dirstate.py - working directory tracking for mercurial | |
3 | |
4 Copyright 2005 Matt Mackall <mpm@selenic.com> | |
5 | |
6 This software may be used and distributed according to the terms | |
7 of the GNU General Public License, incorporated herein by reference. | |
8 """ | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
9 |
1094 | 10 import struct, os |
11 from node import * | |
262 | 12 from demandload import * |
1104 | 13 demandload(globals(), "time bisect stat util re") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
14 |
220 | 15 class dirstate: |
244 | 16 def __init__(self, opener, ui, root): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
17 self.opener = opener |
244 | 18 self.root = root |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
19 self.dirty = 0 |
20 | 20 self.ui = ui |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
21 self.map = None |
227 | 22 self.pl = None |
363 | 23 self.copies = {} |
723 | 24 self.ignorefunc = None |
1183 | 25 self.blockignore = False |
723 | 26 |
27 def wjoin(self, f): | |
28 return os.path.join(self.root, f) | |
29 | |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
30 def getcwd(self): |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
31 cwd = os.getcwd() |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
32 if cwd == self.root: return '' |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
33 return cwd[len(self.root) + 1:] |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
34 |
723 | 35 def ignore(self, f): |
1183 | 36 if self.blockignore: |
37 return False | |
723 | 38 if not self.ignorefunc: |
39 bigpat = [] | |
40 try: | |
41 l = file(self.wjoin(".hgignore")) | |
42 for pat in l: | |
911
d46af8e6b858
Fix .hgignore parsing if last line has no EOL, ignore trailing white space.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
903
diff
changeset
|
43 p = pat.rstrip() |
d46af8e6b858
Fix .hgignore parsing if last line has no EOL, ignore trailing white space.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
903
diff
changeset
|
44 if p: |
723 | 45 try: |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
46 re.compile(p) |
723 | 47 except: |
48 self.ui.warn("ignoring invalid ignore" | |
49 + " regular expression '%s'\n" % p) | |
50 else: | |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
51 bigpat.append(p) |
723 | 52 except IOError: pass |
53 | |
735
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
54 if bigpat: |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
55 s = "(?:%s)" % (")|(?:".join(bigpat)) |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
56 r = re.compile(s) |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
57 self.ignorefunc = r.search |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
58 else: |
3433b228bbb3
An empty .hgignore file must cause us to ignore nothing, not everything!
Bryan O'Sullivan <bos@serpentine.com>
parents:
730
diff
changeset
|
59 self.ignorefunc = util.never |
723 | 60 |
61 return self.ignorefunc(f) | |
220 | 62 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
63 def __del__(self): |
220 | 64 if self.dirty: |
65 self.write() | |
66 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
67 def __getitem__(self, key): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
68 try: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
69 return self.map[key] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
70 except TypeError: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
71 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
72 return self[key] |
220 | 73 |
74 def __contains__(self, key): | |
75 if not self.map: self.read() | |
76 return key in self.map | |
77 | |
227 | 78 def parents(self): |
79 if not self.pl: | |
80 self.read() | |
81 return self.pl | |
82 | |
723 | 83 def markdirty(self): |
84 if not self.dirty: | |
85 self.dirty = 1 | |
86 | |
1062 | 87 def setparents(self, p1, p2=nullid): |
723 | 88 self.markdirty() |
227 | 89 self.pl = p1, p2 |
90 | |
220 | 91 def state(self, key): |
92 try: | |
93 return self[key][0] | |
94 except KeyError: | |
95 return "?" | |
96 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
97 def read(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
98 if self.map is not None: return self.map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
99 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
100 self.map = {} |
227 | 101 self.pl = [nullid, nullid] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
102 try: |
220 | 103 st = self.opener("dirstate").read() |
311 | 104 if not st: return |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
105 except: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
106 |
227 | 107 self.pl = [st[:20], st[20: 40]] |
108 | |
109 pos = 40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
110 while pos < len(st): |
220 | 111 e = struct.unpack(">cllll", st[pos:pos+17]) |
112 l = e[4] | |
113 pos += 17 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
114 f = st[pos:pos + l] |
515 | 115 if '\0' in f: |
363 | 116 f, c = f.split('\0') |
117 self.copies[f] = c | |
220 | 118 self.map[f] = e[:4] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
119 pos += l |
363 | 120 |
121 def copy(self, source, dest): | |
122 self.read() | |
723 | 123 self.markdirty() |
363 | 124 self.copies[dest] = source |
125 | |
126 def copied(self, file): | |
127 return self.copies.get(file, None) | |
515 | 128 |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
129 def update(self, files, state, **kw): |
220 | 130 ''' current states: |
131 n normal | |
231 | 132 m needs merging |
220 | 133 r marked for removal |
134 a marked for addition''' | |
135 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
136 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
137 self.read() |
723 | 138 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
139 for f in files: |
220 | 140 if state == "r": |
141 self.map[f] = ('r', 0, 0, 0) | |
142 else: | |
253 | 143 s = os.stat(os.path.join(self.root, f)) |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
144 st_size = kw.get('st_size', s.st_size) |
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
145 st_mtime = kw.get('st_mtime', s.st_mtime) |
865
2d2fee33ec68
Cleanup after previous changes:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
863
diff
changeset
|
146 self.map[f] = (state, s.st_mode, st_size, st_mtime) |
1117 | 147 if self.copies.has_key(f): |
148 del self.copies[f] | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
149 |
220 | 150 def forget(self, files): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
151 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
152 self.read() |
723 | 153 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
154 for f in files: |
20 | 155 try: |
156 del self.map[f] | |
157 except KeyError: | |
220 | 158 self.ui.warn("not in dirstate: %s!\n" % f) |
20 | 159 pass |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
160 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
161 def clear(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
162 self.map = {} |
723 | 163 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
164 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
165 def write(self): |
220 | 166 st = self.opener("dirstate", "w") |
227 | 167 st.write("".join(self.pl)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
168 for f, e in self.map.items(): |
363 | 169 c = self.copied(f) |
170 if c: | |
171 f = f + "\0" + c | |
220 | 172 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
173 st.write(e + f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
174 self.dirty = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
175 |
879 | 176 def filterfiles(self, files): |
177 ret = {} | |
178 unknown = [] | |
179 | |
180 for x in files: | |
181 if x is '.': | |
182 return self.map.copy() | |
183 if x not in self.map: | |
184 unknown.append(x) | |
185 else: | |
186 ret[x] = self.map[x] | |
919 | 187 |
879 | 188 if not unknown: |
189 return ret | |
190 | |
191 b = self.map.keys() | |
192 b.sort() | |
193 blen = len(b) | |
194 | |
195 for x in unknown: | |
196 bs = bisect.bisect(b, x) | |
919 | 197 if bs != 0 and b[bs-1] == x: |
879 | 198 ret[x] = self.map[x] |
199 continue | |
200 while bs < blen: | |
201 s = b[bs] | |
202 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/': | |
203 ret[s] = self.map[s] | |
204 else: | |
205 break | |
206 bs += 1 | |
207 return ret | |
208 | |
1062 | 209 def walk(self, files=None, match=util.always, dc=None): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
210 self.read() |
879 | 211 |
723 | 212 # walk all files by default |
879 | 213 if not files: |
214 files = [self.root] | |
215 if not dc: | |
216 dc = self.map.copy() | |
217 elif not dc: | |
218 dc = self.filterfiles(files) | |
919 | 219 |
1183 | 220 def statmatch(file, stat): |
221 if file not in dc and self.ignore(file): | |
222 return False | |
223 return match(file) | |
224 return self.walkhelper(files=files, statmatch=statmatch, dc=dc) | |
225 | |
226 # walk recursively through the directory tree, finding all files | |
227 # matched by the statmatch function | |
228 # | |
229 # results are yielded in a tuple (src, filename), where src is one of: | |
230 # 'f' the file was found in the directory tree | |
231 # 'm' the file was only in the dirstate and not in the tree | |
232 # | |
233 # dc is an optional arg for the current dirstate. dc is not modified | |
234 # directly by this function, but might be modified by your statmatch call. | |
235 # | |
236 def walkhelper(self, files, statmatch, dc): | |
237 # recursion free walker, faster than os.walk. | |
238 def findfiles(s): | |
239 retfiles = [] | |
240 work = [s] | |
241 while work: | |
242 top = work.pop() | |
243 names = os.listdir(top) | |
244 names.sort() | |
245 # nd is the top of the repository dir tree | |
246 nd = util.normpath(top[len(self.root) + 1:]) | |
247 if nd == '.': nd = '' | |
248 for f in names: | |
249 np = os.path.join(nd, f) | |
250 if seen(np): | |
251 continue | |
252 p = os.path.join(top, f) | |
253 st = os.stat(p) | |
254 if stat.S_ISDIR(st.st_mode): | |
255 ds = os.path.join(nd, f +'/') | |
256 if statmatch(ds, st): | |
257 work.append(p) | |
258 else: | |
259 if statmatch(np, st): | |
260 yield np | |
261 | |
821
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
262 known = {'.hg': 1} |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
263 def seen(fn): |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
264 if fn in known: return True |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
265 known[fn] = 1 |
1183 | 266 |
267 # step one, find all files that match our criteria | |
268 files.sort() | |
269 for ff in util.unique(files): | |
270 f = os.path.join(self.root, ff) | |
271 try: | |
272 st = os.stat(f) | |
273 except OSError, inst: | |
274 if ff not in dc: self.ui.warn('%s: %s\n' % ( | |
275 util.pathto(self.getcwd(), ff), | |
276 inst.strerror)) | |
277 continue | |
278 if stat.S_ISDIR(st.st_mode): | |
279 sorted = [ x for x in findfiles(f) ] | |
280 sorted.sort() | |
281 for fl in sorted: | |
282 yield 'f', fl | |
283 elif stat.S_ISREG(st.st_mode): | |
284 ff = util.normpath(ff) | |
285 if seen(ff): | |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
883
diff
changeset
|
286 continue |
1183 | 287 found = False |
288 self.blockignore = True | |
289 if statmatch(ff, st): | |
290 found = True | |
291 self.blockignore = False | |
292 if found: | |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
883
diff
changeset
|
293 yield 'f', ff |
1183 | 294 else: |
295 kind = 'unknown' | |
296 if stat.S_ISCHR(st.st_mode): kind = 'character device' | |
297 elif stat.S_ISBLK(st.st_mode): kind = 'block device' | |
298 elif stat.S_ISFIFO(st.st_mode): kind = 'fifo' | |
299 elif stat.S_ISLNK(st.st_mode): kind = 'symbolic link' | |
300 elif stat.S_ISSOCK(st.st_mode): kind = 'socket' | |
301 self.ui.warn('%s: unsupported file type (type is %s)\n' % ( | |
302 util.pathto(self.getcwd(), ff), | |
303 kind)) | |
536 | 304 |
1183 | 305 # step two run through anything left in the dc hash and yield |
306 # if we haven't already seen it | |
307 ks = dc.keys() | |
308 ks.sort() | |
309 for k in ks: | |
310 if not seen(k) and (statmatch(k, None)): | |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
311 yield 'm', k |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
312 |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
313 def changes(self, files=None, match=util.always): |
723 | 314 self.read() |
879 | 315 if not files: |
1183 | 316 files = [self.root] |
879 | 317 dc = self.map.copy() |
318 else: | |
319 dc = self.filterfiles(files) | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
320 lookup, modified, added, unknown = [], [], [], [] |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
321 removed, deleted = [], [] |
723 | 322 |
1183 | 323 # statmatch function to eliminate entries from the dirstate copy |
324 # and put files into the appropriate array. This gets passed | |
325 # to the walking code | |
326 def statmatch(fn, s): | |
327 def checkappend(l, fn): | |
328 if match is util.always or match(fn): | |
329 l.append(fn) | |
330 | |
331 if not s or stat.S_ISDIR(s.st_mode): | |
332 return self.ignore(fn) and False or match(fn) | |
333 | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
334 if not stat.S_ISREG(s.st_mode): |
1183 | 335 return False |
336 c = dc.pop(fn, None) | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
337 if c: |
1183 | 338 type, mode, size, time = c |
339 # check the common case first | |
340 if type == 'n': | |
341 if size != s.st_size or (mode ^ s.st_mode) & 0100: | |
342 checkappend(modified, fn) | |
343 elif time != s.st_mtime: | |
344 checkappend(lookup, fn) | |
345 elif type == 'm': | |
346 checkappend(modified, fn) | |
347 elif type == 'a': | |
348 checkappend(added, fn) | |
349 elif type == 'r': | |
350 checkappend(unknown, fn) | |
351 else: | |
352 if not self.ignore(fn) and match(fn): | |
536 | 353 unknown.append(fn) |
1183 | 354 # return false because we've already handled all cases above. |
355 # there's no need for the walking code to process the file | |
356 # any further. | |
357 return False | |
536 | 358 |
1183 | 359 # because our statmatch always returns false, self.walk will only |
360 # return files in the dirstate map that are not present in the FS. | |
361 # But, we still need to iterate through the results to force the | |
362 # walk to complete | |
363 for src, fn in self.walkhelper(files, statmatch, dc): | |
364 pass | |
365 | |
366 # anything left in dc didn't exist in the filesystem | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
367 for fn, c in [(fn, c) for fn, c in dc.items() if match(fn)]: |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
368 if c[0] == 'r': |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
369 removed.append(fn) |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
370 else: |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
371 deleted.append(fn) |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
372 return (lookup, modified, added, removed + deleted, unknown) |