config

A simple configuration manager

Commit
bfac06a2e3be00a20e27ceb18b6b2aeea50b66a4
Parent
6bd2d814484ca232abf5731e850cc7949cc3a543
Author
Pablo <pablo-escobar@riseup.net>
Date

Implemented functionality to allow the user to only commit specific files

Renamed the 'add' command to 'track'

Moved the functionality of the 'rm' command to the 'track' under a flag (-d|--delete)

Implemented the new 'add' command (analogous to git-add but it checks if the file is tracked or not)

Renamed the 'update' command to 'push'

Removed the functionality to automatically commit changes from the 'push' command

Diffstat

1 file changed, 90 insertions, 77 deletions

Status File Name N° Changes Insertions Deletions
Modified config 167 90 77
diff --git a/config b/config
@@ -10,6 +10,22 @@
 # 2021 (C) Pablo
 # Free use of this software is granted under the terms of the GPL-3.0 License
 
+print_files() 
+{
+  IFS='' read -r file
+
+  if ! [ -z "$file" ]
+  then
+    printf '\033[0;%sm%s files:\033[0m\n' "$2" "$1"
+    while true
+    do
+      printf '\033[0;%sm%s\033[0m\n' "$2" "$file"
+      IFS='' read -r file
+      [ -z "$file" ] && break
+    done
+  fi
+}
+
 # Get the path to the git repository that should be used for storing stuff
 if [ -n "$DOTFILES_REPO" ]
 then
@@ -39,47 +55,46 @@ call_git()
   git --git-dir="$dotfiles_repo" --work-tree="$HOME" "$@"
 }
 
-# Parse the commands
-case "$1" in
-  # Commit and push updates to all remotes
-  update)
-    # Add the relevant files to the repo
-    xargs git --git-dir="$dotfiles_repo" --work-tree="$HOME" add \
-      < "$dotfiles_list"
+# Given a path, print the files and directories matching this path that are
+# included in the list of dotfiles
+get_pathspec()
+{
+  path="$1"
 
-    shift
+  if [ -f "$path" ]
+  then
+    tmp_path="$(realpath "$path")"
 
-    case "$1" in
-      # Edit the commit message from a file
-      -e|--edit|'')
-        # Create a temporary file to store the commit message
-        commit_msg_file="$(mktemp)"
-        touch "$commit_msg_file"
-
-        # Open the editor and edit the message
-        $EDITOR "$commit_msg_file" 
-        if call_git commit -F "$commit_msg_file" 
-        then
-          # Remove the temporary file
-          rm "$commit_msg_file"
-        else
-          # Remove the temporary file and exit with an error
-          rm "$commit_msg_file"
-          exit 1
-        fi
-        ;;
+    # Check if the file is contained in any of the directories listed in the
+    # dotfiles list are the parents of path. If this is the case, print path
+    while [ "$tmp_path" != '/' ]
+    do
+      if grep -Fx "$tmp_path" "$dotfiles_list" > /dev/null
+      then
+        echo "$path"
+        return
+      fi
 
-      # Use to commit messages specified with -m
-      -m)
-        call_git commit "$@" || exit $?
-        ;;
+      tmp_path="$(dirname "$tmp_path")"
+    done
+  elif [ -d "$path" ]
+  then
+    # Print all of the files and directories from the list of dotfiles
+    # contained in path
 
-      # Print an error message and exit with an error
-      *)
-        printf "Unknown option: '%s'\nSee config(1)\n" "$1"
-        exit 1
-        ;;
-    esac
+    # TODO: The regex should only math occurances of path starting at the
+    # beggining of the line
+    grep -F "$(realpath "$path")" "$dotfiles_list"
+  fi
+
+  # TODO: Print a warning if we get to here: No such file or directory
+}
+
+# Parse the commands
+case "$1" in
+  # Push the changes to all of the available remotes
+  push)
+    shift
 
     # Push the changes to all remotes
     for remote in "$(call_git remote -v | awk '/(push)/ { print $1 }' | uniq)"
@@ -90,33 +105,44 @@ case "$1" in
     ;;
 
   # Add files to the list of files
-  add)
+  track)
     shift
 
-    # Add files to the list of dotfiles
-    for item in "$@"
-    do
-      echo "Adding '$item' to the list of dotfiles"
-      realpath "$item" >> "$dotfiles_list"
-      call_git add "$item"
-    done
+    case "$1" in
+      # Remove files from the list of dotfiles
+      -d|--delete)
+        shift
+
+        # Remove files from the list of dotfiles
+        for item in "$@"
+        do
+          echo "Removing '$item' from the list of dotfile"
+          pattern="$(realpath "$item")"
+          pattern="${pattern//\//\\\/}"
+
+          # Remove the files from the git repository and from the list of files
+          # Awk is used because 'item' may be a directory
+          awk -i inplace "!/^$pattern/ { print }" "$dotfiles_list"
+          call_git rm "$item" --cached -r
+        done
+        ;;
+      *)
+        # Add files to the list of dotfiles
+        for item in "$@"
+        do
+          echo "Adding '$item' to the list of dotfiles"
+          realpath "$item" >> "$dotfiles_list"
+        done
+        ;;
+    esac
     ;;
 
-  # Remove files from the list of dotfiles
-  rm)
+  # Add the files
+  add)
     shift
-
-    # Remove files from the list of dotfiles
     for item in "$@"
     do
-      echo "Removing '$item' from the list of dotfile"
-      pattern="$(realpath "$item")"
-      pattern="${pattern//\//\\\/}"
-
-      # Remove the files from the git repository and from the list of files
-      # Awk is used because 'item' may be a directory
-      awk -i inplace "!/^$pattern/ { print }" "$dotfiles_list"
-      call_git rm "$item" --cached -r
+      get_pathspec "$item" | call_git add --pathspec-from-file -
     done
     ;;
 
@@ -127,26 +153,13 @@ case "$1" in
 
   # Show the configuration files that have been modified or deleted
   status)
-    config_git_status="$(mktemp)"
-    call_git status > "$config_git_status"
-
-    if grep modified "$config_git_status" > /dev/null;
-    then
-      printf '\033[0;33mmodified files:\033[0m\n'
-      awk '/modified/ { print $2 }' "$config_git_status" \
-        | xargs -r realpath \
-        | xargs -r -n 1 printf '\033[0;33m    %s\033[0m\n'
-    fi
-
-    if grep deleted "$config_git_status" > /dev/null;
-    then
-      printf '\033[0;31mdeleted files:\033[0m\n'
-      awk '/deleted/ { print $2 }' "$config_git_status" \
-        | xargs -r realpath \
-        | xargs -r -n 1 printf '\033[0;31m    %s\033[0m\n'
-    fi
-
-    rm "$config_git_status"
+    call_git status --porcelain \
+      | awk '/^M / { print "✔️  ~/"$2 }; /^ M/ { print "   ~/"$2 }' \
+      | print_files 'modified' '33'
+
+    call_git status --porcelain \
+      | awk '/^D / { print "✔️  ~/"$2 }; /^ D/ { print "   ~/"$2 }' \
+      | print_files 'deleted' '31'
     ;;
 
   # Just pass the following arguments to git