mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 22:10:55 +01:00
Make the repository "Filesize Limit" and "Clone/Fetch Timeout" configurable in the UI
Summary: Depends on D19830. Ref T13216. See PHI908. See PHI750. See PHI885. Allow users to configure a filesize limit, and allow them to adjust the clone/fetch timeout. Test Plan: {F6021356} - Configured a filesize limit and pushed, hit it. Made the limit larger and pushed, change went through. Reviewers: amckinley Reviewed By: amckinley Subscribers: yelirekim, PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T13216 Differential Revision: https://secure.phabricator.com/D19831
This commit is contained in:
parent
c6fc05ee09
commit
c86c5749ba
10 changed files with 352 additions and 34 deletions
|
@ -950,6 +950,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php',
|
||||
'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php',
|
||||
'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php',
|
||||
'DiffusionRepositoryLimitsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryLimitsManagementPanel.php',
|
||||
'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php',
|
||||
'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php',
|
||||
'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php',
|
||||
|
@ -4104,6 +4105,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryCommitRef' => 'applications/repository/engine/PhabricatorRepositoryCommitRef.php',
|
||||
'PhabricatorRepositoryCommitTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php',
|
||||
'PhabricatorRepositoryConfigOptions' => 'applications/repository/config/PhabricatorRepositoryConfigOptions.php',
|
||||
'PhabricatorRepositoryCopyTimeLimitTransaction' => 'applications/repository/xaction/PhabricatorRepositoryCopyTimeLimitTransaction.php',
|
||||
'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php',
|
||||
'PhabricatorRepositoryDangerousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDangerousTransaction.php',
|
||||
'PhabricatorRepositoryDefaultBranchTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDefaultBranchTransaction.php',
|
||||
|
@ -4115,6 +4117,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php',
|
||||
'PhabricatorRepositoryEnormousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryEnormousTransaction.php',
|
||||
'PhabricatorRepositoryFerretEngine' => 'applications/repository/search/PhabricatorRepositoryFerretEngine.php',
|
||||
'PhabricatorRepositoryFilesizeLimitTransaction' => 'applications/repository/xaction/PhabricatorRepositoryFilesizeLimitTransaction.php',
|
||||
'PhabricatorRepositoryFulltextEngine' => 'applications/repository/search/PhabricatorRepositoryFulltextEngine.php',
|
||||
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php',
|
||||
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php',
|
||||
|
@ -6361,6 +6364,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel',
|
||||
'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'DiffusionRepositoryLimitsManagementPanel' => 'DiffusionRepositoryManagementPanel',
|
||||
'DiffusionRepositoryListController' => 'DiffusionController',
|
||||
'DiffusionRepositoryManageController' => 'DiffusionController',
|
||||
'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController',
|
||||
|
@ -10070,6 +10074,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryCommitRef' => 'Phobject',
|
||||
'PhabricatorRepositoryCommitTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorRepositoryCopyTimeLimitTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorRepositoryDangerousTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
'PhabricatorRepositoryDefaultBranchTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
|
@ -10081,6 +10086,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorRepositoryEngine' => 'Phobject',
|
||||
'PhabricatorRepositoryEnormousTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
'PhabricatorRepositoryFerretEngine' => 'PhabricatorFerretEngine',
|
||||
'PhabricatorRepositoryFilesizeLimitTransaction' => 'PhabricatorRepositoryTransactionType',
|
||||
'PhabricatorRepositoryFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
|
||||
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
|
||||
|
|
|
@ -472,6 +472,25 @@ final class DiffusionRepositoryEditEngine
|
|||
pht('Change the push policy of the repository.'))
|
||||
->setConduitTypeDescription(pht('New policy PHID or constant.'))
|
||||
->setValue($object->getPolicy(DiffusionPushCapability::CAPABILITY)),
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('filesizeLimit')
|
||||
->setLabel(pht('Filesize Limit'))
|
||||
->setTransactionType(
|
||||
PhabricatorRepositoryFilesizeLimitTransaction::TRANSACTIONTYPE)
|
||||
->setDescription(pht('Maximum permitted file size.'))
|
||||
->setConduitDescription(pht('Change the filesize limit.'))
|
||||
->setConduitTypeDescription(pht('New repository filesize limit.'))
|
||||
->setValue($object->getFilesizeLimit()),
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('copyTimeLimit')
|
||||
->setLabel(pht('Clone/Fetch Timeout'))
|
||||
->setTransactionType(
|
||||
PhabricatorRepositoryCopyTimeLimitTransaction::TRANSACTIONTYPE)
|
||||
->setDescription(
|
||||
pht('Maximum permitted duration of internal clone/fetch.'))
|
||||
->setConduitDescription(pht('Change the copy time limit.'))
|
||||
->setConduitTypeDescription(pht('New repository copy time limit.'))
|
||||
->setValue($object->getCopyTimeLimit()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1268,9 +1268,7 @@ final class DiffusionCommitHookEngine extends Phobject {
|
|||
private function rejectOversizedFiles(array $content_updates) {
|
||||
$repository = $this->getRepository();
|
||||
|
||||
// TODO: Allow repositories to be configured for a maximum filesize.
|
||||
$limit = 0;
|
||||
|
||||
$limit = $repository->getFilesizeLimit();
|
||||
if (!$limit) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionRepositoryLimitsManagementPanel
|
||||
extends DiffusionRepositoryManagementPanel {
|
||||
|
||||
const PANELKEY = 'limits';
|
||||
|
||||
public function getManagementPanelLabel() {
|
||||
return pht('Limits');
|
||||
}
|
||||
|
||||
public function getManagementPanelOrder() {
|
||||
return 700;
|
||||
}
|
||||
|
||||
public function shouldEnableForRepository(
|
||||
PhabricatorRepository $repository) {
|
||||
return $repository->isGit();
|
||||
}
|
||||
|
||||
public function getManagementPanelIcon() {
|
||||
$repository = $this->getRepository();
|
||||
|
||||
$any_limit = false;
|
||||
|
||||
if ($repository->getFilesizeLimit()) {
|
||||
$any_limit = true;
|
||||
}
|
||||
|
||||
if ($any_limit) {
|
||||
return 'fa-signal';
|
||||
} else {
|
||||
return 'fa-signal grey';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEditEngineFieldKeys() {
|
||||
return array(
|
||||
'filesizeLimit',
|
||||
'copyTimeLimit',
|
||||
);
|
||||
}
|
||||
|
||||
public function buildManagementPanelCurtain() {
|
||||
$repository = $this->getRepository();
|
||||
$viewer = $this->getViewer();
|
||||
$action_list = $this->newActionList();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$repository,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$limits_uri = $this->getEditPageURI();
|
||||
|
||||
$action_list->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-pencil')
|
||||
->setName(pht('Edit Limits'))
|
||||
->setHref($limits_uri)
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
return $this->newCurtainView()
|
||||
->setActionList($action_list);
|
||||
}
|
||||
|
||||
public function buildManagementPanelContent() {
|
||||
$repository = $this->getRepository();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setViewer($viewer);
|
||||
|
||||
$byte_limit = $repository->getFilesizeLimit();
|
||||
if ($byte_limit) {
|
||||
$filesize_display = pht('%s Bytes', new PhutilNumber($byte_limit));
|
||||
} else {
|
||||
$filesize_display = pht('Unlimited');
|
||||
$filesize_display = phutil_tag('em', array(), $filesize_display);
|
||||
}
|
||||
|
||||
$view->addProperty(pht('Filesize Limit'), $filesize_display);
|
||||
|
||||
$copy_limit = $repository->getCopyTimeLimit();
|
||||
if ($copy_limit) {
|
||||
$copy_display = pht('%s Seconds', new PhutilNumber($copy_limit));
|
||||
} else {
|
||||
$copy_default = $repository->getDefaultCopyTimeLimit();
|
||||
$copy_display = pht(
|
||||
'Default (%s Seconds)',
|
||||
new PhutilNumber($copy_default));
|
||||
$copy_display = phutil_tag('em', array(), $copy_display);
|
||||
}
|
||||
|
||||
$view->addProperty(pht('Clone/Fetch Timeout'), $copy_display);
|
||||
|
||||
return $this->newBox(pht('Limits'), $view);
|
||||
}
|
||||
|
||||
}
|
|
@ -139,7 +139,7 @@ abstract class DiffusionCommandEngine extends Phobject {
|
|||
// to try to avoid cases where `git fetch` hangs for some reason and we're
|
||||
// left sitting with a held lock forever.
|
||||
$repository = $this->getRepository();
|
||||
$future->setTimeout($repository->getCopyTimeLimit());
|
||||
$future->setTimeout($repository->getEffectiveCopyTimeLimit());
|
||||
|
||||
return $future;
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
(string)$repository->getCloneURIObject(),
|
||||
$path);
|
||||
|
||||
$future->setTimeout($repository->getCopyTimeLimit());
|
||||
$future->setTimeout($repository->getEffectiveCopyTimeLimit());
|
||||
|
||||
$futures[$directory] = $future;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
}
|
||||
|
||||
$this->newExecvFuture($interface, $cmd, $arg)
|
||||
->setTimeout($repository->getCopyTimeLimit())
|
||||
->setTimeout($repository->getEffectiveCopyTimeLimit())
|
||||
->resolvex();
|
||||
|
||||
if (idx($spec, 'default')) {
|
||||
|
@ -310,7 +310,7 @@ final class DrydockWorkingCopyBlueprintImplementation
|
|||
|
||||
try {
|
||||
$this->newExecvFuture($interface, $cmd, $arg)
|
||||
->setTimeout($repository->getCopyTimeLimit())
|
||||
->setTimeout($repository->getEffectiveCopyTimeLimit())
|
||||
->resolvex();
|
||||
} catch (CommandException $ex) {
|
||||
$display_command = csprintf(
|
||||
|
|
|
@ -1898,9 +1898,33 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
|||
* @return int Maximum number of seconds to spend copying this repository.
|
||||
*/
|
||||
public function getCopyTimeLimit() {
|
||||
return $this->getDetail('limit.copy');
|
||||
}
|
||||
|
||||
public function setCopyTimeLimit($limit) {
|
||||
return $this->setDetail('limit.copy', $limit);
|
||||
}
|
||||
|
||||
public function getDefaultCopyTimeLimit() {
|
||||
return phutil_units('15 minutes in seconds');
|
||||
}
|
||||
|
||||
public function getEffectiveCopyTimeLimit() {
|
||||
$limit = $this->getCopyTimeLimit();
|
||||
if ($limit) {
|
||||
return $limit;
|
||||
}
|
||||
|
||||
return $this->getDefaultCopyTimeLimit();
|
||||
}
|
||||
|
||||
public function getFilesizeLimit() {
|
||||
return $this->getDetail('limit.filesize');
|
||||
}
|
||||
|
||||
public function setFilesizeLimit($limit) {
|
||||
return $this->setDetail('limit.filesize', $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the service URI for the device hosting this repository.
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryCopyTimeLimitTransaction
|
||||
extends PhabricatorRepositoryTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'limit.copy';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getCopyTimeLimit();
|
||||
}
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
if (!strlen($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = (int)$value;
|
||||
if (!$value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setCopyTimeLimit($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$old = $this->getOldValue();
|
||||
$new = $this->getNewValue();
|
||||
|
||||
if ($old && $new) {
|
||||
return pht(
|
||||
'%s changed the copy time limit for this repository from %s seconds '.
|
||||
'to %s seconds.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
} else if ($new) {
|
||||
return pht(
|
||||
'%s set the copy time limit for this repository to %s seconds.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderNewValue());
|
||||
} else {
|
||||
return pht(
|
||||
'%s reset the copy time limit (%s seconds) for this repository '.
|
||||
'to the default value.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue());
|
||||
}
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$new = $xaction->getNewValue();
|
||||
|
||||
if (!strlen($new)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!preg_match('/^\d+\z/', $new)) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'Unable to parse copy time limit, specify a positive number '.
|
||||
'of seconds.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryFilesizeLimitTransaction
|
||||
extends PhabricatorRepositoryTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'limit.filesize';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getFilesizeLimit();
|
||||
}
|
||||
|
||||
public function generateNewValue($object, $value) {
|
||||
if (!strlen($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = phutil_parse_bytes($value);
|
||||
if (!$value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setFilesizeLimit($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$old = $this->getOldValue();
|
||||
$new = $this->getNewValue();
|
||||
|
||||
if ($old && $new) {
|
||||
return pht(
|
||||
'%s changed the filesize limit for this repository from %s bytes to '.
|
||||
'%s bytes.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
} else if ($new) {
|
||||
return pht(
|
||||
'%s set the filesize limit for this repository to %s bytes.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderNewValue());
|
||||
} else {
|
||||
return pht(
|
||||
'%s removed the filesize limit (%s bytes) for this repository.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue());
|
||||
}
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$new = $xaction->getNewValue();
|
||||
|
||||
if (!strlen($new)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$value = phutil_parse_bytes($new);
|
||||
} catch (Exception $ex) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'Unable to parse filesize limit: %s',
|
||||
$ex->getMessage()),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -236,37 +236,20 @@ fetch from, serve from, and push to.
|
|||
These options are covered in detail in @{article:Diffusion User Guide: URIs}.
|
||||
|
||||
|
||||
Staging Area
|
||||
============
|
||||
|
||||
The **Staging Area** panel configures staging areas, used to make proposed
|
||||
changes available to build and continuous integration systems.
|
||||
|
||||
For more details, see @{article:Harbormaster User Guide}.
|
||||
|
||||
|
||||
Automation
|
||||
==========
|
||||
|
||||
The **Automation** panel configures support for allowing Phabricator to make
|
||||
writes directly to the repository, so that it can perform operations like
|
||||
automatically landing revisions from the web UI.
|
||||
|
||||
For details on repository automation, see
|
||||
@{article:Drydock User Guide: Repository Automation}.
|
||||
|
||||
|
||||
Symbols
|
||||
Limits
|
||||
======
|
||||
|
||||
The **Symbols** panel allows you to customize how symbols (like class and
|
||||
function names) are linked when viewing code in the repository, and when
|
||||
viewing revisions which propose code changes to the repository.
|
||||
The **Limits** panel allows you to configure limits and timeouts.
|
||||
|
||||
To take advantage of this feature, you need to do additional work to build
|
||||
symbol indexes. For details on configuring and populating symbol indexes, see
|
||||
@{article:User Guide: Symbol Indexes}.
|
||||
**Filesize Limit**: Allows you to set a maximum filesize for any file in the
|
||||
repository. If a commit creates a larger file (or modifies an existing file so
|
||||
it becomes too large) it will be rejected. This option only applies to hosted
|
||||
repositories.
|
||||
|
||||
**Clone/Fetch Timeout**: Configure the internal timeout for creating copies
|
||||
of this repository during operations like intracluster synchronization and
|
||||
Drydock working copy construction. This timeout does not affect external
|
||||
users.
|
||||
|
||||
Branches
|
||||
========
|
||||
|
@ -311,6 +294,38 @@ revisions and tasks. If you don't want Phabricator to close objects when it
|
|||
discovers new commits, disable **Autoclose** for the repository.
|
||||
|
||||
|
||||
Staging Area
|
||||
============
|
||||
|
||||
The **Staging Area** panel configures staging areas, used to make proposed
|
||||
changes available to build and continuous integration systems.
|
||||
|
||||
For more details, see @{article:Harbormaster User Guide}.
|
||||
|
||||
|
||||
Automation
|
||||
==========
|
||||
|
||||
The **Automation** panel configures support for allowing Phabricator to make
|
||||
writes directly to the repository, so that it can perform operations like
|
||||
automatically landing revisions from the web UI.
|
||||
|
||||
For details on repository automation, see
|
||||
@{article:Drydock User Guide: Repository Automation}.
|
||||
|
||||
|
||||
Symbols
|
||||
======
|
||||
|
||||
The **Symbols** panel allows you to customize how symbols (like class and
|
||||
function names) are linked when viewing code in the repository, and when
|
||||
viewing revisions which propose code changes to the repository.
|
||||
|
||||
To take advantage of this feature, you need to do additional work to build
|
||||
symbol indexes. For details on configuring and populating symbol indexes, see
|
||||
@{article:User Guide: Symbol Indexes}.
|
||||
|
||||
|
||||
Repository Identifiers and Names
|
||||
================================
|
||||
|
||||
|
|
Loading…
Reference in a new issue