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