diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 287ea8f9..1ba57971 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,1781 +1,1781 @@ 2, 'class' => array( 'AASTNode' => 'parser/aast/api/AASTNode.php', 'AASTNodeList' => 'parser/aast/api/AASTNodeList.php', 'AASTToken' => 'parser/aast/api/AASTToken.php', 'AASTTree' => 'parser/aast/api/AASTTree.php', 'AbstractDirectedGraph' => 'utils/AbstractDirectedGraph.php', 'AbstractDirectedGraphTestCase' => 'utils/__tests__/AbstractDirectedGraphTestCase.php', 'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php', 'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php', 'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php', 'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php', 'ArcanistAlias' => 'toolset/ArcanistAlias.php', 'ArcanistAliasEffect' => 'toolset/ArcanistAliasEffect.php', 'ArcanistAliasEngine' => 'toolset/ArcanistAliasEngine.php', 'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAliasFunctionXHPASTLinterRuleTestCase.php', 'ArcanistAliasWorkflow' => 'toolset/workflow/ArcanistAliasWorkflow.php', 'ArcanistAliasesConfigOption' => 'config/option/ArcanistAliasesConfigOption.php', 'ArcanistAmendWorkflow' => 'workflow/ArcanistAmendWorkflow.php', 'ArcanistAnoidWorkflow' => 'workflow/ArcanistAnoidWorkflow.php', 'ArcanistArcConfigurationEngineExtension' => 'config/arc/ArcanistArcConfigurationEngineExtension.php', 'ArcanistArcToolset' => 'toolset/ArcanistArcToolset.php', 'ArcanistArcWorkflow' => 'toolset/workflow/ArcanistArcWorkflow.php', 'ArcanistArrayCombineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php', 'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayCombineXHPASTLinterRuleTestCase.php', 'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayIndexSpacingXHPASTLinterRule.php', 'ArcanistArrayIndexSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayIndexSpacingXHPASTLinterRuleTestCase.php', 'ArcanistArraySeparatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArraySeparatorXHPASTLinterRule.php', 'ArcanistArraySeparatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArraySeparatorXHPASTLinterRuleTestCase.php', 'ArcanistArrayValueXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayValueXHPASTLinterRule.php', 'ArcanistArrayValueXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayValueXHPASTLinterRuleTestCase.php', 'ArcanistBackoutWorkflow' => 'workflow/ArcanistBackoutWorkflow.php', 'ArcanistBaseCommitParser' => 'parser/ArcanistBaseCommitParser.php', 'ArcanistBaseCommitParserTestCase' => 'parser/__tests__/ArcanistBaseCommitParserTestCase.php', 'ArcanistBaseXHPASTLinter' => 'lint/linter/ArcanistBaseXHPASTLinter.php', 'ArcanistBinaryExpressionSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBinaryExpressionSpacingXHPASTLinterRule.php', 'ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase.php', 'ArcanistBinaryNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php', 'ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php', 'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBlacklistedFunctionXHPASTLinterRule.php', 'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase.php', 'ArcanistBlindlyTrustHTTPEngineExtension' => 'configuration/ArcanistBlindlyTrustHTTPEngineExtension.php', 'ArcanistBookmarkWorkflow' => 'workflow/ArcanistBookmarkWorkflow.php', 'ArcanistBraceFormattingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBraceFormattingXHPASTLinterRule.php', 'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBraceFormattingXHPASTLinterRuleTestCase.php', 'ArcanistBranchRef' => 'ref/ArcanistBranchRef.php', 'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php', 'ArcanistBrowseCommitHardpointLoader' => 'browse/loader/ArcanistBrowseCommitHardpointLoader.php', 'ArcanistBrowseCommitURIHardpointLoader' => 'browse/loader/ArcanistBrowseCommitURIHardpointLoader.php', 'ArcanistBrowseObjectNameURIHardpointLoader' => 'browse/loader/ArcanistBrowseObjectNameURIHardpointLoader.php', 'ArcanistBrowsePathURIHardpointLoader' => 'browse/loader/ArcanistBrowsePathURIHardpointLoader.php', 'ArcanistBrowseRef' => 'browse/ref/ArcanistBrowseRef.php', 'ArcanistBrowseRevisionURIHardpointLoader' => 'browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php', 'ArcanistBrowseURIHardpointLoader' => 'browse/loader/ArcanistBrowseURIHardpointLoader.php', 'ArcanistBrowseURIRef' => 'browse/ref/ArcanistBrowseURIRef.php', 'ArcanistBrowseWorkflow' => 'browse/workflow/ArcanistBrowseWorkflow.php', 'ArcanistBuildPlanRef' => 'ref/ArcanistBuildPlanRef.php', 'ArcanistBuildRef' => 'ref/ArcanistBuildRef.php', 'ArcanistBundle' => 'parser/ArcanistBundle.php', 'ArcanistBundleTestCase' => 'parser/__tests__/ArcanistBundleTestCase.php', 'ArcanistCSSLintLinter' => 'lint/linter/ArcanistCSSLintLinter.php', 'ArcanistCSSLintLinterTestCase' => 'lint/linter/__tests__/ArcanistCSSLintLinterTestCase.php', 'ArcanistCSharpLinter' => 'lint/linter/ArcanistCSharpLinter.php', 'ArcanistCallConduitWorkflow' => 'workflow/ArcanistCallConduitWorkflow.php', 'ArcanistCallParenthesesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCallParenthesesXHPASTLinterRule.php', 'ArcanistCallParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCallParenthesesXHPASTLinterRuleTestCase.php', 'ArcanistCallTimePassByReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCallTimePassByReferenceXHPASTLinterRule.php', 'ArcanistCallTimePassByReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCallTimePassByReferenceXHPASTLinterRuleTestCase.php', 'ArcanistCapabilityNotSupportedException' => 'workflow/exception/ArcanistCapabilityNotSupportedException.php', 'ArcanistCastSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCastSpacingXHPASTLinterRule.php', 'ArcanistCastSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCastSpacingXHPASTLinterRuleTestCase.php', 'ArcanistCheckstyleXMLLintRenderer' => 'lint/renderer/ArcanistCheckstyleXMLLintRenderer.php', 'ArcanistChmodLinter' => 'lint/linter/ArcanistChmodLinter.php', 'ArcanistChmodLinterTestCase' => 'lint/linter/__tests__/ArcanistChmodLinterTestCase.php', 'ArcanistClassExtendsObjectXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php', 'ArcanistClassExtendsObjectXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassExtendsObjectXHPASTLinterRuleTestCase.php', 'ArcanistClassFilenameMismatchXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php', 'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php', 'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase.php', 'ArcanistClassNameLiteralXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php', 'ArcanistClassNameLiteralXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassNameLiteralXHPASTLinterRuleTestCase.php', 'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php', 'ArcanistCloseWorkflow' => 'workflow/ArcanistCloseWorkflow.php', 'ArcanistClosureLinter' => 'lint/linter/ArcanistClosureLinter.php', 'ArcanistClosureLinterTestCase' => 'lint/linter/__tests__/ArcanistClosureLinterTestCase.php', 'ArcanistCoffeeLintLinter' => 'lint/linter/ArcanistCoffeeLintLinter.php', 'ArcanistCoffeeLintLinterTestCase' => 'lint/linter/__tests__/ArcanistCoffeeLintLinterTestCase.php', 'ArcanistCommentRemover' => 'parser/ArcanistCommentRemover.php', 'ArcanistCommentRemoverTestCase' => 'parser/__tests__/ArcanistCommentRemoverTestCase.php', 'ArcanistCommentSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCommentSpacingXHPASTLinterRule.php', 'ArcanistCommentStyleXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php', 'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCommentStyleXHPASTLinterRuleTestCase.php', 'ArcanistCommitRef' => 'ref/ArcanistCommitRef.php', 'ArcanistCommitUpstreamHardpointLoader' => 'loader/ArcanistCommitUpstreamHardpointLoader.php', 'ArcanistCommitWorkflow' => 'workflow/ArcanistCommitWorkflow.php', 'ArcanistCompilerLintRenderer' => 'lint/renderer/ArcanistCompilerLintRenderer.php', 'ArcanistComposerLinter' => 'lint/linter/ArcanistComposerLinter.php', 'ArcanistComprehensiveLintEngine' => 'lint/engine/ArcanistComprehensiveLintEngine.php', 'ArcanistConcatenationOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistConcatenationOperatorXHPASTLinterRule.php', 'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistConcatenationOperatorXHPASTLinterRuleTestCase.php', 'ArcanistConduitCall' => 'conduit/ArcanistConduitCall.php', 'ArcanistConduitEngine' => 'conduit/ArcanistConduitEngine.php', 'ArcanistConduitException' => 'conduit/ArcanistConduitException.php', 'ArcanistConfigOption' => 'config/option/ArcanistConfigOption.php', 'ArcanistConfiguration' => 'configuration/ArcanistConfiguration.php', 'ArcanistConfigurationDrivenLintEngine' => 'lint/engine/ArcanistConfigurationDrivenLintEngine.php', 'ArcanistConfigurationDrivenUnitTestEngine' => 'unit/engine/ArcanistConfigurationDrivenUnitTestEngine.php', 'ArcanistConfigurationEngine' => 'config/ArcanistConfigurationEngine.php', 'ArcanistConfigurationEngineExtension' => 'config/ArcanistConfigurationEngineExtension.php', 'ArcanistConfigurationManager' => 'configuration/ArcanistConfigurationManager.php', 'ArcanistConfigurationSource' => 'config/source/ArcanistConfigurationSource.php', 'ArcanistConfigurationSourceList' => 'config/ArcanistConfigurationSourceList.php', 'ArcanistConfigurationSourceValue' => 'config/ArcanistConfigurationSourceValue.php', 'ArcanistConsoleLintRenderer' => 'lint/renderer/ArcanistConsoleLintRenderer.php', 'ArcanistConsoleLintRendererTestCase' => 'lint/renderer/__tests__/ArcanistConsoleLintRendererTestCase.php', 'ArcanistConstructorParenthesesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistConstructorParenthesesXHPASTLinterRule.php', 'ArcanistConstructorParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistConstructorParenthesesXHPASTLinterRuleTestCase.php', 'ArcanistContinueInsideSwitchXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistContinueInsideSwitchXHPASTLinterRule.php', 'ArcanistContinueInsideSwitchXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistContinueInsideSwitchXHPASTLinterRuleTestCase.php', 'ArcanistControlStatementSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistControlStatementSpacingXHPASTLinterRule.php', 'ArcanistControlStatementSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistControlStatementSpacingXHPASTLinterRuleTestCase.php', 'ArcanistCoverWorkflow' => 'workflow/ArcanistCoverWorkflow.php', 'ArcanistCppcheckLinter' => 'lint/linter/ArcanistCppcheckLinter.php', 'ArcanistCppcheckLinterTestCase' => 'lint/linter/__tests__/ArcanistCppcheckLinterTestCase.php', 'ArcanistCpplintLinter' => 'lint/linter/ArcanistCpplintLinter.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', 'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase.php', 'ArcanistDefaultParametersXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDefaultParametersXHPASTLinterRule.php', 'ArcanistDefaultParametersXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDefaultParametersXHPASTLinterRuleTestCase.php', 'ArcanistDefaultsConfigurationSource' => 'config/source/ArcanistDefaultsConfigurationSource.php', 'ArcanistDeprecationXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDeprecationXHPASTLinterRule.php', 'ArcanistDeprecationXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDeprecationXHPASTLinterRuleTestCase.php', 'ArcanistDictionaryConfigurationSource' => 'config/source/ArcanistDictionaryConfigurationSource.php', 'ArcanistDiffByteSizeException' => 'exception/ArcanistDiffByteSizeException.php', 'ArcanistDiffChange' => 'parser/diff/ArcanistDiffChange.php', 'ArcanistDiffChangeType' => 'parser/diff/ArcanistDiffChangeType.php', 'ArcanistDiffHunk' => 'parser/diff/ArcanistDiffHunk.php', 'ArcanistDiffParser' => 'parser/ArcanistDiffParser.php', 'ArcanistDiffParserTestCase' => 'parser/__tests__/ArcanistDiffParserTestCase.php', 'ArcanistDiffUtils' => 'difference/ArcanistDiffUtils.php', 'ArcanistDiffUtilsTestCase' => 'difference/__tests__/ArcanistDiffUtilsTestCase.php', 'ArcanistDiffWorkflow' => 'workflow/ArcanistDiffWorkflow.php', 'ArcanistDifferentialCommitMessage' => 'differential/ArcanistDifferentialCommitMessage.php', 'ArcanistDifferentialCommitMessageParserException' => 'differential/ArcanistDifferentialCommitMessageParserException.php', 'ArcanistDifferentialDependencyGraph' => 'differential/ArcanistDifferentialDependencyGraph.php', 'ArcanistDifferentialRevisionHash' => 'differential/constants/ArcanistDifferentialRevisionHash.php', 'ArcanistDifferentialRevisionStatus' => 'differential/constants/ArcanistDifferentialRevisionStatus.php', 'ArcanistDoubleQuoteXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDoubleQuoteXHPASTLinterRule.php', 'ArcanistDoubleQuoteXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDoubleQuoteXHPASTLinterRuleTestCase.php', 'ArcanistDownloadWorkflow' => 'workflow/ArcanistDownloadWorkflow.php', 'ArcanistDuplicateKeysInArrayXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDuplicateKeysInArrayXHPASTLinterRule.php', 'ArcanistDuplicateKeysInArrayXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDuplicateKeysInArrayXHPASTLinterRuleTestCase.php', 'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDuplicateSwitchCaseXHPASTLinterRule.php', 'ArcanistDuplicateSwitchCaseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDuplicateSwitchCaseXHPASTLinterRuleTestCase.php', 'ArcanistDynamicDefineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php', 'ArcanistDynamicDefineXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDynamicDefineXHPASTLinterRuleTestCase.php', 'ArcanistElseIfUsageXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php', 'ArcanistElseIfUsageXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistElseIfUsageXHPASTLinterRuleTestCase.php', 'ArcanistEmptyFileXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php', 'ArcanistEmptyStatementXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyStatementXHPASTLinterRule.php', 'ArcanistEmptyStatementXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistEmptyStatementXHPASTLinterRuleTestCase.php', 'ArcanistEventType' => 'events/constant/ArcanistEventType.php', 'ArcanistExitExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php', 'ArcanistExitExpressionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistExitExpressionXHPASTLinterRuleTestCase.php', 'ArcanistExportWorkflow' => 'workflow/ArcanistExportWorkflow.php', 'ArcanistExternalLinter' => 'lint/linter/ArcanistExternalLinter.php', 'ArcanistExternalLinterTestCase' => 'lint/linter/__tests__/ArcanistExternalLinterTestCase.php', 'ArcanistExtractUseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php', 'ArcanistExtractUseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistExtractUseXHPASTLinterRuleTestCase.php', 'ArcanistFeatureWorkflow' => 'workflow/ArcanistFeatureWorkflow.php', 'ArcanistFileConfigurationSource' => 'config/source/ArcanistFileConfigurationSource.php', 'ArcanistFileDataRef' => 'upload/ArcanistFileDataRef.php', 'ArcanistFileUploader' => 'upload/ArcanistFileUploader.php', 'ArcanistFilenameLinter' => 'lint/linter/ArcanistFilenameLinter.php', 'ArcanistFilenameLinterTestCase' => 'lint/linter/__tests__/ArcanistFilenameLinterTestCase.php', 'ArcanistFilesystemConfigurationSource' => 'config/source/ArcanistFilesystemConfigurationSource.php', 'ArcanistFlagWorkflow' => 'workflow/ArcanistFlagWorkflow.php', 'ArcanistFlake8Linter' => 'lint/linter/ArcanistFlake8Linter.php', 'ArcanistFlake8LinterTestCase' => 'lint/linter/__tests__/ArcanistFlake8LinterTestCase.php', 'ArcanistFormattedStringXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistFormattedStringXHPASTLinterRule.php', 'ArcanistFormattedStringXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistFormattedStringXHPASTLinterRuleTestCase.php', 'ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRule.php', 'ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRuleTestCase.php', 'ArcanistFutureLinter' => 'lint/linter/ArcanistFutureLinter.php', 'ArcanistGeneratedLinter' => 'lint/linter/ArcanistGeneratedLinter.php', 'ArcanistGeneratedLinterTestCase' => 'lint/linter/__tests__/ArcanistGeneratedLinterTestCase.php', 'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php', 'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php', 'ArcanistGitCommitMessageHardpointLoader' => 'loader/ArcanistGitCommitMessageHardpointLoader.php', 'ArcanistGitHardpointLoader' => 'loader/ArcanistGitHardpointLoader.php', 'ArcanistGitLandEngine' => 'land/ArcanistGitLandEngine.php', 'ArcanistGitRevisionHardpointLoader' => 'loader/ArcanistGitRevisionHardpointLoader.php', 'ArcanistGitUpstreamPath' => 'repository/api/ArcanistGitUpstreamPath.php', 'ArcanistGitWorkingCopy' => 'workingcopy/ArcanistGitWorkingCopy.php', 'ArcanistGlobalVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistGlobalVariableXHPASTLinterRule.php', 'ArcanistGlobalVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistGlobalVariableXHPASTLinterRuleTestCase.php', 'ArcanistGoLintLinter' => 'lint/linter/ArcanistGoLintLinter.php', 'ArcanistGoLintLinterTestCase' => 'lint/linter/__tests__/ArcanistGoLintLinterTestCase.php', 'ArcanistGoTestResultParser' => 'unit/parser/ArcanistGoTestResultParser.php', 'ArcanistGoTestResultParserTestCase' => 'unit/parser/__tests__/ArcanistGoTestResultParserTestCase.php', 'ArcanistHLintLinter' => 'lint/linter/ArcanistHLintLinter.php', 'ArcanistHLintLinterTestCase' => 'lint/linter/__tests__/ArcanistHLintLinterTestCase.php', 'ArcanistHardpointLoader' => 'loader/ArcanistHardpointLoader.php', 'ArcanistHelpWorkflow' => 'toolset/workflow/ArcanistHelpWorkflow.php', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase.php', 'ArcanistHgClientChannel' => 'hgdaemon/ArcanistHgClientChannel.php', 'ArcanistHgProxyClient' => 'hgdaemon/ArcanistHgProxyClient.php', 'ArcanistHgProxyServer' => 'hgdaemon/ArcanistHgProxyServer.php', 'ArcanistHgServerChannel' => 'hgdaemon/ArcanistHgServerChannel.php', 'ArcanistImplicitConstructorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistImplicitConstructorXHPASTLinterRule.php', 'ArcanistImplicitConstructorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistImplicitConstructorXHPASTLinterRuleTestCase.php', 'ArcanistImplicitFallthroughXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistImplicitFallthroughXHPASTLinterRule.php', 'ArcanistImplicitFallthroughXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistImplicitFallthroughXHPASTLinterRuleTestCase.php', 'ArcanistImplicitVisibilityXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistImplicitVisibilityXHPASTLinterRule.php', 'ArcanistImplicitVisibilityXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistImplicitVisibilityXHPASTLinterRuleTestCase.php', 'ArcanistImplodeArgumentOrderXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistImplodeArgumentOrderXHPASTLinterRule.php', 'ArcanistImplodeArgumentOrderXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistImplodeArgumentOrderXHPASTLinterRuleTestCase.php', 'ArcanistInlineHTMLXHPASTLinterRule' => 'lint/linter/ArcanistInlineHTMLXHPASTLinterRule.php', 'ArcanistInlineHTMLXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInlineHTMLXHPASTLinterRuleTestCase.php', 'ArcanistInnerFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInnerFunctionXHPASTLinterRule.php', 'ArcanistInnerFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInnerFunctionXHPASTLinterRuleTestCase.php', 'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php', 'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php', 'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInstanceofOperatorXHPASTLinterRuleTestCase.php', 'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php', 'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php', 'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceMethodBodyXHPASTLinterRule.php', 'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase.php', 'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php', 'ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase.php', 'ArcanistInvalidModifiersXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php', 'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidModifiersXHPASTLinterRuleTestCase.php', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidOctalNumericScalarXHPASTLinterRule.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', 'ArcanistJSHintLinterTestCase' => 'lint/linter/__tests__/ArcanistJSHintLinterTestCase.php', 'ArcanistJSONLintLinter' => 'lint/linter/ArcanistJSONLintLinter.php', 'ArcanistJSONLintRenderer' => 'lint/renderer/ArcanistJSONLintRenderer.php', 'ArcanistJSONLinter' => 'lint/linter/ArcanistJSONLinter.php', 'ArcanistJSONLinterTestCase' => 'lint/linter/__tests__/ArcanistJSONLinterTestCase.php', 'ArcanistJscsLinter' => 'lint/linter/ArcanistJscsLinter.php', 'ArcanistJscsLinterTestCase' => 'lint/linter/__tests__/ArcanistJscsLinterTestCase.php', 'ArcanistKeywordCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistKeywordCasingXHPASTLinterRule.php', 'ArcanistKeywordCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistKeywordCasingXHPASTLinterRuleTestCase.php', 'ArcanistLambdaFuncFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLambdaFuncFunctionXHPASTLinterRule.php', 'ArcanistLambdaFuncFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLambdaFuncFunctionXHPASTLinterRuleTestCase.php', 'ArcanistLandEngine' => 'land/ArcanistLandEngine.php', 'ArcanistLandWorkflow' => 'workflow/ArcanistLandWorkflow.php', 'ArcanistLanguageConstructParenthesesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLanguageConstructParenthesesXHPASTLinterRule.php', 'ArcanistLanguageConstructParenthesesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLanguageConstructParenthesesXHPASTLinterRuleTestCase.php', 'ArcanistLesscLinter' => 'lint/linter/ArcanistLesscLinter.php', 'ArcanistLesscLinterTestCase' => 'lint/linter/__tests__/ArcanistLesscLinterTestCase.php', 'ArcanistLiberateWorkflow' => 'workflow/ArcanistLiberateWorkflow.php', 'ArcanistLintEngine' => 'lint/engine/ArcanistLintEngine.php', 'ArcanistLintMessage' => 'lint/ArcanistLintMessage.php', 'ArcanistLintMessageTestCase' => 'lint/__tests__/ArcanistLintMessageTestCase.php', 'ArcanistLintPatcher' => 'lint/ArcanistLintPatcher.php', 'ArcanistLintRenderer' => 'lint/renderer/ArcanistLintRenderer.php', 'ArcanistLintResult' => 'lint/ArcanistLintResult.php', 'ArcanistLintSeverity' => 'lint/ArcanistLintSeverity.php', 'ArcanistLintWorkflow' => 'workflow/ArcanistLintWorkflow.php', 'ArcanistLinter' => 'lint/linter/ArcanistLinter.php', 'ArcanistLinterStandard' => 'lint/linter/standards/ArcanistLinterStandard.php', 'ArcanistLinterStandardTestCase' => 'lint/linter/standards/__tests__/ArcanistLinterStandardTestCase.php', 'ArcanistLinterTestCase' => 'lint/linter/__tests__/ArcanistLinterTestCase.php', 'ArcanistLintersWorkflow' => 'workflow/ArcanistLintersWorkflow.php', 'ArcanistListAssignmentXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistListAssignmentXHPASTLinterRule.php', 'ArcanistListAssignmentXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistListAssignmentXHPASTLinterRuleTestCase.php', 'ArcanistListConfigOption' => 'config/option/ArcanistListConfigOption.php', 'ArcanistListWorkflow' => 'workflow/ArcanistListWorkflow.php', 'ArcanistLocalConfigurationSource' => 'config/source/ArcanistLocalConfigurationSource.php', 'ArcanistLogEngine' => 'log/ArcanistLogEngine.php', 'ArcanistLogMessage' => 'log/ArcanistLogMessage.php', 'ArcanistLogicalOperatorsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLogicalOperatorsXHPASTLinterRule.php', 'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLogicalOperatorsXHPASTLinterRuleTestCase.php', 'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLowercaseFunctionsXHPASTLinterRule.php', 'ArcanistLowercaseFunctionsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLowercaseFunctionsXHPASTLinterRuleTestCase.php', 'ArcanistMercurialAPI' => 'repository/api/ArcanistMercurialAPI.php', 'ArcanistMercurialBranchCommitHardpointLoader' => 'loader/ArcanistMercurialBranchCommitHardpointLoader.php', 'ArcanistMercurialHardpointLoader' => 'loader/ArcanistMercurialHardpointLoader.php', 'ArcanistMercurialParser' => 'repository/parser/ArcanistMercurialParser.php', 'ArcanistMercurialParserTestCase' => 'repository/parser/__tests__/ArcanistMercurialParserTestCase.php', 'ArcanistMercurialWorkingCopy' => 'workingcopy/ArcanistMercurialWorkingCopy.php', 'ArcanistMercurialWorkingCopyCommitHardpointLoader' => 'loader/ArcanistMercurialWorkingCopyCommitHardpointLoader.php', 'ArcanistMergeConflictLinter' => 'lint/linter/ArcanistMergeConflictLinter.php', 'ArcanistMergeConflictLinterTestCase' => 'lint/linter/__tests__/ArcanistMergeConflictLinterTestCase.php', 'ArcanistMessageRevisionHardpointLoader' => 'loader/ArcanistMessageRevisionHardpointLoader.php', 'ArcanistMissingLinterException' => 'lint/linter/exception/ArcanistMissingLinterException.php', 'ArcanistModifierOrderingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistModifierOrderingXHPASTLinterRule.php', 'ArcanistModifierOrderingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistModifierOrderingXHPASTLinterRuleTestCase.php', 'ArcanistNamespaceFirstStatementXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNamespaceFirstStatementXHPASTLinterRule.php', 'ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase.php', 'ArcanistNamingConventionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php', 'ArcanistNamingConventionsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNamingConventionsXHPASTLinterRuleTestCase.php', 'ArcanistNestedNamespacesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNestedNamespacesXHPASTLinterRule.php', 'ArcanistNestedNamespacesXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNestedNamespacesXHPASTLinterRuleTestCase.php', 'ArcanistNewlineAfterOpenTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php', 'ArcanistNewlineAfterOpenTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNewlineAfterOpenTagXHPASTLinterRuleTestCase.php', 'ArcanistNoEffectException' => 'exception/usage/ArcanistNoEffectException.php', 'ArcanistNoEngineException' => 'exception/usage/ArcanistNoEngineException.php', 'ArcanistNoLintLinter' => 'lint/linter/ArcanistNoLintLinter.php', 'ArcanistNoLintLinterTestCase' => 'lint/linter/__tests__/ArcanistNoLintLinterTestCase.php', 'ArcanistNoParentScopeXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php', 'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNoParentScopeXHPASTLinterRuleTestCase.php', 'ArcanistNoURIConduitException' => 'conduit/ArcanistNoURIConduitException.php', 'ArcanistNoneLintRenderer' => 'lint/renderer/ArcanistNoneLintRenderer.php', 'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistObjectOperatorSpacingXHPASTLinterRule.php', 'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase.php', 'ArcanistPEP8Linter' => 'lint/linter/ArcanistPEP8Linter.php', 'ArcanistPEP8LinterTestCase' => 'lint/linter/__tests__/ArcanistPEP8LinterTestCase.php', 'ArcanistPHPCloseTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPCloseTagXHPASTLinterRule.php', 'ArcanistPHPCloseTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPCloseTagXHPASTLinterRuleTestCase.php', 'ArcanistPHPCompatibilityXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPCompatibilityXHPASTLinterRule.php', 'ArcanistPHPCompatibilityXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPCompatibilityXHPASTLinterRuleTestCase.php', 'ArcanistPHPEchoTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPEchoTagXHPASTLinterRule.php', 'ArcanistPHPEchoTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPEchoTagXHPASTLinterRuleTestCase.php', 'ArcanistPHPOpenTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPOpenTagXHPASTLinterRule.php', 'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPHPOpenTagXHPASTLinterRuleTestCase.php', 'ArcanistPHPShortTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPHPShortTagXHPASTLinterRule.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', 'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParentMemberReferenceXHPASTLinterRuleTestCase.php', 'ArcanistParenthesesSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParenthesesSpacingXHPASTLinterRule.php', 'ArcanistParenthesesSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParenthesesSpacingXHPASTLinterRuleTestCase.php', 'ArcanistParseStrUseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistParseStrUseXHPASTLinterRule.php', 'ArcanistParseStrUseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistParseStrUseXHPASTLinterRuleTestCase.php', 'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php', 'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php', 'ArcanistPhageToolset' => 'toolset/ArcanistPhageToolset.php', 'ArcanistPhpLinter' => 'lint/linter/ArcanistPhpLinter.php', 'ArcanistPhpLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpLinterTestCase.php', 'ArcanistPhpcsLinter' => 'lint/linter/ArcanistPhpcsLinter.php', 'ArcanistPhpcsLinterTestCase' => 'lint/linter/__tests__/ArcanistPhpcsLinterTestCase.php', 'ArcanistPhpunitTestResultParser' => 'unit/parser/ArcanistPhpunitTestResultParser.php', 'ArcanistPhrequentWorkflow' => 'workflow/ArcanistPhrequentWorkflow.php', 'ArcanistPhutilLibraryLinter' => 'lint/linter/ArcanistPhutilLibraryLinter.php', 'ArcanistPhutilWorkflow' => 'toolset/ArcanistPhutilWorkflow.php', 'ArcanistPhutilXHPASTLinterStandard' => 'lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php', 'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php', 'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase.php', 'ArcanistPregQuoteMisuseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPregQuoteMisuseXHPASTLinterRule.php', 'ArcanistPregQuoteMisuseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPregQuoteMisuseXHPASTLinterRuleTestCase.php', 'ArcanistProjectConfigurationSource' => 'config/source/ArcanistProjectConfigurationSource.php', 'ArcanistPrompt' => 'toolset/ArcanistPrompt.php', 'ArcanistPublicPropertyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPublicPropertyXHPASTLinterRule.php', 'ArcanistPublicPropertyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPublicPropertyXHPASTLinterRuleTestCase.php', 'ArcanistPuppetLintLinter' => 'lint/linter/ArcanistPuppetLintLinter.php', 'ArcanistPuppetLintLinterTestCase' => 'lint/linter/__tests__/ArcanistPuppetLintLinterTestCase.php', 'ArcanistPyFlakesLinter' => 'lint/linter/ArcanistPyFlakesLinter.php', 'ArcanistPyFlakesLinterTestCase' => 'lint/linter/__tests__/ArcanistPyFlakesLinterTestCase.php', 'ArcanistPyLintLinter' => 'lint/linter/ArcanistPyLintLinter.php', 'ArcanistPyLintLinterTestCase' => 'lint/linter/__tests__/ArcanistPyLintLinterTestCase.php', 'ArcanistRaggedClassTreeEdgeXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php', 'ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase.php', 'ArcanistRef' => 'ref/ArcanistRef.php', 'ArcanistRefQuery' => 'ref/ArcanistRefQuery.php', 'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php', 'ArcanistRepositoryAPIMiscTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIMiscTestCase.php', 'ArcanistRepositoryAPIStateTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php', 'ArcanistRepositoryRef' => 'ref/ArcanistRepositoryRef.php', 'ArcanistReusedAsIteratorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistReusedAsIteratorXHPASTLinterRule.php', 'ArcanistReusedAsIteratorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistReusedAsIteratorXHPASTLinterRuleTestCase.php', 'ArcanistReusedIteratorReferenceXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistReusedIteratorReferenceXHPASTLinterRule.php', 'ArcanistReusedIteratorReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistReusedIteratorReferenceXHPASTLinterRuleTestCase.php', 'ArcanistReusedIteratorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistReusedIteratorXHPASTLinterRule.php', 'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistReusedIteratorXHPASTLinterRuleTestCase.php', 'ArcanistRevertWorkflow' => 'workflow/ArcanistRevertWorkflow.php', 'ArcanistRevisionRef' => 'ref/ArcanistRevisionRef.php', 'ArcanistRevisionRefSource' => 'ref/ArcanistRevisionRefSource.php', 'ArcanistRuboCopLinter' => 'lint/linter/ArcanistRuboCopLinter.php', 'ArcanistRuboCopLinterTestCase' => 'lint/linter/__tests__/ArcanistRuboCopLinterTestCase.php', 'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php', 'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php', 'ArcanistRuntime' => 'runtime/ArcanistRuntime.php', 'ArcanistRuntimeConfigurationSource' => 'config/source/ArcanistRuntimeConfigurationSource.php', 'ArcanistScalarConfigOption' => 'config/option/ArcanistScalarConfigOption.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', 'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase.php', 'ArcanistSemicolonSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSemicolonSpacingXHPASTLinterRule.php', 'ArcanistSemicolonSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSemicolonSpacingXHPASTLinterRuleTestCase.php', 'ArcanistSetConfigWorkflow' => 'workflow/ArcanistSetConfigWorkflow.php', 'ArcanistSetting' => 'configuration/ArcanistSetting.php', 'ArcanistSettings' => 'configuration/ArcanistSettings.php', 'ArcanistShellCompleteWorkflow' => 'toolset/workflow/ArcanistShellCompleteWorkflow.php', 'ArcanistSingleLintEngine' => 'lint/engine/ArcanistSingleLintEngine.php', 'ArcanistSlownessXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSlownessXHPASTLinterRule.php', 'ArcanistSlownessXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistSlownessXHPASTLinterRuleTestCase.php', 'ArcanistSpellingLinter' => 'lint/linter/ArcanistSpellingLinter.php', 'ArcanistSpellingLinterTestCase' => 'lint/linter/__tests__/ArcanistSpellingLinterTestCase.php', 'ArcanistStartWorkflow' => 'workflow/ArcanistStartWorkflow.php', 'ArcanistStaticThisXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistStaticThisXHPASTLinterRule.php', 'ArcanistStaticThisXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistStaticThisXHPASTLinterRuleTestCase.php', 'ArcanistStopWorkflow' => 'workflow/ArcanistStopWorkflow.php', 'ArcanistStringConfigOption' => 'config/option/ArcanistStringConfigOption.php', 'ArcanistSubversionAPI' => 'repository/api/ArcanistSubversionAPI.php', 'ArcanistSubversionWorkingCopy' => 'workingcopy/ArcanistSubversionWorkingCopy.php', 'ArcanistSummaryLintRenderer' => 'lint/renderer/ArcanistSummaryLintRenderer.php', 'ArcanistSyntaxErrorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistSyntaxErrorXHPASTLinterRule.php', 'ArcanistSystemConfigurationSource' => 'config/source/ArcanistSystemConfigurationSource.php', 'ArcanistTasksWorkflow' => 'workflow/ArcanistTasksWorkflow.php', 'ArcanistTautologicalExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTautologicalExpressionXHPASTLinterRule.php', 'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTautologicalExpressionXHPASTLinterRuleTestCase.php', 'ArcanistTestResultParser' => 'unit/parser/ArcanistTestResultParser.php', 'ArcanistTestXHPASTLintSwitchHook' => 'lint/linter/__tests__/ArcanistTestXHPASTLintSwitchHook.php', 'ArcanistTextLinter' => 'lint/linter/ArcanistTextLinter.php', 'ArcanistTextLinterTestCase' => 'lint/linter/__tests__/ArcanistTextLinterTestCase.php', 'ArcanistThisReassignmentXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistThisReassignmentXHPASTLinterRule.php', 'ArcanistThisReassignmentXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistThisReassignmentXHPASTLinterRuleTestCase.php', 'ArcanistTimeWorkflow' => 'workflow/ArcanistTimeWorkflow.php', 'ArcanistToStringExceptionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistToStringExceptionXHPASTLinterRule.php', 'ArcanistToStringExceptionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistToStringExceptionXHPASTLinterRuleTestCase.php', 'ArcanistTodoCommentXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTodoCommentXHPASTLinterRule.php', 'ArcanistTodoCommentXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTodoCommentXHPASTLinterRuleTestCase.php', 'ArcanistTodoWorkflow' => 'workflow/ArcanistTodoWorkflow.php', 'ArcanistToolset' => 'toolset/ArcanistToolset.php', 'ArcanistUSEnglishTranslation' => 'internationalization/ArcanistUSEnglishTranslation.php', 'ArcanistUnableToParseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnableToParseXHPASTLinterRule.php', 'ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRule.php', 'ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRuleTestCase.php', 'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRule.php', 'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase.php', 'ArcanistUndeclaredVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUndeclaredVariableXHPASTLinterRule.php', 'ArcanistUndeclaredVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUndeclaredVariableXHPASTLinterRuleTestCase.php', 'ArcanistUnexpectedReturnValueXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnexpectedReturnValueXHPASTLinterRule.php', 'ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase.php', 'ArcanistUnitConsoleRenderer' => 'unit/renderer/ArcanistUnitConsoleRenderer.php', 'ArcanistUnitRenderer' => 'unit/renderer/ArcanistUnitRenderer.php', 'ArcanistUnitTestEngine' => 'unit/engine/ArcanistUnitTestEngine.php', 'ArcanistUnitTestResult' => 'unit/ArcanistUnitTestResult.php', 'ArcanistUnitTestResultTestCase' => 'unit/__tests__/ArcanistUnitTestResultTestCase.php', 'ArcanistUnitTestableLintEngine' => 'lint/engine/ArcanistUnitTestableLintEngine.php', 'ArcanistUnitWorkflow' => 'workflow/ArcanistUnitWorkflow.php', 'ArcanistUnnecessaryFinalModifierXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php', 'ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase.php', 'ArcanistUnnecessarySemicolonXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessarySemicolonXHPASTLinterRule.php', 'ArcanistUnnecessarySymbolAliasXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessarySymbolAliasXHPASTLinterRule.php', 'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase.php', 'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php', 'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase.php', 'ArcanistUpgradeWorkflow' => 'workflow/ArcanistUpgradeWorkflow.php', 'ArcanistUploadWorkflow' => 'workflow/ArcanistUploadWorkflow.php', 'ArcanistUsageException' => 'exception/ArcanistUsageException.php', 'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUseStatementNamespacePrefixXHPASTLinterRule.php', 'ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase.php', 'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUselessOverridingMethodXHPASTLinterRule.php', 'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase.php', 'ArcanistUserAbortException' => 'exception/usage/ArcanistUserAbortException.php', 'ArcanistUserConfigurationSource' => 'config/source/ArcanistUserConfigurationSource.php', 'ArcanistVariableReferenceSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistVariableReferenceSpacingXHPASTLinterRule.php', 'ArcanistVariableReferenceSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistVariableReferenceSpacingXHPASTLinterRuleTestCase.php', 'ArcanistVariableVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistVariableVariableXHPASTLinterRule.php', 'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistVariableVariableXHPASTLinterRuleTestCase.php', 'ArcanistVersionWorkflow' => 'toolset/workflow/ArcanistVersionWorkflow.php', 'ArcanistWeldWorkflow' => 'workflow/ArcanistWeldWorkflow.php', 'ArcanistWhichWorkflow' => 'workflow/ArcanistWhichWorkflow.php', 'ArcanistWildConfigOption' => 'config/option/ArcanistWildConfigOption.php', 'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php', 'ArcanistWorkflowArgument' => 'toolset/ArcanistWorkflowArgument.php', 'ArcanistWorkflowInformation' => 'toolset/ArcanistWorkflowInformation.php', 'ArcanistWorkingCopy' => 'workingcopy/ArcanistWorkingCopy.php', 'ArcanistWorkingCopyConfigurationSource' => 'config/source/ArcanistWorkingCopyConfigurationSource.php', 'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php', 'ArcanistWorkingCopyPath' => 'workingcopy/ArcanistWorkingCopyPath.php', 'ArcanistWorkingCopyStateRef' => 'ref/ArcanistWorkingCopyStateRef.php', 'ArcanistXHPASTLintNamingHook' => 'lint/linter/xhpast/ArcanistXHPASTLintNamingHook.php', 'ArcanistXHPASTLintNamingHookTestCase' => 'lint/linter/xhpast/__tests__/ArcanistXHPASTLintNamingHookTestCase.php', 'ArcanistXHPASTLintSwitchHook' => 'lint/linter/xhpast/ArcanistXHPASTLintSwitchHook.php', 'ArcanistXHPASTLinter' => 'lint/linter/ArcanistXHPASTLinter.php', 'ArcanistXHPASTLinterRule' => 'lint/linter/xhpast/ArcanistXHPASTLinterRule.php', 'ArcanistXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistXHPASTLinterRuleTestCase.php', 'ArcanistXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistXHPASTLinterTestCase.php', 'ArcanistXMLLinter' => 'lint/linter/ArcanistXMLLinter.php', 'ArcanistXMLLinterTestCase' => 'lint/linter/__tests__/ArcanistXMLLinterTestCase.php', 'ArcanistXUnitTestResultParser' => 'unit/parser/ArcanistXUnitTestResultParser.php', 'BaseHTTPFuture' => 'future/http/BaseHTTPFuture.php', 'CSharpToolsTestEngine' => 'unit/engine/CSharpToolsTestEngine.php', 'CaseInsensitiveArray' => 'utils/CaseInsensitiveArray.php', 'CaseInsensitiveArrayTestCase' => 'utils/__tests__/CaseInsensitiveArrayTestCase.php', 'CommandException' => 'future/exec/CommandException.php', 'ConduitClient' => 'conduit/ConduitClient.php', 'ConduitClientException' => 'conduit/ConduitClientException.php', 'ConduitClientTestCase' => 'conduit/__tests__/ConduitClientTestCase.php', 'ConduitFuture' => 'conduit/ConduitFuture.php', 'ExecFuture' => 'future/exec/ExecFuture.php', 'ExecFutureTestCase' => 'future/exec/__tests__/ExecFutureTestCase.php', 'ExecPassthruTestCase' => 'future/exec/__tests__/ExecPassthruTestCase.php', 'FileFinder' => 'filesystem/FileFinder.php', 'FileFinderTestCase' => 'filesystem/__tests__/FileFinderTestCase.php', 'FileList' => 'filesystem/FileList.php', 'Filesystem' => 'filesystem/Filesystem.php', 'FilesystemException' => 'filesystem/FilesystemException.php', 'FilesystemTestCase' => 'filesystem/__tests__/FilesystemTestCase.php', 'Future' => 'future/Future.php', 'FutureIterator' => 'future/FutureIterator.php', 'FutureIteratorTestCase' => 'future/__tests__/FutureIteratorTestCase.php', 'FutureProxy' => 'future/FutureProxy.php', 'HTTPFuture' => 'future/http/HTTPFuture.php', 'HTTPFutureCURLResponseStatus' => 'future/http/status/HTTPFutureCURLResponseStatus.php', 'HTTPFutureCertificateResponseStatus' => 'future/http/status/HTTPFutureCertificateResponseStatus.php', 'HTTPFutureHTTPResponseStatus' => 'future/http/status/HTTPFutureHTTPResponseStatus.php', 'HTTPFutureParseResponseStatus' => 'future/http/status/HTTPFutureParseResponseStatus.php', 'HTTPFutureResponseStatus' => 'future/http/status/HTTPFutureResponseStatus.php', 'HTTPFutureTransportResponseStatus' => 'future/http/status/HTTPFutureTransportResponseStatus.php', 'HTTPSFuture' => 'future/http/HTTPSFuture.php', 'ImmediateFuture' => 'future/ImmediateFuture.php', 'LibphutilUSEnglishTranslation' => 'internationalization/translation/LibphutilUSEnglishTranslation.php', 'LinesOfALarge' => 'filesystem/linesofalarge/LinesOfALarge.php', 'LinesOfALargeExecFuture' => 'filesystem/linesofalarge/LinesOfALargeExecFuture.php', 'LinesOfALargeExecFutureTestCase' => 'filesystem/linesofalarge/__tests__/LinesOfALargeExecFutureTestCase.php', 'LinesOfALargeFile' => 'filesystem/linesofalarge/LinesOfALargeFile.php', 'LinesOfALargeFileTestCase' => 'filesystem/linesofalarge/__tests__/LinesOfALargeFileTestCase.php', 'MFilterTestHelper' => 'utils/__tests__/MFilterTestHelper.php', 'NoseTestEngine' => 'unit/engine/NoseTestEngine.php', 'PHPASTParserTestCase' => 'parser/xhpast/__tests__/PHPASTParserTestCase.php', 'PhageAction' => 'phage/action/PhageAction.php', 'PhageAgentAction' => 'phage/action/PhageAgentAction.php', 'PhageAgentBootloader' => 'phage/bootloader/PhageAgentBootloader.php', 'PhageAgentTestCase' => 'phage/__tests__/PhageAgentTestCase.php', 'PhageExecuteAction' => 'phage/action/PhageExecuteAction.php', 'PhageLocalAction' => 'phage/action/PhageLocalAction.php', 'PhagePHPAgent' => 'phage/agent/PhagePHPAgent.php', 'PhagePHPAgentBootloader' => 'phage/bootloader/PhagePHPAgentBootloader.php', 'PhagePlanAction' => 'phage/action/PhagePlanAction.php', 'PhageWorkflow' => 'phage/workflow/PhageWorkflow.php', 'Phobject' => 'object/Phobject.php', 'PhobjectTestCase' => 'object/__tests__/PhobjectTestCase.php', 'PhpunitTestEngine' => 'unit/engine/PhpunitTestEngine.php', 'PhpunitTestEngineTestCase' => 'unit/engine/__tests__/PhpunitTestEngineTestCase.php', 'PhutilAWSCloudFormationFuture' => 'future/aws/PhutilAWSCloudFormationFuture.php', 'PhutilAWSCloudWatchFuture' => 'future/aws/PhutilAWSCloudWatchFuture.php', 'PhutilAWSEC2Future' => 'future/aws/PhutilAWSEC2Future.php', 'PhutilAWSException' => 'future/aws/PhutilAWSException.php', 'PhutilAWSFuture' => 'future/aws/PhutilAWSFuture.php', 'PhutilAWSManagementWorkflow' => 'future/aws/management/PhutilAWSManagementWorkflow.php', 'PhutilAWSS3DeleteManagementWorkflow' => 'future/aws/management/PhutilAWSS3DeleteManagementWorkflow.php', 'PhutilAWSS3Future' => 'future/aws/PhutilAWSS3Future.php', 'PhutilAWSS3GetManagementWorkflow' => 'future/aws/management/PhutilAWSS3GetManagementWorkflow.php', 'PhutilAWSS3ManagementWorkflow' => 'future/aws/management/PhutilAWSS3ManagementWorkflow.php', 'PhutilAWSS3PutManagementWorkflow' => 'future/aws/management/PhutilAWSS3PutManagementWorkflow.php', 'PhutilAWSv4Signature' => 'future/aws/PhutilAWSv4Signature.php', 'PhutilAWSv4SignatureTestCase' => 'future/aws/__tests__/PhutilAWSv4SignatureTestCase.php', 'PhutilAggregateException' => 'error/PhutilAggregateException.php', 'PhutilAllCapsEnglishLocale' => 'internationalization/locales/PhutilAllCapsEnglishLocale.php', 'PhutilArgumentParser' => 'parser/argument/PhutilArgumentParser.php', 'PhutilArgumentParserException' => 'parser/argument/exception/PhutilArgumentParserException.php', 'PhutilArgumentParserTestCase' => 'parser/argument/__tests__/PhutilArgumentParserTestCase.php', 'PhutilArgumentSpecification' => 'parser/argument/PhutilArgumentSpecification.php', 'PhutilArgumentSpecificationException' => 'parser/argument/exception/PhutilArgumentSpecificationException.php', 'PhutilArgumentSpecificationTestCase' => 'parser/argument/__tests__/PhutilArgumentSpecificationTestCase.php', 'PhutilArgumentSpellingCorrector' => 'parser/argument/PhutilArgumentSpellingCorrector.php', 'PhutilArgumentSpellingCorrectorTestCase' => 'parser/argument/__tests__/PhutilArgumentSpellingCorrectorTestCase.php', 'PhutilArgumentUsageException' => 'parser/argument/exception/PhutilArgumentUsageException.php', 'PhutilArgumentWorkflow' => 'parser/argument/workflow/PhutilArgumentWorkflow.php', 'PhutilArray' => 'utils/PhutilArray.php', 'PhutilArrayTestCase' => 'utils/__tests__/PhutilArrayTestCase.php', 'PhutilArrayWithDefaultValue' => 'utils/PhutilArrayWithDefaultValue.php', 'PhutilAsanaFuture' => 'future/asana/PhutilAsanaFuture.php', 'PhutilBacktraceSignalHandler' => 'future/exec/PhutilBacktraceSignalHandler.php', 'PhutilBallOfPHP' => 'phage/util/PhutilBallOfPHP.php', 'PhutilBinaryAnalyzer' => 'filesystem/binary/PhutilBinaryAnalyzer.php', 'PhutilBinaryAnalyzerTestCase' => 'filesystem/binary/__tests__/PhutilBinaryAnalyzerTestCase.php', 'PhutilBootloader' => 'init/lib/PhutilBootloader.php', 'PhutilBootloaderException' => 'init/lib/PhutilBootloaderException.php', 'PhutilBritishEnglishLocale' => 'internationalization/locales/PhutilBritishEnglishLocale.php', 'PhutilBufferedIterator' => 'utils/PhutilBufferedIterator.php', 'PhutilBufferedIteratorTestCase' => 'utils/__tests__/PhutilBufferedIteratorTestCase.php', 'PhutilBugtraqParser' => 'parser/PhutilBugtraqParser.php', 'PhutilBugtraqParserTestCase' => 'parser/__tests__/PhutilBugtraqParserTestCase.php', 'PhutilCIDRBlock' => 'ip/PhutilCIDRBlock.php', 'PhutilCIDRList' => 'ip/PhutilCIDRList.php', 'PhutilCallbackFilterIterator' => 'utils/PhutilCallbackFilterIterator.php', 'PhutilCallbackSignalHandler' => 'future/exec/PhutilCallbackSignalHandler.php', 'PhutilChannel' => 'channel/PhutilChannel.php', 'PhutilChannelChannel' => 'channel/PhutilChannelChannel.php', 'PhutilChannelTestCase' => 'channel/__tests__/PhutilChannelTestCase.php', 'PhutilChunkedIterator' => 'utils/PhutilChunkedIterator.php', 'PhutilChunkedIteratorTestCase' => 'utils/__tests__/PhutilChunkedIteratorTestCase.php', 'PhutilClassMapQuery' => 'symbols/PhutilClassMapQuery.php', 'PhutilCloudWatchMetric' => 'future/aws/PhutilCloudWatchMetric.php', 'PhutilCommandString' => 'xsprintf/PhutilCommandString.php', 'PhutilConsole' => 'console/PhutilConsole.php', 'PhutilConsoleBlock' => 'console/view/PhutilConsoleBlock.php', 'PhutilConsoleError' => 'console/view/PhutilConsoleError.php', 'PhutilConsoleFormatter' => 'console/PhutilConsoleFormatter.php', 'PhutilConsoleInfo' => 'console/view/PhutilConsoleInfo.php', 'PhutilConsoleList' => 'console/view/PhutilConsoleList.php', 'PhutilConsoleLogLine' => 'console/view/PhutilConsoleLogLine.php', 'PhutilConsoleMessage' => 'console/PhutilConsoleMessage.php', 'PhutilConsoleMetrics' => 'console/PhutilConsoleMetrics.php', 'PhutilConsoleMetricsSignalHandler' => 'future/exec/PhutilConsoleMetricsSignalHandler.php', 'PhutilConsoleProgressBar' => 'console/PhutilConsoleProgressBar.php', 'PhutilConsoleProgressSink' => 'progress/PhutilConsoleProgressSink.php', 'PhutilConsoleServer' => 'console/PhutilConsoleServer.php', 'PhutilConsoleServerChannel' => 'console/PhutilConsoleServerChannel.php', 'PhutilConsoleSkip' => 'console/view/PhutilConsoleSkip.php', 'PhutilConsoleStdinNotInteractiveException' => 'console/PhutilConsoleStdinNotInteractiveException.php', 'PhutilConsoleTable' => 'console/view/PhutilConsoleTable.php', 'PhutilConsoleView' => 'console/view/PhutilConsoleView.php', 'PhutilConsoleWarning' => 'console/view/PhutilConsoleWarning.php', 'PhutilConsoleWrapTestCase' => 'console/__tests__/PhutilConsoleWrapTestCase.php', 'PhutilCowsay' => 'utils/PhutilCowsay.php', 'PhutilCowsayTestCase' => 'utils/__tests__/PhutilCowsayTestCase.php', 'PhutilCsprintfTestCase' => 'xsprintf/__tests__/PhutilCsprintfTestCase.php', 'PhutilCzechLocale' => 'internationalization/locales/PhutilCzechLocale.php', 'PhutilDOMNode' => 'parser/html/PhutilDOMNode.php', 'PhutilDeferredLog' => 'filesystem/PhutilDeferredLog.php', 'PhutilDeferredLogTestCase' => 'filesystem/__tests__/PhutilDeferredLogTestCase.php', 'PhutilDiffBinaryAnalyzer' => 'filesystem/binary/PhutilDiffBinaryAnalyzer.php', 'PhutilDirectedScalarGraph' => 'utils/PhutilDirectedScalarGraph.php', 'PhutilDirectoryFixture' => 'filesystem/PhutilDirectoryFixture.php', 'PhutilDocblockParser' => 'parser/PhutilDocblockParser.php', 'PhutilDocblockParserTestCase' => 'parser/__tests__/PhutilDocblockParserTestCase.php', 'PhutilEditDistanceMatrix' => 'utils/PhutilEditDistanceMatrix.php', 'PhutilEditDistanceMatrixTestCase' => 'utils/__tests__/PhutilEditDistanceMatrixTestCase.php', 'PhutilEditorConfig' => 'parser/PhutilEditorConfig.php', 'PhutilEditorConfigTestCase' => 'parser/__tests__/PhutilEditorConfigTestCase.php', 'PhutilEmailAddress' => 'parser/PhutilEmailAddress.php', 'PhutilEmailAddressTestCase' => 'parser/__tests__/PhutilEmailAddressTestCase.php', 'PhutilEmojiLocale' => 'internationalization/locales/PhutilEmojiLocale.php', 'PhutilEnglishCanadaLocale' => 'internationalization/locales/PhutilEnglishCanadaLocale.php', 'PhutilErrorHandler' => 'error/PhutilErrorHandler.php', 'PhutilErrorHandlerTestCase' => 'error/__tests__/PhutilErrorHandlerTestCase.php', 'PhutilErrorTrap' => 'error/PhutilErrorTrap.php', 'PhutilEvent' => 'events/PhutilEvent.php', 'PhutilEventConstants' => 'events/constant/PhutilEventConstants.php', 'PhutilEventEngine' => 'events/PhutilEventEngine.php', 'PhutilEventListener' => 'events/PhutilEventListener.php', 'PhutilEventType' => 'events/constant/PhutilEventType.php', 'PhutilExampleBufferedIterator' => 'utils/PhutilExampleBufferedIterator.php', 'PhutilExecChannel' => 'channel/PhutilExecChannel.php', 'PhutilExecPassthru' => 'future/exec/PhutilExecPassthru.php', 'PhutilExecutableFuture' => 'future/exec/PhutilExecutableFuture.php', 'PhutilExecutionEnvironment' => 'utils/PhutilExecutionEnvironment.php', 'PhutilFileLock' => 'filesystem/PhutilFileLock.php', 'PhutilFileLockTestCase' => 'filesystem/__tests__/PhutilFileLockTestCase.php', 'PhutilFileTree' => 'filesystem/PhutilFileTree.php', 'PhutilFrenchLocale' => 'internationalization/locales/PhutilFrenchLocale.php', 'PhutilGermanLocale' => 'internationalization/locales/PhutilGermanLocale.php', 'PhutilGitBinaryAnalyzer' => 'filesystem/binary/PhutilGitBinaryAnalyzer.php', 'PhutilGitHubFuture' => 'future/github/PhutilGitHubFuture.php', 'PhutilGitHubResponse' => 'future/github/PhutilGitHubResponse.php', 'PhutilGitURI' => 'parser/PhutilGitURI.php', 'PhutilGitURITestCase' => 'parser/__tests__/PhutilGitURITestCase.php', 'PhutilHTMLParser' => 'parser/html/PhutilHTMLParser.php', 'PhutilHTMLParserTestCase' => 'parser/html/__tests__/PhutilHTMLParserTestCase.php', 'PhutilHTTPEngineExtension' => 'future/http/PhutilHTTPEngineExtension.php', 'PhutilHTTPResponse' => 'parser/http/PhutilHTTPResponse.php', 'PhutilHTTPResponseParser' => 'parser/http/PhutilHTTPResponseParser.php', 'PhutilHTTPResponseParserTestCase' => 'parser/http/__tests__/PhutilHTTPResponseParserTestCase.php', 'PhutilHashingIterator' => 'utils/PhutilHashingIterator.php', 'PhutilHashingIteratorTestCase' => 'utils/__tests__/PhutilHashingIteratorTestCase.php', 'PhutilHelpArgumentWorkflow' => 'parser/argument/workflow/PhutilHelpArgumentWorkflow.php', 'PhutilHgsprintfTestCase' => 'xsprintf/__tests__/PhutilHgsprintfTestCase.php', 'PhutilINIParserException' => 'parser/exception/PhutilINIParserException.php', 'PhutilIPAddress' => 'ip/PhutilIPAddress.php', 'PhutilIPAddressTestCase' => 'ip/__tests__/PhutilIPAddressTestCase.php', 'PhutilIPv4Address' => 'ip/PhutilIPv4Address.php', 'PhutilIPv6Address' => 'ip/PhutilIPv6Address.php', 'PhutilInteractiveEditor' => 'console/PhutilInteractiveEditor.php', 'PhutilInvalidRuleParserGeneratorException' => 'parser/generator/exception/PhutilInvalidRuleParserGeneratorException.php', 'PhutilInvalidStateException' => 'exception/PhutilInvalidStateException.php', 'PhutilInvalidStateExceptionTestCase' => 'exception/__tests__/PhutilInvalidStateExceptionTestCase.php', 'PhutilIrreducibleRuleParserGeneratorException' => 'parser/generator/exception/PhutilIrreducibleRuleParserGeneratorException.php', 'PhutilJSON' => 'parser/PhutilJSON.php', 'PhutilJSONFragmentLexer' => 'lexer/PhutilJSONFragmentLexer.php', 'PhutilJSONParser' => 'parser/PhutilJSONParser.php', 'PhutilJSONParserException' => 'parser/exception/PhutilJSONParserException.php', 'PhutilJSONParserTestCase' => 'parser/__tests__/PhutilJSONParserTestCase.php', 'PhutilJSONProtocolChannel' => 'channel/PhutilJSONProtocolChannel.php', 'PhutilJSONProtocolChannelTestCase' => 'channel/__tests__/PhutilJSONProtocolChannelTestCase.php', 'PhutilJSONTestCase' => 'parser/__tests__/PhutilJSONTestCase.php', 'PhutilJavaFragmentLexer' => 'lexer/PhutilJavaFragmentLexer.php', 'PhutilKoreanLocale' => 'internationalization/locales/PhutilKoreanLocale.php', 'PhutilLanguageGuesser' => 'parser/PhutilLanguageGuesser.php', 'PhutilLanguageGuesserTestCase' => 'parser/__tests__/PhutilLanguageGuesserTestCase.php', 'PhutilLexer' => 'lexer/PhutilLexer.php', 'PhutilLibraryConflictException' => 'init/lib/PhutilLibraryConflictException.php', 'PhutilLibraryMapBuilder' => 'moduleutils/PhutilLibraryMapBuilder.php', 'PhutilLibraryTestCase' => '__tests__/PhutilLibraryTestCase.php', 'PhutilLocale' => 'internationalization/PhutilLocale.php', 'PhutilLocaleTestCase' => 'internationalization/__tests__/PhutilLocaleTestCase.php', 'PhutilLock' => 'filesystem/PhutilLock.php', 'PhutilLockException' => 'filesystem/PhutilLockException.php', 'PhutilLogFileChannel' => 'channel/PhutilLogFileChannel.php', 'PhutilLunarPhase' => 'utils/PhutilLunarPhase.php', 'PhutilLunarPhaseTestCase' => 'utils/__tests__/PhutilLunarPhaseTestCase.php', 'PhutilMercurialBinaryAnalyzer' => 'filesystem/binary/PhutilMercurialBinaryAnalyzer.php', 'PhutilMethodNotImplementedException' => 'error/PhutilMethodNotImplementedException.php', 'PhutilMetricsChannel' => 'channel/PhutilMetricsChannel.php', 'PhutilMissingSymbolException' => 'init/lib/PhutilMissingSymbolException.php', 'PhutilModuleUtilsTestCase' => 'init/lib/__tests__/PhutilModuleUtilsTestCase.php', 'PhutilNumber' => 'internationalization/PhutilNumber.php', 'PhutilOAuth1Future' => 'future/oauth/PhutilOAuth1Future.php', 'PhutilOAuth1FutureTestCase' => 'future/oauth/__tests__/PhutilOAuth1FutureTestCase.php', 'PhutilOpaqueEnvelope' => 'error/PhutilOpaqueEnvelope.php', 'PhutilOpaqueEnvelopeKey' => 'error/PhutilOpaqueEnvelopeKey.php', 'PhutilOpaqueEnvelopeTestCase' => 'error/__tests__/PhutilOpaqueEnvelopeTestCase.php', 'PhutilPHPFragmentLexer' => 'lexer/PhutilPHPFragmentLexer.php', 'PhutilPHPFragmentLexerTestCase' => 'lexer/__tests__/PhutilPHPFragmentLexerTestCase.php', 'PhutilPHPObjectProtocolChannel' => 'channel/PhutilPHPObjectProtocolChannel.php', 'PhutilPHPObjectProtocolChannelTestCase' => 'channel/__tests__/PhutilPHPObjectProtocolChannelTestCase.php', 'PhutilParserGenerator' => 'parser/PhutilParserGenerator.php', 'PhutilParserGeneratorException' => 'parser/generator/exception/PhutilParserGeneratorException.php', 'PhutilParserGeneratorTestCase' => 'parser/__tests__/PhutilParserGeneratorTestCase.php', 'PhutilPayPalAPIFuture' => 'future/paypal/PhutilPayPalAPIFuture.php', 'PhutilPerson' => 'internationalization/PhutilPerson.php', 'PhutilPersonTest' => 'internationalization/__tests__/PhutilPersonTest.php', 'PhutilPhtTestCase' => 'internationalization/__tests__/PhutilPhtTestCase.php', 'PhutilPirateEnglishLocale' => 'internationalization/locales/PhutilPirateEnglishLocale.php', 'PhutilPortugueseBrazilLocale' => 'internationalization/locales/PhutilPortugueseBrazilLocale.php', 'PhutilPortuguesePortugalLocale' => 'internationalization/locales/PhutilPortuguesePortugalLocale.php', 'PhutilPostmarkFuture' => 'future/postmark/PhutilPostmarkFuture.php', 'PhutilPregsprintfTestCase' => 'xsprintf/__tests__/PhutilPregsprintfTestCase.php', 'PhutilProcessQuery' => 'filesystem/PhutilProcessQuery.php', 'PhutilProcessRef' => 'filesystem/PhutilProcessRef.php', 'PhutilProcessRefTestCase' => 'filesystem/__tests__/PhutilProcessRefTestCase.php', 'PhutilProgressSink' => 'progress/PhutilProgressSink.php', 'PhutilProtocolChannel' => 'channel/PhutilProtocolChannel.php', 'PhutilProxyException' => 'error/PhutilProxyException.php', 'PhutilProxyIterator' => 'utils/PhutilProxyIterator.php', 'PhutilPygmentizeBinaryAnalyzer' => 'filesystem/binary/PhutilPygmentizeBinaryAnalyzer.php', 'PhutilPythonFragmentLexer' => 'lexer/PhutilPythonFragmentLexer.php', 'PhutilQueryStringParser' => 'parser/PhutilQueryStringParser.php', 'PhutilQueryStringParserTestCase' => 'parser/__tests__/PhutilQueryStringParserTestCase.php', 'PhutilRawEnglishLocale' => 'internationalization/locales/PhutilRawEnglishLocale.php', 'PhutilReadableSerializer' => 'readableserializer/PhutilReadableSerializer.php', 'PhutilReadableSerializerTestCase' => 'readableserializer/__tests__/PhutilReadableSerializerTestCase.php', 'PhutilRope' => 'utils/PhutilRope.php', 'PhutilRopeTestCase' => 'utils/__tests__/PhutilRopeTestCase.php', 'PhutilServiceProfiler' => 'serviceprofiler/PhutilServiceProfiler.php', 'PhutilShellLexer' => 'lexer/PhutilShellLexer.php', 'PhutilShellLexerTestCase' => 'lexer/__tests__/PhutilShellLexerTestCase.php', 'PhutilSignalHandler' => 'future/exec/PhutilSignalHandler.php', 'PhutilSignalRouter' => 'future/exec/PhutilSignalRouter.php', 'PhutilSimpleOptions' => 'parser/PhutilSimpleOptions.php', 'PhutilSimpleOptionsLexer' => 'lexer/PhutilSimpleOptionsLexer.php', 'PhutilSimpleOptionsLexerTestCase' => 'lexer/__tests__/PhutilSimpleOptionsLexerTestCase.php', 'PhutilSimpleOptionsTestCase' => 'parser/__tests__/PhutilSimpleOptionsTestCase.php', 'PhutilSimplifiedChineseLocale' => 'internationalization/locales/PhutilSimplifiedChineseLocale.php', 'PhutilSlackFuture' => 'future/slack/PhutilSlackFuture.php', 'PhutilSocketChannel' => 'channel/PhutilSocketChannel.php', 'PhutilSortVector' => 'utils/PhutilSortVector.php', 'PhutilSpanishSpainLocale' => 'internationalization/locales/PhutilSpanishSpainLocale.php', 'PhutilStreamIterator' => 'utils/PhutilStreamIterator.php', 'PhutilSubversionBinaryAnalyzer' => 'filesystem/binary/PhutilSubversionBinaryAnalyzer.php', 'PhutilSymbolLoader' => 'symbols/PhutilSymbolLoader.php', 'PhutilSystem' => 'utils/PhutilSystem.php', 'PhutilSystemTestCase' => 'utils/__tests__/PhutilSystemTestCase.php', 'PhutilTerminalString' => 'xsprintf/PhutilTerminalString.php', 'PhutilTestCase' => 'unit/engine/phutil/PhutilTestCase.php', 'PhutilTestCaseTestCase' => 'unit/engine/phutil/testcase/PhutilTestCaseTestCase.php', 'PhutilTestPhobject' => 'object/__tests__/PhutilTestPhobject.php', 'PhutilTestSkippedException' => 'unit/engine/phutil/testcase/PhutilTestSkippedException.php', 'PhutilTestTerminatedException' => 'unit/engine/phutil/testcase/PhutilTestTerminatedException.php', 'PhutilTraditionalChineseLocale' => 'internationalization/locales/PhutilTraditionalChineseLocale.php', 'PhutilTranslation' => 'internationalization/PhutilTranslation.php', 'PhutilTranslationTestCase' => 'internationalization/__tests__/PhutilTranslationTestCase.php', 'PhutilTranslator' => 'internationalization/PhutilTranslator.php', 'PhutilTranslatorTestCase' => 'internationalization/__tests__/PhutilTranslatorTestCase.php', 'PhutilTsprintfTestCase' => 'xsprintf/__tests__/PhutilTsprintfTestCase.php', 'PhutilTwitchFuture' => 'future/twitch/PhutilTwitchFuture.php', 'PhutilTypeCheckException' => 'parser/exception/PhutilTypeCheckException.php', 'PhutilTypeExtraParametersException' => 'parser/exception/PhutilTypeExtraParametersException.php', 'PhutilTypeLexer' => 'lexer/PhutilTypeLexer.php', 'PhutilTypeMissingParametersException' => 'parser/exception/PhutilTypeMissingParametersException.php', 'PhutilTypeSpec' => 'parser/PhutilTypeSpec.php', 'PhutilTypeSpecTestCase' => 'parser/__tests__/PhutilTypeSpecTestCase.php', 'PhutilURI' => 'parser/PhutilURI.php', 'PhutilURITestCase' => 'parser/__tests__/PhutilURITestCase.php', 'PhutilUSEnglishLocale' => 'internationalization/locales/PhutilUSEnglishLocale.php', 'PhutilUTF8StringTruncator' => 'utils/PhutilUTF8StringTruncator.php', 'PhutilUTF8TestCase' => 'utils/__tests__/PhutilUTF8TestCase.php', 'PhutilUnitTestEngine' => 'unit/engine/PhutilUnitTestEngine.php', 'PhutilUnitTestEngineTestCase' => 'unit/engine/__tests__/PhutilUnitTestEngineTestCase.php', 'PhutilUnknownSymbolParserGeneratorException' => 'parser/generator/exception/PhutilUnknownSymbolParserGeneratorException.php', 'PhutilUnreachableRuleParserGeneratorException' => 'parser/generator/exception/PhutilUnreachableRuleParserGeneratorException.php', 'PhutilUnreachableTerminalParserGeneratorException' => 'parser/generator/exception/PhutilUnreachableTerminalParserGeneratorException.php', 'PhutilUrisprintfTestCase' => 'xsprintf/__tests__/PhutilUrisprintfTestCase.php', 'PhutilUtilsTestCase' => 'utils/__tests__/PhutilUtilsTestCase.php', 'PhutilVeryWowEnglishLocale' => 'internationalization/locales/PhutilVeryWowEnglishLocale.php', 'PhutilWordPressFuture' => 'future/wordpress/PhutilWordPressFuture.php', 'PhutilXHPASTBinary' => 'parser/xhpast/bin/PhutilXHPASTBinary.php', 'PytestTestEngine' => 'unit/engine/PytestTestEngine.php', 'TempFile' => 'filesystem/TempFile.php', 'TestAbstractDirectedGraph' => 'utils/__tests__/TestAbstractDirectedGraph.php', 'XHPASTNode' => 'parser/xhpast/api/XHPASTNode.php', 'XHPASTNodeTestCase' => 'parser/xhpast/api/__tests__/XHPASTNodeTestCase.php', 'XHPASTSyntaxErrorException' => 'parser/xhpast/api/XHPASTSyntaxErrorException.php', 'XHPASTToken' => 'parser/xhpast/api/XHPASTToken.php', 'XHPASTTree' => 'parser/xhpast/api/XHPASTTree.php', 'XHPASTTreeTestCase' => 'parser/xhpast/api/__tests__/XHPASTTreeTestCase.php', 'XUnitTestEngine' => 'unit/engine/XUnitTestEngine.php', 'XUnitTestResultParserTestCase' => 'unit/parser/__tests__/XUnitTestResultParserTestCase.php', 'XsprintfUnknownConversionException' => 'xsprintf/exception/XsprintfUnknownConversionException.php', ), 'function' => array( '__phutil_autoload' => 'init/init-library.php', 'array_fuse' => 'utils/utils.php', 'array_interleave' => 'utils/utils.php', 'array_mergev' => 'utils/utils.php', 'array_select_keys' => 'utils/utils.php', 'assert_instances_of' => 'utils/utils.php', 'assert_same_keys' => 'utils/utils.php', 'assert_stringlike' => 'utils/utils.php', 'coalesce' => 'utils/utils.php', 'csprintf' => 'xsprintf/csprintf.php', 'exec_manual' => 'future/exec/execx.php', 'execx' => 'future/exec/execx.php', 'head' => 'utils/utils.php', 'head_key' => 'utils/utils.php', 'hgsprintf' => 'xsprintf/hgsprintf.php', 'id' => 'utils/utils.php', 'idx' => 'utils/utils.php', 'idxv' => 'utils/utils.php', 'ifilter' => 'utils/utils.php', 'igroup' => 'utils/utils.php', 'ipull' => 'utils/utils.php', 'isort' => 'utils/utils.php', 'jsprintf' => 'xsprintf/jsprintf.php', 'last' => 'utils/utils.php', 'last_key' => 'utils/utils.php', 'ldap_sprintf' => 'xsprintf/ldapsprintf.php', 'mfilter' => 'utils/utils.php', 'mgroup' => 'utils/utils.php', 'mpull' => 'utils/utils.php', 'msort' => 'utils/utils.php', 'msortv' => 'utils/utils.php', 'newv' => 'utils/utils.php', 'nonempty' => 'utils/utils.php', 'phlog' => 'error/phlog.php', 'pht' => 'internationalization/pht.php', 'phutil_build_http_querystring' => 'utils/utils.php', 'phutil_build_http_querystring_from_pairs' => 'utils/utils.php', 'phutil_censor_credentials' => 'utils/utils.php', 'phutil_console_confirm' => 'console/format.php', 'phutil_console_format' => 'console/format.php', 'phutil_console_get_terminal_width' => 'console/format.php', 'phutil_console_prompt' => 'console/format.php', 'phutil_console_require_tty' => 'console/format.php', 'phutil_console_select' => 'console/format.php', 'phutil_console_wrap' => 'console/format.php', 'phutil_count' => 'internationalization/pht.php', 'phutil_date_format' => 'utils/viewutils.php', 'phutil_decode_mime_header' => 'utils/utils.php', 'phutil_deprecated' => 'init/lib/moduleutils.php', 'phutil_describe_type' => 'utils/utils.php', 'phutil_error_listener_example' => 'error/phlog.php', 'phutil_escape_uri' => 'utils/utils.php', 'phutil_escape_uri_path_component' => 'utils/utils.php', 'phutil_fnmatch' => 'utils/utils.php', 'phutil_format_bytes' => 'utils/viewutils.php', 'phutil_format_relative_time' => 'utils/viewutils.php', 'phutil_format_relative_time_detailed' => 'utils/viewutils.php', 'phutil_format_units_generic' => 'utils/viewutils.php', 'phutil_fwrite_nonblocking_stream' => 'utils/utils.php', 'phutil_get_current_library_name' => 'init/lib/moduleutils.php', 'phutil_get_library_name_for_root' => 'init/lib/moduleutils.php', 'phutil_get_library_root' => 'init/lib/moduleutils.php', 'phutil_get_library_root_for_path' => 'init/lib/moduleutils.php', 'phutil_get_signal_name' => 'future/exec/execx.php', 'phutil_get_system_locale' => 'utils/utf8.php', 'phutil_hashes_are_identical' => 'utils/utils.php', 'phutil_http_parameter_pair' => 'utils/utils.php', 'phutil_ini_decode' => 'utils/utils.php', 'phutil_is_hiphop_runtime' => 'utils/utils.php', 'phutil_is_natural_list' => 'utils/utils.php', 'phutil_is_system_locale_available' => 'utils/utf8.php', 'phutil_is_utf8' => 'utils/utf8.php', 'phutil_is_utf8_slowly' => 'utils/utf8.php', 'phutil_is_utf8_with_only_bmp_characters' => 'utils/utf8.php', 'phutil_is_windows' => 'utils/utils.php', 'phutil_json_decode' => 'utils/utils.php', 'phutil_json_encode' => 'utils/utils.php', 'phutil_load_library' => 'init/lib/moduleutils.php', 'phutil_loggable_string' => 'utils/utils.php', 'phutil_microseconds_since' => 'utils/utils.php', 'phutil_parse_bytes' => 'utils/viewutils.php', 'phutil_passthru' => 'future/exec/execx.php', 'phutil_person' => 'internationalization/pht.php', 'phutil_register_library' => 'init/lib/core.php', 'phutil_register_library_map' => 'init/lib/core.php', 'phutil_set_system_locale' => 'utils/utf8.php', 'phutil_split_lines' => 'utils/utils.php', 'phutil_string_cast' => 'utils/utils.php', 'phutil_unescape_uri_path_component' => 'utils/utils.php', 'phutil_units' => 'utils/utils.php', 'phutil_utf8_console_strlen' => 'utils/utf8.php', 'phutil_utf8_convert' => 'utils/utf8.php', 'phutil_utf8_encode_codepoint' => 'utils/utf8.php', 'phutil_utf8_hard_wrap' => 'utils/utf8.php', 'phutil_utf8_hard_wrap_html' => 'utils/utf8.php', 'phutil_utf8_is_cjk' => 'utils/utf8.php', 'phutil_utf8_is_combining_character' => 'utils/utf8.php', 'phutil_utf8_strlen' => 'utils/utf8.php', 'phutil_utf8_strtolower' => 'utils/utf8.php', 'phutil_utf8_strtoupper' => 'utils/utf8.php', 'phutil_utf8_strtr' => 'utils/utf8.php', 'phutil_utf8_ucwords' => 'utils/utf8.php', 'phutil_utf8ize' => 'utils/utf8.php', 'phutil_utf8v' => 'utils/utf8.php', 'phutil_utf8v_codepoints' => 'utils/utf8.php', 'phutil_utf8v_combine_characters' => 'utils/utf8.php', 'phutil_utf8v_combined' => 'utils/utf8.php', 'phutil_validate_json' => 'utils/utils.php', 'phutil_var_export' => 'utils/utils.php', 'ppull' => 'utils/utils.php', 'pregsprintf' => 'xsprintf/pregsprintf.php', 'tsprintf' => 'xsprintf/tsprintf.php', 'urisprintf' => 'xsprintf/urisprintf.php', 'vcsprintf' => 'xsprintf/csprintf.php', 'vjsprintf' => 'xsprintf/jsprintf.php', 'vurisprintf' => 'xsprintf/urisprintf.php', 'xhp_parser_node_constants' => 'parser/xhpast/parser_nodes.php', 'xhpast_parser_token_constants' => 'parser/xhpast/parser_tokens.php', 'xsprintf' => 'xsprintf/xsprintf.php', 'xsprintf_callback_example' => 'xsprintf/xsprintf.php', 'xsprintf_command' => 'xsprintf/csprintf.php', 'xsprintf_javascript' => 'xsprintf/jsprintf.php', 'xsprintf_ldap' => 'xsprintf/ldapsprintf.php', 'xsprintf_mercurial' => 'xsprintf/hgsprintf.php', 'xsprintf_regex' => 'xsprintf/pregsprintf.php', 'xsprintf_terminal' => 'xsprintf/tsprintf.php', 'xsprintf_uri' => 'xsprintf/urisprintf.php', ), 'xmap' => array( 'AASTNode' => 'Phobject', 'AASTNodeList' => array( 'Phobject', 'Countable', 'Iterator', ), 'AASTToken' => 'Phobject', 'AASTTree' => 'Phobject', 'AbstractDirectedGraph' => 'Phobject', 'AbstractDirectedGraphTestCase' => 'PhutilTestCase', 'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAlias' => 'Phobject', 'ArcanistAliasEffect' => 'Phobject', 'ArcanistAliasEngine' => 'Phobject', 'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistAliasWorkflow' => 'ArcanistWorkflow', 'ArcanistAliasesConfigOption' => 'ArcanistListConfigOption', 'ArcanistAmendWorkflow' => 'ArcanistWorkflow', - 'ArcanistAnoidWorkflow' => 'ArcanistWorkflow', + 'ArcanistAnoidWorkflow' => 'ArcanistArcWorkflow', 'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension', 'ArcanistArcToolset' => 'ArcanistToolset', 'ArcanistArcWorkflow' => 'ArcanistWorkflow', 'ArcanistArrayCombineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayIndexSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistArraySeparatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArraySeparatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistArrayValueXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayValueXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBackoutWorkflow' => 'ArcanistWorkflow', 'ArcanistBaseCommitParser' => 'Phobject', 'ArcanistBaseCommitParserTestCase' => 'PhutilTestCase', 'ArcanistBaseXHPASTLinter' => 'ArcanistFutureLinter', 'ArcanistBinaryExpressionSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBinaryNumericScalarCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBlindlyTrustHTTPEngineExtension' => 'PhutilHTTPEngineExtension', 'ArcanistBookmarkWorkflow' => 'ArcanistFeatureWorkflow', 'ArcanistBraceFormattingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBranchRef' => 'ArcanistRef', 'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow', 'ArcanistBrowseCommitHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistBrowseCommitURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowseObjectNameURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowsePathURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowseRef' => 'ArcanistRef', 'ArcanistBrowseRevisionURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader', 'ArcanistBrowseURIHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistBrowseURIRef' => 'ArcanistRef', 'ArcanistBrowseWorkflow' => 'ArcanistWorkflow', 'ArcanistBuildPlanRef' => 'Phobject', 'ArcanistBuildRef' => 'Phobject', 'ArcanistBundle' => 'Phobject', 'ArcanistBundleTestCase' => 'PhutilTestCase', 'ArcanistCSSLintLinter' => 'ArcanistExternalLinter', 'ArcanistCSSLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCSharpLinter' => 'ArcanistLinter', 'ArcanistCallConduitWorkflow' => 'ArcanistWorkflow', 'ArcanistCallParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCallParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCallTimePassByReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCallTimePassByReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCapabilityNotSupportedException' => 'Exception', 'ArcanistCastSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCastSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCheckstyleXMLLintRenderer' => 'ArcanistLintRenderer', 'ArcanistChmodLinter' => 'ArcanistLinter', 'ArcanistChmodLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistClassExtendsObjectXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistClassExtendsObjectXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistClassFilenameMismatchXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistClassNameLiteralXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistClassNameLiteralXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCloseRevisionWorkflow' => 'ArcanistWorkflow', 'ArcanistCloseWorkflow' => 'ArcanistWorkflow', 'ArcanistClosureLinter' => 'ArcanistExternalLinter', 'ArcanistClosureLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCoffeeLintLinter' => 'ArcanistExternalLinter', 'ArcanistCoffeeLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCommentRemover' => 'Phobject', 'ArcanistCommentRemoverTestCase' => 'PhutilTestCase', 'ArcanistCommentSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCommentStyleXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCommitRef' => 'ArcanistRef', 'ArcanistCommitUpstreamHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistCommitWorkflow' => 'ArcanistWorkflow', 'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer', 'ArcanistComposerLinter' => 'ArcanistLinter', 'ArcanistComprehensiveLintEngine' => 'ArcanistLintEngine', 'ArcanistConcatenationOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistConcatenationOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistConduitCall' => 'Phobject', 'ArcanistConduitEngine' => 'Phobject', 'ArcanistConduitException' => 'Exception', 'ArcanistConfigOption' => 'Phobject', 'ArcanistConfiguration' => 'Phobject', 'ArcanistConfigurationDrivenLintEngine' => 'ArcanistLintEngine', 'ArcanistConfigurationDrivenUnitTestEngine' => 'ArcanistUnitTestEngine', 'ArcanistConfigurationEngine' => 'Phobject', 'ArcanistConfigurationEngineExtension' => 'Phobject', 'ArcanistConfigurationManager' => 'Phobject', 'ArcanistConfigurationSource' => 'Phobject', 'ArcanistConfigurationSourceList' => 'Phobject', 'ArcanistConfigurationSourceValue' => 'Phobject', 'ArcanistConsoleLintRenderer' => 'ArcanistLintRenderer', 'ArcanistConsoleLintRendererTestCase' => 'PhutilTestCase', 'ArcanistConstructorParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistConstructorParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistContinueInsideSwitchXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistContinueInsideSwitchXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistControlStatementSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistControlStatementSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistCoverWorkflow' => 'ArcanistWorkflow', 'ArcanistCppcheckLinter' => 'ArcanistExternalLinter', 'ArcanistCppcheckLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCpplintLinter' => 'ArcanistExternalLinter', 'ArcanistCpplintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistCurlyBraceArrayIndexXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistCurlyBraceArrayIndexXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDeclarationParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDeclarationParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDefaultParametersXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDefaultParametersXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDefaultsConfigurationSource' => 'ArcanistDictionaryConfigurationSource', 'ArcanistDeprecationXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDeprecationXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDictionaryConfigurationSource' => 'ArcanistConfigurationSource', 'ArcanistDiffByteSizeException' => 'Exception', 'ArcanistDiffChange' => 'Phobject', 'ArcanistDiffChangeType' => 'Phobject', 'ArcanistDiffHunk' => 'Phobject', 'ArcanistDiffParser' => 'Phobject', 'ArcanistDiffParserTestCase' => 'PhutilTestCase', 'ArcanistDiffUtils' => 'Phobject', 'ArcanistDiffUtilsTestCase' => 'PhutilTestCase', 'ArcanistDiffWorkflow' => 'ArcanistWorkflow', 'ArcanistDifferentialCommitMessage' => 'Phobject', 'ArcanistDifferentialCommitMessageParserException' => 'Exception', 'ArcanistDifferentialDependencyGraph' => 'AbstractDirectedGraph', 'ArcanistDifferentialRevisionHash' => 'Phobject', 'ArcanistDifferentialRevisionStatus' => 'Phobject', 'ArcanistDoubleQuoteXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDoubleQuoteXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDownloadWorkflow' => 'ArcanistWorkflow', 'ArcanistDuplicateKeysInArrayXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDuplicateKeysInArrayXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDuplicateSwitchCaseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDynamicDefineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDynamicDefineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistElseIfUsageXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistElseIfUsageXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistEmptyFileXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistEmptyStatementXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistEmptyStatementXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistEventType' => 'PhutilEventType', 'ArcanistExitExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistExitExpressionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistExportWorkflow' => 'ArcanistWorkflow', 'ArcanistExternalLinter' => 'ArcanistFutureLinter', 'ArcanistExternalLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistExtractUseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistExtractUseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistFeatureWorkflow' => 'ArcanistWorkflow', 'ArcanistFileConfigurationSource' => 'ArcanistFilesystemConfigurationSource', 'ArcanistFileDataRef' => 'Phobject', 'ArcanistFileUploader' => 'Phobject', 'ArcanistFilenameLinter' => 'ArcanistLinter', 'ArcanistFilenameLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistFilesystemConfigurationSource' => 'ArcanistDictionaryConfigurationSource', 'ArcanistFlagWorkflow' => 'ArcanistWorkflow', 'ArcanistFlake8Linter' => 'ArcanistExternalLinter', 'ArcanistFlake8LinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistFormattedStringXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistFormattedStringXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistFunctionCallShouldBeTypeCastXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistFutureLinter' => 'ArcanistLinter', 'ArcanistGeneratedLinter' => 'ArcanistLinter', 'ArcanistGeneratedLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow', 'ArcanistGitAPI' => 'ArcanistRepositoryAPI', 'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader', 'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistGitLandEngine' => 'ArcanistLandEngine', 'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader', 'ArcanistGitUpstreamPath' => 'Phobject', 'ArcanistGitWorkingCopy' => 'ArcanistWorkingCopy', 'ArcanistGlobalVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistGlobalVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistGoLintLinter' => 'ArcanistExternalLinter', 'ArcanistGoLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistGoTestResultParser' => 'ArcanistTestResultParser', 'ArcanistGoTestResultParserTestCase' => 'PhutilTestCase', 'ArcanistHLintLinter' => 'ArcanistExternalLinter', 'ArcanistHLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistHardpointLoader' => 'Phobject', 'ArcanistHelpWorkflow' => 'ArcanistWorkflow', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistHgClientChannel' => 'PhutilProtocolChannel', 'ArcanistHgProxyClient' => 'Phobject', 'ArcanistHgProxyServer' => 'Phobject', 'ArcanistHgServerChannel' => 'PhutilProtocolChannel', 'ArcanistImplicitConstructorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistImplicitConstructorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistImplicitFallthroughXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistImplicitFallthroughXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistImplicitVisibilityXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistImplicitVisibilityXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistImplodeArgumentOrderXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistImplodeArgumentOrderXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInlineHTMLXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInlineHTMLXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInnerFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInnerFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInstallCertificateWorkflow' => 'ArcanistWorkflow', 'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidModifiersXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInvalidModifiersXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistInvalidOctalNumericScalarXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistIsAShouldBeInstanceOfXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistIsAShouldBeInstanceOfXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistJSHintLinter' => 'ArcanistExternalLinter', 'ArcanistJSHintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistJSONLintLinter' => 'ArcanistExternalLinter', 'ArcanistJSONLintRenderer' => 'ArcanistLintRenderer', 'ArcanistJSONLinter' => 'ArcanistLinter', 'ArcanistJSONLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistJscsLinter' => 'ArcanistExternalLinter', 'ArcanistJscsLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistKeywordCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistKeywordCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLambdaFuncFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLambdaFuncFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLandEngine' => 'Phobject', 'ArcanistLandWorkflow' => 'ArcanistWorkflow', 'ArcanistLanguageConstructParenthesesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLanguageConstructParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLesscLinter' => 'ArcanistExternalLinter', 'ArcanistLesscLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistLiberateWorkflow' => 'ArcanistArcWorkflow', 'ArcanistLintEngine' => 'Phobject', 'ArcanistLintMessage' => 'Phobject', 'ArcanistLintMessageTestCase' => 'PhutilTestCase', 'ArcanistLintPatcher' => 'Phobject', 'ArcanistLintRenderer' => 'Phobject', 'ArcanistLintResult' => 'Phobject', 'ArcanistLintSeverity' => 'Phobject', 'ArcanistLintWorkflow' => 'ArcanistWorkflow', 'ArcanistLinter' => 'Phobject', 'ArcanistLinterStandard' => 'Phobject', 'ArcanistLinterStandardTestCase' => 'PhutilTestCase', 'ArcanistLinterTestCase' => 'PhutilTestCase', 'ArcanistLintersWorkflow' => 'ArcanistWorkflow', 'ArcanistListAssignmentXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistListAssignmentXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistListConfigOption' => 'ArcanistConfigOption', 'ArcanistListWorkflow' => 'ArcanistWorkflow', 'ArcanistLocalConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource', 'ArcanistLogEngine' => 'Phobject', 'ArcanistLogMessage' => 'Phobject', 'ArcanistLogicalOperatorsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLowercaseFunctionsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistMercurialAPI' => 'ArcanistRepositoryAPI', 'ArcanistMercurialBranchCommitHardpointLoader' => 'ArcanistMercurialHardpointLoader', 'ArcanistMercurialHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistMercurialParser' => 'Phobject', 'ArcanistMercurialParserTestCase' => 'PhutilTestCase', 'ArcanistMercurialWorkingCopy' => 'ArcanistWorkingCopy', 'ArcanistMercurialWorkingCopyCommitHardpointLoader' => 'ArcanistMercurialHardpointLoader', 'ArcanistMergeConflictLinter' => 'ArcanistLinter', 'ArcanistMergeConflictLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistMessageRevisionHardpointLoader' => 'ArcanistHardpointLoader', 'ArcanistMissingLinterException' => 'Exception', 'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistModifierOrderingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNamespaceFirstStatementXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNamingConventionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNamingConventionsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNestedNamespacesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNestedNamespacesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNewlineAfterOpenTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNewlineAfterOpenTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNoEffectException' => 'ArcanistUsageException', 'ArcanistNoEngineException' => 'ArcanistUsageException', 'ArcanistNoLintLinter' => 'ArcanistLinter', 'ArcanistNoLintLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistNoParentScopeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistNoURIConduitException' => 'ArcanistConduitException', 'ArcanistNoneLintRenderer' => 'ArcanistLintRenderer', 'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPEP8Linter' => 'ArcanistExternalLinter', 'ArcanistPEP8LinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistPHPCloseTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPCloseTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPCompatibilityXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPCompatibilityXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPEchoTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPEchoTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPOpenTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPOpenTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPHPShortTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPHPShortTagXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPaamayimNekudotayimSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistParentMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistParentMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistParenthesesSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistParenthesesSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistParseStrUseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistParseStrUseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPasteWorkflow' => 'ArcanistWorkflow', 'ArcanistPatchWorkflow' => 'ArcanistWorkflow', 'ArcanistPhageToolset' => 'ArcanistToolset', 'ArcanistPhpLinter' => 'ArcanistExternalLinter', 'ArcanistPhpLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistPhpcsLinter' => 'ArcanistExternalLinter', 'ArcanistPhpcsLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistPhpunitTestResultParser' => 'ArcanistTestResultParser', 'ArcanistPhrequentWorkflow' => 'ArcanistWorkflow', 'ArcanistPhutilLibraryLinter' => 'ArcanistLinter', 'ArcanistPhutilWorkflow' => 'PhutilArgumentWorkflow', 'ArcanistPhutilXHPASTLinterStandard' => 'ArcanistLinterStandard', 'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPregQuoteMisuseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPregQuoteMisuseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistProjectConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource', 'ArcanistPrompt' => 'Phobject', 'ArcanistPublicPropertyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPublicPropertyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPuppetLintLinter' => 'ArcanistExternalLinter', 'ArcanistPuppetLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistPyFlakesLinter' => 'ArcanistExternalLinter', 'ArcanistPyFlakesLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistPyLintLinter' => 'ArcanistExternalLinter', 'ArcanistPyLintLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistRaggedClassTreeEdgeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistRef' => 'Phobject', 'ArcanistRefQuery' => 'Phobject', 'ArcanistRepositoryAPI' => 'Phobject', 'ArcanistRepositoryAPIMiscTestCase' => 'PhutilTestCase', 'ArcanistRepositoryAPIStateTestCase' => 'PhutilTestCase', 'ArcanistRepositoryRef' => 'ArcanistRef', 'ArcanistReusedAsIteratorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistReusedAsIteratorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistReusedIteratorReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistReusedIteratorReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistReusedIteratorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistRevertWorkflow' => 'ArcanistWorkflow', 'ArcanistRevisionRef' => 'ArcanistRef', 'ArcanistRevisionRefSource' => 'Phobject', 'ArcanistRuboCopLinter' => 'ArcanistExternalLinter', 'ArcanistRuboCopLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistRubyLinter' => 'ArcanistExternalLinter', 'ArcanistRubyLinterTestCase' => 'ArcanistExternalLinterTestCase', 'ArcanistRuntimeConfigurationSource' => 'ArcanistDictionaryConfigurationSource', 'ArcanistScalarConfigOption' => 'ArcanistConfigOption', 'ArcanistScriptAndRegexLinter' => 'ArcanistLinter', 'ArcanistSelfClassReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSelfClassReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistSelfMemberReferenceXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSelfMemberReferenceXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistSemicolonSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSemicolonSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistSetConfigWorkflow' => 'ArcanistWorkflow', 'ArcanistSetting' => 'Phobject', 'ArcanistSettings' => 'Phobject', 'ArcanistShellCompleteWorkflow' => 'ArcanistWorkflow', 'ArcanistSingleLintEngine' => 'ArcanistLintEngine', 'ArcanistSlownessXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSlownessXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistSpellingLinter' => 'ArcanistLinter', 'ArcanistSpellingLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistStartWorkflow' => 'ArcanistPhrequentWorkflow', 'ArcanistStaticThisXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistStaticThisXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistStopWorkflow' => 'ArcanistPhrequentWorkflow', 'ArcanistStringConfigOption' => 'ArcanistScalarConfigOption', 'ArcanistSubversionAPI' => 'ArcanistRepositoryAPI', 'ArcanistSubversionWorkingCopy' => 'ArcanistWorkingCopy', 'ArcanistSummaryLintRenderer' => 'ArcanistLintRenderer', 'ArcanistSyntaxErrorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistSystemConfigurationSource' => 'ArcanistFilesystemConfigurationSource', 'ArcanistTasksWorkflow' => 'ArcanistWorkflow', 'ArcanistTautologicalExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistTestResultParser' => 'Phobject', 'ArcanistTestXHPASTLintSwitchHook' => 'ArcanistXHPASTLintSwitchHook', 'ArcanistTextLinter' => 'ArcanistLinter', 'ArcanistTextLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistThisReassignmentXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistThisReassignmentXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistTimeWorkflow' => 'ArcanistPhrequentWorkflow', 'ArcanistToStringExceptionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistToStringExceptionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistTodoCommentXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistTodoCommentXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistTodoWorkflow' => 'ArcanistWorkflow', 'ArcanistToolset' => 'Phobject', 'ArcanistUSEnglishTranslation' => 'PhutilTranslation', 'ArcanistUnableToParseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnaryPostfixExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnaryPrefixExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUndeclaredVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUndeclaredVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUnexpectedReturnValueXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnexpectedReturnValueXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUnitConsoleRenderer' => 'ArcanistUnitRenderer', 'ArcanistUnitRenderer' => 'Phobject', 'ArcanistUnitTestEngine' => 'Phobject', 'ArcanistUnitTestResult' => 'Phobject', 'ArcanistUnitTestResultTestCase' => 'PhutilTestCase', 'ArcanistUnitTestableLintEngine' => 'ArcanistLintEngine', 'ArcanistUnitWorkflow' => 'ArcanistWorkflow', 'ArcanistUnnecessaryFinalModifierXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUnnecessarySemicolonXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnnecessarySymbolAliasXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUpgradeWorkflow' => 'ArcanistWorkflow', 'ArcanistUploadWorkflow' => 'ArcanistWorkflow', 'ArcanistUsageException' => 'Exception', 'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUserAbortException' => 'ArcanistUsageException', 'ArcanistUserConfigurationSource' => 'ArcanistFilesystemConfigurationSource', 'ArcanistVariableReferenceSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistVariableReferenceSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistVariableVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistVersionWorkflow' => 'ArcanistWorkflow', - 'ArcanistWeldWorkflow' => 'ArcanistWorkflow', + 'ArcanistWeldWorkflow' => 'ArcanistArcWorkflow', 'ArcanistWhichWorkflow' => 'ArcanistWorkflow', 'ArcanistWildConfigOption' => 'ArcanistConfigOption', 'ArcanistWorkflow' => 'Phobject', 'ArcanistWorkflowArgument' => 'Phobject', 'ArcanistWorkflowInformation' => 'Phobject', 'ArcanistWorkingCopy' => 'Phobject', 'ArcanistWorkingCopyConfigurationSource' => 'ArcanistFilesystemConfigurationSource', 'ArcanistWorkingCopyIdentity' => 'Phobject', 'ArcanistWorkingCopyPath' => 'Phobject', 'ArcanistWorkingCopyStateRef' => 'ArcanistRef', 'ArcanistXHPASTLintNamingHook' => 'Phobject', 'ArcanistXHPASTLintNamingHookTestCase' => 'PhutilTestCase', 'ArcanistXHPASTLintSwitchHook' => 'Phobject', 'ArcanistXHPASTLinter' => 'ArcanistBaseXHPASTLinter', 'ArcanistXHPASTLinterRule' => 'Phobject', 'ArcanistXHPASTLinterRuleTestCase' => 'ArcanistLinterTestCase', 'ArcanistXHPASTLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistXMLLinter' => 'ArcanistLinter', 'ArcanistXMLLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistXUnitTestResultParser' => 'Phobject', 'BaseHTTPFuture' => 'Future', 'CSharpToolsTestEngine' => 'XUnitTestEngine', 'CaseInsensitiveArray' => 'PhutilArray', 'CaseInsensitiveArrayTestCase' => 'PhutilTestCase', 'CommandException' => 'Exception', 'ConduitClient' => 'Phobject', 'ConduitClientException' => 'Exception', 'ConduitClientTestCase' => 'PhutilTestCase', 'ConduitFuture' => 'FutureProxy', 'ExecFuture' => 'PhutilExecutableFuture', 'ExecFutureTestCase' => 'PhutilTestCase', 'ExecPassthruTestCase' => 'PhutilTestCase', 'FileFinder' => 'Phobject', 'FileFinderTestCase' => 'PhutilTestCase', 'FileList' => 'Phobject', 'Filesystem' => 'Phobject', 'FilesystemException' => 'Exception', 'FilesystemTestCase' => 'PhutilTestCase', 'Future' => 'Phobject', 'FutureIterator' => array( 'Phobject', 'Iterator', ), 'FutureIteratorTestCase' => 'PhutilTestCase', 'FutureProxy' => 'Future', 'HTTPFuture' => 'BaseHTTPFuture', 'HTTPFutureCURLResponseStatus' => 'HTTPFutureResponseStatus', 'HTTPFutureCertificateResponseStatus' => 'HTTPFutureResponseStatus', 'HTTPFutureHTTPResponseStatus' => 'HTTPFutureResponseStatus', 'HTTPFutureParseResponseStatus' => 'HTTPFutureResponseStatus', 'HTTPFutureResponseStatus' => 'Exception', 'HTTPFutureTransportResponseStatus' => 'HTTPFutureResponseStatus', 'HTTPSFuture' => 'BaseHTTPFuture', 'ImmediateFuture' => 'Future', 'LibphutilUSEnglishTranslation' => 'PhutilTranslation', 'LinesOfALarge' => array( 'Phobject', 'Iterator', ), 'LinesOfALargeExecFuture' => 'LinesOfALarge', 'LinesOfALargeExecFutureTestCase' => 'PhutilTestCase', 'LinesOfALargeFile' => 'LinesOfALarge', 'LinesOfALargeFileTestCase' => 'PhutilTestCase', 'MFilterTestHelper' => 'Phobject', 'NoseTestEngine' => 'ArcanistUnitTestEngine', 'PHPASTParserTestCase' => 'PhutilTestCase', 'PhageAction' => 'Phobject', 'PhageAgentAction' => 'PhageAction', 'PhageAgentBootloader' => 'Phobject', 'PhageAgentTestCase' => 'PhutilTestCase', 'PhageExecuteAction' => 'PhageAction', 'PhageLocalAction' => 'PhageAgentAction', 'PhagePHPAgent' => 'Phobject', 'PhagePHPAgentBootloader' => 'PhageAgentBootloader', 'PhagePlanAction' => 'PhageAction', 'PhageWorkflow' => 'PhutilArgumentWorkflow', 'Phobject' => 'Iterator', 'PhobjectTestCase' => 'PhutilTestCase', 'PhpunitTestEngine' => 'ArcanistUnitTestEngine', 'PhpunitTestEngineTestCase' => 'PhutilTestCase', 'PhutilAWSCloudFormationFuture' => 'PhutilAWSFuture', 'PhutilAWSCloudWatchFuture' => 'PhutilAWSFuture', 'PhutilAWSEC2Future' => 'PhutilAWSFuture', 'PhutilAWSException' => 'Exception', 'PhutilAWSFuture' => 'FutureProxy', 'PhutilAWSManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhutilAWSS3DeleteManagementWorkflow' => 'PhutilAWSS3ManagementWorkflow', 'PhutilAWSS3Future' => 'PhutilAWSFuture', 'PhutilAWSS3GetManagementWorkflow' => 'PhutilAWSS3ManagementWorkflow', 'PhutilAWSS3ManagementWorkflow' => 'PhutilAWSManagementWorkflow', 'PhutilAWSS3PutManagementWorkflow' => 'PhutilAWSS3ManagementWorkflow', 'PhutilAWSv4Signature' => 'Phobject', 'PhutilAWSv4SignatureTestCase' => 'PhutilTestCase', 'PhutilAggregateException' => 'Exception', 'PhutilAllCapsEnglishLocale' => 'PhutilLocale', 'PhutilArgumentParser' => 'Phobject', 'PhutilArgumentParserException' => 'Exception', 'PhutilArgumentParserTestCase' => 'PhutilTestCase', 'PhutilArgumentSpecification' => 'Phobject', 'PhutilArgumentSpecificationException' => 'PhutilArgumentParserException', 'PhutilArgumentSpecificationTestCase' => 'PhutilTestCase', 'PhutilArgumentSpellingCorrector' => 'Phobject', 'PhutilArgumentSpellingCorrectorTestCase' => 'PhutilTestCase', 'PhutilArgumentUsageException' => 'PhutilArgumentParserException', 'PhutilArgumentWorkflow' => 'Phobject', 'PhutilArray' => array( 'Phobject', 'Countable', 'ArrayAccess', 'Iterator', ), 'PhutilArrayTestCase' => 'PhutilTestCase', 'PhutilArrayWithDefaultValue' => 'PhutilArray', 'PhutilAsanaFuture' => 'FutureProxy', 'PhutilBacktraceSignalHandler' => 'PhutilSignalHandler', 'PhutilBallOfPHP' => 'Phobject', 'PhutilBinaryAnalyzer' => 'Phobject', 'PhutilBinaryAnalyzerTestCase' => 'PhutilTestCase', 'PhutilBootloaderException' => 'Exception', 'PhutilBritishEnglishLocale' => 'PhutilLocale', 'PhutilBufferedIterator' => array( 'Phobject', 'Iterator', ), 'PhutilBufferedIteratorTestCase' => 'PhutilTestCase', 'PhutilBugtraqParser' => 'Phobject', 'PhutilBugtraqParserTestCase' => 'PhutilTestCase', 'PhutilCIDRBlock' => 'Phobject', 'PhutilCIDRList' => 'Phobject', 'PhutilCallbackFilterIterator' => 'FilterIterator', 'PhutilCallbackSignalHandler' => 'PhutilSignalHandler', 'PhutilChannel' => 'Phobject', 'PhutilChannelChannel' => 'PhutilChannel', 'PhutilChannelTestCase' => 'PhutilTestCase', 'PhutilChunkedIterator' => array( 'Phobject', 'Iterator', ), 'PhutilChunkedIteratorTestCase' => 'PhutilTestCase', 'PhutilClassMapQuery' => 'Phobject', 'PhutilCloudWatchMetric' => 'Phobject', 'PhutilCommandString' => 'Phobject', 'PhutilConsole' => 'Phobject', 'PhutilConsoleBlock' => 'PhutilConsoleView', 'PhutilConsoleError' => 'PhutilConsoleLogLine', 'PhutilConsoleFormatter' => 'Phobject', 'PhutilConsoleInfo' => 'PhutilConsoleLogLine', 'PhutilConsoleList' => 'PhutilConsoleView', 'PhutilConsoleLogLine' => 'PhutilConsoleView', 'PhutilConsoleMessage' => 'Phobject', 'PhutilConsoleMetrics' => 'Phobject', 'PhutilConsoleMetricsSignalHandler' => 'PhutilSignalHandler', 'PhutilConsoleProgressBar' => 'Phobject', 'PhutilConsoleProgressSink' => 'PhutilProgressSink', 'PhutilConsoleServer' => 'Phobject', 'PhutilConsoleServerChannel' => 'PhutilChannelChannel', 'PhutilConsoleSkip' => 'PhutilConsoleLogLine', 'PhutilConsoleStdinNotInteractiveException' => 'Exception', 'PhutilConsoleTable' => 'PhutilConsoleView', 'PhutilConsoleView' => 'Phobject', 'PhutilConsoleWarning' => 'PhutilConsoleLogLine', 'PhutilConsoleWrapTestCase' => 'PhutilTestCase', 'PhutilCowsay' => 'Phobject', 'PhutilCowsayTestCase' => 'PhutilTestCase', 'PhutilCsprintfTestCase' => 'PhutilTestCase', 'PhutilCzechLocale' => 'PhutilLocale', 'PhutilDOMNode' => 'Phobject', 'PhutilDeferredLog' => 'Phobject', 'PhutilDeferredLogTestCase' => 'PhutilTestCase', 'PhutilDiffBinaryAnalyzer' => 'PhutilBinaryAnalyzer', 'PhutilDirectedScalarGraph' => 'AbstractDirectedGraph', 'PhutilDirectoryFixture' => 'Phobject', 'PhutilDocblockParser' => 'Phobject', 'PhutilDocblockParserTestCase' => 'PhutilTestCase', 'PhutilEditDistanceMatrix' => 'Phobject', 'PhutilEditDistanceMatrixTestCase' => 'PhutilTestCase', 'PhutilEditorConfig' => 'Phobject', 'PhutilEditorConfigTestCase' => 'PhutilTestCase', 'PhutilEmailAddress' => 'Phobject', 'PhutilEmailAddressTestCase' => 'PhutilTestCase', 'PhutilEmojiLocale' => 'PhutilLocale', 'PhutilEnglishCanadaLocale' => 'PhutilLocale', 'PhutilErrorHandler' => 'Phobject', 'PhutilErrorHandlerTestCase' => 'PhutilTestCase', 'PhutilErrorTrap' => 'Phobject', 'PhutilEvent' => 'Phobject', 'PhutilEventConstants' => 'Phobject', 'PhutilEventEngine' => 'Phobject', 'PhutilEventListener' => 'Phobject', 'PhutilEventType' => 'PhutilEventConstants', 'PhutilExampleBufferedIterator' => 'PhutilBufferedIterator', 'PhutilExecChannel' => 'PhutilChannel', 'PhutilExecPassthru' => 'PhutilExecutableFuture', 'PhutilExecutableFuture' => 'Future', 'PhutilExecutionEnvironment' => 'Phobject', 'PhutilFileLock' => 'PhutilLock', 'PhutilFileLockTestCase' => 'PhutilTestCase', 'PhutilFileTree' => 'Phobject', 'PhutilFrenchLocale' => 'PhutilLocale', 'PhutilGermanLocale' => 'PhutilLocale', 'PhutilGitBinaryAnalyzer' => 'PhutilBinaryAnalyzer', 'PhutilGitHubFuture' => 'FutureProxy', 'PhutilGitHubResponse' => 'Phobject', 'PhutilGitURI' => 'Phobject', 'PhutilGitURITestCase' => 'PhutilTestCase', 'PhutilHTMLParser' => 'Phobject', 'PhutilHTMLParserTestCase' => 'PhutilTestCase', 'PhutilHTTPEngineExtension' => 'Phobject', 'PhutilHTTPResponse' => 'Phobject', 'PhutilHTTPResponseParser' => 'Phobject', 'PhutilHTTPResponseParserTestCase' => 'PhutilTestCase', 'PhutilHashingIterator' => array( 'PhutilProxyIterator', 'Iterator', ), 'PhutilHashingIteratorTestCase' => 'PhutilTestCase', 'PhutilHelpArgumentWorkflow' => 'PhutilArgumentWorkflow', 'PhutilHgsprintfTestCase' => 'PhutilTestCase', 'PhutilINIParserException' => 'Exception', 'PhutilIPAddress' => 'Phobject', 'PhutilIPAddressTestCase' => 'PhutilTestCase', 'PhutilIPv4Address' => 'PhutilIPAddress', 'PhutilIPv6Address' => 'PhutilIPAddress', 'PhutilInteractiveEditor' => 'Phobject', 'PhutilInvalidRuleParserGeneratorException' => 'PhutilParserGeneratorException', 'PhutilInvalidStateException' => 'Exception', 'PhutilInvalidStateExceptionTestCase' => 'PhutilTestCase', 'PhutilIrreducibleRuleParserGeneratorException' => 'PhutilParserGeneratorException', 'PhutilJSON' => 'Phobject', 'PhutilJSONFragmentLexer' => 'PhutilLexer', 'PhutilJSONParser' => 'Phobject', 'PhutilJSONParserException' => 'Exception', 'PhutilJSONParserTestCase' => 'PhutilTestCase', 'PhutilJSONProtocolChannel' => 'PhutilProtocolChannel', 'PhutilJSONProtocolChannelTestCase' => 'PhutilTestCase', 'PhutilJSONTestCase' => 'PhutilTestCase', 'PhutilJavaFragmentLexer' => 'PhutilLexer', 'PhutilKoreanLocale' => 'PhutilLocale', 'PhutilLanguageGuesser' => 'Phobject', 'PhutilLanguageGuesserTestCase' => 'PhutilTestCase', 'PhutilLexer' => 'Phobject', 'PhutilLibraryConflictException' => 'Exception', 'PhutilLibraryMapBuilder' => 'Phobject', 'PhutilLibraryTestCase' => 'PhutilTestCase', 'PhutilLocale' => 'Phobject', 'PhutilLocaleTestCase' => 'PhutilTestCase', 'PhutilLock' => 'Phobject', 'PhutilLockException' => 'Exception', 'PhutilLogFileChannel' => 'PhutilChannelChannel', 'PhutilLunarPhase' => 'Phobject', 'PhutilLunarPhaseTestCase' => 'PhutilTestCase', 'PhutilMercurialBinaryAnalyzer' => 'PhutilBinaryAnalyzer', 'PhutilMethodNotImplementedException' => 'Exception', 'PhutilMetricsChannel' => 'PhutilChannelChannel', 'PhutilMissingSymbolException' => 'Exception', 'PhutilModuleUtilsTestCase' => 'PhutilTestCase', 'PhutilNumber' => 'Phobject', 'PhutilOAuth1Future' => 'FutureProxy', 'PhutilOAuth1FutureTestCase' => 'PhutilTestCase', 'PhutilOpaqueEnvelope' => 'Phobject', 'PhutilOpaqueEnvelopeKey' => 'Phobject', 'PhutilOpaqueEnvelopeTestCase' => 'PhutilTestCase', 'PhutilPHPFragmentLexer' => 'PhutilLexer', 'PhutilPHPFragmentLexerTestCase' => 'PhutilTestCase', 'PhutilPHPObjectProtocolChannel' => 'PhutilProtocolChannel', 'PhutilPHPObjectProtocolChannelTestCase' => 'PhutilTestCase', 'PhutilParserGenerator' => 'Phobject', 'PhutilParserGeneratorException' => 'Exception', 'PhutilParserGeneratorTestCase' => 'PhutilTestCase', 'PhutilPayPalAPIFuture' => 'FutureProxy', 'PhutilPersonTest' => array( 'Phobject', 'PhutilPerson', ), 'PhutilPhtTestCase' => 'PhutilTestCase', 'PhutilPirateEnglishLocale' => 'PhutilLocale', 'PhutilPortugueseBrazilLocale' => 'PhutilLocale', 'PhutilPortuguesePortugalLocale' => 'PhutilLocale', 'PhutilPostmarkFuture' => 'FutureProxy', 'PhutilPregsprintfTestCase' => 'PhutilTestCase', 'PhutilProcessQuery' => 'Phobject', 'PhutilProcessRef' => 'Phobject', 'PhutilProcessRefTestCase' => 'PhutilTestCase', 'PhutilProgressSink' => 'Phobject', 'PhutilProtocolChannel' => 'PhutilChannelChannel', 'PhutilProxyException' => 'Exception', 'PhutilProxyIterator' => array( 'Phobject', 'Iterator', ), 'PhutilPygmentizeBinaryAnalyzer' => 'PhutilBinaryAnalyzer', 'PhutilPythonFragmentLexer' => 'PhutilLexer', 'PhutilQueryStringParser' => 'Phobject', 'PhutilQueryStringParserTestCase' => 'PhutilTestCase', 'PhutilRawEnglishLocale' => 'PhutilLocale', 'PhutilReadableSerializer' => 'Phobject', 'PhutilReadableSerializerTestCase' => 'PhutilTestCase', 'PhutilRope' => 'Phobject', 'PhutilRopeTestCase' => 'PhutilTestCase', 'PhutilServiceProfiler' => 'Phobject', 'PhutilShellLexer' => 'PhutilLexer', 'PhutilShellLexerTestCase' => 'PhutilTestCase', 'PhutilSignalHandler' => 'Phobject', 'PhutilSignalRouter' => 'Phobject', 'PhutilSimpleOptions' => 'Phobject', 'PhutilSimpleOptionsLexer' => 'PhutilLexer', 'PhutilSimpleOptionsLexerTestCase' => 'PhutilTestCase', 'PhutilSimpleOptionsTestCase' => 'PhutilTestCase', 'PhutilSimplifiedChineseLocale' => 'PhutilLocale', 'PhutilSlackFuture' => 'FutureProxy', 'PhutilSocketChannel' => 'PhutilChannel', 'PhutilSortVector' => 'Phobject', 'PhutilSpanishSpainLocale' => 'PhutilLocale', 'PhutilStreamIterator' => array( 'Phobject', 'Iterator', ), 'PhutilSubversionBinaryAnalyzer' => 'PhutilBinaryAnalyzer', 'PhutilSystem' => 'Phobject', 'PhutilSystemTestCase' => 'PhutilTestCase', 'PhutilTerminalString' => 'Phobject', 'PhutilTestCase' => 'Phobject', 'PhutilTestCaseTestCase' => 'PhutilTestCase', 'PhutilTestPhobject' => 'Phobject', 'PhutilTestSkippedException' => 'Exception', 'PhutilTestTerminatedException' => 'Exception', 'PhutilTraditionalChineseLocale' => 'PhutilLocale', 'PhutilTranslation' => 'Phobject', 'PhutilTranslationTestCase' => 'PhutilTestCase', 'PhutilTranslator' => 'Phobject', 'PhutilTranslatorTestCase' => 'PhutilTestCase', 'PhutilTsprintfTestCase' => 'PhutilTestCase', 'PhutilTwitchFuture' => 'FutureProxy', 'PhutilTypeCheckException' => 'Exception', 'PhutilTypeExtraParametersException' => 'Exception', 'PhutilTypeLexer' => 'PhutilLexer', 'PhutilTypeMissingParametersException' => 'Exception', 'PhutilTypeSpec' => 'Phobject', 'PhutilTypeSpecTestCase' => 'PhutilTestCase', 'PhutilURI' => 'Phobject', 'PhutilURITestCase' => 'PhutilTestCase', 'PhutilUSEnglishLocale' => 'PhutilLocale', 'PhutilUTF8StringTruncator' => 'Phobject', 'PhutilUTF8TestCase' => 'PhutilTestCase', 'PhutilUnitTestEngine' => 'ArcanistUnitTestEngine', 'PhutilUnitTestEngineTestCase' => 'PhutilTestCase', 'PhutilUnknownSymbolParserGeneratorException' => 'PhutilParserGeneratorException', 'PhutilUnreachableRuleParserGeneratorException' => 'PhutilParserGeneratorException', 'PhutilUnreachableTerminalParserGeneratorException' => 'PhutilParserGeneratorException', 'PhutilUrisprintfTestCase' => 'PhutilTestCase', 'PhutilUtilsTestCase' => 'PhutilTestCase', 'PhutilVeryWowEnglishLocale' => 'PhutilLocale', 'PhutilWordPressFuture' => 'FutureProxy', 'PhutilXHPASTBinary' => 'Phobject', 'PytestTestEngine' => 'ArcanistUnitTestEngine', 'TempFile' => 'Phobject', 'TestAbstractDirectedGraph' => 'AbstractDirectedGraph', 'XHPASTNode' => 'AASTNode', 'XHPASTNodeTestCase' => 'PhutilTestCase', 'XHPASTSyntaxErrorException' => 'Exception', 'XHPASTToken' => 'AASTToken', 'XHPASTTree' => 'AASTTree', 'XHPASTTreeTestCase' => 'PhutilTestCase', 'XUnitTestEngine' => 'ArcanistUnitTestEngine', 'XUnitTestResultParserTestCase' => 'PhutilTestCase', 'XsprintfUnknownConversionException' => 'InvalidArgumentException', ), )); diff --git a/src/runtime/ArcanistRuntime.php b/src/runtime/ArcanistRuntime.php index bd7c629d..f856fbbd 100644 --- a/src/runtime/ArcanistRuntime.php +++ b/src/runtime/ArcanistRuntime.php @@ -1,643 +1,646 @@ checkEnvironment(); } catch (Exception $ex) { echo "CONFIGURATION ERROR\n\n"; echo $ex->getMessage(); echo "\n\n"; return 1; } PhutilTranslator::getInstance() ->setLocale(PhutilLocale::loadLocale('en_US')) ->setTranslations(PhutilTranslation::getTranslationMapForLocale('en_US')); $log = new ArcanistLogEngine(); $this->logEngine = $log; try { return $this->executeCore($argv); } catch (ArcanistConduitException $ex) { $log->writeError(pht('CONDUIT'), $ex->getMessage()); } catch (PhutilArgumentUsageException $ex) { $log->writeError(pht('USAGE EXCEPTION'), $ex->getMessage()); } catch (ArcanistUserAbortException $ex) { $log->writeError(pht('---'), $ex->getMessage()); } return 1; } private function executeCore(array $argv) { $log = $this->getLogEngine(); $config_args = array( array( 'name' => 'library', 'param' => 'path', 'help' => pht('Load a library.'), 'repeat' => true, ), array( 'name' => 'config', 'param' => 'key=value', 'repeat' => true, 'help' => pht('Specify a runtime configuration value.'), ), array( 'name' => 'config-file', 'param' => 'path', 'repeat' => true, 'help' => pht( 'Load one or more configuration files. If this flag is provided, '. 'the system and user configuration files are ignored.'), ), ); $args = id(new PhutilArgumentParser($argv)) ->parseStandardArguments(); $is_trace = $args->getArg('trace'); $log->setShowTraceMessages($is_trace); $log->writeTrace(pht('ARGV'), csprintf('%Ls', $argv)); // We're installing the signal handler after parsing "--trace" so that it // can emit debugging messages. This means there's a very small window at // startup where signals have no special handling, but we couldn't really // route them or do anything interesting with them anyway. $this->installSignalHandler(); $args->parsePartial($config_args, true); $config_engine = $this->loadConfiguration($args); $config = $config_engine->newConfigurationSourceList(); $this->loadLibraries($args, $config); // Now that we've loaded libraries, we can validate configuration. // Do this before continuing since configuration can impact other // behaviors immediately and we want to catch any issues right away. $config->setConfigOptions($config_engine->newConfigOptionsMap()); $config->validateConfiguration($this); $toolset = $this->newToolset($argv); $args->parsePartial($toolset->getToolsetArguments()); $workflows = $this->newWorkflows($toolset); $this->workflows = $workflows; $phutil_workflows = array(); foreach ($workflows as $key => $workflow) { $phutil_workflows[$key] = $workflow->newPhutilWorkflow(); $workflow ->setRuntime($this) ->setConfigurationEngine($config_engine) ->setConfigurationSourceList($config); } $unconsumed_argv = $args->getUnconsumedArgumentVector(); if (!$unconsumed_argv) { // TOOLSETS: This means the user just ran "arc" or some other top-level // toolset without any workflow argument. We should give them a summary // of the toolset, a list of workflows, and a pointer to "arc help" for // more details. // A possible exception is "arc --help", which should perhaps pass // through and act like "arc help". throw new PhutilArgumentUsageException(pht('Choose a workflow!')); } $alias_effects = id(new ArcanistAliasEngine()) ->setRuntime($this) ->setToolset($toolset) ->setWorkflows($workflows) ->setConfigurationSourceList($config) ->resolveAliases($unconsumed_argv); $result_argv = $this->applyAliasEffects($alias_effects, $unconsumed_argv); $args->setUnconsumedArgumentVector($result_argv); // TOOLSETS: Some day, stop falling through to the old "arc" runtime. try { return $args->parseWorkflowsFull($phutil_workflows); } catch (PhutilArgumentUsageException $usage_exception) { - $log->writeHint( - pht('(::)'), - pht( - 'Workflow is unrecognized by modern "arc", falling through '. - 'to classic mode.')); + + // TODO: This is very, very hacky; we're trying to let errors like + // "you passed the wrong arguments" through but fall back to classic + // mode if the workflow itself doesn't exist. + if (!preg_match('/invalid command/i', $usage_exception->getMessage())) { + throw $usage_exception; + } + } $arcanist_root = phutil_get_library_root('arcanist'); $arcanist_root = dirname($arcanist_root); $bin = $arcanist_root.'/scripts/arcanist.php'; $err = phutil_passthru( 'php -f %R -- %Ls', $bin, array_slice($argv, 1)); return $err; } /** * Perform some sanity checks against the possible diversity of PHP builds in * the wild, like very old versions and builds that were compiled with flags * that exclude core functionality. */ private function checkEnvironment() { // NOTE: We don't have phutil_is_windows() yet here. $is_windows = (DIRECTORY_SEPARATOR != '/'); // NOTE: There's a hard PHP version check earlier, in "init-script.php". if ($is_windows) { $need_functions = array( 'curl_init' => array('builtin-dll', 'php_curl.dll'), ); } else { $need_functions = array( 'curl_init' => array( 'text', "You need to install the cURL PHP extension, maybe with ". "'apt-get install php5-curl' or 'yum install php53-curl' or ". "something similar.", ), 'json_decode' => array('flag', '--without-json'), ); } $problems = array(); $config = null; $show_config = false; foreach ($need_functions as $fname => $resolution) { if (function_exists($fname)) { continue; } static $info; if ($info === null) { ob_start(); phpinfo(INFO_GENERAL); $info = ob_get_clean(); $matches = null; if (preg_match('/^Configure Command =>\s*(.*?)$/m', $info, $matches)) { $config = $matches[1]; } } list($what, $which) = $resolution; if ($what == 'flag' && strpos($config, $which) !== false) { $show_config = true; $problems[] = sprintf( 'The build of PHP you are running was compiled with the configure '. 'flag "%s", which means it does not support the function "%s()". '. 'This function is required for Arcanist to run. Install a standard '. 'build of PHP or rebuild it without this flag. You may also be '. 'able to build or install the relevant extension separately.', $which, $fname); continue; } if ($what == 'builtin-dll') { $problems[] = sprintf( 'The build of PHP you are running does not have the "%s" extension '. 'enabled. Edit your php.ini file and uncomment the line which '. 'reads "extension=%s".', $which, $which); continue; } if ($what == 'text') { $problems[] = $which; continue; } $problems[] = sprintf( 'The build of PHP you are running is missing the required function '. '"%s()". Rebuild PHP or install the extension which provides "%s()".', $fname, $fname); } if ($problems) { if ($show_config) { $problems[] = "PHP was built with this configure command:\n\n{$config}"; } $problems = implode("\n\n", $problems); throw new Exception($problems); } } private function loadConfiguration(PhutilArgumentParser $args) { $engine = id(new ArcanistConfigurationEngine()) ->setArguments($args); $working_copy = ArcanistWorkingCopy::newFromWorkingDirectory(getcwd()); if ($working_copy) { $engine->setWorkingCopy($working_copy); } return $engine; } private function loadLibraries( PhutilArgumentParser $args, ArcanistConfigurationSourceList $config) { // TOOLSETS: Make this work again -- or replace it entirely with package // management? return; $is_trace = $args->getArg('trace'); $load = array(); $working_copy = $this->getWorkingCopy(); $cli_libraries = $args->getArg('library'); if ($cli_libraries) { $load[] = array( '--library', $cli_libraries, ); } else { $system_config = $config->readSystemArcConfig(); $load[] = array( $config->getSystemArcConfigLocation(), idx($system_config, 'load', array()), ); $global_config = $config->readUserArcConfig(); $load[] = array( $config->getUserConfigurationFileLocation(), idx($global_config, 'load', array()), ); $load[] = array( '.arcconfig', $working_copy->getProjectConfig('load'), ); $load[] = array( // TODO: We could explain exactly where this is coming from more // clearly. './.../arc/config', $working_copy->getLocalConfig('load'), ); $load[] = array( '--config load=...', $config->getRuntimeConfig('load', array()), ); } foreach ($load as $spec) { list($source, $libraries) = $spec; if ($is_trace) { $this->logTrace( pht('LOAD'), pht( 'Loading libraries from "%s"...', $source)); } if (!$libraries) { if ($is_trace) { $this->logTrace(pht('NONE'), pht('Nothing to load.')); } continue; } if (!is_array($libraries)) { throw new PhutilArgumentUsageException( pht( 'Libraries specified by "%s" are not formatted correctly. '. 'Expected a list of paths. Check your configuration.', $source)); } foreach ($libraries as $library) { $this->loadLibrary($source, $library, $working_copy, $is_trace); } } } private function loadLibrary( $source, $location, ArcanistWorkingCopyIdentity $working_copy, $is_trace) { // Try to resolve the library location. We look in several places, in // order: // // 1. Inside the working copy. This is for phutil libraries within the // project. For instance "library/src" will resolve to // "./library/src" if it exists. // 2. In the same directory as the working copy. This allows you to // check out a library alongside a working copy and reference it. // If we haven't resolved yet, "library/src" will try to resolve to // "../library/src" if it exists. // 3. Using normal libphutil resolution rules. Generally, this means // that it checks for libraries next to libphutil, then libraries // in the PHP include_path. // // Note that absolute paths will just resolve absolutely through rule (1). $resolved = false; // Check inside the working copy. This also checks absolute paths, since // they'll resolve absolute and just ignore the project root. $resolved_location = Filesystem::resolvePath( $location, $working_copy->getProjectRoot()); if (Filesystem::pathExists($resolved_location)) { $location = $resolved_location; $resolved = true; } // If we didn't find anything, check alongside the working copy. if (!$resolved) { $resolved_location = Filesystem::resolvePath( $location, dirname($working_copy->getProjectRoot())); if (Filesystem::pathExists($resolved_location)) { $location = $resolved_location; $resolved = true; } } if ($is_trace) { $this->logTrace( pht('LOAD'), pht('Loading phutil library from "%s"...', $location)); } $error = null; try { phutil_load_library($location); } catch (PhutilBootloaderException $ex) { fwrite( STDERR, '%s', tsprintf( "** %s ** %s\n", pht( 'Failed to load phutil library at location "%s". This library '. 'is specified by "%s". Check that the setting is correct and '. 'the library is located in the right place.', $location, $source))); $prompt = pht('Continue without loading library?'); if (!phutil_console_confirm($prompt)) { throw $ex; } } catch (PhutilLibraryConflictException $ex) { if ($ex->getLibrary() != 'arcanist') { throw $ex; } // NOTE: If you are running `arc` against itself, we ignore the library // conflict created by loading the local `arc` library (in the current // working directory) and continue without loading it. // This means we only execute code in the `arcanist/` directory which is // associated with the binary you are running, whereas we would normally // execute local code. // This can make `arc` development slightly confusing if your setup is // especially bizarre, but it allows `arc` to be used in automation // workflows more easily. For some context, see PHI13. $executing_directory = dirname(dirname(__FILE__)); $working_directory = dirname($location); fwrite( STDERR, tsprintf( "** %s ** %s\n", pht('VERY META'), pht( 'You are running one copy of Arcanist (at path "%s") against '. 'another copy of Arcanist (at path "%s"). Code in the current '. 'working directory will not be loaded or executed.', $executing_directory, $working_directory))); } } private function newToolset(array $argv) { $binary = basename($argv[0]); $toolsets = ArcanistToolset::newToolsetMap(); if (!isset($toolsets[$binary])) { throw new PhutilArgumentUsageException( pht( 'Arcanist toolset "%s" is unknown. The Arcanist binary should '. 'be executed so that "argv[0]" identifies a supported toolset. '. 'Rename the binary or install the library that provides the '. 'desired toolset. Current available toolsets: %s.', $binary, implode(', ', array_keys($toolsets)))); } return $toolsets[$binary]; } private function newWorkflows(ArcanistToolset $toolset) { $workflows = id(new PhutilClassMapQuery()) ->setAncestorClass('ArcanistWorkflow') ->setContinueOnFailure(true) ->execute(); foreach ($workflows as $key => $workflow) { if (!$workflow->supportsToolset($toolset)) { unset($workflows[$key]); } } $map = array(); foreach ($workflows as $workflow) { $key = $workflow->getWorkflowName(); if (isset($map[$key])) { throw new Exception( pht( 'Two workflows ("%s" and "%s") both have the same name ("%s") '. 'and both support the current toolset ("%s", "%s"). Each '. 'workflow in a given toolset must have a unique name.', get_class($workflow), get_class($map[$key]), get_class($toolset), $toolset->getToolsetKey())); } $map[$key] = id(clone $workflow) ->setToolset($toolset); } return $map; } public function getWorkflows() { return $this->workflows; } public function getLogEngine() { return $this->logEngine; } private function applyAliasEffects(array $effects, array $argv) { assert_instances_of($effects, 'ArcanistAliasEffect'); $log = $this->getLogEngine(); $command = null; $arguments = null; foreach ($effects as $effect) { $message = $effect->getMessage(); if ($message !== null) { $log->writeHint(pht('ALIAS'), $message); } if ($effect->getCommand()) { $command = $effect->getCommand(); $arguments = $effect->getArguments(); } } if ($command !== null) { $argv = array_merge(array($command), $arguments); } return $argv; } private function installSignalHandler() { $log = $this->getLogEngine(); if (!function_exists('pcntl_signal')) { $log->writeTrace( pht('PCNTL'), pht( 'Unable to install signal handler, pcntl_signal() unavailable. '. 'Continuing without signal handling.')); return; } // NOTE: SIGHUP, SIGTERM and SIGWINCH are handled by "PhutilSignalRouter". // This logic is largely similar to the logic there, but more specific to // Arcanist workflows. pcntl_signal(SIGINT, array($this, 'routeSignal')); } public function routeSignal($signo) { switch ($signo) { case SIGINT: $this->routeInterruptSignal($signo); break; } } private function routeInterruptSignal($signo) { $log = $this->getLogEngine(); $last_interrupt = $this->lastInterruptTime; $now = microtime(true); $this->lastInterruptTime = $now; $should_exit = false; // If we received another SIGINT recently, always exit. This implements // "press ^C twice in quick succession to exit" regardless of what the // workflow may decide to do. $interval = 2; if ($last_interrupt !== null) { if ($now - $last_interrupt < $interval) { $should_exit = true; } } $handler = null; if (!$should_exit) { // Look for an interrupt handler in the current workflow stack. $stack = $this->getWorkflowStack(); foreach ($stack as $workflow) { if ($workflow->canHandleSignal($signo)) { $handler = $workflow; break; } } // If no workflow in the current execution stack can handle an interrupt // signal, just exit on the first interrupt. if (!$handler) { $should_exit = true; } } // It's common for users to ^C on prompts. Write a newline before writing // a response to the interrupt so the behavior is a little cleaner. This // also avoids lines that read "^C [ INTERRUPT ] ...". $log->writeNewline(); if ($should_exit) { $log->writeHint( pht('INTERRUPT'), pht('Interrupted by SIGINT (^C).')); exit(128 + $signo); } $log->writeHint( pht('INTERRUPT'), pht('Press ^C again to exit.')); $handler->handleSignal($signo); } public function pushWorkflow(ArcanistWorkflow $workflow) { $this->stack[] = $workflow; return $this; } public function popWorkflow() { if (!$this->stack) { throw new Exception(pht('Trying to pop an empty workflow stack!')); } return array_pop($this->stack); } public function getWorkflowStack() { return $this->stack; } } diff --git a/src/toolset/ArcanistWorkflowInformation.php b/src/toolset/ArcanistWorkflowInformation.php index d59d0fc1..55d31ade 100644 --- a/src/toolset/ArcanistWorkflowInformation.php +++ b/src/toolset/ArcanistWorkflowInformation.php @@ -1,27 +1,37 @@ help = $help; return $this; } public function getHelp() { return $this->help; } public function addExample($example) { $this->examples[] = $example; return $this; } public function getExamples() { return $this->examples; } + public function setSynopsis($synopsis) { + $this->synopsis = $synopsis; + return $this; + } + + public function getSynopsis() { + return $this->synopsis; + } + } diff --git a/src/toolset/workflow/ArcanistAliasWorkflow.php b/src/toolset/workflow/ArcanistAliasWorkflow.php index 618dfae4..c74e7948 100644 --- a/src/toolset/workflow/ArcanistAliasWorkflow.php +++ b/src/toolset/workflow/ArcanistAliasWorkflow.php @@ -1,200 +1,201 @@ NOTE: Make sure you use "--" before specifying any flags you want to pass to the command! Otherwise, the flags will be interpreted as flags to "arc alias". **Listing Aliases** Without any arguments, "arc alias" will list aliases. **Removing Aliases** To remove an alias, run: $ arc alias You will be prompted to remove the alias. **Shell Commands** If you begin an alias with "!", the remainder of the alias will be invoked as a shell command. For example, if you want to implement "arc ls", you can do so like this: $ arc alias ls '!ls' When run, "arc ls" will now behave like "ls". **Multiple Toolsets** This workflow supports any toolset, even though the examples in this help text use "arc". If you are working with another toolset, use the binary for that toolset define aliases for it: $ phage alias ... Aliases are bound to the toolset which was used to define them. If you define an "arc draft" alias, that does not also define a "phage draft" alias. **Builtins** You can not overwrite the behavior of builtin workflows, including "alias" itself, and if you install a new workflow it will take precedence over any existing aliases with the same name. EOTEXT ); return $this->newWorkflowInformation() + ->setSynopsis( + pht('Create and modify command aliases.')) ->addExample(pht('**alias**')) - ->addExample(pht('**alias** __command__')) - ->addExample(pht('**alias** __command__ __target__ -- [__options__]')) + ->addExample(pht('**alias** __command__ __target__ -- [__arguments__]')) ->setHelp($help); } public function getWorkflowArguments() { return array( $this->newWorkflowArgument('json') ->setHelp(pht('Output aliases in JSON format.')), $this->newWorkflowArgument('argv') ->setWildcard(true), ); } public function runWorkflow() { $argv = $this->getArgument('argv'); $is_list = false; $is_delete = false; if (!$argv) { $is_list = true; } else if (count($argv) === 1) { $is_delete = true; } $is_json = $this->getArgument('json'); if ($is_json && !$is_list) { throw new PhutilArgumentUsageException( pht( 'The "--json" argument may only be used when listing aliases.')); } if ($is_list) { return $this->runListAliases(); } if ($is_delete) { return $this->runDeleteAlias($argv[0]); } return $this->runCreateAlias($argv); } private function runListAliases() { // TOOLSETS: Actually list aliases. return 1; } private function runDeleteAlias($alias) { // TOOLSETS: Actually delete aliases. return 1; } private function runCreateAlias(array $argv) { $trigger = array_shift($argv); $this->validateAliasTrigger($trigger); $alias = id(new ArcanistAlias()) ->setToolset($this->getToolsetKey()) ->setTrigger($trigger) ->setCommand($argv); $aliases = $this->readAliasesForWrite(); // TOOLSETS: Check if the user already has an alias for this trigger, and // prompt them to overwrite it. Needs prompting to work. $aliases[] = $alias; $this->writeAliases($aliases); // TOOLSETS: Print out a confirmation that we added the alias. return 0; } private function validateAliasTrigger($trigger) { $workflows = $this->getRuntime()->getWorkflows(); if (isset($workflows[$trigger])) { throw new PhutilArgumentUsageException( pht( 'You can not define an alias for "%s" because it is a builtin '. 'workflow for the current toolset ("%s"). The "alias" workflow '. 'can only define new commands as aliases; it can not redefine '. 'existing commands to mean something else.', $trigger, $this->getToolsetKey())); } } private function getEditScope() { return ArcanistConfigurationSource::SCOPE_USER; } private function getAliasesConfigKey() { return ArcanistArcConfigurationEngineExtension::KEY_ALIASES; } private function readAliasesForWrite() { $key = $this->getAliasesConfigKey(); $scope = $this->getEditScope(); $source_list = $this->getConfigurationSourceList(); return $source_list->getConfigFromScopes($key, array($scope)); } private function writeAliases(array $aliases) { assert_instances_of($aliases, 'ArcanistAlias'); $key = $this->getAliasesConfigKey(); $scope = $this->getEditScope(); $source_list = $this->getConfigurationSourceList(); $source = $source_list->getWritableSourceFromScope($scope); $option = $source_list->getConfigOption($key); $option->writeValue($source, $aliases); } } diff --git a/src/toolset/workflow/ArcanistShellCompleteWorkflow.php b/src/toolset/workflow/ArcanistShellCompleteWorkflow.php index ddc5a148..9d65bc59 100644 --- a/src/toolset/workflow/ArcanistShellCompleteWorkflow.php +++ b/src/toolset/workflow/ArcanistShellCompleteWorkflow.php @@ -1,656 +1,657 @@ ...your shell should automatically expand the flag to: $ arc diff --draft **Updating Completion** To update shell completion, run the same command: $ arc shell-complete You can update shell completion without reinstalling it by running: $ arc shell-complete --generate You may need to update shell completion if: - you install new Arcanist toolsets; or - you move the Arcanist directory; or - you upgrade Arcanist and the new version fixes shell completion bugs. EOTEXT ); return $this->newWorkflowInformation() + ->setSynopsis(pht('Install shell completion.')) ->setHelp($help); } public function getWorkflowArguments() { return array( $this->newWorkflowArgument('current') ->setParameter('cursor-position') ->setHelp( pht( 'Internal. Current term in the argument list being completed.')), $this->newWorkflowArgument('generate') ->setHelp( pht( 'Regenerate shell completion rules, without installing any '. 'configuration.')), $this->newWorkflowArgument('shell') ->setParameter('shell-name') ->setHelp( pht( 'Install completion support for a particular shell.')), $this->newWorkflowArgument('argv') ->setWildcard(true), ); } public function runWorkflow() { $log = $this->getLogEngine(); $argv = $this->getArgument('argv'); $is_generate = $this->getArgument('generate'); $is_shell = (bool)strlen($this->getArgument('shell')); $is_current = $this->getArgument('current'); if ($argv) { $should_install = false; $should_generate = false; if ($is_generate) { throw new PhutilArgumentUsageException( pht( 'You can not use "--generate" when completing arguments.')); } if ($is_shell) { throw new PhutilArgumentUsageException( pht( 'You can not use "--shell" when completing arguments.')); } } else if ($is_generate) { $should_install = false; $should_generate = true; if ($is_current) { throw new PhutilArgumentUsageException( pht( 'You can not use "--current" when generating rules.')); } if ($is_shell) { throw new PhutilArgumentUsageException( pht( 'The flags "--generate" and "--shell" are mutually exclusive. '. 'The "--shell" flag selects which shell to install support for, '. 'but the "--generate" suppresses installation.')); } } else { $should_install = true; $should_generate = true; if ($is_current) { throw new PhutilArgumentUsageException( pht( 'You can not use "--current" when installing support.')); } } if ($should_install) { $this->runInstall(); } if ($should_generate) { $this->runGenerate(); } if ($should_install || $should_generate) { $log->writeHint( pht('NOTE'), pht( 'You may need to open a new terminal window or launch a new shell '. 'before the changes take effect.')); return 0; } $this->runAutocomplete(); } protected function newPrompts() { return array( $this->newPrompt('arc.shell-complete.install') ->setDescription( pht( 'Confirms writing to to "~/.profile" (or another similar file) '. 'to install shell completion.')), ); } private function runInstall() { $log = $this->getLogEngine(); $shells = array( array( 'key' => 'bash', 'path' => '/bin/bash', 'file' => '.profile', 'source' => 'hooks/bash-completion.sh', ), ); $shells = ipull($shells, null, 'key'); $shell = $this->getArgument('shell'); if (!$shell) { $shell = $this->detectShell($shells); } else { $shell = $this->selectShell($shells, $shell); } $spec = $shells[$shell]; $file = $spec['file']; $home = getenv('HOME'); if (!strlen($home)) { throw new PhutilArgumentUsageException( pht( 'The "HOME" environment variable is not defined, so this workflow '. 'can not identify where to install shell completion.')); } $file_path = getenv('HOME').'/'.$file; $file_display = '~/'.$file; if (Filesystem::pathExists($file_path)) { $file_path = Filesystem::resolvePath($file_path); $data = Filesystem::readFile($file_path); $is_new = false; } else { $data = ''; $is_new = true; } $line = csprintf( 'source %R # arcanist-shell-complete', $this->getShellPath($spec['source'])); $matches = null; $replace = preg_match( '/(\s*\n)?[^\n]+# arcanist-shell-complete\s*(\n\s*)?/', $data, $matches, PREG_OFFSET_CAPTURE); $log->writeSuccess( pht('INSTALL'), pht('Installing shell completion support for "%s".', $shell)); if ($replace) { $replace_pos = $matches[0][1]; $replace_line = $matches[0][0]; $replace_len = strlen($replace_line); $replace_display = trim($replace_line); if ($replace_pos === 0) { $new_line = $line."\n"; } else { $new_line = "\n\n".$line."\n"; } $new_data = substr_replace($data, $new_line, $replace_pos, $replace_len); if ($new_data === $data) { // If we aren't changing anything in the file, just skip the write // completely. $needs_write = false; $log->writeStatus( pht('SKIP'), pht('Shell completion for "%s" is already installed.', $shell)); return; } echo tsprintf( "%s\n\n %s\n\n%s\n\n %s\n", pht( 'To update shell completion support for "%s", your existing '. '"%s" file will be modified. This line will be removed:', $shell, $file_display), $replace_display, pht('This line will be added:'), $line); $prompt = pht('Rewrite this file?'); } else { if ($is_new) { $new_data = $line."\n"; echo tsprintf( "%s\n\n %s\n", pht( 'To install shell completion support for "%s", a new "%s" file '. 'will be created with this content:', $shell, $file_display), $line); $prompt = pht('Create this file?'); } else { $new_data = rtrim($data)."\n\n".$line."\n"; echo tsprintf( "%s\n\n %s\n", pht( 'To install shell completion support for "%s", this line will be '. 'added to your existing "%s" file:', $shell, $file_display), $line); $prompt = pht('Append to this file?'); } } $this->getPrompt('arc.shell-complete.install') ->setQuery($prompt) ->execute(); Filesystem::writeFile($file_path, $new_data); $log->writeSuccess( pht('INSTALLED'), pht( 'Installed shell completion support for "%s" to "%s".', $shell, $file_display)); } private function selectShell(array $shells, $shell_arg) { foreach ($shells as $shell) { if ($shell['key'] === $shell_arg) { return $shell_arg; } } throw new PhutilArgumentUsageException( pht( 'The shell "%s" is not supported. Supported shells are: %s.', $shell_arg, implode(', ', ipull($shells, 'key')))); } private function detectShell(array $shells) { // NOTE: The "BASH_VERSION" and "ZSH_VERSION" shell variables are not // passed to subprocesses, so we can't inspect them to figure out which // shell launched us. If we could figure this out in some other way, it // would be nice to do so. // Instead, just look at "SHELL" (the user's startup shell). $log = $this->getLogEngine(); $detected = array(); $log->writeStatus( pht('DETECT'), pht('Detecting current shell...')); $shell_env = getenv('SHELL'); if (!strlen($shell_env)) { $log->writeWarning( pht('SHELL'), pht( 'The "SHELL" environment variable is not defined, so it can '. 'not be used to detect the shell to install rules for.')); } else { $found = false; foreach ($shells as $shell) { if ($shell['path'] !== $shell_env) { continue; } $found = true; $detected[] = $shell['key']; $log->writeSuccess( pht('SHELL'), pht( 'The "SHELL" environment variable has value "%s", so the '. 'target shell was detected as "%s".', $shell_env, $shell['key'])); } if (!$found) { $log->writeStatus( pht('SHELL'), pht( 'The "SHELL" environment variable does not match any recognized '. 'shell.')); } } if (!$detected) { throw new PhutilArgumentUsageException( pht( 'Unable to detect any supported shell, so autocompletion rules '. 'can not be installed. Use "--shell" to select a shell.')); } else if (count($detected) > 1) { throw new PhutilArgumentUsageException( pht( 'Multiple supported shells were detected. Unable to determine '. 'which shell to install autocompletion rules for. Use "--shell" '. 'to select a shell.')); } return head($detected); } private function runGenerate() { $log = $this->getLogEngine(); $toolsets = ArcanistToolset::newToolsetMap(); $log->writeStatus( pht('GENERATE'), pht('Generating shell completion rules...')); $shells = array('bash'); foreach ($shells as $shell) { $rules = array(); foreach ($toolsets as $toolset) { $rules[] = $this->newCompletionRules($toolset, $shell); } $rules = implode("\n", $rules); $rules_path = $this->getShellPath('rules/'.$shell.'-rules.sh'); // If a write wouldn't change anything, skip the write. This allows // "arc shell-complete" to work if "arcanist/" is on a read-only NFS // filesystem or something unusual like that. $skip_write = false; if (Filesystem::pathExists($rules_path)) { $current = Filesystem::readFile($rules_path); if ($current === $rules) { $skip_write = true; } } if ($skip_write) { $log->writeStatus( pht('SKIP'), pht( 'Rules are already up to date for "%s" in: %s', $shell, Filesystem::readablePath($rules_path))); } else { Filesystem::writeFile($rules_path, $rules); $log->writeStatus( pht('RULES'), pht( 'Wrote updated completion rules for "%s" to: %s.', $shell, Filesystem::readablePath($rules_path))); } } } private function newCompletionRules(ArcanistToolset $toolset, $shell) { $template_path = $this->getShellPath('templates/'.$shell.'-template.sh'); $template = Filesystem::readFile($template_path); $variables = array( 'BIN' => $toolset->getToolsetKey(), ); foreach ($variables as $key => $value) { $template = str_replace('{{{'.$key.'}}}', $value, $template); } return $template; } private function getShellPath($to_file = null) { $arc_root = dirname(phutil_get_library_root('arcanist')); return $arc_root.'/support/shell/'.$to_file; } private function runAutocomplete() { $argv = $this->getArgument('argv'); $argc = count($argv); $pos = $this->getArgument('current'); if (!$pos) { $pos = $argc - 1; } if ($pos >= $argc) { throw new ArcanistUsageException( pht( 'Argument position specified with "--current" ("%s") is greater '. 'than the number of arguments provided ("%s").', new PhutilNumber($pos), new PhutilNumber($argc))); } $workflows = $this->getRuntime()->getWorkflows(); // NOTE: This isn't quite right. For example, "arc --con" will // try to autocomplete workflows named "--con", but it should actually // autocomplete global flags and suggest "--config". $is_workflow = ($pos <= 1); if ($is_workflow) { // NOTE: There was previously some logic to try to filter impossible // workflows out of the completion list based on the VCS in the current // working directory: for example, if you're in an SVN working directory, // "arc a" is unlikely to complete to "arc amend" because "amend" does // not support SVN. It's not clear this logic is valuable, but we could // consider restoring it if good use cases arise. // TOOLSETS: Restore the ability for workflows to opt out of shell // completion. It is exceptionally unlikely that users want to shell // complete obscure or internal workflows, like "arc shell-complete" // itself. Perhaps a good behavior would be to offer these as // completions if they are the ONLY available completion, since a user // who has typed "arc shell-comp" likely does want "shell-complete". $complete = array(); foreach ($workflows as $workflow) { $complete[] = $workflow->getWorkflowName(); } foreach ($this->getConfig('aliases') as $alias) { if ($alias->getException()) { continue; } if ($alias->getToolset() !== $this->getToolsetKey()) { continue; } $complete[] = $alias->getTrigger(); } $partial = $argv[$pos]; $complete = $this->getMatches($complete, $partial); if ($complete) { return $this->suggestStrings($complete); } else { return $this->suggestNothing(); } } else { // TOOLSETS: We should resolve aliases before picking a workflow, so // that if you alias "arc draft" to "arc diff --draft", we can suggest // other "diff" flags when you type "arc draft --q". // TOOLSETS: It's possible the workflow isn't in position 1. The user // may be running "arc --trace diff --dra", for example. $workflow = idx($workflows, $argv[1]); if (!$workflow) { return $this->suggestNothing(); } $arguments = $workflow->getWorkflowArguments(); $arguments = mpull($arguments, null, 'getKey'); $current = idx($argv, $pos, ''); $argument = null; $prev = idx($argv, $pos - 1, null); if (!strncmp($prev, '--', 2)) { $prev = substr($prev, 2); $argument = idx($arguments, $prev); } // If the last argument was a "--thing" argument, test if "--thing" is // a parameterized argument. If it is, the next argument should be a // parameter. if ($argument && strlen($argument->getParameter())) { if ($argument->getIsPathArgument()) { return $this->suggestPaths($current); } else { return $this->suggestNothing(); } // TOOLSETS: We can allow workflows and arguments to provide a specific // list of completeable values, like the "--shell" argument for this // workflow. } $flags = array(); $wildcard = null; foreach ($arguments as $argument) { if ($argument->getWildcard()) { $wildcard = $argument; continue; } $flags[] = '--'.$argument->getKey(); } $matches = $this->getMatches($flags, $current); // If whatever the user is completing does not match the prefix of any // flag, try to autcomplete a wildcard argument if it has some kind of // meaningful completion. For example, "arc lint READ" should // autocomplete a file. if (!$matches && $wildcard) { // TOOLSETS: There was previously some very questionable support for // autocompleting branches here. This could be moved into Arguments // and Workflows. if ($wildcard->getIsPathArgument()) { return $this->suggestPaths($current); } } // TODO: If a command has only one flag, like "--json", don't suggest // it if the user hasn't typed anything or has only typed "--". // TODO: Don't suggest "--flag" arguments which aren't repeatable if // they are already present in the argument list. return $this->suggestStrings($matches); } } private function suggestPaths($prefix) { // NOTE: We are returning a directive to the bash script to run "compgen" // for us rather than running it ourselves. If we run: // // compgen -A file -- %s // // ...from this context, it fails (exits with error code 1 and no output) // if the prefix is "foo\ ", on my machine. See T9116 for some dicussion. echo ''; return 0; } private function suggestNothing() { return $this->suggestStrings(array()); } private function suggestStrings(array $strings) { sort($strings); echo implode("\n", $strings); return 0; } private function getMatches(array $candidates, $prefix) { $matches = array(); if (strlen($prefix)) { foreach ($candidates as $possible) { if (!strncmp($possible, $prefix, strlen($prefix))) { $matches[] = $possible; } } // If we matched nothing, try a case-insensitive match. if (!$matches) { foreach ($candidates as $possible) { if (!strncasecmp($possible, $prefix, strlen($prefix))) { $matches[] = $possible; } } } } else { $matches = $candidates; } return $matches; } } diff --git a/src/toolset/workflow/ArcanistVersionWorkflow.php b/src/toolset/workflow/ArcanistVersionWorkflow.php index e8ffd069..f004f855 100644 --- a/src/toolset/workflow/ArcanistVersionWorkflow.php +++ b/src/toolset/workflow/ArcanistVersionWorkflow.php @@ -1,78 +1,79 @@ newWorkflowInformation() + ->setSynopsis(pht('Show toolset version information.')) ->addExample(pht('**version**')) ->setHelp($help); } public function getWorkflowArguments() { return array(); } public function runWorkflow() { // TOOLSETS: Show the toolset version, not just the "arc" version. $console = PhutilConsole::getConsole(); if (!Filesystem::binaryExists('git')) { throw new ArcanistUsageException( pht( 'Cannot display current version without "%s" installed.', 'git')); } $roots = array( 'arcanist' => dirname(phutil_get_library_root('arcanist')), ); foreach ($roots as $lib => $root) { $working_copy = ArcanistWorkingCopy::newFromWorkingDirectory($root); $repository_api = $working_copy->newRepositoryAPI(); if (!$repository_api instanceof ArcanistGitAPI) { throw new ArcanistUsageException( pht( 'Library "%s" is not a Git working copy, so no version '. 'information can be provided.', $lib)); } // NOTE: Carefully execute these commands in a way that works on Windows // until T8298 is properly fixed. See PHI52. list($commit) = $repository_api->execxLocal('log -1 --format=%%H'); $commit = trim($commit); list($timestamp) = $repository_api->execxLocal('log -1 --format=%%ct'); $timestamp = trim($timestamp); $console->writeOut( "%s %s (%s)\n", $lib, $commit, date('j M Y', (int)$timestamp)); } } } diff --git a/src/workflow/ArcanistAnoidWorkflow.php b/src/workflow/ArcanistAnoidWorkflow.php index 9dbad9d1..73dd11c2 100644 --- a/src/workflow/ArcanistAnoidWorkflow.php +++ b/src/workflow/ArcanistAnoidWorkflow.php @@ -1,29 +1,43 @@ newWorkflowInformation() + ->setSynopsis(pht('Pilot a probe from the vessel "Arcanoid".')) + ->addExample(pht('**anoid**')) + ->setHelp($help); } - public function getCommandHelp() { - return phutil_console_format(<<newWorkflowInformation() + ->setSynopsis( + pht('Create or update an Arcanist library.')) ->addExample(pht('**liberate**')) ->addExample(pht('**liberate** [__path__]')) ->setHelp($help); } public function getWorkflowArguments() { return array( $this->newWorkflowArgument('clean') ->setHelp( pht('Perform a clean rebuild, ignoring caches. Thorough, but slow.')), $this->newWorkflowArgument('argv') ->setWildcard(true), ); } public function runWorkflow() { $log = $this->getLogEngine(); $argv = $this->getArgument('argv'); if (count($argv) > 1) { throw new ArcanistUsageException( pht( 'Provide only one path to "arc liberate". The path should identify '. 'a directory where you want to create or update a library.')); } else if (!$argv) { $log->writeStatus( pht('SCAN'), pht('Searching for libraries in the current working directory...')); $init_files = id(new FileFinder(getcwd())) ->withPath('*/__phutil_library_init__.php') ->find(); if (!$init_files) { throw new ArcanistUsageException( pht( 'Unable to find any libraries under the current working '. 'directory. To create a library, provide a path.')); } $paths = array(); foreach ($init_files as $init) { $paths[] = Filesystem::resolvePath(dirname($init)); } } else { $paths = array( Filesystem::resolvePath(head($argv)), ); } foreach ($paths as $path) { $log->writeStatus( pht('WORK'), pht( 'Updating library: %s', Filesystem::readablePath($path).DIRECTORY_SEPARATOR)); $this->liberatePath($path); } $log->writeSuccess( pht('DONE'), pht('Updated %s librarie(s).', phutil_count($paths))); return 0; } private function liberatePath($path) { if (!Filesystem::pathExists($path.'/__phutil_library_init__.php')) { echo tsprintf( "%s\n", pht( 'No library currently exists at the path "%s"...', $path)); $this->liberateCreateDirectory($path); $this->liberateCreateLibrary($path); return; } $version = $this->getLibraryFormatVersion($path); switch ($version) { case 1: throw new ArcanistUsageException( pht( 'This very old library is no longer supported.')); case 2: return $this->liberateVersion2($path); default: throw new ArcanistUsageException( pht("Unknown library version '%s'!", $version)); } echo tsprintf("%s\n", pht('Done.')); } private function getLibraryFormatVersion($path) { $map_file = $path.'/__phutil_library_map__.php'; if (!Filesystem::pathExists($map_file)) { // Default to library v1. return 1; } $map = Filesystem::readFile($map_file); $matches = null; if (preg_match('/@phutil-library-version (\d+)/', $map, $matches)) { return (int)$matches[1]; } return 1; } private function liberateVersion2($path) { $bin = $this->getScriptPath('support/lib/rebuild-map.php'); $argv = array(); if ($this->getArgument('clean')) { $argv[] = '--drop-cache'; } return phutil_passthru( 'php -f %R -- %Ls %R', $bin, $argv, $path); } private function liberateCreateDirectory($path) { if (Filesystem::pathExists($path)) { if (!is_dir($path)) { throw new ArcanistUsageException( pht( 'Provide a directory to create or update a libphutil library in.')); } return; } echo pht("The directory '%s' does not exist.", $path); if (!phutil_console_confirm(pht('Do you want to create it?'))) { throw new ArcanistUsageException(pht('Cancelled.')); } execx('mkdir -p %R', $path); } private function liberateCreateLibrary($path) { $init_path = $path.'/__phutil_library_init__.php'; if (Filesystem::pathExists($init_path)) { return; } echo pht("Creating new libphutil library in '%s'.", $path)."\n"; do { echo pht('Choose a name for the new library.')."\n"; $name = phutil_console_prompt( pht('What do you want to name this library?')); if (preg_match('/^[a-z-]+$/', $name)) { break; } else { echo phutil_console_format( "%s\n", pht( 'Library name should contain only lowercase letters and hyphens.')); } } while (true); $template = "liberateVersion2($path); } private function getScriptPath($script) { $root = dirname(phutil_get_library_root('arcanist')); return $root.'/'.$script; } } diff --git a/src/workflow/ArcanistWeldWorkflow.php b/src/workflow/ArcanistWeldWorkflow.php index 7034db54..3c249b19 100644 --- a/src/workflow/ArcanistWeldWorkflow.php +++ b/src/workflow/ArcanistWeldWorkflow.php @@ -1,133 +1,134 @@ newWorkflowInformation() + ->setSynopsis(pht('Robustly fuse files together.')) + ->addExample('**weld** [options] -- __file__ __file__ ...') + ->setHelp($help); } - public function getArguments() { + public function getWorkflowArguments() { return array( - '*' => 'files', + $this->newWorkflowArgument('files') + ->setWildcard(true), ); } - public function run() { + public function runWorkflow() { $files = $this->getArgument('files'); + if (count($files) < 2) { - throw new ArcanistUsageException( + throw new PhutilArgumentUsageException( pht('Specify two or more files to weld together.')); } $buffer = array(); foreach ($files as $file) { $data = Filesystem::readFile($file); if (!strlen($data)) { continue; } $lines = phutil_split_lines($data, true); $overlap = mt_rand(16, 32); if (count($buffer) > 6) { $overlap = min($overlap, ceil(count($buffer) / 2)); } if (count($lines) > 6) { $overlap = min($overlap, ceil(count($lines) / 2)); } $overlap = min($overlap, count($buffer)); $overlap = min($overlap, count($lines)); $buffer_len = count($buffer); for ($ii = 0; $ii < $overlap; $ii++) { $buffer[$buffer_len - $overlap + $ii] = $this->weldLines( $buffer[$buffer_len - $overlap + $ii], $lines[$ii], ($ii + 0.5) / $overlap); } for ($ii = $overlap; $ii < count($lines); $ii++) { $buffer[] = $lines[$ii]; } } echo implode('', $buffer); } private function weldLines($u, $v, $bias) { $newline = null; $matches = null; if (preg_match('/([\r\n]+)\z/', $u, $matches)) { $newline = $matches[1]; } if (preg_match('/([\r\n]+)\z/', $v, $matches)) { $newline = $matches[1]; } $u = rtrim($u, "\r\n"); $v = rtrim($v, "\r\n"); $u = phutil_utf8v_combined($u); $v = phutil_utf8v_combined($v); $len = max(count($u), count($v)); while (count($u) < $len) { $u[] = ' '; } while (count($v) < $len) { $v[] = ' '; } $rand_max = mt_getrandmax(); $result = array(); for ($ii = 0; $ii < $len; $ii++) { $uc = $u[$ii]; $vc = $v[$ii]; $threshold = $bias; if ($uc == ' ') { $threshold = 1; } if ($vc == ' ') { $threshold = 0; } if ((mt_rand() / $rand_max) > $threshold) { $r = $uc; } else { $r = $vc; } $result[] = $r; } if ($newline !== null) { $result[] = $newline; } return implode('', $result); } } diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php index 603686cf..36d62593 100644 --- a/src/workflow/ArcanistWorkflow.php +++ b/src/workflow/ArcanistWorkflow.php @@ -1,2282 +1,2285 @@ toolset = $toolset; return $this; } final public function getToolset() { return $this->toolset; } final public function setRuntime(ArcanistRuntime $runtime) { $this->runtime = $runtime; return $this; } final public function getRuntime() { return $this->runtime; } final public function setConfigurationEngine( ArcanistConfigurationEngine $engine) { $this->configurationEngine = $engine; return $this; } final public function getConfigurationEngine() { return $this->configurationEngine; } final public function setConfigurationSourceList( ArcanistConfigurationSourceList $list) { $this->configurationSourceList = $list; return $this; } final public function getConfigurationSourceList() { return $this->configurationSourceList; } public function newPhutilWorkflow() { $arguments = $this->getWorkflowArguments(); assert_instances_of($arguments, 'ArcanistWorkflowArgument'); $specs = mpull($arguments, 'getPhutilSpecification'); $phutil_workflow = id(new ArcanistPhutilWorkflow()) ->setName($this->getWorkflowName()) ->setWorkflow($this) ->setArguments($specs); $information = $this->getWorkflowInformation(); if ($information) { + $synopsis = $information->getSynopsis(); + if (strlen($synopsis)) { + $phutil_workflow->setSynopsis($synopsis); + } $examples = $information->getExamples(); if ($examples) { $examples = implode("\n", $examples); $phutil_workflow->setExamples($examples); } $help = $information->getHelp(); if (strlen($help)) { // Unwrap linebreaks in the help text so we don't get weird formatting. $help = preg_replace("/(?<=\S)\n(?=\S)/", ' ', $help); $phutil_workflow->setHelp($help); } - } return $phutil_workflow; } final protected function newWorkflowArgument($key) { return id(new ArcanistWorkflowArgument()) ->setKey($key); } final protected function newWorkflowInformation() { return new ArcanistWorkflowInformation(); } final public function executeWorkflow(PhutilArgumentParser $args) { $runtime = $this->getRuntime(); $this->arguments = $args; $caught = null; $runtime->pushWorkflow($this); try { $err = $this->runWorkflow($args); } catch (Exception $ex) { $caught = $ex; } try { $this->runWorkflowCleanup(); } catch (Exception $ex) { phlog($ex); } $runtime->popWorkflow(); if ($caught) { throw $caught; } return $err; } final protected function getLogEngine() { return $this->getRuntime()->getLogEngine(); } protected function runWorkflowCleanup() { // TOOLSETS: Do we need this? return; } public function __construct() {} public function run() { throw new PhutilMethodNotImplementedException(); } /** * Finalizes any cleanup operations that need to occur regardless of * whether the command succeeded or failed. */ public function finalize() { $this->finalizeWorkingCopy(); } /** * Return the command used to invoke this workflow from the command like, * e.g. "help" for @{class:ArcanistHelpWorkflow}. * * @return string The command a user types to invoke this workflow. */ abstract public function getWorkflowName(); /** * Return console formatted string with all command synopses. * * @return string 6-space indented list of available command synopses. */ public function getCommandSynopses() { return array(); } /** * Return console formatted string with command help printed in `arc help`. * * @return string 10-space indented help to use the command. */ public function getCommandHelp() { return null; } public function supportsToolset(ArcanistToolset $toolset) { return false; } /* -( Conduit )------------------------------------------------------------ */ /** * Set the URI which the workflow will open a conduit connection to when * @{method:establishConduit} is called. Arcanist makes an effort to set * this by default for all workflows (by reading ##.arcconfig## and/or the * value of ##--conduit-uri##) even if they don't need Conduit, so a workflow * can generally upgrade into a conduit workflow later by just calling * @{method:establishConduit}. * * You generally should not need to call this method unless you are * specifically overriding the default URI. It is normally sufficient to * just invoke @{method:establishConduit}. * * NOTE: You can not call this after a conduit has been established. * * @param string The URI to open a conduit to when @{method:establishConduit} * is called. * @return this * @task conduit */ final public function setConduitURI($conduit_uri) { if ($this->conduit) { throw new Exception( pht( 'You can not change the Conduit URI after a '. 'conduit is already open.')); } $this->conduitURI = $conduit_uri; return $this; } /** * Returns the URI the conduit connection within the workflow uses. * * @return string * @task conduit */ final public function getConduitURI() { return $this->conduitURI; } /** * Open a conduit channel to the server which was previously configured by * calling @{method:setConduitURI}. Arcanist will do this automatically if * the workflow returns ##true## from @{method:requiresConduit}, or you can * later upgrade a workflow and build a conduit by invoking it manually. * * You must establish a conduit before you can make conduit calls. * * NOTE: You must call @{method:setConduitURI} before you can call this * method. * * @return this * @task conduit */ final public function establishConduit() { if ($this->conduit) { return $this; } if (!$this->conduitURI) { throw new Exception( pht( 'You must specify a Conduit URI with %s before you can '. 'establish a conduit.', 'setConduitURI()')); } $this->conduit = new ConduitClient($this->conduitURI); if ($this->conduitTimeout) { $this->conduit->setTimeout($this->conduitTimeout); } $user = $this->getConfigFromAnySource('http.basicauth.user'); $pass = $this->getConfigFromAnySource('http.basicauth.pass'); if ($user !== null && $pass !== null) { $this->conduit->setBasicAuthCredentials($user, $pass); } return $this; } final public function getConfigFromAnySource($key) { return $this->configurationManager->getConfigFromAnySource($key); } /** * Set credentials which will be used to authenticate against Conduit. These * credentials can then be used to establish an authenticated connection to * conduit by calling @{method:authenticateConduit}. Arcanist sets some * defaults for all workflows regardless of whether or not they return true * from @{method:requireAuthentication}, based on the ##~/.arcrc## and * ##.arcconf## files if they are present. Thus, you can generally upgrade a * workflow which does not require authentication into an authenticated * workflow by later invoking @{method:requireAuthentication}. You should not * normally need to call this method unless you are specifically overriding * the defaults. * * NOTE: You can not call this method after calling * @{method:authenticateConduit}. * * @param dict A credential dictionary, see @{method:authenticateConduit}. * @return this * @task conduit */ final public function setConduitCredentials(array $credentials) { if ($this->isConduitAuthenticated()) { throw new Exception( pht('You may not set new credentials after authenticating conduit.')); } $this->conduitCredentials = $credentials; return $this; } /** * Force arc to identify with a specific Conduit version during the * protocol handshake. This is primarily useful for development (especially * for sending diffs which bump the client Conduit version), since the client * still actually speaks the builtin version of the protocol. * * Controlled by the --conduit-version flag. * * @param int Version the client should pretend to be. * @return this * @task conduit */ final public function forceConduitVersion($version) { $this->forcedConduitVersion = $version; return $this; } /** * Get the protocol version the client should identify with. * * @return int Version the client should claim to be. * @task conduit */ final public function getConduitVersion() { return nonempty($this->forcedConduitVersion, 6); } /** * Override the default timeout for Conduit. * * Controlled by the --conduit-timeout flag. * * @param float Timeout, in seconds. * @return this * @task conduit */ final public function setConduitTimeout($timeout) { $this->conduitTimeout = $timeout; if ($this->conduit) { $this->conduit->setConduitTimeout($timeout); } return $this; } /** * Open and authenticate a conduit connection to a Phabricator server using * provided credentials. Normally, Arcanist does this for you automatically * when you return true from @{method:requiresAuthentication}, but you can * also upgrade an existing workflow to one with an authenticated conduit * by invoking this method manually. * * You must authenticate the conduit before you can make authenticated conduit * calls (almost all calls require authentication). * * This method uses credentials provided via @{method:setConduitCredentials} * to authenticate to the server: * * - ##user## (required) The username to authenticate with. * - ##certificate## (required) The Conduit certificate to use. * - ##description## (optional) Description of the invoking command. * * Successful authentication allows you to call @{method:getUserPHID} and * @{method:getUserName}, as well as use the client you access with * @{method:getConduit} to make authenticated calls. * * NOTE: You must call @{method:setConduitURI} and * @{method:setConduitCredentials} before you invoke this method. * * @return this * @task conduit */ final public function authenticateConduit() { if ($this->isConduitAuthenticated()) { return $this; } $this->establishConduit(); $credentials = $this->conduitCredentials; try { if (!$credentials) { throw new Exception( pht( 'Set conduit credentials with %s before authenticating conduit!', 'setConduitCredentials()')); } // If we have `token`, this server supports the simpler, new-style // token-based authentication. Use that instead of all the certificate // stuff. $token = idx($credentials, 'token'); if (strlen($token)) { $conduit = $this->getConduit(); $conduit->setConduitToken($token); try { $result = $this->getConduit()->callMethodSynchronous( 'user.whoami', array()); $this->userName = $result['userName']; $this->userPHID = $result['phid']; $this->conduitAuthenticated = true; return $this; } catch (Exception $ex) { $conduit->setConduitToken(null); throw $ex; } } if (empty($credentials['user'])) { throw new ConduitClientException( 'ERR-INVALID-USER', pht('Empty user in credentials.')); } if (empty($credentials['certificate'])) { throw new ConduitClientException( 'ERR-NO-CERTIFICATE', pht('Empty certificate in credentials.')); } $description = idx($credentials, 'description', ''); $user = $credentials['user']; $certificate = $credentials['certificate']; $connection = $this->getConduit()->callMethodSynchronous( 'conduit.connect', array( 'client' => 'arc', 'clientVersion' => $this->getConduitVersion(), 'clientDescription' => php_uname('n').':'.$description, 'user' => $user, 'certificate' => $certificate, 'host' => $this->conduitURI, )); } catch (ConduitClientException $ex) { if ($ex->getErrorCode() == 'ERR-NO-CERTIFICATE' || $ex->getErrorCode() == 'ERR-INVALID-USER' || $ex->getErrorCode() == 'ERR-INVALID-AUTH') { $conduit_uri = $this->conduitURI; $message = phutil_console_format( "\n%s\n\n %s\n\n%s\n%s", pht('YOU NEED TO __INSTALL A CERTIFICATE__ TO LOGIN TO PHABRICATOR'), pht('To do this, run: **%s**', 'arc install-certificate'), pht("The server '%s' rejected your request:", $conduit_uri), $ex->getMessage()); throw new ArcanistUsageException($message); } else if ($ex->getErrorCode() == 'NEW-ARC-VERSION') { // Cleverly disguise this as being AWESOME!!! echo phutil_console_format("**%s**\n\n", pht('New Version Available!')); echo phutil_console_wrap($ex->getMessage()); echo "\n\n"; echo pht('In most cases, arc can be upgraded automatically.')."\n"; $ok = phutil_console_confirm( pht('Upgrade arc now?'), $default_no = false); if (!$ok) { throw $ex; } $root = dirname(phutil_get_library_root('arcanist')); chdir($root); $err = phutil_passthru('%s upgrade', $root.'/bin/arc'); if (!$err) { echo "\n".pht('Try running your arc command again.')."\n"; } exit(1); } else { throw $ex; } } $this->userName = $user; $this->userPHID = $connection['userPHID']; $this->conduitAuthenticated = true; return $this; } /** * @return bool True if conduit is authenticated, false otherwise. * @task conduit */ final protected function isConduitAuthenticated() { return (bool)$this->conduitAuthenticated; } /** * Override this to return true if your workflow requires a conduit channel. * Arc will build the channel for you before your workflow executes. This * implies that you only need an unauthenticated channel; if you need * authentication, override @{method:requiresAuthentication}. * * @return bool True if arc should build a conduit channel before running * the workflow. * @task conduit */ public function requiresConduit() { return false; } /** * Override this to return true if your workflow requires an authenticated * conduit channel. This implies that it requires a conduit. Arc will build * and authenticate the channel for you before the workflow executes. * * @return bool True if arc should build an authenticated conduit channel * before running the workflow. * @task conduit */ public function requiresAuthentication() { return false; } /** * Returns the PHID for the user once they've authenticated via Conduit. * * @return phid Authenticated user PHID. * @task conduit */ final public function getUserPHID() { if (!$this->userPHID) { $workflow = get_class($this); throw new Exception( pht( "This workflow ('%s') requires authentication, override ". "%s to return true.", $workflow, 'requiresAuthentication()')); } return $this->userPHID; } /** * Return the username for the user once they've authenticated via Conduit. * * @return string Authenticated username. * @task conduit */ final public function getUserName() { return $this->userName; } /** * Get the established @{class@libphutil:ConduitClient} in order to make * Conduit method calls. Before the client is available it must be connected, * either implicitly by making @{method:requireConduit} or * @{method:requireAuthentication} return true, or explicitly by calling * @{method:establishConduit} or @{method:authenticateConduit}. * * @return @{class@libphutil:ConduitClient} Live conduit client. * @task conduit */ final public function getConduit() { if (!$this->conduit) { $workflow = get_class($this); throw new Exception( pht( "This workflow ('%s') requires a Conduit, override ". "%s to return true.", $workflow, 'requiresConduit()')); } return $this->conduit; } final public function setArcanistConfiguration( ArcanistConfiguration $arcanist_configuration) { $this->arcanistConfiguration = $arcanist_configuration; return $this; } final public function getArcanistConfiguration() { return $this->arcanistConfiguration; } final public function setConfigurationManager( ArcanistConfigurationManager $arcanist_configuration_manager) { $this->configurationManager = $arcanist_configuration_manager; return $this; } final public function getConfigurationManager() { return $this->configurationManager; } public function requiresWorkingCopy() { return false; } public function desiresWorkingCopy() { return false; } public function requiresRepositoryAPI() { return false; } public function desiresRepositoryAPI() { return false; } final public function setCommand($command) { $this->command = $command; return $this; } final public function getCommand() { return $this->command; } public function getArguments() { return array(); } final public function setWorkingDirectory($working_directory) { $this->workingDirectory = $working_directory; return $this; } final public function getWorkingDirectory() { return $this->workingDirectory; } final private function setParentWorkflow($parent_workflow) { $this->parentWorkflow = $parent_workflow; return $this; } final protected function getParentWorkflow() { return $this->parentWorkflow; } final public function buildChildWorkflow($command, array $argv) { $arc_config = $this->getArcanistConfiguration(); $workflow = $arc_config->buildWorkflow($command); $workflow->setParentWorkflow($this); $workflow->setConduitEngine($this->getConduitEngine()); $workflow->setCommand($command); $workflow->setConfigurationManager($this->getConfigurationManager()); if ($this->repositoryAPI) { $workflow->setRepositoryAPI($this->repositoryAPI); } if ($this->userPHID) { $workflow->userPHID = $this->getUserPHID(); $workflow->userName = $this->getUserName(); } if ($this->conduit) { $workflow->conduit = $this->conduit; $workflow->setConduitCredentials($this->conduitCredentials); $workflow->conduitAuthenticated = $this->conduitAuthenticated; } $workflow->setArcanistConfiguration($arc_config); $workflow->parseArguments(array_values($argv)); return $workflow; } final public function getArgument($key, $default = null) { // TOOLSETS: Remove this legacy code. if (is_array($this->arguments)) { return idx($this->arguments, $key, $default); } return $this->arguments->getArg($key); } final public function getPassedArguments() { return $this->passedArguments; } final public function getCompleteArgumentSpecification() { $spec = $this->getArguments(); $arc_config = $this->getArcanistConfiguration(); $command = $this->getCommand(); $spec += $arc_config->getCustomArgumentsForCommand($command); return $spec; } final public function parseArguments(array $args) { $this->passedArguments = $args; $spec = $this->getCompleteArgumentSpecification(); $dict = array(); $more_key = null; if (!empty($spec['*'])) { $more_key = $spec['*']; unset($spec['*']); $dict[$more_key] = array(); } $short_to_long_map = array(); foreach ($spec as $long => $options) { if (!empty($options['short'])) { $short_to_long_map[$options['short']] = $long; } } foreach ($spec as $long => $options) { if (!empty($options['repeat'])) { $dict[$long] = array(); } } $more = array(); $size = count($args); for ($ii = 0; $ii < $size; $ii++) { $arg = $args[$ii]; $arg_name = null; $arg_key = null; if ($arg == '--') { $more = array_merge( $more, array_slice($args, $ii + 1)); break; } else if (!strncmp($arg, '--', 2)) { $arg_key = substr($arg, 2); $parts = explode('=', $arg_key, 2); if (count($parts) == 2) { list($arg_key, $val) = $parts; array_splice($args, $ii, 1, array('--'.$arg_key, $val)); $size++; } if (!array_key_exists($arg_key, $spec)) { $corrected = PhutilArgumentSpellingCorrector::newFlagCorrector() ->correctSpelling($arg_key, array_keys($spec)); if (count($corrected) == 1) { PhutilConsole::getConsole()->writeErr( pht( "(Assuming '%s' is the British spelling of '%s'.)", '--'.$arg_key, '--'.head($corrected))."\n"); $arg_key = head($corrected); } else { throw new ArcanistUsageException( pht( "Unknown argument '%s'. Try '%s'.", $arg_key, 'arc help')); } } } else if (!strncmp($arg, '-', 1)) { $arg_key = substr($arg, 1); if (empty($short_to_long_map[$arg_key])) { throw new ArcanistUsageException( pht( "Unknown argument '%s'. Try '%s'.", $arg_key, 'arc help')); } $arg_key = $short_to_long_map[$arg_key]; } else { $more[] = $arg; continue; } $options = $spec[$arg_key]; if (empty($options['param'])) { $dict[$arg_key] = true; } else { if ($ii == $size - 1) { throw new ArcanistUsageException( pht( "Option '%s' requires a parameter.", $arg)); } if (!empty($options['repeat'])) { $dict[$arg_key][] = $args[$ii + 1]; } else { $dict[$arg_key] = $args[$ii + 1]; } $ii++; } } if ($more) { if ($more_key) { $dict[$more_key] = $more; } else { $example = reset($more); throw new ArcanistUsageException( pht( "Unrecognized argument '%s'. Try '%s'.", $example, 'arc help')); } } foreach ($dict as $key => $value) { if (empty($spec[$key]['conflicts'])) { continue; } foreach ($spec[$key]['conflicts'] as $conflict => $more) { if (isset($dict[$conflict])) { if ($more) { $more = ': '.$more; } else { $more = '.'; } // TODO: We'll always display these as long-form, when the user might // have typed them as short form. throw new ArcanistUsageException( pht( "Arguments '%s' and '%s' are mutually exclusive", "--{$key}", "--{$conflict}").$more); } } } $this->arguments = $dict; $this->didParseArguments(); return $this; } protected function didParseArguments() { // Override this to customize workflow argument behavior. } final public function getWorkingCopy() { $working_copy = $this->getConfigurationManager()->getWorkingCopyIdentity(); if (!$working_copy) { $workflow = get_class($this); throw new Exception( pht( "This workflow ('%s') requires a working copy, override ". "%s to return true.", $workflow, 'requiresWorkingCopy()')); } return $working_copy; } final public function setRepositoryAPI($api) { $this->repositoryAPI = $api; return $this; } final public function hasRepositoryAPI() { try { return (bool)$this->getRepositoryAPI(); } catch (Exception $ex) { return false; } } final public function getRepositoryAPI() { if (!$this->repositoryAPI) { $workflow = get_class($this); throw new Exception( pht( "This workflow ('%s') requires a Repository API, override ". "%s to return true.", $workflow, 'requiresRepositoryAPI()')); } return $this->repositoryAPI; } final protected function shouldRequireCleanUntrackedFiles() { return empty($this->arguments['allow-untracked']); } final public function setCommitMode($mode) { $this->commitMode = $mode; return $this; } final public function finalizeWorkingCopy() { if ($this->stashed) { $api = $this->getRepositoryAPI(); $api->unstashChanges(); echo pht('Restored stashed changes to the working directory.')."\n"; } } final public function requireCleanWorkingCopy() { $api = $this->getRepositoryAPI(); $must_commit = array(); $working_copy_desc = phutil_console_format( " %s: __%s__\n\n", pht('Working copy'), $api->getPath()); // NOTE: this is a subversion-only concept. $incomplete = $api->getIncompleteChanges(); if ($incomplete) { throw new ArcanistUsageException( sprintf( "%s\n\n%s %s\n %s\n\n%s", pht( "You have incompletely checked out directories in this working ". "copy. Fix them before proceeding.'"), $working_copy_desc, pht('Incomplete directories in working copy:'), implode("\n ", $incomplete), pht( "You can fix these paths by running '%s' on them.", 'svn update'))); } $conflicts = $api->getMergeConflicts(); if ($conflicts) { throw new ArcanistUsageException( sprintf( "%s\n\n%s %s\n %s", pht( 'You have merge conflicts in this working copy. Resolve merge '. 'conflicts before proceeding.'), $working_copy_desc, pht('Conflicts in working copy:'), implode("\n ", $conflicts))); } $missing = $api->getMissingChanges(); if ($missing) { throw new ArcanistUsageException( sprintf( "%s\n\n%s %s\n %s\n", pht( 'You have missing files in this working copy. Revert or formally '. 'remove them (with `%s`) before proceeding.', 'svn rm'), $working_copy_desc, pht('Missing files in working copy:'), implode("\n ", $missing))); } $externals = $api->getDirtyExternalChanges(); // TODO: This state can exist in Subversion, but it is currently handled // elsewhere. It should probably be handled here, eventually. if ($api instanceof ArcanistSubversionAPI) { $externals = array(); } if ($externals) { $message = pht( '%s submodule(s) have uncommitted or untracked changes:', new PhutilNumber(count($externals))); $prompt = pht( 'Ignore the changes to these %s submodule(s) and continue?', new PhutilNumber(count($externals))); $list = id(new PhutilConsoleList()) ->setWrap(false) ->addItems($externals); id(new PhutilConsoleBlock()) ->addParagraph($message) ->addList($list) ->draw(); $ok = phutil_console_confirm($prompt, $default_no = false); if (!$ok) { throw new ArcanistUserAbortException(); } } $uncommitted = $api->getUncommittedChanges(); $unstaged = $api->getUnstagedChanges(); // We already dealt with externals. $unstaged = array_diff($unstaged, $externals); // We only want files which are purely uncommitted. $uncommitted = array_diff($uncommitted, $unstaged); $uncommitted = array_diff($uncommitted, $externals); $untracked = $api->getUntrackedChanges(); if (!$this->shouldRequireCleanUntrackedFiles()) { $untracked = array(); } if ($untracked) { echo sprintf( "%s\n\n%s", pht('You have untracked files in this working copy.'), $working_copy_desc); if ($api instanceof ArcanistGitAPI) { $hint = pht( '(To ignore these %s change(s), add them to "%s".)', phutil_count($untracked), '.git/info/exclude'); } else if ($api instanceof ArcanistSubversionAPI) { $hint = pht( '(To ignore these %s change(s), add them to "%s".)', phutil_count($untracked), 'svn:ignore'); } else if ($api instanceof ArcanistMercurialAPI) { $hint = pht( '(To ignore these %s change(s), add them to "%s".)', phutil_count($untracked), '.hgignore'); } $untracked_list = " ".implode("\n ", $untracked); echo sprintf( " %s\n %s\n%s", pht('Untracked changes in working copy:'), $hint, $untracked_list); $prompt = pht( 'Ignore these %s untracked file(s) and continue?', phutil_count($untracked)); if (!phutil_console_confirm($prompt)) { throw new ArcanistUserAbortException(); } } $should_commit = false; if ($unstaged || $uncommitted) { // NOTE: We're running this because it builds a cache and can take a // perceptible amount of time to arrive at an answer, but we don't want // to pause in the middle of printing the output below. $this->getShouldAmend(); echo sprintf( "%s\n\n%s", pht('You have uncommitted changes in this working copy.'), $working_copy_desc); $lists = array(); if ($unstaged) { $unstaged_list = " ".implode("\n ", $unstaged); $lists[] = sprintf( " %s\n%s", pht('Unstaged changes in working copy:'), $unstaged_list); } if ($uncommitted) { $uncommitted_list = " ".implode("\n ", $uncommitted); $lists[] = sprintf( "%s\n%s", pht('Uncommitted changes in working copy:'), $uncommitted_list); } echo implode("\n\n", $lists)."\n"; $all_uncommitted = array_merge($unstaged, $uncommitted); if ($this->askForAdd($all_uncommitted)) { if ($unstaged) { $api->addToCommit($unstaged); } $should_commit = true; } else { $permit_autostash = $this->getConfigFromAnySource('arc.autostash'); if ($permit_autostash && $api->canStashChanges()) { echo pht( 'Stashing uncommitted changes. (You can restore them with `%s`).', 'git stash pop')."\n"; $api->stashChanges(); $this->stashed = true; } else { throw new ArcanistUsageException( pht( 'You can not continue with uncommitted changes. '. 'Commit or discard them before proceeding.')); } } } if ($should_commit) { if ($this->getShouldAmend()) { $commit = head($api->getLocalCommitInformation()); $api->amendCommit($commit['message']); } else if ($api->supportsLocalCommits()) { $template = sprintf( "\n\n# %s\n#\n# %s\n#\n", pht('Enter a commit message.'), pht('Changes:')); $paths = array_merge($uncommitted, $unstaged); $paths = array_unique($paths); sort($paths); foreach ($paths as $path) { $template .= "# ".$path."\n"; } $commit_message = $this->newInteractiveEditor($template) ->setName(pht('commit-message')) ->editInteractively(); if ($commit_message === $template) { throw new ArcanistUsageException( pht('You must provide a commit message.')); } $commit_message = ArcanistCommentRemover::removeComments( $commit_message); if (!strlen($commit_message)) { throw new ArcanistUsageException( pht('You must provide a nonempty commit message.')); } $api->doCommit($commit_message); } } } private function getShouldAmend() { if ($this->shouldAmend === null) { $this->shouldAmend = $this->calculateShouldAmend(); } return $this->shouldAmend; } private function calculateShouldAmend() { $api = $this->getRepositoryAPI(); if ($this->isHistoryImmutable() || !$api->supportsAmend()) { return false; } $commits = $api->getLocalCommitInformation(); if (!$commits) { return false; } $commit = reset($commits); $message = ArcanistDifferentialCommitMessage::newFromRawCorpus( $commit['message']); if ($message->getGitSVNBaseRevision()) { return false; } if ($api->getAuthor() != $commit['author']) { return false; } if ($message->getRevisionID() && $this->getArgument('create')) { return false; } // TODO: Check commits since tracking branch. If empty then return false. // Don't amend the current commit if it has already been published. $repository = $this->loadProjectRepository(); if ($repository) { $repo_id = $repository['id']; $commit_hash = $commit['commit']; $callsign = idx($repository, 'callsign'); if ($callsign) { // The server might be too old to support the new style commit names, // so prefer the old way $commit_name = "r{$callsign}{$commit_hash}"; } else { $commit_name = "R{$repo_id}:{$commit_hash}"; } $result = $this->getConduit()->callMethodSynchronous( 'diffusion.querycommits', array('names' => array($commit_name))); $known_commit = idx($result['identifierMap'], $commit_name); if ($known_commit) { return false; } } if (!$message->getRevisionID()) { return true; } $in_working_copy = $api->loadWorkingCopyDifferentialRevisions( $this->getConduit(), array( 'authors' => array($this->getUserPHID()), 'status' => 'status-open', )); if ($in_working_copy) { return true; } return false; } private function askForAdd(array $files) { if ($this->commitMode == self::COMMIT_DISABLE) { return false; } if ($this->commitMode == self::COMMIT_ENABLE) { return true; } $prompt = $this->getAskForAddPrompt($files); return phutil_console_confirm($prompt); } private function getAskForAddPrompt(array $files) { if ($this->getShouldAmend()) { $prompt = pht( 'Do you want to amend these %s change(s) to the current commit?', phutil_count($files)); } else { $prompt = pht( 'Do you want to create a new commit with these %s change(s)?', phutil_count($files)); } return $prompt; } final protected function loadDiffBundleFromConduit( ConduitClient $conduit, $diff_id) { return $this->loadBundleFromConduit( $conduit, array( 'ids' => array($diff_id), )); } final protected function loadRevisionBundleFromConduit( ConduitClient $conduit, $revision_id) { return $this->loadBundleFromConduit( $conduit, array( 'revisionIDs' => array($revision_id), )); } final private function loadBundleFromConduit( ConduitClient $conduit, $params) { $future = $conduit->callMethod('differential.querydiffs', $params); $diff = head($future->resolve()); if ($diff == null) { throw new Exception( phutil_console_wrap( pht("The diff or revision you specified is either invalid or you ". "don't have permission to view it.")) ); } $changes = array(); foreach ($diff['changes'] as $changedict) { $changes[] = ArcanistDiffChange::newFromDictionary($changedict); } $bundle = ArcanistBundle::newFromChanges($changes); $bundle->setConduit($conduit); // since the conduit method has changes, assume that these fields // could be unset $bundle->setBaseRevision(idx($diff, 'sourceControlBaseRevision')); $bundle->setRevisionID(idx($diff, 'revisionID')); $bundle->setAuthorName(idx($diff, 'authorName')); $bundle->setAuthorEmail(idx($diff, 'authorEmail')); return $bundle; } /** * Return a list of lines changed by the current diff, or ##null## if the * change list is meaningless (for example, because the path is a directory * or binary file). * * @param string Path within the repository. * @param string Change selection mode (see ArcanistDiffHunk). * @return list|null List of changed line numbers, or null to indicate that * the path is not a line-oriented text file. */ final protected function getChangedLines($path, $mode) { $repository_api = $this->getRepositoryAPI(); $full_path = $repository_api->getPath($path); if (is_dir($full_path)) { return null; } if (!file_exists($full_path)) { return null; } $change = $this->getChange($path); if ($change->getFileType() !== ArcanistDiffChangeType::FILE_TEXT) { return null; } $lines = $change->getChangedLines($mode); return array_keys($lines); } final protected function getChange($path) { $repository_api = $this->getRepositoryAPI(); // TODO: Very gross $is_git = ($repository_api instanceof ArcanistGitAPI); $is_hg = ($repository_api instanceof ArcanistMercurialAPI); $is_svn = ($repository_api instanceof ArcanistSubversionAPI); if ($is_svn) { // NOTE: In SVN, we don't currently support a "get all local changes" // operation, so special case it. if (empty($this->changeCache[$path])) { $diff = $repository_api->getRawDiffText($path); $parser = $this->newDiffParser(); $changes = $parser->parseDiff($diff); if (count($changes) != 1) { throw new Exception(pht('Expected exactly one change.')); } $this->changeCache[$path] = reset($changes); } } else if ($is_git || $is_hg) { if (empty($this->changeCache)) { $changes = $repository_api->getAllLocalChanges(); foreach ($changes as $change) { $this->changeCache[$change->getCurrentPath()] = $change; } } } else { throw new Exception(pht('Missing VCS support.')); } if (empty($this->changeCache[$path])) { if ($is_git || $is_hg) { // This can legitimately occur under git/hg if you make a change, // "git/hg commit" it, and then revert the change in the working copy // and run "arc lint". $change = new ArcanistDiffChange(); $change->setCurrentPath($path); return $change; } else { throw new Exception( pht( "Trying to get change for unchanged path '%s'!", $path)); } } return $this->changeCache[$path]; } final public function willRunWorkflow() { $spec = $this->getCompleteArgumentSpecification(); foreach ($this->arguments as $arg => $value) { if (empty($spec[$arg])) { continue; } $options = $spec[$arg]; if (!empty($options['supports'])) { $system_name = $this->getRepositoryAPI()->getSourceControlSystemName(); if (!in_array($system_name, $options['supports'])) { $extended_info = null; if (!empty($options['nosupport'][$system_name])) { $extended_info = ' '.$options['nosupport'][$system_name]; } throw new ArcanistUsageException( pht( "Option '%s' is not supported under %s.", "--{$arg}", $system_name). $extended_info); } } } } final protected function normalizeRevisionID($revision_id) { return preg_replace('/^D/i', '', $revision_id); } protected function shouldShellComplete() { return true; } protected function getShellCompletions(array $argv) { return array(); } public function getSupportedRevisionControlSystems() { return array('git', 'hg', 'svn'); } final protected function getPassthruArgumentsAsMap($command) { $map = array(); foreach ($this->getCompleteArgumentSpecification() as $key => $spec) { if (!empty($spec['passthru'][$command])) { if (isset($this->arguments[$key])) { $map[$key] = $this->arguments[$key]; } } } return $map; } final protected function getPassthruArgumentsAsArgv($command) { $spec = $this->getCompleteArgumentSpecification(); $map = $this->getPassthruArgumentsAsMap($command); $argv = array(); foreach ($map as $key => $value) { $argv[] = '--'.$key; if (!empty($spec[$key]['param'])) { $argv[] = $value; } } return $argv; } /** * Write a message to stderr so that '--json' flags or stdout which is meant * to be piped somewhere aren't disrupted. * * @param string Message to write to stderr. * @return void */ final protected function writeStatusMessage($msg) { fwrite(STDERR, $msg); } final public function writeInfo($title, $message) { $this->writeStatusMessage( phutil_console_format( "** %s ** %s\n", $title, $message)); } final public function writeWarn($title, $message) { $this->writeStatusMessage( phutil_console_format( "** %s ** %s\n", $title, $message)); } final public function writeOkay($title, $message) { $this->writeStatusMessage( phutil_console_format( "** %s ** %s\n", $title, $message)); } final protected function isHistoryImmutable() { $repository_api = $this->getRepositoryAPI(); $config = $this->getConfigFromAnySource('history.immutable'); if ($config !== null) { return $config; } return $repository_api->isHistoryDefaultImmutable(); } /** * Workflows like 'lint' and 'unit' operate on a list of working copy paths. * The user can either specify the paths explicitly ("a.js b.php"), or by * specifying a revision ("--rev a3f10f1f") to select all paths modified * since that revision, or by omitting both and letting arc choose the * default relative revision. * * This method takes the user's selections and returns the paths that the * workflow should act upon. * * @param list List of explicitly provided paths. * @param string|null Revision name, if provided. * @param mask Mask of ArcanistRepositoryAPI flags to exclude. * Defaults to ArcanistRepositoryAPI::FLAG_UNTRACKED. * @return list List of paths the workflow should act on. */ final protected function selectPathsForWorkflow( array $paths, $rev, $omit_mask = null) { if ($omit_mask === null) { $omit_mask = ArcanistRepositoryAPI::FLAG_UNTRACKED; } if ($paths) { $working_copy = $this->getWorkingCopy(); foreach ($paths as $key => $path) { $full_path = Filesystem::resolvePath($path); if (!Filesystem::pathExists($full_path)) { throw new ArcanistUsageException( pht( "Path '%s' does not exist!", $path)); } $relative_path = Filesystem::readablePath( $full_path, $working_copy->getProjectRoot()); $paths[$key] = $relative_path; } } else { $repository_api = $this->getRepositoryAPI(); if ($rev) { $this->parseBaseCommitArgument(array($rev)); } $paths = $repository_api->getWorkingCopyStatus(); foreach ($paths as $path => $flags) { if ($flags & $omit_mask) { unset($paths[$path]); } } $paths = array_keys($paths); } return array_values($paths); } final protected function renderRevisionList(array $revisions) { $list = array(); foreach ($revisions as $revision) { $list[] = ' - D'.$revision['id'].': '.$revision['title']."\n"; } return implode('', $list); } /* -( Scratch Files )------------------------------------------------------ */ /** * Try to read a scratch file, if it exists and is readable. * * @param string Scratch file name. * @return mixed String for file contents, or false for failure. * @task scratch */ final protected function readScratchFile($path) { if (!$this->repositoryAPI) { return false; } return $this->getRepositoryAPI()->readScratchFile($path); } /** * Try to read a scratch JSON file, if it exists and is readable. * * @param string Scratch file name. * @return array Empty array for failure. * @task scratch */ final protected function readScratchJSONFile($path) { $file = $this->readScratchFile($path); if (!$file) { return array(); } return phutil_json_decode($file); } /** * Try to write a scratch file, if there's somewhere to put it and we can * write there. * * @param string Scratch file name to write. * @param string Data to write. * @return bool True on success, false on failure. * @task scratch */ final protected function writeScratchFile($path, $data) { if (!$this->repositoryAPI) { return false; } return $this->getRepositoryAPI()->writeScratchFile($path, $data); } /** * Try to write a scratch JSON file, if there's somewhere to put it and we can * write there. * * @param string Scratch file name to write. * @param array Data to write. * @return bool True on success, false on failure. * @task scratch */ final protected function writeScratchJSONFile($path, array $data) { return $this->writeScratchFile($path, json_encode($data)); } /** * Try to remove a scratch file. * * @param string Scratch file name to remove. * @return bool True if the file was removed successfully. * @task scratch */ final protected function removeScratchFile($path) { if (!$this->repositoryAPI) { return false; } return $this->getRepositoryAPI()->removeScratchFile($path); } /** * Get a human-readable description of the scratch file location. * * @param string Scratch file name. * @return mixed String, or false on failure. * @task scratch */ final protected function getReadableScratchFilePath($path) { if (!$this->repositoryAPI) { return false; } return $this->getRepositoryAPI()->getReadableScratchFilePath($path); } /** * Get the path to a scratch file, if possible. * * @param string Scratch file name. * @return mixed File path, or false on failure. * @task scratch */ final protected function getScratchFilePath($path) { if (!$this->repositoryAPI) { return false; } return $this->getRepositoryAPI()->getScratchFilePath($path); } final protected function getRepositoryEncoding() { return nonempty( idx($this->loadProjectRepository(), 'encoding'), 'UTF-8'); } final protected function loadProjectRepository() { list($info, $reasons) = $this->loadRepositoryInformation(); return coalesce($info, array()); } final protected function newInteractiveEditor($text) { $editor = new PhutilInteractiveEditor($text); $preferred = $this->getConfigFromAnySource('editor'); if ($preferred) { $editor->setPreferredEditor($preferred); } return $editor; } final protected function newDiffParser() { $parser = new ArcanistDiffParser(); if ($this->repositoryAPI) { $parser->setRepositoryAPI($this->getRepositoryAPI()); } $parser->setWriteDiffOnFailure(true); return $parser; } final protected function resolveCall(ConduitFuture $method, $timeout = null) { try { return $method->resolve($timeout); } catch (ConduitClientException $ex) { if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') { echo phutil_console_wrap( pht( 'This feature requires a newer version of Phabricator. Please '. 'update it using these instructions: %s', 'https://secure.phabricator.com/book/phabricator/article/'. 'upgrading/')."\n\n"); } throw $ex; } } final protected function dispatchEvent($type, array $data) { $data += array( 'workflow' => $this, ); $event = new PhutilEvent($type, $data); PhutilEventEngine::dispatchEvent($event); return $event; } final public function parseBaseCommitArgument(array $argv) { if (!count($argv)) { return; } $api = $this->getRepositoryAPI(); if (!$api->supportsCommitRanges()) { throw new ArcanistUsageException( pht('This version control system does not support commit ranges.')); } if (count($argv) > 1) { throw new ArcanistUsageException( pht( 'Specify exactly one base commit. The end of the commit range is '. 'always the working copy state.')); } $api->setBaseCommit(head($argv)); return $this; } final protected function getRepositoryVersion() { if (!$this->repositoryVersion) { $api = $this->getRepositoryAPI(); $commit = $api->getSourceControlBaseRevision(); $versions = array('' => $commit); foreach ($api->getChangedFiles($commit) as $path => $mask) { $versions[$path] = (Filesystem::pathExists($path) ? md5_file($path) : ''); } $this->repositoryVersion = md5(json_encode($versions)); } return $this->repositoryVersion; } /* -( Phabricator Repositories )------------------------------------------- */ /** * Get the PHID of the Phabricator repository this working copy corresponds * to. Returns `null` if no repository can be identified. * * @return phid|null Repository PHID, or null if no repository can be * identified. * * @task phabrep */ final protected function getRepositoryPHID() { return idx($this->getRepositoryInformation(), 'phid'); } /** * Get the name of the Phabricator repository this working copy * corresponds to. Returns `null` if no repository can be identified. * * @return string|null Repository name, or null if no repository can be * identified. * * @task phabrep */ final protected function getRepositoryName() { return idx($this->getRepositoryInformation(), 'name'); } /** * Get the URI of the Phabricator repository this working copy * corresponds to. Returns `null` if no repository can be identified. * * @return string|null Repository URI, or null if no repository can be * identified. * * @task phabrep */ final protected function getRepositoryURI() { return idx($this->getRepositoryInformation(), 'uri'); } final protected function getRepositoryStagingConfiguration() { return idx($this->getRepositoryInformation(), 'staging'); } /** * Get human-readable reasoning explaining how `arc` evaluated which * Phabricator repository corresponds to this working copy. Used by * `arc which` to explain the process to users. * * @return list Human-readable explanation of the repository * association process. * * @task phabrep */ final protected function getRepositoryReasons() { $this->getRepositoryInformation(); return $this->repositoryReasons; } /** * @task phabrep */ private function getRepositoryInformation() { if ($this->repositoryInfo === null) { list($info, $reasons) = $this->loadRepositoryInformation(); $this->repositoryInfo = nonempty($info, array()); $this->repositoryReasons = $reasons; } return $this->repositoryInfo; } /** * @task phabrep */ private function loadRepositoryInformation() { list($query, $reasons) = $this->getRepositoryQuery(); if (!$query) { return array(null, $reasons); } try { $method = 'repository.query'; $results = $this->getConduitEngine()->newCall($method, $query) ->resolve(); } catch (ConduitClientException $ex) { if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') { $reasons[] = pht( 'This version of Arcanist is more recent than the version of '. 'Phabricator you are connecting to: the Phabricator install is '. 'out of date and does not have support for identifying '. 'repositories by callsign or URI. Update Phabricator to enable '. 'these features.'); return array(null, $reasons); } throw $ex; } $result = null; if (!$results) { $reasons[] = pht( 'No repositories matched the query. Check that your configuration '. 'is correct, or use "%s" to select a repository explicitly.', 'repository.callsign'); } else if (count($results) > 1) { $reasons[] = pht( 'Multiple repostories (%s) matched the query. You can use the '. '"%s" configuration to select the one you want.', implode(', ', ipull($results, 'callsign')), 'repository.callsign'); } else { $result = head($results); $reasons[] = pht('Found a unique matching repository.'); } return array($result, $reasons); } /** * @task phabrep */ private function getRepositoryQuery() { $reasons = array(); $callsign = $this->getConfigFromAnySource('repository.callsign'); if ($callsign) { $query = array( 'callsigns' => array($callsign), ); $reasons[] = pht( 'Configuration value "%s" is set to "%s".', 'repository.callsign', $callsign); return array($query, $reasons); } else { $reasons[] = pht( 'Configuration value "%s" is empty.', 'repository.callsign'); } $uuid = $this->getRepositoryAPI()->getRepositoryUUID(); if ($uuid !== null) { $query = array( 'uuids' => array($uuid), ); $reasons[] = pht( 'The UUID for this working copy is "%s".', $uuid); return array($query, $reasons); } else { $reasons[] = pht( 'This repository has no VCS UUID (this is normal for git/hg).'); } $remote_uri = $this->getRepositoryAPI()->getRemoteURI(); if ($remote_uri !== null) { $query = array( 'remoteURIs' => array($remote_uri), ); $reasons[] = pht( 'The remote URI for this working copy is "%s".', $remote_uri); return array($query, $reasons); } else { $reasons[] = pht( 'Unable to determine the remote URI for this repository.'); } return array(null, $reasons); } /** * Build a new lint engine for the current working copy. * * Optionally, you can pass an explicit engine class name to build an engine * of a particular class. Normally this is used to implement an `--engine` * flag from the CLI. * * @param string Optional explicit engine class name. * @return ArcanistLintEngine Constructed engine. */ protected function newLintEngine($engine_class = null) { $working_copy = $this->getWorkingCopy(); $config = $this->getConfigurationManager(); if (!$engine_class) { $engine_class = $config->getConfigFromAnySource('lint.engine'); } if (!$engine_class) { if (Filesystem::pathExists($working_copy->getProjectPath('.arclint'))) { $engine_class = 'ArcanistConfigurationDrivenLintEngine'; } } if (!$engine_class) { throw new ArcanistNoEngineException( pht( "No lint engine is configured for this project. Create an '%s' ". "file, or configure an advanced engine with '%s' in '%s'.", '.arclint', 'lint.engine', '.arcconfig')); } $base_class = 'ArcanistLintEngine'; if (!class_exists($engine_class) || !is_subclass_of($engine_class, $base_class)) { throw new ArcanistUsageException( pht( 'Configured lint engine "%s" is not a subclass of "%s", but must be.', $engine_class, $base_class)); } $engine = newv($engine_class, array()) ->setWorkingCopy($working_copy) ->setConfigurationManager($config); return $engine; } /** * Build a new unit test engine for the current working copy. * * Optionally, you can pass an explicit engine class name to build an engine * of a particular class. Normally this is used to implement an `--engine` * flag from the CLI. * * @param string Optional explicit engine class name. * @return ArcanistUnitTestEngine Constructed engine. */ protected function newUnitTestEngine($engine_class = null) { $working_copy = $this->getWorkingCopy(); $config = $this->getConfigurationManager(); if (!$engine_class) { $engine_class = $config->getConfigFromAnySource('unit.engine'); } if (!$engine_class) { if (Filesystem::pathExists($working_copy->getProjectPath('.arcunit'))) { $engine_class = 'ArcanistConfigurationDrivenUnitTestEngine'; } } if (!$engine_class) { throw new ArcanistNoEngineException( pht( "No unit test engine is configured for this project. Create an ". "'%s' file, or configure an advanced engine with '%s' in '%s'.", '.arcunit', 'unit.engine', '.arcconfig')); } $base_class = 'ArcanistUnitTestEngine'; if (!class_exists($engine_class) || !is_subclass_of($engine_class, $base_class)) { throw new ArcanistUsageException( pht( 'Configured unit test engine "%s" is not a subclass of "%s", '. 'but must be.', $engine_class, $base_class)); } $engine = newv($engine_class, array()) ->setWorkingCopy($working_copy) ->setConfigurationManager($config); return $engine; } protected function openURIsInBrowser(array $uris) { $browser = $this->getBrowserCommand(); foreach ($uris as $uri) { $err = phutil_passthru('%s %s', $browser, $uri); if ($err) { throw new ArcanistUsageException( pht( "Failed to open '%s' in browser ('%s'). ". "Check your 'browser' config option.", $uri, $browser)); } } } private function getBrowserCommand() { $config = $this->getConfigFromAnySource('browser'); if ($config) { return $config; } if (phutil_is_windows()) { return 'start'; } $candidates = array('sensible-browser', 'xdg-open', 'open'); // NOTE: The "open" command works well on OS X, but on many Linuxes "open" // exists and is not a browser. For now, we're just looking for other // commands first, but we might want to be smarter about selecting "open" // only on OS X. foreach ($candidates as $cmd) { if (Filesystem::binaryExists($cmd)) { return $cmd; } } throw new ArcanistUsageException( pht( "Unable to find a browser command to run. Set '%s' in your ". "Arcanist config to specify a command to use.", 'browser')); } /** * Ask Phabricator to update the current repository as soon as possible. * * Calling this method after pushing commits allows Phabricator to discover * the commits more quickly, so the system overall is more responsive. * * @return void */ protected function askForRepositoryUpdate() { // If we know which repository we're in, try to tell Phabricator that we // pushed commits to it so it can update. This hint can help pull updates // more quickly, especially in rarely-used repositories. if ($this->getRepositoryPHID()) { try { $this->getConduit()->callMethodSynchronous( 'diffusion.looksoon', array( 'repositories' => array($this->getRepositoryPHID()), )); } catch (ConduitClientException $ex) { // If we hit an exception, just ignore it. Likely, we are running // against a Phabricator which is too old to support this method. // Since this hint is purely advisory, it doesn't matter if it has // no effect. } } } protected function getModernLintDictionary(array $map) { $map = $this->getModernCommonDictionary($map); return $map; } protected function getModernUnitDictionary(array $map) { $map = $this->getModernCommonDictionary($map); $details = idx($map, 'userData'); if (strlen($details)) { $map['details'] = (string)$details; } unset($map['userData']); return $map; } private function getModernCommonDictionary(array $map) { foreach ($map as $key => $value) { if ($value === null) { unset($map[$key]); } } return $map; } final public function setConduitEngine( ArcanistConduitEngine $conduit_engine) { $this->conduitEngine = $conduit_engine; return $this; } final public function getConduitEngine() { return $this->conduitEngine; } final protected function newWorkingCopyStateRef() { $ref = new ArcanistWorkingCopyStateRef(); $working_copy = $this->getWorkingCopy(); $ref->setRootDirectory($working_copy->getProjectRoot()); return $ref; } final protected function newRefQuery(array $refs) { assert_instances_of($refs, 'ArcanistRef'); $query = id(new ArcanistRefQuery()) ->setConduitEngine($this->getConduitEngine()) ->setRefs($refs); if ($this->hasRepositoryAPI()) { $query->setRepositoryAPI($this->getRepositoryAPI()); } $repository_ref = $this->getRepositoryRef(); if ($repository_ref) { $query->setRepositoryRef($repository_ref); } $working_copy = $this->getConfigurationManager()->getWorkingCopyIdentity(); if ($working_copy) { $working_ref = $this->newWorkingCopyStateRef(); $query->setWorkingCopyRef($working_ref); } return $query; } final public function getRepositoryRef() { if (!$this->getConfigurationManager()->getWorkingCopyIdentity()) { return null; } if (!$this->repositoryAPI) { return null; } if (!$this->repositoryRef) { $ref = id(new ArcanistRepositoryRef()) ->setPHID($this->getRepositoryPHID()) ->setBrowseURI($this->getRepositoryURI()); $this->repositoryRef = $ref; } return $this->repositoryRef; } final public function getToolsetKey() { return $this->getToolset()->getToolsetKey(); } final public function getConfig($key) { return $this->getConfigurationSourceList()->getConfig($key); } } diff --git a/scripts/breakout.py b/support/arcanoid/arcanoid.py similarity index 94% rename from scripts/breakout.py rename to support/arcanoid/arcanoid.py index 0b473b84..55d191a7 100755 --- a/scripts/breakout.py +++ b/support/arcanoid/arcanoid.py @@ -1,228 +1,230 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import sys import time import select import curses from curses import wrapper entities = [] grid = [] class Wall: def collide(self, ball): return False class Block: killed = 0 total = 0 def __init__(self, x, y, w, h, c): - self.x = x - self.y = y - self.w = w - self.h = h + self.x = int(round(x)) + self.y = int(round(y)) + self.w = int(round(w)) + self.h = int(round(h)) self.fmt = curses.A_BOLD | curses.color_pair(c) self.alive = True for i in range(self.x, self.x + self.w): for j in range(self.y, self.y + self.h): grid[j + 1][i + 1] = self Block.total += 1 def collide(self, ball): self.alive = False for i in range(self.x, self.x + self.w): for j in range(self.y, self.y + self.h): grid[j + 1][i + 1] = None Block.killed += 1 return False def tick(self, win): if self.alive: for i in range(self.x, self.x + self.w): for j in range(self.y, self.y + self.h): win.addch(j, i, curses.ACS_BLOCK, self.fmt) return self.alive class Ball: alive = False killed = 0 def __init__(self, x, y, vx, vy): - self.x = x - self.y = y + self.x = int(round(x)) + self.y = int(round(y)) self.vx = vx self.vy = vy Ball.alive = True def collide(self, ball): return True def encounter(self, dx, dy): + dx = int(round(dx)) + dy = int(round(dy)) ent = grid[self.y + dy + 1][self.x + dx + 1] if ent and not ent.collide(self): self.vx -= 2 * dx self.vy -= 2 * dy return ent def tick(self, win): while self.y < ship.y: if self.encounter((self.vx + self.vy) / 2, (self.vy - self.vx) / 2): continue if self.encounter((self.vx - self.vy) / 2, (self.vy + self.vx) / 2): continue if self.encounter(self.vx, self.vy): continue break self.x += self.vx self.y += self.vy try: win.addch(self.y, self.x, 'O') except curses.error: Ball.alive = False Ball.killed += 1 return Ball.alive class Ship: def __init__(self, x, y): - self.x = x - self.y = y + self.x = int(round(x)) + self.y = int(round(y)) self.hw = 10 self.v = 4 self.last = 1 self.update() def update(self): grid[self.y + 1] = ( [ None ] * (self.x - self.hw + 1) + [ self ] * (self.hw * 2 + 1) + [ None ] * (width - self.x - self.hw) ) def collide(self, ball): ball.vy = -1 if ball.x > self.x + self.hw / 2: ball.vx = 1 elif ball.x < self.x - self.hw / 2: ball.vx = -1 return True def shift(self, i): self.last = i self.x += self.v * i if self.x - self.hw < 0: self.x = self.hw elif self.x + self.hw >= width: self.x = width - self.hw - 1 self.update() def spawn(self): if not Ball.alive: entities.append(Ball(self.x, self.y - 1, self.last, -1)) def tick(self, win): if not Ball.alive: win.addch(self.y - 1, self.x, 'O') win.addch(self.y, self.x - self.hw, curses.ACS_LTEE) for i in range(-self.hw + 1, self.hw): win.addch(curses.ACS_HLINE) win.addch(curses.ACS_RTEE) return True class PowerOverwhelmingException(Exception): pass def main(stdscr): global height, width, ship for i in range(1, 8): curses.init_pair(i, i, 0) curses.curs_set(0) curses.raw() height, width = stdscr.getmaxyx() if height < 15 or width < 32: raise PowerOverwhelmingException( 'Your computer is not powerful enough to run "arc anoid". ' 'It must support at least 32 columns and 15 rows of next-gen ' 'full-color 3D graphics.') status = curses.newwin(1, width, 0, 0) height -= 1 game = curses.newwin(height, width, 1, 0) game.nodelay(1) game.keypad(1) grid[:] = [ [ None for x in range(width + 2) ] for y in range(height + 2) ] wall = Wall() for x in range(width + 2): grid[0][x] = wall for y in range(height + 2): grid[y][0] = grid[y][-1] = wall ship = Ship(width / 2, height - 5) entities.append(ship) colors = [ 1, 3, 2, 6, 4, 5 ] h = height / 10 - for x in range(1, width / 7 - 1): + for x in range(1, int(width / 7) - 1): for y in range(1, 7): entities.append(Block(x * 7, y * h + x / 2 % 2, 7, h, colors[y - 1])) while True: while select.select([ sys.stdin ], [], [], 0)[0]: key = game.getch() if key == curses.KEY_LEFT or key == ord('a') or key == ord('A'): ship.shift(-1) elif key == curses.KEY_RIGHT or key == ord('d') or key == ord('D'): ship.shift(1) elif key == ord(' '): ship.spawn() elif key == 0x1b or key == 3 or key == ord('q') or key == ord('Q'): return game.resize(height, width) game.erase() entities[:] = [ ent for ent in entities if ent.tick(game) ] status.hline(0, 0, curses.ACS_HLINE, width) status.addch(0, 2, curses.ACS_RTEE) status.addstr(' SCORE: ', curses.A_BOLD | curses.color_pair(4)) status.addstr('%s/%s ' % (Block.killed, Block.total), curses.A_BOLD) status.addch(curses.ACS_VLINE) status.addstr(' DEATHS: ', curses.A_BOLD | curses.color_pair(4)) # See T8693. At the minimum display size, we only have room to render # two characters for the death count, so just display "99" if the # player has more than 99 deaths. display_deaths = Ball.killed if (display_deaths > 99): display_deaths = 99 status.addstr('%s ' % display_deaths, curses.A_BOLD) status.addch(curses.ACS_LTEE) if Block.killed == Block.total: message = ' A WINNER IS YOU!! ' i = int(time.time() / 0.8) for x in range(width): for y in range(6): game.addch(height / 2 + y - 3 + (x / 8 + i) % 2, x, curses.ACS_BLOCK, curses.A_BOLD | curses.color_pair(colors[y])) game.addstr(height / 2, (width - len(message)) / 2, message, curses.A_BOLD | curses.color_pair(7)) game.refresh() status.refresh() time.sleep(0.05) try: curses.wrapper(main) print ('You destroyed %s blocks out of %s with %s deaths.' % (Block.killed, Block.total, Ball.killed)) except PowerOverwhelmingException as e: print (e)