Move CanonicalizePath into util.h so it can be shared by the other modules.
authorThiago Farina <tfransosi@gmail.com>
Sat, 19 Mar 2011 21:53:43 +0000 (18:53 -0300)
committerEvan Martin <martine@danga.com>
Fri, 15 Apr 2011 19:20:51 +0000 (12:20 -0700)
Also add util_test.cc and move the CanonicalizePathTest into there.

Signed-off-by: Thiago Farina <tfarina@chromium.org>
build.ninja
src/graph.cc
src/graph.h
src/graph_test.cc
src/util.cc
src/util.h
src/util_test.cc [new file with mode: 0644]

index c993ecf..84c10d4 100644 (file)
@@ -63,6 +63,7 @@ build $builddir/ninja_test.o: cxx src/ninja_test.cc
 build $builddir/parsers_test.o: cxx src/parsers_test.cc
 build $builddir/subprocess_test.o: cxx src/subprocess_test.cc
 build $builddir/test.o: cxx src/test.cc
+build $builddir/util_test.o: cxx src/util_test.cc
 build ninja_test: link $builddir/build_test.o $builddir/build_log_test.o \
     $builddir/graph_test.o $builddir/ninja_test.o $builddir/parsers_test.o \
     $builddir/subprocess_test.o $builddir/test.o $builddir/ninja.a
index 35ae088..a4317ba 100644 (file)
 #include "build_log.h"
 #include "ninja.h"
 #include "parsers.h"
-
-// Canonicalize a path like "foo/../bar.h" into just "bar.h".
-bool CanonicalizePath(string* path, string* err) {
-  // Try to fast-path out the common case.
-  if (path->find("/.") == string::npos &&
-      path->find("./") == string::npos) {
-    return true;
-  }
-
-  string inpath = *path;
-  vector<const char*> parts;
-  for (string::size_type start = 0; start < inpath.size(); ++start) {
-    string::size_type end = inpath.find('/', start);
-    if (end == string::npos)
-      end = inpath.size();
-    else
-      inpath[end] = 0;
-    parts.push_back(inpath.data() + start);
-    start = end;
-  }
-
-  vector<const char*>::iterator i = parts.begin();
-  while (i != parts.end()) {
-    const char* part = *i;
-    if (part[0] == '.') {
-      if (part[1] == 0) {
-        // "."; strip.
-        parts.erase(i);
-        continue;
-      } else if (part[1] == '.' && part[2] == 0) {
-        // ".."; go up one.
-        if (i == parts.begin()) {
-          *err = "can't canonicalize path '" + *path + "' that reaches "
-            "above its directory";
-          return false;
-        }
-        --i;
-        parts.erase(i, i + 2);
-        continue;
-      }
-    }
-    ++i;
-  }
-  path->clear();
-
-  for (i = parts.begin(); i != parts.end(); ++i) {
-    if (!path->empty())
-      path->push_back('/');
-    path->append(*i);
-  }
-
-  return true;
-}
+#include "util.h"
 
 bool FileStat::Stat(DiskInterface* disk_interface) {
   mtime_ = disk_interface->Stat(path_);
index ecf9e54..f3cfa97 100644 (file)
@@ -119,7 +119,4 @@ struct Edge {
   bool is_phony() const;
 };
 
-// Exposed for testing.
-bool CanonicalizePath(string* path, string* err);
-
 #endif  // NINJA_GRAPH_H_
index b67cf99..ba41440 100644 (file)
 
 #include "test.h"
 
-TEST(CanonicalizePath, PathSamples) {
-  string path = "foo.h";
-  string err;
-  EXPECT_TRUE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("", err);
-  EXPECT_EQ("foo.h", path);
-
-  path = "./foo.h"; err = "";
-  EXPECT_TRUE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("", err);
-  EXPECT_EQ("foo.h", path);
-
-  path = "./foo/./bar.h"; err = "";
-  EXPECT_TRUE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("", err);
-  EXPECT_EQ("foo/bar.h", path);
-
-  path = "./x/foo/../bar.h"; err = "";
-  EXPECT_TRUE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("", err);
-  EXPECT_EQ("x/bar.h", path);
-
-  path = "./x/foo/../../bar.h"; err = "";
-  EXPECT_TRUE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("", err);
-  EXPECT_EQ("bar.h", path);
-
-  path = "./x/../foo/../../bar.h"; err = "";
-  EXPECT_FALSE(CanonicalizePath(&path, &err));
-  EXPECT_EQ("can't canonicalize path './x/../foo/../../bar.h' that reaches "
-            "above its directory", err);
-}
-
 struct GraphTest : public StateTestWithBuiltinRules {
   VirtualFileSystem fs_;
 };
index 1968702..d0236bc 100644 (file)
@@ -18,6 +18,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <vector>
+
 void Fatal(const char* msg, ...) {
   va_list ap;
   fprintf(stderr, "FATAL: ");
@@ -27,3 +29,55 @@ void Fatal(const char* msg, ...) {
   fprintf(stderr, "\n");
   exit(1);
 }
+
+bool CanonicalizePath(std::string* path, std::string* err) {
+  // Try to fast-path out the common case.
+  if (path->find("/.") == std::string::npos &&
+      path->find("./") == std::string::npos) {
+    return true;
+  }
+
+  std::string inpath = *path;
+  std::vector<const char*> parts;
+  for (std::string::size_type start = 0; start < inpath.size(); ++start) {
+    std::string::size_type end = inpath.find('/', start);
+    if (end == std::string::npos)
+      end = inpath.size();
+    else
+      inpath[end] = 0;
+    parts.push_back(inpath.data() + start);
+    start = end;
+  }
+
+  std::vector<const char*>::iterator i = parts.begin();
+  while (i != parts.end()) {
+    const char* part = *i;
+    if (part[0] == '.') {
+      if (part[1] == 0) {
+        // "."; strip.
+        parts.erase(i);
+        continue;
+      } else if (part[1] == '.' && part[2] == 0) {
+        // ".."; go up one.
+        if (i == parts.begin()) {
+          *err = "can't canonicalize path '" + *path + "' that reaches "
+            "above its directory";
+          return false;
+        }
+        --i;
+        parts.erase(i, i + 2);
+        continue;
+      }
+    }
+    ++i;
+  }
+  path->clear();
+
+  for (i = parts.begin(); i != parts.end(); ++i) {
+    if (!path->empty())
+      path->push_back('/');
+    path->append(*i);
+  }
+
+  return true;
+}
index 188528c..8c5a6a8 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#ifndef NINJA_UTIL_H_
+#define NINJA_UTIL_H_
+#pragma once
+
+#include <string>
+
 // Dump a backtrace to stderr.
 // |skip_frames| is how many frames to skip;
 // DumpBacktrace implicitly skips itself already.
@@ -19,3 +25,8 @@ void DumpBacktrace(int skip_frames);
 
 // Log a fatal message, dump a backtrace, and exit.
 void Fatal(const char* msg, ...);
+
+// Canonicalize a path like "foo/../bar.h" into just "bar.h".
+bool CanonicalizePath(std::string* path, std::string* err);
+
+#endif  // NINJA_UTIL_H_
diff --git a/src/util_test.cc b/src/util_test.cc
new file mode 100644 (file)
index 0000000..145c80e
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util.h"
+
+#include "test.h"
+
+TEST(CanonicalizePath, PathSamples) {
+  std::string path = "foo.h";
+  std::string err;
+  EXPECT_TRUE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("", err);
+  EXPECT_EQ("foo.h", path);
+
+  path = "./foo.h"; err = "";
+  EXPECT_TRUE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("", err);
+  EXPECT_EQ("foo.h", path);
+
+  path = "./foo/./bar.h"; err = "";
+  EXPECT_TRUE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("", err);
+  EXPECT_EQ("foo/bar.h", path);
+
+  path = "./x/foo/../bar.h"; err = "";
+  EXPECT_TRUE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("", err);
+  EXPECT_EQ("x/bar.h", path);
+
+  path = "./x/foo/../../bar.h"; err = "";
+  EXPECT_TRUE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("", err);
+  EXPECT_EQ("bar.h", path);
+
+  path = "./x/../foo/../../bar.h"; err = "";
+  EXPECT_FALSE(CanonicalizePath(&path, &err));
+  EXPECT_EQ("can't canonicalize path './x/../foo/../../bar.h' that reaches "
+            "above its directory", err);
+}