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