Commit 536364be authored by coppro's avatar coppro

Added installer code.

parent c2303646
...@@ -7,11 +7,24 @@ ...@@ -7,11 +7,24 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <data/installer.hpp> #include <data/installer.hpp>
#include <data/locale.hpp>
#include <data/game.hpp>
#include <data/stylesheet.hpp>
#include <data/symbol_font.hpp>
#include <data/export_template.hpp>
#include <util/io/package_manager.hpp> #include <util/io/package_manager.hpp>
#include <util/platform.hpp>
#include <script/to_value.hpp> #include <script/to_value.hpp>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <wx/stdpaths.h>
DECLARE_TYPEOF_COLLECTION(String); DECLARE_TYPEOF_COLLECTION(String);
DECLARE_TYPEOF_COLLECTION(PackageP);
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
DECLARE_POINTER_TYPE(wxFileInputStream);
DECLARE_POINTER_TYPE(wxZipInputStream);
// ----------------------------------------------------------------------------- : Installer // ----------------------------------------------------------------------------- : Installer
...@@ -24,31 +37,96 @@ IMPLEMENT_REFLECTION(Installer) { ...@@ -24,31 +37,96 @@ IMPLEMENT_REFLECTION(Installer) {
// ----------------------------------------------------------------------------- : Installing // ----------------------------------------------------------------------------- : Installing
void Installer::installFrom(const String& filename, bool message_on_success) { void Installer::installFrom(const String& filename, bool message_on_success, bool local) {
Installer i; Installer i;
i.open(filename); i.open(filename);
i.install(); try {
i.install(local);
}
catch (Error& e) {
handle_error(e);
return;
}
if (message_on_success) { if (message_on_success) {
wxMessageBox(String::Format(_("'%s' successfully installed %d package%s."), i.name().c_str(), i.packages.size(), i.packages.size() == 1 ? _("") : _("s")), wxMessageBox(String::Format(_("'%s' successfully installed %d package%s."), i.name().c_str(), i.packages.size(), i.packages.size() == 1 ? _("") : _("s")),
_("Magic Set Editor"), wxOK | wxICON_INFORMATION); _("Magic Set Editor"), wxOK | wxICON_INFORMATION);
} }
} }
void Installer::install() { struct dependency_check : public unary_function<bool, PackagedP> {
// Walk over all files in this installer dependency_check(PackageDependencyP dep) : dep (dep) {}
bool operator () (PackagedP package) {
return package->name() == dep->package && package->version >= dep->version;
}
private:
PackageDependencyP dep;
};
void Installer::install(bool local) {
// Destination directory
String install_dir = local ? ::packages.getLocalDataDir() : ::packages.getGlobalDataDir();
if (!wxDirExists(install_dir))
wxMkdir(install_dir, 0755);
// All the packages we're installing.
vector<PackagedP> new_packages;
FOR_EACH(p, packages) {
if (wxDirExists(install_dir + _("/") + p) || wxFileExists(install_dir + _("/") + p))
throw PackageError(_("Package ") + p + _(" is already installed. Overwriting currently not supported."));
PackagedP pack;
wxString fn(wxFileName(p).GetExt());
if (fn == _("mse-game")) pack = new_intrusive<Game>();
else if (fn == _("mse-style")) pack = new_intrusive<StyleSheet>();
else if (fn == _("mse-locale")) pack = new_intrusive<Locale>();
else if (fn == _("mse-include")) pack = new_intrusive<IncludePackage>();
else if (fn == _("mse-symbol-font")) pack = new_intrusive<SymbolFont>();
else if (fn == _("mse-export-template")) pack = new_intrusive<ExportTemplate>();
else {
throw PackageError(_("Unrecognized package type: '") + fn + _("'\nwhile trying to install: ") + p);
}
Reader reader(openIn(p + _("/") + fn.Mid(4)));
pack->Packaged::reflect_impl(reader);
new_packages.push_back(pack);
}
// Check dependencies for each and every package.
FOR_EACH(p, new_packages) {
FOR_EACH(d, p->dependencies) {
if (find_if(new_packages.begin(), new_packages.end(), dependency_check(d)) == new_packages.end() &&
!::packages.checkDependency(*d, false)) {
throw PackageError(_("Unmet dependency for package ") + p->relativeFilename() + _(": ") + d->package + _(", version ") + d->version.toString() + _(" or higher."));
}
}
}
const FileInfos& file_infos = getFileInfos(); const FileInfos& file_infos = getFileInfos();
for (FileInfos::const_iterator it = file_infos.begin() ; it != file_infos.end() ; ++it) { for (FileInfos::const_iterator it = file_infos.begin() ; it != file_infos.end() ; ++it) {
// const String& filename = it->first; String file = it->first;
//
wxFileName fn(file);
wxArrayString dirs = fn.GetDirs();
if (fn.IsDir() || !dirs.GetCount() || find(packages.begin(), packages.end(), dirs[0]) == packages.end())
continue;
String current_dir = install_dir;
for (size_t j = 0; j < dirs.GetCount(); ++j) {
current_dir += _("/") + dirs[j];
if (!wxDirExists(current_dir) && !wxMkdir(current_dir, 0755))
throw PackageError(_("Cannot create folder ") + current_dir + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed."));
} }
// REMOVE?
FOR_EACH(p, packages) { InputStreamP is = openIn(file);
install(p); wxFileOutputStream os (install_dir + _("/") + file);
if (!os.IsOk())
throw PackageError(_("Cannot create file ") + install_dir + _("/") + file + _(" for install. Warning: some packages may have been installed anyway, and some may only be partially installed."));
os.Write(*is);
} }
} }
void Installer::install(const String& package) { void Installer::install(const String& package) {
// 1. Make sure the package is not loaded
// TODO // TODO
} }
......
...@@ -21,9 +21,9 @@ class Installer : public Packaged { ...@@ -21,9 +21,9 @@ class Installer : public Packaged {
vector<String> packages; ///< Packages to install vector<String> packages; ///< Packages to install
/// Load an installer from a file, and run it /// Load an installer from a file, and run it
static void installFrom(const String& filename, bool message_on_success); static void installFrom(const String& filename, bool message_on_success, bool local);
/// Install all the packages /// Install all the packages
void install(); void install(bool local);
/// Install a specific package /// Install a specific package
void install(const String& package); void install(const String& package);
......
...@@ -156,7 +156,7 @@ IndexMap<FieldP,ValueP>& Settings::exportOptionsFor(const ExportTemplate& export ...@@ -156,7 +156,7 @@ IndexMap<FieldP,ValueP>& Settings::exportOptionsFor(const ExportTemplate& export
/// Retrieve the directory to use for settings and other data files /// Retrieve the directory to use for settings and other data files
String user_settings_dir() { String user_settings_dir() {
String dir = wxStandardPaths::Get().GetUserDataDir(); String dir = wxStandardPaths::Get().GetUserDataDir();
if (!wxDirExists(dir)) wxMkDir(dir); if (!wxDirExists(dir)) wxMkdir(dir);
return dir + _("/"); return dir + _("/");
} }
......
...@@ -64,7 +64,7 @@ void HtmlExportWindow::onOk(wxCommandEvent&) { ...@@ -64,7 +64,7 @@ void HtmlExportWindow::onOk(wxCommandEvent&) {
info.directory_relative = fn.GetName() + _("-files"); info.directory_relative = fn.GetName() + _("-files");
fn.SetFullName(info.directory_relative); fn.SetFullName(info.directory_relative);
info.directory_absolute = fn.GetFullPath(); info.directory_absolute = fn.GetFullPath();
wxMkDir(info.directory_absolute); wxMkdir(info.directory_absolute);
} }
// run export script // run export script
Context& ctx = set->getContext(); Context& ctx = set->getContext();
......
...@@ -19,7 +19,7 @@ DECLARE_TYPEOF_COLLECTION(pair_ThumbnailRequestP_Image); ...@@ -19,7 +19,7 @@ DECLARE_TYPEOF_COLLECTION(pair_ThumbnailRequestP_Image);
String user_settings_dir(); String user_settings_dir();
String image_cache_dir() { String image_cache_dir() {
String dir = user_settings_dir() + _("/cache"); String dir = user_settings_dir() + _("/cache");
if (!wxDirExists(dir)) wxMkDir(dir); if (!wxDirExists(dir)) wxMkdir(dir);
return dir + _("/"); return dir + _("/");
} }
......
...@@ -94,9 +94,13 @@ bool MSE::OnInit() { ...@@ -94,9 +94,13 @@ bool MSE::OnInit() {
return true; return true;
} else if (f.GetExt() == _("mse-installer")) { } else if (f.GetExt() == _("mse-installer")) {
// Installer; install it // Installer; install it
Installer::installFrom(argv[1], true); bool local = false;
packages.destroy(); if (argc > 2) {
return false; String arg2 = argv[2];
local = arg2 == _("--local");
}
Installer::installFrom(argv[1], true, local);
return true;
} else if (arg == _("--symbol-editor")) { } else if (arg == _("--symbol-editor")) {
Window* wnd = new SymbolWindow(nullptr); Window* wnd = new SymbolWindow(nullptr);
wnd->Show(); wnd->Show();
...@@ -112,8 +116,7 @@ bool MSE::OnInit() { ...@@ -112,8 +116,7 @@ bool MSE::OnInit() {
} else { } else {
inst.saveAs(inst.prefered_filename, false); inst.saveAs(inst.prefered_filename, false);
} }
packages.destroy(); return true;
return false;
} else if (arg == _("--help") || arg == _("-?")) { } else if (arg == _("--help") || arg == _("-?")) {
// command line help // command line help
write_stdout( String(_("Magic Set Editor\n\n")) write_stdout( String(_("Magic Set Editor\n\n"))
...@@ -128,17 +131,18 @@ bool MSE::OnInit() { ...@@ -128,17 +131,18 @@ bool MSE::OnInit() {
+ _(" -v --version \tShow version information.\n") + _(" -v --version \tShow version information.\n")
+ _(" --create-installer\n") + _(" --create-installer\n")
+ _(" FILE [FILE]...\tCreate an instaler named FILE, containing the listed packges.\n") ); + _(" FILE [FILE]...\tCreate an instaler named FILE, containing the listed packges.\n") );
return false; return true;
} else if (arg == _("--version") || arg == _("-v")) { } else if (arg == _("--version") || arg == _("-v")) {
// dump version // dump version
write_stdout( _("Magic Set Editor\nVersion ") + app_version.toString() + version_suffix ); write_stdout( _("Magic Set Editor\nVersion ") + app_version.toString() + version_suffix );
packages.destroy(); return true;
return false;
} else { } else {
handle_error(_("Invalid command line argument:\n") + String(argv[1])); handle_error(_("Invalid command line argument:\n") + String(argv[1]));
} }
} catch (const Error& e) { } catch (const Error& e) {
handle_error(e); handle_error(e);
OnExit();
return false;
} }
} }
......
...@@ -497,3 +497,11 @@ void Packaged::validate(Version) { ...@@ -497,3 +497,11 @@ void Packaged::validate(Version) {
packages.checkDependency(*dep, true); packages.checkDependency(*dep, true);
} }
} }
// ----------------------------------------------------------------------------- : IncludePackage
String IncludePackage::typeName() const { return _("include"); }
IMPLEMENT_REFLECTION(IncludePackage) {
REFLECT_BASE(Packaged);
}
\ No newline at end of file
...@@ -171,8 +171,8 @@ class Package : public IntrusivePtrVirtualBase { ...@@ -171,8 +171,8 @@ class Package : public IntrusivePtrVirtualBase {
void openDirectory(); void openDirectory();
void openSubdir(const String&); void openSubdir(const String&);
void openZipfile(); void openZipfile();
void saveToDirectory(const String&, bool);
void saveToZipfile(const String&, bool); void saveToZipfile(const String&, bool);
void saveToDirectory(const String&, bool);
FileInfos::iterator addFile(const String& file); FileInfos::iterator addFile(const String& file);
static String toStandardName(const String& file); static String toStandardName(const String& file);
}; };
...@@ -228,5 +228,14 @@ class Packaged : public Package { ...@@ -228,5 +228,14 @@ class Packaged : public Package {
friend struct JustAsPackageProxy; friend struct JustAsPackageProxy;
}; };
// ----------------------------------------------------------------------------- : IncludePackage
/// A package that just contains a bunch of files that are used from other packages
class IncludePackage : public Packaged {
protected:
String typeName() const;
DECLARE_REFLECTION();
};
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -15,21 +15,6 @@ ...@@ -15,21 +15,6 @@
#include <data/export_template.hpp> #include <data/export_template.hpp>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
// ----------------------------------------------------------------------------- : IncludePackage
/// A package that just contains a bunch of files that are used from other packages
class IncludePackage : public Packaged {
protected:
String typeName() const;
DECLARE_REFLECTION();
};
String IncludePackage::typeName() const { return _("include"); }
IMPLEMENT_REFLECTION(IncludePackage) {
REFLECT_BASE(Packaged);
}
// ----------------------------------------------------------------------------- : PackageManager // ----------------------------------------------------------------------------- : PackageManager
PackageManager packages; PackageManager packages;
......
...@@ -71,6 +71,9 @@ class PackageManager { ...@@ -71,6 +71,9 @@ class PackageManager {
/// Check if the given dependency is currently installed /// Check if the given dependency is currently installed
bool checkDependency(const PackageDependency& dep, bool report_errors = false); bool checkDependency(const PackageDependency& dep, bool report_errors = false);
inline String getGlobalDataDir() const { return global_data_directory; }
inline String getLocalDataDir() const { return local_data_directory; }
private: private:
map<String, PackagedP> loaded_packages; map<String, PackagedP> loaded_packages;
String global_data_directory; String global_data_directory;
......
...@@ -21,15 +21,6 @@ ...@@ -21,15 +21,6 @@
// ----------------------------------------------------------------------------- : Linux // ----------------------------------------------------------------------------- : Linux
#ifdef __linux__
/// wxMkDir as documented
inline void wxMkDir(const String& dir) {
wxMkDir(wxConvLocal.cWX2MB(dir), 0777);
}
#endif
// ----------------------------------------------------------------------------- : GCC // ----------------------------------------------------------------------------- : GCC
#ifdef __GNUC__ #ifdef __GNUC__
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment