1
0
Fork 0
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:
Asher Baker 2013-11-08 11:37:57 -08:00 committed by epriestley
parent 1c73d6cd06
commit d700e7f22d
5 changed files with 166 additions and 2 deletions

View file

@ -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',

View file

@ -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;
}
}

View file

@ -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.'));

View file

@ -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);
}

View file

@ -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);
}
}