/* * Copyright 2015-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.command; import com.facebook.buck.rules.BuildResult; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleSuccessType; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.util.Ansi; import com.facebook.buck.util.Console; import com.facebook.buck.util.ObjectMappers; import com.fasterxml.jackson.databind.SerializationFeature; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; @VisibleForTesting public class BuildReport { private final BuildExecutionResult buildExecutionResult; private final SourcePathResolver pathResolver; /** * @param buildExecutionResult the build result to generate the report for. * @param pathResolver source path resolver which can be used for the result. */ public BuildReport(BuildExecutionResult buildExecutionResult, SourcePathResolver pathResolver) { this.buildExecutionResult = buildExecutionResult; this.pathResolver = pathResolver; } public String generateForConsole(Console console) { Ansi ansi = console.getAnsi(); Map<BuildRule, Optional<BuildResult>> ruleToResult = buildExecutionResult.getResults(); StringBuilder report = new StringBuilder(); for (Map.Entry<BuildRule, Optional<BuildResult>> entry : ruleToResult.entrySet()) { BuildRule rule = entry.getKey(); Optional<BuildRuleSuccessType> success = Optional.empty(); Optional<BuildResult> result = entry.getValue(); if (result.isPresent()) { success = Optional.ofNullable(result.get().getSuccess()); } String successIndicator; String successType; SourcePath outputFile; if (success.isPresent()) { successIndicator = ansi.asHighlightedSuccessText("OK "); successType = success.get().name(); outputFile = rule.getSourcePathToOutput(); } else { successIndicator = ansi.asHighlightedFailureText("FAIL"); successType = null; outputFile = null; } report.append( String.format( "%s %s%s%s\n", successIndicator, rule.getBuildTarget(), successType != null ? " " + successType : "", outputFile != null ? " " + pathResolver.getRelativePath(outputFile) : "")); } if (!buildExecutionResult.getFailures().isEmpty() && console.getVerbosity().shouldPrintCommand()) { report.append("\n ** Summary of failures encountered during the build **\n"); for (BuildResult failureResult : buildExecutionResult.getFailures()) { Throwable failure = Preconditions.checkNotNull(failureResult.getFailure()); report.append( String.format( "Rule %s FAILED because %s.\n", failureResult.getRule().getFullyQualifiedName(), failure.getMessage())); } } return report.toString(); } public String generateJsonBuildReport() throws IOException { Map<BuildRule, Optional<BuildResult>> ruleToResult = buildExecutionResult.getResults(); LinkedHashMap<String, Object> results = Maps.newLinkedHashMap(); LinkedHashMap<String, Object> failures = Maps.newLinkedHashMap(); boolean isOverallSuccess = true; for (Map.Entry<BuildRule, Optional<BuildResult>> entry : ruleToResult.entrySet()) { BuildRule rule = entry.getKey(); Optional<BuildRuleSuccessType> success = Optional.empty(); Optional<BuildResult> result = entry.getValue(); if (result.isPresent()) { success = Optional.ofNullable(result.get().getSuccess()); } Map<String, Object> value = Maps.newLinkedHashMap(); boolean isSuccess = success.isPresent(); value.put("success", isSuccess); if (!isSuccess) { isOverallSuccess = false; } if (isSuccess) { value.put("type", success.get().name()); SourcePath outputFile = rule.getSourcePathToOutput(); value.put( "output", outputFile != null ? pathResolver.getRelativePath(outputFile).toString() : null); } results.put(rule.getFullyQualifiedName(), value); } for (BuildResult failureResult : buildExecutionResult.getFailures()) { Throwable failure = Preconditions.checkNotNull(failureResult.getFailure()); failures.put(failureResult.getRule().getFullyQualifiedName(), failure.getMessage()); } Map<String, Object> report = Maps.newLinkedHashMap(); report.put("success", isOverallSuccess); report.put("results", results); report.put("failures", failures); return ObjectMappers.WRITER .withFeatures(SerializationFeature.INDENT_OUTPUT) .writeValueAsString(report); } }