diff options
| author | Danilo M. <danix@danix.xyz> | 2026-07-08 11:25:38 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-07-08 11:25:38 +0200 |
| commit | efeeeb045ee8f7d92bc718c40661df0f5fb070c7 (patch) | |
| tree | 632e789f2d4ac01487c37f4bcdec2a9f41526efb | |
| parent | 006043e71cf6ee40b69da2e129a095ff4661dfb5 (diff) | |
| download | mkhintfile-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.md | 14 | ||||
| -rw-r--r-- | CLAUDE.md | 20 | ||||
| -rw-r--r-- | TODO.md | 4 | ||||
| -rwxr-xr-x | mkhint | 43 | ||||
| -rw-r--r-- | mkhint.1.gz | bin | 3397 -> 3485 bytes | |||
| -rw-r--r-- | mkhint.1.md | 7 | ||||
| -rwxr-xr-x | tests/mkhint_test.sh | 31 |
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 @@ -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`. @@ -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 @@ -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 Binary files differindex fba1bec..b2f7b41 100644 --- a/mkhint.1.gz +++ b/mkhint.1.gz 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" |
