hgext/inotify/server.py
changeset 8599 1f706b1b62f3
parent 8557 67f76a4463ef
child 8600 d46cdfcecaf1
equal deleted inserted replaced
8557:67f76a4463ef 8599:1f706b1b62f3
   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():
   335                 continue
   350                 continue
   336             try:
   351             try:
   337                 st = self.stat(wfn)
   352                 st = self.stat(wfn)
   338             except OSError:
   353             except OSError:
   339                 status = state[0]
   354                 status = state[0]
   340                 self.updatestatus(wfn, None, newstatus=status)
   355                 self.deletefile(wfn, status)
   341             else:
   356             else:
   342                 self.updatestatus(wfn, st)
   357                 self.updatefile(wfn, st)
   343         self.check_deleted('!')
   358         self.check_deleted('!')
   344         self.check_deleted('r')
   359         self.check_deleted('r')
   345 
   360 
   346     def check_dirstate(self):
   361     def check_dirstate(self):
   347         ds_info = self.dirstate_info()
   362         ds_info = self.dirstate_info()
   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':