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
|
||||
|
||||
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)
|
||||
{
|
||||
#if HECL_UCS2
|
||||
|
@ -1052,7 +1034,6 @@ public:
|
|||
File, /**< Singular file path (confirmed with filesystem) */
|
||||
Directory, /**< Singular directory path (confirmed with filesystem) */
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
@ -1115,20 +1090,6 @@ public:
|
|||
*/
|
||||
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
|
||||
* @return Project
|
||||
|
|
|
@ -10,8 +10,5 @@
|
|||
#include "windows.h"
|
||||
|
||||
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_
|
||||
|
|
|
@ -409,24 +409,8 @@ static void VisitDirectory(const ProjectPath& dir,
|
|||
/* Pass 1: child file count */
|
||||
int childFileCount = 0;
|
||||
for (auto& child : children)
|
||||
{
|
||||
switch (child.second.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::File:
|
||||
{
|
||||
if (child.second.getPathType() == ProjectPath::Type::File)
|
||||
++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 */
|
||||
int progNum = 0;
|
||||
|
@ -434,25 +418,10 @@ static void VisitDirectory(const ProjectPath& dir,
|
|||
progress.changeDir(dir.getLastComponent());
|
||||
for (auto& child : children)
|
||||
{
|
||||
switch (child.second.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::File:
|
||||
if (child.second.getPathType() == ProjectPath::Type::File)
|
||||
{
|
||||
progress.changeFile(child.first.c_str(), progNum++/progDenom);
|
||||
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();
|
||||
|
@ -486,24 +455,8 @@ static void VisitGlob(const ProjectPath& path,
|
|||
/* Pass 1: child file count */
|
||||
int childFileCount = 0;
|
||||
for (ProjectPath& child : children)
|
||||
{
|
||||
switch (child.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::File:
|
||||
{
|
||||
if (child.getPathType() == ProjectPath::Type::File)
|
||||
++childFileCount;
|
||||
break;
|
||||
}
|
||||
case ProjectPath::Type::Link:
|
||||
{
|
||||
ProjectPath target = path.resolveLink();
|
||||
if (target.getPathType() == ProjectPath::Type::File)
|
||||
++childFileCount;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2: child files */
|
||||
int progNum = 0;
|
||||
|
@ -511,45 +464,19 @@ static void VisitGlob(const ProjectPath& path,
|
|||
progress.changeDir(path.getLastComponent());
|
||||
for (ProjectPath& child : children)
|
||||
{
|
||||
switch (child.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::File:
|
||||
if (child.getPathType() == ProjectPath::Type::File)
|
||||
{
|
||||
progress.changeFile(child.getLastComponent(), progNum++/progDenom);
|
||||
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();
|
||||
|
||||
/* Pass 3: child directories */
|
||||
if (recursive)
|
||||
{
|
||||
for (ProjectPath& child : children)
|
||||
{
|
||||
switch (child.getPathType())
|
||||
{
|
||||
case ProjectPath::Type::Directory:
|
||||
{
|
||||
if (child.getPathType() == ProjectPath::Type::Directory)
|
||||
VisitDirectory(child, recursive, force, fast, specInsts, progress);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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:
|
||||
{
|
||||
VisitDirectory(path, recursive, force, fast, specInsts, cookProg);
|
||||
|
|
|
@ -128,16 +128,6 @@ ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) cons
|
|||
|
||||
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))
|
||||
return Type::Glob;
|
||||
Sstat theStat;
|
||||
|
@ -191,22 +181,6 @@ 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(getParentPath(), target);
|
||||
}
|
||||
|
||||
static void _recursiveGlob(Database::Project& proj,
|
||||
std::vector<ProjectPath>& outPaths,
|
||||
size_t level,
|
||||
|
|
|
@ -34,169 +34,3 @@ void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
|
|||
|
||||
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