|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +set -o errexit -o errtrace -o nounset -o pipefail |
| 4 | + |
| 5 | +# ============================================================================== |
| 6 | +: readonly "${RESET_TEXT:=$(tput sgr0)}" # turn off all attributes |
| 7 | +# ------------------------------------------------------------------------------ |
| 8 | +# Foreground colors |
| 9 | +# ------------------------------------------------------------------------------ |
| 10 | +: readonly "${COLOR_BLUE:=$(tput setaf 4)}" |
| 11 | +: readonly "${COLOR_GREEN:=$(tput setaf 2)}" |
| 12 | +: readonly "${COLOR_RED:=$(tput setaf 1)}" |
| 13 | +: readonly "${COLOR_WHITE:=$(tput setaf 7)}" |
| 14 | +: readonly "${COLOR_YELLOW:=$(tput setaf 3)}" |
| 15 | +# ------------------------------------------------------------------------------ |
| 16 | +# Text attributes |
| 17 | +# ------------------------------------------------------------------------------ |
| 18 | +: readonly "${TEXT_BOLD:=$(tput bold)}" # turn on bold (extra bright) mode |
| 19 | +: readonly "${TEXT_INVERSE:=$(tput rev)}" # turn on color inverse mode |
| 20 | +# ------------------------------------------------------------------------------ |
| 21 | +# Text output channels |
| 22 | +# ------------------------------------------------------------------------------ |
| 23 | +: "${ERROR_OUTPUT:=/dev/stderr}" |
| 24 | +: "${NORMAL_OUTPUT:=/dev/stdout}" |
| 25 | +: "${SILENCE_OUTPUT:=/dev/null}" |
| 26 | +# ============================================================================== |
| 27 | + |
| 28 | +: "${GIT:=git}" |
| 29 | + |
| 30 | +check_sources_for_update() { |
| 31 | + |
| 32 | + get_local_version() { |
| 33 | + local sContent sLocalVersion |
| 34 | + |
| 35 | + readonly sContent="${1?One parameter required: <content>}" |
| 36 | + |
| 37 | + sLocalVersion=$(echo "${sContent}" | grep -oE '([0-9]+\.?){3}') |
| 38 | + |
| 39 | + if echo "${sLocalVersion}" | grep --quiet '\.0[0-9]';then |
| 40 | + # Remove unneeded leading zero |
| 41 | + sLocalVersion="$(echo "${sLocalVersion}" | tr '.' "\n" | bc | tr "\n" '.')" |
| 42 | + sLocalVersion="${sLocalVersion:0:-1}" |
| 43 | + fi |
| 44 | + |
| 45 | + echo "${sLocalVersion}" |
| 46 | + } |
| 47 | + |
| 48 | + get_version_from_remote_git() { |
| 49 | + local sProject sRemoteVersion |
| 50 | + |
| 51 | + readonly sProject="${1?One parameter required: <github-project>}" |
| 52 | + |
| 53 | + readonly sRemoteVersion="$("${GIT}" ls-remote --tags "git://github.com/${sProject}.git" \ |
| 54 | + | cut -d'/' -f3 \ |
| 55 | + | grep -E '^v?[0-9.]+$' \ |
| 56 | + | grep -oE '[0-9.]+' \ |
| 57 | + | sort -V \ |
| 58 | + | tail -n1)" || true |
| 59 | + |
| 60 | + echo "${sRemoteVersion}" |
| 61 | + } |
| 62 | + |
| 63 | + compare_versions() { |
| 64 | + local sLocalVersion sRemoteVersion sResponse |
| 65 | + |
| 66 | + readonly sLocalVersion="${1?Two parameters required: <local-version> <remote-version>}" |
| 67 | + sRemoteVersion="${2?Two parameters required: <local-version> <remote-version>}" |
| 68 | + |
| 69 | + if [[ "${sLocalVersion}" == "" ]] || [[ "${sRemoteVersion}" == "" ]];then |
| 70 | + readonly sResponse="${COLOR_RED}No version infromation available${RESET_TEXT}" |
| 71 | + else |
| 72 | + if echo "${sRemoteVersion}" | grep --quiet -E '^[0-9]+\.[0-9]+$';then |
| 73 | + # Pad "x.y" format to "x.y.z" format |
| 74 | + sRemoteVersion="${sRemoteVersion}.0" |
| 75 | + fi |
| 76 | + |
| 77 | + if [[ "$(echo -e "${sRemoteVersion}\n${sLocalVersion}" | sort -V | tail -n 1)" == "${sLocalVersion}" ]];then |
| 78 | + readonly sResponse="${COLOR_GREEN}Up To Date${RESET_TEXT}" |
| 79 | + else |
| 80 | + readonly sResponse="${COLOR_YELLOW}Newer version available ${TEXT_INVERSE} ${sRemoteVersion} ${RESET_TEXT}" |
| 81 | + fi |
| 82 | + fi |
| 83 | + |
| 84 | + echo "${sResponse}" |
| 85 | + } |
| 86 | + |
| 87 | + get_project_name_from_github_url() { |
| 88 | + local sContent sProject sUrl |
| 89 | + |
| 90 | + readonly sContent="${1?One parameter required: <content>}" |
| 91 | + |
| 92 | + readonly sUrl=$(echo "${sContent}" | grep -oE 'https?://.*') |
| 93 | + readonly sProject="$(echo "${sUrl}" | rev | grep -oE '[^/]+/[^/]+' | rev)" |
| 94 | + |
| 95 | + echo "${sProject}" |
| 96 | + } |
| 97 | + |
| 98 | + check_source_for_update() { |
| 99 | + local sContent sLocalVersion sProject sRemoteVersion |
| 100 | + |
| 101 | + readonly sContent="${1?One parameter required: <content>}" |
| 102 | + readonly sLocalVersion="$(get_local_version "${sContent}")" |
| 103 | + readonly sProject="$(get_project_name_from_github_url "${sContent}")" |
| 104 | + |
| 105 | + echo -n "${RESET_TEXT} =====> ${TEXT_BOLD}${sProject}${RESET_TEXT} (${COLOR_BLUE}${sLocalVersion}${RESET_TEXT})" |
| 106 | + |
| 107 | + readonly sRemoteVersion="$(get_version_from_remote_git "${sProject}")" |
| 108 | + |
| 109 | + echo " $(compare_versions "${sLocalVersion}" "${sRemoteVersion}")" |
| 110 | + } |
| 111 | + |
| 112 | + run() { |
| 113 | + local sSourcesFile sSourcePaths |
| 114 | + |
| 115 | + sSourcePaths="${1?One parameter required: <sources-path>}" |
| 116 | + |
| 117 | + for sSourcesFile in "${sSourcePaths}/"*'/INFO';do |
| 118 | + check_source_for_update "$(cat "${sSourcesFile}")" |
| 119 | + done; |
| 120 | + |
| 121 | + # @TODO: Move this to an exit trap, so we don't fuck up the terminal when a user aborts |
| 122 | + echo -n "${RESET_TEXT}" |
| 123 | + } |
| 124 | + |
| 125 | + run "${@}" |
| 126 | +} |
| 127 | + |
| 128 | +if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then |
| 129 | + export -f check_sources_for_update |
| 130 | +else |
| 131 | + check_sources_for_update "${@}" |
| 132 | + exit $? |
| 133 | +fi |
0 commit comments