diff options
| author | srdusr <trevorgray@srdusr.com> | 2025-09-24 06:44:45 +0200 |
|---|---|---|
| committer | srdusr <trevorgray@srdusr.com> | 2025-09-24 06:44:45 +0200 |
| commit | cf3dd258e0ab3a366960a5e4c8c08f13613f36da (patch) | |
| tree | 90b62ea927075a9744d8b5b6d7053884901a9905 | |
| parent | 5e3107a9e3c4bdd87a6cdbd3d7277883e97e5c3d (diff) | |
| download | dotfiles-cf3dd258e0ab3a366960a5e4c8c08f13613f36da.tar.gz dotfiles-cf3dd258e0ab3a366960a5e4c8c08f13613f36da.zip | |
config command now supports common/scripts
| -rw-r--r-- | README.md | 109 | ||||
| -rw-r--r-- | common/config/zsh/user/functions.zsh | 78 | ||||
| -rwxr-xr-x | common/install.sh | 107 |
3 files changed, 133 insertions, 161 deletions
@@ -114,7 +114,7 @@ Copy and paste the following snippet to any profile/startup file ie. `~/.bashrc` ```bash # Dotfiles Management System if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then - # Core git wrapper with repository as work-tree + # Core git wrapper - .cfg is bare repo, work-tree points to .cfg itself _config() { git --git-dir="$HOME/.cfg" --work-tree="$HOME/.cfg" "$@" } @@ -163,7 +163,9 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi case "$repo_path" in - # Common configs → OS-specific config dirs + common/scripts/*) + echo "$HOME/.scripts/${repo_path#common/scripts/}" + ;; common/config/*) case "$CFG_OS" in linux) @@ -174,6 +176,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then echo "$HOME/Library/Application Support/${repo_path#common/config/}" ;; windows) + # Windows Bash (Git Bash, MSYS, WSL) respects LOCALAPPDATA echo "$LOCALAPPDATA\\${repo_path#common/config/}" ;; *) @@ -181,32 +184,18 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then ;; esac ;; - - # Common assets → stay in repo - common/assets/*) + common/assets/*|profile/*|README.md) echo "$HOME/.cfg/$repo_path" ;; - - # Other common files (dotfiles like .bashrc, .gitconfig, etc.) → $HOME common/*) - echo "$HOME/${repo_path#common/}" + echo "$HOME/.cfg/$repo_path" ;; - - # OS-specific home */home/*) echo "$HOME/${repo_path#*/home/}" ;; - - # Profile configs and README → stay in repo - profile/*|README.md) + *) echo "$HOME/.cfg/$repo_path" ;; - - # Default fallback - *) - echo "$HOME/.cfg/$repo_path" - ;; - esac } @@ -232,6 +221,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then config() { local cmd="$1"; shift local target_dir="" + # Parse optional --target flag for add if [[ "$cmd" == "add" ]]; then while [[ "$1" == --* ]]; do @@ -251,7 +241,29 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then case "$cmd" in add) local file_path - for file_path in "$@"; do + local git_opts=() + local files=() + + # Parse arguments + while [[ $# -gt 0 ]]; do + case "$1" in + --target|-t) + target_dir="$2" + shift 2 + ;; + -*) # Any other flags are git flags + git_opts+=("$1") + shift + ;; + *) # Anything else is a file + files+=("$1") + shift + ;; + esac + done + + # Process each file + for file_path in "${files[@]}"; do local repo_path if [[ -n "$target_dir" ]]; then local rel_path @@ -269,11 +281,13 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then mkdir -p "$(dirname "$full_repo_path")" cp -a "$file_path" "$full_repo_path" - git --git-dir="$HOME/.cfg" --work-tree="$HOME/.cfg" add "$repo_path" + # Only git flags + repo_path go to git + _config add "${git_opts[@]}" "$repo_path" echo "Added: $file_path -> $repo_path" done ;; + rm) local rm_opts="" local file_path_list=() @@ -299,11 +313,13 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then echo "Removed: $file_path" done ;; + sync) local direction="${1:-to-repo}"; shift _config ls-files | while read -r repo_file; do local sys_file="$(_sys_path "$repo_file")" local full_repo_path="$HOME/.cfg/$repo_file" + if [[ "$direction" == "to-repo" ]]; then if [[ -e "$sys_file" && -n "$(diff "$full_repo_path" "$sys_file" 2>/dev/null || echo "diff")" ]]; then cp -a "$sys_file" "$full_repo_path" @@ -324,18 +340,36 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi done ;; + status) + # Check for missing files and auto-sync existing ones local auto_synced=() + local missing_files=() + while read -r repo_file; do local sys_file="$(_sys_path "$repo_file")" local full_repo_path="$HOME/.cfg/$repo_file" - if [[ -e "$sys_file" && -e "$full_repo_path" ]]; then + + if [[ ! -e "$full_repo_path" ]]; then + missing_files+=("$repo_file") + elif [[ -e "$sys_file" ]]; then if ! diff -q "$full_repo_path" "$sys_file" >/dev/null 2>&1; then cp -fa "$sys_file" "$full_repo_path" auto_synced+=("$repo_file") fi fi done < <(_config ls-files) + + # Report missing files + if [[ ${#missing_files[@]} -gt 0 ]]; then + echo "=== Missing Files (consider removing from git) ===" + for repo_file in "${missing_files[@]}"; do + echo "missing: $repo_file" + done + echo + fi + + # Report auto-synced files if [[ ${#auto_synced[@]} -gt 0 ]]; then echo "=== Auto-synced Files ===" for repo_file in "${auto_synced[@]}"; do @@ -343,13 +377,15 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then done echo fi + _config status - echo ;; - deploy) + + deploy|checkout) + echo "Deploying dotfiles from .cfg..." _config ls-files | while read -r repo_file; do local full_repo_path="$HOME/.cfg/$repo_file" - local sys_file="$(_sys_path "$repo_file")" # destination only + local sys_file="$(_sys_path "$repo_file")" # Only continue if the source exists if [[ -e "$full_repo_path" && -n "$sys_file" ]]; then @@ -369,29 +405,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi done ;; - checkout) - echo "Checking out dotfiles from .cfg..." - _config ls-files | while read -r repo_file; do - local full_repo_path="$HOME/.cfg/$repo_file" - local sys_file="$(_sys_path "$repo_file")" - - if [[ -e "$full_repo_path" && -n "$sys_file" ]]; then - local dest_dir - dest_dir="$(dirname "$sys_file")" - # Create destination if it doesn't exist - if [[ "$sys_file" == /* && "$sys_file" != "$HOME/"* ]]; then - _sudo_prompt mkdir -p "$dest_dir" - _sudo_prompt cp -a "$full_repo_path" "$sys_file" - else - mkdir -p "$dest_dir" - cp -a "$full_repo_path" "$sys_file" - fi - - echo "Checked out: $repo_file -> $sys_file" - fi - done - ;; backup) local timestamp=$(date +%Y%m%d%H%M%S) local backup_dir="$HOME/.dotfiles_backup/$timestamp" @@ -407,6 +421,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then done echo "Backup complete. To restore, copy files from $backup_dir to their original locations." ;; + *) _config "$cmd" "$@" ;; diff --git a/common/config/zsh/user/functions.zsh b/common/config/zsh/user/functions.zsh index b4fa1c3..7c79ee5 100644 --- a/common/config/zsh/user/functions.zsh +++ b/common/config/zsh/user/functions.zsh @@ -1,6 +1,5 @@ # Dotfiles Management System if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then - # Core git wrapper - .cfg is bare repo, work-tree points to .cfg itself _config() { git --git-dir="$HOME/.cfg" --work-tree="$HOME/.cfg" "$@" @@ -18,13 +17,13 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then _repo_path() { local f="$1" - # Absolute paths outside HOME + # If it's an absolute path that's not in HOME, handle it specially if [[ "$f" == /* && "$f" != "$HOME/"* ]]; then echo "$CFG_OS/${f#/}" return fi - # Files already in repo structure + # Check for paths that should go to the repository root case "$f" in common/*|linux/*|macos/*|windows/*|profile/*|README.md) echo "$f" @@ -35,12 +34,19 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then ;; esac - # Default: OS-specific home + # Default: put under OS-specific home echo "$CFG_OS/home/$f" } _sys_path() { local repo_path="$1" + local os_path_pattern="$CFG_OS/" + + # Handle OS-specific files that are not in the home subdirectory + if [[ "$repo_path" == "$os_path_pattern"* && "$repo_path" != */home/* ]]; then + echo "/${repo_path#$os_path_pattern}" + return + fi case "$repo_path" in common/scripts/*) @@ -261,70 +267,6 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then _config status ;; - clean-missing) - echo "Removing missing files from git index..." - local removed_count=0 - while read -r repo_file; do - local full_repo_path="$HOME/.cfg/$repo_file" - if [[ ! -e "$full_repo_path" ]]; then - _config rm --cached "$repo_file" - echo "Removed from git: $repo_file" - ((removed_count++)) - fi - done < <(_config ls-files) - echo "Removed $removed_count missing files from git index." - ;; - - move-files) - # Move files from one path pattern to another in the repository - local from_pattern="$1" - local to_pattern="$2" - - if [[ -z "$from_pattern" || -z "$to_pattern" ]]; then - echo "Usage: config move-files <from_pattern> <to_pattern>" - echo "Example: config move-files 'common/nvim' 'common/config/nvim'" - return 1 - fi - - echo "Moving files from $from_pattern to $to_pattern..." - local moved_count=0 - - # Find all files matching the from_pattern - _config ls-files | grep "^$from_pattern/" | while read -r repo_file; do - local new_repo_file="${repo_file/$from_pattern/$to_pattern}" - local old_full_path="$HOME/.cfg/$repo_file" - local new_full_path="$HOME/.cfg/$new_repo_file" - - # Create destination directory - mkdir -p "$(dirname "$new_full_path")" - - # Move the file in the filesystem if it exists - if [[ -e "$old_full_path" ]]; then - mv "$old_full_path" "$new_full_path" - echo "Moved: $repo_file -> $new_repo_file" - else - # File doesn't exist, but we still need to update git index - # Try to get it from the system location first - local sys_file="$(_sys_path "$repo_file")" - if [[ -e "$sys_file" ]]; then - cp -a "$sys_file" "$new_full_path" - echo "Copied from system: $sys_file -> $new_repo_file" - else - echo "Warning: Neither repo nor system file exists for $repo_file" - continue - fi - fi - - # Update git index - _config rm --cached "$repo_file" 2>/dev/null || true - _config add "$new_repo_file" - - ((moved_count++)) - done - - echo "Moved $moved_count files from $from_pattern to $to_pattern" - ;; - deploy|checkout) echo "Deploying dotfiles from .cfg..." _config ls-files | while read -r repo_file; do diff --git a/common/install.sh b/common/install.sh index 4a2b209..0fd7993 100755 --- a/common/install.sh +++ b/common/install.sh @@ -1277,7 +1277,7 @@ install_config_command() { # Dotfiles Management System if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then - # Core git wrapper with repository as work-tree + # Core git wrapper - .cfg is bare repo, work-tree points to .cfg itself _config() { git --git-dir="$HOME/.cfg" --work-tree="$HOME/.cfg" "$@" } @@ -1326,7 +1326,9 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi case "$repo_path" in - # Common configs → OS-specific config dirs + common/scripts/*) + echo "$HOME/.scripts/${repo_path#common/scripts/}" + ;; common/config/*) case "$CFG_OS" in linux) @@ -1337,6 +1339,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then echo "$HOME/Library/Application Support/${repo_path#common/config/}" ;; windows) + # Windows Bash (Git Bash, MSYS, WSL) respects LOCALAPPDATA echo "$LOCALAPPDATA\\${repo_path#common/config/}" ;; *) @@ -1344,32 +1347,18 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then ;; esac ;; - - # Common assets → stay in repo - common/assets/*) + common/assets/*|profile/*|README.md) echo "$HOME/.cfg/$repo_path" ;; - - # Other common files (dotfiles like .bashrc, .gitconfig, etc.) → $HOME common/*) - echo "$HOME/${repo_path#common/}" + echo "$HOME/.cfg/$repo_path" ;; - - # OS-specific home */home/*) echo "$HOME/${repo_path#*/home/}" ;; - - # Profile configs and README → stay in repo - profile/*|README.md) + *) echo "$HOME/.cfg/$repo_path" ;; - - # Default fallback - *) - echo "$HOME/.cfg/$repo_path" - ;; - esac } @@ -1415,7 +1404,29 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then case "$cmd" in add) local file_path - for file_path in "$@"; do + local git_opts=() + local files=() + + # Parse arguments + while [[ $# -gt 0 ]]; do + case "$1" in + --target|-t) + target_dir="$2" + shift 2 + ;; + -*) # Any other flags are git flags + git_opts+=("$1") + shift + ;; + *) # Anything else is a file + files+=("$1") + shift + ;; + esac + done + + # Process each file + for file_path in "${files[@]}"; do local repo_path if [[ -n "$target_dir" ]]; then local rel_path @@ -1433,11 +1444,13 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then mkdir -p "$(dirname "$full_repo_path")" cp -a "$file_path" "$full_repo_path" - git --git-dir="$HOME/.cfg" --work-tree="$HOME/.cfg" add "$repo_path" + # Only git flags + repo_path go to git + _config add "${git_opts[@]}" "$repo_path" echo "Added: $file_path -> $repo_path" done ;; + rm) local rm_opts="" local file_path_list=() @@ -1463,11 +1476,13 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then echo "Removed: $file_path" done ;; + sync) local direction="${1:-to-repo}"; shift _config ls-files | while read -r repo_file; do local sys_file="$(_sys_path "$repo_file")" local full_repo_path="$HOME/.cfg/$repo_file" + if [[ "$direction" == "to-repo" ]]; then if [[ -e "$sys_file" && -n "$(diff "$full_repo_path" "$sys_file" 2>/dev/null || echo "diff")" ]]; then cp -a "$sys_file" "$full_repo_path" @@ -1488,18 +1503,36 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi done ;; + status) + # Check for missing files and auto-sync existing ones local auto_synced=() + local missing_files=() + while read -r repo_file; do local sys_file="$(_sys_path "$repo_file")" local full_repo_path="$HOME/.cfg/$repo_file" - if [[ -e "$sys_file" && -e "$full_repo_path" ]]; then + + if [[ ! -e "$full_repo_path" ]]; then + missing_files+=("$repo_file") + elif [[ -e "$sys_file" ]]; then if ! diff -q "$full_repo_path" "$sys_file" >/dev/null 2>&1; then cp -fa "$sys_file" "$full_repo_path" auto_synced+=("$repo_file") fi fi done < <(_config ls-files) + + # Report missing files + if [[ ${#missing_files[@]} -gt 0 ]]; then + echo "=== Missing Files (consider removing from git) ===" + for repo_file in "${missing_files[@]}"; do + echo "missing: $repo_file" + done + echo + fi + + # Report auto-synced files if [[ ${#auto_synced[@]} -gt 0 ]]; then echo "=== Auto-synced Files ===" for repo_file in "${auto_synced[@]}"; do @@ -1507,14 +1540,17 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then done echo fi + _config status - echo ;; - deploy) + + deploy|checkout) + echo "Deploying dotfiles from .cfg..." _config ls-files | while read -r repo_file; do local full_repo_path="$HOME/.cfg/$repo_file" local sys_file="$(_sys_path "$repo_file")" + # Only continue if the source exists if [[ -e "$full_repo_path" && -n "$sys_file" ]]; then local dest_dir dest_dir="$(dirname "$sys_file")" @@ -1532,29 +1568,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then fi done ;; - checkout) - echo "Checking out dotfiles from .cfg..." - _config ls-files | while read -r repo_file; do - local full_repo_path="$HOME/.cfg/$repo_file" - local sys_file="$(_sys_path "$repo_file")" - - if [[ -e "$full_repo_path" && -n "$sys_file" ]]; then - local dest_dir - dest_dir="$(dirname "$sys_file")" - # Create destination if it doesn't exist - if [[ "$sys_file" == /* && "$sys_file" != "$HOME/"* ]]; then - _sudo_prompt mkdir -p "$dest_dir" - _sudo_prompt cp -a "$full_repo_path" "$sys_file" - else - mkdir -p "$dest_dir" - cp -a "$full_repo_path" "$sys_file" - fi - - echo "Checked out: $repo_file -> $sys_file" - fi - done - ;; backup) local timestamp=$(date +%Y%m%d%H%M%S) local backup_dir="$HOME/.dotfiles_backup/$timestamp" @@ -1570,6 +1584,7 @@ if [[ -d "$HOME/.cfg" && -d "$HOME/.cfg/refs" ]]; then done echo "Backup complete. To restore, copy files from $backup_dir to their original locations." ;; + *) _config "$cmd" "$@" ;; |
