path decanonicalization when building command
authorScott Graham <scottmg@chromium.org>
Sat, 8 Nov 2014 19:47:22 +0000 (11:47 -0800)
committerScott Graham <scottmg@chromium.org>
Sat, 8 Nov 2014 19:47:22 +0000 (11:47 -0800)
src/build_test.cc
src/graph.cc
src/graph.h
src/graph_test.cc

index a5b0972..5d6c4e9 100644 (file)
@@ -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));
index aa9c0e8..5bc5c00 100644 (file)
@@ -256,7 +256,7 @@ string EdgeEnv::MakePathList(vector<Node*>::iterator begin,
   for (vector<Node*>::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,
index 5c4112b..9aada38 100644 (file)
@@ -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_:
index 14dc678..382d352 100644 (file)
@@ -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<Node*> 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