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