comparison rhodecode/lib/unionrepo.py @ 3407:6354556781ef beta

update unionrepo for Mercurial 2.5.1
author Mads Kiilerich <madski@unity3d.com>
date Wed, 27 Feb 2013 01:26:38 +0100
parents ead7a902998c
children f3283898d431
comparison
equal deleted inserted replaced
3406:4e9f00ddde4a 3407:6354556781ef
1 # unionrepo.py - repository class for viewing union of repositories 1 # unionrepo.py - repository class for viewing union of repository changesets
2 # 2 #
3 # Derived from Mercurial 2.5 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 """ 12 """
12 13
14 import os
13 from mercurial.node import nullid 15 from mercurial.node import nullid
14 from mercurial import util, mdiff 16 from mercurial.i18n import _
17 from mercurial import util, mdiff, cmdutil, scmutil
15 from mercurial import localrepo, changelog, manifest, filelog, revlog 18 from mercurial import localrepo, changelog, manifest, filelog, revlog
16 19
17 class unionrevlog(revlog.revlog): 20 class unionrevlog(revlog.revlog):
18 def __init__(self, opener, indexfile, revlog2, linkmapper): 21 def __init__(self, opener, indexfile, revlog2, linkmapper):
19 # How it works: 22 # How it works:
20 # To retrieve a revision, we just need to know the node id so we can 23 # To retrieve a revision, we just need to know the node id so we can
21 # look it up in revlog2. 24 # look it up in revlog2.
22 # 25 #
23 # basemap is indexed with revisions coming from the second revlog.
24 #
25 # To differentiate a rev in the second revlog from a rev in the revlog, 26 # To differentiate a rev in the second revlog from a rev in the revlog,
26 # we check revision against basemap. 27 # we check revision against repotiprev.
28 opener = scmutil.readonlyvfs(opener)
27 revlog.revlog.__init__(self, opener, indexfile) 29 revlog.revlog.__init__(self, opener, indexfile)
28 self.revlog2 = revlog2 30 self.revlog2 = revlog2
29 31
30 self.basemap = {} # mapping rev that is in revlog2 to ... nothing
31 n = len(self) 32 n = len(self)
33 self.repotiprev = n - 1
32 self.bundlerevs = set() # used by 'bundle()' revset expression 34 self.bundlerevs = set() # used by 'bundle()' revset expression
33 for rev2 in self.revlog2: 35 for rev2 in self.revlog2:
34 rev = self.revlog2.index[rev2] 36 rev = self.revlog2.index[rev2]
35 # rev numbers - in revlog2, very different from self.rev 37 # rev numbers - in revlog2, very different from self.rev
36 _start, _csize, _rsize, _base, linkrev, p1rev, p2rev, node = rev 38 _start, _csize, _rsize, _base, linkrev, p1rev, p2rev, node = rev
40 link = n 42 link = n
41 else: # rev must be mapped from repo2 cl to unified cl by linkmapper 43 else: # rev must be mapped from repo2 cl to unified cl by linkmapper
42 link = linkmapper(linkrev) 44 link = linkmapper(linkrev)
43 45
44 if node in self.nodemap: 46 if node in self.nodemap:
45 # this happens for for the common revlog revisions 47 # this happens for the common revlog revisions
46 self.bundlerevs.add(self.nodemap[node]) 48 self.bundlerevs.add(self.nodemap[node])
47 continue 49 continue
48 50
49 p1node = self.revlog2.node(p1rev) 51 p1node = self.revlog2.node(p1rev)
50 p2node = self.revlog2.node(p2rev) 52 p2node = self.revlog2.node(p2rev)
51 53
52 e = (None, None, None, None, 54 e = (None, None, None, None,
53 link, self.rev(p1node), self.rev(p2node), node) 55 link, self.rev(p1node), self.rev(p2node), node)
54 self.basemap[n] = None
55 self.index.insert(-1, e) 56 self.index.insert(-1, e)
56 self.nodemap[node] = n 57 self.nodemap[node] = n
57 self.bundlerevs.add(n) 58 self.bundlerevs.add(n)
58 n += 1 59 n += 1
59 60
60 def _chunk(self, rev): 61 def _chunk(self, rev):
61 if rev not in self.basemap: 62 if rev <= self.repotiprev:
62 return revlog.revlog._chunk(self, rev) 63 return revlog.revlog._chunk(self, rev)
63 return self.revlog2._chunk(self.node(rev)) 64 return self.revlog2._chunk(self.node(rev))
64 65
65 def revdiff(self, rev1, rev2): 66 def revdiff(self, rev1, rev2):
66 """return or calculate a delta between two revisions""" 67 """return or calculate a delta between two revisions"""
67 if rev1 in self.basemap and rev2 in self.basemap: 68 if rev1 > self.repotiprev and rev2 > self.repotiprev:
68 return self.revlog2.revdiff( 69 return self.revlog2.revdiff(
69 self.revlog2.rev(self.node(rev1)), 70 self.revlog2.rev(self.node(rev1)),
70 self.revlog2.rev(self.node(rev2))) 71 self.revlog2.rev(self.node(rev2)))
71 elif rev1 not in self.basemap and rev2 not in self.basemap: 72 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
72 return revlog.revlog.revdiff(self, rev1, rev2) 73 return revlog.revlog.revdiff(self, rev1, rev2)
73 74
74 return mdiff.textdiff(self.revision(self.node(rev1)), 75 return mdiff.textdiff(self.revision(self.node(rev1)),
75 self.revision(self.node(rev2))) 76 self.revision(self.node(rev2)))
76 77
86 rev = self.rev(node) 87 rev = self.rev(node)
87 88
88 if node == nullid: 89 if node == nullid:
89 return "" 90 return ""
90 91
91 if rev in self.basemap: 92 if rev > self.repotiprev:
92 text = self.revlog2.revision(node) 93 text = self.revlog2.revision(node)
93 self._cache = (node, rev, text) 94 self._cache = (node, rev, text)
94 else: 95 else:
95 text = revlog.revlog.revision(self, rev) 96 text = revlog.revlog.revision(self, rev)
96 # already cached 97 # already cached
142 143
143 self._url = 'union:%s+%s' % (util.expandpath(path), 144 self._url = 'union:%s+%s' % (util.expandpath(path),
144 util.expandpath(path2)) 145 util.expandpath(path2))
145 self.repo2 = localrepo.localrepository(ui, path2) 146 self.repo2 = localrepo.localrepository(ui, path2)
146 147
147 @util.propertycache 148 @localrepo.unfilteredpropertycache
148 def changelog(self): 149 def changelog(self):
149 return unionchangelog(self.sopener, self.repo2.sopener) 150 return unionchangelog(self.sopener, self.repo2.sopener)
150 151
151 def _clrev(self, rev2): 152 def _clrev(self, rev2):
152 """map from repo2 changelog rev to temporary rev in self.changelog""" 153 """map from repo2 changelog rev to temporary rev in self.changelog"""
153 node = self.repo2.changelog.node(rev2) 154 node = self.repo2.changelog.node(rev2)
154 return self.changelog.rev(node) 155 return self.changelog.rev(node)
155 156
156 @util.propertycache 157 @localrepo.unfilteredpropertycache
157 def manifest(self): 158 def manifest(self):
158 return unionmanifest(self.sopener, self.repo2.sopener, 159 return unionmanifest(self.sopener, self.repo2.sopener,
159 self._clrev) 160 self._clrev)
160 161
161 def url(self): 162 def url(self):
172 return False 173 return False
173 174
174 def peer(self): 175 def peer(self):
175 return unionpeer(self) 176 return unionpeer(self)
176 177
178 def getcwd(self):
179 return os.getcwd() # always outside the repo
180
177 def instance(ui, path, create): 181 def instance(ui, path, create):
178 u = util.url(path) 182 if create:
179 assert u.scheme == 'union' 183 raise util.Abort(_('cannot create new union repository'))
180 repopath, repopath2 = u.path.split("+", 1) 184 parentpath = ui.config("bundle", "mainreporoot", "")
185 if not parentpath:
186 # try to find the correct path to the working directory repo
187 parentpath = cmdutil.findrepo(os.getcwd())
188 if parentpath is None:
189 parentpath = ''
190 if parentpath:
191 # Try to make the full path relative so we get a nice, short URL.
192 # In particular, we don't want temp dir names in test outputs.
193 cwd = os.getcwd()
194 if parentpath == cwd:
195 parentpath = ''
196 else:
197 cwd = os.path.join(cwd,'')
198 if parentpath.startswith(cwd):
199 parentpath = parentpath[len(cwd):]
200 if path.startswith('union:'):
201 s = path.split(":", 1)[1].split("+", 1)
202 if len(s) == 1:
203 repopath, repopath2 = parentpath, s[0]
204 else:
205 repopath, repopath2 = s
206 else:
207 repopath, repopath2 = parentpath, path
181 return unionrepository(ui, repopath, repopath2) 208 return unionrepository(ui, repopath, repopath2)