##// END OF EJS Templates
unionrepo: drop the custom `rawdata` implementation...
marmoute -
r43097:853f7013 default
parent child Browse files
Show More
@@ -1,253 +1,250 b''
1 # unionrepo.py - repository class for viewing union of repository changesets
1 # unionrepo.py - repository class for viewing union of repository changesets
2 #
2 #
3 # Derived from bundlerepo.py
3 # Derived from bundlerepo.py
4 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
4 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
5 # Copyright 2013 Unity Technologies, Mads Kiilerich <madski@unity3d.com>
5 # Copyright 2013 Unity Technologies, Mads Kiilerich <madski@unity3d.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 """Repository class for "in-memory pull" of one local repository to another,
10 """Repository class for "in-memory pull" of one local repository to another,
11 allowing operations like diff and log with revsets.
11 allowing operations like diff and log with revsets.
12 """
12 """
13
13
14 from __future__ import absolute_import
14 from __future__ import absolute_import
15
15
16 from .i18n import _
16 from .i18n import _
17
17
18 from . import (
18 from . import (
19 changelog,
19 changelog,
20 cmdutil,
20 cmdutil,
21 encoding,
21 encoding,
22 error,
22 error,
23 filelog,
23 filelog,
24 localrepo,
24 localrepo,
25 manifest,
25 manifest,
26 mdiff,
26 mdiff,
27 pathutil,
27 pathutil,
28 revlog,
28 revlog,
29 util,
29 util,
30 vfs as vfsmod,
30 vfs as vfsmod,
31 )
31 )
32
32
33 class unionrevlog(revlog.revlog):
33 class unionrevlog(revlog.revlog):
34 def __init__(self, opener, indexfile, revlog2, linkmapper):
34 def __init__(self, opener, indexfile, revlog2, linkmapper):
35 # How it works:
35 # How it works:
36 # To retrieve a revision, we just need to know the node id so we can
36 # To retrieve a revision, we just need to know the node id so we can
37 # look it up in revlog2.
37 # look it up in revlog2.
38 #
38 #
39 # To differentiate a rev in the second revlog from a rev in the revlog,
39 # To differentiate a rev in the second revlog from a rev in the revlog,
40 # we check revision against repotiprev.
40 # we check revision against repotiprev.
41 opener = vfsmod.readonlyvfs(opener)
41 opener = vfsmod.readonlyvfs(opener)
42 revlog.revlog.__init__(self, opener, indexfile)
42 revlog.revlog.__init__(self, opener, indexfile)
43 self.revlog2 = revlog2
43 self.revlog2 = revlog2
44
44
45 n = len(self)
45 n = len(self)
46 self.repotiprev = n - 1
46 self.repotiprev = n - 1
47 self.bundlerevs = set() # used by 'bundle()' revset expression
47 self.bundlerevs = set() # used by 'bundle()' revset expression
48 for rev2 in self.revlog2:
48 for rev2 in self.revlog2:
49 rev = self.revlog2.index[rev2]
49 rev = self.revlog2.index[rev2]
50 # rev numbers - in revlog2, very different from self.rev
50 # rev numbers - in revlog2, very different from self.rev
51 _start, _csize, rsize, base, linkrev, p1rev, p2rev, node = rev
51 _start, _csize, rsize, base, linkrev, p1rev, p2rev, node = rev
52 flags = _start & 0xFFFF
52 flags = _start & 0xFFFF
53
53
54 if linkmapper is None: # link is to same revlog
54 if linkmapper is None: # link is to same revlog
55 assert linkrev == rev2 # we never link back
55 assert linkrev == rev2 # we never link back
56 link = n
56 link = n
57 else: # rev must be mapped from repo2 cl to unified cl by linkmapper
57 else: # rev must be mapped from repo2 cl to unified cl by linkmapper
58 link = linkmapper(linkrev)
58 link = linkmapper(linkrev)
59
59
60 if linkmapper is not None: # link is to same revlog
60 if linkmapper is not None: # link is to same revlog
61 base = linkmapper(base)
61 base = linkmapper(base)
62
62
63 if node in self.nodemap:
63 if node in self.nodemap:
64 # this happens for the common revlog revisions
64 # this happens for the common revlog revisions
65 self.bundlerevs.add(self.nodemap[node])
65 self.bundlerevs.add(self.nodemap[node])
66 continue
66 continue
67
67
68 p1node = self.revlog2.node(p1rev)
68 p1node = self.revlog2.node(p1rev)
69 p2node = self.revlog2.node(p2rev)
69 p2node = self.revlog2.node(p2rev)
70
70
71 # TODO: it's probably wrong to set compressed length to None, but
71 # TODO: it's probably wrong to set compressed length to None, but
72 # I have no idea if csize is valid in the base revlog context.
72 # I have no idea if csize is valid in the base revlog context.
73 e = (flags, None, rsize, base,
73 e = (flags, None, rsize, base,
74 link, self.rev(p1node), self.rev(p2node), node)
74 link, self.rev(p1node), self.rev(p2node), node)
75 self.index.append(e)
75 self.index.append(e)
76 self.nodemap[node] = n
76 self.nodemap[node] = n
77 self.bundlerevs.add(n)
77 self.bundlerevs.add(n)
78 n += 1
78 n += 1
79
79
80 def _chunk(self, rev):
80 def _chunk(self, rev):
81 if rev <= self.repotiprev:
81 if rev <= self.repotiprev:
82 return revlog.revlog._chunk(self, rev)
82 return revlog.revlog._chunk(self, rev)
83 return self.revlog2._chunk(self.node(rev))
83 return self.revlog2._chunk(self.node(rev))
84
84
85 def revdiff(self, rev1, rev2):
85 def revdiff(self, rev1, rev2):
86 """return or calculate a delta between two revisions"""
86 """return or calculate a delta between two revisions"""
87 if rev1 > self.repotiprev and rev2 > self.repotiprev:
87 if rev1 > self.repotiprev and rev2 > self.repotiprev:
88 return self.revlog2.revdiff(
88 return self.revlog2.revdiff(
89 self.revlog2.rev(self.node(rev1)),
89 self.revlog2.rev(self.node(rev1)),
90 self.revlog2.rev(self.node(rev2)))
90 self.revlog2.rev(self.node(rev2)))
91 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
91 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
92 return super(unionrevlog, self).revdiff(rev1, rev2)
92 return super(unionrevlog, self).revdiff(rev1, rev2)
93
93
94 return mdiff.textdiff(self.rawdata(rev1), self.rawdata(rev2))
94 return mdiff.textdiff(self.rawdata(rev1), self.rawdata(rev2))
95
95
96 def _revisiondata(self, nodeorrev, _df=None, raw=False):
96 def _revisiondata(self, nodeorrev, _df=None, raw=False):
97 if isinstance(nodeorrev, int):
97 if isinstance(nodeorrev, int):
98 rev = nodeorrev
98 rev = nodeorrev
99 node = self.node(rev)
99 node = self.node(rev)
100 else:
100 else:
101 node = nodeorrev
101 node = nodeorrev
102 rev = self.rev(node)
102 rev = self.rev(node)
103
103
104 if rev > self.repotiprev:
104 if rev > self.repotiprev:
105 # work around manifestrevlog NOT being a revlog
105 # work around manifestrevlog NOT being a revlog
106 revlog2 = getattr(self.revlog2, '_revlog', self.revlog2)
106 revlog2 = getattr(self.revlog2, '_revlog', self.revlog2)
107 func = revlog2._revisiondata
107 func = revlog2._revisiondata
108 else:
108 else:
109 func = super(unionrevlog, self)._revisiondata
109 func = super(unionrevlog, self)._revisiondata
110 return func(node, _df=_df, raw=raw)
110 return func(node, _df=_df, raw=raw)
111
111
112 def rawdata(self, nodeorrev, _df=None):
113 return self.revision(nodeorrev, _df=_df, raw=True)
114
115 def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
112 def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
116 raise NotImplementedError
113 raise NotImplementedError
117 def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None,
114 def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None,
118 maybemissingparents=False):
115 maybemissingparents=False):
119 raise NotImplementedError
116 raise NotImplementedError
120 def strip(self, minlink, transaction):
117 def strip(self, minlink, transaction):
121 raise NotImplementedError
118 raise NotImplementedError
122 def checksize(self):
119 def checksize(self):
123 raise NotImplementedError
120 raise NotImplementedError
124
121
125 class unionchangelog(unionrevlog, changelog.changelog):
122 class unionchangelog(unionrevlog, changelog.changelog):
126 def __init__(self, opener, opener2):
123 def __init__(self, opener, opener2):
127 changelog.changelog.__init__(self, opener)
124 changelog.changelog.__init__(self, opener)
128 linkmapper = None
125 linkmapper = None
129 changelog2 = changelog.changelog(opener2)
126 changelog2 = changelog.changelog(opener2)
130 unionrevlog.__init__(self, opener, self.indexfile, changelog2,
127 unionrevlog.__init__(self, opener, self.indexfile, changelog2,
131 linkmapper)
128 linkmapper)
132
129
133 class unionmanifest(unionrevlog, manifest.manifestrevlog):
130 class unionmanifest(unionrevlog, manifest.manifestrevlog):
134 def __init__(self, opener, opener2, linkmapper):
131 def __init__(self, opener, opener2, linkmapper):
135 manifest.manifestrevlog.__init__(self, opener)
132 manifest.manifestrevlog.__init__(self, opener)
136 manifest2 = manifest.manifestrevlog(opener2)
133 manifest2 = manifest.manifestrevlog(opener2)
137 unionrevlog.__init__(self, opener, self.indexfile, manifest2,
134 unionrevlog.__init__(self, opener, self.indexfile, manifest2,
138 linkmapper)
135 linkmapper)
139
136
140 class unionfilelog(filelog.filelog):
137 class unionfilelog(filelog.filelog):
141 def __init__(self, opener, path, opener2, linkmapper, repo):
138 def __init__(self, opener, path, opener2, linkmapper, repo):
142 filelog.filelog.__init__(self, opener, path)
139 filelog.filelog.__init__(self, opener, path)
143 filelog2 = filelog.filelog(opener2, path)
140 filelog2 = filelog.filelog(opener2, path)
144 self._revlog = unionrevlog(opener, self.indexfile,
141 self._revlog = unionrevlog(opener, self.indexfile,
145 filelog2._revlog, linkmapper)
142 filelog2._revlog, linkmapper)
146 self._repo = repo
143 self._repo = repo
147 self.repotiprev = self._revlog.repotiprev
144 self.repotiprev = self._revlog.repotiprev
148 self.revlog2 = self._revlog.revlog2
145 self.revlog2 = self._revlog.revlog2
149
146
150 def iscensored(self, rev):
147 def iscensored(self, rev):
151 """Check if a revision is censored."""
148 """Check if a revision is censored."""
152 if rev <= self.repotiprev:
149 if rev <= self.repotiprev:
153 return filelog.filelog.iscensored(self, rev)
150 return filelog.filelog.iscensored(self, rev)
154 node = self.node(rev)
151 node = self.node(rev)
155 return self.revlog2.iscensored(self.revlog2.rev(node))
152 return self.revlog2.iscensored(self.revlog2.rev(node))
156
153
157 class unionpeer(localrepo.localpeer):
154 class unionpeer(localrepo.localpeer):
158 def canpush(self):
155 def canpush(self):
159 return False
156 return False
160
157
161 class unionrepository(object):
158 class unionrepository(object):
162 """Represents the union of data in 2 repositories.
159 """Represents the union of data in 2 repositories.
163
160
164 Instances are not usable if constructed directly. Use ``instance()``
161 Instances are not usable if constructed directly. Use ``instance()``
165 or ``makeunionrepository()`` to create a usable instance.
162 or ``makeunionrepository()`` to create a usable instance.
166 """
163 """
167 def __init__(self, repo2, url):
164 def __init__(self, repo2, url):
168 self.repo2 = repo2
165 self.repo2 = repo2
169 self._url = url
166 self._url = url
170
167
171 self.ui.setconfig('phases', 'publish', False, 'unionrepo')
168 self.ui.setconfig('phases', 'publish', False, 'unionrepo')
172
169
173 @localrepo.unfilteredpropertycache
170 @localrepo.unfilteredpropertycache
174 def changelog(self):
171 def changelog(self):
175 return unionchangelog(self.svfs, self.repo2.svfs)
172 return unionchangelog(self.svfs, self.repo2.svfs)
176
173
177 @localrepo.unfilteredpropertycache
174 @localrepo.unfilteredpropertycache
178 def manifestlog(self):
175 def manifestlog(self):
179 rootstore = unionmanifest(self.svfs, self.repo2.svfs,
176 rootstore = unionmanifest(self.svfs, self.repo2.svfs,
180 self.unfiltered()._clrev)
177 self.unfiltered()._clrev)
181 return manifest.manifestlog(self.svfs, self, rootstore,
178 return manifest.manifestlog(self.svfs, self, rootstore,
182 self.narrowmatch())
179 self.narrowmatch())
183
180
184 def _clrev(self, rev2):
181 def _clrev(self, rev2):
185 """map from repo2 changelog rev to temporary rev in self.changelog"""
182 """map from repo2 changelog rev to temporary rev in self.changelog"""
186 node = self.repo2.changelog.node(rev2)
183 node = self.repo2.changelog.node(rev2)
187 return self.changelog.rev(node)
184 return self.changelog.rev(node)
188
185
189 def url(self):
186 def url(self):
190 return self._url
187 return self._url
191
188
192 def file(self, f):
189 def file(self, f):
193 return unionfilelog(self.svfs, f, self.repo2.svfs,
190 return unionfilelog(self.svfs, f, self.repo2.svfs,
194 self.unfiltered()._clrev, self)
191 self.unfiltered()._clrev, self)
195
192
196 def close(self):
193 def close(self):
197 self.repo2.close()
194 self.repo2.close()
198
195
199 def cancopy(self):
196 def cancopy(self):
200 return False
197 return False
201
198
202 def peer(self):
199 def peer(self):
203 return unionpeer(self)
200 return unionpeer(self)
204
201
205 def getcwd(self):
202 def getcwd(self):
206 return encoding.getcwd() # always outside the repo
203 return encoding.getcwd() # always outside the repo
207
204
208 def instance(ui, path, create, intents=None, createopts=None):
205 def instance(ui, path, create, intents=None, createopts=None):
209 if create:
206 if create:
210 raise error.Abort(_('cannot create new union repository'))
207 raise error.Abort(_('cannot create new union repository'))
211 parentpath = ui.config("bundle", "mainreporoot")
208 parentpath = ui.config("bundle", "mainreporoot")
212 if not parentpath:
209 if not parentpath:
213 # try to find the correct path to the working directory repo
210 # try to find the correct path to the working directory repo
214 parentpath = cmdutil.findrepo(encoding.getcwd())
211 parentpath = cmdutil.findrepo(encoding.getcwd())
215 if parentpath is None:
212 if parentpath is None:
216 parentpath = ''
213 parentpath = ''
217 if parentpath:
214 if parentpath:
218 # Try to make the full path relative so we get a nice, short URL.
215 # Try to make the full path relative so we get a nice, short URL.
219 # In particular, we don't want temp dir names in test outputs.
216 # In particular, we don't want temp dir names in test outputs.
220 cwd = encoding.getcwd()
217 cwd = encoding.getcwd()
221 if parentpath == cwd:
218 if parentpath == cwd:
222 parentpath = ''
219 parentpath = ''
223 else:
220 else:
224 cwd = pathutil.normasprefix(cwd)
221 cwd = pathutil.normasprefix(cwd)
225 if parentpath.startswith(cwd):
222 if parentpath.startswith(cwd):
226 parentpath = parentpath[len(cwd):]
223 parentpath = parentpath[len(cwd):]
227 if path.startswith('union:'):
224 if path.startswith('union:'):
228 s = path.split(":", 1)[1].split("+", 1)
225 s = path.split(":", 1)[1].split("+", 1)
229 if len(s) == 1:
226 if len(s) == 1:
230 repopath, repopath2 = parentpath, s[0]
227 repopath, repopath2 = parentpath, s[0]
231 else:
228 else:
232 repopath, repopath2 = s
229 repopath, repopath2 = s
233 else:
230 else:
234 repopath, repopath2 = parentpath, path
231 repopath, repopath2 = parentpath, path
235
232
236 return makeunionrepository(ui, repopath, repopath2)
233 return makeunionrepository(ui, repopath, repopath2)
237
234
238 def makeunionrepository(ui, repopath1, repopath2):
235 def makeunionrepository(ui, repopath1, repopath2):
239 """Make a union repository object from 2 local repo paths."""
236 """Make a union repository object from 2 local repo paths."""
240 repo1 = localrepo.instance(ui, repopath1, create=False)
237 repo1 = localrepo.instance(ui, repopath1, create=False)
241 repo2 = localrepo.instance(ui, repopath2, create=False)
238 repo2 = localrepo.instance(ui, repopath2, create=False)
242
239
243 url = 'union:%s+%s' % (util.expandpath(repopath1),
240 url = 'union:%s+%s' % (util.expandpath(repopath1),
244 util.expandpath(repopath2))
241 util.expandpath(repopath2))
245
242
246 class derivedunionrepository(unionrepository, repo1.__class__):
243 class derivedunionrepository(unionrepository, repo1.__class__):
247 pass
244 pass
248
245
249 repo = repo1
246 repo = repo1
250 repo.__class__ = derivedunionrepository
247 repo.__class__ = derivedunionrepository
251 unionrepository.__init__(repo1, repo2, url)
248 unionrepository.__init__(repo1, repo2, url)
252
249
253 return repo
250 return repo
General Comments 0
You need to be logged in to leave comments. Login now