##// END OF EJS Templates
convert: don't use multi-argument set.update...
Mads Kiilerich -
r22360:3e483253 default
parent child Browse files
Show More
@@ -1,476 +1,477
1 # hg.py - hg backend for convert extension
1 # hg.py - hg backend for convert extension
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 # Notes for hg->hg conversion:
8 # Notes for hg->hg conversion:
9 #
9 #
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
10 # * Old versions of Mercurial didn't trim the whitespace from the ends
11 # of commit messages, but new versions do. Changesets created by
11 # of commit messages, but new versions do. Changesets created by
12 # those older versions, then converted, may thus have different
12 # those older versions, then converted, may thus have different
13 # hashes for changesets that are otherwise identical.
13 # hashes for changesets that are otherwise identical.
14 #
14 #
15 # * Using "--config convert.hg.saverev=true" will make the source
15 # * Using "--config convert.hg.saverev=true" will make the source
16 # identifier to be stored in the converted revision. This will cause
16 # identifier to be stored in the converted revision. This will cause
17 # the converted revision to have a different identity than the
17 # the converted revision to have a different identity than the
18 # source.
18 # source.
19
19
20
20
21 import os, time, cStringIO
21 import os, time, cStringIO
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23 from mercurial.node import bin, hex, nullid
23 from mercurial.node import bin, hex, nullid
24 from mercurial import hg, util, context, bookmarks, error, scmutil
24 from mercurial import hg, util, context, bookmarks, error, scmutil
25
25
26 from common import NoRepo, commit, converter_source, converter_sink
26 from common import NoRepo, commit, converter_source, converter_sink
27
27
28 import re
28 import re
29 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
29 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
30
30
31 class mercurial_sink(converter_sink):
31 class mercurial_sink(converter_sink):
32 def __init__(self, ui, path):
32 def __init__(self, ui, path):
33 converter_sink.__init__(self, ui, path)
33 converter_sink.__init__(self, ui, path)
34 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
34 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
35 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
35 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
36 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
36 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
37 self.lastbranch = None
37 self.lastbranch = None
38 if os.path.isdir(path) and len(os.listdir(path)) > 0:
38 if os.path.isdir(path) and len(os.listdir(path)) > 0:
39 try:
39 try:
40 self.repo = hg.repository(self.ui, path)
40 self.repo = hg.repository(self.ui, path)
41 if not self.repo.local():
41 if not self.repo.local():
42 raise NoRepo(_('%s is not a local Mercurial repository')
42 raise NoRepo(_('%s is not a local Mercurial repository')
43 % path)
43 % path)
44 except error.RepoError, err:
44 except error.RepoError, err:
45 ui.traceback()
45 ui.traceback()
46 raise NoRepo(err.args[0])
46 raise NoRepo(err.args[0])
47 else:
47 else:
48 try:
48 try:
49 ui.status(_('initializing destination %s repository\n') % path)
49 ui.status(_('initializing destination %s repository\n') % path)
50 self.repo = hg.repository(self.ui, path, create=True)
50 self.repo = hg.repository(self.ui, path, create=True)
51 if not self.repo.local():
51 if not self.repo.local():
52 raise NoRepo(_('%s is not a local Mercurial repository')
52 raise NoRepo(_('%s is not a local Mercurial repository')
53 % path)
53 % path)
54 self.created.append(path)
54 self.created.append(path)
55 except error.RepoError:
55 except error.RepoError:
56 ui.traceback()
56 ui.traceback()
57 raise NoRepo(_("could not create hg repository %s as sink")
57 raise NoRepo(_("could not create hg repository %s as sink")
58 % path)
58 % path)
59 self.lock = None
59 self.lock = None
60 self.wlock = None
60 self.wlock = None
61 self.filemapmode = False
61 self.filemapmode = False
62
62
63 def before(self):
63 def before(self):
64 self.ui.debug('run hg sink pre-conversion action\n')
64 self.ui.debug('run hg sink pre-conversion action\n')
65 self.wlock = self.repo.wlock()
65 self.wlock = self.repo.wlock()
66 self.lock = self.repo.lock()
66 self.lock = self.repo.lock()
67
67
68 def after(self):
68 def after(self):
69 self.ui.debug('run hg sink post-conversion action\n')
69 self.ui.debug('run hg sink post-conversion action\n')
70 if self.lock:
70 if self.lock:
71 self.lock.release()
71 self.lock.release()
72 if self.wlock:
72 if self.wlock:
73 self.wlock.release()
73 self.wlock.release()
74
74
75 def revmapfile(self):
75 def revmapfile(self):
76 return self.repo.join("shamap")
76 return self.repo.join("shamap")
77
77
78 def authorfile(self):
78 def authorfile(self):
79 return self.repo.join("authormap")
79 return self.repo.join("authormap")
80
80
81 def setbranch(self, branch, pbranches):
81 def setbranch(self, branch, pbranches):
82 if not self.clonebranches:
82 if not self.clonebranches:
83 return
83 return
84
84
85 setbranch = (branch != self.lastbranch)
85 setbranch = (branch != self.lastbranch)
86 self.lastbranch = branch
86 self.lastbranch = branch
87 if not branch:
87 if not branch:
88 branch = 'default'
88 branch = 'default'
89 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
89 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
90 pbranch = pbranches and pbranches[0][1] or 'default'
90 pbranch = pbranches and pbranches[0][1] or 'default'
91
91
92 branchpath = os.path.join(self.path, branch)
92 branchpath = os.path.join(self.path, branch)
93 if setbranch:
93 if setbranch:
94 self.after()
94 self.after()
95 try:
95 try:
96 self.repo = hg.repository(self.ui, branchpath)
96 self.repo = hg.repository(self.ui, branchpath)
97 except Exception:
97 except Exception:
98 self.repo = hg.repository(self.ui, branchpath, create=True)
98 self.repo = hg.repository(self.ui, branchpath, create=True)
99 self.before()
99 self.before()
100
100
101 # pbranches may bring revisions from other branches (merge parents)
101 # pbranches may bring revisions from other branches (merge parents)
102 # Make sure we have them, or pull them.
102 # Make sure we have them, or pull them.
103 missings = {}
103 missings = {}
104 for b in pbranches:
104 for b in pbranches:
105 try:
105 try:
106 self.repo.lookup(b[0])
106 self.repo.lookup(b[0])
107 except Exception:
107 except Exception:
108 missings.setdefault(b[1], []).append(b[0])
108 missings.setdefault(b[1], []).append(b[0])
109
109
110 if missings:
110 if missings:
111 self.after()
111 self.after()
112 for pbranch, heads in sorted(missings.iteritems()):
112 for pbranch, heads in sorted(missings.iteritems()):
113 pbranchpath = os.path.join(self.path, pbranch)
113 pbranchpath = os.path.join(self.path, pbranch)
114 prepo = hg.peer(self.ui, {}, pbranchpath)
114 prepo = hg.peer(self.ui, {}, pbranchpath)
115 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
115 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
116 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
116 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
117 self.before()
117 self.before()
118
118
119 def _rewritetags(self, source, revmap, data):
119 def _rewritetags(self, source, revmap, data):
120 fp = cStringIO.StringIO()
120 fp = cStringIO.StringIO()
121 for line in data.splitlines():
121 for line in data.splitlines():
122 s = line.split(' ', 1)
122 s = line.split(' ', 1)
123 if len(s) != 2:
123 if len(s) != 2:
124 continue
124 continue
125 revid = revmap.get(source.lookuprev(s[0]))
125 revid = revmap.get(source.lookuprev(s[0]))
126 if not revid:
126 if not revid:
127 continue
127 continue
128 fp.write('%s %s\n' % (revid, s[1]))
128 fp.write('%s %s\n' % (revid, s[1]))
129 return fp.getvalue()
129 return fp.getvalue()
130
130
131 def putcommit(self, files, copies, parents, commit, source, revmap, full):
131 def putcommit(self, files, copies, parents, commit, source, revmap, full):
132 files = dict(files)
132 files = dict(files)
133 def getfilectx(repo, memctx, f):
133 def getfilectx(repo, memctx, f):
134 try:
134 try:
135 v = files[f]
135 v = files[f]
136 except KeyError:
136 except KeyError:
137 return None
137 return None
138 data, mode = source.getfile(f, v)
138 data, mode = source.getfile(f, v)
139 if data is None:
139 if data is None:
140 return None
140 return None
141 if f == '.hgtags':
141 if f == '.hgtags':
142 data = self._rewritetags(source, revmap, data)
142 data = self._rewritetags(source, revmap, data)
143 return context.memfilectx(self.repo, f, data, 'l' in mode,
143 return context.memfilectx(self.repo, f, data, 'l' in mode,
144 'x' in mode, copies.get(f))
144 'x' in mode, copies.get(f))
145
145
146 pl = []
146 pl = []
147 for p in parents:
147 for p in parents:
148 if p not in pl:
148 if p not in pl:
149 pl.append(p)
149 pl.append(p)
150 parents = pl
150 parents = pl
151 nparents = len(parents)
151 nparents = len(parents)
152 if self.filemapmode and nparents == 1:
152 if self.filemapmode and nparents == 1:
153 m1node = self.repo.changelog.read(bin(parents[0]))[0]
153 m1node = self.repo.changelog.read(bin(parents[0]))[0]
154 parent = parents[0]
154 parent = parents[0]
155
155
156 if len(parents) < 2:
156 if len(parents) < 2:
157 parents.append(nullid)
157 parents.append(nullid)
158 if len(parents) < 2:
158 if len(parents) < 2:
159 parents.append(nullid)
159 parents.append(nullid)
160 p2 = parents.pop(0)
160 p2 = parents.pop(0)
161
161
162 text = commit.desc
162 text = commit.desc
163
163
164 sha1s = re.findall(sha1re, text)
164 sha1s = re.findall(sha1re, text)
165 for sha1 in sha1s:
165 for sha1 in sha1s:
166 oldrev = source.lookuprev(sha1)
166 oldrev = source.lookuprev(sha1)
167 newrev = revmap.get(oldrev)
167 newrev = revmap.get(oldrev)
168 if newrev is not None:
168 if newrev is not None:
169 text = text.replace(sha1, newrev[:len(sha1)])
169 text = text.replace(sha1, newrev[:len(sha1)])
170
170
171 extra = commit.extra.copy()
171 extra = commit.extra.copy()
172
172
173 for label in ('source', 'transplant_source', 'rebase_source'):
173 for label in ('source', 'transplant_source', 'rebase_source'):
174 node = extra.get(label)
174 node = extra.get(label)
175
175
176 if node is None:
176 if node is None:
177 continue
177 continue
178
178
179 # Only transplant stores its reference in binary
179 # Only transplant stores its reference in binary
180 if label == 'transplant_source':
180 if label == 'transplant_source':
181 node = hex(node)
181 node = hex(node)
182
182
183 newrev = revmap.get(node)
183 newrev = revmap.get(node)
184 if newrev is not None:
184 if newrev is not None:
185 if label == 'transplant_source':
185 if label == 'transplant_source':
186 newrev = bin(newrev)
186 newrev = bin(newrev)
187
187
188 extra[label] = newrev
188 extra[label] = newrev
189
189
190 if self.branchnames and commit.branch:
190 if self.branchnames and commit.branch:
191 extra['branch'] = commit.branch
191 extra['branch'] = commit.branch
192 if commit.rev:
192 if commit.rev:
193 extra['convert_revision'] = commit.rev
193 extra['convert_revision'] = commit.rev
194
194
195 while parents:
195 while parents:
196 p1 = p2
196 p1 = p2
197 p2 = parents.pop(0)
197 p2 = parents.pop(0)
198 fileset = set(files)
198 fileset = set(files)
199 if full:
199 if full:
200 fileset.update(self.repo[p1], self.repo[p2])
200 fileset.update(self.repo[p1])
201 fileset.update(self.repo[p2])
201 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
202 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
202 getfilectx, commit.author, commit.date, extra)
203 getfilectx, commit.author, commit.date, extra)
203 self.repo.commitctx(ctx)
204 self.repo.commitctx(ctx)
204 text = "(octopus merge fixup)\n"
205 text = "(octopus merge fixup)\n"
205 p2 = hex(self.repo.changelog.tip())
206 p2 = hex(self.repo.changelog.tip())
206
207
207 if self.filemapmode and nparents == 1:
208 if self.filemapmode and nparents == 1:
208 man = self.repo.manifest
209 man = self.repo.manifest
209 mnode = self.repo.changelog.read(bin(p2))[0]
210 mnode = self.repo.changelog.read(bin(p2))[0]
210 closed = 'close' in commit.extra
211 closed = 'close' in commit.extra
211 if not closed and not man.cmp(m1node, man.revision(mnode)):
212 if not closed and not man.cmp(m1node, man.revision(mnode)):
212 self.ui.status(_("filtering out empty revision\n"))
213 self.ui.status(_("filtering out empty revision\n"))
213 self.repo.rollback(force=True)
214 self.repo.rollback(force=True)
214 return parent
215 return parent
215 return p2
216 return p2
216
217
217 def puttags(self, tags):
218 def puttags(self, tags):
218 try:
219 try:
219 parentctx = self.repo[self.tagsbranch]
220 parentctx = self.repo[self.tagsbranch]
220 tagparent = parentctx.node()
221 tagparent = parentctx.node()
221 except error.RepoError:
222 except error.RepoError:
222 parentctx = None
223 parentctx = None
223 tagparent = nullid
224 tagparent = nullid
224
225
225 oldlines = set()
226 oldlines = set()
226 for branch, heads in self.repo.branchmap().iteritems():
227 for branch, heads in self.repo.branchmap().iteritems():
227 for h in heads:
228 for h in heads:
228 if '.hgtags' in self.repo[h]:
229 if '.hgtags' in self.repo[h]:
229 oldlines.update(
230 oldlines.update(
230 set(self.repo[h]['.hgtags'].data().splitlines(True)))
231 set(self.repo[h]['.hgtags'].data().splitlines(True)))
231 oldlines = sorted(list(oldlines))
232 oldlines = sorted(list(oldlines))
232
233
233 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
234 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
234 if newlines == oldlines:
235 if newlines == oldlines:
235 return None, None
236 return None, None
236
237
237 # if the old and new tags match, then there is nothing to update
238 # if the old and new tags match, then there is nothing to update
238 oldtags = set()
239 oldtags = set()
239 newtags = set()
240 newtags = set()
240 for line in oldlines:
241 for line in oldlines:
241 s = line.strip().split(' ', 1)
242 s = line.strip().split(' ', 1)
242 if len(s) != 2:
243 if len(s) != 2:
243 continue
244 continue
244 oldtags.add(s[1])
245 oldtags.add(s[1])
245 for line in newlines:
246 for line in newlines:
246 s = line.strip().split(' ', 1)
247 s = line.strip().split(' ', 1)
247 if len(s) != 2:
248 if len(s) != 2:
248 continue
249 continue
249 if s[1] not in oldtags:
250 if s[1] not in oldtags:
250 newtags.add(s[1].strip())
251 newtags.add(s[1].strip())
251
252
252 if not newtags:
253 if not newtags:
253 return None, None
254 return None, None
254
255
255 data = "".join(newlines)
256 data = "".join(newlines)
256 def getfilectx(repo, memctx, f):
257 def getfilectx(repo, memctx, f):
257 return context.memfilectx(repo, f, data, False, False, None)
258 return context.memfilectx(repo, f, data, False, False, None)
258
259
259 self.ui.status(_("updating tags\n"))
260 self.ui.status(_("updating tags\n"))
260 date = "%s 0" % int(time.mktime(time.gmtime()))
261 date = "%s 0" % int(time.mktime(time.gmtime()))
261 extra = {'branch': self.tagsbranch}
262 extra = {'branch': self.tagsbranch}
262 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
263 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
263 [".hgtags"], getfilectx, "convert-repo", date,
264 [".hgtags"], getfilectx, "convert-repo", date,
264 extra)
265 extra)
265 self.repo.commitctx(ctx)
266 self.repo.commitctx(ctx)
266 return hex(self.repo.changelog.tip()), hex(tagparent)
267 return hex(self.repo.changelog.tip()), hex(tagparent)
267
268
268 def setfilemapmode(self, active):
269 def setfilemapmode(self, active):
269 self.filemapmode = active
270 self.filemapmode = active
270
271
271 def putbookmarks(self, updatedbookmark):
272 def putbookmarks(self, updatedbookmark):
272 if not len(updatedbookmark):
273 if not len(updatedbookmark):
273 return
274 return
274
275
275 self.ui.status(_("updating bookmarks\n"))
276 self.ui.status(_("updating bookmarks\n"))
276 destmarks = self.repo._bookmarks
277 destmarks = self.repo._bookmarks
277 for bookmark in updatedbookmark:
278 for bookmark in updatedbookmark:
278 destmarks[bookmark] = bin(updatedbookmark[bookmark])
279 destmarks[bookmark] = bin(updatedbookmark[bookmark])
279 destmarks.write()
280 destmarks.write()
280
281
281 def hascommitfrommap(self, rev):
282 def hascommitfrommap(self, rev):
282 # the exact semantics of clonebranches is unclear so we can't say no
283 # the exact semantics of clonebranches is unclear so we can't say no
283 return rev in self.repo or self.clonebranches
284 return rev in self.repo or self.clonebranches
284
285
285 def hascommitforsplicemap(self, rev):
286 def hascommitforsplicemap(self, rev):
286 if rev not in self.repo and self.clonebranches:
287 if rev not in self.repo and self.clonebranches:
287 raise util.Abort(_('revision %s not found in destination '
288 raise util.Abort(_('revision %s not found in destination '
288 'repository (lookups with clonebranches=true '
289 'repository (lookups with clonebranches=true '
289 'are not implemented)') % rev)
290 'are not implemented)') % rev)
290 return rev in self.repo
291 return rev in self.repo
291
292
292 class mercurial_source(converter_source):
293 class mercurial_source(converter_source):
293 def __init__(self, ui, path, rev=None):
294 def __init__(self, ui, path, rev=None):
294 converter_source.__init__(self, ui, path, rev)
295 converter_source.__init__(self, ui, path, rev)
295 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
296 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
296 self.ignored = set()
297 self.ignored = set()
297 self.saverev = ui.configbool('convert', 'hg.saverev', False)
298 self.saverev = ui.configbool('convert', 'hg.saverev', False)
298 try:
299 try:
299 self.repo = hg.repository(self.ui, path)
300 self.repo = hg.repository(self.ui, path)
300 # try to provoke an exception if this isn't really a hg
301 # try to provoke an exception if this isn't really a hg
301 # repo, but some other bogus compatible-looking url
302 # repo, but some other bogus compatible-looking url
302 if not self.repo.local():
303 if not self.repo.local():
303 raise error.RepoError
304 raise error.RepoError
304 except error.RepoError:
305 except error.RepoError:
305 ui.traceback()
306 ui.traceback()
306 raise NoRepo(_("%s is not a local Mercurial repository") % path)
307 raise NoRepo(_("%s is not a local Mercurial repository") % path)
307 self.lastrev = None
308 self.lastrev = None
308 self.lastctx = None
309 self.lastctx = None
309 self._changescache = None, None
310 self._changescache = None, None
310 self.convertfp = None
311 self.convertfp = None
311 # Restrict converted revisions to startrev descendants
312 # Restrict converted revisions to startrev descendants
312 startnode = ui.config('convert', 'hg.startrev')
313 startnode = ui.config('convert', 'hg.startrev')
313 hgrevs = ui.config('convert', 'hg.revs')
314 hgrevs = ui.config('convert', 'hg.revs')
314 if hgrevs is None:
315 if hgrevs is None:
315 if startnode is not None:
316 if startnode is not None:
316 try:
317 try:
317 startnode = self.repo.lookup(startnode)
318 startnode = self.repo.lookup(startnode)
318 except error.RepoError:
319 except error.RepoError:
319 raise util.Abort(_('%s is not a valid start revision')
320 raise util.Abort(_('%s is not a valid start revision')
320 % startnode)
321 % startnode)
321 startrev = self.repo.changelog.rev(startnode)
322 startrev = self.repo.changelog.rev(startnode)
322 children = {startnode: 1}
323 children = {startnode: 1}
323 for r in self.repo.changelog.descendants([startrev]):
324 for r in self.repo.changelog.descendants([startrev]):
324 children[self.repo.changelog.node(r)] = 1
325 children[self.repo.changelog.node(r)] = 1
325 self.keep = children.__contains__
326 self.keep = children.__contains__
326 else:
327 else:
327 self.keep = util.always
328 self.keep = util.always
328 if rev:
329 if rev:
329 self._heads = [self.repo[rev].node()]
330 self._heads = [self.repo[rev].node()]
330 else:
331 else:
331 self._heads = self.repo.heads()
332 self._heads = self.repo.heads()
332 else:
333 else:
333 if rev or startnode is not None:
334 if rev or startnode is not None:
334 raise util.Abort(_('hg.revs cannot be combined with '
335 raise util.Abort(_('hg.revs cannot be combined with '
335 'hg.startrev or --rev'))
336 'hg.startrev or --rev'))
336 nodes = set()
337 nodes = set()
337 parents = set()
338 parents = set()
338 for r in scmutil.revrange(self.repo, [hgrevs]):
339 for r in scmutil.revrange(self.repo, [hgrevs]):
339 ctx = self.repo[r]
340 ctx = self.repo[r]
340 nodes.add(ctx.node())
341 nodes.add(ctx.node())
341 parents.update(p.node() for p in ctx.parents())
342 parents.update(p.node() for p in ctx.parents())
342 self.keep = nodes.__contains__
343 self.keep = nodes.__contains__
343 self._heads = nodes - parents
344 self._heads = nodes - parents
344
345
345 def changectx(self, rev):
346 def changectx(self, rev):
346 if self.lastrev != rev:
347 if self.lastrev != rev:
347 self.lastctx = self.repo[rev]
348 self.lastctx = self.repo[rev]
348 self.lastrev = rev
349 self.lastrev = rev
349 return self.lastctx
350 return self.lastctx
350
351
351 def parents(self, ctx):
352 def parents(self, ctx):
352 return [p for p in ctx.parents() if p and self.keep(p.node())]
353 return [p for p in ctx.parents() if p and self.keep(p.node())]
353
354
354 def getheads(self):
355 def getheads(self):
355 return [hex(h) for h in self._heads if self.keep(h)]
356 return [hex(h) for h in self._heads if self.keep(h)]
356
357
357 def getfile(self, name, rev):
358 def getfile(self, name, rev):
358 try:
359 try:
359 fctx = self.changectx(rev)[name]
360 fctx = self.changectx(rev)[name]
360 return fctx.data(), fctx.flags()
361 return fctx.data(), fctx.flags()
361 except error.LookupError:
362 except error.LookupError:
362 return None, None
363 return None, None
363
364
364 def getchanges(self, rev, full):
365 def getchanges(self, rev, full):
365 ctx = self.changectx(rev)
366 ctx = self.changectx(rev)
366 parents = self.parents(ctx)
367 parents = self.parents(ctx)
367 if full or not parents:
368 if full or not parents:
368 files = copyfiles = ctx.manifest()
369 files = copyfiles = ctx.manifest()
369 if parents:
370 if parents:
370 if self._changescache[0] == rev:
371 if self._changescache[0] == rev:
371 m, a, r = self._changescache[1]
372 m, a, r = self._changescache[1]
372 else:
373 else:
373 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
374 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
374 if not full:
375 if not full:
375 files = m + a + r
376 files = m + a + r
376 copyfiles = m + a
377 copyfiles = m + a
377 # getcopies() is also run for roots and before filtering so missing
378 # getcopies() is also run for roots and before filtering so missing
378 # revlogs are detected early
379 # revlogs are detected early
379 copies = self.getcopies(ctx, parents, copyfiles)
380 copies = self.getcopies(ctx, parents, copyfiles)
380 changes = [(f, rev) for f in files if f not in self.ignored]
381 changes = [(f, rev) for f in files if f not in self.ignored]
381 changes.sort()
382 changes.sort()
382 return changes, copies
383 return changes, copies
383
384
384 def getcopies(self, ctx, parents, files):
385 def getcopies(self, ctx, parents, files):
385 copies = {}
386 copies = {}
386 for name in files:
387 for name in files:
387 if name in self.ignored:
388 if name in self.ignored:
388 continue
389 continue
389 try:
390 try:
390 copysource, _copynode = ctx.filectx(name).renamed()
391 copysource, _copynode = ctx.filectx(name).renamed()
391 if copysource in self.ignored:
392 if copysource in self.ignored:
392 continue
393 continue
393 # Ignore copy sources not in parent revisions
394 # Ignore copy sources not in parent revisions
394 found = False
395 found = False
395 for p in parents:
396 for p in parents:
396 if copysource in p:
397 if copysource in p:
397 found = True
398 found = True
398 break
399 break
399 if not found:
400 if not found:
400 continue
401 continue
401 copies[name] = copysource
402 copies[name] = copysource
402 except TypeError:
403 except TypeError:
403 pass
404 pass
404 except error.LookupError, e:
405 except error.LookupError, e:
405 if not self.ignoreerrors:
406 if not self.ignoreerrors:
406 raise
407 raise
407 self.ignored.add(name)
408 self.ignored.add(name)
408 self.ui.warn(_('ignoring: %s\n') % e)
409 self.ui.warn(_('ignoring: %s\n') % e)
409 return copies
410 return copies
410
411
411 def getcommit(self, rev):
412 def getcommit(self, rev):
412 ctx = self.changectx(rev)
413 ctx = self.changectx(rev)
413 parents = [p.hex() for p in self.parents(ctx)]
414 parents = [p.hex() for p in self.parents(ctx)]
414 if self.saverev:
415 if self.saverev:
415 crev = rev
416 crev = rev
416 else:
417 else:
417 crev = None
418 crev = None
418 return commit(author=ctx.user(),
419 return commit(author=ctx.user(),
419 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
420 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
420 desc=ctx.description(), rev=crev, parents=parents,
421 desc=ctx.description(), rev=crev, parents=parents,
421 branch=ctx.branch(), extra=ctx.extra(),
422 branch=ctx.branch(), extra=ctx.extra(),
422 sortkey=ctx.rev())
423 sortkey=ctx.rev())
423
424
424 def gettags(self):
425 def gettags(self):
425 # This will get written to .hgtags, filter non global tags out.
426 # This will get written to .hgtags, filter non global tags out.
426 tags = [t for t in self.repo.tagslist()
427 tags = [t for t in self.repo.tagslist()
427 if self.repo.tagtype(t[0]) == 'global']
428 if self.repo.tagtype(t[0]) == 'global']
428 return dict([(name, hex(node)) for name, node in tags
429 return dict([(name, hex(node)) for name, node in tags
429 if self.keep(node)])
430 if self.keep(node)])
430
431
431 def getchangedfiles(self, rev, i):
432 def getchangedfiles(self, rev, i):
432 ctx = self.changectx(rev)
433 ctx = self.changectx(rev)
433 parents = self.parents(ctx)
434 parents = self.parents(ctx)
434 if not parents and i is None:
435 if not parents and i is None:
435 i = 0
436 i = 0
436 changes = [], ctx.manifest().keys(), []
437 changes = [], ctx.manifest().keys(), []
437 else:
438 else:
438 i = i or 0
439 i = i or 0
439 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
440 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
440 changes = [[f for f in l if f not in self.ignored] for l in changes]
441 changes = [[f for f in l if f not in self.ignored] for l in changes]
441
442
442 if i == 0:
443 if i == 0:
443 self._changescache = (rev, changes)
444 self._changescache = (rev, changes)
444
445
445 return changes[0] + changes[1] + changes[2]
446 return changes[0] + changes[1] + changes[2]
446
447
447 def converted(self, rev, destrev):
448 def converted(self, rev, destrev):
448 if self.convertfp is None:
449 if self.convertfp is None:
449 self.convertfp = open(self.repo.join('shamap'), 'a')
450 self.convertfp = open(self.repo.join('shamap'), 'a')
450 self.convertfp.write('%s %s\n' % (destrev, rev))
451 self.convertfp.write('%s %s\n' % (destrev, rev))
451 self.convertfp.flush()
452 self.convertfp.flush()
452
453
453 def before(self):
454 def before(self):
454 self.ui.debug('run hg source pre-conversion action\n')
455 self.ui.debug('run hg source pre-conversion action\n')
455
456
456 def after(self):
457 def after(self):
457 self.ui.debug('run hg source post-conversion action\n')
458 self.ui.debug('run hg source post-conversion action\n')
458
459
459 def hasnativeorder(self):
460 def hasnativeorder(self):
460 return True
461 return True
461
462
462 def hasnativeclose(self):
463 def hasnativeclose(self):
463 return True
464 return True
464
465
465 def lookuprev(self, rev):
466 def lookuprev(self, rev):
466 try:
467 try:
467 return hex(self.repo.lookup(rev))
468 return hex(self.repo.lookup(rev))
468 except error.RepoError:
469 except error.RepoError:
469 return None
470 return None
470
471
471 def getbookmarks(self):
472 def getbookmarks(self):
472 return bookmarks.listbookmarks(self.repo)
473 return bookmarks.listbookmarks(self.repo)
473
474
474 def checkrevformat(self, revstr, mapname='splicemap'):
475 def checkrevformat(self, revstr, mapname='splicemap'):
475 """ Mercurial, revision string is a 40 byte hex """
476 """ Mercurial, revision string is a 40 byte hex """
476 self.checkhexformat(revstr, mapname)
477 self.checkhexformat(revstr, mapname)
General Comments 0
You need to be logged in to leave comments. Login now