167 lines
7.0 KiB
Racket
167 lines
7.0 KiB
Racket
#lang scribble/manual
|
|
|
|
@(require (for-label racket/base git))
|
|
|
|
@title{git}
|
|
@author{Hans Dijkema}
|
|
|
|
@defmodule[git]
|
|
|
|
The @racketmodname[git] module provides a small command-line-like Git interface implemented on top of the @tt{libgit2} package. It does not invoke the @tt{git} executable.
|
|
|
|
The short form is intended for build scripts and interactive use:
|
|
|
|
@racketblock[
|
|
(require git)
|
|
|
|
(git status)
|
|
(git add "main.rkt" "info.rkt")
|
|
(git commit "Implement raco support")
|
|
(git tag "v0.1")
|
|
(git checkout "main")
|
|
]
|
|
|
|
@defform[(git command argument ...)]{
|
|
The @racket[git] form is syntax sugar for the corresponding procedures. For example, @racket[(git status)] calls @racket[git-status], and @racket[(git commit "message")] calls @racket[git-commit].
|
|
}
|
|
|
|
@section{Repository}
|
|
|
|
@defproc[(git-repository? [path path-string? (current-directory)]) boolean?]{Returns whether @racket[path] is inside a Git repository.}
|
|
|
|
@defproc[(git-root [path path-string? (current-directory)]) path?]{Returns the repository worktree root.}
|
|
|
|
@defproc[(git-init [path path-string? (current-directory)] [#:bare? bare? any/c #f]) path?]{Initializes a repository.}
|
|
|
|
@defproc*[([(git-clone [url string?]) path?]
|
|
[(git-clone [url string?] [path path-string?]) path?])]{Clones @racket[url]. If @racket[path] is omitted, a directory name is derived from the URL.}
|
|
|
|
@section{Status and index}
|
|
|
|
@defstruct*[git-status-entry ([path string?] [code string?] [flags list?])]{Describes one status entry. The @racket[code] field uses the familiar two-character Git status notation.}
|
|
|
|
@defproc[(git-status) (listof git-status-entry?)]{Returns worktree and index status.}
|
|
|
|
@defproc[(git-status-lines [entries (listof git-status-entry?) (git-status)]) (listof string?)]{Formats status entries as short Git-like lines.}
|
|
|
|
@defproc[(git-clean?) boolean?]{Returns @racket[#t] when @racket[git-status] is empty.}
|
|
|
|
@defproc[(git-add [path path-string?] ...) void?]{Stages the given paths. With no paths, stages the whole repository, including tracked removals.}
|
|
|
|
@section{Configuration and commits}
|
|
|
|
@defproc*[([(git-config [key string?]) string?]
|
|
[(git-config [key string?] [value string?]) string?])]{Reads or writes a repository configuration value. The two-argument form returns @racket[value].}
|
|
|
|
@defproc[(git-head) (or/c string? #f)]{Returns the full OID of HEAD, or @racket[#f] for a repository without commits.}
|
|
|
|
@defproc[(git-commit [message string?]) string?]{Creates a commit from the index and returns its full OID. The author and committer are read from the repository configuration.}
|
|
|
|
@section{Branches, checkout, and tags}
|
|
|
|
@defproc[(git-current-branch) (or/c string? #f)]{Returns the current local branch name, or @racket[#f] for detached HEAD.}
|
|
|
|
@defproc*[([(git-branch) (listof string?)]
|
|
[(git-branch [name string?]) string?])]{Lists local branches, or creates @racket[name] at HEAD.}
|
|
|
|
@defproc[(git-branch-delete [name string?]) void?]{Deletes a local branch.}
|
|
|
|
@defproc[(git-checkout [name string?]) (or/c string? #f)]{Checks out a local branch, tag, or commit. A tag or commit produces detached HEAD.}
|
|
|
|
@defproc[(git-checkout-new [name string?]) string?]{Creates and checks out a new branch.}
|
|
|
|
@defproc*[([(git-tag) (listof string?)]
|
|
[(git-tag [name string?]) string?])]{Lists tags, or creates a lightweight tag at HEAD and returns its OID.}
|
|
|
|
@defproc[(git-tag-delete [name string?]) void?]{Deletes a tag.}
|
|
|
|
@section{Log}
|
|
|
|
@defstruct*[git-log-entry ([id string?] [summary string?] [time integer?])]{Describes one commit returned by @racket[git-log].}
|
|
|
|
@defproc[(git-log [max-count exact-nonnegative-integer? 20]) (listof git-log-entry?)]{Returns commits from HEAD in topological/time order.}
|
|
|
|
@defproc[(git-log-lines [entries (listof git-log-entry?) (git-log)]) (listof string?)]{Formats log entries as short OID plus summary.}
|
|
|
|
@section{Remotes}
|
|
|
|
@defproc[(git-remotes) (listof string?)]{Lists remotes.}
|
|
|
|
@defproc[(git-remote-add [name string?] [url string?]) string?]{Adds a remote.}
|
|
|
|
@defproc[(git-remote-url [name string? "origin"]) string?]{Returns the remote URL.}
|
|
|
|
@defproc[(git-fetch [remote string? "origin"]) void?]{Fetches the configured refspecs from a remote.}
|
|
|
|
@defproc[(git-pull [remote string? "origin"]) (or/c string? #f)]{Fetches and performs a fast-forward-only update of the current branch. Returns the new OID, or @racket[#f] when already up to date. A non-fast-forward update raises an exception.}
|
|
|
|
@defproc*[([(git-push) void?]
|
|
[(git-push [remote string?]) void?]
|
|
[(git-push [remote string?] [branch string?]) void?])]{Pushes a branch to a branch with the same name. With no arguments, the current branch is pushed to @tt{origin}; with only @racket[remote], the current branch is pushed there.}
|
|
|
|
@defproc[(git-push-tag [tag string?] [remote string? "origin"]) void?]{Pushes one tag.}
|
|
|
|
Remote HTTPS operations automatically use credentials from the @tt{racket-git} credential store when an entry exists for the remote host.
|
|
|
|
@section{Command form}
|
|
|
|
The following command-like forms are supported directly:
|
|
|
|
@racketblock[
|
|
(git init)
|
|
(git clone "https://example/repo.git")
|
|
(git status)
|
|
(git add "file.rkt")
|
|
(git config "user.name" "Name")
|
|
(git commit "message")
|
|
(git branch)
|
|
(git branch "feature")
|
|
(git branch -d "feature")
|
|
(git checkout "main")
|
|
(git checkout -b "feature")
|
|
(git tag)
|
|
(git tag "v0.1")
|
|
(git tag -d "v0.1")
|
|
(git log 10)
|
|
(git remote)
|
|
(git remote add "origin" "https://example/repo.git")
|
|
(git remote get-url "origin")
|
|
(git fetch)
|
|
(git pull)
|
|
(git push)
|
|
(git push-tag "v0.1")
|
|
]
|
|
|
|
@section{HTTPS credentials}
|
|
|
|
Git credentials are stored in @tt{racket-git.ini} in the normal Racket
|
|
preferences directory. Tokens are encrypted with AES-GCM. The encryption key is
|
|
derived from the store password with PBKDF2-HMAC-SHA256.
|
|
|
|
@defproc[(git-credentials-init! [password string?]
|
|
[#:unlock-for seconds real? 86400]) void?]{
|
|
Creates the credential store and leaves it unlocked for @racket[seconds].}
|
|
|
|
@defproc[(git-credentials-unlock! [password string?]
|
|
[#:for seconds real? 86400]) void?]{
|
|
Unlocks the credential store. The temporary unlock state is stored separately in
|
|
@tt{racket-git-unlock.ini}, allowing the unlock to survive restarting DrRacket
|
|
or starting another Racket process. Both credential INI files use
|
|
@racket[#:private? #t] storage from @racketmodname[simple-ini], which restricts
|
|
them to mode 0600 on Unix.}
|
|
|
|
@defproc[(git-credentials-lock!) void?]{Locks the credential store immediately.}
|
|
|
|
@defproc[(git-credentials-unlocked?) boolean?]{Returns whether a non-expired
|
|
unlock key is currently available.}
|
|
|
|
@defproc[(git-credentials-set! [remote string?] [username string?] [token string?]) void?]{
|
|
Stores an HTTPS username and token. Credentials are keyed by host.}
|
|
|
|
@defproc[(git-credentials-ref [remote string?]) (or/c #f pair?)]{
|
|
Returns the username/token pair for @racket[remote], or @racket[#f] when none is
|
|
stored. The store must be unlocked when a credential exists.}
|
|
|
|
@defproc[(git-credentials-remove! [remote string?]) void?]{Removes credentials
|
|
for the host represented by @racket[remote].}
|