Java tutorial
/* * Copyright 2016-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.rage; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.model.Pair; import com.facebook.buck.util.Console; import com.facebook.buck.util.environment.BuildEnvironmentDescription; import com.facebook.buck.util.unit.SizeUnit; import com.facebook.buck.util.versioncontrol.VersionControlCommandFailedException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Ordering; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.OptionalInt; /** * Responsible for gathering logs and other interesting information from buck, driven by user * interaction. */ public class InteractiveReport extends AbstractReport { private final BuildLogHelper buildLogHelper; private final Optional<VcsInfoCollector> vcsInfoCollector; private final Console console; private final UserInput input; public InteractiveReport(DefectReporter defectReporter, ProjectFilesystem filesystem, ObjectMapper objectMapper, Console console, InputStream stdin, BuildEnvironmentDescription buildEnvironmentDescription, Optional<VcsInfoCollector> vcsInfoCollector, RageConfig rageConfig, ExtraInfoCollector extraInfoCollector, Optional<WatchmanDiagReportCollector> watchmanDiagReportCollector) { super(filesystem, defectReporter, buildEnvironmentDescription, console, rageConfig, extraInfoCollector, watchmanDiagReportCollector); this.buildLogHelper = new BuildLogHelper(filesystem, objectMapper); this.vcsInfoCollector = vcsInfoCollector; this.console = console; this.input = new UserInput(console.getStdOut(), new BufferedReader(new InputStreamReader(stdin))); } @Override public ImmutableSet<BuildLogEntry> promptForBuildSelection() throws IOException { ImmutableList<BuildLogEntry> buildLogs = buildLogHelper.getBuildLogs(); // Commands with unknown args and buck rage should be excluded. List<BuildLogEntry> interestingBuildLogs = new ArrayList<>(); buildLogs.forEach(entry -> { if (entry.getCommandArgs().isPresent() && !entry.getCommandArgs().get().matches("rage|doctor")) { interestingBuildLogs.add(entry); } }); if (interestingBuildLogs.isEmpty()) { return ImmutableSet.of(); } // Sort the interesting builds based on time, reverse order so the most recent is first. Collections.sort(interestingBuildLogs, Ordering.natural().onResultOf(BuildLogEntry::getLastModifiedTime).reverse()); return input.selectRange("Which buck invocations would you like to report?", interestingBuildLogs, input1 -> { Pair<Double, SizeUnit> humanReadableSize = SizeUnit.getHumanReadableSize(input1.getSize(), SizeUnit.BYTES); return String.format("\t%s\tbuck [%s] %s (%.2f %s)", input1.getLastModifiedTime(), input1.getCommandArgs().orElse("unknown command"), prettyPrintExitCode(input1.getExitCode()), humanReadableSize.getFirst(), humanReadableSize.getSecond().getAbbreviation()); }); } @Override protected Optional<FileChangesIgnoredReport> getFileChangesIgnoredReport() throws IOException, InterruptedException { return runWatchmanDiagReportCollector(input); } @Override protected Optional<SourceControlInfo> getSourceControlInfo() throws IOException, InterruptedException { if (!vcsInfoCollector.isPresent() || !input.confirm("Would you like to attach source control information (this includes " + "information about commits and changed files)?")) { return Optional.empty(); } try { return Optional.of(vcsInfoCollector.get().gatherScmInformation()); } catch (VersionControlCommandFailedException e) { console.printErrorText("Failed to get source control information: %s, proceeding regardless.", e); } return Optional.empty(); } private String prettyPrintExitCode(OptionalInt exitCode) { String result = "Exit code: " + (exitCode.isPresent() ? Integer.toString(exitCode.getAsInt()) : "Unknown"); if (exitCode.isPresent() && console.getAnsi().isAnsiTerminal()) { if (exitCode.getAsInt() == 0) { return console.getAnsi().asGreenText(result); } else { return console.getAnsi().asRedText(result); } } return result; } @Override protected Optional<UserReport> getUserReport() throws IOException { UserReport.Builder userReport = UserReport.builder(); userReport.setUserIssueDescription(input.ask("Please describe the problem you wish to report:")); return Optional.of(userReport.build()); } }