@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Asher Baker and committed by
epriestley
d700e7f2 1c73d6cd

+166 -2
+2
src/__phutil_library_map__.php
··· 388 388 'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php', 389 389 'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php', 390 390 'DifferentialLandingToHostedGit' => 'applications/differential/landing/DifferentialLandingToHostedGit.php', 391 + 'DifferentialLandingToHostedMercurial' => 'applications/differential/landing/DifferentialLandingToHostedMercurial.php', 391 392 'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/DifferentialLinesFieldSpecification.php', 392 393 'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/DifferentialLintFieldSpecification.php', 393 394 'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php', ··· 2647 2648 'DifferentialJIRAIssuesFieldSpecification' => 'DifferentialFieldSpecification', 2648 2649 'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener', 2649 2650 'DifferentialLandingToHostedGit' => 'DifferentialLandingStrategy', 2651 + 'DifferentialLandingToHostedMercurial' => 'DifferentialLandingStrategy', 2650 2652 'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification', 2651 2653 'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification', 2652 2654 'DifferentialLocalCommitsView' => 'AphrontView',
+28
src/applications/differential/DifferentialGetWorkingCopy.php
··· 36 36 return $workspace; 37 37 } 38 38 39 + /** 40 + * Creates and/or cleans a workspace for the requested repo. 41 + * 42 + * return ArcanistMercurialAPI 43 + */ 44 + public static function getCleanMercurialWorkspace( 45 + PhabricatorRepository $repo) { 46 + 47 + $origin_path = $repo->getLocalPath(); 48 + 49 + $path = rtrim($origin_path, '/'); 50 + $path = $path . '__workspace'; 51 + 52 + if (!Filesystem::pathExists($path)) { 53 + $repo->execxLocalCommand( 54 + 'clone -- file://%s %s', 55 + $origin_path, 56 + $path); 57 + } 58 + 59 + $workspace = new ArcanistMercurialAPI($path); 60 + $workspace->execxLocal('pull'); 61 + $workspace->execxLocal('update --clean default'); 62 + $workspace->reloadWorkingCopy(); 63 + 64 + return $workspace; 65 + } 66 + 39 67 }
+1 -1
src/applications/differential/controller/DifferentialRevisionLandController.php
··· 68 68 $prompt = hsprintf('%s<br><br>%s', 69 69 pht( 70 70 'This will squash and rebase revision %s, and push it to '. 71 - 'origin/master.', 71 + 'the default / master branch.', 72 72 $revision_id), 73 73 pht('It is an experimental feature and may not work.')); 74 74
+15 -1
src/applications/differential/landing/DifferentialLandingStrategy.php
··· 35 35 try { 36 36 return DifferentialGetWorkingCopy::getCleanGitWorkspace($repository); 37 37 } catch (Exception $e) { 38 - throw new PhutilProxyException ( 38 + throw new PhutilProxyException( 39 + 'Failed to allocate a workspace', 40 + $e); 41 + } 42 + } 43 + 44 + /** 45 + * might break if repository is not Mercurial. 46 + */ 47 + protected function getMercurialWorkspace(PhabricatorRepository $repository) { 48 + try { 49 + return DifferentialGetWorkingCopy::getCleanMercurialWorkspace( 50 + $repository); 51 + } catch (Exception $e) { 52 + throw new PhutilProxyException( 39 53 'Failed to allocate a workspace', 40 54 $e); 41 55 }
+120
src/applications/differential/landing/DifferentialLandingToHostedMercurial.php
··· 1 + <?php 2 + 3 + final class DifferentialLandingToHostedMercurial 4 + extends DifferentialLandingStrategy { 5 + 6 + public function processLandRequest( 7 + AphrontRequest $request, 8 + DifferentialRevision $revision, 9 + PhabricatorRepository $repository) { 10 + 11 + $viewer = $request->getUser(); 12 + 13 + $workspace = $this->getMercurialWorkspace($repository); 14 + 15 + try { 16 + $this->commitRevisionToWorkspace( 17 + $revision, 18 + $workspace, 19 + $viewer); 20 + } catch (Exception $e) { 21 + throw new PhutilProxyException( 22 + 'Failed to commit patch', 23 + $e); 24 + } 25 + 26 + try { 27 + $this->pushWorkspaceRepository( 28 + $repository, 29 + $workspace, 30 + $viewer); 31 + } catch (Exception $e) { 32 + throw new PhutilProxyException( 33 + 'Failed to push changes upstream', 34 + $e); 35 + } 36 + } 37 + 38 + public function commitRevisionToWorkspace( 39 + DifferentialRevision $revision, 40 + ArcanistRepositoryAPI $workspace, 41 + PhabricatorUser $user) { 42 + 43 + $diff_id = $revision->loadActiveDiff()->getID(); 44 + 45 + $call = new ConduitCall( 46 + 'differential.getrawdiff', 47 + array( 48 + 'diffID' => $diff_id, 49 + )); 50 + 51 + $call->setUser($user); 52 + $raw_diff = $call->execute(); 53 + 54 + $future = $workspace->execFutureLocal('patch --no-commit -'); 55 + $future->write($raw_diff); 56 + $future->resolvex(); 57 + 58 + $workspace->reloadWorkingCopy(); 59 + 60 + $call = new ConduitCall( 61 + 'differential.getcommitmessage', 62 + array( 63 + 'revision_id' => $revision->getID(), 64 + )); 65 + 66 + $call->setUser($user); 67 + $message = $call->execute(); 68 + 69 + $author = id(new PhabricatorUser())->loadOneWhere( 70 + 'phid = %s', 71 + $revision->getAuthorPHID()); 72 + 73 + $author_string = sprintf( 74 + '%s <%s>', 75 + $author->getRealName(), 76 + $author->loadPrimaryEmailAddress()); 77 + $author_date = $revision->getDateCreated(); 78 + 79 + $workspace->execxLocal( 80 + 'commit --date=%s --user=%s '. 81 + '--message=%s', 82 + $author_date.' 0', 83 + $author_string, 84 + $message); 85 + } 86 + 87 + 88 + public function pushWorkspaceRepository( 89 + PhabricatorRepository $repository, 90 + ArcanistRepositoryAPI $workspace, 91 + PhabricatorUser $user) { 92 + 93 + $workspace->execxLocal("push -b default"); 94 + } 95 + 96 + public function createMenuItems( 97 + PhabricatorUser $viewer, 98 + DifferentialRevision $revision, 99 + PhabricatorRepository $repository) { 100 + 101 + $vcs = $repository->getVersionControlSystem(); 102 + if ($vcs !== PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL) { 103 + return; 104 + } 105 + 106 + if (!$repository->isHosted()) { 107 + return; 108 + } 109 + 110 + $can_push = PhabricatorPolicyFilter::hasCapability( 111 + $viewer, 112 + $repository, 113 + DiffusionCapabilityPush::CAPABILITY); 114 + 115 + return $this->createActionView( 116 + $revision, 117 + pht('Land to Hosted Repository'), 118 + !$can_push); 119 + } 120 + }