Last active
January 17, 2023 13:05
-
-
Save pasela/7212517 to your computer and use it in GitHub Desktop.
git-su - switches user and sshCommand in the current repository
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# git-su - Git Switch User | |
# ======================== | |
# | |
# git-su switches user and sshCommand in the current repository. | |
# | |
# USAGE | |
# ----- | |
# | |
# git su <-l|--list> | |
# git su <name> | |
# git su <name> <git_subcommand> <args...> | |
# | |
# e.g. git su -l | |
# git su foo | |
# git su foo clone $REPO | |
# | |
# git-su sets user.name and user.email by the following command. | |
# ("Foo" and "[email protected]" are predefined values) | |
# | |
# git config user.name "Foo" | |
# git config user.email "[email protected]" | |
# git config core.sshCommand "ssh -i ~/.ssh/foo_rsa" | |
# | |
# You can use the third form for init/clone and set user at one command. | |
# | |
# | |
# DEFINITION FILE | |
# --------------- | |
# | |
# The location of the definition file is '$HOME/.gitsu'. Or You can | |
# specify the path using $GIT_SU_CONF environment variable. | |
# Alternatively, you can put definitions into $HOME/.gitconfig directly. | |
# | |
# Definition format: | |
# ------------------------------ | |
# [su "name"] | |
# name = "Your name" | |
# email = "Your email address" | |
# sshCommand = "ssh -i ~/.ssh/id_rsa" | |
# ------------------------------ | |
# `name` and `email` are mandatory, `sshCommand` is optional. | |
# | |
# for example: | |
# ------------------------------ | |
# [su "alice"] | |
# name = "Alice" | |
# email = "[email protected]" | |
# | |
# [su "bob"] | |
# name = "Bob" | |
# email = "[email protected]" | |
# sshCommand = "ssh -i ~/.ssh/bob_rsa" | |
# ------------------------------ | |
# | |
# | |
# LICENSE | |
# ------- | |
# MIT License | |
# | |
# | |
# AUTHOR | |
# ------- | |
# | |
# Yuki <[email protected]> | |
# | |
GIT_SU_CONF=${GIT_SU_CONF:-$HOME/.gitsu} | |
PROGNAME=$(basename "$0") | |
if [[ -n "$1" ]]; then | |
SU_NAME=$1 | |
else | |
echo -e "usage: git su <name> [git-subcommand <args>]" 1>&2 | |
exit 1 | |
fi | |
GIT_VERSION=$(git --version | cut -d" " -f 3) | |
# from: https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash | |
vercomp () { | |
if [[ $1 == $2 ]] | |
then | |
return 0 | |
fi | |
local IFS=. | |
local i ver1=($1) ver2=($2) | |
# fill empty fields in ver1 with zeros | |
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) | |
do | |
ver1[i]=0 | |
done | |
for ((i=0; i<${#ver1[@]}; i++)) | |
do | |
if [[ -z ${ver2[i]} ]] | |
then | |
# fill empty fields in ver2 with zeros | |
ver2[i]=0 | |
fi | |
if ((10#${ver1[i]} > 10#${ver2[i]})) | |
then | |
return 1 | |
fi | |
if ((10#${ver1[i]} < 10#${ver2[i]})) | |
then | |
return 2 | |
fi | |
done | |
return 0 | |
} | |
extract_repo_dir() { | |
local dir=${@:$#} | |
[[ -d "$dir" ]] && echo "$dir" && return | |
dir="${dir##*/}" | |
[[ -d "$dir" ]] && echo "$dir" && return | |
dir="${dir%.git}" | |
[[ -d "$dir" ]] && echo "$dir" && return | |
pwd | |
} | |
print_su_list() | |
{ | |
git config --name-only --get-regexp '^su\..+\.name$' | sed -e 's/^su\.\(.\+\)\.name$/\1/' | |
} | |
get_config() | |
{ | |
local key=$1 | |
if [[ -e "$GIT_SU_CONF" ]]; then | |
git config --file "$GIT_SU_CONF" --get "$key" 2>/dev/null && return | |
fi | |
git config --get "$key" 2>/dev/null && return | |
return 1 | |
} | |
apply_su() | |
{ | |
local SU_NAME=$1 | |
local USER_NAME USER_EMAIL CORE_SSH_COMMAND | |
if [[ "$(git rev-parse --is-inside-work-tree)" != "true" ]]; then | |
return 1 | |
fi | |
USER_NAME=$(get_config "su.${SU_NAME}.name") | |
if (( $? != 0 )); then | |
echo -e "su.${SU_NAME}.name not defined" 1>&2 | |
return 1 | |
fi | |
USER_EMAIL=$(get_config "su.${SU_NAME}.email") | |
if (( $? != 0 )); then | |
echo -e "su.${SU_NAME}.email not defined" 1>&2 | |
return 1 | |
fi | |
CORE_SSH_COMMAND=$(get_config "su.${SU_NAME}.sshCommand") | |
if (( $? != 0 )); then | |
CORE_SSH_COMMAND= | |
fi | |
git config user.name "$USER_NAME" | |
git config user.email "$USER_EMAIL" | |
if [[ -n "$CORE_SSH_COMMAND" ]]; then | |
vercomp "$GIT_VERSION" 2.3 | |
if (( $? == 2 )); then | |
echo "core.sshCommand not supported (Git v${GIT_VERSION} < v2.3)" 1>&2 | |
fi | |
git config core.sshCommand "$CORE_SSH_COMMAND" | |
else | |
git config --unset core.sshCommand | |
fi | |
} | |
su_git() | |
{ | |
if [[ "$2" == "init" ]] || [[ "$2" == "clone" ]]; then | |
su_git_outrepo_cmd "$@" | |
else | |
su_git_inrepo_cmd "$@" | |
fi | |
} | |
su_git_outrepo_cmd() { | |
local SU_NAME=$1 | |
shift | |
vercomp "$GIT_VERSION" 2.3 | |
if (( $? == 2 )); then | |
echo "core.sshCommand not supported (Git v${GIT_VERSION} < v2.3)" 1>&2 | |
fi | |
CORE_SSH_COMMAND=$(get_config "su.${SU_NAME}.sshCommand") | |
if (( $? != 0 )); then | |
CORE_SSH_COMMAND= | |
fi | |
GIT_SSH_COMMAND="$CORE_SSH_COMMAND" git "$@" && (cd "$(extract_repo_dir "$@")" && apply_su "$SU_NAME") | |
} | |
su_git_inrepo_cmd() { | |
local SU_NAME=$1 | |
shift | |
apply_su "$SU_NAME" && git "$@" | |
} | |
if [[ $# == 1 ]]; then | |
if [[ "$1" == "-l" ]] || [[ "$1" == "--list" ]]; then | |
print_su_list | |
else | |
apply_su "$SU_NAME" | |
fi | |
else | |
su_git "$@" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment