Skip to content

Commit

Permalink
AppInfoView: Warn about OS runtime mismatch (#1807)
Browse files Browse the repository at this point in the history
  • Loading branch information
meisenzahl authored Jan 11, 2022
1 parent 7072fb7 commit 107ad29
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 4 deletions.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ conf_data.set('GETTEXT_PACKAGE', meson.project_name())
conf_data.set('APP_NAME', get_option('name'))
conf_data.set('HIDDEN_APP_LIST', get_option('hidden_app_list_file'))
conf_data.set('VERSION', meson.project_version())
conf_data.set('RUNTIME_NAME', get_option('runtime_name'))
conf_data.set('CONFIGDIR', config_dir)
conf_data.set('EXEC_PATH', join_paths (get_option('prefix'), get_option('bindir'), meson.project_name()))
conf_data.set('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir')))
Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ option('name', type : 'string', value : 'AppCenter', description : 'The name of
option('payments', type : 'boolean', value : true, description : 'Enable payment features and display paid apps')
option('sharing', type : 'boolean', value : true, description : 'Display sharing features, i.e. copyable URLs to appcenter.elementary.io')
option('hide_upstream_distro_apps', type : 'boolean', value : true, description : 'Used for hiding Ubuntu repo apps on elementary OS')
option('runtime_name', type : 'string', value : 'io.elementary.Platform', description : 'The name of the distributor runtime')
71 changes: 69 additions & 2 deletions src/Core/FlatpakBackend.vala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public class AppCenterCore.FlatpakPackage : Package {
}

public class AppCenterCore.FlatpakBackend : Backend, Object {
// Based on https://github.com/flatpak/flatpak/blob/417e3949c0ecc314e69311e3ee8248320d3e3d52/common/flatpak-run-private.h
private const string FLATPAK_METADATA_GROUP_APPLICATION = "Application";
private const string FLATPAK_METADATA_KEY_RUNTIME = "runtime";

// AppStream data has to be 1 hour old before it's refreshed
public const uint MAX_APPSTREAM_AGE = 3600;

Expand Down Expand Up @@ -469,10 +473,10 @@ public class AppCenterCore.FlatpakBackend : Backend, Object {
bool system = fp_package.installation == system_installation;

var id = generate_package_list_key (system, package.component.get_origin (), bundle.get_id ());
return yield get_download_size_by_id (id, cancellable, is_update);
return yield get_download_size_by_id (id, cancellable, is_update, package);
}

public async uint64 get_download_size_by_id (string id, Cancellable? cancellable, bool is_update = false) throws GLib.Error {
public async uint64 get_download_size_by_id (string id, Cancellable? cancellable, bool is_update = false, Package? package = null) throws GLib.Error {
bool system;
string origin, bundle_id;
var split_success = get_package_list_key_parts (id, out system, out origin, out bundle_id);
Expand Down Expand Up @@ -527,6 +531,29 @@ public class AppCenterCore.FlatpakBackend : Backend, Object {
return;
}

try {
if (package != null) {
var remote_name = entry.get_remote ();
var kind = entry_ref.kind;
var name = entry_ref.name;
var arch = entry_ref.arch;
var branch = entry_ref.branch;
var remote_ref = installation.fetch_remote_ref_sync (remote_name, kind, name, arch, branch, cancellable);

if (remote_ref.get_eol () != null || remote_ref.get_eol_rebase () != null) {
package.runtime_status = RuntimeStatus.END_OF_LIFE;
} else {
var os_version_id = Environment.get_os_info (GLib.OsInfoKey.VERSION_ID) ?? "";
if (kind == Flatpak.RefKind.APP && Build.RUNTIME_NAME.length > 0 && os_version_id.length > 0) {
var expected_runtime = "%s/%s/%s".printf (Build.RUNTIME_NAME, flatpak_ref.get_arch (), os_version_id);
update_runtime_status (package, entry.get_metadata (), expected_runtime, os_version_id);
}
}
}
} catch (Error e) {
warning ("Could not query runtime status: %s", e.message);
}

// Don't include runtime deps in download size for apps we're updating
// as this is counted in the OS Updates package
var entry_is_runtime_dep = entry_ref.kind == Flatpak.RefKind.RUNTIME;
Expand Down Expand Up @@ -854,6 +881,46 @@ public class AppCenterCore.FlatpakBackend : Backend, Object {
return true;
}

private bool get_runtime_parts (string runtime, out string? id, out string? arch, out string ?branch) {
id = null;
arch = null;
branch = null;

string[] parts = runtime.split ("/", 3);
if (parts.length != 3) {
return false;
}

id = parts[0];
arch = parts[1];
branch = parts[2];

return true;
}

private void update_runtime_status (Package package, KeyFile metadata, string expected_runtime, string os_version_id) throws Error {
var runtime = metadata.get_string (FLATPAK_METADATA_GROUP_APPLICATION, FLATPAK_METADATA_KEY_RUNTIME);
string expected_runtime_id, expected_runtime_arch, expected_runtime_branch;
string runtime_id = "", runtime_arch, runtime_branch = "";
if (get_runtime_parts (expected_runtime, out expected_runtime_id, out expected_runtime_arch, out expected_runtime_branch) &&
get_runtime_parts (runtime, out runtime_id, out runtime_arch, out runtime_branch)) {
if (expected_runtime_id == runtime_id && expected_runtime != runtime) {
// daily, next, ...
if (int.parse (runtime_branch) == 0) {
package.runtime_status = RuntimeStatus.UNSTABLE;
} else if (double.parse (os_version_id) > double.parse (runtime_branch)) {
if (int.parse (os_version_id) > int.parse (runtime_branch)) {
// major os upgrade (7 > 6)
package.runtime_status = RuntimeStatus.MAJOR_OUTDATED;
} else {
// minor os upgrade (6.1 > 6.0)
package.runtime_status = RuntimeStatus.MINOR_OUTDATED;
}
}
}
}
}

private void delete_folder_contents (File folder, Cancellable? cancellable = null) {
FileEnumerator enumerator;
try {
Expand Down
10 changes: 10 additions & 0 deletions src/Core/Package.vala
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,20 @@ public class AppCenterCore.PackageDetails : Object {
public string? version { get; set; }
}

public enum RuntimeStatus {
UP_TO_DATE,
END_OF_LIFE,
MAJOR_OUTDATED,
MINOR_OUTDATED,
UNSTABLE;
}

public class AppCenterCore.Package : Object {
public const string APPCENTER_PACKAGE_ORIGIN = "appcenter";
private const string ELEMENTARY_STABLE_PACKAGE_ORIGIN = "elementary-stable-focal-main";

public RuntimeStatus runtime_status { get; set; default = RuntimeStatus.UP_TO_DATE; }

/* Note: These are just a stopgap, and are not a replacement for a more
* fleshed out parental control system. We assume any of these "moderate"
* or above is considered explicit for our naive warning.
Expand Down
49 changes: 47 additions & 2 deletions src/Views/AppInfoView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ namespace AppCenter.Views {
private Hdy.CarouselIndicatorDots screenshot_switcher;
private ArrowButton screenshot_next;
private ArrowButton screenshot_previous;
private Gtk.FlowBox oars_flowbox;
private Gtk.Revealer oars_flowbox_revealer;

private bool is_runtime_warning_shown = false;

private unowned Gtk.StyleContext stack_context;

Expand Down Expand Up @@ -100,13 +104,16 @@ namespace AppCenter.Views {
"oars-gambling-symbolic"
);

var oars_flowbox = new Gtk.FlowBox () {
oars_flowbox = new Gtk.FlowBox () {
column_spacing = 24,
margin_bottom = 24,
row_spacing = 24,
selection_mode = Gtk.SelectionMode.NONE
};

oars_flowbox_revealer = new Gtk.Revealer ();
oars_flowbox_revealer.add (oars_flowbox);

#if CURATED
if (!package.is_native && !package.is_os_updates) {
var uncurated = new ContentType (
Expand Down Expand Up @@ -522,8 +529,9 @@ namespace AppCenter.Views {
row_spacing = 24
};

content_grid.add (oars_flowbox_revealer);
if (oars_flowbox.get_children ().length () > 0) {
content_grid.add (oars_flowbox);
oars_flowbox_revealer.reveal_child = true;
}

if (screenshots.length > 0) {
Expand Down Expand Up @@ -743,6 +751,43 @@ namespace AppCenter.Views {

var size = yield package.get_download_size_including_deps ();
size_label.update (size, package.is_flatpak);

ContentType? runtime_warning = null;
switch (package.runtime_status) {
case RuntimeStatus.END_OF_LIFE:
runtime_warning = new ContentType (
_("Outdated"),
_("Built with older technologies that may not work as expected or receive security updates"),
"software-update-urgent-symbolic"
);
break;
case RuntimeStatus.MAJOR_OUTDATED:
runtime_warning = new ContentType (
_("Outdated"),
_("Built for an older version of %s; might not support the latest features").printf (Environment.get_os_info (GLib.OsInfoKey.NAME)),
"software-update-available-symbolic"
);
break;
case RuntimeStatus.MINOR_OUTDATED:
break;
case RuntimeStatus.UNSTABLE:
runtime_warning = new ContentType (
_("Unstable"),
_("Built for an unstable version of %s; may contain major issues. Not recommended for use on a production system.").printf (Environment.get_os_info (GLib.OsInfoKey.NAME)),
"applications-development-symbolic"
);
break;
case RuntimeStatus.UP_TO_DATE:
break;
}

if (runtime_warning != null && !is_runtime_warning_shown) {
is_runtime_warning_shown = true;

oars_flowbox.insert (runtime_warning, 0);
oars_flowbox.show_all ();
oars_flowbox_revealer.reveal_child = true;
}
}

public void view_entered () {
Expand Down
1 change: 1 addition & 0 deletions src/config.vala.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ namespace Build {
public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@";
public const string PROJECT_NAME = "@PROJECT_NAME@";
public const string VERSION = "@VERSION@";
public const string RUNTIME_NAME = "@RUNTIME_NAME@";
}

0 comments on commit 107ad29

Please sign in to comment.