diff options
| author | Danilo M. <danix@danix.xyz> | 2026-06-13 18:26:19 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-06-13 18:26:19 +0200 |
| commit | 1be322b71ef7ff19cff6e35551c1a1cc240ca52d (patch) | |
| tree | c5d7e95f762cc516cb4b450b33a22d8e7deced14 | |
| parent | 8c14667b6377e643bd1e6d630e9d12bccf6660d3 (diff) | |
| download | mkhintfile-1be322b71ef7ff19cff6e35551c1a1cc240ca52d.tar.gz mkhintfile-1be322b71ef7ff19cff6e35551c1a1cc240ca52d.zip | |
fix: quote nvchecker section names containing non-bare-key chars
Section names with '.', '-', etc. must be TOML-quoted (e.g. ["yt-dlp"]),
otherwise nvchecker fails to parse them. add_nvchecker_section wrote bare
[pkg] headers, so such names had to be hand-quoted. Worse, _has_nvchecker_section
only matched the bare form, so already-present quoted sections were reported as
missing and re-flagged for populate on every 'mkhint -C' run.
Add _nvchecker_label helper as the single source of truth for the written
label (bare iff name matches ^[A-Za-z0-9_]+$, else double-quoted), used by
both the write side (3 section headers + messages) and the read side
(_has_nvchecker_section grep, with regex metachars escaped so '.' is literal).
Tests T32-T34 cover quoted-header write, no-duplicate on re---new, and
--check recognizing an existing quoted section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| -rwxr-xr-x | mkhint | 31 | ||||
| -rwxr-xr-x | tests/mkhint_test.sh | 56 |
2 files changed, 80 insertions, 7 deletions
@@ -261,11 +261,26 @@ EOF fi } -# Return 0 if NVCHECKER_CONFIG already has a [pkg] section +# Emit the TOML section label for a package: bare if the name is a valid +# bare key ([A-Za-z0-9_] only), otherwise double-quoted. nvchecker (and TOML) +# require quoting for names containing '.', '-', etc. +_nvchecker_label() { + local pkg="$1" + if [[ "$pkg" =~ ^[A-Za-z0-9_]+$ ]]; then + printf '[%s]' "$pkg" + else + printf '["%s"]' "$pkg" + fi +} + +# Return 0 if NVCHECKER_CONFIG already has a section for pkg (bare or quoted) _has_nvchecker_section() { local pkg="$1" [[ -f "$NVCHECKER_CONFIG" ]] || return 1 - grep -qE "^\[${pkg}\][[:space:]]*$" "$NVCHECKER_CONFIG" + local label; label=$(_nvchecker_label "$pkg") + # fixed-string match of the exact label at line start, trailing space allowed + grep -qE "^$(printf '%s' "$label" | sed 's/[][\.*^$/]/\\&/g')[[:space:]]*$" \ + "$NVCHECKER_CONFIG" } # Append an nvchecker [pkg] section to NVCHECKER_CONFIG, auto-detecting the @@ -278,9 +293,11 @@ add_nvchecker_section() { mkdir -p "$(dirname "$NVCHECKER_CONFIG")" touch "$NVCHECKER_CONFIG" + local label; label=$(_nvchecker_label "$pkg") + # Skip if section already present if _has_nvchecker_section "$pkg"; then - echo "nvchecker: [${pkg}] already present in $NVCHECKER_CONFIG" + echo "nvchecker: ${label} already present in $NVCHECKER_CONFIG" return 0 fi @@ -298,7 +315,7 @@ add_nvchecker_section() { repo="${repo%.git}" section=$(cat <<EOF -[${pkg}] +${label} source = "github" github = "${owner}/${repo}" use_max_tag = true @@ -307,7 +324,7 @@ EOF elif [[ "$haystack" =~ (pypi\.org|files\.pythonhosted\.org) ]]; then section=$(cat <<EOF -[${pkg}] +${label} source = "pypi" pypi = "${pkg}" EOF @@ -315,7 +332,7 @@ EOF else section=$(cat <<EOF -[${pkg}] +${label} # TODO: configure nvchecker source for "${pkg}" # source = "regex" # url = "..." @@ -326,7 +343,7 @@ EOF fi printf '%s\n' "$section" >> "$NVCHECKER_CONFIG" - echo "nvchecker: review/fill [${pkg}] section in $NVCHECKER_CONFIG" + echo "nvchecker: review/fill ${label} section in $NVCHECKER_CONFIG" } # Add NODOWNLOAD=yes after MD5SUM_x86_64 line if not already present diff --git a/tests/mkhint_test.sh b/tests/mkhint_test.sh index c2c8fb7..2a17f32 100755 --- a/tests/mkhint_test.sh +++ b/tests/mkhint_test.sh @@ -17,6 +17,7 @@ setup() { "$MOCK_REPO/development/clion" \ "$MOCK_REPO/development/ghpkg" \ "$MOCK_REPO/python/pypkg" \ + "$MOCK_REPO/multimedia/yt-dlp" \ "$MOCK_HINT" \ "$MOCK_TMP" @@ -90,6 +91,20 @@ MAINTAINER="Test" EMAIL="test@test.com" EOF + # github .info with a dash in the package name (needs TOML quoting) + cat > "$MOCK_REPO/multimedia/yt-dlp/yt-dlp.info" << 'EOF' +PRGNAM="yt-dlp" +VERSION="2024.1.1" +HOMEPAGE="https://github.com/yt-dlp/yt-dlp" +DOWNLOAD="https://github.com/yt-dlp/yt-dlp/archive/2024.1.1/yt-dlp-2024.1.1.tar.gz" +MD5SUM="55555555555555555555555555555555" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="Test" +EMAIL="test@test.com" +EOF + # nvchecker config + keyfile for tests cat > "$MOCK_BASE/nvchecker.toml" << EOF [__config__] @@ -662,6 +677,47 @@ echo "$out" | grep -q "no .info found" \ || { echo " FAIL: 'no .info found' not in output"; echo "$out" | sed 's/^/ /'; (( FAIL++ )); ERRORS+=("T31 no info"); } assert_not_contains "no orphanpkg section added" "$MOCK_BASE/nvchecker.toml" '\[orphanpkg\]' +# ── T32: --new with dash in name → section header is TOML-quoted ─────────────── +echo "" +echo "T32: --new yt-dlp → [\"yt-dlp\"] quoted header written" +cat > "$MOCK_BASE/nvchecker.toml" << EOF +[__config__] +oldver = "$MOCK_BASE/old_ver.json" +newver = "$MOCK_BASE/new_ver.json" +EOF +rm -f "$MOCK_HINT"/*.hint "$MOCK_HINT"/*.bak 2>/dev/null +run_mkhint -n yt-dlp +assert_contains "quoted section header" "$MOCK_BASE/nvchecker.toml" '^\["yt-dlp"\]' +assert_not_contains "no bare header" "$MOCK_BASE/nvchecker.toml" '^\[yt-dlp\]' +assert_contains "github source" "$MOCK_BASE/nvchecker.toml" 'github = "yt-dlp/yt-dlp"' + +# ── T33: _has_nvchecker_section matches quoted header → no duplicate on re---new +echo "" +echo "T33: --new yt-dlp again → quoted section not duplicated" +run_mkhint -n yt-dlp # section already exists from T32 (quoted) +dup_count=$(grep -cE '^\["yt-dlp"\]' "$MOCK_BASE/nvchecker.toml") +assert_exit_code "quoted yt-dlp appears once" 1 "$dup_count" + +# ── T34: --check sees quoted section as present, not "no section" ────────────── +echo "" +echo "T34: --check with existing quoted section → not flagged missing" +# yt-dlp quoted section present (from T32); not in keyfile → 'no nvchecker result', NOT 'no section' +cat > "$MOCK_HINT/yt-dlp.hint" << 'EOF' +VERSION="2024.1.1" +ARCH="x86_64" +DOWNLOAD="https://github.com/yt-dlp/yt-dlp/archive/2024.1.1/yt-dlp-2024.1.1.tar.gz" +MD5SUM="55555555555555555555555555555555" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +EOF +out=$(run_mkhint -C yt-dlp < <(printf 'n\n') 2>&1) +echo "$out" | grep -q "yt-dlp: no nvchecker result" \ + && { echo " PASS: quoted section recognized (no result, not no section)"; (( PASS++ )); } \ + || { echo " FAIL: quoted section not recognized"; echo "$out" | sed 's/^/ /'; (( FAIL++ )); ERRORS+=("T34 quoted recognized"); } +echo "$out" | grep -q "yt-dlp: no nvchecker section" \ + && { echo " FAIL: quoted section wrongly flagged missing"; (( FAIL++ )); ERRORS+=("T34 false missing"); } \ + || { echo " PASS: not flagged as missing section"; (( PASS++ )); } + # ─── SUMMARY ────────────────────────────────────────────────────────────────── teardown |
