mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-24 04:29:04 +01:00
(stable) Promote 2021 Week 4
This commit is contained in:
commit
498fcd34ac
44 changed files with 772 additions and 341 deletions
|
@ -1430,12 +1430,16 @@ phutil_register_library_map(array(
|
||||||
'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php',
|
'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php',
|
||||||
'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php',
|
'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php',
|
||||||
'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php',
|
'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php',
|
||||||
|
'HarbormasterBuildStepEditAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildStepEditAPIMethod.php',
|
||||||
|
'HarbormasterBuildStepEditEngine' => 'applications/harbormaster/editor/HarbormasterBuildStepEditEngine.php',
|
||||||
'HarbormasterBuildStepEditor' => 'applications/harbormaster/editor/HarbormasterBuildStepEditor.php',
|
'HarbormasterBuildStepEditor' => 'applications/harbormaster/editor/HarbormasterBuildStepEditor.php',
|
||||||
'HarbormasterBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php',
|
'HarbormasterBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php',
|
||||||
'HarbormasterBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterBuildStepImplementation.php',
|
'HarbormasterBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterBuildStepImplementation.php',
|
||||||
'HarbormasterBuildStepImplementationTestCase' => 'applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php',
|
'HarbormasterBuildStepImplementationTestCase' => 'applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php',
|
||||||
'HarbormasterBuildStepPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php',
|
'HarbormasterBuildStepPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php',
|
||||||
'HarbormasterBuildStepQuery' => 'applications/harbormaster/query/HarbormasterBuildStepQuery.php',
|
'HarbormasterBuildStepQuery' => 'applications/harbormaster/query/HarbormasterBuildStepQuery.php',
|
||||||
|
'HarbormasterBuildStepSearchAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildStepSearchAPIMethod.php',
|
||||||
|
'HarbormasterBuildStepSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildStepSearchEngine.php',
|
||||||
'HarbormasterBuildStepTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php',
|
'HarbormasterBuildStepTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php',
|
||||||
'HarbormasterBuildStepTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildStepTransactionQuery.php',
|
'HarbormasterBuildStepTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildStepTransactionQuery.php',
|
||||||
'HarbormasterBuildTarget' => 'applications/harbormaster/storage/build/HarbormasterBuildTarget.php',
|
'HarbormasterBuildTarget' => 'applications/harbormaster/storage/build/HarbormasterBuildTarget.php',
|
||||||
|
@ -7627,18 +7631,23 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationTransactionInterface',
|
'PhabricatorApplicationTransactionInterface',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorCustomFieldInterface',
|
'PhabricatorCustomFieldInterface',
|
||||||
|
'PhabricatorConduitResultInterface',
|
||||||
),
|
),
|
||||||
'HarbormasterBuildStepCoreCustomField' => array(
|
'HarbormasterBuildStepCoreCustomField' => array(
|
||||||
'HarbormasterBuildStepCustomField',
|
'HarbormasterBuildStepCustomField',
|
||||||
'PhabricatorStandardCustomFieldInterface',
|
'PhabricatorStandardCustomFieldInterface',
|
||||||
),
|
),
|
||||||
'HarbormasterBuildStepCustomField' => 'PhabricatorCustomField',
|
'HarbormasterBuildStepCustomField' => 'PhabricatorCustomField',
|
||||||
|
'HarbormasterBuildStepEditAPIMethod' => 'PhabricatorEditEngineAPIMethod',
|
||||||
|
'HarbormasterBuildStepEditEngine' => 'PhabricatorEditEngine',
|
||||||
'HarbormasterBuildStepEditor' => 'PhabricatorApplicationTransactionEditor',
|
'HarbormasterBuildStepEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'HarbormasterBuildStepGroup' => 'Phobject',
|
'HarbormasterBuildStepGroup' => 'Phobject',
|
||||||
'HarbormasterBuildStepImplementation' => 'Phobject',
|
'HarbormasterBuildStepImplementation' => 'Phobject',
|
||||||
'HarbormasterBuildStepImplementationTestCase' => 'PhabricatorTestCase',
|
'HarbormasterBuildStepImplementationTestCase' => 'PhabricatorTestCase',
|
||||||
'HarbormasterBuildStepPHIDType' => 'PhabricatorPHIDType',
|
'HarbormasterBuildStepPHIDType' => 'PhabricatorPHIDType',
|
||||||
'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
|
'HarbormasterBuildStepSearchAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||||
|
'HarbormasterBuildStepSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'HarbormasterBuildStepTransaction' => 'PhabricatorApplicationTransaction',
|
'HarbormasterBuildStepTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'HarbormasterBuildStepTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'HarbormasterBuildStepTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'HarbormasterBuildTarget' => array(
|
'HarbormasterBuildTarget' => array(
|
||||||
|
|
|
@ -176,7 +176,7 @@ final class AphrontApplicationConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
$host = AphrontRequest::getHTTPHeader('Host');
|
$host = AphrontRequest::getHTTPHeader('Host');
|
||||||
$path = $_REQUEST['__path__'];
|
$path = PhabricatorStartup::getRequestPath();
|
||||||
|
|
||||||
$application = new self();
|
$application = new self();
|
||||||
|
|
||||||
|
@ -759,7 +759,7 @@ final class AphrontApplicationConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function newSelfCheckResponse() {
|
private static function newSelfCheckResponse() {
|
||||||
$path = idx($_REQUEST, '__path__', '');
|
$path = PhabricatorStartup::getRequestPath();
|
||||||
$query = idx($_SERVER, 'QUERY_STRING', '');
|
$query = idx($_SERVER, 'QUERY_STRING', '');
|
||||||
|
|
||||||
$pairs = id(new PhutilQueryStringParser())
|
$pairs = id(new PhutilQueryStringParser())
|
||||||
|
|
|
@ -54,8 +54,8 @@ final class PhabricatorCommitSearchEngine
|
||||||
$query->withUnreachable($map['unreachable']);
|
$query->withUnreachable($map['unreachable']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($map['unpublished'] !== null) {
|
if ($map['permanent'] !== null) {
|
||||||
$query->withUnpublished($map['unpublished']);
|
$query->withPermanent($map['permanent']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($map['ancestorsOf']) {
|
if ($map['ancestorsOf']) {
|
||||||
|
@ -132,15 +132,15 @@ final class PhabricatorCommitSearchEngine
|
||||||
'Find or exclude unreachable commits which are not ancestors of '.
|
'Find or exclude unreachable commits which are not ancestors of '.
|
||||||
'any branch, tag, or ref.')),
|
'any branch, tag, or ref.')),
|
||||||
id(new PhabricatorSearchThreeStateField())
|
id(new PhabricatorSearchThreeStateField())
|
||||||
->setLabel(pht('Unpublished'))
|
->setLabel(pht('Permanent'))
|
||||||
->setKey('unpublished')
|
->setKey('permanent')
|
||||||
->setOptions(
|
->setOptions(
|
||||||
pht('(Show All)'),
|
pht('(Show All)'),
|
||||||
pht('Show Only Unpublished Commits'),
|
pht('Show Only Permanent Commits'),
|
||||||
pht('Hide Unpublished Commits'))
|
pht('Hide Permanent Commits'))
|
||||||
->setDescription(
|
->setDescription(
|
||||||
pht(
|
pht(
|
||||||
'Find or exclude unpublished commits which are not ancestors of '.
|
'Find or exclude permanent commits which are ancestors of '.
|
||||||
'any permanent branch, tag, or ref.')),
|
'any permanent branch, tag, or ref.')),
|
||||||
id(new PhabricatorSearchStringListField())
|
id(new PhabricatorSearchStringListField())
|
||||||
->setLabel(pht('Ancestors Of'))
|
->setLabel(pht('Ancestors Of'))
|
||||||
|
|
|
@ -181,6 +181,12 @@ final class PhabricatorAuthPasswordEngine
|
||||||
$normal_password = phutil_utf8_strtolower($raw_password);
|
$normal_password = phutil_utf8_strtolower($raw_password);
|
||||||
if (strlen($normal_password) >= $minimum_similarity) {
|
if (strlen($normal_password) >= $minimum_similarity) {
|
||||||
foreach ($normal_map as $term => $source) {
|
foreach ($normal_map as $term => $source) {
|
||||||
|
|
||||||
|
// See T2312. This may be required if the term list includes numeric
|
||||||
|
// strings like "12345", which will be cast to integers when used as
|
||||||
|
// array keys.
|
||||||
|
$term = phutil_string_cast($term);
|
||||||
|
|
||||||
if (strpos($term, $normal_password) === false &&
|
if (strpos($term, $normal_password) === false &&
|
||||||
strpos($normal_password, $term) === false) {
|
strpos($normal_password, $term) === false) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -169,7 +169,21 @@ EOREMARKUP
|
||||||
'Maniphest. If you\'d prefer more traditional UI strings like '.
|
'Maniphest. If you\'d prefer more traditional UI strings like '.
|
||||||
'"Add Comment", you can set this flag to disable most of the '.
|
'"Add Comment", you can set this flag to disable most of the '.
|
||||||
'extra flavor.')),
|
'extra flavor.')),
|
||||||
$this->newOption('remarkup.ignored-object-names', 'string', '/^(Q|V)\d$/')
|
$this->newOption(
|
||||||
|
'remarkup.ignored-object-names',
|
||||||
|
'string',
|
||||||
|
|
||||||
|
// Q1, Q2, etc., are common abbreviations for "Quarter".
|
||||||
|
// V1, V2, etc., are common abbreviations for "Version".
|
||||||
|
// P1, P2, etc., are common abbreviations for "Priority".
|
||||||
|
|
||||||
|
// M1 is a computer chip manufactured by Apple.
|
||||||
|
// M2 (commonly spelled "M.2") is an expansion slot on motherboards.
|
||||||
|
// M4 is a carbine.
|
||||||
|
// M8 is a phonetic spelling of "mate", used in culturally significant
|
||||||
|
// copypasta about navy seals.
|
||||||
|
|
||||||
|
'/^(Q|V|M|P)\d$/')
|
||||||
->setSummary(
|
->setSummary(
|
||||||
pht('Text values that match this regex and are also object names '.
|
pht('Text values that match this regex and are also object names '.
|
||||||
'will not be linked.'))
|
'will not be linked.'))
|
||||||
|
|
|
@ -35,22 +35,26 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
protected function getGitResult(ConduitAPIRequest $request) {
|
protected function getGitResult(ConduitAPIRequest $request) {
|
||||||
$drequest = $this->getDiffusionRequest();
|
$drequest = $this->getDiffusionRequest();
|
||||||
$repository = $drequest->getRepository();
|
$repository = $drequest->getRepository();
|
||||||
|
|
||||||
$path = $request->getValue('path');
|
$path = $request->getValue('path');
|
||||||
|
if (!strlen($path)) {
|
||||||
|
$path = null;
|
||||||
|
}
|
||||||
|
|
||||||
$commit = $request->getValue('commit');
|
$commit = $request->getValue('commit');
|
||||||
$offset = (int)$request->getValue('offset');
|
$offset = (int)$request->getValue('offset');
|
||||||
$limit = (int)$request->getValue('limit');
|
$limit = (int)$request->getValue('limit');
|
||||||
$result = $this->getEmptyResultSet();
|
$result = $this->getEmptyResultSet();
|
||||||
|
|
||||||
if ($path == '') {
|
if ($path === null) {
|
||||||
// Fast path to improve the performance of the repository view; we know
|
// Fast path to improve the performance of the repository view; we know
|
||||||
// the root is always a tree at any commit and always exists.
|
// the root is always a tree at any commit and always exists.
|
||||||
$stdout = 'tree';
|
$stdout = 'tree';
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
'cat-file -t %s:%s',
|
'cat-file -t -- %s',
|
||||||
$commit,
|
sprintf('%s:%s', $commit, $path));
|
||||||
$path);
|
|
||||||
} catch (CommandException $e) {
|
} catch (CommandException $e) {
|
||||||
// The "cat-file" command may fail if the path legitimately does not
|
// The "cat-file" command may fail if the path legitimately does not
|
||||||
// exist, but it may also fail if the path is a submodule. This can
|
// exist, but it may also fail if the path is a submodule. This can
|
||||||
|
@ -62,7 +66,7 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
|
|
||||||
list($sub_err, $sub_stdout) = $repository->execLocalCommand(
|
list($sub_err, $sub_stdout) = $repository->execLocalCommand(
|
||||||
'ls-tree %s -- %s',
|
'ls-tree %s -- %s',
|
||||||
$commit,
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
if (!$sub_err) {
|
if (!$sub_err) {
|
||||||
// If the path failed "cat-file" but "ls-tree" worked, we assume it
|
// If the path failed "cat-file" but "ls-tree" worked, we assume it
|
||||||
|
@ -86,8 +90,9 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
if (preg_match('/^fatal: Not a valid object name/', $stderr)) {
|
if (preg_match('/^fatal: Not a valid object name/', $stderr)) {
|
||||||
// Grab two logs, since the first one is when the object was deleted.
|
// Grab two logs, since the first one is when the object was deleted.
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
'log -n2 --format="%%H" %s -- %s',
|
'log -n2 %s %s -- %s',
|
||||||
$commit,
|
'--format=%H',
|
||||||
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
$stdout = trim($stdout);
|
$stdout = trim($stdout);
|
||||||
if ($stdout) {
|
if ($stdout) {
|
||||||
|
@ -120,14 +125,20 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
if ($path === null) {
|
||||||
'ls-tree -z -l %s:%s',
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
$commit,
|
'ls-tree -z -l %s --',
|
||||||
$path);
|
gitsprintf('%s', $commit));
|
||||||
|
} else {
|
||||||
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
|
'ls-tree -z -l %s -- %s',
|
||||||
|
gitsprintf('%s', $commit),
|
||||||
|
$path);
|
||||||
|
}
|
||||||
|
|
||||||
$submodules = array();
|
$submodules = array();
|
||||||
|
|
||||||
if (strlen($path)) {
|
if ($path !== null) {
|
||||||
$prefix = rtrim($path, '/').'/';
|
$prefix = rtrim($path, '/').'/';
|
||||||
} else {
|
} else {
|
||||||
$prefix = '';
|
$prefix = '';
|
||||||
|
@ -207,7 +218,7 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
// the wild.
|
// the wild.
|
||||||
|
|
||||||
list($err, $contents) = $repository->execLocalCommand(
|
list($err, $contents) = $repository->execLocalCommand(
|
||||||
'cat-file blob %s:.gitmodules',
|
'cat-file blob -- %s:.gitmodules',
|
||||||
$commit);
|
$commit);
|
||||||
|
|
||||||
if (!$err) {
|
if (!$err) {
|
||||||
|
@ -225,8 +236,8 @@ final class DiffusionBrowseQueryConduitAPIMethod
|
||||||
$dict[$key] = $value;
|
$dict[$key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($submodules as $path) {
|
foreach ($submodules as $submodule_path) {
|
||||||
$full_path = $path->getFullPath();
|
$full_path = $submodule_path->getFullPath();
|
||||||
$key = 'submodule.'.$full_path.'.url';
|
$key = 'submodule.'.$full_path.'.url';
|
||||||
if (isset($dict[$key])) {
|
if (isset($dict[$key])) {
|
||||||
$path->setExternalURI($dict[$key]);
|
$path->setExternalURI($dict[$key]);
|
||||||
|
|
|
@ -25,7 +25,7 @@ final class DiffusionExistsQueryConduitAPIMethod
|
||||||
$repository = $this->getDiffusionRequest()->getRepository();
|
$repository = $this->getDiffusionRequest()->getRepository();
|
||||||
$commit = $request->getValue('commit');
|
$commit = $request->getValue('commit');
|
||||||
list($err, $merge_base) = $repository->execLocalCommand(
|
list($err, $merge_base) = $repository->execLocalCommand(
|
||||||
'cat-file -t %s',
|
'cat-file -t -- %s',
|
||||||
$commit);
|
$commit);
|
||||||
return !$err;
|
return !$err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,12 @@ final class DiffusionHistoryQueryConduitAPIMethod
|
||||||
$repository = $drequest->getRepository();
|
$repository = $drequest->getRepository();
|
||||||
$commit_hash = $request->getValue('commit');
|
$commit_hash = $request->getValue('commit');
|
||||||
$against_hash = $request->getValue('against');
|
$against_hash = $request->getValue('against');
|
||||||
|
|
||||||
$path = $request->getValue('path');
|
$path = $request->getValue('path');
|
||||||
|
if (!strlen($path)) {
|
||||||
|
$path = null;
|
||||||
|
}
|
||||||
|
|
||||||
$offset = $request->getValue('offset');
|
$offset = $request->getValue('offset');
|
||||||
$limit = $request->getValue('limit');
|
$limit = $request->getValue('limit');
|
||||||
|
|
||||||
|
@ -55,18 +60,27 @@ final class DiffusionHistoryQueryConduitAPIMethod
|
||||||
$commit_range = $commit_hash;
|
$commit_range = $commit_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$argv = array();
|
||||||
|
|
||||||
|
$argv[] = '--skip';
|
||||||
|
$argv[] = $offset;
|
||||||
|
|
||||||
|
$argv[] = '--max-count';
|
||||||
|
$argv[] = $limit;
|
||||||
|
|
||||||
|
$argv[] = '--format=%H:%P';
|
||||||
|
|
||||||
|
$argv[] = gitsprintf('%s', $commit_range);
|
||||||
|
|
||||||
|
$argv[] = '--';
|
||||||
|
|
||||||
|
if ($path !== null) {
|
||||||
|
$argv[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
'log '.
|
'log %Ls',
|
||||||
'--skip=%d '.
|
$argv);
|
||||||
'-n %d '.
|
|
||||||
'--pretty=format:%s '.
|
|
||||||
'%s -- %C',
|
|
||||||
$offset,
|
|
||||||
$limit,
|
|
||||||
'%H:%P',
|
|
||||||
$commit_range,
|
|
||||||
// Git omits merge commits if the path is provided, even if it is empty.
|
|
||||||
(strlen($path) ? csprintf('%s', $path) : ''));
|
|
||||||
|
|
||||||
$lines = explode("\n", trim($stdout));
|
$lines = explode("\n", trim($stdout));
|
||||||
$lines = array_filter($lines);
|
$lines = array_filter($lines);
|
||||||
|
|
|
@ -43,9 +43,9 @@ final class DiffusionInternalGitRawDiffQueryConduitAPIMethod
|
||||||
// it requires the commit to have a parent that we can diff against. The
|
// it requires the commit to have a parent that we can diff against. The
|
||||||
// first commit doesn't, so "commit^" is not a valid ref.
|
// first commit doesn't, so "commit^" is not a valid ref.
|
||||||
list($parents) = $repository->execxLocalCommand(
|
list($parents) = $repository->execxLocalCommand(
|
||||||
'log -n1 --format=%s %s',
|
'log -n1 %s %s --',
|
||||||
'%P',
|
'--format=%P',
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
$use_log = !strlen(trim($parents));
|
$use_log = !strlen(trim($parents));
|
||||||
|
|
||||||
// First, get a fast raw diff without "--find-copies-harder". This flag
|
// First, get a fast raw diff without "--find-copies-harder". This flag
|
||||||
|
@ -96,18 +96,18 @@ final class DiffusionInternalGitRawDiffQueryConduitAPIMethod
|
||||||
// NOTE: "--pretty=format: " is to disable diff output, we only want the
|
// NOTE: "--pretty=format: " is to disable diff output, we only want the
|
||||||
// part we get from "--raw".
|
// part we get from "--raw".
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'log %Ls --pretty=format: %s',
|
'log %Ls --pretty=format: %s --',
|
||||||
$flags,
|
$flags,
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we can use "diff", which will give us output for merges.
|
// Otherwise, we can use "diff", which will give us output for merges.
|
||||||
// We diff against the first parent, as this is generally the expectation
|
// We diff against the first parent, as this is generally the expectation
|
||||||
// and results in sensible behavior.
|
// and results in sensible behavior.
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'diff %Ls %s^1 %s',
|
'diff %Ls %s %s --',
|
||||||
$flags,
|
$flags,
|
||||||
$commit,
|
gitsprintf('%s^1', $commit),
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't spend more than 30 seconds generating the slower output.
|
// Don't spend more than 30 seconds generating the slower output.
|
||||||
|
|
|
@ -33,8 +33,9 @@ final class DiffusionLastModifiedQueryConduitAPIMethod
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
list($hash) = $repository->execxLocalCommand(
|
list($hash) = $repository->execxLocalCommand(
|
||||||
'log -n1 --format=%%H %s -- %s',
|
'log -n1 %s %s -- %s',
|
||||||
$commit,
|
'--format=%H',
|
||||||
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
$results[$path] = trim($hash);
|
$results[$path] = trim($hash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,9 @@ final class DiffusionMergedCommitsQueryConduitAPIMethod
|
||||||
$limit = $this->getLimit($request);
|
$limit = $this->getLimit($request);
|
||||||
|
|
||||||
list($parents) = $repository->execxLocalCommand(
|
list($parents) = $repository->execxLocalCommand(
|
||||||
'log -n 1 --format=%s %s',
|
'log -n 1 %s %s --',
|
||||||
'%P',
|
'--format=%P',
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
|
|
||||||
$parents = preg_split('/\s+/', trim($parents));
|
$parents = preg_split('/\s+/', trim($parents));
|
||||||
if (count($parents) < 2) {
|
if (count($parents) < 2) {
|
||||||
|
@ -50,12 +50,12 @@ final class DiffusionMergedCommitsQueryConduitAPIMethod
|
||||||
|
|
||||||
$first_parent = head($parents);
|
$first_parent = head($parents);
|
||||||
list($logs) = $repository->execxLocalCommand(
|
list($logs) = $repository->execxLocalCommand(
|
||||||
'log -n %d --format=%s %s %s --',
|
'log -n %d %s %s %s --',
|
||||||
// NOTE: "+ 1" accounts for the merge commit itself.
|
// NOTE: "+ 1" accounts for the merge commit itself.
|
||||||
$limit + 1,
|
$limit + 1,
|
||||||
'%H',
|
'--format=%H',
|
||||||
$commit,
|
gitsprintf('%s', $commit),
|
||||||
'^'.$first_parent);
|
gitsprintf('%s', '^'.$first_parent));
|
||||||
|
|
||||||
$hashes = explode("\n", trim($logs));
|
$hashes = explode("\n", trim($logs));
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ final class DiffusionQueryPathsConduitAPIMethod
|
||||||
|
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'ls-tree --name-only -r -z %s -- %s',
|
'ls-tree --name-only -r -z %s -- %s',
|
||||||
$commit,
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
|
|
||||||
$lines = id(new LinesOfALargeExecFuture($future))->setDelimiter("\0");
|
$lines = id(new LinesOfALargeExecFuture($future))->setDelimiter("\0");
|
||||||
|
|
|
@ -28,9 +28,9 @@ final class DiffusionRefsQueryConduitAPIMethod
|
||||||
$commit = $request->getValue('commit');
|
$commit = $request->getValue('commit');
|
||||||
|
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
'log --format=%s -n 1 %s --',
|
'log -n 1 %s %s --',
|
||||||
'%d',
|
'--format=%d',
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
|
|
||||||
// %d, gives a weird output format
|
// %d, gives a weird output format
|
||||||
// similar to (remote/one, remote/two, remote/three)
|
// similar to (remote/one, remote/two, remote/three)
|
||||||
|
|
|
@ -64,7 +64,7 @@ final class DiffusionSearchQueryConduitAPIMethod
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
// NOTE: --perl-regexp is available only with libpcre compiled in.
|
// NOTE: --perl-regexp is available only with libpcre compiled in.
|
||||||
'grep --extended-regexp --null -n --no-color -f - %s -- %s',
|
'grep --extended-regexp --null -n --no-color -f - %s -- %s',
|
||||||
$drequest->getStableCommit(),
|
gitsprintf('%s', $drequest->getStableCommit()),
|
||||||
$path);
|
$path);
|
||||||
|
|
||||||
// NOTE: We're writing the pattern on stdin to avoid issues with UTF8
|
// NOTE: We're writing the pattern on stdin to avoid issues with UTF8
|
||||||
|
|
|
@ -922,18 +922,26 @@ final class DiffusionServeController extends DiffusionController {
|
||||||
// This is a pretty funky fix: it would be nice to more precisely detect
|
// This is a pretty funky fix: it would be nice to more precisely detect
|
||||||
// that a request is a `--depth N` clone request, but we don't have any code
|
// that a request is a `--depth N` clone request, but we don't have any code
|
||||||
// to decode protocol frames yet. Instead, look for reasonable evidence
|
// to decode protocol frames yet. Instead, look for reasonable evidence
|
||||||
// in the error and output that we're looking at a `--depth` clone.
|
// in the output that we're looking at a `--depth` clone.
|
||||||
|
|
||||||
// For evidence this isn't completely crazy, see:
|
// A valid x-git-upload-pack-result response during packfile negotiation
|
||||||
// https://github.com/schacon/grack/pull/7
|
// should end with a flush packet ("0000"). As long as that packet
|
||||||
|
// terminates the response body in the response, we'll assume the response
|
||||||
|
// is correct and complete.
|
||||||
|
|
||||||
|
// See https://git-scm.com/docs/pack-protocol#_packfile_negotiation
|
||||||
|
|
||||||
$stdout_regexp = '(^Content-Type: application/x-git-upload-pack-result)m';
|
$stdout_regexp = '(^Content-Type: application/x-git-upload-pack-result)m';
|
||||||
$stderr_regexp = '(The remote end hung up unexpectedly)';
|
|
||||||
|
|
||||||
$has_pack = preg_match($stdout_regexp, $stdout);
|
$has_pack = preg_match($stdout_regexp, $stdout);
|
||||||
$is_hangup = preg_match($stderr_regexp, $stderr);
|
|
||||||
|
|
||||||
return $has_pack && $is_hangup;
|
if (strlen($stdout) >= 4) {
|
||||||
|
$has_flush_packet = (substr($stdout, -4) === "0000");
|
||||||
|
} else {
|
||||||
|
$has_flush_packet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($has_pack && $has_flush_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCommonEnvironment(PhabricatorUser $viewer) {
|
private function getCommonEnvironment(PhabricatorUser $viewer) {
|
||||||
|
|
|
@ -608,9 +608,9 @@ final class DiffusionCommitHookEngine extends Phobject {
|
||||||
// repository. Particularly, this will cover the cases of a new branch, a
|
// repository. Particularly, this will cover the cases of a new branch, a
|
||||||
// completely moved tag, etc.
|
// completely moved tag, etc.
|
||||||
$futures[$key] = $this->getRepository()->getLocalCommandFuture(
|
$futures[$key] = $this->getRepository()->getLocalCommandFuture(
|
||||||
'log --format=%s %s --not --all',
|
'log %s %s --not --all --',
|
||||||
'%H',
|
'--format=%H',
|
||||||
$ref_update->getRefNew());
|
gitsprintf('%s', $ref_update->getRefNew()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$content_updates = array();
|
$content_updates = array();
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class DiffusionCommitQuery
|
||||||
private $statuses;
|
private $statuses;
|
||||||
private $packagePHIDs;
|
private $packagePHIDs;
|
||||||
private $unreachable;
|
private $unreachable;
|
||||||
private $unpublished;
|
private $permanent;
|
||||||
|
|
||||||
private $needAuditRequests;
|
private $needAuditRequests;
|
||||||
private $needAuditAuthority;
|
private $needAuditAuthority;
|
||||||
|
@ -154,8 +154,8 @@ final class DiffusionCommitQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function withUnpublished($unpublished) {
|
public function withPermanent($permanent) {
|
||||||
$this->unpublished = $unpublished;
|
$this->permanent = $permanent;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,18 +859,18 @@ final class DiffusionCommitQuery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->unpublished !== null) {
|
if ($this->permanent !== null) {
|
||||||
if ($this->unpublished) {
|
if ($this->permanent) {
|
||||||
$where[] = qsprintf(
|
|
||||||
$conn,
|
|
||||||
'(commit.importStatus & %d) = 0',
|
|
||||||
PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE);
|
|
||||||
} else {
|
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'(commit.importStatus & %d) = %d',
|
'(commit.importStatus & %d) = %d',
|
||||||
PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE,
|
PhabricatorRepositoryCommit::IMPORTED_PERMANENT,
|
||||||
PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE);
|
PhabricatorRepositoryCommit::IMPORTED_PERMANENT);
|
||||||
|
} else {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'(commit.importStatus & %d) = 0',
|
||||||
|
PhabricatorRepositoryCommit::IMPORTED_PERMANENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ final class DiffusionGitBlameQuery extends DiffusionBlameQuery {
|
||||||
|
|
||||||
return $repository->getLocalCommandFuture(
|
return $repository->getLocalCommandFuture(
|
||||||
'--no-pager blame --root -s -l %s -- %s',
|
'--no-pager blame --root -s -l %s -- %s',
|
||||||
$commit,
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,8 @@ final class DiffusionGitFileContentQuery extends DiffusionFileContentQuery {
|
||||||
$commit = $drequest->getCommit();
|
$commit = $drequest->getCommit();
|
||||||
|
|
||||||
return $repository->getLocalCommandFuture(
|
return $repository->getLocalCommandFuture(
|
||||||
'cat-file blob %s:%s',
|
'cat-file blob -- %s',
|
||||||
$commit,
|
sprintf('%s:%s', $commit, $path));
|
||||||
$path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,15 @@ final class DiffusionLowLevelCommitQuery
|
||||||
$split_body = true;
|
$split_body = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even though we pass --encoding here, git doesn't always succeed, so
|
$argv = array();
|
||||||
// we try a little harder, since git *does* tell us what the actual encoding
|
|
||||||
// is correctly (unless it doesn't; encoding is sometimes empty).
|
$argv[] = '-n';
|
||||||
list($info) = $repository->execxLocalCommand(
|
$argv[] = '1';
|
||||||
'log -n 1 --encoding=%s --format=%s %s --',
|
|
||||||
'UTF-8',
|
$argv[] = '--encoding=UTF-8';
|
||||||
|
|
||||||
|
$argv[] = sprintf(
|
||||||
|
'--format=%s',
|
||||||
implode(
|
implode(
|
||||||
'%x00',
|
'%x00',
|
||||||
array(
|
array(
|
||||||
|
@ -78,8 +81,15 @@ final class DiffusionLowLevelCommitQuery
|
||||||
// so include an explicit terminator: this makes sure the exact
|
// so include an explicit terminator: this makes sure the exact
|
||||||
// body text is surrounded by "\0" characters.
|
// body text is surrounded by "\0" characters.
|
||||||
'~',
|
'~',
|
||||||
)),
|
)));
|
||||||
$this->identifier);
|
|
||||||
|
// Even though we pass --encoding here, git doesn't always succeed, so
|
||||||
|
// we try a little harder, since git *does* tell us what the actual encoding
|
||||||
|
// is correctly (unless it doesn't; encoding is sometimes empty).
|
||||||
|
list($info) = $repository->execxLocalCommand(
|
||||||
|
'log -n 1 %Ls %s --',
|
||||||
|
$argv,
|
||||||
|
gitsprintf('%s', $this->identifier));
|
||||||
|
|
||||||
$parts = explode("\0", $info);
|
$parts = explode("\0", $info);
|
||||||
$encoding = array_shift($parts);
|
$encoding = array_shift($parts);
|
||||||
|
|
|
@ -33,7 +33,7 @@ final class DiffusionLowLevelFilesizeQuery
|
||||||
|
|
||||||
$paths_future = $repository->getLocalCommandFuture(
|
$paths_future = $repository->getLocalCommandFuture(
|
||||||
'diff-tree -z -r --no-commit-id %s --',
|
'diff-tree -z -r --no-commit-id %s --',
|
||||||
$identifier);
|
gitsprintf('%s', $identifier));
|
||||||
|
|
||||||
// With "-z" we get "<fields>\0<filename>\0" for each line. Process the
|
// With "-z" we get "<fields>\0<filename>\0" for each line. Process the
|
||||||
// delimited text as "<fields>, <filename>" pairs.
|
// delimited text as "<fields>, <filename>" pairs.
|
||||||
|
|
|
@ -37,9 +37,9 @@ final class DiffusionLowLevelParentsQuery
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
|
|
||||||
list($stdout) = $repository->execxLocalCommand(
|
list($stdout) = $repository->execxLocalCommand(
|
||||||
'log -n 1 --format=%s %s',
|
'log -n 1 %s %s --',
|
||||||
'%P',
|
'--format=%P',
|
||||||
$this->identifier);
|
gitsprintf('%s', $this->identifier));
|
||||||
|
|
||||||
return preg_split('/\s+/', trim($stdout));
|
return preg_split('/\s+/', trim($stdout));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ final class DiffusionGitRawDiffQuery extends DiffusionRawDiffQuery {
|
||||||
// Check if this is the root commit by seeing if it has parents, since
|
// Check if this is the root commit by seeing if it has parents, since
|
||||||
// `git diff X^ X` does not work if "X" is the initial commit.
|
// `git diff X^ X` does not work if "X" is the initial commit.
|
||||||
list($parents) = $repository->execxLocalCommand(
|
list($parents) = $repository->execxLocalCommand(
|
||||||
'log -n 1 --format=%s %s --',
|
'log -n 1 %s %s --',
|
||||||
'%P',
|
'--format=%P',
|
||||||
$commit);
|
gitsprintf('%s', $commit));
|
||||||
|
|
||||||
if (strlen(trim($parents))) {
|
if (strlen(trim($parents))) {
|
||||||
$against = $commit.'^';
|
$against = $commit.'^';
|
||||||
|
@ -42,8 +42,8 @@ final class DiffusionGitRawDiffQuery extends DiffusionRawDiffQuery {
|
||||||
return $repository->getLocalCommandFuture(
|
return $repository->getLocalCommandFuture(
|
||||||
'diff %Ls %s %s -- %s',
|
'diff %Ls %s %s -- %s',
|
||||||
$options,
|
$options,
|
||||||
$against,
|
gitsprintf('%s', $against),
|
||||||
$commit,
|
gitsprintf('%s', $commit),
|
||||||
$path);
|
$path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class HarbormasterBuildStepEditAPIMethod
|
||||||
|
extends PhabricatorEditEngineAPIMethod {
|
||||||
|
|
||||||
|
public function getAPIMethodName() {
|
||||||
|
return 'harbormaster.step.edit';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newEditEngine() {
|
||||||
|
return new HarbormasterBuildStepEditEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethodSummary() {
|
||||||
|
return pht(
|
||||||
|
'Apply transactions to create a new build step or edit an existing '.
|
||||||
|
'one.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class HarbormasterBuildStepSearchAPIMethod
|
||||||
|
extends PhabricatorSearchEngineAPIMethod {
|
||||||
|
|
||||||
|
public function getAPIMethodName() {
|
||||||
|
return 'harbormaster.step.search';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newSearchEngine() {
|
||||||
|
return new HarbormasterBuildStepSearchEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethodSummary() {
|
||||||
|
return pht('Retrieve information about Harbormaster build steps.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class HarbormasterBuildStepEditEngine
|
||||||
|
extends PhabricatorEditEngine {
|
||||||
|
|
||||||
|
const ENGINECONST = 'harbormaster.buildstep';
|
||||||
|
|
||||||
|
private $buildPlan;
|
||||||
|
|
||||||
|
public function setBuildPlan(HarbormasterBuildPlan $build_plan) {
|
||||||
|
$this->buildPlan = $build_plan;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuildPlan() {
|
||||||
|
if ($this->buildPlan === null) {
|
||||||
|
throw new PhutilInvalidStateException('setBuildPlan');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->buildPlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEngineConfigurable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEngineName() {
|
||||||
|
return pht('Harbormaster Build Steps');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummaryHeader() {
|
||||||
|
return pht('Edit Harbormaster Build Step Configurations');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummaryText() {
|
||||||
|
return pht('This engine is used to edit Harbormaster build steps.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEngineApplicationClass() {
|
||||||
|
return 'PhabricatorHarbormasterApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newEditableObject() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
|
||||||
|
$plan = HarbormasterBuildPlan::initializeNewBuildPlan($viewer);
|
||||||
|
$this->setBuildPlan($plan);
|
||||||
|
|
||||||
|
$plan = $this->getBuildPlan();
|
||||||
|
|
||||||
|
$step = HarbormasterBuildStep::initializeNewStep($viewer);
|
||||||
|
|
||||||
|
$step->setBuildPlanPHID($plan->getPHID());
|
||||||
|
$step->attachBuildPlan($plan);
|
||||||
|
|
||||||
|
return $step;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newObjectQuery() {
|
||||||
|
return new HarbormasterBuildStepQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateTitleText($object) {
|
||||||
|
return pht('Create Build Step');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateButtonText($object) {
|
||||||
|
return pht('Create Build Step');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectEditTitleText($object) {
|
||||||
|
return pht('Edit Build Step: %s', $object->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectEditShortText($object) {
|
||||||
|
return pht('Edit Build Step');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateShortText() {
|
||||||
|
return pht('Create Build Step');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectName() {
|
||||||
|
return pht('Build Step');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getEditorURI() {
|
||||||
|
return '/harbormaster/step/edit/';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateCancelURI($object) {
|
||||||
|
return '/harbormaster/step/';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectViewURI($object) {
|
||||||
|
$id = $object->getID();
|
||||||
|
return "/harbormaster/step/{$id}/";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildCustomEditFields($object) {
|
||||||
|
$fields = array();
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class HarbormasterBuildStepSearchEngine
|
||||||
|
extends PhabricatorApplicationSearchEngine {
|
||||||
|
|
||||||
|
public function getResultTypeDescription() {
|
||||||
|
return pht('Harbormaster Build Steps');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getApplicationClassName() {
|
||||||
|
return 'PhabricatorHarbormasterApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newQuery() {
|
||||||
|
return new HarbormasterBuildStepQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildCustomSearchFields() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildQueryFromParameters(array $map) {
|
||||||
|
$query = $this->newQuery();
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getURI($path) {
|
||||||
|
return '/harbormaster/step/'.$path;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBuiltinQueryNames() {
|
||||||
|
return array(
|
||||||
|
'all' => pht('All Steps'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildSavedQueryFromBuiltin($query_key) {
|
||||||
|
$query = $this->newSavedQuery();
|
||||||
|
$query->setQueryKey($query_key);
|
||||||
|
|
||||||
|
switch ($query_key) {
|
||||||
|
case 'all':
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderResultList(
|
||||||
|
array $plans,
|
||||||
|
PhabricatorSavedQuery $query,
|
||||||
|
array $handles) {
|
||||||
|
assert_instances_of($plans, 'HarbormasterBuildStep');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,8 @@ final class HarbormasterBuildStep extends HarbormasterDAO
|
||||||
implements
|
implements
|
||||||
PhabricatorApplicationTransactionInterface,
|
PhabricatorApplicationTransactionInterface,
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorCustomFieldInterface {
|
PhabricatorCustomFieldInterface,
|
||||||
|
PhabricatorConduitResultInterface {
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $description;
|
protected $description;
|
||||||
|
@ -169,5 +170,45 @@ final class HarbormasterBuildStep extends HarbormasterDAO
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -( PhabricatorConduitResultInterface )---------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getFieldSpecificationsForConduit() {
|
||||||
|
return array(
|
||||||
|
id(new PhabricatorConduitSearchFieldSpecification())
|
||||||
|
->setKey('name')
|
||||||
|
->setType('string')
|
||||||
|
->setDescription(pht('The name of the build step.')),
|
||||||
|
id(new PhabricatorConduitSearchFieldSpecification())
|
||||||
|
->setKey('description')
|
||||||
|
->setType('remarkup')
|
||||||
|
->setDescription(pht('The build step description.')),
|
||||||
|
id(new PhabricatorConduitSearchFieldSpecification())
|
||||||
|
->setKey('buildPlanPHID')
|
||||||
|
->setType('phid')
|
||||||
|
->setDescription(
|
||||||
|
pht(
|
||||||
|
'The PHID of the build plan this build step belongs to.')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFieldValuesForConduit() {
|
||||||
|
// T6203: This can be removed once the field becomes non-nullable.
|
||||||
|
$name = $this->getName();
|
||||||
|
$name = phutil_string_cast($name);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'name' => $name,
|
||||||
|
'description' => array(
|
||||||
|
'raw' => $this->getDescription(),
|
||||||
|
),
|
||||||
|
'buildPlanPHID' => $this->getBuildPlanPHID(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConduitSearchAttachments() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,24 +64,6 @@ final class PhabricatorMetaMTAMailQuery
|
||||||
$this->actorPHIDs);
|
$this->actorPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->recipientPHIDs !== null) {
|
|
||||||
$where[] = qsprintf(
|
|
||||||
$conn,
|
|
||||||
'recipient.dst IN (%Ls)',
|
|
||||||
$this->recipientPHIDs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->actorPHIDs === null && $this->recipientPHIDs === null) {
|
|
||||||
$viewer = $this->getViewer();
|
|
||||||
if (!$viewer->isOmnipotent()) {
|
|
||||||
$where[] = qsprintf(
|
|
||||||
$conn,
|
|
||||||
'edge.dst = %s OR actorPHID = %s',
|
|
||||||
$viewer->getPHID(),
|
|
||||||
$viewer->getPHID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->createdMin !== null) {
|
if ($this->createdMin !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
|
@ -102,26 +84,29 @@ final class PhabricatorMetaMTAMailQuery
|
||||||
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
$joins = parent::buildJoinClauseParts($conn);
|
$joins = parent::buildJoinClauseParts($conn);
|
||||||
|
|
||||||
if ($this->actorPHIDs === null && $this->recipientPHIDs === null) {
|
if ($this->shouldJoinRecipients()) {
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'LEFT JOIN %T edge ON mail.phid = edge.src AND edge.type = %d',
|
'JOIN %T recipient
|
||||||
|
ON mail.phid = recipient.src
|
||||||
|
AND recipient.type = %d
|
||||||
|
AND recipient.dst IN (%Ls)',
|
||||||
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
||||||
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST);
|
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST,
|
||||||
}
|
$this->recipientPHIDs);
|
||||||
|
|
||||||
if ($this->recipientPHIDs !== null) {
|
|
||||||
$joins[] = qsprintf(
|
|
||||||
$conn,
|
|
||||||
'LEFT JOIN %T recipient '.
|
|
||||||
'ON mail.phid = recipient.src AND recipient.type = %d',
|
|
||||||
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
|
||||||
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $joins;
|
return $joins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function shouldJoinRecipients() {
|
||||||
|
if ($this->recipientPHIDs === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getPrimaryTableAlias() {
|
protected function getPrimaryTableAlias() {
|
||||||
return 'mail';
|
return 'mail';
|
||||||
}
|
}
|
||||||
|
@ -134,4 +119,14 @@ final class PhabricatorMetaMTAMailQuery
|
||||||
return 'PhabricatorMetaMTAApplication';
|
return 'PhabricatorMetaMTAApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function shouldGroupQueryResultRows() {
|
||||||
|
if ($this->shouldJoinRecipients()) {
|
||||||
|
if (count($this->recipientPHIDs) > 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::shouldGroupQueryResultRows();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class PhabricatorPackagesApplication extends PhabricatorApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBaseURI() {
|
public function getBaseURI() {
|
||||||
return '/packages/';
|
return '/packages/package/';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIcon() {
|
public function getIcon() {
|
||||||
|
|
|
@ -19,13 +19,13 @@ final class PhabricatorGitGraphStream
|
||||||
|
|
||||||
if ($start_commit !== null) {
|
if ($start_commit !== null) {
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'log --format=%s %s --',
|
'log %s %s --',
|
||||||
'%H%x01%P%x01%ct',
|
'--format=%H%x01%P%x01%ct',
|
||||||
$start_commit);
|
gitsprintf('%s', $start_commit));
|
||||||
} else {
|
} else {
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'log --format=%s --all --',
|
'log %s --all --',
|
||||||
'%H%x01%P%x01%ct');
|
'--format=%H%x01%P%x01%ct');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->iterator = new LinesOfALargeExecFuture($future);
|
$this->iterator = new LinesOfALargeExecFuture($future);
|
||||||
|
|
|
@ -5,7 +5,7 @@ final class PhabricatorRepositoryCommitRef extends Phobject {
|
||||||
private $identifier;
|
private $identifier;
|
||||||
private $epoch;
|
private $epoch;
|
||||||
private $branch;
|
private $branch;
|
||||||
private $canCloseImmediately;
|
private $isPermanent;
|
||||||
private $parents = array();
|
private $parents = array();
|
||||||
|
|
||||||
public function setIdentifier($identifier) {
|
public function setIdentifier($identifier) {
|
||||||
|
@ -35,13 +35,13 @@ final class PhabricatorRepositoryCommitRef extends Phobject {
|
||||||
return $this->branch;
|
return $this->branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCanCloseImmediately($can_close_immediately) {
|
public function setIsPermanent($is_permanent) {
|
||||||
$this->canCloseImmediately = $can_close_immediately;
|
$this->isPermanent = $is_permanent;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCanCloseImmediately() {
|
public function getIsPermanent() {
|
||||||
return $this->canCloseImmediately;
|
return $this->isPermanent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setParents(array $parents) {
|
public function setParents(array $parents) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$repository,
|
$repository,
|
||||||
$ref->getIdentifier(),
|
$ref->getIdentifier(),
|
||||||
$ref->getEpoch(),
|
$ref->getEpoch(),
|
||||||
$ref->getCanCloseImmediately(),
|
$ref->getIsPermanent(),
|
||||||
$ref->getParents(),
|
$ref->getParents(),
|
||||||
$task_priority);
|
$task_priority);
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$head_refs = $this->discoverStreamAncestry(
|
$head_refs = $this->discoverStreamAncestry(
|
||||||
new PhabricatorGitGraphStream($repository, $commit),
|
new PhabricatorGitGraphStream($repository, $commit),
|
||||||
$commit,
|
$commit,
|
||||||
$publisher->shouldPublishRef($ref));
|
$publisher->isPermanentRef($ref));
|
||||||
|
|
||||||
$this->didDiscoverRefs($head_refs);
|
$this->didDiscoverRefs($head_refs);
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$refs[$identifier] = id(new PhabricatorRepositoryCommitRef())
|
$refs[$identifier] = id(new PhabricatorRepositoryCommitRef())
|
||||||
->setIdentifier($identifier)
|
->setIdentifier($identifier)
|
||||||
->setEpoch($epoch)
|
->setEpoch($epoch)
|
||||||
->setCanCloseImmediately(true);
|
->setIsPermanent(true);
|
||||||
|
|
||||||
if ($upper_bound === null) {
|
if ($upper_bound === null) {
|
||||||
$upper_bound = $identifier;
|
$upper_bound = $identifier;
|
||||||
|
@ -354,7 +354,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$branch_refs = $this->discoverStreamAncestry(
|
$branch_refs = $this->discoverStreamAncestry(
|
||||||
new PhabricatorMercurialGraphStream($repository, $commit),
|
new PhabricatorMercurialGraphStream($repository, $commit),
|
||||||
$commit,
|
$commit,
|
||||||
$close_immediately = true);
|
$is_permanent = true);
|
||||||
|
|
||||||
$this->didDiscoverRefs($branch_refs);
|
$this->didDiscoverRefs($branch_refs);
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
private function discoverStreamAncestry(
|
private function discoverStreamAncestry(
|
||||||
PhabricatorRepositoryGraphStream $stream,
|
PhabricatorRepositoryGraphStream $stream,
|
||||||
$commit,
|
$commit,
|
||||||
$close_immediately) {
|
$is_permanent) {
|
||||||
|
|
||||||
$discover = array($commit);
|
$discover = array($commit);
|
||||||
$graph = array();
|
$graph = array();
|
||||||
|
@ -424,7 +424,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$refs[] = id(new PhabricatorRepositoryCommitRef())
|
$refs[] = id(new PhabricatorRepositoryCommitRef())
|
||||||
->setIdentifier($commit)
|
->setIdentifier($commit)
|
||||||
->setEpoch($epoch)
|
->setEpoch($epoch)
|
||||||
->setCanCloseImmediately($close_immediately)
|
->setIsPermanent($is_permanent)
|
||||||
->setParents($stream->getParents($commit));
|
->setParents($stream->getParents($commit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,13 +459,6 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repairMode) {
|
|
||||||
// In repair mode, rediscover the entire repository, ignoring the
|
|
||||||
// database state. We can hit the local cache above, but if we miss it
|
|
||||||
// stop the script from going to the database cache.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->fillCommitCache(array($identifier));
|
$this->fillCommitCache(array($identifier));
|
||||||
|
|
||||||
return isset($this->commitCache[$identifier]);
|
return isset($this->commitCache[$identifier]);
|
||||||
|
@ -476,6 +469,13 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->repairMode) {
|
||||||
|
// In repair mode, rediscover the entire repository, ignoring the
|
||||||
|
// database state. The engine still maintains a local cache (the
|
||||||
|
// "Working Set") but we just give up before looking in the database.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$max_size = self::MAX_COMMIT_CACHE_SIZE;
|
$max_size = self::MAX_COMMIT_CACHE_SIZE;
|
||||||
|
|
||||||
// If we're filling more identifiers than would fit in the cache, ignore
|
// If we're filling more identifiers than would fit in the cache, ignore
|
||||||
|
@ -507,9 +507,9 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort branches so we process closeable branches first. This makes the
|
* Sort refs so we process permanent refs first. This makes the whole import
|
||||||
* whole import process a little cheaper, since we can close these commits
|
* process a little cheaper, since we can publish these commits the first
|
||||||
* the first time through rather than catching them in the refs step.
|
* time through rather than catching them in the refs step.
|
||||||
*
|
*
|
||||||
* @task internal
|
* @task internal
|
||||||
*
|
*
|
||||||
|
@ -523,7 +523,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$head_refs = array();
|
$head_refs = array();
|
||||||
$tail_refs = array();
|
$tail_refs = array();
|
||||||
foreach ($refs as $ref) {
|
foreach ($refs as $ref) {
|
||||||
if ($publisher->shouldPublishRef($ref)) {
|
if ($publisher->isPermanentRef($ref)) {
|
||||||
$head_refs[] = $ref;
|
$head_refs[] = $ref;
|
||||||
} else {
|
} else {
|
||||||
$tail_refs[] = $ref;
|
$tail_refs[] = $ref;
|
||||||
|
@ -538,7 +538,7 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
PhabricatorRepository $repository,
|
PhabricatorRepository $repository,
|
||||||
$commit_identifier,
|
$commit_identifier,
|
||||||
$epoch,
|
$epoch,
|
||||||
$close_immediately,
|
$is_permanent,
|
||||||
array $parents,
|
array $parents,
|
||||||
$task_priority) {
|
$task_priority) {
|
||||||
|
|
||||||
|
@ -570,8 +570,8 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$commit->setRepositoryID($repository->getID());
|
$commit->setRepositoryID($repository->getID());
|
||||||
$commit->setCommitIdentifier($commit_identifier);
|
$commit->setCommitIdentifier($commit_identifier);
|
||||||
$commit->setEpoch($epoch);
|
$commit->setEpoch($epoch);
|
||||||
if ($close_immediately) {
|
if ($is_permanent) {
|
||||||
$commit->setImportStatus(PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE);
|
$commit->setImportStatus(PhabricatorRepositoryCommit::IMPORTED_PERMANENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = new PhabricatorRepositoryCommitData();
|
$data = new PhabricatorRepositoryCommitData();
|
||||||
|
@ -655,7 +655,12 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$epoch,
|
$epoch,
|
||||||
$task_priority) {
|
$task_priority) {
|
||||||
|
|
||||||
$this->insertTask($repository, $commit, $task_priority);
|
$this->queueCommitImportTask(
|
||||||
|
$repository,
|
||||||
|
$commit->getID(),
|
||||||
|
$commit->getPHID(),
|
||||||
|
$task_priority,
|
||||||
|
$via = 'discovery');
|
||||||
|
|
||||||
// Update the repository summary table.
|
// Update the repository summary table.
|
||||||
queryfx(
|
queryfx(
|
||||||
|
@ -679,36 +684,6 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function insertTask(
|
|
||||||
PhabricatorRepository $repository,
|
|
||||||
PhabricatorRepositoryCommit $commit,
|
|
||||||
$task_priority,
|
|
||||||
$data = array()) {
|
|
||||||
|
|
||||||
$vcs = $repository->getVersionControlSystem();
|
|
||||||
switch ($vcs) {
|
|
||||||
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
|
|
||||||
$class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
|
|
||||||
break;
|
|
||||||
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
|
||||||
$class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
|
|
||||||
break;
|
|
||||||
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
|
|
||||||
$class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception(pht("Unknown repository type '%s'!", $vcs));
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['commitID'] = $commit->getID();
|
|
||||||
|
|
||||||
$options = array(
|
|
||||||
'priority' => $task_priority,
|
|
||||||
);
|
|
||||||
|
|
||||||
PhabricatorWorker::scheduleTask($class, $data, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function isInitialImport(array $refs) {
|
private function isInitialImport(array $refs) {
|
||||||
$commit_count = count($refs);
|
$commit_count = count($refs);
|
||||||
|
|
||||||
|
@ -926,71 +901,4 @@ final class PhabricatorRepositoryDiscoveryEngine
|
||||||
$data['epoch']);
|
$data['epoch']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getImportTaskPriority(
|
|
||||||
PhabricatorRepository $repository,
|
|
||||||
array $refs) {
|
|
||||||
|
|
||||||
// If the repository is importing for the first time, we schedule tasks
|
|
||||||
// at IMPORT priority, which is very low. Making progress on importing a
|
|
||||||
// new repository for the first time is less important than any other
|
|
||||||
// daemon task.
|
|
||||||
|
|
||||||
// If the repository has finished importing and we're just catching up
|
|
||||||
// on recent commits, we usually schedule discovery at COMMIT priority,
|
|
||||||
// which is slightly below the default priority.
|
|
||||||
|
|
||||||
// Note that followup tasks and triggered tasks (like those generated by
|
|
||||||
// Herald or Harbormaster) will queue at DEFAULT priority, so that each
|
|
||||||
// commit tends to fully import before we start the next one. This tends
|
|
||||||
// to give imports fairly predictable progress. See T11677 for some
|
|
||||||
// discussion.
|
|
||||||
|
|
||||||
if ($repository->isImporting()) {
|
|
||||||
$this->log(
|
|
||||||
pht(
|
|
||||||
'Importing %s commit(s) at low priority ("PRIORITY_IMPORT") '.
|
|
||||||
'because this repository is still importing.',
|
|
||||||
phutil_count($refs)));
|
|
||||||
|
|
||||||
return PhabricatorWorker::PRIORITY_IMPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See T13369. If we've discovered a lot of commits at once, import them
|
|
||||||
// at lower priority.
|
|
||||||
|
|
||||||
// This is mostly aimed at reducing the impact that synchronizing thousands
|
|
||||||
// of commits from a remote upstream has on other repositories. The queue
|
|
||||||
// is "mostly FIFO", so queueing a thousand commit imports can stall other
|
|
||||||
// repositories.
|
|
||||||
|
|
||||||
// In a perfect world we'd probably give repositories round-robin queue
|
|
||||||
// priority, but we don't currently have the primitives for this and there
|
|
||||||
// isn't a strong case for building them.
|
|
||||||
|
|
||||||
// Use "a whole lot of commits showed up at once" as a heuristic for
|
|
||||||
// detecting "someone synchronized an upstream", and import them at a lower
|
|
||||||
// priority to more closely approximate fair scheduling.
|
|
||||||
|
|
||||||
if (count($refs) >= PhabricatorRepository::LOWPRI_THRESHOLD) {
|
|
||||||
$this->log(
|
|
||||||
pht(
|
|
||||||
'Importing %s commit(s) at low priority ("PRIORITY_IMPORT") '.
|
|
||||||
'because many commits were discovered at once.',
|
|
||||||
phutil_count($refs)));
|
|
||||||
|
|
||||||
return PhabricatorWorker::PRIORITY_IMPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, import at normal priority.
|
|
||||||
|
|
||||||
if ($refs) {
|
|
||||||
$this->log(
|
|
||||||
pht(
|
|
||||||
'Importing %s commit(s) at normal priority ("PRIORITY_COMMIT").',
|
|
||||||
phutil_count($refs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return PhabricatorWorker::PRIORITY_COMMIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,4 +83,114 @@ abstract class PhabricatorRepositoryEngine extends Phobject {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final protected function queueCommitImportTask(
|
||||||
|
PhabricatorRepository $repository,
|
||||||
|
$commit_id,
|
||||||
|
$commit_phid,
|
||||||
|
$task_priority,
|
||||||
|
$via = null) {
|
||||||
|
|
||||||
|
$vcs = $repository->getVersionControlSystem();
|
||||||
|
switch ($vcs) {
|
||||||
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
|
||||||
|
$class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
|
||||||
|
break;
|
||||||
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
||||||
|
$class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
|
||||||
|
break;
|
||||||
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
|
||||||
|
$class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Unknown repository type "%s"!',
|
||||||
|
$vcs));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
'commitID' => $commit_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($via !== null) {
|
||||||
|
$data['via'] = $via;
|
||||||
|
}
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'priority' => $task_priority,
|
||||||
|
'objectPHID' => $commit_phid,
|
||||||
|
);
|
||||||
|
|
||||||
|
PhabricatorWorker::scheduleTask($class, $data, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function getImportTaskPriority(
|
||||||
|
PhabricatorRepository $repository,
|
||||||
|
array $refs) {
|
||||||
|
assert_instances_of($refs, 'PhabricatorRepositoryCommitRef');
|
||||||
|
|
||||||
|
// If the repository is importing for the first time, we schedule tasks
|
||||||
|
// at IMPORT priority, which is very low. Making progress on importing a
|
||||||
|
// new repository for the first time is less important than any other
|
||||||
|
// daemon task.
|
||||||
|
|
||||||
|
// If the repository has finished importing and we're just catching up
|
||||||
|
// on recent commits, we usually schedule discovery at COMMIT priority,
|
||||||
|
// which is slightly below the default priority.
|
||||||
|
|
||||||
|
// Note that followup tasks and triggered tasks (like those generated by
|
||||||
|
// Herald or Harbormaster) will queue at DEFAULT priority, so that each
|
||||||
|
// commit tends to fully import before we start the next one. This tends
|
||||||
|
// to give imports fairly predictable progress. See T11677 for some
|
||||||
|
// discussion.
|
||||||
|
|
||||||
|
if ($repository->isImporting()) {
|
||||||
|
$this->log(
|
||||||
|
pht(
|
||||||
|
'Importing %s commit(s) at low priority ("PRIORITY_IMPORT") '.
|
||||||
|
'because this repository is still importing.',
|
||||||
|
phutil_count($refs)));
|
||||||
|
|
||||||
|
return PhabricatorWorker::PRIORITY_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See T13369. If we've discovered a lot of commits at once, import them
|
||||||
|
// at lower priority.
|
||||||
|
|
||||||
|
// This is mostly aimed at reducing the impact that synchronizing thousands
|
||||||
|
// of commits from a remote upstream has on other repositories. The queue
|
||||||
|
// is "mostly FIFO", so queueing a thousand commit imports can stall other
|
||||||
|
// repositories.
|
||||||
|
|
||||||
|
// In a perfect world we'd probably give repositories round-robin queue
|
||||||
|
// priority, but we don't currently have the primitives for this and there
|
||||||
|
// isn't a strong case for building them.
|
||||||
|
|
||||||
|
// Use "a whole lot of commits showed up at once" as a heuristic for
|
||||||
|
// detecting "someone synchronized an upstream", and import them at a lower
|
||||||
|
// priority to more closely approximate fair scheduling.
|
||||||
|
|
||||||
|
if (count($refs) >= PhabricatorRepository::LOWPRI_THRESHOLD) {
|
||||||
|
$this->log(
|
||||||
|
pht(
|
||||||
|
'Importing %s commit(s) at low priority ("PRIORITY_IMPORT") '.
|
||||||
|
'because many commits were discovered at once.',
|
||||||
|
phutil_count($refs)));
|
||||||
|
|
||||||
|
return PhabricatorWorker::PRIORITY_IMPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, import at normal priority.
|
||||||
|
|
||||||
|
if ($refs) {
|
||||||
|
$this->log(
|
||||||
|
pht(
|
||||||
|
'Importing %s commit(s) at normal priority ("PRIORITY_COMMIT").',
|
||||||
|
phutil_count($refs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PhabricatorWorker::PRIORITY_COMMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ final class PhabricatorRepositoryRefEngine
|
||||||
|
|
||||||
private $newPositions = array();
|
private $newPositions = array();
|
||||||
private $deadPositions = array();
|
private $deadPositions = array();
|
||||||
private $closeCommits = array();
|
private $permanentCommits = array();
|
||||||
private $rebuild;
|
private $rebuild;
|
||||||
|
|
||||||
public function setRebuild($rebuild) {
|
public function setRebuild($rebuild) {
|
||||||
|
@ -24,7 +24,7 @@ final class PhabricatorRepositoryRefEngine
|
||||||
public function updateRefs() {
|
public function updateRefs() {
|
||||||
$this->newPositions = array();
|
$this->newPositions = array();
|
||||||
$this->deadPositions = array();
|
$this->deadPositions = array();
|
||||||
$this->closeCommits = array();
|
$this->permanentCommits = array();
|
||||||
|
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
@ -96,11 +96,11 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$this->updateCursors($cursor_group, $refs, $type, $all_closing_heads);
|
$this->updateCursors($cursor_group, $refs, $type, $all_closing_heads);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->closeCommits) {
|
if ($this->permanentCommits) {
|
||||||
$this->setCloseFlagOnCommits($this->closeCommits);
|
$this->setPermanentFlagOnCommits($this->permanentCommits);
|
||||||
}
|
}
|
||||||
|
|
||||||
$save_cursors = $this->getCursorsForUpdate($all_cursors);
|
$save_cursors = $this->getCursorsForUpdate($repository, $all_cursors);
|
||||||
|
|
||||||
if ($this->newPositions || $this->deadPositions || $save_cursors) {
|
if ($this->newPositions || $this->deadPositions || $save_cursors) {
|
||||||
$repository->openTransaction();
|
$repository->openTransaction();
|
||||||
|
@ -121,17 +121,19 @@ final class PhabricatorRepositoryRefEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCursorsForUpdate(array $cursors) {
|
private function getCursorsForUpdate(
|
||||||
|
PhabricatorRepository $repository,
|
||||||
|
array $cursors) {
|
||||||
assert_instances_of($cursors, 'PhabricatorRepositoryRefCursor');
|
assert_instances_of($cursors, 'PhabricatorRepositoryRefCursor');
|
||||||
|
|
||||||
|
$publisher = $repository->newPublisher();
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
|
|
||||||
foreach ($cursors as $cursor) {
|
foreach ($cursors as $cursor) {
|
||||||
$ref_type = $cursor->getRefType();
|
$diffusion_ref = $cursor->newDiffusionRepositoryRef();
|
||||||
$ref_name = $cursor->getRefName();
|
|
||||||
|
|
||||||
$is_permanent = $this->isPermanentRef($ref_type, $ref_name);
|
|
||||||
|
|
||||||
|
$is_permanent = $publisher->isPermanentRef($diffusion_ref);
|
||||||
if ($is_permanent == $cursor->getIsPermanent()) {
|
if ($is_permanent == $cursor->getIsPermanent()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -217,9 +219,9 @@ final class PhabricatorRepositoryRefEngine
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function markCloseCommits(array $identifiers) {
|
private function markPermanentCommits(array $identifiers) {
|
||||||
foreach ($identifiers as $identifier) {
|
foreach ($identifiers as $identifier) {
|
||||||
$this->closeCommits[$identifier] = $identifier;
|
$this->permanentCommits[$identifier] = $identifier;
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -259,6 +261,7 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$ref_type,
|
$ref_type,
|
||||||
array $all_closing_heads) {
|
array $all_closing_heads) {
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
|
$publisher = $repository->newPublisher();
|
||||||
|
|
||||||
// NOTE: Mercurial branches may have multiple branch heads; this logic
|
// NOTE: Mercurial branches may have multiple branch heads; this logic
|
||||||
// is complex primarily to account for that.
|
// is complex primarily to account for that.
|
||||||
|
@ -341,7 +344,7 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$this->markPositionNew($new_position);
|
$this->markPositionNew($new_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isPermanentRef($ref_type, $name)) {
|
if ($publisher->isPermanentRef(head($refs))) {
|
||||||
|
|
||||||
// See T13284. If this cursor was already marked as permanent, we
|
// See T13284. If this cursor was already marked as permanent, we
|
||||||
// only need to publish the newly created ref positions. However, if
|
// only need to publish the newly created ref positions. However, if
|
||||||
|
@ -377,7 +380,7 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$identifier,
|
$identifier,
|
||||||
$exclude);
|
$exclude);
|
||||||
|
|
||||||
$this->markCloseCommits($new_identifiers);
|
$this->markPermanentCommits($new_identifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,14 +407,6 @@ final class PhabricatorRepositoryRefEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isPermanentRef($ref_type, $ref_name) {
|
|
||||||
if ($ref_type !== PhabricatorRepositoryRefCursor::TYPE_BRANCH) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getRepository()->isBranchPermanentRef($ref_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all ancestors of a new closing branch head which are not ancestors
|
* Find all ancestors of a new closing branch head which are not ancestors
|
||||||
* of any old closing branch head.
|
* of any old closing branch head.
|
||||||
|
@ -483,17 +478,17 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$ref_list = implode("\n", $ref_list)."\n";
|
$ref_list = implode("\n", $ref_list)."\n";
|
||||||
|
|
||||||
$future = $this->getRepository()->getLocalCommandFuture(
|
$future = $this->getRepository()->getLocalCommandFuture(
|
||||||
'log --format=%s --stdin',
|
'log %s --stdin --',
|
||||||
'%H');
|
'--format=%H');
|
||||||
|
|
||||||
list($stdout) = $future
|
list($stdout) = $future
|
||||||
->write($ref_list)
|
->write($ref_list)
|
||||||
->resolvex();
|
->resolvex();
|
||||||
} else {
|
} else {
|
||||||
list($stdout) = $this->getRepository()->execxLocalCommand(
|
list($stdout) = $this->getRepository()->execxLocalCommand(
|
||||||
'log --format=%s %s',
|
'log %s %s --',
|
||||||
'%H',
|
'--format=%H',
|
||||||
$new_head);
|
gitsprintf('%s', $new_head));
|
||||||
}
|
}
|
||||||
|
|
||||||
$stdout = trim($stdout);
|
$stdout = trim($stdout);
|
||||||
|
@ -507,10 +502,10 @@ final class PhabricatorRepositoryRefEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a list of commits as closeable, and queue workers for those commits
|
* Mark a list of commits as permanent, and queue workers for those commits
|
||||||
* which don't already have the flag.
|
* which don't already have the flag.
|
||||||
*/
|
*/
|
||||||
private function setCloseFlagOnCommits(array $identifiers) {
|
private function setPermanentFlagOnCommits(array $identifiers) {
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
$commit_table = new PhabricatorRepositoryCommit();
|
$commit_table = new PhabricatorRepositoryCommit();
|
||||||
$conn = $commit_table->establishConnection('w');
|
$conn = $commit_table->establishConnection('w');
|
||||||
|
@ -552,7 +547,23 @@ final class PhabricatorRepositoryRefEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$closeable_flag = PhabricatorRepositoryCommit::IMPORTED_CLOSEABLE;
|
$commit_refs = array();
|
||||||
|
foreach ($identifiers as $identifier) {
|
||||||
|
|
||||||
|
// See T13591. This construction is a bit ad-hoc, but the priority
|
||||||
|
// function currently only cares about the number of refs we have
|
||||||
|
// discovered, so we'll get the right result even without filling
|
||||||
|
// these records out in detail.
|
||||||
|
|
||||||
|
$commit_refs[] = id(new PhabricatorRepositoryCommitRef())
|
||||||
|
->setIdentifier($identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
$task_priority = $this->getImportTaskPriority(
|
||||||
|
$repository,
|
||||||
|
$commit_refs);
|
||||||
|
|
||||||
|
$permanent_flag = PhabricatorRepositoryCommit::IMPORTED_PERMANENT;
|
||||||
$published_flag = PhabricatorRepositoryCommit::IMPORTED_PUBLISH;
|
$published_flag = PhabricatorRepositoryCommit::IMPORTED_PUBLISH;
|
||||||
|
|
||||||
$all_commits = ipull($all_commits, null, 'commitIdentifier');
|
$all_commits = ipull($all_commits, null, 'commitIdentifier');
|
||||||
|
@ -568,9 +579,9 @@ final class PhabricatorRepositoryRefEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
$import_status = $row['importStatus'];
|
$import_status = $row['importStatus'];
|
||||||
if (!($import_status & $closeable_flag)) {
|
if (!($import_status & $permanent_flag)) {
|
||||||
// Set the "closeable" flag.
|
// Set the "permanent" flag.
|
||||||
$import_status = ($import_status | $closeable_flag);
|
$import_status = ($import_status | $permanent_flag);
|
||||||
|
|
||||||
// See T13580. Clear the "published" flag, so publishing executes
|
// See T13580. Clear the "published" flag, so publishing executes
|
||||||
// again. We may have previously performed a no-op "publish" on the
|
// again. We may have previously performed a no-op "publish" on the
|
||||||
|
@ -584,17 +595,12 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$import_status,
|
$import_status,
|
||||||
$row['id']);
|
$row['id']);
|
||||||
|
|
||||||
$data = array(
|
$this->queueCommitImportTask(
|
||||||
'commitID' => $row['id'],
|
$repository,
|
||||||
);
|
$row['id'],
|
||||||
|
$row['phid'],
|
||||||
PhabricatorWorker::scheduleTask(
|
$task_priority,
|
||||||
$class,
|
$via = 'ref');
|
||||||
$data,
|
|
||||||
array(
|
|
||||||
'priority' => PhabricatorWorker::PRIORITY_COMMIT,
|
|
||||||
'objectPHID' => $row['phid'],
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,13 +612,17 @@ final class PhabricatorRepositoryRefEngine
|
||||||
$ref_type,
|
$ref_type,
|
||||||
$ref_name) {
|
$ref_name) {
|
||||||
|
|
||||||
$is_permanent = $this->isPermanentRef($ref_type, $ref_name);
|
|
||||||
|
|
||||||
$cursor = id(new PhabricatorRepositoryRefCursor())
|
$cursor = id(new PhabricatorRepositoryRefCursor())
|
||||||
->setRepositoryPHID($repository->getPHID())
|
->setRepositoryPHID($repository->getPHID())
|
||||||
->setRefType($ref_type)
|
->setRefType($ref_type)
|
||||||
->setRefName($ref_name)
|
->setRefName($ref_name);
|
||||||
->setIsPermanent((int)$is_permanent);
|
|
||||||
|
$publisher = $repository->newPublisher();
|
||||||
|
|
||||||
|
$diffusion_ref = $cursor->newDiffusionRepositoryRef();
|
||||||
|
$is_permanent = $publisher->isPermanentRef($diffusion_ref);
|
||||||
|
|
||||||
|
$cursor->setIsPermanent((int)$is_permanent);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return $cursor->save();
|
return $cursor->save();
|
||||||
|
|
|
@ -4,6 +4,8 @@ final class PhabricatorWorkingCopyDiscoveryTestCase
|
||||||
extends PhabricatorWorkingCopyTestCase {
|
extends PhabricatorWorkingCopyTestCase {
|
||||||
|
|
||||||
public function testSubversionCommitDiscovery() {
|
public function testSubversionCommitDiscovery() {
|
||||||
|
$this->requireBinaryForTest('svn');
|
||||||
|
|
||||||
$refs = $this->discoverRefs('ST');
|
$refs = $this->discoverRefs('ST');
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -7,21 +7,22 @@ final class PhabricatorRepositoryManagementDiscoverWorkflow
|
||||||
$this
|
$this
|
||||||
->setName('discover')
|
->setName('discover')
|
||||||
->setExamples('**discover** [__options__] __repository__ ...')
|
->setExamples('**discover** [__options__] __repository__ ...')
|
||||||
->setSynopsis(pht('Discover __repository__.'))
|
->setSynopsis(pht('Discover commits in __repository__.'))
|
||||||
->setArguments(
|
->setArguments(
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
'name' => 'verbose',
|
'name' => 'verbose',
|
||||||
'help' => pht('Show additional debugging information.'),
|
'help' => pht('Show additional debugging information.'),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'repair',
|
'name' => 'repair',
|
||||||
'help' => pht(
|
'help' => pht(
|
||||||
'Repair a repository with gaps in commit history.'),
|
'Discover all commits, even if they are ancestors of known '.
|
||||||
|
'commits. This can repair gaps in repository history.'),
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'repos',
|
'name' => 'repos',
|
||||||
'wildcard' => true,
|
'wildcard' => true,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ final class PhabricatorRepositoryPublisher
|
||||||
return !$this->getCommitHoldReasons($commit);
|
return !$this->getCommitHoldReasons($commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isPermanentRef(DiffusionRepositoryRef $ref) {
|
||||||
|
return !$this->getRefImpermanentReasons($ref);
|
||||||
|
}
|
||||||
|
|
||||||
/* -( Hold Reasons )------------------------------------------------------- */
|
/* -( Hold Reasons )------------------------------------------------------- */
|
||||||
|
|
||||||
public function getRepositoryHoldReasons() {
|
public function getRepositoryHoldReasons() {
|
||||||
|
@ -59,18 +63,8 @@ final class PhabricatorRepositoryPublisher
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
$reasons = $this->getRepositoryHoldReasons();
|
$reasons = $this->getRepositoryHoldReasons();
|
||||||
|
|
||||||
if (!$ref->isBranch()) {
|
foreach ($this->getRefImpermanentReasons($ref) as $reason) {
|
||||||
$reasons[] = self::HOLD_REF_NOT_BRANCH;
|
$reasons[] = $reason;
|
||||||
} else {
|
|
||||||
$branch_name = $ref->getShortName();
|
|
||||||
|
|
||||||
if (!$repository->shouldTrackBranch($branch_name)) {
|
|
||||||
$reasons[] = self::HOLD_UNTRACKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$repository->isBranchPermanentRef($branch_name)) {
|
|
||||||
$reasons[] = self::HOLD_NOT_PERMANENT_REF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $reasons;
|
return $reasons;
|
||||||
|
@ -89,4 +83,25 @@ final class PhabricatorRepositoryPublisher
|
||||||
return $reasons;
|
return $reasons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRefImpermanentReasons(DiffusionRepositoryRef $ref) {
|
||||||
|
$repository = $this->getRepository();
|
||||||
|
$reasons = array();
|
||||||
|
|
||||||
|
if (!$ref->isBranch()) {
|
||||||
|
$reasons[] = self::HOLD_REF_NOT_BRANCH;
|
||||||
|
} else {
|
||||||
|
$branch_name = $ref->getShortName();
|
||||||
|
|
||||||
|
if (!$repository->shouldTrackBranch($branch_name)) {
|
||||||
|
$reasons[] = self::HOLD_UNTRACKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$repository->isBranchPermanentRef($branch_name)) {
|
||||||
|
$reasons[] = self::HOLD_NOT_PERMANENT_REF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $reasons;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ final class PhabricatorRepositoryCommit
|
||||||
const IMPORTED_PUBLISH = 8;
|
const IMPORTED_PUBLISH = 8;
|
||||||
const IMPORTED_ALL = 11;
|
const IMPORTED_ALL = 11;
|
||||||
|
|
||||||
const IMPORTED_CLOSEABLE = 1024;
|
const IMPORTED_PERMANENT = 1024;
|
||||||
const IMPORTED_UNREACHABLE = 2048;
|
const IMPORTED_UNREACHABLE = 2048;
|
||||||
|
|
||||||
private $commitData = self::ATTACHABLE;
|
private $commitData = self::ATTACHABLE;
|
||||||
|
@ -467,7 +467,7 @@ final class PhabricatorRepositoryCommit
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPermanentCommit() {
|
public function isPermanentCommit() {
|
||||||
return (bool)$this->isPartiallyImported(self::IMPORTED_CLOSEABLE);
|
return (bool)$this->isPartiallyImported(self::IMPORTED_PERMANENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newCommitAuthorView(PhabricatorUser $viewer) {
|
public function newCommitAuthorView(PhabricatorUser $viewer) {
|
||||||
|
|
|
@ -88,6 +88,12 @@ final class PhabricatorRepositoryRefCursor
|
||||||
return mpull($this->getPositions(), 'getCommitIdentifier');
|
return mpull($this->getPositions(), 'getCommitIdentifier');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newDiffusionRepositoryRef() {
|
||||||
|
return id(new DiffusionRepositoryRef())
|
||||||
|
->setRefType($this->getRefType())
|
||||||
|
->setShortName($this->getRefName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@ abstract class PhabricatorWorkerManagementWorkflow
|
||||||
'param' => 'int',
|
'param' => 'int',
|
||||||
'help' => pht('Limit to tasks with at least this many failures.'),
|
'help' => pht('Limit to tasks with at least this many failures.'),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'active',
|
||||||
|
'help' => pht('Select all active tasks.'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +32,13 @@ abstract class PhabricatorWorkerManagementWorkflow
|
||||||
$ids = $args->getArg('id');
|
$ids = $args->getArg('id');
|
||||||
$class = $args->getArg('class');
|
$class = $args->getArg('class');
|
||||||
$min_failures = $args->getArg('min-failure-count');
|
$min_failures = $args->getArg('min-failure-count');
|
||||||
|
$active = $args->getArg('active');
|
||||||
|
|
||||||
if (!$ids && !$class && !$min_failures) {
|
if (!$ids && !$class && !$min_failures && !$active) {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht('Use --id, --class, or --min-failure-count to select tasks.'));
|
pht(
|
||||||
|
'Use "--id", "--class", "--active", and/or "--min-failure-count" '.
|
||||||
|
'to select tasks.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$active_query = new PhabricatorWorkerActiveTaskQuery();
|
$active_query = new PhabricatorWorkerActiveTaskQuery();
|
||||||
|
@ -56,7 +63,13 @@ abstract class PhabricatorWorkerManagementWorkflow
|
||||||
}
|
}
|
||||||
|
|
||||||
$active_tasks = $active_query->execute();
|
$active_tasks = $active_query->execute();
|
||||||
$archive_tasks = $archive_query->execute();
|
|
||||||
|
if ($active) {
|
||||||
|
$archive_tasks = array();
|
||||||
|
} else {
|
||||||
|
$archive_tasks = $archive_query->execute();
|
||||||
|
}
|
||||||
|
|
||||||
$tasks =
|
$tasks =
|
||||||
mpull($active_tasks, null, 'getID') +
|
mpull($active_tasks, null, 'getID') +
|
||||||
mpull($archive_tasks, null, 'getID');
|
mpull($archive_tasks, null, 'getID');
|
||||||
|
|
|
@ -61,6 +61,22 @@ final class PhabricatorKeyboardRemarkupRule extends PhutilRemarkupRule {
|
||||||
'escape',
|
'escape',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Enter'),
|
||||||
|
'symbol' => "\xE2\x8F\x8E",
|
||||||
|
'aliases' => array(
|
||||||
|
'enter',
|
||||||
|
'return',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Control'),
|
||||||
|
'symbol' => "\xE2\x8C\x83",
|
||||||
|
'aliases' => array(
|
||||||
|
'ctrl',
|
||||||
|
'control',
|
||||||
|
),
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'name' => pht('Up'),
|
'name' => pht('Up'),
|
||||||
'symbol' => "\xE2\x86\x91",
|
'symbol' => "\xE2\x86\x91",
|
||||||
|
|
|
@ -234,7 +234,7 @@ abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
|
||||||
// T11773 for some discussion.
|
// T11773 for some discussion.
|
||||||
$this->isOverheated = false;
|
$this->isOverheated = false;
|
||||||
|
|
||||||
// See T13386. If we on an old offset-based paging workflow, we need
|
// See T13386. If we are on an old offset-based paging workflow, we need
|
||||||
// to base the overheating limit on both the offset and limit.
|
// to base the overheating limit on both the offset and limit.
|
||||||
$overheat_limit = $need * 10;
|
$overheat_limit = $need * 10;
|
||||||
$total_seen = 0;
|
$total_seen = 0;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
* @task validation Validation
|
* @task validation Validation
|
||||||
* @task ratelimit Rate Limiting
|
* @task ratelimit Rate Limiting
|
||||||
* @task phases Startup Phase Timers
|
* @task phases Startup Phase Timers
|
||||||
|
* @task request-path Request Path
|
||||||
*/
|
*/
|
||||||
final class PhabricatorStartup {
|
final class PhabricatorStartup {
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ final class PhabricatorStartup {
|
||||||
private static $phases;
|
private static $phases;
|
||||||
|
|
||||||
private static $limits = array();
|
private static $limits = array();
|
||||||
|
private static $requestPath;
|
||||||
|
|
||||||
|
|
||||||
/* -( Accessing Request Information )-------------------------------------- */
|
/* -( Accessing Request Information )-------------------------------------- */
|
||||||
|
@ -119,6 +121,7 @@ final class PhabricatorStartup {
|
||||||
self::$phases = array();
|
self::$phases = array();
|
||||||
|
|
||||||
self::$accessLog = null;
|
self::$accessLog = null;
|
||||||
|
self::$requestPath = null;
|
||||||
|
|
||||||
static $registered;
|
static $registered;
|
||||||
if (!$registered) {
|
if (!$registered) {
|
||||||
|
@ -140,7 +143,7 @@ final class PhabricatorStartup {
|
||||||
|
|
||||||
self::normalizeInput();
|
self::normalizeInput();
|
||||||
|
|
||||||
self::verifyRewriteRules();
|
self::readRequestPath();
|
||||||
|
|
||||||
self::beginOutputCapture();
|
self::beginOutputCapture();
|
||||||
}
|
}
|
||||||
|
@ -552,17 +555,29 @@ final class PhabricatorStartup {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @task validation
|
* @task request-path
|
||||||
*/
|
*/
|
||||||
private static function verifyRewriteRules() {
|
private static function readRequestPath() {
|
||||||
|
|
||||||
|
// See T13575. The request path may be provided in:
|
||||||
|
//
|
||||||
|
// - the "$_GET" parameter "__path__" (normal for Apache and nginx); or
|
||||||
|
// - the "$_SERVER" parameter "REQUEST_URI" (normal for the PHP builtin
|
||||||
|
// webserver).
|
||||||
|
//
|
||||||
|
// Locate it wherever it is, and store it for later use. Note that writing
|
||||||
|
// to "$_REQUEST" here won't always work, because later code may rebuild
|
||||||
|
// "$_REQUEST" from other sources.
|
||||||
|
|
||||||
if (isset($_REQUEST['__path__']) && strlen($_REQUEST['__path__'])) {
|
if (isset($_REQUEST['__path__']) && strlen($_REQUEST['__path__'])) {
|
||||||
|
self::setRequestPath($_REQUEST['__path__']);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compatibility with PHP 5.4+ built-in web server.
|
||||||
if (php_sapi_name() == 'cli-server') {
|
if (php_sapi_name() == 'cli-server') {
|
||||||
// Compatibility with PHP 5.4+ built-in web server.
|
$path = parse_url($_SERVER['REQUEST_URI']);
|
||||||
$url = parse_url($_SERVER['REQUEST_URI']);
|
self::setRequestPath($path['path']);
|
||||||
$_REQUEST['__path__'] = $url['path'];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +595,30 @@ final class PhabricatorStartup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task request-path
|
||||||
|
*/
|
||||||
|
public static function getRequestPath() {
|
||||||
|
$path = self::$requestPath;
|
||||||
|
|
||||||
|
if ($path === null) {
|
||||||
|
self::didFatal(
|
||||||
|
'Request attempted to access request path, but no request path is '.
|
||||||
|
'available for this request. You may be calling web request code '.
|
||||||
|
'from a non-request context, or your webserver may not be passing '.
|
||||||
|
'a request path to Phabricator in a format that it understands.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task request-path
|
||||||
|
*/
|
||||||
|
public static function setRequestPath($path) {
|
||||||
|
self::$requestPath = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Rate Limiting )------------------------------------------------------ */
|
/* -( Rate Limiting )------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue