From fffe38a2b0af85e7a4d56ae4d8c024bb5d3e035e Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Sat, 14 Mar 2026 20:23:31 -0700 Subject: [PATCH] common: Report the age of the configuration This change will allow applications to determine if their data is older than the flatpak configuration, to aid cache invalidation. --- common/flatpak-installation.c | 35 ++++++++++++++++++++++++ common/flatpak-installation.h | 1 + doc/reference/flatpak-sections.txt | 1 + tests/testlibrary.c | 44 ++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/common/flatpak-installation.c b/common/flatpak-installation.c index 94f7a93e..378a7faa 100644 --- a/common/flatpak-installation.c +++ b/common/flatpak-installation.c @@ -2675,6 +2675,41 @@ flatpak_installation_create_monitor (FlatpakInstallation *self, cancellable, error); } +/** + * flatpak_installation_get_timestamp: + * @self: a #FlatpakInstallation + * + * Gets the modification time of the installation, based on the file monitored by + * flatpak_installation_create_monitor(). This can be used to detect when + * applications or runtimes have been installed, uninstalled, or updated, or when + * remotes have been added, removed, or modified, to aid cache invalidation. + * + * Returns: the modification time (seconds since the Unix epoch) of the + * installation configuration, or %G_MAXUINT64 if unavailable + * + * Since: 1.18.0 + */ +guint64 +flatpak_installation_get_timestamp (FlatpakInstallation *self) +{ + g_autoptr(FlatpakDir) dir = NULL; + g_autoptr(GFile) changed_file = NULL; + g_autoptr(GFileInfo) info = NULL; + + dir = flatpak_installation_get_dir_maybe_no_repo (self); + changed_file = flatpak_dir_get_changed_path (dir); + + info = g_file_query_info (changed_file, + G_FILE_ATTRIBUTE_TIME_MODIFIED, + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); + if (info == NULL) + return G_MAXUINT64; + + return g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); +} + /** * flatpak_installation_list_remote_related_refs_sync: diff --git a/common/flatpak-installation.h b/common/flatpak-installation.h index 5d679d69..74a70a65 100644 --- a/common/flatpak-installation.h +++ b/common/flatpak-installation.h @@ -236,6 +236,7 @@ FLATPAK_EXTERN gboolean flatpak_installation_launch_full (FlatpakIns FLATPAK_EXTERN GFileMonitor *flatpak_installation_create_monitor (FlatpakInstallation *self, GCancellable *cancellable, GError **error); +FLATPAK_EXTERN guint64 flatpak_installation_get_timestamp (FlatpakInstallation *self); FLATPAK_EXTERN GPtrArray *flatpak_installation_list_installed_refs (FlatpakInstallation *self, GCancellable *cancellable, GError **error); diff --git a/doc/reference/flatpak-sections.txt b/doc/reference/flatpak-sections.txt index 81cfa7c4..1589a708 100644 --- a/doc/reference/flatpak-sections.txt +++ b/doc/reference/flatpak-sections.txt @@ -10,6 +10,7 @@ flatpak_installation_new_for_path flatpak_installation_get_is_user flatpak_installation_get_path flatpak_installation_create_monitor +flatpak_installation_get_timestamp flatpak_installation_install flatpak_installation_install_full flatpak_installation_update diff --git a/tests/testlibrary.c b/tests/testlibrary.c index e4c3dcb6..65a4afc8 100644 --- a/tests/testlibrary.c +++ b/tests/testlibrary.c @@ -546,6 +546,49 @@ test_list_remotes (void) g_assert_cmpuint (remotes2->len, ==, 0); } +static void +test_timestamp (void) +{ + g_autoptr(FlatpakInstallation) inst = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(FlatpakRemote) remote = NULL; + guint64 mtime1, mtime2, mtime3; + + inst = flatpak_installation_new_user (NULL, &error); + g_assert_no_error (error); + + /* Get initial modification time */ + mtime1 = flatpak_installation_get_timestamp (inst); + g_assert_cmpuint (mtime1, <, G_MAXUINT64); + + /* Wait at least 1 second */ + sleep (1); + + /* Modification time should stay the same when nothing changes */ + mtime2 = flatpak_installation_get_timestamp (inst); + g_assert_cmpuint (mtime2, ==, mtime1); + + /* Modifying a remote should update the modification time */ + remote = flatpak_installation_get_remote_by_name (inst, repo_name, NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (remote); + + flatpak_remote_set_disabled (remote, TRUE); + flatpak_installation_modify_remote (inst, remote, NULL, &error); + g_assert_no_error (error); + + /* Need to drop caches to see the new modification time */ + flatpak_installation_drop_caches (inst, NULL, NULL); + + mtime3 = flatpak_installation_get_timestamp (inst); + g_assert_cmpuint (mtime3, >, mtime2); + + /* Restore the remote state */ + flatpak_remote_set_disabled (remote, FALSE); + flatpak_installation_modify_remote (inst, remote, NULL, &error); + g_assert_no_error (error); +} + static void test_remote_by_name (void) { @@ -5088,6 +5131,7 @@ main (int argc, char *argv[]) g_test_add_func ("/library/arches", test_arches); g_test_add_func ("/library/ref", test_ref); g_test_add_func ("/library/list-remotes", test_list_remotes); + g_test_add_func ("/library/timestamp", test_timestamp); g_test_add_func ("/library/remote-by-name", test_remote_by_name); g_test_add_func ("/library/remote", test_remote); g_test_add_func ("/library/remote-new", test_remote_new);