Cleaned up the code. added some documentation.

This commit is contained in:
2026-08-13 00:33:22 +02:00
parent c556b4f452
commit a025481ae4
4 changed files with 177 additions and 73 deletions
+72 -21
View File
@@ -28,6 +28,10 @@
(define git-commands (make-hash))
;; goal: Invoke a supported Git command through the command table.
;; pre: command is a registered Git command symbol.
;; post: The selected command has processed all supplied arguments.
;; result: The command-specific result.
(define-syntax git
(syntax-rules ()
((_ command b1 ...)
@@ -51,6 +55,27 @@
(g args)
(g (cons '--porcelain args)))))
(define (status->symbol status)
(cond
((string=? status " ") 'unchanged)
((string=? status "M") 'modified)
((string=? status "T") 'type-changed)
((string=? status "A") 'added)
((string=? status "D") 'deleted)
((string=? status "R") 'renamed)
((string=? status "C") 'copied)
((string=? status "U") 'unmerged)
((string=? status "?") 'untracked)
((string=? status "!") 'ignored)
(else (error 'git-status "Unexpected status: ~a" status))))
(define (nothing-to-commit? out)
(ormap (λ (line)
(let ((line* (string-downcase line)))
(or (string-contains? line* "nothing to commit")
(string-contains? line* "no changes added to commit"))))
out))
(define-syntax def-cmd
(syntax-rules ()
@@ -68,37 +93,38 @@
)
)
;; goal: Return the complete Git index and worktree status for every reported file.
;; pre: The current directory is inside a Git working tree.
;; post: Git status has been invoked with --porcelain.
;; result: A list containing (index-status worktree-status file) for every file.
(def-cmd git-status cmd-git-status 'status
add-porcelain
(λ (cmd exit-code result output out info)
(dbg-git (format "~a" output))
(if (= exit-code 0)
(if result
(map (λ (line)
(let* ((state (string->symbol (string-trim (substring line 0 2))))
(file (string-trim (substring line 3))))
(cond
([eq? state '??] (list 'new file))
([eq? state 'M] (list 'modified file))
([eq? state 'A] (list 'added file))
([eq? state 'D] (list 'deleted file))
([eq? state 'AM] (list 'modified file))
([eq? state 'AD] (list 'deleted file))
([eq? state 'MM] (list 'modified file))
([eq? state 'MD] (list 'deleted file))
(else
(git-error 'status "Unexpected state" state))
)
))
out)
(git-error 'status "Error" output))
(map (λ (line)
(if (< (string-length line) 3)
(git-error 'status "Unexpected output" line)
(list (status->symbol (substring line 0 1))
(status->symbol (substring line 1 2))
(substring line 3))))
(map cadr
(filter (λ (entry) (eq? (car entry) 'stdout)) output)))
(git-error 'status "Exitcode <> 0" (cons (format "~a\n" exit-code) output))
))
)
;; goal: Add file contents to the Git index.
;; pre: The supplied arguments are valid for git add.
;; post: Git add has completed successfully or an exception has been raised.
;; result: #t after a successful Git command.
(def-cmd git-add cmd-git-add 'add)
;; goal: Create a Git commit.
;; pre: A commit message is supplied or can be requested from the user.
;; post: The commit was created, nothing needed committing, or an exception was raised.
;; result: #t after a commit or when the repository has nothing to commit.
(def-cmd git-commit cmd-git-commit 'commit
(λ (args info)
(with-handlers ([exn:fail? (λ (e)
@@ -109,15 +135,32 @@
(check-git-args 'commit args '((-m 1 "A commit message is mandatory")))))
(λ (cmd exit-code result output out info)
(cond
((= exit-code 1) (git-displ out) #t)
((and (= exit-code 1)
(nothing-to-commit? out))
(git-displ out)
#t)
(else
(std-process-git-result cmd exit-code result output out info))))
)
;; goal: Push local changes to a remote repository.
;; pre: The supplied arguments are valid for git push.
;; post: Git push has completed successfully or an exception has been raised.
;; result: #t after a successful push.
(def-cmd git-push cmd-git-push 'push add-porcelain)
;; goal: Fetch and integrate changes from a remote repository.
;; pre: The supplied arguments are valid for git pull.
;; post: Git pull has completed successfully or an exception has been raised.
;; result: #t after a successful pull.
(def-cmd git-pull cmd-git-pull 'pull)
(def-cmd git-branch cmd-git-branch 'branch)
(def-cmd git-clone cmd-git-clone 'clone)
;; goal: Display the Git commit log.
;; pre: The supplied arguments are valid for git log.
;; post: Git log has completed successfully or an exception has been raised.
;; result: #t after successfully displaying the log.
(def-cmd git-log cmd-git-log 'log)
(def-cmd git-rev-list cmd-git-rev-list 'rev-list)
@@ -129,6 +172,10 @@
(hash-set! git-commands 'version cmd-git-version)
;; goal: Increment the package version in info.rkt.
;; pre: kind is 'maj, 'major, 'min, 'minor or 'patch.
;; post: The version definition in info.rkt has been updated.
;; result: The new version as a list containing major, minor and patch.
(define (git-new-version . args)
(cmd-git-new-version args))
@@ -153,8 +200,12 @@
"\n")))
(diff->html diff)
#t)
#f)))
#f)))
;; goal: Search tracked files for a pattern.
;; pre: The supplied arguments are valid for git grep.
;; post: Git grep has completed; exit code one is treated as no matches.
;; result: A list containing file, line number, match count and matched text.
(def-cmd git-grep cmd-git-grep 'grep
(λ (args info)
(let ((matches #f)