Link removal (complexity not worth it)

This commit is contained in:
Jack Andersen 2016-02-29 17:05:42 -10:00
parent b2a2cd3934
commit e6aeff08a3
6 changed files with 6 additions and 323 deletions

2
hecl/extern/Athena vendored

@ -1 +1 @@
Subproject commit ca0ff04340bd6a25eed1e738e6d976d4a10acf31 Subproject commit b317ac9d9f5205421ab9ae4b919f816c1c1e1ca8

View File

@ -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

View File

@ -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_

View File

@ -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);

View File

@ -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,

View File

@ -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;
}