package volgo-base

  1. Overview
  2. Docs

Module Volgo_base.VcsSource

Extended Vcs API

Sourcemodule Author : sig ... end
Sourcemodule Branch_name : sig ... end
Sourcemodule Commit_message : sig ... end
Sourcemodule Err : sig ... end
Sourcemodule File_contents : sig ... end
Sourcemodule Git : sig ... end
Sourcemodule Graph : sig ... end
Sourcemodule Name_status : sig ... end
Sourcemodule Num_lines_in_diff : sig ... end
Sourcemodule Path_in_repo : sig ... end
Sourcemodule Platform : sig ... end
Sourcemodule Platform_repo : sig ... end
Sourcemodule Ref_kind : sig ... end
Sourcemodule Refs : sig ... end
Sourcemodule Remote_branch_name : sig ... end
Sourcemodule Remote_name : sig ... end
Sourcemodule Repo_name : sig ... end
Sourcemodule Repo_root : sig ... end
Sourcemodule Rev : sig ... end
Sourcemodule Tag_name : sig ... end
Sourcemodule User_email : sig ... end
Sourcemodule User_handle : sig ... end
Sourcemodule User_name : sig ... end
include module type of Volgo.Vcs with module Author := Volgo.Vcs.Author and module Branch_name := Volgo.Vcs.Branch_name and module Commit_message := Volgo.Vcs.Commit_message and module File_contents := Volgo.Vcs.File_contents and module Git := Volgo.Vcs.Git and module Graph := Volgo.Vcs.Graph and module Name_status := Volgo.Vcs.Name_status and module Num_lines_in_diff := Volgo.Vcs.Num_lines_in_diff and module Path_in_repo := Volgo.Vcs.Path_in_repo and module Platform := Volgo.Vcs.Platform and module Platform_repo := Volgo.Vcs.Platform_repo and module Ref_kind := Volgo.Vcs.Ref_kind and module Refs := Volgo.Vcs.Refs and module Remote_branch_name := Volgo.Vcs.Remote_branch_name and module Remote_name := Volgo.Vcs.Remote_name and module Repo_name := Volgo.Vcs.Repo_name and module Repo_root := Volgo.Vcs.Repo_root and module Rev := Volgo.Vcs.Rev and module Tag_name := Volgo.Vcs.Tag_name and module User_email := Volgo.Vcs.User_email and module User_handle := Volgo.Vcs.User_handle and module User_name := Volgo.Vcs.User_name
Sourcemodule Trait = Volgo.Vcs.Trait
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

Sourceval init : < Trait.init.. > t -> path:Fpath_sexp0.Absolute_path.t -> Volgo.Vcs.Repo_root.t

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 * Volgo.Vcs.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 -> Volgo.Vcs.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 Mock_rev_gen = Volgo.Vcs.Mock_rev_gen
Sourcemodule Mock_revs = Volgo.Vcs.Mock_revs

Commits

Sourceval add : < Trait.add.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> path:Volgo.Vcs.Path_in_repo.t -> unit

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

Files

Sourceval show_file_at_rev : < Trait.show.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> rev:Volgo.Vcs.Rev.t -> path:Volgo.Vcs.Path_in_repo.t -> [ `Present of Volgo.Vcs.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 load_file : < Trait.file_system.. > t -> path:Fpath_sexp0.Absolute_path.t -> Volgo.Vcs.File_contents.t
Sourceval save_file : ?perms:int -> < Trait.file_system.. > t -> path:Fpath_sexp0.Absolute_path.t -> file_contents:Volgo.Vcs.File_contents.t -> unit

Create a new file, or truncate an existing one.

Sourceval read_dir : < Trait.file_system.. > t -> dir:Fpath_sexp0.Absolute_path.t -> Fpath_sexp0.Fsegment.t list

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

Branches & Tags

Sourceval rename_current_branch : < Trait.branch.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> to_:Volgo.Vcs.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 Num_status = Volgo.Vcs.Num_status
Sourceval num_status : < Trait.num_status.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> changed:Num_status.Changed.t -> Num_status.t

Manipulating the graph in memory

Sourcemodule Log = Volgo.Vcs.Log
Sourceval log : < Trait.log.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> Log.t
Sourceval refs : < Trait.refs.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> Volgo.Vcs.Refs.t

Current branch & revision

Sourceval current_revision : < Trait.current_revision.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> Volgo.Vcs.Rev.t

User config

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:Volgo.Vcs.Repo_root.t -> user_name:Volgo.Vcs.User_name.t -> unit
Sourceval set_user_email : < Trait.config.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> user_email:Volgo.Vcs.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.

Sourceval git : ?env:string array -> ?run_in_subdir:Volgo.Vcs.Path_in_repo.t -> < Trait.git.. > t -> repo_root:Volgo.Vcs.Repo_root.t -> args:string list -> f:(Volgo.Vcs.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 = Volgo.Vcs.Hg
Sourceval hg : ?env:string array -> ?run_in_subdir:Volgo.Vcs.Path_in_repo.t -> < Trait.hg.. > t -> repo_root:Volgo.Vcs.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 = Volgo.Vcs.Result
Sourcemodule Rresult = Volgo.Vcs.Rresult
Sourcemodule Non_raising = Volgo.Vcs.Non_raising
Sourcemodule Private = Volgo.Vcs.Private

Additional modules

Sourcemodule Or_error : sig ... end

An Vcs API based on Base.Or_error.