##// END OF EJS Templates
drawdag: port to python 3
Augie Fackler -
r34204:5a1b4126 default
parent child Browse files
Show More
@@ -92,6 +92,7 b' from mercurial import ('
92 error,
92 error,
93 node,
93 node,
94 obsolete,
94 obsolete,
95 pycompat,
95 registrar,
96 registrar,
96 scmutil,
97 scmutil,
97 tags as tagsmod,
98 tags as tagsmod,
@@ -100,9 +101,9 b' from mercurial import ('
100 cmdtable = {}
101 cmdtable = {}
101 command = registrar.command(cmdtable)
102 command = registrar.command(cmdtable)
102
103
103 _pipechars = '\\/+-|'
104 _pipechars = b'\\/+-|'
104 _nonpipechars = ''.join(chr(i) for i in xrange(33, 127)
105 _nonpipechars = b''.join(pycompat.bytechr(i) for i in range(33, 127)
105 if chr(i) not in _pipechars)
106 if pycompat.bytechr(i) not in _pipechars)
106
107
107 def _isname(ch):
108 def _isname(ch):
108 """char -> bool. return True if ch looks like part of a name, False
109 """char -> bool. return True if ch looks like part of a name, False
@@ -113,7 +114,7 b' def _parseasciigraph(text):'
113 r"""str -> {str : [str]}. convert the ASCII graph to edges
114 r"""str -> {str : [str]}. convert the ASCII graph to edges
114
115
115 >>> import pprint
116 >>> import pprint
116 >>> pprint.pprint({k: [vv for vv in v]
117 >>> pprint.pprint({pycompat.sysstr(k): [pycompat.sysstr(vv) for vv in v]
117 ... for k, v in _parseasciigraph(br'''
118 ... for k, v in _parseasciigraph(br'''
118 ... G
119 ... G
119 ... |
120 ... |
@@ -132,7 +133,7 b' def _parseasciigraph(text):'
132 'G': ['F'],
133 'G': ['F'],
133 'H': ['A'],
134 'H': ['A'],
134 'I': ['H']}
135 'I': ['H']}
135 >>> pprint.pprint({k: [vv for vv in v]
136 >>> pprint.pprint({pycompat.sysstr(k): [pycompat.sysstr(vv) for vv in v]
136 ... for k, v in _parseasciigraph(br'''
137 ... for k, v in _parseasciigraph(br'''
137 ... o foo
138 ... o foo
138 ... |\
139 ... |\
@@ -163,16 +164,16 b' def _parseasciigraph(text):'
163 """(int, int) -> char. give a coordinate, return the char. return a
164 """(int, int) -> char. give a coordinate, return the char. return a
164 space for anything out of range"""
165 space for anything out of range"""
165 if x < 0 or y < 0:
166 if x < 0 or y < 0:
166 return ' '
167 return b' '
167 try:
168 try:
168 return lines[y][x]
169 return lines[y][x:x + 1] or b' '
169 except IndexError:
170 except IndexError:
170 return ' '
171 return b' '
171
172
172 def getname(y, x):
173 def getname(y, x):
173 """(int, int) -> str. like get(y, x) but concatenate left and right
174 """(int, int) -> str. like get(y, x) but concatenate left and right
174 parts. if name is an 'o', try to replace it to the right"""
175 parts. if name is an 'o', try to replace it to the right"""
175 result = ''
176 result = b''
176 for i in itertools.count(0):
177 for i in itertools.count(0):
177 ch = get(y, x - i)
178 ch = get(y, x - i)
178 if not _isname(ch):
179 if not _isname(ch):
@@ -183,17 +184,17 b' def _parseasciigraph(text):'
183 if not _isname(ch):
184 if not _isname(ch):
184 break
185 break
185 result += ch
186 result += ch
186 if result == 'o':
187 if result == b'o':
187 # special handling, find the name to the right
188 # special handling, find the name to the right
188 result = ''
189 result = b''
189 for i in itertools.count(2):
190 for i in itertools.count(2):
190 ch = get(y, x + i)
191 ch = get(y, x + i)
191 if ch == ' ' or ch in _pipechars:
192 if ch == b' ' or ch in _pipechars:
192 if result or x + i >= len(lines[y]):
193 if result or x + i >= len(lines[y]):
193 break
194 break
194 else:
195 else:
195 result += ch
196 result += ch
196 return result or 'o'
197 return result or b'o'
197 return result
198 return result
198
199
199 def parents(y, x):
200 def parents(y, x):
@@ -209,19 +210,19 b' def _parseasciigraph(text):'
209 if '-' (or '+') is not in excepted, and get(y, x) is '-' (or '+'),
210 if '-' (or '+') is not in excepted, and get(y, x) is '-' (or '+'),
210 the next line (y + 1, x) will be checked instead."""
211 the next line (y + 1, x) will be checked instead."""
211 ch = get(y, x)
212 ch = get(y, x)
212 if any(ch == c and c not in expected for c in '-+'):
213 if any(ch == c and c not in expected for c in (b'-', b'+')):
213 y += 1
214 y += 1
214 return follow(y + 1, x, expected)
215 return follow(y + 1, x, expected)
215 if ch in expected or ('o' in expected and _isname(ch)):
216 if ch in expected or (b'o' in expected and _isname(ch)):
216 visit.append((y, x))
217 visit.append((y, x))
217
218
218 # -o- # starting point:
219 # -o- # starting point:
219 # /|\ # follow '-' (horizontally), and '/|\' (to the bottom)
220 # /|\ # follow '-' (horizontally), and '/|\' (to the bottom)
220 follow(y + 1, x, '|')
221 follow(y + 1, x, b'|')
221 follow(y + 1, x - 1, '/')
222 follow(y + 1, x - 1, b'/')
222 follow(y + 1, x + 1, '\\')
223 follow(y + 1, x + 1, b'\\')
223 follow(y, x - 1, '-')
224 follow(y, x - 1, b'-')
224 follow(y, x + 1, '-')
225 follow(y, x + 1, b'-')
225
226
226 while visit:
227 while visit:
227 y, x = visit.pop()
228 y, x = visit.pop()
@@ -232,28 +233,28 b' def _parseasciigraph(text):'
232 if _isname(ch):
233 if _isname(ch):
233 result.append(getname(y, x))
234 result.append(getname(y, x))
234 continue
235 continue
235 elif ch == '|':
236 elif ch == b'|':
236 follow(y + 1, x, '/|o')
237 follow(y + 1, x, b'/|o')
237 follow(y + 1, x - 1, '/')
238 follow(y + 1, x - 1, b'/')
238 follow(y + 1, x + 1, '\\')
239 follow(y + 1, x + 1, b'\\')
239 elif ch == '+':
240 elif ch == b'+':
240 follow(y, x - 1, '-')
241 follow(y, x - 1, b'-')
241 follow(y, x + 1, '-')
242 follow(y, x + 1, b'-')
242 follow(y + 1, x - 1, '/')
243 follow(y + 1, x - 1, b'/')
243 follow(y + 1, x + 1, '\\')
244 follow(y + 1, x + 1, b'\\')
244 follow(y + 1, x, '|')
245 follow(y + 1, x, b'|')
245 elif ch == '\\':
246 elif ch == b'\\':
246 follow(y + 1, x + 1, '\\|o')
247 follow(y + 1, x + 1, b'\\|o')
247 elif ch == '/':
248 elif ch == b'/':
248 follow(y + 1, x - 1, '/|o')
249 follow(y + 1, x - 1, b'/|o')
249 elif ch == '-':
250 elif ch == b'-':
250 follow(y, x - 1, '-+o')
251 follow(y, x - 1, b'-+o')
251 follow(y, x + 1, '-+o')
252 follow(y, x + 1, b'-+o')
252 return result
253 return result
253
254
254 for y, line in enumerate(lines):
255 for y, line in enumerate(lines):
255 for x, ch in enumerate(line):
256 for x, ch in enumerate(pycompat.bytestr(line)):
256 if ch == '#': # comment
257 if ch == b'#': # comment
257 break
258 break
258 if _isname(ch):
259 if _isname(ch):
259 edges[getname(y, x)] += parents(y, x)
260 edges[getname(y, x)] += parents(y, x)
@@ -278,14 +279,14 b' class simplefilectx(object):'
278 return None
279 return None
279
280
280 def flags(self):
281 def flags(self):
281 return ''
282 return b''
282
283
283 class simplecommitctx(context.committablectx):
284 class simplecommitctx(context.committablectx):
284 def __init__(self, repo, name, parentctxs, added):
285 def __init__(self, repo, name, parentctxs, added):
285 opts = {
286 opts = {
286 'changes': scmutil.status([], list(added), [], [], [], [], []),
287 'changes': scmutil.status([], list(added), [], [], [], [], []),
287 'date': '0 0',
288 'date': b'0 0',
288 'extra': {'branch': 'default'},
289 'extra': {b'branch': b'default'},
289 }
290 }
290 super(simplecommitctx, self).__init__(self, name, **opts)
291 super(simplecommitctx, self).__init__(self, name, **opts)
291 self._repo = repo
292 self._repo = repo
@@ -304,7 +305,7 b' def _walkgraph(edges):'
304 """yield node, parents in topologically order"""
305 """yield node, parents in topologically order"""
305 visible = set(edges.keys())
306 visible = set(edges.keys())
306 remaining = {} # {str: [str]}
307 remaining = {} # {str: [str]}
307 for k, vs in edges.iteritems():
308 for k, vs in edges.items():
308 for v in vs:
309 for v in vs:
309 if v not in remaining:
310 if v not in remaining:
310 remaining[v] = []
311 remaining[v] = []
@@ -317,13 +318,13 b' def _walkgraph(edges):'
317 if leaf in visible:
318 if leaf in visible:
318 yield leaf, edges[leaf]
319 yield leaf, edges[leaf]
319 del remaining[leaf]
320 del remaining[leaf]
320 for k, v in remaining.iteritems():
321 for k, v in remaining.items():
321 if leaf in v:
322 if leaf in v:
322 v.remove(leaf)
323 v.remove(leaf)
323
324
324 def _getcomments(text):
325 def _getcomments(text):
325 """
326 """
326 >>> [s for s in _getcomments(br'''
327 >>> [pycompat.sysstr(s) for s in _getcomments(br'''
327 ... G
328 ... G
328 ... |
329 ... |
329 ... I D C F # split: B -> E, F, G
330 ... I D C F # split: B -> E, F, G
@@ -335,11 +336,11 b' def _getcomments(text):'
335 ['split: B -> E, F, G', 'replace: C -> D -> H', 'prune: F, I']
336 ['split: B -> E, F, G', 'replace: C -> D -> H', 'prune: F, I']
336 """
337 """
337 for line in text.splitlines():
338 for line in text.splitlines():
338 if ' # ' not in line:
339 if b' # ' not in line:
339 continue
340 continue
340 yield line.split(' # ', 1)[1].split(' # ')[0].strip()
341 yield line.split(b' # ', 1)[1].split(b' # ')[0].strip()
341
342
342 @command('debugdrawdag', [])
343 @command(b'debugdrawdag', [])
343 def debugdrawdag(ui, repo, **opts):
344 def debugdrawdag(ui, repo, **opts):
344 """read an ASCII graph from stdin and create changesets
345 """read an ASCII graph from stdin and create changesets
345
346
@@ -360,22 +361,22 b' def debugdrawdag(ui, repo, **opts):'
360
361
361 # parse the graph and make sure len(parents) <= 2 for each node
362 # parse the graph and make sure len(parents) <= 2 for each node
362 edges = _parseasciigraph(text)
363 edges = _parseasciigraph(text)
363 for k, v in edges.iteritems():
364 for k, v in edges.items():
364 if len(v) > 2:
365 if len(v) > 2:
365 raise error.Abort(_('%s: too many parents: %s')
366 raise error.Abort(_('%s: too many parents: %s')
366 % (k, ' '.join(v)))
367 % (k, b' '.join(v)))
367
368
368 # parse comments to get extra file content instructions
369 # parse comments to get extra file content instructions
369 files = collections.defaultdict(dict) # {(name, path): content}
370 files = collections.defaultdict(dict) # {(name, path): content}
370 comments = list(_getcomments(text))
371 comments = list(_getcomments(text))
371 filere = re.compile(r'^(\w+)/([\w/]+)\s*=\s*(.*)$', re.M)
372 filere = re.compile(br'^(\w+)/([\w/]+)\s*=\s*(.*)$', re.M)
372 for name, path, content in filere.findall('\n'.join(comments)):
373 for name, path, content in filere.findall(b'\n'.join(comments)):
373 files[name][path] = content.replace(r'\n', '\n')
374 files[name][path] = content.replace(br'\n', b'\n')
374
375
375 committed = {None: node.nullid} # {name: node}
376 committed = {None: node.nullid} # {name: node}
376
377
377 # for leaf nodes, try to find existing nodes in repo
378 # for leaf nodes, try to find existing nodes in repo
378 for name, parents in edges.iteritems():
379 for name, parents in edges.items():
379 if len(parents) == 0:
380 if len(parents) == 0:
380 try:
381 try:
381 committed[name] = scmutil.revsingle(repo, name)
382 committed[name] = scmutil.revsingle(repo, name)
@@ -407,27 +408,27 b' def debugdrawdag(ui, repo, **opts):'
407 local=True)
408 local=True)
408
409
409 # handle special comments
410 # handle special comments
410 with repo.wlock(), repo.lock(), repo.transaction('drawdag'):
411 with repo.wlock(), repo.lock(), repo.transaction(b'drawdag'):
411 getctx = lambda x: repo.unfiltered()[committed[x.strip()]]
412 getctx = lambda x: repo.unfiltered()[committed[x.strip()]]
412 for comment in comments:
413 for comment in comments:
413 rels = [] # obsolete relationships
414 rels = [] # obsolete relationships
414 args = comment.split(':', 1)
415 args = comment.split(b':', 1)
415 if len(args) <= 1:
416 if len(args) <= 1:
416 continue
417 continue
417
418
418 cmd = args[0].strip()
419 cmd = args[0].strip()
419 arg = args[1].strip()
420 arg = args[1].strip()
420
421
421 if cmd in ('replace', 'rebase', 'amend'):
422 if cmd in (b'replace', b'rebase', b'amend'):
422 nodes = [getctx(m) for m in arg.split('->')]
423 nodes = [getctx(m) for m in arg.split(b'->')]
423 for i in range(len(nodes) - 1):
424 for i in range(len(nodes) - 1):
424 rels.append((nodes[i], (nodes[i + 1],)))
425 rels.append((nodes[i], (nodes[i + 1],)))
425 elif cmd in ('split',):
426 elif cmd in (b'split',):
426 pre, succs = arg.split('->')
427 pre, succs = arg.split(b'->')
427 succs = succs.split(',')
428 succs = succs.split(b',')
428 rels.append((getctx(pre), (getctx(s) for s in succs)))
429 rels.append((getctx(pre), (getctx(s) for s in succs)))
429 elif cmd in ('prune',):
430 elif cmd in (b'prune',):
430 for n in arg.split(','):
431 for n in arg.split(b','):
431 rels.append((getctx(n), ()))
432 rels.append((getctx(n), ()))
432 if rels:
433 if rels:
433 obsolete.createmarkers(repo, rels, date=(0, 0), operation=cmd)
434 obsolete.createmarkers(repo, rels, date=(0, 0), operation=cmd)
General Comments 0
You need to be logged in to leave comments. Login now