#!/usr/bin/env bash # # Darkcloud Neovim Config Update Tool # https://github.com/prurigro/darkcloud-nvimconfig # # Written by Kevin MacMartin (prurigro@gmail.com) # Released under the MIT license # script_name="${0//*\/}" script_home="${0%$script_name}" if [[ -z "$script_home" ]]; then script_home="$PWD" else pushd "$script_home" >/dev/null || exit script_home="$PWD" popd >/dev/null || exit fi repo_version="$(printf "%s.r%s" "$(git show -s --format=%ci master | sed 's/\ .*//g;s/-//g')" "$(git rev-list --count HEAD)")" error_log='update-errors.log' if [[ -t 1 ]]; then cbg_blue=$'\e[44m' cbg_red_bold=$'\e[1;41m' cbg_black=$'\e[40m' cbg_yellow=$'\e[43m' cfg_green_bold=$'\e[1;32m' cfg_red_bold=$'\e[1;31m' cfg_white_bold=$'\e[1;37m' c_reset=$'\e[0m' else cbg_blue='#' fi # error: output and log error function error { printf '%s\n' "$cbg_blue $c_reset$cbg_red_bold ! ERROR: $c_reset$cfg_red_bold $2 " >&2 printf '%s\n' "$cbg_blue $c_reset$cbg_red_bold ! COMMAND: $c_reset ${cfg_white_bold}=> $1$c_reset" >&2 [[ -n "$3" ]] && printf '%s\n' "$cbg_blue $c_reset$cbg_red_bold ! OUTPUT: $c_reset$cfg_white_bold $3" >&2 printf '%s\n%s\n%s\n' "DATE: @ $(date)" "ERROR: $2" "COMMAND: $1" >> "$script_home/$error_log" [[ -n "$3" ]] && printf '%s\n' "OUTPUT: $3" >> "$script_home/$error_log" printf '\n' >> "$script_home/$error_log" } # show_version: displays version information function show_version { printf '%s\n' "$script_name: darkcloud-nvimconfig update tool (version: $repo_version)" } # show_help: this function displays help output function show_help { printf '\n%s\n' 'USAGE' printf ' %s\n\n' "./$script_name [OPTION]" printf '%s\n' 'OPTIONS' printf ' %s\t%s\n' '-v, --version' '| output version information and exit' printf ' %s\t%s\n\n' '-h, --help' '| display this help and exit' printf '%s\n' 'Run with no arguments to update darkcloud-nvimconfig' } ### SETUP if type -P timeout >/dev/null; then timeout_command=timeout elif type -P gtimeout >/dev/null; then timeout_command=gtimeout else error 'type -P timeout' 'The timeout command could not be found (install coreutils)' exit 1 fi cd "$script_home" || exit # delete old error log if it exists [[ -f "$error_log" ]] && rm "$script_home/$error_log" # parse for arguments (then handle them below) [[ -n "$1" ]] && { case "$1" in -h|--help) show_version show_help exit 0 ;; -v|--version) show_version exit 0 ;; *) error "$ERROR" "$1 is not a valid option" show_help exit 1 ;; esac } # display script title printf '\n%s\n' "$cbg_black ~~~ DarkCloud Neovim Config Update Tool ~~~ $c_reset" # create vim/bundle.user if it doesn't exist [[ -d 'vim/bundle.user' ]] || { printf '\n%s' "$cbg_blue >> Creating user plugin directory:$c_reset" process_status="$(install -d 'vim/bundle.user' 2>&1)" if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'install -d vim/bundle.user' "User plugin directory couldn't be created" "$process_status" fi } # create vim/user.vim if it doesn't exist [[ -e 'vim/user.vim' ]] || { printf '\n%s' "$cbg_blue >> Creating user config file:$c_reset" process_status="$(touch 'vim/user.vim' 2>&1)" if (( ! $? )); then { printf '%s\n%s\n\n' '"Auto-start syntax checking: (1:start toggled on | *0:start toggled off)' '"let g:autostartchecker = 1' printf '%s\n%s\n\n' '"Auto-start Tagbar: (1:start open | *0:start closed)' '"let g:autostarttagbar = 1' printf '%s\n%s\n\n' '"Enable Treesitter: (1:treesitter enabled | *0:treesitter disabled)' '"let g:enabletreesitter = 1' printf '%s\n%s\n\n' '"Enable Auto-completion: (1:autocompletion enabled | *0:autocompletion disabled)' '"let g:enablecompletion = 1' printf '%s\n%s\n\n' '"Enable automatic tag generation: (1:enable tag generation | *0:disable automatic tag generation)' '"let g:enableautotags = 1' printf '%s\n%s\n' '"Enable Powerline: (1:use powerline characters | *0:use regular characters)' '"let g:enablepowerline = 1' } >> vim/user.vim if [[ -e 'vim/user.vim' ]]; then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" fi else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error "touch vim/user.vim" "User config couldn't be created" "$process_status" fi } ### REPO UPDATE printf '\n%s' "$cbg_blue >> Updating darkcloud-nvimconfig:$c_reset" process_status="$(git pull origin master 2>&1)" if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'git pull origin master' 'Git failed to sync the repo' "$process_status" exit 1 fi ### SUBMODULE UPDATE { printf '\n%s\n' "$cbg_blue >> Updating plugin submodules >> $c_reset" printf '%s' "$cbg_blue $c_reset$cbg_yellow + Updating plugin URLs:$c_reset" process_status="$(git submodule sync 2>&1)" if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'git submodule sync' 'Git failed to sync the submodules' "$process_status" fi # update each submodule to the new head and run 'git fetch --all' printf '%s' "$cbg_blue $c_reset$cbg_yellow + Fetching updates:$c_reset" git submodule foreach git reset --hard >/dev/null 2>&1 process_status="$(git submodule foreach git fetch --all 2>&1)" if (( ! $? )); then process_status=$(git submodule update --init --recursive 2>&1) if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'git submodule update --init --recursive' 'Git failed to update the submodules' "$process_status" fi else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'git submodule foreach git fetch --all' "Git failed to fetch the submodules from their respective remotes" "$process_status" fi # clean plugin directories and remove plugins no longer in the repo printf '\n%s\n' "$cbg_blue >> Clean plugin directories >> $c_reset" printf '%s' "$cbg_blue $c_reset$cbg_yellow + Remove untracked files:$c_reset" process_status="$(git submodule foreach git clean -dxf 2>&1)" if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error 'git submodule foreach git clean -dxf' 'Git failed to remove untracked files' "$process_status" fi [[ -f '.gitmodules' ]] && { for plugin in vim/bundle/*; do [[ -f "$plugin/.git" ]] && { plugin_dirname="${plugin/*\/}" grep 'path = ' .gitmodules | grep -o -e '[^\/]*$' | grep -q -e "$plugin_dirname$" || { [[ -z "$first_found" ]] && { first_found=1 printf '%s\n' "$cbg_blue $c_reset$cbg_yellow + Removing old plugins: $c_reset" } process_status="$(rm -rf "${plugin:?}")" if (( ! $? )); then printf '%s\n' "$cbg_blue $c_reset$cbg_yellow = $cfg_white_bold$plugin$c_reset" else error "rm -rf $plugin" "Folder couldn't be deleted" "$process_status" exit 1 fi } } done printf '\n' } ### USER PLUGIN UPDATE [[ -d vim/bundle.user ]] && find vim/bundle.user -mindepth 3 -maxdepth 3 -name config | grep -q '.git/config' && { printf '%s\n' "$cbg_blue >> Updating user plugins >> $c_reset" pushd 'vim/bundle.user' >/dev/null || exit for plugin in *; do [[ -d "$plugin/.git" ]] && { pushd "$plugin" >/dev/null || exit printf '%s' "$cbg_blue $c_reset$cbg_yellow + Updating 'vim/bundle.user/$plugin':$c_reset" process_status="$(git pull 2>&1)" if (( ! $? )); then if ! grep -q "Already up-to-date" <<< "$process_status"; then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else printf '%s\n' "$cfg_white_bold UP TO DATE $c_reset" fi else error 'git pull' "Failed pulling changes for $plugin" "$process_status" fi popd >/dev/null || exit } done popd >/dev/null || exit printf '\n' } ### GENERATE PLUGIN HELP type -P vim >/dev/null && { printf '%s' "$cbg_blue >> Generating plugin help:$c_reset" $timeout_command --preserve-status --foreground 1m nvim -c 'Helptags|qa!' if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else reset -I printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error "nvim -c 'Helptags|qa!'" 'Generating helpdocs for the submodules failed' fi } ### UPDATE REMOTE PLUGINS printf '%s' "$cbg_blue >> Updating remote plugins for neovim:$c_reset" $timeout_command --preserve-status --foreground 1m nvim -c ':UpdateRemotePlugins|qa!' if (( ! $? )); then printf '%s\n' "$cfg_green_bold SUCCESS! $c_reset" else reset -I printf '%s\n' "$cfg_red_bold FAIL! $c_reset" error "nvim -c ':UpdateRemotePlugins|qa!'" 'Updating remote plugins for neovim failed' fi ### FINISH printf '\n%s\n\n' "$cbg_black ~~~ Update Complete ~~~ $c_reset"