Revert "Delete the remainder of platform specific code in FileSpec."

This reverts commit r298465 as it breaks
TestLLVM.TestHomeDirectory.test_tilde_home_directory.

llvm-svn: 298509
This commit is contained in:
Pavel Labath 2017-03-22 14:04:43 +00:00
parent 72dc254532
commit ed00beba12
19 changed files with 210 additions and 210 deletions

View File

@ -17,6 +17,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@ -538,6 +539,26 @@ public:
ConstString GetLastPathComponent() const;
//------------------------------------------------------------------
/// Resolves the user name at the beginning of \a src_path, and writes the
/// output
/// to \a dst_path. Note, \a src_path can contain other path components after
/// the
/// user name, they will be copied over, and if the path doesn't start with
/// "~" it
/// will also be copied over to \a dst_path.
///
/// @param[in] src_path
/// Input path to be resolved.
///
/// @param[in] dst_path
/// Buffer to store the resolved path.
//------------------------------------------------------------------
static void ResolveUsername(llvm::SmallVectorImpl<char> &path);
static size_t ResolvePartialUsername(llvm::StringRef partial_name,
StringList &matches);
enum EnumerateDirectoryResult {
eEnumerateDirectoryResultNext, // Enumerate next entry in the current
// directory

View File

@ -44,11 +44,6 @@ public:
/// \returns true if there were any matches, false otherwise.
virtual bool ResolvePartial(llvm::StringRef Expr,
llvm::StringSet<> &Output) = 0;
/// \brief Resolve an entire path that begins with a tilde expression,
/// replacing the username portion with the matched result.
bool ResolveFullPath(llvm::StringRef Expr,
llvm::SmallVectorImpl<char> &Output);
};
class StandardTildeExpressionResolver : public TildeExpressionResolver {

View File

@ -1,4 +1,5 @@
//===-- SBDeclaration.cpp ----------------------------------------*- C++-*-===//
//===-- SBDeclaration.cpp -----------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
@ -9,7 +10,6 @@
#include "lldb/API/SBDeclaration.h"
#include "lldb/API/SBStream.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"

View File

@ -13,7 +13,6 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"

View File

@ -14,7 +14,6 @@
#include "lldb/API/SBStream.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"

View File

@ -11,7 +11,6 @@
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBStream.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

View File

@ -7,13 +7,21 @@
//
//===----------------------------------------------------------------------===//
#include <fstream>
#include <set>
#include <string.h>
#include "llvm/Config/llvm-config.h"
#ifndef LLVM_ON_WIN32
#include <pwd.h>
#endif
#include "lldb/Host/FileSpec.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
@ -136,13 +144,115 @@ size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) {
} // end anonymous namespace
// Resolves the username part of a path of the form ~user/other/directories, and
// writes the result into dst_path. This will also resolve "~" to the current
// user.
// If you want to complete "~" to the list of users, pass it to
// ResolvePartialUsername.
void FileSpec::ResolveUsername(llvm::SmallVectorImpl<char> &path) {
#ifndef LLVM_ON_WIN32
if (path.empty() || path[0] != '~')
return;
llvm::StringRef path_str(path.data(), path.size());
size_t slash_pos = path_str.find('/', 1);
if (slash_pos == 1 || path.size() == 1) {
// A path of ~/ resolves to the current user's home dir
llvm::SmallString<64> home_dir;
// llvm::sys::path::home_directory() only checks if "HOME" is set in the
// environment and does nothing else to locate the user home directory
if (!llvm::sys::path::home_directory(home_dir)) {
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir && pw->pw_dir[0]) {
// Update our environemnt so llvm::sys::path::home_directory() works
// next time
setenv("HOME", pw->pw_dir, 0);
home_dir.assign(llvm::StringRef(pw->pw_dir));
} else {
return;
}
}
// Overwrite the ~ with the first character of the homedir, and insert
// the rest. This way we only trigger one move, whereas an insert
// followed by a delete (or vice versa) would trigger two.
path[0] = home_dir[0];
path.insert(path.begin() + 1, home_dir.begin() + 1, home_dir.end());
return;
}
auto username_begin = path.begin() + 1;
auto username_end = (slash_pos == llvm::StringRef::npos)
? path.end()
: (path.begin() + slash_pos);
size_t replacement_length = std::distance(path.begin(), username_end);
llvm::SmallString<20> username(username_begin, username_end);
struct passwd *user_entry = ::getpwnam(username.c_str());
if (user_entry != nullptr) {
// Copy over the first n characters of the path, where n is the smaller of
// the length
// of the home directory and the slash pos.
llvm::StringRef homedir(user_entry->pw_dir);
size_t initial_copy_length = std::min(homedir.size(), replacement_length);
auto src_begin = homedir.begin();
auto src_end = src_begin + initial_copy_length;
std::copy(src_begin, src_end, path.begin());
if (replacement_length > homedir.size()) {
// We copied the entire home directory, but the ~username portion of the
// path was
// longer, so there's characters that need to be removed.
path.erase(path.begin() + initial_copy_length, username_end);
} else if (replacement_length < homedir.size()) {
// We copied all the way up to the slash in the destination, but there's
// still more
// characters that need to be inserted.
path.insert(username_end, src_end, homedir.end());
}
} else {
// Unable to resolve username (user doesn't exist?)
path.clear();
}
#endif
}
size_t FileSpec::ResolvePartialUsername(llvm::StringRef partial_name,
StringList &matches) {
#if !defined(LLVM_ON_WIN32) && !defined(__ANDROID__)
size_t extant_entries = matches.GetSize();
setpwent();
struct passwd *user_entry;
partial_name = partial_name.drop_front();
std::set<std::string> name_list;
while ((user_entry = getpwent()) != NULL) {
if (llvm::StringRef(user_entry->pw_name).startswith(partial_name)) {
std::string tmp_buf("~");
tmp_buf.append(user_entry->pw_name);
tmp_buf.push_back('/');
name_list.insert(tmp_buf);
}
}
for (auto &name : name_list) {
matches.AppendString(name);
}
return matches.GetSize() - extant_entries;
#else
// Resolving home directories is not supported, just copy the path...
return 0;
#endif // #ifdef LLVM_ON_WIN32
}
void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
if (path.empty())
return;
llvm::SmallString<32> Source(path.begin(), path.end());
StandardTildeExpressionResolver Resolver;
Resolver.ResolveFullPath(Source, path);
#ifndef LLVM_ON_WIN32
if (path[0] == '~')
ResolveUsername(path);
#endif // #ifdef LLVM_ON_WIN32
// Save a copy of the original path that's passed in
llvm::SmallString<128> original_path(path.begin(), path.end());

View File

@ -15,7 +15,6 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/windows/AutoHandle.h"
#include "lldb/Host/windows/PosixApi.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"

View File

@ -14,7 +14,6 @@
#include <mutex> // std::once
#include "lldb/Host/windows/HostInfoWindows.h"
#include "lldb/Host/windows/PosixApi.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"

View File

@ -23,7 +23,6 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/TildeExpressionResolver.h"
// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"
@ -348,10 +347,10 @@ Error TargetList::CreateTargetInternal(Debugger &debugger,
FileSpec file(user_exe_path, false);
if (!file.Exists() && user_exe_path.startswith("~")) {
// we want to expand the tilde but we don't want to resolve any symbolic
// links so we can't use the FileSpec constructor's resolve flag
llvm::SmallString<64> unglobbed_path;
StandardTildeExpressionResolver Resolver;
Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
// links
// so we can't use the FileSpec constructor's resolve flag
llvm::SmallString<64> unglobbed_path(user_exe_path);
FileSpec::ResolveUsername(unglobbed_path);
if (unglobbed_path.empty())
file = FileSpec(user_exe_path, false);

View File

@ -68,22 +68,3 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr,
return true;
#endif
}
bool TildeExpressionResolver::ResolveFullPath(
StringRef Expr, llvm::SmallVectorImpl<char> &Output) {
Output.clear();
if (!Expr.startswith("~")) {
Output.append(Expr.begin(), Expr.end());
return false;
}
namespace path = llvm::sys::path;
StringRef Left =
Expr.take_until([](char c) { return path::is_separator(c); });
if (!ResolveExact(Left, Output))
return false;
Output.append(Expr.begin() + Left.size(), Expr.end());
return true;
}

View File

@ -2,7 +2,6 @@ add_custom_target(LLDBUnitTests)
set_target_properties(LLDBUnitTests PROPERTIES FOLDER "LLDB tests")
include_directories(${LLDB_SOURCE_ROOT})
include_directories(${LLDB_PROJECT_ROOT})
set(LLDB_GTEST_COMMON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/gtest_common.h)
if (MSVC)

View File

@ -4,7 +4,6 @@ add_lldb_unittest(InterpreterTests
LINK_LIBS
lldbInterpreter
lldbUtilityMocks
)
target_link_libraries(InterpreterTests

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/TildeExpressionResolver.h"
@ -17,8 +18,6 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "unittests/Utility/Mocks/MockTildeExpressionResolver.h"
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
using namespace llvm;
@ -37,6 +36,74 @@ using namespace lldb_private;
namespace {
class MockTildeExpressionResolver : public TildeExpressionResolver {
StringRef CurrentUser;
StringMap<StringRef> UserDirectories;
public:
explicit MockTildeExpressionResolver(StringRef CurrentUser, StringRef HomeDir)
: CurrentUser(CurrentUser) {
UserDirectories.insert(std::make_pair(CurrentUser, HomeDir));
}
void AddKnownUser(StringRef User, StringRef HomeDir) {
assert(UserDirectories.find(User) == UserDirectories.end());
UserDirectories.insert(std::make_pair(User, HomeDir));
}
void Clear() {
CurrentUser = StringRef();
UserDirectories.clear();
}
void SetCurrentUser(StringRef User) {
assert(UserDirectories.find(User) != UserDirectories.end());
CurrentUser = User;
}
bool ResolveExact(StringRef Expr, SmallVectorImpl<char> &Output) override {
Output.clear();
assert(!llvm::any_of(
Expr, [](char c) { return llvm::sys::path::is_separator(c); }));
assert(Expr.empty() || Expr[0] == '~');
Expr = Expr.drop_front();
if (Expr.empty()) {
auto Dir = UserDirectories[CurrentUser];
Output.append(Dir.begin(), Dir.end());
return true;
}
for (const auto &User : UserDirectories) {
if (User.getKey() != Expr)
continue;
Output.append(User.getValue().begin(), User.getValue().end());
return true;
}
return false;
}
bool ResolvePartial(StringRef Expr, StringSet<> &Output) override {
Output.clear();
assert(!llvm::any_of(
Expr, [](char c) { return llvm::sys::path::is_separator(c); }));
assert(Expr.empty() || Expr[0] == '~');
Expr = Expr.drop_front();
SmallString<16> QualifiedName("~");
for (const auto &User : UserDirectories) {
if (!User.getKey().startswith(Expr))
continue;
QualifiedName.resize(1);
QualifiedName.append(User.getKey().begin(), User.getKey().end());
Output.insert(QualifiedName);
}
return !Output.empty();
}
};
class CompletionTest : public testing::Test {
protected:
/// Unique temporary directory in which all created filesystem entities must

View File

@ -1,5 +1,3 @@
add_subdirectory(Mocks)
add_lldb_unittest(UtilityTests
ConstStringTest.cpp
ErrorTest.cpp
@ -7,14 +5,12 @@ add_lldb_unittest(UtilityTests
NameMatchesTest.cpp
StringExtractorTest.cpp
TaskPoolTest.cpp
TildeExpressionResolverTest.cpp
TimeoutTest.cpp
UriParserTest.cpp
VASprintfTest.cpp
LINK_LIBS
lldbUtility
lldbUtilityMocks
LINK_COMPONENTS
Support
)

View File

@ -1,9 +0,0 @@
add_lldb_library(lldbUtilityMocks
MockTildeExpressionResolver.cpp
LINK_LIBS
lldbUtility
LINK_COMPONENTS
Support
)

View File

@ -1,80 +0,0 @@
//===----------------- MockTildeExpressionResolver.cpp ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MockTildeExpressionResolver.h"
#include "llvm/Support/Path.h"
using namespace lldb_private;
using namespace llvm;
MockTildeExpressionResolver::MockTildeExpressionResolver(StringRef CurrentUser,
StringRef HomeDir)
: CurrentUser(CurrentUser) {
UserDirectories.insert(std::make_pair(CurrentUser, HomeDir));
}
void MockTildeExpressionResolver::AddKnownUser(StringRef User,
StringRef HomeDir) {
assert(UserDirectories.find(User) == UserDirectories.end());
UserDirectories.insert(std::make_pair(User, HomeDir));
}
void MockTildeExpressionResolver::Clear() {
CurrentUser = StringRef();
UserDirectories.clear();
}
void MockTildeExpressionResolver::SetCurrentUser(StringRef User) {
assert(UserDirectories.find(User) != UserDirectories.end());
CurrentUser = User;
}
bool MockTildeExpressionResolver::ResolveExact(StringRef Expr,
SmallVectorImpl<char> &Output) {
Output.clear();
assert(!llvm::any_of(
Expr, [](char c) { return llvm::sys::path::is_separator(c); }));
assert(Expr.empty() || Expr[0] == '~');
Expr = Expr.drop_front();
if (Expr.empty()) {
auto Dir = UserDirectories[CurrentUser];
Output.append(Dir.begin(), Dir.end());
return true;
}
for (const auto &User : UserDirectories) {
if (User.getKey() != Expr)
continue;
Output.append(User.getValue().begin(), User.getValue().end());
return true;
}
return false;
}
bool MockTildeExpressionResolver::ResolvePartial(StringRef Expr,
StringSet<> &Output) {
Output.clear();
assert(!llvm::any_of(
Expr, [](char c) { return llvm::sys::path::is_separator(c); }));
assert(Expr.empty() || Expr[0] == '~');
Expr = Expr.drop_front();
SmallString<16> QualifiedName("~");
for (const auto &User : UserDirectories) {
if (!User.getKey().startswith(Expr))
continue;
QualifiedName.resize(1);
QualifiedName.append(User.getKey().begin(), User.getKey().end());
Output.insert(QualifiedName);
}
return !Output.empty();
}

View File

@ -1,37 +0,0 @@
//===--------------------- TildeExpressionResolver.h ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_UNITTESTS_UTILITY_MOCKS_MOCK_TILDE_EXPRESSION_RESOLVER_H
#define LLDB_UNITTESTS_UTILITY_MOCKS_MOCK_TILDE_EXPRESSION_RESOLVER_H
#include "lldb/Utility/TildeExpressionResolver.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
namespace lldb_private {
class MockTildeExpressionResolver : public TildeExpressionResolver {
llvm::StringRef CurrentUser;
llvm::StringMap<llvm::StringRef> UserDirectories;
public:
MockTildeExpressionResolver(llvm::StringRef CurrentUser,
llvm::StringRef HomeDir);
void AddKnownUser(llvm::StringRef User, llvm::StringRef HomeDir);
void Clear();
void SetCurrentUser(llvm::StringRef User);
bool ResolveExact(llvm::StringRef Expr,
llvm::SmallVectorImpl<char> &Output) override;
bool ResolvePartial(llvm::StringRef Expr, llvm::StringSet<> &Output) override;
};
}
#endif

View File

@ -1,36 +0,0 @@
#include "gtest/gtest.h"
#include "Mocks/MockTildeExpressionResolver.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;
using namespace lldb_private;
TEST(TildeExpressionResolver, ResolveFullPath) {
MockTildeExpressionResolver Resolver("James", "/james");
Resolver.AddKnownUser("Kirk", "/kirk");
Resolver.AddKnownUser("Lars", "/lars");
Resolver.AddKnownUser("Jason", "/jason");
Resolver.AddKnownUser("Larry", "/larry");
SmallString<32> Result;
ASSERT_TRUE(Resolver.ResolveFullPath("~", Result));
EXPECT_EQ("/james", Result);
ASSERT_TRUE(Resolver.ResolveFullPath("~/", Result));
EXPECT_EQ("/james/", Result);
ASSERT_TRUE(Resolver.ResolveFullPath("~James/bar/baz", Result));
EXPECT_EQ("/james/bar/baz", Result);
ASSERT_TRUE(Resolver.ResolveFullPath("~Jason/", Result));
EXPECT_EQ("/jason/", Result);
ASSERT_TRUE(Resolver.ResolveFullPath("~Lars", Result));
EXPECT_EQ("/lars", Result);
ASSERT_FALSE(Resolver.ResolveFullPath("~Jaso", Result));
ASSERT_FALSE(Resolver.ResolveFullPath("", Result));
ASSERT_FALSE(Resolver.ResolveFullPath("Jason", Result));
}