1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-09-19 16:38:51 +02:00

(stable) Promote 2020 Week 37

This commit is contained in:
epriestley 2020-09-18 12:00:08 -07:00
commit 68dba1a2c6
14 changed files with 99 additions and 37 deletions

View file

@ -72,15 +72,18 @@ final class ArcanistConduitCallFuture
}
protected function didReceiveException($exception) {
switch ($exception->getErrorCode()) {
case 'ERR-INVALID-SESSION':
if (!$this->getEngine()->getConduitToken()) {
$this->raiseLoginRequired();
}
break;
case 'ERR-INVALID-AUTH':
$this->raiseInvalidAuth();
break;
if ($exception instanceof ConduitClientException) {
switch ($exception->getErrorCode()) {
case 'ERR-INVALID-SESSION':
if (!$this->getEngine()->getConduitToken()) {
$this->raiseLoginRequired();
}
break;
case 'ERR-INVALID-AUTH':
$this->raiseInvalidAuth();
break;
}
}
throw $exception;

View file

@ -62,9 +62,14 @@ final class ConduitFuture extends FutureProxy {
}
if ($data['error_code']) {
$message = pht(
'<%s> %s',
$this->conduitMethod,
$data['error_info']);
throw new ConduitClientException(
$data['error_code'],
$data['error_info']);
$message);
}
$result = $data['result'];

View file

@ -194,7 +194,14 @@ final class FutureIterator
* @task iterator
*/
public function next() {
$this->key = null;
// See T13572. If we preivously resolved and returned a Future, release
// it now. This prevents us from holding Futures indefinitely when callers
// like FuturePool build long-lived iterators and keep adding new Futures
// to them.
if ($this->key !== null) {
unset($this->futures[$this->key]);
$this->key = null;
}
$this->updateWorkingSet();

View file

@ -47,7 +47,7 @@ function exec_manual($cmd /* , ... */) {
*/
function phutil_passthru($cmd /* , ... */) {
$args = func_get_args();
return newv('PhutilExecPassthru', $args)->execute();
return newv('PhutilExecPassthru', $args)->resolve();
}

View file

@ -132,7 +132,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
* @return string|false
*/
public static function loadContent($uri, $timeout = null) {
$future = new HTTPSFuture($uri);
$future = new self($uri);
if ($timeout !== null) {
$future->setTimeout($timeout);
}
@ -151,7 +151,8 @@ final class HTTPSFuture extends BaseHTTPFuture {
throw new Exception(
pht(
'Specified download path "%s" already exists, refusing to '.
'overwrite.'));
'overwrite.',
$download_path));
}
return $this;

View file

@ -27,7 +27,9 @@ final class ArcanistHardpointList
pht(
'Hardpoint (at index "%s") has the same key ("%s") as an earlier '.
'hardpoint. Each hardpoint must have a key that is unique '.
'among hardpoints on the object.'));
'among hardpoints on the object.',
$idx,
$key));
}
$map[$key] = $hardpoint;

View file

@ -1459,6 +1459,7 @@ abstract class ArcanistLandEngine
'Merge strategy "%s" specified in "%s" configuration is '.
'unknown. Supported merge strategies are: %s.',
$strategy,
$this->getStrategyConfigurationKey(),
$strategy_list));
}

View file

@ -82,7 +82,12 @@ final class ArcanistFormattedStringXHPASTLinterRule
}
$format = $parameters->getChildByIndex($start);
if ($format->getTypeName() != 'n_STRING_SCALAR') {
if (!$format->isConstantString()) {
// TODO: When this parameter is not a constant string, the call may
// be unsafe. We should make some attempt to warn about this for
// "qsprintf()" and other security-sensitive functions.
continue;
}

View file

@ -11,12 +11,28 @@ fprintf(null, 'x');
queryfx(null, 'x', 'y');
foobar(null, null, '%s');
pht('x %s y');
pht('x %s y'.'z');
pht(<<<HEREDOC
a b c
HEREDOC
);
pht(<<<HEREDOC
a %s c
HEREDOC
);
~~~~~~~~~~
error:3:1:XHP54:Formatted String
error:7:1:XHP54:Formatted String
error:8:1:XHP54:Formatted String
error:11:1:XHP54:Formatted String
error:13:1:XHP54:Formatted String
error:15:1:XHP54:Formatted String
error:16:1:XHP54:Formatted String
error:23:1:XHP54:Formatted String
~~~~~~~~~~
~~~~~~~~~~
{

View file

@ -33,7 +33,9 @@ final class XHPASTNode extends AASTNode {
return $this->getChildByIndex(0)->evalStatic();
break;
case 'n_STRING_SCALAR':
return (string)$this->getStringLiteralValue();
return phutil_string_cast($this->getStringLiteralValue());
case 'n_HEREDOC':
return phutil_string_cast($this->getStringLiteralValue());
case 'n_NUMERIC_SCALAR':
$value = $this->getSemanticString();
if (preg_match('/^0x/i', $value)) {
@ -186,31 +188,51 @@ final class XHPASTNode extends AASTNode {
}
public function getStringLiteralValue() {
if ($this->getTypeName() != 'n_STRING_SCALAR') {
return null;
$type_name = $this->getTypeName();
if ($type_name === 'n_HEREDOC') {
$value = $this->getSemanticString();
$value = phutil_split_lines($value);
$value = array_slice($value, 1, -1);
$value = implode('', $value);
// Strip the final newline from value, this isn't part of the string
// literal.
$value = preg_replace('/(\r|\n|\r\n)\z/', '', $value);
return $this->newStringLiteralFromSemanticString($value);
}
$value = $this->getSemanticString();
$type = $value[0];
$value = preg_replace('/^b?[\'"]|[\'"]$/i', '', $value);
$esc = false;
$len = strlen($value);
$out = '';
if ($type_name === 'n_STRING_SCALAR') {
$value = $this->getSemanticString();
$type = $value[0];
$value = preg_replace('/^b?[\'"]|[\'"]$/i', '', $value);
if ($type == "'") {
// Single quoted strings treat everything as a literal except "\\" and
// "\'".
return str_replace(
array('\\\\', '\\\''),
array('\\', "'"),
$value);
if ($type == "'") {
// Single quoted strings treat everything as a literal except "\\" and
// "\'".
return str_replace(
array('\\\\', '\\\''),
array('\\', "'"),
$value);
}
return $this->newStringLiteralFromSemanticString($value);
}
return null;
}
private function newStringLiteralFromSemanticString($value) {
// Double quoted strings treat "\X" as a literal if X isn't specifically
// a character which needs to be escaped -- e.g., "\q" and "\'" are
// literally "\q" and "\'". stripcslashes() is too aggressive, so find
// all these under-escaped backslashes and escape them.
$len = strlen($value);
$esc = false;
$out = '';
for ($ii = 0; $ii < $len; $ii++) {
$c = $value[$ii];
if ($esc) {

View file

@ -778,7 +778,7 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
pht(
"'%s' has been amended with 'Differential Revision:', ".
"as specified by '%s' in your %s 'base' configuration.",
'.'.
'.',
$rule,
$source));
// NOTE: This should be safe because Mercurial doesn't support

View file

@ -553,6 +553,7 @@ final class ArcanistRuntime {
'workflow in a given toolset must have a unique name.',
get_class($workflow),
get_class($map[$key]),
$key,
get_class($toolset),
$toolset->getToolsetKey()));
}

View file

@ -72,8 +72,8 @@ final class ArcanistAliasEngine
pht(
'Configuration source ("%s") defines an invalid alias, which '.
'will be ignored: %s',
$alias->getConfigurationSource()->getSourceDisplayName()),
$exception->getMessage());
$alias->getConfigurationSource()->getSourceDisplayName(),
$exception->getMessage()));
}
$command = array_shift($argv);

View file

@ -35,8 +35,7 @@ EOTEXT
'help' => pht(
"Close only if the repository is untracked and the revision is ".
"accepted. Continue even if the close can't happen. This is a soft ".
"version of '' used by other workflows.",
'close-revision'),
"version of 'close-revision' used by other workflows."),
),
'quiet' => array(
'help' => pht('Do not print a success message.'),