From 8177085f4d3adf78b9709069a9c3ce5fe442867a Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Sat, 8 Nov 2014 11:47:22 -0800 Subject: [PATCH] path decanonicalization when building command --- src/build_test.cc | 3 +-- src/graph.cc | 14 +++++++++++++- src/graph.h | 5 ++++- src/graph_test.cc | 21 +++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/build_test.cc b/src/build_test.cc index a5b0972..5d6c4e9 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -755,12 +755,11 @@ TEST_F(BuildTest, MakeDirs) { #ifdef _WIN32 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir\\dir2\\file: cat in1\n")); - EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err)); #else ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, "build subdir/dir2/file: cat in1\n")); - EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err)); #endif + EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err)); EXPECT_EQ("", err); EXPECT_TRUE(builder_.Build(&err)); diff --git a/src/graph.cc b/src/graph.cc index aa9c0e8..5bc5c00 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -256,7 +256,7 @@ string EdgeEnv::MakePathList(vector::iterator begin, for (vector::iterator i = begin; i != end; ++i) { if (!result.empty()) result.push_back(sep); - const string& path = (*i)->path(); + const string& path = (*i)->PathDecanonicalized(); if (escape_in_out_ == kShellEscape) { #if _WIN32 GetWin32EscapedString(path, &result); @@ -328,6 +328,18 @@ bool Edge::use_console() const { return pool() == &State::kConsolePool; } +string Node::PathDecanonicalized() const { + string result = path_; + unsigned int mask = 1; + for (char* c = &result[0]; (c = strpbrk(c, "/\\")) != NULL;) { + if (slash_bits_ & mask) + *c = '\\'; + c++; + mask <<= 1; + } + return result; +} + void Node::Dump(const char* prefix) const { printf("%s <%s 0x%p> mtime: %d%s, (:%s), ", prefix, path().c_str(), this, diff --git a/src/graph.h b/src/graph.h index 5c4112b..9aada38 100644 --- a/src/graph.h +++ b/src/graph.h @@ -72,6 +72,8 @@ struct Node { } const string& path() const { return path_; } + /// Get |path()| but use slash_bits to convert back to original slash styles. + string PathDecanonicalized() const; unsigned int slash_bits() const { return slash_bits_; } TimeStamp mtime() const { return mtime_; } @@ -93,7 +95,8 @@ struct Node { private: string path_; - /// XXX See CanonicalizePath. + /// Set bits starting from lowest for backslashes that were normalized to + /// forward slashes by CanonicalizePath. See |PathDecanonicalized|. unsigned int slash_bits_; /// Possible values of mtime_: diff --git a/src/graph_test.cc b/src/graph_test.cc index 14dc678..382d352 100644 --- a/src/graph_test.cc +++ b/src/graph_test.cc @@ -251,3 +251,24 @@ TEST_F(GraphTest, NestedPhonyPrintsDone) { EXPECT_EQ(0, plan_.command_edge_count()); ASSERT_FALSE(plan_.more_to_do()); } + +#ifdef _WIN32 +TEST_F(GraphTest, Decanonicalize) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"build out\\out1: cat src\\in1\n" +"build out\\out2/out3\\out4: cat mid1\n" +"build out3 out4\\foo: cat mid1\n")); + + string err; + vector root_nodes = state_.RootNodes(&err); + EXPECT_EQ(4u, root_nodes.size()); + EXPECT_EQ(root_nodes[0]->path(), "out/out1"); + EXPECT_EQ(root_nodes[1]->path(), "out/out2/out3/out4"); + EXPECT_EQ(root_nodes[2]->path(), "out3"); + EXPECT_EQ(root_nodes[3]->path(), "out4/foo"); + EXPECT_EQ(root_nodes[0]->PathDecanonicalized(), "out\\out1"); + EXPECT_EQ(root_nodes[1]->PathDecanonicalized(), "out\\out2/out3\\out4"); + EXPECT_EQ(root_nodes[2]->PathDecanonicalized(), "out3"); + EXPECT_EQ(root_nodes[3]->PathDecanonicalized(), "out4\\foo"); +} +#endif -- 2.7.4