diff options
-rw-r--r-- | .github/workflows/main.yml | 2 | ||||
-rw-r--r-- | .gitignore | 11 | ||||
-rw-r--r-- | Makefile | 69 | ||||
-rw-r--r-- | README | 15 | ||||
-rw-r--r-- | bin/all.do | 2 | ||||
-rw-r--r-- | bin/clean.do | 2 | ||||
-rw-r--r-- | bin/test.do | 11 | ||||
-rw-r--r-- | clean.do | 5 | ||||
-rw-r--r-- | config.mk | 25 | ||||
-rw-r--r-- | config.rc | 84 | ||||
-rw-r--r-- | default.do | 50 | ||||
-rw-r--r-- | docs/default.do | 27 | ||||
-rw-r--r-- | install.do | 16 | ||||
-rwxr-xr-x | minimal/do | 446 | ||||
-rw-r--r-- | src/Makefile | 4 | ||||
-rw-r--r-- | src/cpt-lib.in (renamed from src/cpt-lib) | 2 | ||||
-rw-r--r-- | src/test.do | 5 | ||||
-rw-r--r-- | uninstall.do | 9 |
18 files changed, 676 insertions, 109 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 836d891..0e61433 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,4 +10,4 @@ jobs: steps: - uses: actions/checkout@v1 - name: Run tests. - run: make test + run: ./minimal/do test @@ -1,7 +1,7 @@ ### Binaries/Objects ### +cpt-lib cpt-stat cpt-readlink -getopt *.o ### Emacs ### @@ -16,5 +16,14 @@ getopt [._]ss[a-gi-z] [._]sw[a-p] +### Redo files +/.redo +/.do_built +/.do_built.dir +*.tmp +*.did +.dep* +.target* + ### Texinfo ### *.info diff --git a/Makefile b/Makefile deleted file mode 100644 index 4e0880d..0000000 --- a/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# See LICENSE for copyright information -include config.mk - -SRC = bin/cpt-readlink.c bin/cpt-stat.c -OBJ = ${SRC:.c=.o} -BIN = ${SRC:.c=} - -.SUFFIXES: -.SUFFIXES: .o .c .org .texi .info - -.org.texi: - ${EMACS} $< --batch -f org-texinfo-export-to-texinfo - -.texi.info: - ${MAKEINFO} $< -o $@ - -all: ${BIN} - -.c: - ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $< ${LIBS} - -clean: - rm -f ${BIN} ${OBJ} - -test: ${BIN} - bin/cpt-stat bin - bin/cpt-stat Makefile - bin/cpt-readlink /bin/sh - ${MAKE} -C src test - -install-bin: ${BIN} - for bin in ${BIN}; do \ - install -Dm755 $${bin} ${DESTDIR}${BINDIR}/$${bin##*/}; done - -install-src: - for bin in src/*; do \ - install -Dm755 $${bin} ${DESTDIR}${BINDIR}/$${bin##*/}; done - -install-contrib: - for bin in contrib/*; do \ - install -Dm755 $${bin} ${DESTDIR}${BINDIR}/$${bin##*/}; done - -install-contrib-static: - mkdir -p ${DESTDIR}${BINDIR} - for bin in contrib/*; do \ - sed '/\. cpt-lib/r src/cpt-lib' $${bin} | \ - sed '/\. cpt-lib/d' > ${DESTDIR}${BINDIR}/$${bin##*/}; \ - chmod 755 ${DESTDIR}${BINDIR}/$${bin##*/}; done - -install-src-static: - mkdir -p ${DESTDIR}${BINDIR} - for bin in src/*; do \ - sed '/\. cpt-lib/r src/cpt-lib' $${bin} | \ - sed '/\. cpt-lib/d' > ${DESTDIR}${BINDIR}/$${bin##*/}; \ - chmod 755 ${DESTDIR}${BINDIR}/$${bin##*/}; done - -install-doc: - for man in man/*.1; do install -Dm644 $${man} ${DESTDIR}${MAN1}/$${man##*/}; done - -install: install-bin install-src install-contrib install-doc -install-static: install-bin install-src-static install-contrib-static install-doc - -uninstall: - for bin in ${BIN} src/* contrib/*; do \ - rm -f ${DESTDIR}${BINDIR}/$${bin##*/}; done - for man in man/*; do rm -f ${DESTDIR}${MAN1}/$${man##*/}; done - - -.PHONY: all install-bin install-src install-contrib install-doc install-src-static install-contrib-static install uninstall test clean @@ -19,25 +19,24 @@ Dependencies To build and use cpt, you need the following software. -- C compiler [make] +MAKE DEPENDS +- C compiler +- redo (the repository contains minimal/do) + +RUNTIME DEPENDS - rsync - curl -- getopt [provided by cpt if not available] - POSIX base utilities [coreutils, busybox, sbase, etc.] - tar [GNU tar, busybox, toybox, libarchive, etc.] -Build configuration can be done from the 'config.mk' file. If you have getopt -on your system, add SYSTEM_GETOPT=1 option to your 'config.mk'. - Directory Structure -------------------------------------------------------------------------------- - / -- cpt, README, Makefile, LICENSE, CHANGELOG + / -- README, LICENSE, CHANGELOG bin/ -- for C programs. contrib/ -- for Shell scripts that wrap around cpt. - doc/ -- for documentation. - getopt-ul -- for cpt provided util-linux standalone getopt(1). + docs/ -- for documentation. man/ -- for manual pages. src/ -- for the tools that make up the package manager. diff --git a/bin/all.do b/bin/all.do new file mode 100644 index 0000000..aceda74 --- /dev/null +++ b/bin/all.do @@ -0,0 +1,2 @@ +. ../config.rc +redo-ifchange cpt-readlink cpt-stat diff --git a/bin/clean.do b/bin/clean.do new file mode 100644 index 0000000..6234248 --- /dev/null +++ b/bin/clean.do @@ -0,0 +1,2 @@ +. ../config.rc +rm -f -- ./*.o cpt-readlink cpt-stat .dep.* diff --git a/bin/test.do b/bin/test.do new file mode 100644 index 0000000..4794751 --- /dev/null +++ b/bin/test.do @@ -0,0 +1,11 @@ +. ../config.rc +redo all +exec >&2 + +./cpt-readlink . +./cpt-readlink .. +./cpt-readlink /bin +./cpt-stat /bin +./cpt-stat cpt-readlink.o + +PHONY diff --git a/clean.do b/clean.do new file mode 100644 index 0000000..b30f907 --- /dev/null +++ b/clean.do @@ -0,0 +1,5 @@ +. ./config.rc +redo bin/clean src/clean +redo_clean +rm -f "cpt-$VERSION.tar.xz" +find docs -name '*.info' -exec rm -f -- {} + diff --git a/config.mk b/config.mk deleted file mode 100644 index ba76118..0000000 --- a/config.mk +++ /dev/null @@ -1,25 +0,0 @@ -# See LICENSE for copyright information -VERSION = 5.1.1 - -# Paths -PREFIX = /usr/local -BINDIR = ${PREFIX}/bin -SHAREDIR = ${PREFIX}/share -DOCDIR = ${SHAREDIR}/doc -CPTDOC = ${DOCDIR}/cpt -MANPREFIX = ${SHAREDIR}/man -MAN1 = ${MANPREFIX}/man1 - -# Flags -CFLAGS = -std=c99 -Wpedantic -Wall -Os -CFLAGS += -D_XOPEN_SOURCE=700 -LDFLAGS = -s -static -LIBS = -lc - -# C compiler and linker -CC = cc -LD = ${CC} - -# Documentation tools -EMACS = emacs -MAKEINFO = makeinfo diff --git a/config.rc b/config.rc new file mode 100644 index 0000000..2f0733b --- /dev/null +++ b/config.rc @@ -0,0 +1,84 @@ +# -*- mode: redo -*- +# See LICENSE for copyright information + +setv() { + # Set variables if unset. Works similar to the Makefile syntax. + [ "$3" ] || { + printf '%s\n' "Faulty variable syntax" >&2 + exit 1 + } + var=$1; sym=$2; shift 2 + case "$sym" in + \?=|=) eval "[ \"\$$var\" ]" || export "$var=$*" ;; + +=) eval "export \"$var=\$$var $*\"" + esac +} + +setv VERSION = 5.1.1 + +# Paths +setv PREFIX = /usr/local +setv BINDIR = "${PREFIX}/bin" +setv SHAREDIR = "${PREFIX}/share" +setv DOCDIR = "${SHAREDIR}/doc" +setv CPTDOC = "${DOCDIR}/cpt" +setv MANPREFIX = "${SHAREDIR}/man" +setv MAN1 = "${MANPREFIX}/man1" + +# Flags +setv CFLAGS = -std=c99 -Wpedantic -Wall -Os +setv CFLAGS += -D_XOPEN_SOURCE=700 +setv LDFLAGS = -s -static +setv LIBS = -lc + +setv CC = cc +setv LD = "${CC}" + +# Documentation tools +setv EMACS = emacs +setv MAKEINFO = makeinfo + +# Helper functions +target=$1 basename=$2 dest=$3 + +redo_clean() { + # Clean function for various redo implementations + [ -r .do_built ] && { + while read -r file; do + [ -d "$file" ] || rm -f "$file" + done < .do_built + } + find . -type f \( -name '*.tmp' -o -name '*.did' -o -name '.dep*' -o -name '.target*' \) \ + -exec rm -f -- {} + + [ "$DO_BUILT" ] || find . -name '.do_built*' -exec rm -rf -- {} + + [ "$REDO_BASE" ] || rm -rf -- .redo +} + +targcheck() { + # Usage: targcheck [target...] + # + # Check if current target is one of the given arguments of this function. + # Returns 0 if target is one of the arguments, returns 1 if not. + case " $* " in *" $target "*) return 0; esac; return 1 +} + +PHONY() { + # Usage: PHONY [[target...]] + # + # Function that resembles the .PHONY: target on the classic 'make' system. + # You can either use it without an argument on a single target, or specify + # multiple targets. + if [ -z "$1" ] || targcheck "$@"; then + # shellcheck disable=2064 + trap "rm -f $dest" EXIT INT + fi +} + +getbin() { + # Function to get all executables + find src contrib bin -name 'cpt-*' ! -name '*.in' ! -name '*.[coh]' +} + + +# Phony targets +PHONY all dist clean install uninstall test diff --git a/default.do b/default.do new file mode 100644 index 0000000..c16f5f8 --- /dev/null +++ b/default.do @@ -0,0 +1,50 @@ +. ./config.rc + +# Extensionless name of file +fn="${1%.*}" + +case "$1" in + all) redo-ifchange src/cpt-lib bin/all docs/all ;; + dist) + redo clean + redo "cpt-$VERSION.tar.xz" + ;; + src/cpt-lib) + redo-ifchange "$1.in" + sed "s|@VERSION@|$VERSION|g" < "$1.in" > "$3" + ;; + bin/cpt-readlink|bin/cpt-stat) + redo-ifchange "$1.o" + "$CC" -o "$3" $LDFLAGS "$1.o" $LIBS + ;; + *.o) + [ -f "${1%.o}.c" ] || exit 99 + redo-ifchange "$fn.c" + "$CC" -c -o "$3" $CFLAGS "$fn.c" + ;; + "cpt-$VERSION.tar.xz") + redo docs/cpt.info + rm -rf -- "cpt-$VERSION" + mkdir -p "cpt-$VERSION" + { git ls-tree -r HEAD --name-only && echo docs/cpt.info ;} | + while read -r file; do + [ "${file##*/*}" ] || + mkdir -p "cpt-$VERSION/${file%/*}" + cp "$file" "cpt-$VERSION/$file" + done + tar cf "cpt-$VERSION.tar" "cpt-$VERSION" + xz -z "cpt-$VERSION.tar" + rm -rf -- "cpt-$VERSION" + mv "$1" "$3" + ;; + test) + redo src/test bin/test + ;; + src/clean) + rm -f src/cpt-lib + PHONY + ;; + *) + echo "Unknown target $1" + exit 99 +esac diff --git a/docs/default.do b/docs/default.do new file mode 100644 index 0000000..a66ed9b --- /dev/null +++ b/docs/default.do @@ -0,0 +1,27 @@ +. ../config.rc + +# Extensionless name of file +fn="${1%.*}" + +case "$1" in + all) redo info ;; + allclean) redo ../clean; rm -f cpt.texi ;; + info) redo-ifchange cpt.info cpt.texi cpt.org ;; + *.info) + redo-ifchange "$fn.texi" + $MAKEINFO "$fn.texi" -o "$3" + ;; + *.texi) + [ -f "$fn.org" ] || exit 0 + redo-ifchange "$fn.org" + cp "$fn.org" "$3.org" + $EMACS "$3.org" --batch -f org-texinfo-export-to-texinfo + rm -f "$3.org" + mv "$3.texi" "$3" + ;; + *) + echo "Unknown target $1" + exit 99 +esac + +PHONY all info html diff --git a/install.do b/install.do new file mode 100644 index 0000000..cc11bd4 --- /dev/null +++ b/install.do @@ -0,0 +1,16 @@ +. ./config.rc +redo all + +# Install executables. +mkdir -p "${DESTDIR}${BINDIR}" +getbin | while read -r file; do + cp "$file" "${DESTDIR}${BINDIR}/${file##*/}" + chmod 755 "${DESTDIR}${BINDIR}/${file##*/}" +done + +# Install manual pages. +mkdir -p "${DESTDIR}${MAN1}" +for man in man/*.1; do + cp "$man" "${DESTDIR}${MAN1}/${man##*/}" + chmod 644 "${DESTDIR}${MAN1}/${man##*/}" +done diff --git a/minimal/do b/minimal/do new file mode 100755 index 0000000..f38a2a7 --- /dev/null +++ b/minimal/do @@ -0,0 +1,446 @@ +#!/bin/sh +# +# A minimal alternative to djb redo that doesn't support incremental builds. +# For the full version, visit http://github.com/apenwarr/redo +# +# The author disclaims copyright to this source file and hereby places it in +# the public domain. (2010 12 14; updated 2019 02 24) +# +USAGE=" +usage: do [-d] [-x] [-v] [-c] <targets...> + -d print extra debug messages (mostly about dependency checks) + -v run .do files with 'set -v' + -x run .do files with 'set -x' + -c clean up all old targets before starting + + Note: do is an implementation of redo that does *not* check dependencies. + It will never rebuild a target it has already built, unless you use -c. +" + +# CDPATH apparently causes unexpected 'cd' output on some platforms. +unset CDPATH + +# By default, no output coloring. +green="" +bold="" +plain="" + +if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then + green="$(printf '\033[32m')" + bold="$(printf '\033[1m')" + plain="$(printf '\033[m')" +fi + +# The 'seq' command is not available on all platforms. +_seq() { + local x=0 max="$1" + while [ "$x" -lt "$max" ]; do + x=$((x + 1)) + echo "$x" + done +} + +# Split $1 into a dir part ($_dirsplit_dir) and base filename ($_dirsplit_base) +_dirsplit() { + _dirsplit_base=${1##*/} + _dirsplit_dir=${1%$_dirsplit_base} +} + +# Like /usr/bin/dirname, but avoids a fork and uses _dirsplit semantics. +qdirname() ( + _dirsplit "$1" + dir=${_dirsplit_dir%/} + echo "${dir:-.}" +) + +_dirsplit "$0" +REDO=$(cd "$(pwd -P)" && + cd "${_dirsplit_dir:-.}" && + echo "$PWD/$_dirsplit_base") +export REDO +_cmd=$_dirsplit_base + +DO_TOP= +if [ -z "$DO_BUILT" ]; then + export _do_opt_debug= + export _do_opt_exec= + export _do_opt_verbose= + export _do_opt_clean= +fi +while getopts 'dxvcj:h?' _opt; do + case $_opt in + d) _do_opt_debug=1 ;; + x) _do_opt_exec=x ;; + v) _do_opt_verbose=v ;; + c) _do_opt_clean=1 ;; + j) ;; # silently ignore, for compat with real redo + \?|h|*) printf "%s" "$USAGE" >&2 + exit 99 + ;; + esac +done +shift "$((OPTIND - 1))" +_debug() { + [ -z "$_do_opt_debug" ] || echo "$@" >&2 +} + +if [ -z "$DO_BUILT" -a "$_cmd" != "redo-whichdo" ]; then + DO_TOP=1 + if [ "$#" -eq 0 ] && [ "$_cmd" = "do" -o "$_cmd" = "redo" ]; then + set all # only toplevel redo has a default target + fi + export DO_STARTDIR="$(pwd -P)" + # If starting /bin/pwd != $PWD, this will fix it. + # That can happen when $PWD contains symlinks that the shell is + # trying helpfully (but unsuccessfully) to hide from the user. + cd "$DO_STARTDIR" || exit 99 + export DO_BUILT="$PWD/.do_built" + if [ -z "$_do_opt_clean" -a -e "$DO_BUILT" ]; then + echo "do: Incremental mode. Use -c for clean rebuild." >&2 + fi + : >>"$DO_BUILT" + sort -u "$DO_BUILT" >"$DO_BUILT.new" + while read f; do + [ -n "$_do_opt_clean" ] && printf "%s\0%s.did\0" "$f" "$f" + printf "%s.did.tmp\0" "$f" + done <"$DO_BUILT.new" | + xargs -0 rm -f 2>/dev/null + mv "$DO_BUILT.new" "$DO_BUILT" + export DO_PATH="$DO_BUILT.dir" + export PATH="$DO_PATH:$PATH" + rm -rf "$DO_PATH" + mkdir "$DO_PATH" + for d in redo redo-ifchange redo-whichdo; do + ln -s "$REDO" "$DO_PATH/$d" + done + for d in redo-ifcreate redo-stamp redo-always redo-ood \ + redo-targets redo-sources; do + echo "#!/bin/sh" >"$DO_PATH/$d" + chmod a+rx "$DO_PATH/$d" + done +fi + + +# Chop the "file" part off a /path/to/file pathname. +# Note that if the filename already ends in a /, we just remove the slash. +_updir() +{ + local v="${1%/*}" + [ "$v" != "$1" ] && echo "$v" + # else "empty" which means we went past the root +} + + +# Returns true if $1 starts with $2. +_startswith() +{ + [ "${1#"$2"}" != "$1" ] +} + + +# Returns true if $1 ends with $2. +_endswith() +{ + [ "${1%"$2"}" != "$1" ] +} + + +# Prints $1 if it's absolute, or $2/$1 if $1 is not absolute. +_abspath() +{ + local here="$2" there="$1" + if _startswith "$1" "/"; then + echo "$1" + else + echo "$2/$1" + fi +} + + +# Prints $1 as a path relative to $PWD (not starting with /). +# If it already doesn't start with a /, doesn't change the string. +_relpath() +{ + local here="$2" there="$1" out= hadslash= + #echo "RP start '$there' hs='$hadslash'" >&2 + _startswith "$there" "/" || { echo "$there" && return; } + [ "$there" != "/" ] && _endswith "$there" "/" && hadslash=/ + here=${here%/}/ + while [ -n "$here" ]; do + #echo "RP out='$out' here='$here' there='$there'" >&2 + [ "${here%/}" = "${there%/}" ] && there= && break; + [ "${there#$here}" != "$there" ] && break + out=../$out + _dirsplit "${here%/}" + here=$_dirsplit_dir + done + there=${there#$here} + if [ -n "$there" ]; then + echo "$out${there%/}$hadslash" + else + echo "${out%/}$hadslash" + fi +} + + +# Prints a "normalized relative" path, with ".." resolved where possible. +# For example, a/b/../c will be reduced to just a/c. +_normpath() +( + local path="$1" relto="$2" out= isabs= + #echo "NP start '$path'" >&2 + if _startswith "$path" "/"; then + isabs=1 + else + path="${relto%/}/$path" + fi + set -f + IFS=/ + for d in ${path%/}; do + #echo "NP out='$out' d='$d'" >&2 + if [ "$d" = ".." ]; then + out=$(_updir "${out%/}")/ + else + out=$out$d/ + fi + done + #echo "NP out='$out' (done)" >&2 + out=${out%/} + if [ -n "$isabs" ]; then + echo "${out:-/}" + else + _relpath "${out:-/}" "$relto" + fi +) + + +# Prints a "real" path, with all symlinks resolved where possible. +_realpath() +{ + local path="$1" relto="$2" isabs= rest= + if _startswith "$path" "/"; then + isabs=1 + else + path="${relto%/}/$path" + fi + ( + for d in $(_seq 100); do + #echo "Trying: $PWD--$path" >&2 + if cd -P "$path" 2>/dev/null; then + # success + pwd=$(pwd -P) + #echo " chdir ok: $pwd--$rest" >&2 + np=$(_normpath "${pwd%/}/$rest" "$relto") + if [ -n "$isabs" ]; then + echo "$np" + else + _relpath "$np" "$relto" + fi + break + fi + _dirsplit "${path%/}" + path=$_dirsplit_dir + rest="$_dirsplit_base/$rest" + done + ) +} + + +# List the possible names for default*.do files in dir $1 matching the target +# pattern in $2. We stop searching when we find the first one that exists. +_find_dofiles_pwd() +{ + local dodir="$1" dofile="$2" + _startswith "$dofile" "default." || dofile=${dofile#*.} + while :; do + dofile=default.${dofile#default.*.} + echo "$dodir$dofile" + [ -e "$dodir$dofile" ] && return 0 + [ "$dofile" = default.do ] && break + done + return 1 +} + + +# List the possible names for default*.do files in $PWD matching the target +# pattern in $1. We stop searching when we find the first name that works. +# If there are no matches in $PWD, we'll search in .., and so on, to the root. +_find_dofiles() +{ + local target="$1" dodir= dofile= newdir= + _debug "find_dofile: '$PWD' '$target'" + dofile="$target.do" + echo "$dofile" + [ -e "$dofile" ] && return 0 + + # Try default.*.do files, walking up the tree + _dirsplit "$dofile" + dodir=$_dirsplit_dir + dofile=$_dirsplit_base + [ -n "$dodir" ] && dodir=${dodir%/}/ + [ -e "$dodir$dofile" ] && return 0 + for i in $(_seq 100); do + [ -n "$dodir" ] && dodir=${dodir%/}/ + #echo "_find_dofiles: '$dodir' '$dofile'" >&2 + _find_dofiles_pwd "$dodir" "$dofile" && return 0 + newdir=$(_realpath "${dodir}.." "$PWD") + [ "$newdir" = "$dodir" ] && break + dodir=$newdir + done + return 1 +} + + +# Print the last .do file returned by _find_dofiles. +# If that file exists, returns 0, else 1. +_find_dofile() +{ + local files="$(_find_dofiles "$1")" + rv=$? + #echo "files='$files'" >&2 + [ "$rv" -ne 0 ] && return $rv + echo "$files" | { + while read -r linex; do line=$linex; done + printf "%s\n" "$line" + } +} + + +# Actually run the given $dofile with the arguments in $@. +# Note: you should always run this in a subshell. +_run_dofile() +{ + export DO_DEPTH="$DO_DEPTH " + export REDO_TARGET="$PWD/$target" + local line1 + set -e + read line1 <"$PWD/$dofile" || true + cmd=${line1#"#!/"} + if [ "$cmd" != "$line1" ]; then + set -$_do_opt_verbose$_do_opt_exec + exec /$cmd "$PWD/$dofile" "$@" + else + set -$_do_opt_verbose$_do_opt_exec + # If $dofile is empty, "." might not change $? at + # all, so we clear it first with ":". + :; . "$PWD/$dofile" + fi +} + + +# Find and run the right .do file, starting in dir $1, for target $2, +# providing a temporary output file as $3. Renames the temp file to $2 when +# done. +_do() +{ + local dir="$1" target="$1$2" tmp="$1$2.redo.tmp" tdir= + local dopath= dodir= dofile= ext= + if [ "$_cmd" = "redo" ] || + ( [ ! -e "$target" -o -d "$target" ] && + [ ! -e "$target.did" ] ); then + printf '%sdo %s%s%s%s\n' \ + "$green" "$DO_DEPTH" "$bold" "$target" "$plain" >&2 + dopath=$(_find_dofile "$target") + if [ ! -e "$dopath" ]; then + echo "do: $target: no .do file ($PWD)" >&2 + return 1 + fi + _dirsplit "$dopath" + dodir=$_dirsplit_dir dofile=$_dirsplit_base + if _startswith "$dofile" "default."; then + ext=${dofile#default} + ext=${ext%.do} + else + ext= + fi + target=$PWD/$target + tmp=$PWD/$tmp + cd "$dodir" || return 99 + target=$(_relpath "$target" "$PWD") || return 98 + tmp=$(_relpath "$tmp" "$PWD") || return 97 + base=${target%$ext} + tdir=$(qdirname "$target") + [ ! -e "$DO_BUILT" ] || [ ! -w "$tdir/." ] || + : >>"$target.did.tmp" + # $qtmp is a temporary file used to capture stdout. + # Since it might be accidentally deleted as a .do file + # does its work, we create it, then open two fds to it, + # then immediately delete the name. We use one fd to + # redirect to stdout, and the other to read from after, + # because there's no way to fseek(fd, 0) in sh. + qtmp=$DO_PATH/do.$$.tmp + ( + rm -f "$qtmp" + ( _run_dofile "$target" "$base" "$tmp" >&3 3>&- 4<&- ) + rv=$? + if [ $rv != 0 ]; then + printf "do: %s%s\n" "$DO_DEPTH" \ + "$target: got exit code $rv" >&2 + rm -f "$tmp.tmp" "$tmp.tmp2" "$target.did" + return $rv + fi + echo "$PWD/$target" >>"$DO_BUILT" + if [ ! -e "$tmp" ]; then + # if $3 wasn't created, copy from stdout file + cat <&4 >$tmp + # if that's zero length too, forget it + [ -s "$tmp" ] || rm -f "$tmp" + fi + ) 3>$qtmp 4<$qtmp # can't use "|| return" here... + # ...because "|| return" would mess up "set -e" inside the () + # on some shells. Running commands in "||" context, even + # deep inside, will stop "set -e" from functioning. + rv=$? + [ "$rv" = 0 ] || return "$rv" + mv "$tmp" "$target" 2>/dev/null + [ -e "$target.did.tmp" ] && + mv "$target.did.tmp" "$target.did" || + : >>"$target.did" + else + _debug "do $DO_DEPTH$target exists." >&2 + fi +} + + +# Implementation of the "redo" command. +_redo() +{ + local i startdir="$PWD" dir base + set +e + for i in "$@"; do + i=$(_abspath "$i" "$startdir") + ( + cd "$DO_STARTDIR" || return 99 + i=$(_realpath "$(_relpath "$i" "$PWD")" "$PWD") + _dirsplit "$i" + dir=$_dirsplit_dir base=$_dirsplit_base + _do "$dir" "$base" + ) + [ "$?" = 0 ] || return 1 + done +} + + +# Implementation of the "redo-whichdo" command. +_whichdo() +{ + _find_dofiles "$1" +} + + +case $_cmd in + do|redo|redo-ifchange) _redo "$@" ;; + redo-whichdo) _whichdo "$1" ;; + do.test) ;; + *) printf "do: '%s': unexpected redo command" "$_cmd" >&2; exit 99 ;; +esac +[ "$?" = 0 ] || exit 1 + +if [ -n "$DO_TOP" ]; then + if [ -n "$_do_opt_clean" ]; then + echo "do: Removing stamp files..." >&2 + [ ! -e "$DO_BUILT" ] || + while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" | + xargs -0 rm -f 2>/dev/null + fi +fi diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index aae4e59..0000000 --- a/src/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -test: - shellcheck -x -f gcc ./cpt* ../contrib/* - -.PHONY: test diff --git a/src/cpt-lib b/src/cpt-lib.in index 8e4ef87..a8fac5c 100644 --- a/src/cpt-lib +++ b/src/cpt-lib.in @@ -8,7 +8,7 @@ # Currently maintained by Cem Keylan. version() { - log "Carbs Packaging Tools" 5.1.1 + log "Carbs Packaging Tools" @VERSION@ exit 0 } diff --git a/src/test.do b/src/test.do new file mode 100644 index 0000000..76771c0 --- /dev/null +++ b/src/test.do @@ -0,0 +1,5 @@ +. ../config.rc +redo-ifchange cpt-lib +exec >&2 +find . ../contrib -name 'cpt-*' ! -name '*.*' -exec shellcheck -x -f gcc {} + +PHONY diff --git a/uninstall.do b/uninstall.do new file mode 100644 index 0000000..d2f4585 --- /dev/null +++ b/uninstall.do @@ -0,0 +1,9 @@ +. ./config.rc + +getbin | while read -r file; do + rm -f "${DESTDIR}${BINDIR}/${file##*/}" +done + +for man in man/*.1; do + rm -f "${DESTDIR}${MAN1}/${man##*/}" +done |