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 |