fix(installer): fix error message if $ZSH exists when installing

Also prefix all formatting functions with fmt_

Related: #9427
This commit is contained in:
Marc Cornellà 2020-10-31 23:53:03 +01:00
parent a3e0f4f2af
commit eef04c62c2
2 changed files with 195 additions and 176 deletions

View file

@ -4,7 +4,5 @@ root = true
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
charset = utf-8 charset = utf-8
indent_size = 2
[*.sh] indent_style = space
indent_size = 4
indent_style = tab

View file

@ -37,6 +37,9 @@
# #
set -e set -e
# Track if $ZSH was provided
custom_zsh=${ZSH:+yes}
# Default settings # Default settings
ZSH=${ZSH:-~/.oh-my-zsh} ZSH=${ZSH:-~/.oh-my-zsh}
REPO=${REPO:-ohmyzsh/ohmyzsh} REPO=${REPO:-ohmyzsh/ohmyzsh}
@ -53,12 +56,16 @@ command_exists() {
command -v "$@" >/dev/null 2>&1 command -v "$@" >/dev/null 2>&1
} }
error() { fmt_error() {
echo ${RED}"Error: $@"${RESET} >&2 echo ${RED}"Error: $@"${RESET} >&2
} }
underline() { fmt_underline() {
echo "$(printf '\033[4m')$@$(printf '\033[24m')" echo "$(printf '\033[4m')$@$(printf '\033[24m')"
}
fmt_code() {
echo "\`$(printf '\033[38;5;247m')$@${RESET}\`"
} }
setup_color() { setup_color() {
@ -81,71 +88,71 @@ setup_color() {
} }
setup_ohmyzsh() { setup_ohmyzsh() {
# Prevent the cloned repository from having insecure permissions. Failing to do # Prevent the cloned repository from having insecure permissions. Failing to do
# so causes compinit() calls to fail with "command not found: compdef" errors # so causes compinit() calls to fail with "command not found: compdef" errors
# for users with insecure umasks (e.g., "002", allowing group writability). Note # for users with insecure umasks (e.g., "002", allowing group writability). Note
# that this will be ignored under Cygwin by default, as Windows ACLs take # that this will be ignored under Cygwin by default, as Windows ACLs take
# precedence over umasks except for filesystems mounted with option "noacl". # precedence over umasks except for filesystems mounted with option "noacl".
umask g-w,o-w umask g-w,o-w
echo "${BLUE}Cloning Oh My Zsh...${RESET}" echo "${BLUE}Cloning Oh My Zsh...${RESET}"
command_exists git || { command_exists git || {
error "git is not installed" fmt_error "git is not installed"
exit 1 exit 1
} }
if [ "$OSTYPE" = cygwin ] && git --version | grep -q msysgit; then if [ "$OSTYPE" = cygwin ] && git --version | grep -q msysgit; then
error "Windows/MSYS Git is not supported on Cygwin" fmt_error "Windows/MSYS Git is not supported on Cygwin"
error "Make sure the Cygwin git package is installed and is first on the \$PATH" fmt_error "Make sure the Cygwin git package is installed and is first on the \$PATH"
exit 1 exit 1
fi fi
git clone -c core.eol=lf -c core.autocrlf=false \ git clone -c core.eol=lf -c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \ -c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \ -c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \ -c receive.fsck.zeroPaddedFilemode=ignore \
--depth=1 --branch "$BRANCH" "$REMOTE" "$ZSH" || { --depth=1 --branch "$BRANCH" "$REMOTE" "$ZSH" || {
error "git clone of oh-my-zsh repo failed" fmt_error "git clone of oh-my-zsh repo failed"
exit 1 exit 1
} }
echo echo
} }
setup_zshrc() { setup_zshrc() {
# Keep most recent old .zshrc at .zshrc.pre-oh-my-zsh, and older ones # Keep most recent old .zshrc at .zshrc.pre-oh-my-zsh, and older ones
# with datestamp of installation that moved them aside, so we never actually # with datestamp of installation that moved them aside, so we never actually
# destroy a user's original zshrc # destroy a user's original zshrc
echo "${BLUE}Looking for an existing zsh config...${RESET}" echo "${BLUE}Looking for an existing zsh config...${RESET}"
# Must use this exact name so uninstall.sh can find it # Must use this exact name so uninstall.sh can find it
OLD_ZSHRC=~/.zshrc.pre-oh-my-zsh OLD_ZSHRC=~/.zshrc.pre-oh-my-zsh
if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then
# Skip this if the user doesn't want to replace an existing .zshrc # Skip this if the user doesn't want to replace an existing .zshrc
if [ $KEEP_ZSHRC = yes ]; then if [ $KEEP_ZSHRC = yes ]; then
echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Keeping...${RESET}" echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Keeping...${RESET}"
return return
fi fi
if [ -e "$OLD_ZSHRC" ]; then if [ -e "$OLD_ZSHRC" ]; then
OLD_OLD_ZSHRC="${OLD_ZSHRC}-$(date +%Y-%m-%d_%H-%M-%S)" OLD_OLD_ZSHRC="${OLD_ZSHRC}-$(date +%Y-%m-%d_%H-%M-%S)"
if [ -e "$OLD_OLD_ZSHRC" ]; then if [ -e "$OLD_OLD_ZSHRC" ]; then
error "$OLD_OLD_ZSHRC exists. Can't back up ${OLD_ZSHRC}" fmt_error "$OLD_OLD_ZSHRC exists. Can't back up ${OLD_ZSHRC}"
error "re-run the installer again in a couple of seconds" fmt_error "re-run the installer again in a couple of seconds"
exit 1 exit 1
fi fi
mv "$OLD_ZSHRC" "${OLD_OLD_ZSHRC}" mv "$OLD_ZSHRC" "${OLD_OLD_ZSHRC}"
echo "${YELLOW}Found old ~/.zshrc.pre-oh-my-zsh." \ echo "${YELLOW}Found old ~/.zshrc.pre-oh-my-zsh." \
"${GREEN}Backing up to ${OLD_OLD_ZSHRC}${RESET}" "${GREEN}Backing up to ${OLD_OLD_ZSHRC}${RESET}"
fi fi
echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Backing up to ${OLD_ZSHRC}${RESET}" echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Backing up to ${OLD_ZSHRC}${RESET}"
mv ~/.zshrc "$OLD_ZSHRC" mv ~/.zshrc "$OLD_ZSHRC"
fi fi
echo "${GREEN}Using the Oh My Zsh template file and adding it to ~/.zshrc.${RESET}" echo "${GREEN}Using the Oh My Zsh template file and adding it to ~/.zshrc.${RESET}"
sed "/^export ZSH=/ c\\ sed "/^export ZSH=/ c\\
export ZSH=\"$ZSH\" export ZSH=\"$ZSH\"
" "$ZSH/templates/zshrc.zsh-template" > ~/.zshrc-omztemp " "$ZSH/templates/zshrc.zsh-template" > ~/.zshrc-omztemp
mv -f ~/.zshrc-omztemp ~/.zshrc mv -f ~/.zshrc-omztemp ~/.zshrc
@ -154,146 +161,160 @@ export ZSH=\"$ZSH\"
} }
setup_shell() { setup_shell() {
# Skip setup if the user wants or stdin is closed (not running interactively). # Skip setup if the user wants or stdin is closed (not running interactively).
if [ $CHSH = no ]; then if [ $CHSH = no ]; then
return return
fi fi
# If this user's login shell is already "zsh", do not attempt to switch. # If this user's login shell is already "zsh", do not attempt to switch.
if [ "$(basename "$SHELL")" = "zsh" ]; then if [ "$(basename -- "$SHELL")" = "zsh" ]; then
return return
fi fi
# If this platform doesn't provide a "chsh" command, bail out. # If this platform doesn't provide a "chsh" command, bail out.
if ! command_exists chsh; then if ! command_exists chsh; then
cat <<-EOF cat <<EOF
I can't change your shell automatically because this system does not have chsh. I can't change your shell automatically because this system does not have chsh.
${BLUE}Please manually change your default shell to zsh${RESET} ${BLUE}Please manually change your default shell to zsh${RESET}
EOF EOF
return return
fi fi
echo "${BLUE}Time to change your default shell to zsh:${RESET}" echo "${BLUE}Time to change your default shell to zsh:${RESET}"
# Prompt for user choice on changing the default login shell # Prompt for user choice on changing the default login shell
printf "${YELLOW}Do you want to change your default shell to zsh? [Y/n]${RESET} " printf "${YELLOW}Do you want to change your default shell to zsh? [Y/n]${RESET} "
read opt read opt
case $opt in case $opt in
y*|Y*|"") echo "Changing the shell..." ;; y*|Y*|"") echo "Changing the shell..." ;;
n*|N*) echo "Shell change skipped."; return ;; n*|N*) echo "Shell change skipped."; return ;;
*) echo "Invalid choice. Shell change skipped."; return ;; *) echo "Invalid choice. Shell change skipped."; return ;;
esac esac
# Check if we're running on Termux # Check if we're running on Termux
case "$PREFIX" in case "$PREFIX" in
*com.termux*) termux=true; zsh=zsh ;; *com.termux*) termux=true; zsh=zsh ;;
*) termux=false ;; *) termux=false ;;
esac esac
if [ "$termux" != true ]; then if [ "$termux" != true ]; then
# Test for the right location of the "shells" file # Test for the right location of the "shells" file
if [ -f /etc/shells ]; then if [ -f /etc/shells ]; then
shells_file=/etc/shells shells_file=/etc/shells
elif [ -f /usr/share/defaults/etc/shells ]; then # Solus OS elif [ -f /usr/share/defaults/etc/shells ]; then # Solus OS
shells_file=/usr/share/defaults/etc/shells shells_file=/usr/share/defaults/etc/shells
else else
error "could not find /etc/shells file. Change your default shell manually." fmt_error "could not find /etc/shells file. Change your default shell manually."
return return
fi fi
# Get the path to the right zsh binary # Get the path to the right zsh binary
# 1. Use the most preceding one based on $PATH, then check that it's in the shells file # 1. Use the most preceding one based on $PATH, then check that it's in the shells file
# 2. If that fails, get a zsh path from the shells file, then check it actually exists # 2. If that fails, get a zsh path from the shells file, then check it actually exists
if ! zsh=$(which zsh) || ! grep -qx "$zsh" "$shells_file"; then if ! zsh=$(which zsh) || ! grep -qx "$zsh" "$shells_file"; then
if ! zsh=$(grep '^/.*/zsh$' "$shells_file" | tail -1) || [ ! -f "$zsh" ]; then if ! zsh=$(grep '^/.*/zsh$' "$shells_file" | tail -1) || [ ! -f "$zsh" ]; then
error "no zsh binary found or not present in '$shells_file'" fmt_error "no zsh binary found or not present in '$shells_file'"
error "change your default shell manually." fmt_error "change your default shell manually."
return return
fi fi
fi fi
fi fi
# We're going to change the default shell, so back up the current one # We're going to change the default shell, so back up the current one
if [ -n "$SHELL" ]; then if [ -n "$SHELL" ]; then
echo $SHELL > ~/.shell.pre-oh-my-zsh echo $SHELL > ~/.shell.pre-oh-my-zsh
else else
grep "^$USER:" /etc/passwd | awk -F: '{print $7}' > ~/.shell.pre-oh-my-zsh grep "^$USER:" /etc/passwd | awk -F: '{print $7}' > ~/.shell.pre-oh-my-zsh
fi fi
# Actually change the default shell to zsh # Actually change the default shell to zsh
if ! chsh -s "$zsh"; then if ! chsh -s "$zsh"; then
error "chsh command unsuccessful. Change your default shell manually." fmt_error "chsh command unsuccessful. Change your default shell manually."
else else
export SHELL="$zsh" export SHELL="$zsh"
echo "${GREEN}Shell successfully changed to '$zsh'.${RESET}" echo "${GREEN}Shell successfully changed to '$zsh'.${RESET}"
fi fi
echo echo
} }
main() { main() {
# Run as unattended if stdin is closed # Run as unattended if stdin is not a tty
if [ ! -t 0 ]; then if [ ! -t 0 ]; then
RUNZSH=no RUNZSH=no
CHSH=no CHSH=no
fi fi
# Parse arguments # Parse arguments
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case $1 in case $1 in
--unattended) RUNZSH=no; CHSH=no ;; --unattended) RUNZSH=no; CHSH=no ;;
--skip-chsh) CHSH=no ;; --skip-chsh) CHSH=no ;;
--keep-zshrc) KEEP_ZSHRC=yes ;; --keep-zshrc) KEEP_ZSHRC=yes ;;
esac esac
shift shift
done done
setup_color setup_color
if ! command_exists zsh; then if ! command_exists zsh; then
echo "${YELLOW}Zsh is not installed.${RESET} Please install zsh first." echo "${YELLOW}Zsh is not installed.${RESET} Please install zsh first."
exit 1 exit 1
fi fi
if [ -d "$ZSH" ]; then if [ -d "$ZSH" ]; then
cat <<-EOF echo "${YELLOW}The \$ZSH folder already exists ($ZSH).${RESET}"
${YELLOW}You already have Oh My Zsh installed.${RESET} if [ "$custom_zsh" = yes ]; then
You'll need to remove '$ZSH' if you want to reinstall. cat <<EOF
EOF
exit 1
fi
setup_ohmyzsh You ran the installer with the \$ZSH setting or the \$ZSH variable is
setup_zshrc exported. You have 3 options:
setup_shell
printf "$GREEN" 1. Unset the ZSH variable when calling the installer:
cat <<-'EOF' $(fmt_code "ZSH= sh install.sh")
__ __ 2. Install Oh My Zsh to a directory that doesn't exist yet:
____ / /_ ____ ___ __ __ ____ _____/ /_ $(fmt_code "ZSH=path/to/new/ohmyzsh/folder sh install.sh")
/ __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \ 3. (Caution) If the folder doesn't contain important information,
/ /_/ / / / / / / / / / / /_/ / / /_(__ ) / / / you can just remove it with $(fmt_code "rm -r $ZSH")
\____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/
/____/ ....is now installed! EOF
else
echo "You'll need to remove it if you want to reinstall."
fi
exit 1
fi
setup_ohmyzsh
setup_zshrc
setup_shell
printf "$GREEN"
cat <<'EOF'
__ __
____ / /_ ____ ___ __ __ ____ _____/ /_
/ __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \
/ /_/ / / / / / / / / / / /_/ / / /_(__ ) / / /
\____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/
/____/ ....is now installed!
EOF EOF
cat <<-EOF cat <<EOF
Before you scream Oh My Zsh! please look over the ~/.zshrc file to select plugins, themes, and options. Before you scream Oh My Zsh! please look over the ~/.zshrc file to select plugins, themes, and options.
• Follow us on Twitter: $(underline https://twitter.com/ohmyzsh) • Follow us on Twitter: $(fmt_underline https://twitter.com/ohmyzsh)
• Join our Discord server: $(underline https://discord.gg/ohmyzsh) • Join our Discord server: $(fmt_underline https://discord.gg/ohmyzsh)
• Get stickers, shirts, coffee mugs and other swag: $(underline https://shop.planetargon.com/collections/oh-my-zsh) • Get stickers, shirts, coffee mugs and other swag: $(fmt_underline https://shop.planetargon.com/collections/oh-my-zsh)
EOF EOF
printf "$RESET" printf "$RESET"
if [ $RUNZSH = no ]; then if [ $RUNZSH = no ]; then
echo "${YELLOW}Run zsh to try it out.${RESET}" echo "${YELLOW}Run zsh to try it out.${RESET}"
exit exit
fi fi
exec zsh -l exec zsh -l
} }
main "$@" main "$@"