Xgit v0.4.0 Xgit.Repository behaviour View Source

Represents an abstract git repository.

Looking for Typical Git Commands?

The operations to inspect or mutate a git repository are not located in this module. (See Design Goals, below, and the README.md file in the lib/xgit folder for an explanation.)

You'll find these operations in the modules named Xgit.Api.* (none yet as of this writing) and Xgit.Plumbing.*

Design Goals

Xgit intends to allow repositories to be stored in multiple different mechanisms. While it includes built-in support for local on-disk repositories (see Xgit.Repository.OnDisk), and in-lib repositories (see Xgit.Repository.InMemory), you could envision repositories stored entirely on a remote file system or database.

Implementing a Storage Architecture

To define a new mechanism for storing a git repo, start by creating a new module that uses this module and implements the required callbacks. Consider the information stored in a typical .git directory in a local repository. You will be building an alternative to that storage mechanism.

Link to this section Summary

Types

Error codes that can be returned by delete_ref/3.

Error codes that can be returned by get_object/2.

Error codes that can be returned by get_ref/2.

Error codes that can be returned by list_refs/1.

Error codes that can be returned by put_loose_object/2.

Error codes that can be returned by put_ref/3.

t()

The process ID for a Repository process.

Functions

Returns a specification to start this module under a supervisor.

Get the default working tree if one has been attached.

Deletes a reference from the repository.

Retrieves an object from the repository.

Reads a reference from the repository.

Returns true if all objects in the list are present in the object dictionary.

Lists all references in the repository.

Writes a loose object to the repository.

Writes or updates a reference in the repository.

Attach a working tree to this repository as the default working tree.

Starts a Repository process linked to the current process.

Returns true if the argument is a PID representing a valid Repository process.

Callbacks

Deletes a reference in the repository.

Retrieves an object from the repository.

Reads a reference from the repository.

Checks for presence of multiple object Ids.

Lists all references in the repository.

Writes a loose object to the repository.

Writes or updates a reference in the repository.

Link to this section Types

Link to this type

delete_ref_reason()

View Source
delete_ref_reason() ::
  :invalid_ref | :cant_delete_file | :old_target_not_matched

Error codes that can be returned by delete_ref/3.

Link to this type

get_object_reason()

View Source
get_object_reason() :: :not_found | :invalid_object

Error codes that can be returned by get_object/2.

Link to this type

get_ref_reason()

View Source
get_ref_reason() :: :invalid_name | :not_found

Error codes that can be returned by get_ref/2.

Link to this type

list_refs_reason()

View Source
list_refs_reason() :: File.posix()

Error codes that can be returned by list_refs/1.

Link to this type

put_loose_object_reason()

View Source
put_loose_object_reason() :: :cant_create_file | :object_exists

Error codes that can be returned by put_loose_object/2.

Link to this type

put_ref_reason()

View Source
put_ref_reason() ::
  :invalid_ref
  | :cant_create_file
  | :target_not_found
  | :target_not_commit
  | :old_target_not_matched

Error codes that can be returned by put_ref/3.

The process ID for a Repository process.

Link to this section Functions

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

default_working_tree(repository)

View Source
default_working_tree(repository :: t()) ::
  Xgit.Repository.WorkingTree.t() | nil

Get the default working tree if one has been attached.

Other working trees may also be attached to this repository, but do not have special status with regard to the repository.

Link to this function

delete_ref(repository, name, opts \\ [])

View Source
delete_ref(repository :: t(), name :: Xgit.Core.Ref.name(), [
  {:old_target, Xgit.Core.ObjectId.t()}
]) :: :ok | {:error, reason :: delete_ref_reason()}

Deletes a reference from the repository.

Options

old_target: If present, a ref with this name must already exist and the target value must match the object ID provided in this option.

TO DO

Support for ref log. https://github.com/elixir-git/xgit/issues/224

Support for --no-deref option. https://github.com/elixir-git/xgit/issues/226

Return Value

:ok if deleted successfully or the reference did not exist.

{:error, :invalid_ref} if name is not a valid ref name.

{:error, :cant_delete_file} if unable to delete the storage for the reference.

{:error, :old_target_not_matched} if old_target was specified and the target ref points to a different object ID or did not exist.

Link to this function

get_object(repository, object_id)

View Source
get_object(repository :: t(), object_id :: Xgit.Core.ObjectId.t()) ::
  {:ok, object :: Xgit.Core.Object.t()}
  | {:error, reason :: get_object_reason()}

Retrieves an object from the repository.

Return Value

{:ok, object} if the object exists in the database.

{:error, :not_found} if the object does not exist in the database.

{:error, :invalid_object} if object was found, but invalid.

Link to this function

get_ref(repository, name, opts \\ [])

View Source
get_ref(repository :: t(), name :: String.t(), [{:follow_link?, boolean()}]) ::
  {:ok, ref :: Xgit.Core.Ref.t()} | {:error, reason :: get_ref_reason()}

Reads a reference from the repository.

If any existing reference exists with this name, it will be returned.

Parameters

name is the name of the reference to be found. It must be a valid name as per Xgit.Core.Ref.valid_name?/1.

Options

follow_link?: (default: true) true to follow symbolic refs

TO DO

Dereference tags? https://github.com/elixir-git/xgit/issues/228

Return Value

{:ok, ref} if the reference was found successfully. ref will be an Xgit.Core.Ref struct.

{:error, :invalid_name} if name is not a valid ref name.

{:error, :not_found} if no such reference exists.

Link to this function

has_all_object_ids?(repository, object_ids)

View Source
has_all_object_ids?(
  repository :: t(),
  object_ids :: [Xgit.Core.ObjectId.t()]
) :: boolean()

Returns true if all objects in the list are present in the object dictionary.

This limit is not enforced, but it's recommended to query for no more than ~100 object IDs at a time.

Link to this function

list_refs(repository)

View Source
list_refs(repository :: t()) ::
  {:ok, refs :: [Xgit.Core.Ref.t()]} | {:error, reason :: list_refs_reason()}

Lists all references in the repository.

Return Value

{:ok, refs} if successful. refs will be a list of Xgit.Core.Ref structs. The sequence of the list is unspecified.

{:error, reason} if unable. See list_refs_reason.

Link to this function

put_loose_object(repository, object)

View Source
put_loose_object(repository :: t(), object :: Xgit.Core.Object.t()) ::
  :ok | {:error, reason :: put_loose_object_reason()}

Writes a loose object to the repository.

Return Value

:ok if written successfully.

{:error, :cant_create_file} if unable to create the storage for the loose object.

{:error, :object_exists} if the object already exists in the database.

Link to this function

put_ref(repository, ref, opts \\ [])

View Source
put_ref(repository :: t(), ref :: Xgit.Core.Ref.t(), [
  {:old_target, Xgit.Core.ObjectId.t()}
]) :: :ok | {:error, reason :: put_ref_reason()}

Writes or updates a reference in the repository.

If any existing reference exists with this name, it will be replaced.

Options

old_target: If present, a ref with this name must already exist and the target value must match the object ID provided in this option. (There is a special value :new which instead requires that the named ref must not exist.)

TO DO

Support for ref log. https://github.com/elixir-git/xgit/issues/224

Support for --no-deref option. https://github.com/elixir-git/xgit/issues/226

Return Value

:ok if written successfully.

{:error, :invalid_ref} if the Xgit.Core.Ref structure is invalid.

{:error, :cant_create_file} if unable to create the storage for the reference.

{:error, :target_not_found} if the target object does not exist in the repository.

{:error, :target_not_commit} if the target object is not of type commit.

{:error, :old_target_not_matched} if old_target was specified and the target ref points to a different object ID.

Link to this function

set_default_working_tree(repository, working_tree)

View Source
set_default_working_tree(
  repository :: t(),
  working_tree :: Xgit.Repository.WorkingTree.t()
) :: :ok | :error

Attach a working tree to this repository as the default working tree.

Future plumbing and API commands that target this repository will use this working tree unless otherwise dictated.

Return Value

:ok if the working tree was successfully attached.

:error if a working tree was already attached or the proposed working tree was not valid.

Link to this function

start_link(module, init_arg, options)

View Source
start_link(module :: module(), init_arg :: term(), GenServer.options()) ::
  GenServer.on_start()

Starts a Repository process linked to the current process.

IMPORTANT: You should not invoke this function directly unless you are implementing a new storage implementation module that implements this behaviour.

Parameters

module is the name of a module that implements the callbacks defined in this module.

init_arg is passed to the init/1 function of module.

options are passed to GenServer.start_link/3.

Return Value

See GenServer.start_link/3.

Link to this function

valid?(repository)

View Source
valid?(repository :: term()) :: boolean()

Returns true if the argument is a PID representing a valid Repository process.

Link to this section Callbacks

Link to this callback

handle_delete_ref(state, name, list)

View Source
handle_delete_ref(state :: any(), name :: Xgit.Core.Ref.name(), [
  {:old_target, Xgit.Core.ObjectId.t()}
]) ::
  {:ok, state :: any()}
  | {:error, reason :: delete_ref_reason(), state :: any()}

Deletes a reference in the repository.

Called when delete_ref/3 is called.

Options

old_target: If present, a ref with this name must already exist and the target value must match the object ID provided in this option.

Return Value

Should return {:ok, state} if deleted successfully or the ref did not exist.

Should return {:error, :cant_delete_file} if unable to delete the storage for the ref.

Should return {:error, :old_target_not_matched} if old_target was specified and the target ref points to a different object ID or the ref did not exist.

Link to this callback

handle_get_object(state, object_id)

View Source
handle_get_object(state :: any(), object_id :: Xgit.Core.ObjectId.t()) ::
  {:ok, object :: Xgit.Core.Object.t(), state :: any()}
  | {:error, reason :: get_object_reason(), state :: any()}

Retrieves an object from the repository.

Called when get_object/2 is called.

Return Value

Should return {:ok, object, state} if read successfully.

Should return {:error, :not_found, state} if unable to find the object.

Should return {:error, :invalid_object, state} if object was found, but invalid.

Link to this callback

handle_get_ref(state, name, list)

View Source
handle_get_ref(state :: any(), name :: String.t(), [{:follow_link?, boolean()}]) ::
  {:ok, ref :: Xgit.Core.Ref.t(), state :: any()}
  | {:error, reason :: get_ref_reason(), state :: any()}

Reads a reference from the repository.

Called when get_ref/3 is called.

Options

follow_link?: (default: true) true to follow symbolic refs

Return Value

Should return {:ok, ref, state} if the reference was found successfully. ref must be an Xgit.Core.Ref struct.

Should return {:error, :not_found, state} if no such reference exists.

Link to this callback

handle_has_all_object_ids?(state, object_ids)

View Source
handle_has_all_object_ids?(
  state :: any(),
  object_ids :: [Xgit.Core.ObjectId.t()]
) :: {:ok, has_all_object_ids? :: boolean(), state :: any()}

Checks for presence of multiple object Ids.

Called when has_all_object_ids?/2 is called.

Return Value

Should return {:ok, has_all_object_ids?, state} where has_all_object_ids? is true if all object IDs can be found in the object dictionary; false otherwise.

Link to this callback

handle_list_refs(state)

View Source
handle_list_refs(state :: any()) ::
  {:ok, refs :: [Xgit.Core.Ref], state :: any()}
  | {:error, reason :: list_refs_reason(), state :: any()}

Lists all references in the repository.

Called when list_refs/1 is called.

Return Value

Should return {:ok, refs, state} if read successfully. refs should be a list of Xgit.Core.Ref structs.

Should return {:error, reason} if unable. Currently only File.posix reasons are expected.

Link to this callback

handle_put_loose_object(state, object)

View Source
handle_put_loose_object(state :: any(), object :: Xgit.Core.Object.t()) ::
  {:ok, state :: any()}
  | {:error, reason :: put_loose_object_reason(), state :: any()}

Writes a loose object to the repository.

Called when put_loose_object/2 is called.

Return Value

Should return {:ok, state} if written successfully.

Should return {:error, :cant_create_file} if unable to create the storage for the loose object.

Should return {:error, :object_exists} if the object already exists in the database.

Link to this callback

handle_put_ref(state, ref, list)

View Source
handle_put_ref(state :: any(), ref :: Xgit.Core.Ref.t(), [
  {:old_target, Xgit.Core.ObjectId.t()}
]) ::
  {:ok, state :: any()} | {:error, reason :: put_ref_reason(), state :: any()}

Writes or updates a reference in the repository.

Called when put_ref/3 is called.

The implementation must validate that the referenced object exists and is of type commit. It does not need to validate that the reference is otherwise valid.

Options

old_target: If present, a ref with this name must already exist and the target value must match the object ID provided in this option. (There is a special value :new which instead requires that the named ref must not exist.)

Return Value

Should return {:ok, state} if written successfully.

Should return {:error, :cant_create_file} if unable to create the storage for the ref.

Should return {:error, :target_not_found} if the target object does not exist in the repository.

Should return {:error, :target_not_commit} if the target object is not of type commit.

Should return {:error, :old_target_not_matched} if old_target was specified and the target ref points to a different object ID.