#!/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 bash_it {
    printf '%q ' "$@" | /bin/bash -x
}

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

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

master=master
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

if ! git rev-parse --git-dir > /dev/null 2>&1; then
    warn_it "Oops, this is not a Git repository"
    exit 1
fi
# 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.14 (https://github.com/yegor256/gitted)\n"
    GITTED_INTRODUCED=true
    export GITTED_INTRODUCED
fi
if ! "${GIT_BIN}" remote | grep -q ^origin; then
    warn_it "No remote by the name 'origin', nothing to pull from"
    exit
fi

branch=$("${GIT_BIN}" symbolic-ref HEAD --short)
if [ -z "${branch}" ]; then
    warn_it "Something is wrong, the current branch was not detected"
    exit 1
fi

if ! "${GIT_BIN}" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
    if git rev-parse --verify HEAD > /dev/null 2>&1; then
        title_it "The upstream is not configured for the ${branch} branch, setting it to origin/${branch}"
        bash_it "${GIT_BIN}" fetch
        bash_it "${GIT_BIN}" branch "--set-upstream-to=origin/${branch}" "${branch}"
    fi
fi

if [ -e .git/modules ]; then
    subs=$(grep -c '^\[submodule' .gitmodules)
    title_it "Updating $(plural "${subs}" 'submodule') first..."
    while true; do
        bash_it "${GIT_BIN}" submodule update --remote && break
        if [ -n "${GITTED_TESTING}" ]; then
            exit 1
        fi
    done
fi

inc=$(${GIT_BIN} status --porcelain | grep -c '^??' || true)
if [ ! "${inc}" == '0' ]; then
    title_it "Staging $(plural "${inc}" 'file')"
    bash_it "${GIT_BIN}" add .
fi

stashed=no
if git rev-parse --verify HEAD > /dev/null 2>&1; then
    if ! git diff --quiet || ! git diff --cached --quiet; then
        trap "title_it 'Applying the changes back' && bash_it \${GIT_BIN} stash apply" EXIT
        df=$(${GIT_BIN} status --porcelain | wc -l | xargs)
        title_it "Stashing $(plural "${df}" 'file')"
        bash_it "${GIT_BIN}" stash
        stashed=yes
    fi
fi

# shellcheck disable=SC2154
if git ls-remote --exit-code origin "refs/heads/${master}" > /dev/null 2>&1; then
    attempt=1
    max=10
    while true; do
        title_it "Pulling from origin/${branch} (attempt no.${attempt}/${max})"
        bash_it "${GIT_BIN}" pull origin "${branch}" && break
        if [ -n "${GITTED_TESTING}" ]; then
            exit 1
        fi
        attempt=$((attempt + 1))
        if [ "${attempt}" -gt "${max}" ]; then
            exit 1
        fi
    done
fi

trap - EXIT
if [ "${stashed}" == 'yes' ]; then
    title_it "Applying the changes back"
    bash_it "${GIT_BIN}" stash apply
fi

if ${GIT_BIN} remote | cut -f1 -d ' ' | grep upstream; then
    title_it "Pulling from upstream"
    ${GIT_BIN} pull upstream "${master}"
fi
