dotfiles v1.0.2
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
# DOTFILES_DIR holds the template files; DOTFILES_BACKUP_DIR holds backups
|
# DOTFILES_DIR holds the template files; DOTFILES_BACKUP_DIR holds backups
|
||||||
# and the last-update-check timestamp.
|
# and the last-update-check timestamp.
|
||||||
|
|
||||||
set -g DOTFILES_VERSION "1.0.1"
|
set -g DOTFILES_VERSION "1.0.2"
|
||||||
|
|
||||||
# --- Remote repository (set this to enable auto-updates) --------------------
|
# --- Remote repository (set this to enable auto-updates) --------------------
|
||||||
# Example:
|
# Example:
|
||||||
|
|||||||
@@ -518,11 +518,15 @@ function dotfiles_publish -d "Push local changes to the remote dotfiles repo"
|
|||||||
set -l local_funcs "$__fish_config_dir/functions/"
|
set -l local_funcs "$__fish_config_dir/functions/"
|
||||||
set -l local_tmpl "$DOTFILES_DIR/"
|
set -l local_tmpl "$DOTFILES_DIR/"
|
||||||
set -l local_confd "$__fish_config_dir/conf.d/"
|
set -l local_confd "$__fish_config_dir/conf.d/"
|
||||||
|
set -l local_install "$__fish_config_dir/install.fish"
|
||||||
|
set -l local_readme "$__fish_config_dir/README.md"
|
||||||
|
|
||||||
set -l repo_config "$tmpdir/.config/fish/config.fish"
|
set -l repo_config "$tmpdir/.config/fish/config.fish"
|
||||||
set -l repo_funcs "$tmpdir/.config/fish/functions/"
|
set -l repo_funcs "$tmpdir/.config/fish/functions/"
|
||||||
set -l repo_tmpl "$tmpdir/.config/fish/dotfiles/"
|
set -l repo_tmpl "$tmpdir/.config/fish/dotfiles/"
|
||||||
set -l repo_confd "$tmpdir/.config/fish/conf.d/"
|
set -l repo_confd "$tmpdir/.config/fish/conf.d/"
|
||||||
|
set -l repo_install "$tmpdir/install.fish"
|
||||||
|
set -l repo_readme "$tmpdir/README.md"
|
||||||
|
|
||||||
# Ensure target directories exist
|
# Ensure target directories exist
|
||||||
for d in (dirname "$repo_config") "$repo_funcs" "$repo_tmpl" "$repo_confd"
|
for d in (dirname "$repo_config") "$repo_funcs" "$repo_tmpl" "$repo_confd"
|
||||||
@@ -539,6 +543,18 @@ function dotfiles_publish -d "Push local changes to the remote dotfiles repo"
|
|||||||
echo " dotfiles/"
|
echo " dotfiles/"
|
||||||
command cp -r "$local_confd." "$repo_confd"
|
command cp -r "$local_confd." "$repo_confd"
|
||||||
echo " conf.d/"
|
echo " conf.d/"
|
||||||
|
if test -f "$local_install"
|
||||||
|
command cp "$local_install" "$repo_install"
|
||||||
|
echo " install.fish"
|
||||||
|
else
|
||||||
|
echo " (no install.fish)"
|
||||||
|
end
|
||||||
|
if test -f "$local_readme"
|
||||||
|
command cp "$local_readme" "$repo_readme"
|
||||||
|
echo " README.md"
|
||||||
|
else
|
||||||
|
echo " (no README.md)"
|
||||||
|
end
|
||||||
|
|
||||||
# ── Step 4: Prompt for version ─────────────────────────────────────────
|
# ── Step 4: Prompt for version ─────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
113
README.md
Normal file
113
README.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# Dotfiles Manager
|
||||||
|
|
||||||
|
A self-managing Fish shell configuration that tracks its own version, can
|
||||||
|
automatically update itself from a Git repository, and manages standard
|
||||||
|
dotfiles (`~/.tmux.conf`, `~/.gitconfig`, etc.) from version-controlled
|
||||||
|
templates.
|
||||||
|
|
||||||
|
## Quick Install
|
||||||
|
|
||||||
|
```fish
|
||||||
|
curl -fsSL https://git.toomuchtaco.net/taco/dots/raw/branch/main/install.fish | fish
|
||||||
|
```
|
||||||
|
|
||||||
|
This one-liner clones the repository, installs everything to
|
||||||
|
`~/.config/fish/`, creates `~/.tmux.conf` and other dotfiles from templates,
|
||||||
|
and prints next steps.
|
||||||
|
|
||||||
|
**Prerequisites:** Fish shell 3.2+, Git.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---|---|
|
||||||
|
| `dotfiles help` | Show all subcommands |
|
||||||
|
| `dotfiles version` | Display current version, repo URL, shell info |
|
||||||
|
| `dotfiles status [name ...]` | Checksum-compare installed files against templates |
|
||||||
|
| `dotfiles init [name ...]` | Create dotfiles from templates (backs up existing) |
|
||||||
|
| `dotfiles update [name ...]` | Re-apply template contents (backs up existing) |
|
||||||
|
| `dotfiles edit <name>` | Open `~/.<name>` in `$EDITOR` |
|
||||||
|
| `dotfiles repo [url]` | Show or set the remote Git repository URL |
|
||||||
|
| `dotfiles sync` | Pull latest templates from remote and re-apply |
|
||||||
|
| `dotfiles publish` | Bump version, commit local changes, push to remote |
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```fish
|
||||||
|
dotfiles status # Check every managed file
|
||||||
|
dotfiles init gitconfig # Create only ~/.gitconfig
|
||||||
|
dotfiles edit tmux # Open ~/.tmux.conf in your editor
|
||||||
|
dotfiles repo # Show current remote URL
|
||||||
|
dotfiles sync # Pull updates and re-apply
|
||||||
|
dotfiles publish # Bump version, commit, push
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.config/fish/
|
||||||
|
├── config.fish Main entry point — version, PATH, interactive setup
|
||||||
|
├── install.fish Bootstrap/install script (also at repo root)
|
||||||
|
├── README.md This file
|
||||||
|
├── conf.d/
|
||||||
|
│ └── aliases.fish Example: Git abbreviations, helper functions
|
||||||
|
├── functions/
|
||||||
|
│ ├── dotfiles.fish The `dotfiles` command and all subcommands
|
||||||
|
│ └── gitea_key.fish Helper: generate SSH key for Gitea
|
||||||
|
└── dotfiles/
|
||||||
|
├── tmux.conf Template → ~/.tmux.conf
|
||||||
|
├── gitconfig Template → ~/.gitconfig
|
||||||
|
└── config/
|
||||||
|
└── starship.toml Template → ~/.config/starship.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### Versioning
|
||||||
|
|
||||||
|
A single `DOTFILES_VERSION` variable at the top of `config.fish` is the
|
||||||
|
source of truth. When you run `dotfiles publish`, you are prompted for a
|
||||||
|
new version (auto-suggested minor bump, or custom), and both the local
|
||||||
|
`config.fish` and the remote repository are updated.
|
||||||
|
|
||||||
|
### Templates
|
||||||
|
|
||||||
|
Each file in `~/.config/fish/dotfiles/` is a template. When you run
|
||||||
|
`dotfiles init`, templates are copied to `~/` with a leading dot prepended
|
||||||
|
(e.g. `tmux.conf` → `~/.tmux.conf`). Templates in subdirectories are
|
||||||
|
placed under `~/` preserving the path (e.g. `config/starship.toml` →
|
||||||
|
`~/.config/starship.toml`).
|
||||||
|
|
||||||
|
To add a new dotfile, simply drop a template file into `dotfiles/` and run
|
||||||
|
`dotfiles init <name>`. No registration needed.
|
||||||
|
|
||||||
|
### Sync & Publish
|
||||||
|
|
||||||
|
- **`dotfiles sync`** — clones the remote repo (shallow) and copies templates
|
||||||
|
into `dotfiles/`, then re-applies them. Pulls changes *down*.
|
||||||
|
- **`dotfiles publish`** — clones the remote repo (full), copies your local
|
||||||
|
`config.fish`, `functions/`, `dotfiles/`, and `conf.d/` into the clone,
|
||||||
|
prompts for a version bump, commits, and pushes. Sends changes *up*.
|
||||||
|
|
||||||
|
## Extending
|
||||||
|
|
||||||
|
- **Add a template:** create a file in `~/.config/fish/dotfiles/`.
|
||||||
|
- **Add shell config:** create a file in `~/.config/fish/conf.d/` (auto-sourced
|
||||||
|
by Fish in alphabetical order).
|
||||||
|
- **Add a function:** create a file in `~/.config/fish/functions/` (auto-loaded
|
||||||
|
by Fish when first called).
|
||||||
|
|
||||||
|
## Custom Install
|
||||||
|
|
||||||
|
Pass a different repository URL to the install script:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
curl -fsSL https://git.toomuchtaco.net/taco/dots/raw/branch/main/install.fish | fish -s -- https://github.com/you/your-dotfiles
|
||||||
|
```
|
||||||
|
|
||||||
|
Or clone manually and run the install script locally:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
git clone git@gitssh.toomuchtaco.net:taco/dots.git /tmp/dots
|
||||||
|
fish /tmp/dots/install.fish
|
||||||
|
```
|
||||||
220
install.fish
Normal file
220
install.fish
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
#!/usr/bin/env fish
|
||||||
|
#
|
||||||
|
# install.fish — Dotfiles bootstrap script
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Quick install (copy-paste this one-liner):
|
||||||
|
#
|
||||||
|
# curl -fsSL https://git.toomuchtaco.net/taco/dots/raw/branch/main/install.fish | fish
|
||||||
|
#
|
||||||
|
# What this script does:
|
||||||
|
# 1. Checks prerequisites: Fish shell, Git, and a few common tools
|
||||||
|
# 2. Clones the dotfiles repository (default: git@gitssh.toomuchtaco.net:taco/dots.git)
|
||||||
|
# 3. Replaces or updates ~/.config/fish/ with the contents of the repo
|
||||||
|
# 4. Sources the new config and runs `dotfiles init` to install templates
|
||||||
|
# (~/.tmux.conf, ~/.gitconfig, ~/.config/starship.toml, etc.)
|
||||||
|
# 5. Prints next steps
|
||||||
|
#
|
||||||
|
# You can pass a custom repo URL as the first argument:
|
||||||
|
#
|
||||||
|
# curl -fsSL https://git.toomuchtaco.net/taco/dots/raw/branch/main/install.fish | fish -s -- https://github.com/you/dotfiles
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# Configuration
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# Default repository URL (overridable via first argument).
|
||||||
|
set -l REPO_URL "git@gitssh.toomuchtaco.net:taco/dots.git"
|
||||||
|
if set -q argv[1]
|
||||||
|
set REPO_URL "$argv[1]"
|
||||||
|
end
|
||||||
|
|
||||||
|
set -l REPO_BRANCH "main"
|
||||||
|
set -l FISH_CONFIG_DIR "$HOME/.config/fish"
|
||||||
|
|
||||||
|
# ANSI colour codes for pretty output.
|
||||||
|
set -l RST (set_color normal)
|
||||||
|
set -l GRN (set_color green)
|
||||||
|
set -l YLW (set_color yellow)
|
||||||
|
set -l RED (set_color red)
|
||||||
|
set -l BOLD (set_color --bold)
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# Helper: print a formatted step header
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function _step -d "Print a step header"
|
||||||
|
echo ""
|
||||||
|
echo (set_color --bold)"[$argv[1]]$RST $argv[2..]"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# 1. Prerequisites check
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "$BOLD━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$RST"
|
||||||
|
echo "$BOLD Dotfiles Installer$RST"
|
||||||
|
echo "$BOLD━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$RST"
|
||||||
|
|
||||||
|
_step "1/5" "Checking prerequisites ..."
|
||||||
|
|
||||||
|
# Fish itself — we're running in it, but just in case.
|
||||||
|
if not set -q FISH_VERSION
|
||||||
|
echo "$RED ERROR: Fish shell is required but not running.$RST"
|
||||||
|
echo " Install fish and re-run this script."
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
echo "$GRN ✓$RST Fish $FISH_VERSION"
|
||||||
|
|
||||||
|
# Git
|
||||||
|
if not command -v git &>/dev/null
|
||||||
|
echo "$RED ERROR: Git is required but not installed.$RST"
|
||||||
|
echo " Install it with your package manager, then re-run."
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
echo "$GRN ✓$RST Git "(git --version | cut -d' ' -f3)
|
||||||
|
|
||||||
|
# Optional but nice-to-have tools
|
||||||
|
for tool in tmux starship
|
||||||
|
if command -v $tool &>/dev/null
|
||||||
|
echo " ⬡ $tool detected (templates available)"
|
||||||
|
else
|
||||||
|
echo " ⬡ $tool not found (optional — templates exist but are skipped)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# 2. Fetch the repository
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
_step "2/5" "Fetching dotfiles from $REPO_URL ..."
|
||||||
|
|
||||||
|
set -l tmpdir (mktemp -d)
|
||||||
|
|
||||||
|
if command git clone --branch "$REPO_BRANCH" "$REPO_URL" "$tmpdir" 2>/dev/null
|
||||||
|
echo "$GRN ✓$RST Repository cloned."
|
||||||
|
else
|
||||||
|
# Clone failed — the repo might not exist yet, or this is a first install.
|
||||||
|
# Print the error and let the user decide.
|
||||||
|
echo "$YLW ⚠ Clone failed.$RST"
|
||||||
|
echo " This might mean:"
|
||||||
|
echo " - The repository doesn't exist yet"
|
||||||
|
echo " - SSH key is not loaded (ssh-add -l)"
|
||||||
|
echo " - No network access"
|
||||||
|
echo ""
|
||||||
|
echo " Attempting alternative clone (HTTPS fallback) ..."
|
||||||
|
|
||||||
|
# Try HTTPS fallback.
|
||||||
|
set -l https_url (string replace "git@gitssh.toomuchtaco.net:" "https://git.toomuchtaco.net/" "$REPO_URL" | string replace ".git" "")
|
||||||
|
if command git clone --branch "$REPO_BRANCH" "$https_url" "$tmpdir" 2>/dev/null
|
||||||
|
echo "$GRN ✓$RST Repository cloned via HTTPS."
|
||||||
|
else
|
||||||
|
echo "$RED ERROR: All clone methods failed.$RST"
|
||||||
|
echo " Manually clone the repo and re-run this script:"
|
||||||
|
echo " git clone $REPO_URL $FISH_CONFIG_DIR"
|
||||||
|
command rm -rf "$tmpdir"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# 3. Install files into ~/.config/fish/
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
_step "3/5" "Installing files to $FISH_CONFIG_DIR ..."
|
||||||
|
|
||||||
|
# Ensure the config directory exists.
|
||||||
|
mkdir -p "$FISH_CONFIG_DIR"
|
||||||
|
|
||||||
|
# Back up any existing config before overwriting.
|
||||||
|
set -l backup_dir "$HOME/.config/fish.backup."(date +%s)
|
||||||
|
if test -d "$FISH_CONFIG_DIR"
|
||||||
|
and not test -L "$FISH_CONFIG_DIR"
|
||||||
|
and count "$FISH_CONFIG_DIR"/* &>/dev/null
|
||||||
|
command cp -r "$FISH_CONFIG_DIR" "$backup_dir"
|
||||||
|
echo " Existing config backed up to $backup_dir"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Copy the repo contents into place.
|
||||||
|
# The repo is expected to have this structure:
|
||||||
|
# install.fish (this script — at repo root)
|
||||||
|
# .config/fish/ (the fish config directory)
|
||||||
|
command cp -r "$tmpdir/.config/fish/." "$FISH_CONFIG_DIR/"
|
||||||
|
|
||||||
|
# Also copy the install script itself and README to the config dir for
|
||||||
|
# future reference.
|
||||||
|
command cp "$tmpdir/install.fish" "$FISH_CONFIG_DIR/install.fish" 2>/dev/null
|
||||||
|
if test -f "$tmpdir/README.md"
|
||||||
|
command cp "$tmpdir/README.md" "$FISH_CONFIG_DIR/README.md"
|
||||||
|
end
|
||||||
|
|
||||||
|
echo "$GRN ✓$RST Files installed."
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# 4. Initialise managed dotfiles
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
_step "4/5" "Initialising managed dotfiles (~/.tmux.conf, ~/.gitconfig, ...) ..."
|
||||||
|
|
||||||
|
# Source the newly installed config so the `dotfiles` function is available.
|
||||||
|
source "$FISH_CONFIG_DIR/config.fish"
|
||||||
|
|
||||||
|
# Load the dotfiles function file explicitly (auto-load won't fire until
|
||||||
|
# the function is first called in a non-sourced context).
|
||||||
|
if test -f "$FISH_CONFIG_DIR/functions/dotfiles.fish"
|
||||||
|
source "$FISH_CONFIG_DIR/functions/dotfiles.fish"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Persist the repo URL so `dotfiles publish` and `dotfiles sync` work.
|
||||||
|
if test -n "$REPO_URL"
|
||||||
|
dotfiles repo "$REPO_URL" 2>/dev/null
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run init for every managed template.
|
||||||
|
dotfiles init
|
||||||
|
|
||||||
|
echo "$GRN ✓$RST Dotfiles initialised."
|
||||||
|
echo ""
|
||||||
|
echo " Installed templates:"
|
||||||
|
for f in (find "$DOTFILES_DIR" -type f | sort)
|
||||||
|
set -l name (string replace "$DOTFILES_DIR/" "" "$f")
|
||||||
|
echo " $(set_color green)•$(set_color normal) ~/.$name"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
# 5. Done — print next steps
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
_step "5/5" "Cleaning up ..."
|
||||||
|
command rm -rf "$tmpdir"
|
||||||
|
echo "$GRN ✓$RST Done."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "$BOLD━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$RST"
|
||||||
|
echo "$GRN Installation complete!$RST"
|
||||||
|
echo "$BOLD━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$RST"
|
||||||
|
echo ""
|
||||||
|
echo " $YLW""Next steps:$RST"
|
||||||
|
echo ""
|
||||||
|
echo " 1. Start a new fish shell or run: exec fish"
|
||||||
|
echo " 2. Check status of managed files: dotfiles status"
|
||||||
|
echo " 3. Edit a dotfile: dotfiles edit tmux"
|
||||||
|
echo " 4. Pull remote updates: dotfiles sync"
|
||||||
|
echo " 5. Push your changes: dotfiles publish"
|
||||||
|
echo ""
|
||||||
|
echo " $YLW""New to the dotfiles system?$RST"
|
||||||
|
echo " dotfiles help"
|
||||||
|
echo ""
|
||||||
|
echo " $YLW""Need to set your Git identity?$RST"
|
||||||
|
echo " dotfiles edit gitconfig"
|
||||||
|
echo " # Change the [user] section, then: dotfiles update gitconfig"
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user