/*
* 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.ExecutableFinder;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.io.Watchman;
import com.facebook.buck.rules.Cell;
import com.facebook.buck.util.ProcessExecutor;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
/** Gets watchman diagnostics using the watchman-diag command. */
public class WatchmanDiagReportCollector {
private final ProjectFilesystem projectFilesystem;
private final String watchmanDiagCommand;
private final ProcessExecutor processExecutor;
public WatchmanDiagReportCollector(
ProjectFilesystem projectFilesystem,
String watchmanDiagCommand,
ProcessExecutor processExecutor) {
this.projectFilesystem = projectFilesystem;
this.watchmanDiagCommand = watchmanDiagCommand;
this.processExecutor = processExecutor;
}
public Path run()
throws IOException, InterruptedException, ExtraInfoCollector.ExtraInfoExecutionException {
Path watchmanDiagReport =
projectFilesystem.getBuckPaths().getLogDir().resolve("watchman-diag-report");
projectFilesystem.deleteFileAtPathIfExists(watchmanDiagReport);
String extraInfoCommandOutput =
DefaultExtraInfoCollector.runCommandAndGetStdout(
ImmutableList.of(watchmanDiagCommand), projectFilesystem, processExecutor);
projectFilesystem.writeContentsToPath(extraInfoCommandOutput, watchmanDiagReport);
return watchmanDiagReport;
}
public static Optional<WatchmanDiagReportCollector> newInstanceIfWatchmanUsed(
Cell rootCell,
ProjectFilesystem projectFilesystem,
ProcessExecutor processExecutor,
ExecutableFinder executableFinder,
ImmutableMap<String, String> environment) {
// We only want to gather watchman diagnostics if any of the cells are actually using Watchman.
ImmutableCollection<Path> allCellRoots = rootCell.getCellPathResolver().getCellPaths().values();
boolean watchmanEverUsed = rootCell.getWatchman() != Watchman.NULL_WATCHMAN;
for (Path cellRoot : allCellRoots) {
if (watchmanEverUsed) {
break;
}
watchmanEverUsed =
watchmanEverUsed || rootCell.getCell(cellRoot).getWatchman() != Watchman.NULL_WATCHMAN;
}
if (!watchmanEverUsed) {
return Optional.empty();
}
Optional<Path> optionalExecutable =
executableFinder.getOptionalExecutable(Paths.get("watchman-diag"), environment);
if (!optionalExecutable.isPresent()) {
return Optional.empty();
}
return Optional.of(
new WatchmanDiagReportCollector(
projectFilesystem,
optionalExecutable.get().toAbsolutePath().toString(),
processExecutor));
}
}