#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
# SPDX-License-Identifier: MIT

set -e -o pipefail

# shellcheck disable=SC1091
# Imported from commons.sh when releasing:
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
# SPDX-License-Identifier: MIT

set -e -o pipefail

if [ -n "${GITTED_TESTING}" ]; then
    set -x
fi

if [ -n "${GITTED_VERBOSE}" ]; then
    set -x
fi

function title_it {
    printf '\n👉 \e[1m%s\e[0m...\n' "$@"
}

function warn_it {
    printf '\n⚠️ \e[38;5;160m%s\e[0m\n' "$@"
}

function fail_it {
    warn_it "$@"
    exit 1
}

function bash_it {
    printf '%q ' "$@" | /bin/bash -x
}

function plural {
    printf "%s %s" "$1" "$2"
    if [ "$1" != '1' ]; then
        printf 's'
    fi
}

function retry_it {
    local message="$1"
    local cmd="$2"
    local max="${3:-10}"
    local attempt=1
    while (( attempt <= max )); do
        title_it "${message} (attempt no.${attempt}/${max})"
        eval "$cmd" && return 0
        if [ -n "${GITTED_TESTING}" ]; then
            exit 1
        fi
        attempt=$(( attempt + 1 ))
        sleep 1
    done
    fail_it "Command failed after ${max} attempts: ${cmd}"
}

base=$(dirname "$0")
export base

branches="$(git branch --format='%(refname:short)')"
if [ -z "${branches}" ]; then
    master="$(git symbolic-ref --short HEAD 2>/dev/null || exit 1)"
elif echo "$branches" | grep -qx 'master'; then
    master=master
elif echo "$branches" | grep -qx 'main'; then
    master=main
else
    fail_it "Neither 'master' nor 'main' branch found."
fi
export master

if [ -z "${GIT_BIN}" ]; then
    GIT_BIN=git
    export GIT_BIN
fi
# Imported from sanity.sh when releasing:
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
# SPDX-License-Identifier: MIT

set -e -o pipefail

GITTED_GIT_MIN_MAJOR=2
GITTED_GIT_MIN_MINOR=13

function gitted_sanity_fail {
    printf '\n⚠️ \e[38;5;160m%s\e[0m\n' "$@" >&2
    exit 1
}

GIT_BIN="${GIT_BIN:-git}"

if ! command -v "${GIT_BIN}" > /dev/null 2>&1; then
    gitted_sanity_fail "Git is not installed: '${GIT_BIN}' command was not found in PATH"
fi

gitted_git_version_raw=$("${GIT_BIN}" --version 2>/dev/null | awk '{print $3}')
if [ -z "${gitted_git_version_raw}" ]; then
    gitted_sanity_fail "Failed to detect Git version (could not parse output of '${GIT_BIN} --version')"
fi
IFS='.' read -r gitted_git_major gitted_git_minor _ <<< "${gitted_git_version_raw}"
if ! [[ "${gitted_git_major}" =~ ^[0-9]+$ ]] || ! [[ "${gitted_git_minor}" =~ ^[0-9]+$ ]]; then
    gitted_sanity_fail "Failed to parse Git version '${gitted_git_version_raw}'"
fi
if (( gitted_git_major < GITTED_GIT_MIN_MAJOR )) || \
    (( gitted_git_major == GITTED_GIT_MIN_MAJOR && gitted_git_minor < GITTED_GIT_MIN_MINOR )); then
    gitted_sanity_fail "Git version ${gitted_git_version_raw} is too old; gitted requires Git ${GITTED_GIT_MIN_MAJOR}.${GITTED_GIT_MIN_MINOR}.0 or higher"
fi

if ! "${GIT_BIN}" rev-parse --git-dir > /dev/null 2>&1; then
    gitted_sanity_fail "Oops, this is not a Git repository"
fi

root=$("${GIT_BIN}" rev-parse --show-toplevel)
cd "${root}"
# Imported from intro.sh when releasing:
help_pull=$(cat << EOT
Usage: pull

We pull from the upstream branch and then also from the upstream repository.
EOT
)

help_push=$(cat << EOT
Usage: push [<message> | <branch>]

You either provide a commit message or a name of the branch you push to. If the
argument is a single integer, we treat it as a branch name. Everything else
is treated as a plain message.
EOT
)

help_branch=$(cat << EOT
Usage: branch <name>

You either provide a "message" or a name of the branch you push to. If the
argument is a single integer, we treat it as a branch name. Everything else
is treated as a plain message.
EOT
)

help_commit=$(cat << EOT
Usage: commit [<message> | <branch>]

You either provide a commit message or a name of the branch you push to. If the
argument is a single integer, we treat it as a branch name. Everything else
is treated as a plain message.
EOT
)

#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
# SPDX-License-Identifier: MIT

set -e -o pipefail

if [ "$1" = '--help' ]; then
    cmd=$(basename "$0")
    var="help_${cmd}"
    help=${!var}
    if [ -z "${help}" ]; then
        echo "Usage: ${cmd} --help"
    else
        echo "${help}"
    fi
    exit
fi

if [ -z "${GITTED_INTRODUCED}" ]; then
    printf "\e[1mGitted\e[0m 0.0.21 (https://github.com/yegor256/gitted)\n"
    GITTED_INTRODUCED=true
    export GITTED_INTRODUCED
fi
# shellcheck disable=SC2154
"${base}/pull" "$*"

if git status --porcelain | grep -q .; then
    # shellcheck disable=SC2154
    "${base}/commit" "$*"
else
    title_it "Nothing to commit, proceeding with push"
fi

branch=$(git symbolic-ref HEAD --short)

max=10
attempt=1
while (( attempt <= max )); do
    title_it "Pushing to origin/${branch} (attempt no.${attempt}/${max})"
    if bash_it "${GIT_BIN}" push origin "${branch}"; then
        exit 0
    fi
    attempt=$(( attempt + 1 ))
    if (( attempt > max )); then
        break
    fi
    title_it "Push was rejected, rebasing on origin/${branch} before retrying"
    bash_it "${GIT_BIN}" pull --rebase origin "${branch}"
done

fail_it "Failed to push to origin/${branch} after ${max} attempts"
