summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 21:07:47 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-23 21:07:47 +0000
commitf6b314d1e54cf31a87825f77abe6df4acedf98e3 (patch)
tree2d7a97bd481b19a4750690fa3b80401425dad155 /tools
parent17f43bf95e9472153b0386280c439a4c34cb6328 (diff)
downloadchromium_src-f6b314d1e54cf31a87825f77abe6df4acedf98e3.zip
chromium_src-f6b314d1e54cf31a87825f77abe6df4acedf98e3.tar.gz
chromium_src-f6b314d1e54cf31a87825f77abe6df4acedf98e3.tar.bz2
Implement MakeAbsolutePathRelativeIfPossible on Windows for GN.
BUG= R=scottmg@chromium.org Review URL: https://codereview.chromium.org/22893047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219332 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r--tools/gn/filesystem_utils.cc88
-rw-r--r--tools/gn/filesystem_utils.h2
-rw-r--r--tools/gn/filesystem_utils_unittest.cc20
-rw-r--r--tools/gn/function_exec_script.cc1
4 files changed, 103 insertions, 8 deletions
diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc
index dfaa303..75b72b2 100644
--- a/tools/gn/filesystem_utils.cc
+++ b/tools/gn/filesystem_utils.cc
@@ -5,6 +5,7 @@
#include "tools/gn/filesystem_utils.h"
#include "base/logging.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "tools/gn/location.h"
@@ -63,7 +64,49 @@ DotDisposition ClassifyAfterDot(const std::string& path,
return NOT_A_DIRECTORY;
}
-} // namesapce
+#if defined(OS_WIN)
+inline char NormalizeWindowsPathChar(char c) {
+ if (c == '/')
+ return '\\';
+ return base::ToLowerASCII(c);
+}
+
+// Attempts to do a case and slash-insensitive comparison of two 8-bit Windows
+// paths.
+bool AreAbsoluteWindowsPathsEqual(const base::StringPiece& a,
+ const base::StringPiece& b) {
+ if (a.size() != b.size())
+ return false;
+
+ // For now, just do a case-insensitive ASCII comparison. We could convert to
+ // UTF-16 and use ICU if necessary. Or maybe base::strcasecmp is good enough?
+ for (size_t i = 0; i < a.size(); i++) {
+ if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i]))
+ return false;
+ }
+ return true;
+}
+
+bool DoesBeginWindowsDriveLetter(const base::StringPiece& path) {
+ if (path.size() < 3)
+ return false;
+
+ // Check colon first, this will generally fail fastest.
+ if (path[1] != ':')
+ return false;
+
+ // Check drive letter
+ if (!((path[0] >= 'A' && path[0] <= 'Z') ||
+ path[0] >= 'a' && path[0] <= 'z'))
+ return false;
+
+ if (path[2] != '/' && path[2] != '\\')
+ return false;
+ return true;
+}
+#endif
+
+} // namespace
SourceFileType GetSourceFileType(const SourceFile& file,
Settings::TargetOS os) {
@@ -286,25 +329,60 @@ bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
// Source root should be canonical on Windows.
DCHECK(source_root.size() > 2 && source_root[0] != '/' &&
source_root[1] == ':' && source_root[2] =='\\');
-#error
+
+ size_t after_common_index = std::string::npos;
+ if (DoesBeginWindowsDriveLetter(path)) {
+ // Handle "C:\foo"
+ if (AreAbsoluteWindowsPathsEqual(source_root,
+ path.substr(0, source_root.size())))
+ after_common_index = source_root.size();
+ else
+ return false;
+ } else if (path[0] == '/' && source_root.size() <= path.size() - 1 &&
+ DoesBeginWindowsDriveLetter(path.substr(1))) {
+ // Handle "/C:/foo"
+ if (AreAbsoluteWindowsPathsEqual(source_root,
+ path.substr(1, source_root.size())))
+ after_common_index = source_root.size() + 1;
+ else
+ return false;
+ } else {
+ return false;
+ }
+
+ // If we get here, there's a match and after_common_index identifies the
+ // part after it.
+
+ // The base may or may not have a trailing slash, so skip all slashes from
+ // the path after our prefix match.
+ size_t first_after_slash = after_common_index;
+ while (first_after_slash < path.size() &&
+ (path[first_after_slash] == '/' || path[first_after_slash] == '\\'))
+ first_after_slash++;
+
+ dest->assign("//"); // Result is source root relative.
+ dest->append(&path.data()[first_after_slash],
+ path.size() - first_after_slash);
+ return true;
+
#else
+
// On non-Windows this is easy. Since we know both are absolute, just do a
// prefix check.
if (path.substr(0, source_root.size()) == source_root) {
- dest->assign("//"); // Result is source root relative.
-
// The base may or may not have a trailing slash, so skip all slashes from
// the path after our prefix match.
size_t first_after_slash = source_root.size();
while (first_after_slash < path.size() && path[first_after_slash] == '/')
first_after_slash++;
+ dest->assign("//"); // Result is source root relative.
dest->append(&path.data()[first_after_slash],
path.size() - first_after_slash);
return true;
}
-#endif
return false;
+#endif
}
std::string InvertDir(const SourceDir& path) {
diff --git a/tools/gn/filesystem_utils.h b/tools/gn/filesystem_utils.h
index 4ab4ec5..90e9d50 100644
--- a/tools/gn/filesystem_utils.h
+++ b/tools/gn/filesystem_utils.h
@@ -111,6 +111,8 @@ bool IsPathAbsolute(const base::StringPiece& path);
// The source_root should be a base::FilePath converted to UTF-8. On Windows,
// it should begin with a "C:/" rather than being our SourceFile's style
// ("/C:/"). The source root can end with a slash or not.
+//
+// Note that this does not attempt to normalize slashes in the output.
bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
const base::StringPiece& path,
std::string* dest);
diff --git a/tools/gn/filesystem_utils_unittest.cc b/tools/gn/filesystem_utils_unittest.cc
index 27e65e2..6c80cdb 100644
--- a/tools/gn/filesystem_utils_unittest.cc
+++ b/tools/gn/filesystem_utils_unittest.cc
@@ -93,6 +93,23 @@ TEST(FilesystemUtils, IsPathAbsolute) {
TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) {
std::string dest;
+#if defined(OS_WIN)
+ EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo",
+ &dest));
+ EXPECT_EQ("//foo", dest);
+ EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo",
+ &dest));
+ EXPECT_EQ("//foo", dest);
+ EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\",
+ &dest));
+ EXPECT_EQ("//foo\\", dest);
+
+ EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest));
+ EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base",
+ "C:\\/notbase/foo",
+ &dest));
+#else
+
EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest));
EXPECT_EQ("//foo/", dest);
EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest));
@@ -104,9 +121,6 @@ TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) {
EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest));
EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo",
&dest));
-
-#if defined(OS_WIN)
- //EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("
#endif
}
diff --git a/tools/gn/function_exec_script.cc b/tools/gn/function_exec_script.cc
index 34c5e96..1d4c511 100644
--- a/tools/gn/function_exec_script.cc
+++ b/tools/gn/function_exec_script.cc
@@ -8,6 +8,7 @@
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "tools/gn/err.h"