Skip to content

Commit 54c0325

Browse files
DeusDatadLo999
andcommitted
Skip update when already on latest version
Check GitHub releases/latest redirect header before downloading. Saves bandwidth and avoids unnecessary index rebuilds. - "Already up to date" when version matches or is ahead - --force flag to bypass the check - Graceful degradation when network is unavailable - Uses same curl dependency as the download itself Fixes #142 Co-Authored-By: dLo999 <dLo999@users.noreply.github.com>
1 parent 3463987 commit 54c0325

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

scripts/security-allowlist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ src/ui/http_server.c:execl:exec indexing binary in child process
4242
# Format: URL:justification
4343
URL:https://api.github.com/repos/DeusData/codebase-memory-mcp/releases/latest:update check
4444
URL:https://github.com/DeusData/codebase-memory-mcp/releases/latest/download:binary download + checksums
45+
URL:https://github.com/DeusData/codebase-memory-mcp/releases/latest:version check via redirect header
4546
URL:http://127.0.0.1:UI server binding (localhost only)

src/cli/cli.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3310,10 +3310,85 @@ static int select_update_variant(int variant_flag) {
33103310
return (choice[0] == '2') ? CLI_TRUE : 0;
33113311
}
33123312

3313+
/* Case-insensitive prefix match (portable — no strncasecmp dependency). */
3314+
static bool prefix_icase(const char *s, const char *prefix) {
3315+
while (*prefix) {
3316+
if (tolower((unsigned char)*s) != tolower((unsigned char)*prefix)) {
3317+
return false;
3318+
}
3319+
s++;
3320+
prefix++;
3321+
}
3322+
return true;
3323+
}
3324+
3325+
/* Fetch latest release tag from GitHub via redirect header.
3326+
* Returns heap-allocated tag (e.g. "v0.5.7") or NULL on failure. */
3327+
static char *fetch_latest_tag(void) {
3328+
FILE *fp = cbm_popen(
3329+
"curl -sfI https://github.com/DeusData/codebase-memory-mcp/releases/latest 2>/dev/null",
3330+
"r");
3331+
if (!fp) {
3332+
return NULL;
3333+
}
3334+
char line[CBM_SZ_512];
3335+
char *tag = NULL;
3336+
while (fgets(line, sizeof(line), fp)) {
3337+
if (!prefix_icase(line, "location:")) {
3338+
continue;
3339+
}
3340+
char *slash = strrchr(line, '/');
3341+
if (!slash) {
3342+
break;
3343+
}
3344+
slash++;
3345+
size_t len = strlen(slash);
3346+
while (len > 0 && (slash[len - SKIP_ONE] == '\r' || slash[len - SKIP_ONE] == '\n' ||
3347+
slash[len - SKIP_ONE] == ' ')) {
3348+
slash[--len] = '\0';
3349+
}
3350+
if (len > 0) {
3351+
tag = strdup(slash);
3352+
}
3353+
break;
3354+
}
3355+
cbm_pclose(fp);
3356+
return tag;
3357+
}
3358+
3359+
/* Check if current version is already latest. Returns true to skip update. */
3360+
static bool check_already_latest(void) {
3361+
char dl_env[CBM_SZ_256] = "";
3362+
cbm_safe_getenv("CBM_DOWNLOAD_URL", dl_env, sizeof(dl_env), NULL);
3363+
if (dl_env[0]) {
3364+
return false; /* testing override — always update */
3365+
}
3366+
char *latest = fetch_latest_tag();
3367+
if (!latest) {
3368+
(void)fprintf(stderr, "warning: could not check latest version (network unavailable?). "
3369+
"Proceeding with update.\n");
3370+
return false;
3371+
}
3372+
int cmp = cbm_compare_versions(latest, CBM_VERSION);
3373+
if (cmp <= 0) {
3374+
if (cmp < 0) {
3375+
printf("Already up to date (%s, ahead of latest %s).\n", CBM_VERSION, latest);
3376+
} else {
3377+
printf("Already up to date (%s).\n", CBM_VERSION);
3378+
}
3379+
free(latest);
3380+
return true;
3381+
}
3382+
printf("Update available: %s -> %s\n", CBM_VERSION, latest);
3383+
free(latest);
3384+
return false;
3385+
}
3386+
33133387
int cbm_cmd_update(int argc, char **argv) {
33143388
parse_auto_answer(argc, argv);
33153389

33163390
bool dry_run = false;
3391+
bool force = false;
33173392
int variant_flag = 0; /* 0 = ask, 1 = standard, 2 = ui */
33183393
for (int i = 0; i < argc; i++) {
33193394
if (strcmp(argv[i], "--dry-run") == 0) {
@@ -3322,6 +3397,8 @@ int cbm_cmd_update(int argc, char **argv) {
33223397
variant_flag = VARIANT_A;
33233398
} else if (strcmp(argv[i], "--ui") == 0) {
33243399
variant_flag = VARIANT_B;
3400+
} else if (strcmp(argv[i], "--force") == 0) {
3401+
force = true;
33253402
}
33263403
}
33273404

@@ -3333,6 +3410,11 @@ int cbm_cmd_update(int argc, char **argv) {
33333410

33343411
printf("codebase-memory-mcp update (current: %s)\n\n", CBM_VERSION);
33353412

3413+
/* Version check — skip download if already on latest. */
3414+
if (!force && check_already_latest()) {
3415+
return 0;
3416+
}
3417+
33363418
/* Step 1: Check for existing indexes */
33373419
if (update_clear_indexes(home, dry_run) != 0) {
33383420
return CLI_TRUE;

0 commit comments

Comments
 (0)