#pragma once #include #include #include #include #include "tasks/Task.h" namespace mojang_files { using Hash = QString; extern const Hash empty_hash; // simple-ish path implementation. assumes always relative and does not allow '..' entries class Path { public: using parts_type = QStringList; Path() = default; Path(QString string) { auto parts_in = string.split('/'); for(auto & part: parts_in) { if(part.isEmpty() || part == ".") { continue; } if(part == "..") { if(parts.size()) { parts.pop_back(); } continue; } parts.push_back(part); } } bool has_parent_path() const { return parts.size() > 0; } Path parent_path() const { if (parts.empty()) return Path(); return Path(parts.begin(), std::prev(parts.end())); } bool empty() const { return parts.empty(); } int length() const { return parts.length(); } bool operator==(const Path & rhs) const { return parts == rhs.parts; } bool operator!=(const Path & rhs) const { return parts != rhs.parts; } inline bool operator<(const Path& rhs) const { return compare(rhs) < 0; } parts_type::const_iterator begin() const { return parts.begin(); } parts_type::const_iterator end() const { return parts.end(); } QString toString() const { return parts.join("/"); } private: Path(const parts_type::const_iterator & start, const parts_type::const_iterator & end) { auto cursor = start; while(cursor != end) { parts.push_back(*cursor); cursor++; } } int compare(const Path& p) const; parts_type parts; }; enum class Compression { Raw, Lzma, Unknown }; struct FileSource { Compression compression = Compression::Unknown; Hash hash; QString url; std::size_t size = 0; void upgrade(const FileSource & other) { if(compression == Compression::Unknown || other.size < size) { *this = other; } } bool isBad() const { return compression == Compression::Unknown; } }; struct File { Hash hash; bool executable; std::uint64_t size = 0; }; struct Package { static Package fromInspectedFolder(const QString &folderPath); static Package fromManifestFile(const QString &path); static Package fromManifestContents(const QByteArray& contents); explicit operator bool() const { return valid; } void addFolder(Path folder); void addFile(const Path & path, const File & file); void addLink(const Path & path, const Path & target); void addSource(const FileSource & source); std::map sources; bool valid = true; std::set folders; std::map files; std::map symlinks; }; struct FileDownload : FileSource { FileDownload(const FileSource& source, bool executable) { static_cast (*this) = source; this->executable = executable; } bool executable = false; }; struct UpdateOperations { static UpdateOperations resolve(const Package & from, const Package & to); bool valid = false; std::vector deletes; std::vector rmdirs; std::vector mkdirs; std::map downloads; std::map mklinks; std::map executable_fixes; }; }