##// END OF EJS Templates
convert: convcmd use absolute_import
timeless -
r28409:c43c5e71 default
parent child Browse files
Show More
@@ -1,580 +1,608 b''
1 # convcmd - convert extension commands definition
1 # convcmd - convert extension commands definition
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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 from __future__ import absolute_import
7
8
8 from common import NoRepo, MissingTool, SKIPREV, mapfile
9 import os
9 from cvs import convert_cvs
10 import shlex
10 from darcs import darcs_source
11 import shutil
11 from git import convert_git
12
12 from hg import mercurial_source, mercurial_sink
13 from mercurial import (
13 from subversion import svn_source, svn_sink
14 encoding,
14 from monotone import monotone_source
15 error,
15 from gnuarch import gnuarch_source
16 hg,
16 from bzr import bzr_source
17 util,
17 from p4 import p4_source
18 )
18 import filemap
19 from mercurial.i18n import _
19
20
20 import os, shutil, shlex
21 from . import (
21 from mercurial import hg, util, encoding, error
22 bzr,
22 from mercurial.i18n import _
23 common,
24 cvs,
25 darcs,
26 filemap,
27 git,
28 gnuarch,
29 hg as hgconvert,
30 monotone,
31 p4,
32 subversion,
33 )
34
35 mapfile = common.mapfile
36 MissingTool = common.MissingTool
37 NoRepo = common.NoRepo
38 SKIPREV = common.SKIPREV
39
40 bzr_source = bzr.bzr_source
41 convert_cvs = cvs.convert_cvs
42 convert_git = git.convert_git
43 darcs_source = darcs.darcs_source
44 gnuarch_source = gnuarch.gnuarch_source
45 mercurial_sink = hgconvert.mercurial_sink
46 mercurial_source = hgconvert.mercurial_source
47 monotone_source = monotone.monotone_source
48 p4_source = p4.p4_source
49 svn_sink = subversion.svn_sink
50 svn_source = subversion.svn_source
23
51
24 orig_encoding = 'ascii'
52 orig_encoding = 'ascii'
25
53
26 def recode(s):
54 def recode(s):
27 if isinstance(s, unicode):
55 if isinstance(s, unicode):
28 return s.encode(orig_encoding, 'replace')
56 return s.encode(orig_encoding, 'replace')
29 else:
57 else:
30 return s.decode('utf-8').encode(orig_encoding, 'replace')
58 return s.decode('utf-8').encode(orig_encoding, 'replace')
31
59
32 def mapbranch(branch, branchmap):
60 def mapbranch(branch, branchmap):
33 '''
61 '''
34 >>> bmap = {'default': 'branch1'}
62 >>> bmap = {'default': 'branch1'}
35 >>> for i in ['', None]:
63 >>> for i in ['', None]:
36 ... mapbranch(i, bmap)
64 ... mapbranch(i, bmap)
37 'branch1'
65 'branch1'
38 'branch1'
66 'branch1'
39 >>> bmap = {'None': 'branch2'}
67 >>> bmap = {'None': 'branch2'}
40 >>> for i in ['', None]:
68 >>> for i in ['', None]:
41 ... mapbranch(i, bmap)
69 ... mapbranch(i, bmap)
42 'branch2'
70 'branch2'
43 'branch2'
71 'branch2'
44 >>> bmap = {'None': 'branch3', 'default': 'branch4'}
72 >>> bmap = {'None': 'branch3', 'default': 'branch4'}
45 >>> for i in ['None', '', None, 'default', 'branch5']:
73 >>> for i in ['None', '', None, 'default', 'branch5']:
46 ... mapbranch(i, bmap)
74 ... mapbranch(i, bmap)
47 'branch3'
75 'branch3'
48 'branch4'
76 'branch4'
49 'branch4'
77 'branch4'
50 'branch4'
78 'branch4'
51 'branch5'
79 'branch5'
52 '''
80 '''
53 # If branch is None or empty, this commit is coming from the source
81 # If branch is None or empty, this commit is coming from the source
54 # repository's default branch and destined for the default branch in the
82 # repository's default branch and destined for the default branch in the
55 # destination repository. For such commits, using a literal "default"
83 # destination repository. For such commits, using a literal "default"
56 # in branchmap below allows the user to map "default" to an alternate
84 # in branchmap below allows the user to map "default" to an alternate
57 # default branch in the destination repository.
85 # default branch in the destination repository.
58 branch = branchmap.get(branch or 'default', branch)
86 branch = branchmap.get(branch or 'default', branch)
59 # At some point we used "None" literal to denote the default branch,
87 # At some point we used "None" literal to denote the default branch,
60 # attempt to use that for backward compatibility.
88 # attempt to use that for backward compatibility.
61 if (not branch):
89 if (not branch):
62 branch = branchmap.get(str(None), branch)
90 branch = branchmap.get(str(None), branch)
63 return branch
91 return branch
64
92
65 source_converters = [
93 source_converters = [
66 ('cvs', convert_cvs, 'branchsort'),
94 ('cvs', convert_cvs, 'branchsort'),
67 ('git', convert_git, 'branchsort'),
95 ('git', convert_git, 'branchsort'),
68 ('svn', svn_source, 'branchsort'),
96 ('svn', svn_source, 'branchsort'),
69 ('hg', mercurial_source, 'sourcesort'),
97 ('hg', mercurial_source, 'sourcesort'),
70 ('darcs', darcs_source, 'branchsort'),
98 ('darcs', darcs_source, 'branchsort'),
71 ('mtn', monotone_source, 'branchsort'),
99 ('mtn', monotone_source, 'branchsort'),
72 ('gnuarch', gnuarch_source, 'branchsort'),
100 ('gnuarch', gnuarch_source, 'branchsort'),
73 ('bzr', bzr_source, 'branchsort'),
101 ('bzr', bzr_source, 'branchsort'),
74 ('p4', p4_source, 'branchsort'),
102 ('p4', p4_source, 'branchsort'),
75 ]
103 ]
76
104
77 sink_converters = [
105 sink_converters = [
78 ('hg', mercurial_sink),
106 ('hg', mercurial_sink),
79 ('svn', svn_sink),
107 ('svn', svn_sink),
80 ]
108 ]
81
109
82 def convertsource(ui, path, type, revs):
110 def convertsource(ui, path, type, revs):
83 exceptions = []
111 exceptions = []
84 if type and type not in [s[0] for s in source_converters]:
112 if type and type not in [s[0] for s in source_converters]:
85 raise error.Abort(_('%s: invalid source repository type') % type)
113 raise error.Abort(_('%s: invalid source repository type') % type)
86 for name, source, sortmode in source_converters:
114 for name, source, sortmode in source_converters:
87 try:
115 try:
88 if not type or name == type:
116 if not type or name == type:
89 return source(ui, path, revs), sortmode
117 return source(ui, path, revs), sortmode
90 except (NoRepo, MissingTool) as inst:
118 except (NoRepo, MissingTool) as inst:
91 exceptions.append(inst)
119 exceptions.append(inst)
92 if not ui.quiet:
120 if not ui.quiet:
93 for inst in exceptions:
121 for inst in exceptions:
94 ui.write("%s\n" % inst)
122 ui.write("%s\n" % inst)
95 raise error.Abort(_('%s: missing or unsupported repository') % path)
123 raise error.Abort(_('%s: missing or unsupported repository') % path)
96
124
97 def convertsink(ui, path, type):
125 def convertsink(ui, path, type):
98 if type and type not in [s[0] for s in sink_converters]:
126 if type and type not in [s[0] for s in sink_converters]:
99 raise error.Abort(_('%s: invalid destination repository type') % type)
127 raise error.Abort(_('%s: invalid destination repository type') % type)
100 for name, sink in sink_converters:
128 for name, sink in sink_converters:
101 try:
129 try:
102 if not type or name == type:
130 if not type or name == type:
103 return sink(ui, path)
131 return sink(ui, path)
104 except NoRepo as inst:
132 except NoRepo as inst:
105 ui.note(_("convert: %s\n") % inst)
133 ui.note(_("convert: %s\n") % inst)
106 except MissingTool as inst:
134 except MissingTool as inst:
107 raise error.Abort('%s\n' % inst)
135 raise error.Abort('%s\n' % inst)
108 raise error.Abort(_('%s: unknown repository type') % path)
136 raise error.Abort(_('%s: unknown repository type') % path)
109
137
110 class progresssource(object):
138 class progresssource(object):
111 def __init__(self, ui, source, filecount):
139 def __init__(self, ui, source, filecount):
112 self.ui = ui
140 self.ui = ui
113 self.source = source
141 self.source = source
114 self.filecount = filecount
142 self.filecount = filecount
115 self.retrieved = 0
143 self.retrieved = 0
116
144
117 def getfile(self, file, rev):
145 def getfile(self, file, rev):
118 self.retrieved += 1
146 self.retrieved += 1
119 self.ui.progress(_('getting files'), self.retrieved,
147 self.ui.progress(_('getting files'), self.retrieved,
120 item=file, total=self.filecount)
148 item=file, total=self.filecount)
121 return self.source.getfile(file, rev)
149 return self.source.getfile(file, rev)
122
150
123 def targetfilebelongstosource(self, targetfilename):
151 def targetfilebelongstosource(self, targetfilename):
124 return self.source.targetfilebelongstosource(targetfilename)
152 return self.source.targetfilebelongstosource(targetfilename)
125
153
126 def lookuprev(self, rev):
154 def lookuprev(self, rev):
127 return self.source.lookuprev(rev)
155 return self.source.lookuprev(rev)
128
156
129 def close(self):
157 def close(self):
130 self.ui.progress(_('getting files'), None)
158 self.ui.progress(_('getting files'), None)
131
159
132 class converter(object):
160 class converter(object):
133 def __init__(self, ui, source, dest, revmapfile, opts):
161 def __init__(self, ui, source, dest, revmapfile, opts):
134
162
135 self.source = source
163 self.source = source
136 self.dest = dest
164 self.dest = dest
137 self.ui = ui
165 self.ui = ui
138 self.opts = opts
166 self.opts = opts
139 self.commitcache = {}
167 self.commitcache = {}
140 self.authors = {}
168 self.authors = {}
141 self.authorfile = None
169 self.authorfile = None
142
170
143 # Record converted revisions persistently: maps source revision
171 # Record converted revisions persistently: maps source revision
144 # ID to target revision ID (both strings). (This is how
172 # ID to target revision ID (both strings). (This is how
145 # incremental conversions work.)
173 # incremental conversions work.)
146 self.map = mapfile(ui, revmapfile)
174 self.map = mapfile(ui, revmapfile)
147
175
148 # Read first the dst author map if any
176 # Read first the dst author map if any
149 authorfile = self.dest.authorfile()
177 authorfile = self.dest.authorfile()
150 if authorfile and os.path.exists(authorfile):
178 if authorfile and os.path.exists(authorfile):
151 self.readauthormap(authorfile)
179 self.readauthormap(authorfile)
152 # Extend/Override with new author map if necessary
180 # Extend/Override with new author map if necessary
153 if opts.get('authormap'):
181 if opts.get('authormap'):
154 self.readauthormap(opts.get('authormap'))
182 self.readauthormap(opts.get('authormap'))
155 self.authorfile = self.dest.authorfile()
183 self.authorfile = self.dest.authorfile()
156
184
157 self.splicemap = self.parsesplicemap(opts.get('splicemap'))
185 self.splicemap = self.parsesplicemap(opts.get('splicemap'))
158 self.branchmap = mapfile(ui, opts.get('branchmap'))
186 self.branchmap = mapfile(ui, opts.get('branchmap'))
159
187
160 def parsesplicemap(self, path):
188 def parsesplicemap(self, path):
161 """ check and validate the splicemap format and
189 """ check and validate the splicemap format and
162 return a child/parents dictionary.
190 return a child/parents dictionary.
163 Format checking has two parts.
191 Format checking has two parts.
164 1. generic format which is same across all source types
192 1. generic format which is same across all source types
165 2. specific format checking which may be different for
193 2. specific format checking which may be different for
166 different source type. This logic is implemented in
194 different source type. This logic is implemented in
167 checkrevformat function in source files like
195 checkrevformat function in source files like
168 hg.py, subversion.py etc.
196 hg.py, subversion.py etc.
169 """
197 """
170
198
171 if not path:
199 if not path:
172 return {}
200 return {}
173 m = {}
201 m = {}
174 try:
202 try:
175 fp = open(path, 'r')
203 fp = open(path, 'r')
176 for i, line in enumerate(fp):
204 for i, line in enumerate(fp):
177 line = line.splitlines()[0].rstrip()
205 line = line.splitlines()[0].rstrip()
178 if not line:
206 if not line:
179 # Ignore blank lines
207 # Ignore blank lines
180 continue
208 continue
181 # split line
209 # split line
182 lex = shlex.shlex(line, posix=True)
210 lex = shlex.shlex(line, posix=True)
183 lex.whitespace_split = True
211 lex.whitespace_split = True
184 lex.whitespace += ','
212 lex.whitespace += ','
185 line = list(lex)
213 line = list(lex)
186 # check number of parents
214 # check number of parents
187 if not (2 <= len(line) <= 3):
215 if not (2 <= len(line) <= 3):
188 raise error.Abort(_('syntax error in %s(%d): child parent1'
216 raise error.Abort(_('syntax error in %s(%d): child parent1'
189 '[,parent2] expected') % (path, i + 1))
217 '[,parent2] expected') % (path, i + 1))
190 for part in line:
218 for part in line:
191 self.source.checkrevformat(part)
219 self.source.checkrevformat(part)
192 child, p1, p2 = line[0], line[1:2], line[2:]
220 child, p1, p2 = line[0], line[1:2], line[2:]
193 if p1 == p2:
221 if p1 == p2:
194 m[child] = p1
222 m[child] = p1
195 else:
223 else:
196 m[child] = p1 + p2
224 m[child] = p1 + p2
197 # if file does not exist or error reading, exit
225 # if file does not exist or error reading, exit
198 except IOError:
226 except IOError:
199 raise error.Abort(_('splicemap file not found or error reading %s:')
227 raise error.Abort(_('splicemap file not found or error reading %s:')
200 % path)
228 % path)
201 return m
229 return m
202
230
203
231
204 def walktree(self, heads):
232 def walktree(self, heads):
205 '''Return a mapping that identifies the uncommitted parents of every
233 '''Return a mapping that identifies the uncommitted parents of every
206 uncommitted changeset.'''
234 uncommitted changeset.'''
207 visit = heads
235 visit = heads
208 known = set()
236 known = set()
209 parents = {}
237 parents = {}
210 numcommits = self.source.numcommits()
238 numcommits = self.source.numcommits()
211 while visit:
239 while visit:
212 n = visit.pop(0)
240 n = visit.pop(0)
213 if n in known:
241 if n in known:
214 continue
242 continue
215 if n in self.map:
243 if n in self.map:
216 m = self.map[n]
244 m = self.map[n]
217 if m == SKIPREV or self.dest.hascommitfrommap(m):
245 if m == SKIPREV or self.dest.hascommitfrommap(m):
218 continue
246 continue
219 known.add(n)
247 known.add(n)
220 self.ui.progress(_('scanning'), len(known), unit=_('revisions'),
248 self.ui.progress(_('scanning'), len(known), unit=_('revisions'),
221 total=numcommits)
249 total=numcommits)
222 commit = self.cachecommit(n)
250 commit = self.cachecommit(n)
223 parents[n] = []
251 parents[n] = []
224 for p in commit.parents:
252 for p in commit.parents:
225 parents[n].append(p)
253 parents[n].append(p)
226 visit.append(p)
254 visit.append(p)
227 self.ui.progress(_('scanning'), None)
255 self.ui.progress(_('scanning'), None)
228
256
229 return parents
257 return parents
230
258
231 def mergesplicemap(self, parents, splicemap):
259 def mergesplicemap(self, parents, splicemap):
232 """A splicemap redefines child/parent relationships. Check the
260 """A splicemap redefines child/parent relationships. Check the
233 map contains valid revision identifiers and merge the new
261 map contains valid revision identifiers and merge the new
234 links in the source graph.
262 links in the source graph.
235 """
263 """
236 for c in sorted(splicemap):
264 for c in sorted(splicemap):
237 if c not in parents:
265 if c not in parents:
238 if not self.dest.hascommitforsplicemap(self.map.get(c, c)):
266 if not self.dest.hascommitforsplicemap(self.map.get(c, c)):
239 # Could be in source but not converted during this run
267 # Could be in source but not converted during this run
240 self.ui.warn(_('splice map revision %s is not being '
268 self.ui.warn(_('splice map revision %s is not being '
241 'converted, ignoring\n') % c)
269 'converted, ignoring\n') % c)
242 continue
270 continue
243 pc = []
271 pc = []
244 for p in splicemap[c]:
272 for p in splicemap[c]:
245 # We do not have to wait for nodes already in dest.
273 # We do not have to wait for nodes already in dest.
246 if self.dest.hascommitforsplicemap(self.map.get(p, p)):
274 if self.dest.hascommitforsplicemap(self.map.get(p, p)):
247 continue
275 continue
248 # Parent is not in dest and not being converted, not good
276 # Parent is not in dest and not being converted, not good
249 if p not in parents:
277 if p not in parents:
250 raise error.Abort(_('unknown splice map parent: %s') % p)
278 raise error.Abort(_('unknown splice map parent: %s') % p)
251 pc.append(p)
279 pc.append(p)
252 parents[c] = pc
280 parents[c] = pc
253
281
254 def toposort(self, parents, sortmode):
282 def toposort(self, parents, sortmode):
255 '''Return an ordering such that every uncommitted changeset is
283 '''Return an ordering such that every uncommitted changeset is
256 preceded by all its uncommitted ancestors.'''
284 preceded by all its uncommitted ancestors.'''
257
285
258 def mapchildren(parents):
286 def mapchildren(parents):
259 """Return a (children, roots) tuple where 'children' maps parent
287 """Return a (children, roots) tuple where 'children' maps parent
260 revision identifiers to children ones, and 'roots' is the list of
288 revision identifiers to children ones, and 'roots' is the list of
261 revisions without parents. 'parents' must be a mapping of revision
289 revisions without parents. 'parents' must be a mapping of revision
262 identifier to its parents ones.
290 identifier to its parents ones.
263 """
291 """
264 visit = sorted(parents)
292 visit = sorted(parents)
265 seen = set()
293 seen = set()
266 children = {}
294 children = {}
267 roots = []
295 roots = []
268
296
269 while visit:
297 while visit:
270 n = visit.pop(0)
298 n = visit.pop(0)
271 if n in seen:
299 if n in seen:
272 continue
300 continue
273 seen.add(n)
301 seen.add(n)
274 # Ensure that nodes without parents are present in the
302 # Ensure that nodes without parents are present in the
275 # 'children' mapping.
303 # 'children' mapping.
276 children.setdefault(n, [])
304 children.setdefault(n, [])
277 hasparent = False
305 hasparent = False
278 for p in parents[n]:
306 for p in parents[n]:
279 if p not in self.map:
307 if p not in self.map:
280 visit.append(p)
308 visit.append(p)
281 hasparent = True
309 hasparent = True
282 children.setdefault(p, []).append(n)
310 children.setdefault(p, []).append(n)
283 if not hasparent:
311 if not hasparent:
284 roots.append(n)
312 roots.append(n)
285
313
286 return children, roots
314 return children, roots
287
315
288 # Sort functions are supposed to take a list of revisions which
316 # Sort functions are supposed to take a list of revisions which
289 # can be converted immediately and pick one
317 # can be converted immediately and pick one
290
318
291 def makebranchsorter():
319 def makebranchsorter():
292 """If the previously converted revision has a child in the
320 """If the previously converted revision has a child in the
293 eligible revisions list, pick it. Return the list head
321 eligible revisions list, pick it. Return the list head
294 otherwise. Branch sort attempts to minimize branch
322 otherwise. Branch sort attempts to minimize branch
295 switching, which is harmful for Mercurial backend
323 switching, which is harmful for Mercurial backend
296 compression.
324 compression.
297 """
325 """
298 prev = [None]
326 prev = [None]
299 def picknext(nodes):
327 def picknext(nodes):
300 next = nodes[0]
328 next = nodes[0]
301 for n in nodes:
329 for n in nodes:
302 if prev[0] in parents[n]:
330 if prev[0] in parents[n]:
303 next = n
331 next = n
304 break
332 break
305 prev[0] = next
333 prev[0] = next
306 return next
334 return next
307 return picknext
335 return picknext
308
336
309 def makesourcesorter():
337 def makesourcesorter():
310 """Source specific sort."""
338 """Source specific sort."""
311 keyfn = lambda n: self.commitcache[n].sortkey
339 keyfn = lambda n: self.commitcache[n].sortkey
312 def picknext(nodes):
340 def picknext(nodes):
313 return sorted(nodes, key=keyfn)[0]
341 return sorted(nodes, key=keyfn)[0]
314 return picknext
342 return picknext
315
343
316 def makeclosesorter():
344 def makeclosesorter():
317 """Close order sort."""
345 """Close order sort."""
318 keyfn = lambda n: ('close' not in self.commitcache[n].extra,
346 keyfn = lambda n: ('close' not in self.commitcache[n].extra,
319 self.commitcache[n].sortkey)
347 self.commitcache[n].sortkey)
320 def picknext(nodes):
348 def picknext(nodes):
321 return sorted(nodes, key=keyfn)[0]
349 return sorted(nodes, key=keyfn)[0]
322 return picknext
350 return picknext
323
351
324 def makedatesorter():
352 def makedatesorter():
325 """Sort revisions by date."""
353 """Sort revisions by date."""
326 dates = {}
354 dates = {}
327 def getdate(n):
355 def getdate(n):
328 if n not in dates:
356 if n not in dates:
329 dates[n] = util.parsedate(self.commitcache[n].date)
357 dates[n] = util.parsedate(self.commitcache[n].date)
330 return dates[n]
358 return dates[n]
331
359
332 def picknext(nodes):
360 def picknext(nodes):
333 return min([(getdate(n), n) for n in nodes])[1]
361 return min([(getdate(n), n) for n in nodes])[1]
334
362
335 return picknext
363 return picknext
336
364
337 if sortmode == 'branchsort':
365 if sortmode == 'branchsort':
338 picknext = makebranchsorter()
366 picknext = makebranchsorter()
339 elif sortmode == 'datesort':
367 elif sortmode == 'datesort':
340 picknext = makedatesorter()
368 picknext = makedatesorter()
341 elif sortmode == 'sourcesort':
369 elif sortmode == 'sourcesort':
342 picknext = makesourcesorter()
370 picknext = makesourcesorter()
343 elif sortmode == 'closesort':
371 elif sortmode == 'closesort':
344 picknext = makeclosesorter()
372 picknext = makeclosesorter()
345 else:
373 else:
346 raise error.Abort(_('unknown sort mode: %s') % sortmode)
374 raise error.Abort(_('unknown sort mode: %s') % sortmode)
347
375
348 children, actives = mapchildren(parents)
376 children, actives = mapchildren(parents)
349
377
350 s = []
378 s = []
351 pendings = {}
379 pendings = {}
352 while actives:
380 while actives:
353 n = picknext(actives)
381 n = picknext(actives)
354 actives.remove(n)
382 actives.remove(n)
355 s.append(n)
383 s.append(n)
356
384
357 # Update dependents list
385 # Update dependents list
358 for c in children.get(n, []):
386 for c in children.get(n, []):
359 if c not in pendings:
387 if c not in pendings:
360 pendings[c] = [p for p in parents[c] if p not in self.map]
388 pendings[c] = [p for p in parents[c] if p not in self.map]
361 try:
389 try:
362 pendings[c].remove(n)
390 pendings[c].remove(n)
363 except ValueError:
391 except ValueError:
364 raise error.Abort(_('cycle detected between %s and %s')
392 raise error.Abort(_('cycle detected between %s and %s')
365 % (recode(c), recode(n)))
393 % (recode(c), recode(n)))
366 if not pendings[c]:
394 if not pendings[c]:
367 # Parents are converted, node is eligible
395 # Parents are converted, node is eligible
368 actives.insert(0, c)
396 actives.insert(0, c)
369 pendings[c] = None
397 pendings[c] = None
370
398
371 if len(s) != len(parents):
399 if len(s) != len(parents):
372 raise error.Abort(_("not all revisions were sorted"))
400 raise error.Abort(_("not all revisions were sorted"))
373
401
374 return s
402 return s
375
403
376 def writeauthormap(self):
404 def writeauthormap(self):
377 authorfile = self.authorfile
405 authorfile = self.authorfile
378 if authorfile:
406 if authorfile:
379 self.ui.status(_('writing author map file %s\n') % authorfile)
407 self.ui.status(_('writing author map file %s\n') % authorfile)
380 ofile = open(authorfile, 'w+')
408 ofile = open(authorfile, 'w+')
381 for author in self.authors:
409 for author in self.authors:
382 ofile.write("%s=%s\n" % (author, self.authors[author]))
410 ofile.write("%s=%s\n" % (author, self.authors[author]))
383 ofile.close()
411 ofile.close()
384
412
385 def readauthormap(self, authorfile):
413 def readauthormap(self, authorfile):
386 afile = open(authorfile, 'r')
414 afile = open(authorfile, 'r')
387 for line in afile:
415 for line in afile:
388
416
389 line = line.strip()
417 line = line.strip()
390 if not line or line.startswith('#'):
418 if not line or line.startswith('#'):
391 continue
419 continue
392
420
393 try:
421 try:
394 srcauthor, dstauthor = line.split('=', 1)
422 srcauthor, dstauthor = line.split('=', 1)
395 except ValueError:
423 except ValueError:
396 msg = _('ignoring bad line in author map file %s: %s\n')
424 msg = _('ignoring bad line in author map file %s: %s\n')
397 self.ui.warn(msg % (authorfile, line.rstrip()))
425 self.ui.warn(msg % (authorfile, line.rstrip()))
398 continue
426 continue
399
427
400 srcauthor = srcauthor.strip()
428 srcauthor = srcauthor.strip()
401 dstauthor = dstauthor.strip()
429 dstauthor = dstauthor.strip()
402 if self.authors.get(srcauthor) in (None, dstauthor):
430 if self.authors.get(srcauthor) in (None, dstauthor):
403 msg = _('mapping author %s to %s\n')
431 msg = _('mapping author %s to %s\n')
404 self.ui.debug(msg % (srcauthor, dstauthor))
432 self.ui.debug(msg % (srcauthor, dstauthor))
405 self.authors[srcauthor] = dstauthor
433 self.authors[srcauthor] = dstauthor
406 continue
434 continue
407
435
408 m = _('overriding mapping for author %s, was %s, will be %s\n')
436 m = _('overriding mapping for author %s, was %s, will be %s\n')
409 self.ui.status(m % (srcauthor, self.authors[srcauthor], dstauthor))
437 self.ui.status(m % (srcauthor, self.authors[srcauthor], dstauthor))
410
438
411 afile.close()
439 afile.close()
412
440
413 def cachecommit(self, rev):
441 def cachecommit(self, rev):
414 commit = self.source.getcommit(rev)
442 commit = self.source.getcommit(rev)
415 commit.author = self.authors.get(commit.author, commit.author)
443 commit.author = self.authors.get(commit.author, commit.author)
416 commit.branch = mapbranch(commit.branch, self.branchmap)
444 commit.branch = mapbranch(commit.branch, self.branchmap)
417 self.commitcache[rev] = commit
445 self.commitcache[rev] = commit
418 return commit
446 return commit
419
447
420 def copy(self, rev):
448 def copy(self, rev):
421 commit = self.commitcache[rev]
449 commit = self.commitcache[rev]
422 full = self.opts.get('full')
450 full = self.opts.get('full')
423 changes = self.source.getchanges(rev, full)
451 changes = self.source.getchanges(rev, full)
424 if isinstance(changes, basestring):
452 if isinstance(changes, basestring):
425 if changes == SKIPREV:
453 if changes == SKIPREV:
426 dest = SKIPREV
454 dest = SKIPREV
427 else:
455 else:
428 dest = self.map[changes]
456 dest = self.map[changes]
429 self.map[rev] = dest
457 self.map[rev] = dest
430 return
458 return
431 files, copies, cleanp2 = changes
459 files, copies, cleanp2 = changes
432 pbranches = []
460 pbranches = []
433 if commit.parents:
461 if commit.parents:
434 for prev in commit.parents:
462 for prev in commit.parents:
435 if prev not in self.commitcache:
463 if prev not in self.commitcache:
436 self.cachecommit(prev)
464 self.cachecommit(prev)
437 pbranches.append((self.map[prev],
465 pbranches.append((self.map[prev],
438 self.commitcache[prev].branch))
466 self.commitcache[prev].branch))
439 self.dest.setbranch(commit.branch, pbranches)
467 self.dest.setbranch(commit.branch, pbranches)
440 try:
468 try:
441 parents = self.splicemap[rev]
469 parents = self.splicemap[rev]
442 self.ui.status(_('spliced in %s as parents of %s\n') %
470 self.ui.status(_('spliced in %s as parents of %s\n') %
443 (_(' and ').join(parents), rev))
471 (_(' and ').join(parents), rev))
444 parents = [self.map.get(p, p) for p in parents]
472 parents = [self.map.get(p, p) for p in parents]
445 except KeyError:
473 except KeyError:
446 parents = [b[0] for b in pbranches]
474 parents = [b[0] for b in pbranches]
447 if len(pbranches) != 2:
475 if len(pbranches) != 2:
448 cleanp2 = set()
476 cleanp2 = set()
449 if len(parents) < 3:
477 if len(parents) < 3:
450 source = progresssource(self.ui, self.source, len(files))
478 source = progresssource(self.ui, self.source, len(files))
451 else:
479 else:
452 # For an octopus merge, we end up traversing the list of
480 # For an octopus merge, we end up traversing the list of
453 # changed files N-1 times. This tweak to the number of
481 # changed files N-1 times. This tweak to the number of
454 # files makes it so the progress bar doesn't overflow
482 # files makes it so the progress bar doesn't overflow
455 # itself.
483 # itself.
456 source = progresssource(self.ui, self.source,
484 source = progresssource(self.ui, self.source,
457 len(files) * (len(parents) - 1))
485 len(files) * (len(parents) - 1))
458 newnode = self.dest.putcommit(files, copies, parents, commit,
486 newnode = self.dest.putcommit(files, copies, parents, commit,
459 source, self.map, full, cleanp2)
487 source, self.map, full, cleanp2)
460 source.close()
488 source.close()
461 self.source.converted(rev, newnode)
489 self.source.converted(rev, newnode)
462 self.map[rev] = newnode
490 self.map[rev] = newnode
463
491
464 def convert(self, sortmode):
492 def convert(self, sortmode):
465 try:
493 try:
466 self.source.before()
494 self.source.before()
467 self.dest.before()
495 self.dest.before()
468 self.source.setrevmap(self.map)
496 self.source.setrevmap(self.map)
469 self.ui.status(_("scanning source...\n"))
497 self.ui.status(_("scanning source...\n"))
470 heads = self.source.getheads()
498 heads = self.source.getheads()
471 parents = self.walktree(heads)
499 parents = self.walktree(heads)
472 self.mergesplicemap(parents, self.splicemap)
500 self.mergesplicemap(parents, self.splicemap)
473 self.ui.status(_("sorting...\n"))
501 self.ui.status(_("sorting...\n"))
474 t = self.toposort(parents, sortmode)
502 t = self.toposort(parents, sortmode)
475 num = len(t)
503 num = len(t)
476 c = None
504 c = None
477
505
478 self.ui.status(_("converting...\n"))
506 self.ui.status(_("converting...\n"))
479 for i, c in enumerate(t):
507 for i, c in enumerate(t):
480 num -= 1
508 num -= 1
481 desc = self.commitcache[c].desc
509 desc = self.commitcache[c].desc
482 if "\n" in desc:
510 if "\n" in desc:
483 desc = desc.splitlines()[0]
511 desc = desc.splitlines()[0]
484 # convert log message to local encoding without using
512 # convert log message to local encoding without using
485 # tolocal() because the encoding.encoding convert()
513 # tolocal() because the encoding.encoding convert()
486 # uses is 'utf-8'
514 # uses is 'utf-8'
487 self.ui.status("%d %s\n" % (num, recode(desc)))
515 self.ui.status("%d %s\n" % (num, recode(desc)))
488 self.ui.note(_("source: %s\n") % recode(c))
516 self.ui.note(_("source: %s\n") % recode(c))
489 self.ui.progress(_('converting'), i, unit=_('revisions'),
517 self.ui.progress(_('converting'), i, unit=_('revisions'),
490 total=len(t))
518 total=len(t))
491 self.copy(c)
519 self.copy(c)
492 self.ui.progress(_('converting'), None)
520 self.ui.progress(_('converting'), None)
493
521
494 if not self.ui.configbool('convert', 'skiptags'):
522 if not self.ui.configbool('convert', 'skiptags'):
495 tags = self.source.gettags()
523 tags = self.source.gettags()
496 ctags = {}
524 ctags = {}
497 for k in tags:
525 for k in tags:
498 v = tags[k]
526 v = tags[k]
499 if self.map.get(v, SKIPREV) != SKIPREV:
527 if self.map.get(v, SKIPREV) != SKIPREV:
500 ctags[k] = self.map[v]
528 ctags[k] = self.map[v]
501
529
502 if c and ctags:
530 if c and ctags:
503 nrev, tagsparent = self.dest.puttags(ctags)
531 nrev, tagsparent = self.dest.puttags(ctags)
504 if nrev and tagsparent:
532 if nrev and tagsparent:
505 # write another hash correspondence to override the
533 # write another hash correspondence to override the
506 # previous one so we don't end up with extra tag heads
534 # previous one so we don't end up with extra tag heads
507 tagsparents = [e for e in self.map.iteritems()
535 tagsparents = [e for e in self.map.iteritems()
508 if e[1] == tagsparent]
536 if e[1] == tagsparent]
509 if tagsparents:
537 if tagsparents:
510 self.map[tagsparents[0][0]] = nrev
538 self.map[tagsparents[0][0]] = nrev
511
539
512 bookmarks = self.source.getbookmarks()
540 bookmarks = self.source.getbookmarks()
513 cbookmarks = {}
541 cbookmarks = {}
514 for k in bookmarks:
542 for k in bookmarks:
515 v = bookmarks[k]
543 v = bookmarks[k]
516 if self.map.get(v, SKIPREV) != SKIPREV:
544 if self.map.get(v, SKIPREV) != SKIPREV:
517 cbookmarks[k] = self.map[v]
545 cbookmarks[k] = self.map[v]
518
546
519 if c and cbookmarks:
547 if c and cbookmarks:
520 self.dest.putbookmarks(cbookmarks)
548 self.dest.putbookmarks(cbookmarks)
521
549
522 self.writeauthormap()
550 self.writeauthormap()
523 finally:
551 finally:
524 self.cleanup()
552 self.cleanup()
525
553
526 def cleanup(self):
554 def cleanup(self):
527 try:
555 try:
528 self.dest.after()
556 self.dest.after()
529 finally:
557 finally:
530 self.source.after()
558 self.source.after()
531 self.map.close()
559 self.map.close()
532
560
533 def convert(ui, src, dest=None, revmapfile=None, **opts):
561 def convert(ui, src, dest=None, revmapfile=None, **opts):
534 global orig_encoding
562 global orig_encoding
535 orig_encoding = encoding.encoding
563 orig_encoding = encoding.encoding
536 encoding.encoding = 'UTF-8'
564 encoding.encoding = 'UTF-8'
537
565
538 # support --authors as an alias for --authormap
566 # support --authors as an alias for --authormap
539 if not opts.get('authormap'):
567 if not opts.get('authormap'):
540 opts['authormap'] = opts.get('authors')
568 opts['authormap'] = opts.get('authors')
541
569
542 if not dest:
570 if not dest:
543 dest = hg.defaultdest(src) + "-hg"
571 dest = hg.defaultdest(src) + "-hg"
544 ui.status(_("assuming destination %s\n") % dest)
572 ui.status(_("assuming destination %s\n") % dest)
545
573
546 destc = convertsink(ui, dest, opts.get('dest_type'))
574 destc = convertsink(ui, dest, opts.get('dest_type'))
547
575
548 try:
576 try:
549 srcc, defaultsort = convertsource(ui, src, opts.get('source_type'),
577 srcc, defaultsort = convertsource(ui, src, opts.get('source_type'),
550 opts.get('rev'))
578 opts.get('rev'))
551 except Exception:
579 except Exception:
552 for path in destc.created:
580 for path in destc.created:
553 shutil.rmtree(path, True)
581 shutil.rmtree(path, True)
554 raise
582 raise
555
583
556 sortmodes = ('branchsort', 'datesort', 'sourcesort', 'closesort')
584 sortmodes = ('branchsort', 'datesort', 'sourcesort', 'closesort')
557 sortmode = [m for m in sortmodes if opts.get(m)]
585 sortmode = [m for m in sortmodes if opts.get(m)]
558 if len(sortmode) > 1:
586 if len(sortmode) > 1:
559 raise error.Abort(_('more than one sort mode specified'))
587 raise error.Abort(_('more than one sort mode specified'))
560 if sortmode:
588 if sortmode:
561 sortmode = sortmode[0]
589 sortmode = sortmode[0]
562 else:
590 else:
563 sortmode = defaultsort
591 sortmode = defaultsort
564
592
565 if sortmode == 'sourcesort' and not srcc.hasnativeorder():
593 if sortmode == 'sourcesort' and not srcc.hasnativeorder():
566 raise error.Abort(_('--sourcesort is not supported by this data source')
594 raise error.Abort(_('--sourcesort is not supported by this data source')
567 )
595 )
568 if sortmode == 'closesort' and not srcc.hasnativeclose():
596 if sortmode == 'closesort' and not srcc.hasnativeclose():
569 raise error.Abort(_('--closesort is not supported by this data source'))
597 raise error.Abort(_('--closesort is not supported by this data source'))
570
598
571 fmap = opts.get('filemap')
599 fmap = opts.get('filemap')
572 if fmap:
600 if fmap:
573 srcc = filemap.filemap_source(ui, srcc, fmap)
601 srcc = filemap.filemap_source(ui, srcc, fmap)
574 destc.setfilemapmode(True)
602 destc.setfilemapmode(True)
575
603
576 if not revmapfile:
604 if not revmapfile:
577 revmapfile = destc.revmapfile()
605 revmapfile = destc.revmapfile()
578
606
579 c = converter(ui, srcc, destc, revmapfile, opts)
607 c = converter(ui, srcc, destc, revmapfile, opts)
580 c.convert(sortmode)
608 c.convert(sortmode)
@@ -1,138 +1,137 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ cd "$TESTDIR"/..
3 $ cd "$TESTDIR"/..
4
4
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 contrib/check-code.py not using absolute_import
6 contrib/check-code.py not using absolute_import
7 contrib/check-code.py requires print_function
7 contrib/check-code.py requires print_function
8 contrib/debugshell.py not using absolute_import
8 contrib/debugshell.py not using absolute_import
9 contrib/import-checker.py not using absolute_import
9 contrib/import-checker.py not using absolute_import
10 contrib/import-checker.py requires print_function
10 contrib/import-checker.py requires print_function
11 contrib/memory.py not using absolute_import
11 contrib/memory.py not using absolute_import
12 contrib/perf.py not using absolute_import
12 contrib/perf.py not using absolute_import
13 contrib/python-hook-examples.py not using absolute_import
13 contrib/python-hook-examples.py not using absolute_import
14 contrib/revsetbenchmarks.py not using absolute_import
14 contrib/revsetbenchmarks.py not using absolute_import
15 contrib/revsetbenchmarks.py requires print_function
15 contrib/revsetbenchmarks.py requires print_function
16 contrib/showstack.py not using absolute_import
16 contrib/showstack.py not using absolute_import
17 contrib/synthrepo.py not using absolute_import
17 contrib/synthrepo.py not using absolute_import
18 contrib/win32/hgwebdir_wsgi.py not using absolute_import
18 contrib/win32/hgwebdir_wsgi.py not using absolute_import
19 doc/check-seclevel.py not using absolute_import
19 doc/check-seclevel.py not using absolute_import
20 doc/gendoc.py not using absolute_import
20 doc/gendoc.py not using absolute_import
21 doc/hgmanpage.py not using absolute_import
21 doc/hgmanpage.py not using absolute_import
22 hgext/__init__.py not using absolute_import
22 hgext/__init__.py not using absolute_import
23 hgext/color.py not using absolute_import
23 hgext/color.py not using absolute_import
24 hgext/convert/__init__.py not using absolute_import
24 hgext/convert/__init__.py not using absolute_import
25 hgext/convert/bzr.py not using absolute_import
25 hgext/convert/bzr.py not using absolute_import
26 hgext/convert/common.py not using absolute_import
26 hgext/convert/common.py not using absolute_import
27 hgext/convert/convcmd.py not using absolute_import
28 hgext/convert/cvs.py not using absolute_import
27 hgext/convert/cvs.py not using absolute_import
29 hgext/convert/transport.py not using absolute_import
28 hgext/convert/transport.py not using absolute_import
30 hgext/eol.py not using absolute_import
29 hgext/eol.py not using absolute_import
31 hgext/extdiff.py not using absolute_import
30 hgext/extdiff.py not using absolute_import
32 hgext/factotum.py not using absolute_import
31 hgext/factotum.py not using absolute_import
33 hgext/fetch.py not using absolute_import
32 hgext/fetch.py not using absolute_import
34 hgext/gpg.py not using absolute_import
33 hgext/gpg.py not using absolute_import
35 hgext/graphlog.py not using absolute_import
34 hgext/graphlog.py not using absolute_import
36 hgext/hgcia.py not using absolute_import
35 hgext/hgcia.py not using absolute_import
37 hgext/hgk.py not using absolute_import
36 hgext/hgk.py not using absolute_import
38 hgext/highlight/__init__.py not using absolute_import
37 hgext/highlight/__init__.py not using absolute_import
39 hgext/highlight/highlight.py not using absolute_import
38 hgext/highlight/highlight.py not using absolute_import
40 hgext/histedit.py not using absolute_import
39 hgext/histedit.py not using absolute_import
41 hgext/largefiles/__init__.py not using absolute_import
40 hgext/largefiles/__init__.py not using absolute_import
42 hgext/largefiles/basestore.py not using absolute_import
41 hgext/largefiles/basestore.py not using absolute_import
43 hgext/largefiles/lfcommands.py not using absolute_import
42 hgext/largefiles/lfcommands.py not using absolute_import
44 hgext/largefiles/lfutil.py not using absolute_import
43 hgext/largefiles/lfutil.py not using absolute_import
45 hgext/largefiles/localstore.py not using absolute_import
44 hgext/largefiles/localstore.py not using absolute_import
46 hgext/largefiles/overrides.py not using absolute_import
45 hgext/largefiles/overrides.py not using absolute_import
47 hgext/largefiles/proto.py not using absolute_import
46 hgext/largefiles/proto.py not using absolute_import
48 hgext/largefiles/remotestore.py not using absolute_import
47 hgext/largefiles/remotestore.py not using absolute_import
49 hgext/largefiles/reposetup.py not using absolute_import
48 hgext/largefiles/reposetup.py not using absolute_import
50 hgext/largefiles/uisetup.py not using absolute_import
49 hgext/largefiles/uisetup.py not using absolute_import
51 hgext/largefiles/wirestore.py not using absolute_import
50 hgext/largefiles/wirestore.py not using absolute_import
52 hgext/mq.py not using absolute_import
51 hgext/mq.py not using absolute_import
53 hgext/notify.py not using absolute_import
52 hgext/notify.py not using absolute_import
54 hgext/patchbomb.py not using absolute_import
53 hgext/patchbomb.py not using absolute_import
55 hgext/rebase.py not using absolute_import
54 hgext/rebase.py not using absolute_import
56 hgext/share.py not using absolute_import
55 hgext/share.py not using absolute_import
57 hgext/transplant.py not using absolute_import
56 hgext/transplant.py not using absolute_import
58 hgext/win32mbcs.py not using absolute_import
57 hgext/win32mbcs.py not using absolute_import
59 hgext/win32text.py not using absolute_import
58 hgext/win32text.py not using absolute_import
60 i18n/check-translation.py not using absolute_import
59 i18n/check-translation.py not using absolute_import
61 i18n/polib.py not using absolute_import
60 i18n/polib.py not using absolute_import
62 setup.py not using absolute_import
61 setup.py not using absolute_import
63 tests/filterpyflakes.py requires print_function
62 tests/filterpyflakes.py requires print_function
64 tests/generate-working-copy-states.py requires print_function
63 tests/generate-working-copy-states.py requires print_function
65 tests/get-with-headers.py requires print_function
64 tests/get-with-headers.py requires print_function
66 tests/heredoctest.py requires print_function
65 tests/heredoctest.py requires print_function
67 tests/hypothesishelpers.py not using absolute_import
66 tests/hypothesishelpers.py not using absolute_import
68 tests/hypothesishelpers.py requires print_function
67 tests/hypothesishelpers.py requires print_function
69 tests/killdaemons.py not using absolute_import
68 tests/killdaemons.py not using absolute_import
70 tests/md5sum.py not using absolute_import
69 tests/md5sum.py not using absolute_import
71 tests/mockblackbox.py not using absolute_import
70 tests/mockblackbox.py not using absolute_import
72 tests/printenv.py not using absolute_import
71 tests/printenv.py not using absolute_import
73 tests/readlink.py not using absolute_import
72 tests/readlink.py not using absolute_import
74 tests/readlink.py requires print_function
73 tests/readlink.py requires print_function
75 tests/revlog-formatv0.py not using absolute_import
74 tests/revlog-formatv0.py not using absolute_import
76 tests/run-tests.py not using absolute_import
75 tests/run-tests.py not using absolute_import
77 tests/seq.py not using absolute_import
76 tests/seq.py not using absolute_import
78 tests/seq.py requires print_function
77 tests/seq.py requires print_function
79 tests/silenttestrunner.py not using absolute_import
78 tests/silenttestrunner.py not using absolute_import
80 tests/silenttestrunner.py requires print_function
79 tests/silenttestrunner.py requires print_function
81 tests/sitecustomize.py not using absolute_import
80 tests/sitecustomize.py not using absolute_import
82 tests/svn-safe-append.py not using absolute_import
81 tests/svn-safe-append.py not using absolute_import
83 tests/svnxml.py not using absolute_import
82 tests/svnxml.py not using absolute_import
84 tests/test-ancestor.py requires print_function
83 tests/test-ancestor.py requires print_function
85 tests/test-atomictempfile.py not using absolute_import
84 tests/test-atomictempfile.py not using absolute_import
86 tests/test-batching.py not using absolute_import
85 tests/test-batching.py not using absolute_import
87 tests/test-batching.py requires print_function
86 tests/test-batching.py requires print_function
88 tests/test-bdiff.py not using absolute_import
87 tests/test-bdiff.py not using absolute_import
89 tests/test-bdiff.py requires print_function
88 tests/test-bdiff.py requires print_function
90 tests/test-context.py not using absolute_import
89 tests/test-context.py not using absolute_import
91 tests/test-context.py requires print_function
90 tests/test-context.py requires print_function
92 tests/test-demandimport.py not using absolute_import
91 tests/test-demandimport.py not using absolute_import
93 tests/test-demandimport.py requires print_function
92 tests/test-demandimport.py requires print_function
94 tests/test-doctest.py not using absolute_import
93 tests/test-doctest.py not using absolute_import
95 tests/test-duplicateoptions.py not using absolute_import
94 tests/test-duplicateoptions.py not using absolute_import
96 tests/test-duplicateoptions.py requires print_function
95 tests/test-duplicateoptions.py requires print_function
97 tests/test-filecache.py not using absolute_import
96 tests/test-filecache.py not using absolute_import
98 tests/test-filecache.py requires print_function
97 tests/test-filecache.py requires print_function
99 tests/test-filelog.py not using absolute_import
98 tests/test-filelog.py not using absolute_import
100 tests/test-filelog.py requires print_function
99 tests/test-filelog.py requires print_function
101 tests/test-hg-parseurl.py not using absolute_import
100 tests/test-hg-parseurl.py not using absolute_import
102 tests/test-hg-parseurl.py requires print_function
101 tests/test-hg-parseurl.py requires print_function
103 tests/test-hgweb-auth.py not using absolute_import
102 tests/test-hgweb-auth.py not using absolute_import
104 tests/test-hgweb-auth.py requires print_function
103 tests/test-hgweb-auth.py requires print_function
105 tests/test-hgwebdir-paths.py not using absolute_import
104 tests/test-hgwebdir-paths.py not using absolute_import
106 tests/test-hybridencode.py not using absolute_import
105 tests/test-hybridencode.py not using absolute_import
107 tests/test-hybridencode.py requires print_function
106 tests/test-hybridencode.py requires print_function
108 tests/test-lrucachedict.py not using absolute_import
107 tests/test-lrucachedict.py not using absolute_import
109 tests/test-lrucachedict.py requires print_function
108 tests/test-lrucachedict.py requires print_function
110 tests/test-manifest.py not using absolute_import
109 tests/test-manifest.py not using absolute_import
111 tests/test-minirst.py not using absolute_import
110 tests/test-minirst.py not using absolute_import
112 tests/test-minirst.py requires print_function
111 tests/test-minirst.py requires print_function
113 tests/test-parseindex2.py not using absolute_import
112 tests/test-parseindex2.py not using absolute_import
114 tests/test-parseindex2.py requires print_function
113 tests/test-parseindex2.py requires print_function
115 tests/test-pathencode.py not using absolute_import
114 tests/test-pathencode.py not using absolute_import
116 tests/test-pathencode.py requires print_function
115 tests/test-pathencode.py requires print_function
117 tests/test-propertycache.py not using absolute_import
116 tests/test-propertycache.py not using absolute_import
118 tests/test-propertycache.py requires print_function
117 tests/test-propertycache.py requires print_function
119 tests/test-revlog-ancestry.py not using absolute_import
118 tests/test-revlog-ancestry.py not using absolute_import
120 tests/test-revlog-ancestry.py requires print_function
119 tests/test-revlog-ancestry.py requires print_function
121 tests/test-run-tests.py not using absolute_import
120 tests/test-run-tests.py not using absolute_import
122 tests/test-simplemerge.py not using absolute_import
121 tests/test-simplemerge.py not using absolute_import
123 tests/test-status-inprocess.py not using absolute_import
122 tests/test-status-inprocess.py not using absolute_import
124 tests/test-status-inprocess.py requires print_function
123 tests/test-status-inprocess.py requires print_function
125 tests/test-symlink-os-yes-fs-no.py not using absolute_import
124 tests/test-symlink-os-yes-fs-no.py not using absolute_import
126 tests/test-trusted.py not using absolute_import
125 tests/test-trusted.py not using absolute_import
127 tests/test-trusted.py requires print_function
126 tests/test-trusted.py requires print_function
128 tests/test-ui-color.py not using absolute_import
127 tests/test-ui-color.py not using absolute_import
129 tests/test-ui-color.py requires print_function
128 tests/test-ui-color.py requires print_function
130 tests/test-ui-config.py not using absolute_import
129 tests/test-ui-config.py not using absolute_import
131 tests/test-ui-config.py requires print_function
130 tests/test-ui-config.py requires print_function
132 tests/test-ui-verbosity.py not using absolute_import
131 tests/test-ui-verbosity.py not using absolute_import
133 tests/test-ui-verbosity.py requires print_function
132 tests/test-ui-verbosity.py requires print_function
134 tests/test-url.py not using absolute_import
133 tests/test-url.py not using absolute_import
135 tests/test-url.py requires print_function
134 tests/test-url.py requires print_function
136 tests/test-walkrepo.py requires print_function
135 tests/test-walkrepo.py requires print_function
137 tests/test-wireproto.py requires print_function
136 tests/test-wireproto.py requires print_function
138 tests/tinyproxy.py requires print_function
137 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now