sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

testpatches.sh (7546B)


      1 #!/bin/sh
      2 # TODO:
      3 # ? build:
      4 #   - set flags per project? (per version too?).
      5 #   - add build status (OK, FAIL, unknown), must be secure though.
      6 
      7 projects() {
      8 cat <<!__EOF__
      9 dmenu	tools.suckless.org/dmenu/patches
     10 dwm	dwm.suckless.org/patches
     11 ii	tools.suckless.org/ii/patches
     12 sent	tools.suckless.org/sent/patches
     13 sic	tools.suckless.org/sic/patches
     14 slock	tools.suckless.org/slock/patches
     15 st	st.suckless.org/patches
     16 surf	surf.suckless.org/patches
     17 tabbed	tools.suckless.org/tabbed/patches
     18 !__EOF__
     19 }
     20 
     21 wikidir="$(pwd)/sites"
     22 repodir="$(pwd)/repos"
     23 revdir="$(pwd)/rev"
     24 resultsdir="$(pwd)/results"
     25 builddir="$(pwd)/build"
     26 
     27 # dryrun patch command (OpenBSD).
     28 # must be unified diff (-u, so no ed script), -t and -C are dryrun (non-POSIX).
     29 dryrun="patch -u -p1 -t -C"
     30 
     31 # getdateutc()
     32 getdateutc() {
     33 	# date as UTC+0 time.
     34 	TZ="UTC+0" date
     35 }
     36 
     37 # log(s)
     38 log() {
     39 	s="[$(date)] $1"
     40 	echo "$s" >&2
     41 }
     42 
     43 # getprojects()
     44 getprojects() {
     45 	# allow commenting to disable.
     46 	projects | grep -v '^#'
     47 }
     48 
     49 # clone()
     50 clone() {
     51 	getprojects | while read -r -- project dir; do
     52 		test -d "$repodir/$project" && continue
     53 
     54 		git clone --bare "git://git.suckless.org/$project" "$repodir/$project"
     55 	done
     56 }
     57 
     58 # pull()
     59 pull() {
     60 	getprojects | while read -r -- project dir; do
     61 		test -d "$repodir/$project" || continue
     62 
     63 		GIT_DIR="$repodir/$project" git fetch "git://git.suckless.org/$project"
     64 	done
     65 }
     66 
     67 # listpatches()
     68 listpatches() {
     69 	getprojects | while read -r -- project dir; do
     70 		find "$wikidir/$dir" -name "*.diff" | while read -r p; do
     71 			test -f "$p" || continue
     72 
     73 			b=$(basename "$p")
     74 			bb="${b%.diff}"
     75 			bb="${bb#${project}-}"
     76 
     77 			# NOTE: historical patches like "r1506" (mercurial) are ignored.
     78 			v=$(echo "$bb" | sed -En 's@^([0-9a-f\.]+)-.*$@\1@p')
     79 			if test -z "$v"; then
     80 				v=$(echo "$bb" | sed -En 's@^.*-([0-9a-f\.]+)$@\1@p')
     81 			fi
     82 
     83 			# version not found, skip.
     84 			if test -z "$v"; then
     85 				continue
     86 			fi
     87 
     88 			name="${p%.diff}"
     89 			name="${name##*/patches/}"
     90 			name="${name%%/*}"
     91 
     92 			printf '%s\t%s\t%s\t%s\t%s\n' "$project" "$v" "$dir" "$name" "$p"
     93 		done
     94 	done
     95 }
     96 
     97 # checkoutrev(project, version)
     98 checkoutrev() {
     99 	project="$1"
    100 	v="$2"
    101 
    102 	test -f "$revdir/$project/$v/fail" && return 1
    103 	test -d "$revdir/$project/$v" && return 0
    104 
    105 	cur=$(pwd)
    106 	d="$revdir/$project/$v"
    107 	mkdir -p "$d"
    108 	cd "$d" || return 1
    109 
    110 	GIT_DIR="$repodir/$project" \
    111 		git archive "$v" 2> "$revdir/$project/$v/fail" | \
    112 		tar xf - 2>/dev/null
    113 	status=$?
    114 	if test x"$status" != x"0"; then
    115 		status=1
    116 	else
    117 		rm -f "$revdir/$project/$v/fail"
    118 	fi
    119 	cd "$cur"
    120 
    121 	return $status
    122 }
    123 
    124 # preparebuilds()
    125 preparebuilds() {
    126 	listpatches | while read -r -- project v dir name p; do
    127 		test -f "$p" || continue
    128 
    129 		# version quirks (wrong tagging).
    130 		if test x"$project" = x"sent"; then
    131 			if test x"$v" = x"1.0"; then
    132 				v="1"
    133 				test -e "$revdir/$project/1.0" || \
    134 					ln -sf "$v" "$revdir/$project/1.0"
    135 			fi
    136 		fi
    137 		if test x"$project" = x"ii"; then
    138 			if test x"$v" = x"1.7"; then
    139 				v="v1.7"
    140 				test -e "$revdir/$project/1.7" || \
    141 					ln -sf "$v" "$revdir/$project/1.7"
    142 			fi
    143 		fi
    144 
    145 		# prepare clean build directory for patch.
    146 		b=$(basename "$p")
    147 		b="${b%.diff}"
    148 
    149 		# cannot prepare revision for build: skip.
    150 		if ! checkoutrev "$project" "$v"; then
    151 			log "CANNOT CHECKOUT REVISION: $project v=$v, name=$name, patch=$b, error=$(cat "$revdir/$project/$v/fail")"
    152 			continue
    153 		fi
    154 
    155 		# already has clean builddir.
    156 		test -d "$builddir/$project/$b" && continue
    157 		cleanbuild "$project" "$v" "$b"
    158 	done
    159 }
    160 
    161 # cleanbuild(project, version, build)
    162 cleanbuild() {
    163 	project="$1"
    164 	v="$2"
    165 	b="$3"
    166 
    167 	test -d "$builddir/$project/$b" && rm -rf "$builddir/$project/$b"
    168 
    169 	mkdir -p "$builddir/$project"
    170 	cp -r "$revdir/$project/$v" "$builddir/$project/$b"
    171 }
    172 
    173 # testpatches()
    174 testpatches() {
    175 	# sort by project, name, version
    176 	listpatches | sort -k1,1 -k4,4 -k2,2 | \
    177 		while read -r -- project v dir name p; do
    178 		test -f "$p" || continue
    179 
    180 		# cannot prepare revision for build: skip.
    181 		checkoutrev "$project" "$v" || continue
    182 
    183 		b=$(basename "$p")
    184 		b="${b%.diff}"
    185 
    186 		test -d "$builddir/$project/$b" || continue
    187 		cd "$builddir/$project/$b" || continue
    188 
    189 		# copy patch file for convenience / debugging.
    190 		cp "$p" "$builddir/$project/$b/p.diff"
    191 
    192 		# lenient: copy config.def.h to config.h if config.h doesn't exist.
    193 		#rm -f "$builddir/$project/$b/config.h" # DEBUG
    194 		#if test -f "$builddir/$project/$b/config.def.h"; then
    195 		#	if ! test -f "$builddir/$project/$b/config.h"; then
    196 		#		cp "$builddir/$project/$b/config.def.h" "$builddir/$project/$b/config.h"
    197 		#	fi
    198 		#fi
    199 
    200 		# patch (dryrun).
    201 		$dryrun < "$p" 2> "$builddir/$project/$b/patch.2.log" >"$builddir/$project/$b/patch.1.log"
    202 		applystatus=$?
    203 
    204 		# write results to metadata file (for creating views).
    205 		printf "%s\t%s\t%s\t%s\t%s\t%s\n" \
    206 			"$project" "$v" "$dir" "$name" "$applystatus" "$b" > "$builddir/$project/$b/metadata"
    207 
    208 		log "$p	$applystatus"
    209 	done
    210 }
    211 
    212 # outputhtml()
    213 outputhtml() {
    214 	index="$resultsdir/index.html"
    215 	title="Last updated on $(getdateutc)"
    216 
    217 cat > "$index" <<!__EOF__
    218 <!DOCTYPE html>
    219 <html>
    220 <head>
    221 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    222 <title>$title - Patch applystatus</title>
    223 <style type="text/css">
    224 table       { border-collapse: collapse; }
    225 td          { padding: 2px; }
    226 thead td    { background-color: #eee; }
    227 .s-0 td     { background-color: #ccffcc; }
    228 .s-1 td     { background-color: #ffcccc; }
    229 .s-2 td     { background-color: #ff0000; color: #fff; }
    230 </style>
    231 </head>
    232 <body>
    233 <h1>$title</h1>
    234 <table>
    235 <thead>
    236 <tr>
    237 	<td><b>Project</b></td>
    238 	<td><b>Version/revision</b></td>
    239 	<td><b>Patch</b></td>
    240 	<td><b>Patch</b></td>
    241 	<td><b>Patch file</b></td>
    242 	<td><b>Patch stdout</b></td>
    243 	<td><b>Patch stderr</b></td>
    244 	<td><b>Exitcode</b></td>
    245 	<td><b>Status</b></td>
    246 </tr>
    247 </thead>
    248 <tbody>
    249 !__EOF__
    250 
    251 	# sort by project, name, version
    252 	find "$builddir" -name "metadata" -type f -exec cat {} \; | \
    253 		sort -k1,1 -k4,4 -k2,2 | \
    254 		while read -r -- project v dir name applystatus b; do
    255 		test -d "$builddir/$project/$b" || continue
    256 
    257 		# HTML output test
    258 		mkdir -p "$resultsdir/$b/"
    259 		cp \
    260 			"$builddir/$project/$b/p.diff"\
    261 			"$builddir/$project/$b/patch.2.log"\
    262 			"$builddir/$project/$b/patch.1.log"\
    263 			"$resultsdir/$b/"
    264 
    265 		statustext="OK"
    266 		pageurl="https://$dir/$name/"
    267 
    268 		case "$applystatus" in
    269 		0) statustext="OK";;
    270 		1) statustext="FAIL";;
    271 		2) statustext="CORRUPT";;
    272 		*) statustext="UNKNOWN";;
    273 		esac
    274 
    275 		cat >> "$index" <<!__EOF__
    276 <tr class="s-$applystatus">
    277 	<td><a href="https://git.suckless.org/$project/">$project</a></td>
    278 	<td>$v</td>
    279 	<td><a href="$pageurl">$name</a></td>
    280 	<td><a href="$pageurl">$b</a></td>
    281 	<td><a href="$b/p.diff">[patch]</a></td>
    282 	<td><a href="$b/patch.1.log">[stdout]</a></td>
    283 	<td><a href="$b/patch.2.log">[stderr]</a></td>
    284 	<td>$applystatus</td>
    285 	<td>$statustext</td>
    286 </tr>
    287 !__EOF__
    288 	done
    289 
    290 	echo "</tbody></table></body></html>" >> "$index"
    291 }
    292 
    293 # outputcsv()
    294 outputcsv() {
    295 	index="$resultsdir/index.csv"
    296 
    297 	# sort by project, name, version
    298 	find "$builddir" -name "metadata" -type f -exec cat {} \; | \
    299 		sort -k1,1 -k4,4 -k2,2 | \
    300 		while read -r -- project v dir name applystatus b; do
    301 		test -d "$builddir/$project/$b" || continue
    302 
    303 		printf '%s\n' "$project	$v	$name	$b	$applystatus" >> "$index"
    304 	done
    305 }
    306 
    307 case "$1" in
    308 clone|pull)
    309 	mkdir -p "$repodir"
    310 	$1
    311 	;;
    312 clean)
    313 	rm -rf "$revdir" "$builddir"
    314 	;;
    315 prepare)
    316 	mkdir -p "$builddir" "$revdir"
    317 	preparebuilds
    318 	;;
    319 test)
    320 	testpatches
    321 	;;
    322 results)
    323 	# output results
    324 	rm -rf "$resultsdir"
    325 	mkdir -p "$resultsdir"
    326 	outputhtml
    327 	outputcsv
    328 	;;
    329 *)
    330 	echo "usage: $0 <clone | pull | clean | prepare | test | results>" >&2
    331 	exit 1
    332 	;;
    333 esac