array( 'help' => "Export change as a git patch. This format is more complete than ". "unified, but less complete than arc bundles. These patches can be ". "applied with 'git apply' or 'arc patch'.", ), 'unified' => array( 'help' => "Export change as a unified patch. This format is less complete ". "than git patches or arc bundles. These patches can be applied with ". "'patch' or 'arc patch'.", ), 'arcbundle' => array( 'param' => 'file', 'help' => "Export change as an arc bundle. This format can represent all ". "changes. These bundles can be applied with 'arc patch'.", ), 'revision' => array( 'param' => 'revision_id', 'help' => "Instead of exporting changes from the working copy, export them ". "from a Differential revision." ), 'diff' => array( 'param' => 'diff_id', 'help' => "Instead of exporting changes from the working copy, export them ". "from a Differential diff." ), '*' => 'paths', ); } protected function didParseArguments() { $source = self::SOURCE_LOCAL; $requested = 0; if ($this->getArgument('revision')) { $source = self::SOURCE_REVISION; $requested++; } if ($this->getArgument('diff')) { $source = self::SOURCE_DIFF; $requested++; } if ($requested > 1) { throw new ArcanistUsageException( "Options '--revision' and '--diff' are not compatible. Choose exactly ". "one change source."); } $this->source = $source; $this->sourceID = $this->getArgument($source); $format = null; $requested = 0; if ($this->getArgument('git')) { $format = self::FORMAT_GIT; $requested++; } if ($this->getArgument('unified')) { $format = self::FORMAT_UNIFIED; $requested++; } if ($this->getArgument('arcbundle')) { $format = self::FORMAT_BUNDLE; $requested++; } if ($requested === 0) { throw new ArcanistUsageException( "Specify one of '--git', '--unified' or '--arcbundle ' to ". "choose an export format."); } else if ($requested > 1) { throw new ArcanistUsageException( "Options '--git', '--unified' and '--arcbundle' are not compatible. ". "Choose exactly one export format."); } $this->format = $format; } public function requiresConduit() { return $this->getSource() != self::SOURCE_LOCAL; } public function requiresAuthentication() { return $this->requiresConduit(); } public function requiresRepositoryAPI() { return $this->getSource() == self::SOURCE_LOCAL; } public function requiresWorkingCopy() { return $this->getSource() == self::SOURCE_LOCAL; } private function getSource() { return $this->source; } private function getSourceID() { return $this->sourceID; } private function getFormat() { return $this->format; } public function run() { $source = $this->getSource(); switch ($source) { case self::SOURCE_LOCAL: $repository_api = $this->getRepositoryAPI(); $parser = new ArcanistDiffParser(); if ($repository_api instanceof ArcanistGitAPI) { $this->parseGitRelativeCommit( $repository_api, $this->getArgument('paths')); $diff = $repository_api->getFullGitDiff(); $changes = $parser->parseDiff($diff); } else { // TODO: paths support $paths = $repository_api->getWorkingCopyStatus(); $changes = $parser->parseSubversionDiff( $repository_api, $paths); } $bundle = ArcanistBundle::newFromChanges($changes); break; case self::SOURCE_REVISION: $bundle = $this->loadRevisionBundleFromConduit( $this->getConduit(), $this->getSourceID()); break; case self::SOURCE_DIFF: $bundle = $this->loadDiffBundleFromConduit( $this->getConduit(), $this->getSourceID()); break; } $format = $this->getFormat(); switch ($format) { case self::FORMAT_GIT: echo $bundle->toGitPatch(); break; case self::FORMAT_UNIFIED: echo $bundle->toUnifiedDiff(); break; case self::FORMAT_BUNDLE: $path = $this->getArgument('arcbundle'); echo "Writing bundle to '{$path}'... "; $bundle->writeToDisk($path); echo "done.\n"; break; } return 0; } }