added extract tool

This commit is contained in:
Jack Andersen 2015-06-11 23:08:49 -10:00
parent 8de863fcba
commit 4b13e9da9d
10 changed files with 123 additions and 22 deletions

View File

@ -0,0 +1,50 @@
#ifndef CTOOL_EXTRACT
#define CTOOL_EXTRACT
#include "ToolBase.hpp"
#include <stdio.h>
class ToolExtract final : public ToolBase
{
public:
ToolExtract(const ToolPassInfo& info)
: ToolBase(info)
{
}
static void Help(HelpOutput& help)
{
help.secHead(_S("NAME"));
help.beginWrap();
help.wrap(_S("hecl-extract - Extract objects from supported package/image formats\n"));
help.endWrap();
help.secHead(_S("SYNOPSIS"));
help.beginWrap();
help.wrap(_S("hecl extract <packagefile>[/<subnode>...]\n"));
help.endWrap();
help.secHead(_S("DESCRIPTION"));
help.beginWrap();
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported "
"package format.\n\n"));
help.endWrap();
help.secHead(_S("OPTIONS"));
help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file"));
help.beginWrap();
help.wrap(_S("Specifies the package file or disc image to source data from. "
"An optional subnode specifies a named hierarchical-node specific "
"to the game architecture (levels/areas)."));
help.endWrap();
}
HECL::SystemString toolName() const {return _S("extract");}
int run()
{
return 0;
}
};
#endif // CTOOL_EXTRACT

View File

@ -60,6 +60,8 @@ public:
helpFunc = ToolInit::Help; helpFunc = ToolInit::Help;
else if (toolName == _S("spec")) else if (toolName == _S("spec"))
helpFunc = ToolSpec::Help; helpFunc = ToolSpec::Help;
else if (toolName == _S("extract"))
helpFunc = ToolExtract::Help;
else if (toolName == _S("add")) else if (toolName == _S("add"))
helpFunc = ToolAdd::Help; helpFunc = ToolAdd::Help;
else if (toolName == _S("remove") || toolName == _S("rm")) else if (toolName == _S("remove") || toolName == _S("rm"))

View File

@ -45,7 +45,8 @@ public:
return -1; return -1;
try try
{ {
HECL::Database::Project(HECL::ProjectRootPath(*m_dir)); HECL::Database::Project proj((HECL::ProjectRootPath(*m_dir)));
proj.enableDataSpecs({_S("hecl-little")});
} }
catch (HECL::Exception& e) catch (HECL::Exception& e)
{ {

View File

@ -23,6 +23,7 @@ SOURCES += \
HEADERS += \ HEADERS += \
ToolBase.hpp \ ToolBase.hpp \
ToolPackage.hpp \ ToolPackage.hpp \
ToolExtract.hpp \
ToolInit.hpp \ ToolInit.hpp \
ToolHelp.hpp \ ToolHelp.hpp \
ToolGroup.hpp \ ToolGroup.hpp \

View File

@ -10,6 +10,7 @@
#include "ToolBase.hpp" #include "ToolBase.hpp"
#include "ToolInit.hpp" #include "ToolInit.hpp"
#include "ToolSpec.hpp" #include "ToolSpec.hpp"
#include "ToolExtract.hpp"
#include "ToolAdd.hpp" #include "ToolAdd.hpp"
#include "ToolRemove.hpp" #include "ToolRemove.hpp"
#include "ToolGroup.hpp" #include "ToolGroup.hpp"
@ -180,6 +181,8 @@ int main(int argc, const char** argv)
tool.reset(new ToolInit(info)); tool.reset(new ToolInit(info));
else if (toolName == _S("spec")) else if (toolName == _S("spec"))
tool.reset(new ToolSpec(info)); tool.reset(new ToolSpec(info));
else if (toolName == _S("extract"))
tool.reset(new ToolExtract(info));
else if (toolName == _S("add")) else if (toolName == _S("add"))
tool.reset(new ToolAdd(info)); tool.reset(new ToolAdd(info));
else if (toolName == _S("remove") || toolName == _S("rm")) else if (toolName == _S("remove") || toolName == _S("rm"))

View File

@ -3,7 +3,7 @@
_hecl () _hecl ()
{ {
local word=${COMP_WORDS[COMP_CWORD]} local word=${COMP_WORDS[COMP_CWORD]}
local filecmds=(init spec add remove group cook clean package) local filecmds=(init spec extract add remove group cook clean package)
if [ $COMP_CWORD == 1 ] if [ $COMP_CWORD == 1 ]
then then
@ -12,7 +12,7 @@ _hecl ()
elif [ $COMP_CWORD == 2 ] elif [ $COMP_CWORD == 2 ]
then then
case ${COMP_WORDS[1]} in case ${COMP_WORDS[1]} in
init|add|remove|group|cook|clean|package) init|extract|add|remove|group|cook|clean|package)
COMPREPLY=($(compgen -f -- "${word}")) COMPREPLY=($(compgen -f -- "${word}"))
;; ;;
spec) spec)

View File

@ -262,6 +262,7 @@ public:
Hash(int64_t hashin) Hash(int64_t hashin)
: hash(hashin) {} : hash(hashin) {}
Hash(const Hash& other) {hash = other.hash;} Hash(const Hash& other) {hash = other.hash;}
inline size_t val() const {return hash;}
inline Hash& operator=(const Hash& other) {hash = other.hash; return *this;} inline Hash& operator=(const Hash& other) {hash = other.hash; return *this;}
inline bool operator==(const Hash& other) const {return hash == other.hash;} inline bool operator==(const Hash& other) const {return hash == other.hash;}
inline bool operator!=(const Hash& other) const {return hash != other.hash;} inline bool operator!=(const Hash& other) const {return hash != other.hash;}
@ -309,7 +310,7 @@ class ProjectPath
protected: protected:
SystemString m_absPath; SystemString m_absPath;
SystemString m_relPath; SystemString m_relPath;
size_t m_hash = 0; Hash m_hash = 0;
#if HECL_UCS2 #if HECL_UCS2
std::string m_utf8AbsPath; std::string m_utf8AbsPath;
const char* m_utf8RelPath; const char* m_utf8RelPath;
@ -404,10 +405,10 @@ public:
void getGlobResults(std::vector<SystemString>& outPaths) const; void getGlobResults(std::vector<SystemString>& outPaths) const;
/** /**
* @brief C++11 compatible runtime hash (NOT USED IN PACKAGES!!) * @brief HECL-specific blowfish hash
* @return System-specific hash value * @return unique hash value
*/ */
inline size_t hash() const {return m_hash;} inline size_t hash() const {return m_hash.val();}
inline bool operator==(const ProjectPath& other) const {return m_hash == other.m_hash;} inline bool operator==(const ProjectPath& other) const {return m_hash == other.m_hash;}
inline bool operator!=(const ProjectPath& other) const {return m_hash != other.m_hash;} inline bool operator!=(const ProjectPath& other) const {return m_hash != other.m_hash;}
@ -517,7 +518,7 @@ namespace std
{ {
template <> struct hash<HECL::ProjectPath> template <> struct hash<HECL::ProjectPath>
{ {
size_t operator()(const HECL::ProjectPath& val) const noexcept inline size_t operator()(const HECL::ProjectPath& val) const noexcept
{return val.hash();} {return val.hash();}
}; };
} }

View File

@ -8,6 +8,7 @@
#include <map> #include <map>
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <memory> #include <memory>
#include <atomic> #include <atomic>
#include <stdexcept> #include <stdexcept>
@ -21,6 +22,7 @@ namespace HECL
{ {
namespace Database namespace Database
{ {
class Project;
/** /**
* @brief Nodegraph class for gathering dependency-resolved objects for packaging * @brief Nodegraph class for gathering dependency-resolved objects for packaging
@ -35,7 +37,8 @@ public:
NODE_DATA, NODE_DATA,
NODE_GROUP NODE_GROUP
} type; } type;
SystemString path; ProjectPath path;
ProjectPath cookedPath;
class ObjectBase* projectObj; class ObjectBase* projectObj;
Node* sub; Node* sub;
Node* next; Node* next;
@ -56,21 +59,62 @@ public:
class IDataSpec class IDataSpec
{ {
public: public:
/**
* @brief Extract Pass Info
*
* An extract pass iterates through a source package or image and
* reverses the cooking process by emitting editable resources
*/
struct ExtractPassInfo struct ExtractPassInfo
{ {
SystemString srcpath; SystemString srcpath;
ProjectPath subpath; ProjectPath subpath;
bool cookedonly;
}; };
virtual bool canExtract(const ExtractPassInfo& info) {(void)info;return false;} virtual bool canExtract(const Project& project, const ExtractPassInfo& info,
virtual void doExtract(const ExtractPassInfo& info) {(void)info;} SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void doExtract(const Project& project, const ExtractPassInfo& info)
{(void)project;(void)info;}
/**
* @brief Cook Task Info
*
* A cook task takes a single tracked path and generates the
* corresponding cooked version
*/
struct CookTaskInfo
{
ProjectPath path;
ProjectPath cookedPath;
};
virtual bool canCook(const Project& project, const CookTaskInfo& info,
SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project& project, const CookTaskInfo& info)
{(void)project;(void)info;}
/**
* @brief Package Pass Info
*
* A package pass performs last-minute queries of source resources,
* gathers dependencies and packages cooked data together in the
* most efficient form for the dataspec
*/
struct PackagePassInfo struct PackagePassInfo
{ {
PackageDepsgraph& depsgraph; const PackageDepsgraph& depsgraph;
ProjectPath subpath; ProjectPath subpath;
ProjectPath outpath;
}; };
virtual bool canPackage(const PackagePassInfo& info) {(void)info;return false;} virtual bool canPackage(const Project& project, const PackagePassInfo& info,
virtual void doPackage(const PackagePassInfo& info) {(void)info;} SystemString& reasonNo)
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
virtual void gatherDependencies(const Project& project, const PackagePassInfo& info,
std::unordered_set<ProjectPath>& implicitsOut)
{(void)project;(void)info;(void)implicitsOut;}
virtual void doPackage(const Project& project, const PackagePassInfo& info)
{(void)project;(void)info;}
}; };
/** /**
@ -189,7 +233,8 @@ public:
std::list<std::string> m_lines; std::list<std::string> m_lines;
FILE* m_lockedFile = NULL; FILE* m_lockedFile = NULL;
public: public:
ConfigFile(const Project& project, const SystemString& name); ConfigFile(const Project& project, const SystemString& name,
const SystemString& subdir=_S("/.hecl/"));
std::list<std::string>& lockAndRead(); std::list<std::string>& lockAndRead();
void addLine(const std::string& line); void addLine(const std::string& line);
void removeLine(const std::string& refLine); void removeLine(const std::string& refLine);

View File

@ -51,9 +51,7 @@ ProjectPath::ProjectPath(const ProjectRootPath& rootPath, const SystemString& pa
if (*beginit == _S('/')) if (*beginit == _S('/'))
++beginit; ++beginit;
m_relPath = SystemString(beginit, m_absPath.end()); m_relPath = SystemString(beginit, m_absPath.end());
m_hash = Hash(m_relPath);
std::hash<std::string> hash_fn;
m_hash = hash_fn(std::string(m_relPath));
#if HECL_UCS2 #if HECL_UCS2
m_utf8AbsPath = WideToUTF8(m_absPath); m_utf8AbsPath = WideToUTF8(m_absPath);
@ -205,7 +203,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
while (begin != end) while (begin != end)
{ {
SystemString testPath(begin, end); SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _S("/.hecl/index"); SystemString testIndexPath = testPath + _S("/.hecl/beacon");
struct stat theStat; struct stat theStat;
if (!HECL::Stat(testIndexPath.c_str(), &theStat)) if (!HECL::Stat(testIndexPath.c_str(), &theStat))
{ {

View File

@ -40,9 +40,10 @@ static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
return false; return false;
} }
Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name) Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name,
const SystemString& subdir)
{ {
m_filepath = project.m_rootPath.getAbsolutePath() + _S("/.hecl/config/") + name; m_filepath = project.m_rootPath.getAbsolutePath() + subdir + name;
} }
std::list<std::string>& Project::ConfigFile::lockAndRead() std::list<std::string>& Project::ConfigFile::lockAndRead()
@ -184,7 +185,6 @@ Project::Project(const ProjectRootPath& rootPath)
/* Create project directory structure */ /* Create project directory structure */
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl")); HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked")); HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/config"));
/* 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")); FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));