248 return 'n' |
248 return 'n' |
249 if type_ == '?' and self.repo.dirstate._ignore(fn): |
249 if type_ == '?' and self.repo.dirstate._ignore(fn): |
250 return 'i' |
250 return 'i' |
251 return type_ |
251 return type_ |
252 |
252 |
253 def updatestatus(self, wfn, osstat=None, newstatus=None): |
253 def updatefile(self, wfn, osstat): |
|
254 ''' |
|
255 update the file entry of an existing file. |
|
256 |
|
257 osstat: (mode, size, time) tuple, as returned by os.lstat(wfn) |
|
258 ''' |
|
259 |
|
260 self._updatestatus(wfn, self.filestatus(wfn, osstat)) |
|
261 |
|
262 def deletefile(self, wfn, oldstatus): |
|
263 ''' |
|
264 update the entry of a file which has been deleted. |
|
265 |
|
266 oldstatus: char in statuskeys, status of the file before deletion |
|
267 ''' |
|
268 if oldstatus == 'r': |
|
269 newstatus = 'r' |
|
270 elif oldstatus in 'almn': |
|
271 newstatus = '!' |
|
272 else: |
|
273 newstatus = None |
|
274 |
|
275 self.statcache.pop(wfn, None) |
|
276 self._updatestatus(wfn, newstatus) |
|
277 |
|
278 def _updatestatus(self, wfn, newstatus): |
254 ''' |
279 ''' |
255 Update the stored status of a file or directory. |
280 Update the stored status of a file or directory. |
256 |
281 |
257 osstat: (mode, size, time) tuple, as returned by os.lstat(wfn) |
282 newstatus: - char in (statuskeys + 'ni'), new status to apply. |
258 |
283 - or None, to stop tracking wfn |
259 newstatus: char in statuskeys, new status to apply. |
|
260 ''' |
284 ''' |
261 if osstat: |
|
262 newstatus = self.filestatus(wfn, osstat) |
|
263 else: |
|
264 self.statcache.pop(wfn, None) |
|
265 root, fn = self.split(wfn) |
285 root, fn = self.split(wfn) |
266 d = self.dir(self.tree, root) |
286 d = self.dir(self.tree, root) |
|
287 |
267 oldstatus = d.get(fn) |
288 oldstatus = d.get(fn) |
268 isdir = False |
289 # oldstatus can be either: |
269 if oldstatus: |
290 # - None : fn is new |
270 try: |
291 # - a char in statuskeys: fn is a (tracked) file |
271 if not newstatus: |
292 # - a dict: fn is a directory |
272 if oldstatus in 'almn': |
293 isdir = isinstance(oldstatus, dict) |
273 newstatus = '!' |
294 |
274 elif oldstatus == 'r': |
|
275 newstatus = 'r' |
|
276 except TypeError: |
|
277 # oldstatus may be a dict left behind by a deleted |
|
278 # directory |
|
279 isdir = True |
|
280 else: |
|
281 if oldstatus in self.statuskeys and oldstatus != newstatus: |
|
282 del self.dir(self.statustrees[oldstatus], root)[fn] |
|
283 if self.ui.debugflag and oldstatus != newstatus: |
295 if self.ui.debugflag and oldstatus != newstatus: |
284 if isdir: |
296 if isdir: |
285 self.ui.note(_('status: %r dir(%d) -> %s\n') % |
297 self.ui.note(_('status: %r dir(%d) -> %s\n') % |
286 (wfn, len(oldstatus), newstatus)) |
298 (wfn, len(oldstatus), newstatus)) |
287 else: |
299 else: |
288 self.ui.note(_('status: %r %s -> %s\n') % |
300 self.ui.note(_('status: %r %s -> %s\n') % |
289 (wfn, oldstatus, newstatus)) |
301 (wfn, oldstatus, newstatus)) |
290 if not isdir: |
302 if not isdir: |
|
303 if oldstatus and oldstatus in self.statuskeys \ |
|
304 and oldstatus != newstatus: |
|
305 del self.dir(self.statustrees[oldstatus], root)[fn] |
291 if newstatus and newstatus != 'i': |
306 if newstatus and newstatus != 'i': |
292 d[fn] = newstatus |
307 d[fn] = newstatus |
293 if newstatus in self.statuskeys: |
308 if newstatus in self.statuskeys: |
294 dd = self.dir(self.statustrees[newstatus], root) |
309 dd = self.dir(self.statustrees[newstatus], root) |
295 if oldstatus != newstatus or fn not in dd: |
310 if oldstatus != newstatus or fn not in dd: |
297 else: |
312 else: |
298 d.pop(fn, None) |
313 d.pop(fn, None) |
299 elif not newstatus: |
314 elif not newstatus: |
300 # a directory is being removed, check its contents |
315 # a directory is being removed, check its contents |
301 for subfile, b in oldstatus.copy().iteritems(): |
316 for subfile, b in oldstatus.copy().iteritems(): |
302 self.updatestatus(wfn + '/' + subfile, None) |
317 self._updatestatus(wfn + '/' + subfile, None) |
303 |
318 |
304 |
319 |
305 def check_deleted(self, key): |
320 def check_deleted(self, key): |
306 # Files that had been deleted but were present in the dirstate |
321 # Files that had been deleted but were present in the dirstate |
307 # may have vanished from the dirstate; we must clean them up. |
322 # may have vanished from the dirstate; we must clean them up. |
323 self.add_watch(join(root, d), self.mask) |
338 self.add_watch(join(root, d), self.mask) |
324 wroot = root[len(self.wprefix):] |
339 wroot = root[len(self.wprefix):] |
325 d = self.dir(self.tree, wroot) |
340 d = self.dir(self.tree, wroot) |
326 for fn in files: |
341 for fn in files: |
327 wfn = join(wroot, fn) |
342 wfn = join(wroot, fn) |
328 self.updatestatus(wfn, self.getstat(wfn)) |
343 self.updatefile(wfn, self.getstat(wfn)) |
329 ds.pop(wfn, None) |
344 ds.pop(wfn, None) |
330 wtopdir = topdir |
345 wtopdir = topdir |
331 if wtopdir and wtopdir[-1] != '/': |
346 if wtopdir and wtopdir[-1] != '/': |
332 wtopdir += '/' |
347 wtopdir += '/' |
333 for wfn, state in ds.iteritems(): |
348 for wfn, state in ds.iteritems(): |
407 if wpath == '.hgignore': |
422 if wpath == '.hgignore': |
408 self.update_hgignore() |
423 self.update_hgignore() |
409 try: |
424 try: |
410 st = self.stat(wpath) |
425 st = self.stat(wpath) |
411 if stat.S_ISREG(st[0]): |
426 if stat.S_ISREG(st[0]): |
412 self.updatestatus(wpath, st) |
427 self.updatefile(wpath, st) |
413 except OSError: |
428 except OSError: |
414 pass |
429 pass |
415 |
430 |
416 def modified(self, wpath): |
431 def modified(self, wpath): |
417 if wpath == '.hgignore': |
432 if wpath == '.hgignore': |
418 self.update_hgignore() |
433 self.update_hgignore() |
419 try: |
434 try: |
420 st = self.stat(wpath) |
435 st = self.stat(wpath) |
421 if stat.S_ISREG(st[0]): |
436 if stat.S_ISREG(st[0]): |
422 if self.repo.dirstate[wpath] in 'lmn': |
437 if self.repo.dirstate[wpath] in 'lmn': |
423 self.updatestatus(wpath, st) |
438 self.updatefile(wpath, st) |
424 except OSError: |
439 except OSError: |
425 pass |
440 pass |
426 |
441 |
427 def deleted(self, wpath): |
442 def deleted(self, wpath): |
428 if wpath == '.hgignore': |
443 if wpath == '.hgignore': |
430 elif wpath.startswith('.hg/'): |
445 elif wpath.startswith('.hg/'): |
431 if wpath == '.hg/wlock': |
446 if wpath == '.hg/wlock': |
432 self.check_dirstate() |
447 self.check_dirstate() |
433 return |
448 return |
434 |
449 |
435 self.updatestatus(wpath, None) |
450 self.deletefile(wpath, self.repo.dirstate[wpath]) |
436 |
451 |
437 def schedule_work(self, wpath, evt): |
452 def schedule_work(self, wpath, evt): |
438 prev = self.eventq.setdefault(wpath, []) |
453 prev = self.eventq.setdefault(wpath, []) |
439 try: |
454 try: |
440 if prev and evt == 'm' and prev[-1] in 'cm': |
455 if prev and evt == 'm' and prev[-1] in 'cm': |