diff --git a/src/upload/ArcanistFileUploader.php b/src/upload/ArcanistFileUploader.php --- a/src/upload/ArcanistFileUploader.php +++ b/src/upload/ArcanistFileUploader.php @@ -45,10 +45,27 @@ /** + * + * @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 @@ /** + * 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 Files with results populated. * @task upload */ public function uploadFiles() { diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php --- a/src/workflow/ArcanistDiffWorkflow.php +++ b/src/workflow/ArcanistDiffWorkflow.php @@ -2544,72 +2544,51 @@ $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; + $errors = false; + foreach ($files as $key => $file) { + if ($file->getErrors()) { + unset($files[$key]); + $errors = true; + echo pht( + 'Failed to upload binary "%s".', + $file->getName()); } + } - if ($phid) { - $change->setMetadata("{$type}:binary-phid", $phid); - unset($need_upload[$key]); - echo pht("Uploaded '%s' (%s).", $name, $type)."\n"; + 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')); } } - $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']), - )); - } + foreach ($files as $key => $file) { + $spec = $need_upload[$key]; + $phid = $file->getPHID(); - $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']; + $change = $spec['change']; + $type = $spec['type']; + $change->setMetadata("{$type}:binary-phid", $phid); - 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')); - } - } + echo pht('Uploaded binary data for "%s".', $file->getName())."\n"; } echo pht('Upload complete.')."\n";