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