diff --git a/README.md b/README.md index e91a389..a0b89f9 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,17 @@ Most are also exported as direct procedures such as `git-status`, `git-add`, `git-fetch`, `git-switch`, `git-tag`, `git-log`, `git-diff`, and `git-show`. See the Scribble documentation for command-specific behavior and return values. + +## Low-level Git execution + +`run-git` can be used when direct access to Git's stdin/stdout protocol is +needed. Optional text can be supplied to Git with `#:input`. + +```racket +(run-git '(credential fill) + #:input "protocol=https\nhost=git.dijkewijk.nl\n\n") +``` + +The result remains two values: Git's exit code and the ordered +`(source line)` output items. + diff --git a/private/git-provider.rkt b/private/git-provider.rkt index dc054bf..6ae4e22 100644 --- a/private/git-provider.rkt +++ b/private/git-provider.rkt @@ -88,11 +88,13 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goal : Run Git without allowing interactive terminal prompts. -; pre : args contains the Git command and its arguments. -; post : Standard output and error have been read completely. +; pre : args contains the Git command and its arguments; input is #f or a string +; that must be written to Git's standard input. +; post : Optional input has been written and standard output and error have been +; read completely. ; result : The exit code and ordered (source line) output items. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define (run-git args) +(define (run-git args #:input (input #f)) (putenv "GIT_TERMINAL_PROMPT" "0") (let-values (((process stdout stdin stderr) (apply subprocess @@ -102,6 +104,9 @@ (git-exe) (map (λ (arg) (format "~a" arg)) args) ))) + (when input + (display input stdin) + (flush-output stdin)) (close-output-port stdin) (let ((output-channel (make-channel))) (define (read-output source port) diff --git a/scribblings/git.scrbl b/scribblings/git.scrbl index 8982684..1a02dfa 100644 --- a/scribblings/git.scrbl +++ b/scribblings/git.scrbl @@ -251,3 +251,21 @@ Updates the version in @filepath{info.rkt}. The kind is @racket['major], @racket['minor], or @racket['patch], with @racket['maj] and @racket['min] as abbreviations. The result is the new version as a list of three integers. } + + +@section{Low-level Git execution} + +@defproc[(run-git [args list?] + [#:input input (or/c #f string?) #f]) + (values exact-integer? list?)]{ +Runs Git without interactive terminal prompts. When @racket[input] is a string, +it is written to Git's standard input before that input port is closed. + +The procedure returns two values: Git's exit code and the ordered output items, +where each item identifies either @racket['stdout] or @racket['stderr]. + +@racketblock[ +(run-git '(credential fill) + #:input "protocol=https\nhost=git.dijkewijk.nl\n\n") +] +}