add Geef.Revwalk module for Elixir
This commit is contained in:
committed by
Carlos Martín Nieto
parent
01254f2f90
commit
79f89bcd41
@@ -108,6 +108,18 @@ geef_revwalk_sorting(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
return atoms.ok;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM
|
||||
geef_revwalk_simplify_first_parent(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
geef_revwalk *walk;
|
||||
|
||||
if (!enif_get_resource(env, argv[0], geef_revwalk_type, (void **) &walk))
|
||||
return enif_make_badarg(env);
|
||||
|
||||
git_revwalk_simplify_first_parent(walk->walk);
|
||||
|
||||
return atoms.ok;
|
||||
}
|
||||
|
||||
ERL_NIF_TERM
|
||||
geef_revwalk_reset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
|
||||
@@ -18,6 +18,7 @@ ERL_NIF_TERM geef_revwalk_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[
|
||||
ERL_NIF_TERM geef_revwalk_next(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM geef_revwalk_push(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM geef_revwalk_sorting(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM geef_revwalk_simplify_first_parent(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
ERL_NIF_TERM geef_revwalk_reset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@ defmodule Geef do
|
||||
alias Geef.Oid
|
||||
alias Geef.Reference
|
||||
alias Geef.Repository
|
||||
alias Geef.Revwalk
|
||||
alias Geef.Signature
|
||||
alias Geef.Tree
|
||||
alias Geef.Tag
|
||||
|
||||
@@ -18,6 +18,7 @@ defmodule Geef.Repository do
|
||||
def gitdir(repo), do: :geef_repo.path(repo)
|
||||
def workdir(repo), do: :geef_repo.workdir(repo)
|
||||
def config(repo), do: :geef_repo.config(repo)
|
||||
def revwalk(repo), do: :geef_repo.revwalk(repo)
|
||||
|
||||
def reference_names(repo), do: :geef_repo.references(repo)
|
||||
end
|
||||
|
||||
32
lib/geef/revwalk.ex
Normal file
32
lib/geef/revwalk.ex
Normal file
@@ -0,0 +1,32 @@
|
||||
defmodule Geef.Revwalk do
|
||||
import Geef
|
||||
alias Geef.Object
|
||||
|
||||
def stop(walk), do: :geef_revwalk.stop(walk)
|
||||
|
||||
def open(repo) when is_pid(repo), do: Repository.revwalk(repo)
|
||||
def open!(arg), do: open(arg) |> assert_ok
|
||||
|
||||
def push(walk, %Object{type: :commit, id: commit}), do: push(walk, commit)
|
||||
def push(walk, commit), do: :geef_revwalk.push(walk, commit)
|
||||
|
||||
def hide(walk, %Object{type: :commit, id: commit}), do: hide(walk, commit)
|
||||
def hide(walk, commit), do: :geef_revwalk.hide(walk, commit)
|
||||
|
||||
def simplify_first_parent(walk), do: :geef_revwalk.simplify_first_parent(walk)
|
||||
|
||||
def sorting(walk, flags \\ [])
|
||||
def sorting(walk, flags) when is_list(flags) do
|
||||
flags = Enum.map(flags, &compile_sorting_flag/1)
|
||||
:geef_revwalk.sorting(walk, flags)
|
||||
end
|
||||
def sorting(walk, flag), do: sorting(walk, [flag])
|
||||
|
||||
def next(walk), do: :geef_revwalk.next(walk)
|
||||
|
||||
def reset(walk), do: :geef_revwalk.reset(walk)
|
||||
|
||||
defp compile_sorting_flag(:topological_sort), do: :toposort
|
||||
defp compile_sorting_flag(:time_sort), do: :timesort
|
||||
defp compile_sorting_flag(:reverse_sort), do: :reversesort
|
||||
end
|
||||
@@ -159,6 +159,9 @@ revwalk_next(_Walk) ->
|
||||
revwalk_sorting(_Walk, _Sort) ->
|
||||
?NIF_FN.
|
||||
|
||||
revwalk_simplify_first_parent(_Walk) ->
|
||||
?NIF_FN.
|
||||
|
||||
revwalk_reset(_Walk) ->
|
||||
?NIF_FN.
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
%% API
|
||||
-export([open/1, init/2, path/1, workdir/1, odb/1, is_bare/1, references/1, discover/1,
|
||||
lookup_object/2, revwalk/1, stop/1,
|
||||
reference_dwim/2, handle/1, iterator/2]).
|
||||
lookup_object/2, revwalk/1, stop/1,
|
||||
reference_dwim/2, handle/1, iterator/2]).
|
||||
-export([reference_has_log/2]).
|
||||
-export([reference_resolve/2]).
|
||||
-export([reflog_read/2, reflog_delete/2]).
|
||||
@@ -37,20 +37,20 @@ discover(Path) ->
|
||||
-spec open(iolist()) -> {ok, pid()} | {error, term()}.
|
||||
open(Path) ->
|
||||
case geef_nif:repository_open(Path) of
|
||||
{ok, Handle} ->
|
||||
start_link(Handle);
|
||||
Other ->
|
||||
Other
|
||||
{ok, Handle} ->
|
||||
start_link(Handle);
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
%% @doc Initialize a new repository
|
||||
-spec init(iolist(), boolean()) -> {ok, pid()} | {error, term()}.
|
||||
init(Path, Bare) ->
|
||||
case geef_nif:repository_init(Path, Bare) of
|
||||
{ok, Handle} ->
|
||||
start_link(Handle);
|
||||
Other ->
|
||||
Other
|
||||
{ok, Handle} ->
|
||||
start_link(Handle);
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
%% @doc The repository's git-dir path
|
||||
@@ -224,18 +224,18 @@ start_link(Handle) ->
|
||||
|
||||
handle_odb(Handle) ->
|
||||
case geef_nif:repository_get_odb(Handle) of
|
||||
{ok, OdbHandle} ->
|
||||
geef_odb:start_link(OdbHandle);
|
||||
Other ->
|
||||
Other
|
||||
{ok, OdbHandle} ->
|
||||
geef_odb:start_link(OdbHandle);
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
handle_revwalk(Handle) ->
|
||||
case geef_nif:revwalk_new(Handle) of
|
||||
{ok, WalkHandle} ->
|
||||
geef_revwalk:start_link(WalkHandle);
|
||||
Error ->
|
||||
Error
|
||||
{ok, WalkHandle} ->
|
||||
geef_revwalk:start_link(WalkHandle);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
handle_config(Handle) ->
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
|
||||
%% API
|
||||
-export([start_link/1]).
|
||||
-export([push/2, hide/2, next/1, sorting/2, stop/1]).
|
||||
-export([push/2, hide/2, next/1, sorting/2, simplify_first_parent/1, reset/1, stop/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-record(state, {handle}).
|
||||
-include("geef_records.hrl").
|
||||
@@ -46,7 +46,16 @@ sorting(Pid, Opts) when is_list(Opts) ->
|
||||
sorting(Pid, Opt) when is_atom(Opt) ->
|
||||
gen_server:call(Pid, {sort, [Opt]}).
|
||||
|
||||
-spec simplify_first_parent(pid) -> ok.
|
||||
simplify_first_parent(Pid) ->
|
||||
gen_server:call(Pid, simplify_first_parent).
|
||||
|
||||
-spec reset(pid) -> ok.
|
||||
reset(Pid) ->
|
||||
gen_server:call(Pid, reset).
|
||||
|
||||
%% @doc Next commit in the walk
|
||||
-spec next(pid) -> {ok, geef_oid:oid()} | {error, iterover}.
|
||||
next(Pid) ->
|
||||
gen_server:call(Pid, next).
|
||||
|
||||
@@ -76,12 +85,18 @@ init(Handle) ->
|
||||
handle_call({sort, Opts}, _From, State = #state{handle=Handle}) ->
|
||||
geef_nif:revwalk_sorting(Handle, Opts),
|
||||
{reply, ok, State};
|
||||
handle_call(simplify_first_parent, _From, State = #state{handle=Handle}) ->
|
||||
geef_nif:revwalk_simplify_first_parent(Handle),
|
||||
{reply, ok, State};
|
||||
handle_call({push, Oid}, _From, State = #state{handle=Handle}) ->
|
||||
Reply = geef_nif:revwalk_push(Handle, Oid, false),
|
||||
{reply, Reply, State};
|
||||
handle_call({hide, Oid}, _From, State = #state{handle=Handle}) ->
|
||||
Reply = geef_nif:revwalk_push(Handle, Oid, true),
|
||||
{reply, Reply, State};
|
||||
handle_call(reset, _From, State = #state{handle=Handle}) ->
|
||||
geef_nif:revwalk_reset(Handle),
|
||||
{reply, ok, State};
|
||||
handle_call(next, _From, State = #state{handle=Handle}) ->
|
||||
Reply = geef_nif:revwalk_next(Handle),
|
||||
{reply, Reply, State};
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
repo_test_() ->
|
||||
case os:getenv("GEEF_RESOURCES") of
|
||||
false ->
|
||||
[];
|
||||
_ ->
|
||||
{foreach, fun start/0, fun stop/1, [fun amount_test/1]}
|
||||
false ->
|
||||
[];
|
||||
_ ->
|
||||
{foreach, fun start/0, fun stop/1, [fun amount_test/1]}
|
||||
end.
|
||||
|
||||
start() ->
|
||||
@@ -18,10 +18,10 @@ start() ->
|
||||
|
||||
count_walk(Walk, Acc) ->
|
||||
case geef_revwalk:next(Walk) of
|
||||
{ok, _} ->
|
||||
count_walk(Walk, Acc + 1);
|
||||
{error, iterover} ->
|
||||
Acc
|
||||
{ok, _} ->
|
||||
count_walk(Walk, Acc + 1);
|
||||
{error, iterover} ->
|
||||
Acc
|
||||
end.
|
||||
|
||||
amount_test(Repo) ->
|
||||
|
||||
29
test/revwalk_test.exs
Normal file
29
test/revwalk_test.exs
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule RevwalkTest do
|
||||
use ExUnit.Case
|
||||
use Geef
|
||||
import RepoHelpers
|
||||
|
||||
|
||||
setup do
|
||||
{repo, path, head, boring_ancestor} = tmp_commit_line
|
||||
Process.link(repo)
|
||||
{:ok, walk} = Repository.revwalk(repo)
|
||||
on_exit(fn -> File.rm_rf!(path) end)
|
||||
{:ok, [walk: walk, head: head, boring_ancestor: boring_ancestor]}
|
||||
end
|
||||
|
||||
test "walk and count", meta do
|
||||
walk = meta[:walk]
|
||||
Revwalk.push(walk, meta[:head])
|
||||
Revwalk.hide(walk, meta[:boring_ancestor])
|
||||
assert 3 = count_walk(walk)
|
||||
end
|
||||
|
||||
defp count_walk walk, acc \\ 0
|
||||
defp count_walk walk, acc do
|
||||
case Revwalk.next(walk) do
|
||||
{:ok, _} -> count_walk(walk, acc + 1)
|
||||
{:error, :iterover} -> acc
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,12 +1,33 @@
|
||||
ExUnit.start
|
||||
|
||||
defmodule RepoHelpers do
|
||||
use Geef
|
||||
|
||||
def tmp_bare do
|
||||
{a, b, c} = :erlang.timestamp()
|
||||
n = node()
|
||||
dir = :io_lib.format("geef-~p~p~p~p.git", [n, a, b, c])
|
||||
path = Path.join(System.tmp_dir!, dir)
|
||||
{:ok, repo} = Geef.Repository.init(path, true)
|
||||
{:ok, repo} = Repository.init(path, true)
|
||||
{repo, path}
|
||||
end
|
||||
|
||||
def tmp_commit_line do
|
||||
{repo, path} = tmp_bare()
|
||||
sig = Signature.now("Geef Test", "test@geef")
|
||||
message = "commit message"
|
||||
{:ok, idx} = Index.new()
|
||||
{:ok, empty_index} = Index.write_tree(idx, repo)
|
||||
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [])
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [c])
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [c])
|
||||
boring_ancestor = c
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [c])
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [c])
|
||||
{:ok, c} = Commit.create(repo, sig, sig, message, empty_index, [c])
|
||||
head = c
|
||||
|
||||
{repo, path, head, boring_ancestor}
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user