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