From fc5ba9f99dec4b7472fd118933032429c38e10ce Mon Sep 17 00:00:00 2001 From: Andrejus Date: Tue, 25 Feb 2020 23:13:21 +0000 Subject: [PATCH] Finishing touches --- .gitignore | 1 + Makefile | 2 +- bootstrap.sh | 57 +++++++++++++++----------------- fish/config.fish | 13 +++++++- fish/fishfile | 3 +- git/.gitignore_global | 1 + install.sh | 24 +++++++------- install/00-apt.sh | 15 +++++---- install/01-fish.sh | 19 +++++------ install/10-git.sh | 4 +-- install/11-keybase.sh | 9 +++--- install/12-docker.sh | 32 +++++++++--------- install/20-pyenv.sh | 14 ++++---- install/21-python.sh | 3 +- install/22-poetry.sh | 5 ++- install/99-apt-clean.sh | 4 +-- utils.sh | 72 ++++++++++++++++++++++++++++------------- 17 files changed, 157 insertions(+), 121 deletions(-) mode change 120000 => 100644 fish/config.fish mode change 120000 => 100644 fish/fishfile diff --git a/.gitignore b/.gitignore index cf7e053..4fc0043 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .dotlock +*.deb \ No newline at end of file diff --git a/Makefile b/Makefile index 9ef3353..a95d7a2 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,4 @@ clean: .PHONY: run run: - bash bootstrap.sh \ No newline at end of file + bash bootstrap.sh diff --git a/bootstrap.sh b/bootstrap.sh index 6edfc09..3978ebe 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,48 +1,43 @@ #!/bin/bash # # Script to set up and install dotfiles repository. -# +# # Usage: # `source path/to/bootstrap.sh` # `source <(wget path/to/bootstrap.sh)` # -set -euo pipefail +set -o pipefail +echo "setting up..." -# Set up variables and imports -readonly repository="andrejusk/dotfiles" -readonly repository_url="https://github.com/$repository.git" -readonly workspace_dir="$HOME/workspace" -readonly dotfiles_dir="$workspace_dir/dotfiles" -readonly install_dir="$dotfiles_dir/install" -readonly lock_file="$dotfiles_dir/.dotlock" -source "$dotfiles_dir/utils.sh" +# Variables: git +if [ -z "$REPOSITORY" ]; then + export REPOSITORY="andrejusk/dotfiles" +fi +readonly repository_url="https://github.com/$REPOSITORY.git" +echo "using repository: $repository_url" -# Log execution -printf "Setting up ${C_CYAN}$repository${C_NC} with:\n" -printf " repository:\t ${C_YELLOW}$repository${C_NC}\n" -printf " repository_url: ${C_YELLOW}$repository_url${C_NC}\n" -printf " workspace_dir: ${C_YELLOW}$workspace_dir${C_NC}\n" -printf " dotfiles_dir:\t ${C_YELLOW}$dotfiles_dir${C_NC}\n" -printf " install_dir:\t ${C_YELLOW}$install_dir${C_NC}\n" -printf " lock_file:\t ${C_YELLOW}$lock_file${C_NC}\n\n" +# Variables: workspace +if [ -z "$WORKSPACE" ]; then + export WORKSPACE="$HOME/workspace" +fi +readonly dotfiles_dir="$WORKSPACE/dotfiles" +echo "using dir: $dotfiles_dir" # Ensure git is installed -if ! hash git 2>/dev/null -then - sudo apt-get update -yqq - sudo apt-get install -yqq git -fi - -# Ensure repository is cloned -if [[ ! -d "$dotfiles_dir" ]] -then - mkdir -p "$workspace_dir" - git clone -q "$repository_url" "$dotfiles_dir" +if ! [ -x "$(command -v git)" ]; then + echo "installing git..." + sudo apt-get update -qqy + sudo apt-get install git -qqy fi # Ensure repository is up to date -cd "$dotfiles_dir" -git pull -q origin master || true +echo "pulling latest..." +if [[ ! -d $dotfiles_dir ]]; then + mkdir -p "$dotfiles_dir" + git clone -q "$repository_url" "$dotfiles_dir" +else + git --git-dir="$dotfiles_dir/.git" pull -q origin master || true +fi # Install dotfiles source "$dotfiles_dir/install.sh" diff --git a/fish/config.fish b/fish/config.fish deleted file mode 120000 index b3a41f0..0000000 --- a/fish/config.fish +++ /dev/null @@ -1 +0,0 @@ -/home/andrejus/.config/fish \ No newline at end of file diff --git a/fish/config.fish b/fish/config.fish new file mode 100644 index 0000000..e127afe --- /dev/null +++ b/fish/config.fish @@ -0,0 +1,12 @@ +# Ensure fisher is installed +if not functions -q fisher + set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config + curl https://git.io/fisher --create-dirs -sLo $XDG_CONFIG_HOME/fish/functions/fisher.fish + fish -c fisher +end + +# Poetry +set -gx PATH $HOME/.poetry/bin $PATH + +# Wipe greeting +set fish_greeting diff --git a/fish/fishfile b/fish/fishfile deleted file mode 120000 index b3a41f0..0000000 --- a/fish/fishfile +++ /dev/null @@ -1 +0,0 @@ -/home/andrejus/.config/fish \ No newline at end of file diff --git a/fish/fishfile b/fish/fishfile new file mode 100644 index 0000000..69245b2 --- /dev/null +++ b/fish/fishfile @@ -0,0 +1,2 @@ +rafaelrinaldi/pure +jorgebucaran/fish-nvm diff --git a/git/.gitignore_global b/git/.gitignore_global index e69de29..3c3629e 100644 --- a/git/.gitignore_global +++ b/git/.gitignore_global @@ -0,0 +1 @@ +node_modules diff --git a/install.sh b/install.sh index 49f1b7b..ae20b26 100755 --- a/install.sh +++ b/install.sh @@ -2,32 +2,32 @@ # # Invokes all install scripts. # +set -euo pipefail -# Log execution -printf "Installing ${C_CYAN}$repository${C_NC}" +source "$dotfiles_dir/utils.sh" +printf "Installing ${C_CYAN}$REPOSITORY${C_NC}" printf " as ${C_YELLOW}$USER${C_NC}\n\n" # Prevent running as root -if [ "$USER" == "root" ] -then +if [[ $USER == root ]]; then printf "Failed: ${C_RED}Running as root${C_NC}\n" printf "Please run as user, not ${C_YELLOW}sudo${C_NC}\n" exit 1 fi -# Prevent concurrent scripts -if [ -f "$lock_file" ] -then +# Prevent concurrent runs +readonly install_lock_file="$dotfiles_dir/.dotlock" +if [ -f $install_lock_file ]; then printf "Failed: ${C_RED}Script already running${C_NC}\n" printf "Please wait for script to exit or ${C_YELLOW}make clean${C_NC}\n" exit 1 fi -touch "$lock_file" # Requires clean +touch "$install_lock_file" # Requires clean # Run all install scripts -script_filter="$install_dir/*.sh" -for script in $script_filter -do +readonly install_dir="$dotfiles_dir/install" +readonly script_filter="$install_dir/*.sh" +for script in $script_filter; do # Avoid pattern matching self [ -e "$script" ] || continue @@ -38,7 +38,7 @@ do # Run and indent output source "$script" | indent - printf "${C_NC}\n" + printf "${C_NC}" done diff --git a/install/00-apt.sh b/install/00-apt.sh index 1a1b8f8..cd2a0ca 100644 --- a/install/00-apt.sh +++ b/install/00-apt.sh @@ -1,14 +1,15 @@ #!/bin/bash # -# Always updates apt, upgrades apt, and installes 00-apt-pkglist +# apt update and upgrade # +# Install list of packages in ./00-apt-pkglist +# +readonly package_list_file="00-apt-pkglist" # apt update and upgrade non-interactively -sudo apt-get update -y -DEBIAN_FRONTEND=noninteractive sudo apt-get \ - -o Dpkg::Options::="--force-confdef" \ - -o Dpkg::Options::="--force-confold" upgrade -y +update +upgrade # Package installs -readonly apt_pkglist=$(cat $install_dir/00-apt-pkglist) -sudo apt-get install -y $apt_pkglist +readonly package_list=$(cat $install_dir/$package_list_file) +install -y "$package_list" diff --git a/install/01-fish.sh b/install/01-fish.sh index a85abaa..5f2ce3d 100644 --- a/install/01-fish.sh +++ b/install/01-fish.sh @@ -7,36 +7,33 @@ # # 1. fish shell is installed -if [ is_missing fish ] 2>/dev/null -then +if not_installed "fish"; then printf "Installing fish...\n" # Add fish repository - sudo apt-add-repository -y ppa:fish-shell/release-3 - sudo apt-get -y update + app_ppa fish-shell/release-3 + update # Install fish - sudo apt-get -y install fish + install fish fi printf "fish is installed\n" +fish --version # 2. fish shell is default login shell readonly fish_path=$(which fish) -if [ $SHELL != fish_path ] -then - - printf "Setting fish as default...\n" +if [ "$SHELL" != fish_path ]; then # Update default login shell - usermod -s $fish_path $USER + usermod -s "$fish_path" "$USER" fi printf "fish is default login shell\n" # 3. fish dotfiles are symlinked -readonly fish_source="$dotfiles_dir/fish/*" +readonly fish_source="$dotfiles_dir/fish" readonly fish_target="$HOME/.config/fish" link_folder "$fish_source" "$fish_target" printf "fish dotfiles linked\n" diff --git a/install/10-git.sh b/install/10-git.sh index 3a4d6a8..12a8463 100644 --- a/install/10-git.sh +++ b/install/10-git.sh @@ -5,7 +5,7 @@ # # 1. git dotfiles are symlinked -readonly git_source="$dotfiles_dir/git/*" +readonly git_source="$dotfiles_dir/git" readonly git_target="$HOME" -link_folder $git_source $git_target +link_folder "$git_source" "$git_target" printf "git dotfiles linked\n" diff --git a/install/11-keybase.sh b/install/11-keybase.sh index 1fbc5f8..8d92f1c 100644 --- a/install/11-keybase.sh +++ b/install/11-keybase.sh @@ -5,14 +5,15 @@ # # 1.keybase is installed -if [ ! hash keybase ] 2>/dev/null -then +if not_installed "keybase"; then printf "Installing keybase...\n" curl --remote-name https://prerelease.keybase.io/keybase_amd64.deb - sudo apt-get install -y ./keybase_amd64.deb - run_keybase + install ./keybase_amd64.deb + rm ./keybase_amd64.deb fi printf "keybase is installed\n" +run_keybase +keybase --version diff --git a/install/12-docker.sh b/install/12-docker.sh index 341fdcd..a08f6a0 100644 --- a/install/12-docker.sh +++ b/install/12-docker.sh @@ -8,13 +8,12 @@ # # 1. docker is installed -if ! hash docker 2>/dev/null -then +if not_installed "docker"; then printf "Installing docker...\n" # Requirements - sudo apt-get -y install \ + install \ apt-transport-https \ ca-certificates \ curl \ @@ -22,41 +21,42 @@ then software-properties-common # Add repository - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - + add_key https://download.docker.com/linux/ubuntu/gpg sudo add-apt-repository -y \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) \ - stable" - sudo apt-get -y update + $(lsb_release -cs) \ + stable" + update + + # Install + install docker-ce fi printf "docker is installed\n" +docker --version # 2. docker-compose if installed -if ! hash docker-compose 2>/dev/null -then +if not_installed "docker-compose"; then printf "Installing docker-compose...\n" # Docker-compose curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose - docker-compose --version fi printf "docker-compose is installed\n" +docker-compose --version # 3. docker group exists readonly docker_group='docker' -if ! grep -q $docker_group /etc/group -then - sudo groupadd $docker_group +if ! grep -q "$docker_group" /etc/group; then + sudo groupadd "$docker_group" fi printf "group '$docker_group' is created\n" # 4. user is in docker group -if ! groups $USER | grep -q "\b$docker_group\b" -then - sudo usermod -aG docker $USER +if ! groups $USER | grep -q "\b$docker_group\b"; then + sudo usermod -aG docker "$USER" fi printf "user '$USER' is in '$docker_group' group\n" diff --git a/install/20-pyenv.sh b/install/20-pyenv.sh index 2eb1267..4096fac 100644 --- a/install/20-pyenv.sh +++ b/install/20-pyenv.sh @@ -5,20 +5,22 @@ # # 1. pyenv is installed -if ! hash pyenv 2>/dev/null -then +if not_installed "pyenv"; then printf "Installing pyenv...\n" # Install pyenv prerequisites # see https://github.com/pyenv/pyenv/wiki/common-build-problems - sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \ -libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ -xz-utils tk-dev libffi-dev liblzma-dev python-openssl git + install make build-essential libssl-dev zlib1g-dev libbz2-dev \ + libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ + xz-utils tk-dev libffi-dev liblzma-dev python-openssl git # Install pyenv # see https://github.com/pyenv/pyenv-installer - curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + run https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer bash + + # Add to install path + export PATH="$HOME/.pyenv/bin:$PATH" fi printf "pyenv is installed\n" diff --git a/install/21-python.sh b/install/21-python.sh index 458c9b5..da62fe4 100644 --- a/install/21-python.sh +++ b/install/21-python.sh @@ -5,8 +5,7 @@ # # 1. python is installed -if ! hash python 2>/dev/null -then +if not_installed "python"; then printf "Installing python...\n" diff --git a/install/22-poetry.sh b/install/22-poetry.sh index 44576e8..2a4e47f 100644 --- a/install/22-poetry.sh +++ b/install/22-poetry.sh @@ -5,13 +5,12 @@ # # 1. poetry is installed -if ! hash poetry 2>/dev/null -then +if not_installed "poetry"; then printf "Installing poetry...\n" # Install poetry - curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 + run https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py python3 fi printf "poetry is installed\n" diff --git a/install/99-apt-clean.sh b/install/99-apt-clean.sh index 091af14..9be0851 100644 --- a/install/99-apt-clean.sh +++ b/install/99-apt-clean.sh @@ -1,5 +1,5 @@ #!/bin/bash # Clean up -sudo apt-get -y autoremove -sudo apt-get -y autoclean +sudo apt-get -qqy autoremove +sudo apt-get -qqy autoclean diff --git a/utils.sh b/utils.sh index 188c660..a55696e 100644 --- a/utils.sh +++ b/utils.sh @@ -1,29 +1,57 @@ +#!/bin/bash +# +# Alias commands and utilities. +# + +update() { + sudo apt-get update -y +} + +# Non-interactive upgrade +upgrade() { + DEBIAN_FRONTEND=noninteractive \ + sudo apt-get upgrade -y \ + -o Dpkg::Options::="--force-confdef" \ + -o Dpkg::Options::="--force-confold" +} + +# @arg $1 packages to install +install() { + sudo apt-get install -y $1 +} + +# @arg $1 repository to add +app_ppa() { + sudo add-apt-repository -y ppa:"$1" &>/dev/null +} + +# @arg $1 url to add +add_key() { + curl -fsSL $1 | sudo apt-key add - +} + +# @arg $1 URL to run +# @arg $2 binary to use +run() { + curl -fsSL $1 | $2 +} + +# Symlink contents of source folder to target +# +# @arg $1 source folder +# @arg $2 target folder +link_folder() { + cp -srf $1 $2 +} + indent() { sed 's/^/ /'; } -# Symlink contents of source folder to target -# -# @arg $1 source -# @arg $2 target -# -link_folder () { - - source=$1 - target=$2 - - for file in $(ls -d $source) - do - rel_path=$(realpath --relative-to="$target" "$file") - printf "Linking $file to $target as $rel_path...\n" - ln -sf $target $rel_path - done - -} - -# Return if specified binary is not in PATH -is_missing () { - return ! hash $1 +# @arg $1 binary to test +not_installed() { + ! [ -x "$(command -v $1)" ] } +# Colors C_BLACK='\033[0;30m' C_DGRAY='\033[1;30m' C_RED='\033[0;31m'