mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
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
This commit is contained in:
parent
fd20b89b56
commit
89f9f97159
4 changed files with 102 additions and 37 deletions
|
@ -54,10 +54,62 @@ if (!$repository->isHosted()) {
|
||||||
|
|
||||||
$engine->setRepository($repository);
|
$engine->setRepository($repository);
|
||||||
|
|
||||||
|
$args = new PhutilArgumentParser($argv);
|
||||||
|
$args->parsePartial(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'hook-mode',
|
||||||
|
'param' => 'mode',
|
||||||
|
'help' => pht('Hook execution mode.'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$argv = array_merge(
|
||||||
|
array($argv[0]),
|
||||||
|
$args->getUnconsumedArgumentVector());
|
||||||
|
|
||||||
// Figure out which user is writing the commit.
|
// Figure out which user is writing the commit.
|
||||||
|
$hook_mode = $args->getArg('hook-mode');
|
||||||
|
if ($hook_mode !== null) {
|
||||||
|
$known_modes = array(
|
||||||
|
'svn-revprop' => true,
|
||||||
|
);
|
||||||
|
|
||||||
if ($repository->isGit() || $repository->isHg()) {
|
if (empty($known_modes[$hook_mode])) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Invalid Hook Mode: This hook was invoked in "%s" mode, but this '.
|
||||||
|
'is not a recognized hook mode. Valid modes are: %s.',
|
||||||
|
$hook_mode,
|
||||||
|
implode(', ', array_keys($known_modes))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_svnrevprop = ($hook_mode == 'svn-revprop');
|
||||||
|
|
||||||
|
if ($is_svnrevprop) {
|
||||||
|
// For now, we let these through if the repository allows dangerous changes
|
||||||
|
// and prevent them if it doesn't. See T11208 for discussion.
|
||||||
|
|
||||||
|
$revprop_key = $argv[5];
|
||||||
|
|
||||||
|
if ($repository->shouldAllowDangerousChanges()) {
|
||||||
|
$err = 0;
|
||||||
|
} else {
|
||||||
|
$err = 1;
|
||||||
|
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
$console->writeErr(
|
||||||
|
pht(
|
||||||
|
"DANGEROUS CHANGE: Dangerous change protection is enabled for this ".
|
||||||
|
"repository, so you can not change revision properties (you are ".
|
||||||
|
"attempting to edit \"%s\").\n".
|
||||||
|
"Edit the repository configuration before making dangerous changes.",
|
||||||
|
$revprop_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
exit($err);
|
||||||
|
} else if ($repository->isGit() || $repository->isHg()) {
|
||||||
$username = getenv(DiffusionCommitHookEngine::ENV_USER);
|
$username = getenv(DiffusionCommitHookEngine::ENV_USER);
|
||||||
if (!strlen($username)) {
|
if (!strlen($username)) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
|
|
@ -18,25 +18,14 @@ final class DiffusionRepositoryEditDangerousController
|
||||||
->getPanelURI();
|
->getPanelURI();
|
||||||
|
|
||||||
if (!$repository->canAllowDangerousChanges()) {
|
if (!$repository->canAllowDangerousChanges()) {
|
||||||
if ($repository->isSVN()) {
|
return $this->newDialog()
|
||||||
return $this->newDialog()
|
->setTitle(pht('Unprotectable Repository'))
|
||||||
->setTitle(pht('Not in Danger'))
|
->appendParagraph(
|
||||||
->appendParagraph(
|
pht(
|
||||||
pht(
|
'This repository can not be protected from dangerous changes '.
|
||||||
'It is not possible for users to push any dangerous changes '.
|
'because Phabricator does not control what users are allowed '.
|
||||||
'to a Subversion repository. Pushes to a Subversion repository '.
|
'to push to it.'))
|
||||||
'can always be reverted and never destroy data.'))
|
->addCancelButton($panel_uri);
|
||||||
->addCancelButton($panel_uri);
|
|
||||||
} else {
|
|
||||||
return $this->newDialog()
|
|
||||||
->setTitle(pht('Unprotectable Repository'))
|
|
||||||
->appendParagraph(
|
|
||||||
pht(
|
|
||||||
'This repository can not be protected from dangerous changes '.
|
|
||||||
'because Phabricator does not control what users are allowed '.
|
|
||||||
'to push to it.'))
|
|
||||||
->addCancelButton($panel_uri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
@ -57,18 +46,34 @@ final class DiffusionRepositoryEditDangerousController
|
||||||
|
|
||||||
if ($repository->shouldAllowDangerousChanges()) {
|
if ($repository->shouldAllowDangerousChanges()) {
|
||||||
$title = pht('Prevent Dangerous Changes');
|
$title = pht('Prevent Dangerous Changes');
|
||||||
$body = pht(
|
|
||||||
'It will no longer be possible to delete branches from this '.
|
if ($repository->isSVN()) {
|
||||||
'repository, or %s push to this repository.',
|
$body = pht(
|
||||||
$force);
|
'It will no longer be possible to edit revprops in this '.
|
||||||
|
'repository.');
|
||||||
|
} else {
|
||||||
|
$body = pht(
|
||||||
|
'It will no longer be possible to delete branches from this '.
|
||||||
|
'repository, or %s push to this repository.',
|
||||||
|
$force);
|
||||||
|
}
|
||||||
|
|
||||||
$submit = pht('Prevent Dangerous Changes');
|
$submit = pht('Prevent Dangerous Changes');
|
||||||
} else {
|
} else {
|
||||||
$title = pht('Allow Dangerous Changes');
|
$title = pht('Allow Dangerous Changes');
|
||||||
$body = pht(
|
if ($repository->isSVN()) {
|
||||||
'If you allow dangerous changes, it will be possible to delete '.
|
$body = pht(
|
||||||
'branches and %s push this repository. These operations can '.
|
'If you allow dangerous changes, it will be possible to edit '.
|
||||||
'alter a repository in a way that is difficult to recover from.',
|
'reprops in this repository, including arbitrarily rewriting '.
|
||||||
$force);
|
'commit messages. These operations can alter a repository in a '.
|
||||||
|
'way that is difficult to recover from.');
|
||||||
|
} else {
|
||||||
|
$body = pht(
|
||||||
|
'If you allow dangerous changes, it will be possible to delete '.
|
||||||
|
'branches and %s push this repository. These operations can '.
|
||||||
|
'alter a repository in a way that is difficult to recover from.',
|
||||||
|
$force);
|
||||||
|
}
|
||||||
$submit = pht('Allow Dangerous Changes');
|
$submit = pht('Allow Dangerous Changes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ final class PhabricatorRepositoryPullEngine
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function installHook($path) {
|
private function installHook($path, array $hook_argv = array()) {
|
||||||
$this->log('%s', pht('Installing commit hook to "%s"...', $path));
|
$this->log('%s', pht('Installing commit hook to "%s"...', $path));
|
||||||
|
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
|
@ -202,10 +202,11 @@ final class PhabricatorRepositoryPullEngine
|
||||||
|
|
||||||
$full_php_path = Filesystem::resolveBinary('php');
|
$full_php_path = Filesystem::resolveBinary('php');
|
||||||
$cmd = csprintf(
|
$cmd = csprintf(
|
||||||
'exec %s -f %s -- %s "$@"',
|
'exec %s -f %s -- %s %Ls "$@"',
|
||||||
$full_php_path,
|
$full_php_path,
|
||||||
$bin,
|
$bin,
|
||||||
$identifier);
|
$identifier,
|
||||||
|
$hook_argv);
|
||||||
|
|
||||||
$hook = "#!/bin/sh\nexport TERM=dumb\n{$cmd}\n";
|
$hook = "#!/bin/sh\nexport TERM=dumb\n{$cmd}\n";
|
||||||
|
|
||||||
|
@ -585,8 +586,16 @@ final class PhabricatorRepositoryPullEngine
|
||||||
$root = $repository->getLocalPath();
|
$root = $repository->getLocalPath();
|
||||||
|
|
||||||
$path = '/hooks/pre-commit';
|
$path = '/hooks/pre-commit';
|
||||||
|
|
||||||
$this->installHook($root.$path);
|
$this->installHook($root.$path);
|
||||||
|
|
||||||
|
$revprop_path = '/hooks/pre-revprop-change';
|
||||||
|
|
||||||
|
$revprop_argv = array(
|
||||||
|
'--hook-mode',
|
||||||
|
'svn-revprop',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->installHook($root.$revprop_path, $revprop_argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1623,11 +1623,10 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isGit() || $this->isHg()) {
|
// In Git and Mercurial, ref deletions and rewrites are dangerous.
|
||||||
return true;
|
// In Subversion, editing revprops is dangerous.
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shouldAllowDangerousChanges() {
|
public function shouldAllowDangerousChanges() {
|
||||||
|
|
Loading…
Reference in a new issue