diff --git a/git-build.sh b/git-build.sh index 0a4532b..43e84a9 100755 --- a/git-build.sh +++ b/git-build.sh @@ -14,17 +14,21 @@ DEBUG=0 # We set custom logging functions so that later we can decorate stuff warn() { - echo -e "\e[33mWARNING:\e[0m $@" > /dev/stderr + [[ $INFO = 1 ]] && echo -e "\e[33mWARNING:\e[0m $@" > /dev/stderr } info() { - echo "[git-build] $@" + [[ $INFO = 1 ]] && echo "[git-build] $@" } error () { echo -e "\e[31mERROR:\e[0m $@" > /dev/stderr } +debug () { + [[ $DEBUG = 1 ]] && echo -e "\e[36mDEBUG:\e[0m $@" +} + # Logging is done with the LOG="debug|info|error" environment variable if [ ! -z $LOG ] && [ "$LOG" != "" ]; then case $LOG in @@ -35,6 +39,7 @@ if [ ! -z $LOG ] && [ "$LOG" != "" ]; then INFO=0 ;; "info"|"INFO") + # Default settings ;; *) warn "\$LOG is \"$LOG\" which is not understood to be a logging level." @@ -44,19 +49,20 @@ fi run() { p_name="$1" - info "[$p_name] RUN" + info "$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) -# TODO needs to be reworked so multiple instances can run at the same time +# TODO needs to be reworked so multiple instances can run at the same time https://tildegit.org/southerntofu/git-build.sh/issues/13 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 +# TODO: maybe we should just match for $BASEDIR/$HOSTNAME directly? Would allow to fallback to global config for multihost setup where one host is not configured.. but is that desired? Also enables to have more folders in $BASEDIR (maybe logs/) 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. @@ -64,15 +70,18 @@ for folder in $BASEDIR/*/; do done # Pass either local or global config to the task -[[ LOCAL = 1 ]] && CONFDIR=$BASEDIR/config || CONFDIR="$BASEDIR/$HOSTNAME" +[[ LOCAL = 1 ]] && CONFDIR=$BASEDIR/config || CONFDIR="$BASEDIR/$HOSTNAME" && info "Using config: $CONFDIR" -# Find targeted projects from args +# Find targeted projects from args and extra arguments PROJECTS=() for arg in "$@"; do if [[ "$arg" = "-f" ]] || [[ "$arg" = "--force" ]]; then + info "Running task(s) regardless of updates (--force)" FORCE=1 # Maybe it's a task name and we find a corresponding source? + # TODO: Support source-less tasks https://tildegit.org/southerntofu/git-build.sh/issues/8 elif [ -f $BASEDIR/$arg.source ]; then + debug "Found task $arg" 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 @@ -80,64 +89,88 @@ for arg in "$@"; do 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") + if [[ "$task_name" != "" ]]; then + debug "Found task $arg from URL $arg" + PROJECT+=("$task_name") + fi done else - echo "ERROR: Unknown argument '$arg' (doesn't match a task name or source URL)" + error "Unknown argument/task '$arg' (no such task or source)" exit 1 fi done # If no project argument passed, default to all projects if [[ ${#PROJECTS[*]} = 0 ]]; then - for project in $BASEDIR/*.source; do + info "No project was specified. Trying all projects" + # TODO: sourceless tasks + for file in $BASEDIR/*.source; do # Extract the project name from path - PROJECTS+=("$(basename $project .source)") + task="$(basename $file .source)" + debug "Found task $task" + PROJECTS+=("$task") done fi + +# TODO: sourceless tasks for p_name in ${PROJECTS[*]}; do + debug "Start processing task $p_name" # 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" + debug "$p_name: SKIPPED for current host" continue fi # The task has a PROJECT.ignore file in host config, ignore - [ -f $BASEDIR/$HOSTNAME/$p_name.ignore ] && echo "[$p_name] IGNORED" && continue + [ -f $BASEDIR/$HOSTNAME/$p_name.ignore ] && info "$p_name: IGNORED for current host ($HOSTNAME)" && continue fi - echo "[$p_name] START" - [ -f $BASEDIR/$p_name.branch ] && p_branch="$(cat $BASEDIR/$p_name.branch)" || p_branch="master" + info "$p_name: PROCESS" + # TODO: Should be able to switch branch after a repo was cloned + if [ -f $BASEDIR/$p_name.branch ]; then + p_branch="$(cat $BASEDIR/$p_name.branch)" + info "$p_name: Using branch $p_branch" + else + p_branch="master" + debug "$p_name: Defaulting to branch master" + fi p_dir="$BASEDIR/.$p_name" if [ ! -d $p_dir ]; then source="$(cat $BASEDIR/$p_name.source)" - echo "[$p_name] CLONE $source" + info "$p_name: CLONE $source" # Don't forget the git submodules! git clone --recursive "$source" "$p_dir" - [[ $? != 0 ]] && echo "[$p_name] CLONE FAILED" && exit 1 + [[ $? != 0 ]] && error "$p_name: CLONE failed" && exit 1 cd $p_dir if [[ "$p_branch" != "master" ]]; then - echo "[$p_name] CHECKOUT BRANCH $p_branch" + debug "$p_name: Checking out branch $p_branch" git checkout "$p_branch" - [[ $? != 0 ]] && echo "[$p_name] CHECKOUT FAILED" && exit 1 + [[ $? != 0 ]] && error "$p_name: CHECKOUT failed" && exit 1 fi run $p_name + # Skip to the next task! + continue fi + debug "$p_name: Task source already downloaded, checking for updates" 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" + info "$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 + debug "$p_name: Forcing run despite no update found" run $p_name + else + debug "$p_name: No updates found" fi done +# TODO: better locking mechanism rm $BASEDIR/.LOCK