Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mirage/ocaml-git

Pure OCaml Git format and protocol
https://github.com/mirage/ocaml-git

git ocaml

Last synced: 22 days ago
JSON representation

Pure OCaml Git format and protocol

Awesome Lists containing this project

README

        

## ocaml-git -- Git format and protocol in pure OCaml

Support for on-disk and in-memory Git stores. Can read and write all the Git
objects: blobs, trees, commits and tags. It can also handle pack files, pack
indexes and index files (where the staging area lives - only for `git-unix`
package).

All the objects share a consistent API, and convenience functions are provided
to manipulate the different objects. For instance, it is possible to make a pack
file position independent (as the Zlib compression might change the relative
offsets between the packed objects), to generate pack indexes from pack files,
or to expand the filesystem of a given commit.

The library comes with some command-line tools called `ogit-*` as a
Proof-of-concept of the core library which shares a similar interface with
`git`, but where all operations are mapped to the API exposed by `ocaml-git` (and
hence using only OCaml code). However, these tools are not meant to be used. They
are just examples of how to use `ocaml-git`.

`ocaml-git` wants to be a low-level library for [irmin][irmin]. By this fact,
high-level commands such as a ([patience][patience-diff]) diff, `git status`,
etc. are not implemented.

As a MirageOS project, `ocaml-git` is system agnostic. However, it provides a
`git-unix` package which uses UNIX _syscall_ and is able to introspect a usual Git
repository in a filesystem. However, `ocaml-git` handles only Git objects
and does not _populate_ your filesystem as `git` does. For example, `Git_unix.Sync.fetch`
does not give you files fetched from the repository but only synchronizes `.git` with
that repository.

The API documentation is available [online][documentation].

[![Build Status](https://travis-ci.org/mirage/ocaml-git.svg?branch=master)](https://travis-ci.org/mirage/ocaml-git)

### Build, Install Instructions and Packages

To build and install the project, simply run:
```sh
$ opam install git
$ opam install git-unix
$ opam install git-mirage
```

### _Linking-trick_

`ocaml-git` uses 2 libraries with the linking-trick:
* [digestif][digestif]
* [checkseum][checkseum]

These libraries provide a C implementation and an OCaml implementation (mostly
to be compatible with `js_of_ocaml`). However, `utop` or any a build-system such
as `ocamlbuild` are not able to choose between these implementations. So, you
must __explicitely__ choose one.

These libraries use [virtual-library][virtual-library] available with `dune`. If
your build-system is `dune`, you should not have any problem about that where
`dune` is able to take the _default_ implementation of these libraries.

### What is supported

* The loose object files can be read and written;
- [blobs][blob] (files)
- [trees][tree] (directories)
- [commits][commit] (revision history)
- [tags][tag] (annotated tags)
- [references][reference] (branch names)

* The [PACK files][pack-file] (collections of compressed loose objects using a
binary-diff representation) and [PACK indexes][pack-index] (indexes of pack
files) can be read and written). The binary diff hunks are exposed using a
high-level position-independent representation so that they can be manipulated
more easily. Pack file can be created and is compressed.

* The [INDEX file][index] (used as for managing the staging area) are fully
supported, which means that `git diff` and `git status` will work as expected
on a repository created by the library. This feature is only available for
`git-unix` when it needs to introspect a file-system.

* [Cloning and fetching][git-sync] (using various options) are fully supported
for the Git protocol, the smart-HTTP protocol and `git+ssh`. A subset of the
protocol capabilities are implemented (mainly `thin-pack`, `ofs-delta`,
`side-band-64k` and `allow-reachable-sha1-in-want`).

* Pushing is still experimental and needs more testing.

* An abstraction for Git [Store][git-store]
Is available. Various store implementations are available:
- An [in-memory][git-store-memory] implementation;
- A [unix filesystem][git-store-unix] implementation;

### What is *not* supported

* No server-side operations are currently supported.
* No GC.
* Updates, merge and rebase are not supported. Use [irmin][irmin] instead.

### Performance

Performance is comparable to the Git tool.

### Example

This `utop` example must run into the `ocaml-git` repository when the given path
is `.`.

```ocaml
# ;; load necessary modules
# #require "checkseum.c" ;;
# #require "digestif.c" ;;
# #require "git-unix" ;;

# ;; we are going to use this project's local repository
# module Store = Git_unix.Store ;;
module Store = Git_unix.Store

# ;; this module is useful for finding git objects in a git store
# module Search = Git.Search.Make (Digestif.SHA1) (Store) ;;
module Search :
sig
type hash = Store.hash
type store = Store.t
type pred =
[ `Commit of hash
| `Tag of string * hash
| `Tree of string * hash
| `Tree_root of hash ]
val pred : store -> ?full:bool -> hash -> pred list Lwt.t
type path =
[ `Commit of path | `Path of string list | `Tag of string * path ]
val mem : store -> hash -> path -> bool Lwt.t
val find : store -> hash -> path -> hash option Lwt.t
end

# ;; we want to read the contents of a blob under name [filename]
# let read filename =
let open Lwt_result.Syntax in
(* get store located in current root's .git folder *)
let* store = Store.v (Fpath.v (Sys.getcwd ())) in
(* find obj-id pointed at by main branch (reference) *)
let* commit_id = Store.Ref.resolve store Git.Reference.main in
let open Lwt.Syntax in
(* find obj-id of of [filename] as a git blob *)
let* blob_id = Search.find store commit_id (`Commit (`Path [ filename ])) in
match blob_id with
| None -> Lwt.return (Error (`Not_found commit_id))
| Some hash ->
(* read contents of the blob *)
Store.read store hash
;;
val read : string -> (Store.Value.t, Store.error) Lwt_result.t =

# let pp =
let ok ppf = function
| Git.Value.Blob b -> Fmt.string ppf (Git.Blob.to_string b)
| _ -> Fmt.string ppf "#git-object"
in
Fmt.result ~ok ~error:Store.pp_error;;
val pp : ('_weak1 Git.Value.t, Store.error) result Fmt.t =

# Lwt_main.run Lwt.Infix.(read "README.md" >|= pp Fmt.stdout) ;;

ocaml-git -- Git format and protocol in pure OCaml

Support for on-disk and in-memory Git stores. Can read and write all
the Git objects: the usual blobs, trees, commits and tags but also
the pack files, pack indexes and the index file (where the staging area
lives).

[...]
```

()

### License

MIT, see [LICENSE.md][LICENSE.md] file for its text.

[documentation]: http://mirage.github.io/ocaml-git/
[irmin]: https://github.com/mirage/irmin
[patience-diff]: https://git-scm.com/docs/git-diff
[digestif]: https://github.com/mirage/digestif
[checkseum]: https://github.com/mirage/checkseum
[virtual-library]: https://dune.readthedocs.io/en/stable/variants.html
[blob]: http://mirage.github.io/ocaml-git/git/Git/Blob/module-type-S/index.html
[tree]: http://mirage.github.io/ocaml-git/git/Git/Tree/module-type-S/index.html
[commit]: http://mirage.github.io/ocaml-git/git/Git/Commit/module-type-S/index.html
[tag]: http://mirage.github.io/ocaml-git/git/Git/Tag/module-type-S/index.html
[reference]: http://mirage.github.io/ocaml-git/git/Git/Reference/module-type-S/index.html
[pack-file]: http://mirage.github.io/ocaml-git/git/Git/Pack/index.html
[pack-index]: http://mirage.github.io/ocaml-git/git/Git/Index_pack/index.html
[index]: http://mirage.github.io/ocaml-git/git-unix/Git_unix/Index/index.html
[git-sync]: http://mirage.github.io/ocaml-git/git/Git/Sync/module-type-S/index.html
[git-store]: http://mirage.github.io/ocaml-git/git/Git/Store/index.html
[git-store-memory]: http://mirage.github.io/ocaml-git/git/Git/Mem/index.html
[git-store-unix]: http://mirage.github.io/ocaml-git/git-unix/Git_unix/Store/index.html
[LICENSE.md]: ./LICENSE.md