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() |