Skip to content

Commit 0889bbb

Browse files
Merge pull request #80 from mabaritw/master
added install and uninstall scripts for installation with homebrew
2 parents 0c82b82 + 73e0c11 commit 0889bbb

File tree

2 files changed

+381
-0
lines changed

2 files changed

+381
-0
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
shopt -s extglob
4+
5+
DEBUG=${DEBUG:-''}
6+
7+
# default is a pre-commit hook; if "pre-push" is the first arg to the script, then it sets up as pre-push
8+
declare HOOK_SCRIPT='pre-commit'
9+
if [[ $# -gt 0 && $1 =~ pre-push.* ]] ; then
10+
HOOK_SCRIPT='pre-push'
11+
fi
12+
13+
function run() {
14+
# Arguments: $1 = 'pre-commit' or 'pre-push'. whether to set talisman up as pre-commit or pre-push hook
15+
# Environment variables:
16+
# DEBUG="any-non-emply-value": verbose output for debugging the script
17+
# FORCE_DOWNLOAD="non-empty" : download talisman binary & hook script even if already installed. useful as an upgrade option.
18+
# VERSION="version-number" : download a specific version of talisman
19+
# INSTALL_ORG_REPO="..." : the github org/repo to install from (default thoughtworks/talisman)
20+
21+
# Get other related install scripts from github
22+
# Copy the talisman_hook_script to $TALISMAN_SETUP_DIR (/usr/local/talisman/bin)
23+
# Setup a hook script at <git-template-dir>/hooks/pre-<commit/push>.
24+
# When a new repo is created via either git clone or init, this hook script is copied across.
25+
# This is symlinked to the talisman_hook_script in $TALISMAN_SETUP_DIR, for ease of upgrade.
26+
# For each git repo found in the search root (default $HOME), setup a hook script at .git/hooks/pre-<commit/push>
27+
# This is symlinked to the talisman_hook_script in $TALISMAN_SETUP_DIR, for ease of upgrade.
28+
29+
declare TALISMAN_BINARY_NAME="talisman"
30+
31+
32+
IFS=$'\n'
33+
INSTALL_ORG_REPO=${INSTALL_ORG_REPO:-'thoughtworks/talisman'}
34+
35+
DEFAULT_GLOBAL_TEMPLATE_DIR="$HOME/.git-template" # create git-template dir here if not already setup
36+
TALISMAN_SETUP_DIR="/usr/local/Cellar/talisman/*/bin" # location of central install: talisman binary and hook script
37+
TALISMAN_HOOK_SCRIPT_DIR="$HOME/.talisman"
38+
TALISMAN_HOOK_SCRIPT_PATH="$HOME/.talisman"/talisman_hook_script
39+
SCRIPT_ORG_REPO=${SCRIPT_ORG_REPO:-$INSTALL_ORG_REPO}
40+
SCRIPT_BASE="https://raw.githubusercontent.com/${SCRIPT_ORG_REPO}/master/global_install_scripts"
41+
42+
TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'talisman_setup')
43+
trap "rm -r ${TEMP_DIR}" EXIT
44+
chmod 0700 ${TEMP_DIR}
45+
46+
REPO_HOOK_SETUP_SCRIPT_PATH="${TEMP_DIR}/setup_talisman_hook_in_repo.bash" # script for setting up git hooks on one repo
47+
48+
function echo_error() {
49+
echo -ne $(tput setaf 1) >&2
50+
echo "$1" >&2
51+
echo -ne $(tput sgr0) >&2
52+
}
53+
export -f echo_error
54+
55+
function echo_debug() {
56+
[[ -z "${DEBUG}" ]] && return
57+
echo -ne $(tput setaf 3) >&2
58+
echo "$1" >&2
59+
echo -ne $(tput sgr0) >&2
60+
}
61+
export -f echo_debug
62+
63+
function echo_success {
64+
echo -ne $(tput setaf 2)
65+
echo "$1" >&2
66+
echo -ne $(tput sgr0)
67+
}
68+
export -f echo_success
69+
70+
function get_dependent_scripts() {
71+
echo "Downloading dependent scripts"
72+
curl --silent "${SCRIPT_BASE}/talisman_hook_script.bash" > ${TEMP_DIR}/talisman_hook_script.bash
73+
curl --silent "${SCRIPT_BASE}/setup_talisman_hook_in_repo.bash" > ${REPO_HOOK_SETUP_SCRIPT_PATH}
74+
chmod +x ${REPO_HOOK_SETUP_SCRIPT_PATH}
75+
echo "Contents of temp_dir: `ls ${TEMP_DIR}`"
76+
}
77+
78+
function setup_talisman() {
79+
# setup talisman & hook script in a central location for ease of download ($TALISMAN_SETUP_DIR)
80+
mkdir -p ${TALISMAN_HOOK_SCRIPT_DIR}
81+
sed -e "s@\${TALISMAN_BINARY}@"${TALISMAN_SETUP_DIR}/${TALISMAN_BINARY_NAME}"@" ${TEMP_DIR}/talisman_hook_script.bash > ${TALISMAN_HOOK_SCRIPT_PATH}
82+
chmod +x ${TALISMAN_HOOK_SCRIPT_PATH}
83+
add_talisman_home_as $TALISMAN_SETUP_DIR
84+
}
85+
86+
function setup_git_template_talisman_hook() {
87+
# check for existing git-template dir, if not create it in $HOME/.git-template
88+
# if git-template dir already contains the pre-<commit/push> script that we want to use for talisman,
89+
# don't setup talisman, warn the user and suggest using a hook chaining mechanism like pre-commit (from pre-commit.com)
90+
# Setup a symlink from <.git-template dir>/hooks/pre-<commit/push> to the central talisman hook script
91+
92+
TEMPLATE_DIR=$(git config --global init.templatedir) || true # find the template_dir if it exists
93+
94+
if [[ "$TEMPLATE_DIR" == "" ]]; then # if no template dir, create one
95+
echo "No git template directory is configured. Let's add one."
96+
echo "(this will override any system git templates and modify your git config file)"
97+
echo
98+
read -u1 -p "Git template directory: ($DEFAULT_GLOBAL_TEMPLATE_DIR) " TEMPLATE_DIR
99+
echo
100+
TEMPLATE_DIR=${TEMPLATE_DIR:-$DEFAULT_GLOBAL_TEMPLATE_DIR}
101+
git config --global init.templatedir ${TEMPLATE_DIR}
102+
else
103+
echo "Using existing git template dir: $TEMPLATE_DIR."
104+
echo
105+
fi
106+
107+
# Support '~' in path
108+
TEMPLATE_DIR=${TEMPLATE_DIR/#\~/$HOME}
109+
110+
if [ -e "${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}" ]; then
111+
# does this handle the case of upgrade - already have the hook installed, but is the old version?
112+
if [ "${TALISMAN_HOOK_SCRIPT_PATH}" -ef "${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}" ]; then
113+
echo_success "Talisman template hook already installed."
114+
else
115+
echo_error "It looks like you already have a ${HOOK_SCRIPT} hook"
116+
echo_error "installed at '${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}'."
117+
echo_error "If this is a expected, you should consider setting-up a tool"
118+
echo_error "like pre-commit (brew install pre-commit)"
119+
echo_error "WARNING! Global talisman hook not installed into git template."
120+
echo_error "Newly (git-init/git-clone)-ed repositories will not be covered by talisman."
121+
fi
122+
else
123+
mkdir -p "$TEMPLATE_DIR/hooks"
124+
echo "Setting up template ${HOOK_SCRIPT} hook"
125+
ln -svf ${TALISMAN_HOOK_SCRIPT_PATH} ${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}
126+
echo_success "Talisman template hook successfully installed."
127+
fi
128+
}
129+
130+
function add_talisman_home_as() {
131+
# set TALISMAN_HOME path for user if user opts for it
132+
# user has option to set TALISMAN_HOME in .bashrc or .profile
133+
# user can opt out of auto-setup of TALISMAN_HOME to set it up later manually
134+
TALISMAN_SETUP_DIR="$1"
135+
echo "Setting up TALISMAN_HOME in path"
136+
137+
if [ -n "${TALISMAN_HOME:-}" ]; then
138+
echo -e "TALISMAN_HOME is already set\n"
139+
return 0;
140+
fi
141+
142+
BASHRC_OPT="Set TALISMAN_HOME in ~/.bashrc"
143+
BASHPROFILE_OPT="Set TALISMAN_HOME in ~/.bash_profile"
144+
PROFILE_OPT="Set TALISMAN_HOME in ~/.profile"
145+
SELFSETUP_OPT="I will set it later"
146+
TALISMAN_HOME=""
147+
148+
echo -e "\n\nPLEASE CHOOSE WHERE YOU WISH TO SET TALISMAN_HOME VARIABLE (Enter option number): "
149+
options=(${BASHRC_OPT} ${BASHPROFILE_OPT} ${PROFILE_OPT} ${SELFSETUP_OPT})
150+
select opt in "${options[@]}"
151+
do
152+
case $opt in
153+
${BASHRC_OPT})
154+
set_talisman_home_in ~/.bashrc
155+
break
156+
;;
157+
${BASHPROFILE_OPT})
158+
set_talisman_home_in ~/.bash_profile
159+
break
160+
;;
161+
${PROFILE_OPT})
162+
set_talisman_home_in ~/.profile
163+
break
164+
;;
165+
${SELFSETUP_OPT})
166+
echo "You chose to set TALISMAN_HOME by yourself. Remember to set TALISMAN_HOME=${TALISMAN_SETUP_DIR}\n\n"
167+
break
168+
;;
169+
*) echo "invalid option $REPLY";;
170+
esac
171+
done
172+
}
173+
174+
function set_talisman_home_in() {
175+
ENV_FILE="$1"
176+
echo -e "Setting up TALISMAN_HOME in ${ENV_FILE}"
177+
echo "export TALISMAN_HOME=${TALISMAN_SETUP_DIR}" >> ${ENV_FILE}
178+
printf '\e[1;34m%-6s\e[m' "After the installation is complete, you will need to manually restart the terminal or source ${ENV_FILE} file"
179+
echo
180+
read -n 1 -s -r -p "Press any key to continue ..."
181+
echo
182+
}
183+
184+
function setup_git_talisman_hooks_at() {
185+
# find all .git repos from a specified $SEARCH_ROOT and setup .git/hooks/pre-<commit/push> in each of those
186+
# Symlink .git/hooks/pre-<commit/push> to the central talisman hook script
187+
# use find -name .git -exec REPO_HOOK_SETUP_SCRIPT to find all git repos and setup the hook
188+
# If the $SEARCH_ROOT is root, then use sudo and ask for the user's password to execute
189+
# This will not clobber any pre-existing hooks, instead suggesting a hook chaining tool like pre-commit (pre-commit.com)
190+
# The REPO_HOOK_SETUP_SCRIPT takes care of pre-commit vs pre-push & not clobbering any hooks which are already setup
191+
# If the REPO_HOOK_SETUP_SCRIPT finds a pre-existing hook, it will write these to the EXCEPTIONS_FILE
192+
# Look into the REPO_HOOK_SETUP_SCRIPT for more detailed info on that script
193+
194+
SEARCH_ROOT="$1"
195+
SEARCH_CMD="find"
196+
EXTRA_SEARCH_OPTS=""
197+
echo -e "\tSearching ${SEARCH_ROOT} for git repositories"
198+
199+
SUDO_PREFIX=""
200+
if [[ "${SEARCH_ROOT}" == "/" ]]; then
201+
echo -e "\tPlease enter your password when prompted to enable script to search as root user:"
202+
SUDO_PREFIX="sudo"
203+
EXTRA_SEARCH_OPTS="-xdev \( -path '/private/var' -prune \) -o"
204+
fi
205+
EXCEPTIONS_FILE=${TEMP_DIR}/pre-existing-hooks.paths
206+
touch ${EXCEPTIONS_FILE}
207+
208+
CMD_STRING="${SUDO_PREFIX} ${SEARCH_CMD} ${SEARCH_ROOT} ${EXTRA_SEARCH_OPTS} -name .git -type d -exec ${REPO_HOOK_SETUP_SCRIPT_PATH} ${TALISMAN_HOOK_SCRIPT_PATH} ${EXCEPTIONS_FILE} {} ${HOOK_SCRIPT} \;"
209+
210+
echo_debug "EXECUTING: ${CMD_STRING}"
211+
eval "${CMD_STRING}" || true
212+
213+
NUMBER_OF_EXCEPTION_REPOS=`cat ${EXCEPTIONS_FILE} | wc -l`
214+
215+
OS=$(uname -s)
216+
if [ ${NUMBER_OF_EXCEPTION_REPOS} -gt 0 ]; then
217+
EXCEPTIONS_FILE_HOME_PATH="${HOME}/talisman_missed_repositories.paths"
218+
mv ${EXCEPTIONS_FILE} ${EXCEPTIONS_FILE_HOME_PATH}
219+
echo_error ""
220+
echo_error "Please see ${EXCEPTIONS_FILE_HOME_PATH} for a list of repositories"
221+
echo_error "that couldn't automatically be hooked up with talisman as ${HOOK_SCRIPT}"
222+
echo_error "You should consider installing a tool like pre-commit (https://pre-commit.com) in those repositories"
223+
echo_error "Add the following repo definition into .pre-commit-config.yaml after installing pre-commit in each such repository"
224+
tee $HOME/.talisman-precommit-config <<END_OF_SCRIPT
225+
- repo: local
226+
hooks:
227+
- id: talisman-precommit
228+
name: talisman
229+
entry: bash -c 'if [ -n "\${TALISMAN_HOME:-}" ]; then \${TALISMAN_HOME}/talisman_hook_script pre-commit; else echo "TALISMAN does not exist. Consider installing from https://github.com/thoughtworks/talisman . If you already have talisman installed, please ensure TALISMAN_HOME variable is set to where talisman_hook_script resides, for example, TALISMAN_HOME=\${HOME}/.talisman/bin"; fi'
230+
language: system
231+
pass_filenames: false
232+
types: [text]
233+
verbose: true
234+
END_OF_SCRIPT
235+
fi
236+
}
237+
238+
get_dependent_scripts
239+
240+
# currently doesn't check if the talisman binary and the talisman hook script are upto date
241+
# would be good to create a separate script which does the upgrade and the initial install
242+
setup_talisman
243+
echo "Setting up ${HOOK_SCRIPT} hook in git template directory"
244+
setup_git_template_talisman_hook
245+
echo
246+
echo "Setting up talisman hook recursively in git repos"
247+
read -p "Please enter root directory to search for git repos (Default: ${HOME}): " SEARCH_ROOT
248+
SEARCH_ROOT=${SEARCH_ROOT:-$HOME}
249+
setup_git_talisman_hooks_at $SEARCH_ROOT
250+
}
251+
252+
run $0 $@
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
shopt -s extglob
4+
5+
DEBUG=${DEBUG:-''}
6+
7+
declare HOOK_SCRIPT='pre-commit' # TODO: need ability to uninstall pre-push hook as well.
8+
if [[ $# -gt 0 && $1 =~ pre-push.* ]] ; then
9+
HOOK_SCRIPT='pre-push'
10+
fi
11+
12+
function run() {
13+
# Arguments: $1 = 'pre-commit' or 'pre-push'. whether to set talisman up as pre-commit or pre-push hook : TODO: not implemented yet
14+
# Environment variables:
15+
# DEBUG="any-non-emply-value": verbose output for debugging the script
16+
# INSTALL_ORG_REPO="..." : the github org/repo to install from (default thoughtworks/talisman)
17+
#
18+
# Download the script needed for uninstalling the repo level hooks
19+
# For each git repo found in the search root (default $HOME)
20+
# Run the repo level uninstall hook. This will remove the symlink from .git/hooks/pre-<commit/push> to the central $TALISMAN_SETUP_DIR
21+
# The script will only remove talisman hook, not a pre-commit.com script or some other non-talisman hook
22+
# Write exceptions to a file for manual action
23+
# Look in the uninstall_git_repo_hook.bash script for more details on what it does
24+
# Remove the talisman_hook_script in .git-template/hooks/pre-<commit/push>
25+
# Remove talisman binary and talisman_hook_script from $TALISMAN_SETUP_DIR ($HOME/.talisman/bin)
26+
27+
function echo_error() {
28+
echo -ne $(tput setaf 1) >&2
29+
echo "$1" >&2
30+
echo -ne $(tput sgr0) >&2
31+
}
32+
export -f echo_error
33+
34+
function echo_debug() {
35+
[[ -z "${DEBUG}" ]] && return
36+
echo -ne $(tput setaf 3) >&2
37+
echo "$1" >&2
38+
echo -ne $(tput sgr0) >&2
39+
}
40+
export -f echo_debug
41+
42+
function echo_success {
43+
echo -ne $(tput setaf 2)
44+
echo "$1" >&2
45+
echo -ne $(tput sgr0)
46+
}
47+
export -f echo_success
48+
49+
TALISMAN_SETUP_DIR="/usr/local/Cellar/talisman"
50+
TALISMAN_HOOK_SCRIPT_DIR=${HOME}/".talisman"
51+
TEMPLATE_DIR=$(git config --global init.templatedir) || true
52+
INSTALL_ORG_REPO=${INSTALL_ORG_REPO:-'thoughtworks/talisman'}
53+
SCRIPT_BASE="https://raw.githubusercontent.com/${INSTALL_ORG_REPO}/master/global_install_scripts"
54+
55+
TEMP_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'talisman_uninstall')
56+
trap "rm -r ${TEMP_DIR}" EXIT
57+
chmod 0700 ${TEMP_DIR}
58+
59+
DELETE_REPO_HOOK_SCRIPT=${TEMP_DIR}/uninstall_git_repo_hook.bash
60+
function get_dependent_scripts() {
61+
curl --silent "${SCRIPT_BASE}/uninstall_git_repo_hook.bash" > ${DELETE_REPO_HOOK_SCRIPT}
62+
chmod +x ${DELETE_REPO_HOOK_SCRIPT}
63+
}
64+
65+
function remove_git_talisman_hooks() {
66+
if [[ ! -x ${DELETE_REPO_HOOK_SCRIPT} ]]; then
67+
echo_error "Couldn't find executable script ${DELETE_REPO_HOOK_SCRIPT}"
68+
exit 1
69+
fi
70+
71+
echo "Removing talisman hooks recursively in git repos"
72+
read -p "Please enter root directory to search for git repos (Default: ${HOME}): " SEARCH_ROOT
73+
SEARCH_ROOT=${SEARCH_ROOT:-$HOME}
74+
SEARCH_CMD="find"
75+
EXTRA_SEARCH_OPTS=""
76+
echo -e "\tSearching ${SEARCH_ROOT} for git repositories"
77+
78+
SUDO_PREFIX=""
79+
if [[ "${SEARCH_ROOT}" == "/" ]]; then
80+
echo -e "\tPlease enter your password when prompted to enable script to search as root user:"
81+
SUDO_PREFIX="sudo"
82+
EXTRA_SEARCH_OPTS="-xdev \( -path '/private/var' -prune \) -o"
83+
fi
84+
EXCEPTIONS_FILE=${TEMP_DIR}/repos_with_multiple_hooks.paths
85+
touch ${EXCEPTIONS_FILE}
86+
87+
TALISMAN_HOOK_SCRIPT_PATH=${TALISMAN_HOOK_SCRIPT_DIR}/talisman_hook_script
88+
CMD_STRING="${SUDO_PREFIX} ${SEARCH_CMD} ${SEARCH_ROOT} ${EXTRA_SEARCH_OPTS} -name .git -type d -exec ${DELETE_REPO_HOOK_SCRIPT} ${TALISMAN_HOOK_SCRIPT_PATH} ${EXCEPTIONS_FILE} {} ${HOOK_SCRIPT} \;"
89+
echo_debug "EXECUTING: ${CMD_STRING}"
90+
eval "${CMD_STRING}" || true
91+
92+
NUMBER_OF_EXCEPTION_REPOS=`cat ${EXCEPTIONS_FILE} | wc -l`
93+
94+
if [ ${NUMBER_OF_EXCEPTION_REPOS} -gt 0 ]; then
95+
EXCEPTIONS_FILE_HOME_PATH="${HOME}/repos_to_remove_talisman_from.paths"
96+
mv ${EXCEPTIONS_FILE} ${EXCEPTIONS_FILE_HOME_PATH}
97+
echo_error ""
98+
echo_error "Please see ${EXCEPTIONS_FILE_HOME_PATH} for a list of repositories"
99+
echo_error "that talisman couldn't be automatically removed from"
100+
echo_error "This is likely because these repos are using pre-commit (https://pre-commit.com)"
101+
echo_error "Remove lines related to talisman from the .pre-commit-config.yaml manually"
102+
fi
103+
}
104+
105+
get_dependent_scripts
106+
remove_git_talisman_hooks
107+
108+
echo_debug "Removing talisman hooks from .git-template"
109+
echo_debug "${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}"
110+
if [[ -n $TEMPLATE_DIR && -e ${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT} && \
111+
${TALISMAN_HOOK_SCRIPT_DIR}/talisman_hook_script -ef ${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT} ]]; then
112+
rm -f "${TEMPLATE_DIR}/hooks/${HOOK_SCRIPT}" && \
113+
echo_success "Removed ${HOOK_SCRIPT} from ${TEMPLATE_DIR}"
114+
fi
115+
116+
echo_debug "Removing talisman from $TALISMAN_SETUP_DIR"
117+
rm -rf $TALISMAN_SETUP_DIR && \
118+
echo_success "Removed global talisman install from ${TALISMAN_SETUP_DIR}"
119+
120+
echo_debug "Removing talisman hook script from ${TALISMAN_HOOK_SCRIPT_DIR}"
121+
rm -rf $TALISMAN_HOOK_SCRIPT_DIR && \
122+
echo_success "Removed talisman hook script from ${TALISMAN_HOOK_SCRIPT_DIR}"
123+
124+
if [ -n "${TALISMAN_HOME:-}" ]; then
125+
echo "Please remember to remove TALISMAN_HOME from your environment variables"
126+
fi
127+
}
128+
129+
run $0 $@

0 commit comments

Comments
 (0)