terom@583: #!/bin/bash terom@575: # vim: set ft=sh : terom@575: # terom@575: # Dependency-based updates + utils terom@575: terom@575: ## Compare the given output file with all given source files: terom@575: # terom@575: # check_update $out ${deps[@]} && do_update $out ... || ... terom@575: # terom@575: # Returns true if the output file needs to be updated. terom@575: function check_update { terom@575: # target terom@608: local out="$1"; shift terom@575: terom@575: debug "$out" terom@575: terom@575: # need update? terom@575: local update= terom@575: terom@575: if [ ${#@} == 0 ]; then terom@575: debug " update: unknown deps" terom@575: update=y terom@575: terom@608: elif [ ! -e "$out" ]; then terom@575: debug " update: dest missing" terom@575: update=y terom@575: terom@575: elif [ $UPDATE_FORCE ]; then terom@575: debug " update: forced" terom@575: update=y terom@575: fi terom@575: terom@575: # check deps terom@575: for dep in "$@"; do terom@575: # don't bother checking if already figured out terom@575: [ $update ] && continue terom@575: terom@575: # check terom@607: if [ ! -e "$dep" ]; then terom@608: warn "$out: Missing source: $dep" terom@575: terom@608: elif [ "$out" -ot "$dep" ]; then terom@575: debug " update: $dep" terom@575: update=y terom@575: else terom@575: debug " check: $dep" terom@575: fi terom@575: done terom@575: terom@575: [ ! $update ] && debug " up-to-date" terom@575: terom@575: # return terom@575: [ $update ] terom@575: } terom@575: terom@575: ## Generate updated output file from given command's stdout: terom@575: # terom@575: # do_update $out $BIN/cmd --args terom@575: # terom@575: # Writes output to a temporary .new file, optionally shows a diff of changes, and commits terom@575: # the new version to $out (unless noop'd). terom@575: function do_update { terom@608: local out="$1"; shift terom@608: local tmp="$out.new" terom@575: terom@575: debug "$out" terom@608: cmd "$@" > "$tmp" terom@575: terom@575: # compare terom@608: if [ -e "$out" ] && [ $UPDATE_DIFF ]; then terom@575: debug " changes:" terom@575: terom@575: # terse terom@608: indent " " diff --unified=1 "$out" "$tmp" || true terom@575: fi terom@575: terom@575: # deploy terom@575: if [ $UPDATE_NOOP ]; then terom@575: # cleanup terom@575: debug " no-op" terom@575: terom@608: cmd rm "$tmp" terom@575: else terom@575: # commit terom@575: debug " deploy" terom@575: terom@608: cmd mv "$tmp" "$out" terom@575: fi terom@575: } terom@575: terom@575: ## Compare symlink to target: terom@575: # terom@575: # check_link $lnk $tgt && do_link $lnk $tgt || ... terom@575: # terom@575: # Tests if the symlink exists, and the target matches. terom@575: # Fails if the target does not exist. terom@575: function check_link { terom@608: local lnk="$1" terom@608: local tgt="$2" terom@575: terom@608: [ ! -e "$tgt" ] && fail "$tgt: target does not exist" terom@575: terom@608: [ ! -e "$lnk" ] || [ $(readlink "$lnk") != "$tgt" ] terom@575: } terom@575: terom@575: ## Update symlink to point to target: terom@575: # terom@575: # do_link $lnk $tgt terom@575: # terom@575: function do_link { terom@608: local lnk="$1" terom@608: local tgt="$2" terom@575: terom@608: cmd ln -sf "$tgt" "$lnk" terom@575: } terom@575: terom@608: ## Read include paths from file terom@608: function read_zone_includes { terom@608: cmd sed -n -E 's/^\$INCLUDE\s+"(.+)"/\1/p' "$@" terom@608: } terom@608: terom@608: ## (cached) include paths for zone file terom@608: function zone_includes { terom@608: local cache="$1" terom@608: local src="$2" terom@610: local prefix="${3:-}" terom@608: terom@608: if [ ! -e "$cache" -o "$cache" -ot "$src" ]; then terom@608: read_zone_includes "$src" > "$cache" terom@608: fi terom@608: terom@608: while read include; do terom@610: echo -n "$prefix$include " terom@608: done < "$cache" terom@608: } terom@610: terom@610: ## Search for prefix-matching includes in zone file terom@610: function zone_includes_grep { terom@610: local cache="$1" terom@610: local src="$2" terom@610: local prefix="$3" terom@610: terom@610: for include in $(zone_includes $cache $src); do terom@610: if [ "${include#$prefix}" != "$include" ]; then terom@610: echo -n " ${include#$prefix}" terom@610: fi terom@610: done terom@610: }