Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/hg.py @ 723:9e0f3ba4a9c2
Work on walk code.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Sat, 16 Jul 2005 15:13:40 -0800 |
parents | 574869103985 |
children | 1c0c413cccdd |
comparison
equal
deleted
inserted
replaced
705:574869103985 | 723:9e0f3ba4a9c2 |
---|---|
10 from revlog import * | 10 from revlog import * |
11 from demandload import * | 11 from demandload import * |
12 demandload(globals(), "re lock urllib urllib2 transaction time socket") | 12 demandload(globals(), "re lock urllib urllib2 transaction time socket") |
13 demandload(globals(), "tempfile httprangereader bdiff") | 13 demandload(globals(), "tempfile httprangereader bdiff") |
14 demandload(globals(), "bisect select") | 14 demandload(globals(), "bisect select") |
15 | |
16 def always(fn): | |
17 return True | |
15 | 18 |
16 class filelog(revlog): | 19 class filelog(revlog): |
17 def __init__(self, opener, path): | 20 def __init__(self, opener, path): |
18 revlog.__init__(self, opener, | 21 revlog.__init__(self, opener, |
19 os.path.join("data", path + ".i"), | 22 os.path.join("data", path + ".i"), |
274 self.dirty = 0 | 277 self.dirty = 0 |
275 self.ui = ui | 278 self.ui = ui |
276 self.map = None | 279 self.map = None |
277 self.pl = None | 280 self.pl = None |
278 self.copies = {} | 281 self.copies = {} |
282 self.ignorefunc = None | |
283 | |
284 def wjoin(self, f): | |
285 return os.path.join(self.root, f) | |
286 | |
287 def ignore(self, f): | |
288 if not self.ignorefunc: | |
289 bigpat = [] | |
290 try: | |
291 l = file(self.wjoin(".hgignore")) | |
292 for pat in l: | |
293 if pat != "\n": | |
294 p = util.pconvert(pat[:-1]) | |
295 try: | |
296 r = re.compile(p) | |
297 except: | |
298 self.ui.warn("ignoring invalid ignore" | |
299 + " regular expression '%s'\n" % p) | |
300 else: | |
301 bigpat.append(util.pconvert(pat[:-1])) | |
302 except IOError: pass | |
303 | |
304 s = "(?:%s)" % (")|(?:".join(bigpat)) | |
305 r = re.compile(s) | |
306 self.ignorefunc = r.search | |
307 | |
308 return self.ignorefunc(f) | |
279 | 309 |
280 def __del__(self): | 310 def __del__(self): |
281 if self.dirty: | 311 if self.dirty: |
282 self.write() | 312 self.write() |
283 | 313 |
295 def parents(self): | 325 def parents(self): |
296 if not self.pl: | 326 if not self.pl: |
297 self.read() | 327 self.read() |
298 return self.pl | 328 return self.pl |
299 | 329 |
330 def markdirty(self): | |
331 if not self.dirty: | |
332 self.dirty = 1 | |
333 | |
300 def setparents(self, p1, p2 = nullid): | 334 def setparents(self, p1, p2 = nullid): |
301 self.dirty = 1 | 335 self.markdirty() |
302 self.pl = p1, p2 | 336 self.pl = p1, p2 |
303 | 337 |
304 def state(self, key): | 338 def state(self, key): |
305 try: | 339 try: |
306 return self[key][0] | 340 return self[key][0] |
331 self.map[f] = e[:4] | 365 self.map[f] = e[:4] |
332 pos += l | 366 pos += l |
333 | 367 |
334 def copy(self, source, dest): | 368 def copy(self, source, dest): |
335 self.read() | 369 self.read() |
336 self.dirty = 1 | 370 self.markdirty() |
337 self.copies[dest] = source | 371 self.copies[dest] = source |
338 | 372 |
339 def copied(self, file): | 373 def copied(self, file): |
340 return self.copies.get(file, None) | 374 return self.copies.get(file, None) |
341 | 375 |
346 r marked for removal | 380 r marked for removal |
347 a marked for addition''' | 381 a marked for addition''' |
348 | 382 |
349 if not files: return | 383 if not files: return |
350 self.read() | 384 self.read() |
351 self.dirty = 1 | 385 self.markdirty() |
352 for f in files: | 386 for f in files: |
353 if state == "r": | 387 if state == "r": |
354 self.map[f] = ('r', 0, 0, 0) | 388 self.map[f] = ('r', 0, 0, 0) |
355 else: | 389 else: |
356 s = os.stat(os.path.join(self.root, f)) | 390 s = os.stat(os.path.join(self.root, f)) |
357 self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime) | 391 self.map[f] = (state, s.st_mode, s.st_size, s.st_mtime) |
358 | 392 |
359 def forget(self, files): | 393 def forget(self, files): |
360 if not files: return | 394 if not files: return |
361 self.read() | 395 self.read() |
362 self.dirty = 1 | 396 self.markdirty() |
363 for f in files: | 397 for f in files: |
364 try: | 398 try: |
365 del self.map[f] | 399 del self.map[f] |
366 except KeyError: | 400 except KeyError: |
367 self.ui.warn("not in dirstate: %s!\n" % f) | 401 self.ui.warn("not in dirstate: %s!\n" % f) |
368 pass | 402 pass |
369 | 403 |
370 def clear(self): | 404 def clear(self): |
371 self.map = {} | 405 self.map = {} |
372 self.dirty = 1 | 406 self.markdirty() |
373 | 407 |
374 def write(self): | 408 def write(self): |
375 st = self.opener("dirstate", "w") | 409 st = self.opener("dirstate", "w") |
376 st.write("".join(self.pl)) | 410 st.write("".join(self.pl)) |
377 for f, e in self.map.items(): | 411 for f, e in self.map.items(): |
380 f = f + "\0" + c | 414 f = f + "\0" + c |
381 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) | 415 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
382 st.write(e + f) | 416 st.write(e + f) |
383 self.dirty = 0 | 417 self.dirty = 0 |
384 | 418 |
385 def changes(self, files, ignore): | 419 def walk(self, files = None, match = always): |
386 self.read() | 420 self.read() |
387 dc = self.map.copy() | 421 dc = self.map.copy() |
388 lookup, changed, added, unknown = [], [], [], [] | 422 # walk all files by default |
389 | |
390 # compare all files by default | |
391 if not files: files = [self.root] | 423 if not files: files = [self.root] |
392 | 424 def traverse(): |
393 # recursive generator of all files listed | |
394 def walk(files): | |
395 for f in util.unique(files): | 425 for f in util.unique(files): |
396 f = os.path.join(self.root, f) | 426 f = os.path.join(self.root, f) |
397 if os.path.isdir(f): | 427 if os.path.isdir(f): |
398 for dir, subdirs, fl in os.walk(f): | 428 for dir, subdirs, fl in os.walk(f): |
399 d = dir[len(self.root) + 1:] | 429 d = dir[len(self.root) + 1:] |
430 if d == '.hg': | |
431 subdirs[:] = [] | |
432 continue | |
400 for sd in subdirs: | 433 for sd in subdirs: |
401 if ignore(os.path.join(d, sd +'/')): | 434 ds = os.path.join(d, sd +'/') |
435 if self.ignore(ds) or not match(ds): | |
402 subdirs.remove(sd) | 436 subdirs.remove(sd) |
403 for fn in fl: | 437 for fn in fl: |
404 fn = util.pconvert(os.path.join(d, fn)) | 438 fn = util.pconvert(os.path.join(d, fn)) |
405 yield fn | 439 yield fn |
406 else: | 440 else: |
407 yield f[len(self.root) + 1:] | 441 yield f[len(self.root) + 1:] |
408 | 442 |
409 for k in dc.keys(): | 443 for k in dc.keys(): |
410 yield k | 444 yield k |
411 | 445 |
412 for fn in util.unique(walk(files)): | 446 # yield only files that match: all in dirstate, others only if |
447 # not in .hgignore | |
448 | |
449 for fn in util.unique(traverse()): | |
450 if fn in dc: | |
451 del dc[fn] | |
452 elif self.ignore(fn): | |
453 continue | |
454 if match(fn): | |
455 yield fn | |
456 | |
457 def changes(self, files = None, match = always): | |
458 self.read() | |
459 dc = self.map.copy() | |
460 lookup, changed, added, unknown = [], [], [], [] | |
461 | |
462 for fn in self.walk(files, match): | |
413 try: s = os.stat(os.path.join(self.root, fn)) | 463 try: s = os.stat(os.path.join(self.root, fn)) |
414 except: continue | 464 except: continue |
415 | 465 |
416 if fn in dc: | 466 if fn in dc: |
417 c = dc[fn] | 467 c = dc[fn] |
426 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: | 476 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: |
427 changed.append(fn) | 477 changed.append(fn) |
428 elif c[1] != s.st_mode or c[3] != s.st_mtime: | 478 elif c[1] != s.st_mode or c[3] != s.st_mtime: |
429 lookup.append(fn) | 479 lookup.append(fn) |
430 else: | 480 else: |
431 if not ignore(fn): unknown.append(fn) | 481 if match(fn): unknown.append(fn) |
432 | 482 |
433 return (lookup, changed, added, dc.keys(), unknown) | 483 return (lookup, changed, added, dc.keys(), unknown) |
434 | 484 |
435 # used to avoid circular references so destructors work | 485 # used to avoid circular references so destructors work |
436 def opener(base): | 486 def opener(base): |
490 | 540 |
491 self.opener = opener(self.path) | 541 self.opener = opener(self.path) |
492 self.wopener = opener(self.root) | 542 self.wopener = opener(self.root) |
493 self.manifest = manifest(self.opener) | 543 self.manifest = manifest(self.opener) |
494 self.changelog = changelog(self.opener) | 544 self.changelog = changelog(self.opener) |
495 self.ignorefunc = None | |
496 self.tagscache = None | 545 self.tagscache = None |
497 self.nodetagscache = None | 546 self.nodetagscache = None |
498 | 547 |
499 if not self.remote: | 548 if not self.remote: |
500 self.dirstate = dirstate(self.opener, ui, self.root) | 549 self.dirstate = dirstate(self.opener, ui, self.root) |
501 try: | 550 try: |
502 self.ui.readconfig(self.opener("hgrc")) | 551 self.ui.readconfig(self.opener("hgrc")) |
503 except IOError: pass | 552 except IOError: pass |
504 | |
505 def ignore(self, f): | |
506 if not self.ignorefunc: | |
507 bigpat = ["^.hg/$"] | |
508 try: | |
509 l = file(self.wjoin(".hgignore")) | |
510 for pat in l: | |
511 if pat != "\n": | |
512 p = util.pconvert(pat[:-1]) | |
513 try: | |
514 r = re.compile(p) | |
515 except: | |
516 self.ui.warn("ignoring invalid ignore" | |
517 + " regular expression '%s'\n" % p) | |
518 else: | |
519 bigpat.append(util.pconvert(pat[:-1])) | |
520 except IOError: pass | |
521 | |
522 s = "(?:%s)" % (")|(?:".join(bigpat)) | |
523 r = re.compile(s) | |
524 self.ignorefunc = r.search | |
525 | |
526 return self.ignorefunc(f) | |
527 | 553 |
528 def hook(self, name, **args): | 554 def hook(self, name, **args): |
529 s = self.ui.config("hooks", name) | 555 s = self.ui.config("hooks", name) |
530 if s: | 556 if s: |
531 self.ui.note("running hook %s: %s\n" % (name, s)) | 557 self.ui.note("running hook %s: %s\n" % (name, s)) |
735 elif s == 'r': | 761 elif s == 'r': |
736 remove.append(f) | 762 remove.append(f) |
737 else: | 763 else: |
738 self.ui.warn("%s not tracked!\n" % f) | 764 self.ui.warn("%s not tracked!\n" % f) |
739 else: | 765 else: |
740 (c, a, d, u) = self.changes(None, None) | 766 (c, a, d, u) = self.changes() |
741 commit = c + a | 767 commit = c + a |
742 remove = d | 768 remove = d |
743 | 769 |
744 if not commit and not remove: | 770 if not commit and not remove: |
745 self.ui.status("nothing changed\n") | 771 self.ui.status("nothing changed\n") |
812 self.dirstate.forget(remove) | 838 self.dirstate.forget(remove) |
813 | 839 |
814 if not self.hook("commit", node=hex(n)): | 840 if not self.hook("commit", node=hex(n)): |
815 return 1 | 841 return 1 |
816 | 842 |
817 def changes(self, node1, node2, files=None): | 843 def walk(self, rev = None, files = [], match = always): |
844 if rev is None: fns = self.dirstate.walk(files, match) | |
845 else: fns = filter(match, self.manifest.read(rev)) | |
846 for fn in fns: yield fn | |
847 | |
848 def changes(self, node1 = None, node2 = None, files = [], match = always): | |
818 mf2, u = None, [] | 849 mf2, u = None, [] |
819 | 850 |
820 def fcmp(fn, mf): | 851 def fcmp(fn, mf): |
821 t1 = self.wfile(fn).read() | 852 t1 = self.wfile(fn).read() |
822 t2 = self.file(fn).revision(mf[fn]) | 853 t2 = self.file(fn).revision(mf[fn]) |
823 return cmp(t1, t2) | 854 return cmp(t1, t2) |
824 | 855 |
856 def mfmatches(node): | |
857 mf = dict(self.manifest.read(node)) | |
858 for fn in mf.keys(): | |
859 if not match(fn): | |
860 del mf[fn] | |
861 return mf | |
862 | |
825 # are we comparing the working directory? | 863 # are we comparing the working directory? |
826 if not node2: | 864 if not node2: |
827 l, c, a, d, u = self.dirstate.changes(files, self.ignore) | 865 l, c, a, d, u = self.dirstate.changes(files, match) |
828 | 866 |
829 # are we comparing working dir against its parent? | 867 # are we comparing working dir against its parent? |
830 if not node1: | 868 if not node1: |
831 if l: | 869 if l: |
832 # do a full compare of any files that might have changed | 870 # do a full compare of any files that might have changed |
833 change = self.changelog.read(self.dirstate.parents()[0]) | 871 change = self.changelog.read(self.dirstate.parents()[0]) |
834 mf2 = self.manifest.read(change[0]) | 872 mf2 = mfmatches(change[0]) |
835 for f in l: | 873 for f in l: |
836 if fcmp(f, mf2): | 874 if fcmp(f, mf2): |
837 c.append(f) | 875 c.append(f) |
838 | 876 |
839 for l in c, a, d, u: | 877 for l in c, a, d, u: |
844 # are we comparing working dir against non-tip? | 882 # are we comparing working dir against non-tip? |
845 # generate a pseudo-manifest for the working dir | 883 # generate a pseudo-manifest for the working dir |
846 if not node2: | 884 if not node2: |
847 if not mf2: | 885 if not mf2: |
848 change = self.changelog.read(self.dirstate.parents()[0]) | 886 change = self.changelog.read(self.dirstate.parents()[0]) |
849 mf2 = self.manifest.read(change[0]).copy() | 887 mf2 = mfmatches(change[0]) |
850 for f in a + c + l: | 888 for f in a + c + l: |
851 mf2[f] = "" | 889 mf2[f] = "" |
852 for f in d: | 890 for f in d: |
853 if f in mf2: del mf2[f] | 891 if f in mf2: del mf2[f] |
854 else: | 892 else: |
855 change = self.changelog.read(node2) | 893 change = self.changelog.read(node2) |
856 mf2 = self.manifest.read(change[0]) | 894 mf2 = mfmatches(change[0]) |
857 | 895 |
858 # flush lists from dirstate before comparing manifests | 896 # flush lists from dirstate before comparing manifests |
859 c, a = [], [] | 897 c, a = [], [] |
860 | 898 |
861 change = self.changelog.read(node1) | 899 change = self.changelog.read(node1) |
862 mf1 = self.manifest.read(change[0]).copy() | 900 mf1 = mfmatches(change[0]) |
863 | 901 |
864 for fn in mf2: | 902 for fn in mf2: |
865 if mf1.has_key(fn): | 903 if mf1.has_key(fn): |
866 if mf1[fn] != mf2[fn]: | 904 if mf1[fn] != mf2[fn]: |
867 if mf2[fn] != "" or fcmp(fn, mf1): | 905 if mf2[fn] != "" or fcmp(fn, mf1): |
1265 m2 = self.manifest.read(m2n) | 1303 m2 = self.manifest.read(m2n) |
1266 mf2 = self.manifest.readflags(m2n) | 1304 mf2 = self.manifest.readflags(m2n) |
1267 ma = self.manifest.read(man) | 1305 ma = self.manifest.read(man) |
1268 mfa = self.manifest.readflags(man) | 1306 mfa = self.manifest.readflags(man) |
1269 | 1307 |
1270 (c, a, d, u) = self.changes(None, None) | 1308 (c, a, d, u) = self.changes() |
1271 | 1309 |
1272 # is this a jump, or a merge? i.e. is there a linear path | 1310 # is this a jump, or a merge? i.e. is there a linear path |
1273 # from p1 to p2? | 1311 # from p1 to p2? |
1274 linear_path = (pa == p1 or pa == p2) | 1312 linear_path = (pa == p1 or pa == p2) |
1275 | 1313 |