#!/bin/bash # Simple ports tracker # # Johannes Winkelmann, jw at smts dot ch STATE_DIR=.spt-state-dir PORT=port PARENT_PATH=parent SPT_CONF=$HOME/.sptrc DEFAULT_BASE=~/.spt-master-trees STATE_DIR_PATH="" TRACK_DIR="" error() { echo "Error: $@" >&2 } transform_path() { echo $1|sed -e 's|/|_|g' } retransform_path() { echo $1|sed -e 's|_|/|g' } get_parent() { cat $TRACK_DIR/$PARENT_PATH } find_state_dir() { old=`pwd` while [ ! `pwd` = "/" ]; do if [ -d $STATE_DIR ]; then STATE_DIR_PATH=`pwd` cd $old return 0 fi cd .. done echo "Failed to find STATE_DIR" exit 1 } find_track_dir() { find_state_dir delta=` pwd|sed -e "s|^$STATE_DIR_PATH/\?||g"` TRACK_DIR="$STATE_DIR_PATH/$STATE_DIR/"`transform_path $delta` if [ ! -d $TRACK_DIR -a ! "$1" = "nofail" ] || [ "$TRACK_DIR" = "$STATE_DIR_PATH/$STATE_DIR/" ]; then echo "Failed to find track dir for current working directory. Exiting" exit 1 fi } # -- commands do_init() { if [ $1 ]; then cd $1 fi mkdir $STATE_DIR } do_untrack() { find_track_dir $1 rm -rf $TRACK_DIR } do_track() { find_track_dir "nofail" do_untrack "nofail" mkdir $TRACK_DIR cp -r $1 $TRACK_DIR/$PORT # TODO: make sure $1 is absolute echo $1 > $TRACK_DIR/$PARENT_PATH } do_diff() { find_track_dir if [ "x$1" = "x-a" ]; then arg=N elif [ "x$1" = "x" ]; then arg=q else file="/$1" fi if [ ! -d $TRACK_DIR ]; then echo "`pwd` is currently not tracked. Exiting" exit 1 fi parent=`cat $TRACK_DIR/$PARENT_PATH` if [ ! -d "$parent" ]; then error "Parent $parent does not exist" else diff -${arg}ru $TRACK_DIR/port/$file $parent$file|\ sed -e "s|$STATE_DIR_PATH/$STATE_DIR/\?||g" fi } do_cat() { find_track_dir parent=`cat $TRACK_DIR/$PARENT_PATH` cat $parent/$1 } do_merged() { find_track_dir parent=`cat $TRACK_DIR/$PARENT_PATH` do_track $parent } do_fetch() { base=$(basename $1) cp -r $1 $base cd $base do_track $1 } do_fetch-file() { find_track_dir parent=`cat $TRACK_DIR/$PARENT_PATH` cp -r $parent/$1 . } do_check() { find_state_dir for d in $STATE_DIR_PATH/$STATE_DIR/*; do parent=`cat $d/$PARENT_PATH` port=`echo $d|sed -e "s|$STATE_DIR_PATH/$STATE_DIR/||g"` port=`echo $port|sed -e 's|_|/|g'` if [ ! -d $parent ]; then echo "D $port" else (cd $STATE_DIR_PATH/$port; if [ -n "$(do_diff)" ]; then echo "M $port" else echo "= $port" fi ) fi done } ### # rc handling # # repo type must be the first argument in the repo string. The rest is # type specific # Add both an add_repo_ and a do_sync_ to implement a new type # Important: always sync to 'base_dir' # # Note: this could be extracted add_repo_rsync() { repos="$repos rsync|$1|$2::$3" } do_sync_rsync() { name=$(echo $1|sed -e 's/|.*//') url=$(echo $1|sed -e 's/.*|//') echo "rsync: $name $url" rsync -az $url $base_dir/$name } add_repo_httpup() { repos="$repos httpup|$1|$2" } do_sync_httpup() { name=$(echo $1|sed -e 's/|.*//') url=$(echo $1|sed -e 's/.*|//') httpup sync $url $base_dir/$name } repo() { name=$1 type=$2 if [ -z "$name" ]; then echo "Skipping empty add_repo call (check your sptrc)" elif [ -z "$type" ]; then echo "Skipping repository '$name' with no type" else shift 2 add_repo_$type $name $@ fi } do_sync-masters() { base_dir=$DEFAULT_BASE repos="" . $SPT_CONF echo "Syncing masters to $base_dir" mkdir -p $base_dir for r in $repos; do type=$(echo $r|sed -e 's/|.*//') remainder=$(echo $r|sed -e 's/[^|]*|//') do_sync_$type $remainder done } command=do_$1 shift if [ "`type -t $command`" = "function" ]; then set -e $command $@ else echo "Usage: blah" fi