summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Niklas Hasse <jhasse@bixense.com>2020-01-16 23:10:52 +0100
committerJan Niklas Hasse <jhasse@bixense.com>2020-01-16 23:10:52 +0100
commitd47e1eb00d2eac4a3b864639ab972a53e60f4925 (patch)
tree90aada012686ab9f16128ea55c238ce6ecfae4d2
parent26fc40c59a5630bf1429f8df90bb9352c7b593a0 (diff)
downloadninja-d47e1eb00d2eac4a3b864639ab972a53e60f4925.tar.gz
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.
-rw-r--r--src/build_log.cc20
-rw-r--r--src/build_log.h2
-rw-r--r--src/build_log_test.cc9
-rw-r--r--src/ninja.cc20
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<LogEntry*>::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<char*>("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;