Browse Source

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

Also prefix all formatting functions with fmt_

Related: #9427
Marc Cornellà 3 years ago
parent
commit
eef04c62c2
2 changed files with 226 additions and 207 deletions
  1. 2 4
      .editorconfig
  2. 224 203
      tools/install.sh

+ 2 - 4
.editorconfig

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

+ 224 - 203
tools/install.sh

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