1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-24 06:20:56 +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:
epriestley 2018-11-21 16:48:00 -08:00
parent c6fc05ee09
commit c86c5749ba
10 changed files with 352 additions and 34 deletions

View file

@ -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',

View file

@ -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()),
);
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

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

View file

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

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

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