diff -uNr a/vtools/manifest b/vtools/manifest --- a/vtools/manifest adb6177045ca615e1fbdaff613e0574ab8173c8ba7d8cc2ccc3df4c08a0c75d42288add35c0f3a3ae9ff376e60c1c670c22ae1574a646c66399147e630e9eab2 +++ b/vtools/manifest 7a44b950832602e9d82b261bfa48709b8ff406950ad9ebf9ba1702cb1dc9a8e2e5e7b6affed5f936b4f1a29aa7fe674bf6796e7417e10cb5f410ada892c08875 @@ -11,3 +11,4 @@ 584341 bvt vdiff_blockwise_read Fix stack overflow in vdiff when hashing large files. 589066 bvt vtools_fixes_rootdir_files Fix creation of files in the vtree root. Fix handling of empty vpatches. 615541 bvt vtools_small_fixes Fix vdiff gprbuild and remove useless variable from ksum. +615544 bvt vtools_add_vsh Add shell v-presser implementation. diff -uNr a/vtools/v.sh b/vtools/v.sh --- a/vtools/v.sh false +++ b/vtools/v.sh f33146be83aca8ebb2e0c75f69599985aeba8597ca79d00a2ed60b613147a48794ba4917edecac44920ead6d308c341c9b8b9531dd440d62f14f5f1a1a951a5b @@ -0,0 +1,262 @@ +#!/bin/sh + +set -e + +vgpgdir="" +vpatches="" +flow="" +filtered="" +selfile="" +simplified="" +topo="" + +usage() { + cat </dev/null 2>&1 + done +} + +cleanup() { + if [ ! -z "$vgpgdir" ]; then + rm -rf "$vgpgdir" + fi + exit 0 +} +trap cleanup TERM INT + +exit_msg() { + echo $1 + cleanup +} + +verify() { + vpatchpath="$1" + vpatch="$(basename $vpatchpath)" + signers="" + + checkdir seals + for i in seals/$vpatch.*.sig; do + signature="$(basename $i | sed 's/.sig$//g')" + signer="${signature#$vpatch.}" + if ! gpg --homedir "$vgpgdir" --logger-fd 1 --batch \ + --keyid-format=long \ + --verify "$i" "$vpatchpath" 2>&1 >/dev/null; then + exit_msg "Bad signature $i for $vpatch" + fi + signers="$signers $signer" + done + + [ -z "$signers" ] && exit_msg "No signatures for $vpatch" + + echo "$vpatch $signers" >> "$vgpgdir"/signers.txt +} + +verifyall() { + checkdir patches + for i in patches/*.vpatch; do + verify $i; + done +} + +filterall() { + n=0 + + for i in patches/*.vpatch; do + vfilter "$n" < "$i" + echo "$i $n" >> "$vpatches" + n="$((n+1))" + done +} + +internall() { + awk ' +function dedupf(i) {if (!(i in a)) {a[i]=fcnt; fcnt++;} return a[i];} +function deduph(i) {if (!(i in b)) {b[i]=hcnt; hcnt++;} return b[i];} +BEGIN{fcnt=1;hcnt=0; deduph("false")} +{print $1, dedupf($2), dedupf($3), deduph($4), deduph($5)}' +} + +vpatchnos() { + awk -v VF="$vpatches" ' +FILENAME==VF {a[$1]=$2} FILENAME=="-" {print a[$1]}' "$vpatches" - +} + +vpatchnames() { + awk -v VF="$vpatches" ' +FILENAME==VF {a[$2]=$1} FILENAME=="-" {print a[$1]}' "$vpatches" - +} + +vpatchflow() { + [ -z "$*" ] && exit_msg "No leaves selected." + filterall | internall >"$filtered" + selected="" + if [ "$*" == "-" ]; then + selected=$(awk '{print $2}' < "$vpatches") + else + selected="$(echo $* | tr ' ' '\n' | vpatchnos)" + fi + vflow $(wc -l <"$filtered") $(wc -l <"$vpatches") <"$filtered" >"$flow" + echo "$selected" | sed -e 's/^/s /g' - | sort | uniq >"$selfile" + cat "$flow" "$selfile" | vtoposort > "$topo" +} + +vpatchflowerr() { + ret=$(head -n1 "$topo" | awk '{print $1}') + if [ "$ret" = "C" ]; then + printf "\nConflicting leaves selected:\n" + awk '$1 == "C" {print $2}' < "$topo" | vpatchnames | sort | uniq + cleanup + elif [ $ret == "L" ]; then + echo "\nLoop among vpatches:" + awk '{print $2}' < "$topo" | vpatchnames + cleanup + elif [ "$ret" != "P" ]; then + echo "Unknown error. Investigate in $vgpgdir:" + cat "$topo" + exit 0 # no cleanup + fi +} + +[ -z "$1" ] && usage + +loadwot + +if [ "$1" == "wot" ]; then + gpg --homedir "$vgpgdir" --logger-fd 1 --batch --keyid-format=long -k + cleanup +fi + +verifyall + +if [ "$1" == "patches" ]; then + cat "$vgpgdir"/signers.txt + cleanup +fi + +if [ "$1" == "graph" ]; then + shift + dotfile="$1" + shift + svgfile="$1" + shift + + vpatchflow - + cat "$flow" "$topo" | vsimplify > "$simplified" + cat >"$dotfile" < \""a[$2]"\""} +' "$vpatches" - <"$simplified" >>"$dotfile" + echo "}" >> "$dotfile" + dot -Tsvg $dotfile -o $svgfile + # dot -Tcmapx $dotfile -o $svgfile.html-map + cleanup +fi + +if [ "$1" == "antecedents" ]; then + shift + vpatch="$1" + shift + + vpatchflow - + vno=$(awk -v V="$vpatch" '$1==V {print $2}' < "$vpatches") + cat "$flow" "$topo" | vsimplify > "$simplified" + awk -v S="$simplified" -v T="$topo" -v N="$vno" ' +FILENAME==S && ($1 == "I" || $1 == "d" ) && $2 == N {a[$3]=1} +FILENAME==T && ($1 == "P") {if ($2 in a) {print $2}} +' "$simplified" "$topo" | vpatchnames + cleanup +fi + +if [ "$1" == "descendants" ]; then + shift + vpatch="$1" + shift + + vpatchflow - + vno=$(awk -v V="$vpatch" '$1==V {print $2}' < "$vpatches") + cat "$flow" "$topo" | vsimplify > "$simplified" + awk -v S="$simplified" -v T="$topo" -v N="$vno" ' +FILENAME==S && ($1 == "I" || $1 == "d" ) && $3 == N {a[$2]=1} +FILENAME==T && ($1 == "P") {if ($2 in a) {print $2}} +' "$simplified" "$topo" | vpatchnames + cleanup +fi + +if [ "$1" == "origin" ]; then + shift + hash="$1" + shift + + filterall >"$filtered" + awk -v hash="$hash" '$5 == hash {print $1}' <"$filtered" | vpatchnames + cleanup +fi; + +if [ "$1" == "flow" ]; then + shift + + vpatchflow $* + + echo "Press order:" + awk '$1 == "P" {print $2}' < "$topo" | vpatchnames + + vpatchflowerr + cleanup +fi + +if [ "$1" == "press" ]; then + shift + dir="$1" + shift + + [ -d "$dir" ] && exit_msg "Directory $dir already exists" + mkdir -p "$dir" + + vpatchflow $* + vpatchflowerr + + awk '{print $2}' < "$topo" | vpatchnames | while read i; do + i=$(readlink -f $i) + cd "$dir" + vpatch <"$i" >/dev/null + cd - >/dev/null + done + cleanup +fi + +cleanup