#!/bin/sh

# Script for show current tasks and task status for ALT Linux build system
# (c) 2014-2015, 2020 Andrey Cherepanov <cas@altlinux.org>

ver="1.5.10"

# Usage: girar-show [<task num>]
# <task num> can contains suffix @ for subtasks list or @<subtask> to specified subtask log 

# Note: you should have access to gyle.altlinux.org to show you own tasks

source="$1"

default_build_host="gyle.altlinux.org"

# Print girar build host from ~/.ssh/config
function get_build_host_from_config {
        cat $HOME/.ssh/config | \
        sed -nr 's/^[[:space:]]*(host(|name))[[:space:]]*/\1 /Ip' | \
        grep -i "^HostName $default_build_host$" -B1 | \
        sed -n 's/^Host //p' | \
        head -1
}

# Return girar build host from ~/.ssh/config or $GIT_ALT, check it or exit with error
function get_build_host {
        local dhost="$(get_build_host_from_config)"
        if [ -n "$GIT_ALT" ]; then
                dhost="$GIT_ALT"
        fi
        if [ -z "$dhost" ]; then
                echo 'Unable to get build host name from ~/.ssh/config or $GIT_ALT' >&2
                exit 1
        fi
        # Check for ssh work
        ssh -n "$dhost" help >/dev/null 2>&1
        if [ $? -ne 0 ]; then
                echo "Host '$dhost' is not properly configured for work with $default_build_host" >&2
                exit 1
        fi

        echo "$dhost"
}

GIT_ALT="$(get_build_host)"

# Regular expressions
re_errors="^\(E:\|error[ (#0-7)]*:\|.*: error:\|.*: fatal error:\|.*: NEW unmet\|[[:alnum:]._-]\+\#[[:alnum:]._:-]*\|.* FAILED --\|Can't locate [[:alnum:]]\+.pm in @INC\|Package .* has broken dep on\)[[:space:]].*$"
re_subtasks="^#[0-7]\+ .*$"

list="$(expr match "$source" ".*\(@\)")"
subtask="${source/*@}"
task="${source/@*}"
exclude=""

filter_list=""
if [ -n "$list" ] ; then
	filter_list="$re_subtasks"
else
	subtask=""
fi

# Highlight by pattern and specified ANSI color code
hl() {
  pattern="$1"
  shift
  color="$1"
  shift
  esc=$(printf "\033")
  sed 's"'"${pattern}"'"'$esc'['${color}'m&'$esc'[0m"g' "$@"
}

# Highlight all output in red (treat string as error)
hlerror() {
	echo "$1" | hl '^.*$' '31' >&2
}

output_exclude() {
	if [ -n "$1" ]; then
		sed -n '/^#[0-7]\+ removed$/d;/ :: .*FAILED$/p;/ :: /d;p' | grep -v '^#[0-7]\+ .* -> .*$'
	else
		grep -v '^#[0-7]\+ removed$' | grep -v '^#[0-7]\+ .* -> .*$'
	fi
}

ctime="$(date +'%s')"

# Show complete task list without any arguments
if [ -z "$task" -o "$task" = "-t" ]; then
	ssh -n "$GIT_ALT" task ls | sed 's/^#//' | while read l
	do
		num="$(echo $l | cut -f1 -d ' ')"
		status="$(echo $l | cut -f2 -d ' ')"

		# Show day from last build
		if [ "$task" = "-t" ];then
			task_date=`date -d "$(curl -sI http://git.altlinux.org/tasks/$num/ | sed -n 's/Last-Modified: //p')" +'%s'`
			days="$(expr \( $ctime - $task_date \) / 86400)"
			l="$days $l"
		fi

		case "$status" in
			BUILDING|COMMITTING)
				echo -e "\033[33m$l\033[0m"
				;;
			AWAITING|POSTPONED)
				echo -e "\033[36m$l\033[0m"
				;;
			TESTED)
				echo -e "\033[32m$l\033[0m"
				;;
			FAILED)
				echo -e "\033[35m$l\033[0m"
				;;
			*)
				echo "$l"
				;;
		esac
	done
	exit
fi

# Check supported argements
if [ -z "$(echo "$task" | egrep '^(-t|-h|--help|--version|[0-9]+@?[0-9]*)$')" ]; then
	hlerror "Error: bad argument $task"
	task="-h"
fi

# Show help usage
if [ "$task" = "--help" -o "$task" = "-h" ]; then
	prg_name="${0##*/}"
	cat << _USAGE_
Usage: $prg_name [<source>]

Supported sources:
 without source      Show all active user tasks (requires access to gyle.altlinux.org)
 <task num> 	     Show task brief log
 <task num@>	     Show subtask list
 <task num@!>	     Show statistics and possible errors in task log
 <task num@subtask>  Show specified subtask log
 -t                  Show all active user tasks preceding with days from last build
 --help or -h	     Show usage and exit
 --version	     Show version
_USAGE_
	exit
fi

# Show version
if [ "$task" = "--version" ]; then
	echo "$ver"
	exit
fi

# Show specifies task content
if [ -n "$task" ]; then

	if [ "$subtask" = '!' ]; then
		# Show only possible errors, subtask headers and common subtask statistics (contains ::)
		filter_list="${re_errors/\\)/\\|#[0-7]\\+\\|.*::\\)}"
		exclude="yes"
		subtask=""
	fi

	if [ -n "$subtask" ] ; then
		# Show complete subtask log
		target="http://git.altlinux.org/tasks/$task/build/$subtask/i586/log"
		filter_list=""
	else
		# Show task log
		# Test url for availability
		if [ "$(curl --write-out %{http_code} -s "http://git.altlinux.org/tasks/$task/info.json" -o /dev/null)" != "200" ]; then
			hlerror "Task log for $task is missing"
			exit 1
		fi
		try="$(curl -s http://git.altlinux.org/tasks/$task/info.json | python -c 'import json,sys;obj=json.load(sys.stdin);print "%d.%d" % (obj["try"],obj["iter"])')"
		if [ -z "$try" ] ; then
			hlerror "Unable to show log for task #$task"
			exit 1
		fi
		target="http://git.altlinux.org/tasks/$task/logs/events.$try.log"
	fi

	# Test url for availability
	if [ "$(curl --write-out %{http_code} -s "$target" -o /dev/null)" != "200" ]; then
		hlerror "Unknown source $source"
		exit 1
	fi

	curl -s "$target" | \
	        grep --color=never "$filter_list" | \
		output_exclude "$exclude" | \
		hl "$re_subtasks" '33' | \
		hl "$re_errors"   '31'
	exit
fi
