1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2025-01-16 09:41:06 +01:00

(stable) Promote 2015 Week 52

This commit is contained in:
epriestley 2015-12-26 03:19:54 -08:00
commit 3dbc1418ff
47 changed files with 809 additions and 285 deletions

View file

@ -74,17 +74,27 @@ $config = null;
$workflow = null; $workflow = null;
try { try {
if ($config_trace_mode) {
echo tsprintf(
"**<bg:magenta> %s </bg>** %s\n",
pht('ARGV'),
csprintf('%Ls', $original_argv));
$console->writeLog( $libraries = array(
"%s\n", 'phutil',
'arcanist',
);
foreach ($libraries as $library_name) {
echo tsprintf(
"**<bg:magenta> %s </bg>** %s\n",
pht('LOAD'),
pht( pht(
"libphutil loaded from '%s'.", 'Loaded "%s" from "%s".',
phutil_get_library_root('phutil'))); $library_name,
$console->writeLog( phutil_get_library_root($library_name)));
"%s\n", }
pht( }
"arcanist loaded from '%s'.",
phutil_get_library_root('arcanist')));
if (!$args) { if (!$args) {
if ($help) { if ($help) {

View file

@ -1,6 +1,3 @@
#!/bin/sh #!/bin/sh
diff "$@" diff "$@" || exit 1
if [ "$?" = "2" ]; then
exit 1
fi

View file

@ -96,6 +96,8 @@ phutil_register_library_map(array(
'ArcanistCppcheckLinterTestCase' => 'lint/linter/__tests__/ArcanistCppcheckLinterTestCase.php', 'ArcanistCppcheckLinterTestCase' => 'lint/linter/__tests__/ArcanistCppcheckLinterTestCase.php',
'ArcanistCpplintLinter' => 'lint/linter/ArcanistCpplintLinter.php', 'ArcanistCpplintLinter' => 'lint/linter/ArcanistCpplintLinter.php',
'ArcanistCpplintLinterTestCase' => 'lint/linter/__tests__/ArcanistCpplintLinterTestCase.php', 'ArcanistCpplintLinterTestCase' => 'lint/linter/__tests__/ArcanistCpplintLinterTestCase.php',
'ArcanistCurlyBraceArrayIndexXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCurlyBraceArrayIndexXHPASTLinterRule.php',
'ArcanistCurlyBraceArrayIndexXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCurlyBraceArrayIndexXHPASTLinterRuleTestCase.php',
'ArcanistDeclarationParenthesesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php', 'ArcanistDeclarationParenthesesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDeclarationParenthesesXHPASTLinterRule.php',
'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase.php', 'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase.php',
'ArcanistDefaultParametersXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDefaultParametersXHPASTLinterRule.php', 'ArcanistDefaultParametersXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDefaultParametersXHPASTLinterRule.php',
@ -194,6 +196,8 @@ phutil_register_library_map(array(
'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidModifiersXHPASTLinterRuleTestCase.php', 'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidModifiersXHPASTLinterRuleTestCase.php',
'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidOctalNumericScalarXHPASTLinterRule.php', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidOctalNumericScalarXHPASTLinterRule.php',
'ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase.php', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase.php',
'ArcanistIsAShouldBeInstanceOfXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistIsAShouldBeInstanceOfXHPASTLinterRule.php',
'ArcanistIsAShouldBeInstanceOfXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistIsAShouldBeInstanceOfXHPASTLinterRuleTestCase.php',
'ArcanistJSHintLinter' => 'lint/linter/ArcanistJSHintLinter.php', 'ArcanistJSHintLinter' => 'lint/linter/ArcanistJSHintLinter.php',
'ArcanistJSHintLinterTestCase' => 'lint/linter/__tests__/ArcanistJSHintLinterTestCase.php', 'ArcanistJSHintLinterTestCase' => 'lint/linter/__tests__/ArcanistJSHintLinterTestCase.php',
'ArcanistJSONLintLinter' => 'lint/linter/ArcanistJSONLintLinter.php', 'ArcanistJSONLintLinter' => 'lint/linter/ArcanistJSONLintLinter.php',
@ -270,6 +274,8 @@ phutil_register_library_map(array(
'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPOpenTagXHPASTLinterRuleTestCase.php', 'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPOpenTagXHPASTLinterRuleTestCase.php',
'ArcanistPHPShortTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPShortTagXHPASTLinterRule.php', 'ArcanistPHPShortTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPShortTagXHPASTLinterRule.php',
'ArcanistPHPShortTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPShortTagXHPASTLinterRuleTestCase.php', 'ArcanistPHPShortTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPShortTagXHPASTLinterRuleTestCase.php',
'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPaamayimNekudotayimSpacingXHPASTLinterRule.php',
'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPaamayimNekudotayimSpacingXHPASTLinterRuleTestCase.php',
'ArcanistParentMemberReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParentMemberReferenceXHPASTLinterRule.php', 'ArcanistParentMemberReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParentMemberReferenceXHPASTLinterRule.php',
'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParentMemberReferenceXHPASTLinterRuleTestCase.php', 'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParentMemberReferenceXHPASTLinterRuleTestCase.php',
'ArcanistParenthesesSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParenthesesSpacingXHPASTLinterRule.php', 'ArcanistParenthesesSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParenthesesSpacingXHPASTLinterRule.php',
@ -315,6 +321,8 @@ phutil_register_library_map(array(
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php', 'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php', 'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php',
'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php', 'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php',
'ArcanistSelfClassReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSelfClassReferenceXHPASTLinterRule.php',
'ArcanistSelfClassReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSelfClassReferenceXHPASTLinterRuleTestCase.php',
'ArcanistSelfMemberReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSelfMemberReferenceXHPASTLinterRule.php', 'ArcanistSelfMemberReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSelfMemberReferenceXHPASTLinterRule.php',
'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase.php', 'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase.php',
'ArcanistSemicolonSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSemicolonSpacingXHPASTLinterRule.php', 'ArcanistSemicolonSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSemicolonSpacingXHPASTLinterRule.php',
@ -502,6 +510,8 @@ phutil_register_library_map(array(
'ArcanistCppcheckLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCppcheckLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistCpplintLinter' => 'ArcanistExternalLinter', 'ArcanistCpplintLinter' => 'ArcanistExternalLinter',
'ArcanistCpplintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCpplintLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistCurlyBraceArrayIndexXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistCurlyBraceArrayIndexXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistDeclarationParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDeclarationParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistDefaultParametersXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDefaultParametersXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@ -600,6 +610,8 @@ phutil_register_library_map(array(
'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistIsAShouldBeInstanceOfXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistIsAShouldBeInstanceOfXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistJSHintLinter' => 'ArcanistExternalLinter', 'ArcanistJSHintLinter' => 'ArcanistExternalLinter',
'ArcanistJSHintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistJSHintLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistJSONLintLinter' => 'ArcanistExternalLinter', 'ArcanistJSONLintLinter' => 'ArcanistExternalLinter',
@ -676,6 +688,8 @@ phutil_register_library_map(array(
'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistPHPShortTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPShortTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistPHPShortTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPShortTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistParentMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistParentMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistParenthesesSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistParenthesesSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@ -721,6 +735,8 @@ phutil_register_library_map(array(
'ArcanistRubyLinter' => 'ArcanistExternalLinter', 'ArcanistRubyLinter' => 'ArcanistExternalLinter',
'ArcanistRubyLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistRubyLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter', 'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
'ArcanistSelfClassReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistSelfClassReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistSelfMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSelfMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistSemicolonSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSemicolonSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',

View file

@ -29,9 +29,7 @@ final class ArcanistGitLandEngine
$this->updateWorkingCopy(); $this->updateWorkingCopy();
if ($this->getShouldHold()) { if ($this->getShouldHold()) {
$this->writeInfo( $this->didHoldChanges();
pht('HOLD'),
pht('Holding change locally, it has not been pushed.'));
} else { } else {
$this->pushChange(); $this->pushChange();
$this->reconcileLocalState(); $this->reconcileLocalState();
@ -542,4 +540,41 @@ final class ArcanistGitLandEngine
); );
} }
private function didHoldChanges() {
$this->writeInfo(
pht('HOLD'),
pht(
'Holding change locally, it has not been pushed.'));
$push_command = csprintf(
'$ git push -- %R %R:%R',
$this->getTargetRemote(),
$this->mergedRef,
$this->getTargetOnto());
$restore_command = csprintf(
'$ git checkout %R --',
$this->localRef);
echo tsprintf(
"\n%s\n\n".
"%s\n\n".
" %s\n\n".
"%s\n\n".
" %s\n\n".
"%s\n",
pht(
'This local working copy now contains the merged changes in a '.
'detached state.'),
pht('You can push the changes manually with this command:'),
$push_command,
pht(
'You can go back to how things were before you ran `arc land` with '.
'this command:'),
$restore_command,
pht(
'Local branches have not been changed, and are still in exactly the '.
'same state as before.'));
}
} }

View file

@ -24,14 +24,6 @@ final class ArcanistBraceFormattingXHPASTLinterRule
if (!$before) { if (!$before) {
$first = head($tokens); $first = head($tokens);
// Only insert the space if we're after a closing parenthesis. If
// we're in a construct like "else{}", other rules will insert space
// after the 'else' correctly.
$prev = $first->getPrevToken();
if (!$prev || $prev->getValue() !== ')') {
continue;
}
$this->raiseLintAtToken( $this->raiseLintAtToken(
$first, $first,
pht( pht(

View file

@ -46,7 +46,7 @@ final class ArcanistClassFilenameMismatchXHPASTLinterRule
$this->raiseLintAtNode( $this->raiseLintAtNode(
$decl_name, $decl_name,
pht( pht(
"The name of this file differs from the name of the ". 'The name of this file differs from the name of the '.
'class or interface it declares. Rename the file to `%s`.', 'class or interface it declares. Rename the file to `%s`.',
$rename)); $rename));
} }

View file

@ -0,0 +1,56 @@
<?php
final class ArcanistCurlyBraceArrayIndexXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 119;
public function getLintName() {
return pht('Curly Brace Array Index');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$index_accesses = $root->selectDescendantsOfType('n_INDEX_ACCESS');
foreach ($index_accesses as $index_access) {
$tokens = $index_access->getChildByIndex(1)->getTokens();
if (!$tokens) {
continue;
}
$left_brace = head($tokens)->getPrevToken();
while (!$left_brace->isSemantic()) {
$left_brace = $left_brace->getPrevToken();
}
$right_brace = last($tokens)->getNextToken();
while (!$right_brace->isSemantic()) {
$right_brace = $right_brace->getNextToken();
}
if ($left_brace->getValue() == '{' || $right_brace->getValue() == '}') {
$replacement = null;
foreach ($index_access->getTokens() as $token) {
if ($token === $left_brace) {
$replacement .= '[';
} else if ($token === $right_brace) {
$replacement .= ']';
} else {
$replacement .= $token->getValue();
}
}
$this->raiseLintAtNode(
$index_access,
pht('Use `%s` instead of `%s`.', "\$x['key']", "\$x{'key'}"),
$replacement);
}
}
}
}

View file

@ -193,7 +193,7 @@ final class ArcanistImplicitFallthroughXHPASTLinterRule
'This `%s` or `%s` has a nonempty block which does not end '. 'This `%s` or `%s` has a nonempty block which does not end '.
'with `%s`, `%s`, `%s`, `%s` or `%s`. Did you forget to add '. 'with `%s`, `%s`, `%s`, `%s` or `%s`. Did you forget to add '.
'one of those? If you intend to fall through, add a `%s` '. 'one of those? If you intend to fall through, add a `%s` '.
"comment to silence this warning.", 'comment to silence this warning.',
'case', 'case',
'default', 'default',
'break', 'break',

View file

@ -0,0 +1,69 @@
<?php
final class ArcanistIsAShouldBeInstanceOfXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 111;
public function getLintName() {
return pht('`%s` Should Be `%s`', 'is_a', 'instanceof');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_ADVICE;
}
public function process(XHPASTNode $root) {
$calls = $this->getFunctionCalls($root, array('is_a'));
foreach ($calls as $call) {
$parameters = $call->getChildOfType(1, 'n_CALL_PARAMETER_LIST');
if (count($parameters->getChildren()) > 2) {
// If the `$allow_string` parameter is `true` then the `instanceof`
// operator cannot be used. Evaluating whether an expression is truthy
// or falsely is hard, and so we only check that the `$allow_string`
// parameter is either absent or literally `false`.
$allow_string = $parameters->getChildByIndex(2);
if (strtolower($allow_string->getConcreteString()) != 'false') {
continue;
}
}
$object = $parameters->getChildByIndex(0);
$class = $parameters->getChildByIndex(1);
switch ($class->getTypeName()) {
case 'n_STRING_SCALAR':
$replacement = stripslashes(
substr($class->getConcreteString(), 1, -1));
break;
case 'n_VARIABLE':
$replacement = $class->getConcreteString();
break;
default:
$replacement = null;
break;
}
$this->raiseLintAtNode(
$call,
pht(
'Use `%s` instead of `%s`. The former is a language '.
'construct whereas the latter is a function call, which '.
'has additional overhead.',
'instanceof',
'is_a'),
($replacement === null)
? null
: sprintf(
'%s instanceof %s',
$object->getConcreteString(),
$replacement));
}
}
}

View file

@ -15,73 +15,98 @@ final class ArcanistKeywordCasingXHPASTLinterRule
public function process(XHPASTNode $root) { public function process(XHPASTNode $root) {
$keywords = $root->selectTokensOfTypes(array( $keywords = $root->selectTokensOfTypes(array(
'T_REQUIRE_ONCE', 'T_ABSTRACT',
'T_REQUIRE', 'T_ARRAY',
'T_AS',
'T_BREAK',
'T_CALLABLE',
'T_CASE',
'T_CATCH',
'T_CLASS',
'T_CLONE',
'T_CONST',
'T_CONTINUE',
'T_DECLARE',
'T_DEFAULT',
'T_DO',
'T_ECHO',
'T_ELSE',
'T_ELSEIF',
'T_EMPTY',
'T_ENDDECLARE',
'T_ENDFOR',
'T_ENDFOREACH',
'T_ENDIF',
'T_ENDSWITCH',
'T_ENDWHILE',
'T_EVAL', 'T_EVAL',
'T_INCLUDE_ONCE', 'T_EXIT',
'T_EXTENDS',
'T_FINAL',
'T_FINALLY',
'T_FOR',
'T_FOREACH',
'T_FUNCTION',
'T_GLOBAL',
'T_GOTO',
'T_HALT_COMPILER',
'T_IF',
'T_IMPLEMENTS',
'T_INCLUDE', 'T_INCLUDE',
'T_INCLUDE_ONCE',
'T_INSTANCEOF',
'T_INSTEADOF',
'T_INTERFACE',
'T_ISSET',
'T_LIST',
'T_LOGICAL_AND',
'T_LOGICAL_OR', 'T_LOGICAL_OR',
'T_LOGICAL_XOR', 'T_LOGICAL_XOR',
'T_LOGICAL_AND',
'T_PRINT',
'T_INSTANCEOF',
'T_CLONE',
'T_NEW',
'T_EXIT',
'T_IF',
'T_ELSEIF',
'T_ELSE',
'T_ENDIF',
'T_ECHO',
'T_DO',
'T_WHILE',
'T_ENDWHILE',
'T_FOR',
'T_ENDFOR',
'T_FOREACH',
'T_ENDFOREACH',
'T_DECLARE',
'T_ENDDECLARE',
'T_AS',
'T_SWITCH',
'T_ENDSWITCH',
'T_CASE',
'T_DEFAULT',
'T_BREAK',
'T_CONTINUE',
'T_GOTO',
'T_FUNCTION',
'T_CONST',
'T_RETURN',
'T_TRY',
'T_CATCH',
'T_THROW',
'T_USE',
'T_GLOBAL',
'T_PUBLIC',
'T_PROTECTED',
'T_PRIVATE',
'T_FINAL',
'T_ABSTRACT',
'T_STATIC',
'T_VAR',
'T_UNSET',
'T_ISSET',
'T_EMPTY',
'T_HALT_COMPILER',
'T_CLASS',
'T_INTERFACE',
'T_EXTENDS',
'T_IMPLEMENTS',
'T_LIST',
'T_ARRAY',
'T_NAMESPACE', 'T_NAMESPACE',
'T_INSTEADOF', 'T_NEW',
'T_CALLABLE', 'T_PRINT',
'T_PRIVATE',
'T_PROTECTED',
'T_PUBLIC',
'T_REQUIRE',
'T_REQUIRE_ONCE',
'T_RETURN',
'T_STATIC',
'T_SWITCH',
'T_THROW',
'T_TRAIT', 'T_TRAIT',
'T_TRY',
'T_UNSET',
'T_USE',
'T_VAR',
'T_WHILE',
'T_YIELD', 'T_YIELD',
'T_FINALLY',
)); ));
// Because there is no `T_SELF` or `T_PARENT` token.
$class_static_accesses = $root
->selectDescendantsOfType('n_CLASS_DECLARATION')
->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
foreach ($class_static_accesses as $class_static_access) {
$class_ref = $class_static_access->getChildByIndex(0);
switch (strtolower($class_ref->getConcreteString())) {
case 'parent':
case 'self':
$tokens = $class_ref->getTokens();
if (count($tokens) > 1) {
throw new Exception(
pht(
'Unexpected tokens whilst processing `%s`.',
__CLASS__));
}
$keywords[] = head($tokens);
break;
}
}
foreach ($keywords as $keyword) { foreach ($keywords as $keyword) {
$value = $keyword->getValue(); $value = $keyword->getValue();

View file

@ -0,0 +1,40 @@
<?php
final class ArcanistPaamayimNekudotayimSpacingXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 96;
public function getLintName() {
return pht('Paamayim Nekudotayim Spacing');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$double_colons = $root->selectTokensOfType('T_PAAMAYIM_NEKUDOTAYIM');
foreach ($double_colons as $double_colon) {
$tokens = $double_colon->getNonsemanticTokensBefore() +
$double_colon->getNonsemanticTokensAfter();
foreach ($tokens as $token) {
if ($token->isAnyWhitespace()) {
if (strpos($token->getValue(), "\n") !== false) {
continue;
}
$this->raiseLintAtToken(
$token,
pht(
'Unnecessary whitespace around paamayim nekudotayim '.
'(double colon) operator.'),
'');
}
}
}
}
}

View file

@ -0,0 +1,45 @@
<?php
final class ArcanistSelfClassReferenceXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 95;
public function getLintName() {
return pht('Self Class Reference');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$class_declarations = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
foreach ($class_declarations as $class_declaration) {
$class_name = $class_declaration
->getChildOfType(1, 'n_CLASS_NAME')
->getConcreteString();
$instantiations = $class_declaration
->selectDescendantsOfType('n_NEW');
foreach ($instantiations as $instantiation) {
$type = $instantiation->getChildByIndex(0);
if ($type->getTypeName() != 'n_CLASS_NAME') {
continue;
}
if (strtolower($type->getConcreteString()) == strtolower($class_name)) {
$this->raiseLintAtNode(
$type,
pht(
'Use `%s` to instantiate the current class.',
'self'),
'self');
}
}
}
}
}

View file

@ -10,7 +10,7 @@ final class ArcanistSelfMemberReferenceXHPASTLinterRule
} }
public function getLintSeverity() { public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_ADVICE; return ArcanistLintSeverity::SEVERITY_WARNING;
} }
public function process(XHPASTNode $root) { public function process(XHPASTNode $root) {
@ -20,14 +20,11 @@ final class ArcanistSelfMemberReferenceXHPASTLinterRule
$class_name = $class_declaration $class_name = $class_declaration
->getChildOfType(1, 'n_CLASS_NAME') ->getChildOfType(1, 'n_CLASS_NAME')
->getConcreteString(); ->getConcreteString();
$class_static_accesses = $class_declaration $class_static_accesses = $class_declaration
->selectDescendantsOfType('n_CLASS_STATIC_ACCESS'); ->selectDescendantsOfType('n_CLASS_STATIC_ACCESS');
$closures = $this->getAnonymousClosures($class_declaration); $closures = $this->getAnonymousClosures($class_declaration);
foreach ($class_static_accesses as $class_static_access) { foreach ($class_static_accesses as $class_static_access) {
$double_colons = $class_static_access
->selectTokensOfType('T_PAAMAYIM_NEKUDOTAYIM');
$class_ref = $class_static_access->getChildByIndex(0); $class_ref = $class_static_access->getChildByIndex(0);
if ($class_ref->getTypeName() != 'n_CLASS_NAME') { if ($class_ref->getTypeName() != 'n_CLASS_NAME') {
@ -54,43 +51,6 @@ final class ArcanistSelfMemberReferenceXHPASTLinterRule
'self'); 'self');
} }
} }
static $self_refs = array(
'parent',
'self',
'static',
);
if (!in_array(strtolower($class_ref_name), $self_refs)) {
continue;
}
if ($class_ref_name != strtolower($class_ref_name)) {
$this->raiseLintAtNode(
$class_ref,
pht('PHP keywords should be lowercase.'),
strtolower($class_ref_name));
}
}
}
$double_colons = $root->selectTokensOfType('T_PAAMAYIM_NEKUDOTAYIM');
foreach ($double_colons as $double_colon) {
$tokens = $double_colon->getNonsemanticTokensBefore() +
$double_colon->getNonsemanticTokensAfter();
foreach ($tokens as $token) {
if ($token->isAnyWhitespace()) {
if (strpos($token->getValue(), "\n") !== false) {
continue;
}
$this->raiseLintAtToken(
$token,
pht('Unnecessary whitespace around double colon operator.'),
'');
}
} }
} }
} }

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistCurlyBraceArrayIndexXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/curly-brace-array-index/');
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistIsAShouldBeInstanceOfXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/is_a-should-be-instanceof/');
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistPaamayimNekudotayimSpacingXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/paamayim-nekudotayim-spacing/');
}
}

View file

@ -0,0 +1,10 @@
<?php
final class ArcanistSelfClassReferenceXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(dirname(__FILE__).'/self-class-reference/');
}
}

View file

@ -1,87 +0,0 @@
<?php
function f() {
}
function g()
{
}
if (1)
{}
foreach (x() as $y)
{}
while (1)
{}
switch (1)
{}
try
{}
catch (Exception $x)
{}
function h(){}
if ($x) foo();
else bar();
do baz(); while ($x);
if ($x) {}
else if ($y) {}
else {}
if ($x) {}else{}
declare(ticks = 1);
~~~~~~~~~~
warning:7:13
warning:12:7
warning:15:20
warning:18:10
warning:21:11
warning:24:4
warning:26:21
warning:29:13
warning:30:9
warning:31:6
warning:32:4
warning:34:11
warning:35:16
warning:38:11
~~~~~~~~~~
<?php
function f() {
}
function g() {
}
if (1) {}
foreach (x() as $y) {}
while (1) {}
switch (1) {}
try {}
catch (Exception $x) {}
function h() {}
if ($x) foo();
else bar();
do baz(); while ($x);
if ($x) {} else if ($y) {} else {}
if ($x) {} else{}
declare(ticks = 1);

View file

@ -0,0 +1,14 @@
<?php
class SomeClass {}
class SomeOtherClass{}
class YetAnotherClass extends SomeClass{}
~~~~~~~~~~
warning:4:21
warning:5:40
~~~~~~~~~~
<?php
class SomeClass {}
class SomeOtherClass {}
class YetAnotherClass extends SomeClass {}

View file

@ -0,0 +1,53 @@
<?php
if (1)
{}
foreach (x() as $y)
{}
while (1)
{}
switch (1)
{}
if ($x) foo();
else bar();
do baz(); while ($x);
if ($x) {}
else if ($y) {}
else {}
if ($x) {}else{}
~~~~~~~~~~
warning:3:7
warning:6:20
warning:9:10
warning:12:11
warning:15:9
warning:16:6
warning:17:4
warning:19:11
warning:20:16
warning:23:11
warning:23:15
~~~~~~~~~~
<?php
if (1) {}
foreach (x() as $y) {}
while (1) {}
switch (1) {}
if ($x) foo();
else bar();
do baz(); while ($x);
if ($x) {} else if ($y) {} else {}
if ($x) {} else {}

View file

@ -0,0 +1,4 @@
<?php
declare(ticks = 1);
~~~~~~~~~~

View file

@ -0,0 +1,27 @@
<?php
function f() {
}
function g()
{
}
function h(){}
~~~~~~~~~~
warning:7:13
warning:12:13
~~~~~~~~~~
<?php
function f() {
}
function g() {
}
function h() {}

View file

@ -0,0 +1,14 @@
<?php
try
{}
catch (Exception $x)
{}
~~~~~~~~~~
warning:3:4
warning:5:21
~~~~~~~~~~
<?php
try {}
catch (Exception $x) {}

View file

@ -0,0 +1,9 @@
<?php
$x['key'];
$y{'key'};
~~~~~~~~~~
warning:3:1
~~~~~~~~~~
<?php
$x['key'];
$y['key'];

View file

@ -0,0 +1,3 @@
<?php
$x[] = 'value';
~~~~~~~~~~

View file

@ -0,0 +1,7 @@
<?php
$x[$y{'key'}];
~~~~~~~~~~
warning:2:4
~~~~~~~~~~
<?php
$x[$y['key']];

View file

@ -0,0 +1,7 @@
<?php
$x { 'key' /* comment */ };
~~~~~~~~~~
warning:2:1
~~~~~~~~~~
<?php
$x [ 'key' /* comment */ ];

View file

@ -0,0 +1,3 @@
<?php
is_a('SubClass', 'BaseClass', true);
~~~~~~~~~~

View file

@ -0,0 +1,16 @@
<?php
is_a($x, $y);
is_a($x, 'SomeClass');
is_a($x, '\\SomeClass');
is_a($x, '\\'.'Some'.'Class');
~~~~~~~~~~
advice:2:1
advice:3:1
advice:4:1
advice:5:1
~~~~~~~~~~
<?php
$x instanceof $y;
$x instanceof SomeClass;
$x instanceof \SomeClass;
is_a($x, '\\'.'Some'.'Class');

View file

@ -0,0 +1,25 @@
<?php
class Foo extends Bar {
public static function doSomething() {
return PARENT::doSomething();
}
public static function doSomethingElse() {
return parent::doSomethingElse();
}
}
~~~~~~~~~~
warning:5:12
~~~~~~~~~~
<?php
class Foo extends Bar {
public static function doSomething() {
return parent::doSomething();
}
public static function doSomethingElse() {
return parent::doSomethingElse();
}
}

View file

@ -0,0 +1,25 @@
<?php
class Foo extends Bar {
public static function doSomething() {
return SELF::doSomethingElse();
}
public static function doSomethingElse() {
return self::doSomething();
}
}
~~~~~~~~~~
warning:5:12
~~~~~~~~~~
<?php
class Foo extends Bar {
public static function doSomething() {
return self::doSomethingElse();
}
public static function doSomethingElse() {
return self::doSomething();
}
}

View file

@ -0,0 +1,5 @@
<?php
// This is quite odd, but seems somewhat reasonable.
MyClass/* comment */::/* another comment */myMethod();
~~~~~~~~~~

View file

@ -0,0 +1,6 @@
<?php
SomeReallyLongClassName::
someMethod();
SomeReallyLongClassName
::someMethod();
~~~~~~~~~~

View file

@ -0,0 +1,36 @@
<?php
class Foo extends Bar {
public function bar() {
echo self::FOOBAR;
echo self :: FOOBAR;
}
}
MyClass::myMethod();
MyClass :: myMethod();
MyClass::$myProperty;
MyClass :: $myProperty;
~~~~~~~~~~
warning:6:14
warning:6:17
warning:11:8
warning:11:11
warning:14:8
warning:14:11
~~~~~~~~~~
<?php
class Foo extends Bar {
public function bar() {
echo self::FOOBAR;
echo self::FOOBAR;
}
}
MyClass::myMethod();
MyClass::myMethod();
MyClass::$myProperty;
MyClass::$myProperty;

View file

@ -0,0 +1,25 @@
<?php
class Foo extends Bar {
public static function newInstance() {
return new Foo();
}
public static function init() {
return new self();
}
}
~~~~~~~~~~
warning:5:16
~~~~~~~~~~
<?php
class Foo extends Bar {
public static function newInstance() {
return new self();
}
public static function init() {
return new self();
}
}

View file

@ -4,12 +4,13 @@ final class SomeClass extends Phobject {
public static function someMethod() { public static function someMethod() {
$closure = function () { $closure = function () {
SomeClass::someOtherMethod(); SomeClass::someOtherMethod();
self::someOtherMethod();
}; };
$closure(); $closure();
} }
} }
~~~~~~~~~~ ~~~~~~~~~~
advice:6:7 warning:6:7
~~~~~~~~~~ ~~~~~~~~~~
<?php <?php
@ -17,6 +18,7 @@ final class SomeClass extends Phobject {
public static function someMethod() { public static function someMethod() {
$closure = function () { $closure = function () {
self::someOtherMethod(); self::someOtherMethod();
self::someOtherMethod();
}; };
$closure(); $closure();
} }

View file

@ -3,59 +3,21 @@
class Foo extends Bar { class Foo extends Bar {
const FOOBAR = 'FOOBAR'; const FOOBAR = 'FOOBAR';
public function __construct() { public function baz() {
PARENT::__construct(null);
}
public function bar() {
echo self::FOOBAR;
echo Self :: FOOBAR;
}
public function baz(Foo $x) {
echo static::FOOBAR;
echo Foo::FOOBAR; echo Foo::FOOBAR;
echo self::FOOBAR;
$x::bar();
} }
} }
MyClass :: myMethod();
SomeReallyLongClassName
::someMethod();
~~~~~~~~~~ ~~~~~~~~~~
advice:7:5 warning:7:10
advice:12:10
advice:12:14
advice:12:17
advice:17:10
advice:23:8
advice:23:11
~~~~~~~~~~ ~~~~~~~~~~
<?php <?php
class Foo extends Bar { class Foo extends Bar {
const FOOBAR = 'FOOBAR'; const FOOBAR = 'FOOBAR';
public function __construct() { public function baz() {
parent::__construct(null);
}
public function bar() {
echo self::FOOBAR; echo self::FOOBAR;
echo self::FOOBAR; echo self::FOOBAR;
} }
public function baz(Foo $x) {
echo static::FOOBAR;
echo self::FOOBAR;
$x::bar();
}
} }
MyClass::myMethod();
SomeReallyLongClassName
::someMethod();

View file

@ -8,7 +8,6 @@ final class ArcanistBaseCommitParser extends Phobject {
public function __construct(ArcanistRepositoryAPI $api) { public function __construct(ArcanistRepositoryAPI $api) {
$this->api = $api; $this->api = $api;
return $this;
} }
private function tokenizeBaseCommitSpecification($raw_spec) { private function tokenizeBaseCommitSpecification($raw_spec) {

View file

@ -1216,8 +1216,20 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
// Ideally, we would use something like "for-each-ref --contains" // Ideally, we would use something like "for-each-ref --contains"
// to get a filtered list of branches ready for script consumption. // to get a filtered list of branches ready for script consumption.
// Instead, try to get predictable output from "branch --contains". // Instead, try to get predictable output from "branch --contains".
$flags = array();
$flags[] = '--no-color';
// NOTE: The "--no-column" flag was introduced in Git 1.7.11, so
// don't pass it if we're running an older version. See T9953.
$version = $this->getGitVersion();
if (version_compare($version, '1.7.11', '>=')) {
$flags[] = '--no-column';
}
list($branches) = $this->execxLocal( list($branches) = $this->execxLocal(
'-c column.ui=never -c color.ui=never branch --contains %s', 'branch %Ls --contains %s',
$flags,
$commit); $commit);
$branches = array_filter(explode("\n", $branches)); $branches = array_filter(explode("\n", $branches));

View file

@ -360,7 +360,7 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
$working_status = ArcanistMercurialParser::parseMercurialStatus($stdout); $working_status = ArcanistMercurialParser::parseMercurialStatus($stdout);
foreach ($working_status as $path => $mask) { foreach ($working_status as $path => $mask) {
if (!($mask & ArcanistRepositoryAPI::FLAG_UNTRACKED)) { if (!($mask & parent::FLAG_UNTRACKED)) {
// Mark tracked files as uncommitted. // Mark tracked files as uncommitted.
$mask |= self::FLAG_UNCOMMITTED; $mask |= self::FLAG_UNCOMMITTED;
} }

View file

@ -139,7 +139,7 @@ final class ArcanistSubversionAPI extends ArcanistRepositoryAPI {
$status = $this->svnStatus; $status = $this->svnStatus;
if (!$with_externals) { if (!$with_externals) {
foreach ($status as $path => $mask) { foreach ($status as $path => $mask) {
if ($mask & ArcanistRepositoryAPI::FLAG_EXTERNALS) { if ($mask & parent::FLAG_EXTERNALS) {
unset($status[$path]); unset($status[$path]);
} }
} }
@ -384,7 +384,7 @@ final class ArcanistSubversionAPI extends ArcanistRepositoryAPI {
$status = $status[$path]; $status = $status[$path];
// Build meaningful diff text for "svn copy" operations. // Build meaningful diff text for "svn copy" operations.
if ($status & ArcanistRepositoryAPI::FLAG_ADDED) { if ($status & parent::FLAG_ADDED) {
$info = $this->getSVNInfo($path); $info = $this->getSVNInfo($path);
if (!empty($info['Copied From URL'])) { if (!empty($info['Copied From URL'])) {
return $this->buildSyntheticAdditionDiff( return $this->buildSyntheticAdditionDiff(
@ -403,7 +403,7 @@ final class ArcanistSubversionAPI extends ArcanistRepositoryAPI {
if (preg_match('/\.(gif|png|jpe?g|swf|pdf|ico)$/i', $path, $matches)) { if (preg_match('/\.(gif|png|jpe?g|swf|pdf|ico)$/i', $path, $matches)) {
// Check if the file is deleted first; SVN will complain if we try to // Check if the file is deleted first; SVN will complain if we try to
// get properties of a deleted file. // get properties of a deleted file.
if ($status & ArcanistRepositoryAPI::FLAG_DELETED) { if ($status & parent::FLAG_DELETED) {
return <<<EODIFF return <<<EODIFF
Index: {$path} Index: {$path}
=================================================================== ===================================================================

View file

@ -139,14 +139,14 @@ final class NoseTestEngine extends ArcanistUnitTestEngine {
for ($ii = 0; $ii < $lines->length; $ii++) { for ($ii = 0; $ii < $lines->length; $ii++) {
$line = $lines->item($ii); $line = $lines->item($ii);
$next_line = intval($line->getAttribute('number')); $next_line = (int)$line->getAttribute('number');
for ($start_line; $start_line < $next_line; $start_line++) { for ($start_line; $start_line < $next_line; $start_line++) {
$coverage .= 'N'; $coverage .= 'N';
} }
if (intval($line->getAttribute('hits')) == 0) { if ((int)$line->getAttribute('hits') == 0) {
$coverage .= 'U'; $coverage .= 'U';
} else if (intval($line->getAttribute('hits')) > 0) { } else if ((int)$line->getAttribute('hits') > 0) {
$coverage .= 'C'; $coverage .= 'C';
} }

View file

@ -116,14 +116,14 @@ final class PytestTestEngine extends ArcanistUnitTestEngine {
for ($ii = 0; $ii < $lines->length; $ii++) { for ($ii = 0; $ii < $lines->length; $ii++) {
$line = $lines->item($ii); $line = $lines->item($ii);
$next_line = intval($line->getAttribute('number')); $next_line = (int)$line->getAttribute('number');
for ($start_line; $start_line < $next_line; $start_line++) { for ($start_line; $start_line < $next_line; $start_line++) {
$coverage .= 'N'; $coverage .= 'N';
} }
if (intval($line->getAttribute('hits')) == 0) { if ((int)$line->getAttribute('hits') == 0) {
$coverage .= 'U'; $coverage .= 'U';
} else if (intval($line->getAttribute('hits')) > 0) { } else if ((int)$line->getAttribute('hits') > 0) {
$coverage .= 'C'; $coverage .= 'C';
} }

View file

@ -531,6 +531,7 @@ EOTEXT
$this->updateLintDiffProperty(); $this->updateLintDiffProperty();
$this->updateUnitDiffProperty(); $this->updateUnitDiffProperty();
$this->updateLocalDiffProperty(); $this->updateLocalDiffProperty();
$this->updateOntoDiffProperty();
$this->resolveDiffPropertyUpdates(); $this->resolveDiffPropertyUpdates();
$output_json = $this->getArgument('json'); $output_json = $this->getArgument('json');
@ -2406,6 +2407,54 @@ EOTEXT
$this->updateDiffProperty('local:commits', json_encode($local_info)); $this->updateDiffProperty('local:commits', json_encode($local_info));
} }
private function updateOntoDiffProperty() {
$onto = $this->getDiffOntoTargets();
if (!$onto) {
return;
}
$this->updateDiffProperty('arc:onto', json_encode($onto));
}
private function getDiffOntoTargets() {
$api = $this->getRepositoryAPI();
if (!($api instanceof ArcanistGitAPI)) {
return null;
}
// If we track an upstream branch either directly or indirectly, use that.
$branch = $api->getBranchName();
if (strlen($branch)) {
$upstream_path = $api->getPathToUpstream($branch);
$remote_branch = $upstream_path->getRemoteBranchName();
if (strlen($remote_branch)) {
return array(
array(
'type' => 'branch',
'name' => $remote_branch,
'kind' => 'upstream',
),
);
}
}
// If "arc.land.onto.default" is configured, use that.
$config_key = 'arc.land.onto.default';
$onto = $this->getConfigFromAnySource($config_key);
if (strlen($onto)) {
return array(
array(
'type' => 'branch',
'name' => $onto,
'kind' => 'arc.land.onto.default',
),
);
}
return null;
}
/** /**
* Update an arbitrary diff property. * Update an arbitrary diff property.

View file

@ -14,14 +14,30 @@ final class ArcanistFlagWorkflow extends ArcanistWorkflow {
); );
private static $colorSpec = array( private static $colorSpec = array(
'red' => 0, 'r' => 0, 0 => 0, 'red' => 0,
'orange' => 1, 'o' => 1, 1 => 1, 'r' => 0,
'yellow' => 2, 'y' => 2, 2 => 2, 0 => 0,
'green' => 3, 'g' => 3, 3 => 3, 'orange' => 1,
'blue' => 4, 'b' => 4, 4 => 4, 'o' => 1,
'pink' => 5, 'p' => 5, 5 => 5, 1 => 1,
'purple' => 6, 'v' => 6, 6 => 6, 'yellow' => 2,
'checkered' => 7, 'c' => 7, 7 => 7, 'y' => 2,
2 => 2,
'green' => 3,
'g' => 3,
3 => 3,
'blue' => 4,
'b' => 4,
4 => 4,
'pink' => 5,
'p' => 5,
5 => 5,
'purple' => 6,
'v' => 6,
6 => 6,
'checkered' => 7,
'c' => 7,
7 => 7,
); );
public function getWorkflowName() { public function getWorkflowName() {

View file

@ -87,19 +87,23 @@ EOTEXT
With **--preview**, execution stops here, before the change is With **--preview**, execution stops here, before the change is
merged. merged.
The change is merged into the target branch, following these rules: The change is merged with the changes in the target branch,
following these rules:
In mutable repositories or with **--squash**, this will perform a In repositories with mutable history or with **--squash**, this will
squash merge (the entire branch will be represented as one commit on perform a squash merge (the entire branch will be represented as one
the target branch). commit after the merge).
In immutable repositories or with **--merge**, this will perform a In repositories with immutable history or with **--merge**, this will
strict merge (a merge commit will always be created, and local perform a strict merge (a merge commit will always be created, and
commits will be preserved). local commits will be preserved).
The resulting commit will be given an up-to-date commit message The resulting commit will be given an up-to-date commit message
describing the final state of the revision in Differential. describing the final state of the revision in Differential.
In Git, the merge occurs in a detached HEAD. The local branch
reference (if one exists) is not updated yet.
With **--hold**, execution stops here, before the change is pushed. With **--hold**, execution stops here, before the change is pushed.
The change is pushed into the remote. The change is pushed into the remote.

View file

@ -691,7 +691,7 @@ EOTEXT
Filesystem::writeFile($patchfile, $bundle->toGitPatch()); Filesystem::writeFile($patchfile, $bundle->toGitPatch());
$passthru = new PhutilExecPassthru( $passthru = new PhutilExecPassthru(
'git apply --index --reject -- %s', 'git apply --whitespace nowarn --index --reject -- %s',
$patchfile); $patchfile);
$passthru->setCWD($repository_api->getPath()); $passthru->setCWD($repository_api->getPath());
$err = $passthru->execute(); $err = $passthru->execute();