#!/bin/bash # Charlemagne Ports Command # # Douglas Thrift # # $Id$ # Copyright 2006 Douglas Thrift # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. source `dirname $0`/defaults function usage() { echo "Usage: `basename $0` [fetch|extract|build|package|install|sums|clean] ..." exit 1 } declare -a commands for arg in $@; do case $arg in (fetch|extract|build|package|install|sums|clean) commands[${#commands[*]}]=$arg ;; (*) usage ;; esac done [[ ${#commands[*]} -eq 0 ]] && usage port=`pwd` if [[ ! -r $port/port ]]; then echo "`basename $0`: No port found." 1>&2 exit 1 fi source $port/port # XXX: validate port files=$port/files source=$port/source package=$port/package function already() { echo "$bright$green||$reset $1 for $display $bright${green}already done$reset" 1>&2 } function begin() { echo "$bright$green>>$reset $1 for $display $bright${green}beginning$reset" 1>&2 } function warn() { echo "$bright$yellow!!$reset $1 for $display $bright$yellow$2$reset" 1>&2 } function fail() { if [[ $1 -ne 0 ]]; then echo "$bright$red!!$reset $2 for $display $bright$red$3$reset" 1>&2 exit $1 fi } function end() { echo "$bright$green<<$reset $1 for $display $bright${green}successful$reset" 1>&2 } function do_clean() { begin 'Cleaning' rm -frv $source $package $port/.{fetch,extract,build,package} fail $? 'Cleaning' 'failed cleaning' end 'Cleaning' } function do_fetch() { setup_sources if [[ -r $port/.fetch ]]; then if grep -q $target $port/.fetch; then already 'Fetching' return else do_clean fi fi begin 'Fetching' mkdir -p $source $package cd $source for ((index = 0; index != ${#sources[*]}; ++index)); do if grep -q '^.*://.*/' <<<${sources[$index]}; then if [[ ! -r $distfiles/$subdir/${source_files[$index]} ]]; then local mirror for mirror in ${!mirror_*}; do if eval "grep -q ^$(eval "escape \$$mirror") <<<\${sources[$index]}"; then local mirrors=${mirror/#mirror_/mirrors_} break fi done if [[ -z $mirrors ]]; then wget ${sources[$index]} else if ! wget ${sources[$index]}; then if eval "grep -qv ^$(eval "escape \${$mirrors[0]}") <<<\${sources[$index]}"; then local -i index_=0 else local -i index_=1 fi eval "local -i count=\${#$mirrors[*]}" for ((; index_ != count; ++index_)); do warn 'Fetching' "retrying from a different mirror" if [[ $index_ -eq 0 ]]; then eval "sources[$index]=\`sed -e \"s#\$$mirror#\${$mirrors[$index_]}#\" <<<\${sources[$index]}\`" else eval "sources[$index]=\`sed -e \"s#^\${$mirrors[$((index_ - 1))]}#\${$mirrors[$index_]}#\" <<<\${sources[$index]}\`" fi wget ${sources[$index]} && break done fi fi fail $? 'Fetching' "failed fetching ${source_files[$index]}" [[ -n $subdir ]] && mkdir -pv $distfiles/$subdir cp -v ${source_files[$index]} `realpath $distfiles/$subdir` else cp -v `realpath $distfiles/$subdir/${source_files[$index]}` ${source_files[$index]} fi fail $? 'Fetching' "failed fetching ${source_files[$index]}" else cp -v $files/${sources[$index]} ${source_files[$index]} fail $? 'Fetching' "failed fetching ${source_files[$index]}" fi done if [[ ${#sources[*]} -ne 0 ]]; then if [[ ${FUNCNAME[1]} == do_sums ]]; then warn 'Fetching' "not checking $port/sums file" elif [[ -r $port/sums ]]; then for ((index = 0; index != ${#source_files[*]}; ++index)); do local sum="$(grep "^[0-9a-f]\{32\} `escape ${source_files[$index]}`$" $port/sums)" if [[ -n $sum ]]; then md5sum -c <<<"$sum" fail $? 'Fetching' 'failed checking MD5 sums' else warn 'Fetching' "no MD5 sum for ${source_files[$index]} in $port/sums" fi done else warn 'Fetching' "no $port/sums file" fi fi end 'Fetching' echo $target > $port/.fetch } function do_extract() { do_fetch if [[ -r $port/.extract ]]; then already 'Extracting' return fi begin 'Extracting' cd $source for ((index = 0; index != ${#source_files[*]}; ++index)); do case ${source_files[$index]} in (*.tar.@(bz2|gz|Z)|*.tbz?(2)|*.tgz|*.zip) bsdtar -xvf ${source_files[$index]} ;; (*.tar.rz) rzip -dP ${source_files[$index]} bsdtar -xvf `sed -e 's/.rz$//' <<<${source_files[$index]}` ;; (*.bz2) bzip2 -dkv ${source_files[$index]} ;; (*.gz|*.Z) gzip -cdv ${source_files[$index]} > ${source_files[$index]%.gz} ;; (*.rz) rzip -dkP ${source_files[$index]} ;; (*.rpm) rpm_extract ${source_files[$index]} ;; (*) echo "not extracting ${source_files[$index]}" ;; esac fail $? 'Extracting' "failed extracting ${source_files[$index]}" done end 'Extracting' echo $target > $port/.extract } function do_build() { do_extract if [[ -r $port/.build ]]; then already 'Building' return fi begin 'Building' # XXX: dependency stuff! source $ports/functions : ${sourcedir:=$name-$version} cd $source build fail $? 'Building' 'failed building' end 'Building' echo $target > $port/.build } function do_package() { do_build if [[ -r $port/.package ]]; then already 'Packaging' return fi begin 'Packaging' cd $package for man in usr/@(X11R6|share|local)/man{,/*}/*/*.??(?)?(.gz); do if [[ -f $man ]] && [[ ! -h $man ]]; then local man_=${man##*/} for link in `find ${man%/*.??(?)?(.gz)} -maxdepth 1 -lname $man_ -or -not -wholename $man -samefile $man`; do rm -fv $link && ln -sv ${man_%.gz}.bz2 ${link%.gz}.bz2 fail $? 'Packaging' "failed relinking ${link%.gz}.bz2" done case $man in (*.gz) gzip -dv $man && bzip2 -v ${man%.gz} fail $? 'Packaging' "failed recompressing ${man/%.gz/.bz2}" ;; (*) bzip2 -v $man fail $? 'Packaging' "failed compressing $man.bz2" ;; esac fi done rm -fv usr/@(X11R6|share|local)/info{,/*}/dir?(.old) for info in usr/@(X11R6|share|local)/info{,/*}/*.info?(-+([0-9]))?(.gz); do if [[ -f $info ]] && [[ ! -h $info ]]; then local info_=${info##*/} for link in `find ${info%/*.info??(-+([0-9]))(.gz)} -maxdepth 1 -lname $info_ -or -not -wholename $info -samefile $info`; do rm -fv $link && ln -sv ${info_%.gz}.bz2 ${link%.gz}.bz2 fail $? 'Packaging' "failed relinking ${link%.gz}.bz2" done case $info in (*.gz) gzip -dv $info && bzip2 -v ${info%.gz} fail $? 'Packaging' "failed recompressing ${info/%.gz/.bz2}" ;; (*) bzip2 -v $info fail $? 'Packaging' "failed compressing $info.bz2" ;; esac fi done for perl in usr{,/{X11R6,local}}/lib/perl*; do find $perl -name .packlist -exec rm -fv '{}' + done rm -f +* # XXX: create other +files echo $description > +description echo $url > +url for ((index = 0; index != ${#depends[*]}; ++index)); do echo ${depends[$index]} >> +depends done for task in ${tasks[*]}; do if [[ -z ${task//@(deinstall|install|upgrade)/} ]]; then cp -v $port/$task +$task else warn 'Packaging' "unknown task: $task" fi done find !(+*) -not -type d -or -empty | sort > +filelist fail $? 'Packaging' 'failed creating file list' bsdtar --format pax -cjvf $packages/$target.tbz +* !(+*) fail $? 'Packaging' 'failed creating package file' for ((index = 1; index < ${#categories[*]}; ++index)); do ln -fsv ../$target.tbz ${categories[$index]/#/$packages/} fail $? 'Packaging' 'failed creating package symlink' done end 'Packaging' echo $target > $port/.package } function do_install() { do_package echo 'STUB: do_install' } # XXX: figure out how to handle different with/without source_files as well as different architectures (i.e. for the jre and jdk) function do_sums() { do_fetch begin 'Creating MD5 sums' if [[ ${#sources[*]} -ne 0 ]]; then cd $source md5sum ${source_files[*]} | tee $port/sums fail $PIPESTATUS 'Creating MD5 sums' 'failed creating MD5 sums' stat -c '%n %s' ${source_files[*]} > $port/sizes fail $? 'Creating MD5 sums' 'failed creating file sizes' else warn 'Creating MD5 sums' 'no source files' fi end 'Creating MD5 sums' } unset with_without for option in ${!with_*}; do if eval "[[ -n \$$option ]]"; then option=${option/#with_} grep -q $option <<<${with[*]} && with_without[${#with_without[*]}]=+$option else unset $option fi done for option in ${!without_*}; do if eval "[[ -n \$$option ]]"; then option=${option/#without_} grep -q $option <<<${without[*]} && with_without[${#with_without[*]}]=-$option else unset $option fi done ifs=$IFS IFS=, display="$bright$categories$reset/$bright$name $blue$version $black$revision ${magenta}_$cyan${with_without[*]}${magenta}_$reset" target="$categories/$name-$version-$revision-_${with_without[*]}_" IFS=$ifs unset ifs # XXX: assert correct $target format for command in ${commands[*]}; do case $command in (fetch) do_fetch ;; (extract) do_extract ;; (build) do_build ;; (package) do_package ;; (install) do_install ;; (sums) do_sums ;; (clean) do_clean ;; esac done