##// END OF EJS Templates
convert: make hg sink cleanup safer
Matt Mackall -
r10086:e388f5ee stable
parent child Browse files
Show More
@@ -1,370 +1,372
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, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
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, error
24 from mercurial import hg, util, context, error
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 class mercurial_sink(converter_sink):
28 class mercurial_sink(converter_sink):
29 def __init__(self, ui, path):
29 def __init__(self, ui, path):
30 converter_sink.__init__(self, ui, path)
30 converter_sink.__init__(self, ui, path)
31 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
31 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
32 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
32 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
33 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
33 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
34 self.lastbranch = None
34 self.lastbranch = None
35 if os.path.isdir(path) and len(os.listdir(path)) > 0:
35 if os.path.isdir(path) and len(os.listdir(path)) > 0:
36 try:
36 try:
37 self.repo = hg.repository(self.ui, path)
37 self.repo = hg.repository(self.ui, path)
38 if not self.repo.local():
38 if not self.repo.local():
39 raise NoRepo(_('%s is not a local Mercurial repo') % path)
39 raise NoRepo(_('%s is not a local Mercurial repo') % path)
40 except error.RepoError, err:
40 except error.RepoError, err:
41 ui.traceback()
41 ui.traceback()
42 raise NoRepo(err.args[0])
42 raise NoRepo(err.args[0])
43 else:
43 else:
44 try:
44 try:
45 ui.status(_('initializing destination %s repository\n') % path)
45 ui.status(_('initializing destination %s repository\n') % path)
46 self.repo = hg.repository(self.ui, path, create=True)
46 self.repo = hg.repository(self.ui, path, create=True)
47 if not self.repo.local():
47 if not self.repo.local():
48 raise NoRepo(_('%s is not a local Mercurial repo') % path)
48 raise NoRepo(_('%s is not a local Mercurial repo') % path)
49 self.created.append(path)
49 self.created.append(path)
50 except error.RepoError:
50 except error.RepoError:
51 ui.traceback()
51 ui.traceback()
52 raise NoRepo("could not create hg repo %s as sink" % path)
52 raise NoRepo("could not create hg repo %s as sink" % path)
53 self.lock = None
53 self.lock = None
54 self.wlock = None
54 self.wlock = None
55 self.filemapmode = False
55 self.filemapmode = False
56
56
57 def before(self):
57 def before(self):
58 self.ui.debug('run hg sink pre-conversion action\n')
58 self.ui.debug('run hg sink pre-conversion action\n')
59 self.wlock = self.repo.wlock()
59 self.wlock = self.repo.wlock()
60 self.lock = self.repo.lock()
60 self.lock = self.repo.lock()
61
61
62 def after(self):
62 def after(self):
63 self.ui.debug('run hg sink post-conversion action\n')
63 self.ui.debug('run hg sink post-conversion action\n')
64 if self.lock:
64 self.lock.release()
65 self.lock.release()
66 if self.wlock:
65 self.wlock.release()
67 self.wlock.release()
66
68
67 def revmapfile(self):
69 def revmapfile(self):
68 return os.path.join(self.path, ".hg", "shamap")
70 return os.path.join(self.path, ".hg", "shamap")
69
71
70 def authorfile(self):
72 def authorfile(self):
71 return os.path.join(self.path, ".hg", "authormap")
73 return os.path.join(self.path, ".hg", "authormap")
72
74
73 def getheads(self):
75 def getheads(self):
74 h = self.repo.changelog.heads()
76 h = self.repo.changelog.heads()
75 return [ hex(x) for x in h ]
77 return [ hex(x) for x in h ]
76
78
77 def setbranch(self, branch, pbranches):
79 def setbranch(self, branch, pbranches):
78 if not self.clonebranches:
80 if not self.clonebranches:
79 return
81 return
80
82
81 setbranch = (branch != self.lastbranch)
83 setbranch = (branch != self.lastbranch)
82 self.lastbranch = branch
84 self.lastbranch = branch
83 if not branch:
85 if not branch:
84 branch = 'default'
86 branch = 'default'
85 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
87 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
86 pbranch = pbranches and pbranches[0][1] or 'default'
88 pbranch = pbranches and pbranches[0][1] or 'default'
87
89
88 branchpath = os.path.join(self.path, branch)
90 branchpath = os.path.join(self.path, branch)
89 if setbranch:
91 if setbranch:
90 self.after()
92 self.after()
91 try:
93 try:
92 self.repo = hg.repository(self.ui, branchpath)
94 self.repo = hg.repository(self.ui, branchpath)
93 except:
95 except:
94 self.repo = hg.repository(self.ui, branchpath, create=True)
96 self.repo = hg.repository(self.ui, branchpath, create=True)
95 self.before()
97 self.before()
96
98
97 # pbranches may bring revisions from other branches (merge parents)
99 # pbranches may bring revisions from other branches (merge parents)
98 # Make sure we have them, or pull them.
100 # Make sure we have them, or pull them.
99 missings = {}
101 missings = {}
100 for b in pbranches:
102 for b in pbranches:
101 try:
103 try:
102 self.repo.lookup(b[0])
104 self.repo.lookup(b[0])
103 except:
105 except:
104 missings.setdefault(b[1], []).append(b[0])
106 missings.setdefault(b[1], []).append(b[0])
105
107
106 if missings:
108 if missings:
107 self.after()
109 self.after()
108 for pbranch, heads in missings.iteritems():
110 for pbranch, heads in missings.iteritems():
109 pbranchpath = os.path.join(self.path, pbranch)
111 pbranchpath = os.path.join(self.path, pbranch)
110 prepo = hg.repository(self.ui, pbranchpath)
112 prepo = hg.repository(self.ui, pbranchpath)
111 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
113 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
112 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
114 self.repo.pull(prepo, [prepo.lookup(h) for h in heads])
113 self.before()
115 self.before()
114
116
115 def _rewritetags(self, source, revmap, data):
117 def _rewritetags(self, source, revmap, data):
116 fp = cStringIO.StringIO()
118 fp = cStringIO.StringIO()
117 for line in data.splitlines():
119 for line in data.splitlines():
118 s = line.split(' ', 1)
120 s = line.split(' ', 1)
119 if len(s) != 2:
121 if len(s) != 2:
120 continue
122 continue
121 revid = revmap.get(source.lookuprev(s[0]))
123 revid = revmap.get(source.lookuprev(s[0]))
122 if not revid:
124 if not revid:
123 continue
125 continue
124 fp.write('%s %s\n' % (revid, s[1]))
126 fp.write('%s %s\n' % (revid, s[1]))
125 return fp.getvalue()
127 return fp.getvalue()
126
128
127 def putcommit(self, files, copies, parents, commit, source, revmap):
129 def putcommit(self, files, copies, parents, commit, source, revmap):
128
130
129 files = dict(files)
131 files = dict(files)
130 def getfilectx(repo, memctx, f):
132 def getfilectx(repo, memctx, f):
131 v = files[f]
133 v = files[f]
132 data = source.getfile(f, v)
134 data = source.getfile(f, v)
133 e = source.getmode(f, v)
135 e = source.getmode(f, v)
134 if f == '.hgtags':
136 if f == '.hgtags':
135 data = self._rewritetags(source, revmap, data)
137 data = self._rewritetags(source, revmap, data)
136 return context.memfilectx(f, data, 'l' in e, 'x' in e, copies.get(f))
138 return context.memfilectx(f, data, 'l' in e, 'x' in e, copies.get(f))
137
139
138 pl = []
140 pl = []
139 for p in parents:
141 for p in parents:
140 if p not in pl:
142 if p not in pl:
141 pl.append(p)
143 pl.append(p)
142 parents = pl
144 parents = pl
143 nparents = len(parents)
145 nparents = len(parents)
144 if self.filemapmode and nparents == 1:
146 if self.filemapmode and nparents == 1:
145 m1node = self.repo.changelog.read(bin(parents[0]))[0]
147 m1node = self.repo.changelog.read(bin(parents[0]))[0]
146 parent = parents[0]
148 parent = parents[0]
147
149
148 if len(parents) < 2: parents.append(nullid)
150 if len(parents) < 2: parents.append(nullid)
149 if len(parents) < 2: parents.append(nullid)
151 if len(parents) < 2: parents.append(nullid)
150 p2 = parents.pop(0)
152 p2 = parents.pop(0)
151
153
152 text = commit.desc
154 text = commit.desc
153 extra = commit.extra.copy()
155 extra = commit.extra.copy()
154 if self.branchnames and commit.branch:
156 if self.branchnames and commit.branch:
155 extra['branch'] = commit.branch
157 extra['branch'] = commit.branch
156 if commit.rev:
158 if commit.rev:
157 extra['convert_revision'] = commit.rev
159 extra['convert_revision'] = commit.rev
158
160
159 while parents:
161 while parents:
160 p1 = p2
162 p1 = p2
161 p2 = parents.pop(0)
163 p2 = parents.pop(0)
162 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(), getfilectx,
164 ctx = context.memctx(self.repo, (p1, p2), text, files.keys(), getfilectx,
163 commit.author, commit.date, extra)
165 commit.author, commit.date, extra)
164 self.repo.commitctx(ctx)
166 self.repo.commitctx(ctx)
165 text = "(octopus merge fixup)\n"
167 text = "(octopus merge fixup)\n"
166 p2 = hex(self.repo.changelog.tip())
168 p2 = hex(self.repo.changelog.tip())
167
169
168 if self.filemapmode and nparents == 1:
170 if self.filemapmode and nparents == 1:
169 man = self.repo.manifest
171 man = self.repo.manifest
170 mnode = self.repo.changelog.read(bin(p2))[0]
172 mnode = self.repo.changelog.read(bin(p2))[0]
171 if not man.cmp(m1node, man.revision(mnode)):
173 if not man.cmp(m1node, man.revision(mnode)):
172 self.ui.status(_("filtering out empty revision\n"))
174 self.ui.status(_("filtering out empty revision\n"))
173 self.repo.rollback()
175 self.repo.rollback()
174 return parent
176 return parent
175 return p2
177 return p2
176
178
177 def puttags(self, tags):
179 def puttags(self, tags):
178 try:
180 try:
179 parentctx = self.repo[self.tagsbranch]
181 parentctx = self.repo[self.tagsbranch]
180 tagparent = parentctx.node()
182 tagparent = parentctx.node()
181 except error.RepoError:
183 except error.RepoError:
182 parentctx = None
184 parentctx = None
183 tagparent = nullid
185 tagparent = nullid
184
186
185 try:
187 try:
186 oldlines = sorted(parentctx['.hgtags'].data().splitlines(True))
188 oldlines = sorted(parentctx['.hgtags'].data().splitlines(True))
187 except:
189 except:
188 oldlines = []
190 oldlines = []
189
191
190 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
192 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
191 if newlines == oldlines:
193 if newlines == oldlines:
192 return None, None
194 return None, None
193 data = "".join(newlines)
195 data = "".join(newlines)
194 def getfilectx(repo, memctx, f):
196 def getfilectx(repo, memctx, f):
195 return context.memfilectx(f, data, False, False, None)
197 return context.memfilectx(f, data, False, False, None)
196
198
197 self.ui.status(_("updating tags\n"))
199 self.ui.status(_("updating tags\n"))
198 date = "%s 0" % int(time.mktime(time.gmtime()))
200 date = "%s 0" % int(time.mktime(time.gmtime()))
199 extra = {'branch': self.tagsbranch}
201 extra = {'branch': self.tagsbranch}
200 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
202 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
201 [".hgtags"], getfilectx, "convert-repo", date,
203 [".hgtags"], getfilectx, "convert-repo", date,
202 extra)
204 extra)
203 self.repo.commitctx(ctx)
205 self.repo.commitctx(ctx)
204 return hex(self.repo.changelog.tip()), hex(tagparent)
206 return hex(self.repo.changelog.tip()), hex(tagparent)
205
207
206 def setfilemapmode(self, active):
208 def setfilemapmode(self, active):
207 self.filemapmode = active
209 self.filemapmode = active
208
210
209 class mercurial_source(converter_source):
211 class mercurial_source(converter_source):
210 def __init__(self, ui, path, rev=None):
212 def __init__(self, ui, path, rev=None):
211 converter_source.__init__(self, ui, path, rev)
213 converter_source.__init__(self, ui, path, rev)
212 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
214 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
213 self.ignored = set()
215 self.ignored = set()
214 self.saverev = ui.configbool('convert', 'hg.saverev', False)
216 self.saverev = ui.configbool('convert', 'hg.saverev', False)
215 try:
217 try:
216 self.repo = hg.repository(self.ui, path)
218 self.repo = hg.repository(self.ui, path)
217 # try to provoke an exception if this isn't really a hg
219 # try to provoke an exception if this isn't really a hg
218 # repo, but some other bogus compatible-looking url
220 # repo, but some other bogus compatible-looking url
219 if not self.repo.local():
221 if not self.repo.local():
220 raise error.RepoError()
222 raise error.RepoError()
221 except error.RepoError:
223 except error.RepoError:
222 ui.traceback()
224 ui.traceback()
223 raise NoRepo("%s is not a local Mercurial repo" % path)
225 raise NoRepo("%s is not a local Mercurial repo" % path)
224 self.lastrev = None
226 self.lastrev = None
225 self.lastctx = None
227 self.lastctx = None
226 self._changescache = None
228 self._changescache = None
227 self.convertfp = None
229 self.convertfp = None
228 # Restrict converted revisions to startrev descendants
230 # Restrict converted revisions to startrev descendants
229 startnode = ui.config('convert', 'hg.startrev')
231 startnode = ui.config('convert', 'hg.startrev')
230 if startnode is not None:
232 if startnode is not None:
231 try:
233 try:
232 startnode = self.repo.lookup(startnode)
234 startnode = self.repo.lookup(startnode)
233 except error.RepoError:
235 except error.RepoError:
234 raise util.Abort(_('%s is not a valid start revision')
236 raise util.Abort(_('%s is not a valid start revision')
235 % startnode)
237 % startnode)
236 startrev = self.repo.changelog.rev(startnode)
238 startrev = self.repo.changelog.rev(startnode)
237 children = {startnode: 1}
239 children = {startnode: 1}
238 for rev in self.repo.changelog.descendants(startrev):
240 for rev in self.repo.changelog.descendants(startrev):
239 children[self.repo.changelog.node(rev)] = 1
241 children[self.repo.changelog.node(rev)] = 1
240 self.keep = children.__contains__
242 self.keep = children.__contains__
241 else:
243 else:
242 self.keep = util.always
244 self.keep = util.always
243
245
244 def changectx(self, rev):
246 def changectx(self, rev):
245 if self.lastrev != rev:
247 if self.lastrev != rev:
246 self.lastctx = self.repo[rev]
248 self.lastctx = self.repo[rev]
247 self.lastrev = rev
249 self.lastrev = rev
248 return self.lastctx
250 return self.lastctx
249
251
250 def parents(self, ctx):
252 def parents(self, ctx):
251 return [p for p in ctx.parents() if p and self.keep(p.node())]
253 return [p for p in ctx.parents() if p and self.keep(p.node())]
252
254
253 def getheads(self):
255 def getheads(self):
254 if self.rev:
256 if self.rev:
255 heads = [self.repo[self.rev].node()]
257 heads = [self.repo[self.rev].node()]
256 else:
258 else:
257 heads = self.repo.heads()
259 heads = self.repo.heads()
258 return [hex(h) for h in heads if self.keep(h)]
260 return [hex(h) for h in heads if self.keep(h)]
259
261
260 def getfile(self, name, rev):
262 def getfile(self, name, rev):
261 try:
263 try:
262 return self.changectx(rev)[name].data()
264 return self.changectx(rev)[name].data()
263 except error.LookupError, err:
265 except error.LookupError, err:
264 raise IOError(err)
266 raise IOError(err)
265
267
266 def getmode(self, name, rev):
268 def getmode(self, name, rev):
267 return self.changectx(rev).manifest().flags(name)
269 return self.changectx(rev).manifest().flags(name)
268
270
269 def getchanges(self, rev):
271 def getchanges(self, rev):
270 ctx = self.changectx(rev)
272 ctx = self.changectx(rev)
271 parents = self.parents(ctx)
273 parents = self.parents(ctx)
272 if not parents:
274 if not parents:
273 files = sorted(ctx.manifest())
275 files = sorted(ctx.manifest())
274 if self.ignoreerrors:
276 if self.ignoreerrors:
275 # calling getcopies() is a simple way to detect missing
277 # calling getcopies() is a simple way to detect missing
276 # revlogs and populate self.ignored
278 # revlogs and populate self.ignored
277 self.getcopies(ctx, parents, files)
279 self.getcopies(ctx, parents, files)
278 return [(f, rev) for f in files if f not in self.ignored], {}
280 return [(f, rev) for f in files if f not in self.ignored], {}
279 if self._changescache and self._changescache[0] == rev:
281 if self._changescache and self._changescache[0] == rev:
280 m, a, r = self._changescache[1]
282 m, a, r = self._changescache[1]
281 else:
283 else:
282 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
284 m, a, r = self.repo.status(parents[0].node(), ctx.node())[:3]
283 # getcopies() detects missing revlogs early, run it before
285 # getcopies() detects missing revlogs early, run it before
284 # filtering the changes.
286 # filtering the changes.
285 copies = self.getcopies(ctx, parents, m + a)
287 copies = self.getcopies(ctx, parents, m + a)
286 changes = [(name, rev) for name in m + a + r
288 changes = [(name, rev) for name in m + a + r
287 if name not in self.ignored]
289 if name not in self.ignored]
288 return sorted(changes), copies
290 return sorted(changes), copies
289
291
290 def getcopies(self, ctx, parents, files):
292 def getcopies(self, ctx, parents, files):
291 copies = {}
293 copies = {}
292 for name in files:
294 for name in files:
293 if name in self.ignored:
295 if name in self.ignored:
294 continue
296 continue
295 try:
297 try:
296 copysource, copynode = ctx.filectx(name).renamed()
298 copysource, copynode = ctx.filectx(name).renamed()
297 if copysource in self.ignored or not self.keep(copynode):
299 if copysource in self.ignored or not self.keep(copynode):
298 continue
300 continue
299 # Ignore copy sources not in parent revisions
301 # Ignore copy sources not in parent revisions
300 found = False
302 found = False
301 for p in parents:
303 for p in parents:
302 if copysource in p:
304 if copysource in p:
303 found = True
305 found = True
304 break
306 break
305 if not found:
307 if not found:
306 continue
308 continue
307 copies[name] = copysource
309 copies[name] = copysource
308 except TypeError:
310 except TypeError:
309 pass
311 pass
310 except error.LookupError, e:
312 except error.LookupError, e:
311 if not self.ignoreerrors:
313 if not self.ignoreerrors:
312 raise
314 raise
313 self.ignored.add(name)
315 self.ignored.add(name)
314 self.ui.warn(_('ignoring: %s\n') % e)
316 self.ui.warn(_('ignoring: %s\n') % e)
315 return copies
317 return copies
316
318
317 def getcommit(self, rev):
319 def getcommit(self, rev):
318 ctx = self.changectx(rev)
320 ctx = self.changectx(rev)
319 parents = [p.hex() for p in self.parents(ctx)]
321 parents = [p.hex() for p in self.parents(ctx)]
320 if self.saverev:
322 if self.saverev:
321 crev = rev
323 crev = rev
322 else:
324 else:
323 crev = None
325 crev = None
324 return commit(author=ctx.user(), date=util.datestr(ctx.date()),
326 return commit(author=ctx.user(), date=util.datestr(ctx.date()),
325 desc=ctx.description(), rev=crev, parents=parents,
327 desc=ctx.description(), rev=crev, parents=parents,
326 branch=ctx.branch(), extra=ctx.extra(),
328 branch=ctx.branch(), extra=ctx.extra(),
327 sortkey=ctx.rev())
329 sortkey=ctx.rev())
328
330
329 def gettags(self):
331 def gettags(self):
330 tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
332 tags = [t for t in self.repo.tagslist() if t[0] != 'tip']
331 return dict([(name, hex(node)) for name, node in tags
333 return dict([(name, hex(node)) for name, node in tags
332 if self.keep(node)])
334 if self.keep(node)])
333
335
334 def getchangedfiles(self, rev, i):
336 def getchangedfiles(self, rev, i):
335 ctx = self.changectx(rev)
337 ctx = self.changectx(rev)
336 parents = self.parents(ctx)
338 parents = self.parents(ctx)
337 if not parents and i is None:
339 if not parents and i is None:
338 i = 0
340 i = 0
339 changes = [], ctx.manifest().keys(), []
341 changes = [], ctx.manifest().keys(), []
340 else:
342 else:
341 i = i or 0
343 i = i or 0
342 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
344 changes = self.repo.status(parents[i].node(), ctx.node())[:3]
343 changes = [[f for f in l if f not in self.ignored] for l in changes]
345 changes = [[f for f in l if f not in self.ignored] for l in changes]
344
346
345 if i == 0:
347 if i == 0:
346 self._changescache = (rev, changes)
348 self._changescache = (rev, changes)
347
349
348 return changes[0] + changes[1] + changes[2]
350 return changes[0] + changes[1] + changes[2]
349
351
350 def converted(self, rev, destrev):
352 def converted(self, rev, destrev):
351 if self.convertfp is None:
353 if self.convertfp is None:
352 self.convertfp = open(os.path.join(self.path, '.hg', 'shamap'),
354 self.convertfp = open(os.path.join(self.path, '.hg', 'shamap'),
353 'a')
355 'a')
354 self.convertfp.write('%s %s\n' % (destrev, rev))
356 self.convertfp.write('%s %s\n' % (destrev, rev))
355 self.convertfp.flush()
357 self.convertfp.flush()
356
358
357 def before(self):
359 def before(self):
358 self.ui.debug('run hg source pre-conversion action\n')
360 self.ui.debug('run hg source pre-conversion action\n')
359
361
360 def after(self):
362 def after(self):
361 self.ui.debug('run hg source post-conversion action\n')
363 self.ui.debug('run hg source post-conversion action\n')
362
364
363 def hasnativeorder(self):
365 def hasnativeorder(self):
364 return True
366 return True
365
367
366 def lookuprev(self, rev):
368 def lookuprev(self, rev):
367 try:
369 try:
368 return hex(self.repo.lookup(rev))
370 return hex(self.repo.lookup(rev))
369 except error.RepoError:
371 except error.RepoError:
370 return None
372 return None
General Comments 0
You need to be logged in to leave comments. Login now