##// END OF EJS Templates
convert: hg use absolute_import
timeless -
r28370:c1878afb default
parent child Browse files
Show More
@@ -1,634 +1,651 b''
1 1 # hg.py - hg backend for convert extension
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # Notes for hg->hg conversion:
9 9 #
10 10 # * Old versions of Mercurial didn't trim the whitespace from the ends
11 11 # of commit messages, but new versions do. Changesets created by
12 12 # those older versions, then converted, may thus have different
13 13 # hashes for changesets that are otherwise identical.
14 14 #
15 15 # * Using "--config convert.hg.saverev=true" will make the source
16 16 # identifier to be stored in the converted revision. This will cause
17 17 # the converted revision to have a different identity than the
18 18 # source.
19 from __future__ import absolute_import
19 20
21 import cStringIO
22 import os
23 import re
24 import time
20 25
21 import os, time, cStringIO
26 from mercurial import (
27 bookmarks,
28 context,
29 error,
30 exchange,
31 hg,
32 lock as lockmod,
33 merge as mergemod,
34 node as nodemod,
35 phases,
36 scmutil,
37 util,
38 )
22 39 from mercurial.i18n import _
23 from mercurial.node import bin, hex, nullid
24 from mercurial import hg, util, context, bookmarks, error, scmutil, exchange
25 from mercurial import phases
26 from mercurial import lock as lockmod
27 from mercurial import merge as mergemod
40 from . import common
41 mapfile = common.mapfile
42 NoRepo = common.NoRepo
28 43
29 from common import NoRepo, commit, converter_source, converter_sink, mapfile
30
31 import re
32 44 sha1re = re.compile(r'\b[0-9a-f]{12,40}\b')
33 45
34 class mercurial_sink(converter_sink):
46 class mercurial_sink(common.converter_sink):
35 47 def __init__(self, ui, path):
36 converter_sink.__init__(self, ui, path)
48 common.converter_sink.__init__(self, ui, path)
37 49 self.branchnames = ui.configbool('convert', 'hg.usebranchnames', True)
38 50 self.clonebranches = ui.configbool('convert', 'hg.clonebranches', False)
39 51 self.tagsbranch = ui.config('convert', 'hg.tagsbranch', 'default')
40 52 self.lastbranch = None
41 53 if os.path.isdir(path) and len(os.listdir(path)) > 0:
42 54 try:
43 55 self.repo = hg.repository(self.ui, path)
44 56 if not self.repo.local():
45 57 raise NoRepo(_('%s is not a local Mercurial repository')
46 58 % path)
47 59 except error.RepoError as err:
48 60 ui.traceback()
49 61 raise NoRepo(err.args[0])
50 62 else:
51 63 try:
52 64 ui.status(_('initializing destination %s repository\n') % path)
53 65 self.repo = hg.repository(self.ui, path, create=True)
54 66 if not self.repo.local():
55 67 raise NoRepo(_('%s is not a local Mercurial repository')
56 68 % path)
57 69 self.created.append(path)
58 70 except error.RepoError:
59 71 ui.traceback()
60 72 raise NoRepo(_("could not create hg repository %s as sink")
61 73 % path)
62 74 self.lock = None
63 75 self.wlock = None
64 76 self.filemapmode = False
65 77 self.subrevmaps = {}
66 78
67 79 def before(self):
68 80 self.ui.debug('run hg sink pre-conversion action\n')
69 81 self.wlock = self.repo.wlock()
70 82 self.lock = self.repo.lock()
71 83
72 84 def after(self):
73 85 self.ui.debug('run hg sink post-conversion action\n')
74 86 if self.lock:
75 87 self.lock.release()
76 88 if self.wlock:
77 89 self.wlock.release()
78 90
79 91 def revmapfile(self):
80 92 return self.repo.join("shamap")
81 93
82 94 def authorfile(self):
83 95 return self.repo.join("authormap")
84 96
85 97 def setbranch(self, branch, pbranches):
86 98 if not self.clonebranches:
87 99 return
88 100
89 101 setbranch = (branch != self.lastbranch)
90 102 self.lastbranch = branch
91 103 if not branch:
92 104 branch = 'default'
93 105 pbranches = [(b[0], b[1] and b[1] or 'default') for b in pbranches]
94 106 if pbranches:
95 107 pbranch = pbranches[0][1]
96 108 else:
97 109 pbranch = 'default'
98 110
99 111 branchpath = os.path.join(self.path, branch)
100 112 if setbranch:
101 113 self.after()
102 114 try:
103 115 self.repo = hg.repository(self.ui, branchpath)
104 116 except Exception:
105 117 self.repo = hg.repository(self.ui, branchpath, create=True)
106 118 self.before()
107 119
108 120 # pbranches may bring revisions from other branches (merge parents)
109 121 # Make sure we have them, or pull them.
110 122 missings = {}
111 123 for b in pbranches:
112 124 try:
113 125 self.repo.lookup(b[0])
114 126 except Exception:
115 127 missings.setdefault(b[1], []).append(b[0])
116 128
117 129 if missings:
118 130 self.after()
119 131 for pbranch, heads in sorted(missings.iteritems()):
120 132 pbranchpath = os.path.join(self.path, pbranch)
121 133 prepo = hg.peer(self.ui, {}, pbranchpath)
122 134 self.ui.note(_('pulling from %s into %s\n') % (pbranch, branch))
123 135 exchange.pull(self.repo, prepo,
124 136 [prepo.lookup(h) for h in heads])
125 137 self.before()
126 138
127 139 def _rewritetags(self, source, revmap, data):
128 140 fp = cStringIO.StringIO()
129 141 for line in data.splitlines():
130 142 s = line.split(' ', 1)
131 143 if len(s) != 2:
132 144 continue
133 145 revid = revmap.get(source.lookuprev(s[0]))
134 146 if not revid:
135 if s[0] == hex(nullid):
147 if s[0] == nodemod.nullhex:
136 148 revid = s[0]
137 149 else:
138 150 continue
139 151 fp.write('%s %s\n' % (revid, s[1]))
140 152 return fp.getvalue()
141 153
142 154 def _rewritesubstate(self, source, data):
143 155 fp = cStringIO.StringIO()
144 156 for line in data.splitlines():
145 157 s = line.split(' ', 1)
146 158 if len(s) != 2:
147 159 continue
148 160
149 161 revid = s[0]
150 162 subpath = s[1]
151 if revid != hex(nullid):
163 if revid != nodemod.nullhex:
152 164 revmap = self.subrevmaps.get(subpath)
153 165 if revmap is None:
154 166 revmap = mapfile(self.ui,
155 167 self.repo.wjoin(subpath, '.hg/shamap'))
156 168 self.subrevmaps[subpath] = revmap
157 169
158 170 # It is reasonable that one or more of the subrepos don't
159 171 # need to be converted, in which case they can be cloned
160 172 # into place instead of converted. Therefore, only warn
161 173 # once.
162 174 msg = _('no ".hgsubstate" updates will be made for "%s"\n')
163 175 if len(revmap) == 0:
164 176 sub = self.repo.wvfs.reljoin(subpath, '.hg')
165 177
166 178 if self.repo.wvfs.exists(sub):
167 179 self.ui.warn(msg % subpath)
168 180
169 181 newid = revmap.get(revid)
170 182 if not newid:
171 183 if len(revmap) > 0:
172 184 self.ui.warn(_("%s is missing from %s/.hg/shamap\n") %
173 185 (revid, subpath))
174 186 else:
175 187 revid = newid
176 188
177 189 fp.write('%s %s\n' % (revid, subpath))
178 190
179 191 return fp.getvalue()
180 192
181 193 def _calculatemergedfiles(self, source, p1ctx, p2ctx):
182 194 """Calculates the files from p2 that we need to pull in when merging p1
183 195 and p2, given that the merge is coming from the given source.
184 196
185 197 This prevents us from losing files that only exist in the target p2 and
186 198 that don't come from the source repo (like if you're merging multiple
187 199 repositories together).
188 200 """
189 201 anc = [p1ctx.ancestor(p2ctx)]
190 202 # Calculate what files are coming from p2
191 203 actions, diverge, rename = mergemod.calculateupdates(
192 204 self.repo, p1ctx, p2ctx, anc,
193 205 True, # branchmerge
194 206 True, # force
195 207 False, # acceptremote
196 208 False, # followcopies
197 209 )
198 210
199 211 for file, (action, info, msg) in actions.iteritems():
200 212 if source.targetfilebelongstosource(file):
201 213 # If the file belongs to the source repo, ignore the p2
202 214 # since it will be covered by the existing fileset.
203 215 continue
204 216
205 217 # If the file requires actual merging, abort. We don't have enough
206 218 # context to resolve merges correctly.
207 219 if action in ['m', 'dm', 'cd', 'dc']:
208 220 raise error.Abort(_("unable to convert merge commit "
209 221 "since target parents do not merge cleanly (file "
210 222 "%s, parents %s and %s)") % (file, p1ctx,
211 223 p2ctx))
212 224 elif action == 'k':
213 225 # 'keep' means nothing changed from p1
214 226 continue
215 227 else:
216 228 # Any other change means we want to take the p2 version
217 229 yield file
218 230
219 231 def putcommit(self, files, copies, parents, commit, source, revmap, full,
220 232 cleanp2):
221 233 files = dict(files)
222 234
223 235 def getfilectx(repo, memctx, f):
224 236 if p2ctx and f in p2files and f not in copies:
225 237 self.ui.debug('reusing %s from p2\n' % f)
226 238 try:
227 239 return p2ctx[f]
228 240 except error.ManifestLookupError:
229 241 # If the file doesn't exist in p2, then we're syncing a
230 242 # delete, so just return None.
231 243 return None
232 244 try:
233 245 v = files[f]
234 246 except KeyError:
235 247 return None
236 248 data, mode = source.getfile(f, v)
237 249 if data is None:
238 250 return None
239 251 if f == '.hgtags':
240 252 data = self._rewritetags(source, revmap, data)
241 253 if f == '.hgsubstate':
242 254 data = self._rewritesubstate(source, data)
243 255 return context.memfilectx(self.repo, f, data, 'l' in mode,
244 256 'x' in mode, copies.get(f))
245 257
246 258 pl = []
247 259 for p in parents:
248 260 if p not in pl:
249 261 pl.append(p)
250 262 parents = pl
251 263 nparents = len(parents)
252 264 if self.filemapmode and nparents == 1:
253 m1node = self.repo.changelog.read(bin(parents[0]))[0]
265 m1node = self.repo.changelog.read(nodemod.bin(parents[0]))[0]
254 266 parent = parents[0]
255 267
256 268 if len(parents) < 2:
257 parents.append(nullid)
269 parents.append(nodemod.nullid)
258 270 if len(parents) < 2:
259 parents.append(nullid)
271 parents.append(nodemod.nullid)
260 272 p2 = parents.pop(0)
261 273
262 274 text = commit.desc
263 275
264 276 sha1s = re.findall(sha1re, text)
265 277 for sha1 in sha1s:
266 278 oldrev = source.lookuprev(sha1)
267 279 newrev = revmap.get(oldrev)
268 280 if newrev is not None:
269 281 text = text.replace(sha1, newrev[:len(sha1)])
270 282
271 283 extra = commit.extra.copy()
272 284
273 285 sourcename = self.repo.ui.config('convert', 'hg.sourcename')
274 286 if sourcename:
275 287 extra['convert_source'] = sourcename
276 288
277 289 for label in ('source', 'transplant_source', 'rebase_source',
278 290 'intermediate-source'):
279 291 node = extra.get(label)
280 292
281 293 if node is None:
282 294 continue
283 295
284 296 # Only transplant stores its reference in binary
285 297 if label == 'transplant_source':
286 node = hex(node)
298 node = nodemod.hex(node)
287 299
288 300 newrev = revmap.get(node)
289 301 if newrev is not None:
290 302 if label == 'transplant_source':
291 newrev = bin(newrev)
303 newrev = nodemod.bin(newrev)
292 304
293 305 extra[label] = newrev
294 306
295 307 if self.branchnames and commit.branch:
296 308 extra['branch'] = commit.branch
297 309 if commit.rev and commit.saverev:
298 310 extra['convert_revision'] = commit.rev
299 311
300 312 while parents:
301 313 p1 = p2
302 314 p2 = parents.pop(0)
303 315 p1ctx = self.repo[p1]
304 316 p2ctx = None
305 if p2 != nullid:
317 if p2 != nodemod.nullid:
306 318 p2ctx = self.repo[p2]
307 319 fileset = set(files)
308 320 if full:
309 321 fileset.update(self.repo[p1])
310 322 fileset.update(self.repo[p2])
311 323
312 324 if p2ctx:
313 325 p2files = set(cleanp2)
314 326 for file in self._calculatemergedfiles(source, p1ctx, p2ctx):
315 327 p2files.add(file)
316 328 fileset.add(file)
317 329
318 330 ctx = context.memctx(self.repo, (p1, p2), text, fileset,
319 331 getfilectx, commit.author, commit.date, extra)
320 332
321 333 # We won't know if the conversion changes the node until after the
322 334 # commit, so copy the source's phase for now.
323 335 self.repo.ui.setconfig('phases', 'new-commit',
324 336 phases.phasenames[commit.phase], 'convert')
325 337
326 338 with self.repo.transaction("convert") as tr:
327 node = hex(self.repo.commitctx(ctx))
339 node = nodemod.hex(self.repo.commitctx(ctx))
328 340
329 341 # If the node value has changed, but the phase is lower than
330 342 # draft, set it back to draft since it hasn't been exposed
331 343 # anywhere.
332 344 if commit.rev != node:
333 345 ctx = self.repo[node]
334 346 if ctx.phase() < phases.draft:
335 347 phases.retractboundary(self.repo, tr, phases.draft,
336 348 [ctx.node()])
337 349
338 350 text = "(octopus merge fixup)\n"
339 351 p2 = node
340 352
341 353 if self.filemapmode and nparents == 1:
342 354 man = self.repo.manifest
343 mnode = self.repo.changelog.read(bin(p2))[0]
355 mnode = self.repo.changelog.read(nodemod.bin(p2))[0]
344 356 closed = 'close' in commit.extra
345 357 if not closed and not man.cmp(m1node, man.revision(mnode)):
346 358 self.ui.status(_("filtering out empty revision\n"))
347 359 self.repo.rollback(force=True)
348 360 return parent
349 361 return p2
350 362
351 363 def puttags(self, tags):
352 364 try:
353 365 parentctx = self.repo[self.tagsbranch]
354 366 tagparent = parentctx.node()
355 367 except error.RepoError:
356 368 parentctx = None
357 tagparent = nullid
369 tagparent = nodemod.nullid
358 370
359 371 oldlines = set()
360 372 for branch, heads in self.repo.branchmap().iteritems():
361 373 for h in heads:
362 374 if '.hgtags' in self.repo[h]:
363 375 oldlines.update(
364 376 set(self.repo[h]['.hgtags'].data().splitlines(True)))
365 377 oldlines = sorted(list(oldlines))
366 378
367 379 newlines = sorted([("%s %s\n" % (tags[tag], tag)) for tag in tags])
368 380 if newlines == oldlines:
369 381 return None, None
370 382
371 383 # if the old and new tags match, then there is nothing to update
372 384 oldtags = set()
373 385 newtags = set()
374 386 for line in oldlines:
375 387 s = line.strip().split(' ', 1)
376 388 if len(s) != 2:
377 389 continue
378 390 oldtags.add(s[1])
379 391 for line in newlines:
380 392 s = line.strip().split(' ', 1)
381 393 if len(s) != 2:
382 394 continue
383 395 if s[1] not in oldtags:
384 396 newtags.add(s[1].strip())
385 397
386 398 if not newtags:
387 399 return None, None
388 400
389 401 data = "".join(newlines)
390 402 def getfilectx(repo, memctx, f):
391 403 return context.memfilectx(repo, f, data, False, False, None)
392 404
393 405 self.ui.status(_("updating tags\n"))
394 406 date = "%s 0" % int(time.mktime(time.gmtime()))
395 407 extra = {'branch': self.tagsbranch}
396 408 ctx = context.memctx(self.repo, (tagparent, None), "update tags",
397 409 [".hgtags"], getfilectx, "convert-repo", date,
398 410 extra)
399 411 node = self.repo.commitctx(ctx)
400 return hex(node), hex(tagparent)
412 return nodemod.hex(node), nodemod.hex(tagparent)
401 413
402 414 def setfilemapmode(self, active):
403 415 self.filemapmode = active
404 416
405 417 def putbookmarks(self, updatedbookmark):
406 418 if not len(updatedbookmark):
407 419 return
408 420 wlock = lock = tr = None
409 421 try:
410 422 wlock = self.repo.wlock()
411 423 lock = self.repo.lock()
412 424 tr = self.repo.transaction('bookmark')
413 425 self.ui.status(_("updating bookmarks\n"))
414 426 destmarks = self.repo._bookmarks
415 427 for bookmark in updatedbookmark:
416 destmarks[bookmark] = bin(updatedbookmark[bookmark])
428 destmarks[bookmark] = nodemod.bin(updatedbookmark[bookmark])
417 429 destmarks.recordchange(tr)
418 430 tr.close()
419 431 finally:
420 432 lockmod.release(lock, wlock, tr)
421 433
422 434 def hascommitfrommap(self, rev):
423 435 # the exact semantics of clonebranches is unclear so we can't say no
424 436 return rev in self.repo or self.clonebranches
425 437
426 438 def hascommitforsplicemap(self, rev):
427 439 if rev not in self.repo and self.clonebranches:
428 440 raise error.Abort(_('revision %s not found in destination '
429 441 'repository (lookups with clonebranches=true '
430 442 'are not implemented)') % rev)
431 443 return rev in self.repo
432 444
433 class mercurial_source(converter_source):
445 class mercurial_source(common.converter_source):
434 446 def __init__(self, ui, path, revs=None):
435 converter_source.__init__(self, ui, path, revs)
447 common.converter_source.__init__(self, ui, path, revs)
436 448 self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False)
437 449 self.ignored = set()
438 450 self.saverev = ui.configbool('convert', 'hg.saverev', False)
439 451 try:
440 452 self.repo = hg.repository(self.ui, path)
441 453 # try to provoke an exception if this isn't really a hg
442 454 # repo, but some other bogus compatible-looking url
443 455 if not self.repo.local():
444 456 raise error.RepoError
445 457 except error.RepoError:
446 458 ui.traceback()
447 459 raise NoRepo(_("%s is not a local Mercurial repository") % path)
448 460 self.lastrev = None
449 461 self.lastctx = None
450 462 self._changescache = None, None
451 463 self.convertfp = None
452 464 # Restrict converted revisions to startrev descendants
453 465 startnode = ui.config('convert', 'hg.startrev')
454 466 hgrevs = ui.config('convert', 'hg.revs')
455 467 if hgrevs is None:
456 468 if startnode is not None:
457 469 try:
458 470 startnode = self.repo.lookup(startnode)
459 471 except error.RepoError:
460 472 raise error.Abort(_('%s is not a valid start revision')
461 473 % startnode)
462 474 startrev = self.repo.changelog.rev(startnode)
463 475 children = {startnode: 1}
464 476 for r in self.repo.changelog.descendants([startrev]):
465 477 children[self.repo.changelog.node(r)] = 1
466 478 self.keep = children.__contains__
467 479 else:
468 480 self.keep = util.always
469 481 if revs:
470 482 self._heads = [self.repo[r].node() for r in revs]
471 483 else:
472 484 self._heads = self.repo.heads()
473 485 else:
474 486 if revs or startnode is not None:
475 487 raise error.Abort(_('hg.revs cannot be combined with '
476 488 'hg.startrev or --rev'))
477 489 nodes = set()
478 490 parents = set()
479 491 for r in scmutil.revrange(self.repo, [hgrevs]):
480 492 ctx = self.repo[r]
481 493 nodes.add(ctx.node())
482 494 parents.update(p.node() for p in ctx.parents())
483 495 self.keep = nodes.__contains__
484 496 self._heads = nodes - parents
485 497
486 498 def _changectx(self, rev):
487 499 if self.lastrev != rev:
488 500 self.lastctx = self.repo[rev]
489 501 self.lastrev = rev
490 502 return self.lastctx
491 503
492 504 def _parents(self, ctx):
493 505 return [p for p in ctx.parents() if p and self.keep(p.node())]
494 506
495 507 def getheads(self):
496 return [hex(h) for h in self._heads if self.keep(h)]
508 return [nodemod.hex(h) for h in self._heads if self.keep(h)]
497 509
498 510 def getfile(self, name, rev):
499 511 try:
500 512 fctx = self._changectx(rev)[name]
501 513 return fctx.data(), fctx.flags()
502 514 except error.LookupError:
503 515 return None, None
504 516
505 517 def _changedfiles(self, ctx1, ctx2):
506 518 ma, r = [], []
507 519 maappend = ma.append
508 520 rappend = r.append
509 521 d = ctx1.manifest().diff(ctx2.manifest())
510 522 for f, ((node1, flag1), (node2, flag2)) in d.iteritems():
511 523 if node2 is None:
512 524 rappend(f)
513 525 else:
514 526 maappend(f)
515 527 return ma, r
516 528
517 529 def getchanges(self, rev, full):
518 530 ctx = self._changectx(rev)
519 531 parents = self._parents(ctx)
520 532 if full or not parents:
521 533 files = copyfiles = ctx.manifest()
522 534 if parents:
523 535 if self._changescache[0] == rev:
524 536 ma, r = self._changescache[1]
525 537 else:
526 538 ma, r = self._changedfiles(parents[0], ctx)
527 539 if not full:
528 540 files = ma + r
529 541 copyfiles = ma
530 542 # _getcopies() is also run for roots and before filtering so missing
531 543 # revlogs are detected early
532 544 copies = self._getcopies(ctx, parents, copyfiles)
533 545 cleanp2 = set()
534 546 if len(parents) == 2:
535 547 d = parents[1].manifest().diff(ctx.manifest(), clean=True)
536 548 for f, value in d.iteritems():
537 549 if value is None:
538 550 cleanp2.add(f)
539 551 changes = [(f, rev) for f in files if f not in self.ignored]
540 552 changes.sort()
541 553 return changes, copies, cleanp2
542 554
543 555 def _getcopies(self, ctx, parents, files):
544 556 copies = {}
545 557 for name in files:
546 558 if name in self.ignored:
547 559 continue
548 560 try:
549 561 copysource, _copynode = ctx.filectx(name).renamed()
550 562 if copysource in self.ignored:
551 563 continue
552 564 # Ignore copy sources not in parent revisions
553 565 found = False
554 566 for p in parents:
555 567 if copysource in p:
556 568 found = True
557 569 break
558 570 if not found:
559 571 continue
560 572 copies[name] = copysource
561 573 except TypeError:
562 574 pass
563 575 except error.LookupError as e:
564 576 if not self.ignoreerrors:
565 577 raise
566 578 self.ignored.add(name)
567 579 self.ui.warn(_('ignoring: %s\n') % e)
568 580 return copies
569 581
570 582 def getcommit(self, rev):
571 583 ctx = self._changectx(rev)
572 584 parents = [p.hex() for p in self._parents(ctx)]
573 585 crev = rev
574 586
575 return commit(author=ctx.user(),
576 date=util.datestr(ctx.date(), '%Y-%m-%d %H:%M:%S %1%2'),
577 desc=ctx.description(), rev=crev, parents=parents,
578 branch=ctx.branch(), extra=ctx.extra(),
579 sortkey=ctx.rev(), saverev=self.saverev,
580 phase=ctx.phase())
587 return common.commit(author=ctx.user(),
588 date=util.datestr(ctx.date(),
589 '%Y-%m-%d %H:%M:%S %1%2'),
590 desc=ctx.description(),
591 rev=crev,
592 parents=parents,
593 branch=ctx.branch(),
594 extra=ctx.extra(),
595 sortkey=ctx.rev(),
596 saverev=self.saverev,
597 phase=ctx.phase())
581 598
582 599 def gettags(self):
583 600 # This will get written to .hgtags, filter non global tags out.
584 601 tags = [t for t in self.repo.tagslist()
585 602 if self.repo.tagtype(t[0]) == 'global']
586 return dict([(name, hex(node)) for name, node in tags
603 return dict([(name, nodemod.hex(node)) for name, node in tags
587 604 if self.keep(node)])
588 605
589 606 def getchangedfiles(self, rev, i):
590 607 ctx = self._changectx(rev)
591 608 parents = self._parents(ctx)
592 609 if not parents and i is None:
593 610 i = 0
594 611 ma, r = ctx.manifest().keys(), []
595 612 else:
596 613 i = i or 0
597 614 ma, r = self._changedfiles(parents[i], ctx)
598 615 ma, r = [[f for f in l if f not in self.ignored] for l in (ma, r)]
599 616
600 617 if i == 0:
601 618 self._changescache = (rev, (ma, r))
602 619
603 620 return ma + r
604 621
605 622 def converted(self, rev, destrev):
606 623 if self.convertfp is None:
607 624 self.convertfp = open(self.repo.join('shamap'), 'a')
608 625 self.convertfp.write('%s %s\n' % (destrev, rev))
609 626 self.convertfp.flush()
610 627
611 628 def before(self):
612 629 self.ui.debug('run hg source pre-conversion action\n')
613 630
614 631 def after(self):
615 632 self.ui.debug('run hg source post-conversion action\n')
616 633
617 634 def hasnativeorder(self):
618 635 return True
619 636
620 637 def hasnativeclose(self):
621 638 return True
622 639
623 640 def lookuprev(self, rev):
624 641 try:
625 return hex(self.repo.lookup(rev))
642 return nodemod.hex(self.repo.lookup(rev))
626 643 except (error.RepoError, error.LookupError):
627 644 return None
628 645
629 646 def getbookmarks(self):
630 647 return bookmarks.listbookmarks(self.repo)
631 648
632 649 def checkrevformat(self, revstr, mapname='splicemap'):
633 650 """ Mercurial, revision string is a 40 byte hex """
634 651 self.checkhexformat(revstr, mapname)
@@ -1,153 +1,152 b''
1 1 #require test-repo
2 2
3 3 $ cd "$TESTDIR"/..
4 4
5 5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 6 contrib/check-code.py not using absolute_import
7 7 contrib/check-code.py requires print_function
8 8 contrib/debugshell.py not using absolute_import
9 9 contrib/hgfixes/fix_bytes.py not using absolute_import
10 10 contrib/hgfixes/fix_bytesmod.py not using absolute_import
11 11 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
12 12 contrib/import-checker.py not using absolute_import
13 13 contrib/import-checker.py requires print_function
14 14 contrib/memory.py not using absolute_import
15 15 contrib/perf.py not using absolute_import
16 16 contrib/python-hook-examples.py not using absolute_import
17 17 contrib/revsetbenchmarks.py not using absolute_import
18 18 contrib/revsetbenchmarks.py requires print_function
19 19 contrib/showstack.py not using absolute_import
20 20 contrib/synthrepo.py not using absolute_import
21 21 contrib/win32/hgwebdir_wsgi.py not using absolute_import
22 22 doc/check-seclevel.py not using absolute_import
23 23 doc/gendoc.py not using absolute_import
24 24 doc/hgmanpage.py not using absolute_import
25 25 hgext/__init__.py not using absolute_import
26 26 hgext/color.py not using absolute_import
27 27 hgext/convert/__init__.py not using absolute_import
28 28 hgext/convert/bzr.py not using absolute_import
29 29 hgext/convert/common.py not using absolute_import
30 30 hgext/convert/convcmd.py not using absolute_import
31 31 hgext/convert/cvs.py not using absolute_import
32 hgext/convert/hg.py not using absolute_import
33 32 hgext/convert/monotone.py not using absolute_import
34 33 hgext/convert/p4.py not using absolute_import
35 34 hgext/convert/subversion.py not using absolute_import
36 35 hgext/convert/transport.py not using absolute_import
37 36 hgext/eol.py not using absolute_import
38 37 hgext/extdiff.py not using absolute_import
39 38 hgext/factotum.py not using absolute_import
40 39 hgext/fetch.py not using absolute_import
41 40 hgext/gpg.py not using absolute_import
42 41 hgext/graphlog.py not using absolute_import
43 42 hgext/hgcia.py not using absolute_import
44 43 hgext/hgk.py not using absolute_import
45 44 hgext/highlight/__init__.py not using absolute_import
46 45 hgext/highlight/highlight.py not using absolute_import
47 46 hgext/histedit.py not using absolute_import
48 47 hgext/largefiles/__init__.py not using absolute_import
49 48 hgext/largefiles/basestore.py not using absolute_import
50 49 hgext/largefiles/lfcommands.py not using absolute_import
51 50 hgext/largefiles/lfutil.py not using absolute_import
52 51 hgext/largefiles/localstore.py not using absolute_import
53 52 hgext/largefiles/overrides.py not using absolute_import
54 53 hgext/largefiles/proto.py not using absolute_import
55 54 hgext/largefiles/remotestore.py not using absolute_import
56 55 hgext/largefiles/reposetup.py not using absolute_import
57 56 hgext/largefiles/uisetup.py not using absolute_import
58 57 hgext/largefiles/wirestore.py not using absolute_import
59 58 hgext/mq.py not using absolute_import
60 59 hgext/notify.py not using absolute_import
61 60 hgext/patchbomb.py not using absolute_import
62 61 hgext/purge.py not using absolute_import
63 62 hgext/rebase.py not using absolute_import
64 63 hgext/record.py not using absolute_import
65 64 hgext/relink.py not using absolute_import
66 65 hgext/schemes.py not using absolute_import
67 66 hgext/share.py not using absolute_import
68 67 hgext/shelve.py not using absolute_import
69 68 hgext/strip.py not using absolute_import
70 69 hgext/transplant.py not using absolute_import
71 70 hgext/win32mbcs.py not using absolute_import
72 71 hgext/win32text.py not using absolute_import
73 72 i18n/check-translation.py not using absolute_import
74 73 i18n/polib.py not using absolute_import
75 74 setup.py not using absolute_import
76 75 tests/filterpyflakes.py requires print_function
77 76 tests/generate-working-copy-states.py requires print_function
78 77 tests/get-with-headers.py requires print_function
79 78 tests/heredoctest.py requires print_function
80 79 tests/hypothesishelpers.py not using absolute_import
81 80 tests/hypothesishelpers.py requires print_function
82 81 tests/killdaemons.py not using absolute_import
83 82 tests/md5sum.py not using absolute_import
84 83 tests/mockblackbox.py not using absolute_import
85 84 tests/printenv.py not using absolute_import
86 85 tests/readlink.py not using absolute_import
87 86 tests/readlink.py requires print_function
88 87 tests/revlog-formatv0.py not using absolute_import
89 88 tests/run-tests.py not using absolute_import
90 89 tests/seq.py not using absolute_import
91 90 tests/seq.py requires print_function
92 91 tests/silenttestrunner.py not using absolute_import
93 92 tests/silenttestrunner.py requires print_function
94 93 tests/sitecustomize.py not using absolute_import
95 94 tests/svn-safe-append.py not using absolute_import
96 95 tests/svnxml.py not using absolute_import
97 96 tests/test-ancestor.py requires print_function
98 97 tests/test-atomictempfile.py not using absolute_import
99 98 tests/test-batching.py not using absolute_import
100 99 tests/test-batching.py requires print_function
101 100 tests/test-bdiff.py not using absolute_import
102 101 tests/test-bdiff.py requires print_function
103 102 tests/test-context.py not using absolute_import
104 103 tests/test-context.py requires print_function
105 104 tests/test-demandimport.py not using absolute_import
106 105 tests/test-demandimport.py requires print_function
107 106 tests/test-dispatch.py not using absolute_import
108 107 tests/test-dispatch.py requires print_function
109 108 tests/test-doctest.py not using absolute_import
110 109 tests/test-duplicateoptions.py not using absolute_import
111 110 tests/test-duplicateoptions.py requires print_function
112 111 tests/test-filecache.py not using absolute_import
113 112 tests/test-filecache.py requires print_function
114 113 tests/test-filelog.py not using absolute_import
115 114 tests/test-filelog.py requires print_function
116 115 tests/test-hg-parseurl.py not using absolute_import
117 116 tests/test-hg-parseurl.py requires print_function
118 117 tests/test-hgweb-auth.py not using absolute_import
119 118 tests/test-hgweb-auth.py requires print_function
120 119 tests/test-hgwebdir-paths.py not using absolute_import
121 120 tests/test-hybridencode.py not using absolute_import
122 121 tests/test-hybridencode.py requires print_function
123 122 tests/test-lrucachedict.py not using absolute_import
124 123 tests/test-lrucachedict.py requires print_function
125 124 tests/test-manifest.py not using absolute_import
126 125 tests/test-minirst.py not using absolute_import
127 126 tests/test-minirst.py requires print_function
128 127 tests/test-parseindex2.py not using absolute_import
129 128 tests/test-parseindex2.py requires print_function
130 129 tests/test-pathencode.py not using absolute_import
131 130 tests/test-pathencode.py requires print_function
132 131 tests/test-propertycache.py not using absolute_import
133 132 tests/test-propertycache.py requires print_function
134 133 tests/test-revlog-ancestry.py not using absolute_import
135 134 tests/test-revlog-ancestry.py requires print_function
136 135 tests/test-run-tests.py not using absolute_import
137 136 tests/test-simplemerge.py not using absolute_import
138 137 tests/test-status-inprocess.py not using absolute_import
139 138 tests/test-status-inprocess.py requires print_function
140 139 tests/test-symlink-os-yes-fs-no.py not using absolute_import
141 140 tests/test-trusted.py not using absolute_import
142 141 tests/test-trusted.py requires print_function
143 142 tests/test-ui-color.py not using absolute_import
144 143 tests/test-ui-color.py requires print_function
145 144 tests/test-ui-config.py not using absolute_import
146 145 tests/test-ui-config.py requires print_function
147 146 tests/test-ui-verbosity.py not using absolute_import
148 147 tests/test-ui-verbosity.py requires print_function
149 148 tests/test-url.py not using absolute_import
150 149 tests/test-url.py requires print_function
151 150 tests/test-walkrepo.py requires print_function
152 151 tests/test-wireproto.py requires print_function
153 152 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now