Search in sources :

Example 1 with QueryOptions

use of com.google.devtools.build.lib.query2.output.QueryOptions in project bazel by bazelbuild.

the class XmlOutputFormatter method createPostFactoStreamCallback.

@Override
public OutputFormatterCallback<Target> createPostFactoStreamCallback(final OutputStream out, final QueryOptions options) {
    return new OutputFormatterCallback<Target>() {

        private Document doc;

        private Element queryElem;

        @Override
        public void start() {
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                doc = factory.newDocumentBuilder().newDocument();
            } catch (ParserConfigurationException e) {
                // This shouldn't be possible: all the configuration is hard-coded.
                throw new IllegalStateException("XML output failed", e);
            }
            doc.setXmlVersion("1.1");
            queryElem = doc.createElement("query");
            queryElem.setAttribute("version", "2");
            doc.appendChild(queryElem);
        }

        @Override
        public void processOutput(Iterable<Target> partialResult) throws IOException, InterruptedException {
            for (Target target : partialResult) {
                queryElem.appendChild(createTargetElement(doc, target));
            }
        }

        @Override
        public void close(boolean failFast) throws IOException {
            if (!failFast) {
                try {
                    Transformer transformer = TransformerFactory.newInstance().newTransformer();
                    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                    transformer.transform(new DOMSource(doc), new StreamResult(out));
                } catch (TransformerFactoryConfigurationError | TransformerException e) {
                    // This shouldn't be possible: all the configuration is hard-coded.
                    throw new IllegalStateException("XML output failed", e);
                }
            }
        }
    };
}
Also used : TransformerFactoryConfigurationError(javax.xml.transform.TransformerFactoryConfigurationError) DOMSource(javax.xml.transform.dom.DOMSource) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) Transformer(javax.xml.transform.Transformer) StreamResult(javax.xml.transform.stream.StreamResult) Element(org.w3c.dom.Element) SynchronizedDelegatingOutputFormatterCallback(com.google.devtools.build.lib.query2.engine.SynchronizedDelegatingOutputFormatterCallback) ThreadSafeOutputFormatterCallback(com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback) OutputFormatterCallback(com.google.devtools.build.lib.query2.engine.OutputFormatterCallback) Document(org.w3c.dom.Document) FakeSubincludeTarget(com.google.devtools.build.lib.query2.FakeSubincludeTarget) Target(com.google.devtools.build.lib.packages.Target) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) TransformerException(javax.xml.transform.TransformerException)

Example 2 with QueryOptions

use of com.google.devtools.build.lib.query2.output.QueryOptions in project bazel by bazelbuild.

the class QueryCommand method exec.

/**
   * Exit codes:
   *   0   on successful evaluation.
   *   1   if query evaluation did not complete.
   *   2   if query parsing failed.
   *   3   if errors were reported but evaluation produced a partial result
   *        (only when --keep_going is in effect.)
   */
@Override
public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
    BlazeRuntime runtime = env.getRuntime();
    QueryOptions queryOptions = options.getOptions(QueryOptions.class);
    try {
        env.setupPackageCache(options, runtime.getDefaultsPackageContent());
    } catch (InterruptedException e) {
        env.getReporter().handle(Event.error("query interrupted"));
        return ExitCode.INTERRUPTED;
    } catch (AbruptExitException e) {
        env.getReporter().handle(Event.error(null, "Unknown error: " + e.getMessage()));
        return e.getExitCode();
    }
    String query;
    if (!options.getResidue().isEmpty()) {
        if (!queryOptions.queryFile.isEmpty()) {
            env.getReporter().handle(Event.error("Command-line query and --query_file cannot both be specified"));
            return ExitCode.COMMAND_LINE_ERROR;
        }
        query = Joiner.on(' ').join(options.getResidue());
    } else if (!queryOptions.queryFile.isEmpty()) {
        // Works for absolute or relative query file.
        Path residuePath = env.getWorkingDirectory().getRelative(queryOptions.queryFile);
        try {
            query = new String(FileSystemUtils.readContent(residuePath), StandardCharsets.UTF_8);
        } catch (IOException e) {
            env.getReporter().handle(Event.error("I/O error reading from " + residuePath.getPathString()));
            return ExitCode.COMMAND_LINE_ERROR;
        }
    } else {
        env.getReporter().handle(Event.error(String.format("missing query expression. Type '%s help query' for syntax and help", runtime.getProductName())));
        return ExitCode.COMMAND_LINE_ERROR;
    }
    Iterable<OutputFormatter> formatters = runtime.getQueryOutputFormatters();
    OutputFormatter formatter = OutputFormatter.getFormatter(formatters, queryOptions.outputFormat);
    if (formatter == null) {
        env.getReporter().handle(Event.error(String.format("Invalid output format '%s'. Valid values are: %s", queryOptions.outputFormat, OutputFormatter.formatterNames(formatters))));
        return ExitCode.COMMAND_LINE_ERROR;
    }
    Set<Setting> settings = queryOptions.toSettings();
    boolean streamResults = QueryOutputUtils.shouldStreamResults(queryOptions, formatter);
    QueryEvalResult result;
    AbstractBlazeQueryEnvironment<Target> queryEnv = newQueryEnvironment(env, queryOptions.keepGoing, !streamResults, queryOptions.universeScope, queryOptions.loadingPhaseThreads, settings);
    // 1. Parse and transform query:
    QueryExpression expr;
    try {
        expr = QueryExpression.parse(query, queryEnv);
    } catch (QueryException e) {
        env.getReporter().handle(Event.error(null, "Error while parsing '" + query + "': " + e.getMessage()));
        return ExitCode.COMMAND_LINE_ERROR;
    }
    expr = queryEnv.transformParsedQuery(expr);
    OutputStream out = env.getReporter().getOutErr().getOutputStream();
    ThreadSafeOutputFormatterCallback<Target> callback;
    if (streamResults) {
        disableAnsiCharactersFiltering(env);
        // 2. Evaluate expression:
        StreamedFormatter streamedFormatter = ((StreamedFormatter) formatter);
        streamedFormatter.setOptions(queryOptions, queryOptions.aspectDeps.createResolver(env.getPackageManager(), env.getReporter()));
        callback = streamedFormatter.createStreamCallback(out, queryOptions, queryEnv);
    } else {
        callback = QueryUtil.newOrderedAggregateAllOutputFormatterCallback();
    }
    boolean catastrophe = true;
    try {
        result = queryEnv.evaluateQuery(expr, callback);
        catastrophe = false;
    } catch (QueryException e) {
        catastrophe = false;
        // Keep consistent with reportBuildFileError()
        env.getReporter().handle(Event.error(e.getMessage() == null ? e.toString() : e.getMessage()));
        return ExitCode.ANALYSIS_FAILURE;
    } catch (InterruptedException e) {
        catastrophe = false;
        IOException ioException = callback.getIoException();
        if (ioException == null || ioException instanceof ClosedByInterruptException) {
            env.getReporter().handle(Event.error("query interrupted"));
            return ExitCode.INTERRUPTED;
        } else {
            env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
            return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
        }
    } catch (IOException e) {
        catastrophe = false;
        env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
        return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
    } finally {
        if (!catastrophe) {
            try {
                out.flush();
            } catch (IOException e) {
                env.getReporter().handle(Event.error("Failed to flush query results: " + e.getMessage()));
                return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
            }
        }
    }
    env.getEventBus().post(new NoBuildEvent());
    if (!streamResults) {
        disableAnsiCharactersFiltering(env);
        // 3. Output results:
        try {
            Set<Target> targets = ((AggregateAllOutputFormatterCallback<Target>) callback).getResult();
            QueryOutputUtils.output(queryOptions, result, targets, formatter, env.getReporter().getOutErr().getOutputStream(), queryOptions.aspectDeps.createResolver(env.getPackageManager(), env.getReporter()));
        } catch (ClosedByInterruptException | InterruptedException e) {
            env.getReporter().handle(Event.error("query interrupted"));
            return ExitCode.INTERRUPTED;
        } catch (IOException e) {
            env.getReporter().handle(Event.error("I/O error: " + e.getMessage()));
            return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
        } finally {
            try {
                out.flush();
            } catch (IOException e) {
                env.getReporter().handle(Event.error("Failed to flush query results: " + e.getMessage()));
                return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
            }
        }
    }
    if (result.isEmpty()) {
        env.getReporter().handle(Event.info("Empty results"));
    }
    return result.getSuccess() ? ExitCode.SUCCESS : ExitCode.PARTIAL_ANALYSIS_FAILURE;
}
Also used : OutputStream(java.io.OutputStream) QueryEvalResult(com.google.devtools.build.lib.query2.engine.QueryEvalResult) StreamedFormatter(com.google.devtools.build.lib.query2.output.OutputFormatter.StreamedFormatter) AggregateAllOutputFormatterCallback(com.google.devtools.build.lib.query2.engine.QueryUtil.AggregateAllOutputFormatterCallback) QueryOptions(com.google.devtools.build.lib.query2.output.QueryOptions) OutputFormatter(com.google.devtools.build.lib.query2.output.OutputFormatter) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) Target(com.google.devtools.build.lib.packages.Target) QueryExpression(com.google.devtools.build.lib.query2.engine.QueryExpression) Path(com.google.devtools.build.lib.vfs.Path) Setting(com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting) NoBuildEvent(com.google.devtools.build.lib.analysis.NoBuildEvent) IOException(java.io.IOException) BlazeRuntime(com.google.devtools.build.lib.runtime.BlazeRuntime) QueryException(com.google.devtools.build.lib.query2.engine.QueryException) AbruptExitException(com.google.devtools.build.lib.util.AbruptExitException)

Example 3 with QueryOptions

use of com.google.devtools.build.lib.query2.output.QueryOptions in project bazel by bazelbuild.

the class QueryOutputUtils method output.

public static void output(QueryOptions queryOptions, QueryEvalResult result, Set<Target> targetsResult, OutputFormatter formatter, OutputStream outputStream, AspectResolver aspectResolver) throws IOException, InterruptedException {
    /*
     * This is not really streaming, but we are using the streaming interface for writing into the
     * output everything in one batch. This happens when the QueryEnvironment does not
     * support streaming but we don't care about ordered results.
     */
    boolean orderedResults = !shouldStreamResults(queryOptions, formatter);
    if (orderedResults) {
        formatter.output(queryOptions, ((DigraphQueryEvalResult<Target>) result).getGraph().extractSubgraph(targetsResult), outputStream, aspectResolver);
    } else {
        StreamedFormatter streamedFormatter = (StreamedFormatter) formatter;
        streamedFormatter.setOptions(queryOptions, aspectResolver);
        OutputFormatterCallback.processAllTargets(streamedFormatter.createPostFactoStreamCallback(outputStream, queryOptions), targetsResult);
    }
}
Also used : StreamedFormatter(com.google.devtools.build.lib.query2.output.OutputFormatter.StreamedFormatter) DigraphQueryEvalResult(com.google.devtools.build.lib.query2.engine.DigraphQueryEvalResult)

Example 4 with QueryOptions

use of com.google.devtools.build.lib.query2.output.QueryOptions in project bazel by bazelbuild.

the class GenQuery method create.

@Override
@Nullable
public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException {
    Artifact outputArtifact = ruleContext.createOutputArtifact();
    // The query string
    final String query = ruleContext.attributes().get("expression", Type.STRING);
    OptionsParser optionsParser = OptionsParser.newOptionsParser(QueryOptions.class);
    optionsParser.setAllowResidue(false);
    try {
        optionsParser.parse(ruleContext.attributes().get("opts", Type.STRING_LIST));
    } catch (OptionsParsingException e) {
        ruleContext.attributeError("opts", "error while parsing query options: " + e.getMessage());
        return null;
    }
    // Parsed query options
    QueryOptions queryOptions = optionsParser.getOptions(QueryOptions.class);
    if (queryOptions.keepGoing) {
        ruleContext.attributeError("opts", "option --keep_going is not allowed");
        return null;
    }
    if (!queryOptions.universeScope.isEmpty()) {
        ruleContext.attributeError("opts", "option --universe_scope is not allowed");
        return null;
    }
    if (optionsParser.containsExplicitOption("order_results")) {
        ruleContext.attributeError("opts", "option --order_results is not allowed");
        return null;
    }
    if (optionsParser.containsExplicitOption("noorder_results")) {
        ruleContext.attributeError("opts", "option --noorder_results is not allowed");
        return null;
    }
    if (optionsParser.containsExplicitOption("order_output")) {
        ruleContext.attributeError("opts", "option --order_output is not allowed");
        return null;
    }
    // Force results to be deterministic.
    queryOptions.orderOutput = OrderOutput.FULL;
    // force relative_locations to true so it has a deterministic output across machines.
    queryOptions.relativeLocations = true;
    final byte[] result = executeQuery(ruleContext, queryOptions, getScope(ruleContext), query);
    if (result == null || ruleContext.hasErrors()) {
        return null;
    }
    ruleContext.registerAction(new QueryResultAction(ruleContext.getActionOwner(), outputArtifact, result));
    NestedSet<Artifact> filesToBuild = NestedSetBuilder.create(Order.STABLE_ORDER, outputArtifact);
    return new RuleConfiguredTargetBuilder(ruleContext).setFilesToBuild(filesToBuild).add(RunfilesProvider.class, RunfilesProvider.simple(new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).addTransitiveArtifacts(filesToBuild).build())).build();
}
Also used : Runfiles(com.google.devtools.build.lib.analysis.Runfiles) RuleConfiguredTargetBuilder(com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder) OptionsParsingException(com.google.devtools.common.options.OptionsParsingException) OptionsParser(com.google.devtools.common.options.OptionsParser) QueryOptions(com.google.devtools.build.lib.query2.output.QueryOptions) RunfilesProvider(com.google.devtools.build.lib.analysis.RunfilesProvider) Artifact(com.google.devtools.build.lib.actions.Artifact) Nullable(javax.annotation.Nullable)

Example 5 with QueryOptions

use of com.google.devtools.build.lib.query2.output.QueryOptions in project bazel by bazelbuild.

the class GenQuery method doQuery.

@SuppressWarnings("unchecked")
@Nullable
private byte[] doQuery(QueryOptions queryOptions, PackageProvider packageProvider, Predicate<Label> labelFilter, TargetPatternEvaluator evaluator, String query, RuleContext ruleContext) throws InterruptedException {
    DigraphQueryEvalResult<Target> queryResult;
    OutputFormatter formatter;
    AggregateAllOutputFormatterCallback<Target> targets = QueryUtil.newOrderedAggregateAllOutputFormatterCallback();
    try {
        Set<Setting> settings = queryOptions.toSettings();
        // Turns out, if we have two targets with a cycle of length 2 were one of
        // the edges is of type NODEP_LABEL type, the targets both show up in
        // each other's result for deps(X) when the query is executed using
        // 'blaze query'. This obviously does not fly when doing the query as a
        // part of the build, thus, there is a slight discrepancy between the
        // behavior of the query engine in these two use cases.
        settings.add(Setting.NO_NODEP_DEPS);
        ImmutableList<OutputFormatter> outputFormatters = QUERY_OUTPUT_FORMATTERS.get(ruleContext.getAnalysisEnvironment().getSkyframeEnv());
        // This is a precomputed value so it should have been injected by the rules module by the
        // time we get there.
        formatter = OutputFormatter.getFormatter(Preconditions.checkNotNull(outputFormatters), queryOptions.outputFormat);
        // All the packages are already loaded at this point, so there is no need
        // to start up many threads. 4 are started up to make good use of multiple
        // cores.
        BlazeQueryEnvironment queryEnvironment = (BlazeQueryEnvironment) QUERY_ENVIRONMENT_FACTORY.create(/*transitivePackageLoader=*/
        null, /*graph=*/
        null, packageProvider, evaluator, /*keepGoing=*/
        false, ruleContext.attributes().get("strict", Type.BOOLEAN), /*orderedResults=*/
        !QueryOutputUtils.shouldStreamResults(queryOptions, formatter), /*universeScope=*/
        ImmutableList.<String>of(), /*loadingPhaseThreads=*/
        4, labelFilter, getEventHandler(ruleContext), settings, ImmutableList.<QueryFunction>of(), /*packagePath=*/
        null, /*blockUniverseEvaluationErrors=*/
        false);
        queryResult = (DigraphQueryEvalResult<Target>) queryEnvironment.evaluateQuery(query, targets);
    } catch (SkyframeRestartQueryException e) {
        // inconsistent from run to run, and make detecting legitimate errors more difficult.
        return null;
    } catch (QueryException e) {
        ruleContext.ruleError("query failed: " + e.getMessage());
        return null;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
        QueryOutputUtils.output(queryOptions, queryResult, targets.getResult(), formatter, outputStream, queryOptions.aspectDeps.createResolver(packageProvider, getEventHandler(ruleContext)));
    } catch (ClosedByInterruptException e) {
        throw new InterruptedException(e.getMessage());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return outputStream.toByteArray();
}
Also used : Setting(com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) OutputFormatter(com.google.devtools.build.lib.query2.output.OutputFormatter) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) Target(com.google.devtools.build.lib.packages.Target) QueryException(com.google.devtools.build.lib.query2.engine.QueryException) SkyframeRestartQueryException(com.google.devtools.build.lib.query2.engine.SkyframeRestartQueryException) BlazeQueryEnvironment(com.google.devtools.build.lib.query2.BlazeQueryEnvironment) QueryFunction(com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction) SkyframeRestartQueryException(com.google.devtools.build.lib.query2.engine.SkyframeRestartQueryException) Nullable(javax.annotation.Nullable)

Aggregations

Target (com.google.devtools.build.lib.packages.Target)3 Setting (com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting)2 QueryException (com.google.devtools.build.lib.query2.engine.QueryException)2 OutputFormatter (com.google.devtools.build.lib.query2.output.OutputFormatter)2 StreamedFormatter (com.google.devtools.build.lib.query2.output.OutputFormatter.StreamedFormatter)2 QueryOptions (com.google.devtools.build.lib.query2.output.QueryOptions)2 IOException (java.io.IOException)2 ClosedByInterruptException (java.nio.channels.ClosedByInterruptException)2 Nullable (javax.annotation.Nullable)2 Artifact (com.google.devtools.build.lib.actions.Artifact)1 ConfiguredTarget (com.google.devtools.build.lib.analysis.ConfiguredTarget)1 NoBuildEvent (com.google.devtools.build.lib.analysis.NoBuildEvent)1 RuleConfiguredTargetBuilder (com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder)1 Runfiles (com.google.devtools.build.lib.analysis.Runfiles)1 RunfilesProvider (com.google.devtools.build.lib.analysis.RunfilesProvider)1 BlazeQueryEnvironment (com.google.devtools.build.lib.query2.BlazeQueryEnvironment)1 FakeSubincludeTarget (com.google.devtools.build.lib.query2.FakeSubincludeTarget)1 DigraphQueryEvalResult (com.google.devtools.build.lib.query2.engine.DigraphQueryEvalResult)1 OutputFormatterCallback (com.google.devtools.build.lib.query2.engine.OutputFormatterCallback)1 QueryFunction (com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction)1