From 5f9abd9707a6fbaf320af44afb40b0e1490bf24b Mon Sep 17 00:00:00 2001 From: varch Date: Sun, 7 Jun 2026 01:06:21 +0700 Subject: [PATCH] refactor: remove vendored binaries and raw assets from repo --- .gitignore | 12 +++ README.md | 25 +++++++ docs/deployment-vm.md | 7 ++ docs/repo-size-cleanup.md | 18 +++++ scripts/purge-git-history.sh | 14 ++++ scripts/setup-dcmtk.sh | 139 +++++++++++++++++++++++++++++++++++ scripts/setup-microdicom.sh | 120 ++++++++++++++++++++++++++++++ 7 files changed, 335 insertions(+) create mode 100644 docs/repo-size-cleanup.md create mode 100755 scripts/purge-git-history.sh create mode 100755 scripts/setup-dcmtk.sh create mode 100755 scripts/setup-microdicom.sh diff --git a/.gitignore b/.gitignore index 06368b1..ee81615 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,11 @@ config.yaml # ISO output files *.iso +# Vendored/runtime assets fetched outside git +dcmtk-bin/ +legacy/raw/ +.local/ + # Temp directories /tmp/dicomdir_* @@ -20,3 +25,10 @@ Thumbs.db # Local-only docs tell @VArtzy for request docs/phases + +# Keep placeholder docs for ignored asset directories +!dcmtk-bin/ +!dcmtk-bin/README.md +!legacy/ +!legacy/raw/ +!legacy/raw/README.md diff --git a/README.md b/README.md index 4558d70..b7279b6 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ The service needs: - MicroDicom files - writable temp storage +Large runtime assets are intentionally not stored in git. +Use the setup scripts in `scripts/` to stage local copies in ignored directories. + ## Setup Before running the service, make sure the VM has: - Go installed, if you are building on that machine @@ -33,6 +36,27 @@ Before running the service, make sure the VM has: - network access to PACS, the patient API, and the CD publisher - a writable temp directory +Stage local runtime assets if needed: + +```bash +scripts/setup-dcmtk.sh --source-dir /path/to/dcmtk/bin +scripts/setup-microdicom.sh --source-dir /path/to/microdicom +``` + +Or download your hosted release assets directly: + +```bash +scripts/setup-dcmtk.sh --archive-url https://///releases/download//dcmtk-bin.tar.gz +scripts/setup-microdicom.sh --archive-url https://///releases/download//microdicom.zip +``` + +Example: + +```bash +scripts/setup-dcmtk.sh --archive-url https://devone.aplikasi.web.id/gitea/farrel/dicom-iso/releases/download/1/dcmtk-bin.tar.gz +scripts/setup-microdicom.sh --archive-url https://devone.aplikasi.web.id/gitea/farrel/dicom-iso/releases/download/1/microdicom.zip +``` + Create a local config file from the template: ```bash @@ -40,6 +64,7 @@ cp config.example.yaml config.yaml ``` Then adjust the paths, hosts, ports, and tokens for your environment. +For local staging via the setup scripts, point config at `.local/dcmtk-bin/` and `.local/microdicom/`. ## Build A normal Go build is enough in a friendly environment: diff --git a/docs/deployment-vm.md b/docs/deployment-vm.md index 4178aef..607bb8f 100644 --- a/docs/deployment-vm.md +++ b/docs/deployment-vm.md @@ -29,6 +29,13 @@ The service needs: - a writable temp directory - a free port range for `storescp` +If you do not manage these assets globally on the VM, you can stage them locally first: + +```bash +scripts/setup-dcmtk.sh --source-dir /path/to/dcmtk/bin --install-dir /opt/dicom-iso/dcmtk-bin +scripts/setup-microdicom.sh --source-dir /path/to/microdicom --install-dir /opt/dicom-iso/microdicom +``` + ## Build note The build environment cannot depend on public internet access. That means the binary must be built through an approved offline-friendly path. diff --git a/docs/repo-size-cleanup.md b/docs/repo-size-cleanup.md new file mode 100644 index 0000000..504a429 --- /dev/null +++ b/docs/repo-size-cleanup.md @@ -0,0 +1,18 @@ +# Repo size cleanup + +Implemented in the working tree: +- removed tracked binaries from `dcmtk-bin/` +- removed tracked raw assets from `legacy/raw/` +- added `.gitignore` protections +- added setup scripts for DCMTK and MicroDicom + +## Finish the cleanup in git history +Rewriting history is still required to shrink the remote repository size. + +```bash +git filter-repo --path dcmtk-bin --path legacy/raw --invert-paths +git push --force --all +git push --force --tags +``` + +Coordinate this with any collaborators first. diff --git a/scripts/purge-git-history.sh b/scripts/purge-git-history.sh new file mode 100755 index 0000000..309e06f --- /dev/null +++ b/scripts/purge-git-history.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +cat <<'EOF' +This rewrites git history to remove large vendored assets. +Run only after committing the current tree cleanup and coordinating with collaborators. + +Commands: + git filter-repo --path dcmtk-bin --path legacy/raw --invert-paths + git push --force --all + git push --force --tags + +Afterward, collaborators should reclone or hard-reset to the rewritten history. +EOF diff --git a/scripts/setup-dcmtk.sh b/scripts/setup-dcmtk.sh new file mode 100755 index 0000000..1b00093 --- /dev/null +++ b/scripts/setup-dcmtk.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +INSTALL_DIR="${INSTALL_DIR:-$ROOT_DIR/.local/dcmtk-bin}" +REQUIRED_BINS=(storescp movescu storescu findscu dcmdump dcmodify getscu echoscu dcmj2pnm) +SOURCE_DIR="" +ARCHIVE_URL="" +TMP_DIR="" + +usage() { + cat <<'EOF' +Usage: + scripts/setup-dcmtk.sh [--source-dir DIR | --archive-url URL] [--install-dir DIR] + +Behavior: + - Copies required DCMTK binaries into a local ignored directory. + - If --source-dir is omitted, binaries are resolved from PATH. + - If --archive-url is given, the script downloads and extracts an archive, + then searches for the required binaries inside it. + +Examples: + scripts/setup-dcmtk.sh --source-dir /opt/dcmtk/bin + scripts/setup-dcmtk.sh --archive-url https://github.com///releases/download//dcmtk-bin.tar.gz + scripts/setup-dcmtk.sh --install-dir /data/dcmtk-bin +EOF +} + +download() { + local url="$1" + local out="$2" + if command -v curl >/dev/null 2>&1; then + curl -fL "$url" -o "$out" + elif command -v wget >/dev/null 2>&1; then + wget -O "$out" "$url" + else + echo "need curl or wget to download $url" >&2 + exit 1 + fi +} + +extract_archive() { + local archive="$1" + local dest="$2" + case "$archive" in + *.tar.gz|*.tgz) tar -xzf "$archive" -C "$dest" ;; + *.tar.xz) tar -xJf "$archive" -C "$dest" ;; + *.tar) tar -xf "$archive" -C "$dest" ;; + *.zip) + command -v unzip >/dev/null 2>&1 || { echo "unzip is required for $archive" >&2; exit 1; } + unzip -q "$archive" -d "$dest" + ;; + *) + echo "unsupported archive format: $archive" >&2 + exit 1 + ;; + esac +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --source-dir) + SOURCE_DIR="${2:?missing value for --source-dir}" + shift 2 + ;; + --archive-url) + ARCHIVE_URL="${2:?missing value for --archive-url}" + shift 2 + ;; + --install-dir) + INSTALL_DIR="${2:?missing value for --install-dir}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -n "$SOURCE_DIR" && -n "$ARCHIVE_URL" ]]; then + echo "use only one of --source-dir or --archive-url" >&2 + exit 1 +fi + +cleanup() { + [[ -n "$TMP_DIR" && -d "$TMP_DIR" ]] && rm -rf "$TMP_DIR" +} +trap cleanup EXIT + +if [[ -n "$ARCHIVE_URL" ]]; then + TMP_DIR="$(mktemp -d)" + archive_name="$(basename "${ARCHIVE_URL%%\?*}")" + [[ -n "$archive_name" && "$archive_name" != "/" ]] || archive_name="archive.tar.gz" + archive="$TMP_DIR/$archive_name" + download "$ARCHIVE_URL" "$archive" + mkdir -p "$TMP_DIR/extracted" + extract_archive "$archive" "$TMP_DIR/extracted" + SOURCE_DIR="$TMP_DIR/extracted" +fi + +mkdir -p "$INSTALL_DIR" + +resolve_bin() { + local name="$1" + if [[ -n "$SOURCE_DIR" ]]; then + local candidate + candidate="$(find "$SOURCE_DIR" -type f -name "$name" -perm -u+x | head -n 1 || true)" + [[ -n "$candidate" ]] || candidate="$(find "$SOURCE_DIR" -type f -name "$name" | head -n 1 || true)" + [[ -n "$candidate" ]] || { echo "missing binary in source: $name" >&2; return 1; } + printf '%s\n' "$candidate" + return 0 + fi + + command -v "$name" >/dev/null 2>&1 || { echo "binary not found in PATH: $name" >&2; return 1; } + command -v "$name" +} + +for bin in "${REQUIRED_BINS[@]}"; do + src="$(resolve_bin "$bin")" + install -m 0755 "$src" "$INSTALL_DIR/$bin" + echo "installed $bin -> $INSTALL_DIR/$bin" +done + +cat <//releases/download//microdicom.zip +EOF +} + +download() { + local url="$1" + local out="$2" + if command -v curl >/dev/null 2>&1; then + curl -fL "$url" -o "$out" + elif command -v wget >/dev/null 2>&1; then + wget -O "$out" "$url" + else + echo "need curl or wget to download $url" >&2 + exit 1 + fi +} + +extract_archive() { + local archive="$1" + local dest="$2" + case "$archive" in + *.tar.gz|*.tgz) tar -xzf "$archive" -C "$dest" ;; + *.tar.xz) tar -xJf "$archive" -C "$dest" ;; + *.tar) tar -xf "$archive" -C "$dest" ;; + *.zip) + command -v unzip >/dev/null 2>&1 || { echo "unzip is required for $archive" >&2; exit 1; } + unzip -q "$archive" -d "$dest" + ;; + *) + echo "unsupported archive format: $archive" >&2 + exit 1 + ;; + esac +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --source-dir) + SOURCE_DIR="${2:?missing value for --source-dir}" + shift 2 + ;; + --archive-url) + ARCHIVE_URL="${2:?missing value for --archive-url}" + shift 2 + ;; + --install-dir) + INSTALL_DIR="${2:?missing value for --install-dir}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -n "$SOURCE_DIR" && -n "$ARCHIVE_URL" ]]; then + echo "use only one of --source-dir or --archive-url" >&2 + exit 1 +fi + +cleanup() { + [[ -n "$TMP_DIR" && -d "$TMP_DIR" ]] && rm -rf "$TMP_DIR" +} +trap cleanup EXIT + +if [[ -n "$ARCHIVE_URL" ]]; then + TMP_DIR="$(mktemp -d)" + archive_name="$(basename "${ARCHIVE_URL%%\?*}")" + [[ -n "$archive_name" && "$archive_name" != "/" ]] || archive_name="microdicom.zip" + archive="$TMP_DIR/$archive_name" + download "$ARCHIVE_URL" "$archive" + mkdir -p "$TMP_DIR/extracted" + extract_archive "$archive" "$TMP_DIR/extracted" + SOURCE_DIR="$(find "$TMP_DIR/extracted" -type f -name AUTORUN.INF -printf '%h\n' | head -n 1 || true)" +fi + +[[ -n "$SOURCE_DIR" ]] || { echo "one of --source-dir or --archive-url is required" >&2; exit 1; } +[[ -d "$SOURCE_DIR" ]] || { echo "source directory does not exist: $SOURCE_DIR" >&2; exit 1; } +[[ -f "$SOURCE_DIR/AUTORUN.INF" ]] || { echo "missing AUTORUN.INF in source directory" >&2; exit 1; } +[[ -d "$SOURCE_DIR/MICROD" ]] || { echo "missing MICROD/ in source directory" >&2; exit 1; } + +rm -rf "$INSTALL_DIR" +mkdir -p "$INSTALL_DIR" +cp -a "$SOURCE_DIR"/. "$INSTALL_DIR"/ + +echo "installed MicroDicom assets -> $INSTALL_DIR" +cat <