Browse Source

Sync: 2025-10-25 11:33:25

Gabriel Capella 5 ngày trước cách đây
mục cha
commit
331d65ffb1
2 tập tin đã thay đổi với 188 bổ sung43 xóa
  1. 1 1
      dots/.config/fish/fish_variables
  2. 187 42
      start

+ 1 - 1
dots/.config/fish/fish_variables

@@ -30,7 +30,7 @@ SETUVAR fish_color_user:brgreen
 SETUVAR fish_color_valid_path:\x2d\x2dunderline
 SETUVAR fish_greeting:Capella
 SETUVAR fish_key_bindings:fish_vi_key_bindings
-SETUVAR fish_most_recent_dir:/home/capella/\x2econfig
+SETUVAR fish_most_recent_dir:/home/capella/\x2edofiles/dotfiles
 SETUVAR fish_pager_color_completion:\x1d
 SETUVAR fish_pager_color_description:B3A06D\x1eyellow
 SETUVAR fish_pager_color_prefix:white\x1e\x2d\x2dbold\x1e\x2d\x2dunderline

+ 187 - 42
start

@@ -1,78 +1,223 @@
 #!/bin/bash
 
+# Dotfiles sync script
+set -euo pipefail
+
+# Configuration
 checkout_dir=$HOME/.dofiles
 script_dir=$checkout_dir/dotfiles
 dots_dir=$checkout_dir/dotfiles/dots
 repo="https://git.capella.pro/capella/dotfiles.git"
+ProgName=$(basename "$0")
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
 
-set -ex
-trap popd EXIT
+# Logging functions
+log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
+log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
 
-mkdir -pv $checkout_dir
-pushd $checkout_dir
+# Ensure we cleanup on exit
+trap 'cd "$HOME"' EXIT
+
+# Create checkout directory if needed
+mkdir -p "$checkout_dir"
 
 
 sub_help(){
-    echo "Usage: $ProgName <subcommand> [options]\n"
-    echo "Subcommands:"
-    echo "    sync <dot_file_to_add>    add a dotfyle to sync"
-    echo ""
-    echo "For help with each subcommand run:"
-    echo "$ProgName <subcommand> -h|--help"
-    echo ""
+    cat << EOF
+Usage: $ProgName <subcommand> [options]
+
+Subcommands:
+    sync [dot_file_to_add]    Sync dotfiles (optionally add a new dotfile to track)
+    list                      List currently synced dotfiles
+    status                    Show git status of dotfiles repo
+
+For help with each subcommand run:
+    $ProgName <subcommand> -h|--help
+
+EOF
 }
 
 sub_sync(){
-    if [[ ! -d $checkout_dir/dotfiles/.git ]]; then
-        git clone $repo
-        pushd dotfiles
+    # Clone repo if it doesn't exist
+    if [[ ! -d "$checkout_dir/dotfiles/.git" ]]; then
+        log_info "Cloning dotfiles repository..."
+        cd "$checkout_dir"
+        if ! git clone "$repo"; then
+            log_error "Failed to clone repository"
+            exit 1
+        fi
+        cd "$script_dir"
         git submodule init
-        popd
+        git submodule update
     fi
 
-    cd $script_dir
-    git pull origin master
-    git submodule update
+    # Navigate to script directory
+    cd "$script_dir"
+
+    # Get current branch
+    current_branch=$(git branch --show-current)
+    log_info "Pulling latest changes from $current_branch..."
+    git pull origin "$current_branch" || log_warn "Git pull failed, continuing anyway"
+    git submodule update --init --recursive
+
+    # Add new dotfile if provided
+    if [ -n "${1:-}" ]; then
+        local file_to_add="$1"
+
+        # Validate that file exists
+        if [[ ! -e "$HOME/$file_to_add" ]]; then
+            log_error "File $HOME/$file_to_add does not exist"
+            exit 1
+        fi
 
-    if [ ! -z "$1" ]; then
-        real_path=$(realpath $HOME/$1)
-        to_copy=${real_path#*$HOME}
-        cp -R $real_path $dots_dir/$to_copy
-        rm -rf $real_path
-        echo "${to_copy/\//}" >> $script_dir/to_sync
+        log_info "Adding new dotfile: $file_to_add"
+
+        real_path=$(realpath "$HOME/$file_to_add")
+        to_copy=${real_path#"$HOME/"}
+
+        # Create parent directory structure in dots_dir
+        mkdir -p "$(dirname "$dots_dir/$to_copy")"
+
+        # Copy to dots directory
+        if cp -R "$real_path" "$dots_dir/$to_copy"; then
+            log_info "Copied $file_to_add to $dots_dir/$to_copy"
+        else
+            log_error "Failed to copy $file_to_add"
+            exit 1
+        fi
+
+        # Add to to_sync file if not already there
+        if ! grep -qxF "$to_copy" "$script_dir/to_sync" 2>/dev/null; then
+            echo "$to_copy" >> "$script_dir/to_sync"
+            log_info "Added $to_copy to sync list"
+        else
+            log_info "$to_copy already in sync list"
+        fi
+
+        # Remove original and create symlink
+        rm -rf "$real_path"
+        ln -s "$dots_dir/$to_copy" "$real_path"
+        log_info "Created symlink: $real_path -> $dots_dir/$to_copy"
     fi
 
-    while read p; do
+    # Add tracked files to git
+    log_info "Staging changes..."
+    while IFS= read -r p; do
+        [[ -z "$p" ]] && continue  # Skip empty lines
         file="$dots_dir/$p"
-        git add $file
-    done < $script_dir/to_sync
+        if [[ -e "$file" ]]; then
+            git add "$file"
+        else
+            log_warn "Tracked file $file does not exist"
+        fi
+    done < "$script_dir/to_sync"
+
     git add start to_sync
 
-    if git commit -am "$(date)"; then
-        git remote add origin $repo || true
-        git push -u origin master
+    # Commit and push if there are changes
+    if git diff --cached --quiet; then
+        log_info "No changes to commit"
+    else
+        log_info "Committing changes..."
+        if git commit -m "Sync: $(date '+%Y-%m-%d %H:%M:%S')"; then
+            log_info "Pushing to remote..."
+            git remote add origin "$repo" 2>/dev/null || true
+            if git push -u origin "$current_branch"; then
+                log_info "Successfully pushed changes"
+            else
+                log_error "Failed to push changes"
+                exit 1
+            fi
+        else
+            log_error "Failed to commit changes"
+            exit 1
+        fi
     fi
 
-    while read p; do
+    # Create symlinks for all tracked dotfiles
+    log_info "Creating symlinks..."
+    while IFS= read -r p; do
+        [[ -z "$p" ]] && continue  # Skip empty lines
         destination="$HOME/$p"
-        rm -rf $destination
-        ln -s "$dots_dir/$p" $destination
-    done < $script_dir/to_sync
+        source="$dots_dir/$p"
+
+        if [[ ! -e "$source" ]]; then
+            log_warn "Source file $source does not exist, skipping"
+            continue
+        fi
+
+        # Check if destination is already a correct symlink
+        if [[ -L "$destination" ]] && [[ "$(readlink "$destination")" == "$source" ]]; then
+            continue  # Already correctly linked
+        fi
+
+        # Remove destination if it exists
+        if [[ -e "$destination" ]] || [[ -L "$destination" ]]; then
+            log_warn "Removing existing $destination"
+            rm -rf "$destination"
+        fi
+
+        # Create parent directory if needed
+        mkdir -p "$(dirname "$destination")"
+
+        # Create symlink
+        if ln -s "$source" "$destination"; then
+            log_info "Linked: $destination -> $source"
+        else
+            log_error "Failed to create symlink for $p"
+        fi
+    done < "$script_dir/to_sync"
+
+    log_info "Sync complete!"
+}
+
+sub_list(){
+    if [[ ! -f "$script_dir/to_sync" ]]; then
+        log_error "No to_sync file found"
+        exit 1
+    fi
+
+    echo "Currently synced dotfiles:"
+    while IFS= read -r p; do
+        [[ -z "$p" ]] && continue
+        if [[ -L "$HOME/$p" ]]; then
+            echo "  ✓ $p"
+        else
+            echo "  ✗ $p (not linked)"
+        fi
+    done < "$script_dir/to_sync"
+}
+
+sub_status(){
+    if [[ ! -d "$script_dir/.git" ]]; then
+        log_error "Dotfiles repository not found"
+        exit 1
+    fi
+
+    cd "$script_dir"
+    log_info "Git status:"
+    git status
 }
 
 
-subcommand=$1
+subcommand=${1:-}
 case $subcommand in
     "" | "-h" | "--help")
         sub_help
         ;;
-    *)
+    sync|list|status)
         shift
-        sub_${subcommand} $@
-        if [ $? = 127 ]; then
-            echo "Error: '$subcommand' is not a known subcommand." >&2
-            echo "       Run '$ProgName --help' for a list of known subcommands." >&2
-            exit 1
-        fi
+        "sub_${subcommand}" "$@"
+        ;;
+    *)
+        log_error "'$subcommand' is not a known subcommand."
+        echo "       Run '$ProgName --help' for a list of known subcommands." >&2
+        exit 1
         ;;
 esac