Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/etcupdate/etcupdate.sh
Show First 20 Lines • Show All 220 Lines • ▼ Show 20 Lines | build_tree() | ||||
# Remove empty files. These just clutter the output of 'diff'. | # Remove empty files. These just clutter the output of 'diff'. | ||||
find $1 -type f -size 0 -delete >&3 2>&1 || return 1 | find $1 -type f -size 0 -delete >&3 2>&1 || return 1 | ||||
# Trim empty directories. | # Trim empty directories. | ||||
find -d $1 -type d -empty -delete >&3 2>&1 || return 1 | find -d $1 -type d -empty -delete >&3 2>&1 || return 1 | ||||
return 0 | return 0 | ||||
} | } | ||||
# Generate a new NEWTREE tree. If tarball is set, then the tree is | # Generate a new tree. If tarball is set, then the tree is | ||||
# extracted from the tarball. Otherwise the tree is built from a | # extracted from the tarball. Otherwise the tree is built from a | ||||
# source tree. | # source tree. | ||||
# | |||||
# $1 - directory to store new tree in | |||||
extract_tree() | extract_tree() | ||||
{ | { | ||||
local files | local files | ||||
# If we have a tarball, extract that into the new directory. | # If we have a tarball, extract that into the new directory. | ||||
if [ -n "$tarball" ]; then | if [ -n "$tarball" ]; then | ||||
files= | files= | ||||
if [ -n "$preworld" ]; then | if [ -n "$preworld" ]; then | ||||
files="$PREWORLD_FILES" | files="$PREWORLD_FILES" | ||||
fi | fi | ||||
if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE $files) \ | if ! (mkdir -p $1 && tar xf $tarball -C $1 $files) \ | ||||
>&3 2>&1; then | >&3 2>&1; then | ||||
echo "Failed to extract new tree." | echo "Failed to extract new tree." | ||||
remove_tree $NEWTREE | remove_tree $1 | ||||
exit 1 | exit 1 | ||||
fi | fi | ||||
else | else | ||||
if ! build_tree $NEWTREE; then | if ! build_tree $1; then | ||||
echo "Failed to build new tree." | echo "Failed to build new tree." | ||||
remove_tree $NEWTREE | remove_tree $1 | ||||
exit 1 | exit 1 | ||||
fi | fi | ||||
fi | fi | ||||
} | } | ||||
# Forcefully remove a tree. Returns true (0) if the operation succeeds. | # Forcefully remove a tree. Returns true (0) if the operation succeeds. | ||||
# | # | ||||
# $1 - path to tree | # $1 - path to tree | ||||
▲ Show 20 Lines • Show All 1,088 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if [ $# -ne 0 ]; then | if [ $# -ne 0 ]; then | ||||
usage | usage | ||||
fi | fi | ||||
log "extract command: tarball=$tarball" | log "extract command: tarball=$tarball" | ||||
# Create a temporary directory to hold the tree | |||||
dir=`mktemp -d $WORKDIR/etcupdate-XXXXXXX` | |||||
if [ $? -ne 0 ]; then | |||||
echo "Unable to create temporary directory." | |||||
exit 1 | |||||
fi | |||||
extract_tree $dir | |||||
if [ -d $NEWTREE ]; then | if [ -d $NEWTREE ]; then | ||||
if ! remove_tree $NEWTREE; then | if ! remove_tree $NEWTREE; then | ||||
echo "Unable to remove current tree." | echo "Unable to remove current tree." | ||||
remove_tree $dir | |||||
exit 1 | exit 1 | ||||
fi | fi | ||||
fi | fi | ||||
extract_tree | if ! mv $dir $NEWTREE >&3 2>&1; then | ||||
echo "Unable to rename temp tree to current tree." | |||||
remove_tree $dir | |||||
exit 1 | |||||
fi | |||||
} | } | ||||
# Resolve conflicts left from an earlier merge. | # Resolve conflicts left from an earlier merge. | ||||
resolve_cmd() | resolve_cmd() | ||||
{ | { | ||||
local conflicts | local conflicts | ||||
if [ $# -ne 0 ]; then | if [ $# -ne 0 ]; then | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | status_cmd() | ||||
fi | fi | ||||
} | } | ||||
# Perform an actual merge. The new tree can either already exist (if | # Perform an actual merge. The new tree can either already exist (if | ||||
# rerunning a merge), be extracted from a tarball, or generated from a | # rerunning a merge), be extracted from a tarball, or generated from a | ||||
# source tree. | # source tree. | ||||
update_cmd() | update_cmd() | ||||
{ | { | ||||
local dir | local dir new old | ||||
if [ $# -ne 0 ]; then | if [ $# -ne 0 ]; then | ||||
usage | usage | ||||
fi | fi | ||||
log "update command: rerun=$rerun tarball=$tarball preworld=$preworld" | log "update command: rerun=$rerun tarball=$tarball preworld=$preworld" | ||||
if [ `id -u` -ne 0 ]; then | if [ `id -u` -ne 0 ]; then | ||||
Show All 12 Lines | if [ -e $CONFLICTS ]; then | ||||
find -d $CONFLICTS -type d -empty -delete >&3 2>&1 | find -d $CONFLICTS -type d -empty -delete >&3 2>&1 | ||||
rmdir $CONFLICTS >&3 2>&1 | rmdir $CONFLICTS >&3 2>&1 | ||||
fi | fi | ||||
if [ -d $CONFLICTS ]; then | if [ -d $CONFLICTS ]; then | ||||
echo "Conflicts remain from previous update, aborting." | echo "Conflicts remain from previous update, aborting." | ||||
exit 1 | exit 1 | ||||
fi | fi | ||||
# Save tree names to use for rotation later. | |||||
old=$OLDTREE | |||||
new=$NEWTREE | |||||
if [ -z "$rerun" ]; then | if [ -z "$rerun" ]; then | ||||
# For a dryrun that is not a rerun, do not rotate the existing | # Extract the new tree to a temporary directory. The | ||||
# stock tree. Instead, extract a tree to a temporary directory | # trees are only rotated after a successful update to | ||||
# and use that for the comparison. | # avoid races if an update command is interrupted | ||||
if [ -n "$dryrun" ]; then | # before it completes. | ||||
dir=`mktemp -d $WORKDIR/etcupdate-XXXXXXX` | dir=`mktemp -d $WORKDIR/etcupdate-XXXXXXX` | ||||
if [ $? -ne 0 ]; then | if [ $? -ne 0 ]; then | ||||
echo "Unable to create temporary directory." | echo "Unable to create temporary directory." | ||||
exit 1 | exit 1 | ||||
fi | fi | ||||
# A pre-world dryrun has already set OLDTREE to | # Populate the new tree. | ||||
# point to the current stock tree. | extract_tree $dir | ||||
# Compare the new tree against the previous tree. For | |||||
# the preworld case OLDTREE already points to the | |||||
# current stock tree. | |||||
if [ -z "$preworld" ]; then | if [ -z "$preworld" ]; then | ||||
OLDTREE=$NEWTREE | OLDTREE=$NEWTREE | ||||
fi | fi | ||||
NEWTREE=$dir | NEWTREE=$dir | ||||
# For a pre-world update, blow away any pre-existing | |||||
# NEWTREE. | |||||
elif [ -n "$preworld" ]; then | |||||
if ! remove_tree $NEWTREE; then | |||||
echo "Unable to remove pre-world tree." | |||||
exit 1 | |||||
fi | fi | ||||
# Rotate the existing stock tree to the old tree. | |||||
elif [ -d $NEWTREE ]; then | |||||
# First, delete the previous old tree if it exists. | |||||
if ! remove_tree $OLDTREE; then | |||||
echo "Unable to remove old tree." | |||||
exit 1 | |||||
fi | |||||
# Move the current stock tree. | |||||
if ! mv $NEWTREE $OLDTREE >&3 2>&1; then | |||||
echo "Unable to rename current stock tree." | |||||
exit 1 | |||||
fi | |||||
fi | |||||
if ! [ -d $OLDTREE ]; then | if ! [ -d $OLDTREE ]; then | ||||
cat <<EOF | cat <<EOF | ||||
No previous tree to compare against, a sane comparison is not possible. | No previous tree to compare against, a sane comparison is not possible. | ||||
EOF | EOF | ||||
log "No previous tree to compare against." | log "No previous tree to compare against." | ||||
if [ -n "$dir" ]; then | if [ -n "$dir" ]; then | ||||
rmdir $dir | if [ -n "$rerun" ]; then | ||||
panic "Should not have a temporary directory" | |||||
fi | fi | ||||
remove_tree $dir | |||||
fi | |||||
exit 1 | exit 1 | ||||
fi | fi | ||||
# Populate the new tree. | |||||
extract_tree | |||||
fi | |||||
# Build lists of nodes in the old and new trees. | # Build lists of nodes in the old and new trees. | ||||
(cd $OLDTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/old.files | (cd $OLDTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/old.files | ||||
(cd $NEWTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/new.files | (cd $NEWTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/new.files | ||||
# Split the files up into three groups using comm. | # Split the files up into three groups using comm. | ||||
comm -23 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/removed.files | comm -23 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/removed.files | ||||
comm -13 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/added.files | comm -13 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/added.files | ||||
comm -12 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/both.files | comm -12 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/both.files | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | EOF | ||||
# Run any special one-off commands after an update has completed. | # Run any special one-off commands after an update has completed. | ||||
post_update | post_update | ||||
if [ -s $WARNINGS ]; then | if [ -s $WARNINGS ]; then | ||||
echo "Warnings:" | echo "Warnings:" | ||||
cat $WARNINGS | cat $WARNINGS | ||||
fi | fi | ||||
if [ -n "$dir" ]; then | # Finally, rotate any needed trees. | ||||
if [ -z "$dryrun" -o -n "$rerun" ]; then | if [ "$new" != "$NEWTREE" ]; then | ||||
if [ -n "$rerun" ]; then | |||||
panic "Should not have a temporary directory" | panic "Should not have a temporary directory" | ||||
fi | fi | ||||
if [ -z "$dir" ]; then | |||||
panic "Should have a temporary directory" | |||||
fi | |||||
remove_tree $dir | # Rotate the old tree if needed | ||||
if [ "$old" != "$OLDTREE" ]; then | |||||
if [ -n "$preworld" ]; then | |||||
panic "Old tree should be unchanged" | |||||
fi | |||||
if ! remove_tree $old; then | |||||
echo "Unable to remove previous old tree." | |||||
exit 1 | |||||
fi | |||||
if ! mv $OLDTREE $old >&3 2>&1; then | |||||
echo "Unable to rename old tree." | |||||
exit 1 | |||||
fi | |||||
fi | |||||
# Rotate the new tree. Remove a previous pre-world | |||||
# tree if it exists. | |||||
if [ -d $new ]; then | |||||
if [ -z "$preworld" ]; then | |||||
panic "New tree should be rotated to old" | |||||
fi | |||||
if ! remove_tree $old; then | |||||
echo "Unable to remove previous pre-world tree." | |||||
exit 1 | |||||
fi | |||||
fi | |||||
if ! mv $NEWTREE $new >&3 2>&1; then | |||||
echo "Unable to rename current tree." | |||||
exit 1 | |||||
fi | |||||
fi | fi | ||||
} | } | ||||
# Determine which command we are executing. A command may be | # Determine which command we are executing. A command may be | ||||
# specified as the first word. If one is not specified then 'update' | # specified as the first word. If one is not specified then 'update' | ||||
# is assumed as the default command. | # is assumed as the default command. | ||||
command="update" | command="update" | ||||
if [ $# -gt 0 ]; then | if [ $# -gt 0 ]; then | ||||
▲ Show 20 Lines • Show All 223 Lines • Show Last 20 Lines |