Mercurial > hg
comparison hgext/phabricator.py @ 44609:53d75fdeaaaa
phabricator: add basectx arguments to file related `phabsend` utilities
This is in support of a future `--fold` option, that allows rolling up several
commits into a single review with a diff from the start to the end of the range.
There are no functional changes yet- the original `ctx` is also passed as the
new `basectx`, which represents the first commit in the review range (similar to
`qbase` in MQ parlance). Other functions will need the range of commits, but
these deal with status or the diffs, so they only need the end points.
Differential Revision: https://phab.mercurial-scm.org/D8306
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Mon, 24 Feb 2020 12:06:34 -0500 |
parents | 7b9aaec17126 |
children | 022bf71515c9 |
comparison
equal
deleted
inserted
replaced
44608:7b9aaec17126 | 44609:53d75fdeaaaa |
---|---|
548 break | 548 break |
549 | 549 |
550 return result | 550 return result |
551 | 551 |
552 | 552 |
553 def getdiff(ctx, diffopts): | 553 def getdiff(basectx, ctx, diffopts): |
554 """plain-text diff without header (user, commit message, etc)""" | 554 """plain-text diff without header (user, commit message, etc)""" |
555 output = util.stringio() | 555 output = util.stringio() |
556 for chunk, _label in patch.diffui( | 556 for chunk, _label in patch.diffui( |
557 ctx.repo(), ctx.p1().node(), ctx.node(), None, opts=diffopts | 557 ctx.repo(), basectx.p1().node(), ctx.node(), None, opts=diffopts |
558 ): | 558 ): |
559 output.write(chunk) | 559 output.write(chunk) |
560 return output.getvalue() | 560 return output.getvalue() |
561 | 561 |
562 | 562 |
659 self.changes[change.currentPath] = pycompat.byteskwargs( | 659 self.changes[change.currentPath] = pycompat.byteskwargs( |
660 attr.asdict(change) | 660 attr.asdict(change) |
661 ) | 661 ) |
662 | 662 |
663 | 663 |
664 def maketext(pchange, ctx, fname): | 664 def maketext(pchange, basectx, ctx, fname): |
665 """populate the phabchange for a text file""" | 665 """populate the phabchange for a text file""" |
666 repo = ctx.repo() | 666 repo = ctx.repo() |
667 fmatcher = match.exact([fname]) | 667 fmatcher = match.exact([fname]) |
668 diffopts = mdiff.diffopts(git=True, context=32767) | 668 diffopts = mdiff.diffopts(git=True, context=32767) |
669 _pfctx, _fctx, header, fhunks = next( | 669 _pfctx, _fctx, header, fhunks = next( |
670 patch.diffhunks(repo, ctx.p1(), ctx, fmatcher, opts=diffopts) | 670 patch.diffhunks(repo, basectx.p1(), ctx, fmatcher, opts=diffopts) |
671 ) | 671 ) |
672 | 672 |
673 for fhunk in fhunks: | 673 for fhunk in fhunks: |
674 (oldOffset, oldLength, newOffset, newLength), lines = fhunk | 674 (oldOffset, oldLength, newOffset, newLength), lines = fhunk |
675 corpus = b''.join(lines[1:]) | 675 corpus = b''.join(lines[1:]) |
811 % fctx.path() | 811 % fctx.path() |
812 ) | 812 ) |
813 return True | 813 return True |
814 | 814 |
815 | 815 |
816 def addremoved(pdiff, ctx, removed): | 816 def addremoved(pdiff, basectx, ctx, removed): |
817 """add removed files to the phabdiff. Shouldn't include moves""" | 817 """add removed files to the phabdiff. Shouldn't include moves""" |
818 for fname in removed: | 818 for fname in removed: |
819 pchange = phabchange( | 819 pchange = phabchange( |
820 currentPath=fname, oldPath=fname, type=DiffChangeType.DELETE | 820 currentPath=fname, oldPath=fname, type=DiffChangeType.DELETE |
821 ) | 821 ) |
822 oldfctx = ctx.p1()[fname] | 822 oldfctx = basectx.p1()[fname] |
823 pchange.addoldmode(gitmode[oldfctx.flags()]) | 823 pchange.addoldmode(gitmode[oldfctx.flags()]) |
824 if not (oldfctx.isbinary() or notutf8(oldfctx)): | 824 if not (oldfctx.isbinary() or notutf8(oldfctx)): |
825 maketext(pchange, ctx, fname) | 825 maketext(pchange, basectx, ctx, fname) |
826 | 826 |
827 pdiff.addchange(pchange) | 827 pdiff.addchange(pchange) |
828 | 828 |
829 | 829 |
830 def addmodified(pdiff, ctx, modified): | 830 def addmodified(pdiff, basectx, ctx, modified): |
831 """add modified files to the phabdiff""" | 831 """add modified files to the phabdiff""" |
832 for fname in modified: | 832 for fname in modified: |
833 fctx = ctx[fname] | 833 fctx = ctx[fname] |
834 oldfctx = ctx.p1()[fname] | 834 oldfctx = basectx.p1()[fname] |
835 pchange = phabchange(currentPath=fname, oldPath=fname) | 835 pchange = phabchange(currentPath=fname, oldPath=fname) |
836 filemode = gitmode[fctx.flags()] | 836 filemode = gitmode[fctx.flags()] |
837 originalmode = gitmode[oldfctx.flags()] | 837 originalmode = gitmode[oldfctx.flags()] |
838 if filemode != originalmode: | 838 if filemode != originalmode: |
839 pchange.addoldmode(originalmode) | 839 pchange.addoldmode(originalmode) |
846 or notutf8(oldfctx) | 846 or notutf8(oldfctx) |
847 ): | 847 ): |
848 makebinary(pchange, fctx) | 848 makebinary(pchange, fctx) |
849 addoldbinary(pchange, oldfctx, fctx) | 849 addoldbinary(pchange, oldfctx, fctx) |
850 else: | 850 else: |
851 maketext(pchange, ctx, fname) | 851 maketext(pchange, basectx, ctx, fname) |
852 | 852 |
853 pdiff.addchange(pchange) | 853 pdiff.addchange(pchange) |
854 | 854 |
855 | 855 |
856 def addadded(pdiff, ctx, added, removed): | 856 def addadded(pdiff, basectx, ctx, added, removed): |
857 """add file adds to the phabdiff, both new files and copies/moves""" | 857 """add file adds to the phabdiff, both new files and copies/moves""" |
858 # Keep track of files that've been recorded as moved/copied, so if there are | 858 # Keep track of files that've been recorded as moved/copied, so if there are |
859 # additional copies we can mark them (moves get removed from removed) | 859 # additional copies we can mark them (moves get removed from removed) |
860 copiedchanges = {} | 860 copiedchanges = {} |
861 movedchanges = {} | 861 movedchanges = {} |
867 filemode = gitmode[fctx.flags()] | 867 filemode = gitmode[fctx.flags()] |
868 renamed = fctx.renamed() | 868 renamed = fctx.renamed() |
869 | 869 |
870 if renamed: | 870 if renamed: |
871 originalfname = renamed[0] | 871 originalfname = renamed[0] |
872 oldfctx = ctx.p1()[originalfname] | 872 oldfctx = basectx.p1()[originalfname] |
873 originalmode = gitmode[oldfctx.flags()] | 873 originalmode = gitmode[oldfctx.flags()] |
874 pchange.oldPath = originalfname | 874 pchange.oldPath = originalfname |
875 | 875 |
876 if originalfname in removed: | 876 if originalfname in removed: |
877 origpchange = phabchange( | 877 origpchange = phabchange( |
912 ): | 912 ): |
913 makebinary(pchange, fctx) | 913 makebinary(pchange, fctx) |
914 if renamed: | 914 if renamed: |
915 addoldbinary(pchange, oldfctx, fctx) | 915 addoldbinary(pchange, oldfctx, fctx) |
916 else: | 916 else: |
917 maketext(pchange, ctx, fname) | 917 maketext(pchange, basectx, ctx, fname) |
918 | 918 |
919 pdiff.addchange(pchange) | 919 pdiff.addchange(pchange) |
920 | 920 |
921 for _path, copiedchange in copiedchanges.items(): | 921 for _path, copiedchange in copiedchanges.items(): |
922 pdiff.addchange(copiedchange) | 922 pdiff.addchange(copiedchange) |
923 for _path, movedchange in movedchanges.items(): | 923 for _path, movedchange in movedchanges.items(): |
924 pdiff.addchange(movedchange) | 924 pdiff.addchange(movedchange) |
925 | 925 |
926 | 926 |
927 def creatediff(ctx): | 927 def creatediff(basectx, ctx): |
928 """create a Differential Diff""" | 928 """create a Differential Diff""" |
929 repo = ctx.repo() | 929 repo = ctx.repo() |
930 repophid = getrepophid(repo) | 930 repophid = getrepophid(repo) |
931 # Create a "Differential Diff" via "differential.creatediff" API | 931 # Create a "Differential Diff" via "differential.creatediff" API |
932 pdiff = phabdiff( | 932 pdiff = phabdiff( |
933 sourceControlBaseRevision=b'%s' % ctx.p1().hex(), | 933 sourceControlBaseRevision=b'%s' % basectx.p1().hex(), |
934 branch=b'%s' % ctx.branch(), | 934 branch=b'%s' % ctx.branch(), |
935 ) | 935 ) |
936 modified, added, removed, _d, _u, _i, _c = ctx.p1().status(ctx) | 936 modified, added, removed, _d, _u, _i, _c = basectx.p1().status(ctx) |
937 # addadded will remove moved files from removed, so addremoved won't get | 937 # addadded will remove moved files from removed, so addremoved won't get |
938 # them | 938 # them |
939 addadded(pdiff, ctx, added, removed) | 939 addadded(pdiff, basectx, ctx, added, removed) |
940 addmodified(pdiff, ctx, modified) | 940 addmodified(pdiff, basectx, ctx, modified) |
941 addremoved(pdiff, ctx, removed) | 941 addremoved(pdiff, basectx, ctx, removed) |
942 if repophid: | 942 if repophid: |
943 pdiff.repositoryPHID = repophid | 943 pdiff.repositoryPHID = repophid |
944 diff = callconduit( | 944 diff = callconduit( |
945 repo.ui, | 945 repo.ui, |
946 b'differential.creatediff', | 946 b'differential.creatediff', |
947 pycompat.byteskwargs(attr.asdict(pdiff)), | 947 pycompat.byteskwargs(attr.asdict(pdiff)), |
948 ) | 948 ) |
949 if not diff: | 949 if not diff: |
950 raise error.Abort(_(b'cannot create diff for %s') % ctx) | 950 if basectx != ctx: |
951 msg = _(b'cannot create diff for %s::%s') % (basectx, ctx) | |
952 else: | |
953 msg = _(b'cannot create diff for %s') % ctx | |
954 raise error.Abort(msg) | |
951 return diff | 955 return diff |
952 | 956 |
953 | 957 |
954 def writediffproperties(ctx, diff): | 958 def writediffproperties(ctx, diff): |
955 """write metadata to diff so patches could be applied losslessly""" | 959 """write metadata to diff so patches could be applied losslessly""" |
1006 If oldnode is not None, check if the patch content (without commit message | 1010 If oldnode is not None, check if the patch content (without commit message |
1007 and metadata) has changed before creating another diff. | 1011 and metadata) has changed before creating another diff. |
1008 | 1012 |
1009 If actions is not None, they will be appended to the transaction. | 1013 If actions is not None, they will be appended to the transaction. |
1010 """ | 1014 """ |
1015 basectx = ctx | |
1011 repo = ctx.repo() | 1016 repo = ctx.repo() |
1012 if oldnode: | 1017 if oldnode: |
1013 diffopts = mdiff.diffopts(git=True, context=32767) | 1018 diffopts = mdiff.diffopts(git=True, context=32767) |
1014 oldctx = repo.unfiltered()[oldnode] | 1019 oldctx = repo.unfiltered()[oldnode] |
1015 neednewdiff = getdiff(ctx, diffopts) != getdiff(oldctx, diffopts) | 1020 oldbasectx = oldctx |
1021 neednewdiff = getdiff(basectx, ctx, diffopts) != getdiff( | |
1022 oldbasectx, oldctx, diffopts | |
1023 ) | |
1016 else: | 1024 else: |
1017 neednewdiff = True | 1025 neednewdiff = True |
1018 | 1026 |
1019 transactions = [] | 1027 transactions = [] |
1020 if neednewdiff: | 1028 if neednewdiff: |
1021 diff = creatediff(ctx) | 1029 diff = creatediff(basectx, ctx) |
1022 transactions.append({b'type': b'update', b'value': diff[b'phid']}) | 1030 transactions.append({b'type': b'update', b'value': diff[b'phid']}) |
1023 if comment: | 1031 if comment: |
1024 transactions.append({b'type': b'comment', b'value': comment}) | 1032 transactions.append({b'type': b'comment', b'value': comment}) |
1025 else: | 1033 else: |
1026 # Even if we don't need to upload a new diff because the patch content | 1034 # Even if we don't need to upload a new diff because the patch content |