summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-07-08 11:25:38 +0200
committerDanilo M. <danix@danix.xyz>2026-07-08 11:25:38 +0200
commitefeeeb045ee8f7d92bc718c40661df0f5fb070c7 (patch)
tree632e789f2d4ac01487c37f4bcdec2a9f41526efb
parent006043e71cf6ee40b69da2e129a095ff4661dfb5 (diff)
downloadmkhintfile-efeeeb045ee8f7d92bc718c40661df0f5fb070c7.tar.gz
mkhintfile-efeeeb045ee8f7d92bc718c40661df0f5fb070c7.zip
fix: version-aware bundled-dep reconcile; release v1.2.1v1.2.1
reconcile_bundle_deps flagged a dep as changed on raw URL-string inequality. Manifests serve bare-tag archive URLs (.../archive/v0.26.7.tar.gz) while hints use the SBo-fetched tree shape (.../archive/v0.26.7/tree-sitter-0.26.7.tar.gz) — same version, different path — so every dep was reported changed at a version that had not moved. Add _url_version to parse and normalize the version from a URL basename, and detect change by version rather than URL string. Only rewrite a line when the version actually differs. Change report now shows "name old-ver -> new-ver". Regression test T-BM17 pins the same-version, different-shape case as no change (180 passed). Bump MKHINT_VERSION and man title to 1.2.1, rebuild mkhint.1.gz. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-rw-r--r--CHANGELOG.md14
-rw-r--r--CLAUDE.md20
-rw-r--r--TODO.md4
-rwxr-xr-xmkhint43
-rw-r--r--mkhint.1.gzbin3397 -> 3485 bytes
-rw-r--r--mkhint.1.md7
-rwxr-xr-xtests/mkhint_test.sh31
7 files changed, 102 insertions, 17 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb42635..32fe3a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,20 @@ All notable changes to this project are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/), and this project adheres to
[Semantic Versioning](https://semver.org/).
+## [1.2.1] - 2026-07-08
+
+### Fixed
+- Bundled-dep reconcile now detects change by upstream version, not raw URL
+ string. Manifests serve bare-tag archive URLs
+ (`.../archive/v0.26.7.tar.gz`) while hints use the SBo-fetched tree shape
+ (`.../archive/v0.26.7/tree-sitter-0.26.7.tar.gz`); these are the same
+ version in different path shapes, so the old string comparison flagged every
+ dep as changed at a version that had not moved. Reconcile now extracts the
+ version from each URL (`_url_version`) and only rewrites a line when the
+ version actually differs.
+- The changed-deps report now shows `name old-ver -> new-ver` from the parsed
+ identity and version, instead of version-stripped URL basenames.
+
## [1.2.0] - 2026-07-07
### Added
diff --git a/CLAUDE.md b/CLAUDE.md
index c245686..77af699 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -155,13 +155,19 @@ When adding new features, add a corresponding test case to `tests/mkhint_test.sh
the upstream deps manifest (`NAME_URL`/`NAME_SHA256` pairs, e.g. neovim's
`cmake.deps/deps.txt`), matches each extra `DOWNLOAD` line via
`match_dep_url` (repo-path first, exact basename-stem fallback for blob
- hosts), and rewrites changed lines + recomputes their md5. Runs
- automatically when the primary changed this run, otherwise only with
- `--force` (check-only flag). `--new` on a listed package prints the reconcile
- report without changing the hint. Manifest deps with no hint line are listed
- as an FYI, never added (would need a SlackBuild change). Helpers:
- `load_bundle_manifests`, `manifest_url_for`, `fetch_manifest`,
- `parse_manifest`, `match_dep_url`, `reconcile_bundle_deps`.
+ hosts). A matched line is rewritten only when its upstream *version* differs
+ (`_url_version` parses the version from each URL basename and normalizes it),
+ not when only the URL path shape differs, so a manifest's bare-tag
+ `archive/v0.26.7.tar.gz` and the hint's SBo-fetched
+ `archive/v0.26.7/tree-sitter-0.26.7.tar.gz` at the same version are treated as
+ current. Changed lines get their md5 recomputed; the report shows
+ `name old-ver -> new-ver`. Runs automatically when the primary changed this
+ run, otherwise only with `--force` (check-only flag). `--new` on a listed
+ package prints the reconcile report without changing the hint. Manifest deps
+ with no hint line are listed as an FYI, never added (would need a SlackBuild
+ change). Helpers: `load_bundle_manifests`, `manifest_url_for`,
+ `fetch_manifest`, `parse_manifest`, `match_dep_url`, `_url_version`,
+ `reconcile_bundle_deps`.
- `--delete` / `-d`: removes hint file and `.bak` if present. Accepts multiple package names. Exits 2 on first missing file.
- Downloads go to `/tmp/mkhint/download` (single shared temp file, deleted after md5 calculation).
- Multiline `DOWNLOAD`/`DOWNLOAD_x86_64`: parsed via `parse_multiline_var` (awk). First URL always re-downloaded. Continuation URLs (2+) prompt user interactively — changed URLs re-downloaded, unchanged URLs keep existing md5. Written back via `perl -i` with `\` continuation format preserved. Shared logic in `update_checksums` → `_process_download_var`.
diff --git a/TODO.md b/TODO.md
index 1e75bb1..0d0d5bf 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,7 +1,7 @@
## Post-1.2.0 (bundled-dep feature followups)
- - [ ] **v1.2.1 (bug): reconcile change-detection must be version-aware, not raw-URL-equality.** `reconcile_bundle_deps` currently flags a dep as "changed" whenever the manifest URL string differs from the hint URL string, even when the upstream VERSION/pin is identical. On the real neovim 0.12.4 hint this fired on all 13 deps: the manifest serves bare-tag archive URLs (e.g. `.../archive/refs/tags/v0.26.7.tar.gz`) while the hint uses the SBo-fetched shape (`.../archive/v0.26.7/tree-sitter-0.26.7.tar.gz`) — same content, same version, different path. Answering `Y` would needlessly rewrite every URL to the manifest shape (which the SlackBuild may not expect), re-download 12 tarballs, and produce a huge spurious diff with zero real version change. Fix: detect "changed" by comparing the matched dep's upstream version/sha (parsed from the manifest URL + its `NAME_SHA256` line) against the hint's current version/pin, NOT by URL-string inequality. Only rewrite a line when the pin actually moved. Add a regression test whose manifest URL shape differs from the hint at the same version and assert NO change is reported.
- - [ ] related to the above: the change-report labels (`_dep_label`/basename) render badly for bare-tag manifest URLs — showed `v0.26.7.tar.gz` / `fbb36bb...tar.gz` (dropped the name prefix) because manifest basenames carry no name stem. Once change-detection is version-aware, report `name old-ver -> new-ver` from the parsed identity+version rather than URL basenames.
+ - [x] **v1.2.1 (bug): reconcile change-detection is now version-aware.** `reconcile_bundle_deps` detects change via `_url_version` (version parsed from each URL basename, normalized), not raw URL string. Report shows `name old-ver -> new-ver`. Regression test T-BM17. Compares version strings only, not `NAME_SHA256`; add sha compare if a same-version-different-content case ever appears.
+ - [ ] verify on the VM that utf8proc (previously reported no-match AND in the FYI) now reconciles correctly with the version-aware fix; if it still no-matches, it is a `match_dep_url` stem issue, not change-detection.
- [ ] add a `--special` flag to add a package to the bundled list, asking for a link to it's upstream deps list file
- [ ] consider splitting `mkhint` into multiple files for easier maintenance
- [ ] add a noDL column to `--list` similar to what we do with DelReq
diff --git a/mkhint b/mkhint
index e606f86..f3ff50a 100755
--- a/mkhint
+++ b/mkhint
@@ -45,7 +45,7 @@ if [[ ! -d $TMP_DIR ]]; then
mkdir $TMP_DIR
fi
-readonly MKHINT_VERSION="1.2.0"
+readonly MKHINT_VERSION="1.2.1"
# Variables
VERSION=""
@@ -457,6 +457,29 @@ _url_stem() {
printf '%s\n' "$base"
}
+# _url_version <url> — extract the version token from a download URL's basename.
+# Same archive stripping as _url_stem, then take the trailing version: a
+# leading-v-or-digit tail after a "-" separator, else the whole basename if it
+# is itself a version (e.g. "v0.26.7"). Used to detect real version drift
+# independent of URL path shape. Empty if no version found.
+_url_version() {
+ local base="${1##*/}"
+ base="${base%.tar.gz}"; base="${base%.tar.xz}"; base="${base%.tar.bz2}"
+ base="${base%.zip}"; base="${base%.tgz}"
+ local ver=""
+ if [[ "$base" =~ -([vV]?[0-9][^/]*)$ ]]; then
+ ver="${BASH_REMATCH[1]}"
+ elif [[ "$base" =~ -([0-9a-f]{7,})$ ]]; then
+ ver="${BASH_REMATCH[1]}"
+ elif [[ "$base" =~ ^([vV]?[0-9][^/]*)$ ]]; then
+ ver="${BASH_REMATCH[1]}"
+ elif [[ "$base" =~ ^([0-9a-f]{7,})$ ]]; then
+ ver="${BASH_REMATCH[1]}"
+ fi
+ ver="${ver#[vV]}"
+ printf '%s\n' "$(_normalize_version "$ver")"
+}
+
# _url_repo <url> — echo owner/repo for a github URL, empty otherwise.
_url_repo() {
[[ "$1" =~ github\.com/([^/]+)/([^/]+) ]] && printf '%s/%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]%.git}"
@@ -572,7 +595,8 @@ reconcile_bundle_deps() {
# Track which manifest URLs got matched (for the FYI of unmatched ones).
local -A matched_manifest=()
local -a new_urls=("${urls[@]}")
- local -a changed_idx=() changed_from=() changed_to=()
+ local -a changed_idx=() changed_to=()
+ local -a changed_name=() changed_oldver=() changed_newver=()
local i m
# The primary hint URL (index 0) is never reconciled, but its manifest
@@ -587,9 +611,16 @@ reconcile_bundle_deps() {
continue
fi
matched_manifest["$m"]=1
- if [[ "$m" != "${urls[$i]}" ]]; then
- changed_idx+=("$i"); changed_from+=("${urls[$i]}"); changed_to+=("$m")
- new_urls[$i]="$m"
+ # Detect real drift by version, not URL string: the manifest and the
+ # hint often carry the same version in different path shapes (bare-tag
+ # archive vs SBo-fetched tree). Only a version change is a change.
+ local hv mv
+ hv=$(_url_version "${urls[$i]}")
+ mv=$(_url_version "$m")
+ if [[ -n "$mv" && "$hv" != "$mv" ]]; then
+ changed_idx+=("$i"); changed_to+=("$m"); new_urls[$i]="$m"
+ changed_name+=("$(_dep_label "${urls[$i]}")")
+ changed_oldver+=("${hv:-?}"); changed_newver+=("$mv")
fi
done
@@ -612,7 +643,7 @@ reconcile_bundle_deps() {
echo ""
echo "$pkg bundled deps changed upstream:"
for (( i=0; i<${#changed_idx[@]}; i++ )); do
- printf ' %s -> %s\n' "${changed_from[$i]##*/}" "${changed_to[$i]##*/}"
+ printf ' %s %s -> %s\n' "${changed_name[$i]}" "${changed_oldver[$i]}" "${changed_newver[$i]}"
done
return 0
fi
diff --git a/mkhint.1.gz b/mkhint.1.gz
index fba1bec..b2f7b41 100644
--- a/mkhint.1.gz
+++ b/mkhint.1.gz
Binary files differ
diff --git a/mkhint.1.md b/mkhint.1.md
index d9d751f..f4f43e0 100644
--- a/mkhint.1.md
+++ b/mkhint.1.md
@@ -1,4 +1,4 @@
-% MKHINT(1) mkhint 1.2.0 | User Commands
+% MKHINT(1) mkhint 1.2.1 | User Commands
% Danilo M.
% July 2026
@@ -226,7 +226,10 @@ The URL is an upstream, machine-readable deps manifest (NAME_URL / NAME_SHA256
pairs); {VERSION} is substituted with the hint's version. For a listed package,
\--new prints a reconcile report (no changes), and \--check reconciles the extra
download lines against the manifest after the primary bump, rewriting changed
-lines and recomputing their checksums. Bundled deps are never followed to their
+lines and recomputing their checksums. A dep counts as changed only when its
+upstream version differs, not merely its URL path shape, so a manifest's
+bare-tag archive URL and the hint's SBo-fetched tree URL at the same version
+are treated as current. Bundled deps are never followed to their
own latest release; only the manifest's pinned URLs are used. Manifest entries
with no matching download line are reported but not added.
diff --git a/tests/mkhint_test.sh b/tests/mkhint_test.sh
index 1afda97..316d9b7 100755
--- a/tests/mkhint_test.sh
+++ b/tests/mkhint_test.sh
@@ -1611,6 +1611,37 @@ grep -q 'tree-sitter/archive/v0.26.8' "$MOCK_HINT/nvim.hint" \
|| { echo " FAIL: apply mode:"; cat "$MOCK_HINT/nvim.hint"; (( FAIL++ )); ERRORS+=("T-BM9"); }
rm -f "$MOCK_BASE/manifest_fixture"
+# ── T-BM17: same version, different URL shape → NOT a change (v1.2.1 regr.) ───
+# The manifest serves bare-tag archive URLs (.../archive/v0.26.7.tar.gz) while
+# the hint uses the SBo-fetched tree shape (.../archive/v0.26.7/tree-sitter-
+# 0.26.7.tar.gz). Same version → reconcile must report all current, no rewrite.
+echo ""
+echo "T-BM17: reconcile detects no change when only URL shape differs at same version"
+cat > "$MOCK_BASE/manifest_fixture" << 'EOF'
+NVIM_URL https://github.com/neovim/neovim/archive/v0.13.0.tar.gz
+NVIM_SHA256 a
+TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.26.7.tar.gz
+TREESITTER_SHA256 b
+EOF
+cat > "$MOCK_HINT/nvim17.hint" << 'EOF'
+VERSION="0.13.0"
+DOWNLOAD="https://github.com/neovim/neovim/archive/v0.13.0/neovim-0.13.0.tar.gz \
+ https://github.com/tree-sitter/tree-sitter/archive/v0.26.7/tree-sitter-0.26.7.tar.gz"
+MD5SUM="aaa \
+ bbb"
+DOWNLOAD_x86_64=""
+MD5SUM_x86_64=""
+ARCH="x86_64"
+EOF
+cp "$MOCK_HINT/nvim17.hint" "$MOCK_BASE/nvim17.before"
+rep17=$(bash -c "TMP_DIR='$MOCK_TMP'; PATH=\"$MOCK_BASE/bin:\$PATH\"; source '$SCRIPT' 2>/dev/null; reconcile_bundle_deps nvim '$MOCK_HINT/nvim17.hint' 'https://x/deps.txt' report" 2>&1) || true
+echo "$rep17" | grep -q 'all current' \
+ && ! echo "$rep17" | grep -q 'changed upstream' \
+ && diff -q "$MOCK_HINT/nvim17.hint" "$MOCK_BASE/nvim17.before" >/dev/null \
+ && { echo " PASS: same-version shape diff → no change"; (( PASS++ )); } \
+ || { echo " FAIL: T-BM17 falsely flagged change. out=$rep17"; (( FAIL++ )); ERRORS+=("T-BM17"); }
+rm -f "$MOCK_BASE/manifest_fixture" "$MOCK_HINT/nvim17.hint" "$MOCK_BASE/nvim17.before"
+
# ── T-BM10: --new listed pkg prints reconcile report, does NOT rewrite ───────
echo ""
echo "T-BM10: --new listed pkg → manifest report, hint not rewritten by manifest"