#lang scribble/manual @(require (for-label racket/base racket/contract "../main.rkt")) @title[#:tag "top"]{git-cli} @author{Hans Dijkema} @defmodule[git-cli] The @racketmodname[git-cli] module provides a command-line-like Git interface implemented by invoking the @tt{git} executable. Git never reads credentials or other answers from standard input. @section{Command interface} @defform[(git command argument ...)]{ Runs a registered command. Every command is also available as a normal procedure. For example, @racket[(git 'fetch '--prune)] and @racket[(git-fetch '--prune)] are equivalent. Registered command symbols are @racket['status], @racket['add], @racket['commit], @racket['push], @racket['pull], @racket['fetch], @racket['branch], @racket['clone], @racket['log], @racket['rev-list], @racket['diff], @racket['grep], @racket['help], @racket['switch], @racket['restore], @racket['show], @racket['tag], @racket['stash], @racket['remote], @racket['init], @racket['current-branch], @racket['branches], @racket['remotes], @racket['tags], @racket['stashes], @racket['save], @racket['save-all], @racket['sync], @racket['start-branch], @racket['release], @racket['version], and @racket['new-version]. } @section{Basic commands} @defproc[(git-status [argument any/c] ...) list?]{ Runs @tt{git status --porcelain} with the supplied arguments. Each result item has the form @racket[(index-status worktree-status file)]. The first status describes the index: the change already staged for the next commit. The second describes the working tree relative to the index: the change that is not staged yet. Both statuses are one of @racket['unchanged], @racket['modified], @racket['type-changed], @racket['added], @racket['deleted], @racket['renamed], @racket['copied], @racket['unmerged], @racket['untracked], or @racket['ignored]. Git reports an untracked file as @tt{??}, so both statuses are @racket['untracked]. @racketblock[ ((modified unchanged "staged.rkt") (unchanged modified "working-tree.rkt") (modified modified "both.rkt") (renamed unchanged "old.rkt -> new.rkt") (untracked untracked "new.rkt")) ]} @defproc[(git-add [argument any/c] ...) boolean?]{ Adds file contents to the index. Returns @racket[#t] when Git exits with status zero; otherwise an exception is raised. } @defproc[(git-commit [argument any/c] ...) boolean?]{ Creates a commit. When @tt{-m} is omitted, a commit message is requested before Git is started. A repository with nothing to commit returns @racket[#t]. Other non-zero exit statuses, including a rejected commit hook, raise an exception. } @defproc[(git-push [argument any/c] ...) boolean?]{ Pushes changes using @tt{--porcelain}. Returns @racket[#t] when Git exits with status zero; otherwise an exception is raised. } @defproc[(git-pull [argument any/c] ...) boolean?]{ Fetches and integrates changes. Normal progress written by Git to standard error is accepted when Git exits successfully. } @defproc[(git-fetch [argument any/c] ...) boolean?]{ Downloads refs and objects without integrating them into the current branch. } @defproc[(git-branch [argument any/c] ...) boolean?]{ Passes the arguments to @tt{git branch}. Use @racket[git-branches] when a list of local branch names is required. } @defproc[(git-clone [argument any/c] ...) boolean?]{ Clones a repository. Normal progress on standard error is accepted when Git exits successfully. } @defproc[(git-log [argument any/c] ...) boolean?]{ Displays the commit log. } @defproc[(git-rev-list [argument any/c] ...) boolean?]{ Lists commit objects reachable from the supplied revisions. } @defproc[(git-diff [argument any/c] ...) boolean?]{ Renders the Git diff as HTML and opens it in the default browser. Returns @racket[#t] when a diff was rendered and @racket[#f] otherwise. } @defproc[(git-grep [argument any/c] ...) (or/c list? #f)]{ Searches tracked files. Each result contains the file, optional line number, optional match count, and matched text. Exit status one means that no matches were found and returns an empty list. } @defproc[(git-help [argument any/c] ...) boolean?]{ Displays help for Git or a supplied Git command. } @defproc[(git-switch [argument any/c] ...) boolean?]{ Switches branches. @racket[(git-switch '-c "feature")] creates and checks out a new branch. } @defproc[(git-restore [argument any/c] ...) boolean?]{ Restores working-tree or index files. For example, @racket[(git-restore '--staged "main.rkt")] removes a file from the index without discarding its working-tree changes. } @defproc[(git-show [argument any/c] ...) boolean?]{ Displays one or more Git objects. } @defproc[(git-tag [argument any/c] ...) boolean?]{ Lists, creates, verifies or deletes tags. Use @racket[git-tags] when a list of tag names is required. } @defproc[(git-stash [argument any/c] ...) boolean?]{ Stores or restores uncommitted work, for example @racket[(git-stash 'push '-m "Temporary work")] and @racket[(git-stash 'pop)]. } @defproc[(git-remote [argument any/c] ...) boolean?]{ Lists or manages remotes. Use @racket[git-remotes] when a list of remote names is required. } @defproc[(git-init [argument any/c] ...) boolean?]{ Creates an empty repository or reinitializes an existing repository. } @section{Repository information} @defproc[(git-current-branch) (or/c string? #f)]{ Returns the current local branch name, or @racket[#f] for a detached HEAD. } @defproc[(git-branches) (listof string?)]{ Returns the local branch names. } @defproc[(git-remotes) (listof string?)]{ Returns the configured remote names. } @defproc[(git-tags) (listof string?)]{ Returns the repository tag names. } @defproc[(git-stashes) list?]{ Returns stash information as @racket[(reference description)] items. } @section{Easy workflows} @defproc[(git-save [message string?] [file any/c] ...) boolean?]{ Stages only the supplied files and commits them with @racket[message]. At least one file is required. } @defproc[(git-save-all [message string?]) boolean?]{ Runs @tt{git add -A} and commits every change with @racket[message]. } @defproc[(git-start-branch [name any/c] [start-point any/c #f]) boolean?]{ Creates and switches to a branch with @tt{git switch -c}. When @racket[start-point] is supplied, the branch starts there. } @defproc[(git-sync [argument any/c] ...) boolean?]{ Requires a clean working tree, then pulls and pushes. Supply either no arguments, so Git uses the configured upstream, or both a remote and branch. The pull behavior remains controlled by Git configuration such as @tt{pull.rebase}. } @defproc[(git-release [kind symbol?]) string?]{ Requires a clean working tree, increments the package version in @filepath{info.rkt}, commits it as @tt{Version }, creates a tag, and returns the tag name. The release is not pushed automatically. } @section{Package version} @defproc[(git-version) list?]{ Returns the version from @filepath{info.rkt} as a list containing major, minor and patch. } @defproc[(git-new-version [kind symbol?]) list?]{ 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{Configuration} @defproc[(git-exe) (or/c path? #f)]{ Returns the configured Git executable. Git is first searched on @tt{PATH}. If it is absent, the executable is requested interactively and stored in the @tt{git-cli} simple-ini file. } @defproc[(set-git-exe! [exe-path path?]) void?]{ Stores and caches the path to Git. } @defproc[(git-config [key symbol?]) any/c]{ Returns one of the public settings: @itemlist[ @item{@racket['display-output], default @racket[#t], controls normal Git output.} @item{@racket['display-command], default @racket[#f], displays the command before execution.} @item{@racket['tag-prefix], default @racket["v"], controls tags made by @racket[git-release].} ]} The display settings are stored in section @tt{git}; the tag prefix is stored in section @tt{release}. Git settings such as remotes, upstream branches, @tt{pull.rebase}, credentials and SSH keys remain Git's own configuration. } @defproc[(set-git-config! [key symbol?] [value any/c]) any/c]{ Validates and stores a public setting, then returns @racket[value]. The display settings require booleans and @racket['tag-prefix] requires a string. }