Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1217)

Unified Diff: tools/gn/filesystem_utils.cc

Issue 165823003: GN: Change gen command syntax, support relative dirs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change in build file writing Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/gn/filesystem_utils.cc
diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc
index c692425e19236ea0d13cf71f804dd41f9faf790e..a40fe69d20d281c588e6022bce1fba20014c4cc4 100644
--- a/tools/gn/filesystem_utils.cc
+++ b/tools/gn/filesystem_utils.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -109,6 +110,59 @@ bool DoesBeginWindowsDriveLetter(const base::StringPiece& path) {
}
#endif
+// A wrapper around FilePath.GetComponents that works the way we need. This is
+// not super efficient since it does some O9n) transformations on the path. If
Dirk Pranke 2014/02/18 19:22:35 typo: O9n) -> O(n)
+// this is called a lot, we might want to optimize.
+std::vector<base::FilePath::StringType> GetPathComponents(
+ const base::FilePath& path) {
+ std::vector<base::FilePath::StringType> result;
+ path.GetComponents(&result);
+
+ if (result.empty())
+ return result;
+
+ // GetComponents will preserve the "/" at the beginning, which confuses us.
+ // We don't expect to have relative paths in this function.
+ // Don't use IsSeparator since we always want to allow backslashes.
+ if (result[0] == FILE_PATH_LITERAL("/") ||
+ result[0] == FILE_PATH_LITERAL("\\"))
+ result.erase(result.begin());
+
+#if defined(OS_WIN)
+ // On Windows, GetComponents will give us [ "C:", "/", "foo" ], and we
+ // don't want the slash in there. This doesn't support input like "C:foo"
+ // which means foo relative to the current directory of the C drive but
+ // that's basically legacy DOS behavior we don't need to support.
+ if (result.size() >= 2 && result[1] == L"/" || result[1] == L"\\")
+ result.erase(result.begin() + 1);
+#endif
+
+ return result;
+}
+
+// Provides the equivalent of == for filesystem strings, trying to do
+// approximately the right thing with case.
+bool FilesystemStringsEqual(const base::FilePath::StringType& a,
+ const base::FilePath::StringType& b) {
+#if defined(OS_WIN)
+ // Assume case-insesitive filesystems on Windows. We use the CompareString
Dirk Pranke 2014/02/18 19:22:35 typo: case-insesitive -> case-insensitive.
+ // function to do a case-insensitive comparison based on the current locale
+ // (we don't want GN to depend on ICU which is large and requires data
+ // files). This isn't perfect, but getting this perfectly right is very
+ // difficult and requires I/O, and this comparison should cover 99.9999% of
+ // all cases.
+ //
+ // Note: The documentation for CompareString says it runs fastest on
+ // null-terminated strings with -1 passed for the length, so we do that here.
+ // There should not be embedded nulls in filesystem strings.
+ return ::CompareString(LOCALE_USER_DEFAULT, LINGUISTIC_IGNORECASE,
+ a.c_str(), -1, b.c_str(), -1) == CSTR_EQUAL;
+#else
+ // Assume case-sensitive filesystems on non-Windows.
+ return a == b;
Dirk Pranke 2014/02/18 19:22:35 isn't Mac also case-insensitive by default? (thoug
brettw 2014/02/18 20:22:46 Hey, I didn't even know that. Let's see if we can
+#endif
+}
+
} // namespace
SourceFileType GetSourceFileType(const SourceFile& file,
@@ -564,6 +618,55 @@ std::string DirectoryWithNoLastSlash(const SourceDir& dir) {
return ret;
}
+SourceDir SourceDirForPath(const base::FilePath& source_root,
+ const base::FilePath& path) {
+ std::vector<base::FilePath::StringType> source_comp =
+ GetPathComponents(source_root);
+ std::vector<base::FilePath::StringType> path_comp =
+ GetPathComponents(path);
+
+ // See if path is inside the source root by looking for each of source root's
+ // components at the beginning of path.
+ bool is_inside_source;
+ if (path_comp.size() < source_comp.size()) {
+ // Too small to fit.
+ is_inside_source = false;
+ } else {
+ is_inside_source = true;
+ for (size_t i = 0; i < source_comp.size(); i++) {
+ if (!FilesystemStringsEqual(source_comp[i], path_comp[i])) {
+ is_inside_source = false;
+ break;
+ }
+ }
+ }
+
+ std::string result_str;
+ size_t initial_path_comp_to_use;
+ if (is_inside_source) {
+ // Construct a source-relative path beginning in // and skip all of the
+ // shared directories.
+ result_str = "//";
+ initial_path_comp_to_use = source_comp.size();
+ } else {
+ // Not inside source code, construct a system-absolute path.
+ result_str = "/";
+ initial_path_comp_to_use = 0;
+ }
+
+ for (size_t i = initial_path_comp_to_use; i < path_comp.size(); i++) {
+ result_str.append(FilePathToUTF8(path_comp[i]));
+ result_str.push_back('/');
+ }
+ return SourceDir(result_str);
+}
+
+SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root) {
+ base::FilePath cd;
+ file_util::GetCurrentDirectory(&cd);
+ return SourceDirForPath(source_root, cd);
+}
+
SourceDir GetToolchainOutputDir(const Settings* settings) {
const OutputFile& toolchain_subdir = settings->toolchain_output_subdir();

Powered by Google App Engine
This is Rietveld 408576698