ENH: Move relative path to kwsys
This commit is contained in:
parent
f71a085f74
commit
e5a8e115bc
|
@ -1225,29 +1225,6 @@ bool cmSystemTools::CreateSymlink(const char* origName, const char* newName)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
std::vector<cmStdString> cmSystemTools::SplitString(const char* p, char sep, bool isPath)
|
|
||||||
{
|
|
||||||
std::string path = p;
|
|
||||||
std::vector<cmStdString> paths;
|
|
||||||
if(isPath && path[0] == '/')
|
|
||||||
{
|
|
||||||
path.erase(path.begin());
|
|
||||||
paths.push_back("/");
|
|
||||||
}
|
|
||||||
std::string::size_type pos1 = 0;
|
|
||||||
std::string::size_type pos2 = path.find(sep, pos1+1);
|
|
||||||
while(pos2 != std::string::npos)
|
|
||||||
{
|
|
||||||
paths.push_back(path.substr(pos1, pos2-pos1));
|
|
||||||
pos1 = pos2+1;
|
|
||||||
pos2 = path.find(sep, pos1+1);
|
|
||||||
}
|
|
||||||
paths.push_back(path.substr(pos1, pos2-pos1));
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// compute the relative path from here to there
|
// compute the relative path from here to there
|
||||||
std::string cmSystemTools::RelativePath(const char* local, const char* remote)
|
std::string cmSystemTools::RelativePath(const char* local, const char* remote)
|
||||||
{
|
{
|
||||||
|
@ -1259,74 +1236,9 @@ std::string cmSystemTools::RelativePath(const char* local, const char* remote)
|
||||||
{
|
{
|
||||||
cmSystemTools::Error("RelativePath must be passed a full path to remote: ", remote);
|
cmSystemTools::Error("RelativePath must be passed a full path to remote: ", remote);
|
||||||
}
|
}
|
||||||
|
return cmsys::SystemTools::RelativePath(local, remote);
|
||||||
// split up both paths into arrays of strings using / as a separator
|
|
||||||
std::vector<cmStdString> localSplit = cmSystemTools::SplitString(local, '/', true);
|
|
||||||
std::vector<cmStdString> remoteSplit = cmSystemTools::SplitString(remote, '/', true);
|
|
||||||
std::vector<cmStdString> commonPath; // store shared parts of path in this array
|
|
||||||
std::vector<cmStdString> finalPath; // store the final relative path here
|
|
||||||
// count up how many matching directory names there are from the start
|
|
||||||
unsigned int sameCount = 0;
|
|
||||||
while(
|
|
||||||
((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
|
|
||||||
&&
|
|
||||||
// for windows and apple do a case insensitive string compare
|
|
||||||
#if defined(_WIN32) || defined(__APPLE__)
|
|
||||||
cmSystemTools::Strucmp(localSplit[sameCount].c_str(),
|
|
||||||
remoteSplit[sameCount].c_str()) == 0
|
|
||||||
#else
|
|
||||||
localSplit[sameCount] == remoteSplit[sameCount]
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// put the common parts of the path into the commonPath array
|
|
||||||
commonPath.push_back(localSplit[sameCount]);
|
|
||||||
// erase the common parts of the path from the original path arrays
|
|
||||||
localSplit[sameCount] = "";
|
|
||||||
remoteSplit[sameCount] = "";
|
|
||||||
sameCount++;
|
|
||||||
}
|
|
||||||
// If there is nothing in common but the root directory, then just
|
|
||||||
// return the full path.
|
|
||||||
if(sameCount <= 1)
|
|
||||||
{
|
|
||||||
return remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each entry that is not common in the local path
|
|
||||||
// add a ../ to the finalpath array, this gets us out of the local
|
|
||||||
// path into the remote dir
|
|
||||||
for(unsigned int i = 0; i < localSplit.size(); ++i)
|
|
||||||
{
|
|
||||||
if(localSplit[i].size())
|
|
||||||
{
|
|
||||||
finalPath.push_back("../");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// for each entry that is not common in the remote path add it
|
|
||||||
// to the final path.
|
|
||||||
for(std::vector<cmStdString>::iterator i = remoteSplit.begin();
|
|
||||||
i != remoteSplit.end(); ++i)
|
|
||||||
{
|
|
||||||
if(i->size())
|
|
||||||
{
|
|
||||||
finalPath.push_back(*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::string relativePath; // result string
|
|
||||||
// now turn the array of directories into a unix path by puttint /
|
|
||||||
// between each entry that does not already have one
|
|
||||||
for(std::vector<cmStdString>::iterator i = finalPath.begin();
|
|
||||||
i != finalPath.end(); ++i)
|
|
||||||
{
|
|
||||||
if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
|
|
||||||
{
|
|
||||||
relativePath += "/";
|
|
||||||
}
|
|
||||||
relativePath += *i;
|
|
||||||
}
|
|
||||||
return relativePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class cmDeletingCharVector : public std::vector<char*>
|
class cmDeletingCharVector : public std::vector<char*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -285,14 +285,7 @@ public:
|
||||||
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
|
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
|
||||||
*/
|
*/
|
||||||
static std::string RelativePath(const char* local, const char* remote);
|
static std::string RelativePath(const char* local, const char* remote);
|
||||||
|
|
||||||
/** split a path by separator into an array of strings, default is /.
|
|
||||||
If isPath is true then the string is treated like a path and if
|
|
||||||
s starts with a / then the first element of the returned array will
|
|
||||||
be /, so /foo/bar will be [/, foo, bar]
|
|
||||||
*/
|
|
||||||
static std::vector<cmStdString> SplitString(const char* s, char separator = '/',
|
|
||||||
bool isPath = false);
|
|
||||||
/** put a string into the environment
|
/** put a string into the environment
|
||||||
of the form var=value */
|
of the form var=value */
|
||||||
static bool PutEnv(const char* value);
|
static bool PutEnv(const char* value);
|
||||||
|
|
|
@ -1130,6 +1130,29 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
|
||||||
|
{
|
||||||
|
std::string path = p;
|
||||||
|
std::vector<kwsys::String> paths;
|
||||||
|
if(isPath && path[0] == '/')
|
||||||
|
{
|
||||||
|
path.erase(path.begin());
|
||||||
|
paths.push_back("/");
|
||||||
|
}
|
||||||
|
std::string::size_type pos1 = 0;
|
||||||
|
std::string::size_type pos2 = path.find(sep, pos1+1);
|
||||||
|
while(pos2 != std::string::npos)
|
||||||
|
{
|
||||||
|
paths.push_back(path.substr(pos1, pos2-pos1));
|
||||||
|
pos1 = pos2+1;
|
||||||
|
pos2 = path.find(sep, pos1+1);
|
||||||
|
}
|
||||||
|
paths.push_back(path.substr(pos1, pos2-pos1));
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
int SystemTools::EstimateFormatLength(const char *format, va_list ap)
|
int SystemTools::EstimateFormatLength(const char *format, va_list ap)
|
||||||
{
|
{
|
||||||
|
@ -2395,6 +2418,85 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
|
||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute the relative path from here to there
|
||||||
|
std::string SystemTools::RelativePath(const char* local, const char* remote)
|
||||||
|
{
|
||||||
|
if(!SystemTools::FileIsFullPath(local))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if(!SystemTools::FileIsFullPath(remote))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// split up both paths into arrays of strings using / as a separator
|
||||||
|
std::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
|
||||||
|
std::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
|
||||||
|
std::vector<kwsys::String> commonPath; // store shared parts of path in this array
|
||||||
|
std::vector<kwsys::String> finalPath; // store the final relative path here
|
||||||
|
// count up how many matching directory names there are from the start
|
||||||
|
unsigned int sameCount = 0;
|
||||||
|
while(
|
||||||
|
((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
|
||||||
|
&&
|
||||||
|
// for windows and apple do a case insensitive string compare
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
cmSystemTools::Strucmp(localSplit[sameCount].c_str(),
|
||||||
|
remoteSplit[sameCount].c_str()) == 0
|
||||||
|
#else
|
||||||
|
localSplit[sameCount] == remoteSplit[sameCount]
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// put the common parts of the path into the commonPath array
|
||||||
|
commonPath.push_back(localSplit[sameCount]);
|
||||||
|
// erase the common parts of the path from the original path arrays
|
||||||
|
localSplit[sameCount] = "";
|
||||||
|
remoteSplit[sameCount] = "";
|
||||||
|
sameCount++;
|
||||||
|
}
|
||||||
|
// If there is nothing in common but the root directory, then just
|
||||||
|
// return the full path.
|
||||||
|
if(sameCount <= 1)
|
||||||
|
{
|
||||||
|
return remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each entry that is not common in the local path
|
||||||
|
// add a ../ to the finalpath array, this gets us out of the local
|
||||||
|
// path into the remote dir
|
||||||
|
for(unsigned int i = 0; i < localSplit.size(); ++i)
|
||||||
|
{
|
||||||
|
if(localSplit[i].size())
|
||||||
|
{
|
||||||
|
finalPath.push_back("../");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// for each entry that is not common in the remote path add it
|
||||||
|
// to the final path.
|
||||||
|
for(std::vector<kwsys_stl::string>::iterator i = remoteSplit.begin();
|
||||||
|
i != remoteSplit.end(); ++i)
|
||||||
|
{
|
||||||
|
if(i->size())
|
||||||
|
{
|
||||||
|
finalPath.push_back(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string relativePath; // result string
|
||||||
|
// now turn the array of directories into a unix path by puttint /
|
||||||
|
// between each entry that does not already have one
|
||||||
|
for(std::vector<kwsys_stl::string>::iterator i = finalPath.begin();
|
||||||
|
i != finalPath.end(); ++i)
|
||||||
|
{
|
||||||
|
if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
|
||||||
|
{
|
||||||
|
relativePath += "/";
|
||||||
|
}
|
||||||
|
relativePath += *i;
|
||||||
|
}
|
||||||
|
return relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
// OK, some fun stuff to get the actual case of a given path.
|
// OK, some fun stuff to get the actual case of a given path.
|
||||||
// Basically, you just need to call ShortPath, then GetLongPathName,
|
// Basically, you just need to call ShortPath, then GetLongPathName,
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <@KWSYS_NAMESPACE@/stl/map>
|
#include <@KWSYS_NAMESPACE@/stl/map>
|
||||||
|
|
||||||
#include <@KWSYS_NAMESPACE@/Configure.h>
|
#include <@KWSYS_NAMESPACE@/Configure.h>
|
||||||
|
#include <@KWSYS_NAMESPACE@/String.hxx>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
@ -176,6 +177,13 @@ public:
|
||||||
*/
|
*/
|
||||||
static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len);
|
static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len);
|
||||||
|
|
||||||
|
/** split a path by separator into an array of strings, default is /.
|
||||||
|
If isPath is true then the string is treated like a path and if
|
||||||
|
s starts with a / then the first element of the returned array will
|
||||||
|
be /, so /foo/bar will be [/, foo, bar]
|
||||||
|
*/
|
||||||
|
static std::vector<String> SplitString(const char* s, char separator = '/',
|
||||||
|
bool isPath = false);
|
||||||
/**
|
/**
|
||||||
* Perform a case-independent string comparison
|
* Perform a case-independent string comparison
|
||||||
*/
|
*/
|
||||||
|
@ -574,6 +582,16 @@ public:
|
||||||
static kwsys_stl::string FileExistsInParentDirectories(const char* fname,
|
static kwsys_stl::string FileExistsInParentDirectories(const char* fname,
|
||||||
const char* directory, const char* toplevel);
|
const char* directory, const char* toplevel);
|
||||||
|
|
||||||
|
/** compute the relative path from local to remote. local must
|
||||||
|
be a directory. remote can be a file or a directory.
|
||||||
|
Both remote and local must be full paths. Basically, if
|
||||||
|
you are in directory local and you want to access the file in remote
|
||||||
|
what is the relative path to do that. For example:
|
||||||
|
/a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
|
||||||
|
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
|
||||||
|
*/
|
||||||
|
static std::string RelativePath(const char* local, const char* remote);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return file's modified time
|
* Return file's modified time
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue