Write a generated client extension module into `path` as a managed block. * * The module is generated from the tool registry rather than shipped (see * src/cli/client_adapter.h), and it goes in as a MARKED BLOCK rather than a * whole-file write: the directory is auto-loaded by the client, so a user may * legitimately keep their own module there, and clobbering it would be the * install routi
| 8143 | * than a skip, because a silently absent extension is exactly the failure mode |
| 8144 | * that left #616 a no-op for six weeks. */ |
| 8145 | static void install_generated_client_extension(const char *label, const char *path, |
| 8146 | const char *binary_path, |
| 8147 | char *(*generate)(const char *), bool dry_run) { |
| 8148 | if (g_install_plan) { |
| 8149 | plan_record(label, "extension", path); |
| 8150 | return; |
| 8151 | } |
| 8152 | char *content = generate(binary_path); |
| 8153 | if (!content) { |
| 8154 | record_agent_config_error(false, label, "extension_generate", path); |
| 8155 | return; |
| 8156 | } |
| 8157 | bool installed = true; |
| 8158 | if (!dry_run && (!prepare_config_parent(path) || |
| 8159 | cbm_text_upsert_managed_block(path, CBM_ADAPTER_MARKER_START, |
| 8160 | CBM_ADAPTER_MARKER_END, content) != 0)) { |
| 8161 | installed = false; |
| 8162 | record_agent_config_error(false, label, "extension_install", path); |
| 8163 | } |
| 8164 | free(content); |
| 8165 | if (installed) { |
| 8166 | printf(" extension: %s\n", path); |
| 8167 | } |
| 8168 | } |
| 8169 | |
| 8170 | /* Remove only OUR marked block, never the file: a user's own module may share |
| 8171 | * it, and owned removal is the convention every other uninstall path here |
no test coverage detected