Module Vcs

A versatile library for Git interaction.

Vcs is a library providing a direct-style API for interacting with Git repositories in a type-safe way. It is designed as an "interface", or "virtual" library with the actual implementation dynamically dispatched at runtime.

How it works?

Vcs is an interface composed of traits, each providing different functionalities associated with Git interaction. The dynamic dispatch implementation uses the provider library.

module Trait : sig ... end

The traits that Vcs depends on to implement its functionality.

type -'a t

At its core, a 'a Vcs.t is a value encapsulating the functionalities implemented by a set of traits, represented by the 'a parameter. It is a phantom type used to provide compiler guidance on which functions from the API you can use with such a vcs. The type is contravariant by its parameter : indeed, if you need a set of traits, having more makes it compatible.

val create : 'a Provider.t -> 'a t

create provider returns a vcs that implements a given set of traits. Typical users do not use create directly, but rather will rely on an actual provider. See for example Vcs_git.create.

Error handling

The default API of Vcs is one that exposes functions that may raise a single exception, named E, which carries an abstract payload err containing printable information. err is not meant for pattern matching - we're only targeting a non-specialized error recovery.

A general design principle that we follow here is that if an error result is of interest for pattern matching, we want to incorporate it into the successful branch of the function's result, rather than in its error part - either by making the result a variant type, or otherwise adding more functions to the API with finer granularity for particular use cases. Consider opening an issue on GitHub if what you'd like to match on isn't available.

As library authors we realize that manipulating Result.t is a popular choice too: we also export the Vcs's functionality via non-raising APIs if you prefer.

module Err : sig ... end

Payload of the exception raised by Vcs functions.

exception E of Err.t

E is meant to be the only exception ever raised by functions from the Vcs interface. Err.t doesn't carry the raw backtrace, so you'll need to manipulate the backtrace yourself if you care about it (like you would with any other exceptions).

Creating repositories

module Platform : sig ... end

Online software development platforms where users host repositories, e.g. "GitHub".

module Repo_name : sig ... end

The name of a repository as configured on a platform such as GitHub.

module Repo_root : sig ... end

The root of a version control repository that is expected to exists on the local file system.

module Url : sig ... end

A url to access a repository on a supported platform.

val init : [> Trait.init ] t -> path:Fpath_base.Absolute_path.t -> Repo_root.t

Initialize a git repository at the given path. This errors out if a repository is already initialized there.

Revisions

module Rev : sig ... end

A revision uniquely identifies a node in the dag formed by the commits of a repository. The name was inherited from Mercurial. For git, this correspond to the commit-hash. In both systems, these are 40-chars hashes.

module Mock_rev_gen : sig ... end

Creating mock revisions for use in expect tests.

module Mock_revs : sig ... end

Maintaining a mapping between mock revs and actual revs.

Commits

module Commit_message : sig ... end

A commit message.

module Path_in_repo : sig ... end

A path for a file versioned in a repository.

val add : [> Trait.add ] t -> repo_root:Repo_root.t -> path:Path_in_repo.t -> Base.unit
val commit : [> Trait.rev_parse | Trait.commit ] t -> repo_root:Repo_root.t -> commit_message:Commit_message.t -> Rev.t

When this succeeds, this returns the revision of the commit that was just created.

Files

module File_contents : sig ... end

Representing the raw contents of files on disk.

val ls_files : [> Trait.ls_files ] t -> repo_root:Repo_root.t -> below:Path_in_repo.t -> Path_in_repo.t Base.list
val show_file_at_rev : [> Trait.show ] t -> repo_root:Repo_root.t -> rev:Rev.t -> path:Path_in_repo.t -> [ `Present of File_contents.t | `Absent ]

Files IO

Vcs contains some basic provider based functions to manipulate files from the file system. The goal is to allow some users of Vcs to use this simple API without committing to a particular implementation. If the Vcs provider used at runtime is based on Eio, these functions will use Eio.Path underneath.

val load_file : [> Trait.file_system ] t -> path:Fpath_base.Absolute_path.t -> File_contents.t
val save_file : ?perms:Base.int -> [> Trait.file_system ] t -> path:Fpath_base.Absolute_path.t -> file_contents:File_contents.t -> Base.unit

Branches & Tags

module Branch_name : sig ... end
module Remote_name : sig ... end
module Remote_branch_name : sig ... end
module Tag_name : sig ... end
val rename_current_branch : [> Trait.branch ] t -> repo_root:Repo_root.t -> to_:Branch_name.t -> Base.unit

This translates to git branch --move $NAME, which is used to enforce the name of a default branch during tests. If the current branch already has this name, this has no further effect.

Computing diffs

module Name_status : sig ... end
module Num_status : sig ... end
module Num_lines_in_diff : sig ... end

Number of lines involved in a change.

val name_status : [> Trait.name_status ] t -> repo_root:Repo_root.t -> changed:Name_status.Changed.t -> Name_status.t
val num_status : [> Trait.num_status ] t -> repo_root:Repo_root.t -> changed:Num_status.Changed.t -> Num_status.t

Manipulating the tree in memory

module Log : sig ... end

A log is a complete listing of the structure of the dag.

module Ref_kind : sig ... end
module Refs : sig ... end

Capturing the information related to git refs.

module Tree : sig ... end

Building an in-memory representation of a git tree, for queries about history contents.

val log : [> Trait.log ] t -> repo_root:Repo_root.t -> Log.t
val refs : [> Trait.refs ] t -> repo_root:Repo_root.t -> Refs.t
val tree : [> Trait.log | Trait.refs ] t -> repo_root:Repo_root.t -> Tree.t

Rev parse utils

module Rev_parse : sig ... end
val rev_parse : [> Trait.rev_parse ] t -> repo_root:Repo_root.t -> arg:Rev_parse.Arg.t -> Rev.t

User config

module Author : sig ... end

Author information as commonly used in Git.

module User_email : sig ... end
module User_handle : sig ... end

A user handle, such as user pseudonym on GitHub, used in CR comments, etc.

module User_name : sig ... end

User name information as specified by the Git config user.name value.

During tests in the GitHub environment we end up having issues if we do not set the user name and email. Also, we rather not do it globally. If this is never called, the current user config is used as usual by git processes invocations.

val set_user_name : [> Trait.config ] t -> repo_root:Repo_root.t -> user_name:User_name.t -> Base.unit
val set_user_email : [> Trait.config ] t -> repo_root:Repo_root.t -> user_email:User_email.t -> Base.unit

Low level Git cli

This part of Vcs provides direct access to the "git" command line interface. This should be considered non portable and brittle. Generally speaking, one hope is that you shouldn't have to use git directly. Instead, consider requesting proper integration of your use case into the typed and parametrized API of Vcs. However, sometimes this is just what you need e.g. in tests, or for quick one-off, and if your backend happens to be a CLI based vcs provider, we might as well expose this. Use at your own risk/convenience.

module Git : sig ... end

Manipulating the output of process running the "git" command.

val git : ?env:Base.string Base.array -> ?run_in_subdir:Path_in_repo.t -> [> Trait.git ] t -> repo_root:Repo_root.t -> args:Base.string Base.list -> f:(Git.Output.t -> 'a) -> 'a

Note a non trivial behavior nuance depending on whether you are using this function using the raising or non-raising API. In the raising API, f is allowed to raise, and git will catch any exception raised by f, and rewrap it under a proper E err exception with added context. In the non-raising APIs, if f raises instead of returning an Error, that exception would escape the function git and be raised by git as an uncaught exception. This would be considered a programming error.

Test utils

module For_test : sig ... end

This part of Vcs provides utilities for testing.

Non-raising APIs

For convenience and to allow experimenting with different error handling strategies, Vcs exports non-raising APIs. The functions there return Result.ts instead of raising.

module Or_error : sig ... end

An Vcs API based on Base.Or_error.

module Result : sig ... end

An Vcs API in the style of Rresult.

module Non_raising : sig ... end

A functor to build non raising interfaces for Vcs based on a custom result type.

module Private : sig ... end

Module exposed for testing of Vcs only.