blob: bfa448b41f87a820975df14e01bca5acf9dc84f7 [file] [log] [blame]
// Copyright 2018 The Bazel Authors. 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.
#ifndef BAZEL_SRC_MAIN_CPP_UTIL_PATH_PLATFORM_H_
#define BAZEL_SRC_MAIN_CPP_UTIL_PATH_PLATFORM_H_
#include <string>
namespace blaze_util {
// Platform-native, absolute, normalized path.
// It can be converted to a printable path (for error messages) or to a native
// path (for API calls).
class Path {
public:
Path() {}
explicit Path(const std::string &path);
bool operator==(const Path &o) const { return path_ == o.path_; }
bool operator!=(const Path &o) const { return path_ != o.path_; }
bool operator<(const Path &o) const { return path_ < o.path_; }
bool IsEmpty() const { return path_.empty(); }
bool IsNull() const;
bool Contains(const char c) const;
bool Contains(const std::string &s) const;
Path GetRelative(const std::string &r) const;
// Returns the canonical form (like realpath(1)) of this path.
// All symlinks in the path are resolved.
// If canonicalization fails, returns an empty Path.
Path Canonicalize() const;
Path GetParent() const;
// Returns a printable string representing this path.
// Only use when printing user messages, do not pass to filesystem API
// functions.
std::string AsPrintablePath() const;
// Returns a string representation of this path that's safe to pass on the
// command line as a JVM argument.
std::string AsJvmArgument() const;
// Returns a string representation of this path, safe to pass to the Bazel
// server.
std::string AsCommandLineArgument() const;
#if defined(_WIN32) || defined(__CYGWIN__)
// Returns a platform-native, absolute, normalized path.
// Use this to pass paths to filesystem API functions.
const std::wstring AsNativePath() const { return path_; }
#else
// Returns a platform-native, absolute, normalized path.
// Use this to pass paths to filesystem API functions.
const std::string AsNativePath() const { return path_; }
#endif
private:
#if defined(_WIN32) || defined(__CYGWIN__)
explicit Path(const std::wstring &wpath) : path_(wpath) {}
std::wstring path_;
#else
std::string path_;
#endif
};
// Convert a path from Bazel internal form to underlying OS form.
// On Unixes this is an identity operation.
// On Windows, Bazel internal form is cygwin path, and underlying OS form
// is Windows path.
std::string ConvertPath(const std::string &path);
// Converts `path` to a string that's safe to pass as path in a JVM flag.
// See https://github.com/bazelbuild/bazel/issues/2576
std::string PathAsJvmFlag(const std::string &path);
// Compares two absolute paths. Necessary because the same path can have
// multiple different names under msys2: "C:\foo\bar" or "C:/foo/bar"
// (Windows-style) and "/c/foo/bar" (msys2 style). Returns if the paths are
// equal.
bool CompareAbsolutePaths(const std::string &a, const std::string &b);
// Split a path to dirname and basename parts.
std::pair<std::string, std::string> SplitPath(const std::string &path);
bool IsDevNull(const char *path);
// Returns true if `path` is the root directory or a Windows drive root.
bool IsRootDirectory(const std::string &path);
bool IsRootDirectory(const Path &path);
// Returns true if `path` is absolute.
bool IsAbsolute(const std::string &path);
// Returns the given path in absolute form. Does not change paths that are
// already absolute.
//
// If called from working directory "/bar":
// MakeAbsolute("foo") --> "/bar/foo"
// MakeAbsolute("/foo") ---> "/foo"
// MakeAbsolute("C:/foo") ---> "C:/foo"
std::string MakeAbsolute(const std::string &path);
// Returns the given path in absolute form, taking into account a
// possible starting environment variable, so that we can accept
// standard path variables like %USERPROFILE% or ${BAZEL}. For
// simplicity, we implement only those two forms, not $BAZEL.
//
// MakeAbsolute("foo") in wd "/bar" --> "/bar/foo"
// MakeAbsoluteAndResolveEnvvars("%USERPROFILE%/foo") -->
// "C:\Users\bazel-user\foo"
// MakeAbsoluteAndResolveEnvvars("${BAZEL}/foo") --> "/opt/bazel/foo"
std::string MakeAbsoluteAndResolveEnvvars(const std::string &path);
// TODO(bazel-team) consider changing the path(_platform) header split to be a
// path.h and path_windows.h split, which would make it clearer what functions
// are included by an import statement. The downside to this gain in clarity
// is that this would add more complexity to the implementation file(s)? of
// path.h, which would have to have the platform-specific implementations.
#if defined(_WIN32) || defined(__CYGWIN__)
bool IsDevNull(const wchar_t *path);
bool IsAbsolute(const std::wstring &path);
const wchar_t *RemoveUncPrefixMaybe(const wchar_t *ptr);
void AddUncPrefixMaybe(std::wstring *path);
std::pair<std::wstring, std::wstring> SplitPathW(const std::wstring &path);
bool IsRootDirectoryW(const std::wstring &path);
// Converts 'path' to Windows style.
//
// 'path' is absolute or relative or current-drive-relative (e.g.
// "\foo"), possibly non-normalized, possibly using slash as separator. If it
// starts with the UNC prefix, the function won't process it further, just
// copies it to 'result'.
//
// 'result' equals 'path' if 'path' started with the UNC prefix, otherwise
// 'result' is normalized, using backslash as separator.
//
// Encoding: there is no assumption about encoding, 'path' is read as ASCII
// (Latin-1) and 'result' uses the same encoding.
bool AsWindowsPath(const std::string &path, std::string *result,
std::string *error);
// Converts 'path' to Windows style.
//
// Same as the other AsWindowsPath methods, but 'path' is encoded as multibyte
// and 'result' is widechar. (MSDN does not clarify what multibyte means. The
// function uses blaze_util::WstringToCstring.)
bool AsWindowsPath(const std::string &path, std::wstring *result,
std::string *error);
// Converts 'path' to Windows style.
//
// Same as the other AsWindowsPath methods, but 'path' and 'result' are
// widechar.
bool AsWindowsPath(const std::wstring &path, std::wstring *result,
std::string *error);
// Converts 'path' to absolute, Windows-style path.
//
// Same as AsWindowsPath, but 'result' is always absolute and always has a UNC
// prefix.
bool AsAbsoluteWindowsPath(const std::string &path, std::wstring *result,
std::string *error);
// Converts 'path' to absolute, Windows-style path.
//
// Same as AsWindowsPath, but 'result' is always absolute and always has a UNC
// prefix.
bool AsAbsoluteWindowsPath(const std::wstring &path, std::wstring *result,
std::string *error);
// Converts 'path' to absolute, shortened, Windows-style path.
//
// Same as `AsWindowsPath`, but 'result' is always absolute, lowercase,
// 8dot3-style shortened path, without trailing backslash and without UNC
// prefix.
//
// Works even for non-existent paths (and non-existent drives), shortening the
// existing segments and leaving the rest unshortened.
bool AsShortWindowsPath(const std::string &path, std::string *result,
std::string *error);
bool AsShortWindowsPath(const std::wstring &path, std::wstring *result,
std::string *error);
#else
std::string TestOnly_NormalizeAbsPath(const std::string &s);
#endif // defined(_WIN32) || defined(__CYGWIN__)
} // namespace blaze_util
#endif // BAZEL_SRC_MAIN_CPP_UTIL_PATH_PLATFORM_H_