comparison hgext/phabricator.py @ 44643:0437959de6f5

phabricator: record all local commits used to create a Differential revision Arcanist records all of the commits that it squashes into a single review, and that info will be helpful when adding similar functionality. This info is used when submitting an updated review, so that the extension can recalculate the old diff and see if a new one is necessary, or if it is just a property update. It also shows on the `commits` tab in the `Revision Contents` section. When submitting in the usual 1:1 commit to review mode, the wire protocol is unchanged. The content of `hg:meta` is a bit odd, but such is the problem when folding several commits. The choice for the parent node is obvious, but the `node` value uses the tip commit because that seems more natural, and is used elsewhere to look up the previous diff when updating. The rest of the attributes follow from there. Differential Revision: https://phab.mercurial-scm.org/D8308
author Matt Harbison <matt_harbison@yahoo.com>
date Wed, 26 Feb 2020 13:13:49 -0500
parents 022bf71515c9
children dbe9182c90f5
comparison
equal deleted inserted replaced
44642:da9b7f9635a2 44643:0437959de6f5
966 msg = _(b'cannot create diff for %s') % ctx 966 msg = _(b'cannot create diff for %s') % ctx
967 raise error.Abort(msg) 967 raise error.Abort(msg)
968 return diff 968 return diff
969 969
970 970
971 def writediffproperties(ctx, diff): 971 def writediffproperties(ctxs, diff):
972 """write metadata to diff so patches could be applied losslessly""" 972 """write metadata to diff so patches could be applied losslessly
973
974 ``ctxs`` is the list of commits that created the diff, in ascending order.
975 The list is generally a single commit, but may be several when using
976 ``phabsend --fold``.
977 """
973 # creatediff returns with a diffid but query returns with an id 978 # creatediff returns with a diffid but query returns with an id
974 diffid = diff.get(b'diffid', diff.get(b'id')) 979 diffid = diff.get(b'diffid', diff.get(b'id'))
980 basectx = ctxs[0]
981 tipctx = ctxs[-1]
982
975 params = { 983 params = {
976 b'diff_id': diffid, 984 b'diff_id': diffid,
977 b'name': b'hg:meta', 985 b'name': b'hg:meta',
978 b'data': templatefilters.json( 986 b'data': templatefilters.json(
979 { 987 {
980 b'user': ctx.user(), 988 b'user': tipctx.user(),
981 b'date': b'%d %d' % ctx.date(), 989 b'date': b'%d %d' % tipctx.date(),
982 b'branch': ctx.branch(), 990 b'branch': tipctx.branch(),
983 b'node': ctx.hex(), 991 b'node': tipctx.hex(),
984 b'parent': ctx.p1().hex(), 992 b'parent': basectx.p1().hex(),
985 } 993 }
986 ), 994 ),
987 } 995 }
988 callconduit(ctx.repo().ui, b'differential.setdiffproperty', params) 996 callconduit(basectx.repo().ui, b'differential.setdiffproperty', params)
989 997
998 commits = {}
999 for ctx in ctxs:
1000 commits[ctx.hex()] = {
1001 b'author': stringutil.person(ctx.user()),
1002 b'authorEmail': stringutil.email(ctx.user()),
1003 b'time': int(ctx.date()[0]),
1004 b'commit': ctx.hex(),
1005 b'parents': [ctx.p1().hex()],
1006 b'branch': ctx.branch(),
1007 }
990 params = { 1008 params = {
991 b'diff_id': diffid, 1009 b'diff_id': diffid,
992 b'name': b'local:commits', 1010 b'name': b'local:commits',
993 b'data': templatefilters.json( 1011 b'data': templatefilters.json(commits),
994 {
995 ctx.hex(): {
996 b'author': stringutil.person(ctx.user()),
997 b'authorEmail': stringutil.email(ctx.user()),
998 b'time': int(ctx.date()[0]),
999 b'commit': ctx.hex(),
1000 b'parents': [ctx.p1().hex()],
1001 b'branch': ctx.branch(),
1002 },
1003 }
1004 ),
1005 } 1012 }
1006 callconduit(ctx.repo().ui, b'differential.setdiffproperty', params) 1013 callconduit(basectx.repo().ui, b'differential.setdiffproperty', params)
1007 1014
1008 1015
1009 def createdifferentialrevision( 1016 def createdifferentialrevision(
1010 ctx, 1017 ctx,
1011 revid=None, 1018 revid=None,
1047 # Even if we don't need to upload a new diff because the patch content 1054 # Even if we don't need to upload a new diff because the patch content
1048 # does not change. We might still need to update its metadata so 1055 # does not change. We might still need to update its metadata so
1049 # pushers could know the correct node metadata. 1056 # pushers could know the correct node metadata.
1050 assert olddiff 1057 assert olddiff
1051 diff = olddiff 1058 diff = olddiff
1052 writediffproperties(ctx, diff) 1059 writediffproperties([ctx], diff)
1053 1060
1054 # Set the parent Revision every time, so commit re-ordering is picked-up 1061 # Set the parent Revision every time, so commit re-ordering is picked-up
1055 if parentrevphid: 1062 if parentrevphid:
1056 transactions.append( 1063 transactions.append(
1057 {b'type': b'parents.set', b'value': [parentrevphid]} 1064 {b'type': b'parents.set', b'value': [parentrevphid]}
1287 mapping[old.node()] = [newnode] 1294 mapping[old.node()] = [newnode]
1288 # Update diff property 1295 # Update diff property
1289 # If it fails just warn and keep going, otherwise the DREV 1296 # If it fails just warn and keep going, otherwise the DREV
1290 # associations will be lost 1297 # associations will be lost
1291 try: 1298 try:
1292 writediffproperties(unfi[newnode], diffmap[old.node()]) 1299 writediffproperties(
1300 [unfi[newnode]], diffmap[old.node()]
1301 )
1293 except util.urlerr.urlerror: 1302 except util.urlerr.urlerror:
1294 ui.warnnoi18n( 1303 ui.warnnoi18n(
1295 b'Failed to update metadata for D%d\n' % drevid 1304 b'Failed to update metadata for D%d\n' % drevid
1296 ) 1305 )
1297 # Remove local tags since it's no longer necessary 1306 # Remove local tags since it's no longer necessary