Skip to content

Commit 89f9f97

Browse files
author
epriestley
committedJun 24, 2016
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
1 parent fd20b89 commit 89f9f97

File tree

4 files changed

+102
-37
lines changed

4 files changed

+102
-37
lines changed
 

‎scripts/repository/commit_hook.php

+53-1
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,62 @@
5454

5555
$engine->setRepository($repository);
5656

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());
5770

5871
// 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+
);
5977

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()) {
61113
$username = getenv(DiffusionCommitHookEngine::ENV_USER);
62114
if (!strlen($username)) {
63115
throw new Exception(

‎src/applications/diffusion/controller/DiffusionRepositoryEditDangerousController.php

+33-28
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,14 @@ public function handleRequest(AphrontRequest $request) {
1818
->getPanelURI();
1919

2020
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);
4029
}
4130

4231
if ($request->isFormPost()) {
@@ -57,18 +46,34 @@ public function handleRequest(AphrontRequest $request) {
5746

5847
if ($repository->shouldAllowDangerousChanges()) {
5948
$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+
6461
$submit = pht('Prevent Dangerous Changes');
6562
} else {
6663
$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+
}
7277
$submit = pht('Allow Dangerous Changes');
7378
}
7479

‎src/applications/repository/engine/PhabricatorRepositoryPullEngine.php

+13-4
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ private function updateRepositoryInitStatus($code, $message = null) {
191191
));
192192
}
193193

194-
private function installHook($path) {
194+
private function installHook($path, array $hook_argv = array()) {
195195
$this->log('%s', pht('Installing commit hook to "%s"...', $path));
196196

197197
$repository = $this->getRepository();
@@ -202,10 +202,11 @@ private function installHook($path) {
202202

203203
$full_php_path = Filesystem::resolveBinary('php');
204204
$cmd = csprintf(
205-
'exec %s -f %s -- %s "$@"',
205+
'exec %s -f %s -- %s %Ls "$@"',
206206
$full_php_path,
207207
$bin,
208-
$identifier);
208+
$identifier,
209+
$hook_argv);
209210

210211
$hook = "#!/bin/sh\nexport TERM=dumb\n{$cmd}\n";
211212

@@ -585,8 +586,16 @@ private function installSubversionHook() {
585586
$root = $repository->getLocalPath();
586587

587588
$path = '/hooks/pre-commit';
588-
589589
$this->installHook($root.$path);
590+
591+
$revprop_path = '/hooks/pre-revprop-change';
592+
593+
$revprop_argv = array(
594+
'--hook-mode',
595+
'svn-revprop',
596+
);
597+
598+
$this->installHook($root.$revprop_path, $revprop_argv);
590599
}
591600

592601

‎src/applications/repository/storage/PhabricatorRepository.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -1623,11 +1623,10 @@ public function canAllowDangerousChanges() {
16231623
return false;
16241624
}
16251625

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

1630-
return false;
1629+
return true;
16311630
}
16321631

16331632
public function shouldAllowDangerousChanges() {

0 commit comments

Comments
 (0)
Failed to load comments.