lib/update.updates
author Tero Marttila <terom@paivola.fi>
Tue, 17 Dec 2013 01:17:49 +0200
branchdns-new
changeset 84 77df429f63a3
parent 82 26a307558602
child 85 4ad9c9b7cd0e
permissions -rw-r--r--
update: full host forward/dhcp/reverse zones
#!/bin/bash
# vim: set ft=sh :
#
# Dependency-based updates + utils

## Compare the given output file with all given source files:
#
#   check_update $out ${deps[@]} && do_update $out ... || ...
#
# Returns true if the output file needs to be updated.
function check_update {
    # target
    local out=$1; shift

    debug "$out"

    # need update?
    local update=

    if [ ${#@} == 0 ]; then
        debug "  update: unknown deps"
        update=y

    elif [ ! -e $out ]; then
        debug "  update: dest missing"
        update=y
        
    elif [ $UPDATE_FORCE ]; then
        debug "  update: forced"
        update=y
    fi

    # check deps
    for dep in "$@"; do
        # don't bother checking if already figured out
        [ $update ] && continue

        # check
        if [ ! -e "$dep" ]; then
            fail "$out: Missing source: $dep"

        elif [ $out -ot "$dep" ]; then
            debug "  update: $dep"
            update=y
        else
            debug "  check: $dep"
        fi
    done

    [ ! $update ] && debug "  up-to-date"

    # return
    [ $update ]
}

## Generate updated output file from given command's stdout:
#
#   do_update $out $BIN/cmd --args
#
# Writes output to a temporary .new file, optionally shows a diff of changes, and commits
# the new version to $out (unless noop'd).
function do_update {
    local out=$1; shift
    local tmp=$out.new

    debug "$out"
    cmd "$@" > $tmp

    # compare
    if [ -e $out ] && [ $UPDATE_DIFF ]; then
        debug "  changes:"

        # terse
        indent "        " diff --unified=1 $out $tmp || true
    fi
    
    # deploy
    if [ $UPDATE_NOOP ]; then
        # cleanup
        debug "  no-op"

        cmd rm $tmp
    else
        # commit
        debug "  deploy"

        cmd mv $tmp $out
    fi
}

## Look for a link target:
#
#   find_link   $lnk    $tgt...
#
# Outputs the first given target to exist, skipping any that are the same as the given $lnk.
# If no $tgt matches, outputs the last one, or '-'.
function choose_link {
    local lnk=$1; shift
    local tgt=-

    for tgt in "$@"; do
        [ $tgt != $out ] && [ -e $tgt ] && break
    done
    
    echo $tgt
}


## Compare symlink to target:
#
#   check_link $lnk $tgt && do_link $lnk $tgt || ...
#
# Tests if the symlink exists, and the target matches.
# Fails if the target does not exist.
function check_link {
    local lnk=$1
    local tgt=$2

    [ ! -e $tgt ] && fail "$tgt: target does not exist"
    
    [ ! -e $lnk ] || [ $(readlink $lnk) != $tgt ]
}

## Update symlink to point to target:
#
#   do_link $lnk $tgt
#
function do_link {
    local lnk=$1
    local tgt=$2

    cmd ln -sf $tgt $lnk
}