Page MenuHomePhabricator

D7534.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -388,6 +388,7 @@
'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 @@
'DifferentialJIRAIssuesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener',
'DifferentialLandingToHostedGit' => 'DifferentialLandingStrategy',
+ 'DifferentialLandingToHostedMercurial' => 'DifferentialLandingStrategy',
'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLocalCommitsView' => 'AphrontView',
diff --git a/src/applications/differential/DifferentialGetWorkingCopy.php b/src/applications/differential/DifferentialGetWorkingCopy.php
--- a/src/applications/differential/DifferentialGetWorkingCopy.php
+++ b/src/applications/differential/DifferentialGetWorkingCopy.php
@@ -36,4 +36,32 @@
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;
+ }
+
}
diff --git a/src/applications/differential/controller/DifferentialRevisionLandController.php b/src/applications/differential/controller/DifferentialRevisionLandController.php
--- a/src/applications/differential/controller/DifferentialRevisionLandController.php
+++ b/src/applications/differential/controller/DifferentialRevisionLandController.php
@@ -68,7 +68,7 @@
$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.'));
diff --git a/src/applications/differential/landing/DifferentialLandingStrategy.php b/src/applications/differential/landing/DifferentialLandingStrategy.php
--- a/src/applications/differential/landing/DifferentialLandingStrategy.php
+++ b/src/applications/differential/landing/DifferentialLandingStrategy.php
@@ -35,7 +35,21 @@
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);
}
diff --git a/src/applications/differential/landing/DifferentialLandingToHostedMercurial.php b/src/applications/differential/landing/DifferentialLandingToHostedMercurial.php
new file mode 100644
--- /dev/null
+++ b/src/applications/differential/landing/DifferentialLandingToHostedMercurial.php
@@ -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);
+ }
+}

File Metadata

Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/oy/ss/vwto7mrj5zexl3aq
Default Alt Text
D7534.diff (7 KB)

Event Timeline