aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormerakor <cem@ckyln.com>2020-12-21 10:02:45 +0000
committermerakor <cem@ckyln.com>2020-12-21 10:02:45 +0000
commitc1c68a205b8cbf0a8ee55f099c27d0a0c7f8afe2 (patch)
tree0e28e76b2391ba290180df87acdab6577d1dfe3f
parent08af0013de1d77cf0ee46245e50007a9fbf79035 (diff)
parent1535d115d8d0c58ca4a90acbf16b263cf85bb0a1 (diff)
downloadcpt-c1c68a205b8cbf0a8ee55f099c27d0a0c7f8afe2.tar.gz
Merge branch 'redo'
FossilOrigin-Name: 046e1a0012624ed9a8934a8a4099710264281bcb6814c1fc0fbe3157c1121d2f
-rw-r--r--.github/workflows/main.yml2
-rw-r--r--.gitignore11
-rw-r--r--Makefile69
-rw-r--r--README15
-rw-r--r--bin/all.do2
-rw-r--r--bin/clean.do2
-rw-r--r--bin/test.do11
-rw-r--r--clean.do5
-rw-r--r--config.mk25
-rw-r--r--config.rc84
-rw-r--r--default.do50
-rw-r--r--docs/default.do27
-rw-r--r--install.do16
-rwxr-xr-xminimal/do446
-rw-r--r--src/Makefile4
-rw-r--r--src/cpt-lib.in (renamed from src/cpt-lib)2
-rw-r--r--src/test.do5
-rw-r--r--uninstall.do9
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
diff --git a/.gitignore b/.gitignore
index 3744e4c..45ab818 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/README b/README
index 0e83582..6479e35 100644
--- a/README
+++ b/README
@@ -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