131 lines
3.3 KiB
Bash
131 lines
3.3 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
|
|
: ${DATA_DIRECTORY:="/usr/local/share/freebsdupdate"}
|
|
: ${STAGE_FILE:="${DATA_DIRECTORY}/stage"}
|
|
: ${RELEASE_DIRECTORY:="${DATA_DIRECTORY}/release"}
|
|
: ${LOG_DIRECTORY:="${DATA_DIRECTORY}/logs"}
|
|
: ${PORTS_TREE:="/usr/ports"}
|
|
: ${PORTS_REPO:="https://git.FreeBSD.org/ports.git"}
|
|
|
|
############## Setup #########################
|
|
|
|
function die {
|
|
local status_code="$1"
|
|
shift
|
|
(>&2 echo "${@}")
|
|
exit "$status_code"
|
|
}
|
|
|
|
function log {
|
|
(>&2 echo "${@}")
|
|
}
|
|
|
|
############## Program #########################
|
|
|
|
function main {
|
|
assert_directories
|
|
|
|
local stage=""
|
|
if [ -e "$STAGE_FILE" ]; then
|
|
local stage=$(cat "$STAGE_FILE")
|
|
fi
|
|
if [ "$stage" = "selfbuild" ]; then
|
|
log_cmd stage_selfbuild
|
|
elif [ "$stage" = "selfinstallworld" ]; then
|
|
log_cmd stage_selfinstallworld
|
|
elif [ "$stage" = "selfconflictcheck" ]; then
|
|
log_cmd stage_selfconflictcheck
|
|
elif [ "$stage" = "releasebuild" ]; then
|
|
log_cmd stage_releasebuild
|
|
elif [ "$stage" = "done" ]; then
|
|
log_cmd stage_done
|
|
else
|
|
die 1 "Unhandled stage: \"$stage\"."
|
|
fi
|
|
}
|
|
|
|
function log_cmd {
|
|
"${@}" |& tee "$LOG_DIRECTORY/$(date +%Y%m%d-%s).log"
|
|
}
|
|
|
|
function self_conflict_check {
|
|
if etcupdate status | grep -qE '^ C '; then
|
|
die 1 'Conflicts remain in etcupdate. Run `etcupdate resolve` to fix them first.'
|
|
fi
|
|
}
|
|
|
|
function assert_directories {
|
|
for d in "$DATA_DIRECTORY" "$RELEASE_DIRECTORY" "$LOG_DIRECTORY"; do
|
|
if [ ! -e "$d" ]; then
|
|
mkdir -p "$d"
|
|
fi
|
|
done
|
|
}
|
|
|
|
function update_ports_tree {
|
|
if [ ! -e "$PORTS_TREE" ]; then
|
|
mkdir -p $PORTS_TREE
|
|
git -C $PORTS_TREE init --initial-branch=main
|
|
git -C $PORTS_TREE remote add origin $PORTS_REPO
|
|
fi
|
|
git -C $PORTS_TREE fetch origin main # 'refs/heads/main'
|
|
git -C $PORTS_TREE checkout FETCH_HEAD
|
|
}
|
|
|
|
function set_stage {
|
|
echo "${@}" > "$STAGE_FILE"
|
|
}
|
|
|
|
function stage_selfbuild {
|
|
self_conflict_check
|
|
assert_directories
|
|
update_ports_tree
|
|
|
|
SRCCONF=/dev/null __MAKE_CONF=/dev/null make -C /usr/src clean
|
|
SRCCONF=/dev/null __MAKE_CONF=/dev/null make -C /usr/src buildworld buildkernel
|
|
SRCCONF=/dev/null __MAKE_CONF=/dev/null make -C /usr/src installkernel
|
|
|
|
set_stage "selfinstallworld"
|
|
/sbin/shutdown -r now
|
|
}
|
|
|
|
function stage_selfinstallworld {
|
|
etcupdate -p
|
|
SRCCONF=/dev/null __MAKE_CONF=/dev/null make -C /usr/src installworld
|
|
etcupdate -B
|
|
|
|
set_stage "selfconflictcheck"
|
|
stage_selfconflictcheck
|
|
}
|
|
|
|
function stage_selfconflictcheck {
|
|
self_conflict_check
|
|
set_stage "releasebuild"
|
|
/sbin/shutdown -r now
|
|
}
|
|
|
|
function stage_releasebuild {
|
|
local today=$(date +%Y%m%d)
|
|
local target_directory="${RELEASE_DIRECTORY}/${today}"
|
|
if [ -e "$target_directory" ]; then
|
|
die 1 "The release directory $target_directory already exists. Exiting."
|
|
fi
|
|
SRCCONF=/dev/null __MAKE_CONF=/dev/null make -C /usr/src clean
|
|
make -C /usr/src buildworld buildkernel
|
|
make -C /usr/src/release obj
|
|
make -C /usr/src/release release
|
|
mkdir -p "$target_directory"
|
|
make -C /usr/src/release install DESTDIR="$target_directory"
|
|
set_stage "done"
|
|
}
|
|
|
|
function stage_done {
|
|
log "Everything is done."
|
|
}
|
|
|
|
main "${@}"
|