/* * 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.cli; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.RuleKey; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.rules.keys.DefaultRuleKeyFactory; import com.facebook.buck.rules.keys.RuleKeyCacheRecycler; import com.facebook.buck.rules.keys.RuleKeyFieldLoader; import com.facebook.buck.util.RichStream; import com.facebook.buck.util.cache.FileHashCache; import com.facebook.buck.util.cache.FileHashCacheVerificationResult; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.io.PrintStream; import java.util.Map; /** Verify the contents of our FileHashCache. */ public class VerifyCachesCommand extends AbstractCommand { private boolean verifyFileHashCache(PrintStream stdOut, FileHashCache cache) throws IOException { FileHashCacheVerificationResult result = cache.verify(); stdOut.println("Examined " + result.getCachesExamined() + " caches."); stdOut.println("Examined " + result.getFilesExamined() + " files."); if (result.getVerificationErrors().isEmpty()) { stdOut.println("No errors"); return true; } else { stdOut.println("Errors detected:"); for (String err : result.getVerificationErrors()) { stdOut.println(" " + err); } return false; } } private boolean verifyRuleKeyCache( PrintStream stdOut, int ruleKeySeed, FileHashCache fileHashCache, RuleKeyCacheRecycler<RuleKey> recycler) { ImmutableList<Map.Entry<BuildRule, RuleKey>> contents = recycler.getCachedBuildRules(); RuleKeyFieldLoader fieldLoader = new RuleKeyFieldLoader(ruleKeySeed); BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); contents.forEach(e -> resolver.addToIndex(e.getKey())); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); DefaultRuleKeyFactory defaultRuleKeyFactory = new DefaultRuleKeyFactory(fieldLoader, fileHashCache, pathResolver, ruleFinder); stdOut.println(String.format("Examining %d build rule keys.", contents.size())); ImmutableList<BuildRule> mismatches = RichStream.from(contents) .filter(entry -> !defaultRuleKeyFactory.build(entry.getKey()).equals(entry.getValue())) .map(Map.Entry::getKey) .toImmutableList(); if (mismatches.isEmpty()) { stdOut.println("No rule key cache errors found."); } else { stdOut.println("Found rule key cache errors:"); for (BuildRule rule : mismatches) { stdOut.println(String.format(" %s", rule)); } } return true; } @Override public int runWithoutHelp(CommandRunnerParams params) throws IOException, InterruptedException { boolean success = true; // Verify file hash caches. params.getConsole().getStdOut().println("Verifying file hash caches..."); success &= verifyFileHashCache(params.getConsole().getStdOut(), params.getFileHashCache()); // Verify rule key caches. params.getConsole().getStdOut().println("Verifying rule key caches..."); success &= params .getDefaultRuleKeyFactoryCacheRecycler() .map( recycler -> verifyRuleKeyCache( params.getConsole().getStdOut(), params.getBuckConfig().getKeySeed(), params.getFileHashCache(), recycler)) .orElse(true); return success ? 0 : 1; } @Override public boolean isReadOnly() { return true; } @Override public String getShortDescription() { return "Verify contents of internal Buck in-memory caches."; } }