diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 21:07:47 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-23 21:07:47 +0000 |
commit | f6b314d1e54cf31a87825f77abe6df4acedf98e3 (patch) | |
tree | 2d7a97bd481b19a4750690fa3b80401425dad155 /tools | |
parent | 17f43bf95e9472153b0386280c439a4c34cb6328 (diff) | |
download | chromium_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.cc | 88 | ||||
-rw-r--r-- | tools/gn/filesystem_utils.h | 2 | ||||
-rw-r--r-- | tools/gn/filesystem_utils_unittest.cc | 20 | ||||
-rw-r--r-- | tools/gn/function_exec_script.cc | 1 |
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" |