592 elif f not in self.dirstate: |
592 elif f not in self.dirstate: |
593 self.ui.warn("%s not tracked!\n" % f) |
593 self.ui.warn("%s not tracked!\n" % f) |
594 else: |
594 else: |
595 self.dirstate.update([f], "r") |
595 self.dirstate.update([f], "r") |
596 |
596 |
|
597 def heads(self): |
|
598 return self.changelog.heads() |
|
599 |
597 def branches(self, nodes): |
600 def branches(self, nodes): |
598 if not nodes: nodes = [self.changelog.tip()] |
601 if not nodes: nodes = [self.changelog.tip()] |
599 b = [] |
602 b = [] |
600 for n in nodes: |
603 for n in nodes: |
601 t = n |
604 t = n |
657 search = [] |
660 search = [] |
658 fetch = [] |
661 fetch = [] |
659 seen = {} |
662 seen = {} |
660 seenbranch = {} |
663 seenbranch = {} |
661 |
664 |
662 self.ui.status("searching for changes\n") |
|
663 tip = remote.branches([])[0] |
|
664 self.ui.debug("remote tip branch is %s:%s\n" % |
|
665 (short(tip[0]), short(tip[1]))) |
|
666 |
|
667 # if we have an empty repo, fetch everything |
665 # if we have an empty repo, fetch everything |
668 if self.changelog.tip() == nullid: |
666 if self.changelog.tip() == nullid: |
|
667 self.ui.status("requesting all changes\n") |
669 return remote.changegroup([nullid]) |
668 return remote.changegroup([nullid]) |
670 |
669 |
671 # otherwise, assume we're closer to the tip than the root |
670 # otherwise, assume we're closer to the tip than the root |
672 unknown = [tip] |
671 self.ui.status("searching for changes\n") |
673 |
672 heads = remote.heads() |
674 if tip[0] in m: |
673 unknown = [] |
|
674 for h in heads: |
|
675 if h not in m: |
|
676 unknown.append(h) |
|
677 |
|
678 if not unknown: |
675 self.ui.status("nothing to do!\n") |
679 self.ui.status("nothing to do!\n") |
676 return None |
680 return None |
677 |
681 |
|
682 unknown = remote.branches(unknown) |
678 while unknown: |
683 while unknown: |
679 n = unknown.pop(0) |
684 n = unknown.pop(0) |
680 seen[n[0]] = 1 |
685 seen[n[0]] = 1 |
681 |
686 |
682 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
687 self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) |
764 g = self.file(f).group(linkmap) |
769 g = self.file(f).group(linkmap) |
765 for y in g: |
770 for y in g: |
766 yield y |
771 yield y |
767 |
772 |
768 def addchangegroup(self, generator): |
773 def addchangegroup(self, generator): |
|
774 |
|
775 class genread: |
|
776 def __init__(self, generator): |
|
777 self.g = generator |
|
778 self.buf = "" |
|
779 def read(self, l): |
|
780 while l > len(self.buf): |
|
781 try: |
|
782 self.buf += self.g.next() |
|
783 except StopIteration: |
|
784 break |
|
785 d, self.buf = self.buf[:l], self.buf[l:] |
|
786 return d |
|
787 |
|
788 def getchunk(): |
|
789 d = source.read(4) |
|
790 if not d: return "" |
|
791 l = struct.unpack(">l", d)[0] |
|
792 if l <= 4: return "" |
|
793 return source.read(l - 4) |
|
794 |
|
795 def getgroup(): |
|
796 while 1: |
|
797 c = getchunk() |
|
798 if not c: break |
|
799 yield c |
|
800 |
|
801 def csmap(x): |
|
802 self.ui.debug("add changeset %s\n" % short(x)) |
|
803 return self.changelog.count() |
|
804 |
|
805 def revmap(x): |
|
806 return self.changelog.rev(x) |
|
807 |
|
808 if not generator: return |
|
809 changesets = files = revisions = 0 |
|
810 self.lock() |
|
811 source = genread(generator) |
|
812 tr = self.transaction() |
|
813 |
|
814 # pull off the changeset group |
|
815 self.ui.status("adding changesets\n") |
|
816 co = self.changelog.tip() |
|
817 cn = self.changelog.addgroup(getgroup(), csmap, tr) |
|
818 changesets = self.changelog.rev(cn) - self.changelog.rev(co) |
|
819 |
|
820 # pull off the manifest group |
|
821 self.ui.status("adding manifests\n") |
|
822 mm = self.manifest.tip() |
|
823 mo = self.manifest.addgroup(getgroup(), revmap, tr) |
|
824 |
|
825 # process the files |
|
826 self.ui.status("adding file revisions\n") |
|
827 while 1: |
|
828 f = getchunk() |
|
829 if not f: break |
|
830 self.ui.debug("adding %s revisions\n" % f) |
|
831 fl = self.file(f) |
|
832 o = fl.tip() |
|
833 n = fl.addgroup(getgroup(), revmap, tr) |
|
834 revisions += fl.rev(n) - fl.rev(o) |
|
835 files += 1 |
|
836 |
|
837 self.ui.status(("modified %d files, added %d changesets" + |
|
838 " and %d new revisions\n") |
|
839 % (files, changesets, revisions)) |
|
840 |
|
841 tr.close() |
|
842 return |
|
843 |
|
844 def merge(self, generator): |
769 changesets = files = revisions = 0 |
845 changesets = files = revisions = 0 |
770 |
846 |
771 self.lock() |
847 self.lock() |
772 class genread: |
848 class genread: |
773 def __init__(self, generator): |
849 def __init__(self, generator): |
978 q.update(args) |
1054 q.update(args) |
979 qs = urllib.urlencode(q) |
1055 qs = urllib.urlencode(q) |
980 cu = "%s?%s" % (self.url, qs) |
1056 cu = "%s?%s" % (self.url, qs) |
981 return urllib.urlopen(cu) |
1057 return urllib.urlopen(cu) |
982 |
1058 |
|
1059 def heads(self): |
|
1060 d = self.do_cmd("heads").read() |
|
1061 try: |
|
1062 return map(bin, d[:-1].split(" ")) |
|
1063 except: |
|
1064 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") |
|
1065 raise |
|
1066 |
983 def branches(self, nodes): |
1067 def branches(self, nodes): |
984 n = " ".join(map(hex, nodes)) |
1068 n = " ".join(map(hex, nodes)) |
985 d = self.do_cmd("branches", nodes=n).read() |
1069 d = self.do_cmd("branches", nodes=n).read() |
986 try: |
1070 try: |
987 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] |
1071 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] |