|  | 
|  | 1 | +#!/usr/bin/env bash | 
|  | 2 | + | 
|  | 3 | +error_exit() { printf '%s\n' "$@" >&2; exit 1; } | 
|  | 4 | +exit_if_error() { local ec=$1; shift; (($ec)) && error_exit "$@"; } | 
|  | 5 | +cd_base() { cd -- "$BASE_HOME" || exit_if_error 1 "Can't cd to BASE_HOME at '$BASE_HOME'"; } | 
|  | 6 | + | 
|  | 7 | +show_common_help() { | 
|  | 8 | + cat << EOF | 
|  | 9 | +Usage: base [-b DIR] [-t TEAM] [-x] [install|embrace|update|run|status|help] ... | 
|  | 10 | +-b DIR - use DIR as BASE_HOME directory | 
|  | 11 | +-t TEAM - use TEAM as BASE_TEAM | 
|  | 12 | +-x - turn on bash debug mode | 
|  | 13 | +
 | 
|  | 14 | +install - install Base | 
|  | 15 | +embrace - override .bash_profile and .bashrc so that Base gets enabled upon login | 
|  | 16 | +update - update Base by running 'git pull' in BASE_HOME directory | 
|  | 17 | +run - run the rest of the command line after initializing Base | 
|  | 18 | +status - check if Base is installed or not | 
|  | 19 | +help - show this help message | 
|  | 20 | +
 | 
|  | 21 | +When invoked without any arguments, base gives you an interactive bash shell with Base initialized. | 
|  | 22 | +EOF | 
|  | 23 | +} | 
|  | 24 | + | 
|  | 25 | +base_init() { | 
|  | 26 | + local base_init=$BASE_HOME/base_init.sh | 
|  | 27 | + [[ -f $base_init ]] && source "$base_init" | 
|  | 28 | +} | 
|  | 29 | + | 
|  | 30 | +get_base_home() { | 
|  | 31 | + # if BASE_HOME is not already set, source .baserc to see it is defined there | 
|  | 32 | + if [[ ! $BASE_HOME ]]; then | 
|  | 33 | + local baserc=$HOME/.baserc | 
|  | 34 | + [[ -f $baserc ]] && source "$baserc" | 
|  | 35 | + fi | 
|  | 36 | + | 
|  | 37 | + # if BASE_HOME is still not set, go with the default value | 
|  | 38 | + BASE_HOME=${BASE_HOME:-$HOME/base} | 
|  | 39 | +} | 
|  | 40 | + | 
|  | 41 | +create_base_home() { | 
|  | 42 | + # if set, BASE_HOME must hold a directory name | 
|  | 43 | + if [[ -e $BASE_HOME && ! -d $BASE_HOME ]]; then | 
|  | 44 | + error_exit "$BASE_HOME exists but it is not a directory!" | 
|  | 45 | + else | 
|  | 46 | + mkdir -- "$BASE_HOME" | 
|  | 47 | + exit_if_error $? "Can't create directory '$BASE_HOME'" | 
|  | 48 | + fi | 
|  | 49 | +} | 
|  | 50 | + | 
|  | 51 | +verify_base() { | 
|  | 52 | + # now make sure BASE_HOME directory is actually a git repo | 
|  | 53 | + local git=$BASE_HOME/.git | 
|  | 54 | + if [[ ! -d $git ]]; then | 
|  | 55 | + glb_error_message="Directory '$BASE_HOME' isn't a git repo" | 
|  | 56 | + return 1 | 
|  | 57 | + else | 
|  | 58 | + local oldpwd=$PWD | 
|  | 59 | + cd -- "$git" || { glb_error_message="Can't cd to '$git' directory"; return 1; } | 
|  | 60 | + if ! git rev-parse --git-dir &>/dev/null; then | 
|  | 61 | + glb_error_message="Directory '$git' isn't a git repo" | 
|  | 62 | + return 1 | 
|  | 63 | + fi | 
|  | 64 | + local file missing | 
|  | 65 | + for file in base_init.sh lib/bash_profile lib/bashrc; do | 
|  | 66 | + if [[ ! -f $BASE_HOME/$file ]]; then | 
|  | 67 | + missing+=($file) | 
|  | 68 | + fi | 
|  | 69 | + done | 
|  | 70 | + cd -- "$oldpwd" | 
|  | 71 | + if (( ${#missing[@]} > 0)); then | 
|  | 72 | + glb_error_message="Files missing in base repo: ${missing[@]}" | 
|  | 73 | + return 1 | 
|  | 74 | + fi | 
|  | 75 | + fi | 
|  | 76 | + return 0 | 
|  | 77 | +} | 
|  | 78 | + | 
|  | 79 | +do_install() { | 
|  | 80 | + local repo="ssh://git.corp.linkedin.com:29418/tools-sre/base" | 
|  | 81 | + if [[ -d $BASE_HOME ]]; then | 
|  | 82 | + printf '%s\n' "base is already installed at '$BASE_HOME'" | 
|  | 83 | + else | 
|  | 84 | + git clone "$repo" "$BASE_HOME" | 
|  | 85 | + exit_if_error $? "Couldn't install base" | 
|  | 86 | + printf '%s\n' "Installed base at '$BASE_HOME'" | 
|  | 87 | + # | 
|  | 88 | + # patch .baserc | 
|  | 89 | + # This is how we remember custom BASE_HOME path and BASE_TEAM values. | 
|  | 90 | + # The user is free to put custom code into the .baserc file. | 
|  | 91 | + # A marker is appended to the lines managed by base CLI | 
|  | 92 | + # | 
|  | 93 | + local baserc=$HOME/.baserc | 
|  | 94 | + local baserc_temp=$HOME/.baserc.temp | 
|  | 95 | + local marker="# BASE_MARKER, do not delete" | 
|  | 96 | + if [[ ! -f $baserc ]]; then | 
|  | 97 | + touch -- "$baserc" | 
|  | 98 | + exit_if_error $? "Couldn't create '$baserc'" | 
|  | 99 | + else | 
|  | 100 | + local base_text_array=("export BASE_HOME=$BASE_HOME $marker" | 
|  | 101 | + "export BASE_TEAM=$BASE_TEam $marker") | 
|  | 102 | + local base_text | 
|  | 103 | + printf -v base_text '%s\n' "${base_text_array[@]}" | 
|  | 104 | + cat <(grep -v -- "$marker" "$baserc") - <<< "base_text" > "$baserc_temp" | 
|  | 105 | + exit_if_error $? "Couldn't create '$baserc_temp'" | 
|  | 106 | + mv -f -- "$baserc_temp" "$baserc" | 
|  | 107 | + exit_if_error $? "Couldn't overwrite '$baserc'" | 
|  | 108 | + fi | 
|  | 109 | + fi | 
|  | 110 | + exit 0 | 
|  | 111 | +} | 
|  | 112 | + | 
|  | 113 | +do_embrace() { | 
|  | 114 | + if ! verify_base; then | 
|  | 115 | + error_exit "$glb_error_message" | 
|  | 116 | + fi | 
|  | 117 | + local base_bash_profile=$BASE_HOME/lib/bash_profile | 
|  | 118 | + local base_bashrc=$BASE_HOME/lib/bashrc | 
|  | 119 | + local bash_profile=$HOME/.bash_profile | 
|  | 120 | + local bashrc=$HOME/.bashrc | 
|  | 121 | + if [[ -L $bash_profile ]]; then | 
|  | 122 | + local bash_profile_link=$(readlink "$bash_profile") | 
|  | 123 | + fi | 
|  | 124 | + if [[ -L $bashrc ]]; then | 
|  | 125 | + local bashrc_link=$(readlink "$bashrc") | 
|  | 126 | + fi | 
|  | 127 | + local current_time | 
|  | 128 | + printf -v current_time '%(%Y-%m-%d:%H:%M:%S)T' -1 | 
|  | 129 | + if [[ $bash_profile_link = $base_bash_profile ]]; then | 
|  | 130 | + printf '%s\n' "$bash_profile is already symlinked to $base_bash_profile" | 
|  | 131 | + else | 
|  | 132 | + local bash_profile_backup=$HOME/.bash_profile.$current_time | 
|  | 133 | + printf '%s\n' "Backing up $bash_profile to $bash_profile_backup and overriding it with $base_bash_profile" | 
|  | 134 | + if cp -- "$bash_profile" "$bash_profile_backup"; then | 
|  | 135 | + ln -sf -- "$base_bash_profile" "$bash_profile" | 
|  | 136 | + else | 
|  | 137 | + exit_if_error $? "ERROR: can't create a backup of $bash_profile" | 
|  | 138 | + fi | 
|  | 139 | + fi | 
|  | 140 | + if [[ $bashrc_link = $base_bashrc ]]; then | 
|  | 141 | + printf '%s\n' "$bashrc is already symlinked to $base_bashrc" | 
|  | 142 | + else | 
|  | 143 | + local bashrc_backup=$HOME/.bashrc.$current_time | 
|  | 144 | + printf '%s\n' "Backing up $bashrc to $bashrc_backup and overriding it with $base_bashrc" | 
|  | 145 | + if cp -- "$bashrc" "$bashrc_backup"; then | 
|  | 146 | + ln -sf -- "$base_bashrc" "$bashrc" | 
|  | 147 | + else | 
|  | 148 | + exit_if_error $? "ERROR: can't create a backup of $bashrc" | 
|  | 149 | + fi | 
|  | 150 | + fi | 
|  | 151 | +} | 
|  | 152 | + | 
|  | 153 | +do_update() { | 
|  | 154 | + if [[ -d $BASE_HOME ]]; then | 
|  | 155 | + cd -- "$BASE_HOME" || error_exit "Can't cd to BASE_HOME at '$BASE_HOME'" | 
|  | 156 | + git pull | 
|  | 157 | + else | 
|  | 158 | + printf '%s\n' "ERROR: base is not installed at BASE_HOME '$BASE_HOME'" | 
|  | 159 | + exit 1 | 
|  | 160 | + fi | 
|  | 161 | +} | 
|  | 162 | + | 
|  | 163 | +do_run() { | 
|  | 164 | + base_init | 
|  | 165 | + "$@" | 
|  | 166 | +} | 
|  | 167 | + | 
|  | 168 | +do_status() { | 
|  | 169 | + if [[ ! -d $BASE_HOME ]]; then | 
|  | 170 | + printf '%s\n' "base is not installed at '$BASE_HOME'" | 
|  | 171 | + exit 1 | 
|  | 172 | + fi | 
|  | 173 | + | 
|  | 174 | + if ! verify_base; then | 
|  | 175 | + error_exit "$glb_error_message" | 
|  | 176 | + else | 
|  | 177 | + printf '%s\n' "base is installed at $BASE_HOME" | 
|  | 178 | + fi | 
|  | 179 | + exit 0 | 
|  | 180 | +} | 
|  | 181 | + | 
|  | 182 | +do_shell() { | 
|  | 183 | + export BASE_SHELL=1 | 
|  | 184 | + exec bash --rcfile "$BASE_HOME/lib/bash_profile" | 
|  | 185 | +} | 
|  | 186 | + | 
|  | 187 | +main() { | 
|  | 188 | + if [[ $1 =~ -h|--help|-help|help ]]; then | 
|  | 189 | + show_common_help | 
|  | 190 | + exit 0 | 
|  | 191 | + fi | 
|  | 192 | + | 
|  | 193 | + while getopts "hb:t:x" opt; do | 
|  | 194 | + case $opt in | 
|  | 195 | + b) export BASE_HOME=$OPTARG | 
|  | 196 | + ;; | 
|  | 197 | + t) export BASE_TEAM=$OPTARG | 
|  | 198 | + ;; | 
|  | 199 | + x) set -x | 
|  | 200 | + ;; | 
|  | 201 | + *) show_common_help >&2 | 
|  | 202 | + exit 2 | 
|  | 203 | + ;; | 
|  | 204 | + esac | 
|  | 205 | + done | 
|  | 206 | + shift $((OPTIND-1)) | 
|  | 207 | + command=$1 | 
|  | 208 | + shift 2>/dev/null | 
|  | 209 | + get_base_home | 
|  | 210 | + case $command in | 
|  | 211 | + install) | 
|  | 212 | + do_install | 
|  | 213 | + ;; | 
|  | 214 | + update) | 
|  | 215 | + do_update | 
|  | 216 | + ;; | 
|  | 217 | + embrace) | 
|  | 218 | + do_embrace | 
|  | 219 | + ;; | 
|  | 220 | + run) | 
|  | 221 | + do_run "$@" | 
|  | 222 | + ;; | 
|  | 223 | + status) | 
|  | 224 | + do_status | 
|  | 225 | + ;; | 
|  | 226 | + help) | 
|  | 227 | + show_common_help | 
|  | 228 | + ;; | 
|  | 229 | + "") | 
|  | 230 | + do_shell | 
|  | 231 | + ;; | 
|  | 232 | + *) | 
|  | 233 | + printf '%s\n' "Unrecognized command: $command" >&2 | 
|  | 234 | + show_common_help >&2 | 
|  | 235 | + exit 2 | 
|  | 236 | + ;; | 
|  | 237 | + esac | 
|  | 238 | +} | 
|  | 239 | + | 
|  | 240 | +main "$@" | 
0 commit comments