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

Provide basic support for Subversion revprops

Summary:
Ref T11208. See that task for a more detailed description of revprops.

This allows revprop changes in a hosted Subversion repository if the repository has the "allow dangerous changes" flag set.

In the future, we could expand this into real Herald support, but the only use case we have for now is letting `svnsync` work.

Test Plan:
Edited revprops with `svn propset --revprop -r 2 propkey propvalue repositoryuri`:

- Tried before patch, got a "configure a commit hook" error.
- Tried after patch, got a "dangerous change" error.
- Allowed dangerous changes.
- Did a revprop edit.
- Prevented dangerous changes.
- Got an error again.
- Made a normal commit to an SVN repository.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11208

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

+102 -37
+53 -1
scripts/repository/commit_hook.php
··· 54 54 55 55 $engine->setRepository($repository); 56 56 57 + $args = new PhutilArgumentParser($argv); 58 + $args->parsePartial( 59 + array( 60 + array( 61 + 'name' => 'hook-mode', 62 + 'param' => 'mode', 63 + 'help' => pht('Hook execution mode.'), 64 + ), 65 + )); 66 + 67 + $argv = array_merge( 68 + array($argv[0]), 69 + $args->getUnconsumedArgumentVector()); 57 70 58 71 // Figure out which user is writing the commit. 72 + $hook_mode = $args->getArg('hook-mode'); 73 + if ($hook_mode !== null) { 74 + $known_modes = array( 75 + 'svn-revprop' => true, 76 + ); 59 77 60 - if ($repository->isGit() || $repository->isHg()) { 78 + if (empty($known_modes[$hook_mode])) { 79 + throw new Exception( 80 + pht( 81 + 'Invalid Hook Mode: This hook was invoked in "%s" mode, but this '. 82 + 'is not a recognized hook mode. Valid modes are: %s.', 83 + $hook_mode, 84 + implode(', ', array_keys($known_modes)))); 85 + } 86 + } 87 + 88 + $is_svnrevprop = ($hook_mode == 'svn-revprop'); 89 + 90 + if ($is_svnrevprop) { 91 + // For now, we let these through if the repository allows dangerous changes 92 + // and prevent them if it doesn't. See T11208 for discussion. 93 + 94 + $revprop_key = $argv[5]; 95 + 96 + if ($repository->shouldAllowDangerousChanges()) { 97 + $err = 0; 98 + } else { 99 + $err = 1; 100 + 101 + $console = PhutilConsole::getConsole(); 102 + $console->writeErr( 103 + pht( 104 + "DANGEROUS CHANGE: Dangerous change protection is enabled for this ". 105 + "repository, so you can not change revision properties (you are ". 106 + "attempting to edit \"%s\").\n". 107 + "Edit the repository configuration before making dangerous changes.", 108 + $revprop_key)); 109 + } 110 + 111 + exit($err); 112 + } else if ($repository->isGit() || $repository->isHg()) { 61 113 $username = getenv(DiffusionCommitHookEngine::ENV_USER); 62 114 if (!strlen($username)) { 63 115 throw new Exception(
+33 -28
src/applications/diffusion/controller/DiffusionRepositoryEditDangerousController.php
··· 18 18 ->getPanelURI(); 19 19 20 20 if (!$repository->canAllowDangerousChanges()) { 21 - if ($repository->isSVN()) { 22 - return $this->newDialog() 23 - ->setTitle(pht('Not in Danger')) 24 - ->appendParagraph( 25 - pht( 26 - 'It is not possible for users to push any dangerous changes '. 27 - 'to a Subversion repository. Pushes to a Subversion repository '. 28 - 'can always be reverted and never destroy data.')) 29 - ->addCancelButton($panel_uri); 30 - } else { 31 - return $this->newDialog() 32 - ->setTitle(pht('Unprotectable Repository')) 33 - ->appendParagraph( 34 - pht( 35 - 'This repository can not be protected from dangerous changes '. 36 - 'because Phabricator does not control what users are allowed '. 37 - 'to push to it.')) 38 - ->addCancelButton($panel_uri); 39 - } 21 + return $this->newDialog() 22 + ->setTitle(pht('Unprotectable Repository')) 23 + ->appendParagraph( 24 + pht( 25 + 'This repository can not be protected from dangerous changes '. 26 + 'because Phabricator does not control what users are allowed '. 27 + 'to push to it.')) 28 + ->addCancelButton($panel_uri); 40 29 } 41 30 42 31 if ($request->isFormPost()) { ··· 57 46 58 47 if ($repository->shouldAllowDangerousChanges()) { 59 48 $title = pht('Prevent Dangerous Changes'); 60 - $body = pht( 61 - 'It will no longer be possible to delete branches from this '. 62 - 'repository, or %s push to this repository.', 63 - $force); 49 + 50 + if ($repository->isSVN()) { 51 + $body = pht( 52 + 'It will no longer be possible to edit revprops in this '. 53 + 'repository.'); 54 + } else { 55 + $body = pht( 56 + 'It will no longer be possible to delete branches from this '. 57 + 'repository, or %s push to this repository.', 58 + $force); 59 + } 60 + 64 61 $submit = pht('Prevent Dangerous Changes'); 65 62 } else { 66 63 $title = pht('Allow Dangerous Changes'); 67 - $body = pht( 68 - 'If you allow dangerous changes, it will be possible to delete '. 69 - 'branches and %s push this repository. These operations can '. 70 - 'alter a repository in a way that is difficult to recover from.', 71 - $force); 64 + if ($repository->isSVN()) { 65 + $body = pht( 66 + 'If you allow dangerous changes, it will be possible to edit '. 67 + 'reprops in this repository, including arbitrarily rewriting '. 68 + 'commit messages. These operations can alter a repository in a '. 69 + 'way that is difficult to recover from.'); 70 + } else { 71 + $body = pht( 72 + 'If you allow dangerous changes, it will be possible to delete '. 73 + 'branches and %s push this repository. These operations can '. 74 + 'alter a repository in a way that is difficult to recover from.', 75 + $force); 76 + } 72 77 $submit = pht('Allow Dangerous Changes'); 73 78 } 74 79
+13 -4
src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
··· 191 191 )); 192 192 } 193 193 194 - private function installHook($path) { 194 + private function installHook($path, array $hook_argv = array()) { 195 195 $this->log('%s', pht('Installing commit hook to "%s"...', $path)); 196 196 197 197 $repository = $this->getRepository(); ··· 202 202 203 203 $full_php_path = Filesystem::resolveBinary('php'); 204 204 $cmd = csprintf( 205 - 'exec %s -f %s -- %s "$@"', 205 + 'exec %s -f %s -- %s %Ls "$@"', 206 206 $full_php_path, 207 207 $bin, 208 - $identifier); 208 + $identifier, 209 + $hook_argv); 209 210 210 211 $hook = "#!/bin/sh\nexport TERM=dumb\n{$cmd}\n"; 211 212 ··· 585 586 $root = $repository->getLocalPath(); 586 587 587 588 $path = '/hooks/pre-commit'; 589 + $this->installHook($root.$path); 590 + 591 + $revprop_path = '/hooks/pre-revprop-change'; 588 592 589 - $this->installHook($root.$path); 593 + $revprop_argv = array( 594 + '--hook-mode', 595 + 'svn-revprop', 596 + ); 597 + 598 + $this->installHook($root.$revprop_path, $revprop_argv); 590 599 } 591 600 592 601
+3 -4
src/applications/repository/storage/PhabricatorRepository.php
··· 1623 1623 return false; 1624 1624 } 1625 1625 1626 - if ($this->isGit() || $this->isHg()) { 1627 - return true; 1628 - } 1626 + // In Git and Mercurial, ref deletions and rewrites are dangerous. 1627 + // In Subversion, editing revprops is dangerous. 1629 1628 1630 - return false; 1629 + return true; 1631 1630 } 1632 1631 1633 1632 public function shouldAllowDangerousChanges() {