X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=build%2Fredo_scripts%2Fredo-ifchange;fp=build%2Fredo_scripts%2Fredo-ifchange;h=0000000000000000000000000000000000000000;hb=a50806df8116a81729220bd79870639b18da9d8c;hp=532587a0c4d81b18fea609a9e3801dd2df76fe84;hpb=3a308dfb8b0ede5ab0a23d867cdf33394825538e;p=plomrogue diff --git a/build/redo_scripts/redo-ifchange b/build/redo_scripts/redo-ifchange deleted file mode 100755 index 532587a..0000000 --- a/build/redo_scripts/redo-ifchange +++ /dev/null @@ -1,321 +0,0 @@ -#!/bin/sh -# redo-ifchange – bourne shell implementation of DJB redo -# Copyright © 2014 Nils Dagsson Moskopp (erlehmann) - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. - -# Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu -# steigern. Gelegentlich packe ich sogar einen handfesten Buffer -# Overflow oder eine Format String Vulnerability zwischen die anderen -# Codezeilen und schreibe das auch nicht dran. - -# GNU vs BSD. -test=`command -v md5sum | wc -l` -if [ 1 -gt $test ] -then - alias md5sum='md5 -r' -fi -alias stat_cY='stat -c%Y' -test=`stat --version 2>&1 | grep GNU | wc -l` -if [ 1 -gt $test ] -then - alias stat_cY='stat -f%Y' -fi - -_add_ctime_md5sum() { - target=$1 - local base; _dirsplit "$target" - [ -d "$REDO_DIR/$dir" ] || LANG=C mkdir -p "$REDO_DIR/$dir" - LANG=C stat_cY "$target" >"$REDO_DIR/$target".ctime - LANG=C md5sum <"$target" >"$REDO_DIR/$target".md5sum -} - -_add_dependency() { - parent=$1 - dependency=$2 - # Do not record circular dependencies. - [ "$parent" = "$dependency" ] && exit 1 - local base; _dirsplit "$parent" - [ -d "$REDO_DIR/$dir" ] || LANG=C mkdir -p "$REDO_DIR/$dir" - ctime="$(LANG=C stat_cY "$dependency")" - md5sum="$(LANG=C md5sum < "$dependency")" - printf '%s\t%s\t%s\n' "$dependency" "$ctime" "$md5sum" >> \ - "$REDO_DIR"/"$parent".dependencies.tmp -} - -_add_dependency_ne() { - parent="$1" - dependency_ne="$2" - # Do not record circular dependencies. - [ "$parent" = "$dependency_ne" ] && exit 1 - # Do not record existing files as non-existence dependencies. - [ -e "$dependency_ne" ] && return - local base; _dirsplit "$parent" - [ -d "$REDO_DIR/$dir" ] || mkdir -p "$REDO_DIR/$dir" - printf '%s\n' "$dependency_ne" >> "$REDO_DIR/$parent".dependencies_ne.tmp -} - -_dependencies_ne_uptodate() { - target=$1 - # If no non-existence dependencies exist, they are by definition up to date. - if [ ! -s "$REDO_DIR/$target".dependencies_ne ]; then - _echo_debug_message "$target has no non-existence dependencies." - return 0 - fi - _echo_debug_message "$target non-existence dependency check:" - while read dependency_ne; do - _echo_debug_message "\t$dependency_ne should not exist." - # If a non-existence dependency exists, it is out of date. - # Dependencies, e.g. on default.do files may also be out of date. - # Naive implementation: Pretend target is not up to date and rebuild. - if [ -e "$dependency_ne" ]; then - _echo_debug_message "\t$dependency_ne does exist." - return 1 - fi - _echo_debug_message "\t$dependency_ne does not exist." - done < "$REDO_DIR/$target".dependencies_ne - _echo_debug_message "$target non-existence dependencies uptodate." - return 0 -} - -_target_uptodate() { - target=$1 - # If a target is a top-level target, it is not up to date. - if [ -z "$REDO_TARGET" ]; then - return 1 - fi - # If a target does not exist, it is not up to date. - if [ ! -e "$target" ]; then - _echo_debug_message "$target does not exist." - return 1 - fi - # If an .always file exists, the target is out of date. - if [ -e "$REDO_DIR/$target".always ]; then - _echo_debug_message "$target is always out of date." - return 1 - fi - # If .stamp file exists, the target is out of date. - if [ -e "$REDO_DIR/$target".stamp ]; then - _echo_debug_message "$target is out of date due to redo-stamp." - return 1 - fi - if [ -e "$REDO_DIR/$target".ctime ]; then - read ctime_stored <"$REDO_DIR/$target".ctime - ctime_actual="$(LANG=C stat_cY "$target")" - _echo_debug_message "$target stored ctime $ctime_stored" - _echo_debug_message "$target actual ctime $ctime_actual" - if [ "$ctime_stored" = "$ctime_actual" ]; then - _echo_debug_message "$target up to date." - return 0 - elif [ -e "$REDO_DIR/$target".md5sum ]; then - read md5sum_stored <"$REDO_DIR/$target".md5sum - md5sum_actual="$(LANG=C md5sum < "$target")" - _echo_debug_message "$target stored md5sum $md5sum_stored" - _echo_debug_message "$target actual md5sum $md5sum_actual" - if [ "$md5sum_stored" = "$md5sum_actual" ]; then - # If stored md5sum of target matches actual md5sum, but stored - # ctime does not, redo needs to update stored ctime of target. - LANG=C stat_cY "$target" >"$REDO_DIR/$target".md5sum - return 0 - fi - _echo_debug_message "$target out of date." - return 1 - fi - fi -} - -_dependencies_uptodate() { - target=$1 - # If no dependencies exist, they are by definition up to date. - if [ ! -e "$REDO_DIR/$target".dependencies ]; then - _echo_debug_message "$target has no dependencies." - return 0 - fi - if [ "$REDO_SHUFFLE" = "1" ]; then - shuf "$REDO_DIR/$target".dependencies -o "$REDO_DIR/$target".dependencies \ - 2>&- - fi - _echo_debug_message "$target dependency check:" - # If any dependency does not exist, the target is out of date. - LANG=C stat_cY $(LANG=C cut -f1 "$REDO_DIR/$target".dependencies) > \ - "$REDO_DIR/$target".dependencies.ctimes 2>&- || return 1 - exec 3< "$REDO_DIR/$target".dependencies.ctimes - exec 4< "$REDO_DIR/$target".dependencies - while read ctime_actual <&3 && read dependency ctime_stored md5sum_stored <&4; do - # If a .always file exists, the dependency is out of date. - if [ -e "$REDO_DIR/$dependency".always ]; then - _echo_debug_message "\t$dependency is always out of date." - return 1 - fi - # If a .stamp file exists, the dependency is out of date. - if [ -e "$REDO_DIR/$dependency".stamp ]; then - _echo_debug_message "\t$dependency is always out of date." - return 1 - fi - # If a dependency of a dependency is out of date, the dependency is out of date. - if ( ! _dependencies_uptodate "$dependency" ); then - return 1 - fi - # If the ctime of a dependency did not change, the dependency is up to date. - _echo_debug_message "\t$dependency stored ctime $ctime_stored" - _echo_debug_message "\t$dependency actual ctime $ctime_actual" - if [ "$ctime_stored" = "$ctime_actual" ]; then - _echo_debug_message "\t$dependency up to date." - continue - fi - # If the md5sum of a dependency did not change, the dependency is up to date. - md5sum_actual="$(LANG=C md5sum < "$dependency")" - _echo_debug_message "\t$dependency stored md5sum $md5sum_stored" - _echo_debug_message "\t$dependency actual md5sum $md5sum_actual" - if [ "$md5sum_stored" = "$md5sum_actual" ]; then - _echo_debug_message "\t$dependency up to date." - continue - else - # if both ctime and md5sum did change, the dependency is out of date. - _echo_debug_message "\t$dependency out of date." - return 1 - fi - done - exec 4>&- - exec 3>&- - _echo_debug_message "$target dependencies up to date." - # If a non-existence dependency is out of date, the target is out of date. - if ( ! _dependencies_ne_uptodate "$target" ); then - return 1 - fi - return 0 -} - -_dirsplit() { - base=${1##*/} - dir=${1%"$base"} -} - -_do() { - local dir="$1" target="$2" tmp="$3" - target_abspath="$PWD/$target" - target_relpath="${target_abspath##$REDO_BASE/}" - # If target is not up to date or its dependencies are not up to date, build it. - if ( - ! _target_uptodate "$target_abspath" || \ - ! _dependencies_uptodate "$target_abspath" - ); then - dofile="$target".do - base="$target" - ext= - [ -e "$target.do" ] || _find_dofile "$target" - if [ ! -e "$dofile" ]; then - # If .do file does not exist and target exists, it is a source file. - if [ -e "$target_abspath" ]; then - _add_dependency "$REDO_TARGET" "$target_abspath" - _add_ctime_md5sum "$target_abspath" - return 0 - # If .do file does not exist and target does not exist, stop. - else - echo "redo: $target: no .do file" >&2 - exit 1 - fi - fi - printf '%sredo %s%s%s%s%s\n' \ - "$green" "$REDO_DEPTH" "$bold" "$target_relpath" "$plain" >&2 - ( _run_dofile "$target" "${base##*/}" "$tmp.tmp" ) - rv="$?" - # Add non existing .do file to non-existence dependencies so - # target is built when .do file in question is created. - [ -e "$target.do" ] || _add_dependency_ne "$target_abspath" "$PWD/$target.do" - # Add .do file to dependencies so target is built when .do file changes. - _add_dependency "$target_abspath" "$PWD/$dofile" - if [ $rv != 0 ]; then - rm -f "$tmp.tmp" "$tmp.tmp2" - # Exit code 123 conveys that target was considered uptodate at runtime. - if [ $rv != 123 ]; then - printf "%sredo: %s%s: got exit code %s.%s\n" \ - "$red" "$REDO_DEPTH" "$target" "$rv" "$plain" >&2 - exit 1 - fi - fi - mv "$tmp.tmp" "$target" 2>&- || - ! test -s "$tmp.tmp2" || - mv "$tmp.tmp2" "$target" 2>&- - rm -f "$tmp.tmp2" - # After build is finished, update dependencies. - touch "$REDO_DIR/$target_abspath".dependencies.tmp - touch "$REDO_DIR/$target_abspath".dependencies_ne.tmp - mv "$REDO_DIR/$target_abspath".dependencies.tmp \ - "$REDO_DIR/$target_abspath".dependencies >&2 - mv "$REDO_DIR/$target_abspath".dependencies_ne.tmp \ - "$REDO_DIR/$target_abspath".dependencies_ne >&2 - fi - # Some do files (like all.do) do not usually generate output. - if [ -e "$target_abspath" ]; then - # Record dependency on parent target. - _add_dependency "$REDO_TARGET" "$target_abspath" - _add_ctime_md5sum "$target_abspath" - fi -} - -_echo_debug_message() { - [ "$REDO_DEBUG" = "1" ] && echo "$@" >&2 -} - -_find_dofile() { - local prefix= - while :; do - _find_dofile_pwd "$1" - [ -e "$dofile" ] && break - [ "$PWD" = "/" ] && break - target=${PWD##*/}/"$target" - tmp=${PWD##*/}/"$tmp" - prefix=${PWD##*/}/"$prefix" - cd .. - done - base="$prefix""$base" -} - -_find_dofile_pwd() { - dofile=default."$1".do - while :; do - dofile=default.${dofile#default.*.} - [ -e "$dofile" -o "$dofile" = default.do ] && break - done - ext=${dofile#default} - ext=${ext%.do} - base=${1%$ext} -} - -_run_dofile() { - export REDO_DEPTH="$REDO_DEPTH " - export REDO_TARGET="$PWD"/"$target" - local line1 - set -e - read line1 <"$PWD/$dofile" || true - cmd=${line1#"#!"} - # If the first line of a do file does not have a hashbang (#!), use /bin/sh. - if [ "$cmd" = "$line1" ] || [ "$cmd" = "/bin/sh" ]; then - if [ "$REDO_XTRACE" = "1" ]; then - cmd="/bin/sh -ex" - else - cmd="/bin/sh -e" - fi - fi - $cmd "$PWD/$dofile" "$@" >"$tmp.tmp2" -} - -set +e -if [ -n "$1" ]; then - targets="$@" - [ "$REDO_SHUFFLE" = "1" ] && targets=$(LANG=C shuf -e "$@") - for target in $targets; do - # If relative path to target is given, convert to absolute absolute path. - case "$target" in - /*) ;; - *) target="$PWD"/"$target" >&2;; - esac - _dirsplit "$target" - ( cd "$dir" && _do "$dir" "$base" "$base" ) - [ "$?" = 0 ] || exit 1 - done -fi