11 from mercurial import cmdutil |
11 from mercurial import cmdutil |
12 from mercurial import hg |
12 from mercurial import hg |
13 from mercurial import scmutil |
13 from mercurial import scmutil |
14 from mercurial import error |
14 from mercurial import error |
15 from mercurial import extensions |
15 from mercurial import extensions |
16 |
16 from mercurial import phases |
17 |
|
18 import re |
|
19 |
|
20 import json |
|
21 |
|
22 |
17 |
23 ### old compat code |
18 ### old compat code |
24 ############################# |
19 ############################# |
25 |
20 |
26 BRANCHNAME="qsubmit2" |
21 BRANCHNAME="qsubmit2" |
27 OLDBRANCHNAME="pyves-qsubmit" |
|
28 |
22 |
29 ### new command |
23 ### new command |
30 ############################# |
24 ############################# |
31 cmdtable = {} |
25 cmdtable = {} |
32 command = cmdutil.command(cmdtable) |
26 command = cmdutil.command(cmdtable) |
57 |
51 |
58 .. warning:: Series files is ordered topologically. So two series with |
52 .. warning:: Series files is ordered topologically. So two series with |
59 interleaved changeset will appear interleaved. |
53 interleaved changeset will appear interleaved. |
60 ''' |
54 ''' |
61 |
55 |
62 review = None |
|
63 review = 'edit' |
56 review = 'edit' |
64 if opts['review_all']: |
57 if opts['review_all']: |
65 review = 'all' |
58 review = 'all' |
66 mqrepo = repo.mq.qrepo() |
59 mqrepo = repo.mq.qrepo() |
67 try: |
60 try: |
68 parent = mqrepo[BRANCHNAME] |
61 parent = mqrepo[BRANCHNAME] |
69 except error.RepoLookupError: |
62 except error.RepoLookupError: |
70 try: |
63 parent = initqsubmit(mqrepo) |
71 parent = mqrepo[OLDBRANCHNAME] |
|
72 except error.RepoLookupError: |
|
73 parent = initqsubmit(mqrepo) |
|
74 store, data, touched = fillstore(repo, parent) |
64 store, data, touched = fillstore(repo, parent) |
75 if not touched: |
65 if not touched: |
76 raise util.Abort('Nothing changed') |
66 raise util.Abort('Nothing changed') |
77 files = ['qsubmitdata', 'series'] + touched |
67 files = ['qsubmitdata', 'series'] + touched |
78 # mark some as ready for review |
68 # mark some as ready for review |
79 message = 'qsubmit commit\n\n' |
69 message = 'qsubmit commit\n\n' |
80 review_list = [] |
70 review_list = [] |
|
71 applied_list = [] |
81 if review: |
72 if review: |
|
73 olddata = get_old_data(parent) |
|
74 oldfiles = dict([(name, ctxhex) for ctxhex, name in olddata]) |
|
75 |
82 for patch_name in touched: |
76 for patch_name in touched: |
83 try: |
77 try: |
84 store.getfile(patch_name) |
78 store.getfile(patch_name) |
85 review_list.append(patch_name) |
79 review_list.append(patch_name) |
86 except IOError: |
80 except IOError: |
87 pass |
81 oldnode = oldfiles[patch_name] |
|
82 obsolete = extensions.find('obsolete') |
|
83 newnodes = obsolete.newerversion(repo, oldnode) |
|
84 if newnodes: |
|
85 newnodes = [n for n in newnodes if n] # remove killing |
|
86 if not newnodes: |
|
87 # changeset has been killed (eg. reject) |
|
88 pass |
|
89 else: |
|
90 assert len(newnodes) == 1 # conflict!!! |
|
91 newnode = newnodes[0] |
|
92 assert len(newnode) == 1 # split unsupported for now |
|
93 newnode = list(newnode)[0] |
|
94 # XXX unmanaged case where a cs is obsoleted by an unavailable one |
|
95 #if newnode.node() not in repo.changelog.nodemap: |
|
96 # raise util.Abort('%s is obsoleted by an unknown node %s'% (oldnode, newnode)) |
|
97 ctx = repo[newnode] |
|
98 if ctx.phase() == phases.public: |
|
99 # applied |
|
100 applied_list.append(patch_name) |
|
101 elif ctx.phase() == phases.secret: |
|
102 # already exported changeset is now secret |
|
103 repo.ui.warn("An already exported changeset is now secret!!!") |
|
104 else: |
|
105 # draft |
|
106 assert False, "Should be exported" |
88 |
107 |
89 if review: |
108 if review: |
|
109 message += '\n'.join('* applied %s' % x for x in applied_list) |
90 message += '\n'.join('* %s ready for review' % x for x in review_list) |
110 message += '\n'.join('* %s ready for review' % x for x in review_list) |
91 memctx = patch.makememctx(mqrepo, (parent.node(), nullid), |
111 memctx = patch.makememctx(mqrepo, (parent.node(), nullid), |
92 message, |
112 message, |
93 None, |
113 None, |
94 None, |
114 None, |
120 return json.loads(old_data.data()) |
140 return json.loads(old_data.data()) |
121 except error.LookupError: |
141 except error.LookupError: |
122 return [] |
142 return [] |
123 |
143 |
124 def get_current_data(repo): |
144 def get_current_data(repo): |
125 """Return what would be exported if not previous data exists""" |
145 """Return what would be exported if no previous data exists""" |
126 data = [] |
146 data = [] |
127 for ctx in repo.set('draft() - (obsolete() + merge())'): |
147 for ctx in repo.set('draft() - (obsolete() + merge())'): |
128 name = makename(ctx) |
148 name = makename(ctx) |
129 data.append([ctx.hex(), makename(ctx)]) |
149 data.append([ctx.hex(), makename(ctx)]) |
130 merges = repo.revs('draft() and merge()') |
150 merges = repo.revs('draft() and merge()') |
186 touched.add(newname) |
206 touched.add(newname) |
187 # sort by branchrev number |
207 # sort by branchrev number |
188 finaldata.sort(key=lambda x: sort_key(repo[x[0]])) |
208 finaldata.sort(key=lambda x: sort_key(repo[x[0]])) |
189 # sort touched too (ease review list) |
209 # sort touched too (ease review list) |
190 stouched = [f[1] for f in finaldata if f[1] in touched] |
210 stouched = [f[1] for f in finaldata if f[1] in touched] |
|
211 stouched += [x for x in touched if x not in stouched] |
191 return finaldata, stouched |
212 return finaldata, stouched |
192 |
213 |
193 def sort_key(ctx): |
214 def sort_key(ctx): |
194 """ctx sort key: (branch, rev)""" |
215 """ctx sort key: (branch, rev)""" |
195 return (ctx.branch(), ctx.rev()) |
216 return (ctx.branch(), ctx.rev()) |
196 |
217 |
197 |
218 |
198 def fillstore(repo, basemqctx): |
219 def fillstore(repo, basemqctx): |
199 """file store with patch data""" |
220 """fill store with patch data""" |
200 olddata = get_old_data(basemqctx) |
221 olddata = get_old_data(basemqctx) |
201 newdata = get_current_data(repo) |
222 newdata = get_current_data(repo) |
202 store = patch.filestore() |
223 store = patch.filestore() |
203 try: |
224 try: |
204 data, touched = patchmq(repo, store, olddata, newdata) |
225 data, touched = patchmq(repo, store, olddata, newdata) |
205 # put all name in the series |
226 # put all name in the series |
206 series ='\n'.join(d[1] for d in data) + '\n' |
227 series ='\n'.join(d[1] for d in data) + '\n' |
207 store.setfile('series', series, (False, False)) |
228 store.setfile('series', series, (False, False)) |
208 |
229 |
209 # export data to ease futur work |
230 # export data to ease futur work |
210 series ='\n'.join(d[1] for d in data) + '\n' |
|
211 store.setfile('qsubmitdata', json.dumps(data, indent=True), |
231 store.setfile('qsubmitdata', json.dumps(data, indent=True), |
212 (False, False)) |
232 (False, False)) |
213 finally: |
233 finally: |
214 store.close() |
234 store.close() |
215 return store, data, touched |
235 return store, data, touched |