Skip to content

Commit

Permalink
Converting absolute paths to relative on client side
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewtff committed Oct 9, 2017
1 parent b492412 commit fa24218
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 1 deletion.
2 changes: 2 additions & 0 deletions dist-clang.files
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,8 @@ src/client/clean_command.hh
src/client/command.cc
src/client/command.hh
src/client/command_test.cc
src/client/configuration.cc
src/client/configuration.hh
src/client/configuration.proto
src/client/driver_command.cc
src/client/driver_command.hh
Expand Down
3 changes: 3 additions & 0 deletions src/base/file_utils.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <base/c_utils.h>
#include <base/string_utils.h>

#include <stdio.h>

Expand Down Expand Up @@ -66,5 +67,7 @@ inline Path GetCurrentDir(String* error = nullptr) {
return current_dir;
}

String GetRelativePath(const String& current_dir, const String& path);

} // namespace base
} // namespace dist_clang
31 changes: 31 additions & 0 deletions src/base/file_utils_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,36 @@ Pair<time_t> GetModificationTime(const String& path, String* error) {
return {time_spec.tv_sec, time_spec.tv_nsec};
}

String GetRelativePath(const String& current_dir, const String& path) {
// Remove dot directories from inputs to make behavior more consistent.
std::regex dot_pattern("\\/./");
List<String> current_dir_parts, path_parts;
base::SplitString<'/'>(
std::regex_replace(current_dir, dot_pattern, "/"), current_dir_parts);
base::SplitString<'/'>(
std::regex_replace(path, dot_pattern, "/"), path_parts);

auto current_dir_part = current_dir_parts.begin();
auto path_part = path_parts.begin();
while (current_dir_part != current_dir_parts.end() &&
path_part != path_parts.end() &&
*current_dir_part == *path_part) {
++current_dir_part;
++path_part;
}

String result(".");
while (current_dir_part != current_dir_parts.end()) {
result += "/..";
++current_dir_part;
}

while (path_part != path_parts.end()) {
result += "/" + *path_part;
++path_part;
}
return result;
}

} // namespace base
} // namespace dist_clang
14 changes: 14 additions & 0 deletions src/base/file_utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,19 @@ TEST(FileUtilsTest, CreateDirectory) {
}
}

TEST(FileUtilsTest, GetRelativeDirectory) {
const String cur_dir = "/path/to/current/dir";
EXPECT_EQ("./out/bin/../lib/1.0.0",
base::GetRelativePath(
cur_dir, "/path/to/current/dir/./out/bin/../lib/1.0.0"));
EXPECT_EQ("./and/more",
base::GetRelativePath(cur_dir, "/path/to/current/dir/and/more"));
EXPECT_EQ("./../../other/dir",
base::GetRelativePath(cur_dir, "/path/to/other/dir"));
EXPECT_EQ("./../../../../absolute/path/to/other/dir",
base::GetRelativePath(cur_dir, "/absolute/path/to/other/dir"));
EXPECT_EQ("./.", base::GetRelativePath("/", "."));
}

} // namespace base
} // namespace dist_clang
7 changes: 6 additions & 1 deletion src/client/clang_command.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <base/assert.h>
#include <base/base.pb.h>
#include <base/c_utils.h>
#include <base/file_utils.h>
#include <base/logging.h>
#include <base/process_impl.h>

Expand Down Expand Up @@ -64,6 +65,8 @@ bool ClangCommand::FillFlags(base::proto::Flags* flags,
return true;
}

const String current_dir = base::GetCurrentDir();

flags->Clear();

llvm::opt::ArgStringList non_direct_list, non_cached_list, other_list;
Expand Down Expand Up @@ -158,8 +161,10 @@ bool ClangCommand::FillFlags(base::proto::Flags* flags,
replaced_command.replace(
pos, self_path.size(),
clang_path.substr(0, clang_path.find_last_of('/')));
const String relative_command =
base::GetRelativePath(current_dir, replaced_command);
non_direct_list.push_back(arg->getSpelling().data());
non_direct_list.push_back(tmp_list.MakeArgString(replaced_command));
non_direct_list.push_back(tmp_list.MakeArgString(relative_command));
LOG(VERBOSE) << "Replaced command: " << non_direct_list.back();
} else {
non_cached_list.push_back(arg->getSpelling().data());
Expand Down
58 changes: 58 additions & 0 deletions src/client/command_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,64 @@ TEST(CommandTest, FillFlagsAppendsRewriteIncludes) {
}
}

class ScopedCurrentDir {
public:
explicit ScopedCurrentDir(const Path& path)
: initial_dir_(base::GetCurrentDir()) {
base::ChangeCurrentDir(path);
}
~ScopedCurrentDir() {
base::ChangeCurrentDir(initial_dir_);
}
private:
const Path initial_dir_;
};

TEST(CommandTest, RelativeResourceDir) {
String self_path = base::GetCurrentDir();
ASSERT_TRUE(base::GetSelfPath(self_path));
const String input = "/test_file.cc";
const String output = "/tmp/output.o";
const String clang_path = self_path + "/path/to/llvm-build/bin/clang";
const String resource_dir = self_path + "/../lib/1.0.0";
const char* argv[] = {"clang++",
"-Xclang",
"-resource-dir",
"-Xclang",
resource_dir.c_str(),
"-c",
input.c_str(),
"-o",
output.c_str(),
nullptr};
const int argc = 9;

ScopedCurrentDir tests_binary_dir(std::move(self_path));

Command::List commands;
ASSERT_TRUE(Command::GenerateFromArgs(argc, argv, commands));
ASSERT_EQ(1u, commands.size());

auto& command = commands.front();
base::proto::Flags flags;
ASSERT_TRUE(command->CanFillFlags());
ASSERT_TRUE(command->FillFlags(&flags, clang_path, "1.0.0", false));

EXPECT_EQ(input, flags.input());
EXPECT_EQ(output, flags.output());
EXPECT_EQ("-emit-obj", flags.action());
EXPECT_EQ("c++", flags.language());
EXPECT_EQ("-cc1", *flags.other().begin());

EXPECT_NE(flags.non_direct().end(),
std::find(flags.non_direct().begin(), flags.non_direct().end(),
"./path/to/llvm-build/bin/../lib/1.0.0"));

if (HasNonfatalFailure()) {
FAIL() << command->RenderAllArgs();
}
}

TEST(CommandTest, AppendCleanTempFilesCommand) {
const String temp_input = base::CreateTempFile(".cc");
const char* argv[] = {"clang++", temp_input.c_str(), nullptr};
Expand Down

0 comments on commit fa24218

Please sign in to comment.