sort of
34
README.md
@@ -1,6 +1,24 @@
|
||||
# Dotfiles
|
||||
|
||||
Mirrors `$HOME`. Symlinked via `bootstrap.sh`.
|
||||
Filesystem overlay. Structure mirrors actual paths on disk.
|
||||
|
||||
```
|
||||
dotfiles/
|
||||
home/benk/ -> symlinked into $HOME
|
||||
.config/nvim/
|
||||
.config/fish/
|
||||
.config/wezterm/
|
||||
.tmux.conf
|
||||
.vimrc
|
||||
...
|
||||
etc/ -> copied into /etc (prompted, needs sudo)
|
||||
fstab
|
||||
nginx/nginx.conf
|
||||
packages/ -> package lists for brew/yay
|
||||
bootstrap.sh -> does everything
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
git clone git@github.com:benkyd/dotfiles.git ~/dotfiles
|
||||
@@ -8,11 +26,11 @@ cd ~/dotfiles
|
||||
./bootstrap.sh
|
||||
```
|
||||
|
||||
The bootstrap script will:
|
||||
1. Detect your OS (macOS or Arch Linux)
|
||||
2. Optionally install packages (Homebrew on macOS, yay on Arch)
|
||||
3. Install tmux plugin manager and fisher (fish plugin manager)
|
||||
4. Symlink all dotfiles into `$HOME` (existing files backed up to `~/dotfiles.bak/`)
|
||||
5. Optionally copy system configs from `etc/` to `/etc/` (with sudo, prompted)
|
||||
The bootstrap will:
|
||||
1. Detect OS (macOS / Arch)
|
||||
2. Optionally install packages (Homebrew or yay)
|
||||
3. Install oh-my-fish, fisher, tmux plugin manager
|
||||
4. Symlink `home/benk/` into `$HOME`
|
||||
5. Optionally copy `etc/` to `/etc` (prompted)
|
||||
|
||||
Works on both macOS and Linux — wezterm, tmux, and fish auto-detect the platform.
|
||||
Existing files are backed up to `~/dotfiles.bak/`.
|
||||
|
||||
153
bootstrap.sh
@@ -2,13 +2,50 @@
|
||||
set -euo pipefail
|
||||
|
||||
DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
HOME_DIR="$HOME"
|
||||
BACKUP_DIR="$HOME/dotfiles.bak"
|
||||
USER="$(whoami)"
|
||||
|
||||
usage() {
|
||||
echo "Usage: ./bootstrap.sh [--pull]"
|
||||
echo ""
|
||||
echo " (no args) Install packages, sync repo -> system"
|
||||
echo " --pull Sync system -> repo (pull changes back)"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Pull mode: copy live files back into the repo ---
|
||||
pull_back() {
|
||||
OVERLAY_HOME="$DOTFILES_DIR/home/$USER"
|
||||
if [ ! -d "$OVERLAY_HOME" ]; then
|
||||
OVERLAY_HOME="$DOTFILES_DIR/home/benk"
|
||||
fi
|
||||
|
||||
echo "==> Pulling home files back into repo..."
|
||||
rsync -av --itemize-changes --existing --update \
|
||||
"$HOME/" "$OVERLAY_HOME/"
|
||||
echo ""
|
||||
|
||||
if [ -d "$DOTFILES_DIR/etc" ]; then
|
||||
echo "==> Pulling /etc files back into repo..."
|
||||
sudo rsync -av --itemize-changes --existing --update \
|
||||
/etc/ "$DOTFILES_DIR/etc/"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "Done. Review changes with 'git diff' then commit."
|
||||
exit 0
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "--pull" ]]; then
|
||||
pull_back
|
||||
elif [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
echo "Ben's dotfiles"
|
||||
echo "=============="
|
||||
echo "Dotfiles dir: $DOTFILES_DIR"
|
||||
echo "Home dir: $HOME_DIR"
|
||||
echo "Repo: $DOTFILES_DIR"
|
||||
echo "User: $USER"
|
||||
echo ""
|
||||
|
||||
# --- Detect OS ---
|
||||
@@ -62,94 +99,70 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- tmux plugin manager ---
|
||||
# --- Shell tooling ---
|
||||
echo "==> Setting up shell tooling..."
|
||||
|
||||
# tmux plugin manager
|
||||
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
|
||||
echo "==> Installing tmux plugin manager..."
|
||||
echo " Installing tmux plugin manager..."
|
||||
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
|
||||
echo " Done. Run <C-b>I in tmux to install plugins."
|
||||
echo ""
|
||||
else
|
||||
echo " ok tmux plugin manager"
|
||||
fi
|
||||
|
||||
# --- fish plugin manager ---
|
||||
# oh-my-fish
|
||||
if command -v fish &>/dev/null; then
|
||||
if ! fish -c "type -q fisher" 2>/dev/null; then
|
||||
echo "==> Installing fisher (fish plugin manager)..."
|
||||
fish -c "curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- $HOME symlinks ---
|
||||
echo "==> Symlinking home files..."
|
||||
|
||||
find "$DOTFILES_DIR" -maxdepth 1 -name '.*' -not -name '.git' -not -name '.gitignore' -not -name '.gitmodules' | while read -r src; do
|
||||
item="$(basename "$src")"
|
||||
dst="$HOME_DIR/$item"
|
||||
|
||||
if [ -L "$dst" ] && [ "$(readlink "$dst")" = "$src" ]; then
|
||||
echo " ok $item"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -e "$dst" ] || [ -L "$dst" ]; then
|
||||
backup="$BACKUP_DIR/$item"
|
||||
mkdir -p "$(dirname "$backup")"
|
||||
mv "$dst" "$backup"
|
||||
echo " bak $item -> dotfiles.bak/$item"
|
||||
fi
|
||||
|
||||
ln -s "$src" "$dst"
|
||||
echo " ln $item"
|
||||
done
|
||||
|
||||
if [ -d "$DOTFILES_DIR/pictures" ]; then
|
||||
dst="$HOME_DIR/pictures"
|
||||
src="$DOTFILES_DIR/pictures"
|
||||
if [ -L "$dst" ] && [ "$(readlink "$dst")" = "$src" ]; then
|
||||
echo " ok pictures"
|
||||
if [ ! -d "$HOME/.local/share/omf" ]; then
|
||||
echo " Installing oh-my-fish..."
|
||||
curl -L https://get.oh-my.fish | fish
|
||||
else
|
||||
if [ -e "$dst" ] || [ -L "$dst" ]; then
|
||||
mv "$dst" "$BACKUP_DIR/pictures"
|
||||
echo " bak pictures -> dotfiles.bak/pictures"
|
||||
fi
|
||||
ln -s "$src" "$dst"
|
||||
echo " ln pictures"
|
||||
echo " ok oh-my-fish"
|
||||
fi
|
||||
|
||||
# fisher
|
||||
if ! fish -c "type -q fisher" 2>/dev/null; then
|
||||
echo " Installing fisher (fish plugin manager)..."
|
||||
fish -c "curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisher"
|
||||
else
|
||||
echo " ok fisher"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# --- /etc copies ---
|
||||
# --- Overlay: home/benk/ -> $HOME ---
|
||||
OVERLAY_HOME="$DOTFILES_DIR/home/$USER"
|
||||
|
||||
if [ ! -d "$OVERLAY_HOME" ]; then
|
||||
echo "WARNING: No home overlay for user '$USER', falling back to home/benk/"
|
||||
OVERLAY_HOME="$DOTFILES_DIR/home/benk"
|
||||
fi
|
||||
|
||||
echo "==> Syncing $OVERLAY_HOME -> $HOME"
|
||||
mkdir -p "$BACKUP_DIR/home"
|
||||
rsync -av --itemize-changes --backup --backup-dir="$BACKUP_DIR/home" \
|
||||
"$OVERLAY_HOME/" "$HOME/"
|
||||
echo ""
|
||||
|
||||
# --- Overlay: etc/ -> /etc ---
|
||||
if [ -d "$DOTFILES_DIR/etc" ]; then
|
||||
etc_files=$(find "$DOTFILES_DIR/etc" -type f 2>/dev/null)
|
||||
if [ -n "$etc_files" ]; then
|
||||
echo "==> System config files found in etc/"
|
||||
|
||||
echo "==> System config files in etc/:"
|
||||
echo "$etc_files" | while read -r src; do
|
||||
rel="${src#$DOTFILES_DIR/}"
|
||||
echo " /$rel"
|
||||
echo " /${src#$DOTFILES_DIR/}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
read -p "Copy system configs to /etc? This requires sudo. [y/N] " -n 1 -r
|
||||
read -p "Sync to /etc? Requires sudo. [y/N] " -n 1 -r
|
||||
echo ""
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "$etc_files" | while read -r src; do
|
||||
rel="${src#$DOTFILES_DIR/}"
|
||||
dst="/$rel"
|
||||
|
||||
if [ -f "$dst" ]; then
|
||||
backup="$BACKUP_DIR/$rel"
|
||||
sudo mkdir -p "$(dirname "$backup")"
|
||||
sudo cp "$dst" "$backup"
|
||||
echo " bak /$rel -> dotfiles.bak/$rel"
|
||||
fi
|
||||
|
||||
sudo mkdir -p "$(dirname "$dst")"
|
||||
sudo cp "$src" "$dst"
|
||||
echo " cp $rel"
|
||||
done
|
||||
mkdir -p "$BACKUP_DIR/etc"
|
||||
sudo rsync -av --itemize-changes --backup --backup-dir="$BACKUP_DIR/etc" \
|
||||
"$DOTFILES_DIR/etc/" /etc/
|
||||
echo " Originals backed up to ~/dotfiles.bak/etc/"
|
||||
else
|
||||
echo " Skipped."
|
||||
fi
|
||||
@@ -157,4 +170,4 @@ if [ -d "$DOTFILES_DIR/etc" ]; then
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done. Backup at ~/dotfiles.bak/ (if anything was moved)"
|
||||
echo "Done. Backups at ~/dotfiles.bak/"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 679 B After Width: | Height: | Size: 679 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 501 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 719 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 633 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 751 B |
|
Before Width: | Height: | Size: 211 B After Width: | Height: | Size: 211 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 157 B |
|
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 157 B |
|
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 157 B After Width: | Height: | Size: 157 B |
|
Before Width: | Height: | Size: 156 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 383 KiB After Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |