mirror of
https://github.com/vishapoberon/vipatsar.git
synced 2026-04-05 21:12:25 +00:00
Massive improvements for upcoming updates
- All JSON definitions have been updates to become lowercase - _Scripts/convert_vipakfile.sh now understand BasicAuth - Improvements to the overall code
This commit is contained in:
parent
91191b6b62
commit
5bf0a1065c
44 changed files with 896 additions and 491 deletions
218
_Scripts/convert_vipakfile.sh
Executable file
218
_Scripts/convert_vipakfile.sh
Executable file
|
|
@ -0,0 +1,218 @@
|
|||
#!/bin/sh
|
||||
# convert_vipakfile.sh: Convert JSON vipakfile to plain-text .vipakfile format
|
||||
|
||||
|
||||
PROGNAME=${0##*/}
|
||||
VERSION="0.1.0"
|
||||
|
||||
COLOUR_SET_R="\033[0;31m"
|
||||
COLOUR_SET_G="\033[0;32m"
|
||||
COLOUR_SET_B="\033[0;34m"
|
||||
COLOUR_END="\033[0m"
|
||||
|
||||
perror() {
|
||||
printf "${COLOUR_SET_R}[-] ${COLOUR_END}%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pinfo() {
|
||||
printf "${COLOUR_SET_B}[*] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
paction() {
|
||||
printf "${COLOUR_SET_G}[+] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $PROGNAME [-o <output_file> | -c] [-f] [--verbose] <input_json_file>
|
||||
Convert JSON vipakfile to new plain-text .vipakfile format.
|
||||
-o <output_file> Write to specified file (default: stdout)
|
||||
-c Write to <package>-<version>.vipakfile
|
||||
-f Force overwrite of existing output file
|
||||
--verbose Print debug information about extracted fields
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
command -v jq >/dev/null 2>&1 || perror "jq is required but not found"
|
||||
command -v sed >/dev/null 2>&1 || perror "sed is required but not found"
|
||||
|
||||
output_mode="stdout"
|
||||
output_file=""
|
||||
input_file=""
|
||||
force_overwrite=""
|
||||
verbose=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-o)
|
||||
[ $# -lt 2 ] && perror "Option -o requires an output file"
|
||||
output_mode="file"
|
||||
output_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
-c)
|
||||
output_mode="versioned"
|
||||
shift
|
||||
;;
|
||||
-f)
|
||||
force_overwrite=1
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
verbose=1
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
perror "Unknown option: $1"
|
||||
;;
|
||||
*)
|
||||
[ -n "$input_file" ] && perror "Only one input file allowed"
|
||||
input_file="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -z "$input_file" ] && usage
|
||||
[ -f "$input_file" ] || perror "Input file '$input_file' not found"
|
||||
[ -r "$input_file" ] || perror "Input file '$input_file' is not readable"
|
||||
|
||||
jq -e . "$input_file" >/dev/null 2>&1 || perror "Invalid JSON in $input_file"
|
||||
|
||||
paction "Parsing $input_file"
|
||||
name=$(jq -r '.package // ""' "$input_file")
|
||||
version=$(jq -r '.version // ""' "$input_file")
|
||||
author=$(jq -r '.author // ""' "$input_file")
|
||||
license=$(jq -r '.license // ""' "$input_file")
|
||||
|
||||
[ -z "$name" ] && perror "package field is required"
|
||||
[ -z "$version" ] && perror "version field is required"
|
||||
|
||||
# Extract Remote (handle git and https)
|
||||
remote_type=$(jq -r '.remote.type // ""' "$input_file")
|
||||
remote=""
|
||||
case "$remote_type" in
|
||||
git)
|
||||
remote_url=$(jq -r '.remote.url // .remote.path // ""' "$input_file")
|
||||
remote_tag=$(jq -r '.remote.tag // ""' "$input_file")
|
||||
if [ -z "$remote_url" ]; then
|
||||
perror "remote.url or remote.path required for remote.type=git"
|
||||
fi
|
||||
remote="git $remote_url"
|
||||
[ -n "$remote_tag" ] && remote="$remote $remote_tag"
|
||||
;;
|
||||
https)
|
||||
# Extract remote.files as raw data
|
||||
remote_files=$(jq -r '.remote.files // [] | map(
|
||||
[.url, .authtype // "None", .authcredentials.user // "", .authcredentials.password // "", .md5 // ""] | join("\t")
|
||||
) | join("\n")' "$input_file") || {
|
||||
perror "Failed to process remote.files in $input_file"
|
||||
exit 1
|
||||
}
|
||||
if [ -z "$remote_files" ]; then
|
||||
perror "remote.files required for remote.type=https"
|
||||
fi
|
||||
# Process each file entry in shell
|
||||
remote_files_out=""
|
||||
IFS='
|
||||
'
|
||||
for file in $remote_files; do
|
||||
url=$(echo "$file" | cut -f1)
|
||||
authtype=$(echo "$file" | cut -f2)
|
||||
user=$(echo "$file" | cut -f3)
|
||||
password=$(echo "$file" | cut -f4)
|
||||
md5=$(echo "$file" | cut -f5)
|
||||
if [ "$authtype" = "BasicAuth" ]; then
|
||||
if [ -z "$user" ] || [ -z "$password" ]; then
|
||||
perror "Missing authcredentials.user or authcredentials.password for BasicAuth in $input_file"
|
||||
fi
|
||||
# Insert user:password@ after protocol
|
||||
auth_url=$(echo "$url" | sed -E "s,^(https?://),\1$user:$password@,")
|
||||
entry="$auth_url md5,$md5"
|
||||
else
|
||||
entry="$url md5,$md5"
|
||||
fi
|
||||
if [ -z "$remote_files_out" ]; then
|
||||
remote_files_out="$entry"
|
||||
else
|
||||
remote_files_out="$remote_files_out;$entry"
|
||||
fi
|
||||
done
|
||||
unset IFS
|
||||
remote="https $remote_files_out"
|
||||
;;
|
||||
"")
|
||||
: # Empty remote is valid
|
||||
;;
|
||||
*)
|
||||
perror "Unsupported remote.type: $remote_type. Only 'git' or 'https' allowed"
|
||||
;;
|
||||
esac
|
||||
|
||||
deps=$(jq -r 'if .dependencies then .dependencies | to_entries | map("\(.key):\(.value)") | join(" ") else "" end' "$input_file")
|
||||
build=$(jq -r '.build // [] | map(.command + " " + .file) | join(";")' "$input_file")
|
||||
[ "$build" = "null" ] && build=""
|
||||
|
||||
run=""
|
||||
main=""
|
||||
test_run=""
|
||||
test_main=""
|
||||
test_cmd=""
|
||||
|
||||
[ -n "$verbose" ] && {
|
||||
pinfo "Extracted fields:"
|
||||
pinfo " NAME=$name"
|
||||
pinfo " VERSION=$version"
|
||||
pinfo " AUTHOR=$author"
|
||||
pinfo " LICENSE=$license"
|
||||
pinfo " REMOTE=$remote"
|
||||
pinfo " DEPS=$deps"
|
||||
pinfo " BUILD=$build"
|
||||
pinfo " RUN=$run"
|
||||
pinfo " MAIN=$main"
|
||||
pinfo " TEST_RUN=$test_run"
|
||||
pinfo " TEST_MAIN=$test_main"
|
||||
pinfo " TEST=$test_cmd"
|
||||
}
|
||||
|
||||
vipakfile_content=$(cat <<EOF
|
||||
NAME = $name
|
||||
VERSION = $version
|
||||
|
||||
AUTHOR = $author
|
||||
LICENSE = $license
|
||||
|
||||
REMOTE = $remote
|
||||
|
||||
DEPS = $deps
|
||||
|
||||
RUN = $run
|
||||
MAIN = $main
|
||||
BUILD = $build
|
||||
|
||||
TEST_RUN = $test_run
|
||||
TEST_MAIN = $test_main
|
||||
TEST = $test_cmd
|
||||
EOF
|
||||
)
|
||||
|
||||
case "$output_mode" in
|
||||
stdout)
|
||||
paction "Writing to stdout"
|
||||
printf "%s\n" "$vipakfile_content"
|
||||
;;
|
||||
file)
|
||||
[ -z "$force_overwrite" ] && [ -f "$output_file" ] && perror "Output file '$output_file' already exists"
|
||||
paction "Writing $output_file"
|
||||
printf "%s\n" "$vipakfile_content" > "$output_file" 2>/dev/null || perror "Failed to write to '$output_file'"
|
||||
pinfo "Conversion complete: $output_file"
|
||||
;;
|
||||
versioned)
|
||||
output_file="$name-$version.vipakfile"
|
||||
[ -z "$force_overwrite" ] && [ -f "$output_file" ] && perror "Output file '$output_file' already exists"
|
||||
paction "Writing $output_file"
|
||||
printf "%s\n" "$vipakfile_content" > "$output_file" 2>/dev/null || perror "Failed to write to '$output_file'"
|
||||
pinfo "Conversion complete: $output_file"
|
||||
;;
|
||||
esac
|
||||
42
_Scripts/convert_vipatsar.sh
Executable file
42
_Scripts/convert_vipatsar.sh
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
# convert_vipatsar.sh: Convert old JSON vipakfiles to new plain-text format with
|
||||
# proper file naming and versioning using convert_vipakfile.sh
|
||||
|
||||
# Program name and version
|
||||
PROGNAME=${0##*/}
|
||||
VERSION="0.1.0"
|
||||
|
||||
# Colors for output
|
||||
COLOUR_SET_R="\033[0;31m"
|
||||
COLOUR_SET_G="\033[0;32m"
|
||||
COLOUR_SET_B="\033[0;34m"
|
||||
COLOUR_END="\033[0m"
|
||||
|
||||
# Error, info, and action print functions
|
||||
perror() {
|
||||
printf "${COLOUR_SET_R}[-] ${COLOUR_END}%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pinfo() {
|
||||
printf "${COLOUR_SET_B}[+] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
paction() {
|
||||
printf "${COLOUR_SET_G}[*] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
# We assume that we're running inside vipatsar tree
|
||||
for dir in $(find . -not -path '*/.git/*' -not -path '.' -type d) ;
|
||||
do
|
||||
# The port/library name is derived from the directory
|
||||
port=${dir##./}
|
||||
pinfo "Working on ${port}"
|
||||
cd $dir
|
||||
paction "Converting ${port}.json"
|
||||
../_Scripts/convert_vipakfile.sh -c "../${port}.json"
|
||||
pinfo "Conversion done"
|
||||
|
||||
cd - >/dev/null || return
|
||||
done
|
||||
|
||||
79
_Scripts/to_lower.sh
Executable file
79
_Scripts/to_lower.sh
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/sh
|
||||
# to_lower.sh: Convert JSON keys to lowercase, preserving dependencies subkeys
|
||||
|
||||
|
||||
PROGNAME=${0##*/}
|
||||
|
||||
COLOUR_SET_R="\033[0;31m"
|
||||
COLOUR_SET_G="\033[0;32m"
|
||||
COLOUR_SET_B="\033[0;34m"
|
||||
COLOUR_END="\033[0m"
|
||||
|
||||
perror() {
|
||||
printf "${COLOUR_SET_R}[-] ${COLOUR_END}%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pinfo() {
|
||||
printf "${COLOUR_SET_B}[*] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
paction() {
|
||||
printf "${COLOUR_SET_G}[+] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $PROGNAME [--all] [file ...]
|
||||
Convert JSON keys to lowercase, preserving dependencies subkeys.
|
||||
--all Process all .json files in current directory
|
||||
file Process specified JSON files
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
command -v jq >/dev/null 2>&1 || perror "jq is required but not found"
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "$1" = "--all" ]; then
|
||||
files=$(ls *.json 2>/dev/null)
|
||||
[ -z "$files" ] && perror "No JSON files found in current directory"
|
||||
else
|
||||
files="$*"
|
||||
for file in $files; do
|
||||
[ -f "$file" ] || perror "File $file not found"
|
||||
case "$file" in
|
||||
*.json) : ;;
|
||||
*) perror "File $file is not a .json file" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
for file in $files; do
|
||||
[ -r "$file" ] || perror "File $file is not readable"
|
||||
paction "Converting keys to lowercase in $file"
|
||||
tmpfile=$(mktemp)
|
||||
jq '
|
||||
def to_lower:
|
||||
if type == "object" then
|
||||
with_entries(
|
||||
.key |= (if . == "dependencies" then . else ascii_downcase end)
|
||||
) | map_values(to_lower)
|
||||
elif type == "array" then
|
||||
map(to_lower)
|
||||
else
|
||||
.
|
||||
end;
|
||||
to_lower
|
||||
' "$file" > "$tmpfile" 2>/dev/null || {
|
||||
rm -f "$tmpfile"
|
||||
perror "Failed to process $file with jq"
|
||||
}
|
||||
mv "$tmpfile" "$file" || perror "Failed to overwrite $file"
|
||||
pinfo "Processed $file"
|
||||
done
|
||||
|
||||
pinfo "All files processed successfully"
|
||||
145
_Scripts/validate_json.sh
Executable file
145
_Scripts/validate_json.sh
Executable file
|
|
@ -0,0 +1,145 @@
|
|||
#!/bin/sh
|
||||
# validate_json.sh: Validate JSON vipakfiles
|
||||
|
||||
|
||||
PROGNAME=${0##*/}
|
||||
|
||||
COLOUR_SET_R="\033[0;31m"
|
||||
COLOUR_SET_G="\033[0;32m"
|
||||
COLOUR_SET_B="\033[0;34m"
|
||||
COLOUR_END="\033[0m"
|
||||
|
||||
perror() {
|
||||
printf "${COLOUR_SET_R}[-] ${COLOUR_END}%s\n" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pinfo() {
|
||||
printf "${COLOUR_SET_B}[*] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
paction() {
|
||||
printf "${COLOUR_SET_G}[+] ${COLOUR_END}%s\n" "$@" >&2
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $PROGNAME [--all] [file ...]
|
||||
Validate JSON vipakfiles.
|
||||
--all Validate all .json files in current directory
|
||||
file Validate specified JSON files
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
command -v jq >/dev/null 2>&1 || perror "jq is required but not found"
|
||||
|
||||
validate_json() {
|
||||
json="$1"
|
||||
errors=0
|
||||
if ! jq -e . "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json is not valid JSON"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.package | type == "string" and length > 0' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json missing or invalid package field"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.version | type == "string" and length > 0' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json missing or invalid version field"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.author | type == "string"' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid author field (must be string)"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.license | type == "string"' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid license field (must be string)"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if jq -e '.remote | type == "object"' "$json" >/dev/null 2>/dev/null; then
|
||||
if ! jq -e '.remote.type | type == "string" and (. == "" or . == "git" or . == "https")' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid remote.type (must be empty, 'git', or 'https')"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if jq -e '.remote.type == "git"' "$json" >/dev/null 2>/dev/null; then
|
||||
if ! jq -e '.remote.url // .remote.path | type == "string" and length > 0' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json with remote.type=git missing or invalid remote.url or remote.path"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if jq -e '.remote.tag | type != "string"' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid remote.tag (must be string)"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
fi
|
||||
if jq -e '.remote.type == "https"' "$json" >/dev/null 2>/dev/null; then
|
||||
if ! jq -e '.remote.files | type == "array" and length > 0' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json with remote.type=https missing or empty remote.files array"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.remote.files[] | select(type == "object" and (.url | test("^(http|https)://") and .md5 | test("^[0-9a-f]{32}$")) and (.authtype != "BasicAuth" or (.authcredentials.user | type == "string" and length > 0 and .authcredentials.password | type == "string" and length > 0)))' "$json" >/dev/null 2>/dev/null; then
|
||||
jq -r '.remote.files[] | select(type != "object" or (.url | not or (.url | test("^(http|https)://") | not) or (.md5 | not or (.md5 | test("^[0-9a-f]{32}$") | not)) or (.authtype == "BasicAuth" and (.authcredentials.user | not or (.authcredentials.user | type != "string" or length == 0) or .authcredentials.password | not or (.authcredentials.password | type != "string" or length == 0)))) | .url // "missing"' "$json" 2>/dev/null | while read -r url; do
|
||||
perror "$json has invalid remote.files entry (url: $url, must be object with valid URL, 32-char MD5, and for BasicAuth, non-empty user/password)"
|
||||
errors=$((errors + 1))
|
||||
done
|
||||
if [ $? -ne 0 ]; then
|
||||
perror "$json remote.files validation failed due to jq error"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if jq -e '.dependencies | type != "object"' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid dependencies field (must be object)"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.build | type == "array"' "$json" >/dev/null 2>/dev/null; then
|
||||
perror "$json invalid build field (must be array)"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
if ! jq -e '.build[] | select(type == "object" and .command | type == "string" and length > 0 and .file | type == "string" and length > 0)' "$json" >/dev/null 2>/dev/null; then
|
||||
jq -r '.build[] | select(type != "object" or (.command | not or (.command | type != "string" or length == 0) or .file | not or (.file | type != "string" or length == 0))) | .file // "missing"' "$json" 2>/dev/null | while read -r file; do
|
||||
perror "$json has invalid build entry (file: $file, must be object with non-empty command and file)"
|
||||
errors=$((errors + 1))
|
||||
done
|
||||
if [ $? -ne 0 ]; then
|
||||
perror "$json build validation failed due to jq error"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
fi
|
||||
[ $errors -eq 0 ] && pinfo "$json is valid"
|
||||
return $errors
|
||||
}
|
||||
|
||||
errors=0
|
||||
if [ $# -eq 0 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "$1" = "--all" ]; then
|
||||
files=$(ls *.json 2>/dev/null)
|
||||
[ -z "$files" ] && perror "No JSON files found in current directory"
|
||||
else
|
||||
files="$*"
|
||||
for file in $files; do
|
||||
[ -f "$file" ] || perror "File $file not found"
|
||||
case "$file" in
|
||||
*.json) : ;;
|
||||
*) perror "File $file is not a .json file" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
for file in $files; do
|
||||
paction "Validating $file"
|
||||
validate_json "$file"
|
||||
[ $? -ne 0 ] && errors=$((errors + 1))
|
||||
done
|
||||
|
||||
if [ $errors -eq 0 ]; then
|
||||
pinfo "All JSON files validated successfully"
|
||||
exit 0
|
||||
else
|
||||
perror "Validation failed with $errors error(s)"
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Add table
Add a link
Reference in a new issue