;;; stash.scm --- A Guile script for moving directories and creating symlinks with conflict resolution ;;; ;;; Author: Glenn Thompson ;;; Version: 0.1.0-alpha.1 ;;; Created: 2024-12-03 ;;; Compatibility: Guile 3.0.9 ;;; Keywords: symlink, file management, conflict resolution, backup ;;; ;;; Commentary: ;;; ;;; Stash is a command-line utility written in Guile Scheme designed to facilitate the movement of directories and ;;; creation of symbolic links (symlinks) for files and directories. It allows users to specify a source directory ;;; and a target directory where the symlink should be created. The utility handles potential conflicts with existing ;;; files or directories at the target location, offering users the choice to overwrite, back up, or skip the creation of new symlinks. ;;; ;;; Main Features: ;;; - Command-line argument parsing for specifying source and target paths. ;;; - Conflict detection with interactive user resolution options (overwrite, backup, skip, or cancel). ;;; - Moving directories and creating symlinks. ;;; - Simple and interactive user interface for easy use. ;;; ;;; Usage: ;;; ;;; guile -L . stash.scm --target= --source= ;;; ;;; Replace with the directory where you want the symlink to be created, ;;; and with the path to the source directory. ;;; ;;; License: ;;; ;;; This project is licensed under the GNU General Public License v3. ;;; ;;; CODE (define-module (stash) #:use-module (ice-9 getopt-long) #:use-module (stash help) #:use-module (stash colors) #:use-module (stash log) #:use-module (stash paths) #:use-module (stash conflict) #:use-module (stash file-ops) #:use-module (stash package) #:use-module (stash tree) #:use-module (srfi srfi-1) #:use-module (srfi srfi-19)) ;;; Command-line options (define %options '((target (value #t) (single-char #\t)) (source (value #t) (single-char #\s)) (help (value #f) (single-char #\h)) (version (value #f) (single-char #\v)) (no-folding (value #f) (single-char #\n)) (simulate (value #f) (single-char #\S)) (adopt (value #f) (single-char #\a)) (restow (value #f) (single-char #\R)) (delete (value #f) (single-char #\D)))) ;;; Function to handle dot directory stashing (define (handle-dot-stash current-dir) "Handle stashing when using the '.' syntax. Uses parent as stow dir and $HOME as target." (let* ((pkg-dir (canonicalize-path current-dir)) (stow-dir (dirname pkg-dir)) (home-dir (getenv "HOME"))) (format #t "pkg-dir: ~a~%" pkg-dir) (format #t "stow-dir: ~a~%" stow-dir) (format #t "home-dir: ~a~%" home-dir) (values pkg-dir stow-dir home-dir))) ;;; Version function (define (display-version) "Display the current version of the program." (newline) (display "Stash version 0.1.0-alpha.1\n") (exit 0)) ;;; Helper function to check for version flag and display version (define (check-for-version args) "Check if --version or -v is in the arguments list." (if (or (member "--version" args) (member "-v" args)) (display-version))) ;;; Main function to handle stowing operations (define (handle-stow package options) (let* ((tree (analyze-tree package)) (simulate? (assoc-ref options 'simulate)) (no-folding? (assoc-ref options 'no-folding))) (plan-operations tree package))) ;;; Main entry point (define (main args) "Main function to parse arguments and execute the program." (setenv "GUILE_AUTO_COMPILE" "0") (let* ((options (getopt-long args %options)) (source-dir (assoc-ref options 'source)) (target-dir (assoc-ref options 'target)) (non-option-args (option-ref options '() '()))) (cond ((assoc-ref options 'help) (display-help)) ((assoc-ref options 'version) (display-version)) ;; Handle "stash ." syntax ((and (= (length non-option-args) 1) (string=? (car non-option-args) ".")) (call-with-values (lambda () (handle-dot-stash (getcwd))) (lambda (pkg-dir stow-dir home-dir) (let ((package (make-package (basename pkg-dir) pkg-dir home-dir (read-ignore-patterns pkg-dir)))) (handle-stow package options))))) ;; Handle traditional --source --target syntax ((not (and target-dir source-dir)) (display (color-message "Error: Either use '.' in a package directory or provide both --source and --target arguments.\n" red-text)) (display (color-message "Usage: stash.scm [--target --source ] | [.]\n" yellow-text)) (exit 1)) (else (let* ((expanded-source (expand-home source-dir)) (expanded-target (expand-home target-dir)) (package (make-package (basename expanded-source) expanded-source expanded-target (read-ignore-patterns expanded-source)))) (handle-stow package options)))))) ;; Entry point for stash (main (command-line))