mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-30 01:10:58 +01:00
Add support for landing to hosted Mercurial repos.
Summary: I've kept this as close as possible to the Git version for ease of review and later refactoring of them both together. At minimum, the functions to get the working dir should probably be cleaned up one day. Test Plan: Landed a revision. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley CC: Korvin, epriestley, aran Differential Revision: https://secure.phabricator.com/D7534
This commit is contained in:
parent
1c73d6cd06
commit
d700e7f22d
5 changed files with 166 additions and 2 deletions
|
@ -388,6 +388,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php',
|
||||
'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php',
|
||||
'DifferentialLandingToHostedGit' => 'applications/differential/landing/DifferentialLandingToHostedGit.php',
|
||||
'DifferentialLandingToHostedMercurial' => 'applications/differential/landing/DifferentialLandingToHostedMercurial.php',
|
||||
'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/DifferentialLinesFieldSpecification.php',
|
||||
'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/DifferentialLintFieldSpecification.php',
|
||||
'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php',
|
||||
|
@ -2647,6 +2648,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialJIRAIssuesFieldSpecification' => 'DifferentialFieldSpecification',
|
||||
'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener',
|
||||
'DifferentialLandingToHostedGit' => 'DifferentialLandingStrategy',
|
||||
'DifferentialLandingToHostedMercurial' => 'DifferentialLandingStrategy',
|
||||
'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification',
|
||||
'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification',
|
||||
'DifferentialLocalCommitsView' => 'AphrontView',
|
||||
|
|
|
@ -36,4 +36,32 @@ final class DifferentialGetWorkingCopy {
|
|||
return $workspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and/or cleans a workspace for the requested repo.
|
||||
*
|
||||
* return ArcanistMercurialAPI
|
||||
*/
|
||||
public static function getCleanMercurialWorkspace(
|
||||
PhabricatorRepository $repo) {
|
||||
|
||||
$origin_path = $repo->getLocalPath();
|
||||
|
||||
$path = rtrim($origin_path, '/');
|
||||
$path = $path . '__workspace';
|
||||
|
||||
if (!Filesystem::pathExists($path)) {
|
||||
$repo->execxLocalCommand(
|
||||
'clone -- file://%s %s',
|
||||
$origin_path,
|
||||
$path);
|
||||
}
|
||||
|
||||
$workspace = new ArcanistMercurialAPI($path);
|
||||
$workspace->execxLocal('pull');
|
||||
$workspace->execxLocal('update --clean default');
|
||||
$workspace->reloadWorkingCopy();
|
||||
|
||||
return $workspace;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ final class DifferentialRevisionLandController extends DifferentialController {
|
|||
$prompt = hsprintf('%s<br><br>%s',
|
||||
pht(
|
||||
'This will squash and rebase revision %s, and push it to '.
|
||||
'origin/master.',
|
||||
'the default / master branch.',
|
||||
$revision_id),
|
||||
pht('It is an experimental feature and may not work.'));
|
||||
|
||||
|
|
|
@ -35,7 +35,21 @@ abstract class DifferentialLandingStrategy {
|
|||
try {
|
||||
return DifferentialGetWorkingCopy::getCleanGitWorkspace($repository);
|
||||
} catch (Exception $e) {
|
||||
throw new PhutilProxyException (
|
||||
throw new PhutilProxyException(
|
||||
'Failed to allocate a workspace',
|
||||
$e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* might break if repository is not Mercurial.
|
||||
*/
|
||||
protected function getMercurialWorkspace(PhabricatorRepository $repository) {
|
||||
try {
|
||||
return DifferentialGetWorkingCopy::getCleanMercurialWorkspace(
|
||||
$repository);
|
||||
} catch (Exception $e) {
|
||||
throw new PhutilProxyException(
|
||||
'Failed to allocate a workspace',
|
||||
$e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialLandingToHostedMercurial
|
||||
extends DifferentialLandingStrategy {
|
||||
|
||||
public function processLandRequest(
|
||||
AphrontRequest $request,
|
||||
DifferentialRevision $revision,
|
||||
PhabricatorRepository $repository) {
|
||||
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$workspace = $this->getMercurialWorkspace($repository);
|
||||
|
||||
try {
|
||||
$this->commitRevisionToWorkspace(
|
||||
$revision,
|
||||
$workspace,
|
||||
$viewer);
|
||||
} catch (Exception $e) {
|
||||
throw new PhutilProxyException(
|
||||
'Failed to commit patch',
|
||||
$e);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->pushWorkspaceRepository(
|
||||
$repository,
|
||||
$workspace,
|
||||
$viewer);
|
||||
} catch (Exception $e) {
|
||||
throw new PhutilProxyException(
|
||||
'Failed to push changes upstream',
|
||||
$e);
|
||||
}
|
||||
}
|
||||
|
||||
public function commitRevisionToWorkspace(
|
||||
DifferentialRevision $revision,
|
||||
ArcanistRepositoryAPI $workspace,
|
||||
PhabricatorUser $user) {
|
||||
|
||||
$diff_id = $revision->loadActiveDiff()->getID();
|
||||
|
||||
$call = new ConduitCall(
|
||||
'differential.getrawdiff',
|
||||
array(
|
||||
'diffID' => $diff_id,
|
||||
));
|
||||
|
||||
$call->setUser($user);
|
||||
$raw_diff = $call->execute();
|
||||
|
||||
$future = $workspace->execFutureLocal('patch --no-commit -');
|
||||
$future->write($raw_diff);
|
||||
$future->resolvex();
|
||||
|
||||
$workspace->reloadWorkingCopy();
|
||||
|
||||
$call = new ConduitCall(
|
||||
'differential.getcommitmessage',
|
||||
array(
|
||||
'revision_id' => $revision->getID(),
|
||||
));
|
||||
|
||||
$call->setUser($user);
|
||||
$message = $call->execute();
|
||||
|
||||
$author = id(new PhabricatorUser())->loadOneWhere(
|
||||
'phid = %s',
|
||||
$revision->getAuthorPHID());
|
||||
|
||||
$author_string = sprintf(
|
||||
'%s <%s>',
|
||||
$author->getRealName(),
|
||||
$author->loadPrimaryEmailAddress());
|
||||
$author_date = $revision->getDateCreated();
|
||||
|
||||
$workspace->execxLocal(
|
||||
'commit --date=%s --user=%s '.
|
||||
'--message=%s',
|
||||
$author_date.' 0',
|
||||
$author_string,
|
||||
$message);
|
||||
}
|
||||
|
||||
|
||||
public function pushWorkspaceRepository(
|
||||
PhabricatorRepository $repository,
|
||||
ArcanistRepositoryAPI $workspace,
|
||||
PhabricatorUser $user) {
|
||||
|
||||
$workspace->execxLocal("push -b default");
|
||||
}
|
||||
|
||||
public function createMenuItems(
|
||||
PhabricatorUser $viewer,
|
||||
DifferentialRevision $revision,
|
||||
PhabricatorRepository $repository) {
|
||||
|
||||
$vcs = $repository->getVersionControlSystem();
|
||||
if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$repository->isHosted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$can_push = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$repository,
|
||||
DiffusionCapabilityPush::CAPABILITY);
|
||||
|
||||
return $this->createActionView(
|
||||
$revision,
|
||||
pht('Land to Hosted Repository'),
|
||||
!$can_push);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue