lib/update.updates
author Tero Marttila <terom@paivola.fi>
Thu, 19 Dec 2013 20:47:43 +0200
branchdns-new
changeset 92 639a5093039b
parent 87 cb4607af8663
permissions -rw-r--r--
lib/update.operations: update_domain_forward/reverse: use --add-origin, unless hosts name does not include a .
#!/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
            warn "$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
}

## 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"
}

## Read include paths from file
function read_zone_includes {
    cmd sed -n -E 's/^\$INCLUDE\s+"(.+)"/\1/p' "$@"
}

## (cached) include paths for zone file
function zone_includes {
    local cache="$1"
    local src="$2"
    local prefix="${3:-}"

    if [ ! -e "$cache" -o "$cache" -ot "$src" ]; then
        read_zone_includes "$src" > "$cache"
    fi

    while read include; do
        echo -n "$prefix$include "
    done < "$cache"
}

## Search for prefix-matching includes in zone file
function zone_includes_grep {
    local cache="$1"
    local src="$2"
    local prefix="$3"
    
    for include in $(zone_includes $cache $src); do
        if [ "${include#$prefix}" != "$include" ]; then
            echo -n " ${include#$prefix}"
        fi
    done
}