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