hgext/phabricator.py
changeset 44614 53d75fdeaaaa
parent 44613 7b9aaec17126
child 44615 022bf71515c9
equal deleted inserted replaced
44613:7b9aaec17126 44614: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