##// END OF EJS Templates
add dirstate._dirtypl variable...
Alexis S. L. Carvalho -
r4952:a11921d2 default
parent child Browse files
Show More
@@ -1,491 +1,496 b''
1 """
1 """
2 dirstate.py - working directory tracking for mercurial
2 dirstate.py - working directory tracking for mercurial
3
3
4 Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5
5
6 This software may be used and distributed according to the terms
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
7 of the GNU General Public License, incorporated herein by reference.
8 """
8 """
9
9
10 from node import *
10 from node import *
11 from i18n import _
11 from i18n import _
12 import struct, os, time, bisect, stat, strutil, util, re, errno, ignore
12 import struct, os, time, bisect, stat, strutil, util, re, errno, ignore
13 import cStringIO
13 import cStringIO
14
14
15 _unknown = ('?', 0, 0, 0)
15 _unknown = ('?', 0, 0, 0)
16 _format = ">cllll"
16 _format = ">cllll"
17
17
18 class dirstate(object):
18 class dirstate(object):
19
19
20 def __init__(self, opener, ui, root):
20 def __init__(self, opener, ui, root):
21 self._opener = opener
21 self._opener = opener
22 self._root = root
22 self._root = root
23 self._dirty = 0
23 self._dirty = 0
24 self._dirtypl = 0
24 self._ui = ui
25 self._ui = ui
25
26
26 def __getattr__(self, name):
27 def __getattr__(self, name):
27 if name == '_map':
28 if name == '_map':
28 self._read()
29 self._read()
29 return self._map
30 return self._map
30 elif name == '_copymap':
31 elif name == '_copymap':
31 self._read()
32 self._read()
32 return self._copymap
33 return self._copymap
33 elif name == '_branch':
34 elif name == '_branch':
34 try:
35 try:
35 self._branch = (self._opener("branch").read().strip()
36 self._branch = (self._opener("branch").read().strip()
36 or "default")
37 or "default")
37 except IOError:
38 except IOError:
38 self._branch = "default"
39 self._branch = "default"
39 return self._branch
40 return self._branch
40 elif name == '_pl':
41 elif name == '_pl':
41 self._pl = [nullid, nullid]
42 self._pl = [nullid, nullid]
42 try:
43 try:
43 st = self._opener("dirstate").read(40)
44 st = self._opener("dirstate").read(40)
44 if len(st) == 40:
45 if len(st) == 40:
45 self._pl = st[:20], st[20:40]
46 self._pl = st[:20], st[20:40]
46 except IOError, err:
47 except IOError, err:
47 if err.errno != errno.ENOENT: raise
48 if err.errno != errno.ENOENT: raise
48 return self._pl
49 return self._pl
49 elif name == '_dirs':
50 elif name == '_dirs':
50 self._dirs = {}
51 self._dirs = {}
51 for f in self._map:
52 for f in self._map:
52 self._incpath(f)
53 self._incpath(f)
53 return self._dirs
54 return self._dirs
54 elif name == '_ignore':
55 elif name == '_ignore':
55 files = [self.wjoin('.hgignore')]
56 files = [self.wjoin('.hgignore')]
56 for name, path in self._ui.configitems("ui"):
57 for name, path in self._ui.configitems("ui"):
57 if name == 'ignore' or name.startswith('ignore.'):
58 if name == 'ignore' or name.startswith('ignore.'):
58 files.append(os.path.expanduser(path))
59 files.append(os.path.expanduser(path))
59 self._ignore = ignore.ignore(self._root, files, self._ui.warn)
60 self._ignore = ignore.ignore(self._root, files, self._ui.warn)
60 return self._ignore
61 return self._ignore
61 elif name == '_slash':
62 elif name == '_slash':
62 self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/'
63 self._slash = self._ui.configbool('ui', 'slash') and os.sep != '/'
63 return self._slash
64 return self._slash
64 else:
65 else:
65 raise AttributeError, name
66 raise AttributeError, name
66
67
67 def wjoin(self, f):
68 def wjoin(self, f):
68 return os.path.join(self._root, f)
69 return os.path.join(self._root, f)
69
70
70 def getcwd(self):
71 def getcwd(self):
71 cwd = os.getcwd()
72 cwd = os.getcwd()
72 if cwd == self._root: return ''
73 if cwd == self._root: return ''
73 # self._root ends with a path separator if self._root is '/' or 'C:\'
74 # self._root ends with a path separator if self._root is '/' or 'C:\'
74 rootsep = self._root
75 rootsep = self._root
75 if not rootsep.endswith(os.sep):
76 if not rootsep.endswith(os.sep):
76 rootsep += os.sep
77 rootsep += os.sep
77 if cwd.startswith(rootsep):
78 if cwd.startswith(rootsep):
78 return cwd[len(rootsep):]
79 return cwd[len(rootsep):]
79 else:
80 else:
80 # we're outside the repo. return an absolute path.
81 # we're outside the repo. return an absolute path.
81 return cwd
82 return cwd
82
83
83 def pathto(self, f, cwd=None):
84 def pathto(self, f, cwd=None):
84 if cwd is None:
85 if cwd is None:
85 cwd = self.getcwd()
86 cwd = self.getcwd()
86 path = util.pathto(self._root, cwd, f)
87 path = util.pathto(self._root, cwd, f)
87 if self._slash:
88 if self._slash:
88 return path.replace(os.sep, '/')
89 return path.replace(os.sep, '/')
89 return path
90 return path
90
91
91 def __del__(self):
92 def __del__(self):
92 self.write()
93 self.write()
93
94
94 def __getitem__(self, key):
95 def __getitem__(self, key):
95 return self._map[key]
96 return self._map[key]
96
97
97 def __contains__(self, key):
98 def __contains__(self, key):
98 return key in self._map
99 return key in self._map
99
100
100 def __iter__(self):
101 def __iter__(self):
101 a = self._map.keys()
102 a = self._map.keys()
102 a.sort()
103 a.sort()
103 for x in a:
104 for x in a:
104 yield x
105 yield x
105
106
106 def parents(self):
107 def parents(self):
107 return self._pl
108 return self._pl
108
109
109 def branch(self):
110 def branch(self):
110 return self._branch
111 return self._branch
111
112
112 def markdirty(self):
113 def markdirty(self):
113 self._dirty = 1
114 self._dirty = 1
114
115
115 def setparents(self, p1, p2=nullid):
116 def setparents(self, p1, p2=nullid):
116 self.markdirty()
117 self.markdirty()
118 self._dirtypl = 1
117 self._pl = p1, p2
119 self._pl = p1, p2
118
120
119 def setbranch(self, branch):
121 def setbranch(self, branch):
120 self._branch = branch
122 self._branch = branch
121 self._opener("branch", "w").write(branch + '\n')
123 self._opener("branch", "w").write(branch + '\n')
122
124
123 def state(self, key):
125 def state(self, key):
124 return self._map.get(key, ("?",))[0]
126 return self._map.get(key, ("?",))[0]
125
127
126 def _read(self):
128 def _read(self):
127 self._map = {}
129 self._map = {}
128 self._copymap = {}
130 self._copymap = {}
129 self._pl = [nullid, nullid]
131 if not self._dirtypl:
132 self._pl = [nullid, nullid]
130 try:
133 try:
131 st = self._opener("dirstate").read()
134 st = self._opener("dirstate").read()
132 except IOError, err:
135 except IOError, err:
133 if err.errno != errno.ENOENT: raise
136 if err.errno != errno.ENOENT: raise
134 return
137 return
135 if not st:
138 if not st:
136 return
139 return
137
140
138 self._pl = [st[:20], st[20: 40]]
141 if not self._dirtypl:
142 self._pl = [st[:20], st[20: 40]]
139
143
140 # deref fields so they will be local in loop
144 # deref fields so they will be local in loop
141 dmap = self._map
145 dmap = self._map
142 copymap = self._copymap
146 copymap = self._copymap
143 unpack = struct.unpack
147 unpack = struct.unpack
144
148
145 pos = 40
149 pos = 40
146 e_size = struct.calcsize(_format)
150 e_size = struct.calcsize(_format)
147
151
148 while pos < len(st):
152 while pos < len(st):
149 newpos = pos + e_size
153 newpos = pos + e_size
150 e = unpack(_format, st[pos:newpos])
154 e = unpack(_format, st[pos:newpos])
151 l = e[4]
155 l = e[4]
152 pos = newpos
156 pos = newpos
153 newpos = pos + l
157 newpos = pos + l
154 f = st[pos:newpos]
158 f = st[pos:newpos]
155 if '\0' in f:
159 if '\0' in f:
156 f, c = f.split('\0')
160 f, c = f.split('\0')
157 copymap[f] = c
161 copymap[f] = c
158 dmap[f] = e[:4]
162 dmap[f] = e[:4]
159 pos = newpos
163 pos = newpos
160
164
161 def invalidate(self):
165 def invalidate(self):
162 for a in "_map _copymap _branch _pl _dirs _ignore".split():
166 for a in "_map _copymap _branch _pl _dirs _ignore".split():
163 if hasattr(self, a):
167 if hasattr(self, a):
164 self.__delattr__(a)
168 self.__delattr__(a)
165 self._dirty = 0
169 self._dirty = 0
166
170
167 def copy(self, source, dest):
171 def copy(self, source, dest):
168 self.markdirty()
172 self.markdirty()
169 self._copymap[dest] = source
173 self._copymap[dest] = source
170
174
171 def copied(self, file):
175 def copied(self, file):
172 return self._copymap.get(file, None)
176 return self._copymap.get(file, None)
173
177
174 def copies(self):
178 def copies(self):
175 return self._copymap
179 return self._copymap
176
180
177 def _incpath(self, path):
181 def _incpath(self, path):
178 for c in strutil.findall(path, '/'):
182 for c in strutil.findall(path, '/'):
179 pc = path[:c]
183 pc = path[:c]
180 self._dirs.setdefault(pc, 0)
184 self._dirs.setdefault(pc, 0)
181 self._dirs[pc] += 1
185 self._dirs[pc] += 1
182
186
183 def _decpath(self, path):
187 def _decpath(self, path):
184 for c in strutil.findall(path, '/'):
188 for c in strutil.findall(path, '/'):
185 pc = path[:c]
189 pc = path[:c]
186 self._dirs.setdefault(pc, 0)
190 self._dirs.setdefault(pc, 0)
187 self._dirs[pc] -= 1
191 self._dirs[pc] -= 1
188
192
189 def _incpathcheck(self, f):
193 def _incpathcheck(self, f):
190 if '\r' in f or '\n' in f:
194 if '\r' in f or '\n' in f:
191 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames"))
195 raise util.Abort(_("'\\n' and '\\r' disallowed in filenames"))
192 # shadows
196 # shadows
193 if f in self._dirs:
197 if f in self._dirs:
194 raise util.Abort(_('directory named %r already in dirstate') % f)
198 raise util.Abort(_('directory named %r already in dirstate') % f)
195 for c in strutil.rfindall(f, '/'):
199 for c in strutil.rfindall(f, '/'):
196 d = f[:c]
200 d = f[:c]
197 if d in self._dirs:
201 if d in self._dirs:
198 break
202 break
199 if d in self._map:
203 if d in self._map:
200 raise util.Abort(_('file named %r already in dirstate') % d)
204 raise util.Abort(_('file named %r already in dirstate') % d)
201 self._incpath(f)
205 self._incpath(f)
202
206
203 def update(self, files, state, **kw):
207 def update(self, files, state, **kw):
204 ''' current states:
208 ''' current states:
205 n normal
209 n normal
206 m needs merging
210 m needs merging
207 r marked for removal
211 r marked for removal
208 a marked for addition'''
212 a marked for addition'''
209
213
210 if not files: return
214 if not files: return
211 self.markdirty()
215 self.markdirty()
212 for f in files:
216 for f in files:
213 if self._copymap.has_key(f):
217 if self._copymap.has_key(f):
214 del self._copymap[f]
218 del self._copymap[f]
215
219
216 if state == "r":
220 if state == "r":
217 self._map[f] = ('r', 0, 0, 0)
221 self._map[f] = ('r', 0, 0, 0)
218 self._decpath(f)
222 self._decpath(f)
219 continue
223 continue
220 else:
224 else:
221 if state == "a":
225 if state == "a":
222 self._incpathcheck(f)
226 self._incpathcheck(f)
223 s = os.lstat(self.wjoin(f))
227 s = os.lstat(self.wjoin(f))
224 st_size = kw.get('st_size', s.st_size)
228 st_size = kw.get('st_size', s.st_size)
225 st_mtime = kw.get('st_mtime', s.st_mtime)
229 st_mtime = kw.get('st_mtime', s.st_mtime)
226 self._map[f] = (state, s.st_mode, st_size, st_mtime)
230 self._map[f] = (state, s.st_mode, st_size, st_mtime)
227
231
228 def forget(self, files):
232 def forget(self, files):
229 if not files: return
233 if not files: return
230 self.markdirty()
234 self.markdirty()
231 for f in files:
235 for f in files:
232 try:
236 try:
233 del self._map[f]
237 del self._map[f]
234 self._decpath(f)
238 self._decpath(f)
235 except KeyError:
239 except KeyError:
236 self._ui.warn(_("not in dirstate: %s!\n") % f)
240 self._ui.warn(_("not in dirstate: %s!\n") % f)
237 pass
241 pass
238
242
239 def rebuild(self, parent, files):
243 def rebuild(self, parent, files):
240 self.invalidate()
244 self.invalidate()
241 for f in files:
245 for f in files:
242 if files.execf(f):
246 if files.execf(f):
243 self._map[f] = ('n', 0777, -1, 0)
247 self._map[f] = ('n', 0777, -1, 0)
244 else:
248 else:
245 self._map[f] = ('n', 0666, -1, 0)
249 self._map[f] = ('n', 0666, -1, 0)
246 self._pl = (parent, nullid)
250 self._pl = (parent, nullid)
247 self.markdirty()
251 self.markdirty()
248
252
249 def write(self):
253 def write(self):
250 if not self._dirty:
254 if not self._dirty:
251 return
255 return
252 cs = cStringIO.StringIO()
256 cs = cStringIO.StringIO()
253 cs.write("".join(self._pl))
257 cs.write("".join(self._pl))
254 for f, e in self._map.iteritems():
258 for f, e in self._map.iteritems():
255 c = self.copied(f)
259 c = self.copied(f)
256 if c:
260 if c:
257 f = f + "\0" + c
261 f = f + "\0" + c
258 e = struct.pack(_format, e[0], e[1], e[2], e[3], len(f))
262 e = struct.pack(_format, e[0], e[1], e[2], e[3], len(f))
259 cs.write(e)
263 cs.write(e)
260 cs.write(f)
264 cs.write(f)
261 st = self._opener("dirstate", "w", atomictemp=True)
265 st = self._opener("dirstate", "w", atomictemp=True)
262 st.write(cs.getvalue())
266 st.write(cs.getvalue())
263 st.rename()
267 st.rename()
264 self._dirty = 0
268 self._dirty = 0
269 self._dirtypl = 0
265
270
266 def filterfiles(self, files):
271 def filterfiles(self, files):
267 ret = {}
272 ret = {}
268 unknown = []
273 unknown = []
269
274
270 for x in files:
275 for x in files:
271 if x == '.':
276 if x == '.':
272 return self._map.copy()
277 return self._map.copy()
273 if x not in self._map:
278 if x not in self._map:
274 unknown.append(x)
279 unknown.append(x)
275 else:
280 else:
276 ret[x] = self._map[x]
281 ret[x] = self._map[x]
277
282
278 if not unknown:
283 if not unknown:
279 return ret
284 return ret
280
285
281 b = self._map.keys()
286 b = self._map.keys()
282 b.sort()
287 b.sort()
283 blen = len(b)
288 blen = len(b)
284
289
285 for x in unknown:
290 for x in unknown:
286 bs = bisect.bisect(b, "%s%s" % (x, '/'))
291 bs = bisect.bisect(b, "%s%s" % (x, '/'))
287 while bs < blen:
292 while bs < blen:
288 s = b[bs]
293 s = b[bs]
289 if len(s) > len(x) and s.startswith(x):
294 if len(s) > len(x) and s.startswith(x):
290 ret[s] = self._map[s]
295 ret[s] = self._map[s]
291 else:
296 else:
292 break
297 break
293 bs += 1
298 bs += 1
294 return ret
299 return ret
295
300
296 def _supported(self, f, st, verbose=False):
301 def _supported(self, f, st, verbose=False):
297 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
302 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
298 return True
303 return True
299 if verbose:
304 if verbose:
300 kind = 'unknown'
305 kind = 'unknown'
301 if stat.S_ISCHR(st.st_mode): kind = _('character device')
306 if stat.S_ISCHR(st.st_mode): kind = _('character device')
302 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
307 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
303 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
308 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
304 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
309 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
305 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
310 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
306 self._ui.warn(_('%s: unsupported file type (type is %s)\n')
311 self._ui.warn(_('%s: unsupported file type (type is %s)\n')
307 % (self.pathto(f), kind))
312 % (self.pathto(f), kind))
308 return False
313 return False
309
314
310 def walk(self, files=None, match=util.always, badmatch=None):
315 def walk(self, files=None, match=util.always, badmatch=None):
311 # filter out the stat
316 # filter out the stat
312 for src, f, st in self.statwalk(files, match, badmatch=badmatch):
317 for src, f, st in self.statwalk(files, match, badmatch=badmatch):
313 yield src, f
318 yield src, f
314
319
315 def statwalk(self, files=None, match=util.always, ignored=False,
320 def statwalk(self, files=None, match=util.always, ignored=False,
316 badmatch=None, directories=False):
321 badmatch=None, directories=False):
317 '''
322 '''
318 walk recursively through the directory tree, finding all files
323 walk recursively through the directory tree, finding all files
319 matched by the match function
324 matched by the match function
320
325
321 results are yielded in a tuple (src, filename, st), where src
326 results are yielded in a tuple (src, filename, st), where src
322 is one of:
327 is one of:
323 'f' the file was found in the directory tree
328 'f' the file was found in the directory tree
324 'd' the file is a directory of the tree
329 'd' the file is a directory of the tree
325 'm' the file was only in the dirstate and not in the tree
330 'm' the file was only in the dirstate and not in the tree
326 'b' file was not found and matched badmatch
331 'b' file was not found and matched badmatch
327
332
328 and st is the stat result if the file was found in the directory.
333 and st is the stat result if the file was found in the directory.
329 '''
334 '''
330
335
331 # walk all files by default
336 # walk all files by default
332 if not files:
337 if not files:
333 files = ['.']
338 files = ['.']
334 dc = self._map.copy()
339 dc = self._map.copy()
335 else:
340 else:
336 files = util.unique(files)
341 files = util.unique(files)
337 dc = self.filterfiles(files)
342 dc = self.filterfiles(files)
338
343
339 def imatch(file_):
344 def imatch(file_):
340 if file_ not in dc and self._ignore(file_):
345 if file_ not in dc and self._ignore(file_):
341 return False
346 return False
342 return match(file_)
347 return match(file_)
343
348
344 ignore = self._ignore
349 ignore = self._ignore
345 if ignored:
350 if ignored:
346 imatch = match
351 imatch = match
347 ignore = util.never
352 ignore = util.never
348
353
349 # self._root may end with a path separator when self._root == '/'
354 # self._root may end with a path separator when self._root == '/'
350 common_prefix_len = len(self._root)
355 common_prefix_len = len(self._root)
351 if not self._root.endswith(os.sep):
356 if not self._root.endswith(os.sep):
352 common_prefix_len += 1
357 common_prefix_len += 1
353 # recursion free walker, faster than os.walk.
358 # recursion free walker, faster than os.walk.
354 def findfiles(s):
359 def findfiles(s):
355 work = [s]
360 work = [s]
356 if directories:
361 if directories:
357 yield 'd', util.normpath(s[common_prefix_len:]), os.lstat(s)
362 yield 'd', util.normpath(s[common_prefix_len:]), os.lstat(s)
358 while work:
363 while work:
359 top = work.pop()
364 top = work.pop()
360 names = os.listdir(top)
365 names = os.listdir(top)
361 names.sort()
366 names.sort()
362 # nd is the top of the repository dir tree
367 # nd is the top of the repository dir tree
363 nd = util.normpath(top[common_prefix_len:])
368 nd = util.normpath(top[common_prefix_len:])
364 if nd == '.':
369 if nd == '.':
365 nd = ''
370 nd = ''
366 else:
371 else:
367 # do not recurse into a repo contained in this
372 # do not recurse into a repo contained in this
368 # one. use bisect to find .hg directory so speed
373 # one. use bisect to find .hg directory so speed
369 # is good on big directory.
374 # is good on big directory.
370 hg = bisect.bisect_left(names, '.hg')
375 hg = bisect.bisect_left(names, '.hg')
371 if hg < len(names) and names[hg] == '.hg':
376 if hg < len(names) and names[hg] == '.hg':
372 if os.path.isdir(os.path.join(top, '.hg')):
377 if os.path.isdir(os.path.join(top, '.hg')):
373 continue
378 continue
374 for f in names:
379 for f in names:
375 np = util.pconvert(os.path.join(nd, f))
380 np = util.pconvert(os.path.join(nd, f))
376 if seen(np):
381 if seen(np):
377 continue
382 continue
378 p = os.path.join(top, f)
383 p = os.path.join(top, f)
379 # don't trip over symlinks
384 # don't trip over symlinks
380 st = os.lstat(p)
385 st = os.lstat(p)
381 if stat.S_ISDIR(st.st_mode):
386 if stat.S_ISDIR(st.st_mode):
382 if not ignore(np):
387 if not ignore(np):
383 work.append(p)
388 work.append(p)
384 if directories:
389 if directories:
385 yield 'd', np, st
390 yield 'd', np, st
386 if imatch(np) and np in dc:
391 if imatch(np) and np in dc:
387 yield 'm', np, st
392 yield 'm', np, st
388 elif imatch(np):
393 elif imatch(np):
389 if self._supported(np, st):
394 if self._supported(np, st):
390 yield 'f', np, st
395 yield 'f', np, st
391 elif np in dc:
396 elif np in dc:
392 yield 'm', np, st
397 yield 'm', np, st
393
398
394 known = {'.hg': 1}
399 known = {'.hg': 1}
395 def seen(fn):
400 def seen(fn):
396 if fn in known: return True
401 if fn in known: return True
397 known[fn] = 1
402 known[fn] = 1
398
403
399 # step one, find all files that match our criteria
404 # step one, find all files that match our criteria
400 files.sort()
405 files.sort()
401 for ff in files:
406 for ff in files:
402 nf = util.normpath(ff)
407 nf = util.normpath(ff)
403 f = self.wjoin(ff)
408 f = self.wjoin(ff)
404 try:
409 try:
405 st = os.lstat(f)
410 st = os.lstat(f)
406 except OSError, inst:
411 except OSError, inst:
407 found = False
412 found = False
408 for fn in dc:
413 for fn in dc:
409 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
414 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
410 found = True
415 found = True
411 break
416 break
412 if not found:
417 if not found:
413 if inst.errno != errno.ENOENT or not badmatch:
418 if inst.errno != errno.ENOENT or not badmatch:
414 self._ui.warn('%s: %s\n' %
419 self._ui.warn('%s: %s\n' %
415 (self.pathto(ff), inst.strerror))
420 (self.pathto(ff), inst.strerror))
416 elif badmatch and badmatch(ff) and imatch(nf):
421 elif badmatch and badmatch(ff) and imatch(nf):
417 yield 'b', ff, None
422 yield 'b', ff, None
418 continue
423 continue
419 if stat.S_ISDIR(st.st_mode):
424 if stat.S_ISDIR(st.st_mode):
420 cmp1 = (lambda x, y: cmp(x[1], y[1]))
425 cmp1 = (lambda x, y: cmp(x[1], y[1]))
421 sorted_ = [ x for x in findfiles(f) ]
426 sorted_ = [ x for x in findfiles(f) ]
422 sorted_.sort(cmp1)
427 sorted_.sort(cmp1)
423 for e in sorted_:
428 for e in sorted_:
424 yield e
429 yield e
425 else:
430 else:
426 if not seen(nf) and match(nf):
431 if not seen(nf) and match(nf):
427 if self._supported(ff, st, verbose=True):
432 if self._supported(ff, st, verbose=True):
428 yield 'f', nf, st
433 yield 'f', nf, st
429 elif ff in dc:
434 elif ff in dc:
430 yield 'm', nf, st
435 yield 'm', nf, st
431
436
432 # step two run through anything left in the dc hash and yield
437 # step two run through anything left in the dc hash and yield
433 # if we haven't already seen it
438 # if we haven't already seen it
434 ks = dc.keys()
439 ks = dc.keys()
435 ks.sort()
440 ks.sort()
436 for k in ks:
441 for k in ks:
437 if not seen(k) and imatch(k):
442 if not seen(k) and imatch(k):
438 yield 'm', k, None
443 yield 'm', k, None
439
444
440 def status(self, files=None, match=util.always, list_ignored=False,
445 def status(self, files=None, match=util.always, list_ignored=False,
441 list_clean=False):
446 list_clean=False):
442 lookup, modified, added, unknown, ignored = [], [], [], [], []
447 lookup, modified, added, unknown, ignored = [], [], [], [], []
443 removed, deleted, clean = [], [], []
448 removed, deleted, clean = [], [], []
444
449
445 for src, fn, st in self.statwalk(files, match, ignored=list_ignored):
450 for src, fn, st in self.statwalk(files, match, ignored=list_ignored):
446 try:
451 try:
447 type_, mode, size, time = self[fn]
452 type_, mode, size, time = self[fn]
448 except KeyError:
453 except KeyError:
449 if list_ignored and self._ignore(fn):
454 if list_ignored and self._ignore(fn):
450 ignored.append(fn)
455 ignored.append(fn)
451 else:
456 else:
452 unknown.append(fn)
457 unknown.append(fn)
453 continue
458 continue
454 if src == 'm':
459 if src == 'm':
455 nonexistent = True
460 nonexistent = True
456 if not st:
461 if not st:
457 try:
462 try:
458 st = os.lstat(self.wjoin(fn))
463 st = os.lstat(self.wjoin(fn))
459 except OSError, inst:
464 except OSError, inst:
460 if inst.errno != errno.ENOENT:
465 if inst.errno != errno.ENOENT:
461 raise
466 raise
462 st = None
467 st = None
463 # We need to re-check that it is a valid file
468 # We need to re-check that it is a valid file
464 if st and self._supported(fn, st):
469 if st and self._supported(fn, st):
465 nonexistent = False
470 nonexistent = False
466 # XXX: what to do with file no longer present in the fs
471 # XXX: what to do with file no longer present in the fs
467 # who are not removed in the dirstate ?
472 # who are not removed in the dirstate ?
468 if nonexistent and type_ in "nm":
473 if nonexistent and type_ in "nm":
469 deleted.append(fn)
474 deleted.append(fn)
470 continue
475 continue
471 # check the common case first
476 # check the common case first
472 if type_ == 'n':
477 if type_ == 'n':
473 if not st:
478 if not st:
474 st = os.lstat(self.wjoin(fn))
479 st = os.lstat(self.wjoin(fn))
475 if (size >= 0 and (size != st.st_size
480 if (size >= 0 and (size != st.st_size
476 or (mode ^ st.st_mode) & 0100)
481 or (mode ^ st.st_mode) & 0100)
477 or fn in self._copymap):
482 or fn in self._copymap):
478 modified.append(fn)
483 modified.append(fn)
479 elif time != int(st.st_mtime):
484 elif time != int(st.st_mtime):
480 lookup.append(fn)
485 lookup.append(fn)
481 elif list_clean:
486 elif list_clean:
482 clean.append(fn)
487 clean.append(fn)
483 elif type_ == 'm':
488 elif type_ == 'm':
484 modified.append(fn)
489 modified.append(fn)
485 elif type_ == 'a':
490 elif type_ == 'a':
486 added.append(fn)
491 added.append(fn)
487 elif type_ == 'r':
492 elif type_ == 'r':
488 removed.append(fn)
493 removed.append(fn)
489
494
490 return (lookup, modified, added, removed, deleted, unknown, ignored,
495 return (lookup, modified, added, removed, deleted, unknown, ignored,
491 clean)
496 clean)
General Comments 0
You need to be logged in to leave comments. Login now