// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/filesystem_utils.h"

#include <algorithm>

#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "gn/file_writer.h"
#include "gn/location.h"
#include "gn/settings.h"
#include "gn/source_dir.h"
#include "gn/target.h"
#include "util/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

namespace {

enum DotDisposition {
  // The given dot is just part of a filename and is not special.
  NOT_A_DIRECTORY,

  // The given dot is the current directory.
  DIRECTORY_CUR,

  // The given dot is the first of a double dot that should take us up one.
  DIRECTORY_UP
};

// When we find a dot, this function is called with the character following
// that dot to see what it is. The return value indicates what type this dot is
// (see above). This code handles the case where the dot is at the end of the
// input.
//
// |*consumed_len| will contain the number of characters in the input that
// express what we found.
DotDisposition ClassifyAfterDot(const std::string& path,
                                size_t after_dot,
                                size_t* consumed_len) {
  if (after_dot == path.size()) {
    // Single dot at the end.
    *consumed_len = 1;
    return DIRECTORY_CUR;
  }
  if (IsSlash(path[after_dot])) {
    // Single dot followed by a slash.
    *consumed_len = 2;  // Consume the slash
    return DIRECTORY_CUR;
  }

  if (path[after_dot] == '.') {
    // Two dots.
    if (after_dot + 1 == path.size()) {
      // Double dot at the end.
      *consumed_len = 2;
      return DIRECTORY_UP;
    }
    if (IsSlash(path[after_dot + 1])) {
      // Double dot folowed by a slash.
      *consumed_len = 3;
      return DIRECTORY_UP;
    }
  }

  // The dots are followed by something else, not a directory.
  *consumed_len = 1;
  return NOT_A_DIRECTORY;
}

#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(std::string_view a, std::string_view 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.
  for (size_t i = 0; i < a.size(); i++) {
    if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i]))
      return false;
  }
  return true;
}

bool DoesBeginWindowsDriveLetter(std::string_view path) {
  if (path.size() < 3)
    return false;

  // Check colon first, this will generally fail fastest.
  if (path[1] != ':')
    return false;

  // Check drive letter.
  if (!base::IsAsciiAlpha(path[0]))
    return false;

  if (!IsSlash(path[2]))
    return false;
  return true;
}
#endif

// A wrapper around FilePath.GetComponents that works the way we need. This is
// not super efficient since it does some O(n) transformations on the path. If
// 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].size() == 1 &&
      IsSlash(static_cast<char>(result[1][0])))
    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-insensitive filesystems on Windows. We use the CompareString
  // 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,
                         reinterpret_cast<LPCWSTR>(a.c_str()), -1,
                         reinterpret_cast<LPCWSTR>(b.c_str()),
                         -1) == CSTR_EQUAL;
#else
  // Assume case-sensitive filesystems on non-Windows.
  return a == b;
#endif
}

// Helper function for computing subdirectories in the build directory
// corresponding to absolute paths. This will try to resolve the absolute
// path as a source-relative path first, and otherwise it creates a
// special subdirectory for absolute paths to keep them from colliding with
// other generated sources and outputs.
void AppendFixedAbsolutePathSuffix(const BuildSettings* build_settings,
                                   const SourceDir& source_dir,
                                   OutputFile* result) {
  const std::string& build_dir = build_settings->build_dir().value();

  if (base::StartsWith(source_dir.value(), build_dir,
                       base::CompareCase::SENSITIVE)) {
    size_t build_dir_size = build_dir.size();
    result->value().append(&source_dir.value()[build_dir_size],
                           source_dir.value().size() - build_dir_size);
  } else {
    result->value().append("ABS_PATH");
#if defined(OS_WIN)
    // Windows absolute path contains ':' after drive letter. Remove it to
    // avoid inserting ':' in the middle of path (eg. "ABS_PATH/C:/").
    std::string src_dir_value = source_dir.value();
    const auto colon_pos = src_dir_value.find(':');
    if (colon_pos != std::string::npos)
      src_dir_value.erase(src_dir_value.begin() + colon_pos);
#else
    const std::string& src_dir_value = source_dir.value();
#endif
    result->value().append(src_dir_value);
  }
}

size_t AbsPathLenWithNoTrailingSlash(std::string_view path) {
  size_t len = path.size();
#if defined(OS_WIN)
  size_t min_len = 3;
#else
  // On posix system. The minimal abs path is "/".
  size_t min_len = 1;
#endif
  for (; len > min_len && IsSlash(path[len - 1]); len--)
    ;
  return len;
}
}  // namespace

std::string FilePathToUTF8(const base::FilePath::StringType& str) {
#if defined(OS_WIN)
  return base::UTF16ToUTF8(str);
#else
  return str;
#endif
}

base::FilePath UTF8ToFilePath(std::string_view sp) {
#if defined(OS_WIN)
  return base::FilePath(base::UTF8ToUTF16(sp));
#else
  return base::FilePath(sp);
#endif
}

size_t FindExtensionOffset(const std::string& path) {
  for (int i = static_cast<int>(path.size()); i >= 0; i--) {
    if (IsSlash(path[i]))
      break;
    if (path[i] == '.')
      return i + 1;
  }
  return std::string::npos;
}

std::string_view FindExtension(const std::string* path) {
  size_t extension_offset = FindExtensionOffset(*path);
  if (extension_offset == std::string::npos)
    return std::string_view();
  return std::string_view(&path->data()[extension_offset],
                          path->size() - extension_offset);
}

size_t FindFilenameOffset(const std::string& path) {
  for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) {
    if (IsSlash(path[i]))
      return i + 1;
  }
  return 0;  // No filename found means everything was the filename.
}

std::string_view FindFilename(const std::string* path) {
  size_t filename_offset = FindFilenameOffset(*path);
  if (filename_offset == 0)
    return std::string_view(*path);  // Everything is the file name.
  return std::string_view(&(*path).data()[filename_offset],
                          path->size() - filename_offset);
}

std::string_view FindFilenameNoExtension(const std::string* path) {
  if (path->empty())
    return std::string_view();
  size_t filename_offset = FindFilenameOffset(*path);
  size_t extension_offset = FindExtensionOffset(*path);

  size_t name_len;
  if (extension_offset == std::string::npos)
    name_len = path->size() - filename_offset;
  else
    name_len = extension_offset - filename_offset - 1;

  return std::string_view(&(*path).data()[filename_offset], name_len);
}

void RemoveFilename(std::string* path) {
  path->resize(FindFilenameOffset(*path));
}

bool EndsWithSlash(std::string_view s) {
  return !s.empty() && IsSlash(s[s.size() - 1]);
}

std::string_view FindDir(const std::string* path) {
  size_t filename_offset = FindFilenameOffset(*path);
  if (filename_offset == 0u)
    return std::string_view();
  return std::string_view(path->data(), filename_offset);
}

std::string_view FindLastDirComponent(const SourceDir& dir) {
  const std::string& dir_string = dir.value();

  if (dir_string.empty())
    return std::string_view();
  int cur = static_cast<int>(dir_string.size()) - 1;
  DCHECK(dir_string[cur] == '/');
  int end = cur;
  cur--;  // Skip before the last slash.

  for (; cur >= 0; cur--) {
    if (dir_string[cur] == '/')
      return std::string_view(&dir_string[cur + 1], end - cur - 1);
  }
  return std::string_view(&dir_string[0], end);
}

bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str) {
  // This check will be wrong for all proper prefixes "e.g. "/output" will
  // match "/out" but we don't really care since this is just a sanity check.
  const std::string& dir_str = output_dir.value();
  return str.compare(0, dir_str.length(), dir_str) == 0;
}

bool EnsureStringIsInOutputDir(const SourceDir& output_dir,
                               const std::string& str,
                               const ParseNode* origin,
                               Err* err) {
  if (IsStringInOutputDir(output_dir, str))
    return true;  // Output directory is hardcoded.

  *err = Err(
      origin, "File is not inside output directory.",
      "The given file should be in the output directory. Normally you would "
      "specify\n\"$target_out_dir/foo\" or "
      "\"$target_gen_dir/foo\". I interpreted this as\n\"" +
          str + "\".");
  return false;
}

bool IsPathAbsolute(std::string_view path) {
  if (path.empty())
    return false;

  if (!IsSlash(path[0])) {
#if defined(OS_WIN)
    // Check for Windows system paths like "C:\foo".
    if (path.size() > 2 && path[1] == ':' && IsSlash(path[2]))
      return true;
#endif
    return false;  // Doesn't begin with a slash, is relative.
  }

  // Double forward slash at the beginning means source-relative (we don't
  // allow backslashes for denoting this).
  if (path.size() > 1 && path[1] == '/')
    return false;

  return true;
}

bool IsPathSourceAbsolute(std::string_view path) {
  return (path.size() >= 2 && path[0] == '/' && path[1] == '/');
}

bool MakeAbsolutePathRelativeIfPossible(std::string_view source_root,
                                        std::string_view path,
                                        std::string* dest) {
  DCHECK(IsPathAbsolute(source_root));
  DCHECK(IsPathAbsolute(path));

  dest->clear();

  // There is no specification of how many slashes may be at the end of
  // source_root or path. Trim them off for easier string manipulation.
  size_t path_len = AbsPathLenWithNoTrailingSlash(path);
  size_t source_root_len = AbsPathLenWithNoTrailingSlash(source_root);

  if (source_root_len > path_len)
    return false;  // The source root is longer: the path can never be inside.
#if defined(OS_WIN)
  // Source root should be canonical on Windows. Note that the initial slash
  // must be forward slash, but that the other ones can be either forward or
  // backward.
  DCHECK(source_root.size() > 2 && source_root[0] != '/' &&
         source_root[1] == ':' && IsSlash(source_root[2]));

  size_t after_common_index = std::string::npos;
  if (DoesBeginWindowsDriveLetter(path)) {
    // Handle "C:\foo"
    if (AreAbsoluteWindowsPathsEqual(source_root.substr(0, source_root_len),
                                     path.substr(0, source_root_len))) {
      after_common_index = source_root_len;
      if (path_len == source_root_len) {
        *dest = "//";
        return true;
      }
    } else {
      return false;
    }
  } else if (path[0] == '/' && source_root_len <= path_len - 1 &&
             DoesBeginWindowsDriveLetter(path.substr(1))) {
    // Handle "/C:/foo"
    if (AreAbsoluteWindowsPathsEqual(source_root.substr(0, source_root_len),
                                     path.substr(1, source_root_len))) {
      after_common_index = source_root_len + 1;
      if (path_len + 1 == source_root_len) {
        *dest = "//";
        return true;
      }
    } else {
      return false;
    }
  } else {
    return false;
  }

  // If we get here, there's a match and after_common_index identifies the
  // part after it.

  if (!IsSlash(path[after_common_index])) {
    // path is ${source-root}SUFFIX/...
    return false;
  }
  // A source-root relative path, The input may have an unknown number of
  // slashes after the previous match. Skip over them.
  size_t first_after_slash = after_common_index + 1;
  while (first_after_slash < path_len && IsSlash(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_len) ==
      source_root.substr(0, source_root_len)) {
    if (path_len == source_root_len) {
      // path is equivalent to source_root.
      *dest = "//";
      return true;
    } else if (!IsSlash(path[source_root_len])) {
      // path is ${source-root}SUFFIX/...
      return false;
    }
    // A source-root relative path, The input may have an unknown number of
    // slashes after the previous match. Skip over them.
    size_t first_after_slash = source_root_len + 1;
    while (first_after_slash < path_len && IsSlash(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;
  }
  return false;
#endif
}

base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
    const base::FilePath& base,
    const base::FilePath& target) {
  DCHECK(base.IsAbsolute());
  DCHECK(target.IsAbsolute());
  std::vector<base::FilePath::StringType> base_components;
  std::vector<base::FilePath::StringType> target_components;
  base.GetComponents(&base_components);
  target.GetComponents(&target_components);
#if defined(OS_WIN)
  // On Windows, it's impossible to have a relative path from C:\foo to D:\bar,
  // so return the target as an absolute path instead.
  if (base_components[0] != target_components[0])
    return target;

  // GetComponents() returns the first slash after the root. Set it to the
  // same value in both component lists so that relative paths between
  // "C:/foo/..." and "C:\foo\..." are computed correctly.
  target_components[1] = base_components[1];
#endif
  size_t i;
  for (i = 0; i < base_components.size() && i < target_components.size(); i++) {
    if (base_components[i] != target_components[i])
      break;
  }
  std::vector<base::FilePath::StringType> relative_components;
  for (size_t j = i; j < base_components.size(); j++)
    relative_components.push_back(base::FilePath::kParentDirectory);
  for (size_t j = i; j < target_components.size(); j++)
    relative_components.push_back(target_components[j]);
  if (relative_components.size() <= 1) {
    // In case the file pointed-to is an executable, prepend the current
    // directory to the path -- if the path was "gn", use "./gn" instead.  If
    // the file path is used in a command, this prevents issues where "gn" might
    // not be in the PATH (or it is in the path, and the wrong gn is used).
    relative_components.insert(relative_components.begin(),
                               base::FilePath::kCurrentDirectory);
  }
  // base::FilePath::Append(component) replaces the file path with |component|
  // if the path is base::Filepath::kCurrentDirectory.  We want to preserve the
  // leading "./", so we build the path ourselves and use that to construct the
  // base::FilePath.
  base::FilePath::StringType separator(&base::FilePath::kSeparators[0], 1);
  return base::FilePath(base::JoinString(relative_components, separator));
}

void NormalizePath(std::string* path, std::string_view source_root) {
  char* pathbuf = path->empty() ? nullptr : &(*path)[0];

  // top_index is the first character we can modify in the path. Anything
  // before this indicates where the path is relative to.
  size_t top_index = 0;
  bool is_relative = true;
  if (!path->empty() && pathbuf[0] == '/') {
    is_relative = false;

    if (path->size() > 1 && pathbuf[1] == '/') {
      // Two leading slashes, this is a path into the source dir.
      top_index = 2;
    } else {
      // One leading slash, this is a system-absolute path.
      top_index = 1;
    }
  }

  size_t dest_i = top_index;
  for (size_t src_i = top_index; src_i < path->size(); /* nothing */) {
    if (pathbuf[src_i] == '.') {
      if (src_i == 0 || IsSlash(pathbuf[src_i - 1])) {
        // Slash followed by a dot, see if it's something special.
        size_t consumed_len;
        switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) {
          case NOT_A_DIRECTORY:
            // Copy the dot to the output, it means nothing special.
            pathbuf[dest_i++] = pathbuf[src_i++];
            break;
          case DIRECTORY_CUR:
            // Current directory, just skip the input.
            src_i += consumed_len;
            break;
          case DIRECTORY_UP:
            // Back up over previous directory component. If we're already
            // at the top, preserve the "..".
            if (dest_i > top_index) {
              // The previous char was a slash, remove it.
              dest_i--;
            }

            if (dest_i == top_index) {
              if (is_relative) {
                // We're already at the beginning of a relative input, copy the
                // ".." and continue. We need the trailing slash if there was
                // one before (otherwise we're at the end of the input).
                pathbuf[dest_i++] = '.';
                pathbuf[dest_i++] = '.';
                if (consumed_len == 3)
                  pathbuf[dest_i++] = '/';

                // This also makes a new "root" that we can't delete by going
                // up more levels.  Otherwise "../.." would collapse to
                // nothing.
                top_index = dest_i;
              } else if (top_index == 2 && !source_root.empty()) {
                // |path| was passed in as a source-absolute path. Prepend
                // |source_root| to make |path| absolute. |source_root| must not
                // end with a slash unless we are at root.
                DCHECK(source_root.size() == 1u ||
                       !IsSlash(source_root[source_root.size() - 1u]));
                size_t source_root_len = source_root.size();

#if defined(OS_WIN)
                // On Windows, if the source_root does not start with a slash,
                // append one here for consistency.
                if (!IsSlash(source_root[0])) {
                  path->insert(0, "/" + std::string(source_root));
                  source_root_len++;
                } else {
                  path->insert(0, source_root.data(), source_root_len);
                }

                // Normalize slashes in source root portion.
                for (size_t i = 0; i < source_root_len; ++i) {
                  if ((*path)[i] == '\\')
                    (*path)[i] = '/';
                }
#else
                path->insert(0, source_root.data(), source_root_len);
#endif

                // |path| is now absolute, so |top_index| is 1. |dest_i| and
                // |src_i| should be incremented to keep the same relative
                // position. Consume the leading "//" by decrementing |dest_i|.
                top_index = 1;
                pathbuf = &(*path)[0];
                dest_i += source_root_len - 2;
                src_i += source_root_len;

                // Just find the previous slash or the beginning of input.
                while (dest_i > 0 && !IsSlash(pathbuf[dest_i - 1]))
                  dest_i--;
              }
              // Otherwise we're at the beginning of a system-absolute path, or
              // a source-absolute path for which we don't know the absolute
              // path. Don't allow ".." to go up another level, and just eat it.
            } else {
              // Just find the previous slash or the beginning of input.
              while (dest_i > 0 && !IsSlash(pathbuf[dest_i - 1]))
                dest_i--;
            }
            src_i += consumed_len;
        }
      } else {
        // Dot not preceded by a slash, copy it literally.
        pathbuf[dest_i++] = pathbuf[src_i++];
      }
    } else if (IsSlash(pathbuf[src_i])) {
      if (src_i > 0 && IsSlash(pathbuf[src_i - 1])) {
        // Two slashes in a row, skip over it.
        src_i++;
      } else {
        // Just one slash, copy it, normalizing to forward slash.
        pathbuf[dest_i] = '/';
        dest_i++;
        src_i++;
      }
    } else {
      // Input nothing special, just copy it.
      pathbuf[dest_i++] = pathbuf[src_i++];
    }
  }
  path->resize(dest_i);
}

void ConvertPathToSystem(std::string* path) {
#if defined(OS_WIN)
  for (size_t i = 0; i < path->size(); i++) {
    if ((*path)[i] == '/')
      (*path)[i] = '\\';
  }
#endif
}

std::string MakeRelativePath(const std::string& input,
                             const std::string& dest) {
#if defined(OS_WIN)
  // Make sure that absolute |input| path starts with a slash if |dest| path
  // does. Otherwise skipping common prefixes won't work properly. Ensure the
  // same for |dest| path too.
  if (IsPathAbsolute(input) && !IsSlash(input[0]) && IsSlash(dest[0])) {
    std::string corrected_input(1, dest[0]);
    corrected_input.append(input);
    return MakeRelativePath(corrected_input, dest);
  }
  if (IsPathAbsolute(dest) && !IsSlash(dest[0]) && IsSlash(input[0])) {
    std::string corrected_dest(1, input[0]);
    corrected_dest.append(dest);
    return MakeRelativePath(input, corrected_dest);
  }

  // Make sure that both absolute paths use the same drive letter case.
  if (IsPathAbsolute(input) && IsPathAbsolute(dest) && input.size() > 1 &&
      dest.size() > 1) {
    int letter_pos = base::IsAsciiAlpha(input[0]) ? 0 : 1;
    if (input[letter_pos] != dest[letter_pos] &&
        base::ToUpperASCII(input[letter_pos]) ==
            base::ToUpperASCII(dest[letter_pos])) {
      std::string corrected_input = input;
      corrected_input[letter_pos] = dest[letter_pos];
      return MakeRelativePath(corrected_input, dest);
    }
  }
#endif

  DCHECK(EndsWithSlash(dest));
  std::string ret;

  // Skip the common prefixes of the source and dest as long as they end in
  // a [back]slash or end the string. dest always ends with a (back)slash in
  // this function, so checking dest for just that is sufficient.
  size_t common_prefix_len = 0;
  size_t max_common_length = std::min(input.size(), dest.size());
  for (size_t i = common_prefix_len; i <= max_common_length; i++) {
    if ((IsSlash(input[i]) || input[i] == '\0') && IsSlash(dest[i]))
      common_prefix_len = i + 1;
    else if (input[i] != dest[i])
      break;
  }

  // Invert the dest dir starting from the end of the common prefix.
  for (size_t i = common_prefix_len; i < dest.size(); i++) {
    if (IsSlash(dest[i]))
      ret.append("../");
  }

  // Append any remaining unique input.
  if (common_prefix_len <= input.size())
    ret.append(&input[common_prefix_len], input.size() - common_prefix_len);
  else if (input.back() != '/' && !ret.empty())
    ret.pop_back();

  // If the result is still empty, the paths are the same.
  if (ret.empty())
    ret.push_back('.');

  return ret;
}

std::string RebasePath(const std::string& input,
                       const SourceDir& dest_dir,
                       std::string_view source_root) {
  std::string ret;
  DCHECK(source_root.empty() ||
         !base::EndsWith(source_root, "/", base::CompareCase::SENSITIVE));

  bool input_is_source_path =
      (input.size() >= 2 && input[0] == '/' && input[1] == '/');

  if (!source_root.empty() &&
      (!input_is_source_path || !dest_dir.is_source_absolute())) {
    std::string input_full;
    std::string dest_full;
    if (input_is_source_path) {
      input_full.append(source_root);
      input_full.push_back('/');
      input_full.append(input, 2, std::string::npos);
    } else {
      input_full.append(input);
    }
    if (dest_dir.is_source_absolute()) {
      dest_full.append(source_root);
      dest_full.push_back('/');
      dest_full.append(dest_dir.value(), 2, std::string::npos);
    } else {
#if defined(OS_WIN)
      // On Windows, SourceDir system-absolute paths start
      // with /, e.g. "/C:/foo/bar".
      const std::string& value = dest_dir.value();
      if (value.size() > 2 && value[2] == ':')
        dest_full.append(dest_dir.value().substr(1));
      else
        dest_full.append(dest_dir.value());
#else
      dest_full.append(dest_dir.value());
#endif
    }
    bool remove_slash = false;
    if (!EndsWithSlash(input_full)) {
      input_full.push_back('/');
      remove_slash = true;
    }
    ret = MakeRelativePath(input_full, dest_full);
    if (remove_slash && ret.size() > 1)
      ret.pop_back();
    return ret;
  }

  ret = MakeRelativePath(input, dest_dir.value());
  return ret;
}

base::FilePath ResolvePath(const std::string& value,
                           bool as_file,
                           const base::FilePath& source_root) {
  if (value.empty())
    return base::FilePath();

  std::string converted;
  if (!IsPathSourceAbsolute(value)) {
    if (value.size() > 2 && value[2] == ':') {
      // Windows path, strip the leading slash.
      converted.assign(&value[1], value.size() - 1);
    } else {
      converted.assign(value);
    }
    return base::FilePath(UTF8ToFilePath(converted));
  }

  // String the double-leading slash for source-relative paths.
  converted.assign(&value[2], value.size() - 2);

  if (as_file && source_root.empty())
    return UTF8ToFilePath(converted).NormalizePathSeparatorsTo('/');

  return source_root.Append(UTF8ToFilePath(converted))
      .NormalizePathSeparatorsTo('/');
}

std::string ResolveRelative(std::string_view input,
                            const std::string& value,
                            bool as_file,
                            std::string_view source_root) {
  std::string result;

  if (input.size() >= 2 && input[0] == '/' && input[1] == '/') {
    // Source-relative.
    result.assign(input.data(), input.size());
    if (!as_file) {
      if (!EndsWithSlash(result))
        result.push_back('/');
    }
    NormalizePath(&result, source_root);
    return result;
  } else if (IsPathAbsolute(input)) {
    if (source_root.empty() ||
        !MakeAbsolutePathRelativeIfPossible(source_root, input, &result)) {
#if defined(OS_WIN)
      if (input[0] != '/')  // See the file case for why we do this check.
        result = "/";
#endif
      result.append(input.data(), input.size());
    }
    NormalizePath(&result);
    if (!as_file) {
      if (!EndsWithSlash(result))
        result.push_back('/');
    }
    return result;
  }

  if (!source_root.empty()) {
    std::string absolute =
        FilePathToUTF8(ResolvePath(value, as_file, UTF8ToFilePath(source_root))
                           .AppendASCII(input)
                           .value());
    NormalizePath(&absolute);
    if (!MakeAbsolutePathRelativeIfPossible(source_root, absolute, &result)) {
#if defined(OS_WIN)
      if (absolute[0] != '/')  // See the file case for why we do this check.
        result = "/";
#endif
      result.append(absolute.data(), absolute.size());
    }
    if (!as_file && !EndsWithSlash(result))
      result.push_back('/');
    return result;
  }

  // With no source_root, there's nothing we can do about
  // e.g. input=../../../path/to/file and value=//source and we'll
  // erroneously return //file.
  result.reserve(value.size() + input.size());
  result.assign(value);
  result.append(input.data(), input.size());

  NormalizePath(&result);
  if (!as_file && !EndsWithSlash(result))
    result.push_back('/');

  return result;
}

std::string DirectoryWithNoLastSlash(const SourceDir& dir) {
  std::string ret;

  if (dir.value().empty()) {
    // Just keep input the same.
  } else if (dir.value() == "/") {
    ret.assign("/.");
  } else if (dir.value() == "//") {
    ret.assign("//.");
  } else {
    ret.assign(dir.value());
    ret.resize(ret.size() - 1);
  }
  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() || source_root.empty()) {
    // 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(std::move(result_str));
}

SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root) {
  base::FilePath cd;
  base::GetCurrentDirectory(&cd);
  return SourceDirForPath(source_root, cd);
}

std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) {
  // The default toolchain has no subdir.
  if (is_default)
    return std::string();

  // For now just assume the toolchain name is always a valid dir name. We may
  // want to clean up the in the future.
  return toolchain_label.name() + "/";
}

bool ContentsEqual(const base::FilePath& file_path, const std::string& data) {
  // Compare file and stream sizes first. Quick and will save us some time if
  // they are different sizes.
  int64_t file_size;
  if (!base::GetFileSize(file_path, &file_size) ||
      static_cast<size_t>(file_size) != data.size()) {
    return false;
  }

  std::string file_data;
  file_data.resize(file_size);
  if (!base::ReadFileToString(file_path, &file_data))
    return false;

  return file_data == data;
}

bool WriteFile(const base::FilePath& file_path,
               const std::string& data,
               Err* err) {
  // Create the directory if necessary.
  if (!base::CreateDirectory(file_path.DirName())) {
    if (err) {
      *err =
          Err(Location(), "Unable to create directory.",
              "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\".");
    }
    return false;
  }

  FileWriter writer;
  writer.Create(file_path);
  writer.Write(data);
  bool write_success = writer.Close();

  if (!write_success && err) {
    *err = Err(Location(), "Unable to write file.",
               "I was writing \"" + FilePathToUTF8(file_path) + "\".");
  }

  return write_success;
}

BuildDirContext::BuildDirContext(const Target* target)
    : BuildDirContext(target->settings()) {}

BuildDirContext::BuildDirContext(const Settings* settings)
    : BuildDirContext(settings->build_settings(),
                      settings->toolchain_label(),
                      settings->is_default()) {}

BuildDirContext::BuildDirContext(const Scope* execution_scope)
    : BuildDirContext(execution_scope->settings()) {}

BuildDirContext::BuildDirContext(const Scope* execution_scope,
                                 const Label& toolchain_label)
    : BuildDirContext(execution_scope->settings()->build_settings(),
                      toolchain_label,
                      execution_scope->settings()->default_toolchain_label() ==
                          toolchain_label) {}

BuildDirContext::BuildDirContext(const BuildSettings* in_build_settings,
                                 const Label& in_toolchain_label,
                                 bool in_is_default_toolchain)
    : build_settings(in_build_settings),
      toolchain_label(in_toolchain_label),
      is_default_toolchain(in_is_default_toolchain) {}

SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context,
                                 BuildDirType type) {
  return GetBuildDirAsOutputFile(context, type)
      .AsSourceDir(context.build_settings);
}

OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context,
                                   BuildDirType type) {
  OutputFile result(GetOutputSubdirName(context.toolchain_label,
                                        context.is_default_toolchain));
  DCHECK(result.value().empty() || result.value().back() == '/');

  if (type == BuildDirType::GEN)
    result.value().append("gen/");
  else if (type == BuildDirType::OBJ)
    result.value().append("obj/");
  else if (type == BuildDirType::PHONY)
    result.value().append("phony/");
  return result;
}

SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context,
                                    const SourceDir& source_dir,
                                    BuildDirType type) {
  return GetSubBuildDirAsOutputFile(context, source_dir, type)
      .AsSourceDir(context.build_settings);
}

OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context,
                                      const SourceDir& source_dir,
                                      BuildDirType type) {
  DCHECK(type != BuildDirType::TOOLCHAIN_ROOT);
  OutputFile result = GetBuildDirAsOutputFile(context, type);

  if (source_dir.is_source_absolute()) {
    std::string_view build_dir = context.build_settings->build_dir().value();
    std::string_view source_dir_path = source_dir.value();
    if (source_dir_path.substr(0, build_dir.size()) == build_dir) {
      // The source dir is source-absolute, but in the build directory
      // (e.g. `//out/Debug/gen/src/foo.cc` or
      // `//out/Debug/toolchain1/gen/foo.cc`), which happens for generated
      // sources. In this case, remove the build directory prefix, and replace
      // it with `BUILD_DIR`. This will create results like `obj/BUILD_DIR/gen`
      // or `toolchain2/obj/BUILD_DIR/toolchain1/gen` which look surprising,
      // but guarantee unicity.
      result.value().append("BUILD_DIR/");
      result.value().append(source_dir_path.substr(build_dir.size()));

    } else {
      // The source dir is source-absolute, so we trim off the two leading
      // slashes to append to the toolchain object directory.
      result.value().append(&source_dir.value()[2],
                            source_dir.value().size() - 2);
    }
  } else {
    // System-absolute.
    AppendFixedAbsolutePathSuffix(context.build_settings, source_dir, &result);
  }
  return result;
}

SourceDir GetBuildDirForTargetAsSourceDir(const Target* target,
                                          BuildDirType type) {
  return GetSubBuildDirAsSourceDir(BuildDirContext(target),
                                   target->label().dir(), type);
}

OutputFile GetBuildDirForTargetAsOutputFile(const Target* target,
                                            BuildDirType type) {
  return GetSubBuildDirAsOutputFile(BuildDirContext(target),
                                    target->label().dir(), type);
}

SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope,
                                             BuildDirType type) {
  if (type == BuildDirType::TOOLCHAIN_ROOT)
    return GetBuildDirAsSourceDir(BuildDirContext(scope), type);
  return GetSubBuildDirAsSourceDir(BuildDirContext(scope),
                                   scope->GetSourceDir(), type);
}
