Files
git-cli/README.md
T

4.1 KiB

git

A small command-line-like Git module for Racket, implemented directly on top of the libgit2 package.

(require git)

(git 'help)
(git 'help 'grep)
(git 'status)
(git 'diff)
(git 'diff '--cached)
(git 'add "main.rkt" "info.rkt")
(git 'restore '--staged "scratch.rkt")
(git 'reset 'HEAD "--" "main.rkt")
(git 'grep '-i '-n "todo")
(git 'commit "Implement raco support")
(git 'tag "v0.2")
(git 'branch-current)
(git 'switch "main")

;; Display-oriented variant:
(dgit 'status)

git is an ordinary procedure; command names are symbols. dgit performs the same operation, displays a compact human-readable result, and returns that result.

(git 'help) opens the locally installed Scribble documentation. A command can be supplied to jump directly to its section, for example (git 'help 'restore) or (git 'help 'grep).

For grep, the natural (git 'grep '-i "pattern") spelling is supported even though Racket's reader represents -i as the complex number 0-1i; in grep option position that value is interpreted as Git's -i flag.

The same operations are available as normal procedures such as git-status, git-add, git-commit, git-tag, git-current-branch, git-switch, and git-checkout.

Help

Open the locally installed Scribble documentation through Racket's documentation cross-reference index:

(git 'help)
(git 'help 'grep)
(git 'help 'restore)

raco setup git builds and indexes the package documentation. The help command builds a fresh cross-reference view for each request, so documentation generated during the current DrRacket session is visible immediately. It uses the indexed path and anchor instead of assuming a particular documentation directory.

HTTPS credentials

Version 0.2 adds persistent HTTPS credentials. They are stored in the racket-git.ini file in Racket's preferences directory. Tokens are encrypted with AES-GCM using a key derived from the store password with PBKDF2-HMAC-SHA256.

Create the credential store once:

(git 'credentials 'init "store password")

Store a token for a Git host:

(git 'credentials 'set
     "https://git.dijkewijk.nl"
     "hans"
     token)

The host is used as the credential key, so the same entry is used for all HTTPS repositories on that host.

The store is unlocked for one day by default:

(git 'credentials 'unlock "store password")

or for an explicit number of seconds:

(git 'credentials 'unlock "store password" (* 8 60 60))

The temporary unlock state is stored in racket-git-unlock.ini in Racket's preferences directory, so it survives restarting DrRacket and starting a new Racket process. Both files are opened through simple-ini with #:private? #t; on Unix this restricts them to mode 0600 before sensitive contents are written. The cached derived key grants access to the credentials until its expiry, so racket-git-unlock.ini must be treated as sensitive during that period.

Lock immediately with:

(git 'credentials 'lock)

After credentials have been stored and the store is unlocked, normal remote operations use them automatically:

(git 'fetch)
(git 'pull)
(git 'push)
;; Example while a real push is in progress:
;; [git] push origin/main: compressing 45% (37/82 objects)
;; [git] push origin/main: sending 58% (48/82 objects)

;; Suppress network progress when desired:
(git 'push #:quiet #t)

Supported Git operations

Version 0.2 supports help, repository discovery, init, clone, status, diff, add, restore, reset, grep, config, commit, branch, branch-current, switch, checkout, merge, lightweight tags, log, remotes, fetch, fast-forward-only pull, push, tag push, network transfer progress, and HTTPS username/token credentials.

SSH credentials, merge/rebase pull, annotated tags, and submodules are not yet part of this module.

Install from the package directory with:

raco pkg install .

Recover a detached HEAD commit

(git 'branch-current) ; #f
(git 'branch-create "rescue-readme")
(git 'switch "main")
(git 'merge "rescue-readme")
(git 'status)
(dgit 'log 5)
(git 'push)
(git 'branch '-d "rescue-readme")