34 raise util.Abort(_("premature EOF reading chunk" |
30 raise util.Abort(_("premature EOF reading chunk" |
35 " (got %d bytes, expected %d)") |
31 " (got %d bytes, expected %d)") |
36 % (len(d), l - 4)) |
32 % (len(d), l - 4)) |
37 return d |
33 return d |
38 |
34 |
39 class bundlerevlog(revlog): |
35 class bundlerevlog(revlog.revlog): |
40 def __init__(self, opener, indexfile, datafile, bundlefile, |
36 def __init__(self, opener, indexfile, datafile, bundlefile, |
41 linkmapper=None): |
37 linkmapper=None): |
42 # How it works: |
38 # How it works: |
43 # to retrieve a revision, we need to know the offset of |
39 # to retrieve a revision, we need to know the offset of |
44 # the revision in the bundlefile (an opened file). |
40 # the revision in the bundlefile (an opened file). |
46 # We store this offset in the index (start), to differentiate a |
42 # We store this offset in the index (start), to differentiate a |
47 # rev in the bundle and from a rev in the revlog, we check |
43 # rev in the bundle and from a rev in the revlog, we check |
48 # len(index[r]). If the tuple is bigger than 7, it is a bundle |
44 # len(index[r]). If the tuple is bigger than 7, it is a bundle |
49 # (it is bigger since we store the node to which the delta is) |
45 # (it is bigger since we store the node to which the delta is) |
50 # |
46 # |
51 revlog.__init__(self, opener, indexfile, datafile) |
47 revlog.revlog.__init__(self, opener, indexfile, datafile) |
52 self.bundlefile = bundlefile |
48 self.bundlefile = bundlefile |
53 def genchunk(): |
49 def genchunk(): |
54 while 1: |
50 while 1: |
55 pos = bundlefile.tell() |
51 pos = bundlefile.tell() |
56 chunk = getchunk(bundlefile) |
52 chunk = getchunk(bundlefile) |
78 link = linkmapper(cs) |
74 link = linkmapper(cs) |
79 |
75 |
80 if not prev: |
76 if not prev: |
81 prev = p1 |
77 prev = p1 |
82 # start, size, base is not used, link, p1, p2, delta ref |
78 # start, size, base is not used, link, p1, p2, delta ref |
83 # warning: |
|
84 e = (start, size, None, link, p1, p2, node, prev) |
79 e = (start, size, None, link, p1, p2, node, prev) |
85 self.index.append(e) |
80 self.index.append(e) |
86 self.nodemap[node] = n |
81 self.nodemap[node] = n |
87 prev = node |
82 prev = node |
88 n += 1 |
83 n += 1 |
96 def chunk(self, rev): |
91 def chunk(self, rev): |
97 # Warning: in case of bundle, the diff is against bundlebase, |
92 # Warning: in case of bundle, the diff is against bundlebase, |
98 # not against rev - 1 |
93 # not against rev - 1 |
99 # XXX: could use some caching |
94 # XXX: could use some caching |
100 if not self.bundle(rev): |
95 if not self.bundle(rev): |
101 return revlog.chunk(self, rev) |
96 return revlog.revlog.chunk(self, rev) |
102 self.bundlefile.seek(self.start(rev)) |
97 self.bundlefile.seek(self.start(rev)) |
103 return self.bundlefile.read(self.length(rev)) |
98 return self.bundlefile.read(self.length(rev)) |
104 |
99 |
105 def revdiff(self, rev1, rev2): |
100 def revdiff(self, rev1, rev2): |
106 """return or calculate a delta between two revisions""" |
101 """return or calculate a delta between two revisions""" |
108 # hot path for bundle |
103 # hot path for bundle |
109 revb = self.rev(self.bundlebase(rev2)) |
104 revb = self.rev(self.bundlebase(rev2)) |
110 if revb == rev1: |
105 if revb == rev1: |
111 return self.chunk(rev2) |
106 return self.chunk(rev2) |
112 elif not self.bundle(rev1) and not self.bundle(rev2): |
107 elif not self.bundle(rev1) and not self.bundle(rev2): |
113 return revlog.chunk(self, rev1, rev2) |
108 return revlog.revlog.chunk(self, rev1, rev2) |
114 |
109 |
115 return self.diff(self.revision(self.node(rev1)), |
110 return self.diff(self.revision(self.node(rev1)), |
116 self.revision(self.node(rev2))) |
111 self.revision(self.node(rev2))) |
117 |
112 |
118 def revision(self, node): |
113 def revision(self, node): |
130 break |
125 break |
131 chain.append(rev) |
126 chain.append(rev) |
132 iter_node = self.bundlebase(rev) |
127 iter_node = self.bundlebase(rev) |
133 rev = self.rev(iter_node) |
128 rev = self.rev(iter_node) |
134 if text is None: |
129 if text is None: |
135 text = revlog.revision(self, iter_node) |
130 text = revlog.revlog.revision(self, iter_node) |
136 |
131 |
137 while chain: |
132 while chain: |
138 delta = self.chunk(chain.pop()) |
133 delta = self.chunk(chain.pop()) |
139 text = self.patches(text, [delta]) |
134 text = self.patches(text, [delta]) |
140 |
135 |
141 p1, p2 = self.parents(node) |
136 p1, p2 = self.parents(node) |
142 if node != hash(text, p1, p2): |
137 if node != revlog.hash(text, p1, p2): |
143 raise RevlogError(_("integrity check failed on %s:%d") |
138 raise RevlogError(_("integrity check failed on %s:%d") |
144 % (self.datafile, self.rev(node))) |
139 % (self.datafile, self.rev(node))) |
145 |
140 |
146 self.cache = (node, rev, text) |
141 self.cache = (node, rev, text) |
147 return text |
142 return text |
153 def strip(self, rev, minlink): |
148 def strip(self, rev, minlink): |
154 raise NotImplementedError |
149 raise NotImplementedError |
155 def checksize(self): |
150 def checksize(self): |
156 raise NotImplementedError |
151 raise NotImplementedError |
157 |
152 |
158 class bundlechangelog(bundlerevlog, changelog): |
153 class bundlechangelog(bundlerevlog, changelog.changelog): |
159 def __init__(self, opener, bundlefile): |
154 def __init__(self, opener, bundlefile): |
160 changelog.__init__(self, opener) |
155 changelog.changelog.__init__(self, opener) |
161 bundlerevlog.__init__(self, opener, "00changelog.i", "00changelog.d", |
156 bundlerevlog.__init__(self, opener, "00changelog.i", "00changelog.d", |
162 bundlefile) |
157 bundlefile) |
163 |
158 |
164 class bundlemanifest(bundlerevlog, manifest): |
159 class bundlemanifest(bundlerevlog, manifest.manifest): |
165 def __init__(self, opener, bundlefile, linkmapper): |
160 def __init__(self, opener, bundlefile, linkmapper): |
166 manifest.__init__(self, opener) |
161 manifest.manifest.__init__(self, opener) |
167 bundlerevlog.__init__(self, opener, self.indexfile, self.datafile, |
162 bundlerevlog.__init__(self, opener, self.indexfile, self.datafile, |
168 bundlefile, linkmapper) |
163 bundlefile, linkmapper) |
169 |
164 |
170 class bundlefilelog(bundlerevlog, filelog): |
165 class bundlefilelog(bundlerevlog, filelog.filelog): |
171 def __init__(self, opener, path, bundlefile, linkmapper): |
166 def __init__(self, opener, path, bundlefile, linkmapper): |
172 filelog.__init__(self, opener, path) |
167 filelog.filelog.__init__(self, opener, path) |
173 bundlerevlog.__init__(self, opener, self.indexfile, self.datafile, |
168 bundlerevlog.__init__(self, opener, self.indexfile, self.datafile, |
174 bundlefile, linkmapper) |
169 bundlefile, linkmapper) |
175 |
170 |
176 class bundlerepository(localrepository): |
171 class bundlerepository(localrepo.localrepository): |
177 def __init__(self, ui, path, bundlename): |
172 def __init__(self, ui, path, bundlename): |
178 localrepository.__init__(self, ui, path) |
173 localrepo.localrepository.__init__(self, ui, path) |
179 f = open(bundlename, "rb") |
174 f = open(bundlename, "rb") |
180 s = os.fstat(f.fileno()) |
175 s = os.fstat(f.fileno()) |
181 self.bundlefile = f |
176 self.bundlefile = f |
182 header = self.bundlefile.read(4) |
177 header = self.bundlefile.read(4) |
183 if header == "HG10": |
178 if header == "HG10": |