144 lines
4.5 KiB
Bash
Executable File
144 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# publish-rename: normalize filenames for ipfs.kane-il.us publishing
|
||
# - Category content: /<category>/YYYYMMDDThhmmssZ_<slug>.<ext>
|
||
# - Root design docs: /<NAME>_vN.md
|
||
|
||
set -euo pipefail
|
||
|
||
VERSION="1.0"
|
||
|
||
# ---------- config ----------
|
||
ALLOWED_EXT_REGEX='^(md|txt|jsonl)$'
|
||
UTC_FMT='+%Y%m%dT%H%M%SZ'
|
||
|
||
# ---------- helpers ----------
|
||
err(){ printf 'error: %s\n' "$*" >&2; exit 1; }
|
||
note(){ printf '%s\n' "$*" >&2; }
|
||
ts(){ date -u "${UTC_FMT}"; }
|
||
|
||
slugify(){
|
||
# lower, spaces->_, remove disallowed chars, collapse repeats, trim underscores
|
||
printf '%s' "$1" \
|
||
| tr '[:upper:] ' '[:lower:]_' \
|
||
| sed -E 's/[^a-z0-9_]+/_/g; s/_+/_/g; s/^_+//; s/_+$//'
|
||
}
|
||
|
||
print_man(){
|
||
cat <<'MAN'
|
||
NAME
|
||
publish-rename — normalize filenames for publishing to ipfs.kane-il.us
|
||
|
||
SYNOPSIS
|
||
publish-rename category [--dry-run] <category> <file> <slug>
|
||
publish-rename root [--dry-run] --version <N> <file> <name>
|
||
|
||
DESCRIPTION
|
||
Renames content into the repository’s required shapes:
|
||
|
||
1) CATEGORY MODE
|
||
Target: /<category>/YYYYMMDDThhmmssZ_<slug>.<ext>
|
||
- <category> must be one of: legal, civics, naics, barter, w3pbs, onet
|
||
- <ext> must be md|txt|jsonl (unchanged from <file>)
|
||
- <slug> is normalized (lowercase, underscores, ASCII)
|
||
|
||
2) ROOT MODE (design docs)
|
||
Target: /<NAME>_vN.md (no timestamp)
|
||
- <NAME> is normalized (e.g., CONVENTIONS -> conventions)
|
||
- --version N is required (integer >= 1)
|
||
- Extension forced to .md
|
||
|
||
OPTIONS
|
||
--dry-run Print the rename that would occur; do not move files.
|
||
--version N Root mode only: version number N (e.g., 1, 2, 3...)
|
||
-h, --help Show this help.
|
||
|
||
EXAMPLES
|
||
# Category: rename to legal/20250829T171500Z_conventions_v1.md
|
||
publish-rename category legal CONVENTIONS_v1.md conventions_v1
|
||
|
||
# Category: rename a text file into naics with a slug
|
||
publish-rename category naics notes.txt procurement_policy_notes
|
||
|
||
# Root: versioned design doc at repo root (CONVENTIONS_v1.md)
|
||
publish-rename root --version 1 CONVENTIONS.md CONVENTIONS
|
||
|
||
NOTES
|
||
- This tool changes only the filename/location; it does not git add/commit.
|
||
- For legal citations, always use the CID after publishing; the repo path
|
||
is for structure and operator convenience only.
|
||
|
||
AUTHOR
|
||
vMAN 1.0 — tailored for ipfs.kane-il.us
|
||
|
||
MAN
|
||
}
|
||
|
||
# ---------- argparse ----------
|
||
[[ $# -lt 1 ]] && { print_man; exit 1; }
|
||
|
||
mode="$1"; shift || true
|
||
|
||
dry_run=0
|
||
root_version=''
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--dry-run) dry_run=1; shift;;
|
||
-h|--help) print_man; exit 0;;
|
||
--version) shift; root_version="${1:-}"; [[ -z "$root_version" ]] && err "--version requires a number"; shift;;
|
||
*) break;;
|
||
esac
|
||
done
|
||
|
||
case "$mode" in
|
||
category)
|
||
[[ $# -ne 3 ]] && { print_man; err "category mode requires <category> <file> <slug>"; }
|
||
category_raw="$1"; file="$2"; slug_raw="$3"
|
||
|
||
category="$(slugify "$category_raw")"
|
||
case "$category" in
|
||
legal|civics|naics|barter|w3pbs|onet) : ;;
|
||
*) err "invalid category '$category_raw' (expected: legal|civics|naics|barter|w3pbs|onet)";;
|
||
esac
|
||
|
||
[[ -f "$file" ]] || err "file not found: $file"
|
||
ext="${file##*.}"; [[ "$ext" =~ $ALLOWED_EXT_REGEX ]] || err "extension '.$ext' not allowed (md|txt|jsonl)"
|
||
|
||
slug="$(slugify "$slug_raw")"; [[ -n "$slug" ]] || err "slug normalization produced empty value"
|
||
stamp="$(ts)"
|
||
dest_dir="$category"
|
||
dest_file="${stamp}_${slug}.${ext}"
|
||
dest_path="${dest_dir}/${dest_file}"
|
||
|
||
[[ $dry_run -eq 1 ]] && { printf 'DRY-RUN: %s -> %s\n' "$file" "$dest_path"; exit 0; }
|
||
|
||
mkdir -p "$dest_dir"
|
||
mv -- "$file" "$dest_path"
|
||
printf 'Renamed %s -> %s\n' "$file" "$dest_path"
|
||
;;
|
||
|
||
root)
|
||
# root design docs: <NAME>_vN.md at repo root
|
||
[[ -z "$root_version" ]] && { print_man; err "root mode requires --version <N>"; }
|
||
[[ $# -ne 2 ]] && { print_man; err "root mode requires <file> <name>"; }
|
||
|
||
file="$1"; name_raw="$2"
|
||
[[ -f "$file" ]] || err "file not found: $file"
|
||
|
||
# version must be integer >=1
|
||
[[ "$root_version" =~ ^[0-9]+$ ]] || err "version must be an integer"
|
||
[[ "$root_version" -ge 1 ]] || err "version must be >= 1"
|
||
|
||
name="$(slugify "$name_raw")"; [[ -n "$name" ]] || err "name normalization produced empty value"
|
||
dest_path="${name}_v${root_version}.md"
|
||
|
||
[[ $dry_run -eq 1 ]] && { printf 'DRY-RUN: %s -> %s\n' "$file" "$dest_path"; exit 0; }
|
||
|
||
mv -- "$file" "$dest_path"
|
||
printf 'Renamed %s -> %s\n' "$file" "$dest_path"
|
||
;;
|
||
|
||
*)
|
||
print_man; err "unknown mode '$mode' (use 'category' or 'root')"
|
||
;;
|
||
esac
|