mirror of https://github.com/AxioDL/metaforce.git
Link removal (complexity not worth it)
This commit is contained in:
parent
b2a2cd3934
commit
e6aeff08a3
|
@ -1 +1 @@
|
||||||
Subproject commit ca0ff04340bd6a25eed1e738e6d976d4a10acf31
|
Subproject commit b317ac9d9f5205421ab9ae4b919f816c1c1e1ca8
|
|
@ -194,24 +194,6 @@ static inline void MakeDir(const wchar_t* dir)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void MakeLink(const SystemChar* target, const SystemChar* linkPath)
|
|
||||||
{
|
|
||||||
#if _WIN32
|
|
||||||
HRESULT res = CreateShellLink(target, linkPath, _S("HECL Link")); /* :(( */
|
|
||||||
if (!SUCCEEDED(res))
|
|
||||||
{
|
|
||||||
LPWSTR messageBuffer = nullptr;
|
|
||||||
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL, res, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); /* :((( */
|
|
||||||
LogModule.report(LogVisor::FatalError, _S("MakeLink(%s, %s): %s"), target, linkPath, messageBuffer);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (symlink(target, linkPath)) /* :) */
|
|
||||||
if (errno != EEXIST)
|
|
||||||
LogModule.report(LogVisor::FatalError, "MakeLink(%s, %s): %s", target, linkPath, strerror(errno));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline SystemChar* Getcwd(SystemChar* buf, int maxlen)
|
static inline SystemChar* Getcwd(SystemChar* buf, int maxlen)
|
||||||
{
|
{
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
|
@ -1052,7 +1034,6 @@ public:
|
||||||
File, /**< Singular file path (confirmed with filesystem) */
|
File, /**< Singular file path (confirmed with filesystem) */
|
||||||
Directory, /**< Singular directory path (confirmed with filesystem) */
|
Directory, /**< Singular directory path (confirmed with filesystem) */
|
||||||
Glob, /**< Glob-path (whenever one or more '*' occurs in syntax) */
|
Glob, /**< Glob-path (whenever one or more '*' occurs in syntax) */
|
||||||
Link /**< Link (symlink on POSIX, ShellLink on Windows) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1071,12 +1052,6 @@ public:
|
||||||
*/
|
*/
|
||||||
Time getModtime() const;
|
Time getModtime() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief For link paths, get the target path
|
|
||||||
* @return Target path
|
|
||||||
*/
|
|
||||||
ProjectPath resolveLink() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Insert directory children into list
|
* @brief Insert directory children into list
|
||||||
* @param outPaths list to append children to
|
* @param outPaths list to append children to
|
||||||
|
@ -1115,20 +1090,6 @@ public:
|
||||||
*/
|
*/
|
||||||
void makeDir() const {MakeDir(m_absPath.c_str());}
|
void makeDir() const {MakeDir(m_absPath.c_str());}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create relative symbolic link at calling path targeting another path
|
|
||||||
* @param target Path to target
|
|
||||||
*/
|
|
||||||
void makeLinkTo(const ProjectPath& target) const
|
|
||||||
{
|
|
||||||
SystemString relTarget;
|
|
||||||
for (SystemChar ch : m_relPath)
|
|
||||||
if (ch == _S('/') || ch == _S('\\'))
|
|
||||||
relTarget += _S("../");
|
|
||||||
relTarget += target.m_relPath;
|
|
||||||
MakeLink(relTarget.c_str(), m_absPath.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fetch project that contains path
|
* @brief Fetch project that contains path
|
||||||
* @return Project
|
* @return Project
|
||||||
|
|
|
@ -10,8 +10,5 @@
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
|
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_
|
#endif // _HECL_WINSUPPORT_H_
|
||||||
|
|
|
@ -409,24 +409,8 @@ static void VisitDirectory(const ProjectPath& dir,
|
||||||
/* Pass 1: child file count */
|
/* Pass 1: child file count */
|
||||||
int childFileCount = 0;
|
int childFileCount = 0;
|
||||||
for (auto& child : children)
|
for (auto& child : children)
|
||||||
{
|
if (child.second.getPathType() == ProjectPath::Type::File)
|
||||||
switch (child.second.getPathType())
|
|
||||||
{
|
|
||||||
case ProjectPath::Type::File:
|
|
||||||
{
|
|
||||||
++childFileCount;
|
++childFileCount;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProjectPath::Type::Link:
|
|
||||||
{
|
|
||||||
ProjectPath target = child.second.resolveLink();
|
|
||||||
if (target.getPathType() == ProjectPath::Type::File)
|
|
||||||
++childFileCount;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pass 2: child files */
|
/* Pass 2: child files */
|
||||||
int progNum = 0;
|
int progNum = 0;
|
||||||
|
@ -434,25 +418,10 @@ static void VisitDirectory(const ProjectPath& dir,
|
||||||
progress.changeDir(dir.getLastComponent());
|
progress.changeDir(dir.getLastComponent());
|
||||||
for (auto& child : children)
|
for (auto& child : children)
|
||||||
{
|
{
|
||||||
switch (child.second.getPathType())
|
if (child.second.getPathType() == ProjectPath::Type::File)
|
||||||
{
|
|
||||||
case ProjectPath::Type::File:
|
|
||||||
{
|
{
|
||||||
progress.changeFile(child.first.c_str(), progNum++/progDenom);
|
progress.changeFile(child.first.c_str(), progNum++/progDenom);
|
||||||
VisitFile(child.second, force, fast, specInsts, progress);
|
VisitFile(child.second, force, fast, specInsts, progress);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProjectPath::Type::Link:
|
|
||||||
{
|
|
||||||
ProjectPath target = child.second.resolveLink();
|
|
||||||
if (target.getPathType() == ProjectPath::Type::File)
|
|
||||||
{
|
|
||||||
progress.changeFile(target.getLastComponent(), progNum++/progDenom);
|
|
||||||
VisitFile(target, force, fast, specInsts, progress);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.reportDirComplete();
|
progress.reportDirComplete();
|
||||||
|
@ -486,24 +455,8 @@ static void VisitGlob(const ProjectPath& path,
|
||||||
/* Pass 1: child file count */
|
/* Pass 1: child file count */
|
||||||
int childFileCount = 0;
|
int childFileCount = 0;
|
||||||
for (ProjectPath& child : children)
|
for (ProjectPath& child : children)
|
||||||
{
|
if (child.getPathType() == ProjectPath::Type::File)
|
||||||
switch (child.getPathType())
|
|
||||||
{
|
|
||||||
case ProjectPath::Type::File:
|
|
||||||
{
|
|
||||||
++childFileCount;
|
++childFileCount;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProjectPath::Type::Link:
|
|
||||||
{
|
|
||||||
ProjectPath target = path.resolveLink();
|
|
||||||
if (target.getPathType() == ProjectPath::Type::File)
|
|
||||||
++childFileCount;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pass 2: child files */
|
/* Pass 2: child files */
|
||||||
int progNum = 0;
|
int progNum = 0;
|
||||||
|
@ -511,45 +464,19 @@ static void VisitGlob(const ProjectPath& path,
|
||||||
progress.changeDir(path.getLastComponent());
|
progress.changeDir(path.getLastComponent());
|
||||||
for (ProjectPath& child : children)
|
for (ProjectPath& child : children)
|
||||||
{
|
{
|
||||||
switch (child.getPathType())
|
if (child.getPathType() == ProjectPath::Type::File)
|
||||||
{
|
|
||||||
case ProjectPath::Type::File:
|
|
||||||
{
|
{
|
||||||
progress.changeFile(child.getLastComponent(), progNum++/progDenom);
|
progress.changeFile(child.getLastComponent(), progNum++/progDenom);
|
||||||
VisitFile(child, force, fast, specInsts, progress);
|
VisitFile(child, force, fast, specInsts, progress);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProjectPath::Type::Link:
|
|
||||||
{
|
|
||||||
ProjectPath target = path.resolveLink();
|
|
||||||
if (target.getPathType() == ProjectPath::Type::File)
|
|
||||||
{
|
|
||||||
progress.changeFile(target.getLastComponent(), progNum++/progDenom);
|
|
||||||
VisitFile(target, force, fast, specInsts, progress);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.reportDirComplete();
|
progress.reportDirComplete();
|
||||||
|
|
||||||
/* Pass 3: child directories */
|
/* Pass 3: child directories */
|
||||||
if (recursive)
|
if (recursive)
|
||||||
{
|
|
||||||
for (ProjectPath& child : children)
|
for (ProjectPath& child : children)
|
||||||
{
|
if (child.getPathType() == ProjectPath::Type::Directory)
|
||||||
switch (child.getPathType())
|
|
||||||
{
|
|
||||||
case ProjectPath::Type::Directory:
|
|
||||||
{
|
|
||||||
VisitDirectory(child, recursive, force, fast, specInsts, progress);
|
VisitDirectory(child, recursive, force, fast, specInsts, progress);
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Project::cookPath(const ProjectPath& path, FProgress progress,
|
bool Project::cookPath(const ProjectPath& path, FProgress progress,
|
||||||
|
@ -573,16 +500,6 @@ bool Project::cookPath(const ProjectPath& path, FProgress progress,
|
||||||
VisitFile(path, force, fast, specInsts, cookProg);
|
VisitFile(path, force, fast, specInsts, cookProg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ProjectPath::Type::Link:
|
|
||||||
{
|
|
||||||
ProjectPath target = path.resolveLink();
|
|
||||||
if (target.getPathType() == ProjectPath::Type::File)
|
|
||||||
{
|
|
||||||
cookProg.changeFile(target.getLastComponent(), 0.0);
|
|
||||||
VisitFile(target, force, fast, specInsts, cookProg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ProjectPath::Type::Directory:
|
case ProjectPath::Type::Directory:
|
||||||
{
|
{
|
||||||
VisitDirectory(path, recursive, force, fast, specInsts, cookProg);
|
VisitDirectory(path, recursive, force, fast, specInsts, cookProg);
|
||||||
|
|
|
@ -128,16 +128,6 @@ ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) cons
|
||||||
|
|
||||||
ProjectPath::Type ProjectPath::getPathType() const
|
ProjectPath::Type ProjectPath::getPathType() const
|
||||||
{
|
{
|
||||||
#if WIN32
|
|
||||||
if (TestShellLink(m_absPath.c_str()))
|
|
||||||
return Type::Link;
|
|
||||||
#else
|
|
||||||
HECL::Sstat lnStat;
|
|
||||||
if (lstat(m_absPath.c_str(), &lnStat))
|
|
||||||
return Type::None;
|
|
||||||
if (S_ISLNK(lnStat.st_mode))
|
|
||||||
return Type::Link;
|
|
||||||
#endif
|
|
||||||
if (std::regex_search(m_absPath, regGLOB))
|
if (std::regex_search(m_absPath, regGLOB))
|
||||||
return Type::Glob;
|
return Type::Glob;
|
||||||
Sstat theStat;
|
Sstat theStat;
|
||||||
|
@ -191,22 +181,6 @@ Time ProjectPath::getModtime() const
|
||||||
return Time();
|
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(getParentPath(), target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _recursiveGlob(Database::Project& proj,
|
static void _recursiveGlob(Database::Project& proj,
|
||||||
std::vector<ProjectPath>& outPaths,
|
std::vector<ProjectPath>& outPaths,
|
||||||
size_t level,
|
size_t level,
|
||||||
|
|
|
@ -34,169 +34,3 @@ void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clearly, MS doesn't require enough headers for this */
|
|
||||||
#include "winnls.h"
|
|
||||||
#include "shobjidl.h"
|
|
||||||
#include "objbase.h"
|
|
||||||
#include "objidl.h"
|
|
||||||
#include "shlguid.h"
|
|
||||||
#include "strsafe.h"
|
|
||||||
|
|
||||||
#define HECL_MAX_PATH 2048
|
|
||||||
|
|
||||||
HRESULT CreateShellLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
|
|
||||||
{
|
|
||||||
std::wstring targetStr(lpszPathObj);
|
|
||||||
for (wchar_t& ch : targetStr)
|
|
||||||
if (ch == L'/')
|
|
||||||
ch = L'\\';
|
|
||||||
std::wstring linkStr(lpszPathLink);
|
|
||||||
linkStr += L".lnk";
|
|
||||||
for (wchar_t& ch : linkStr)
|
|
||||||
if (ch == L'/')
|
|
||||||
ch = L'\\';
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
IShellLink* psl;
|
|
||||||
|
|
||||||
// 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))
|
|
||||||
{
|
|
||||||
IPersistFile* ppf;
|
|
||||||
|
|
||||||
// Set the path to the shortcut target and add the description.
|
|
||||||
WCHAR targetBuf[HECL_MAX_PATH];
|
|
||||||
WCHAR linkBuf[HECL_MAX_PATH];
|
|
||||||
WCHAR* linkFinalPart = nullptr;
|
|
||||||
GetFullPathNameW(linkStr.c_str(), HECL_MAX_PATH, linkBuf, &linkFinalPart);
|
|
||||||
if (linkFinalPart != linkBuf)
|
|
||||||
*(linkFinalPart-1) = L'\0';
|
|
||||||
StringCbPrintfW(targetBuf, HECL_MAX_PATH, L"%s\\%s", linkBuf, targetStr.c_str());
|
|
||||||
if (linkFinalPart != linkBuf)
|
|
||||||
*(linkFinalPart - 1) = L'\\';
|
|
||||||
psl->SetPath(targetBuf);
|
|
||||||
psl->SetRelativePath(linkBuf, 0);
|
|
||||||
psl->SetDescription(lpszDesc);
|
|
||||||
|
|
||||||
// Query IShellLink for the IPersistFile interface, used for saving the
|
|
||||||
// shortcut in persistent storage.
|
|
||||||
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
// Save the link by calling IPersistFile::Save.
|
|
||||||
hres = ppf->Save(linkBuf, TRUE);
|
|
||||||
ppf->Release();
|
|
||||||
}
|
|
||||||
psl->Release();
|
|
||||||
}
|
|
||||||
return hres;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferSize)
|
|
||||||
{
|
|
||||||
HRESULT hres;
|
|
||||||
IShellLink* psl;
|
|
||||||
WCHAR szGotPath[HECL_MAX_PATH];
|
|
||||||
WCHAR szDescription[HECL_MAX_PATH];
|
|
||||||
WIN32_FIND_DATA wfd;
|
|
||||||
|
|
||||||
*lpszPath = 0; // Assume failure
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
// Get the path to the link target.
|
|
||||||
hres = psl->GetPath(szGotPath, HECL_MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
// Get the description of the target.
|
|
||||||
hres = psl->GetDescription(szDescription, HECL_MAX_PATH);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
hres = StringCbCopy(lpszPath, iPathBufferSize, szGotPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the pointer to the IPersistFile interface.
|
|
||||||
ppf->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the pointer to the IShellLink interface.
|
|
||||||
psl->Release();
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
ppf->Release();
|
|
||||||
psl->Release();
|
|
||||||
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