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