|
1 | 1 | #!/usr/bin/env bash |
2 | | -# pack.sh — build a release tarball of the viktorani project |
3 | | -# |
4 | | -# Usage: |
5 | | -# ./scripts/pack.sh # outputs viktorani.tar.gz in repo root |
6 | | -# ./scripts/pack.sh -o ~/Desktop # output to a specific directory |
7 | | -# ./scripts/pack.sh -n --quiet # dry-run, no output |
8 | | -# ./scripts/pack.sh --help |
9 | | - |
| 2 | +# scripts/pack.sh — produce a source-only tarball for AI analysis. |
| 3 | +# Excludes binaries, generated files, and anything an AI cannot read. |
| 4 | +# Output: viktorani-<version>.tgz in the repo root. |
10 | 5 | set -euo pipefail |
11 | 6 |
|
12 | | -# ── helpers ─────────────────────────────────────────────────────────────────── |
13 | | - |
14 | | -PROG=$(basename "$0") |
15 | | -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" |
16 | | - |
17 | | -_use_color() { |
18 | | - [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]] && [[ -t 2 ]] |
19 | | -} |
20 | | - |
21 | | -err() { |
22 | | - if _use_color; then printf '\033[31mError:\033[0m %s\n' "$*" >&2 |
23 | | - else printf 'Error: %s\n' "$*" >&2; fi |
24 | | -} |
25 | | - |
26 | | -info() { |
27 | | - [[ "${QUIET:-0}" == "1" ]] && return |
28 | | - printf '%s\n' "$*" >&2 |
29 | | -} |
30 | | - |
31 | | -ok() { |
32 | | - [[ "${QUIET:-0}" == "1" ]] && return |
33 | | - if _use_color; then printf '\033[32m✓\033[0m %s\n' "$*" >&2 |
34 | | - else printf '✓ %s\n' "$*" >&2; fi |
35 | | -} |
36 | | - |
37 | | -usage() { |
38 | | - cat >&2 <<EOF |
39 | | -USAGE |
40 | | - $PROG [flags] |
41 | | -
|
42 | | -DESCRIPTION |
43 | | - Build a release tarball of the viktorani project, excluding |
44 | | - node_modules, dist, and other dev artifacts. |
45 | | -
|
46 | | -EXAMPLES |
47 | | - $PROG # create viktorani.tar.gz in repo root |
48 | | - $PROG -o ~/Desktop # write to a specific directory |
49 | | - $PROG --name my-release # custom archive name (no .tar.gz needed) |
50 | | - $PROG -n # dry-run: show what would be included |
51 | | -
|
52 | | -FLAGS |
53 | | - -o, --output DIR Directory to write the archive (default: repo root) |
54 | | - -N, --name NAME Archive base name without extension (default: viktorani) |
55 | | - -n, --dry-run List files that would be included; don't write anything |
56 | | - -q, --quiet Suppress non-essential output |
57 | | - --no-color Disable colour output |
58 | | - -h, --help Show this help |
59 | | -
|
60 | | -EOF |
61 | | -} |
62 | | - |
63 | | -# ── defaults ────────────────────────────────────────────────────────────────── |
64 | | - |
65 | | -OUTPUT_DIR="$REPO_ROOT/dist" |
66 | | -ARCHIVE_NAME="viktorani" |
67 | | -DRY_RUN=0 |
68 | | -QUIET=0 |
69 | | - |
70 | | -# ── arg parsing ─────────────────────────────────────────────────────────────── |
71 | | - |
72 | | -while [[ $# -gt 0 ]]; do |
73 | | - case "$1" in |
74 | | - -o|--output) OUTPUT_DIR="${2:?'--output requires a DIR'}"; shift 2 ;; |
75 | | - -N|--name) ARCHIVE_NAME="${2:?'--name requires a NAME'}"; shift 2 ;; |
76 | | - -n|--dry-run) DRY_RUN=1; shift ;; |
77 | | - -q|--quiet) QUIET=1; shift ;; |
78 | | - --no-color) NO_COLOR=1; export NO_COLOR; shift ;; |
79 | | - -h|--help) usage; exit 0 ;; |
80 | | - *) err "unknown flag: $1"; usage; exit 2 ;; |
81 | | - esac |
82 | | -done |
83 | | - |
84 | | -# ── validate ────────────────────────────────────────────────────────────────── |
85 | | - |
86 | | -if [[ ! -d "$OUTPUT_DIR" ]]; then |
87 | | - err "output directory does not exist: $OUTPUT_DIR" |
88 | | - exit 1 |
89 | | -fi |
90 | | - |
91 | | -ARCHIVE="${OUTPUT_DIR%/}/${ARCHIVE_NAME}.tar.gz" |
92 | | - |
93 | | -# ── excludes ───────────────────────────────────────────────────────────────── |
94 | | -# Keep this list minimal — pack everything that belongs in the repo. |
| 7 | +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" |
| 8 | +VERSION="$(node -p "require('./package.json').version")" |
| 9 | +OUT="$ROOT/archives/viktorani-${VERSION}.tgz" |
95 | 10 |
|
| 11 | +# Files and dirs to exclude (binaries, generated, irrelevant to source analysis) |
96 | 12 | EXCLUDES=( |
97 | 13 | --exclude='.git' |
98 | 14 | --exclude='node_modules' |
99 | | - --exclude='archives' |
100 | 15 | --exclude='dist' |
101 | | - --exclude='.vite' |
102 | 16 | --exclude='coverage' |
103 | | - --exclude='*.tar.gz' |
104 | | - --exclude='.DS_Store' |
105 | | - --exclude='*.local' |
| 17 | + --exclude='*.png' |
| 18 | + --exclude='*.ico' |
| 19 | + --exclude='*.svg' |
| 20 | + --exclude='*.webp' |
| 21 | + --exclude='*.jpg' |
| 22 | + --exclude='*.jpeg' |
| 23 | + --exclude='*.woff2' |
| 24 | + --exclude='*.woff' |
| 25 | + --exclude='CHANGELOG.md' |
| 26 | + --exclude='LICENSE' |
| 27 | + --exclude='src/assets' |
| 28 | + --exclude='public' |
| 29 | + --exclude='deploy' |
| 30 | + --exclude='archives' |
106 | 31 | ) |
107 | 32 |
|
108 | | -# ── dry-run ─────────────────────────────────────────────────────────────────── |
109 | | - |
110 | | -if [[ "$DRY_RUN" == "1" ]]; then |
111 | | - info "Dry run — files that would be included:" |
112 | | - tar "${EXCLUDES[@]}" -cz --to-stdout -C "$(dirname "$REPO_ROOT")" \ |
113 | | - "$(basename "$REPO_ROOT")" 2>/dev/null \ |
114 | | - | tar -tz 2>/dev/null \ |
115 | | - | sed 's|^[^/]*/||' \ |
116 | | - | grep -v '^$' |
117 | | - info "" |
118 | | - info "Archive would be written to: $ARCHIVE" |
119 | | - exit 0 |
120 | | -fi |
121 | | - |
122 | | -# ── build ───────────────────────────────────────────────────────────────────── |
123 | | - |
124 | | -info "Packing $(basename "$REPO_ROOT") → $ARCHIVE …" |
125 | | - |
126 | | -tar "${EXCLUDES[@]}" \ |
127 | | - -czf "$ARCHIVE" \ |
128 | | - -C "$(dirname "$REPO_ROOT")" \ |
129 | | - "$(basename "$REPO_ROOT")" |
130 | | - |
131 | | -SIZE=$(du -sh "$ARCHIVE" | cut -f1) |
132 | | -ok "Done — $ARCHIVE ($SIZE)" |
| 33 | +cd "$ROOT" |
| 34 | +tar -czf "$OUT" "${EXCLUDES[@]}" . |
| 35 | +SIZE="$(du -sh "$OUT" | cut -f1)" |
| 36 | +echo "Packed: $OUT ($SIZE)" |
| 37 | +echo "" |
| 38 | +echo "Contents by size:" |
| 39 | +tar -tzf "$OUT" | xargs -I{} du -sh "$ROOT/{}" 2>/dev/null | sort -rh | head -20 |
0 commit comments