Mercurial > evolve
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 |