update checker

This commit is contained in:
GenevensiS
2026-02-08 02:27:19 +01:00
parent 42b9c241f3
commit 46414307fd
36 changed files with 917 additions and 544 deletions
+38 -26
View File
@@ -20,6 +20,7 @@
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
#include <wx/stdpaths.h>
#include <unordered_set>
// Don't do this check for now, because we can't bless packages
#define USE_MODIFIED_CHECK 0
@@ -36,17 +37,17 @@ IMPLEMENT_REFLECTION(Installer) {
void Installer::validate(Version file_app_version) {
Packaged::validate(file_app_version);
// load icons where possible
// load icons if it's a disk path
FOR_EACH(p,packages) {
String url = p->icon_url;
String filename = p->icon_url;
if (settings.darkMode() && !p->dark_icon_url.empty()) {
url = p->dark_icon_url;
filename = p->dark_icon_url;
}
if (!url.empty() && !starts_with(url,_("http:"))) {
if (!filename.empty() && !starts_with(filename,_("http"))) {
// TODO: support absolute icon names
try{
String filename = p->name + _("/") + url;
auto img_stream = openIn(p->name + _("/") + url);
String filepath = p->name + _("/") + filename;
auto img_stream = openIn(filepath);
image_load_file(p->icon, *img_stream);
} catch (...) {
// ignore errors, it's just an image
@@ -251,7 +252,7 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) {
}
void PackageDescription::merge(const PackageDescription& p2) {
if (!icon.Ok() && !icon_url) icon = p2.icon;
if (!icon.Ok()) icon = p2.icon;
if (installer_group.empty()) installer_group = p2.installer_group;
if (short_name.empty()) short_name = p2.short_name;
if (full_name.empty()) full_name = p2.full_name;
@@ -505,33 +506,44 @@ void remove_package_dependency(InstallablePackages& packages, Dep dep, PackageAc
// ----------------------------------------------------------------------------- : Installable package : dependency stuff (OLD)
bool add_package_dependency(InstallablePackages& packages, const PackageDependency& dep, PackageAction where, bool set) {
bool add_package_dependency(InstallablePackages& packages, const InstallablePackageP& package, const PackageDependency& dep, PackageAction where, bool set, unordered_set<String>& already_checked) {
FOR_EACH(p, packages) {
if (p->description->name == dep.package) {
// Some package depends on this package, so install it if needed
if (p->description->name == dep.package) {
if (already_checked.find(p->description->name) != already_checked.end()) return true;
already_checked.insert(p->description->name);
// package depends on p, so install p if needed
// Mark the installation as "automatically needed for X packages"
// if !set then instead the dependency is no longer needed because we are not installing the package
// if !set then instead the dependency is no longer needed because we are no longer installing package
if (!p->installed || p->installed->version < dep.version) {
bool change = false;
if (p->action & PACKAGE_ACT_INSTALL) {
// this package is already scheduled for installation
// p is already scheduled for installation
if (p->automatic) {
// we are already automatically depending on this package
// we are already automatically depending on p
p->automatic += set ? +1 : -1;
if (p->automatic == 0) {
// no one needs this package anymore
// no one needs p anymore
p->action = PACKAGE_ACT_NOTHING;
change = true;
}
}
// handle circular dependencies
if (!set) {
FOR_EACH(pdep, p->description->dependencies) {
if (package->description->name == pdep->package && (!package->installed || package->installed->version < pdep->version)) {
// p depends on package, so we can no longer install p
// because it depends on a version of package that we are no longer installing
p->automatic = 0;
p->action = PACKAGE_ACT_NOTHING;
break;
}
}
}
} else if (set) {
p->action = where | PACKAGE_ACT_INSTALL;
p->automatic = 1;
change = true;
}
// recursively add/remove dependencies
FOR_EACH(dep, p->description->dependencies) {
if (!add_package_dependency(packages, *dep, where, set)) {
if (!add_package_dependency(packages, p, *dep, where, set, already_checked)) {
return false; // failed
}
}
@@ -573,9 +585,10 @@ bool set_package_action_unsafe(InstallablePackages& packages, const InstallableP
// need the package
package->automatic = 0;
package->action = action;
// check dependencies
// check dependencies
unordered_set<String> already_checked;
FOR_EACH(dep, package->description->dependencies) {
if (!add_package_dependency(packages, *dep, where, !(action & PACKAGE_ACT_NOTHING))) return false;
if (!add_package_dependency(packages, package, *dep, where, !(action & PACKAGE_ACT_NOTHING), already_checked)) return false;
}
return true;
} else if ((action & PACKAGE_ACT_REMOVE) || ((action & PACKAGE_ACT_NOTHING) && !package->has(PACKAGE_INSTALLED))) {
@@ -608,7 +621,7 @@ bool set_package_action(InstallablePackages& packages, const InstallablePackageP
// ----------------------------------------------------------------------------- : MSE package
String mse_package = _("magicseteditor.exe");
String mse_package = _("Magic Set Editor");
InstallablePackageP mse_installable_package() {
PackageVersionP mse_version(new PackageVersion(
@@ -618,11 +631,10 @@ InstallablePackageP mse_installable_package() {
mse_version->name = mse_package;
mse_version->version = app_version;
PackageDescriptionP mse_description(new PackageDescription);
mse_description->name = mse_package;
mse_description->short_name = mse_description->full_name = mse_description->installer_group
= _TITLE_("magic set editor");
mse_description->position_hint = -100;
mse_description->icon = load_resource_image(_("installer_program"));
mse_description->name = mse_description->installer_group = mse_package;
mse_description->short_name = mse_description->full_name = _TITLE_("magic set editor");
mse_description->position_hint = -100;
mse_description->icon = load_resource_image(_("installer_program"));
//mse_description->description = _LABEL_("magic set editor package");
return make_intrusive<InstallablePackage>(mse_description, mse_version);
}
+1 -1
View File
@@ -191,7 +191,7 @@ bool set_package_action(InstallablePackages& packages, const InstallablePackageP
// ----------------------------------------------------------------------------- : Program package
/// The "magicseteditor.exe" package is special, it refers to the program
/// The "Magic Set Editor" package is special, it refers to the program
extern String mse_package;
InstallablePackageP mse_installable_package();
+17 -19
View File
@@ -26,9 +26,16 @@
// ----------------------------------------------------------------------------- : Extra types
IMPLEMENT_REFLECTION_ENUM(CheckUpdates) {
VALUE_N("if connected", CHECK_IF_CONNECTED); //default
VALUE_N("always", CHECK_ALWAYS);
VALUE_N("never", CHECK_NEVER);
VALUE_N("always", CHECK_ALWAYS);
VALUE_N("every 5", CHECK_5); //default
VALUE_N("every 10", CHECK_10);
VALUE_N("never", CHECK_NEVER);
}
IMPLEMENT_REFLECTION_ENUM(CheckUpdatesTargets) {
VALUE_N("update app", CHECK_APP);
VALUE_N("update games", CHECK_GAMES);
VALUE_N("update everything", CHECK_EVERYTHING); //default
}
IMPLEMENT_REFLECTION_ENUM(InstallType) {
@@ -203,13 +210,10 @@ Settings::Settings()
, dark_mode_type (DARKMODE_SYSTEM)
, import_scale_selection (0)
, allow_image_download (true)
#if USE_OLD_STYLE_UPDATE_CHECKER
, updates_url (_("https://magicseteditor.boards.net/page/downloads"))
#endif
, package_versions_url (_("https://magicseteditor.boards.net/page/downloads"))
, installer_list_url (_("https://magicseteditor.boards.net/page/downloads"))
, check_updates (CHECK_IF_CONNECTED)
, check_updates_all (true)
, installer_list_url (_("https://raw.githubusercontent.com/MagicSetEditorPacks/Installer-Pack/refs/heads/main/packages.txt"))
, check_updates_what (CHECK_EVERYTHING)
, check_updates_when (CHECK_5)
, check_updates_counter (0)
, website_url (_("https://magicseteditor.boards.net/"))
, documentation_url (_("https://mseverse.miraheze.org/wiki/Dev:Documentation#Topics"))
, install_type (INSTALL_DEFAULT)
@@ -344,15 +348,9 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) {
REFLECT(apprentice_location);
REFLECT(import_scale_selection);
REFLECT(allow_image_download);
#if USE_OLD_STYLE_UPDATE_CHECKER
REFLECT(updates_url);
#else
REFLECT_COMPAT_IGNORE(<306,"updates_url",String);
#endif
REFLECT(package_versions_url);
REFLECT(installer_list_url);
REFLECT(check_updates);
REFLECT(check_updates_all);
REFLECT(check_updates_what);
REFLECT(check_updates_when);
REFLECT(check_updates_counter);
REFLECT(install_type);
REFLECT(website_url);
REFLECT(documentation_url);
+15 -10
View File
@@ -24,18 +24,23 @@ DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Value);
DECLARE_POINTER_TYPE(AutoReplace);
// For now, use the old style update checker
#define USE_OLD_STYLE_UPDATE_CHECKER 1
// ----------------------------------------------------------------------------- : Extra data structures
/// When to check for updates?
enum CheckUpdates
{ CHECK_ALWAYS
, CHECK_IF_CONNECTED
, CHECK_5
, CHECK_10
, CHECK_NEVER
};
/// What to check for updates?
enum CheckUpdatesTargets
{ CHECK_APP
, CHECK_GAMES
, CHECK_EVERYTHING
};
/// Where to install to?
enum InstallType
{ INSTALL_DEFAULT // the platform default.
@@ -236,13 +241,13 @@ public:
// --------------------------------------------------- : Update checking
#if USE_OLD_STYLE_UPDATE_CHECKER
String updates_url;
#endif
String package_versions_url; ///< latest package versions
String installer_list_url; ///< available installers
CheckUpdates check_updates;
bool check_updates_all; ///< Check updates of all packages, not just the program
CheckUpdatesTargets check_updates_what;
CheckUpdates check_updates_when;
int check_updates_counter;
// --------------------------------------------------- : Help links
String website_url;
String documentation_url;
+50
View File
@@ -0,0 +1,50 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make card games |
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <data/updater.hpp>
#include <util/io/package_manager.hpp>
// ----------------------------------------------------------------------------- : Updater
void Updater::updateApplication(String argv) {
String path = absoluteFilename() + wxFileName::GetPathSeparator() + updater_name;
path = path + _(".exe");
if (wxFileExists(path)) {
wxExecute(path + _(" ") + argv, wxEXEC_ASYNC);
}
else {
queue_message(MESSAGE_ERROR, _("Executable file '" + path + "' not found!"));
}
}
UpdaterP Updater::byName(const String& name) {
return package_manager.open<Updater>(name + _(".mse-updater"));
}
IMPLEMENT_REFLECTION_NO_SCRIPT(Updater) {
REFLECT_BASE(Packaged);
REFLECT(updater_name);
}
String Updater::typeNameStatic() { return _("updater"); }
String Updater::typeName() const { return _("updater"); }
Version Updater::fileVersion() const { return app_version; }
void Updater::validate(Version file_app_version) {
Packaged::validate(file_app_version);
}
// special behaviour of reading/writing UpdaterPs: only read/write the name
void Reader::handle(UpdaterP& updater) {
updater = Updater::byName(getValue());
}
void Writer::handle(const UpdaterP& updater) {
if (updater) handle(updater->name());
}
+44
View File
@@ -0,0 +1,44 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make card games |
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#pragma once
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/reflect.hpp>
#include <util/io/package.hpp>
DECLARE_POINTER_TYPE(Updater);
// ----------------------------------------------------------------------------- : Updater
/// A description of an updater for the app (There should really only ever be one updater)
class Updater : public Packaged {
public:
Updater() {};
String updater_name;
// Close MSE and run the updater exe
void updateApplication(String argv);
static UpdaterP byName(const String& name);
static String typeNameStatic();
String typeName() const override;
Version fileVersion() const override;
protected:
void validate(Version) override;
DECLARE_REFLECTION();
};
inline String type_name(const Updater&) {
return _TYPE_("updater");
}