mirror of https://github.com/AxioDL/metaforce.git
Added link resolution to ProjectPath
This commit is contained in:
parent
f78aa15980
commit
f0325f7946
|
@ -467,6 +467,28 @@ public:
|
|||
*/
|
||||
const SystemString& getAbsolutePath() const {return m_projRoot;}
|
||||
|
||||
/**
|
||||
* @brief Make absolute path project relative
|
||||
* @param absPath
|
||||
* @return
|
||||
*/
|
||||
const SystemString getProjectRelativeFromAbsolute(const SystemString& absPath) const
|
||||
{
|
||||
if (absPath.size() > m_projRoot.size())
|
||||
{
|
||||
if (!absPath.compare(0, m_projRoot.size(), m_projRoot))
|
||||
{
|
||||
auto beginIt = absPath.cbegin() + m_projRoot.size();
|
||||
while (*beginIt == _S('/') || *beginIt == _S('\\'))
|
||||
++beginIt;
|
||||
return SystemString(beginIt, absPath.cend());
|
||||
}
|
||||
}
|
||||
LogModule.report(LogVisor::FatalError, "unable to resolve '%s' as project relative '%s'",
|
||||
absPath.c_str(), m_projRoot.c_str());
|
||||
return SystemString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create directory at path
|
||||
*
|
||||
|
@ -686,7 +708,8 @@ public:
|
|||
PT_NONE, /**< If path doesn't reference a valid filesystem entity, this is returned */
|
||||
PT_FILE, /**< Singular file path (confirmed with filesystem) */
|
||||
PT_DIRECTORY, /**< Singular directory path (confirmed with filesystem) */
|
||||
PT_GLOB /**< Glob-path (whenever one or more '*' occurs in syntax) */
|
||||
PT_GLOB, /**< Glob-path (whenever one or more '*' occurs in syntax) */
|
||||
PT_LINK /**< Link (symlink on POSIX, ShellLink on Windows) */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -705,6 +728,12 @@ public:
|
|||
*/
|
||||
Time getModtime() const;
|
||||
|
||||
/**
|
||||
* @brief For link paths, get the target path
|
||||
* @return Target path
|
||||
*/
|
||||
ProjectPath resolveLink() const;
|
||||
|
||||
/**
|
||||
* @brief Insert directory children into list
|
||||
* @param outPaths list to append children to
|
||||
|
|
|
@ -9,5 +9,6 @@
|
|||
void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
|
||||
HRESULT CreateShellLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc);
|
||||
HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferSize);
|
||||
bool TestShellLink(LPCWSTR lpszLinkFile);
|
||||
|
||||
#endif // _HECL_WINSUPPORT_H_
|
||||
|
|
|
@ -8,15 +8,22 @@ static const SystemRegex regGLOB(_S("\\*"), SystemRegex::ECMAScript|SystemRegex:
|
|||
static const SystemRegex regPATHCOMP(_S("[/\\\\]*([^/\\\\]+)"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||
static const SystemRegex regDRIVELETTER(_S("^([^/]*)/"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||
|
||||
static SystemString canonRelPath(const SystemString& path)
|
||||
static bool IsAbsolute(const SystemString& path)
|
||||
{
|
||||
/* Absolute paths not allowed */
|
||||
if (path[0] == _S('/') || path[0] == _S('\\'))
|
||||
{
|
||||
LogModule.report(LogVisor::Error, "Absolute path provided; expected relative: %s", path.c_str());
|
||||
return _S(".");
|
||||
}
|
||||
#if WIN32
|
||||
if (path.size() && (path[0] == _S('\\') || path[0] == _S('/')))
|
||||
return true;
|
||||
if (path.size() >= 2 && iswalpha(path[0]) && path[1] == _S(':'))
|
||||
return true;
|
||||
#else
|
||||
if (path[0] == _S('/'))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static SystemString CanonRelPath(const SystemString& path)
|
||||
{
|
||||
/* Tokenize Path */
|
||||
std::vector<SystemString> comps;
|
||||
HECL::SystemRegexMatch matches;
|
||||
|
@ -48,18 +55,29 @@ static SystemString canonRelPath(const SystemString& path)
|
|||
SystemString retval = *it;
|
||||
for (++it ; it != comps.end() ; ++it)
|
||||
{
|
||||
retval += _S('/');
|
||||
retval += *it;
|
||||
if ((*it).size())
|
||||
{
|
||||
retval += _S('/');
|
||||
retval += *it;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
return _S(".");
|
||||
}
|
||||
|
||||
static SystemString CanonRelPath(const SystemString& path, const ProjectRootPath& projectRoot)
|
||||
{
|
||||
/* Absolute paths not allowed; attempt to make project-relative */
|
||||
if (IsAbsolute(path))
|
||||
return CanonRelPath(projectRoot.getProjectRelativeFromAbsolute(path));
|
||||
return CanonRelPath(path);
|
||||
}
|
||||
|
||||
void ProjectPath::assign(Database::Project& project, const SystemString& path)
|
||||
{
|
||||
m_proj = &project;
|
||||
m_relPath = canonRelPath(path);
|
||||
m_relPath = CanonRelPath(path);
|
||||
m_absPath = project.getProjectRootPath().getAbsolutePath() + _S('/') + m_relPath;
|
||||
SanitizePath(m_relPath);
|
||||
SanitizePath(m_absPath);
|
||||
|
@ -89,7 +107,7 @@ void ProjectPath::assign(Database::Project& project, const std::string& path)
|
|||
void ProjectPath::assign(const ProjectPath& parentPath, const SystemString& path)
|
||||
{
|
||||
m_proj = parentPath.m_proj;
|
||||
m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + path);
|
||||
m_relPath = CanonRelPath(parentPath.m_relPath + _S('/') + path);
|
||||
m_absPath = m_proj->getProjectRootPath().getAbsolutePath() + _S('/') + m_relPath;
|
||||
SanitizePath(m_relPath);
|
||||
SanitizePath(m_absPath);
|
||||
|
@ -124,6 +142,16 @@ ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) cons
|
|||
|
||||
ProjectPath::PathType ProjectPath::getPathType() const
|
||||
{
|
||||
#if WIN32
|
||||
if (TestShellLink(m_absPath.c_str()))
|
||||
return PT_LINK;
|
||||
#else
|
||||
HECL::Sstat lnStat;
|
||||
if (lstat(m_absPath.c_str(), &lnStat))
|
||||
return PT_NONE;
|
||||
if (S_ISLNK(lnStat.st_mode))
|
||||
return PT_LINK;
|
||||
#endif
|
||||
if (std::regex_search(m_absPath, regGLOB))
|
||||
return PT_GLOB;
|
||||
Sstat theStat;
|
||||
|
@ -184,6 +212,22 @@ Time ProjectPath::getModtime() const
|
|||
return Time();
|
||||
}
|
||||
|
||||
ProjectPath ProjectPath::resolveLink() const
|
||||
{
|
||||
#if WIN32
|
||||
wchar_t target[2048];
|
||||
if (FAILED(ResolveShellLink(m_absPath.c_str(), target, 2048)))
|
||||
LogModule.report(LogVisor::FatalError, _S("unable to resolve link '%s'"), m_absPath.c_str());
|
||||
#else
|
||||
char target[2048];
|
||||
ssize_t targetSz;
|
||||
if ((targetSz = readlink(m_absPath.c_str(), target, 2048)) < 0)
|
||||
LogModule.report(LogVisor::FatalError, _S("unable to resolve link '%s': %s"), m_absPath.c_str(), strerror(errno));
|
||||
target[targetSz] = '\0';
|
||||
#endif
|
||||
return ProjectPath(*this, target);
|
||||
}
|
||||
|
||||
static void _recursiveGlob(Database::Project& proj,
|
||||
std::vector<ProjectPath>& outPaths,
|
||||
size_t level,
|
||||
|
|
|
@ -106,8 +106,6 @@ HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferS
|
|||
|
||||
*lpszPath = 0; // Assume failure
|
||||
|
||||
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
|
||||
// has already been called.
|
||||
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
|
@ -157,4 +155,46 @@ HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferS
|
|||
return hres;
|
||||
}
|
||||
|
||||
bool TestShellLink(LPCWSTR lpszLinkFile)
|
||||
{
|
||||
HRESULT hres;
|
||||
IShellLink* psl;
|
||||
|
||||
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
IPersistFile* ppf;
|
||||
|
||||
// Get a pointer to the IPersistFile interface.
|
||||
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
// Load the shortcut.
|
||||
hres = ppf->Load(lpszLinkFile, STGM_READ);
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
// Resolve the link.
|
||||
HWND hwnd = GetConsoleWindow();
|
||||
if (!hwnd)
|
||||
hwnd = GetTopWindow(nullptr);
|
||||
hres = psl->Resolve(hwnd, 0);
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Release the pointer to the IPersistFile interface.
|
||||
ppf->Release();
|
||||
}
|
||||
|
||||
// Release the pointer to the IShellLink interface.
|
||||
psl->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue