ExGitEngine.Git (ex_git_engine v0.9.0)

Copy Markdown

Erlang NIF that exposes a subset of libgit2's library functions.

Most functions available in this module are implemented in C for performance reasons. These functions are compiled into a dynamic loadable, shared library. They are called like any other Elixir functions.

As a NIF library is dynamically linked into the emulator process, this is the fastest way of calling C-code from Erlang (alongside port drivers). Calling NIFs requires no context switches. But it is also the least safe, because a crash in a NIF brings the emulator down too.

Erlang documentation - NIFs

Example

Let's start with a basic code example showing the last commit author and message:

alias ExGitEngine.Git

# load repository
{:ok, repo} = Git.repository_open("/tmp/my-repo.git")

# fetch commit pointed by master
{:ok, :commit, _oid, commit} = Git.reference_peel(repo, "refs/heads/master")

# fetch commit author & message
{:ok, name, email, time, _offset} = Git.commit_author(commit)
{:ok, message} = Git.commit_message(commit)

IO.puts "Last commit by #{name} <#{email}>:"
IO.puts message

First we open our repository using repository_open/1, passing the path of the Git repository. We can fetch a commit by passing the exact reference path to reference_peel/2. In our example, this allows us to retrieve the commit refs/heads/master is pointing to.

This is one of many ways to fetch a given revision, reference_lookup/2 and reference_glob/2 offer similar functionalities. There are other related functions such as revparse_single/2 and revparse_ext/2 which provide support for parsing revspecs.

Walk commit history

In order to walk the commit ancestry chain, we have a few functions at our disposal: revwalk_new/1, revwalk_push/2, revwalk_next/1, revwalk_reset/1, etc.

# create revision walk iterator
{:ok, revwalk} = Git.revwalk_new(repo)

# set root commit for traversal
 :ok = Git.revwalk_push(walk, commit_oid)

# create (lazy) stream of ancestors from iterator
{:ok, stream} = Git.revwalk_stream(walk)

for ancestor_oid <- stream do
  # fetch commit object
  {:ok, :commit, commit} = Git.object_lookup(ancestor_oid)

  # fetch commit message
  {:ok, message} = Git.commit_message(commit)

  IO.puts "#{Git.oid_fmt_short(ancestor_oid)} - #{message}"
end

In this example revwalk_new/1 returns a revwalk/0, a mutable C-like iteratable object. This means that revwalk_push/2 mutates the revwalk object instead of returning a new object.

The revwalk_stream/1 function converts the revwalk iterator to a Enumerable.t/0 we can then use to walk the commit ancestry chain.

When iterating through a commit's history, revwalk_sorting/2 and revwalk_simplify_first_parent/1 provide conveniences for sorting and filtering while revwalk_push/3 can be used to hide specific commits.

Retrieve blobs & trees

In order to access the actual files and directories of a repository, we have to retrieve the Git blob and tree objects of a given revision. Here we simply list files and folders at the root directory:

# fetch commit tree
{:ok, tree} = Git.commit_tree(commit)

# fetch tree entries at /
{:ok, tree_entries} = Git.tree_entries(tree)

for {mode, type, oid, name} <- tree_entries do
  # fetch tree entry object by oid (blob or tree)
  case Git.object_lookup(repo, oid) do
    {:ok, :blob, blob} ->
      # fetch blob size
      {:ok, blob_size} = Git.blob_size(blob)
      IO.puts "#{name} -- #{blob_size} bytes"
    {:ok, :tree, tree} ->
      # fetch number of sub entries
      {:ok, count} <- Git.tree_count(tree)
      IO.puts "#{name}/ -- #{count} items"
  end
end

Note that tree_entries/1 and tree_nth/2 return a tuple in the form of {mode, type, oid, name}. In order to call blob and tree specific functions such as blob_size/1 and tree_count/1, we still need to lookup the Git object using object_lookup/2.

Here's an other example showing a convenient way to retrieve a tree entry by path:

# fetch commit tree
{:ok, tree} = Git.commit_tree(commit)

# fetch blob by path
{:ok, mode, :blob, oid, name} Git.tree_bypath(tree, "README.md")

# fetch blob object by oid
{:ok, :blob, blob} = Git.object_lookup(repo, oid)

# fetch blob content
{:ok, data} = Git.blob_content(blob)

IO.binwrite data

Compare revisions

Now that we know how to access files and directories, it might be interesting to determine the changes between two versions. In order to do so, we need to compare two tree objects from different revisions:

# fetch tree for tag v1.2
{:ok, v1_2, :commit, _oid} = Git.revparse_single(repo, "v1.2")
{:ok, v1_2_tree} = Git.commit_tree(v1_2)

# fetch tree for tag v1.3
{:ok, v1_3, :commit, _oid} = Git.revparse_single(repo, "v1.3")
{:ok, v1_3_tree} = Git.commit_tree(v1_3)

# fetch diff between v1.2 and v1.3
{:ok, diff} = Git.diff_tree(repo, v1_2_tree, v1_3_tree)

# format diff to string
{:ok, patch} = Git.diff_format(diff, :patch)

IO.puts patch

Note that diff_tree/4 takes options such as :pathspec allowing to filter changes based on a given path.

For example, we might want to see the different between two revision for a specific file. In this case we could modify the above example as follow to print changes affecting README.md:

# fetch diff between v1.2 and v1.3 for README.md
{:ok, diff} = Git.diff_tree(repo, v1_2_tree, v1_3_tree, pathspec: "README.md")

# format diff to string
{:ok, patch} = Git.diff_format(diff, :patch)

IO.puts patch

Commit changes

Committing changes to a repository is done in a serie of distinct steps.

First, we add a new blob object to the repository:

# Blob content
blob_content = "Hello world\n"

# Open repository ODB
{:ok, odb} = Git.repository_get_odb(repo)

# Write new blob object
{:ok, blob_oid} = Git.odb_write(odb, blob_content, :blob)

We create an in-memory index to stage our modifications (an index is a list of path names, each with permissions and the SHA1 of a blob object). In order to create a new tree object reflecting our changes, we have to assign our new blob object at a given path in the index and write the index back to the repository:

# Blob path
blob_path = "README"

# Create new index
{:ok, index} = Git.index_new()

# Read last commit tree into index
:ok = Git.index_read_tree(index, tree)

# Add newly added blob object to index
:ok = Git.index_add(repo, index, blob_oid, blob_path, byte_size(blob_content), 0o100644)

# Write index
{:ok, tree_oid} = Git.index_write_tree(index)

The repository now contains a new blob object and a new tree object reflecting our changes. We now have all the ingredients for creating a commit and update the master branch accordingly:

# Commit message
commit_message = "Add README"

# Fetch repository default signature for authoring and committing
{:ok, sig_name, sig_email, sig_ts, sig_tz} = Git.signature_default(repo)
commit_author = {sig_name, sig_email, sig_ts, sig_tz}
commit_committer = commit_author

# Fetch reference to update
{:ok, :commit, parent_oid, _parent} = Git.reference_peel(repo, "refs/heads/master")

# Create new commit
{:ok, commit_oid} = Git.commit_create(repo, :undefined, commit_author, commit_committer, :undefined, commit_message, tree_oid, [parent_oid])

# Update master branch to new commit
:ok = Git.reference_create(repo, "refs/heads/master", :oid, commit_oid)

IO.puts "File #{blob_path} added in commit #{Git.oid_fmt(commit_oid)}."

We have created a commit pointing at the new tree object. The commit refers the newly created tree and requires two user signatures (author and committer), a commit message and the commit ancestor(s).

Finally we have updated the master branch to point at our new commit.

Thread safety

Accessing a repo/0 or any NIF allocated pointer (blob/0, commit/0, config/0, etc.) from multiple processes simultaneously is not safe. These pointers should never be shared across processes.

In order to access a repository in a concurrent manner, each process has to initialize it's own repository resource using repository_open/1. Alternatively, the ExGitEngine.GitAgent module provides a similar API but can use a dedicated process, so that its access can be serialized.

Summary

Functions

Returns blame hunks for path in repo.

Returns the raw content of the given blob.

Returns the size in bytes of the given blob.

Returns the author of the given commit.

Returns the committer of the given commit.

Returns an arbitrary header field of the given commit.

Returns the message for the given commit.

Looks for a parent commit of the given commit by its index.

Returns the number of parents for the given commit.

Returns parent commits of the given commit.

Returns the full raw header of the given commit.

Returns the time of the given commit.

Returns the tree for the given commit.

Returns the tree id for the given commit.

Returns the value of the config entry with the given name.

Returns the value of the config entry with the given name.

Returns a config handle for the given path.

Sets the config entry with the given name to val.

Sets the config entry with the given name to val.

Returns the number of deltas in the given diff.

Returns a list of deltas for the given diff.

Returns a binary represention of the given diff.

Returns stats for the given diff.

Returns a diff with the difference between two tree objects.

Returns the number of unique commits between two commit objects.

Adds or updates the given entry.

Retrieves an entry contained in the index given its relative path.

Clears the contents (all the entries) of the given index.

Returns the number of entries in the given index.

Creates an new in-memory index object.

Looks for an entry by its position in the given index.

Reads the given tree into the given index file with stats.

Removes an entry from the given index.

Removes all entries from the given index under a given directory.

Writes the given index from memory back to disk using an atomic file lock.

Writes the given index as a tree.

Writes the given index as a tree.

Returns the libgit2 library version.

Finds the merge base (common ancestor) OID for two commits.

Merges two commits and returns the merged index. Returns {:ok, index} on success, {:error, :conflict} if there are conflicts.

Returns the OID for the given obj.

Looks for an object with the given oid.

Returns the repository that owns the given obj.

Inflates the given data with zlib.

Returns an ODB write-pack for the given odb.

Returns true if the given oid exists in odb; elsewise returns false.

Returns the OID of an object type and raw data.

Return the uncompressed, raw data of an ODB object.

Writes the given object data with the given type into the odb.

Writes the given PACK data into the odb.

Appends the given data to the odb_writepack.

Commits the written data to the odb_writepack.

Returns the SHA hash for the given oid.

Returns the abbreviated SHA hash for the given oid.

Returns the OID for the given SHA hash.

Returns a PACK file for the given pack.

Inserts commit as well as the completed referenced tree.

Inserts objects as given by the walk.

Creates a new PACK object for the given repo.

Returns true if tree matches the given pathspec; otherwise returns false.

Creates a new reference name which points to an object or to an other reference.

Deletes an existing reference.

Looks for a reference by DWIMing its short_name.

Similar to reference_list/1 but allows glob patterns.

Returns an iterator for the references that match the specific glob pattern.

Returns all references for the given repo.

Returns true if a reflog exists for the given reference name.

Looks for a reference by name.

Returns the next reference.

Recursively peels the given reference name until an object of type type is found.

Resolves a symbolic reference to a direct reference.

Returns a stream for the references that match the specific glob pattern.

Looks for a reference by name and returns its id.

Reads the number of entry for the given reflog name.

Deletes the reflog for the given reference name.

Reads the reflog for the given reference name.

Returns true if repo is bare; elsewise returns false.

Clones a repository from url into local_path. Runs on a dirty IO scheduler.

Looks for a repository and returns its path.

Returns true if repo is empty; elsewise returns false.

Returns the config for the given repo.

Returns the index for the given repository.

Returns the ODB for the given repository.

Returns the absolute path for the given repo.

Returns the normalized path to the working directory for the given repo.

Initializes a new repository at the given path.

Returns a repository handle for the path.

Finds a single object and intermediate reference, as specified by the given revision.

Finds a single object, as specified by the given revision.

Creates a new revision walk object for the given repo.

Returns the next commit from the given revision walk.

Returns a PACK file for the given walk.

Adds a new root for the traversal.

Returns the repository on which the given walker is operating.

Resets the revision walk for reuse.

Simplifies the history by first-parent.

Changes the sorting mode when iterating through the repository's contents.

Returns a stream for the given revision walk.

Returns the default signature for the given repo.

Creates a new signature with the given name and email.

Creates a new signature with the given name, email and time.

Returns the author of the given tag.

Returns all tags for the given repo.

Returns the message of the given tag.

Returns the name of the given tag.

Recursively peels the given tag until a non tag object is found.

Retrieves a tree entry owned by the given tree, given its id.

Retrieves a tree entry contained in the given tree or in any of its subtrees, given its relative path.

Returns the number of entries listed in the given tree.

Returns all entries in the given tree.

Looks for a tree entry by its position in the given tree.

Adds a new working tree for the given repo

Prunes a working tree.

Types

blob()

@type blob() :: reference()

commit()

@type commit() :: reference()

config()

@type config() :: reference()

diff()

@type diff() :: reference()

diff_delta()

@type diff_delta() :: {diff_file(), diff_file(), non_neg_integer(), non_neg_integer()}

diff_file()

@type diff_file() :: {oid(), binary(), integer(), non_neg_integer()}

diff_format()

@type diff_format() :: :patch | :patch_header | :raw | :name_only | :name_status

diff_hunk()

@type diff_hunk() :: {binary(), integer(), integer(), integer(), integer()}

diff_line()

@type diff_line() :: {char(), integer(), integer(), integer(), integer(), binary()}

index()

@type index() :: reference()

index_entry()

indexer_progress()

@type indexer_progress() :: reference()

obj()

@type obj() :: blob() | commit() | tree() | tag()

obj_type()

@type obj_type() :: :blob | :commit | :tree | :tag

odb()

@type odb() :: reference()

odb_type()

@type odb_type() :: atom()

odb_writepack()

@type odb_writepack() :: reference()

odb_writepack_progress()

@type odb_writepack_progress() :: map()

oid()

@type oid() :: binary()

pack()

@type pack() :: reference()

ref_iter()

@type ref_iter() :: reference()

ref_type()

@type ref_type() :: :oid | :symbolic

reflog_entry()

@type reflog_entry() ::
  {binary(), binary(), non_neg_integer(), non_neg_integer(), oid(), oid(),
   binary()}

repo()

@type repo() :: reference()

revwalk()

@type revwalk() :: reference()

revwalk_sort()

@type revwalk_sort() :: :sort_topo | :sort_time | :sort_reverse

signature()

@type signature() :: {binary(), binary(), non_neg_integer(), non_neg_integer()}

tag()

@type tag() :: reference()

tree()

@type tree() :: reference()

tree_entry()

@type tree_entry() :: {integer(), :blob | :tree, oid(), binary()}

worktree()

@type worktree() :: reference()

Functions

blame_file(repo, path, newest_commit_oid)

@spec blame_file(repo(), Path.t(), binary() | nil) ::
  {:ok,
   [{binary(), pos_integer(), pos_integer(), binary(), binary(), integer()}]}
  | {:error, term()}

Returns blame hunks for path in repo.

Each hunk is a tuple {oid, start_line, line_count, author_name, author_email, timestamp} where start_line is 1-based, and timestamp is Unix seconds.

blob_content(blob)

@spec blob_content(blob()) :: {:ok, binary()} | {:error, term()}

Returns the raw content of the given blob.

blob_size(blob)

@spec blob_size(blob()) :: {:ok, integer()} | {:error, term()}

Returns the size in bytes of the given blob.

commit_author(commit)

@spec commit_author(commit()) ::
  {:ok, binary(), binary(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Returns the author of the given commit.

commit_committer(commit)

@spec commit_committer(commit()) ::
  {:ok, binary(), binary(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Returns the committer of the given commit.

commit_create(repo, ref, author, commiter, encoding, message, tree, parents)

@spec commit_create(
  repo(),
  binary() | :undefined,
  signature(),
  signature(),
  binary() | :undefined,
  binary(),
  oid(),
  [binary()]
) :: {:ok, oid()} | {:error, term()}

Creates a new commit with the given params.

commit_header(commit, field)

@spec commit_header(commit(), binary()) :: {:ok, binary()} | {:error, term()}

Returns an arbitrary header field of the given commit.

commit_message(commit)

@spec commit_message(commit()) :: {:ok, binary()} | {:error, term()}

Returns the message for the given commit.

commit_parent(commit, index)

@spec commit_parent(commit(), non_neg_integer()) ::
  {:ok, oid(), commit()} | {:error, term()}

Looks for a parent commit of the given commit by its index.

commit_parent_count(commit)

@spec commit_parent_count(commit()) :: {:ok, non_neg_integer()} | {:error, term()}

Returns the number of parents for the given commit.

commit_parents(commit)

@spec commit_parents(commit()) :: {:ok, Enumerable.t()} | {:error, term()}

Returns parent commits of the given commit.

commit_raw_header(commit)

@spec commit_raw_header(commit()) :: {:ok, binary()} | {:error, term()}

Returns the full raw header of the given commit.

commit_time(commit)

@spec commit_time(commit()) ::
  {:ok, non_neg_integer(), non_neg_integer()} | {:error, term()}

Returns the time of the given commit.

commit_tree(commit)

@spec commit_tree(commit()) :: {:ok, oid(), tree()} | {:error, term()}

Returns the tree for the given commit.

commit_tree_id(commit)

@spec commit_tree_id(commit()) :: oid()

Returns the tree id for the given commit.

config_get_bool(config, name)

@spec config_get_bool(config(), binary()) :: {:ok, boolean()} | {:error, term()}

Returns the value of the config entry with the given name.

config_get_string(config, name)

@spec config_get_string(config(), binary()) :: {:ok, binary()} | {:error, term()}

Returns the value of the config entry with the given name.

config_open(path)

@spec config_open(binary()) :: {:ok, config()} | {:error, term()}

Returns a config handle for the given path.

config_set_bool(config, name, val)

@spec config_set_bool(config(), binary(), boolean()) :: :ok | {:error, term()}

Sets the config entry with the given name to val.

config_set_string(config, name, val)

@spec config_set_string(config(), binary(), binary()) :: :ok | {:error, term()}

Sets the config entry with the given name to val.

diff_delta_count(diff)

@spec diff_delta_count(diff()) :: {:ok, non_neg_integer()} | {:error, term()}

Returns the number of deltas in the given diff.

diff_deltas(diff)

@spec diff_deltas(diff()) ::
  {:ok, [{diff_delta(), [{diff_hunk(), [diff_line()]}]}]} | {:error, term()}

Returns a list of deltas for the given diff.

diff_format(diff, format \\ :patch)

@spec diff_format(diff(), diff_format()) :: {:ok, binary()} | {:error, term()}

Returns a binary represention of the given diff.

diff_stats(diff)

@spec diff_stats(diff()) ::
  {:ok, non_neg_integer(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Returns stats for the given diff.

diff_tree(repo, old_tree, new_tree, opts \\ [])

Returns a diff with the difference between two tree objects.

graph_ahead_behind(repo, local, upstream)

@spec graph_ahead_behind(repo(), oid(), oid()) ::
  {:ok, non_neg_integer(), non_neg_integer()} | {:error, term()}

Returns the number of unique commits between two commit objects.

index_add(index, entry)

@spec index_add(index(), index_entry()) :: :ok | {:error, term()}

Adds or updates the given entry.

index_bypath(index, path, stage)

Retrieves an entry contained in the index given its relative path.

index_clear(index)

@spec index_clear(index()) :: :ok | {:error, term()}

Clears the contents (all the entries) of the given index.

index_count(index)

@spec index_count(index()) :: non_neg_integer()

Returns the number of entries in the given index.

index_new()

@spec index_new() :: {:ok, index()} | {:error, term()}

Creates an new in-memory index object.

index_nth(index, nth)

Looks for an entry by its position in the given index.

index_read_tree(index, tree)

@spec index_read_tree(index(), tree()) :: :ok | {:error, term()}

Reads the given tree into the given index file with stats.

index_remove(index, path, stage \\ 0)

@spec index_remove(index(), Path.t(), non_neg_integer()) :: :ok | {:error, term()}

Removes an entry from the given index.

index_remove_dir(index, path, stage \\ 0)

@spec index_remove_dir(index(), Path.t(), non_neg_integer()) :: :ok | {:error, term()}

Removes all entries from the given index under a given directory.

index_write(index)

@spec index_write(index()) :: :ok | {:error, term()}

Writes the given index from memory back to disk using an atomic file lock.

index_write_tree(index)

@spec index_write_tree(index()) :: {:ok, oid()} | {:error, term()}

Writes the given index as a tree.

index_write_tree(index, repo)

@spec index_write_tree(index(), repo()) :: {:ok, oid()} | {:error, term()}

Writes the given index as a tree.

library_version()

@spec library_version() :: {integer(), integer(), integer()}

Returns the libgit2 library version.

merge_base(repo, oid1, oid2)

@spec merge_base(repo(), oid(), oid()) :: {:ok, oid()} | {:error, term()}

Finds the merge base (common ancestor) OID for two commits.

merge_commits(repo, our_commit, their_commit)

@spec merge_commits(repo(), obj(), obj()) ::
  {:ok, index()} | {:error, :conflict} | {:error, term()}

Merges two commits and returns the merged index. Returns {:ok, index} on success, {:error, :conflict} if there are conflicts.

object_id(obj)

@spec object_id(obj()) :: {:ok, oid()} | {:error, term()}

Returns the OID for the given obj.

object_lookup(repo, oid)

@spec object_lookup(repo(), oid()) :: {:ok, obj_type(), obj()} | {:error, term()}

Looks for an object with the given oid.

object_repository(obj)

@spec object_repository(obj()) :: {:ok, repo()} | {:error, term()}

Returns the repository that owns the given obj.

object_zlib_inflate(data, buffer_size \\ 16384)

@spec object_zlib_inflate(binary(), pos_integer()) ::
  {:ok, iodata(), non_neg_integer()} | {:error, term()}

Inflates the given data with zlib.

odb_get_writepack(odb)

@spec odb_get_writepack(odb()) :: {:ok, odb_writepack()} | {:error, term()}

Returns an ODB write-pack for the given odb.

odb_object_exists?(odb, oid)

@spec odb_object_exists?(odb(), oid()) :: boolean()

Returns true if the given oid exists in odb; elsewise returns false.

odb_object_hash(type, data)

@spec odb_object_hash(obj_type(), binary()) :: {:ok, oid()} | {:error, term()}

Returns the OID of an object type and raw data.

The resulting SHA-1 OID will be the identifier for the data buffer as if the data buffer it were to written to the ODB.

odb_read(odb, oid)

@spec odb_read(odb(), oid()) :: {:ok, obj_type(), binary()} | {:error, term()}

Return the uncompressed, raw data of an ODB object.

odb_write(odb, data, type)

@spec odb_write(odb(), binary(), odb_type()) :: {:ok, oid()} | {:error, term()}

Writes the given object data with the given type into the odb.

odb_write_pack(odb, data)

@spec odb_write_pack(odb(), binary()) :: :ok | {:error, term()}

Writes the given PACK data into the odb.

odb_writepack_append(odb_writepack, data, progress)

@spec odb_writepack_append(odb_writepack(), binary(), odb_writepack_progress()) ::
  {:ok, odb_writepack_progress()} | {:error, term()}

Appends the given data to the odb_writepack.

odb_writepack_commit(odb_writepack, progress)

@spec odb_writepack_commit(odb_writepack(), odb_writepack_progress()) ::
  :ok | {:error, term()}

Commits the written data to the odb_writepack.

oid_fmt(oid)

@spec oid_fmt(oid()) :: binary()

Returns the SHA hash for the given oid.

oid_fmt_short(oid)

@spec oid_fmt_short(oid()) :: binary()

Returns the abbreviated SHA hash for the given oid.

oid_parse(hash)

@spec oid_parse(binary()) :: oid()

Returns the OID for the given SHA hash.

pack_data(pack)

@spec pack_data(pack()) :: {:ok, binary()} | {:error, term()}

Returns a PACK file for the given pack.

pack_insert_commit(pack, oid)

@spec pack_insert_commit(pack(), oid()) :: :ok | {:error, term()}

Inserts commit as well as the completed referenced tree.

pack_insert_walk(pack, walk)

@spec pack_insert_walk(pack(), revwalk()) :: :ok | {:error, term()}

Inserts objects as given by the walk.

pack_new(repo)

@spec pack_new(repo()) :: {:ok, pack()} | {:error, term()}

Creates a new PACK object for the given repo.

pathspec_match_tree(tree, pathspec)

@spec pathspec_match_tree(tree(), [binary()]) :: {:ok, boolean()} | {:error, term()}

Returns true if tree matches the given pathspec; otherwise returns false.

reference_create(repo, name, type, target, force \\ false)

@spec reference_create(repo(), binary(), ref_type(), binary() | oid(), boolean()) ::
  :ok | {:error, term()}

Creates a new reference name which points to an object or to an other reference.

reference_delete(repo, name)

@spec reference_delete(repo(), binary()) :: :ok | {:error, term()}

Deletes an existing reference.

reference_dwim(repo, short_name)

@spec reference_dwim(repo(), binary()) ::
  {:ok, binary(), ref_type(), binary()} | {:error, term()}

Looks for a reference by DWIMing its short_name.

reference_glob(repo, glob)

@spec reference_glob(repo(), binary()) :: {:ok, [binary()]} | {:error, term()}

Similar to reference_list/1 but allows glob patterns.

reference_iterator(repo, glob \\ :undefined)

@spec reference_iterator(repo(), binary() | :undefined) ::
  {:ok, ref_iter()} | {:error, term()}

Returns an iterator for the references that match the specific glob pattern.

reference_list(repo)

@spec reference_list(repo()) :: {:ok, [binary()]} | {:error, term()}

Returns all references for the given repo.

reference_log?(repo, name)

@spec reference_log?(repo(), binary()) :: {:ok, boolean()} | {:error, term()}

Returns true if a reflog exists for the given reference name.

reference_lookup(repo, name)

@spec reference_lookup(repo(), binary()) ::
  {:ok, binary(), ref_type(), binary()} | {:error, term()}

Looks for a reference by name.

reference_next(iter)

@spec reference_next(ref_iter()) ::
  {:ok, binary(), binary(), ref_type(), binary()} | {:error, term()}

Returns the next reference.

reference_peel(repo, name, type \\ :undefined)

@spec reference_peel(repo(), binary(), obj_type() | :undefined) ::
  {:ok, obj_type(), oid(), obj()} | {:error, term()}

Recursively peels the given reference name until an object of type type is found.

reference_resolve(repo, name)

@spec reference_resolve(repo(), binary()) ::
  {:ok, binary(), binary(), oid()} | {:error, term()}

Resolves a symbolic reference to a direct reference.

reference_stream(repo, glob \\ :undefined)

@spec reference_stream(repo(), binary() | :undefined) ::
  {:ok, Enumerable.t()} | {:error, term()}

Returns a stream for the references that match the specific glob pattern.

reference_to_id(repo, name)

@spec reference_to_id(repo(), binary()) :: {:ok, oid()} | {:error, term()}

Looks for a reference by name and returns its id.

reflog_count(repo, name)

@spec reflog_count(repo(), binary()) :: {:ok, pos_integer()} | {:error, term()}

Reads the number of entry for the given reflog name.

reflog_delete(repo, name)

@spec reflog_delete(repo(), binary()) :: :ok | {:error, term()}

Deletes the reflog for the given reference name.

reflog_read(repo, name)

@spec reflog_read(repo(), binary()) :: {:ok, [reflog_entry()]} | {:error, term()}

Reads the reflog for the given reference name.

repository_bare?(repo)

@spec repository_bare?(repo()) :: boolean()

Returns true if repo is bare; elsewise returns false.

repository_clone(url, local_path, bare \\ true)

@spec repository_clone(binary(), Path.t(), boolean()) ::
  {:ok, repo()} | {:error, term()}

Clones a repository from url into local_path. Runs on a dirty IO scheduler.

repository_discover(path)

@spec repository_discover(Path.t()) :: {:ok, Path.t()} | {:error, term()}

Looks for a repository and returns its path.

repository_empty?(repo)

@spec repository_empty?(repo()) :: boolean()

Returns true if repo is empty; elsewise returns false.

repository_get_config(repo)

@spec repository_get_config(repo()) :: {:ok, config()} | {:error, term()}

Returns the config for the given repo.

repository_get_index(repo)

@spec repository_get_index(repo()) :: {:ok, index()} | {:error, term()}

Returns the index for the given repository.

repository_get_odb(repo)

@spec repository_get_odb(repo()) :: {:ok, odb()} | {:error, term()}

Returns the ODB for the given repository.

repository_get_path(repo)

@spec repository_get_path(repo()) :: Path.t()

Returns the absolute path for the given repo.

repository_get_workdir(repo)

@spec repository_get_workdir(repo()) :: Path.t()

Returns the normalized path to the working directory for the given repo.

repository_init(path, bare \\ false, initial_head \\ "master")

@spec repository_init(Path.t(), boolean(), binary()) ::
  {:ok, repo()} | {:error, term()}

Initializes a new repository at the given path.

repository_open(path)

@spec repository_open(Path.t()) :: {:ok, repo()} | {:error, term()}

Returns a repository handle for the path.

revparse_ext(repo, revision)

@spec revparse_ext(repo(), binary()) ::
  {:ok, obj(), obj_type(), oid(), binary() | nil} | {:error, term()}

Finds a single object and intermediate reference, as specified by the given revision.

revparse_single(repo, revision)

@spec revparse_single(repo(), binary()) ::
  {:ok, obj(), obj_type(), oid()} | {:error, term()}

Finds a single object, as specified by the given revision.

revwalk_new(repo)

@spec revwalk_new(repo()) :: {:ok, reference()} | {:error, term()}

Creates a new revision walk object for the given repo.

revwalk_next(walk)

@spec revwalk_next(revwalk()) :: {:ok, oid()} | {:error, term()}

Returns the next commit from the given revision walk.

revwalk_pack(walk)

@spec revwalk_pack(revwalk()) :: {:ok, binary()} | {:error, term()}

Returns a PACK file for the given walk.

revwalk_push(walk, oid, hide \\ false)

@spec revwalk_push(revwalk(), oid(), boolean()) :: :ok | {:error, term()}

Adds a new root for the traversal.

revwalk_repository(walk)

@spec revwalk_repository(revwalk()) :: {:ok, repo()} | {:error, term()}

Returns the repository on which the given walker is operating.

revwalk_reset(walk)

@spec revwalk_reset(revwalk()) :: revwalk()

Resets the revision walk for reuse.

revwalk_simplify_first_parent(walk)

@spec revwalk_simplify_first_parent(revwalk()) :: :ok | {:error, term()}

Simplifies the history by first-parent.

revwalk_sorting(walk, sort_mode)

@spec revwalk_sorting(revwalk(), [revwalk_sort()]) :: :ok | {:error, term()}

Changes the sorting mode when iterating through the repository's contents.

revwalk_stream(walk)

@spec revwalk_stream(revwalk()) :: {:ok, ExGitEngine.GitStream.t()} | {:error, term()}

Returns a stream for the given revision walk.

signature_default(repo)

@spec signature_default(repo()) ::
  {:ok, binary(), binary(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Returns the default signature for the given repo.

signature_new(name, email)

@spec signature_new(binary(), binary()) :: {:ok, binary(), binary()}

Creates a new signature with the given name and email.

signature_new(name, email, time)

@spec signature_new(binary(), binary(), non_neg_integer()) ::
  {:ok, binary(), binary(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Creates a new signature with the given name, email and time.

tag_author(tag)

@spec tag_author(tag()) ::
  {:ok, binary(), binary(), non_neg_integer(), non_neg_integer()}
  | {:error, term()}

Returns the author of the given tag.

tag_list(repo)

@spec tag_list(repo()) :: {:ok, [binary()]} | {:error, term()}

Returns all tags for the given repo.

tag_message(tag)

@spec tag_message(tag()) :: {:ok, binary()} | {:error, term()}

Returns the message of the given tag.

tag_name(tag)

@spec tag_name(tag()) :: {:ok, binary()} | {:error, term()}

Returns the name of the given tag.

tag_peel(tag)

@spec tag_peel(tag()) :: {:ok, obj_type(), oid(), obj()} | {:error, term()}

Recursively peels the given tag until a non tag object is found.

tree_byid(tree, oid)

@spec tree_byid(tree(), oid()) ::
  {:ok, integer(), atom(), binary(), binary()} | {:error, term()}

Retrieves a tree entry owned by the given tree, given its id.

tree_bypath(tree, path)

@spec tree_bypath(tree(), Path.t()) ::
  {:ok, integer(), atom(), binary(), binary()} | {:error, term()}

Retrieves a tree entry contained in the given tree or in any of its subtrees, given its relative path.

tree_count(tree)

@spec tree_count(tree()) :: {:ok, non_neg_integer()} | {:error, term()}

Returns the number of entries listed in the given tree.

tree_entries(tree)

@spec tree_entries(tree()) :: {:ok, Enumerable.t()} | {:error, term()}

Returns all entries in the given tree.

tree_nth(tree, nth)

@spec tree_nth(tree(), non_neg_integer()) ::
  {:ok, integer(), atom(), binary(), binary()} | {:error, term()}

Looks for a tree entry by its position in the given tree.

worktree_add(repo, name, path, ref)

@spec worktree_add(repo(), binary(), binary(), binary() | :undefined) ::
  {:ok, worktree()} | {:error, term()}

Adds a new working tree for the given repo

worktree_prune(worktree)

@spec worktree_prune(worktree()) :: :ok | {:error, term()}

Prunes a working tree.