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
| 8358 | * than a skip, because a silently absent extension is exactly the failure mode |
| 8359 | * that left #616 a no-op for six weeks. */ |
| 8360 | static void install_generated_client_extension(const char *label, const char *path, |
| 8361 | const char *binary_path, |
| 8362 | char *(*generate)(const char *), bool dry_run) { |
| 8363 | if (g_install_plan) { |
| 8364 | plan_record(label, "extension", path); |
| 8365 | return; |
| 8366 | } |
| 8367 | char *content = generate(binary_path); |
| 8368 | if (!content) { |
| 8369 | record_agent_config_error(false, label, "extension_generate", path); |
| 8370 | return; |
| 8371 | } |
| 8372 | bool installed = true; |
| 8373 | if (!dry_run && (!prepare_config_parent(path) || |
| 8374 | cbm_text_upsert_managed_block(path, CBM_ADAPTER_MARKER_START, |
| 8375 | CBM_ADAPTER_MARKER_END, content) != 0)) { |
| 8376 | installed = false; |
| 8377 | record_agent_config_error(false, label, "extension_install", path); |
| 8378 | } |
| 8379 | free(content); |
| 8380 | if (installed) { |
| 8381 | printf(" extension: %s\n", path); |
| 8382 | } |
| 8383 | } |
| 8384 | |
| 8385 | /* Remove only OUR marked block, never the file: a user's own module may share |
| 8386 | * it, and owned removal is the convention every other uninstall path here |
no test coverage detected