Skip to content

Commit

Permalink
Install PackageKit based Operating System Updates as Offline Updates (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
meisenzahl committed Dec 27, 2022
1 parent 4b336a9 commit 73ac7e6
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 42 deletions.
16 changes: 16 additions & 0 deletions src/Core/BackendAggregator.vala
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ public class AppCenterCore.BackendAggregator : Backend, Object {
set { }
}

public async Gee.Collection<PackageDetails> get_prepared_applications (Cancellable? cancellable = null) {
var apps = new Gee.TreeSet<PackageDetails> ();
foreach (var backend in backends) {
if (cancellable.is_cancelled ()) {
break;
}

var prepared = yield backend.get_prepared_applications (cancellable);
if (prepared != null) {
apps.add_all (prepared);
}
}

return apps;
}

public async Gee.Collection<Package> get_installed_applications (Cancellable? cancellable = null) {
var apps = new Gee.TreeSet<Package> ();
foreach (var backend in backends) {
Expand Down
1 change: 1 addition & 0 deletions src/Core/BackendInterface.vala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface AppCenterCore.Backend : Object {
public abstract Job.Type job_type { get; protected set; }
public abstract bool working { public get; protected set; }

public abstract async Gee.Collection<PackageDetails> get_prepared_applications (Cancellable? cancellable = null);
public abstract async Gee.Collection<Package> get_installed_applications (Cancellable? cancellable = null);
public abstract Gee.Collection<Package> get_applications_for_category (AppStream.Category category);
public abstract Gee.Collection<Package> search_applications (string query, AppStream.Category? category);
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Client.vala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public class AppCenterCore.Client : Object {
last_cache_update = new DateTime.from_unix_utc (AppCenter.App.settings.get_int64 ("last-refresh-time"));
}

public async Gee.Collection<AppCenterCore.PackageDetails> get_prepared_applications (Cancellable? cancellable = null) {
return yield BackendAggregator.get_default ().get_prepared_applications (cancellable);
}

public async Gee.Collection<AppCenterCore.Package> get_installed_applications (Cancellable? cancellable = null) {
return yield BackendAggregator.get_default ().get_installed_applications (cancellable);
}
Expand Down
6 changes: 6 additions & 0 deletions src/Core/FlatpakBackend.vala
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ public class AppCenterCore.FlatpakBackend : Backend, Object {
return job;
}

public async Gee.Collection<PackageDetails> get_prepared_applications (Cancellable? cancellable = null) {
var prepared_apps = new Gee.HashSet<PackageDetails> ();

return prepared_apps;
}

public async Gee.Collection<Package> get_installed_applications (Cancellable? cancellable = null) {
var installed_apps = new Gee.HashSet<Package> ();

Expand Down
7 changes: 6 additions & 1 deletion src/Core/Job.vala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public class AppCenterCore.Job : Object {
REMOVE_PACKAGE,
IS_PACKAGE_INSTALLED,
GET_PACKAGE_DETAILS,
GET_PACKAGE_DEPENDENCIES
GET_PACKAGE_DEPENDENCIES,
GET_PREPARED_PACKAGES
}

public Job (Type type) {
Expand All @@ -47,6 +48,10 @@ public class AppCenterCore.Job : Object {

public abstract class AppCenterCore.JobArgs { }

public class AppCenterCore.GetPreparedPackagesArgs : JobArgs {
public Cancellable? cancellable;
}

public class AppCenterCore.GetInstalledPackagesArgs : JobArgs {
public Cancellable? cancellable;
}
Expand Down
160 changes: 152 additions & 8 deletions src/Core/PackageKitBackend.vala
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
job_type = job.operation;
working = true;
switch (job.operation) {
case Job.Type.GET_PREPARED_PACKAGES:
get_prepared_packages_internal (job);
break;
case Job.Type.GET_INSTALLED_PACKAGES:
get_installed_packages_internal (job);
break;
Expand Down Expand Up @@ -148,7 +151,9 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
});

loop.run ();
client = new Task ();
client = new Task () {
only_download = true
};
}

private PackageKitBackend () {
Expand Down Expand Up @@ -325,6 +330,27 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
return null;
}

public async Gee.Collection<AppCenterCore.PackageDetails> get_prepared_applications (Cancellable? cancellable = null) {
var packages = new Gee.TreeSet<AppCenterCore.PackageDetails> ();

var pk_prepared = yield get_prepared_packages ();
var package_array = pk_prepared.get_package_array ();
foreach (var pk_package in package_array) {
packages.add (new PackageDetails () {
name = pk_package.get_name (),
description = pk_package.description,
summary = pk_package.get_summary (),
version = pk_package.get_version ()
});
}

if (package_array.length > 0) {
updates_changed_callback ();
}

return packages;
}

public async Gee.Collection<AppCenterCore.Package> get_installed_applications (Cancellable? cancellable = null) {
var packages = new Gee.TreeSet<AppCenterCore.Package> ();
var installed = yield get_installed_packages (cancellable);
Expand Down Expand Up @@ -479,6 +505,62 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
return job;
}

private void get_prepared_packages_internal (Job job) {
var args = (GetPreparedPackagesArgs)job.args;
var cancellable = args.cancellable;

Pk.Results? results = null;
try {
results = client.get_updates (0, cancellable, (t, p) => { });
} catch (Error e) {
job.error = e;
job.results_ready ();
return;
}

string[] package_ids = {};
var downloaded_updates = get_downloaded_updates ();
results.get_package_array ().foreach ((pk_package) => {
if (downloaded_updates.contains (pk_package.get_id ())) {
package_ids += pk_package.get_id ();
}
});

if (package_ids.length == 0) {
job.result = Value (typeof (Object));
job.result.take_object (new Pk.Results ());
job.results_ready ();
return;
}

package_ids += null;

Pk.Results details;
try {
details = client.get_details (package_ids, cancellable, (p, t) => {});
} catch (Error e) {
job.error = e;
job.results_ready ();
return;
}

details.get_details_array ().foreach ((details) => {
results.add_details (details);
});

job.result = Value (typeof (Object));
job.result.take_object ((owned) results);
job.results_ready ();
}

public async Pk.Results get_prepared_packages (Cancellable? cancellable = null) {
var job_args = new GetPreparedPackagesArgs ();
job_args.cancellable = cancellable;

var job = yield launch_job (Job.Type.GET_PREPARED_PACKAGES, job_args);
return (Pk.Results)job.result.get_object ();
}

private void get_installed_packages_internal (Job job) {
unowned var args = (GetInstalledPackagesArgs)job.args;
unowned var cancellable = args.cancellable;
Expand Down Expand Up @@ -670,6 +752,9 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
});

exit_status = results.get_exit_code ();
if (exit_status == Pk.Exit.SUCCESS) {
Pk.offline_trigger (Pk.OfflineAction.REBOOT, cancellable);
}
} catch (Error e) {
job.error = e;
job.results_ready ();
Expand Down Expand Up @@ -756,6 +841,53 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
return job.result.get_boolean ();
}

private Gee.ArrayList<string> get_downloaded_updates () {
var downloaded_updates = new Gee.ArrayList<string> ();

// A PackageKit update query with Filters set to Pk.Filter.DOWNLOADED and Pk.Filter.NOT_INSTALLED
// returns all downloaded but not installed packages even if they are not prepared for an update.
// So instead we read the prepared updates from the configuration file which would also be read
// by the PackageKit daemon on boot.
const string PK_PREPARED_IDS_PATH = "/var/lib/PackageKit/prepared-update";

if (!FileUtils.test (PK_PREPARED_IDS_PATH, FileTest.IS_REGULAR)) {
return downloaded_updates;
}

var key_file = new KeyFile ();
try {
key_file.load_from_file (PK_PREPARED_IDS_PATH, KeyFileFlags.NONE);
var prepared_ids = key_file.get_string ("update", "prepared_ids").split (",");
downloaded_updates = new Gee.ArrayList<string>.wrap (prepared_ids);
} catch (Error e) {
warning ("Unable to read PackageKit prepared ids: %s", e.message);
}

return downloaded_updates;
}

public bool is_restart_required () {
const string PK_OFFLINE_UPDATE_ACTION_PATH = "/var/lib/PackageKit/offline-update-action";

if (!FileUtils.test (PK_OFFLINE_UPDATE_ACTION_PATH, FileTest.IS_REGULAR)) {
return false;
}

var pk_offline_update_action = File.new_for_path (PK_OFFLINE_UPDATE_ACTION_PATH);
try {
var @is = pk_offline_update_action.read ();
var dis = new DataInputStream (@is);

if ("reboot" in dis.read_line ()) {
return true;
}
} catch (Error e) {
critical ("Couldn't read PackageKit offline update action: %s", e.message);
}

return false;
}

private void get_updates_internal (Job job) {
var args = (GetUpdatesArgs)job.args;
var cancellable = args.cancellable;
Expand All @@ -782,18 +914,21 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
return;
}

if (results.get_package_array ().length == 0) {
string[] package_ids = {};
var downloaded_updates = get_downloaded_updates ();
results.get_package_array ().foreach ((pk_package) => {
if (!downloaded_updates.contains (pk_package.get_id ())) {
package_ids += pk_package.get_id ();
}
});

if (package_ids.length == 0) {
job.result = Value (typeof (Object));
job.result.take_object (results);
job.result.take_object (new Pk.Results ());
job.results_ready ();
return;
}

string[] package_ids = {};
results.get_package_array ().foreach ((pk_package) => {
package_ids += pk_package.get_id ();
});

package_ids += null;

Pk.Results details;
Expand Down Expand Up @@ -830,6 +965,15 @@ public class AppCenterCore.PackageKitBackend : Backend, Object {
unowned var args = (RefreshCacheArgs)job.args;
unowned var cancellable = args.cancellable;

// Don't refresh cache if PackageKit prepared updates.
// Otherwise PackageKit deletes all information related to prepared updates
if (get_downloaded_updates ().size > 0) {
job.result = Value (typeof (bool));
job.result.set_boolean (true);
job.results_ready ();
return;
}

Pk.Results? results = null;
try {
results = client.refresh_cache (false, cancellable, (t, p) => { });
Expand Down
6 changes: 6 additions & 0 deletions src/Core/UbuntuDriversBackend.vala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ public class AppCenterCore.UbuntuDriversBackend : Backend, Object {
return command.get_exit_status () == 0;
}

public async Gee.Collection<PackageDetails> get_prepared_applications (Cancellable? cancellable = null) {
var prepared_packages = new Gee.HashSet<PackageDetails> ();

return prepared_packages;
}

public async Gee.Collection<Package> get_installed_applications (Cancellable? cancellable = null) {
if (cached_packages != null) {
return cached_packages;
Expand Down
53 changes: 20 additions & 33 deletions src/Core/UpdateManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,16 @@ public class AppCenterCore.UpdateManager : Object {

package_array.foreach ((pk_package) => {
var pkg_name = pk_package.get_name ();
var appcenter_package = client.lookup_package_by_id (pkg_name);
if (appcenter_package != null) {
debug ("Added %s to app updates", pkg_name);
apps_with_updates.add (appcenter_package);
count++;
appcenter_package.latest_version = pk_package.get_version ();
updates_size += appcenter_package.change_information.size;
} else {
debug ("Added %s to OS updates", pkg_name);
os_count++;
unowned string pkg_summary = pk_package.get_summary ();
unowned string pkg_version = pk_package.get_version ();
os_desc += Markup.printf_escaped (
"%s\n\t%s\n\t%s\n",
pkg_name,
pkg_summary,
_("Version: %s").printf (pkg_version)
);
}
debug ("Added %s to OS updates", pkg_name);
os_count++;
unowned string pkg_summary = pk_package.get_summary ();
unowned string pkg_version = pk_package.get_version ();
os_desc += Markup.printf_escaped (
"%s\n\t%s\n\t%s\n",
pkg_name,
pkg_summary,
_("Version: %s").printf (pkg_version)
);
});

os_updates.component.set_pkgnames ({});
Expand Down Expand Up @@ -221,19 +212,13 @@ public class AppCenterCore.UpdateManager : Object {
try {
pk_package.set_id (pk_detail.get_package_id ());
var pkg_name = pk_package.get_name ();
var appcenter_package = client.lookup_package_by_id (pkg_name);
if (appcenter_package != null) {
appcenter_package.change_information.updatable_packages.@set (client, pk_package.get_id ());
appcenter_package.change_information.size += pk_detail.size;
appcenter_package.update_state ();
} else {
var pkgnames = os_updates.component.pkgnames;
pkgnames += pkg_name;
os_updates.component.pkgnames = pkgnames;

os_updates.change_information.updatable_packages.@set (client, pk_package.get_id ());
os_updates.change_information.size += pk_detail.size;
}

var pkgnames = os_updates.component.pkgnames;
pkgnames += pkg_name;
os_updates.component.pkgnames = pkgnames;

os_updates.change_information.updatable_packages.@set (client, pk_package.get_id ());
os_updates.change_information.size += pk_detail.size;
} catch (Error e) {
critical (e.message);
}
Expand All @@ -245,7 +230,9 @@ public class AppCenterCore.UpdateManager : Object {
}

public void update_restart_state () {
if (restart_file.query_exists ()) {
var should_restart = restart_file.query_exists () || PackageKitBackend.get_default ().is_restart_required ();

if (should_restart) {
if (!restart_required) {
string title = _("Restart Required");
string body = _("Please restart your system to finalize updates");
Expand Down
1 change: 1 addition & 0 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public class AppCenter.MainWindow : Hdy.ApplicationWindow {
case GET_DOWNLOAD_SIZE:
overlaybar.label = _("Getting download size…");
break;
case GET_PREPARED_PACKAGES:
case GET_INSTALLED_PACKAGES:
case GET_UPDATES:
case REFRESH_CACHE:
Expand Down
Loading

0 comments on commit 73ac7e6

Please sign in to comment.