#!/bin/bash # called as editor from 'svn commit' if [ "$1" = "ed" ]; then x=`mktemp` { echo; sed '/^--- / Q;' ${SMAP_PATCHFILE:-/dev/null} echo; echo "$SMAP_PATCHID"; echo; cat $2; } | \ awk '!x || $0!="" {print;x=0;} $0=="" {x=1;}' > $x cat $x > $2; cp $x /tmp/xxxx; rm -f $x if [ $SMAP_EDITMESSAGE = 1 ]; then exec ${EDITOR:-vi} $2 exit 1 fi exit 0 fi URL=NONE USER=guest PASS=guest popt="-p0" lopt="" Ropt="" dry_run=0; addf="" addc="smap" addonly=0; skipsvn=0 editmsg=0; skipdel=0 checkit=0; domark=0 getmode=0 merge="" copy="" if [ -f smap.cfg ]; then source smap.cfg fi if [ -f "$PWD.sm/SM/server.txt" ]; then { read a; read b; read c; } < "$PWD.sm/SM/server.txt" if [ -n "$a" ]; then URL="$a"; fi if [ -n "$b" ]; then USER="$b"; fi if [ -n "$c" ]; then PASS="$c"; fi fi if [ "$URL" = NONE ]; then echo; echo "!!! No configuration found !!!" set -- -help fi while [ -z "${1##[-+]*}" ]; do [ -z "${1##[-+][!aADSECOPg]*}" ] && addc="$addc $1" case "$1" in -p*) popt="$1" ; shift ;; -l) lopt="-l" ; shift ;; -R) Ropt="-R" ; shift ;; -d) dry_run=1 ; shift ;; -S) skipsvn=1 ; shift ;; -D) skipdel=1 ; shift ;; -E) editmsg=1 ; shift ;; -A) addonly=1 ; shift ;; -a) addf="$2" ; shift ; shift ;; -O) merge="$2"; shift ; shift ;; -P) copy="$2" ; shift ; shift ;; -M) domark=1 ; shift ;; -C) checkit=1 ; shift ;; -g) getmode=1 ; shift ;; +l) lopt="" ; shift ;; +R) Ropt="" ; shift ;; +d) dry_run=0 ; shift ;; +S) skipsvn=0 ; shift ;; +D) skipdel=0 ; shift ;; +E) editmsg=0 ; shift ;; +A) addonly=0 ; shift ;; +a) addf="" ; shift ;; +O) merge="" ; shift ;; +M) domark=0 ; shift ;; +C) checkit=0 ; shift ;; +g) getmode=0 ; shift ;; *) break ;; esac done if [ -z "${1##[-+]*}" ]; then echo "" echo "Usage: $0 [options] " echo "" echo " -pN -l -R pass this option to the patch program" echo " -d just make a dry-run" echo "" echo " -S don't commit to svn (e.g. if this isn't a svn tree)" echo " -E edit commit message before running svn commit" echo " -D don't remove temp files after success" echo "" echo " -a filename add this smap command to file after success" echo " -O filename merge diff with this file (create combined diff)" echo " -P dirname copy all applied patches to this directory" echo " -A don't apply anything, just do -a and -O" echo "" echo " -M mark patch as applied on SM Server" echo " -C do nothing if already marked as applied" echo "" echo " -g just get the patch, do nothing else" echo "" echo " +l +R +d +S +D +E +A +a +M +C" echo " revert the effect of a prior specified -? option." echo "" echo "If $0 is called in a SubMaster working copy, it reads the server URL" echo "as well as username/passwords from .sm/SM/server.txt." echo echo "But $0 can also be configured by using an smap.cfg in the current" echo "working directory. This file can be used to set access data and to" echo "set defaults for the command line options:" echo echo " set -- -E -l \"\$@\"" echo " URL=https://www.rocklinux.net/submaster" echo " USER=username" echo " PASS=password" echo "" exit 1 fi for rawid in $* do read id1 id2 < <( perl -e '$_="'"$rawid"'"; print "$1/$2/$3 $1$2$3\n" if \/^([0-9]{4})[\/_]?([0-9]{2})[\/_]?([0-9]+)$/'; ) if [ -z "$id1" ]; then echo "ID has wrong format!" exit 1 fi error() { echo; echo "Error while auto-applying patch $id2." echo; exit 1 } if [ $checkit = 1 -a $getmode = 0 ]; then echo; echo "Checking if patch $id2 is still open ..." curl -k -o $id2.stat "$URL/smadm.cgi?i=$id1" if ! grep -q "Open Patch.* $id2" $id2.stat; then echo "No, it's not. Skipping this patch." if [ "$skipdel" = 0 ]; then rm -f "$id2.stat"; fi continue fi fi echo; echo "Downloading $id2.patch ..." curl -k -o $id2.patch $URL/data/$id1.patch || error if [ -f fixdiff_$id2.patch ]; then echo; echo "Applying fixdiff_$id2.patch ..." patch $id2.patch < fixdiff_$id2.patch || error fi if [ $addonly = 0 -a $getmode = 0 ] then echo; echo "Test-applying $id2.patch ..." patch -Ef $popt $lopt $Ropt --dry-run < $id2.patch || error echo; echo "Extra test for adding files ..." if [ -z "$Ropt" ]; then plus="+"; else plus="-"; fi if [ -z "$Ropt" ]; then minus="-"; else minus="+"; fi while read a b; do if [ ".$a" = ".$plus" -a -f "$b" ]; then echo "Patch would create already existing file $b." error fi done < <( lsdiff -sE --strip=${popt#-p} $id2.patch ) if [ $dry_run = 0 ]; then echo; echo "Applying $id2.patch ..." patch -Ef $popt $lopt $Ropt < $id2.patch || error else svn() { echo "svn $*"; } fi if [ $skipsvn = 0 ] then function svn_add_dir() { local p="${1%/*}" [ "$p" = "$1" ] && return echo ">> $1 -> $p" [ -d "$p/.svn" ] && return svn_add_dir "$p" svn add -N "$p" commit_list="$commit_list $p" } echo; echo "Running svn add and svn del commands ..." commit_list="" while read a b; do if [ "$a" = "$plus" ]; then svn_add_dir "$b"; fi if [ "$a" = "$plus" ]; then svn add "$b" || error; fi if [ "$a" = "$minus" ]; then svn del "$b" || error; fi commit_list="$commit_list $b" done < <( lsdiff -sE --strip=${popt#-p} $id2.patch ) echo; echo "Commiting patch to subversion ..." export SMAP_PATCHFILE="$PWD/$id2.patch" export SMAP_EDITMESSAGE=$editmsg export SMAP_PATCHID="[$id2] ($URL)" svn commit --editor-cmd "$0 ed" $commit_list || error fi if [ $domark = 1 -a $dry_run = 0 -a $USER != guest ]; then echo; echo "Marking patch $id2 as applied ..." curl -k -q -o $id2.stat "$URL/smadm.cgi?u=$USER&p=$PASS&a=details&i=$id1&s1=1" grep -q "Applied Patch.* $id2" $id2.stat || error fi fi if [ $dry_run = 0 -a -n "$addf" -a $getmode = 0 ]; then echo; echo "Adding journal block to $addf ..." { echo; echo "### $URL/smadm.cgi?i=$id2"; echo "$addc $id2" sed '/^--- / Q; s/^/# /;' < $id2.patch } >> "$addf" fi if [ $dry_run = 0 -a -n "$merge" -a $getmode = 0 ]; then echo; echo "Merging patch with $merge .."; touch "$merge" combinediff -q "$merge" $id2.patch > "$merge.new" || error mv "$merge.new" "$merge" fi if [ $dry_run = 0 -a -n "$copy" -a $getmode = 0 ]; then echo; echo "Copying patch to $copy .." mkdir -p "$copy"; cp $id2.patch "$copy" fi if [ $skipdel = 0 -a $getmode = 0 ]; then echo; echo "Removing $id2.{patch,stat} ..." rm -f $id2.{patch,stat} fi done