package volgo

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module Volgo.VcsSource

A Versatile Library for Git Operations.

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 composed of traits, each providing different functionalities associated with Git interaction.

Vcs dynamically dispatches its implementation at runtime thanks to a design powered by the use of OCaml Objects under the hood, with some design guidelines aimed at making it so that users only need to make limited direct use of objects in their code.

Sourcemodule Trait : sig ... end

The traits that Vcs depends on to implement its functionality.

Sourcetype +'a t

At its core, Vcs operates on a value encapsulating the functionalities implemented by a set of traits, represented by a set of classes indicating which functions from the API you can use with such a vcs.

In your interfaces, you should specify the exact list of traits you need, while keeping the type of the object parameter open, to make your code flexible and compatible with backend offering more traits than your strict requirements.

Sourceval create : 'a -> 'a t

create traits returns a vcs that implements a given set of traits. Typical users do not use create vcs objects directly, but rather will rely on helper library. See for example Volgo_git_eio.create.

Error handling

The default API of Vcs is one that exposes functions that may raise a single exception Err.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.

Err.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).

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.

Creating repositories

Sourcemodule Platform : sig ... end

A platform in vcs' terminology is an online software development service where users host repositories, such as "GitHub".

Sourcemodule Platform_repo : sig ... end

A type to uniquely identify a repository hosted on a platform.

Sourcemodule Repo_name : sig ... end

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

Sourcemodule Repo_root : sig ... end

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

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

Sourceval find_enclosing_repo_root : < Trait.file_system.. > t -> from:Fpath_sexp0.Absolute_path.t -> store:(Fpath_sexp0.Fsegment.t * 'store) list -> ('store * Repo_root.t) option

find_enclosing_repo_root vcs ~from:dir ~store walks up the path from the given directory dir and stops when at the root of a repository. If no repo root has been found when reaching the root path "/", the function returns None.

The way we determine whether we are at the root of a repo is by looking for the presence of one of the store entries in the directory (e.g. ".git").

When present, we do not check that the store is itself a directory, so that this function is able to correctly infer and return the root of Git repos where ".git" is not a directory (e.g. Git worktrees).

You may supply several stores if you want to stop at the first store that is encountered, if you do not know in what kind of repo you are. For example, [".git", `Git; ".hg", `Hg]. The store that was matched is returned as part of the result.

If you know you are in a Git repository you may want to use the wrapper find_enclosing_git_repo_root instead.

Sourceval find_enclosing_git_repo_root : < Trait.file_system.. > t -> from:Fpath_sexp0.Absolute_path.t -> Repo_root.t option

find_enclosing_git_repo_root vcs ~from:dir is a convenient wrapper around find_enclosing_repo_root for Git repositories. This is looking for the deepest directory containing a ".git" entry, starting from dir and walking up.

Revisions

Sourcemodule 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.

Sourcemodule Mock_rev_gen : sig ... end

Creating mock revisions for use in expect tests.

Sourcemodule Mock_revs : sig ... end

Maintaining a mapping between mock revs and actual revs.

Commits

Sourcemodule Commit_message : sig ... end

A commit message.

Sourcemodule Path_in_repo : sig ... end

A path for a file versioned in a repository.

Sourceval add : < Trait.add.. > t -> repo_root:Repo_root.t -> path:Path_in_repo.t -> unit
Sourceval commit : < Trait.commit ; Trait.current_revision.. > 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

Sourcemodule File_contents : sig ... end

Representing the raw contents of files on disk.

Sourceval ls_files : < Trait.ls_files.. > t -> repo_root:Repo_root.t -> below:Path_in_repo.t -> Path_in_repo.t list
Sourceval 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 backend 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. For example, if the backend used at runtime is based on Eio, these functions will use Eio.Path underneath.

Sourceval save_file : ?perms:int -> < Trait.file_system.. > t -> path:Fpath_sexp0.Absolute_path.t -> file_contents:File_contents.t -> unit

Create a new file, or truncate an existing one.

Returns the entries of the supplied directory, ordered increasingly according to String.compare. The result does not include the unix entries ".", "..".

Branches & Tags

Sourcemodule Branch_name : sig ... end
Sourcemodule Remote_name : sig ... end
Sourcemodule Remote_branch_name : sig ... end
Sourcemodule Tag_name : sig ... end
Sourceval rename_current_branch : < Trait.branch.. > t -> repo_root:Repo_root.t -> to_:Branch_name.t -> 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

Sourcemodule Name_status : sig ... end
Sourcemodule Num_status : sig ... end
Sourcemodule Num_lines_in_diff : sig ... end

Number of lines involved in a change.

Sourceval name_status : < Trait.name_status.. > t -> repo_root:Repo_root.t -> changed:Name_status.Changed.t -> Name_status.t
Sourceval num_status : < Trait.num_status.. > t -> repo_root:Repo_root.t -> changed:Num_status.Changed.t -> Num_status.t

Manipulating the graph in memory

Sourcemodule Log : sig ... end

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

Sourcemodule Ref_kind : sig ... end
Sourcemodule Refs : sig ... end

Capturing the information related to git refs.

Sourcemodule Graph : sig ... end

Building an in-memory representation of the commit graph of a git repository for queries related to the structure of its nodes and edges.

Sourceval log : < Trait.log.. > t -> repo_root:Repo_root.t -> Log.t
Sourceval refs : < Trait.refs.. > t -> repo_root:Repo_root.t -> Refs.t
Sourceval graph : < Trait.log ; Trait.refs.. > t -> repo_root:Repo_root.t -> Graph.t

Current branch & revision

Sourceval current_branch : < Trait.current_branch.. > t -> repo_root:Repo_root.t -> Branch_name.t
Sourceval current_revision : < Trait.current_revision.. > t -> repo_root:Repo_root.t -> Rev.t

User config

Sourcemodule Author : sig ... end

Author information as commonly used in Git.

Sourcemodule User_email : sig ... end
Sourcemodule User_handle : sig ... end

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

Sourcemodule 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.

Sourceval set_user_name : < Trait.config.. > t -> repo_root:Repo_root.t -> user_name:User_name.t -> unit
Sourceval set_user_email : < Trait.config.. > t -> repo_root:Repo_root.t -> user_email:User_email.t -> 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 backend, we might as well expose this. Use at your own risk/convenience.

Sourcemodule Git : sig ... end

Manipulating the output of processes run by vcs and backends - typically the "git" command.

Sourceval git : ?env:string array -> ?run_in_subdir:Path_in_repo.t -> < Trait.git.. > t -> repo_root:Repo_root.t -> args:string 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: 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.

Some helpers are provided by the module Git to help you build the f parameter. Non-raising modules are also included in the Git module dedicated to their respective result type (see for example Volgo_base.Vcs.Git.Or_error).

The expectation is that you should be using the Git module of the API you are using to access the git function, and not mix and match.

For example using the raising API::

  let git_status () : string =
    Vcs.git vcs ~repo_root ~args:[ "status" ] ~f:Vcs.Git.exit0_and_stdout
  ;;

Or the non-raising API (result):

  let git_status () : string Vcs.Result.t =
    Vcs.Result.git
      vcs
      ~repo_root
      ~args:[ "status" ]
      ~f:Vcs.Git.Result.exit0_and_stdout
  ;;

Low level Mercurial cli

This part of Vcs provides direct access to the "hg" command line interface when operating in a Mercurial repository.

This is similar to the low level access provided by git and the same restrictions and advices apply.

Sourcemodule Hg : sig ... end

Manipulating the output of processes run by vcs and backends - typically the "hg" command.

Sourceval hg : ?env:string array -> ?run_in_subdir:Path_in_repo.t -> < Trait.hg.. > t -> repo_root:Repo_root.t -> args:string list -> f:(Hg.Output.t -> 'a) -> 'a

Simiar to git, helpers are provided by the module Hg to build the f parameter.

The expectation is that you should be using the Hg module of the API you are using to access the hg function, and not mix and match.

For example using the raising API:

  let hg_status () : string =
    Vcs.hg vcs ~repo_root ~args:[ "status" ] ~f:Vcs.Hg.exit0_and_stdout
  ;;

Or the non-raising API (result):

  let hg_status () : string Vcs.Result.t =
    Vcs.Result.hg vcs ~repo_root ~args:[ "status" ] ~f:Vcs.Hg.Result.exit0_and_stdout
  ;;

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.

Sourcemodule Result : sig ... end

An Vcs API based on Result and Vcs.Err.

Sourcemodule Rresult : sig ... end

An Vcs API in the style of Rresult.

Sourcemodule Non_raising : sig ... end

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

Sourcemodule Private : sig ... end

This part of the interface is not stable. Things may break without notice and outside of the guidelines set by semver when upgrading to a new version of Vcs. This is used e.g. by tests or libraries with strong ties to Vcs. Do not use.

OCaml

Innovation. Community. Security.