Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 525 lines (515 sloc) 19.1 KB
#!/bin/bash
#
# GPair is a Git Pair programming tool
# Do pair programing with many people, from many domnain names with git.
#
# zsh autocompletion
if [[ -n "$SHELL" ]]; then
USER_SHELL=$SHELL[-3,-1]
if [[ "$USER_SHELL" == "zsh" ]]; then
compctl -k "(alone author for help license list list-profiles list-colleagues new-profile new-colleague show usage version with whoami hook forever)" gpair
fi
fi
# ~~~~~ Functions ~~~~~
function show_banner {
echo "GPair version $APPLICATION_VERSION by zedtux under GPLv3"
echo
}
function show_version {
echo "$APPLICATION_VERSION"
}
function show_author {
echo "zedtux <zedtux@zedroot.org> [https://launchpad.net/~zedtux]"
}
function show_license {
echo "GPLv3 [http://gplv3.fsf.org/]"
}
function show_help {
show_banner
echo "Usage: $APPLICATION_NAME [action] (value)"
echo
echo "Actions:"
echo " alone Define that you are now working alone for the current profile."
echo " author Show the application's author."
echo " for Define the profile to use for the current pair."
echo " forever Write passing configuration into a gpairrc file."
echo " help Show this screen."
echo " hook Install or upgrade RVM hook. (Usefull if you re-install rvm.)"
echo " license Show the application's license."
echo " list Show all aliases."
echo " list-profiles Show the list of registered profiles."
echo " list-colleagues Show the list of registered colleagues."
echo " new-profile Register a new profile."
echo " new-colleague Register a new colleague."
echo " show Show the current pairing string."
echo " usage Show usage examples."
echo " version Show the application's version."
echo " with Set the colleague with whom you are working for the current profile."
echo " whoami Set or show who you are."
}
function show_usage_examples {
show_banner
echo "Usage examples"
echo
echo " # To see who you are:"
echo " $ $APPLICATION_NAME whoami"
echo
echo " # To define who you are:"
echo " $ $APPLICATION_NAME whoami '$GPAIR_WHOAMI_STRING_EXAMPLE'"
echo
echo " # To add a new colleague associated with an alias:"
echo " $ $APPLICATION_NAME new-colleague alias_name='$GPAIR_WHOAMI_STRING_EXAMPLE'"
echo " -> Example: \`$APPLICATION_NAME new-colleague greg='Grégoire Clanton'\`"
echo
echo
echo " # To add a new profile associated to an alias:"
echo " $ $APPLICATION_NAME new-profile profile_name"
echo
echo " # To see the list of registered things:"
echo " $ $APPLICATION_NAME list"
echo
echo " # To set the colleague whom you are working with:"
echo " $ $APPLICATION_NAME with colleague_alias for profile_alias"
echo
echo " For example, if you are working with the colleague that is registered"
echo " with the alias greg, for profile registered with alias free:"
echo " $ $APPLICATION_NAME with greg for free"
echo
echo " To define that you're working alone:"
echo " $ $APPLICATION_NAME alone for alias_name"
echo
echo " If now you want to save forever (or until you change it) a configuration:"
echo " $ $APPLICATION_NAME alone for alias_name forever"
echo
}
function show_profiles_list {
if [ -f "$PROFILES_FILE" ]; then
while read line
do
PROFILE_ALIAS=`echo "$line" | cut -d "=" -f1`
PROFILE_CONTENT=`echo "$line" | cut -d "=" -f2`
echo "As $PROFILE_ALIAS: $PROFILE_CONTENT"
done < "$PROFILES_FILE"
else
echo "You have not register any profile until now."
message_look_at_usage
fi
}
function show_all {
echo "Colleagues:"
show_colleagues_list
echo
echo "Profiles:"
show_profiles_list
}
function show_pair {
if [[ -z "$GIT_AUTHOR_NAME" ]]; then
echo "You didn't defined pairing yet. "
message_look_at_usage
else
echo "Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>"
echo "Commiter: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
fi
}
function show_invalid_setup {
echo "Your setup is not valid. Please, before continuing, fix those points:"
echo
if [[ "$CURRENT_USER_NAME" == "Unknow" ]]; then
echo " * Set who you are with \`$APPLICATION_NAME whoami\`."
echo
message_look_at_usage
fi
}
function whoami {
if [[ -z "$GPAIR_WHOAMI" ]]; then
if [[ "$CURRENT_USER_NAME" == "Unknow" ]]; then
echo "I currently not know who you are."
else
echo "$CURRENT_USER_NAME"
fi
else
echo "$GPAIR_WHOAMI" > "$GPAIR_WHOAMI_FILE"
fi
}
function check_email_address {
if [ -z "$EMAIL_ADDRESS" ]; then
echo "$ERROR_TAG Given email address is empty."
else
validate_email="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
if [[ $EMAIL_ADDRESS =~ $validate_email ]]; then
EMAIL_ADDRESS_IS_VALID="true"
only_alphabetic="^[A-Za-z]+$"
if [[ `echo "$EMAIL_ADDRESS" | cut -d "@" -f 1` =~ $only_alphabetic ]]; then
EMAIL_COMPOSED="false"
else
EMAIL_COMPOSED="true"
fi
EXTRACTED_ALIAS=${EMAIL_ADDRESS%%[!a-zA-Z]*}
EXTRACTED_DOMAIN=`echo "$EMAIL_ADDRESS" | cut -d "@" -f 2`
else
echo "$ERROR_TAG Given email address is invalid."
fi
fi
}
function message_look_at_usage {
echo "Look at usage examples with: \`$APPLICATION_NAME usage\`"
}
function install_rvm_hook {
echo " Installing gpair hook into rvm..."
touch "$RVM_AFTERCD_HOOK_PATH"
echo "#!/usr/bin/env bash" >> "$RVM_AFTERCD_HOOK_PATH"
echo "[[ -f \"\$PWD/.gpairrc\" && \"\$PWD\" != \"\$HOME\" ]] && gpair --gpairrc \"\$PWD/.gpairrc\"" >> "$RVM_AFTERCD_HOOK_PATH"
chmod 755 "$RVM_AFTERCD_HOOK_PATH"
}
function check_and_upgrade_hook {
if [[ -s "$HOME/.rvm/scripts/rvm" ]]; then
echo "[!] Rvm detected."
[[ -d "$HOME/.rvm/hooks" ]] || mkdir -p "$HOME/.rvm/hooks"
if [[ ! -f "$HOME/.rvm/hooks/after_cd" ]]; then
install_rvm_hook
else
echo " Checking gpair hook..."
gpair_hook_string="^.*\[\[\ \-f\ \"\\$\PWD\/\.gpairrc\"\ \&\&\ \"\\$\PWD\"\ \!\=\ \"\\$\HOME\"\ \]\]\ \&\&\ gpair\ \-\-gpairrc\ \"\\$\PWD\/.gpairrc\""
AFTER_CD_HOOK=`cat $HOME/.rvm/hooks/after_cd`
if [[ $AFTER_CD_HOOK =~ $gpair_hook_string ]]; then
echo " Gpair hook already present. Nothing todo."
else
echo " Adding gpair hook to $RVM_AFTERCD_HOOK_PATH"
install_rvm_hook
fi
fi
fi
}
function write_configuration {
echo "$GPAIR_ARGS" > "`pwd`/.gpairrc"
}
# ----- Colleagues -----
function parse_colleague_string {
COLLEAGUE_ALIAS=`echo "$COLLEAGUE_STRING" | cut -d "=" -f1 | tr "A-Z" "a-z"`
COLLEAGUE_WITHOUT_ALIAS=`echo "$COLLEAGUE_STRING" | cut -d "=" -f2`
COLLEAGUE_NAME=`echo $COLLEAGUE_WITHOUT_ALIAS | awk '{gsub(/^ +| +$/,"")}1'`
if [[ -z "$COLLEAGUE_NAME" ]] || [[ "$COLLEAGUE_NAME" == "${COLLEAGUE_NAME% *}" ]]; then
HAVE_ERROR=true;
echo "$ERROR_TAG Unable to read your colleague's name and first name."
fi
}
function check_if_colleague_alias_exists {
if [ -f "$COLLEAGUES_FILE" ]; then
if [ -z "$COLLEAGUE_STRING" ] && [ -n "$COLLEAGUE_ALIAS" ]; then
COLLEAGUE_STRING=$COLLEAGUE_ALIAS
fi
COLLEAGUES=`cat "$COLLEAGUES_FILE" | tr -d " " | tr "A-Z" "a-z"`
if [ `echo "$COLLEAGUES" | grep -e "^$COLLEAGUE_ALIAS=" | wc -l | tr -d " "` != "0" ]; then
COLLEAGUE_ALIAS_EXISTS="true"
while read line
do
if [ `echo "$line" | grep -e "^$COLLEAGUE_ALIAS=" | wc -l | tr -d " "` != "0" ]; then
COLLEAGUE_STRING="$line"
parse_colleague_string
break
fi
done < "$COLLEAGUES_FILE"
fi
fi
}
function check_if_colleague_exists {
if [ -f "$COLLEAGUES_FILE" ]; then
COLLEAGUES=`cat "$COLLEAGUES_FILE" | tr -d " " | tr "A-Z" "a-z"`
COLLEAGUE=`echo "$COLLEAGUE_STRING" | cut -d "=" -f2`
COLLEAGUE=`echo "$COLLEAGUE" | tr -d " " | tr "A-Z" "a-z"`
if [ `echo "$COLLEAGUES" | grep "^$COLLEAGUE=" | wc -l | tr -d " "` != "0" ]; then
COLLEAGUE_EXISTS=true
fi
fi
}
function register_colleague {
parse_colleague_string
if [ $HAVE_ERROR ]; then
echo "See usage examples with: \`$APPLICATION_NAME usage\`"
else
check_if_colleague_alias_exists
if [[ "$COLLEAGUE_ALIAS_EXISTS" == "true" ]]; then
echo "$ERROR_TAG The alias $COLLEAGUE_ALIAS is already associated to $COLLEAGUE_NAME"
else
check_if_colleague_exists
if [[ "$COLLEAGUE_EXISTS" == "true" ]]; then
echo "$ERROR_TAG This colleague already exists! Check the list with \`$APPLICATION_NAME list\`"
else
echo "$COLLEAGUE_ALIAS=$COLLEAGUE_NAME" >> "$COLLEAGUES_FILE"
echo "Your new colleague $COLLEAGUE_NAME registered with alias $COLLEAGUE_ALIAS !"
fi
fi
fi
}
function show_colleagues_list {
if [ -f "$COLLEAGUES_FILE" ]; then
while read line
do
COLLEAGUE_STRING="$line"
parse_colleague_string
if [ $HAVE_ERROR ]; then
echo "See usage examples with: \`$APPLICATION_NAME usage\`"
else
echo "As $COLLEAGUE_ALIAS: $COLLEAGUE_NAME"
fi
done < "$COLLEAGUES_FILE"
else
echo "You have not registered any colleagues until now."
message_look_at_usage
fi
}
# ----- Profiles -----
function check_if_profile_exists {
if [[ -f "$PROFILES_FILE" ]]; then
PROFILES=`cat "$PROFILES_FILE" | tr -d " " | tr "A-Z" "a-z"`
PROFILE=`echo "$PROFILE_STRING" | cut -d "=" -f2`
PROFILE=`echo "$PROFILE" | tr -d " " | tr "A-Z" "a-z"`
if [ `echo "$PROFILES" | grep "^$PROFILE=" | wc -l | tr -d " "` != "0" ]; then
PROFILE_EXISTS=true
fi
fi
}
function parse_profile_string {
PROFILE_ALIAS=`echo "$PROFILE_STRING" | cut -d "=" -f1 | tr "A-Z" "a-z"`
PROFILE_WITHOUT_ALIAS=`echo "$PROFILE_STRING" | cut -d "=" -f2`
EMAIL_ADDRESS=`echo $PROFILE_WITHOUT_ALIAS | awk '{gsub(/^ +| +$/,"")}1'`
ALIAS_FOR_PROFILE=`echo "$EMAIL_ADDRESS" | cut -d ":" -f1`
EMAIL_ADDRESS=`echo "$EMAIL_ADDRESS" | cut -d ":" -f2`
check_email_address
if [ $EMAIL_ADDRESS_IS_VALID ]; then
if [[ "$WORKING_ALONE" == "true" ]]; then
CURRENT_USER_ALIAS=`echo "$EMAIL_ADDRESS" | cut -d "@" -f1`
else
CURRENT_USER_ALIAS=$ALIAS_FOR_PROFILE
fi
PROFILE_DOMAIN_NAME=`echo "$EMAIL_ADDRESS" | cut -d "@" -f2`
fi
PROFILE_ALIAS_EXISTS="true"
}
function check_if_profile_alias_exists {
if [[ -f "$PROFILES_FILE" ]]; then
if [[ -z "$PROFILE_STRING" && -n "$PROFILE_ALIAS" ]]; then
PROFILE_STRING=$PROFILE_ALIAS
fi
PROFILES=`cat "$PROFILES_FILE" | tr -d " " | tr "A-Z" "a-z"`
if [ `echo "$PROFILES" | grep -e "^$PROFILE_ALIAS=" | wc -l | tr -d " "` != "0" ]; then
PROFILE_ALIAS_EXISTS="true"
while read line
do
if [ `echo "$line" | grep -e "^$PROFILE_ALIAS=" | wc -l | tr -d " "` != "0" ]; then
PROFILE_STRING="$line"
parse_profile_string
break
fi
done < "$PROFILES_FILE"
fi
fi
}
function register_profile {
check_if_profile_exists
if [ $PROFILE_EXISTS ]; then
echo "$ERROR_TAG The profile $PROFILE_STRING already exists."
else
echo "This wizard will help you to create the new profile $PROFILE_STRING."
echo
echo "Your email address will be used when working alone as the git author email address,"
echo "and also used to define the git author email address domain name when working with someone else."
echo "For example:"
echo "Given your email address is alain@example.com, when you will work alone the git author email address"
echo "will be alain@example.com. But if you are working with greg, the git author email address will"
echo "be dev+greg+alain@example.com"
echo
echo "What is your email address for this profile? (i.e: alain@example.com)"
read EMAIL_ADDRESS
check_email_address
if [[ "$EMAIL_ADDRESS_IS_VALID" != "true" ]]; then
echo "$ERROR_TAG The given email address is invalid!"
else
if [[ "$EMAIL_COMPOSED" == "true" ]]; then
echo
echo "The given email address is made of several words."
echo "The git author email address will not be like you'll expect when working with a colleague."
echo "If you are working with greg, it will be dev+greg+$EMAIL_ADDRESS."
echo "To fix that, you should provide me now an alias."
echo "For example, you should use $EXTRACTED_ALIAS to set the git author email address to dev+greg+$EXTRACTED_ALIAS@$EXTRACTED_DOMAIN"
echo
echo "Which alias would you like for this profile? (default: $EXTRACTED_ALIAS)"
read ALIAS_FOR_PROFILE
fi
[[ -z "$ALIAS_FOR_PROFILE" ]] && ALIAS_FOR_PROFILE=$EXTRACTED_ALIAS
echo
echo "Result:"
echo " When working alone the git author email address will be $EMAIL_ADDRESS"
echo " When working with greg the git author email address will be dev+greg+$ALIAS_FOR_PROFILE@$EXTRACTED_DOMAIN"
echo
echo "Is this correct? [Yn]"
read ACCEPT_SETUP
POSSIBLE_ANSWERS=( y ye yes Y YE YES )
for ANSWER in ${POSSIBLE_ANSWERS[@]}
do
if [[ "$ACCEPT_SETUP" == "$ANSWER" || "$ACCEPT_SETUP" == "" ]]; then
echo "$PROFILE_STRING=$ALIAS_FOR_PROFILE:$EMAIL_ADDRESS" >> "$PROFILES_FILE"
echo "Your new profile has been registered with the alias $PROFILE_STRING."
echo "To use it: \`$APPLICATION_NAME alone for $PROFILE_STRING\` or \`$APPLICATION_NAME with greg for $PROFILE_STRING\`."
break
fi
done
fi
fi
}
function set_working_with {
[[ "$SETUP_IS_INVALID" == "true" ]] && show_invalid_setup
[[ "$WORKING_ALONE" == "true" ]] || check_if_colleague_alias_exists
check_if_profile_alias_exists
if [[ "$COLLEAGUE_ALIAS_EXISTS" == "true" || "$WORKING_ALONE" == "true" ]] && [[ "$PROFILE_ALIAS_EXISTS" == "true" ]]; then
if [[ "$WORKING_ALONE" == "true" ]]; then
export GIT_AUTHOR_NAME="$CURRENT_USER_NAME" GIT_AUTHOR_EMAIL="$CURRENT_USER_ALIAS@$PROFILE_DOMAIN_NAME"
else
export GIT_AUTHOR_NAME="$COLLEAGUE_NAME and $CURRENT_USER_NAME" GIT_AUTHOR_EMAIL="dev+$COLLEAGUE_ALIAS+$CURRENT_USER_ALIAS@$PROFILE_DOMAIN_NAME"
fi
export GIT_COMMITTER_NAME="$CURRENT_USER_NAME" GIT_COMMITTER_EMAIL="$EMAIL_ADDRESS"
echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>"
if [[ "$WORKING_ALONE" == "true" ]]; then
GPAIRRC_CONTENT="alone for $PROFILE_ALIAS"
else
GPAIRRC_CONTENT="with $COLLEAGUE_ALIAS for $PROFILE_ALIAS"
fi
echo "$GPAIRRC_CONTENT" > "$PAIR_FILE"
elif [[ "$COLLEAGUE_ALIAS_EXISTS" == "false" && "$WORKING_ALONE" == "false" ]]; then
echo "$ERROR_TAG Unknow colleague alias $COLLEAGUE_ALIAS."
message_look_at_usage
elif [[ "$PROFILE_ALIAS_EXISTS" == "false" ]]; then
echo "$ERROR_TAG Unknow profile alias $PROFILE_ALIAS."
message_look_at_usage
fi
}
function run_gpairrc_file {
DO_GPAIR=1
GPAIR_GIT_CONFIG_PATH="$(pwd)/.git/config"
if [[ -f $GPAIR_GIT_CONFIG_PATH ]]; then
search_author=".*\[author\]"
search_author_name=".*\[author\].*name\ \=\ "
search_author_email=".*\[author\].*email\ \=\ "
GIT_CONFIG_FILE=`cat $GPAIR_GIT_CONFIG_PATH`
if [[ $GIT_CONFIG_FILE =~ $search_author ]]; then
if [[ $GIT_CONFIG_FILE =~ $search_author_name || $GIT_CONFIG_FILE =~ $search_author_email ]]; then
DO_GPAIR=0
fi
fi
fi
if [[ $DO_GPAIR == 1 ]]; then
gpair `cat "$GPAIRRC"`
GPAIRRC="Done"
else
echo "Gpair: Nothing todo as you have defined author values (from .git/config)."
fi
}
# ~~~~~ Unix cp command callback ~~~~~
if [[ ! -s "$HOME/.rvm/scripts/rvm" ]]; then
echo "Overriding cd function..."
function cd () {
builtin cd $@
[[ -f "`pwd`/.gpairrc" && "`pwd`" != "$HOME" ]] && gpair --gpairrc "`pwd`/.gpairrc"
}
fi
# ~~~~~ Arguments parser ~~~~~
function gpair {
# ~~~~~ Configuration ~~~~~
APPLICATION_VERSION="1.3"
APPLICATION_NAME="gpair"
CONFIG_PATH="$HOME/.gpair/data"
[[ ! -d "$CONFIG_PATH/" ]] && mkdir "$CONFIG_PATH"
GPAIR_WHOAMI_STRING_EXAMPLE="Firstname Lastname"
GPAIR_WHOAMI=""
GPAIR_WHOAMI_FILE="$CONFIG_PATH/whoami"
COLLEAGUES_FILE="$CONFIG_PATH/colleagues"
PROFILES_FILE="$CONFIG_PATH/profiles"
PAIR_FILE="$HOME/.gpairrc"
CURRENT_USER_NAME="Unknow"
CURRENT_USER_ALIAS=""
DOMAIN_STRING=""
[[ -f "$GPAIR_WHOAMI_FILE" ]] && CURRENT_USER_NAME=`cat $GPAIR_WHOAMI_FILE | awk '{gsub(/^ +| +$/,"")}1'`
[[ "$CURRENT_USER_NAME" == "Unknow" ]] && SETUP_IS_INVALID="true" || SETUP_IS_INVALID="false"
ERROR_TAG="Error:"
COLLEAGUE_ALIAS=""
PROFILE_ALIAS=""
WORKING_ALONE="false"
COLLEAGUE_ALIAS_EXISTS="false"
COLLEAGUE_ALIAS=""
PROFILE_ALIAS_EXISTS="false"
PROFILE_ALIAS=""
CURRENT_OPTION=""
OPTION_ARG=""
GPAIRRC=""
GPAIRRC_CONTENT=""
PROFILE_EXISTS=""
EMAIL_ADDRESS_IS_VALID=""
ALIAS_FOR_PROFILE=""
RVM_AFTERCD_HOOK_PATH="$HOME/.rvm/hooks/after_cd_gpair"
GPAIR_ARGS=""
search_slash=".*\/.*"
for arg
do
# Save arguments for forever switch
[[ $arg =~ $search_slash ]] || [[ "$arg" == "--gpairrc" ]] || [[ "$arg" == "forever" ]] || GPAIR_ARGS="$GPAIR_ARGS $arg"
case "$arg" in
--help|help) show_help; CURRENT_OPTION="$arg";;
--usage|usage) show_usage_examples; CURRENT_OPTION="$arg";;
--version|version) show_version; CURRENT_OPTION="$arg";;
--author|author) show_author; CURRENT_OPTION="$arg";;
--license|license) show_license; CURRENT_OPTION="$arg";;
--gpairrc|whoami|list|list-colleagues|list-profiles|new-colleague|new-profile|with|show|for|hook|forever) CURRENT_OPTION="$arg";;
alone) WORKING_ALONE="true";;
*)
OPTION_ARG="$arg"
case "$CURRENT_OPTION" in
whoami) GPAIR_WHOAMI="$OPTION_ARG"; whoami;;
new-colleague) COLLEAGUE_STRING="$OPTION_ARG"; register_colleague;;
new-profile) PROFILE_STRING="$OPTION_ARG"; register_profile;;
with) COLLEAGUE_ALIAS="$OPTION_ARG";;
for) PROFILE_ALIAS="$OPTION_ARG";;
--gpairrc) [[ -f "$OPTION_ARG" ]] && GPAIRRC="$OPTION_ARG"; run_gpairrc_file;;
*) echo "$ERROR_TAG Unknow option $OPTION_ARG. Try \`$APPLICATION_NAME --help\`."; CURRENT_OPTION="$OPTION_ARG";;
esac
[[ -z "$GPAIRRC" ]] && [[ -n "$COLLEAGUE_ALIAS" || "$WORKING_ALONE" == "true" ]] && [[ -n "$PROFILE_ALIAS" ]] && set_working_with
;;
esac
done
case "$CURRENT_OPTION" in
whoami) [[ -z "$OPTION_ARG" ]] && whoami ;;
list) show_all;;
list-colleagues) show_colleagues_list;;
list-profiles) show_profiles_list;;
new-*)
if [[ -z "$OPTION_ARG" ]]; then
echo "$ERROR_TAG You must give a value for $CURRENT_OPTION action."
message_look_at_usage
fi
;;
with)
if [[ -z "$OPTION_ARG" ]]; then
echo "$ERROR_TAG You must give the alias of the colleague you want to work with."
message_look_at_usage
fi
;;
for)
if [[ -z "$OPTION_ARG" ]]; then
echo "$ERROR_TAG You must give the alias of the domain you want to work for."
message_look_at_usage
fi
;;
show) show_pair;;
hook) check_and_upgrade_hook;;
forever) write_configuration;;
*)
if [[ -z "$CURRENT_OPTION" ]]; then
if [[ "$SETUP_IS_INVALID" == "true" ]]; then
show_invalid_setup
else
show_help
fi
fi
;;
esac
}
[[ -f "$HOME/.gpairrc" ]] && gpair --gpairrc "$HOME/.gpairrc"