286 f = f + "\0" + c |
286 f = f + "\0" + c |
287 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
287 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
288 st.write(e + f) |
288 st.write(e + f) |
289 self.dirty = 0 |
289 self.dirty = 0 |
290 |
290 |
291 def dup(self): |
291 def changes(self, files, ignore): |
292 self.read() |
292 self.read() |
293 return self.map.copy() |
293 dc = self.map.copy() |
|
294 lookup, changed, added, unknown = [], [], [], [] |
|
295 |
|
296 # compare all files by default |
|
297 if not files: files = [self.root] |
|
298 |
|
299 def uniq(g): |
|
300 seen = {} |
|
301 for f in g: |
|
302 if f not in seen: |
|
303 seen[f] = 1 |
|
304 yield f |
|
305 |
|
306 # recursive generator of all files listed |
|
307 def walk(files): |
|
308 for f in uniq(files): |
|
309 if os.path.isdir(f): |
|
310 for dir, subdirs, fl in os.walk(f): |
|
311 d = dir[len(self.root) + 1:] |
|
312 if ".hg" in subdirs: subdirs.remove(".hg") |
|
313 for fn in fl: |
|
314 fn = util.pconvert(os.path.join(d, fn)) |
|
315 yield fn |
|
316 else: |
|
317 yield f[len(self.root) + 1:] |
|
318 |
|
319 for fn in uniq(walk(files)): |
|
320 try: s = os.stat(os.path.join(self.root, fn)) |
|
321 except: continue |
|
322 |
|
323 if fn in dc: |
|
324 c = dc[fn] |
|
325 del dc[fn] |
|
326 |
|
327 if c[0] == 'm': |
|
328 changed.append(fn) |
|
329 elif c[0] == 'a': |
|
330 added.append(fn) |
|
331 elif c[0] == 'r': |
|
332 unknown.append(fn) |
|
333 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: |
|
334 changed.append(fn) |
|
335 elif c[1] != s.st_mode or c[3] != s.st_mtime: |
|
336 lookup.append(fn) |
|
337 else: |
|
338 if not ignore(fn): unknown.append(fn) |
|
339 |
|
340 return (lookup, changed, added, dc.keys(), unknown) |
294 |
341 |
295 # used to avoid circular references so destructors work |
342 # used to avoid circular references so destructors work |
296 def opener(base): |
343 def opener(base): |
297 p = base |
344 p = base |
298 def o(path, mode="r"): |
345 def o(path, mode="r"): |
642 |
689 |
643 self.dirstate.setparents(n) |
690 self.dirstate.setparents(n) |
644 self.dirstate.update(new, "n") |
691 self.dirstate.update(new, "n") |
645 self.dirstate.forget(remove) |
692 self.dirstate.forget(remove) |
646 |
693 |
647 def diffdir(self, path, changeset = None): |
694 def changes(self, node1, node2, *files): |
648 changed = [] |
695 # changed, added, deleted, unknown |
649 added = [] |
696 c, a, d, u, mf1 = [], [], [], [], None |
650 unknown = [] |
697 |
651 mf = {} |
698 def fcmp(fn, mf): |
652 |
|
653 if changeset: |
|
654 change = self.changelog.read(changeset) |
|
655 mf = self.manifest.read(change[0]) |
|
656 dc = dict.fromkeys(mf) |
|
657 else: |
|
658 changeset = self.dirstate.parents()[0] |
|
659 change = self.changelog.read(changeset) |
|
660 mf = self.manifest.read(change[0]) |
|
661 dc = self.dirstate.dup() |
|
662 |
|
663 def fcmp(fn): |
|
664 t1 = self.wfile(fn).read() |
699 t1 = self.wfile(fn).read() |
665 t2 = self.file(fn).revision(mf[fn]) |
700 t2 = self.file(fn).revision(mf[fn]) |
666 return cmp(t1, t2) |
701 return cmp(t1, t2) |
667 |
702 |
668 for dir, subdirs, files in os.walk(path): |
703 # are we comparing the working directory? |
669 d = dir[len(self.root)+1:] |
704 if not node1: |
670 if ".hg" in subdirs: subdirs.remove(".hg") |
705 l, c, a, d, u = self.dirstate.changes(files, self.ignore) |
671 |
706 |
672 for f in files: |
707 # are we comparing working dir against its parent? |
673 fn = util.pconvert(os.path.join(d, f)) |
708 if not node2: |
674 try: s = os.stat(os.path.join(self.root, fn)) |
709 if l: |
675 except: continue |
710 # do a full compare of any files that might have changed |
676 if fn in dc: |
711 change = self.changelog.read(self.dirstate.parents()[0]) |
677 c = dc[fn] |
712 mf1 = self.manifest.read(change[0]) |
678 del dc[fn] |
713 for f in lookup: |
679 if not c: |
714 if fcmp(f, mf): |
680 if fcmp(fn): |
715 c.append(f) |
681 changed.append(fn) |
716 return (c, a, d, u) |
682 elif c[0] == 'm': |
717 |
683 changed.append(fn) |
718 # are we comparing working dir against non-tip? |
684 elif c[0] == 'a': |
719 # generate a pseudo-manifest for the working dir |
685 added.append(fn) |
720 if not node1: |
686 elif c[0] == 'r': |
721 if not mf1: |
687 unknown.append(fn) |
722 change = self.changelog.read(self.dirstate.parents()[0]) |
688 elif c[2] != s.st_size or (c[1] ^ s.st_mode) & 0100: |
723 mf1 = self.manifest.read(change[0]) |
689 changed.append(fn) |
724 for f in a + c + l: |
690 elif c[1] != s.st_mode or c[3] != s.st_mtime: |
725 mf1[f] = "" |
691 if fcmp(fn): |
726 for f in d: |
692 changed.append(fn) |
727 if f in mf1: del mf1[f] |
693 else: |
728 else: |
694 if self.ignore(fn): continue |
729 change = self.changelog.read(node1) |
695 unknown.append(fn) |
730 mf1 = self.manifest.read(change[0]) |
696 |
731 |
697 deleted = dc.keys() |
|
698 deleted.sort() |
|
699 |
|
700 return (changed, added, deleted, unknown) |
|
701 |
|
702 def diffrevs(self, node1, node2): |
|
703 changed, added = [], [] |
|
704 |
|
705 change = self.changelog.read(node1) |
|
706 mf1 = self.manifest.read(change[0]) |
|
707 change = self.changelog.read(node2) |
732 change = self.changelog.read(node2) |
708 mf2 = self.manifest.read(change[0]) |
733 mf2 = self.manifest.read(change[0]) |
709 |
734 |
710 for fn in mf2: |
735 for fn in mf2: |
711 if mf1.has_key(fn): |
736 if mf1.has_key(fn): |
712 if mf1[fn] != mf2[fn]: |
737 if mf1[fn] != mf2[fn]: |
713 changed.append(fn) |
738 if mf1[fn] != "" or fcmp(fn, mf2): |
|
739 c.append(fn) |
714 del mf1[fn] |
740 del mf1[fn] |
715 else: |
741 else: |
716 added.append(fn) |
742 a.append(fn) |
717 |
743 |
718 deleted = mf1.keys() |
744 d = mf1.keys() |
719 deleted.sort() |
745 d.sort() |
720 |
746 |
721 return (changed, added, deleted) |
747 return (c, a, d, u) |
722 |
748 |
723 def add(self, list): |
749 def add(self, list): |
724 for f in list: |
750 for f in list: |
725 p = self.wjoin(f) |
751 p = self.wjoin(f) |
726 if not os.path.isfile(p): |
752 if not os.path.isfile(p): |
1042 m2 = self.manifest.read(m2n) |
1068 m2 = self.manifest.read(m2n) |
1043 mf2 = self.manifest.readflags(m2n) |
1069 mf2 = self.manifest.readflags(m2n) |
1044 ma = self.manifest.read(man) |
1070 ma = self.manifest.read(man) |
1045 mfa = self.manifest.readflags(man) |
1071 mfa = self.manifest.readflags(man) |
1046 |
1072 |
1047 (c, a, d, u) = self.diffdir(self.root) |
1073 (c, a, d, u) = self.changes(None, None) |
1048 |
1074 |
1049 # is this a jump, or a merge? i.e. is there a linear path |
1075 # is this a jump, or a merge? i.e. is there a linear path |
1050 # from p1 to p2? |
1076 # from p1 to p2? |
1051 linear_path = (pa == p1 or pa == p2) |
1077 linear_path = (pa == p1 or pa == p2) |
1052 |
1078 |