#!/bin/sh # # Bump the canonical zyginit version. # # Usage: ./scripts/bump-version.sh # # Rewrites in lock-step: # - reef.toml (canonical) # - tools/zygctl/reef.toml # - src/version.reef (regenerated) # - tools/zygctl/src/version.reef (regenerated) # - tools/sysv-wrapper/version.h (regenerated) # # Does NOT auto-commit. Review with `hg diff` and commit by hand. # # ---------------------------------------------------------------------------- # Helpers for regenerating templated files. # ---------------------------------------------------------------------------- gen_reef_module() { project="$1" path="$2" version="$3" cat > "$path" < License: Description: Generated version constant. Do not edit by hand — regenerated by scripts/bump-version.sh. ******************************************************************************/ module version export fn VERSION(): string end export fn VERSION(): string return "$version" end VERSION end module EOF } gen_c_header() { path="$1" version="$2" cat > "$path" < License: Description: Generated version constant. Do not edit by hand — regenerated by scripts/bump-version.sh. ******************************************************************************/ #ifndef ZYGINIT_VERSION_H #define ZYGINIT_VERSION_H #define ZYGINIT_VERSION "$version" #endif EOF } set -e # This script uses GNU sed extensions (-i without backup suffix, 0,/addr/ # first-match range). Bumps are cut on a Linux dev host, not on Hammerhead; # fail fast if invoked elsewhere so the breakage isn't a cryptic sed error. case "$(uname -s)" in Linux) ;; *) echo "error: bump-version.sh requires GNU sed (Linux dev host)" >&2 echo " detected: $(uname -s)" >&2 exit 1 ;; esac if [ $# -ne 1 ]; then echo "usage: $0 " >&2 exit 1 fi NEW="$1" # Validate semver shape (no pre-release suffix yet). echo "$NEW" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || { echo "error: '$NEW' is not in MAJOR.MINOR.PATCH form" >&2 exit 1 } SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) ROOT=$(dirname "$SCRIPT_DIR") cd "$ROOT" CURRENT=$(grep '^version' reef.toml | head -1 | sed 's/.*"\([^"]*\)".*/\1/') if [ -z "$CURRENT" ]; then echo "error: could not read current version from reef.toml" >&2 exit 1 fi if [ "$CURRENT" = "$NEW" ]; then echo "error: version is already $NEW" >&2 exit 1 fi echo "zyginit: bumping $CURRENT -> $NEW" # 1. Root reef.toml — sed in place. Match only the first 'version = "..."' # in the [package] table (top of file). # $NEW is safe inside the substitution: the semver regex above guarantees # digits + dots only — no '/' or '&' to misinterpret. echo " rewriting reef.toml" sed -i "0,/^version = \"[^\"]*\"/s//version = \"$NEW\"/" reef.toml # 2. tools/zygctl/reef.toml # $NEW is safe inside the substitution: the semver regex above guarantees # digits + dots only — no '/' or '&' to misinterpret. echo " rewriting tools/zygctl/reef.toml" sed -i "0,/^version = \"[^\"]*\"/s//version = \"$NEW\"/" tools/zygctl/reef.toml # 3. src/version.reef — full regenerate. echo " regenerating src/version.reef" gen_reef_module zyginit src/version.reef "$NEW" # 4. tools/zygctl/src/version.reef — full regenerate. echo " regenerating tools/zygctl/src/version.reef" gen_reef_module zygctl tools/zygctl/src/version.reef "$NEW" # 5. tools/sysv-wrapper/version.h — full regenerate. echo " regenerating tools/sysv-wrapper/version.h" gen_c_header tools/sysv-wrapper/version.h "$NEW" echo echo "summary of changes:" hg diff --stat || true echo echo "review with 'hg diff' and commit:" echo " hg ci -m 'Bump version to $NEW'" #!/bin/sh # # Create a source release tarball for the zyginit suite. # # Usage: ./scripts/make-release.sh [version-override] # # Reads the canonical version from reef.toml unless an override is given. # Produces: # releases/zyginit--source.tar.xz # releases/zyginit--source.tar.xz.sha256 # set -e SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) ROOT=$(dirname "$SCRIPT_DIR") cd "$ROOT" if [ -n "$1" ]; then VERSION="$1" else VERSION=$(grep '^version' reef.toml | head -1 | sed 's/.*"\([^"]*\)".*/\1/') fi if [ -z "$VERSION" ]; then echo "error: could not determine version" >&2 exit 1 fi NAME="zyginit-${VERSION}-source" RELEASES="releases" TARBALL="${RELEASES}/${NAME}.tar.xz" echo "Creating release: $NAME" mkdir -p "$RELEASES" tar \ --exclude='build' \ --exclude='build/*' \ --exclude='tools/*/build' \ --exclude='tools/*/build/*' \ --exclude='releases' \ --exclude='.hg' \ --exclude='.hgignore' \ --exclude='.hgtags' \ --exclude='resume' \ --exclude='ss' \ --exclude='stub' \ --exclude='*.o' \ --exclude='*.a' \ --exclude='*.swp' \ --transform "s,^,${NAME}/," \ -cJf "$TARBALL" \ reef.toml \ README.md \ ROADMAP.md \ CLAUDE.md \ SRCHEADER.txt \ src \ docs \ tests \ examples \ bugs \ tools \ utils \ scripts echo "Created: $TARBALL" ls -la "$TARBALL" sha256sum "$TARBALL" > "${TARBALL}.sha256" echo "Checksum: ${TARBALL}.sha256" cat "${TARBALL}.sha256" #!/bin/sh # ***************************************************************************** # __ ____ __ # / / ___ ____ _/ __/_____________ _/ /__ # / / / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \ # / /___/ __/ /_/ / __(__ ) /__/ /_/ / / __/ # /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/ # # (C)opyright 2025-2026, Leafscale, LLC - https://www.leafscale.com # # Project: zyginit # Filename: migrate-layout.sh # Authors: Chris Tusa # License: CDDL-1.0 # Description: Migrate a 0.1.x /etc/zyginit/ flat layout to the 0.2.0 # per-service directory layout. Idempotent. Dry-run by default. # Run with --apply to actually move files. # # ***************************************************************************** set -e usage() { cat <] --dry-run Print planned moves and exit (default) --apply Perform the moves --config-dir DIR Target directory (default /etc/zyginit/) -h, --help Show this help EOF } MODE=dry-run CONFIG_DIR=/etc/zyginit while [ $# -gt 0 ]; do case "$1" in --dry-run) MODE=dry-run; shift ;; --apply) MODE=apply; shift ;; --config-dir) CONFIG_DIR="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "error: unknown arg: $1" >&2; usage >&2; exit 2 ;; esac done if [ ! -d "$CONFIG_DIR" ]; then echo "error: $CONFIG_DIR is not a directory" >&2 exit 1 fi cd "$CONFIG_DIR" # Ambiguity check: refuse if any service has BOTH .toml at top level # AND services//service.toml. AMBIGUOUS="" if [ -d services ]; then for f in *.toml; do [ -f "$f" ] || continue name="${f%.toml}" if [ -f "services/$name/service.toml" ]; then AMBIGUOUS="$AMBIGUOUS $name" fi done fi if [ -n "$AMBIGUOUS" ]; then echo "error: ambiguous layout — both old .toml and services//service.toml exist for:$AMBIGUOUS" >&2 echo " Resolve manually before re-running." >&2 exit 3 fi # Plan moves PLAN_FILE=$(mktemp /tmp/migrate-plan.XXXXXX) trap 'rm -f "$PLAN_FILE"' EXIT COUNT=0 for f in *.toml; do [ -f "$f" ] || continue name="${f%.toml}" echo "mkdir -p services/$name" >> "$PLAN_FILE" echo "mv $f services/$name/service.toml" >> "$PLAN_FILE" if [ -d "$name" ] && [ ! -L "$name" ]; then # Move helper scripts (start.sh, stop.sh, etc.) into the new dir for sf in "$name"/*; do [ -e "$sf" ] || continue base=$(basename "$sf") echo "mv $name/$base services/$name/$base" >> "$PLAN_FILE" done echo "rmdir $name" >> "$PLAN_FILE" fi COUNT=$((COUNT + 1)) done # Plan enabled.d symlink retarget if [ -d enabled.d ]; then for link in enabled.d/*; do [ -L "$link" ] || continue target=$(readlink "$link") case "$target" in *.toml) name=$(basename "$link") echo "ln -sfn ../services/$name $link" >> "$PLAN_FILE" ;; esac done fi # Plan examples/ migration (same convention as services/) if [ -d examples ]; then for f in examples/*.toml; do [ -f "$f" ] || continue name=$(basename "${f%.toml}") echo "mkdir -p examples/$name" >> "$PLAN_FILE" echo "mv $f examples/$name/service.toml" >> "$PLAN_FILE" done fi if [ ! -s "$PLAN_FILE" ]; then echo "no changes — tree already in 0.2.0 layout" exit 0 fi if [ "$MODE" = "dry-run" ]; then echo "PLANNED MOVES ($COUNT services):" cat "$PLAN_FILE" echo echo "Re-run with --apply to perform these moves." exit 0 fi # Apply echo "Applying $COUNT services..." while IFS= read -r line; do eval "$line" done < "$PLAN_FILE" echo "Migration complete."