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