comparison mercurial/dirstate.py @ 4616:9b00b73a5286

dirstate: hide some more internals
author Matt Mackall <mpm@selenic.com>
date Mon, 18 Jun 2007 13:24:34 -0500
parents a8be3c875988
children 70352337934e
comparison
equal deleted inserted replaced
4615:a8be3c875988 4616:9b00b73a5286
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"
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.updatedirs(f, 1) 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')] + self._ui.hgignorefiles() 55 files = [self.wjoin('.hgignore')] + self._ui.hgignorefiles()
56 self._ignore = ignore.ignore(self._root, files, self._ui.warn) 56 self._ignore = ignore.ignore(self._root, files, self._ui.warn)
57 return self._ignore 57 return self._ignore
58 elif name == '_slash': 58 elif name == '_slash':
118 self._opener("branch", "w").write(branch + '\n') 118 self._opener("branch", "w").write(branch + '\n')
119 119
120 def state(self, key): 120 def state(self, key):
121 return self._map.get(key, ("?",))[0] 121 return self._map.get(key, ("?",))[0]
122 122
123 def read(self): 123 def _read(self):
124 self._map = {} 124 self._map = {}
125 self._copymap = {} 125 self._copymap = {}
126 self._pl = [nullid, nullid] 126 self._pl = [nullid, nullid]
127 try: 127 try:
128 st = self._opener("dirstate").read() 128 st = self._opener("dirstate").read()
154 copymap[f] = c 154 copymap[f] = c
155 dmap[f] = e[:4] 155 dmap[f] = e[:4]
156 pos = newpos 156 pos = newpos
157 157
158 def invalidate(self): 158 def invalidate(self):
159 for a in "_map _copymap _branch pl dirs _ignore".split(): 159 for a in "_map _copymap _branch pl _dirs _ignore".split():
160 if hasattr(self, a): 160 if hasattr(self, a):
161 self.__delattr__(a) 161 self.__delattr__(a)
162 162
163 def copy(self, source, dest): 163 def copy(self, source, dest):
164 self.markdirty() 164 self.markdirty()
168 return self._copymap.get(file, None) 168 return self._copymap.get(file, None)
169 169
170 def copies(self): 170 def copies(self):
171 return self._copymap 171 return self._copymap
172 172
173 def updatedirs(self, path, delta): 173 def _incpath(self, path):
174 for c in strutil.findall(path, '/'): 174 for c in strutil.findall(path, '/'):
175 pc = path[:c] 175 pc = path[:c]
176 self.dirs.setdefault(pc, 0) 176 self._dirs.setdefault(pc, 0)
177 self.dirs[pc] += delta 177 self._dirs[pc] += 1
178
179 def _decpath(self, path):
180 for c in strutil.findall(path, '/'):
181 pc = path[:c]
182 self._dirs.setdefault(pc, 0)
183 self._dirs[pc] -= 1
178 184
179 def checkinterfering(self, files): 185 def checkinterfering(self, files):
180 def prefixes(f): 186 def prefixes(f):
181 for c in strutil.rfindall(f, '/'): 187 for c in strutil.rfindall(f, '/'):
182 yield f[:c] 188 yield f[:c]
183 seendirs = {} 189 seendirs = {}
184 for f in files: 190 for f in files:
185 # shadows 191 # shadows
186 if self.dirs.get(f): 192 if self._dirs.get(f):
187 raise util.Abort(_('directory named %r already in dirstate') % 193 raise util.Abort(_('directory named %r already in dirstate') %
188 f) 194 f)
189 for d in prefixes(f): 195 for d in prefixes(f):
190 if d in seendirs: 196 if d in seendirs:
191 break 197 break
209 if state == "a": 215 if state == "a":
210 self.checkinterfering(files) 216 self.checkinterfering(files)
211 for f in files: 217 for f in files:
212 if state == "r": 218 if state == "r":
213 self._map[f] = ('r', 0, 0, 0) 219 self._map[f] = ('r', 0, 0, 0)
214 self.updatedirs(f, -1) 220 self._decpath(f)
215 else: 221 else:
216 if state == "a": 222 if state == "a":
217 self.updatedirs(f, 1) 223 self._incpath(f)
218 s = os.lstat(self.wjoin(f)) 224 s = os.lstat(self.wjoin(f))
219 st_size = kw.get('st_size', s.st_size) 225 st_size = kw.get('st_size', s.st_size)
220 st_mtime = kw.get('st_mtime', s.st_mtime) 226 st_mtime = kw.get('st_mtime', s.st_mtime)
221 self._map[f] = (state, s.st_mode, st_size, st_mtime) 227 self._map[f] = (state, s.st_mode, st_size, st_mtime)
222 if self._copymap.has_key(f): 228 if self._copymap.has_key(f):
226 if not files: return 232 if not files: return
227 self.markdirty() 233 self.markdirty()
228 for f in files: 234 for f in files:
229 try: 235 try:
230 del self._map[f] 236 del self._map[f]
231 self.updatedirs(f, -1) 237 self._decpath(f)
232 except KeyError: 238 except KeyError:
233 self._ui.warn(_("not in dirstate: %s!\n") % f) 239 self._ui.warn(_("not in dirstate: %s!\n") % f)
234 pass 240 pass
235 241
236 def rebuild(self, parent, files): 242 def rebuild(self, parent, files):
288 else: 294 else:
289 break 295 break
290 bs += 1 296 bs += 1
291 return ret 297 return ret
292 298
293 def supported_type(self, f, st, verbose=False): 299 def _supported(self, f, st, verbose=False):
294 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode): 300 if stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode):
295 return True 301 return True
296 if verbose: 302 if verbose:
297 kind = 'unknown' 303 kind = 'unknown'
298 if stat.S_ISCHR(st.st_mode): kind = _('character device') 304 if stat.S_ISCHR(st.st_mode): kind = _('character device')
381 if directories: 387 if directories:
382 yield 'd', np, st 388 yield 'd', np, st
383 if imatch(np) and np in dc: 389 if imatch(np) and np in dc:
384 yield 'm', np, st 390 yield 'm', np, st
385 elif imatch(np): 391 elif imatch(np):
386 if self.supported_type(np, st): 392 if self._supported(np, st):
387 yield 'f', np, st 393 yield 'f', np, st
388 elif np in dc: 394 elif np in dc:
389 yield 'm', np, st 395 yield 'm', np, st
390 396
391 known = {'.hg': 1} 397 known = {'.hg': 1}
419 sorted_.sort(cmp1) 425 sorted_.sort(cmp1)
420 for e in sorted_: 426 for e in sorted_:
421 yield e 427 yield e
422 else: 428 else:
423 if not seen(nf) and match(nf): 429 if not seen(nf) and match(nf):
424 if self.supported_type(ff, st, verbose=True): 430 if self._supported(ff, st, verbose=True):
425 yield 'f', nf, st 431 yield 'f', nf, st
426 elif ff in dc: 432 elif ff in dc:
427 yield 'm', nf, st 433 yield 'm', nf, st
428 434
429 # step two run through anything left in the dc hash and yield 435 # step two run through anything left in the dc hash and yield
456 except OSError, inst: 462 except OSError, inst:
457 if inst.errno != errno.ENOENT: 463 if inst.errno != errno.ENOENT:
458 raise 464 raise
459 st = None 465 st = None
460 # We need to re-check that it is a valid file 466 # We need to re-check that it is a valid file
461 if st and self.supported_type(fn, st): 467 if st and self._supported(fn, st):
462 nonexistent = False 468 nonexistent = False
463 # XXX: what to do with file no longer present in the fs 469 # XXX: what to do with file no longer present in the fs
464 # who are not removed in the dirstate ? 470 # who are not removed in the dirstate ?
465 if nonexistent and type_ in "nm": 471 if nonexistent and type_ in "nm":
466 deleted.append(fn) 472 deleted.append(fn)