Commit 854feacc authored by Kitware Robot's avatar Kitware Robot Committed by Brad King

KWSys 2018-02-01 (04fcc449)

Code extracted from:

    https://gitlab.kitware.com/utils/kwsys.git

at commit 04fcc449646eb2ff3d701986946a1db60b2161b7 (master).

Upstream Shortlog
-----------------

Ben Boeckel (11):
      ba270398 SystemToolsAppendComponents: move strings when building components
      cfd0f1e6 JoinPath: push back as a character
      6770cb3e GetFilenameName: optionally don't search for \ on non-Windows
      22b189b0 ConvertToUnixSlashes: remove escaped space logic
      342d69a4 ConvertToUnixSlashes: short-circuit on hasDoubleSlash
      5dd87350 ConvertToUnixSlashes: remove pos1
      3b46b7c0 ConvertToUnixSlashes: bail early on empty paths
      55d1d6ab CollapseFullPath: reserve space for components
      68807138 CollapseFullPath: prefer .empty() to .length() == 0
      71a6de42 CollapseFullPath: refactor the overloads to share implementations
      318550c7 CheckCollapsePath: add more test cases
parent 7a756570
......@@ -496,6 +496,16 @@ IF(KWSYS_USE_SystemTools)
KWSYS_CXX_STAT_HAS_ST_MTIM=${KWSYS_CXX_STAT_HAS_ST_MTIM}
KWSYS_CXX_STAT_HAS_ST_MTIMESPEC=${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC}
)
IF(NOT WIN32)
IF(KWSYS_STANDALONE)
OPTION(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES "If true, Windows paths will be supported on Unix as well" ON)
ENDIF()
IF(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
SET_PROPERTY(SOURCE SystemTools.cxx testSystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS
KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES
)
ENDIF()
ENDIF()
# Disable getpwnam for static linux builds since it depends on shared glibc
GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
......
......@@ -1884,21 +1884,23 @@ static void ConvertVMSToUnix(std::string& path)
// convert windows slashes to unix slashes
void SystemTools::ConvertToUnixSlashes(std::string& path)
{
if (path.empty()) {
return;
}
const char* pathCString = path.c_str();
bool hasDoubleSlash = false;
#ifdef __VMS
ConvertVMSToUnix(path);
#else
const char* pos0 = pathCString;
const char* pos1 = pathCString + 1;
for (std::string::size_type pos = 0; *pos0; ++pos) {
// make sure we don't convert an escaped space to a unix slash
if (*pos0 == '\\' && *pos1 != ' ') {
if (*pos0 == '\\') {
path[pos] = '/';
}
// Also, reuse the loop to check for slash followed by another slash
if (*pos1 == '/' && *(pos1 + 1) == '/' && !hasDoubleSlash) {
if (!hasDoubleSlash && *(pos0 + 1) == '/' && *(pos0 + 2) == '/') {
#ifdef _WIN32
// However, on windows if the first characters are both slashes,
// then keep them that way, so that network paths can be handled.
......@@ -1911,43 +1913,41 @@ void SystemTools::ConvertToUnixSlashes(std::string& path)
}
pos0++;
pos1++;
}
if (hasDoubleSlash) {
SystemTools::ReplaceString(path, "//", "/");
}
#endif
// remove any trailing slash
if (!path.empty()) {
// if there is a tilda ~ then replace it with HOME
pathCString = path.c_str();
if (pathCString[0] == '~' &&
(pathCString[1] == '/' || pathCString[1] == '\0')) {
std::string homeEnv;
if (SystemTools::GetEnv("HOME", homeEnv)) {
path.replace(0, 1, homeEnv);
}
// if there is a tilda ~ then replace it with HOME
pathCString = path.c_str();
if (pathCString[0] == '~' &&
(pathCString[1] == '/' || pathCString[1] == '\0')) {
std::string homeEnv;
if (SystemTools::GetEnv("HOME", homeEnv)) {
path.replace(0, 1, homeEnv);
}
}
#ifdef HAVE_GETPWNAM
else if (pathCString[0] == '~') {
std::string::size_type idx = path.find_first_of("/\0");
std::string user = path.substr(1, idx - 1);
passwd* pw = getpwnam(user.c_str());
if (pw) {
path.replace(0, idx, pw->pw_dir);
}
else if (pathCString[0] == '~') {
std::string::size_type idx = path.find_first_of("/\0");
std::string user = path.substr(1, idx - 1);
passwd* pw = getpwnam(user.c_str());
if (pw) {
path.replace(0, idx, pw->pw_dir);
}
}
#endif
// remove trailing slash if the path is more than
// a single /
pathCString = path.c_str();
size_t size = path.size();
if (size > 1 && *path.rbegin() == '/') {
// if it is c:/ then do not remove the trailing slash
if (!((size == 3 && pathCString[1] == ':'))) {
path.resize(size - 1);
}
// remove trailing slash if the path is more than
// a single /
pathCString = path.c_str();
size_t size = path.size();
if (size > 1 && *path.rbegin() == '/') {
// if it is c:/ then do not remove the trailing slash
if (!((size == 3 && pathCString[1] == ':'))) {
path.resize(size - 1);
}
}
}
......@@ -3171,8 +3171,8 @@ void SystemTools::CheckTranslationPath(std::string& path)
static void SystemToolsAppendComponents(
std::vector<std::string>& out_components,
std::vector<std::string>::const_iterator first,
std::vector<std::string>::const_iterator last)
std::vector<std::string>::iterator first,
std::vector<std::string>::iterator last)
{
static const std::string up = "..";
static const std::string cur = ".";
......@@ -3182,7 +3182,11 @@ static void SystemToolsAppendComponents(
out_components.resize(out_components.size() - 1);
}
} else if (!i->empty() && *i != cur) {
#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
out_components.push_back(std::move(*i));
#else
out_components.push_back(*i);
#endif
}
}
}
......@@ -3190,63 +3194,18 @@ static void SystemToolsAppendComponents(
std::string SystemTools::CollapseFullPath(const std::string& in_path,
const char* in_base)
{
// Collect the output path components.
std::vector<std::string> out_components;
// Split the input path components.
std::vector<std::string> path_components;
SystemTools::SplitPath(in_path, path_components);
// If the input path is relative, start with a base path.
if (path_components[0].empty()) {
std::vector<std::string> base_components;
if (in_base) {
// Use the given base path.
SystemTools::SplitPath(in_base, base_components);
// Use the current working directory as a base path.
char buf[2048];
const char* res_in_base = in_base;
if (!res_in_base) {
if (const char* cwd = Getcwd(buf, 2048)) {
res_in_base = cwd;
} else {
// Use the current working directory as a base path.
char buf[2048];
if (const char* cwd = Getcwd(buf, 2048)) {
SystemTools::SplitPath(cwd, base_components);
} else {
base_components.push_back("");
}
res_in_base = "";
}
// Append base path components to the output path.
out_components.push_back(base_components[0]);
SystemToolsAppendComponents(out_components, base_components.begin() + 1,
base_components.end());
}
// Append input path components to the output path.
SystemToolsAppendComponents(out_components, path_components.begin(),
path_components.end());
// Transform the path back to a string.
std::string newPath = SystemTools::JoinPath(out_components);
// Update the translation table with this potentially new path. I am not
// sure why this line is here, it seems really questionable, but yet I
// would put good money that if I remove it something will break, basically
// from what I can see it created a mapping from the collapsed path, to be
// replaced by the input path, which almost completely does the opposite of
// this function, the only thing preventing this from happening a lot is
// that if the in_path has a .. in it, then it is not added to the
// translation table. So for most calls this either does nothing due to the
// .. or it adds a translation between identical paths as nothing was
// collapsed, so I am going to try to comment it out, and see what hits the
// fan, hopefully quickly.
// Commented out line below:
// SystemTools::AddTranslationPath(newPath, in_path);
SystemTools::CheckTranslationPath(newPath);
#ifdef _WIN32
newPath = SystemTools::GetActualCaseForPath(newPath);
SystemTools::ConvertToUnixSlashes(newPath);
#endif
// Return the reconstructed path.
return newPath;
return SystemTools::CollapseFullPath(in_path, std::string(res_in_base));
}
std::string SystemTools::CollapseFullPath(const std::string& in_path,
......@@ -3258,9 +3217,10 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
// Split the input path components.
std::vector<std::string> path_components;
SystemTools::SplitPath(in_path, path_components);
out_components.reserve(path_components.size());
// If the input path is relative, start with a base path.
if (path_components[0].length() == 0) {
if (path_components[0].empty()) {
std::vector<std::string> base_components;
// Use the given base path.
SystemTools::SplitPath(in_base, base_components);
......@@ -3619,7 +3579,7 @@ std::string SystemTools::JoinPath(
// All remaining components are always separated with a slash.
while (first != last) {
result.append("/");
result.push_back('/');
result.append((*first++));
}
......@@ -3715,7 +3675,12 @@ std::string SystemTools::GetFilenamePath(const std::string& filename)
*/
std::string SystemTools::GetFilenameName(const std::string& filename)
{
std::string::size_type slash_pos = filename.find_last_of("/\\");
#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
const char* separators = "/\\";
#else
char separators = '/';
#endif
std::string::size_type slash_pos = filename.find_last_of(separators);
if (slash_pos != std::string::npos) {
return filename.substr(slash_pos + 1);
} else {
......
......@@ -39,19 +39,19 @@ typedef unsigned short mode_t;
static const char* toUnixPaths[][2] = {
{ "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
{ "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
{ "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" },
{ "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
{ "c:/usr/local/bin/passwd", "c:/usr/local/bin/passwd" },
{ "c:/usr/lo cal/bin/pa sswd", "c:/usr/lo cal/bin/pa sswd" },
{ "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" },
{ "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
{ "\\usr\\local\\bin\\passwd", "/usr/local/bin/passwd" },
{ "\\usr\\lo cal\\bin\\pa sswd", "/usr/lo cal/bin/pa sswd" },
{ "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" },
{ "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
{ "c:\\usr\\local\\bin\\passwd", "c:/usr/local/bin/passwd" },
{ "c:\\usr\\lo cal\\bin\\pa sswd", "c:/usr/lo cal/bin/pa sswd" },
{ "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" },
{ "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
{ "\\\\usr\\local\\bin\\passwd", "//usr/local/bin/passwd" },
{ "\\\\usr\\lo cal\\bin\\pa sswd", "//usr/lo cal/bin/pa sswd" },
{ "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo\\ cal/bin/pa\\ sswd" },
{ "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo/ cal/bin/pa/ sswd" },
{ KWSYS_NULLPTR, KWSYS_NULLPTR }
};
......@@ -700,6 +700,16 @@ static bool CheckCollapsePath()
bool res = true;
res &= CheckCollapsePath("/usr/share/*", "/usr/share/*");
res &= CheckCollapsePath("C:/Windows/*", "C:/Windows/*");
res &= CheckCollapsePath("/usr/share/../lib", "/usr/lib");
res &= CheckCollapsePath("/usr/share/./lib", "/usr/share/lib");
res &= CheckCollapsePath("/usr/share/../../lib", "/lib");
res &= CheckCollapsePath("/usr/share/.././../lib", "/lib");
res &= CheckCollapsePath("/../lib", "/lib");
res &= CheckCollapsePath("/../lib/", "/lib");
res &= CheckCollapsePath("/", "/");
res &= CheckCollapsePath("C:/", "C:/");
res &= CheckCollapsePath("C:/../", "C:/");
res &= CheckCollapsePath("C:/../../", "C:/");
return res;
}
......@@ -764,20 +774,26 @@ static bool CheckGetFilenameName()
const char* windowsFilepath = "C:\\somewhere\\something";
const char* unixFilepath = "/somewhere/something";
std::string expectedFilename = "something";
#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
std::string expectedWindowsFilename = "something";
#else
std::string expectedWindowsFilename = "C:\\somewhere\\something";
#endif
std::string expectedUnixFilename = "something";
bool res = true;
std::string filename = kwsys::SystemTools::GetFilenameName(windowsFilepath);
if (filename != expectedFilename) {
if (filename != expectedWindowsFilename) {
std::cerr << "GetFilenameName(" << windowsFilepath << ") yielded "
<< filename << " instead of " << expectedFilename << std::endl;
<< filename << " instead of " << expectedWindowsFilename
<< std::endl;
res = false;
}
filename = kwsys::SystemTools::GetFilenameName(unixFilepath);
if (filename != expectedFilename) {
if (filename != expectedUnixFilename) {
std::cerr << "GetFilenameName(" << unixFilepath << ") yielded " << filename
<< " instead of " << expectedFilename << std::endl;
<< " instead of " << expectedUnixFilename << std::endl;
res = false;
}
return res;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment