1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-30 02:32:41 +01:00
phorge-arcanist/src/workflow/ArcanistExportWorkflow.php

275 lines
7.8 KiB
PHP
Raw Normal View History

2011-01-10 00:22:25 +01:00
<?php
/**
* Exports changes from Differential or the working copy to a file.
*/
final class ArcanistExportWorkflow extends ArcanistWorkflow {
2011-01-10 00:22:25 +01:00
const SOURCE_LOCAL = 'local';
const SOURCE_DIFF = 'diff';
const SOURCE_REVISION = 'revision';
const FORMAT_GIT = 'git';
const FORMAT_UNIFIED = 'unified';
const FORMAT_BUNDLE = 'arcbundle';
private $source;
private $sourceID;
private $format;
public function getWorkflowName() {
return 'export';
}
public function getCommandSynopses() {
2011-01-10 00:22:25 +01:00
return phutil_console_format(<<<EOTEXT
**export** [__paths__] __format__ (svn)
**export** [__commit_range__] __format__ (git, hg)
2011-01-10 00:22:25 +01:00
**export** __--revision__ __revision_id__ __format__
**export** __--diff__ __diff_id__ __format__
EOTEXT
);
}
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
Supports: svn, git, hg
2011-01-10 00:22:25 +01:00
Export the local changeset (or a Differential changeset) to a file,
in some __format__: git diff (__--git__), unified diff
(__--unified__), or arc bundle (__--arcbundle__ __path__) format.
EOTEXT
);
}
public function getArguments() {
return array(
'git' => array(
'help' => pht(
2011-01-10 00:22:25 +01:00
"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 '%s' or '%s'.",
'git apply',
'arc patch'),
2011-01-10 00:22:25 +01:00
),
'unified' => array(
'help' => pht(
2011-01-10 00:22:25 +01:00
"Export change as a unified patch. This format is less complete ".
"than git patches or arc bundles. These patches can be applied with ".
"'%s' or '%s'.",
'patch',
'arc patch'),
2011-01-10 00:22:25 +01:00
),
'arcbundle' => array(
'param' => 'file',
'help' => pht(
2011-01-10 00:22:25 +01:00
"Export change as an arc bundle. This format can represent all ".
"changes. These bundles can be applied with '%s'.",
'arc patch'),
2011-01-10 00:22:25 +01:00
),
'encoding' => array(
'param' => 'encoding',
'help' => pht(
'Attempt to convert non UTF-8 patch into specified encoding.'),
),
2011-01-10 00:22:25 +01:00
'revision' => array(
'param' => 'revision_id',
'help' => pht(
'Instead of exporting changes from the working copy, export them '.
'from a Differential revision.'),
2011-01-10 00:22:25 +01:00
),
'diff' => array(
'param' => 'diff_id',
'help' => pht(
'Instead of exporting changes from the working copy, export them '.
'from a Differential diff.'),
2011-01-10 00:22:25 +01:00
),
'*' => 'paths',
);
}
protected function didParseArguments() {
$source = self::SOURCE_LOCAL;
$requested = 0;
if ($this->getArgument('revision')) {
$source = self::SOURCE_REVISION;
$requested++;
$source_id = $this->getArgument($source);
$this->sourceID = $this->normalizeRevisionID($source_id);
2011-01-10 00:22:25 +01:00
}
if ($this->getArgument('diff')) {
$source = self::SOURCE_DIFF;
$requested++;
$this->sourceID = $this->getArgument($source);
2011-01-10 00:22:25 +01:00
}
$this->source = $source;
2011-01-10 00:22:25 +01:00
if ($requested > 1) {
throw new ArcanistUsageException(
pht(
"Options '%s' and '%s' are not compatible. Choose exactly ".
"one change source.",
'--revision',
'--diff'));
2011-01-10 00:22:25 +01:00
}
$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(
pht(
"Specify one of '%s', '%s' or '%s' to choose an export format.",
'--git',
'--unified',
'--arcbundle <path>'));
2011-01-10 00:22:25 +01:00
} else if ($requested > 1) {
throw new ArcanistUsageException(
pht(
"Options '%s', '%s' and '%s' are not compatible. ".
"Choose exactly one export format.",
'--git',
'--unified',
'--arcbundle'));
2011-01-10 00:22:25 +01:00
}
$this->format = $format;
}
public function requiresConduit() {
return true;
2011-01-10 00:22:25 +01:00
}
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();
$parser->setRepositoryAPI($repository_api);
2011-02-06 22:04:01 +01:00
if ($repository_api instanceof ArcanistGitAPI) {
$this->parseBaseCommitArgument($this->getArgument('paths'));
$diff = $repository_api->getFullGitDiff(
$repository_api->getBaseCommit(),
$repository_api->getHeadCommit());
$changes = $parser->parseDiff($diff);
$authors = $this->getConduit()->callMethodSynchronous(
'user.query',
array(
'phids' => array($this->getUserPHID()),
));
$author_dict = reset($authors);
list($email) = $repository_api->execxLocal('config user.email');
$author = sprintf('%s <%s>',
$author_dict['realName'],
$email);
} else if ($repository_api instanceof ArcanistMercurialAPI) {
$this->parseBaseCommitArgument($this->getArgument('paths'));
$diff = $repository_api->getFullMercurialDiff();
$changes = $parser->parseDiff($diff);
$authors = $this->getConduit()->callMethodSynchronous(
'user.query',
array(
'phids' => array($this->getUserPHID()),
));
list($author) = $repository_api->execxLocal('showconfig ui.username');
} else {
// TODO: paths support
$paths = $repository_api->getWorkingCopyStatus();
$changes = $parser->parseSubversionDiff(
$repository_api,
$paths);
$author = $this->getUserName();
}
2011-01-10 00:22:25 +01:00
$bundle = ArcanistBundle::newFromChanges($changes);
$bundle->setBaseRevision(
$repository_api->getSourceControlBaseRevision());
// NOTE: we can't get a revision ID for SOURCE_LOCAL
$parser = new PhutilEmailAddress($author);
$bundle->setAuthorName($parser->getDisplayName());
$bundle->setAuthorEmail($parser->getAddress());
2011-01-10 00:22:25 +01:00
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;
}
$try_encoding = nonempty($this->getArgument('encoding'), null);
if ($try_encoding) {
$bundle->setEncoding($try_encoding);
}
2011-01-10 00:22:25 +01:00
$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 pht("Writing bundle to '%s'...", $path)."\n";
2011-01-10 00:22:25 +01:00
$bundle->writeToDisk($path);
echo pht('Done.')."\n";
2011-01-10 00:22:25 +01:00
break;
}
return 0;
}
2011-01-10 00:22:25 +01:00
}