#!/bin/bash source $(dirname $0)/io.sh || exit 255 source $(dirname $0)/basic.sh || exit 255 source $(dirname $0)/pkg.sh || exit 255 ######################################################## # Shorthands for git ######################################################## git.clone_quick() { require git git clone --depth=1 --single-branch $* } git.is_repo() { require git [ "$1" ] || die "Path is not specified" 101 require_dir "$1/" check_dir "$1/.git" } git.require_repo() { require git git.is_repo "$1" || die "'$1' is not git repository!" 10 } git.cfg() { require git [ "$1" ] || die "Key is not specified" 101 if [[ "$2" ]]; then git config --global --replace-all "$1" "$2" else echo $(git config --global --get-all "$1") fi } git.set_user() { require git [ "$1" ] || die "git.set_user: Repo is not specified" 100 git.cfg "$1" "user.name" "$2" git.cfg "$1" "user.email" "$3" success "User set to '$name <$email>' in ${FWHITE}$1" } git.fetch() { require git if [ "$1" ]; then if git.remote_branch_exists "origin/$1"; then git fetch origin "refs/heads/$1:refs/remotes/origin/$1" --progress --prune --quiet 2>&1 || die "Could not fetch $1 from origin" 12 else warn "Tried to fetch branch 'origin/$1' but it does not exist." fi else git fetch origin --progress --prune --quiet 2>&1 || exit 12 fi } git.reset() { require git git reset --hard HEAD git clean -fd } git.clone() { require git git clone $* 2>&1 } git.co() { require git git checkout $* 2>&1 } git.is_it_current_branch() { require git [ "$1" ] || die "git.is_it_current_branch: Branch is not specified" 19 [[ "$(git.current_branch)" = "$1" ]] } git.pull() { require git [ "$1" ] && BRANCH=$1 || BRANCH=$(git.current_branch) # note "Updating branch $BRANCH..." git pull origin "refs/heads/$BRANCH:refs/remotes/origin/$BRANCH" --prune --force --quiet 2>&1 || exit 13 git pull origin --tags --force --quiet 2>&1 || exit 13 # [ "$1" ] || die "git.pull: Branch is not specified" 19 # if [ "$1" ]; then # note "Updating branch $1..." # git pull origin "refs/heads/$1:refs/remotes/origin/$1" --prune --force --quiet 2>&1 || exit 13 # else # note "Updating current branch..." # git pull # fi } git.current_branch() { require git git branch --show-current || exit 18 } git.local_branch_exists() { require git [ -n "$(git for-each-ref --format='%(refname:short)' refs/heads/$1)" ] } git.update_refs() { require git info "Updating local refs..." git remote update origin --prune 1>/dev/null 2>&1 || exit 18 } git.delete_remote_branch() { require git [ "$1" ] || die "git.remote_branch_exists: Branch is not specified" 19 if git.remote_branch_exists "origin/$1"; then git push origin :"$1" # || die "Could not delete the remote $1 in $ORIGIN" return 0 else warn "Trying to delete the remote branch $1, but it does not exists in origin" return 1 fi } git.is_clean_worktree() { require git git rev-parse --verify HEAD >/dev/null || exit 18 git update-index -q --ignore-submodules --refresh git diff-files --quiet --ignore-submodules || return 1 git diff-index --quiet --ignore-submodules --cached HEAD -- || return 2 return 0 } git.is_branch_merged_into() { require git [ "$1" ] || die "git.remote_branch_exists: Branch1 is not specified" 19 [ "$2" ] || die "git.remote_branch_exists: Branch2 is not specified" 19 git.update_refs local merge_hash=$(git merge-base "$1"^{} "$2"^{}) local base_hash=$(git rev-parse "$1"^{}) [ "$merge_hash" = "$base_hash" ] } git.remote_branch_exists() { require git [ "$1" ] || die "git.remote_branch_exists: Branch is not specified" 19 git.update_refs [ -n "$(git for-each-ref --format='%(refname:short)' refs/remotes/$1)" ] } git.new_branch() { require git [ "$1" ] || die "git.new_branch: Branch is not specified" 19 if [ "$2" ] && ! git.local_branch_exists "$2" && git.remote_branch_exists "origin/$2"; then git.co -b "$1" origin/"$2" else git.co -b "$1" "$2" fi } git.require_clean_worktree() { require git if ! git.is_clean_worktree; then warn "Your working tree is dirty! Look at this:" git status -bs _T="What should you do now?\n" _T="${_T}\t${BOLD}${FWHITE}0.${RESET} try to continue as is\t- errors may occur!\n" _T="${_T}\t${BOLD}${FWHITE}1.${RESET} hard reset\t\t\t- clear current changes and new files\n" _T="${_T}\t${BOLD}${FWHITE}2.${RESET} stash changes (default)\t- save all changes in safe to apply them later via 'git stash pop'\n" _T="${_T}\t${BOLD}${FWHITE}3.${RESET} cancel\n" ask "${_T}${BOLD}${FWHITE}Your choice [0-3]" reset_answer case $reset_answer in 1 ) warn "Clearing your work..." && git.reset ;; 3 ) exit ;; * ) git stash -a -u -m "WIP before switch to $branch_task" ;; esac fi }