From e50f76c7d09667f255cf64590e4e0acdb7ecf4d2 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Thu, 8 May 2025 14:20:02 +0200 Subject: [PATCH] makeHardcodeGsettingsPatch: Add support for `schemaExistsFunction` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit evolution-ews introduced a check for optional schemas, which would skip our hardcoded code paths. https://gitlab.gnome.org/GNOME/evolution-ews/-/commit/a0c514bd345c67fe0fd2ed6ef48a25649b1f4d8e Let’s update the semantic patch to also replace the invocations of specified `schemaExistsFunction` for known schemas with `true`. --- .../make-hardcode-gsettings-patch/default.nix | 6 + .../hardcode-gsettings.cocci | 20 +++ .../make-hardcode-gsettings-patch/default.nix | 43 ++++-- .../main.c | 129 ++++++++++++++++++ .../fixtures/example-project-patched/main.c | 44 ++++++ .../fixtures/example-project/main.c | 26 ++++ 6 files changed, 257 insertions(+), 11 deletions(-) create mode 100644 pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched-with-exists-fn/main.c diff --git a/pkgs/build-support/make-hardcode-gsettings-patch/default.nix b/pkgs/build-support/make-hardcode-gsettings-patch/default.nix index e63e5976f3eb..b803bd97eacf 100644 --- a/pkgs/build-support/make-hardcode-gsettings-patch/default.nix +++ b/pkgs/build-support/make-hardcode-gsettings-patch/default.nix @@ -27,6 +27,10 @@ For example, `{ "org.gnome.evolution" = "EVOLUTION_SCHEMA_PATH"; }` hardcodes looking for `org.gnome.evolution` into `@EVOLUTION_SCHEMA_PATH@`. + - `schemaExistsFunction`: name of the function that is used for checking + if optional schema exists. Its invocation will be replaced with TRUE + for known schemas. + - `patches`: A list of patches to apply before generating the patch. Example: @@ -54,6 +58,7 @@ src, patches ? [ ], schemaIdToVariableMapping, + schemaExistsFunction ? null, }: runCommand "hardcode-gsettings.patch" @@ -71,6 +76,7 @@ runCommand "hardcode-gsettings.patch" patchPhase set -x cp ${builtins.toFile "glib-schema-to-var.json" (builtins.toJSON schemaIdToVariableMapping)} ./glib-schema-to-var.json + cp ${builtins.toFile "glib-schema-exists-function.json" (builtins.toJSON schemaExistsFunction)} ./glib-schema-exists-function.json git init git add -A spatch --sp-file "${./hardcode-gsettings.cocci}" --dir . --in-place diff --git a/pkgs/build-support/make-hardcode-gsettings-patch/hardcode-gsettings.cocci b/pkgs/build-support/make-hardcode-gsettings-patch/hardcode-gsettings.cocci index e916d74fd1f5..ceee9a657610 100644 --- a/pkgs/build-support/make-hardcode-gsettings-patch/hardcode-gsettings.cocci +++ b/pkgs/build-support/make-hardcode-gsettings-patch/hardcode-gsettings.cocci @@ -34,6 +34,17 @@ def get_schema_directory(schema_id): return f'"@{schema_to_var[schema_id]}@"' raise Exception(f"Unknown schema path {schema_id!r}, please add it to ./glib-schema-to-var.json") + +@script:python schema_exists_fn@ +fn; +@@ +import json + +with open("./glib-schema-exists-function.json") as fn_file: + if (fn := json.load(fn_file)): + coccinelle.fn = fn + + @find_cpp_constants@ identifier const_name; expression val; @@ -143,3 +154,12 @@ fresh identifier SCHEMA_DIRECTORY = script:python(SCHEMA_ID) { get_schema_direct + schema = g_settings_schema_source_lookup(schema_source, SCHEMA_ID, FALSE); + settings = g_settings_new_full(schema, NULL, PATH); +} + + +@replace_schema_exists_fns depends on ever record_cpp_constants || never record_cpp_constants@ +// We want to run after #define constants have been collected but even if there are no #defines. +expression SCHEMA_ID; +identifier schema_exists_fn.fn; +@@ +-fn(SCHEMA_ID) ++true diff --git a/pkgs/test/make-hardcode-gsettings-patch/default.nix b/pkgs/test/make-hardcode-gsettings-patch/default.nix index 66e1c5eeb666..db79d7a3af6b 100644 --- a/pkgs/test/make-hardcode-gsettings-patch/default.nix +++ b/pkgs/test/make-hardcode-gsettings-patch/default.nix @@ -13,14 +13,16 @@ let expected, src, patches ? [ ], - schemaIdToVariableMapping, + args, }: let - patch = makeHardcodeGsettingsPatch ({ - inherit src schemaIdToVariableMapping; - inherit patches; - }); + patch = makeHardcodeGsettingsPatch ( + args + // { + inherit src patches; + } + ); in runCommandLocal "makeHardcodeGsettingsPatch-tests-${name}" @@ -54,10 +56,12 @@ in basic = mkTest { name = "basic"; src = ./fixtures/example-project; - schemaIdToVariableMapping = { - "org.gnome.evolution-data-server.addressbook" = "EDS"; - "org.gnome.evolution.calendar" = "EVO"; - "org.gnome.seahorse.nautilus.window" = "SEANAUT"; + args = { + schemaIdToVariableMapping = { + "org.gnome.evolution-data-server.addressbook" = "EDS"; + "org.gnome.evolution.calendar" = "EVO"; + "org.gnome.seahorse.nautilus.window" = "SEANAUT"; + }; }; expected = ./fixtures/example-project-patched; }; @@ -69,9 +73,26 @@ in # Avoid using wrapper function, which the generator cannot handle. ./fixtures/example-project-wrapped-settings-constructor-resolve.patch ]; - schemaIdToVariableMapping = { - "org.gnome.evolution-data-server.addressbook" = "EDS"; + args = { + schemaIdToVariableMapping = { + "org.gnome.evolution-data-server.addressbook" = "EDS"; + }; }; expected = ./fixtures/example-project-wrapped-settings-constructor-patched; }; + + existsFn = mkTest { + name = "exists-fn"; + src = ./fixtures/example-project; + args = { + schemaIdToVariableMapping = { + "org.gnome.evolution-data-server.addressbook" = "EDS"; + "org.gnome.evolution.calendar" = "EVO"; + "org.gnome.seahorse.nautilus.window" = "SEANAUT"; + }; + schemaExistsFunction = "e_ews_common_utils_gsettings_schema_exists"; + }; + expected = ./fixtures/example-project-patched-with-exists-fn; + }; + } diff --git a/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched-with-exists-fn/main.c b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched-with-exists-fn/main.c new file mode 100644 index 000000000000..f99324cd9c64 --- /dev/null +++ b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched-with-exists-fn/main.c @@ -0,0 +1,129 @@ +#include +#include + +void schema_id_literal() { + GSettings *settings; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution-data-server.addressbook", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + g_object_unref(settings); +} + +#define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook" +int schema_id_from_constant() { + GSettings *settings; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, SELF_UID_PATH_ID, FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + g_object_unref(settings); +} + +void schema_id_autoptr() { + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } +} + +void schema_id_with_backend() { + GSettings *settings; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EDS@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution-data-server.addressbook", FALSE); + settings = g_settings_new_full(schema, g_settings_backend_get_default(), NULL); + } + g_object_unref(settings); +} + +void schema_id_with_backend_and_path() { + GSettings *settings; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@SEANAUT@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.seahorse.nautilus.window", FALSE); + settings = g_settings_new_full(schema, g_settings_backend_get_default(), "/org/gnome/seahorse/nautilus/windows/123/"); + } + g_object_unref(settings); +} + +void schema_id_with_path() { + GSettings *settings; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@SEANAUT@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.seahorse.nautilus.window", FALSE); + settings = g_settings_new_full(schema, NULL, "/org/gnome/seahorse/nautilus/windows/123/"); + } + g_object_unref(settings); +} + +void exists_fn_guard() { + if (!true) { + return; + } + + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } +} + +void exists_fn_nested() { + if (true) { + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + } +} + +void exists_fn_unknown() { + if (true) { + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + } +} + +int main() { + schema_id_literal(); + schema_id_from_constant(); + schema_id_autoptr(); + schema_id_with_backend(); + schema_id_with_backend_and_path(); + schema_id_with_path(); + exists_fn_guard(); + exists_fn_nested(); + exists_fn_unknown(); + + return 0; +} diff --git a/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c index 7822a42b840a..4525c4d5a658 100644 --- a/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c +++ b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project-patched/main.c @@ -73,6 +73,47 @@ void schema_id_with_path() { g_object_unref(settings); } +void exists_fn_guard() { + if (!e_ews_common_utils_gsettings_schema_exists("org.gnome.evolution.calendar")) { + return; + } + + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } +} + +void exists_fn_nested() { + if (e_ews_common_utils_gsettings_schema_exists("org.gnome.evolution.calendar")) { + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + } +} + +void exists_fn_unknown() { + if (e_ews_common_utils_gsettings_schema_exists("org.gnome.foo")) { + g_autoptr(GSettings) settings = NULL; + { + g_autoptr(GSettingsSchemaSource) schema_source; + g_autoptr(GSettingsSchema) schema; + schema_source = g_settings_schema_source_new_from_directory("@EVO@", g_settings_schema_source_get_default(), TRUE, NULL); + schema = g_settings_schema_source_lookup(schema_source, "org.gnome.evolution.calendar", FALSE); + settings = g_settings_new_full(schema, NULL, NULL); + } + } +} + int main() { schema_id_literal(); schema_id_from_constant(); @@ -80,6 +121,9 @@ int main() { schema_id_with_backend(); schema_id_with_backend_and_path(); schema_id_with_path(); + exists_fn_guard(); + exists_fn_nested(); + exists_fn_unknown(); return 0; } diff --git a/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c index afcb3686ec84..65b93a8ef074 100644 --- a/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c +++ b/pkgs/test/make-hardcode-gsettings-patch/fixtures/example-project/main.c @@ -37,6 +37,29 @@ void schema_id_with_path() { g_object_unref(settings); } +void exists_fn_guard() { + if (!e_ews_common_utils_gsettings_schema_exists("org.gnome.evolution.calendar")) { + return; + } + + g_autoptr(GSettings) settings = NULL; + settings = g_settings_new("org.gnome.evolution.calendar"); +} + +void exists_fn_nested() { + if (e_ews_common_utils_gsettings_schema_exists("org.gnome.evolution.calendar")) { + g_autoptr(GSettings) settings = NULL; + settings = g_settings_new("org.gnome.evolution.calendar"); + } +} + +void exists_fn_unknown() { + if (e_ews_common_utils_gsettings_schema_exists("org.gnome.foo")) { + g_autoptr(GSettings) settings = NULL; + settings = g_settings_new("org.gnome.evolution.calendar"); + } +} + int main() { schema_id_literal(); schema_id_from_constant(); @@ -44,6 +67,9 @@ int main() { schema_id_with_backend(); schema_id_with_backend_and_path(); schema_id_with_path(); + exists_fn_guard(); + exists_fn_nested(); + exists_fn_unknown(); return 0; }