about summary refs log tree commit diff stats
path: root/ok
blob: 028518ab3a3826bf02c35d4da822f4e5af299502 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/bin/sh

QUIET=false
NORUN=false
DIE=true
FNEW=false
_ARGS=true

OKFILE=./ok
FRFILE=.fr

usage(){
	exec >&2
	cat<<EOH
Usage: ok [OPTIONS] [TARGET...]
Options:
 -h		Show this help and exit
 -q		Run quietly
 -x		Run with 'set -x'
 -B		Run all targets as if they were "new"
 -f FILE	Use FILE as \$OKFILE (default: 'ok')
 -C DIRECTORY	Change to DIRECTORY before doing anything
Targets defined in $OKFILE:
$(sed -n \
      -e 's/^alias *\(.*\)/*\1/p' \
      -e 's/^\([a-z][a-z]*\)().*##* *\(.*\)/ \1       	# \2/p' \
      -e 's/^\([a-z][a-z]*\)().*/ \1/p' \
      "$OKFILE")
EOH
}

die(){
	ec="$1"; shift
	printf '%s\n' "$*" >&2
	exit $ec
}

procargs(){
	$_ARGS || return 1
	while getopts hqnxBf:C: OPT
	do
		case "$OPT" in
			(h) usage; exit ;;
			(q) QUIET=true ;;
			(x) set -x ;;
			(n) NORUN=true ;;
			(B) FNEW=true ;;
			(f) test -f "$OPTARG" && OKFILE="$OPTARG" || exit 2 ;;
			(C) cd "$OPTARG" || exit 2 ;;
			(*) usage; exit 1 ;;
		esac
	done
}

go(){
	procargs "$@" && shift $((OPTIND - 1))
	DEFAULT="$(sed -n 's/^\([a-z][a-z]*\)().*/\1/p' "$OKFILE"|sed q)"
	. "$OKFILE" || exit 3
	test -z "$1" && "$DEFAULT"
	for target
	do
		if grep -q "$target" "$FRFILE" 2>/dev/null
		then if buildp "$target" \
			       "$(grep "$target" "$FRFILE" | cut -f3-)"
		     then eval "$(grep "$target" "$FRFILE" | cut -f2-)"
		     fi
		else "$target"
		fi
	done
}

dep(){
	_ARGS=false go "$@" || exit "$((200 + $?))"
}

buildp(){ 			# buildp TARGET DEPENDENCIES...
	$FNEW && return 0
	target="$1"; shift
	test -e "$target" || return 0
	for f
	do
		test x-- = "x$f" && continue
		test "$f" -nt "$target" && return 0
	done
	return 1
}

ok(){				# ok COMMAND ARGS..
	case "$1" in (-) DIE=false; shift ;; esac
	$QUIET || printf >&2 '* %s\n' "$*"
	$NORUN || "$@"; ec="$?"
	if $DIE && test $ec -ne 0
	then die $((100 + $?)) not ok
	else return $ec
	fi
}

quietly(){ "$@" >/dev/null 2>&1; }

allfiles(){
	while read -r target line
	do TARGET="$target" eval "$line"
	done <"$FRFILE"
}

fr(){				# fr < TARGET JOB DEPS...
	# recommended: use a heredoc
	:>"$FRFILE"
	while read -r target job deps
	do
		eval set -- "$deps"
		printf '%s\tok %s\t%s\n' \
		       "$target" \
		       "$job" \
		       "$(printf '%s\n' "$deps"|sed 's/--.*//')" \
		       >>"$FRFILE"
	done
}

go "$@" && echo ok