#!/bin/bash # (c) 2005-2007 Miklos Vajna # repoman for Frugalware # distributed under GPL License usage() { man repoman } msg() { echo -e "\033[1;32m==>\033[1;0m \033[1;1m$1\033[1;0m" >&2 } dry_run() { if [ -z "$dryrun" ]; then eval "$*" return $? else echo $* fi } check_servers() { server=$(eval "echo \$${reponame}_servers") if [ "$F_makepkg_scm" = "git" ]; then _server=`GIT_DIR=$fst_root/$reponame/.git git config --get remote.origin.url 2>/dev/null` if echo $_server |grep -q :/[^/]; then server=$_server fi else if [ -f "$fst_root/$reponame/_darcs/prefs/defaultrepo" ]; then server="`cat $fst_root/$reponame/_darcs/prefs/defaultrepo`" fi fi if echo $server |grep -q :/[^/]; then host=${server%:*} path=${server#*:} else die "The first server in the $reponame repo is read-only, please update the list of servers." fi } get_root() { local i if [ "$F_makepkg_scm" = "git" ]; then i=`git rev-parse --git-dir 2>/dev/null` echo `dirname $i` else i=`pwd` while true do if [ -e "$i/_darcs" ]; then break elif [ "$i" == "" ]; then break fi i=`echo $i|sed 's|\(.*\)/.*|\1|'` done echo $i fi } _set_lockname() { if [ -z "$F_makepkg_scm" -o "$F_makepkg_scm" = "git" ]; then lock=".git/lock" else lock="_darcs/lock" fi } delete() { local i files rmopts host check_servers sudouser=$(eval "echo \$${reponame}_sudo") if [ -n "$sudouser" ]; then sudo_cmd="$sudo_env -u $sudouser" else sudo_cmd="" fi # Strip leading / and any .. for i in $* do files="$files `echo $i|sed 's|^/||;s|\.\./||g'`" done if [ "$verbose" != 0 ]; then rmopts="-v" fi for i in $files do msg "Deleting file(s): $i" _set_lockname ssh $host "cd $path; if [ ! -e $lock ]; then $sudo_cmd rm $rmopts $path/$i; else echo \"Couldn't get lock.\"; fi" done } upload() { if [ "$#" -lt 2 ]; then echo "Too few parameters!" usage exit 1 fi check_servers sudouser=$(eval "echo \$${reponame}_sudo") if [ -n "$sudouser" ]; then sudo_cmd="$sudo_env -u $sudouser" else sudo_cmd="" fi # Strip leading / and any .. dest=`echo ${@:$#} |sed 's|^/||;s|\.\./||g'` for src in "${@:1:$#-1}" do name=`basename $src` msg "Requesting a temporary file" tmp=`ssh $host $mktemp_remote 2>/dev/null` msg "Uploading file: $src (to $tmp)" scp $src $host:$tmp if echo "`sha1sum $src|sed 's/\(.*\) .*/\1/'` $tmp" |ssh $host sha1sum -c - >/dev/null 2>&1; then msg "Copying to $dest" ssh $host "chmod 644 $tmp; $sudo_cmd cp $tmp $path/$dest/$name && rm $tmp" else echo "The uploaded file is corrupted :-/" ssh $host "rm $tmp" exit 1 fi done } fpmmerge() { if [ -z "$1" ]; then echo "fpmmerge needs a parameter! (a repo name to pull in fpms from)" usage exit 1 fi check_servers sudouser=$(eval "echo \$${reponame}_sudo") if [ -n "$sudouser" ]; then sudo_cmd="$sudo_env -u $sudouser" else sudo_cmd="" fi srcurl=$(eval "echo \$$1_servers") if [ -z "$srcurl" ]; then die "so such repo!" fi if ! ssh $host "cd $path/frugalware-$arch && $sudo_cmd rsync -avP `echo $srcurl|sed 's/^.*@//'`/frugalware-$arch/*.fpm ./"; then die "rsync failed! :/" fi # now push dg pull -a || die 'dg pull failed' git diff|grep -q -- 'diff --cc' && die 'detected conflicts' dg push -a # finally run repoman cl for each for i in `$0 -t $1 ls /frugalware-$arch/ 2>/dev/null|sed 's/-[^-]\+-[^-]\+-[^-]\+$//'` do cd `git rev-parse --git-dir`/../source/*/$i 2>/dev/null || continue $0 -t $reponame cl $i done } list() { check_servers for i in $* do msg "Fetching contents of directory: $i" ssh $host "ls $path/$i" ret=$? done exit $ret } split_group_pkg() { if echo $1 |grep -q '^[^/]\+/[^/]\+$'; then group=${1%/*} pkg=${1#*/} else group=$groups pkg=$1 fi } clean() { check_servers sudouser=$(eval "echo \$${reponame}_sudo") if [ -n "$sudouser" ]; then sudo_cmd="$sudo_env -u $sudouser" else sudo_cmd="" fi fdb=$(eval "echo \$${reponame}_fdb") [ -z "$fdb" ] && fdb="$reponame.fdb" for i in $* do # drop the group/ prefix if any i=${i#*/} msg "Cleaning up $i" ssh $host "`declare -f _check_nobuild`; cd $path/frugalware-$arch && \ _check_nobuild || arch=$arch $sudo_cmd updatesync del $fdb $i && \ genchangelog --clean $i" done } changelog() { msg "Generating Changelog for $1" split_group_pkg $1 check_servers sudouser=$(eval "echo \$${reponame}_sudo") if [ -n "$sudouser" ]; then sudo_cmd="$sudo_env -u $sudouser" else sudo_cmd="" fi fdb=$(eval "echo \$${reponame}_fdb") [ -z "$fdb" ] && fdb="$reponame.fdb" if [ "$verbose" == 1 ]; then catcmd="cat Changelog" else # just a workaround for the "syntax error near unexpected token `;'" bug catcmd="echo -n \"\"" fi _set_lockname ssh $host "`declare -f _check_nobuild`; \ options=\"${options[@]}\" cd $path; \ if [ ! -e $lock ]; then \ touch $lock; \ cd frugalware-$arch; \ if [ ! -e '$fdb' ]; then \ _check_nobuild || arch=$arch $sudo_cmd gensync ../source/$group/$pkg $fdb; \ else \ _check_nobuild || arch=$arch $sudo_cmd updatesync upd $fdb ../source/$group/$pkg/FrugalBuild; \ fi; \ cd $path; rm $lock; \ cd $path/source/$group/$pkg; arch=$arch $sudo_cmd genchangelog; \ $catcmd; \ else \ echo \"Couldn't get lock.\"; \ fi" } _keypress() { local old=$(stty -g) stty -icanon c=$(head -c1) stty "$old" echo $c } ask() { if [ -z "$noask" ]; then echo $* echo -n "Is this ok? [Y/n] " c=`_keypress` echo fi if [ -n "$noask" ] || [[ "(y|Y)?" =~ "$c" ]]; then eval "$*" fi } _check_nobuild() { # trick: we require subpkgs not to be set. this is because this way: # 1) kde-i18n and such pkgs (only the main pkg is a nobuild one) is # recgnized as a normal pkg # 2) opera and friends (where we use nobuild is there because of # license issues) will be recognized as a nobuild one if echo ${options[@]} | grep -q nobuild && [ -z "$subpkgs" ]; then return 0 else return 1 fi } _do_record() { if [ "$F_makepkg_scm" = "git" ]; then echo -e "$pkgname-$pkgver-$pkgrel-$arch $@" | git commit -a -F - . else root="`_get_root`" echo -e "`LANG= LC_ALL= date +"%a %b %d %H:%M:%S %Z %Y"` `cat $root/_darcs/prefs/author` $pkgname-$pkgver-$pkgrel-$arch $@" | darcs rec -a --pipe . fi } record() { echo -n "Checking FrugalBuild... " if fblint &>/dev/null; then echo "OK" else echo "Failed" exit 1 fi if [ -n "$*" ]; then _do_record $* else if [ "$F_makepkg_scm" = "git" ]; then dg what -s . ask "dg record --edit-long-comment -m '$pkgname-$pkgver-$pkgrel-$arch' ." else darcs what -s . ask "darcs record --edit-long-comment -m '$pkgname-$pkgver-$pkgrel-$arch' ." fi fi } # returns true if the file is a build log for some other arch (we should not remove them) _is_log() { local i for i in ${archs[@]} do [ $i = $arch ] && continue if echo $1 |grep -q "$i\.log\.bz2$"; then return 0 fi done return 1 } srcdel() { mydir=$(pwd|sed "s|$(get_root)||") for i in ${archs[@]} $arch do export CARCH=$i unset pkgver source for j in `set|grep ^_F_|sed 's/\(=.*\| ()\)//'`; do unset $j; done export startdir=`pwd` . FrugalBuild srclocal=(${srclocal[@]} ${source[@]}) done srclocal=(${srclocal[@]} ${signatures[@]}) if [ "$F_makepkg_scm" = "git" ]; then check_servers for i in $(ssh $host "[ -d $path/$mydir ] && cd $path/$mydir && git clean -n -x ."|sed 's/.* remove //') do if ! echo ${srclocal[@]} |grep -q $i && ! _is_log $i && [ "$i" != "Changelog" ]; then dry_run delete $mydir/$i fi done else srckeep=$($mktemp_local) darcsdir="_darcs/pristine" if ! $0 -t $reponame ls $darcsdir &>/dev/null; then darcsdir="_darcs/current" fi $0 -t $reponame ls $darcsdir/$mydir 2>/dev/null >$srckeep for i in $($0 -t $reponame ls $mydir 2>/dev/null) do if ! grep -q $i $srckeep && ! _is_log $i && [ "$i" != "Changelog" ]; then if ! echo ${srclocal[@]} |grep -q $i; then dry_run delete $mydir/$i fi fi done rm -f $srckeep fi } fpmdel() { fpmkeep=$($mktemp_local) fpmserver=$($mktemp_local) for i in $pkgname ${subpkgs[@]} do echo $i-$pkgver-$pkgrel-$arch.fpm >> $fpmkeep $0 -t $reponame ls frugalware-$arch 2>/dev/null |grep "^$i-[^-]\+-[^-]\+-$arch.fpm" >> $fpmserver done for i in $(cat $fpmserver) do if ! grep -q $i $fpmkeep; then dry_run delete frugalware-$arch/$i fi done rm -f $fpmkeep $fpmserver } sync() { ls *-$arch.fpm &>/dev/null && srcdel if ls *-$arch.fpm &>/dev/null; then for i in *-$arch.fpm do _check_nobuild || dry_run upload $i frugalware-$arch/ done fi modpkgname=$(echo $pkgname | sed 's/\+/\\+/g') if [ -n "$noask" ]; then opts="-a" else opts="" fi if [ "$F_makepkg_scm" = "git" ]; then cmd="dg pull $opts || (git diff|grep -q -- 'diff --cc' && echo 'detected conflicts'; die 'dg pull failed'); dg push $opts" else cmd="darcs push --match 'name $modpkgname' $opts" fi dry_run "$cmd" || die "push failed" # here we _could_ upload the new sources but that'll be done by changelog() buildlog="$pkgname-$pkgver-$pkgrel-$arch.log" if [ -f $buildlog -o -f $buildlog.bz2 ]; then [ -f $buildlog ] && dry_run bzip2 $buildlog _check_nobuild || dry_run upload $buildlog.bz2 source/$groups/$pkgname/ fi ls *-$arch.fpm &>/dev/null && fpmdel dry_run changelog $groups/$pkgname if [ "$1" == "-c" ]; then if [ "$F_makepkg_scm" = "git" ]; then git clean -x -d else rm -rvf *-$arch.fpm rm -vf *.log.bz2 rm -rf src fi fi } push() { if [ "$1" == "--clean" -o "$1" == "-c" ]; then clean="-c" shift 1 else clean="" fi dry_run record $* sync $clean } die() { echo -e "$0: $*" exit 1 } update() { if [ ! "`type -p rsync`" ]; then die "The rsync program is missing. Please install it with pacman-g2 -S rsync." elif [ ! "`type -p git`" ]; then die "The git program is missing. Please install it with pacman-g2 -S git." fi for i in ${repos[@]} do pushonly=$(eval "echo \$${i}_pushonly") [ "$pushonly" = "y" ] && continue # Search for a server. eval "servers=(\${${i}_servers[@]})" if [ -z "$servers" ]; then echo -e "$0: Can't find any server!" if [ -e /etc/repoman.conf.pacnew ]; then echo -e "$0: HINT: merge the contents of /etc/repoman.conf.pacnew to /etc/repoman.conf!" fi exit 1 fi echo ":: Synchronizing source trees..." for j in ${servers[@]} do echo "warning: this operation can take minutes, please be patient" # support upgraders if [ -d $fst_root/$i -a ! -d $fst_root/$i/.git ]; then rm -rf $fst_root/$i fi # check for scm if rsync -q $j/.git 2>/dev/null; then if [ -d $fst_root/$i/.git ]; then cmd="cd $i && git pull" else cmd="git clone $j/.git $i" fi elif rsync -q $j/_darcs 2>/dev/null; then cmd="rsync -azvP $j/_darcs/current/ $i" else echo "This server ($j) does not support git nor darcs." echo "HINT: if you are upgrading from a previous version of Frugalware, try running 'rm -rf /var/fst/' and 'repoman upd'." continue fi mkdir -p $fst_root cd $fst_root if [ "$verbose" != 1 ]; then echo -n "$i... " eval $cmd &>/dev/null ret=$? else echo "$i..." eval $cmd ret=$? fi if [ $ret != 0 ]; then echo "failed." else echo "done." break fi done done } chk_updated() { if [ ! -d $1 ]; then echo "ERROR: Could not find FrugalBuild scripts in $1" echo " have you used 'repoman upd' yet?" exit 1 fi } search() { chk_updated $fst_root [ -z "$*" ] || grepcmd="|grep $*" for i in ${repos[@]} do eval "find $fst_root/$i/source -name FrugalBuild |xargs grep '\(options=(.*nobuild.*)\|^nobuild=\)' |sed 's|$fst_root/||;s|/source/[^/]*||;s|/FrugalBuild:.*||' $grepcmd" done } merge() { local i repo target if echo $1 |grep -q /; then repo=${1%/*} target=${1#*/} else repo="${repos[@]}" target=$1 fi # install essential packages if necessary echo -n "checking for essential packages... " . /etc/makepkg.conf for i in "$COREPKGS" do missing="$missing `pacman -Sg $i |grep -v '^\w'` " done missdep=`pacman-g2 -T $missing` ret=$? if [ "$ret" != "0" ]; then echo "failed" echo "Use the following command to install the missing packages:" echo "pacman-g2 -S `echo $missdep| sed 's|.\+: ||g;s|=.*$||;s|>.*$||;s|<.*$||'`" exit 1 else echo "done" fi found=0 for i in ${repo[@]} do # sanility checks chk_updated $fst_root/$i pushonly=$(eval "echo \$${i}_pushonly") [ "$pushonly" = "y" ] && continue dir=`find $fst_root/$i -maxdepth 4 -type d -name "$target"|sed -n '$ p'` if [ -z "$dir" ]; then continue else found=1 cd $dir makepkg $makepkg_opts fi done [ "$found" = 0 ] && die "package '$target' not found" } [ -e /etc/repoman.conf ] && . /etc/repoman.conf || \ die "Can't find /etc/repoman.conf!" if [ -e FrugalBuild ]; then [ -e /usr/lib/frugalware/fwmakepkg ] && . /usr/lib/frugalware/fwmakepkg || \ die "Can't find /usr/lib/frugalware/fwmakepkg!" [ -e /etc/makepkg.conf ] && . /etc/makepkg.conf || \ die "Can't find /etc/makepkg.conf!" . FrugalBuild fi # Initializating variables. version='0.3.1' [ -z "$arch" ] && arch=`uname -m` if [ -n "$REMOTEHOME" ]; then mktemp_remote="mktemp -p $REMOTEHOME" else mktemp_remote="mktemp -p $HOME" fi mktemp_local="mktemp -p $HOME" sudo_env="sudo -E" if [ "$F_makepkg_scm" = "git" ]; then # Checking for git. which git >/dev/null 2>&1 if [ $? != 0 ]; then echo "ERROR: Can't find git. You can install it with pacman-g2 -S git." exit 1 fi else # Checking for darcs. which darcs >/dev/null 2>&1 if [ $? != 0 ]; then echo "ERROR: Can't find darcs. You can install it with pacman-g2 -S darcs." exit 1 fi fi # Pharsing parameters. if [ $# -le 0 ]; then usage exit 0 fi # default for the -t parameter reponame=${repos[0]} while [ "$1" != "" ]; do case $1 in -h|--help) usage exit 0 ;; -v|--verbose) verbose=1 ;; --version) echo repoman $version exit 0 ;; -t|--tree) shift 1 reponame=$1 ;; -k) noask=1 ;; -d|--dry-run) dryrun=1 ;; -*) echo "Wrong parameter!" usage exit 1 ;; cl|changelog) shift 1 changelog $* ;; c|clean) shift 1 clean $* ;; del|delete) shift 1 delete $* ;; ls|list) shift 1 list $* exit 0 ;; m|merge) shift 1 merge $* ;; fpmmerge) shift 1 fpmmerge $* ;; up|upload) shift 1 upload $* ;; upd|update) shift 1 update $* ;; s|search) shift 1 search $* ;; rec|record) shift 1 record $* ;; push) shift 1 push $* ;; sync) shift 1 sync $* ;; esac shift 1 done