| 11887 | #endif /* CBM_CLI_ENABLE_TEST_API */ |
| 11888 | |
| 11889 | int cbm_cmd_update(int argc, char **argv) { |
| 11890 | parse_auto_answer(argc, argv); |
| 11891 | |
| 11892 | bool dry_run = false; |
| 11893 | bool force = false; |
| 11894 | bool legacy_variant_flag = false; |
| 11895 | for (int i = 0; i < argc; i++) { |
| 11896 | if (strcmp(argv[i], "--dry-run") == 0) { |
| 11897 | dry_run = true; |
| 11898 | } else if (strcmp(argv[i], "--force") == 0) { |
| 11899 | force = true; |
| 11900 | } else if (strcmp(argv[i], "--ui") == 0 || strcmp(argv[i], "--standard") == 0) { |
| 11901 | /* v0.10.2 deleted the ui/standard chooser and, with it, these flags — |
| 11902 | * which turned `update --ui` from a working command into a hard |
| 11903 | * error for everyone who had it in a script, an alias, or muscle |
| 11904 | * memory (#1544). Removing a CHOICE is fine; removing the WORDS |
| 11905 | * people type is a break we owe them nothing for. Accept both, |
| 11906 | * ignore them, and say once why they no longer mean anything. */ |
| 11907 | legacy_variant_flag = true; |
| 11908 | } else if (strcmp(argv[i], "-y") != 0 && strcmp(argv[i], "--yes") != 0 && |
| 11909 | strcmp(argv[i], "-n") != 0 && strcmp(argv[i], "--no") != 0) { |
| 11910 | (void)fprintf(stderr, "error: unknown update option: %s\n", argv[i]); |
| 11911 | return CLI_TRUE; |
| 11912 | } |
| 11913 | } |
| 11914 | if (legacy_variant_flag) { |
| 11915 | (void)fprintf(stderr, "note: --ui/--standard are accepted but no longer do anything; since " |
| 11916 | "v0.10.0 there is one build per platform and it always includes the " |
| 11917 | "graph UI.\n"); |
| 11918 | } |
| 11919 | |
| 11920 | /* #1566: we cannot update a binary a package manager owns, and pretending |
| 11921 | * otherwise is the dishonest-success pattern this project keeps fixing: |
| 11922 | * reporting that an update ran while changing nothing leaves the user |
| 11923 | * convinced they are current. Refuse, and name the command that WILL work. */ |
| 11924 | { |
| 11925 | char self_path[CLI_BUF_1K] = {0}; |
| 11926 | const char *home = cbm_get_home_dir(); |
| 11927 | bool self_exact = home && cbm_detect_self_path(self_path, sizeof(self_path), home); |
| 11928 | char managed_dir[CLI_BUF_1K] = {0}; |
| 11929 | if (self_exact && home) { |
| 11930 | snprintf(managed_dir, sizeof(managed_dir), "%s/.local/bin", home); |
| 11931 | } |
| 11932 | if (self_exact && cli_binary_is_externally_managed(self_path, true, managed_dir)) { |
| 11933 | const char *manager = cli_external_manager_name(self_path); |
| 11934 | (void)fprintf(stderr, |
| 11935 | "error: this binary is managed by %s, so `update` cannot replace it:\n" |
| 11936 | " %s\n", |
| 11937 | manager ? manager : "another installer", self_path); |
| 11938 | if (manager && strcmp(manager, "mise") == 0) { |
| 11939 | (void)fprintf(stderr, " update it with: mise upgrade codebase-memory-mcp\n"); |
| 11940 | } else if (manager && strcmp(manager, "Homebrew") == 0) { |
| 11941 | (void)fprintf(stderr, " update it with: brew upgrade codebase-memory-mcp\n"); |
| 11942 | } else { |
| 11943 | (void)fprintf(stderr, " update it through whichever tool installed it.\n"); |
| 11944 | } |
| 11945 | (void)fprintf(stderr, " to refresh only the agent configurations, run: " |
| 11946 | "codebase-memory-mcp install --skip-binary\n"); |
no test coverage detected