mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-26 00:32:41 +01:00
Use file.allocate to upload large files from arc diff
Summary: Fixes T8259. Depends on D13016. Use modern logic to support large file uploads. Test Plan: - Diffed with some images, saw them show up in the diff. - Diffed with a 12MB binary, saw it upload in chunks. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T8259 Differential Revision: https://secure.phabricator.com/D13017
This commit is contained in:
parent
877e7b6388
commit
5c7b22e620
2 changed files with 58 additions and 57 deletions
|
@ -45,10 +45,27 @@ final class ArcanistFileUploader extends Phobject {
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ArcanistFileDataRef File data to upload.
|
||||
* @param null|string Optional key to use to identify this file.
|
||||
* @return this
|
||||
* @task add
|
||||
*/
|
||||
public function addFile(ArcanistFileDataRef $file) {
|
||||
$this->files[] = $file;
|
||||
public function addFile(ArcanistFileDataRef $file, $key = null) {
|
||||
|
||||
if ($key === null) {
|
||||
$this->files[] = $file;
|
||||
} else {
|
||||
if (isset($this->files[$key])) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Two files were added with identical explicit keys ("%s"); each '.
|
||||
'explicit key must be unique.',
|
||||
$key));
|
||||
}
|
||||
$this->files[$key] = $file;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -57,6 +74,11 @@ final class ArcanistFileUploader extends Phobject {
|
|||
|
||||
|
||||
/**
|
||||
* This method returns a map of all file data references. If references were
|
||||
* added with an explicit key when @{method:addFile} was called, the key is
|
||||
* retained in the result map.
|
||||
*
|
||||
* @return map<string, ArcanistFileDataRef> Files with results populated.
|
||||
* @task upload
|
||||
*/
|
||||
public function uploadFiles() {
|
||||
|
|
|
@ -2544,72 +2544,51 @@ EOTEXT
|
|||
$change->setMetadata("{$type}:file:mime-type", $mime);
|
||||
}
|
||||
|
||||
echo pht('Uploading %d files...', count($need_upload))."\n";
|
||||
$uploader = id(new ArcanistFileUploader())
|
||||
->setConduitClient($this->getConduit());
|
||||
|
||||
$hash_futures = array();
|
||||
foreach ($need_upload as $key => $spec) {
|
||||
$hash_futures[$key] = $this->getConduit()->callMethod(
|
||||
'file.uploadhash',
|
||||
array(
|
||||
'name' => $spec['name'],
|
||||
'hash' => sha1($spec['data']),
|
||||
));
|
||||
$ref = id(new ArcanistFileDataRef())
|
||||
->setName($spec['name'])
|
||||
->setData($spec['data']);
|
||||
|
||||
$uploader->addFile($ref, $key);
|
||||
}
|
||||
|
||||
$futures = id(new FutureIterator($hash_futures))
|
||||
->limit(8);
|
||||
foreach ($futures as $key => $future) {
|
||||
$type = $need_upload[$key]['type'];
|
||||
$change = $need_upload[$key]['change'];
|
||||
$name = $need_upload[$key]['name'];
|
||||
$files = $uploader->uploadFiles();
|
||||
|
||||
$phid = null;
|
||||
try {
|
||||
$phid = $future->resolve();
|
||||
} catch (Exception $e) {
|
||||
// Just try uploading normally if the hash upload failed.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($phid) {
|
||||
$change->setMetadata("{$type}:binary-phid", $phid);
|
||||
unset($need_upload[$key]);
|
||||
echo pht("Uploaded '%s' (%s).", $name, $type)."\n";
|
||||
$errors = false;
|
||||
foreach ($files as $key => $file) {
|
||||
if ($file->getErrors()) {
|
||||
unset($files[$key]);
|
||||
$errors = true;
|
||||
echo pht(
|
||||
'Failed to upload binary "%s".',
|
||||
$file->getName());
|
||||
}
|
||||
}
|
||||
|
||||
$upload_futures = array();
|
||||
foreach ($need_upload as $key => $spec) {
|
||||
$upload_futures[$key] = $this->getConduit()->callMethod(
|
||||
'file.upload',
|
||||
array(
|
||||
'name' => $spec['name'],
|
||||
'data_base64' => base64_encode($spec['data']),
|
||||
));
|
||||
if ($errors) {
|
||||
$prompt = pht('Continue?');
|
||||
$ok = phutil_console_confirm($prompt, $default_no = false);
|
||||
if (!$ok) {
|
||||
throw new ArcanistUsageException(
|
||||
pht(
|
||||
'Aborted due to file upload failure. You can use %s '.
|
||||
'to skip binary uploads.',
|
||||
'--skip-binaries'));
|
||||
}
|
||||
}
|
||||
|
||||
$futures = id(new FutureIterator($upload_futures))
|
||||
->limit(4);
|
||||
foreach ($futures as $key => $future) {
|
||||
$type = $need_upload[$key]['type'];
|
||||
$change = $need_upload[$key]['change'];
|
||||
$name = $need_upload[$key]['name'];
|
||||
foreach ($files as $key => $file) {
|
||||
$spec = $need_upload[$key];
|
||||
$phid = $file->getPHID();
|
||||
|
||||
try {
|
||||
$phid = $future->resolve();
|
||||
$change->setMetadata("{$type}:binary-phid", $phid);
|
||||
echo pht("Uploaded '%s' (%s).", $name, $type)."\n";
|
||||
} catch (Exception $e) {
|
||||
echo pht("Failed to upload %s binary '%s'.", $type, $name)."\n\n";
|
||||
echo $e->getMessage()."\n";
|
||||
if (!phutil_console_confirm(pht('Continue?'), $default_no = false)) {
|
||||
throw new ArcanistUsageException(
|
||||
pht(
|
||||
'Aborted due to file upload failure. You can use %s '.
|
||||
'to skip binary uploads.',
|
||||
'--skip-binaries'));
|
||||
}
|
||||
}
|
||||
$change = $spec['change'];
|
||||
$type = $spec['type'];
|
||||
$change->setMetadata("{$type}:binary-phid", $phid);
|
||||
|
||||
echo pht('Uploaded binary data for "%s".', $file->getName())."\n";
|
||||
}
|
||||
|
||||
echo pht('Upload complete.')."\n";
|
||||
|
|
Loading…
Reference in a new issue