Patchwork D7047: phabricator: add the uploadfile function

login
register
mail settings
Submitter phabricator
Date Oct. 10, 2019, 9:52 p.m.
Message ID <differential-rev-PHID-DREV-usyqgdhe7sb52iucxhfv-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/42203/
State Superseded
Headers show

Comments

phabricator - Oct. 10, 2019, 9:52 p.m.
Kwan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D7047

AFFECTED FILES
  hgext/phabricator.py

CHANGE DETAILS




To: Kwan, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/hgext/phabricator.py b/hgext/phabricator.py
--- a/hgext/phabricator.py
+++ b/hgext/phabricator.py
@@ -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()