aboutsummaryrefslogtreecommitdiffstats
path: root/mkhint
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-05-18 10:49:06 +0200
committerDanilo M. <danix@danix.xyz>2026-05-18 10:49:06 +0200
commit9f1ad23a187a493ffa812064e6641061553e6386 (patch)
treea164278161830d2f168f830f81fbafbb07670f9e /mkhint
parente647c20e9f387b250469cda2b515cf767d2955a8 (diff)
downloadmkhintfile-master.tar.gz
mkhintfile-master.zip
feat: multiline DOWNLOAD support, test suite, updated docsHEADmaster
- Add parse_multiline_var, prompt_continuation_urls, build_multiline_value, _process_download_var; refactor update_checksums to handle multi-URL vars - First URL always re-downloaded; continuation URLs prompt user, skip re-download if unchanged - Add tests/mkhint_test.sh: 44 cases covering all commands and edge cases - Update README and CLAUDE.md: correct -N semantics, --new behavior, multiline DOWNLOAD flow, test suite docs
Diffstat (limited to 'mkhint')
-rwxr-xr-xmkhint148
1 files changed, 135 insertions, 13 deletions
diff --git a/mkhint b/mkhint
index 9d307f5..62e6d05 100755
--- a/mkhint
+++ b/mkhint
@@ -218,25 +218,147 @@ add_nodownload() {
fi
}
+# Parse multiline variable value (handles \ continuation lines)
+# Prints each whitespace-separated token on its own line
+parse_multiline_var() {
+ local varname="$1"
+ local file="$2"
+ # Join continuation lines, strip variable name and quotes, print one token per line
+ awk -v var="${varname}" '
+ BEGIN { found=0; buf="" }
+ !found && $0 ~ "^"var"=\"" {
+ found=1
+ buf=$0
+ sub("^"var"=\"", "", buf)
+ if (buf !~ /\\[[:space:]]*$/) {
+ gsub(/"[[:space:]]*$/, "", buf)
+ n=split(buf, arr, /[[:space:]]+/)
+ for (k=1;k<=n;k++) if(arr[k]!="") print arr[k]
+ found=0; buf=""
+ } else {
+ gsub(/\\[[:space:]]*$/, "", buf)
+ }
+ next
+ }
+ found {
+ if ($0 ~ /\\[[:space:]]*$/) {
+ line=$0; gsub(/\\[[:space:]]*$/, "", line)
+ buf=buf" "line
+ } else {
+ line=$0; gsub(/"[[:space:]]*$/, "", line)
+ buf=buf" "line
+ n=split(buf, arr, /[[:space:]]+/)
+ for (k=1;k<=n;k++) if(arr[k]!="") print arr[k]
+ found=0; buf=""
+ }
+ }
+ ' "$file"
+}
+
+# Prompt user for updated continuation URLs; returns updated URLs via nameref array
+# First URL is always kept as-is (already updated by version sed before this call)
+prompt_continuation_urls() {
+ local -n _urls="$1" # nameref: array of current URLs
+ local varname="$2"
+
+ local i
+ for (( i=1; i<${#_urls[@]}; i++ )); do
+ local current="${_urls[$i]}"
+ echo ""
+ echo " ${varname} line $((i+1)) (current): $current"
+ read -r -p " New URL (leave blank to keep): " new_url
+ if [[ -n "$new_url" ]]; then
+ _urls[$i]="$new_url"
+ fi
+ done
+}
+
+# Build multiline variable string for writing back to file
+# Usage: build_multiline_value urls_array -> prints quoted multiline value
+build_multiline_value() {
+ local -n _arr="$1"
+ local count=${#_arr[@]}
+ local i
+ for (( i=0; i<count; i++ )); do
+ if (( i == 0 )); then
+ printf '"%s' "${_arr[$i]}"
+ else
+ printf ' \\\n %s' "${_arr[$i]}"
+ fi
+ done
+ printf '"\n'
+}
+
# Download files and update MD5SUM/MD5SUM_x86_64 in hint file
update_checksums() {
local file="$1"
- local download
- download=$(grep '^DOWNLOAD=' "$file" | sed 's/DOWNLOAD="//;s/"$//')
- if [[ -n "$download" && $download != "UNSUPPORTED" && $download != "UNTESTED" ]]; then
- local sum
- sum=$(download_file "$download")
- sed -i "/^MD5SUM=/s/MD5SUM=\"[^\"]*\"/MD5SUM=\"$sum\"/" "$file"
- fi
+ _process_download_var "DOWNLOAD" "MD5SUM" "$file"
+ _process_download_var "DOWNLOAD_x86_64" "MD5SUM_x86_64" "$file"
+}
- local download_x64
- download_x64=$(grep '^DOWNLOAD_x86_64=' "$file" | sed 's/DOWNLOAD_x86_64="//;s/"$//')
- if [[ -n "$download_x64" && $download_x64 != "UNSUPPORTED" && $download_x64 != "UNTESTED" ]]; then
- local sum64
- sum64=$(download_file "$download_x64")
- sed -i "/^MD5SUM_x86_64=/s/MD5SUM_x86_64=\"[^\"]*\"/MD5SUM_x86_64=\"$sum64\"/" "$file"
+# Process one DOWNLOAD/MD5SUM variable pair in a hint file
+_process_download_var() {
+ local dl_var="$1"
+ local md5_var="$2"
+ local file="$3"
+
+ # Read current URLs into array
+ mapfile -t urls < <(parse_multiline_var "$dl_var" "$file")
+
+ [[ ${#urls[@]} -eq 0 ]] && return
+ [[ "${urls[0]}" == "UNSUPPORTED" || "${urls[0]}" == "UNTESTED" ]] && return
+
+ # Read current md5sums into array (parallel to urls)
+ mapfile -t md5s < <(parse_multiline_var "$md5_var" "$file")
+
+ # Save original URLs for change detection after prompt
+ local orig_urls=("${urls[@]}")
+
+ # Prompt user to update continuation URLs if present
+ if (( ${#urls[@]} > 1 )); then
+ echo ""
+ echo "Multiline ${dl_var} detected in $(basename "$file")."
+ prompt_continuation_urls urls "$dl_var"
fi
+
+ # Download and calculate md5 for each URL
+ local new_md5s=()
+ local i
+ for (( i=0; i<${#urls[@]}; i++ )); do
+ local url="${urls[$i]}"
+ if (( i == 0 )); then
+ # Always re-download first URL
+ echo "Downloading: $url"
+ new_md5s+=( "$(download_file "$url")" )
+ else
+ # Only re-download if URL changed from original
+ if [[ "$url" != "${orig_urls[$i]}" ]]; then
+ echo "Downloading (updated): $url"
+ new_md5s+=( "$(download_file "$url")" )
+ else
+ echo "Keeping existing md5 for: $url"
+ new_md5s+=( "${md5s[$i]}" )
+ fi
+ fi
+ done
+
+ # Rebuild and write back DOWNLOAD variable (may have updated continuation URLs)
+ local new_dl_value
+ new_dl_value=$(build_multiline_value urls)
+ # Strip surrounding quotes — perl wraps them in the substitution
+ new_dl_value="${new_dl_value#\"}"
+ new_dl_value="${new_dl_value%\"}"
+ perl -i -0pe 'BEGIN{$v=shift} s|^'"${dl_var}"'="[^"]*(?:\\\n[^"]*)*"|'"${dl_var}"'="$v"|m' \
+ "$new_dl_value" "$file"
+
+ # Rebuild and write back MD5SUM variable
+ local new_md5_value
+ new_md5_value=$(build_multiline_value new_md5s)
+ new_md5_value="${new_md5_value#\"}"
+ new_md5_value="${new_md5_value%\"}"
+ perl -i -0pe 'BEGIN{$v=shift} s|^'"${md5_var}"'="[^"]*(?:\\\n[^"]*)*"|'"${md5_var}"'="$v"|m' \
+ "$new_md5_value" "$file"
}
# Update existing hint file