Mercurial > hg-git
annotate hggit/overlay.py @ 466:ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Thu, 26 Jul 2012 18:59:19 -0500 |
parents | f29401590803 |
children | 4f4ab2d89375 41f6e3df67b1 |
rev | line source |
---|---|
408 | 1 # overlay classes for repositories |
2 # unifies access to unimported git objects and committed hg objects | |
3 # designed to support incoming | |
4 # | |
5 # incomplete, implemented on demand | |
6 | |
7 from mercurial import context | |
8 from mercurial.node import bin, hex, nullid | |
9 | |
10 class overlaymanifest(object): | |
11 def __init__(self, repo, sha): | |
12 self.repo = repo | |
13 self.tree = repo.handler.git.get_object(sha) | |
14 self._map = None | |
15 self._flagmap = None | |
16 | |
466
ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
Augie Fackler <raf@durin42.com>
parents:
423
diff
changeset
|
17 def withflags(self): |
ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
Augie Fackler <raf@durin42.com>
parents:
423
diff
changeset
|
18 self.load() |
ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
Augie Fackler <raf@durin42.com>
parents:
423
diff
changeset
|
19 return set([path for path, flag in self._flagmap.iteritems() |
ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
Augie Fackler <raf@durin42.com>
parents:
423
diff
changeset
|
20 if flag & 020100]) |
ac16efd25cc4
overlaymanifest: add the withflags method introduced in hg change a1dcd842ce17
Augie Fackler <raf@durin42.com>
parents:
423
diff
changeset
|
21 |
408 | 22 def copy(self): |
23 return overlaymanifest(self.repo, self.tree.id) | |
24 | |
25 def keys(self): | |
26 self.load() | |
27 return self._map.keys() | |
28 | |
29 def flags(self, path): | |
30 self.load() | |
31 | |
32 def hgflag(gitflag): | |
33 if gitflag & 0100: | |
34 return 'x' | |
35 elif gitflag & 020000: | |
36 return 'l' | |
37 else: | |
38 return '' | |
39 | |
40 return hgflag(self._flagmap[path]) | |
41 | |
42 def load(self): | |
43 if self._map is not None: | |
44 return | |
45 | |
46 self._map = {} | |
47 self._flagmap = {} | |
48 | |
49 def addtree(tree, dirname): | |
423
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
50 for entry in tree.iteritems(): |
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
51 if entry.mode & 040000: |
408 | 52 # expand directory |
423
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
53 subtree = self.repo.handler.git.get_object(entry.sha) |
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
54 addtree(subtree, dirname + entry.path + '/') |
408 | 55 else: |
423
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
56 path = dirname + entry.path |
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
57 self._map[path] = bin(entry.sha) |
f29401590803
overlay: stop using deprecated tree.entries() method
Augie Fackler <durin42@gmail.com>
parents:
408
diff
changeset
|
58 self._flagmap[path] = entry.mode |
408 | 59 |
60 addtree(self.tree, '') | |
61 | |
62 def __iter__(self): | |
63 self.load() | |
64 return self._map.__iter__() | |
65 | |
66 def __getitem__(self, path): | |
67 self.load() | |
68 return self._map[path] | |
69 | |
70 def __delitem__(self, path): | |
71 del self._map[path] | |
72 | |
73 class overlayfilectx(object): | |
74 def __init__(self, repo, path, fileid=None): | |
75 self.repo = repo | |
76 self._path = path | |
77 self.fileid = fileid | |
78 | |
79 # this is a hack to skip copy detection | |
80 def ancestors(self): | |
81 return [self, self] | |
82 | |
83 def rev(self): | |
84 return -1 | |
85 | |
86 def path(self): | |
87 return self._path | |
88 | |
89 def filelog(self): | |
90 return self.fileid | |
91 | |
92 def data(self): | |
93 blob = self.repo.handler.git.get_object(self.fileid) | |
94 return blob.data | |
95 | |
96 class overlaychangectx(context.changectx): | |
97 def __init__(self, repo, sha): | |
98 self.repo = repo | |
99 self.commit = repo.handler.git.get_object(sha) | |
100 | |
101 def node(self): | |
102 return bin(self.commit.id) | |
103 | |
104 def rev(self): | |
105 return self.repo.rev(bin(self.commit.id)) | |
106 | |
107 def date(self): | |
108 return self.commit.author_time, self.commit.author_timezone | |
109 | |
110 def branch(self): | |
111 return 'default' | |
112 | |
113 def user(self): | |
114 return self.commit.author | |
115 | |
116 def files(self): | |
117 return [] | |
118 | |
119 def extra(self): | |
120 return {} | |
121 | |
122 def description(self): | |
123 return self.commit.message | |
124 | |
125 def parents(self): | |
126 return [overlaychangectx(self.repo, sha) for sha in self.commit.parents] | |
127 | |
128 def manifestnode(self): | |
129 return bin(self.commit.tree) | |
130 | |
131 def hex(self): | |
132 return self.commit.id | |
133 | |
134 def tags(self): | |
135 return [] | |
136 | |
137 def bookmarks(self): | |
138 return [] | |
139 | |
140 def manifest(self): | |
141 return overlaymanifest(self.repo, self.commit.tree) | |
142 | |
143 def filectx(self, path, filelog=None): | |
144 mf = self.manifest() | |
145 return overlayfilectx(self.repo, path, mf[path]) | |
146 | |
147 def flags(self, path): | |
148 mf = self.manifest() | |
149 return mf.flags(path) | |
150 | |
151 def __nonzero__(self): | |
152 return True | |
153 | |
154 class overlayrevlog(object): | |
155 def __init__(self, repo, base): | |
156 self.repo = repo | |
157 self.base = base | |
158 | |
159 def parents(self, n): | |
160 gitrev = self.repo.revmap.get(n) | |
161 if not gitrev: | |
162 # we've reached a revision we have | |
163 return self.base.parents(n) | |
164 commit = self.repo.handler.git.get_object(n) | |
165 | |
166 def gitorhg(n): | |
167 hn = self.repo.handler.map_hg_get(hex(n)) | |
168 if hn is not None: | |
169 return bin(hn) | |
170 return n | |
171 | |
172 # currently ignores the octopus | |
173 p1 = gitorhg(bin(commit.parents[0])) | |
174 if len(commit.parents) > 1: | |
175 p2 = gitorhg(bin(commit.parents[1])) | |
176 else: | |
177 p2 = nullid | |
178 | |
179 return [p1, p2] | |
180 | |
181 def parentrevs(self, rev): | |
182 return [self.rev(p) for p in self.parents(self.node(rev))] | |
183 | |
184 def node(self, rev): | |
185 gitnode = self.repo.nodemap.get(rev) | |
186 if gitnode is None: | |
187 return self.base.node(rev) | |
188 return gitnode | |
189 | |
190 def rev(self, n): | |
191 gitrev = self.repo.revmap.get(n) | |
192 if gitrev is None: | |
193 return self.base.rev(n) | |
194 return gitrev | |
195 | |
196 def nodesbetween(self, nodelist, revs): | |
197 # this is called by pre-1.9 incoming with the nodelist we returned from | |
198 # getremotechanges. Just return it back. | |
199 return [nodelist] | |
200 | |
201 def __len__(self): | |
202 return len(self.repo.handler.repo) + len(self.repo.revmap) | |
203 | |
204 | |
205 class overlayrepo(object): | |
206 def __init__(self, handler, commits, refs): | |
207 self.handler = handler | |
208 | |
209 self.changelog = overlayrevlog(self, handler.repo.changelog) | |
210 self.manifest = overlayrevlog(self, handler.repo.manifest) | |
211 | |
212 # for incoming -p | |
213 self.root = handler.repo.root | |
214 self.getcwd = handler.repo.getcwd | |
215 self.status = handler.repo.status | |
216 self.ui = handler.repo.ui | |
217 | |
218 self.revmap = None | |
219 self.nodemap = None | |
220 self.refmap = None | |
221 self.tagmap = None | |
222 | |
223 self._makemaps(commits, refs) | |
224 | |
225 def __getitem__(self, n): | |
226 if n not in self.revmap: | |
227 return self.handler.repo[n] | |
228 return overlaychangectx(self, n) | |
229 | |
230 def nodebookmarks(self, n): | |
231 return self.refmap.get(n, []) | |
232 | |
233 def nodetags(self, n): | |
234 return self.tagmap.get(n, []) | |
235 | |
236 def rev(self, n): | |
237 return self.revmap[n] | |
238 | |
239 def filectx(self, path, fileid=None): | |
240 return overlayfilectx(self, path, fileid=fileid) | |
241 | |
242 def _makemaps(self, commits, refs): | |
243 baserev = self.handler.repo['tip'].rev() | |
244 self.revmap = {} | |
245 self.nodemap = {} | |
246 for i, n in enumerate(commits): | |
247 rev = baserev + i + 1 | |
248 self.revmap[n] = rev | |
249 self.nodemap[rev] = n | |
250 | |
251 self.refmap = {} | |
252 self.tagmap = {} | |
253 for ref in refs: | |
254 if ref.startswith('refs/heads/'): | |
255 refname = ref[11:] | |
256 self.refmap.setdefault(bin(refs[ref]), []).append(refname) | |
257 elif ref.startswith('refs/tags/'): | |
258 tagname = ref[10:] | |
259 self.tagmap.setdefault(bin(refs[ref]), []).append(tagname) |