comparison hgext3rd/topic/stack.py @ 2669:b933a8068c17

topic: add some initial support for using stack on named branch Stack is a useful command that can make sense in other context. The current support is hacky and awful, but we have something!
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 28 Jun 2017 02:45:57 +0200
parents 1d2c66dc4ee3
children f5d52fa1cd55
comparison
equal deleted inserted replaced
2668:1d2c66dc4ee3 2669:b933a8068c17
8 error, 8 error,
9 node, 9 node,
10 ) 10 )
11 from .evolvebits import builddependencies, _orderrevs, _singlesuccessor 11 from .evolvebits import builddependencies, _orderrevs, _singlesuccessor
12 12
13 def getstack(repo, topic=None): 13 def getstack(repo, branch=None, topic=None):
14 # XXX need sorting 14 # XXX need sorting
15 trevs = repo.revs("topic(%s) - obsolete()", topic) 15 if topic is not None and branch is not None:
16 raise error.ProgrammingError('both branch and topic specified (not defined yet)')
17 elif topic is not None:
18 trevs = repo.revs("topic(%s) - obsolete()", topic)
19 elif branch is not None:
20 trevs = repo.revs("branch(%s) - obsolete()", branch)
21 else:
22 raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
16 return _orderrevs(repo, trevs) 23 return _orderrevs(repo, trevs)
17 24
18 def labelsgen(prefix, labelssuffix): 25 def labelsgen(prefix, labelssuffix):
19 """ Takes a label prefix and a list of suffixes. Returns a string of the prefix 26 """ Takes a label prefix and a list of suffixes. Returns a string of the prefix
20 formatted with each suffix separated with a space. 27 formatted with each suffix separated with a space.
21 """ 28 """
22 return ' '.join(prefix % suffix for suffix in labelssuffix) 29 return ' '.join(prefix % suffix for suffix in labelssuffix)
23 30
24 def showstack(ui, repo, topic=None, opts=None): 31 def showstack(ui, repo, branch=None, topic=None, opts=None):
25 if opts is None: 32 if opts is None:
26 opts = {} 33 opts = {}
27 34
28 if topic not in repo.topics: 35 if topic is not None and branch is not None:
29 raise error.Abort(_('cannot resolve "%s": no such topic found') % topic) 36 msg = 'both branch and topic specified [%s]{%s}(not defined yet)'
37 msg %= (branch, topic)
38 raise error.ProgrammingError(msg)
39 elif topic is not None:
40 prefix = 't'
41 if topic not in repo.topics:
42 raise error.Abort(_('cannot resolve "%s": no such topic found') % topic)
43 elif branch is not None:
44 prefix = 'b'
45 else:
46 raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
30 47
31 fm = ui.formatter('topicstack', opts) 48 fm = ui.formatter('topicstack', opts)
32 prev = None 49 prev = None
33 entries = [] 50 entries = []
34 idxmap = {} 51 idxmap = {}
35 52
36 label = 'topic' 53 label = 'topic'
37 if topic == repo.currenttopic: 54 if topic == repo.currenttopic:
38 label = 'topic.active' 55 label = 'topic.active'
39 56
40 data = stackdata(repo, topic=topic) 57 data = stackdata(repo, branch=branch, topic=topic)
41 fm.plain(_('### topic: %s') % ui.label(topic, label), 58 fm.plain(_('### topic: %s') % ui.label(topic, label),
42 label='topic.stack.summary.topic') 59 label='topic.stack.summary.topic')
43 60
44 if 1 < data['headcount']: 61 if 1 < data['headcount']:
45 fm.plain(' (') 62 fm.plain(' (')
56 elif data['behindcount']: 73 elif data['behindcount']:
57 fm.plain(', ') 74 fm.plain(', ')
58 fm.plain('%d behind' % data['behindcount'], label='topic.stack.summary.behindcount') 75 fm.plain('%d behind' % data['behindcount'], label='topic.stack.summary.behindcount')
59 fm.plain('\n') 76 fm.plain('\n')
60 77
61 for idx, r in enumerate(getstack(repo, topic=topic), 1): 78 for idx, r in enumerate(getstack(repo, branch=branch, topic=topic), 1):
62 ctx = repo[r] 79 ctx = repo[r]
63 p1 = ctx.p1() 80 p1 = ctx.p1()
64 if p1.obsolete(): 81 if p1.obsolete():
65 p1 = repo[_singlesuccessor(repo, p1)] 82 p1 = repo[_singlesuccessor(repo, p1)]
66 if p1.rev() != prev and p1.node() != node.nullid: 83 if p1.rev() != prev and p1.node() != node.nullid:
98 fm.data(isentry=isentry) 115 fm.data(isentry=isentry)
99 116
100 if idx is None: 117 if idx is None:
101 fm.plain(' ') 118 fm.plain(' ')
102 else: 119 else:
103 fm.write('topic.stack.index', 't%d', idx, 120 fm.write('topic.stack.index', '%s%%d' % prefix, idx,
104 label='topic.stack.index ' + labelsgen('topic.stack.index.%s', states)) 121 label='topic.stack.index ' + labelsgen('topic.stack.index.%s', states))
105 fm.write('topic.stack.state.symbol', '%s', symbol, 122 fm.write('topic.stack.state.symbol', '%s', symbol,
106 label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states)) 123 label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states))
107 fm.plain(' ') 124 fm.plain(' ')
108 fm.write('topic.stack.desc', '%s', ctx.description().splitlines()[0], 125 fm.write('topic.stack.desc', '%s', ctx.description().splitlines()[0],
111 ' (%s)', fm.formatlist(states, 'topic.stack.state'), 128 ' (%s)', fm.formatlist(states, 'topic.stack.state'),
112 label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states)) 129 label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states))
113 fm.plain('\n') 130 fm.plain('\n')
114 fm.end() 131 fm.end()
115 132
116 def stackdata(repo, topic=None): 133 def stackdata(repo, branch=None, topic=None):
117 """get various data about a stack 134 """get various data about a stack
118 135
119 :changesetcount: number of non-obsolete changesets in the stack 136 :changesetcount: number of non-obsolete changesets in the stack
120 :troubledcount: number on troubled changesets 137 :troubledcount: number on troubled changesets
121 :headcount: number of heads on the topic 138 :headcount: number of heads on the topic
122 :behindcount: number of changeset on rebase destination 139 :behindcount: number of changeset on rebase destination
123 """ 140 """
124 data = {} 141 data = {}
125 revs = repo.revs("topic(%s) - obsolete()", topic) 142 revs = getstack(repo, branch, topic)
126 data['changesetcount'] = len(revs) 143 data['changesetcount'] = len(revs)
127 data['troubledcount'] = len([r for r in revs if repo[r].troubled()]) 144 data['troubledcount'] = len([r for r in revs if repo[r].troubled()])
128 deps, rdeps = builddependencies(repo, revs) 145 deps, rdeps = builddependencies(repo, revs)
129 data['headcount'] = len([r for r in revs if not rdeps[r]]) 146 data['headcount'] = len([r for r in revs if not rdeps[r]])
130 data['behindcount'] = 0 147 data['behindcount'] = 0