From d47e1eb00d2eac4a3b864639ab972a53e60f4925 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Thu, 16 Jan 2020 23:10:52 +0100 Subject: restat: Accept list of outputs to restat (none means all) This will become handy when the generator only wants to restat the build.ninja entry in the log. See #1718. --- src/build_log.cc | 20 +++++++++++++++----- src/build_log.h | 2 +- src/build_log_test.cc | 9 ++++++++- src/ninja.cc | 20 +++++++++++++++++++- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/build_log.cc b/src/build_log.cc index e2a9344..98543b6 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -422,6 +422,7 @@ bool BuildLog::Recompact(const string& path, const BuildLogUser& user, bool BuildLog::Restat(const StringPiece path, const DiskInterface& disk_interface, + const int output_count, char** outputs, std::string* const err) { METRIC_RECORD(".ninja_log restat"); @@ -439,12 +440,21 @@ bool BuildLog::Restat(const StringPiece path, return false; } for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { - const TimeStamp mtime = disk_interface.Stat(i->second->output, err); - if (mtime == -1) { - fclose(f); - return false; + bool skip = output_count > 0; + for (int j = 0; j < output_count; ++j) { + if (i->second->output == outputs[j]) { + skip = false; + break; + } + } + if (!skip) { + const TimeStamp mtime = disk_interface.Stat(i->second->output, err); + if (mtime == -1) { + fclose(f); + return false; + } + i->second->mtime = mtime; } - i->second->mtime = mtime; if (!WriteEntry(f, *i->second)) { *err = strerror(errno); diff --git a/src/build_log.h b/src/build_log.h index ed59d79..ebe0530 100644 --- a/src/build_log.h +++ b/src/build_log.h @@ -85,7 +85,7 @@ struct BuildLog { /// Restat all outputs in the log bool Restat(StringPiece path, const DiskInterface& disk_interface, - std::string* err); + int output_count, char** outputs, std::string* err); typedef ExternalStringHashMap::Type Entries; const Entries& entries() const { return entries_; } diff --git a/src/build_log_test.cc b/src/build_log_test.cc index 48ece23..a8b1733 100644 --- a/src/build_log_test.cc +++ b/src/build_log_test.cc @@ -252,7 +252,14 @@ TEST_F(BuildLogTest, Restat) { ASSERT_EQ(3, e->mtime); TestDiskInterface testDiskInterface; - EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, &err)); + char out2[] = { 'o', 'u', 't', '2' }; + char* filter2[] = { out2 }; + EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, 1, filter2, &err)); + ASSERT_EQ("", err); + e = log.LookupByOutput("out"); + ASSERT_EQ(3, e->mtime); // unchanged, since the filter doesn't match + + EXPECT_TRUE(log.Restat(kTestFilename, testDiskInterface, 0, NULL, &err)); ASSERT_EQ("", err); e = log.LookupByOutput("out"); ASSERT_EQ(4, e->mtime); diff --git a/src/ninja.cc b/src/ninja.cc index 08f717f..b122cb6 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -859,6 +859,24 @@ int NinjaMain::ToolRecompact(const Options* options, int argc, char* argv[]) { } int NinjaMain::ToolRestat(const Options* options, int argc, char* argv[]) { + // The restat tool uses getopt, and expects argv[0] to contain the name of the + // tool, i.e. "restat" + argc++; + argv--; + + optind = 1; + int opt; + while ((opt = getopt(argc, argv, const_cast("h"))) != -1) { + switch (opt) { + case 'h': + default: + printf("usage: ninja -t restat [outputs]\n"); + return 1; + } + } + argv += optind; + argc -= optind; + if (!EnsureBuildDirExists()) return 1; @@ -882,7 +900,7 @@ int NinjaMain::ToolRestat(const Options* options, int argc, char* argv[]) { err.clear(); } - bool success = build_log_.Restat(log_path, disk_interface_, &err); + bool success = build_log_.Restat(log_path, disk_interface_, argc, argv, &err); if (!success) { Error("failed recompaction: %s", err.c_str()); return EXIT_FAILURE; -- cgit v0.12