diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index 0783ede0..e1ba91d4 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -10302,6 +10302,7 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self, { RemoteFilter *filter = NULL; const char *filter_path; + gboolean handled_fallback = FALSE; g_autoptr(GFile) filter_file = NULL; if (checksum_out) @@ -10331,6 +10332,15 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self, filter = NULL; /* New path, reload */ else if ((now - filter->last_mtime_check) > (1000 * (FILTER_MTIME_CHECK_TIMEOUT_MSEC))) { + /* Fall back to backup copy if remote filter disappears */ + handled_fallback = TRUE; + if (!g_file_query_exists (filter_file, NULL)) + { + char *basename = g_strconcat (name, ".filter", NULL); + g_object_unref (filter_file); + filter_file = flatpak_build_file (self->basedir, "repo", basename, NULL); + } + filter->last_mtime_check = now; if (!get_mtime (filter_file, &mtime, NULL, NULL) || mtime.tv_sec != filter->mtime.tv_sec || @@ -10354,6 +10364,14 @@ flatpak_dir_lookup_remote_filter (FlatpakDir *self, if (filter) /* This is outside the lock, but we already copied the returned data, and we're not dereferencing filter */ return TRUE; + /* Fall back to backup copy if remote filter disappears */ + if (!handled_fallback && !g_file_query_exists (filter_file, NULL)) + { + char *basename = g_strconcat (name, ".filter", NULL); + g_object_unref (filter_file); + filter_file = flatpak_build_file (self->basedir, "repo", basename, NULL); + } + filter = remote_filter_load (filter_file, error); if (filter == NULL) return FALSE; @@ -12741,6 +12759,7 @@ flatpak_dir_modify_remote (FlatpakDir *self, g_autofree char *url = NULL; g_autofree char *metalink = NULL; g_autoptr(GKeyFile) new_config = NULL; + g_autofree gchar *filter_path = NULL; gboolean has_remote; if (strchr (remote_name, '/') != NULL) @@ -12819,6 +12838,32 @@ flatpak_dir_modify_remote (FlatpakDir *self, imported, (imported == 1) ? "" : "s", remote_name); } + filter_path = g_key_file_get_value (new_config, group, "xa.filter", NULL); + if (filter_path && *filter_path && g_file_test (filter_path, G_FILE_TEST_EXISTS)) + { + /* Make a backup filter copy in case it goes away later */ + char *filter_name = g_strconcat (remote_name, ".filter", NULL); + g_autoptr(GFile) filter_file = g_file_new_for_path (filter_path); + g_autoptr(GFile) filter_copy = flatpak_build_file (self->basedir, "repo", filter_name, NULL); + g_autoptr(GError) local_error = NULL; + g_autofree char *backup_data = NULL; + gsize backup_data_size; + + if (g_file_load_contents (filter_file, cancellable, &backup_data, &backup_data_size, NULL, &local_error)) + { + g_autofree char *backup_data_copy = + g_strdup_printf ("# backup copy of %s, do not edit!\n%s", filter_path, backup_data); + + if (!g_file_replace_contents (filter_copy, backup_data_copy, strlen (backup_data_copy), + NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, cancellable, &local_error)) + g_debug ("Failed to save backup copy of filter file %s: %s\n", filter_path, local_error->message); + } + else + { + g_debug ("Failed to read filter %s file while making a backup copy: %s\n", filter_path, local_error->message); + } + } + if (!flatpak_dir_mark_changed (self, error)) return FALSE; diff --git a/tests/test-repo.sh b/tests/test-repo.sh index c0db3a92..028a3f10 100644 --- a/tests/test-repo.sh +++ b/tests/test-repo.sh @@ -620,8 +620,9 @@ assert_file_has_content remote-ref-info "ID: org\.test\.Hello" ${FLATPAK} ${U} update --appstream test-repo assert_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello" - -${FLATPAK} ${U} remote-modify test-repo --filter ${test_builddir}/test.filter +# Make a copy so we can remove it later +cp ${test_builddir}/test.filter test.filter +${FLATPAK} ${U} remote-modify test-repo --filter $(pwd)/test.filter ${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log @@ -640,6 +641,24 @@ fi ${FLATPAK} ${U} update --appstream test-repo assert_not_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello" +# Ensure that filter works even when the filter file is removed (uses the backup) +rm test.filter +${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log +assert_not_file_has_content remote-ls-log "app/org\.test\.Hello" +assert_not_file_has_content remote-ls-log "runtime/org\.test\.Hello\.Locale" +assert_file_has_content remote-ls-log "runtime/org\.test\.Platform" +if ${FLATPAK} ${U} remote-info test-repo org.test.Hello > remote-ref-info; then + assert_not_reached "flatpak remote-info test-repo org.test.Hello should fail due to filter" +fi +if ${FLATPAK} ${U} install -y test-repo org.test.Hello; then + assert_not_reached "should not be able to install org.test.Hello should fail due to filter" +fi + +${FLATPAK} ${U} update --appstream test-repo +assert_not_file_has_content $FL_DIR/appstream/test-repo/$ARCH/active/appstream.xml "app/org\.test\.Hello" + +# Remove filter + ${FLATPAK} ${U} remote-modify test-repo --no-filter ${FLATPAK} ${U} remote-ls -d -a test-repo > remote-ls-log