#/bin/bash # This script was indeed self-updated! # Catch signals so we don't leave zombie tasks behind if we Ctrl^C # No idea why but it seems to prevent the script from working? Disable! #trap "exit" INT TERM ERR #trap "kill 0" EXIT BASEDIR="$HOME/.git-build" run() { p_name="$1" echo "[$p_name] RUN" # Run in background and redirect output to $p_name.log (GITBUILDCONF="$CONFDIR" GITBUILDDIR="$BASEDIR" nohup $BASEDIR/$p_name $p_name > $BASEDIR/$p_name.log 2> $BASEDIR/$p_name.err) & } # So scripts can know we're still running (for autoupdater) touch $BASEDIR/.LOCK # Overriden by -f/--force to force rebuild when no update is available FORCE=0 # Check if we have host-specific config then LOCAL=0 LOCAL=1 for folder in $BASEDIR/*/; do # Hidden folders (repos) are ignored by the pattern, so we can assume if a folder is not config/ then there are host-based configs here. [[ "$(basename $folder)" != "config" ]] && LOCAL=0 && break done # Pass either local or global config to the task [[ LOCAL = 1 ]] && CONFDIR=$BASEDIR/config || CONFDIR="$BASEDIR/$HOSTNAME" # Find targeted projects from args PROJECTS=() for arg in "$@"; do if [[ "$arg" = "-f" ]] || [[ "$arg" = "--force" ]]; then FORCE=1 # Maybe it's a task name and we find a corresponding source? elif [ -f $BASEDIR/$arg.source ]; then PROJECTS+=("$arg") # Maybe it's a repo URL and we find a corresponding task? elif matches="$(grep --files-with-matches --word-regexp "$arg" $BASEDIR/*.source)"; then # Iterate over the files found to extract the task name IFS= echo "$matches" | while read -r file; do task_name="$(basename "$file" .source)" # Make sure we don't have a .source file without name lying around, just in case [[ "$task_name" != "" ]] && PROJECT+=("$task_name") done else echo "ERROR: Unknown argument '$arg' (doesn't match a task name or source URL)" exit 1 fi done # If no project argument passed, default to all projects if [[ ${#PROJECTS[*]} = 0 ]]; then for project in $BASEDIR/*.source; do # Extract the project name from path PROJECTS+=("$(basename $project .source)") done fi for p_name in ${PROJECTS[*]}; do # Check if task should run on host if [[ $LOCAL = 0 ]]; then if [ -f $BASEDIR/$p_name.host ] && [[ "$(cat $BASEDIR/$p_name.host)" != "$HOSTNAME" ]]; then # The task is specifically configured for a different host, ignore echo "[$p_name] SKIPPED" continue fi # The task has a PROJECT.ignore file in host config, ignore [ -f $BASEDIR/$HOSTNAME/$p_name.ignore ] && echo "[$p_name] IGNORED" && continue fi echo "[$p_name] START" [ -f $BASEDIR/$p_name.branch ] && p_branch="$(cat $BASEDIR/$p_name.branch)" || p_branch="master" p_dir="$BASEDIR/.$p_name" if [ ! -d $p_dir ]; then source="$(cat $BASEDIR/$p_name.source)" echo "[$p_name] CLONE $source" # Don't forget the git submodules! git clone --recursive "$source" "$p_dir" [[ $? != 0 ]] && echo "[$p_name] CLONE FAILED" && exit 1 cd $p_dir if [[ "$p_branch" != "master" ]]; then echo "[$p_name] CHECKOUT BRANCH $p_branch" git checkout "$p_branch" [[ $? != 0 ]] && echo "[$p_name] CHECKOUT FAILED" && exit 1 fi run $p_name fi cd "$p_dir" # Refresh remote before comparing with local git fetch --quiet origin git diff --quiet remotes/origin/$p_branch if [[ $? != 0 ]]; then echo "[$p_name] PULL" # Update all submodules, for now only when the main repo changed (TODO) git pull --quiet --recurse-submodules [[ $? != 0 ]] && echo "[$p_name] PULL FAILED" && exit 1 run $p_name # If no update was found, we can still force rebuild with -f/--force elif [[ $FORCE = 1 ]]; then run $p_name fi done rm $BASEDIR/.LOCK