Skip to content

Commit

Permalink
update: Make autopruned refs automatically removed
Browse files Browse the repository at this point in the history
In order to maintain a system over time update automatically removes any EOL runtimes that are unused.

This extends it to also remove any autopruned refs. In practice this means removing no longer used driver versions as the system is updated.

Closes #5261
  • Loading branch information
TingPing committed Dec 25, 2023
1 parent 65bc369 commit 13413aa
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 30 deletions.
2 changes: 1 addition & 1 deletion app/flatpak-builtins-uninstall.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ flatpak_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GEr

udir = uninstall_dir_ensure (uninstall_dirs, dir);

unused = flatpak_dir_list_unused_refs (dir, opt_arch, NULL, NULL, NULL, FALSE, cancellable, error);
unused = flatpak_dir_list_unused_refs (dir, opt_arch, NULL, NULL, NULL, FLATPAK_DIR_FILTER_NONE, cancellable, error);
if (unused == NULL)
return FALSE;

Expand Down
8 changes: 7 additions & 1 deletion common/flatpak-dir-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ typedef enum {
FLATPAK_DIR_STORAGE_TYPE_NETWORK,
} FlatpakDirStorageType;

typedef enum {
FLATPAK_DIR_FILTER_NONE = 0,
FLATPAK_DIR_FILTER_EOL = 1 << 0,
FLATPAK_DIR_FILTER_AUTOPRUNE = 1 << 1,
} FlatpakDirFilterFlags;

typedef enum {
FIND_MATCHING_REFS_FLAGS_NONE = 0,
FIND_MATCHING_REFS_FLAGS_FUZZY = (1 << 0),
Expand Down Expand Up @@ -1049,7 +1055,7 @@ char ** flatpak_dir_list_unused_refs (Fla
GHashTable *metadata_injection,
GHashTable *eol_injection,
const char * const *refs_to_exclude,
gboolean filter_by_eol,
FlatpakDirFilterFlags filter_flags,
GCancellable *cancellable,
GError **error);

Expand Down
44 changes: 28 additions & 16 deletions common/flatpak-dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -16491,6 +16491,7 @@ find_used_refs (FlatpakDir *self,
GHashTable *metadata_injection,
GHashTable *refs_to_exclude,
GHashTable *used_refs, /* This is filled in */
GHashTable *autopruned_refs, /* This is filled in */
GCancellable *cancellable,
GError **error)
{
Expand Down Expand Up @@ -16662,6 +16663,10 @@ find_used_refs (FlatpakDir *self,
flatpak_decomposed_get_ref (ref_to_analyze), dir_name);
queue_ref_for_analysis (rel->ref, arch, analyzed_refs, refs_to_analyze);
}
else
{
g_hash_table_add (autopruned_refs, flatpak_decomposed_ref (rel->ref));
}
}
}

Expand All @@ -16672,19 +16677,22 @@ find_used_refs (FlatpakDir *self,
* flatpak_installation_list_unused_refs_with_options().
* The returned pointer array is transfer full. */
char **
flatpak_dir_list_unused_refs (FlatpakDir *self,
const char *arch,
GHashTable *metadata_injection,
GHashTable *eol_injection,
const char * const *refs_to_exclude,
gboolean filter_by_eol,
GCancellable *cancellable,
GError **error)
flatpak_dir_list_unused_refs (FlatpakDir *self,
const char *arch,
GHashTable *metadata_injection,
GHashTable *eol_injection,
const char * const *refs_to_exclude,
FlatpakDirFilterFlags filter_flags,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GHashTable) used_refs = NULL;
g_autoptr(GHashTable) autoprune_refs = NULL;
g_autoptr(GHashTable) excluded_refs_ht = NULL;
g_autoptr(GPtrArray) refs = NULL;
g_autoptr(GPtrArray) runtime_refs = NULL;
gboolean filter_by_eol = filter_flags & FLATPAK_DIR_FILTER_EOL;
gboolean filter_by_autoprune = filter_flags & FLATPAK_DIR_FILTER_AUTOPRUNE;

/* Convert refs_to_exclude to hashtable for fast repeated lookups */
if (refs_to_exclude)
Expand All @@ -16700,12 +16708,14 @@ flatpak_dir_list_unused_refs (FlatpakDir *self,
}

used_refs = g_hash_table_new_full ((GHashFunc)flatpak_decomposed_hash, (GEqualFunc)flatpak_decomposed_equal, (GDestroyNotify)flatpak_decomposed_unref, NULL);
autoprune_refs = g_hash_table_new_full ((GHashFunc)flatpak_decomposed_hash, (GEqualFunc)flatpak_decomposed_equal, (GDestroyNotify)flatpak_decomposed_unref, NULL);

g_info ("Checking installation ‘%s’ %s",
g_info ("Checking installation ‘%s’ %s %s",
flatpak_dir_get_name_cached (self),
filter_by_eol ? "for EOL unused refs" : "for unused refs");
filter_by_eol ? "for EOL unused refs" : "for unused refs",
filter_by_autoprune ? "and autoprunes" : "");
if (!find_used_refs (self, NULL, arch, metadata_injection, excluded_refs_ht,
used_refs, cancellable, error))
used_refs, autoprune_refs, cancellable, error))
return NULL;

/* If @self is a system installation, also check the per-user installation
Expand All @@ -16722,7 +16732,7 @@ flatpak_dir_list_unused_refs (FlatpakDir *self,
g_info ("Checking installation ‘%s’ by checking for dependent refs in ‘%s’",
flatpak_dir_get_name_cached (self), flatpak_dir_get_name_cached (user_dir));
if (!find_used_refs (self, user_dir, arch, metadata_injection, excluded_refs_ht,
used_refs, cancellable, &local_error))
used_refs, autoprune_refs, cancellable, &local_error))
{
/* We may get permission denied if the process is sandboxed with
* systemd's ProtectHome=
Expand Down Expand Up @@ -16752,9 +16762,10 @@ flatpak_dir_list_unused_refs (FlatpakDir *self,
if (arch != NULL && !flatpak_decomposed_is_arch (ref, arch))
continue;

if (filter_by_eol)
if (filter_flags)
{
gboolean is_eol = FALSE;
gboolean is_autopruned = g_hash_table_contains (autoprune_refs, ref);

if (eol_injection && g_hash_table_contains (eol_injection, flatpak_decomposed_get_ref (ref)))
{
Expand All @@ -16772,11 +16783,12 @@ flatpak_dir_list_unused_refs (FlatpakDir *self,
flatpak_deploy_data_get_eol_rebase (deploy_data));
}

if (!is_eol)
if (!((is_autopruned && filter_by_autoprune) || (is_eol && filter_by_eol)))
{
g_debug ("%s: Ref %s (%s) not end-of-life, so excluding from EOL unused refs",
g_debug ("%s: Ref %s (%s) not %s, so excluding from unused refs",
G_STRFUNC, flatpak_decomposed_get_ref (ref),
flatpak_dir_get_name_cached (self));
flatpak_dir_get_name_cached (self),
(!is_eol && filter_by_eol) ? "end-of-life" : "autopruned");
continue;
}
}
Expand Down
20 changes: 15 additions & 5 deletions common/flatpak-installation.c
Original file line number Diff line number Diff line change
Expand Up @@ -3071,10 +3071,11 @@ flatpak_installation_list_unused_refs (FlatpakInstallation *self,
*
* * exclude-refs (as): Act as if these refs are not installed even if they
* are when determining the set of unused refs
* * filter-by-eol (b): Only return refs as unused if they are End-Of-Life.
* Note that if this option is combined with other filters (of which there
* are none currently) non-EOL refs may also be returned.
*
* * filter-by-eol (b): Return refs as unused if they are End-Of-Life.
* Note that if this option is combined with other filters so non-EOL refs may also be returned.
* * filter-by-autoprune (b): Return refs as unused if they should be autopruned.
* Note that if this option is combined with other filters so non-autoprune refs may also be returned.
* Returns: (transfer container) (element-type FlatpakInstalledRef): a GPtrArray of
* #FlatpakInstalledRef instances
*
Expand All @@ -3093,19 +3094,28 @@ flatpak_installation_list_unused_refs_with_options (FlatpakInstallation *self,
g_auto(GStrv) refs_strv = NULL;
g_autofree char **refs_to_exclude = NULL;
gboolean filter_by_eol = FALSE;
gboolean filter_by_autoprune = FALSE;
FlatpakDirFilterFlags filter_flags = FLATPAK_DIR_FILTER_NONE;

if (options)
{
(void) g_variant_lookup (options, "exclude-refs", "^a&s", &refs_to_exclude);
(void) g_variant_lookup (options, "filter-by-eol", "b", &filter_by_eol);
(void) g_variant_lookup (options, "filter-by-autoprune", "b", &filter_by_autoprune);
}

dir = flatpak_installation_get_dir (self, error);
if (dir == NULL)
return NULL;

if (filter_by_eol)
filter_flags |= FLATPAK_DIR_FILTER_EOL;
if (filter_by_autoprune)
filter_flags |= FLATPAK_DIR_FILTER_AUTOPRUNE;

refs_strv = flatpak_dir_list_unused_refs (dir, arch, metadata_injection, NULL,
(const char * const *)refs_to_exclude, filter_by_eol,
(const char * const *)refs_to_exclude,
filter_flags,
cancellable, error);
if (refs_strv == NULL)
return NULL;
Expand Down
5 changes: 3 additions & 2 deletions common/flatpak-transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <glib/gi18n-lib.h>

#include "flatpak-auth-private.h"
#include "flatpak-dir-private.h"
#include "flatpak-error.h"
#include "flatpak-installation-private.h"
#include "flatpak-progress-private.h"
Expand Down Expand Up @@ -4999,7 +5000,7 @@ add_uninstall_unused_ops (FlatpakTransaction *self,
NULL, /* metadata_injection */
NULL, /* eol_injection */
NULL, /* exclude_refs */
TRUE, /* filter_by_eol */
FLATPAK_DIR_FILTER_EOL | FLATPAK_DIR_FILTER_AUTOPRUNE,
cancellable, error);
if (old_unused_refs == NULL)
return FALSE;
Expand Down Expand Up @@ -5056,7 +5057,7 @@ add_uninstall_unused_ops (FlatpakTransaction *self,
metadata_injection,
eol_injection,
to_be_excluded_strv,
TRUE, /* filter_by_eol */
FLATPAK_DIR_FILTER_EOL | FLATPAK_DIR_FILTER_AUTOPRUNE,
cancellable, error);
if (unused_refs == NULL)
return FALSE;
Expand Down
8 changes: 4 additions & 4 deletions doc/flatpak-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -925,10 +925,10 @@
<term><option>autoprune-unless</option> (string)</term>
<listitem><para>
A condition that must be false for the extension to be considered unused when
pruning. For example, <command>flatpak uninstall --unused</command> uses
this information. The only currently recognized value is active-gl-driver,
which is true if the name of the active GL driver matches the extension
point basename. Available since 0.11.8.
pruning. For example, <command>flatpak uninstall --unused</command> and
<command>flatpak update</command> use this information. The only currently
recognized value is active-gl-driver, which is true if the name of the active
GL driver matches the extension point basename. Available since 0.11.8.
</para></listitem>
</varlistentry>
<varlistentry>
Expand Down
13 changes: 12 additions & 1 deletion tests/list-unused.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

static char **opt_exclude_refs;
static gboolean opt_user;
static gboolean opt_filter_eol;
static gboolean opt_filter_autoprune;

static GOptionEntry options[] = {
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, "Work on the user installation", NULL },
{ "exclude", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_exclude_refs, "Exclude ref", "REF" },
{ "filter-eol", 0, 0, G_OPTION_ARG_NONE, &opt_filter_eol, "Filter results to include end-of-life refs", NULL },
{ "filter-autoprune", 0, 0, G_OPTION_ARG_NONE, &opt_filter_autoprune, "Filter results to include autopruned refs", NULL },
{ NULL }
};

Expand All @@ -19,6 +23,7 @@ main (int argc, char *argv[])
g_autoptr(GError) error = NULL;
g_auto(GStrv) refs = NULL;
g_autoptr(GOptionContext) context = NULL;
FlatpakDirFilterFlags filter_flags = FLATPAK_DIR_FILTER_NONE;
int i;

context = g_option_context_new ("");
Expand All @@ -35,7 +40,13 @@ main (int argc, char *argv[])
else
dir = flatpak_dir_get_system_default ();

refs = flatpak_dir_list_unused_refs (dir, NULL, NULL, NULL, (const char * const *)opt_exclude_refs, FALSE, NULL, &error);
if (opt_filter_eol)
filter_flags |= FLATPAK_DIR_FILTER_EOL;

if (opt_filter_autoprune)
filter_flags |= FLATPAK_DIR_FILTER_AUTOPRUNE;

refs = flatpak_dir_list_unused_refs (dir, NULL, NULL, NULL, (const char * const *)opt_exclude_refs, filter_flags, NULL, &error);
g_assert_nonnull (refs);
g_assert_no_error (error);

Expand Down
6 changes: 6 additions & 0 deletions tests/test-unused.sh
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ verify_unused() {
assert_not_file_has_content unused.txt "\.APP"
}

verify_autopruned() {
assert_file_has_content autopruned.txt "\.NONACTIVEGL"
}

# This is used for the autoprune check
export FLATPAK_GL_DRIVERS=ACTIVEGL

Expand Down Expand Up @@ -384,8 +388,10 @@ assert_file_has_content user-installed.txt UNUSED_EXT2_K
assert_not_file_has_content user-installed.txt USED_EXT_K

${test_builddir}/list-unused | sed s@^app/@@g | sed s@^runtime/@@g | sort > unused.txt
${test_builddir}/list-unused --filter-autoprune | sed s@^app/@@g | sed s@^runtime/@@g | sort > autopruned.txt

verify_unused
verify_autopruned

ok "list unused regular"

Expand Down

0 comments on commit 13413aa

Please sign in to comment.