mercurial/dirstate.py
changeset 7093 16bafcebd3d1
parent 7069 852f39691a0a
child 7096 6dab29f6df37
equal deleted inserted replaced
7092:fb3fc27617a2 7093:16bafcebd3d1
     8 """
     8 """
     9 
     9 
    10 from node import nullid
    10 from node import nullid
    11 from i18n import _
    11 from i18n import _
    12 import struct, os, stat, util, errno, ignore
    12 import struct, os, stat, util, errno, ignore
    13 import cStringIO, osutil, sys
    13 import cStringIO, osutil, sys, parsers
    14 
    14 
    15 _unknown = ('?', 0, 0, 0)
    15 _unknown = ('?', 0, 0, 0)
    16 _format = ">cllll"
    16 _format = ">cllll"
    17 
    17 
    18 def _finddirs(path):
    18 def _finddirs(path):
   188         self._opener("branch", "w").write(branch + '\n')
   188         self._opener("branch", "w").write(branch + '\n')
   189 
   189 
   190     def _read(self):
   190     def _read(self):
   191         self._map = {}
   191         self._map = {}
   192         self._copymap = {}
   192         self._copymap = {}
   193         if not self._dirtypl:
       
   194             self._pl = [nullid, nullid]
       
   195         try:
   193         try:
   196             st = self._opener("dirstate").read()
   194             st = self._opener("dirstate").read()
   197         except IOError, err:
   195         except IOError, err:
   198             if err.errno != errno.ENOENT: raise
   196             if err.errno != errno.ENOENT: raise
   199             return
   197             return
   200         if not st:
   198         if not st:
   201             return
   199             return
   202 
   200 
       
   201         p = parsers.parse_dirstate(self._map, self._copymap, st);
   203         if not self._dirtypl:
   202         if not self._dirtypl:
   204             self._pl = [st[:20], st[20: 40]]
   203             self._pl = p
   205 
       
   206         # deref fields so they will be local in loop
       
   207         dmap = self._map
       
   208         copymap = self._copymap
       
   209         unpack = struct.unpack
       
   210         e_size = struct.calcsize(_format)
       
   211         pos1 = 40
       
   212         l = len(st)
       
   213 
       
   214         # the inner loop
       
   215         while pos1 < l:
       
   216             pos2 = pos1 + e_size
       
   217             e = unpack(">cllll", st[pos1:pos2]) # a literal here is faster
       
   218             pos1 = pos2 + e[4]
       
   219             f = st[pos2:pos1]
       
   220             if '\0' in f:
       
   221                 f, c = f.split('\0')
       
   222                 copymap[f] = c
       
   223             dmap[f] = e # we hold onto e[4] because making a subtuple is slow
       
   224 
   204 
   225     def invalidate(self):
   205     def invalidate(self):
   226         for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split():
   206         for a in "_map _copymap _foldmap _branch _pl _dirs _ignore".split():
   227             if a in self.__dict__:
   207             if a in self.__dict__:
   228                 delattr(self, a)
   208                 delattr(self, a)
   272     def normal(self, f):
   252     def normal(self, f):
   273         'mark a file normal and clean'
   253         'mark a file normal and clean'
   274         self._dirty = True
   254         self._dirty = True
   275         self._addpath(f)
   255         self._addpath(f)
   276         s = os.lstat(self._join(f))
   256         s = os.lstat(self._join(f))
   277         self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0)
   257         self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime)
   278         if f in self._copymap:
   258         if f in self._copymap:
   279             del self._copymap[f]
   259             del self._copymap[f]
   280 
   260 
   281     def normallookup(self, f):
   261     def normallookup(self, f):
   282         'mark a file normal, but possibly dirty'
   262         'mark a file normal, but possibly dirty'
   295                 return
   275                 return
   296             if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
   276             if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
   297                 return
   277                 return
   298         self._dirty = True
   278         self._dirty = True
   299         self._addpath(f)
   279         self._addpath(f)
   300         self._map[f] = ('n', 0, -1, -1, 0)
   280         self._map[f] = ('n', 0, -1, -1)
   301         if f in self._copymap:
   281         if f in self._copymap:
   302             del self._copymap[f]
   282             del self._copymap[f]
   303 
   283 
   304     def normaldirty(self, f):
   284     def normaldirty(self, f):
   305         'mark a file normal, but dirty'
   285         'mark a file normal, but dirty'
   306         self._dirty = True
   286         self._dirty = True
   307         self._addpath(f)
   287         self._addpath(f)
   308         self._map[f] = ('n', 0, -2, -1, 0)
   288         self._map[f] = ('n', 0, -2, -1)
   309         if f in self._copymap:
   289         if f in self._copymap:
   310             del self._copymap[f]
   290             del self._copymap[f]
   311 
   291 
   312     def add(self, f):
   292     def add(self, f):
   313         'mark a file added'
   293         'mark a file added'
   314         self._dirty = True
   294         self._dirty = True
   315         self._addpath(f, True)
   295         self._addpath(f, True)
   316         self._map[f] = ('a', 0, -1, -1, 0)
   296         self._map[f] = ('a', 0, -1, -1)
   317         if f in self._copymap:
   297         if f in self._copymap:
   318             del self._copymap[f]
   298             del self._copymap[f]
   319 
   299 
   320     def remove(self, f):
   300     def remove(self, f):
   321         'mark a file removed'
   301         'mark a file removed'
   326             entry = self._map[f]
   306             entry = self._map[f]
   327             if entry[0] == 'm':
   307             if entry[0] == 'm':
   328                 size = -1
   308                 size = -1
   329             elif entry[0] == 'n' and entry[2] == -2:
   309             elif entry[0] == 'n' and entry[2] == -2:
   330                 size = -2
   310                 size = -2
   331         self._map[f] = ('r', 0, size, 0, 0)
   311         self._map[f] = ('r', 0, size, 0)
   332         if size == 0 and f in self._copymap:
   312         if size == 0 and f in self._copymap:
   333             del self._copymap[f]
   313             del self._copymap[f]
   334 
   314 
   335     def merge(self, f):
   315     def merge(self, f):
   336         'mark a file merged'
   316         'mark a file merged'
   337         self._dirty = True
   317         self._dirty = True
   338         s = os.lstat(self._join(f))
   318         s = os.lstat(self._join(f))
   339         self._addpath(f)
   319         self._addpath(f)
   340         self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0)
   320         self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime)
   341         if f in self._copymap:
   321         if f in self._copymap:
   342             del self._copymap[f]
   322             del self._copymap[f]
   343 
   323 
   344     def forget(self, f):
   324     def forget(self, f):
   345         'forget a file'
   325         'forget a file'
   371 
   351 
   372     def rebuild(self, parent, files):
   352     def rebuild(self, parent, files):
   373         self.clear()
   353         self.clear()
   374         for f in files:
   354         for f in files:
   375             if 'x' in files.flags(f):
   355             if 'x' in files.flags(f):
   376                 self._map[f] = ('n', 0777, -1, 0, 0)
   356                 self._map[f] = ('n', 0777, -1, 0)
   377             else:
   357             else:
   378                 self._map[f] = ('n', 0666, -1, 0, 0)
   358                 self._map[f] = ('n', 0666, -1, 0)
   379         self._pl = (parent, nullid)
   359         self._pl = (parent, nullid)
   380         self._dirty = True
   360         self._dirty = True
   381 
   361 
   382     def write(self):
   362     def write(self):
   383         if not self._dirty:
   363         if not self._dirty:
   399         write("".join(self._pl))
   379         write("".join(self._pl))
   400         for f, e in self._map.iteritems():
   380         for f, e in self._map.iteritems():
   401             if f in copymap:
   381             if f in copymap:
   402                 f = "%s\0%s" % (f, copymap[f])
   382                 f = "%s\0%s" % (f, copymap[f])
   403             if e[3] > limit and e[0] == 'n':
   383             if e[3] > limit and e[0] == 'n':
   404                 e = (e[0], 0, -1, -1, 0)
   384                 e = (e[0], 0, -1, -1)
   405             e = pack(_format, e[0], e[1], e[2], e[3], len(f))
   385             e = pack(_format, e[0], e[1], e[2], e[3], len(f))
   406             write(e)
   386             write(e)
   407             write(f)
   387             write(f)
   408         st.write(cs.getvalue())
   388         st.write(cs.getvalue())
   409         st.rename()
   389         st.rename()
   575                         iadd(fn)
   555                         iadd(fn)
   576                 elif listunknown:
   556                 elif listunknown:
   577                     uadd(fn)
   557                     uadd(fn)
   578                 continue
   558                 continue
   579 
   559 
   580             state, mode, size, time, foo = dmap[fn]
   560             state, mode, size, time = dmap[fn]
   581 
   561 
   582             if not st and state in "nma":
   562             if not st and state in "nma":
   583                 dadd(fn)
   563                 dadd(fn)
   584             elif state == 'n':
   564             elif state == 'n':
   585                 if (size >= 0 and
   565                 if (size >= 0 and