mirror of https://github.com/AxioDL/metaforce.git
extract behavior tweaks
This commit is contained in:
parent
050085cc6d
commit
662c2bc689
|
@ -20,6 +20,7 @@ public:
|
||||||
|
|
||||||
m_einfo.srcpath = m_info.args[0];
|
m_einfo.srcpath = m_info.args[0];
|
||||||
m_einfo.extractArgs.reserve(info.args.size() - 1);
|
m_einfo.extractArgs.reserve(info.args.size() - 1);
|
||||||
|
m_einfo.force = info.force;
|
||||||
for (std::vector<HECL::SystemString>::const_iterator it=info.args.begin() + 1;
|
for (std::vector<HECL::SystemString>::const_iterator it=info.args.begin() + 1;
|
||||||
it != info.args.end();
|
it != info.args.end();
|
||||||
++it)
|
++it)
|
||||||
|
|
|
@ -21,7 +21,8 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!info.project)
|
if (!info.project)
|
||||||
LogModule.report(LogVisor::FatalError, "hecl spec must be ran within a project directory");
|
LogModule.report(LogVisor::FatalError,
|
||||||
|
"hecl spec must be ran within a project directory");
|
||||||
|
|
||||||
const auto& specs = info.project->getDataSpecs();
|
const auto& specs = info.project->getDataSpecs();
|
||||||
HECL::SystemString firstArg = info.args[0];
|
HECL::SystemString firstArg = info.args[0];
|
||||||
|
@ -47,14 +48,16 @@ public:
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto& spec : specs)
|
for (auto& spec : specs)
|
||||||
{
|
{
|
||||||
if (!spec.first.m_name.compare(*it))
|
if (!spec.spec.m_name.compare(*it))
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
LogModule.report(LogVisor::FatalError, _S("'%s' is not found in the dataspec registry"), it->c_str());
|
LogModule.report(LogVisor::FatalError,
|
||||||
|
_S("'%s' is not found in the dataspec registry"),
|
||||||
|
it->c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,17 +110,17 @@ public:
|
||||||
for (auto& spec : specs)
|
for (auto& spec : specs)
|
||||||
{
|
{
|
||||||
if (XTERM_COLOR)
|
if (XTERM_COLOR)
|
||||||
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL ""), spec.first.m_name.c_str());
|
HECL::Printf(_S("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.c_str());
|
||||||
else
|
else
|
||||||
HECL::Printf(_S("%s"), spec.first.m_name.c_str());
|
HECL::Printf(_S("%s"), spec.spec.m_name.c_str());
|
||||||
if (spec.second)
|
if (spec.active)
|
||||||
{
|
{
|
||||||
if (XTERM_COLOR)
|
if (XTERM_COLOR)
|
||||||
HECL::Printf(_S(" " BOLD GREEN "[ENABLED]" NORMAL ""));
|
HECL::Printf(_S(" " BOLD GREEN "[ENABLED]" NORMAL ""));
|
||||||
else
|
else
|
||||||
HECL::Printf(_S(" [ENABLED]"));
|
HECL::Printf(_S(" [ENABLED]"));
|
||||||
}
|
}
|
||||||
HECL::Printf(_S("\n %s\n"), spec.first.m_desc.c_str());
|
HECL::Printf(_S("\n %s\n"), spec.spec.m_desc.c_str());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -131,9 +134,9 @@ public:
|
||||||
HECL::ToLower(itName);
|
HECL::ToLower(itName);
|
||||||
for (auto& spec : specs)
|
for (auto& spec : specs)
|
||||||
{
|
{
|
||||||
if (!spec.first.m_name.compare(itName))
|
if (!spec.spec.m_name.compare(itName))
|
||||||
{
|
{
|
||||||
opSpecs.push_back(spec.first.m_name);
|
opSpecs.push_back(spec.spec.m_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 94d84d8991dd0c6b5fdb5557476eb4c3421d7b09
|
Subproject commit dea341d27b52e60ab3b8f4ee7e7b808ef516b39d
|
|
@ -200,6 +200,7 @@ public:
|
||||||
{
|
{
|
||||||
SystemString srcpath;
|
SystemString srcpath;
|
||||||
std::vector<SystemString> extractArgs;
|
std::vector<SystemString> extractArgs;
|
||||||
|
bool force;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -383,10 +384,17 @@ public:
|
||||||
class Project
|
class Project
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::vector<std::pair<const DataSpecEntry&, bool>> CompiledSpecs;
|
struct ProjectDataSpec
|
||||||
|
{
|
||||||
|
const DataSpecEntry& spec;
|
||||||
|
ProjectPath cookedPath;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
ProjectRootPath m_rootPath;
|
ProjectRootPath m_rootPath;
|
||||||
CompiledSpecs m_compiledSpecs;
|
ProjectPath m_dotPath;
|
||||||
|
ProjectPath m_cookedRoot;
|
||||||
|
std::vector<ProjectDataSpec> m_compiledSpecs;
|
||||||
public:
|
public:
|
||||||
Project(const HECL::ProjectRootPath& rootPath);
|
Project(const HECL::ProjectRootPath& rootPath);
|
||||||
|
|
||||||
|
@ -440,13 +448,29 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the path of the project's root-directory
|
* @brief Get the path of the project's root-directory
|
||||||
* @param absolute return as absolute-path
|
|
||||||
* @return project root path
|
* @return project root path
|
||||||
*
|
*
|
||||||
* Self explanatory
|
* Self explanatory
|
||||||
*/
|
*/
|
||||||
inline const ProjectRootPath& getProjectRootPath() const {return m_rootPath;}
|
inline const ProjectRootPath& getProjectRootPath() const {return m_rootPath;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the path of project's cooked directory for a specific DataSpec
|
||||||
|
* @param DataSpec to retrieve path for
|
||||||
|
* @return project cooked path
|
||||||
|
*
|
||||||
|
* The cooked path matches the directory layout of the working directory,
|
||||||
|
* except data is
|
||||||
|
*/
|
||||||
|
inline const ProjectPath& getProjectCookedPath(const DataSpecEntry& spec) const
|
||||||
|
{
|
||||||
|
for (const ProjectDataSpec& sp : m_compiledSpecs)
|
||||||
|
if (&sp.spec == &spec)
|
||||||
|
return sp.cookedPath;
|
||||||
|
LogModule.report(LogVisor::FatalError, "Unable to find spec '%s'", spec.m_name.c_str());
|
||||||
|
return m_cookedRoot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add given file(s) to the database
|
* @brief Add given file(s) to the database
|
||||||
* @param path file or pattern within project
|
* @param path file or pattern within project
|
||||||
|
@ -502,7 +526,7 @@ public:
|
||||||
* @brief Return map populated with dataspecs targetable by this project interface
|
* @brief Return map populated with dataspecs targetable by this project interface
|
||||||
* @return Platform map with name-string keys and enable-status values
|
* @return Platform map with name-string keys and enable-status values
|
||||||
*/
|
*/
|
||||||
inline const CompiledSpecs& getDataSpecs() {return m_compiledSpecs;}
|
inline const std::vector<ProjectDataSpec>& getDataSpecs() {return m_compiledSpecs;}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable persistent user preference for particular spec string(s)
|
* @brief Enable persistent user preference for particular spec string(s)
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef HECL_HPP
|
#ifndef HECL_HPP
|
||||||
#define HECL_HPP
|
#define HECL_HPP
|
||||||
|
|
||||||
#if _WIN32
|
#ifndef _WIN32
|
||||||
char* win_realpath(const char* name, char* restrict resolved);
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -50,16 +48,24 @@ class SystemUTF8View
|
||||||
public:
|
public:
|
||||||
SystemUTF8View(const SystemString& str)
|
SystemUTF8View(const SystemString& str)
|
||||||
: m_utf8(WideToUTF8(str)) {}
|
: m_utf8(WideToUTF8(str)) {}
|
||||||
inline const std::string& utf8_str() {return m_utf8;}
|
inline operator const std::string&() const {return m_utf8;}
|
||||||
|
inline std::string operator+(const std::string& other) const {return m_utf8 + other;}
|
||||||
|
inline std::string operator+(const char* other) const {return m_utf8 + other;}
|
||||||
};
|
};
|
||||||
|
inline std::string operator+(const std::string& lhs, const SystemUTF8View& rhs) {return lhs + std::string(rhs);}
|
||||||
|
inline std::string operator+(const char* lhs, const SystemUTF8View& rhs) {return lhs + std::string(rhs);}
|
||||||
class SystemStringView
|
class SystemStringView
|
||||||
{
|
{
|
||||||
std::wstring m_sys;
|
std::wstring m_sys;
|
||||||
public:
|
public:
|
||||||
SystemStringView(const std::string& str)
|
SystemStringView(const std::string& str)
|
||||||
: m_sys(UTF8ToWide(str)) {}
|
: m_sys(UTF8ToWide(str)) {}
|
||||||
inline const std::wstring& sys_str() {return m_sys;}
|
inline operator const std::wstring&() const {return m_sys;}
|
||||||
|
inline std::wstring operator+(const std::wstring& other) const {return m_sys + other;}
|
||||||
|
inline std::wstring operator+(const wchar_t* other) const {return m_sys + other;}
|
||||||
};
|
};
|
||||||
|
inline std::wstring operator+(const std::wstring& lhs, const SystemStringView& rhs) {return lhs + std::wstring(rhs);}
|
||||||
|
inline std::wstring operator+(const wchar_t* lhs, const SystemStringView& rhs) {return lhs + std::wstring(rhs);}
|
||||||
#ifndef _S
|
#ifndef _S
|
||||||
#define _S(val) L ## val
|
#define _S(val) L ## val
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,16 +82,24 @@ class SystemUTF8View
|
||||||
public:
|
public:
|
||||||
SystemUTF8View(const SystemString& str)
|
SystemUTF8View(const SystemString& str)
|
||||||
: m_utf8(str) {}
|
: m_utf8(str) {}
|
||||||
inline const std::string& utf8_str() {return m_utf8;}
|
inline operator const std::string&() const {return m_utf8;}
|
||||||
|
inline std::string operator+(const std::string& other) const {return std::string(m_utf8) + other;}
|
||||||
|
inline std::string operator+(const char* other) const {return std::string(m_utf8) + other;}
|
||||||
};
|
};
|
||||||
|
inline std::string operator+(const std::string& lhs, const SystemUTF8View& rhs) {return lhs + std::string(rhs);}
|
||||||
|
inline std::string operator+(const char* lhs, const SystemUTF8View& rhs) {return lhs + std::string(rhs);}
|
||||||
class SystemStringView
|
class SystemStringView
|
||||||
{
|
{
|
||||||
const std::string& m_sys;
|
const std::string& m_sys;
|
||||||
public:
|
public:
|
||||||
SystemStringView(const std::string& str)
|
SystemStringView(const std::string& str)
|
||||||
: m_sys(str) {}
|
: m_sys(str) {}
|
||||||
inline const std::string& sys_str() {return m_sys;}
|
inline operator const std::string&() const {return m_sys;}
|
||||||
|
inline std::string operator+(const std::string& other) const {return m_sys + other;}
|
||||||
|
inline std::string operator+(const char* other) const {return m_sys + other;}
|
||||||
};
|
};
|
||||||
|
inline std::string operator+(const std::string& lhs, const SystemStringView& rhs) {return lhs + std::string(rhs);}
|
||||||
|
inline std::string operator+(const char* lhs, const SystemStringView& rhs) {return lhs + std::string(rhs);}
|
||||||
#ifndef _S
|
#ifndef _S
|
||||||
#define _S(val) val
|
#define _S(val) val
|
||||||
#endif
|
#endif
|
||||||
|
@ -318,6 +332,7 @@ public:
|
||||||
class ProjectPath
|
class ProjectPath
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
SystemString m_projRoot;
|
||||||
SystemString m_absPath;
|
SystemString m_absPath;
|
||||||
SystemString m_relPath;
|
SystemString m_relPath;
|
||||||
Hash m_hash = 0;
|
Hash m_hash = 0;
|
||||||
|
@ -325,9 +340,14 @@ protected:
|
||||||
std::string m_utf8AbsPath;
|
std::string m_utf8AbsPath;
|
||||||
const char* m_utf8RelPath;
|
const char* m_utf8RelPath;
|
||||||
#endif
|
#endif
|
||||||
ProjectPath() {}
|
ProjectPath(const SystemString& projRoot)
|
||||||
bool _canonAbsPath(const SystemString& path, bool& needsMake);
|
: m_projRoot(projRoot), m_absPath(projRoot), m_relPath("."), m_hash(m_relPath)
|
||||||
inline void _makeDir() const {MakeDir(m_absPath);}
|
{
|
||||||
|
#if HECL_UCS2
|
||||||
|
m_utf8AbsPath = WideToUTF8(m_absPath);
|
||||||
|
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Construct a project subpath representation within another subpath
|
* @brief Construct a project subpath representation within another subpath
|
||||||
|
@ -415,6 +435,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void getGlobResults(std::vector<SystemString>& outPaths) const;
|
void getGlobResults(std::vector<SystemString>& outPaths) const;
|
||||||
|
|
||||||
|
inline void makeDir() const {MakeDir(m_absPath);}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HECL-specific blowfish hash
|
* @brief HECL-specific blowfish hash
|
||||||
* @return unique hash value
|
* @return unique hash value
|
||||||
|
@ -435,12 +457,7 @@ class ProjectRootPath : public ProjectPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectRootPath(const SystemString& path)
|
ProjectRootPath(const SystemString& path)
|
||||||
{
|
: ProjectPath(path) {}
|
||||||
bool needsMake = false;
|
|
||||||
_canonAbsPath(path, needsMake);
|
|
||||||
if (needsMake)
|
|
||||||
_makeDir();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,6 +28,7 @@ void InitASEngine()
|
||||||
InitEntered = true;
|
InitEntered = true;
|
||||||
assert(asENGINE = AngelScript::asCreateScriptEngine(ANGELSCRIPT_VERSION));
|
assert(asENGINE = AngelScript::asCreateScriptEngine(ANGELSCRIPT_VERSION));
|
||||||
assert(asENGINE->SetEngineProperty(AngelScript::asEP_COPY_SCRIPT_SECTIONS, false) >= 0);
|
assert(asENGINE->SetEngineProperty(AngelScript::asEP_COPY_SCRIPT_SECTIONS, false) >= 0);
|
||||||
|
assert(asENGINE->SetEngineProperty(AngelScript::asEP_ALLOW_MULTILINE_STRINGS, true) >= 0);
|
||||||
assert(asENGINE->SetMessageCallback(AngelScript::asFUNCTION(MessageCallback), nullptr, AngelScript::asCALL_CDECL) >= 0);
|
assert(asENGINE->SetMessageCallback(AngelScript::asFUNCTION(MessageCallback), nullptr, AngelScript::asCALL_CDECL) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,8 @@ void Project::ConfigFile::removeLine(const std::string& refLine)
|
||||||
{
|
{
|
||||||
if (!m_lockedFile)
|
if (!m_lockedFile)
|
||||||
{
|
{
|
||||||
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
|
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__,
|
||||||
|
"Project::ConfigFile::lockAndRead not yet called");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +116,8 @@ bool Project::ConfigFile::checkForLine(const std::string& refLine)
|
||||||
{
|
{
|
||||||
if (!m_lockedFile)
|
if (!m_lockedFile)
|
||||||
{
|
{
|
||||||
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
|
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__,
|
||||||
|
"Project::ConfigFile::lockAndRead not yet called");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +133,8 @@ void Project::ConfigFile::unlockAndDiscard()
|
||||||
{
|
{
|
||||||
if (!m_lockedFile)
|
if (!m_lockedFile)
|
||||||
{
|
{
|
||||||
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
|
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__,
|
||||||
|
"Project::ConfigFile::lockAndRead not yet called");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +147,8 @@ bool Project::ConfigFile::unlockAndCommit()
|
||||||
{
|
{
|
||||||
if (!m_lockedFile)
|
if (!m_lockedFile)
|
||||||
{
|
{
|
||||||
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
|
LogModule.reportSource(LogVisor::FatalError, __FILE__, __LINE__,
|
||||||
|
"Project::ConfigFile::lockAndRead not yet called");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +190,8 @@ bool Project::ConfigFile::unlockAndCommit()
|
||||||
|
|
||||||
Project::Project(const ProjectRootPath& rootPath)
|
Project::Project(const ProjectRootPath& rootPath)
|
||||||
: m_rootPath(rootPath),
|
: m_rootPath(rootPath),
|
||||||
|
m_dotPath(m_rootPath, _S(".hecl")),
|
||||||
|
m_cookedRoot(m_dotPath, _S("cooked")),
|
||||||
m_specs(*this, _S("specs")),
|
m_specs(*this, _S("specs")),
|
||||||
m_paths(*this, _S("paths")),
|
m_paths(*this, _S("paths")),
|
||||||
m_groups(*this, _S("groups"))
|
m_groups(*this, _S("groups"))
|
||||||
|
@ -200,11 +206,12 @@ Project::Project(const ProjectRootPath& rootPath)
|
||||||
m_rootPath.getAbsolutePathUTF8() + "' isn't");
|
m_rootPath.getAbsolutePathUTF8() + "' isn't");
|
||||||
|
|
||||||
/* Create project directory structure */
|
/* Create project directory structure */
|
||||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
|
m_dotPath.makeDir();
|
||||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
|
m_cookedRoot.makeDir();
|
||||||
|
|
||||||
/* Ensure beacon is valid or created */
|
/* Ensure beacon is valid or created */
|
||||||
FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));
|
ProjectPath beaconPath(m_dotPath, _S("beacon"));
|
||||||
|
FILE* bf = HECL::Fopen(beaconPath.getAbsolutePath().c_str(), _S("a+b"));
|
||||||
struct BeaconStruct
|
struct BeaconStruct
|
||||||
{
|
{
|
||||||
HECL::FourCC magic;
|
HECL::FourCC magic;
|
||||||
|
@ -286,7 +293,8 @@ void Project::rescanDataSpecs()
|
||||||
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY)
|
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY)
|
||||||
{
|
{
|
||||||
SystemUTF8View specUTF8(spec->m_name);
|
SystemUTF8View specUTF8(spec->m_name);
|
||||||
m_compiledSpecs.push_back({*spec, m_specs.checkForLine(specUTF8.utf8_str()) ? true : false});
|
m_compiledSpecs.push_back({*spec, ProjectPath(m_cookedRoot, spec->m_name + ".spec"),
|
||||||
|
m_specs.checkForLine(specUTF8) ? true : false});
|
||||||
}
|
}
|
||||||
m_specs.unlockAndDiscard();
|
m_specs.unlockAndDiscard();
|
||||||
}
|
}
|
||||||
|
@ -296,7 +304,9 @@ bool Project::enableDataSpecs(const std::vector<SystemString>& specs)
|
||||||
m_specs.lockAndRead();
|
m_specs.lockAndRead();
|
||||||
for (const SystemString& spec : specs)
|
for (const SystemString& spec : specs)
|
||||||
m_specs.addLine(spec);
|
m_specs.addLine(spec);
|
||||||
return m_specs.unlockAndCommit();
|
bool result = m_specs.unlockAndCommit();
|
||||||
|
rescanDataSpecs();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
|
bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
|
||||||
|
@ -304,7 +314,9 @@ bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
|
||||||
m_specs.lockAndRead();
|
m_specs.lockAndRead();
|
||||||
for (const SystemString& spec : specs)
|
for (const SystemString& spec : specs)
|
||||||
m_specs.removeLine(spec);
|
m_specs.removeLine(spec);
|
||||||
return m_specs.unlockAndCommit();
|
bool result = m_specs.unlockAndCommit();
|
||||||
|
rescanDataSpecs();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Project::cookPath(const ProjectPath& path,
|
bool Project::cookPath(const ProjectPath& path,
|
||||||
|
|
|
@ -2,79 +2,72 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
char* win_realpath(const char* name, char* restrict resolved)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace HECL
|
namespace HECL
|
||||||
{
|
{
|
||||||
|
|
||||||
static const SystemRegex regGLOB(_S("\\*"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
static const SystemRegex regGLOB(_S("\\*"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
static const SystemRegex regPATHCOMP(_S("/([^/]+)"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
static const SystemRegex regPATHCOMP(_S("[/\\\\]*([^/\\\\]+)"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
static const SystemRegex regDRIVELETTER(_S("^([^/]*)/"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
static const SystemRegex regDRIVELETTER(_S("^([^/]*)/"), SystemRegex::ECMAScript|SystemRegex::optimize);
|
||||||
|
|
||||||
inline bool isAbsolute(const SystemString& path)
|
static SystemString canonRelPath(const SystemString& path)
|
||||||
{
|
{
|
||||||
if (path.size() && path[0] == '/')
|
/* Absolute paths not allowed */
|
||||||
return true;
|
if (path[0] == _S('/') || path[0] == _S('\\'))
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProjectPath::_canonAbsPath(const SystemString& path, bool& needsMake)
|
|
||||||
{
|
|
||||||
#if _WIN32
|
|
||||||
#else
|
|
||||||
SystemChar resolvedPath[PATH_MAX];
|
|
||||||
if (!realpath(path.c_str(), resolvedPath))
|
|
||||||
{
|
{
|
||||||
if (errno != ENOENT)
|
throw std::invalid_argument("Absolute path provided; expected relative: " + path);
|
||||||
{
|
return _S(".");
|
||||||
throw std::system_error(errno, std::system_category(),
|
|
||||||
"Unable to resolve '" + SystemUTF8View(path).utf8_str() +
|
|
||||||
"' as a canonicalized path");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
needsMake = true;
|
|
||||||
}
|
}
|
||||||
m_absPath = resolvedPath;
|
|
||||||
#endif
|
/* Tokenize Path */
|
||||||
return true;
|
std::vector<SystemString> comps;
|
||||||
|
HECL::SystemRegexMatch matches;
|
||||||
|
SystemString in = path;
|
||||||
|
while (std::regex_search(in, matches, regPATHCOMP))
|
||||||
|
{
|
||||||
|
in = matches.suffix();
|
||||||
|
const SystemString& match = matches[1];
|
||||||
|
if (!match.compare(_S(".")))
|
||||||
|
continue;
|
||||||
|
else if (!match.compare(_S("..")))
|
||||||
|
{
|
||||||
|
if (comps.empty())
|
||||||
|
{
|
||||||
|
/* Unable to resolve outside project */
|
||||||
|
SystemUTF8View pathView(path);
|
||||||
|
throw std::invalid_argument("Unable to resolve outside project root in " + pathView);
|
||||||
|
return _S(".");
|
||||||
|
}
|
||||||
|
comps.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
comps.push_back(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit relative path */
|
||||||
|
if (comps.size())
|
||||||
|
{
|
||||||
|
auto it = comps.begin();
|
||||||
|
SystemString retval = *it;
|
||||||
|
for (++it ; it != comps.end() ; ++it)
|
||||||
|
{
|
||||||
|
retval += _S('/');
|
||||||
|
retval += *it;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
return ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPath::ProjectPath(const ProjectPath& parentPath, const SystemString& path)
|
ProjectPath::ProjectPath(const ProjectPath& parentPath, const SystemString& path)
|
||||||
|
: m_projRoot(parentPath.m_projRoot)
|
||||||
{
|
{
|
||||||
bool needsMake = false;
|
m_relPath = canonRelPath(parentPath.m_relPath + '/' + path);
|
||||||
if (!_canonAbsPath(parentPath.getRelativePath() + '/' + path, needsMake))
|
m_absPath = parentPath.m_projRoot + '/' + m_relPath;
|
||||||
return;
|
|
||||||
if (m_absPath.size() < parentPath.m_absPath.size() ||
|
|
||||||
m_absPath.compare(0, parentPath.m_absPath.size(),
|
|
||||||
parentPath.m_absPath))
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("'" + SystemUTF8View(m_absPath).utf8_str() + "' is not a subpath of '" +
|
|
||||||
SystemUTF8View(parentPath.m_absPath).utf8_str() + "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_absPath.size() == parentPath.m_absPath.size())
|
|
||||||
{
|
|
||||||
/* Copies of the project root are permitted */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SystemString::iterator beginit = m_absPath.begin() + parentPath.m_absPath.size();
|
|
||||||
if (*beginit == _S('/'))
|
|
||||||
++beginit;
|
|
||||||
m_relPath = SystemString(beginit, m_absPath.end());
|
|
||||||
m_hash = Hash(m_relPath);
|
m_hash = Hash(m_relPath);
|
||||||
|
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
m_utf8AbsPath = WideToUTF8(m_absPath);
|
m_utf8AbsPath = WideToUTF8(m_absPath);
|
||||||
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size();
|
m_utf8RelPath = m_utf8AbsPath.c_str() + ((ProjectPath&)rootPath).m_utf8AbsPath.size();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (needsMake)
|
|
||||||
_makeDir();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPath::PathType ProjectPath::getPathType() const
|
ProjectPath::PathType ProjectPath::getPathType() const
|
||||||
|
|
Loading…
Reference in New Issue