git

libgit2 bindings for Git operations in Kit

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and dependencies
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
c/kit_git.cC FFI wrapper
c/kit_git.hC header for FFI wrapper
examples/basic.kitBasic usage example
kit.tomlPackage manifest with metadata and dependencies
src/git.kitKit Git - libgit2 bindings for Git operations
tests/git.test.kitTests for git

Dependencies

No Kit package dependencies.

Installation

kit add gitlab.com/kit-lang/packages/kit-git.git

System Requirements

PlatformCommand
macOSbrew install libgit2
Ubuntusudo apt install libgit2-dev
Fedorasudo dnf install libgit2-devel

Usage

import Kit.Git as Git

main = fn =>
  Git.lib-init()

  match Git.repo-open "."
    | Ok repo ->
      # Repository info
      println ("Path: " ++ Git.repo-path repo)
      println ("Workdir: " ++ Git.repo-workdir repo)

      # Current branch and HEAD
      match Git.head-name repo
        | Some name -> println ("Branch: " ++ name)
        | None -> println "HEAD is detached"

      match Git.head-oid repo
        | Some sha -> println ("HEAD SHA: " ++ (String.take 8 sha))
        | None -> println "No commits yet"

      # List branches
      println "\nBranches:"
      List.map (fn(b) => println ("  " ++ b)) (Git.branch-list repo)

      # Recent commits
      println "\nRecent commits:"
      List.map (fn(c) => println ("  " ++ c)) (Git.log repo 5)

      # Working directory status
      changes = Git.status repo
      if List.length changes == 0 then
        println "\nClean working directory"
      else
        println "\nChanges:"
        List.map (fn(c) => println ("  " ++ c)) changes

      # Config values
      match Git.config-get repo "user.name"
        | Some name -> println ("\nuser.name: " ++ name)
        | None -> println "\nuser.name: (not set)"

      Git.repo-free repo
    | Err e -> println ("Error: " ++ e)

  Git.lib-shutdown()

main

Development

Running Examples

Run examples with the interpreter:

kit run examples/basic.kit

Compile examples to a native binary:

kit build examples/basic.kit && ./basic

Running Tests

Run the test suite:

kit test

Run the test suite with coverage:

kit test --coverage

Running kit dev

Run the standard development workflow (format, check, test):

kit dev

This will:

  1. Format and check source files in src/
  2. Run tests in tests/ with coverage

Generating Documentation

Generate API documentation from doc comments:

kit doc

Note: Kit sources with doc comments (##) will generate HTML documents in docs/*.html

Cleaning Build Artifacts

Remove generated files, caches, and build artifacts:

kit task clean

Note: Defined in kit.toml.

Local Installation

To install this package locally for development:

kit install

This installs the package to ~/.kit/packages/@kit/git/, making it available for import as Kit.Git in other projects.

License

This package is released under the MIT License - see LICENSE for details.

libgit2 is released under the GPL 2.0 with linking exception.

Exported Functions & Types

lib-init

Initialize the libgit2 library. Must be called before any other git functions.

Returns:

Int

lib-init()
# ... use git functions ...
lib-shutdown()

lib-shutdown

Shutdown the libgit2 library. Call once when done with all git operations.

Unit

lib-shutdown()

repo-open

Open an existing git repository.

Parameters:

Returns:

String -> Result Ptr String

match repo-open "."
  | Ok repo ->
    println ("Path: " ++ (repo-workdir repo))
    repo-free repo
  | Err e -> println "Error: ${e}"

repo-init

Initialize a new git repository.

Parameters:

Returns:

String -> Result Ptr String

match repo-init "/tmp/my-project"
  | Ok repo ->
    println "Repository created!"
    repo-free repo
  | Err e -> println "Error: ${e}"

clone

Clone a remote repository.

Parameters:

Returns:

String -> String -> Result Ptr String

match clone "https://github.com/user/repo.git" "/tmp/repo"
  | Ok repo ->
    println "Cloned!"
    repo-free repo
  | Err e -> println "Clone failed: ${e}"

repo-free

Free a repository handle and release resources.

Parameters:

Ptr -> Unit

repo-free repo

repo-path

Get the .git directory path of a repository.

Parameters:

Returns:

Ptr -> String

println (repo-path repo)  # "/path/to/repo/.git/"

repo-workdir

Get the working directory path of a repository.

Parameters:

Returns:

Ptr -> String

println (repo-workdir repo)  # "/path/to/repo/"

is-bare?

Check if the repository is bare (no working directory).

Parameters:

Returns:

Ptr -> Bool

is-empty?

Check if the repository is empty (no commits).

Parameters:

Returns:

Ptr -> Bool

head-name

Get the short name of the current HEAD reference (e.g., "main").

Parameters:

Returns:

Ptr -> Option String

match head-name repo
  | Some name -> println ("On branch: " ++ name)
  | None -> println "HEAD is detached"

head-oid

Get the full SHA-1 hash of the HEAD commit.

Parameters:

Returns:

Ptr -> Option String

match head-oid repo
  | Some sha -> println ("HEAD: " ++ sha)
  | None -> println "No commits yet"

status

Get the file status of the working directory.

Returns a list of strings, each formatted as "S path" where S is a status character: M (modified), A (added), D (deleted), R (renamed), ? (untracked).

Parameters:

Returns:

Ptr -> [String]

entries = status repo
List.map (fn(e) => println e) entries

log

Get the commit log history.

Returns a list of strings, each formatted as "sha1 summary" where sha1 is the full commit hash and summary is the first line of the commit message.

Parameters:

Returns:

Ptr -> Int -> [String]

entries = log repo 10
List.map (fn(e) => println e) entries

branch-list

List all local branches.

Parameters:

Returns:

Ptr -> [String]

branches = branch-list repo
List.map (fn(b) => println b) branches

branch-create

Create a new local branch at the current HEAD.

Parameters:

Returns:

Ptr -> String -> Result Unit String

match branch-create repo "feature/new-thing"
  | Ok _ -> println "Branch created!"
  | Err e -> println "Error: ${e}"

tag-list

List all tags in the repository.

Parameters:

Returns:

Ptr -> [String]

tags = tag-list repo
List.map (fn(t) => println t) tags

diff-workdir

Get a summary of changes between the index and working directory.

Returns a list of strings, each formatted as "S path" where S is a status character: A (added), D (deleted), M (modified), R (renamed), C (copied).

Parameters:

Returns:

Ptr -> [String]

changes = diff-workdir repo
List.map (fn(c) => println c) changes

remote-list

List all remote names.

Parameters:

Returns:

Ptr -> [String]

remotes = remote-list repo
List.map (fn(r) => println r) remotes

config-get

Get a configuration value from the repository config.

Parameters:

Returns:

Ptr -> String -> Option String

match config-get repo "user.name"
  | Some name -> println ("User: " ++ name)
  | None -> println "user.name not set"