Jelajahi Sumber

Expand directories with markers into per-file deploy operations

Directories in to_sync that contain files with @host/@group markers
can no longer be symlinked as a whole. Instead, the deploy loop now
walks such directories and handles each file individually: processing
marker files and symlinking the rest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
G. Capella 1 hari lalu
induk
melakukan
8656edb404
1 mengubah file dengan 82 tambahan dan 34 penghapusan
  1. 82 34
      start

+ 82 - 34
start

@@ -65,6 +65,11 @@ file_has_markers() {
     grep -qE '@(host|group) ' "$1" 2>/dev/null
 }
 
+# Check if any file in a directory tree contains markers
+dir_has_markers() {
+    grep -rqlE '@(host|group) ' "$1" 2>/dev/null
+}
+
 # Detect the comment prefix from the first marker line in a file
 detect_comment_prefix() {
     local src="$1"
@@ -302,61 +307,104 @@ sub_sync(){
         fi
     fi
 
-    # Deploy dotfiles (symlink or process markers)
-    log_info "Deploying dotfiles for $hostname_id..."
-    get_sync_list | while IFS= read -r p; do
-        local source
-        source=$(resolve_source "$p")
-        local destination="$HOME/$p"
-
-        if [[ ! -e "$source" ]]; then
-            log_warn "Source file $source does not exist, skipping"
-            continue
-        fi
+    # Deploy a single file: process markers or symlink
+    deploy_file() {
+        local src="$1"
+        local dest="$2"
 
-        mkdir -p "$(dirname "$destination")"
+        mkdir -p "$(dirname "$dest")"
 
-        if [[ -f "$source" ]] && file_has_markers "$source"; then
+        if file_has_markers "$src"; then
             # File has markers — process and write (not symlink)
-            if [[ -L "$destination" ]]; then
-                rm "$destination"
+            if [[ -L "$dest" ]]; then
+                rm "$dest"
             fi
 
             local comment_prefix
-            comment_prefix=$(detect_comment_prefix "$source")
+            comment_prefix=$(detect_comment_prefix "$src")
 
             {
                 echo "$comment_prefix DO NOT EDIT - Generated by dotsync from:"
-                echo "$comment_prefix $source"
+                echo "$comment_prefix $src"
                 echo ""
-                process_markers "$source"
-            } > "$destination.dotsync_tmp"
+                process_markers "$src"
+            } > "$dest.dotsync_tmp"
 
             # Only update if content changed
-            if [[ -f "$destination" ]] && cmp -s "$destination" "$destination.dotsync_tmp"; then
-                rm "$destination.dotsync_tmp"
+            if [[ -f "$dest" ]] && cmp -s "$dest" "$dest.dotsync_tmp"; then
+                rm "$dest.dotsync_tmp"
             else
-                [[ -e "$destination" ]] && rm "$destination"
-                mv "$destination.dotsync_tmp" "$destination"
-                chmod --reference="$source" "$destination"
-                log_info "Processed: $destination (from $source)"
+                [[ -e "$dest" ]] && rm "$dest"
+                mv "$dest.dotsync_tmp" "$dest"
+                chmod --reference="$src" "$dest"
+                log_info "Processed: $dest (from $src)"
             fi
         else
-            # No markers — symlink as before
-            if [[ -L "$destination" ]] && [[ "$(readlink "$destination")" == "$source" ]]; then
-                continue  # Already correctly linked
+            # No markers — symlink
+            if [[ -L "$dest" ]] && [[ "$(readlink "$dest")" == "$src" ]]; then
+                return  # Already correctly linked
             fi
 
-            if [[ -e "$destination" ]] || [[ -L "$destination" ]]; then
-                log_warn "Removing existing $destination"
-                rm -rf "$destination"
+            if [[ -e "$dest" ]] || [[ -L "$dest" ]]; then
+                log_warn "Removing existing $dest"
+                rm -rf "$dest"
             fi
 
-            if ln -s "$source" "$destination"; then
-                log_info "Linked: $destination -> $source"
+            if ln -s "$src" "$dest"; then
+                log_info "Linked: $dest -> $src"
+            else
+                log_error "Failed to create symlink for $(basename "$dest")"
+            fi
+        fi
+    }
+
+    # Deploy dotfiles (symlink or process markers)
+    log_info "Deploying dotfiles for $hostname_id..."
+    get_sync_list | while IFS= read -r p; do
+        local source
+        source=$(resolve_source "$p")
+        local destination="$HOME/$p"
+
+        if [[ ! -e "$source" ]]; then
+            log_warn "Source $source does not exist, skipping"
+            continue
+        fi
+
+        if [[ -d "$source" ]]; then
+            if dir_has_markers "$source"; then
+                # Directory contains markers — expand into per-file operations
+                # Remove directory-level symlink if present
+                if [[ -L "$destination" ]]; then
+                    log_warn "Replacing directory symlink $destination with expanded files"
+                    rm "$destination"
+                fi
+                mkdir -p "$destination"
+
+                # Walk all files in the source directory
+                while IFS= read -r src_file; do
+                    local rel="${src_file#"$source/"}"
+                    deploy_file "$src_file" "$destination/$rel"
+                done < <(find "$source" -type f | sort)
             else
-                log_error "Failed to create symlink for $p"
+                # No markers in directory — symlink the whole directory
+                if [[ -L "$destination" ]] && [[ "$(readlink "$destination")" == "$source" ]]; then
+                    continue  # Already correctly linked
+                fi
+
+                if [[ -e "$destination" ]] || [[ -L "$destination" ]]; then
+                    log_warn "Removing existing $destination"
+                    rm -rf "$destination"
+                fi
+
+                if ln -s "$source" "$destination"; then
+                    log_info "Linked: $destination -> $source"
+                else
+                    log_error "Failed to create symlink for $p"
+                fi
             fi
+        else
+            # Single file entry
+            deploy_file "$source" "$destination"
         fi
     done