##// END OF EJS Templates
convert: avoid updating tags when there is nothing new...
Sean Farley -
r20377:5842d63c default
parent child Browse files
Show More
@@ -1,431 +1,450
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 getheads(self):
81 def getheads(self):
82 h = self.repo.changelog.heads()
82 h = self.repo.changelog.heads()
83 return [hex(x) for x in h]
83 return [hex(x) for x in h]
84
84
85 def setbranch(self, branch, pbranches):
85 def setbranch(self, branch, pbranches):
86 if not self.clonebranches:
86 if not self.clonebranches:
87 return
87 return
88
88
89 setbranch = (branch != self.lastbranch)
89 setbranch = (branch != self.lastbranch)
90 self.lastbranch = branch
90 self.lastbranch = branch
91 if not branch:
91 if not branch:
92 branch = 'default'
92 branch = 'default'
93 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
93 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
94 pbranch = pbranches and pbranches[0][1] or 'default'
94 pbranch = pbranches and pbranches[0][1] or 'default'
95
95
96 branchpath = os.path.join(self.path, branch)
96 branchpath = os.path.join(self.path, branch)
97 if setbranch:
97 if setbranch:
98 self.after()
98 self.after()
99 try:
99 try:
100 self.repo = hg.repository(self.ui, branchpath)
100 self.repo = hg.repository(self.ui, branchpath)
101 except Exception:
101 except Exception:
102 self.repo = hg.repository(self.ui, branchpath, create=True)
102 self.repo = hg.repository(self.ui, branchpath, create=True)
103 self.before()
103 self.before()
104
104
105 # pbranches may bring revisions from other branches (merge parents)
105 # pbranches may bring revisions from other branches (merge parents)
106 # Make sure we have them, or pull them.
106 # Make sure we have them, or pull them.
107 missings = {}
107 missings = {}
108 for b in pbranches:
108 for b in pbranches:
109 try:
109 try:
110 self.repo.lookup(b[0])
110 self.repo.lookup(b[0])
111 except Exception:
111 except Exception:
112 missings.setdefault(b[1], []).append(b[0])
112 missings.setdefault(b[1], []).append(b[0])
113
113
114 if missings:
114 if missings:
115 self.after()
115 self.after()
116 for pbranch, heads in sorted(missings.iteritems()):
116 for pbranch, heads in sorted(missings.iteritems()):
117 pbranchpath = os.path.join(self.path, pbranch)
117 pbranchpath = os.path.join(self.path, pbranch)
118 prepo = hg.peer(self.ui, {}, pbranchpath)
118 prepo = hg.peer(self.ui, {}, pbranchpath)
119 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
119 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
120 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
120 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
121 self.before()
121 self.before()
122
122
123 def _rewritetags(self, source, revmap, data):
123 def _rewritetags(self, source, revmap, data):
124 fp = cStringIO.StringIO()
124 fp = cStringIO.StringIO()
125 for line in data.splitlines():
125 for line in data.splitlines():
126 s = line.split(' ', 1)
126 s = line.split(' ', 1)
127 if len(s) != 2:
127 if len(s) != 2:
128 continue
128 continue
129 revid = revmap.get(source.lookuprev(s[0]))
129 revid = revmap.get(source.lookuprev(s[0]))
130 if not revid:
130 if not revid:
131 continue
131 continue
132 fp.write('%s %s\n' % (revid, s[1]))
132 fp.write('%s %s\n' % (revid, s[1]))
133 return fp.getvalue()
133 return fp.getvalue()
134
134
135 def putcommit(self, files, copies, parents, commit, source, revmap):
135 def putcommit(self, files, copies, parents, commit, source, revmap):
136
136
137 files = dict(files)
137 files = dict(files)
138 def getfilectx(repo, memctx, f):
138 def getfilectx(repo, memctx, f):
139 v = files[f]
139 v = files[f]
140 data, mode = source.getfile(f, v)
140 data, mode = source.getfile(f, v)
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(f, data, 'l' in mode, 'x' in mode,
143 return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
144 copies.get(f))
144 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 if self.branchnames and commit.branch:
172 if self.branchnames and commit.branch:
173 extra['branch'] = commit.branch
173 extra['branch'] = commit.branch
174 if commit.rev:
174 if commit.rev:
175 extra['convert_revision'] = commit.rev
175 extra['convert_revision'] = commit.rev
176
176
177 while parents:
177 while parents:
178 p1 = p2
178 p1 = p2
179 p2 = parents.pop(0)
179 p2 = parents.pop(0)
180 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
180 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(),
181 getfilectx, commit.author, commit.date, extra)
181 getfilectx, commit.author, commit.date, extra)
182 self.repo.commitctx(ctx)
182 self.repo.commitctx(ctx)
183 text = "(octopus merge fixup)\n"
183 text = "(octopus merge fixup)\n"
184 p2 = hex(self.repo.changelog.tip())
184 p2 = hex(self.repo.changelog.tip())
185
185
186 if self.filemapmode and nparents == 1:
186 if self.filemapmode and nparents == 1:
187 man = self.repo.manifest
187 man = self.repo.manifest
188 mnode = self.repo.changelog.read(bin(p2))[0]
188 mnode = self.repo.changelog.read(bin(p2))[0]
189 closed = 'close' in commit.extra
189 closed = 'close' in commit.extra
190 if not closed and not man.cmp(m1node, man.revision(mnode)):
190 if not closed and not man.cmp(m1node, man.revision(mnode)):
191 self.ui.status(_("filtering out empty revision\n"))
191 self.ui.status(_("filtering out empty revision\n"))
192 self.repo.rollback(force=True)
192 self.repo.rollback(force=True)
193 return parent
193 return parent
194 return p2
194 return p2
195
195
196 def puttags(self, tags):
196 def puttags(self, tags):
197 try:
197 try:
198 parentctx = self.repo[self.tagsbranch]
198 parentctx = self.repo[self.tagsbranch]
199 tagparent = parentctx.node()
199 tagparent = parentctx.node()
200 except error.RepoError:
200 except error.RepoError:
201 parentctx = None
201 parentctx = None
202 tagparent = nullid
202 tagparent = nullid
203
203
204 oldlines = set()
204 oldlines = set()
205 for branch, heads in self.repo.branchmap().iteritems():
205 for branch, heads in self.repo.branchmap().iteritems():
206 for h in heads:
206 for h in heads:
207 if '.hgtags' in self.repo[h]:
207 if '.hgtags' in self.repo[h]:
208 oldlines.update(
208 oldlines.update(
209 set(self.repo[h]['.hgtags'].data().splitlines(True)))
209 set(self.repo[h]['.hgtags'].data().splitlines(True)))
210 oldlines = sorted(list(oldlines))
210 oldlines = sorted(list(oldlines))
211
211
212 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
212 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
213 if newlines == oldlines:
213 if newlines == oldlines:
214 return None, None
214 return None, None
215
216 # if the old and new tags match, then there is nothing to update
217 oldtags = set()
218 newtags = set()
219 for line in oldlines:
220 s = line.strip().split(' ', 1)
221 if len(s) != 2:
222 continue
223 oldtags.add(s[1])
224 for line in newlines:
225 s = line.strip().split(' ', 1)
226 if len(s) != 2:
227 continue
228 if s[1] not in oldtags:
229 newtags.add(s[1].strip())
230
231 if not newtags:
232 return None, None
233
215 data = "".join(newlines)
234 data = "".join(newlines)
216 def getfilectx(repo, memctx, f):
235 def getfilectx(repo, memctx, f):
217 return context.memfilectx(f, data, False, False, None)
236 return context.memfilectx(f, data, False, False, None)
218
237
219 self.ui.status(_("updating tags\n"))
238 self.ui.status(_("updating tags\n"))
220 date = "%s 0" % int(time.mktime(time.gmtime()))
239 date = "%s 0" % int(time.mktime(time.gmtime()))
221 extra = {'branch': self.tagsbranch}
240 extra = {'branch': self.tagsbranch}
222 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
241 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
223 [".hgtags"], getfilectx, "convert-repo", date,
242 [".hgtags"], getfilectx, "convert-repo", date,
224 extra)
243 extra)
225 self.repo.commitctx(ctx)
244 self.repo.commitctx(ctx)
226 return hex(self.repo.changelog.tip()), hex(tagparent)
245 return hex(self.repo.changelog.tip()), hex(tagparent)
227
246
228 def setfilemapmode(self, active):
247 def setfilemapmode(self, active):
229 self.filemapmode = active
248 self.filemapmode = active
230
249
231 def putbookmarks(self, updatedbookmark):
250 def putbookmarks(self, updatedbookmark):
232 if not len(updatedbookmark):
251 if not len(updatedbookmark):
233 return
252 return
234
253
235 self.ui.status(_("updating bookmarks\n"))
254 self.ui.status(_("updating bookmarks\n"))
236 destmarks = self.repo._bookmarks
255 destmarks = self.repo._bookmarks
237 for bookmark in updatedbookmark:
256 for bookmark in updatedbookmark:
238 destmarks[bookmark] = bin(updatedbookmark[bookmark])
257 destmarks[bookmark] = bin(updatedbookmark[bookmark])
239 destmarks.write()
258 destmarks.write()
240
259
241 def hascommit(self, rev):
260 def hascommit(self, rev):
242 if rev not in self.repo and self.clonebranches:
261 if rev not in self.repo and self.clonebranches:
243 raise util.Abort(_('revision %s not found in destination '
262 raise util.Abort(_('revision %s not found in destination '
244 'repository (lookups with clonebranches=true '
263 'repository (lookups with clonebranches=true '
245 'are not implemented)') % rev)
264 'are not implemented)') % rev)
246 return rev in self.repo
265 return rev in self.repo
247
266
248 class mercurial_source(converter_source):
267 class mercurial_source(converter_source):
249 def __init__(self, ui, path, rev=None):
268 def __init__(self, ui, path, rev=None):
250 converter_source.__init__(self, ui, path, rev)
269 converter_source.__init__(self, ui, path, rev)
251 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
270 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
252 self.ignored = set()
271 self.ignored = set()
253 self.saverev = ui.configbool('convert', 'hg.saverev', False)
272 self.saverev = ui.configbool('convert', 'hg.saverev', False)
254 try:
273 try:
255 self.repo = hg.repository(self.ui, path)
274 self.repo = hg.repository(self.ui, path)
256 # try to provoke an exception if this isn't really a hg
275 # try to provoke an exception if this isn't really a hg
257 # repo, but some other bogus compatible-looking url
276 # repo, but some other bogus compatible-looking url
258 if not self.repo.local():
277 if not self.repo.local():
259 raise error.RepoError
278 raise error.RepoError
260 except error.RepoError:
279 except error.RepoError:
261 ui.traceback()
280 ui.traceback()
262 raise NoRepo(_("%s is not a local Mercurial repository") % path)
281 raise NoRepo(_("%s is not a local Mercurial repository") % path)
263 self.lastrev = None
282 self.lastrev = None
264 self.lastctx = None
283 self.lastctx = None
265 self._changescache = None
284 self._changescache = None
266 self.convertfp = None
285 self.convertfp = None
267 # Restrict converted revisions to startrev descendants
286 # Restrict converted revisions to startrev descendants
268 startnode = ui.config('convert', 'hg.startrev')
287 startnode = ui.config('convert', 'hg.startrev')
269 hgrevs = ui.config('convert', 'hg.revs')
288 hgrevs = ui.config('convert', 'hg.revs')
270 if hgrevs is None:
289 if hgrevs is None:
271 if startnode is not None:
290 if startnode is not None:
272 try:
291 try:
273 startnode = self.repo.lookup(startnode)
292 startnode = self.repo.lookup(startnode)
274 except error.RepoError:
293 except error.RepoError:
275 raise util.Abort(_('%s is not a valid start revision')
294 raise util.Abort(_('%s is not a valid start revision')
276 % startnode)
295 % startnode)
277 startrev = self.repo.changelog.rev(startnode)
296 startrev = self.repo.changelog.rev(startnode)
278 children = {startnode: 1}
297 children = {startnode: 1}
279 for r in self.repo.changelog.descendants([startrev]):
298 for r in self.repo.changelog.descendants([startrev]):
280 children[self.repo.changelog.node(r)] = 1
299 children[self.repo.changelog.node(r)] = 1
281 self.keep = children.__contains__
300 self.keep = children.__contains__
282 else:
301 else:
283 self.keep = util.always
302 self.keep = util.always
284 if rev:
303 if rev:
285 self._heads = [self.repo[rev].node()]
304 self._heads = [self.repo[rev].node()]
286 else:
305 else:
287 self._heads = self.repo.heads()
306 self._heads = self.repo.heads()
288 else:
307 else:
289 if rev or startnode is not None:
308 if rev or startnode is not None:
290 raise util.Abort(_('hg.revs cannot be combined with '
309 raise util.Abort(_('hg.revs cannot be combined with '
291 'hg.startrev or --rev'))
310 'hg.startrev or --rev'))
292 nodes = set()
311 nodes = set()
293 parents = set()
312 parents = set()
294 for r in scmutil.revrange(self.repo, [hgrevs]):
313 for r in scmutil.revrange(self.repo, [hgrevs]):
295 ctx = self.repo[r]
314 ctx = self.repo[r]
296 nodes.add(ctx.node())
315 nodes.add(ctx.node())
297 parents.update(p.node() for p in ctx.parents())
316 parents.update(p.node() for p in ctx.parents())
298 self.keep = nodes.__contains__
317 self.keep = nodes.__contains__
299 self._heads = nodes - parents
318 self._heads = nodes - parents
300
319
301 def changectx(self, rev):
320 def changectx(self, rev):
302 if self.lastrev != rev:
321 if self.lastrev != rev:
303 self.lastctx = self.repo[rev]
322 self.lastctx = self.repo[rev]
304 self.lastrev = rev
323 self.lastrev = rev
305 return self.lastctx
324 return self.lastctx
306
325
307 def parents(self, ctx):
326 def parents(self, ctx):
308 return [p for p in ctx.parents() if p and self.keep(p.node())]
327 return [p for p in ctx.parents() if p and self.keep(p.node())]
309
328
310 def getheads(self):
329 def getheads(self):
311 return [hex(h) for h in self._heads if self.keep(h)]
330 return [hex(h) for h in self._heads if self.keep(h)]
312
331
313 def getfile(self, name, rev):
332 def getfile(self, name, rev):
314 try:
333 try:
315 fctx = self.changectx(rev)[name]
334 fctx = self.changectx(rev)[name]
316 return fctx.data(), fctx.flags()
335 return fctx.data(), fctx.flags()
317 except error.LookupError, err:
336 except error.LookupError, err:
318 raise IOError(err)
337 raise IOError(err)
319
338
320 def getchanges(self, rev):
339 def getchanges(self, rev):
321 ctx = self.changectx(rev)
340 ctx = self.changectx(rev)
322 parents = self.parents(ctx)
341 parents = self.parents(ctx)
323 if not parents:
342 if not parents:
324 files = sorted(ctx.manifest())
343 files = sorted(ctx.manifest())
325 # getcopies() is not needed for roots, but it is a simple way to
344 # getcopies() is not needed for roots, but it is a simple way to
326 # detect missing revlogs and abort on errors or populate
345 # detect missing revlogs and abort on errors or populate
327 # self.ignored
346 # self.ignored
328 self.getcopies(ctx, parents, files)
347 self.getcopies(ctx, parents, files)
329 return [(f, rev) for f in files if f not in self.ignored], {}
348 return [(f, rev) for f in files if f not in self.ignored], {}
330 if self._changescache and self._changescache[0] == rev:
349 if self._changescache and self._changescache[0] == rev:
331 m, a, r = self._changescache[1]
350 m, a, r = self._changescache[1]
332 else:
351 else:
333 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
352 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
334 # getcopies() detects missing revlogs early, run it before
353 # getcopies() detects missing revlogs early, run it before
335 # filtering the changes.
354 # filtering the changes.
336 copies = self.getcopies(ctx, parents, m + a)
355 copies = self.getcopies(ctx, parents, m + a)
337 changes = [(name, rev) for name in m + a + r
356 changes = [(name, rev) for name in m + a + r
338 if name not in self.ignored]
357 if name not in self.ignored]
339 return sorted(changes), copies
358 return sorted(changes), copies
340
359
341 def getcopies(self, ctx, parents, files):
360 def getcopies(self, ctx, parents, files):
342 copies = {}
361 copies = {}
343 for name in files:
362 for name in files:
344 if name in self.ignored:
363 if name in self.ignored:
345 continue
364 continue
346 try:
365 try:
347 copysource, _copynode = ctx.filectx(name).renamed()
366 copysource, _copynode = ctx.filectx(name).renamed()
348 if copysource in self.ignored:
367 if copysource in self.ignored:
349 continue
368 continue
350 # Ignore copy sources not in parent revisions
369 # Ignore copy sources not in parent revisions
351 found = False
370 found = False
352 for p in parents:
371 for p in parents:
353 if copysource in p:
372 if copysource in p:
354 found = True
373 found = True
355 break
374 break
356 if not found:
375 if not found:
357 continue
376 continue
358 copies[name] = copysource
377 copies[name] = copysource
359 except TypeError:
378 except TypeError:
360 pass
379 pass
361 except error.LookupError, e:
380 except error.LookupError, e:
362 if not self.ignoreerrors:
381 if not self.ignoreerrors:
363 raise
382 raise
364 self.ignored.add(name)
383 self.ignored.add(name)
365 self.ui.warn(_('ignoring: %s\n') % e)
384 self.ui.warn(_('ignoring: %s\n') % e)
366 return copies
385 return copies
367
386
368 def getcommit(self, rev):
387 def getcommit(self, rev):
369 ctx = self.changectx(rev)
388 ctx = self.changectx(rev)
370 parents = [p.hex() for p in self.parents(ctx)]
389 parents = [p.hex() for p in self.parents(ctx)]
371 if self.saverev:
390 if self.saverev:
372 crev = rev
391 crev = rev
373 else:
392 else:
374 crev = None
393 crev = None
375 return commit(author=ctx.user(),
394 return commit(author=ctx.user(),
376 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
395 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
377 desc=ctx.description(), rev=crev, parents=parents,
396 desc=ctx.description(), rev=crev, parents=parents,
378 branch=ctx.branch(), extra=ctx.extra(),
397 branch=ctx.branch(), extra=ctx.extra(),
379 sortkey=ctx.rev())
398 sortkey=ctx.rev())
380
399
381 def gettags(self):
400 def gettags(self):
382 tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
401 tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
383 return dict([(name, hex(node)) for name, node in tags
402 return dict([(name, hex(node)) for name, node in tags
384 if self.keep(node)])
403 if self.keep(node)])
385
404
386 def getchangedfiles(self, rev, i):
405 def getchangedfiles(self, rev, i):
387 ctx = self.changectx(rev)
406 ctx = self.changectx(rev)
388 parents = self.parents(ctx)
407 parents = self.parents(ctx)
389 if not parents and i is None:
408 if not parents and i is None:
390 i = 0
409 i = 0
391 changes = [], ctx.manifest().keys(), []
410 changes = [], ctx.manifest().keys(), []
392 else:
411 else:
393 i = i or 0
412 i = i or 0
394 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
413 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
395 changes = [[f for f in l if f not in self.ignored] for l in changes]
414 changes = [[f for f in l if f not in self.ignored] for l in changes]
396
415
397 if i == 0:
416 if i == 0:
398 self._changescache = (rev, changes)
417 self._changescache = (rev, changes)
399
418
400 return changes[0] + changes[1] + changes[2]
419 return changes[0] + changes[1] + changes[2]
401
420
402 def converted(self, rev, destrev):
421 def converted(self, rev, destrev):
403 if self.convertfp is None:
422 if self.convertfp is None:
404 self.convertfp = open(self.repo.join('shamap'), 'a')
423 self.convertfp = open(self.repo.join('shamap'), 'a')
405 self.convertfp.write('%s %s\n' % (destrev, rev))
424 self.convertfp.write('%s %s\n' % (destrev, rev))
406 self.convertfp.flush()
425 self.convertfp.flush()
407
426
408 def before(self):
427 def before(self):
409 self.ui.debug('run hg source pre-conversion action\n')
428 self.ui.debug('run hg source pre-conversion action\n')
410
429
411 def after(self):
430 def after(self):
412 self.ui.debug('run hg source post-conversion action\n')
431 self.ui.debug('run hg source post-conversion action\n')
413
432
414 def hasnativeorder(self):
433 def hasnativeorder(self):
415 return True
434 return True
416
435
417 def hasnativeclose(self):
436 def hasnativeclose(self):
418 return True
437 return True
419
438
420 def lookuprev(self, rev):
439 def lookuprev(self, rev):
421 try:
440 try:
422 return hex(self.repo.lookup(rev))
441 return hex(self.repo.lookup(rev))
423 except error.RepoError:
442 except error.RepoError:
424 return None
443 return None
425
444
426 def getbookmarks(self):
445 def getbookmarks(self):
427 return bookmarks.listbookmarks(self.repo)
446 return bookmarks.listbookmarks(self.repo)
428
447
429 def checkrevformat(self, revstr, mapname='splicemap'):
448 def checkrevformat(self, revstr, mapname='splicemap'):
430 """ Mercurial, revision string is a 40 byte hex """
449 """ Mercurial, revision string is a 40 byte hex """
431 self.checkhexformat(revstr, mapname)
450 self.checkhexformat(revstr, mapname)
General Comments 0
You need to be logged in to leave comments. Login now