summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/deps_log.cc32
-rw-r--r--src/deps_log_test.cc46
2 files changed, 76 insertions, 2 deletions
diff --git a/src/deps_log.cc b/src/deps_log.cc
index da6cd93..0f10b5c 100644
--- a/src/deps_log.cc
+++ b/src/deps_log.cc
@@ -50,15 +50,43 @@ bool DepsLog::OpenForWrite(const string& path, string* err) {
bool DepsLog::RecordDeps(Node* node, TimeStamp mtime,
const vector<Node*>& nodes) {
+ // Track whether there's any new data to be recorded.
+ bool made_change = false;
+
// Assign ids to all nodes that are missing one.
- if (node->id() < 0)
+ if (node->id() < 0) {
RecordId(node);
+ made_change = true;
+ }
for (vector<Node*>::const_iterator i = nodes.begin();
i != nodes.end(); ++i) {
- if ((*i)->id() < 0)
+ if ((*i)->id() < 0) {
RecordId(*i);
+ made_change = true;
+ }
+ }
+
+ // See if the new data is different than the existing data, if any.
+ if (!made_change) {
+ Deps* deps = GetDeps(node);
+ if (!deps ||
+ deps->mtime != mtime ||
+ deps->node_count != (int)nodes.size()) {
+ made_change = true;
+ } else {
+ for (int i = 0; i < (int)nodes.size(); ++i) {
+ if (deps->nodes[i] != nodes[i]) {
+ made_change = true;
+ break;
+ }
+ }
+ }
}
+ // Don't write anything if there's no new info.
+ if (!made_change)
+ return true;
+
uint16_t size = 4 * (1 + 1 + (uint16_t)nodes.size());
size |= 0x8000; // Deps record: set high bit.
fwrite(&size, 2, 1, file_);
diff --git a/src/deps_log_test.cc b/src/deps_log_test.cc
index 3f47fef..e411e12 100644
--- a/src/deps_log_test.cc
+++ b/src/deps_log_test.cc
@@ -76,4 +76,50 @@ TEST_F(DepsLogTest, WriteRead) {
ASSERT_EQ("bar.h", deps->nodes[1]->path());
}
+// Verify that adding the same deps twice doesn't grow the file.
+TEST_F(DepsLogTest, DoubleEntry) {
+ // Write some deps to the file and grab its size.
+ int file_size;
+ {
+ State state;
+ DepsLog log;
+ string err;
+ EXPECT_TRUE(log.OpenForWrite(kTestFilename, &err));
+ ASSERT_EQ("", err);
+
+ vector<Node*> deps;
+ deps.push_back(state.GetNode("foo.h"));
+ deps.push_back(state.GetNode("bar.h"));
+ log.RecordDeps(state.GetNode("out.o"), 1, deps);
+ log.Close();
+
+ struct stat st;
+ ASSERT_EQ(0, stat(kTestFilename, &st));
+ file_size = (int)st.st_size;
+ ASSERT_GT(file_size, 0);
+ }
+
+ // Now reload the file, and readd the same deps.
+ {
+ State state;
+ DepsLog log;
+ string err;
+ EXPECT_TRUE(log.Load(kTestFilename, &state, &err));
+
+ EXPECT_TRUE(log.OpenForWrite(kTestFilename, &err));
+ ASSERT_EQ("", err);
+
+ vector<Node*> deps;
+ deps.push_back(state.GetNode("foo.h"));
+ deps.push_back(state.GetNode("bar.h"));
+ log.RecordDeps(state.GetNode("out.o"), 1, deps);
+ log.Close();
+
+ struct stat st;
+ ASSERT_EQ(0, stat(kTestFilename, &st));
+ int file_size_2 = (int)st.st_size;
+ ASSERT_EQ(file_size, file_size_2);
+ }
+}
+
} // anonymous namespace