#!/bin/bash
# vim: sw=2:ts=2:sts=2

# abb is command-line client for abf <http://abf.rosa.ru>
# Copyright (C) 2012 alexander barakin aka sash-kan <alex@barak.in>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# defaults:

# using proto (http|https)
proto=https
# server
server=abf.rosa.ru
# yes yes!
export GIT_SSL_NO_VERIFY=true
# owner of repo (user name or group name)
owner=import
# default branch
branch=rosa13
# default remote
remote=origin
# insecure:
#auth=user:password
# more secure, but very-very uncomfortable:
#auth=user
# default rpmbuild action
action="-bb"
# name of abf yml file to store sha1sums
abfyml=".abf.yml"
# write buildlog (any, even empty value, cancels log creation)
buildlog=yes
# do restore after clone (always,ask,none)
restore=always
# limit rows of "status" output
rows=4
# interval (seconds) to refresh "status" output
refresh=120
# path to spec skeleton
defaultspec=/usr/share/abb/spek.skel
# build arch
arch="i686,x86_64,aarch64"
# platform
platform=rosa13
# repos to include from platform (f.e. "repos=main,contrib")
repos=
# update type (security bugfix enhancement recommended newpackage)
updatetype=security
# hash of commit to remote build
commit=
# auto publish (true|false)
publish=false
# repo to save
# in form "platform/repo"
# f.e.:
# "username_personal/main" (simply "personal")
# "rosa2012.1/contrib" (simply "rosa2012.1"
# if project default repo is "contrib" for platform "rosa2012.1")
reposave=
# server api part
serverapi=api/v1
# if used wrapper from /etc/profile.d/abb.bash.profile,
# cd to project dir after clone one project
cdafterclone=yes

# get user settings
# first look in ~/.abbrc
[ -f ~/.abbrc ] && . ~/.abbrc
# if it does not exist then look for .abbrc in curdir
[ ! -f ~/.abbrc -a -f .abbrc ] && . .abbrc
# if both do not exist, using defaults written above

usage() {
	[ $# == 1 ] && echo -e "$1"
  cat <<EOT
usage:
$0 clone <name of project>
$0 build [<name of project>]
$0 restore [<name of project>]
$0 store <name of file>

settings are in ~/.abbrc
see readme, please!
EOT
	exit 1
}

yesno() {
	local cont
	read -p "$@ is it ok? (Y|n): " cont
	[ "${cont}" == "" -o "${cont}" == "y" -o "${cont}" == "Y" ] && return 0
	return 1
}

get_project_from_curdir() {
	# believe that we are in a directory with the source
	#project=$(basename $PWD)
	# more smart method
	# 1. try git
	project=$(git config remote.origin.url | sed -rn '/.*'${owner}'\/[^\/]*$/{s/\.git$//;s!^.*/!!;p}')
	if [ -n "${project}" ]; then
		[ "${silent}" == "1" ] || echo "assume project name from git url: ${project}"
	elif [ $(ls *.spec 2>/dev/null | wc -l) -eq 1 ]; then
		# 2. try spec name
		project=$(basename $(ls *.spec) .spec)
		[ "${silent}" == "1" ] || echo "assume project name from spec-file name: ${project}"
	elif [ $# -eq 1 -a "$1" == "nodir" ]; then
		:
	else
		# 3. assume that project == current dir
		project=$(basename $PWD)
		[ "${silent}" == "1" ] || echo "assume project name from name of curdir: ${project}"
	fi
}

do_restore() {
	if [ ${in_proj_dir} -eq 0 ]; then
		pushd "$project" >/dev/null || return 1
	fi
	local file sha
	echo "try to restore files from abf storage"
	if [ "${abfyml}" == "" ]; then
		echo "error: name of abf yml file not specified"
		echo "for example:"
		echo "$0 $command abfyml=.abf.yml"
	else
		if [ -e "${abfyml}" ]; then
			echo "parsing file '${abfyml}'"
			sed -rn '$G;s/^[\"'\''[:space:]]*([^[:space:]:\"'\'']+)[\"'\''[:space:]]*.*[\"'\''[:space:]]*([0-9a-fA-F]{40})[\"'\''[:space:]]*$/\1 \2/p' ${abfyml} | \
			while read file sha; do
				#echo -n "found entry: file=${file} sha1sum=${sha} ... "
				echo -n "found entry: file=${file} ... "
				if [ -e ${file} ]; then
					if echo "${sha}  ${file}" | sha1sum -c --status; then
						echo "ok"
					else
						echo "sha1sum INCORRECT! skipping..."
					fi
				else
					echo -n "try to download... "
					if wget -qO - "http://file-store.rosa.ru/download/${sha}" > "${file}"; then
						echo "ok"
						echo -n "check sum... "
						if echo "${sha}  ${file}" | sha1sum -c --status; then
							echo "ok"
						else
							echo "sha1sum INCORRECT! skipping..."
						fi
					else
						echo "filed! skipping..."
					fi
				fi
			done
		fi
	fi
	if [ ${in_proj_dir} -eq 0 ]; then
		popd >/dev/null
	fi
}

do_clone() {
	local url="${projurl}/${project}.git"
	git clone "$url" || return 1
	[ -d "$project" ] || return 1
	pushd "$project" >/dev/null
	if [ -n "$branch" ]; then
		echo "try to checkout to branch '$branch' of remote '$remote'" 
		git checkout -t "$remote/$branch"
	fi
	if [ "${restore}" == "always" ]; then
		in_proj_dir=1 do_restore
	elif [ "${restore}" == "ask" ] && yesno "restore files."; then
		in_proj_dir=1 do_restore
	fi
	popd >/dev/null
}

do_build() {
	if [ ${in_proj_dir} -eq 0 ]; then
		pushd "$project" >/dev/null || return 1
	fi
	if [ "${restore}" == "always" ]; then
		in_proj_dir=1 do_restore
	elif [ "${restore}" == "ask" ] && yesno "restore files."; then
		in_proj_dir=1 do_restore
	fi
	echo "try to build ${project}"
	local d=$PWD
	local spec=(*.spec)
	if [ ${#spec[@]} -eq 1 ]; then
		local cmd="mkdir -p ${d}/BUILD; rpmbuild --define '_topdir ${d}' --define '_sourcedir ${d}' ${spec}"
		if [ "${buildlog}" == "yes" ]; then
			local logname="${project}.${action}.$(/bin/date +%Y%m%d-%H%M%S.$(printf %05d $$)).$(hostname -s).buildlog"
			eval $cmd $action "${opts[@]}" 2>&1 | tee ${logname}
			echo "build log is saved in ${logname}"
		else
			eval $cmd $action "${opts[@]}"
		fi
	else
		echo "one and only one spec required in current dir"
	fi
	if [ ${in_proj_dir} -eq 0 ]; then
		popd >/dev/null
	fi
}

do_store() {
	local file=${project}
	if [ "${abfyml}" == "" ]; then
		echo "error: name of abf yml file not specified"
		echo "for example:"
		echo "$0 $command $file abfyml=.abf.yml"
		return 1
	fi

	local sha=$(sha1sum "${file}" | sed 's/\s.*//')
	echo "sha1sum = '${sha}'"

	if [ -e "${abfyml}" ]; then
		if grep -qE "\<${file}\>|\<${sha}\>" ${abfyml}; then
			echo "file '${abfyml}' also contains this line:"
			grep -E "\<${file}\>|\<${sha}\>" ${abfyml}
			echo "aborting..."
			return 1
		fi
	fi

	echo -n "check if file also stored... "
	if wget -q --spider http://file-store.rosa.ru/download/${sha}; then
		echo "yes"
		echo "skip storing"
	else
		echo "no"
		echo "try to store file ${file}"
		local curloutput=$(curl -s -X POST -F "file_store[file]=@${file}" http://${auth}file-store.rosa.ru/api/v1/upload)

		echo -n "check if file stored correctly... "
		if wget -q --spider http://file-store.rosa.ru/download/${sha}; then
			echo "ok"
		else
			echo "error: can't check"
			echo "curl output:"
			echo ${curloutput}
			echo "aborting..."
			return 1
		fi
	fi
	if [ ! -e "${abfyml}" ]; then
		echo "${abfyml} not exist, create one"
		#echo "---" > "${abfyml}"
		echo "sources:" >> "${abfyml}"
	fi
	echo "adding line to '${abfyml}'"
	# fix missing newline at end of .abf.yml
	sed -i '$a\' "${abfyml}"
	echo "  ${file}: ${sha}" >> "${abfyml}"
}

do_status() {
	local out="" out2="" sleep_cmd="break"
	project=${args[0]}
	if [ -z "${project}" ]; then
		echo "please specify project"
	else
		if [ -n "${refresh}" ] && [ ${refresh} -ge 60 ] 2>/dev/null; then
			sleep_cmd="sleep ${refresh}; date"
			echo "query server every ${refresh} seconds (see readme)"
		fi
		echo "Id Status Project Version SaveToRepository Architecture User"
		while true; do
			#out2=$(lynx -dump "https://${auth}abf.rosa.ru/${owner}/${project}/build_lists" | \
			out2=$(lynx -dump "${projurl}/${project}/build_lists" | \
				sed -rn '/^[[:space:]]+\[[0-9]+\][0-9]+ /{N;N;s/\[[0-9]+\]//g;s/\n/ /g;s/ +/ /g;p}' | \
				tac | tail -n ${rows})
			comm --nocheck-order -1 -3 <(echo "${out}") <(echo "${out2}")
			out="$out2"
			eval ${sleep_cmd}
		done
	fi
}

substvars() {
	cat "$1" | sed -r 's/@@project@@/'${project}'/g' > $2
	# another case, imho dangerous
	#eval "echo \"$(< $1)\"" > $2
}

do_new() {
	local url="${projurl}/${project}.git"
	[ -d ${project} ] && { echo "directory '${project}' exists, not creating new project"; return 1; }
	mkdir ${project}
	pushd ${project} >/dev/null
	if [ -r "${defaultspec}" ]; then
		substvars "${defaultspec}" ${project}.spec
	else
		echo "can't read '${defaultspec}', not creating ${project}.spec"
	fi
	git init
	echo "add remote 'origin'"
	git remote add origin "${url}"
	popd >/dev/null
}

do_view() {
	if [[ ${project} =~ ^[0-9]+$ ]]; then
		# number - assume it is build list id
		w3m "https://${auth}abf.rosa.ru/build_lists/${project}"
	else
		# not number - assume it is name of project
		w3m "${projurl}/${project}"
	fi
}

do_publish() {
	local temp1 temp2
	# trick with saving stdout and stderr from here: http://mywiki.wooledge.org/BashFAQ/002
	temp1=$( { temp2=$(wget -SO - ${apiurl}'/build_lists/'${project}'/publish.json') ; } 2>&1; echo "abb separator line"; echo "${temp2}")
	local fulljson=${temp1#*abb separator line}
	local fullwget=${temp1%abb separator line*}
	fulljson=${fulljson#$'\n'}
	fullwget=${fullwget%$'\n'}
	if [ -n "${fulljson}" ]; then
		echo "${fulljson}" | abb.json.sh | sed -rn 's/^\["message"\][[:space:]]*"(.*)"[[:space:]]*$/'${project}': \1/p'
	else
		echo "wget output:"
		echo "${fullwget}"
		echo "${project}: ERROR api server returns empty reply. check build id with 'abb status [<project>]'"
	fi
}

do_rejectpublish() {
	local temp1 temp2
	# trick with saving stdout and stderr from here: http://mywiki.wooledge.org/BashFAQ/002
	temp1=$( { temp2=$(wget -SO - ${apiurl}'/build_lists/'${project}'/reject_publish.json') ; } 2>&1; echo "abb separator line"; echo "${temp2}")
	local fulljson=${temp1#*abb separator line}
	local fullwget=${temp1%abb separator line*}
	fulljson=${fulljson#$'\n'}
	fullwget=${fullwget%$'\n'}
	if [ -n "${fulljson}" ]; then
		echo "${fulljson}" | abb.json.sh | sed -rn 's/^\["message"\][[:space:]]*"(.*)"[[:space:]]*$/'${project}': \1/p'
	else
		echo "wget output:"
		echo "${fullwget}"
		echo "${project}: ERROR api server returns empty reply. check build id with 'abb status [<project>]'"
	fi
}

do_send() {

	debug=${debug:-0}
	local i
	allrepos=(main contrib non-free restricted testing extra test nightly base)
	arches=($(echo ${arch} | sed -r 's/,+/ /'))
	platform=${platform:-${branch}}
	[ "${debug}" -gt 0 ] && echo "platform: '${platform}'"


  #\"auto_publish\": ${auto_publish},

	local auto_publish=false
	[ "${publish}" == "true" -o "${publish}" == "yes" ] && auto_publish=true
	[ "${debug}" -gt 0 ] && echo "auto_publish: ${auto_publish}"


	#\"update_type\": \"${update_type}\",

	update_types=(security bugfix enhancement recommended newpackage)
	for i in "${update_types[@]}"; do
		if [ "${updatetype}" == "$i" ]; then
			update_type="${i}"
			break
		fi
	done
	update_type=${update_type:-security}
	[ "${debug}" -gt 0 ] && echo "update_type: ${update_type}"


  #\"project_id\": ${project_id},

	local project_id=$(wget -qO - \
		${apiurl}'/projects/get_id.json?name='$(echo ${project} | sed 's/+/%2B/g')'&owner='${owner} |\
		abb.json.sh |\
		sed -rn 's/^\["project","id"\][[:space:]]+([0-9]+)[[:space:]]*$/\1/p')
	if [ -z "${project_id}" ]; then
		echo "cant retrieve project '${owner}/${project}' id"
	else
		[ "${debug}" -gt 0 ] && echo "project_id: ${project_id}"


		#\"commit_hash\": \"${commit_hash}\",

		local commit_hash=$(echo "${commit}" | sed -rn 's/^([0-9a-zA-Z]{40})$/\1/p')

		if [ -z "${commit_hash}" ]; then
			local all_project_refs=$(wget -qO - \
				${apiurl}'/projects/'${project_id}'/refs_list.json' |\
				abb.json.sh)
			[ "${debug}" -gt 1 ] && echo "all_project_refs: ${all_project_refs}"
			local branch_num=$(echo "${all_project_refs}" |\
				sed -rn 's/^\["refs_list",([0-9]+),"ref"\][[:space:]]*"?'$(echo "${branch}" | sed 's!/!\\/!g')'"?[[:space:]]*$/\1/p')
			[ "${debug}" -gt 0 ] && echo "branch_num: ${branch_num}"
			local commit_hash=$(echo "${all_project_refs}" |\
				sed -rn 's/^\["refs_list",'${branch_num}',"object","sha"\][[:space:]]*"?([0-9a-zA-Z]+)"?[[:space:]]*$/\1/p')
		fi

		if [ -z "${commit_hash}" ]; then
			echo "do not know commit hash"
		else
			[ "${debug}" -gt 0 ] && echo "commit_hash: ${commit_hash}"



			#\"build_for_platform_id\": ${build_for_platform_id},

			local platforms_for_build=$(wget -qO - \
				${apiurl}'/platforms/platforms_for_build.json' |\
				abb.json.sh)
			[ "${debug}" -gt 1 ] && echo "platforms_for_build: ${platforms_for_build}"
			local platform_for_build_num=$(echo "${platforms_for_build}" |\
				sed -rn 's/^\["platforms",([0-9]+),"name"\][[:space:]]+"?'${platform}'"?[[:space:]]*$/\1/p')
			[ "${debug}" -gt 0 ] && echo "platform_for_build_num: ${platform_for_build_num}"
			local build_for_platform_id=$(echo "${platforms_for_build}" |\
				sed -rn 's/^\["platforms",'${platform_for_build_num}',"id"\][[:space:]]+([0-9]+)[[:space:]]*$/\1/p')
			if [ -z "${build_for_platform_id}" ]; then
				echo "do not know platform for build"
			else
				[ "${debug}" -gt 0 ] && echo "build_for_platform_id: ${build_for_platform_id}"


				#\"save_to_repository_id\": ${save_to_repository_id},

				local all_project_info=$(wget -qO - \
					${apiurl}'/projects/'${project_id}'.json' |\
					abb.json.sh)

				local save_to_repository_id
				local save_to_repository_name
				if [ -z "${reposave}" ]; then
					# repo not specified

					local platform_repo_num=$(echo "${all_project_info}" |\
						sed -rn 's/^\["project","repositories",([0-9]+),"platform","name"\][[:space:]]+"?'${platform}'"?[[:space:]]*$/\1/p' |\
						head -n 1)
					[ "${debug}" -gt 0 ] && echo "platform_repo_num: ${platform_repo_num}"

					save_to_repository_id=$(echo "${all_project_info}" |\
						sed -rn 's/^\["project","repositories",'${platform_repo_num}',"id"\][[:space:]]+([0-9]+)[[:space:]]*$/\1/p')
					save_to_repository_name=$(echo "${all_project_info}" |\
						sed -rn 's/^\["project","repositories",'${platform_repo_num}',"name"\][[:space:]]+"?([-_.[:alnum:]]+)"?[[:space:]]*$/\1/p')
					[ "${debug}" -gt 0 ] && echo "save_to_repository_name: ${save_to_repository_name}"

					# check if we can save to this repo
					local save_to_repo_in_platforms_for_build=$(echo "${platforms_for_build}" |\
						sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",[0-9]+,"id"\][[:space:]]+('${save_to_repository_id}')[[:space:]]*$/\1/p')
				else
					# repo to save is specified
					[ "${debug}" -gt 0 ] && echo "repo specified: ${reposave}"
					# split $repo into parts
					local split_repo_platform=${reposave%\/*}
					local split_repo_repo=${reposave#${split_repo_platform}}
					split_repo_repo=${split_repo_repo#/}
					# add pattern
					local split_repo_platform_withp=${split_repo_platform}
					if [ "${split_repo_platform}" == "personal" ]; then
						split_repo_platform_withp='[-_.[:alnum:]]+_'${split_repo_platform}
						if [ -z "${split_repo_repo}" ]; then
							split_repo_repo=master
						fi
					fi
					[ "${debug}" -gt 0 ] && echo "split_repo_platform: ${split_repo_platform}"
					[ "${debug}" -gt 0 ] && echo "split_repo_repo: ${split_repo_repo}"
					local split_repo_num=$(echo "${all_project_info}" |\
						sed -rn 's/^\["project","repositories",([0-9]+),"platform","name"\][[:space:]]"?'${split_repo_platform_withp}'"?[[:space:]]*$/\1/p')
					[ "${debug}" -gt 0 ] && echo "split_repo_num: ${split_repo_num}"
					local split_repo_name=$(echo "${all_project_info}" |\
						sed -rn 's/^\["project","repositories",'${split_repo_num}',"name"\][[:space:]]+"?([-_.[:alnum:]]+)"?[[:space:]]*$/\1/p')
					if [ -n "${split_repo_repo}" -a "${split_repo_repo}" != "${split_repo_name}" ]; then
						echo "error: you specify to save build into repo '${split_repo_repo}' of platform '${split_repo_platform}'"
						echo "but this platform contains repo '${split_repo_name}'"
					else
						save_to_repository_id=$(echo "${all_project_info}" |\
							sed -rn 's/^\["project","repositories",'${split_repo_num}',"id"\][[:space:]]+([0-9]+)[[:space:]]*$/\1/p')
						#save_to_repo_in_platforms_for_build=${save_to_repository_id}
						save_to_repository_name=$(echo "${all_project_info}" |\
							sed -rn 's/^\["project","repositories",'${split_repo_num}',"name"\][[:space:]]+"?([-_.[:alnum:]]+)"?[[:space:]]*$/\1/p')
						[ "${debug}" -gt 0 ] && echo "save_to_repository_name: ${save_to_repository_name}"
					fi
				fi

				if [ -z "${save_to_repository_id}" ]; then
					echo "do not know repo to save. if this is personal project, please specify 'reposave=personal'"
				elif [ -z "${save_to_repo_in_platforms_for_build}" -a -z "${reposave}" ]; then
					echo "you can't save to repo with id ${save_to_repository_id}"
				else
					[ "${debug}" -gt 0 ] && echo "save_to_repository_id: ${save_to_repository_id}"

					# include repos
					local include_repos
					# check option "repos" first
					if [ -n "${repos}" ]; then
						local split_repos=( $(echo "${repos}" | sed 's/,/ /g') )
						local split_repo_ids=""
						for i in ${split_repos[@]}; do
							local split_repo_num=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",([0-9]+),"name"\][[:space:]]+"?'${i}'"?[[:space:]]*$/\1/p')
							local split_repo_id=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",'${split_repo_num}',"id"\][[:space:]]+([-_.[:alnum:]]+)[[:space:]]*$/\1/p')
							split_repo_ids="${split_repo_ids}${split_repo_id},"
						done
						include_repos=${split_repo_ids%,}
					fi

					if [ -z "${include_repos}" ]; then
						# if repo to include not specified, got it and add main repo if needed
						local include_repo_num
						local include_repo_name
						if [ -n "${save_to_repo_in_platforms_for_build}" ]; then
							# repo to save belongs to build platform
							include_repos=${save_to_repo_in_platforms_for_build}
							include_repo_num=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",([0-9]+),"id"\][[:space:]]+'${save_to_repository_id}'[[:space:]]*$/\1/p')
							include_repo_name=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",'${include_repo_num=}',"name"\][[:space:]]+"?([-_.[:alnum:]]+)"?[[:space:]]*$/\1/p')
						else
							# repo to save do not belongs to build platform
							# so get first repo from platform
							include_repo_num=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",([0-9]+),"id"\].*$/\1/p' |\
								head -n 1)
							include_repo_name=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",'${include_repo_num=}',"name"\][[:space:]]+"?([-_.[:alnum:]]+)"?[[:space:]]*$/\1/p')
							include_repos=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",'${include_repo_num=}',"id"\][[:space:]]+([0-9]+)"?[[:space:]]*$/\1/p')
						fi
						[ "${debug}" -gt 0 ] && echo "include_repo_num: ${include_repo_num}"
						[ "${debug}" -gt 0 ] && echo "include_repo_name: ${include_repo_name}"
						if [ "${include_repo_name}" != "main" ]; then
							# try to find repo with name "main" in platform
							include_repo_num=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",([0-9]+),"name"\][[:space:]]+"?main"?[[:space:]]*$/\1/p')
							local include_repo_id=$(echo "${platforms_for_build}" |\
								sed -rn 's/^\["platforms",'${platform_for_build_num}',"repositories",'${include_repo_num=}',"id"\][[:space:]]+([0-9]+)"?[[:space:]]*$/\1/p')
							if [ -n "${include_repo_id}" ]; then
								include_repos="${include_repo_id},${include_repos}"
							fi
						fi
					fi

					if [ -z "${include_repos}" ]; then
						echo "do not know repos to include"
					else
						[ "${debug}" -gt 0 ] && echo "include_repos: ${include_repos}"

						local archnames="1 i586 2 x86_64"
						## if needed, take arch names from abf:
						#local archnames=$(wget -qO - \
						#	${apiurl}'/arches.json' |\
						#	abb.json.sh |\
						#	sed -rn '/^\["architectures"\]/{s/"id":([0-9]+),"name":"([-_[:alnum:]]+)"/<\1 \2>/g;s/^[^<]*<//;s/>[^>]*$//;s/>[^<>]+</ /g;p}')
						[ "${debug}" -gt 0 ] && echo "arch names: ${archnames}"
						[ "${debug}" -gt 0 ] && echo "build arches: ${arches[@]}"

						for i in ${arches[@]}; do
							local archn=$(echo ${archnames} | sed -rn 's/^.*\<([0-9]+) '${i}'\>.*$/\1/p')
							[ -z "${archn}" ] && continue

							local post="
								{
								\"build_list\": {
									\"project_id\": ${project_id},
									\"commit_hash\": \"${commit_hash}\",
									\"update_type\": \"${update_type}\",
									\"save_to_repository_id\": ${save_to_repository_id},
									\"build_for_platform_id\": ${build_for_platform_id},
									\"auto_publish\": ${auto_publish},
									\"include_repos\": [ ${include_repos} ],
									\"arch_id\": ${archn}
								}
							}"
							post=$(echo $post | sed -r 's/[[:space:]]+//g')

							[ "${debug}" -gt 0 ] && echo "post: ${post}"

							# lets go

							local temp1 temp2

							# trick with saving stdout and stderr from here: http://mywiki.wooledge.org/BashFAQ/002
							temp1=$( { temp2=$(wget -SO - ${apiurl}'/build_lists.json' --header="Content-Type: application/json" --header="Accept: application/json" --post-data="${post}") ; } 2>&1; echo "abb separator line"; echo "${temp2}")
							local fulljson=${temp1#*abb separator line}
							local fullwget=${temp1%abb separator line*}
							fulljson=${fulljson#$'\n'}
							fullwget=${fullwget%$'\n'}
							if [ "${debug}" -gt 1 ]; then
								echo >> fulljson.log
								date >> fulljson.log
								echo "${fulljson}" >> fulljson.log
								echo >> fullwget.log
								date >> fullwget.log
								echo "${fullwget}" >> fullwget.log
								echo >> fullreq.log
								date >> fullreq.log
								echo "${post}" >> fullreq.log
							fi

							# parse output
							local sent_id=$(echo "${fulljson}" | abb.json.sh | \
								sed -rn 's/^\["build_list","id"\][[:space:]]*"?([0-9]+)"?.*$/\1/p')
							if [ -n "${sent_id}" ]; then
								echo "${sent_id}"
							else
								echo "there is no buildlist id in the buildserver reply:"
								echo "${fulljson}"
							fi
						done
					fi
				fi
			fi
		fi
	fi
}

do_vars() {
	local varslist="proto server owner branch remote abfyml buildlog restore project rows refresh defaultspec arch platform repos updatetype commit publish reposave"
	local varslistcase="${varslist[@]// /|}"
	local vars
	if [ ${#args[@]} -eq 0 ]; then
		vars=( $varslist )
	else
		vars=( "${args[@]}" )
	fi
	for i in "${vars[@]}"; do
		case "$i" in
			proto|server|owner|branch|remote|abfyml|buildlog|restore|project|rows|refresh|defaultspec|arch|platform|repos|updatetype|commit|publish|reposave|cdafterclone)
				echo "$i=${!i}"
				;;
			auth)
				echo "$i=${!i%@}"
				;;
			*)
				;;
		esac
	done | sort
}

main_case() {
	case "$command" in
		clone|store|status|new|view|build|restore|publish|rejectpublish|vars|send)
			do_${command}
			;;
		*)
			usage "unknown command: $command"
			;;
	esac
}

unset command
declare -a args=()
declare -a opts=()
declare -a buildlist=()

# parse arguments
for i in "$@"; do
	case "$i" in
		clone|build|store|restore|status|new|view|publish|rejectpublish|vars|send)
			if [ "${command}" == "vars" ]; then
				args=("${args[@]}" "${i%%/}")
			else
				[ -n "${command}" ] && usage "only one command at a time supported, but you want: ${command} and ${i%%/}"
				command=${i%%/}
			fi
			;;
		build?)
			if [ "${command}" == "vars" ]; then
				args=("${args[@]}" "${i%%/}")
			else
				[ -n "${command}" ] && usage "only one command at a time supported, but you want: ${command} and ${i%%/}"
				command="build"
				action="${i/build/-b}"
			fi
			;;
		-b?)
			action="$i"
			;;
		-*)
			opts=("${opts[@]}" "$i")
			;;
		proto=*)
			proto=${i#proto=}
			;;
		server=*)
			server=${i#server=}
			;;
		owner=*)
			owner=${i#owner=}
			;;
		branch=*)
			branch=${i#branch=}
			;;
		remote=*)
			remote=${i#remote=}
			;;
		auth=*)
			auth=${i#auth=}
			;;
		abfyml=*)
			abfyml=${i#abfyml=}
			;;
		buildlog=*)
			buildlog=${i#buildlog=}
			;;
		restore=*)
			restore=${i#restore=}
			;;
		project=*)
			args=("${args[@]}" "${i#project=}")
			;;
		rows=*)
			rows=${i#rows=}
			;;
		refresh=*)
			refresh=${i#refresh=}
			;;
		defaultspec=*)
			defaultspec=${i#defaultspec=}
			;;
		arch=*)
			arch=${i#arch=}
			;;
		platform=*)
			platform=${i#platform=}
			;;
		repos=*)
			repos=${i#repos=}
			;;
		updatetype=*)
			updatetype=${i#updatetype=}
			;;
		commit=*)
			commit=${i#commit=}
			;;
		publish=*)
			publish=${i#publish=}
			;;
		reposave=*)
			reposave=${i#reposave=}
			;;
		debug=*)
			debug=${i#debug=}
			;;
		*=*)
			echo "unknown option: ${i}" | sed 's/=.*//'
			exit 1
			;;
		*)
			args=("${args[@]}" "${i%%/}")
			;;
	esac
done

# if auth not empty, add "@" to the end
auth=${auth:+${auth}@}

# check arguments
[ -z "$command" ] && usage "please specify a command"
#[ ${#args[@]} -eq 1 ] && project=${args[0]}

# assume we are not in proj dir
in_proj_dir=0

projurl=${proto}://${auth}${server}/${owner}

apiurl=${proto}://${auth}${server}/${serverapi}

case "$command" in
	clone|new)
		[ ${#args[@]} -lt 1 ] && usage "command '${command}' requires at least one argument - project name"
		;;
	build|restore)
		case ${#args[@]} in
			0)
				get_project_from_curdir
				[ -z "${project}" ] && usage "can't determine project name"
				in_proj_dir=1
				;;
			1)
				# silently check if we are in specified project dir
				silent=1 get_project_from_curdir nodir
				if [ -n "${project}" ]; then
					if [ "${project}" == "${args[0]}" ]; then
						in_proj_dir=1
					else
						echo "you specify project '${args[0]}', but it seems that we are in dir of project '${project}'"
						echo -n "so we clone project '${args[0]}'. "
						yesno || exit 1
					fi
				fi
				# if we are out of project dir, clone repo first
				if [ ${in_proj_dir} -eq 0 -a ! -d ${args[0]} ]; then
					restore=none project=${args[0]} do_clone || exit 1
				fi
				;;
			*)
				for project in "${args[@]}"; do
					if [ ! -d "${project}" ]; then
						restore=none do_clone
					fi
				done
				;;
		esac
		;;
	status|view|send)
		case ${#args[@]} in
			0)
				get_project_from_curdir
				[ -z "${project}" ] && usage "can't determine project name"
				args=(${project})
				;;
			1)
				# silently check if we are in specified project dir
				;;
			*)
				usage "command '${command}' requires zero ore one argument"
				;;
		esac
		;;
	store)
		[ ${#args[@]} -lt 1 ] && usage "command '${command}' requires at least one argument - file name"
		;;
	publish|rejectpublish)
		[ ${#args[@]} -lt 1 ] && usage "command '${command}' requires at least one argument - build_list id"
		;;
	vars)
		;;
	*)
		usage "unknown command: $command"
		;;
esac

# let's start
if [ ${#args[@]} -eq 0 -o "${command}" == "vars" -o "${command}" == "status" ]; then
	main_case
else
	for project in "${args[@]}"; do
		in_proj_dir=0
		main_case
	done
fi
