#!/usr/bin/env bash
# vim: set filetype=sh:
#
#
#
#!/usr/bin/env bash
# vim: set filetype=sh:
#
# yap.sh
# ~~~~~~
#
# Shortest way to terraform a Ubuntu 16.04 environment as for my taste
#
# $ curl -sL yap.sh | bash
# or
# $ wget -qO- yap.sh | bash
#
set -euo pipefail;
# Don't update APT if the last updated time is in a day.
readonly update_apt_after=86400
readonly apt_updated_at="$HOME/.yap.sh-apt-updated-at"
# Where some backup files to be stored.
readonly timestamp=$(date +%s)
readonly backup_dir=~/.yap.sh-bak-$timestamp
print_help () {
# Print the help message for --help.
echo "Usage: curl -sL yap.sh | bash [-s - OPTIONS]"
echo
echo "Options:"
echo " --help Show this message and exit."
echo " --no-apt-update Do not update APT package lists."
echo " --force-apt-update Update APT package lists on regardless of"
echo " updating period."
}
git_repo () {
# Clone git repo. if the repo already exists, just pull
local url="$1"
local save_path="$2"
if [[ -d "$save_path" ]]; then
git -C "$save_path" pull --rebase
else
mkdir -p "$save_path"
git clone "$url" "$save_path"
fi
}
github_repo () {
local url="$1"
local save_path="$2"
git_repo "https://github.com/$1" "$2"
}
secho () {
local color="$1"
local msg="$2"
if [[ -z "$TERM" ]]; then
echo "$msg"
else
echo -e "$(tput setaf "${color}")${msg}$(tput sgr0)"
fi
}
info () {
local msg="$1"
# Print an information log.
secho 6 "$msg"
}
err () {
local msg="$1"
# Print a red colored error message.
secho 1 "$msg"
}
fatal () {
# Print a red colored error message and exit the script.
err "$@"
exit 1
}
failed () {
fatal "Failed to running yap.sh. Error on line $1"
}
trap 'failed $LINENO' ERR
sym_link () {
# Make a symbolic link. If something should be backed up at
# the destination path, it moves that to $BAKUP_DIR.
local src="$1"
local dest="$2"
if [[ -e "$dest" || -L "$dest" ]]; then
if [[ "$(readlink -f "$src")" == "$(readlink -f "$dest")" ]]; then
return
fi
mkdir -p "$backup_dir"
mv "$dest" "$backup_dir"
fi
ln -s "$src" "$dest"
}
check_ubuntu_ver () {
local version="$1"
if [ -f '/etc/os-release' ]; then
# shellcheck disable=SC1091
source '/etc/os-release'
if [[ "$NAME" != "Ubuntu" ]]; then
false
fi
if [[ "$VERSION_ID" != "$version" ]]; then
false
else
true
fi
else
false
fi
}
is_ubuntu_16_04 () {
check_ubuntu_ver "16.04"
}
is_ubuntu_18_04 () {
check_ubuntu_ver "18.04"
}
is_osx () {
[[ "$(uname)" == "Darwin" ]]
}
get_os_type () {
if is_ubuntu_16_04; then
echo "ubuntu1604"
elif is_osx; then
echo "osx"
else
echo "unknown"
fi
}
has () {
type "$1" > /dev/null 2>&1
}
brew_inst () {
local brew_pkg="$1"
if brew ls --versions "$brew_pkg" >/dev/null; then
# Upgrade brew package if outdated
if brew outdated | grep -wq "$brew_pkg"; then
brew upgrade "$brew_pkg"
fi
else
# Install brew package if not installed
brew install "$brew_pkg"
fi
}
echo '================================================================================'
info 'Running 000-base-dependencies.sh...'
#!/usr/bin/env bash
set -euo pipefail
check_sudo_requires_password() {
if ! sudo -n true 2>/dev/null; then
err "sudo without a password is required for run yap.sh"
echo
echo "Run the following command to make $USER can use sudo without password:"
info " sudo sh -c \"echo '$USER ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/$USER\""
echo
exit 1
fi
}
check_sudo_requires_password
if is_ubuntu_16_04; then
readonly apt_pkgs=(
aptitude
build-essential
curl
git
git-flow
htop
zsh
gawk # Fix zplug update raises unknown error, SEE: https://github.com/zplug/zplug/issues/359#issuecomment-349534715
wget
)
sudo apt-get update
sudo apt-get install -y "${apt_pkgs[@]}"
elif is_osx; then
xcode-select --install
# install brew without prompt
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null
else
info "Skipped: $(get_os_type)"
fi
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 100-rc.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
readonly rc_repo="$HOME/rc"
# Symbolic links config files.
info "Linking dot files from kexplo/rc..."
github_repo kexplo/rc.git "$rc_repo"
sym_link "$rc_repo/stdlib.sh" "$HOME/stdlib.sh"
sym_link "$rc_repo/.vimrc" "$HOME/.vimrc"
sym_link "$rc_repo/.zshrc" "$HOME/.zshrc"
sym_link "$rc_repo/.gitconfig" "$HOME/.gitconfig"
sym_link "$rc_repo/.tmux.conf" "$HOME/.tmux.conf"
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 120-python.sh...'
#!/usr/bin/env bash
set -euo pipefail
if is_ubuntu_16_04; then
info "Setting up the Python environment..."
sudo apt-get install -y \
python-minimal
sudo apt-get install -y \
python2.7-dev
sudo apt-get install -y \
python-setuptools \
python-pip \
virtualenv
sudo apt-get install -y \
python3 \
python3-dev
fi
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 121-pyenv.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
github_repo pyenv/pyenv "$HOME/.pyenv"
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 122-pyenv-virtualenv.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
github_repo pyenv/pyenv-virtualenv.git "$HOME/.pyenv/plugins/pyenv-virtualenv"
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 200-linuxbrew.sh...'
#!/usr/bin/env bash
# pass os: ubuntu 16.04
# pass os: ubuntu 18.04
set -euo pipefail
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
if ! has brew; then
if [[ "$(uname -s)" == "Linux" ]]; then
info "Installing linuxbrew...."
(yes | sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)") || true
fi
else
info "Skipped, Linuxbrew already installed"
fi
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 201-direnv.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
brew_inst direnv
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 202-fpp.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
info "Installing facebook's PathPicker(fpp)..."
brew_inst fpp
# fix YCM import error.
# SEE: https://github.com/Valloric/YouCompleteMe/issues/2883
if brew ls --versions 'python@2' >/dev/null; then
brew uninstall --ignore-dependencies python@2
fi
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 300-cargo.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
if ! has cargo; then
info "Installing cargo..."
curl -sSf https://static.rust-lang.org/rustup.sh | sh
else
info "Skipped, cargo already installed"
fi
export PATH="$HOME/.cargo/bin:$PATH"
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 301-ripgrep.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
if ! has rg; then
info "Installing ripgrep..."
cargo install ripgrep
else
info "Skipped, ripgrep already installed"
fi
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 302-z.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
brew_inst z
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 400-zplug.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
info "Setting up the Zsh environment..."
set_zsh_as_default_shell() {
sudo chsh -s "$(which zsh)" "$USER"
}
install_zplug() {
github_repo zplug/zplug "$HOME/.zplug"
}
ensure_zplug_plugins() {
# Ensure the latest zplug plugins installed
zsh -c "
source \"$HOME/.zshrc\"
if ! zplug check; then
zplug install
else
zplug update
fi
"
}
set_zsh_as_default_shell
install_zplug
ensure_zplug_plugins
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 410-tmux.sh...'
#!/usr/bin/env bash
set -euo pipefail
# if is_ubuntu_16_04; then
# sudo apt-get install -y tmux
# fi
function install_tmux_dependencies() {
if is_ubuntu_16_04; then
local pkgs=(
automake
build-essential
pkg-config
libevent-dev
libncurses5-dev
)
sudo apt-get install -y "${pkgs[@]}"
fi
}
function check_tmux_installed() {
version="$1"
if ! has tmux; then
false
fi
tmux -V | grep -q "tmux $version"
}
function install_tmux() {
local version="$1"
if check_tmux_installed "$version"; then
echo "tmux $version already installed"
return
fi
mkdir -p /tmp/tmux
wget -qO- "https://github.com/tmux/tmux/releases/download/${version}/tmux-${version}.tar.gz" | tar xvz -C /tmp/tmux
pushd /tmp/tmux/tmux*
./configure
make
sudo make install
popd
rm -rf /tmp/tmux
}
install_tmux_dependencies
install_tmux 2.7
info "Installing tpm"
github_repo tmux-plugins/tpm ~/.tmux/plugins/tpm
# Install tmux plugin ( https://github.com/tmux-plugins/tpm/issues/6 )
info "Installing tmux plugins..."
# start a server but don't attach to it
tmux start-server
# create a new session but don't attach to it either
tmux new-session -d
# install the plugins
~/.tmux/plugins/tpm/scripts/install_plugins.sh
# killing the server is not required, I guess
tmux kill-server
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 420-vim.sh...'
#!/usr/bin/env bash
set -euo pipefail
function install_vim_dependencies() {
if is_ubuntu_16_04; then
local pkgs=(
lua5.1
liblua5.1-dev
luajit
libluajit-5.1-dev
ruby-dev
libperl-dev
ncurses-dev
mono-xbuild # for YouCompleteMe
mono-devel # for YouCompleteMe
cmake # for YouCompleteMe
)
sudo apt-get install -y "${pkgs[@]}"
fi
}
function check_vim_installed() {
version="$1"
if ! has vim; then
false
fi
vim --version | head -1 | grep -q "Vi IMproved $version"
}
function install_vim () {
version="$1"
if check_vim_installed "$version"; then
echo "Vim $version already installed"
return
fi
version_regex="${version/./\\.}"
# Clone latest revision of version
git clone -b "$(git ls-remote --tags https://github.com/vim/vim.git | grep -o "v${version_regex}"'\.[0-9]\+' | tail -1)" --depth 1 https://github.com/vim/vim.git /tmp/vim
pushd '/tmp/vim'
install_vim_dependencies
# NOTE: If both python2.x and python3.x are enabled then the linking will be via dlopen(), dlsym(), dlclose().
# SEE: https://github.com/vim/vim/blob/master/src/Makefile#L444-L445
./configure --with-features=huge \
--enable-multibyte \
--enable-rubyinterp=yes \
--enable-pythoninterp=yes \
--with-python-command=/usr/bin/python2 \
--enable-perlinterp=dynamic \
--enable-luainterp=yes \
--with-luajit \
--enable-cscope \
--enable-fail-if-missing \
--prefix=/usr/local
# --enable-python3interp=yes \
# --with-python3-command=/usr/bin/python3 \
sudo make install
popd
sudo rm -rf /tmp/vim
}
function install_vim_ycm() {
pushd "$HOME/.vim/plugged/YouCompleteMe"
python ./install.py --cs-completer --clang-completer
popd
}
function install_vim_plugins() {
if [ ! -f "$HOME/.vim/autoload/plug.vim" ]
then
info "Installing Vim-Plug..."
curl -fLo "$HOME/.vim/autoload/plug.vim" --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
fi
local prev_ycm_version=""
if [ -d "$HOME/.vim/plugged/YouCompleteMe" ]; then
prev_ycm_version=$(git -C "$HOME/.vim/plugged/YouCompleteMe" rev-parse --short HEAD)
fi
info "Installing Vim plugins..."
vim +PlugUpdate +qall || true
local new_ycm_version
new_ycm_version=$(git -C "$HOME/.vim/plugged/YouCompleteMe" rev-parse --short HEAD)
if [[ "$prev_ycm_version" != "$new_ycm_version" ]]; then
install_vim_ycm
fi
}
function install_vi_symbolic_link() {
sudo ln -fs $(which vim) /usr/bin/vi
}
install_vim 8.1
install_vi_symbolic_link
install_vim_plugins
echo '================================================================================'
echo ''
echo '================================================================================'
info 'Running 999-logo.sh...'
#!/usr/bin/env bash
# pass os: all
set -euo pipefail
# Show funny logo.
info '
_ _ __ ____ _
( \/ )/ _\ ( _ \/ \
) // \ ) __/\_/
(__/ \_/\_/(__) (_)
'
info "Terraformed successfully by yap.sh."
if [[ -d "$backup_dir" ]]; then
info "Backup files are stored in $backup_dir"
fi
if [ "$SHELL" != "$(which zsh)" ] && [ "${ZSH:-x}" == "x" ]; then
info "Now, ZSH is default shell. To use terraformed ZSH, re-login or"
echo
info " $ zsh"
echo
fi
echo '================================================================================'
echo ''