michael@428: ##
michael@428: ## OpenPKG Software Stack Generation
michael@428: ## Copyright (c) 2010-2012 OpenPKG GmbH
michael@428: ##
michael@428: ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
michael@428: ## All rights reserved. Licenses which grant limited permission to use,
michael@428: ## copy, modify and distribute this software are available from the
michael@428: ## OpenPKG GmbH.
michael@428: ##
michael@428: ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
michael@428: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
michael@428: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@428: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
michael@428: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@428: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@428: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
michael@428: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
michael@428: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
michael@428: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
michael@428: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@428: ## SUCH DAMAGE.
michael@428: ##
michael@428:
michael@428: # configuration
michael@428: openpkg="${OPENPKG_PREFIX}/bin/openpkg"
michael@428: curl="${OPENPKG_PREFIX}/bin/openpkg curl"
michael@428: shtool="${OPENPKG_PREFIX}/lib/openpkg/shtool"
michael@428:
michael@428: ##
michael@428: ## COMMAND LINE PARSING
michael@428: ##
michael@428:
michael@428: str_usage="[-h|--help] [-v|--verbose ] [-o|--output ] [-D|--define = ...] [-u|--unversioned] [-q|--query] .stk"
michael@428: arg_spec="1="
michael@428: opt_spec="h.v:o:D+u.q."
michael@428: opt_alias="h:help,v:verbose,o:output,D:define,u:unversioned,q:query"
michael@428: opt_h=no
michael@428: opt_v=4
michael@428: opt_o="."
michael@428: opt_D=""
michael@428: opt_u=no
michael@428: opt_q=no
michael@428:
michael@428: # parse argument specification string
michael@428: eval `echo $arg_spec |\
michael@428: sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
michael@428:
michael@428: # parse option specification string
michael@428: eval `echo $opt_spec |\
michael@428: sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
michael@428:
michael@428: # parse option alias string
michael@428: eval `echo $opt_alias |\
michael@428: sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
michael@428:
michael@428: # interate over argument line
michael@428: opt_PREV=''
michael@428: while [ $# -gt 0 ]; do
michael@428: # special option stops processing
michael@428: if [ ".$1" = ".--" ]; then
michael@428: shift
michael@428: break
michael@428: fi
michael@428:
michael@428: # determine option and argument
michael@428: opt_ARG_OK=no
michael@428: if [ ".$opt_PREV" != . ]; then
michael@428: # merge previous seen option with argument
michael@428: opt_OPT="$opt_PREV"
michael@428: opt_ARG="$1"
michael@428: opt_ARG_OK=yes
michael@428: opt_PREV=''
michael@428: else
michael@428: # split argument into option and argument
michael@428: case "$1" in
michael@428: --[a-zA-Z0-9]*=*)
michael@428: eval `echo "x$1" |\
michael@428: sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
michael@428: opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
michael@428: eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
michael@428: ;;
michael@428: --[a-zA-Z0-9]*)
michael@428: opt_OPT=`echo "x$1" | cut -c4-`
michael@428: opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
michael@428: eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
michael@428: opt_ARG=''
michael@428: ;;
michael@428: -[a-zA-Z0-9]*)
michael@428: eval `echo "x$1" |\
michael@428: sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
michael@428: -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
michael@428: ;;
michael@428: -[a-zA-Z0-9])
michael@428: opt_OPT=`echo "x$1" | cut -c3-`
michael@428: opt_ARG=''
michael@428: ;;
michael@428: *)
michael@428: break
michael@428: ;;
michael@428: esac
michael@428: fi
michael@428:
michael@428: # eat up option
michael@428: shift
michael@428:
michael@428: # determine whether option needs an argument
michael@428: eval "opt_MODE=\$opt_MODE_${opt_OPT}"
michael@428: if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
michael@428: if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
michael@428: opt_PREV="$opt_OPT"
michael@428: continue
michael@428: fi
michael@428: fi
michael@428:
michael@428: # process option
michael@428: case $opt_MODE in
michael@428: '.' )
michael@428: # boolean option
michael@428: eval "opt_${opt_OPT}=yes"
michael@428: ;;
michael@428: ':' )
michael@428: # option with argument (multiple occurances override)
michael@428: eval "opt_${opt_OPT}=\"\$opt_ARG\""
michael@428: ;;
michael@428: '+' )
michael@428: # option with argument (multiple occurances append)
michael@428: eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
michael@428: ;;
michael@428: * )
michael@428: echo "$0: ERROR: unknown option: \`$opt_OPT'" 1>&2
michael@428: exit 1
michael@428: ;;
michael@428: esac
michael@428: done
michael@428: if [ ".$opt_PREV" != . ]; then
michael@428: echo "$0: ERROR: missing argument to option \`$opt_PREV'" 1>&2
michael@428: exit 1
michael@428: fi
michael@428:
michael@428: # process help option
michael@428: if [ ".$opt_h" = .yes ]; then
michael@428: echo "Usage: $0 $str_usage"
michael@428: exit 0
michael@428: fi
michael@428:
michael@428: # complain about incorrect number of arguments
michael@428: case $arg_MODE in
michael@428: '=' )
michael@428: if [ $# -ne $arg_NUMS ]; then
michael@428: echo "$0: ERROR: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
michael@428: exit 1
michael@428: fi
michael@428: ;;
michael@428: '+' )
michael@428: if [ $# -lt $arg_NUMS ]; then
michael@428: echo "$0: ERROR: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
michael@428: exit 1
michael@428: fi
michael@428: ;;
michael@428: esac
michael@428:
michael@428: ##
michael@428: ## HELPER FUNCTIONS
michael@428: ##
michael@428:
michael@428: # helper function for graceful termination
michael@428: die () {
michael@428: echo "$0: ERROR: $*"
michael@428: exit 1
michael@428: }
michael@428:
michael@428: # helper function for verbose messages
michael@428: verbose () {
michael@428: lvl="$1"
michael@428: msg="$2"
michael@428: if [ $opt_v -ge $lvl ]; then
michael@428: case "$lvl" in
michael@428: 1 ) str_prefix="**" ;;
michael@428: 2 ) str_prefix="++" ;;
michael@428: 3 ) str_prefix="--" ;;
michael@428: 4 ) str_prefix=".." ;;
michael@428: esac
michael@428: echo "${str_prefix} ${msg}"
michael@428: fi
michael@428: }
michael@428:
michael@428: # expand macros
michael@428: macro_expand () {
michael@428: stk="$1"
michael@428:
michael@428: # load all options and their default values
michael@428: options=""
michael@428: for option in `sed <$stk \
michael@428: -e "1,/^%options/d" -e '/^%/,$d' \
michael@428: -e 's/#.*$//' -e 's/^ *//' -e 's/ *$//' -e '/^ *$/d' \
michael@428: -e 's; *[^ ]*$;;'`; do
michael@428: options="$options $option"
michael@428: done
michael@428: eval `sed <$stk \
michael@428: -e "1,/^%options/d" -e '/^%/,$d' \
michael@428: -e 's/#.*$//' -e 's/^ *//' -e '/^ *$/d' \
michael@428: -e 's:^\([^ ]*\) *\([^ ]*\)$:option_\1="\2";:'`
michael@428:
michael@428: # override options with defined values
michael@428: for define in $opt_D; do
michael@428: name=`echo "$define" | sed -e 's;=.*$;;'`
michael@428: value=`echo "$define" | sed -e 's;^.*=;;'`
michael@428: eval "exists=\"\${option_${name}}\""
michael@428: if [ ".$exists" = . ]; then
michael@428: die "definition of not-existing option \"$name\""
michael@428: fi
michael@428: eval "option_${name}=\"${value}\""
michael@428: done
michael@428:
michael@428: # expand macros
michael@428: cmd="sed"
michael@428: for name in $options; do
michael@428: eval "value=\"\${option_${name}}\""
michael@428: cmd="$cmd -e 's;%{[?]$name:\\([^}]*\\)};\1;g'"
michael@428: cmd="$cmd -e 's;%{![?]$name:\\([^}]*\\)};;g'"
michael@428: cmd="$cmd -e 's;%{$name};$value;g'"
michael@428: done
michael@428: cmd="$cmd -e 's;%{[?][^:}]*:[^}]*};;g'"
michael@428: cmd="$cmd -e 's;%{![?][^:}]*:\([^}]*\)};\1;g'"
michael@428: eval "$cmd"
michael@428: }
michael@428:
michael@428: # extract macro-expanded header
michael@428: header () {
michael@428: stk="$1"
michael@428: hdr="$2"
michael@428: exists=`egrep "^${hdr}" $stk`
michael@428: if [ ".$exists" != . ]; then
michael@428: egrep "^${hdr}:" $stk | \
michael@428: sed -e 's;^[^:]*: *;;' -e 's/#.*$//' -e 's/^ *//' -e 's/ *$//' -e '/^ *$/d' | \
michael@428: macro_expand "$stk"
michael@428: fi
michael@428: }
michael@428:
michael@428: # extract macro-expanded section
michael@428: section () {
michael@428: stk="$1"
michael@428: sec="$2"
michael@428: exists=`egrep "^%${sec}" $stk`
michael@428: if [ ".$exists" != . ]; then
michael@428: sed <$stk \
michael@428: -e "1,/^%${sec}/d" -e '/^%/,$d' \
michael@428: -e 's/#.*$//' -e 's/^ *//' -e 's/ *$//' -e '/^ *$/d' | \
michael@428: macro_expand "$stk"
michael@428: fi
michael@428: }
michael@428:
michael@428: ##
michael@428: ## MAIN
michael@428: ##
michael@428:
michael@428: # determine stack file
michael@428: stk="$1"
michael@428: shift
michael@428:
michael@428: # support stand-alone query operation
michael@428: if [ ".$opt_q" = .yes ]; then
michael@428: name=`header "$stk" "Name"`
michael@428: summary=`header "$stk" "Summary"`
michael@428: packager=`header "$stk" "Packager"`
michael@428: version=`header "$stk" "Version"`
michael@428: release=`header "$stk" "Release"`
michael@428: echo "name=\"$name\";"
michael@428: echo "summary=\"$summary\";"
michael@428: echo "packager=\"$packager\";"
michael@428: echo "version=\"$version\";"
michael@428: echo "release=\"$release\";"
michael@428: sed <$stk \
michael@428: -e "1,/^%options/d" -e '/^%/,$d' \
michael@428: -e 's/#.*$//' -e 's/^ *//' -e '/^ *$/d' \
michael@428: -e 's:^\([^ ]*\) *\([^ ]*\)$:\1="\2";:'
michael@428: exit 0
michael@428: fi
michael@428:
michael@428: # determine temporary directory
michael@428: tmpdir="${TMPDIR-/tmp}"
michael@428:
michael@428: # provide verbose header
michael@428: verbose 1 "OpenPKG Software Stack Generation"
michael@428:
michael@428: # determine information
michael@428: verbose 2 "determining software stack information"
michael@428: name=`header "$stk" "Name"`
michael@428: summary=`header "$stk" "Summary"`
michael@428: packager=`header "$stk" "Packager"`
michael@428: version=`header "$stk" "Version"`
michael@428: release=`header "$stk" "Release"`
michael@428: verbose 3 "Name: $name"
michael@428: verbose 3 "Summary: $summary"
michael@428: verbose 3 "Packager: $packager"
michael@428: verbose 3 "Version: $version"
michael@428: verbose 3 "Release: $release"
michael@428: if [ ".$opt_u" = .yes ]; then
michael@428: basename="$name"
michael@428: else
michael@428: basename="$name-$version-$release"
michael@428: fi
michael@428:
michael@428: # determine URLs
michael@428: verbose 2 "determining software stack packages"
michael@428: repo=`section "$stk" "repository"`
michael@428: verbose 3 "repository: [URL] $repo"
michael@428: $openpkg build -r "$repo" -Z -u -K -B \
michael@428: `section "$stk" "packages"` | \
michael@428: egrep "openpkg curl" | \
michael@428: sed -e 's;^.* \([^ ]*\) || exit.*$;\1;' \
michael@428: -e '/\/openpkg-[0-9].*\.src\.rpm/{h;s/\.src\.rpm$/.src.sh/;p;x}' \
michael@428: >$tmpdir/url.txt
michael@428:
michael@428: # provide header
michael@428: verbose 2 "assembling software stack sources"
michael@428:
michael@428: # download source packages
michael@428: if [ ! -d "$opt_o/$basename.src.d" ]; then
michael@428: verbose 3 "creating: [DIR] $opt_o/$basename.src.d"
michael@428: $shtool mkdir -p -m 755 "$opt_o/$basename.src.d"
michael@428: else
michael@428: verbose 3 "reusing: [DIR] $opt_o/$basename.src.d"
michael@428: fi
michael@428: for url in `cat $tmpdir/url.txt`; do
michael@428: url_file=`echo $url | sed -e 's;^.*/\([^/]*\)$;\1;'`
michael@428: if [ ! -f "$opt_o/$basename.src.d/$url_file" ]; then
michael@428: verbose 3 "downloading: [FILE] $opt_o/$basename.src.d/$url_file"
michael@428: if [ $opt_v -ge 4 ]; then
michael@428: $curl '-#' -L -k -o $opt_o/$basename.src.d/$url_file $url
michael@428: else
michael@428: $curl -s -L -k -o $opt_o/$basename.src.d/$url_file $url
michael@428: fi
michael@428: else
michael@428: verbose 3 "reusing: [FILE] $opt_o/$basename.src.d/$url_file"
michael@428: fi
michael@428: done
michael@428: for path in $opt_o/$basename.src.d/*.src.sh $opt_o/$basename.src.d/*.src.rpm; do
michael@428: if [ ! -f "$path" ]; then
michael@428: continue
michael@428: fi
michael@428: path_file=`echo $path | sed -e 's;^.*/\([^/]*\)$;\1;'`
michael@428: found=no
michael@428: for url in `cat $tmpdir/url.txt`; do
michael@428: url_file=`echo $url | sed -e 's;^.*/\([^/]*\)$;\1;'`
michael@428: if [ ".$url_file" = ".$path_file" ]; then
michael@428: found=yes
michael@428: break
michael@428: fi
michael@428: done
michael@428: if [ ".$found" = .no ]; then
michael@428: verbose 3 "removing: [FILE] $path"
michael@428: rm -f "$path"
michael@428: fi
michael@428: done
michael@428: rm -f $tmpdir/url.txt
michael@428:
michael@428: # generate XML/RDF index for SRPM packages
michael@428: verbose 3 "generating: [FILE] $opt_o/$basename.src.d/00INDEX.rdf"
michael@428: $openpkg index -r "OpenPKG/SRPM" \
michael@428: -o $opt_o/$basename.src.d/00INDEX.rdf \
michael@428: -i $opt_o/$basename.src.d
michael@428:
michael@428: # generate deployment utility
michael@428: verbose 3 "generating: [FILE] $opt_o/$basename.sh"; \
michael@428: section "$stk" "framework" >$tmpdir/framework.txt
michael@428: section "$stk" "prolog" >$tmpdir/prolog.txt
michael@428: section "$stk" "epilog" >$tmpdir/epilog.txt
michael@428: HAVE_PROLOG=no; if [ ".`cat $tmpdir/prolog.txt`" != . ]; then HAVE_PROLOG=yes; fi
michael@428: HAVE_EPILOG=no; if [ ".`cat $tmpdir/epilog.txt`" != . ]; then HAVE_EPILOG=yes; fi
michael@428: $openpkg build -r "$repo" -Z -u -K \
michael@428: `section "$stk" "packages"` | \
michael@428: grep -v "^#" | \
michael@428: grep -v "^echo" | \
michael@428: grep -v "^rm" | \
michael@428: egrep -v "^(if|fi)" | \
michael@428: grep -v "openpkg curl" | \
michael@428: grep -v "openpkg rpm -Uvh" | \
michael@428: sed -e 's;.*openpkg rpm ;;' \
michael@428: -e 's; || exit.*;;' \
michael@428: -e 's;--rebuild ;;' \
michael@428: -e 's;/.*/\([^/]*\.src\.rpm\);\1;' \
michael@428: -e 's;^\(.*\) \([^/]*\.src\.rpm\);\2 \1;' \
michael@428: -e "s;--define '\\([^ ]*\\) \\([^ ]*\\)';\\1=\\2;g" \
michael@428: -e 's;\.src\.rpm;;' \
michael@428: >$tmpdir/packages.txt
michael@428: sed <$0 \
michael@428: -e '1,/^____/d' \
michael@428: -e "/^CFG_FRAMEWORK=\"/r $tmpdir/framework.txt" \
michael@428: -e "/^CFG_PACKAGES=\"/r $tmpdir/packages.txt" \
michael@428: -e "s;@HAVE_PROLOG@;$HAVE_PROLOG;" \
michael@428: -e "/%prolog/r $tmpdir/prolog.txt" \
michael@428: -e "s;@HAVE_EPILOG@;$HAVE_EPILOG;" \
michael@428: -e "/%epilog/r $tmpdir/epilog.txt" \
michael@428: -e "/^## SHTOOL ##/r $shtool" \
michael@428: -e "s;^\\(CFG_NAME=\"\\).*\\(\"\\);\\1$name\\2;" \
michael@428: -e "s;^\\(CFG_SUMMARY=\"\\).*\\(\"\\);\\1$summary\\2;" \
michael@428: -e "s;^\\(CFG_PACKAGER=\"\\).*\\(\"\\);\\1$packager\\2;" \
michael@428: -e "s;^\\(CFG_VERSION=\"\\).*\\(\"\\);\\1$version\\2;" \
michael@428: -e "s;^\\(CFG_RELEASE=\"\\).*\\(\"\\);\\1$release\\2;" \
michael@428: -e "s;^\\(CFG_UNVERSIONED=\"\\).*\\(\"\\);\\1$opt_u\\2;" \
michael@428: >$opt_o/$basename.sh
michael@428:
michael@428: # cleanup
michael@428: rm -f $tmpdir/framework.txt
michael@428: rm -f $tmpdir/packages.txt
michael@428: rm -f $tmpdir/prolog.txt
michael@428: rm -f $tmpdir/epilog.txt
michael@428:
michael@428: # exit gracefully
michael@428: exit 0
michael@428:
michael@428: ##
michael@428: ## DEPLOYMENT SCRIPT
michael@428: ##
michael@428:
michael@428: ______________________________________________________________________________
michael@428: #!/bin/sh
michael@428: #![OpenPKG]
michael@428: ##
michael@428: ## OpenPKG Software Stack Deployment
michael@428: ## Copyright (c) 2010-2012 OpenPKG GmbH
michael@428: ##
michael@428: ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
michael@428: ## All rights reserved. Licenses which grant limited permission to use,
michael@428: ## copy, modify and distribute this software are available from the
michael@428: ## OpenPKG GmbH.
michael@428: ##
michael@428: ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
michael@428: ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
michael@428: ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
michael@428: ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
michael@428: ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@428: ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@428: ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
michael@428: ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
michael@428: ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
michael@428: ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
michael@428: ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@428: ## SUCH DAMAGE.
michael@428: ##
michael@428:
michael@428: ##
michael@428: ## COMMAND LINE PARSING
michael@428: ##
michael@428:
michael@428: str_usage="[-h|--help] [-v|--verbose ] [-c|--cleanup ] [-D|--define = ...] [-s|--srcdir ] [-o|--outdir ] [-t|--tmpdir ] [-S ]"
michael@428: arg_spec="0="
michael@428: opt_spec="h.v:c:D+s:o:t:S:"
michael@428: opt_alias="h:help,v:verbose,c:cleanup,D:define,s:srcdir,o:outdir,t:tmpdir,S:sudo"
michael@428: opt_h=no
michael@428: opt_v=3
michael@428: opt_c=1
michael@428: opt_D=""
michael@428: opt_s=""
michael@428: opt_o=""
michael@428: opt_t="${TMPDIR-/tmp}"
michael@428: opt_S=""
michael@428:
michael@428: # parse argument specification string
michael@428: eval `echo $arg_spec |\
michael@428: sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
michael@428:
michael@428: # parse option specification string
michael@428: eval `echo $opt_spec |\
michael@428: sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
michael@428:
michael@428: # parse option alias string
michael@428: eval `echo $opt_alias |\
michael@428: sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
michael@428:
michael@428: # interate over argument line
michael@428: opt_PREV=''
michael@428: while [ $# -gt 0 ]; do
michael@428: # special option stops processing
michael@428: if [ ".$1" = ".--" ]; then
michael@428: shift
michael@428: break
michael@428: fi
michael@428:
michael@428: # determine option and argument
michael@428: opt_ARG_OK=no
michael@428: if [ ".$opt_PREV" != . ]; then
michael@428: # merge previous seen option with argument
michael@428: opt_OPT="$opt_PREV"
michael@428: opt_ARG="$1"
michael@428: opt_ARG_OK=yes
michael@428: opt_PREV=''
michael@428: else
michael@428: # split argument into option and argument
michael@428: case "$1" in
michael@428: --[a-zA-Z0-9]*=*)
michael@428: eval `echo "x$1" |\
michael@428: sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
michael@428: opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
michael@428: eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
michael@428: ;;
michael@428: --[a-zA-Z0-9]*)
michael@428: opt_OPT=`echo "x$1" | cut -c4-`
michael@428: opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
michael@428: eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
michael@428: opt_ARG=''
michael@428: ;;
michael@428: -[a-zA-Z0-9]*)
michael@428: eval `echo "x$1" |\
michael@428: sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
michael@428: -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
michael@428: ;;
michael@428: -[a-zA-Z0-9])
michael@428: opt_OPT=`echo "x$1" | cut -c3-`
michael@428: opt_ARG=''
michael@428: ;;
michael@428: *)
michael@428: break
michael@428: ;;
michael@428: esac
michael@428: fi
michael@428:
michael@428: # eat up option
michael@428: shift
michael@428:
michael@428: # determine whether option needs an argument
michael@428: eval "opt_MODE=\$opt_MODE_${opt_OPT}"
michael@428: if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
michael@428: if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
michael@428: opt_PREV="$opt_OPT"
michael@428: continue
michael@428: fi
michael@428: fi
michael@428:
michael@428: # process option
michael@428: case $opt_MODE in
michael@428: '.' )
michael@428: # boolean option
michael@428: eval "opt_${opt_OPT}=yes"
michael@428: ;;
michael@428: ':' )
michael@428: # option with argument (multiple occurances override)
michael@428: eval "opt_${opt_OPT}=\"\$opt_ARG\""
michael@428: ;;
michael@428: '+' )
michael@428: # option with argument (multiple occurances append)
michael@428: eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
michael@428: ;;
michael@428: * )
michael@428: echo "$0: ERROR: unknown option: \`$opt_OPT'" 1>&2
michael@428: exit 1
michael@428: ;;
michael@428: esac
michael@428: done
michael@428: if [ ".$opt_PREV" != . ]; then
michael@428: echo "$0: ERROR: missing argument to option \`$opt_PREV'" 1>&2
michael@428: exit 1
michael@428: fi
michael@428:
michael@428: # process help option
michael@428: if [ ".$opt_h" = .yes ]; then
michael@428: echo "Usage: $0 $str_usage"
michael@428: exit 0
michael@428: fi
michael@428:
michael@428: # complain about incorrect number of arguments
michael@428: case $arg_MODE in
michael@428: '=' )
michael@428: if [ $# -ne $arg_NUMS ]; then
michael@428: echo "$0: ERROR: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
michael@428: exit 1
michael@428: fi
michael@428: ;;
michael@428: '+' )
michael@428: if [ $# -lt $arg_NUMS ]; then
michael@428: echo "$0: ERROR: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
michael@428: exit 1
michael@428: fi
michael@428: ;;
michael@428: esac
michael@428:
michael@428: # helper function for verbose messages
michael@428: verbose () {
michael@428: lvl="$1"
michael@428: msg="$2"
michael@428: if [ $opt_v -ge $lvl ]; then
michael@428: case "$lvl" in
michael@428: 1 ) str_prefix="**" ;;
michael@428: 2 ) str_prefix="++" ;;
michael@428: 3 ) str_prefix="--" ;;
michael@428: 4 ) str_prefix=".." ;;
michael@428: esac
michael@428: echo "${str_prefix} ${msg}"
michael@428: fi
michael@428: }
michael@428:
michael@428: # helper function for graceful termination
michael@428: die () {
michael@428: echo "$0: ERROR: $*"
michael@428: exit 1
michael@428: }
michael@428:
michael@428: ##
michael@428: ## MAIN
michael@428: ##
michael@428:
michael@428: # the stack information
michael@428: CFG_NAME=""
michael@428: CFG_SUMMARY=""
michael@428: CFG_PACKAGER=""
michael@428: CFG_VERSION=""
michael@428: CFG_RELEASE=""
michael@428:
michael@428: # the required OpenPKG framework parameters
michael@428: CFG_FRAMEWORK="
michael@428: "
michael@428:
michael@428: # the required OpenPKG packages
michael@428: # (in topological order and with build options resolved)
michael@428: CFG_PACKAGES="
michael@428: "
michael@428:
michael@428: # whether unversioned output directory should be used
michael@428: CFG_UNVERSIONED=""
michael@428:
michael@428: # display information
michael@428: verbose 1 "OpenPKG Software Stack Deployment"
michael@428: verbose 2 "determining information"
michael@428:
michael@428: # parse OpenPKG framework parameters
michael@428: params="
michael@428: prefix
michael@428: user group
michael@428: susr musr rusr nusr
michael@428: sgrp mgrp rgrp ngrp
michael@428: suid muid ruid nuid
michael@428: sgid mgid rgid ngid
michael@428: tag
michael@428: "
michael@428: for param in $params; do
michael@428: eval "CF_$param=''"
michael@428: done
michael@428: for opt in $CFG_FRAMEWORK; do
michael@428: case "$opt" in
michael@428: --[a-zA-Z0-9-]*=* )
michael@428: name=`echo "$opt" | sed -e 's;^--\([^=]*\)=.*$;\1;'`
michael@428: value=`echo "$opt" | sed -e 's;^--[^=]*=\(.*\)$;\1;'`
michael@428: eval "CF_$name='$value'"
michael@428: ;;
michael@428: esac
michael@428: done
michael@428: for define in $opt_D; do
michael@428: name=`echo "$define" | sed -e 's;=.*$;;'`
michael@428: value=`echo "$define" | sed -e 's;^.*=;;'`
michael@428: eval "CF_$name='$value'"
michael@428: done
michael@428: CFG_FRAMEWORK=''
michael@428: for name in $params; do
michael@428: eval "value=\"\$CF_$name\""
michael@428: if [ ".$value" != . ]; then
michael@428: if [ ".$CFG_FRAMEWORK" = . ]; then
michael@428: CFG_FRAMEWORK="--$name=$value"
michael@428: else
michael@428: CFG_FRAMEWORK="$CFG_FRAMEWORK --$name=$value"
michael@428: fi
michael@428: fi
michael@428: done
michael@428: if [ ".$CF_musr" = . ]; then CF_musr="$CF_user"; fi
michael@428: if [ ".$CF_mgrp" = . ]; then CF_mgrp="$CF_group"; fi
michael@428: if [ ".$CF_rusr" = . ]; then CF_rusr="$CF_user-r"; fi
michael@428: if [ ".$CF_rgrp" = . ]; then CF_rgrp="$CF_group-r"; fi
michael@428: if [ ".$CF_nusr" = . ]; then CF_nusr="$CF_user-n"; fi
michael@428: if [ ".$CF_ngrp" = . ]; then CF_ngrp="$CF_group-n"; fi
michael@428: verbose 3 "name: $CFG_NAME"
michael@428: verbose 3 "summary: $CFG_SUMMARY"
michael@428: verbose 3 "packager: $CFG_PACKAGER"
michael@428: verbose 3 "version: $CFG_VERSION"
michael@428: verbose 3 "release: $CFG_RELEASE"
michael@428:
michael@428: # determine target parameters
michael@428: if [ ".$CF_prefix" = . ]; then
michael@428: die "OpenPKG Framework parameter \"prefix\" required"
michael@428: fi
michael@428: prefix="$CF_prefix"
michael@428: if [ ".$CF_tag" = . ]; then
michael@428: die "OpenPKG Framework parameter \"tag\" required"
michael@428: fi
michael@428: tag="$CF_tag"
michael@428: shtool="$opt_t/$CFG_NAME-$CFG_VERSION-$CFG_RELEASE.shtool.sh"
michael@428: sed <$0 -e '1,/^## SHTOOL ##.*/d' >$shtool
michael@428: platform=`sh $shtool platform -n -L -S "" -C "+" -F '%-%'`
michael@428: verbose 3 "platform: $platform"
michael@428: verbose 3 "tag: $tag"
michael@428: verbose 3 "prefix: $prefix"
michael@428:
michael@428: # determine operation directories
michael@428: srcdir="$opt_s"
michael@428: if [ ".$srcdir" = . ]; then
michael@428: srcdir="$CFG_NAME-$CFG_VERSION-$CFG_RELEASE.src.d"
michael@428: fi
michael@428: tmpdir="$opt_t/$CFG_NAME-$CFG_VERSION-$CFG_RELEASE.d"
michael@428: if [ ! -d "$tmpdir" ]; then
michael@428: ( umask 077
michael@428: rm -rf "$tmpdir" >/dev/null 2>&1 || true
michael@428: sh $shtool mkdir -p -m 700 "$tmpdir" >/dev/null 2>&1
michael@428: if [ $? -ne 0 ]; then
michael@428: die "failed to create temporary directory: \"$tmpdir\""
michael@428: fi
michael@428: ) || exit $?
michael@428: fi
michael@428: outdir="$opt_o"
michael@428: if [ ".$outdir" = . ]; then
michael@428: if [ ".$CFG_UNVERSIONED" = .yes ]; then
michael@428: outdir="$CFG_NAME.$platform-$tag.d"
michael@428: else
michael@428: outdir="$CFG_NAME-$CFG_VERSION-$CFG_RELEASE.$platform-$tag.d"
michael@428: fi
michael@428: fi
michael@428: if [ ! -d "$outdir" ]; then
michael@428: sh $shtool mkdir -p -m 755 "$outdir" >/dev/null 2>&1
michael@428: if [ $? -ne 0 ]; then
michael@428: die "failed to create output directory: \"$outdir\""
michael@428: fi
michael@428: fi
michael@428: verbose 3 "srcdir: $srcdir"
michael@428: verbose 3 "outdir: $outdir"
michael@428: verbose 3 "tmpdir: $tmpdir"
michael@428:
michael@428: # execute prolog script
michael@428: if [ ".@HAVE_PROLOG@" = .yes ]; then
michael@428: verbose 2 "execute prolog script"
michael@428: cat >$tmpdir/prolog.sh </dev/null`
michael@428: if [ ".$check" != ".$pkg" ]; then
michael@428: # upgrade (regular)
michael@428: if [ ! -f "$outdir/$pkg.$platform-$tag.rpm" ]; then
michael@428: die "binary RPM package not existing: $outdir/$pkg.$platform-$tag.rpm"
michael@428: fi
michael@428: verbose 3 "UPGRADE: $outdir/$pkg.$platform-$tag.rpm"
michael@428: rpm_opt="-U"; if [ $opt_v -ge 4 ]; then rpm_opt="${rpm_opt}vh"; fi
michael@428: $opt_S $prefix/bin/openpkg rpm $rpm_opt \
michael@428: $outdir/$pkg.$platform-$tag.rpm || \
michael@428: die "failed to upgrade package: $outdir/$pkg.$platform-$tag.rpm"
michael@428: else
michael@428: # keep as-is
michael@428: verbose 3 "KEEP AS-IS: $pkg @ $prefix"
michael@428: fi
michael@428: fi
michael@428: else
michael@428: #
michael@428: # OpenPKG Packages
michael@428: #
michael@428: if [ ! -x "$prefix/bin/openpkg" ]; then
michael@428: # usually will not happen because of correctly
michael@428: # generated topologically correct package list
michael@428: die "command \"$prefix/bin/openpkg\" has to exit for building a regular OpenPKG package" 1>&2
michael@428: fi
michael@428: if [ ! -f $outdir/$pkg.$platform-$tag.rpm ]; then
michael@428: # build (regular)
michael@428: if [ ! -f "$srcdir/$pkg.src.rpm" ]; then
michael@428: die "source RPM package not existing: $srcdir/$pkg.src.rpm"
michael@428: fi
michael@428: verbose 3 "BUILD: $srcdir/$pkg.src.rpm"
michael@428: if [ ".$opts" != . ]; then
michael@428: verbose 4 "options: $opts"
michael@428: fi
michael@428: rm -rf "$tmpdir/$pkg" >/dev/null 2>&1 || true
michael@428: sh $shtool mkdir -p -m 755 "$tmpdir/$pkg" >/dev/null 2>&1
michael@428: cmd="$prefix/bin/openpkg --keep-privileges"
michael@428: cmd="$cmd rpm --rebuild"
michael@428: cmd="$cmd --define \"_specdir $tmpdir/$pkg\""
michael@428: cmd="$cmd --define \"_sourcedir $tmpdir/$pkg\""
michael@428: cmd="$cmd --define \"_builddir $tmpdir/$pkg\""
michael@428: cmd="$cmd --define \"_tmppath $tmpdir/$pkg\""
michael@428: cmd="$cmd --define \"_srcrpmdir $tmpdir/$pkg\""
michael@428: cmd="$cmd --define \"_rpmdir $outdir\""
michael@428: OIFS2="$IFS"; IFS="$DIFS"
michael@428: for opt in $opts; do
michael@428: opt_name=`echo "$opt" | sed -e 's;^\([^=]*\)=.*$;\1;'`
michael@428: opt_value=`echo "$opt" | sed -e 's;^[^=]*=\(.*\)$;\1;'`
michael@428: cmd="$cmd --define \"$opt_name $opt_value\""
michael@428: done
michael@428: IFS="$OIFS2"
michael@428: cmd="$cmd $srcdir/$pkg.src.rpm"
michael@428: if [ $opt_v -lt 4 ]; then cmd="$cmd >/dev/null 2>&1"; fi
michael@428: eval "$cmd" || \
michael@428: die "failed to build package \"$srcdir/$pkg.src.rpm\""
michael@428: fi
michael@428: check=`$prefix/bin/openpkg rpm -q "$name" 2>/dev/null`
michael@428: if [ ".$check" = ".package $name is not installed" ]; then
michael@428: # install (regular)
michael@428: if [ ! -f "$outdir/$pkg.$platform-$tag.rpm" ]; then
michael@428: die "binary RPM package not existing: $outdir/$pkg.$platform-$tag.rpm"
michael@428: fi
michael@428: verbose 3 "INSTALL: $outdir/$pkg.$platform-$tag.rpm"
michael@428: rpm_opt="-i"; if [ $opt_v -ge 4 ]; then rpm_opt="${rpm_opt}vh"; fi
michael@428: $opt_S $prefix/bin/openpkg rpm $rpm_opt \
michael@428: $outdir/$pkg.$platform-$tag.rpm || \
michael@428: die "failed to install package: $outdir/$pkg.$platform-$tag.rpm"
michael@428: elif [ ".$check" != ".$pkg" ]; then
michael@428: # upgrade (regular)
michael@428: if [ ! -f "$outdir/$pkg.$platform-$tag.rpm" ]; then
michael@428: die "binary RPM package not existing: $outdir/$pkg.$platform-$tag.rpm"
michael@428: fi
michael@428: verbose 3 "UPGRADE: $outdir/$pkg.$platform-$tag.rpm"
michael@428: rpm_opt="-U"; if [ $opt_v -ge 4 ]; then rpm_opt="${rpm_opt}vh"; fi
michael@428: $opt_S $prefix/bin/openpkg rpm $rpm_opt \
michael@428: $outdir/$pkg.$platform-$tag.rpm || \
michael@428: die "failed to upgrade package: $outdir/$pkg.$platform-$tag.rpm"
michael@428: else
michael@428: # keep as-is
michael@428: verbose 3 "KEEP AS-IS: $pkg @ $prefix"
michael@428: fi
michael@428: fi
michael@428: done
michael@428: IFS="$OIFS"
michael@428:
michael@428: # optionally remove residue packages from binary RPM package directory
michael@428: if [ $opt_c -lt 3 ]; then
michael@428: verbose 2 "cleanup target directory from residue packages"
michael@428: for pkg in $outdir/*.sh $outdir/*.rpm; do
michael@428: if [ ! -f "$pkg" ]; then
michael@428: continue
michael@428: fi
michael@428: pkg_base=`echo "$pkg" | sed -e 's;^.*/\([^/][^/]*-[0-9][^/-]*-[0-9][0-9.]*\)\.[^/][^/]*$;\1;'`
michael@428: erase=yes
michael@428: for spec in $CFG_PACKAGES; do
michael@428: spec_base=`echo "$spec" | sed -e 's;^\(.*-[^-][^-]*-[^-][^-]*\).*$;\1;'`
michael@428: if [ ".$pkg_base" = ".$spec_base" ]; then
michael@428: erase=no
michael@428: break
michael@428: fi
michael@428: done
michael@428: if [ ".$erase" = .yes ]; then
michael@428: verbose 3 "REMOVE: $pkg"
michael@428: rm -f "$pkg"
michael@428: fi
michael@428: done
michael@428: fi
michael@428:
michael@428: # optionally remove residue packages from OpenPKG instance
michael@428: if [ $opt_c -lt 3 ]; then
michael@428: verbose 2 "cleanup OpenPKG instance from residue packages"
michael@428: for pkg1 in `$prefix/bin/openpkg rpm -qa | egrep -v '^(openpkg-[0-9]|gpg-pubkey-)'`; do
michael@428: name1=`echo "$pkg1" | sed -e 's;^\(.*\)-[^-][^-]*-[^-][^-]*$;\1;'`
michael@428: erase=yes
michael@428: for spec in $CFG_PACKAGES; do
michael@428: name2=`echo "$spec" | sed -e 's;^\(.*\)-[^-][^-]*-[^-][^-]*.*$;\1;'`
michael@428: if [ ".$name1" = ".$name2" ]; then
michael@428: erase=no
michael@428: break
michael@428: fi
michael@428: done
michael@428: if [ ".$erase" = .yes ]; then
michael@428: verbose 3 "REMOVE: pkg1 @ $prefix"
michael@428: $opt_S $prefix/bin/openpkg rpm -e "$pkg1" || \
michael@428: die "failed to erase residue package \"$pkg1\""
michael@428: fi
michael@428: done
michael@428: fi
michael@428:
michael@428: # execute epilog script
michael@428: if [ ".@HAVE_EPILOG@" = .yes ]; then
michael@428: verbose 2 "execute epilog script"
michael@428: cat >$tmpdir/epilog.sh </dev/null 3>&1 || true
michael@428: rm -rf $tmpdir >/dev/null 2>&1 || true
michael@428:
michael@428: exit 0
michael@428:
michael@428: ## SHTOOL ###################################################################
michael@428: