;; ;; util-git.scm ;; ;; Support for simple git integration. ;; ;; ISC License ;; ;; Copyright 2023 Brmlab, z.s. ;; Dominik Pantůček ;; ;; Permission to use, copy, modify, and/or distribute this software ;; for any purpose with or without fee is hereby granted, provided ;; that the above copyright notice and this permission notice appear ;; in all copies. ;; ;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL ;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED ;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE ;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR ;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS ;; OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, ;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ;; (declare (unit util-git)) (module util-git ( git git-status ) (import scheme (chicken base) util-io util-dict-list) ;; Valid git operating modes (define git-modes '((#:exit exit) (#:output output) (#:exit+output exit+output))) ;; Used for actual invocation of git binary, returns two values: exit ;; code and output lines (define (invoke-git repo args) (apply get-process-exit+output-lines "git" "-C" repo args)) ;; Curried git repo command wrapper (define (git repo . defargs) (let ((defmode (if (null? defargs) 'output ;; Raises an error if not valid (cadr (assq (car defargs) git-modes))))) (case defmode ((exit) (lambda args (let-values (((exit-code _) (invoke-git repo args))) exit-code))) ((output) (lambda args (let-values (((_ output) (invoke-git repo args))) output))) ((exit+output) (lambda args (invoke-git repo args)))))) ;; Known status types (define git-status-types '((" M" 'modified) ("??" 'untracked))) ;; Returns a dictionary of unknown, modified, deleted and added files (define (git-status repo) (let* ((lines ((git repo) 'status '--porcelain)) (clean? (null? lines))) (let loop ((lines lines) (res (make-ldict `((clean . ,clean?))))) (if (null? lines) res (let* ((line (car lines)) (st (substring line 0 2)) (fname (substring line 4)) (status (or (assoc st git-status-types) 'unknown))) (loop (cdr lines) (ldict-set res status (cons fname (ldict-ref res status '()))))))))) )