Files
Odoo-Wiki/task
T

289 lines
8.5 KiB
Bash
Executable File

#!/bin/bash
set -e
if [[ -a ".env" ]]; then
export $(cat .env | sed 's/^#.*//g' | xargs)
fi
help() {
echo
echo "task <command> [options]"
echo
echo "commands:"
echo
local -a rows
local max_cmd=7 max_opt=6 max_desc=11
rows+=("Command|Option|Description")
rows+=("install-vuepress||Install build dependencies.")
rows+=("update-vuepres||Update build dependencies.")
rows+=("dev-vuepress||Start vuepress development server.")
rows+=("build-vuepress||Create vuepress build.")
rows+=("serve-vuepress||Serve vuepress build.")
rows+=("download-icons||Download module icons from Odoo assets.")
rows+=("update-module-versions|[file]|Check and update frontmatter versions list.")
rows+=("get-frontmatter-field|<file> <field>|Read a single frontmatter field value.")
rows+=("set-frontmatter-field|<file> <versions>|Write versions list to frontmatter.")
rows+=("lint||Lint code with prettier.")
for row in "${rows[@]}"; do
IFS='|' read -r cmd opt desc <<< "$row"
(( ${#cmd} > max_cmd )) && max_cmd=${#cmd}
(( ${#opt} > max_opt )) && max_opt=${#opt}
(( ${#desc} > max_desc )) && max_desc=${#desc}
done
printf '| %-*s | %-*s | %-*s |\n' \
"$max_cmd" "Command" \
"$max_opt" "Option" \
"$max_desc" "Description"
printf '|-%*s-|-%*s-|-%*s-|\n' \
"$max_cmd" "$(printf '%*s' "$max_cmd" '' | tr ' ' '-')" \
"$max_opt" "$(printf '%*s' "$max_opt" '' | tr ' ' '-')" \
"$max_desc" "$(printf '%*s' "$max_desc" '' | tr ' ' '-')"
for row in "${rows[@]:1}"; do
IFS='|' read -r cmd opt desc <<< "$row"
printf '| %-*s | %-*s | %-*s |\n' \
"$max_cmd" "$cmd" \
"$max_opt" "$opt" \
"$max_desc" "$desc"
done
}
if [ -d "$HOME/taskfile.build/bin" ]; then
for file in "$HOME/taskfile.build/bin/"*; do
if [ -f "$file" ]; then
source "$file"
fi
done
fi
get-frontmatter-field() {
local FILE="$1"
local FIELD="$2"
awk '
BEGIN { in_fm=0; found=0 }
/^---$/ {
if (in_fm == 0) { in_fm=1; next }
else { exit }
}
in_fm && /^'"$FIELD"':[ \t]*/ {
sub(/^'"$FIELD"':[ \t]*/, "")
# Strip surrounding quotes if present
gsub(/^'"'"'|'"'"'$/, "")
gsub(/^"|"$/, "")
print
found=1
}
' "$FILE"
}
set-frontmatter-field() {
local FILE="$1"
shift
local VERSIONS=("$@")
# Build the replacement block: "versions:\n - 'x.y'\n - ..."
local NEW_BLOCK="versions:"
for V in "${VERSIONS[@]}"; do
NEW_BLOCK="${NEW_BLOCK}\n - '${V}'"
done
# Use awk to replace the existing versions block inside the frontmatter.
# The versions block may span multiple lines (the key line + list items).
# Skips any lines that are part of a YAML block sequence (optional indent + "- ").
awk -v new_block="$NEW_BLOCK" '
BEGIN { in_fm=0; in_versions=0; fm_done=0 }
/^---$/ {
if (in_fm == 0) { in_fm=1; print; next }
else { fm_done=1; in_fm=0 }
}
# Once frontmatter is closed, print everything verbatim
fm_done { print; next }
in_fm {
if (/^versions:/) {
# Print replacement block and enter versions-skip mode
printf "%s\n", new_block
in_versions=1
next
}
if (in_versions) {
# Skip continuation list items (lines starting with optional whitespace + "- ")
if (/^[ \t]*- /) { next }
else { in_versions=0 }
}
print
}
!in_fm { print }
' "$FILE" > "${FILE}.tmp" && mv "${FILE}.tmp" "$FILE"
}
update-module-versions() {
local TARGET_FILE="${1:-}" # Optional: single file path to process
local VERSIONS=("14.0" "15.0" "16.0" "17.0" "18.0" "19.0")
local PROGRESS_FILE="tmp/update-module-versions.progress"
# Collect files to process
local FILES=()
if [[ -n "$TARGET_FILE" ]]; then
if [[ ! -f "$TARGET_FILE" ]]; then
echo "Error: File '$TARGET_FILE' not found."
exit 1
fi
FILES=("$TARGET_FILE")
else
while IFS= read -r -d '' f; do
FILES+=("$f")
done < <(find . -maxdepth 1 -name "*.md" -type f -print0)
fi
local TOTAL_FILES=${#FILES[@]}
local FILE_COUNT=0
local RESUME_COUNT=0
if [[ -z "$TARGET_FILE" ]]; then
mkdir -p tmp
if [[ -f "$PROGRESS_FILE" ]]; then
RESUME_COUNT=$(cat "$PROGRESS_FILE" 2>/dev/null || echo 0)
if ! [[ "$RESUME_COUNT" =~ ^[0-9]+$ ]]; then
RESUME_COUNT=0
fi
fi
fi
if [[ -z "$TARGET_FILE" && "$RESUME_COUNT" -gt 0 ]]; then
echo "Resuming from file $RESUME_COUNT/$TOTAL_FILES"
fi
for FILE in "${FILES[@]}"; do
FILE_COUNT=$((FILE_COUNT + 1))
if [[ -z "$TARGET_FILE" && "$FILE_COUNT" -le "$RESUME_COUNT" ]]; then
continue
fi
echo "Processing file '$FILE' ($FILE_COUNT/$TOTAL_FILES)"
local SKIP_FILE=0
# Only process files that have a versions: key in their frontmatter
if ! awk '/^---$/{c++;next} c==1 && /^versions:/{found=1} c==2{exit} END{exit !found}' "$FILE"; then
echo " Skipping: no 'versions' key in frontmatter."
SKIP_FILE=1
fi
if [[ "$SKIP_FILE" -eq 0 ]]; then
# Read required frontmatter fields
local FORGE
FORGE=$(get-frontmatter-field "$FILE" "forge")
local REPO
REPO=$(get-frontmatter-field "$FILE" "repo")
local NAME
NAME=$(get-frontmatter-field "$FILE" "name")
if [[ -z "$FORGE" || -z "$REPO" || -z "$NAME" ]]; then
echo " Skipping: missing forge/repo/name in frontmatter."
SKIP_FILE=1
fi
fi
if [[ "$SKIP_FILE" -eq 0 ]]; then
# Test each version and collect available ones
local AVAILABLE_VERSIONS=()
for VERSION in "${VERSIONS[@]}"; do
local URL
if [[ "${FORGE}" == "github.com" ]]; then
URL="https://raw.githubusercontent.com/${REPO}/${VERSION}/${NAME}/__manifest__.py"
else
URL="https://${FORGE}/${REPO}/tree/${VERSION}/${NAME}"
fi
local HTTP_STATUS
HTTP_STATUS=$(curl -o /dev/null -s -w "%{http_code}" --max-time 10 "$URL" || echo "ERR")
if [[ "$HTTP_STATUS" == "200" ]]; then
echo " ✓ $VERSION available ($URL)"
AVAILABLE_VERSIONS+=("$VERSION")
else
echo " ✗ $VERSION not found (HTTP $HTTP_STATUS)"
fi
done
if [[ ${#AVAILABLE_VERSIONS[@]} -eq 0 ]]; then
echo " No available versions found. Frontmatter unchanged."
SKIP_FILE=1
fi
fi
if [[ "$SKIP_FILE" -eq 0 ]]; then
# Reverse so that the latest version appears first in the list
local REVERSED=()
for (( i=${#AVAILABLE_VERSIONS[@]}-1; i>=0; i-- )); do
REVERSED+=("${AVAILABLE_VERSIONS[$i]}")
done
echo " Updating versions: ${REVERSED[*]}"
set-frontmatter-field "$FILE" "${REVERSED[@]}"
fi
if [[ -z "$TARGET_FILE" ]]; then
echo "$FILE_COUNT" > "$PROGRESS_FILE"
fi
done
if [[ -z "$TARGET_FILE" && -f "$PROGRESS_FILE" ]]; then
rm -f "$PROGRESS_FILE"
fi
}
install-vuepress() {
pnpm install
}
update() {
pnpm install -D @vuepress/bundler-vite@next
pnpm install -D @vuepress/client@next
pnpm install -D @vuepress/plugin-docsearch@next
pnpm install -D @vuepress/plugin-search@next
pnpm install -D @vuepress/plugin-shiki@next
pnpm install -D @vuepress/theme-default@next
pnpm install -D @vuepress/utils@next
pnpm install -D vuepress@next
}
dev-vuepress() {
open-url "http://localhost:8080/"
pnpm run dev
}
build-vuepress() {
pnpm run build
}
serve-vuepress() {
cd ./src/.vuepress/dist
npx serve
}
download-icons() {
pnpm run download-icons
}
lint() {
pnpm exec prettier . --write
}
if declare -f "$1" > /dev/null; then
"$1" "${@:2}"
else
case "$1" in
*)
echo "Unknown command: $1"
help
exit 1
;;
esac
fi