@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.

Support Mercurial pretxnchangegroup hooks

Summary: Ref T4189. Fixes T2066. Mercurial has a //lot// of hooks so I'm not 100% sure this is all we need to install (we may need separate hooks for tags/bookmarks) but it should cover most of what we're after at least.

Test Plan:
- `bin/repository pull`'d a Mercurial repo and got a hook install.
- Pushed to a Mercurial repository over SSH and HTTP, with good/bad hooks. Saw hooks fire.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2066, T4189

Differential Revision: https://secure.phabricator.com/D7685

+65 -9
+17 -5
scripts/repository/commit_hook.php
··· 29 29 30 30 // Figure out which user is writing the commit. 31 31 32 - if ($repository->isGit()) { 32 + if ($repository->isGit() || $repository->isHg()) { 33 33 $username = getenv('PHABRICATOR_USER'); 34 34 if (!strlen($username)) { 35 35 throw new Exception(pht('usage: PHABRICATOR_USER should be defined!')); 36 36 } 37 + 38 + // TODO: If this is a Mercurial repository, the hook we're responding to 39 + // is available in $argv[2]. It's unclear if we actually need this, or if 40 + // we can block all actions we care about with just pretxnchangegroup. 41 + 37 42 } else if ($repository->isSVN()) { 38 43 // NOTE: In Subversion, the entire environment gets wiped so we can't read 39 44 // PHABRICATOR_USER. Instead, we've set "--tunnel-user" to specify the ··· 50 55 51 56 $engine->setSubversionTransactionInfo($svn_txn, $svn_repo); 52 57 } else { 53 - throw new Exceptiont(pht('Unknown repository type.')); 58 + throw new Exception(pht('Unknown repository type.')); 54 59 } 55 60 56 61 $user = id(new PhabricatorPeopleQuery()) ··· 67 72 68 73 // Read stdin for the hook engine. 69 74 70 - $stdin = @file_get_contents('php://stdin'); 71 - if ($stdin === false) { 72 - throw new Exception(pht('Failed to read stdin!')); 75 + if ($repository->isHg()) { 76 + // Mercurial leaves stdin open, so we can't just read it until EOF. 77 + $stdin = ''; 78 + } else { 79 + // Git and Subversion write data into stdin and then close it. Read the 80 + // data. 81 + $stdin = @file_get_contents('php://stdin'); 82 + if ($stdin === false) { 83 + throw new Exception(pht('Failed to read stdin!')); 84 + } 73 85 } 74 86 75 87 $engine->setStdin($stdin);
+6 -2
src/applications/diffusion/controller/DiffusionServeController.php
··· 406 406 return $user; 407 407 } 408 408 409 - private function serveMercurialRequest(PhabricatorRepository $repository) { 409 + private function serveMercurialRequest( 410 + PhabricatorRepository $repository, 411 + PhabricatorUser $viewer) { 410 412 $request = $this->getRequest(); 411 413 412 414 $bin = Filesystem::resolveBinary('hg'); ··· 414 416 throw new Exception("Unable to find `hg` in PATH!"); 415 417 } 416 418 417 - $env = array(); 419 + $env = array( 420 + 'PHABRICATOR_USER' => $viewer->getUsername(), 421 + ); 418 422 $input = PhabricatorStartup::getRawInput(); 419 423 420 424 $cmd = $request->getStr('cmd');
+10
src/applications/diffusion/engine/DiffusionCommitHookEngine.php
··· 51 51 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 52 52 $err = $this->executeSubversionHook(); 53 53 break; 54 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 55 + $err = $this->executeMercurialHook(); 56 + break; 54 57 default: 55 58 throw new Exception(pht('Unsupported repository type "%s"!', $type)); 56 59 } ··· 69 72 private function executeSubversionHook() { 70 73 71 74 // TODO: Do useful things here, too. 75 + 76 + return 0; 77 + } 78 + 79 + private function executeMercurialHook() { 80 + 81 + // TODO: Here, too, useful things should be done. 72 82 73 83 return 0; 74 84 }
+2 -1
src/applications/diffusion/ssh/DiffusionSSHMercurialServeWorkflow.php
··· 42 42 $command = csprintf('hg -R %s serve --stdio', $repository->getLocalPath()); 43 43 $command = PhabricatorDaemon::sudoCommandAsDaemonUser($command); 44 44 45 - $future = new ExecFuture('%C', $command); 45 + $future = id(new ExecFuture('%C', $command)) 46 + ->setEnv($this->getEnvironment()); 46 47 47 48 $io_channel = $this->getIOChannel(); 48 49 $protocol_channel = new DiffusionSSHMercurialWireClientProtocolChannel(
+30 -1
src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
··· 87 87 $this->installGitHook(); 88 88 } else if ($is_svn) { 89 89 $this->installSubversionHook(); 90 + } else if ($is_hg) { 91 + $this->installMercurialHook(); 90 92 } else { 91 93 $this->logPull( 92 94 pht( ··· 335 337 $path); 336 338 } else { 337 339 $repository->execxRemoteCommand( 338 - 'clone -- %s %s', 340 + 'clone --noupdate -- %s %s', 339 341 $repository->getRemoteURI(), 340 342 $path); 341 343 } ··· 380 382 throw $ex; 381 383 } 382 384 } 385 + } 386 + 387 + 388 + /** 389 + * @task hg 390 + */ 391 + private function installMercurialHook() { 392 + $repository = $this->getRepository(); 393 + $path = $repository->getLocalPath().'.hg/hgrc'; 394 + 395 + $root = dirname(phutil_get_library_root('phabricator')); 396 + $bin = $root.'/bin/commit-hook'; 397 + 398 + $data = array(); 399 + $data[] = '[hooks]'; 400 + $data[] = csprintf( 401 + 'pretxnchangegroup.phabricator = %s %s %s', 402 + $bin, 403 + $repository->getCallsign(), 404 + 'pretxnchangegroup'); 405 + $data[] = null; 406 + 407 + $data = implode("\n", $data); 408 + 409 + $this->log('%s', pht('Installing commit hook config to "%s"...', $path)); 410 + 411 + Filesystem::writeFile($path, $data); 383 412 } 384 413 385 414