Files
geef/src/geef_ref.erl
Carlos Martín Nieto fe4c72a811 Expose utility ref-type functions
These allow you to determine whether you're dealing with a branch, tag,
note or remote-tracking branch.
2014-02-15 01:38:33 +01:00

132 lines
4.4 KiB
Erlang

-module(geef_ref).
-export([lookup/2, iterator/1, iterator/2, next/1, resolve/1, create/4, create_symbolic/4, dwim/2, shorthand/1]).
-export([has_log/1, has_log/2]).
-export([is_branch/1, is_tag/1, is_note/1, is_remote/1]).
-include("geef_records.hrl").
-type iterator() :: #geef_iterator{type :: ref}.
-type type() :: oid | symbolic.
-type target() :: binary() | geef_oid:oid().
-type ref() :: #geef_reference{repo :: pid(), name :: binary()}.
-export_type([reference/0, type/0, target/0, iterator/0]).
-spec create(pid(), iolist(), geef_oid:oid(), boolean()) -> {ok, ref()} | {error, term()}.
create(Repo, Refname, Target, Force) ->
RepoHandle = geef_repo:handle(Repo),
case geef_nif:reference_create(RepoHandle, Refname, oid, Target, Force) of
ok ->
{ok, make(Repo, iolist_to_binary(Refname), oid, Target)};
Err = {error, _} ->
Err
end.
-spec create_symbolic(pid(), iolist(), iolist(), boolean()) -> {ok, ref()} | {error, term()}.
create_symbolic(Repo, Refname, Target, Force) ->
RepoHandle = geef_repo:handle(Repo),
case geef_nif:reference_create(RepoHandle, Refname, symbolic, Target, Force) of
ok ->
{ok, make(Repo, iolist_to_binary(Refname), symbolic, iolist_to_binary(Target))};
Err = {error, _} ->
Err
end.
-spec make(pid(), binary(), type(), target()) -> ref().
make(Repo, Name, oid, Target) ->
#geef_reference{repo=Repo, name=Name, type=oid, target=Target};
make(Repo, Name, symbolic, Target) ->
#geef_reference{repo=Repo, name=Name, type=symbolic, target=Target}.
-spec lookup(pid(), iolist()) -> {ok, ref()} | {error, term()}.
lookup(Repo, Refname) ->
Name = iolist_to_binary(Refname),
RepoHandle = geef_repo:handle(Repo),
case geef_nif:reference_lookup(RepoHandle, Name) of
{ok, Type, Target} ->
{ok, make(Repo, Name, Type, Target)};
Other ->
Other
end.
-spec iterator(pid(), iolist() | undefined) -> {ok, iterator()} | {error, term()}.
iterator(Repo, Regexp) ->
case geef_repo:iterator(Repo, Regexp) of
{ok, Handle} ->
{ok, #geef_iterator{type=ref, repo=Repo, regexp=Regexp, handle=Handle}};
Other ->
Other
end.
-spec iterator(pid()) -> {ok, iterator()} | {error, term()}.
iterator(Repo) ->
iterator(Repo, undefined).
-spec next(iterator()) -> {ok, ref()} | {error, term()}.
next(#geef_iterator{type=ref, repo=Repo, handle=Handle}) ->
case geef_nif:reference_next(Handle) of
{ok, Name, Type, Target} ->
{ok, make(Repo, Name, Type, Target)};
Other ->
Other
end.
-spec resolve(ref()) -> {ok, ref()} | {error, term()}.
resolve(Ref = #geef_reference{type=oid}) ->
{ok, Ref}; % resolving an oid ref is a no-op, skip going into the NIF
resolve(#geef_reference{repo=Repo, type=symbolic, target=Name}) ->
RepoHandle = geef_repo:handle(Repo),
case geef_nif:reference_resolve(RepoHandle, Name) of
{ok, ResolvedName, Target} ->
{ok, make(Repo, ResolvedName, oid, Target)};
Other = {error, _} ->
Other
end.
-spec dwim(pid(), iolist()) -> {ok, ref()} | {error, term()}.
dwim(Repo, Name) ->
RepoHandle = geef_repo:handle(Repo),
case geef_nif:reference_dwim(RepoHandle, Name) of
{ok, RealName, Type, Target} ->
{ok, make(Repo, RealName, Type, Target)};
Err = {error, _}->
Err
end.
%% @doc Get the shorthand name for a particular reference
-spec shorthand(ref() | binary()) -> binary().
shorthand(<<"refs/heads/", Rest/binary>>) ->
Rest;
shorthand(<<"refs/tags/", Rest/binary>>) ->
Rest;
shorthand(<<"refs/remotes/", Rest/binary>>) ->
Rest;
shorthand(<<"refs/", Rest/binary>>) ->
Rest;
shorthand(#geef_reference{name=Name}) ->
shorthand(Name).
%% @doc Return whether the reference has a reflog
-spec has_log(pid(), iolist() | binary()) -> {ok, boolean()} | {error, term()}.
has_log(Repo, Name) ->
geef_repo:reference_has_log(Repo, Name).
-spec has_log(ref()) -> {ok, boolean()} | {error, term()}.
has_log(#geef_reference{repo=Repo, name=Name}) ->
has_log(Repo, Name).
-define(assert_prefix(FunctionName, Prefix),
FunctionName(<<Prefix, _/binary>>) ->
true;
FunctionName(#geef_reference{name=Name}) ->
FunctionName(Name);
FunctionName(Name) when is_list(Name) ->
FunctionName(iolist_to_binary(Name));
FunctionName(_) ->
false).
?assert_prefix(is_branch, "refs/heads/").
?assert_prefix(is_tag, "refs/tags/").
?assert_prefix(is_note, "refs/notes/").
?assert_prefix(is_remote, "refs/remotes/").