comparison mercurial/bundlerepo.py @ 18643:cc28a84db8c9

bundlerepo: replace basemap with the base field in the index Bundle revisions had some info in their fake revlog intries and some info in a dict with all the bundle revisions. This dict was used to get the stored data and to distinguish repo revisions from bundle revisions. Real repo revisions and bundle revisions will now be distinguished by comparing with the tip revision of the original repo. This reintroduces something similar to disktiprev which was unused and removed in a928865b4a4f and let that replace the O(reposize) dict.
author Mads Kiilerich <mads@kiilerich.com>
date Fri, 08 Feb 2013 23:26:00 +0100
parents cd403d6d96ef
children f0564402d059
comparison
equal deleted inserted replaced
18642:a40d608e2a7b 18643:cc28a84db8c9
20 class bundlerevlog(revlog.revlog): 20 class bundlerevlog(revlog.revlog):
21 def __init__(self, opener, indexfile, bundle, linkmapper): 21 def __init__(self, opener, indexfile, bundle, linkmapper):
22 # How it works: 22 # How it works:
23 # To retrieve a revision, we need to know the offset of the revision in 23 # To retrieve a revision, we need to know the offset of the revision in
24 # the bundle (an unbundle object). We store this offset in the index 24 # the bundle (an unbundle object). We store this offset in the index
25 # (start). 25 # (start). The base of the delta is stored in the base field.
26 #
27 # basemap is indexed with revisions coming from the bundle, and it
28 # maps to the revision that is the base of the corresponding delta.
29 # 26 #
30 # To differentiate a rev in the bundle from a rev in the revlog, we 27 # To differentiate a rev in the bundle from a rev in the revlog, we
31 # check revision against basemap. 28 # check revision against repotiprev.
32 opener = scmutil.readonlyvfs(opener) 29 opener = scmutil.readonlyvfs(opener)
33 revlog.revlog.__init__(self, opener, indexfile) 30 revlog.revlog.__init__(self, opener, indexfile)
34 self.bundle = bundle 31 self.bundle = bundle
35 self.basemap = {} # mapping rev to delta base rev
36 n = len(self) 32 n = len(self)
33 self.repotiprev = n - 1
37 chain = None 34 chain = None
38 self.bundlerevs = set() # used by 'bundle()' revset expression 35 self.bundlerevs = set() # used by 'bundle()' revset expression
39 while True: 36 while True:
40 chunkdata = bundle.deltachunk(chain) 37 chunkdata = bundle.deltachunk(chain)
41 if not chunkdata: 38 if not chunkdata:
66 raise LookupError(deltabase, self.indexfile, 63 raise LookupError(deltabase, self.indexfile,
67 _('unknown delta base')) 64 _('unknown delta base'))
68 65
69 baserev = self.rev(deltabase) 66 baserev = self.rev(deltabase)
70 # start, size, full unc. size, base (unused), link, p1, p2, node 67 # start, size, full unc. size, base (unused), link, p1, p2, node
71 e = (revlog.offset_type(start, 0), size, -1, -1, link, 68 e = (revlog.offset_type(start, 0), size, -1, baserev, link,
72 self.rev(p1), self.rev(p2), node) 69 self.rev(p1), self.rev(p2), node)
73 self.basemap[n] = baserev
74 self.index.insert(-1, e) 70 self.index.insert(-1, e)
75 self.nodemap[node] = n 71 self.nodemap[node] = n
76 self.bundlerevs.add(n) 72 self.bundlerevs.add(n)
77 chain = node 73 chain = node
78 n += 1 74 n += 1
79 75
80 def _chunk(self, rev): 76 def _chunk(self, rev):
81 # Warning: in case of bundle, the diff is against self.basemap, 77 # Warning: in case of bundle, the diff is against what we stored as
82 # not against rev - 1 78 # delta base, not against rev - 1
83 # XXX: could use some caching 79 # XXX: could use some caching
84 if rev not in self.basemap: 80 if rev <= self.repotiprev:
85 return revlog.revlog._chunk(self, rev) 81 return revlog.revlog._chunk(self, rev)
86 self.bundle.seek(self.start(rev)) 82 self.bundle.seek(self.start(rev))
87 return self.bundle.read(self.length(rev)) 83 return self.bundle.read(self.length(rev))
88 84
89 def revdiff(self, rev1, rev2): 85 def revdiff(self, rev1, rev2):
90 """return or calculate a delta between two revisions""" 86 """return or calculate a delta between two revisions"""
91 if rev1 in self.basemap and rev2 in self.basemap: 87 if rev1 > self.repotiprev and rev2 > self.repotiprev:
92 # hot path for bundle 88 # hot path for bundle
93 revb = self.basemap[rev2] 89 revb = self.index[rev2][3]
94 if revb == rev1: 90 if revb == rev1:
95 return self._chunk(rev2) 91 return self._chunk(rev2)
96 elif rev1 not in self.basemap and rev2 not in self.basemap: 92 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
97 return revlog.revlog.revdiff(self, rev1, rev2) 93 return revlog.revlog.revdiff(self, rev1, rev2)
98 94
99 return mdiff.textdiff(self.revision(self.node(rev1)), 95 return mdiff.textdiff(self.revision(self.node(rev1)),
100 self.revision(self.node(rev2))) 96 self.revision(self.node(rev2)))
101 97
115 111
116 text = None 112 text = None
117 chain = [] 113 chain = []
118 iterrev = rev 114 iterrev = rev
119 # reconstruct the revision if it is from a changegroup 115 # reconstruct the revision if it is from a changegroup
120 while iterrev in self.basemap: 116 while iterrev > self.repotiprev:
121 if self._cache and self._cache[1] == iterrev: 117 if self._cache and self._cache[1] == iterrev:
122 text = self._cache[2] 118 text = self._cache[2]
123 break 119 break
124 chain.append(iterrev) 120 chain.append(iterrev)
125 iterrev = self.basemap[iterrev] 121 iterrev = self.index[iterrev][3]
126 if text is None: 122 if text is None:
127 text = revlog.revlog.revision(self, iterrev) 123 text = revlog.revlog.revision(self, iterrev)
128 124
129 while chain: 125 while chain:
130 delta = self._chunk(chain.pop()) 126 delta = self._chunk(chain.pop())