# HG changeset patch # User Ian Moody # Date 1570371407 -3600 # Node ID 24e8aac7c630f161867e62559a9c365b87adf483 # Parent 4530796052427266c945b129de1a17b1539783fe phabricator: add the uploadfile function This is needed to be able to submit binary files such as images in commits (and also non-UTF-8 text files). One of the primary disadvantages of the current use of createrawdiff is that Phabricator simply drops any binary diffs included in the patch, but not the files, so if such a diff is then committed it corrupts any binary files in it. Differential Revision: https://phab.mercurial-scm.org/D7047 diff -r 453079605242 -r 24e8aac7c630 hgext/phabricator.py --- a/hgext/phabricator.py Sun Oct 06 15:04:54 2019 +0100 +++ b/hgext/phabricator.py Sun Oct 06 15:16:47 2019 +0100 @@ -43,6 +43,7 @@ import base64 import contextlib +import hashlib import itertools import json import operator @@ -608,6 +609,43 @@ progress.complete() +def uploadfile(fctx): + """upload binary files to Phabricator""" + repo = fctx.repo() + ui = repo.ui + fname = fctx.path() + size = fctx.size() + fhash = pycompat.bytestr(hashlib.sha256(fctx.data()).hexdigest()) + + # an allocate call is required first to see if an upload is even required + # (Phab might already have it) and to determine if chunking is needed + allocateparams = { + b'name': fname, + b'contentLength': size, + b'contentHash': fhash, + } + filealloc = callconduit(ui, b'file.allocate', allocateparams) + fphid = filealloc[b'filePHID'] + + if filealloc[b'upload']: + ui.write(_(b'uploading %s\n') % bytes(fctx)) + if not fphid: + uploadparams = { + b'name': fname, + b'data_base64': base64.b64encode(fctx.data()), + } + fphid = callconduit(ui, b'file.upload', uploadparams) + else: + uploadchunks(fctx, fphid) + else: + ui.debug(b'server already has %s\n' % bytes(fctx)) + + if not fphid: + raise error.Abort(b'Upload of %s failed.' % bytes(fctx)) + + return fphid + + def creatediff(ctx): """create a Differential Diff""" repo = ctx.repo()