git-cli
| (require git-cli) | package: git-cli |
The git-cli module provides a command-line-like Git interface implemented by invoking the git executable. Commands do not allow Git to read credentials or other answers from the terminal.
1 Command interface
syntax
(git command argument ...)
Most registered commands invoke the Git command with the same name. Some commands process the result into a Racket value, such as 'status, 'grep, 'log with –list, 'version, and 'new-version.
syntax
(git* command argument ...)
(git* remote -v) (git* switch main)
An argument written as (eval expression) is evaluated instead of being converted from its literal syntax.
(define branch "develop") (git* switch (eval branch))
gt is retained as a compatibility alias for git*.
2 Provided commands
procedure
(git-status argument ...) → list?
argument : any/c
Each result item has the form (index-status worktree-status file). The index status describes the change staged for the next commit. The worktree status describes the change in the working tree relative to the index.
Both statuses are one of 'unchanged, 'modified, 'type-changed, 'added, 'deleted, 'renamed, 'copied, 'unmerged, 'untracked, or 'ignored. For an untracked file, Git reports ??, so both statuses are 'untracked.
'((modified unchanged "staged.rkt") (unchanged modified "working-tree.rkt") (modified modified "both.rkt") (renamed unchanged "old.rkt -> new.rkt") (untracked untracked "new.rkt"))
procedure
(git-commit argument ...) → boolean?
argument : any/c
For example:
(git-fetch) (git-fetch '--prune) (git 'fetch '--prune)
procedure
(git-config argument ...) → any/c
argument : any/c
(git 'config '--all) (git 'config 'get '--all) (git 'config '--global 'get '--all) (git 'config 'get '--global '--all)
returns all visible configuration entries as key/value items:
'(("user.name" "Hans Dijkema") ("user.email" "hans@example.invalid") ("credential.helper" "manager"))
(git 'config 'get "credential.helper")
returns one value as a string, or #f when the key is absent.
(git 'config 'get '--all "credential.helper")
returns all values for one key as a list. An absent key produces the empty list.
Configuration values can be written with 'set!:
(git 'config 'set! "user.email" "hans@example.invalid") (git 'config '--global 'set! "user.email" "hans@example.invalid") (git 'config 'set! '--global "user.email" "hans@example.invalid")
The optional scope can be –global, –local, or –system. It may appear directly after 'config or directly after 'get / 'set!. A successful write returns #t.
procedure
(git-branch argument ...) → (or/c boolean? list?)
argument : any/c
With Git’s -l or –list option, git-cli returns structured branch information. Each item starts with one of 'current, 'local, or 'remote, followed by the branch name.
(git-branch '-l) '((current "main") (local "develop"))
Git’s normal branch selection and sorting options are passed through. For example, remote branches can be requested with -r, all branches with -a, and Git’s –sort=<key> option controls the returned order.
(git 'branch '-l '-a "--sort=refname") '((current "main") (local "develop") (remote "origin/main"))
procedure
(git-remote argument ...) → any/c
argument : any/c
With no arguments, the remote names are returned as a Racket list.
(git-remote) '("origin" "upstream")
With top-level -v or –verbose, each line reported by Git is returned as a separate structured item containing the remote name, URL, and the 'fetch or 'push role.
(git-remote '-v) '(("origin" "https://example.invalid/project.git" fetch) ("origin" "https://example.invalid/project.git" push))
The two Git lines are deliberately not merged. This keeps the result close to the output and semantics of git remote -v.
For get-url, one URL is returned as a string. With –all, a list of URLs is returned.
(git 'remote 'get-url "origin") (git 'remote 'get-url '--all "origin") (git 'remote 'get-url '--push '--all "origin")
git stash list is returned as structured Racket data. Each item contains the stash reference and Git’s stash description.
(git-stash 'list) '(("stash@{0}" "WIP on main: 1234567 Example") ("stash@{1}" "On main: older work"))
The structured form is only used when the caller has not supplied a –format or –pretty option. Explicit Git formatting is left unchanged.
Other stash subcommands, including push, show, pop, apply, drop, clear, branch, create, store, export, and import, are passed to Git unchanged.
procedure
(git-restore argument ...) → boolean?
argument : any/c
(git-restore "main.rkt") (git-restore '--staged "main.rkt") (git* restore --source=HEAD~1 main.rkt)
(git-reset '--hard 'HEAD) (git* reset --soft HEAD~1)
procedure
(git-revert argument ...) → boolean?
argument : any/c
(git-revert 'HEAD) (git* revert --abort)
procedure
(git-rebase argument ...) → boolean?
argument : any/c
(git-rebase "main") (git* rebase --continue) (git* rebase --abort)
(git-merge "feature") (git* merge --abort)
procedure
(git-cherry-pick argument ...) → boolean?
argument : any/c
(git-cherry-pick "abc1234") (git* cherry-pick --continue)
procedure
(git-switch argument ...) → boolean?
argument : any/c
(git-switch "main") (git-switch '-c "feature") (git 'switch "main")
When -l or –list is supplied, the matching tag names are returned as a Racket list. Git’s sorting options are passed through unchanged, so the returned list keeps Git’s order.
(git-tag '-l) (git-tag '--list "--sort=version:refname") (git-tag '--list "--sort=-creatordate")
When -n or -n1 is combined with -l or –list, each result item contains the tag name and the subject reported by Git.
(git-tag '-l '-n) '(("v0.3.16" "Release 0.3.16") ("v0.3.17" "Release 0.3.17"))
With -n<number> and a number greater than one, git-cli asks Git for that many content lines using %(contents:lines=<number>). The returned message is kept as one string, including embedded newlines.
For structured tag output git-cli asks Git for an explicit format using %(refname:strip=2) and either %(contents:subject) or %(contents:lines=<number>). Generated field and record delimiters are used to split the result safely.
procedure
(git-rev-list argument ...) → boolean?
argument : any/c
By default a successful diff is rendered as HTML in the default browser. The git-cli-specific option –output=- keeps Git’s textual output on standard output. –output=string returns the textual diff as a string.
(git-diff) (git-diff '--cached) (git-diff '--output=-) (git-diff '--output=string)
The git-cli-specific option –list, or its short form -l, changes the result to a Racket list. Internally this option is replaced by Git’s –oneline option. Each returned item contains the abbreviated commit id and the commit subject.
(git-log '--list '-5) '(("003f371" "Diverse commando's toegevoegd. Ik weet nog niet of ik ze allemaal ga houden") ("2cb7e93" "Small changes. git main function is now a real function, not syntax"))
Other Git log options are still passed to Git. Consequently, options that add extra output lines can also influence how useful –list is as a structured result.
For a commit that includes a patch, the default git-cli output is HTML. The commit information is shown above the diff and the diff is rendered using the same Diff2Html presentation as git-diff.
The git-cli-specific output options are –output=html, –output=-, and –output=string. –output=html explicitly selects the HTML presentation, –output=- keeps Git’s normal textual output, and –output=string returns that textual output as a string. Options such as –stat, –name-only, –name-status, and –no-patch default to textual output because they do not normally contain a patch.
The git-cli-specific option –list, or its short form -l, returns a Racket value. Without another show-format option it implies –stat.
(git-show '-l "9741b1c")
The result of –stat –list contains 'file and 'total items:
'((file "README.md" 67 "+++---") (file "main.rkt" 532 "++++-------------------------------------------") (total 9 124 823))
With –name-only –list, the result is a list of file names. With –name-status –list, every result item is the tab-separated Git name-status record converted to a list of strings.
–list/-l cannot be combined with –output=.... Only one of –stat, –name-only, and –name-status can be used with –list.
3 Package version
procedure
(git-version) → list?
procedure
(git-new-version kind) → list?
kind : symbol?
4 Low-level Git execution
procedure
(run-git args [#:input input]) →
exact-integer? list? args : list? input : (or/c #f string?) = #f
The procedure returns two values: Git’s exit code and the ordered output items, where each item identifies either 'stdout or 'stderr.
(run-git '(credential fill) #:input "protocol=https\nhost=git.dijkewijk.nl\n\n")
5 Authentication retry
Git commands recognize common authentication failures immediately after the Git process finishes and before command-specific result processing takes place. Such a failure is represented by exn:fail:git-auth?.
parameter
(current-git-authentication-handler handler) → void? handler : procedure?
The callback returns a true value when it has handled authentication and the original Git command should be tried again. A command is retried at most once. The default callback is default-git-authentication-handler.
(current-git-authentication-handler (lambda (cmd args e) #t))
procedure
(exn:fail:git-auth? v) → boolean?
v : any/c
procedure
e : exn:fail:git-auth?
procedure
(exn:fail:git-auth-args e) → list?
e : exn:fail:git-auth?
procedure
e : exn:fail:git-auth?
procedure
e : exn:fail:git-auth?
6 Authentication
procedure
(default-git-authentication-handler cmd args e) → boolean? cmd : symbol? args : list? e : exn:fail:git-auth?
parameter
(current-git-authentication-handler handler) → void? handler : procedure?