Merge branch 'ramonsnir'

This commit is contained in:
Carlos Martín Nieto
2015-07-31 21:50:22 +02:00
21 changed files with 261 additions and 60 deletions

View File

@@ -117,7 +117,7 @@ geef_commit_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return geef_oom(env);
i = 0;
tail = argv[8];
tail = argv[7];
while (enif_get_list_cell(env, tail, &head, &tail)) {
if (!enif_inspect_binary(env, head, &bin))
return enif_make_badarg(env);
@@ -145,14 +145,12 @@ ERL_NIF_TERM
geef_commit_message(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary bin;
geef_object *obj, *tree;
geef_object *obj;
const char *msg;
if (!enif_get_resource(env, argv[0], geef_object_type, (void **) &obj))
return enif_make_badarg(env);
tree = enif_alloc_resource(geef_object_type, sizeof(geef_object));
msg = git_commit_message((git_commit *) obj->obj);
if (geef_string_to_bin(&bin, msg) < 0)
return geef_error(env);

View File

@@ -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[])

View File

@@ -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

View File

@@ -2,17 +2,21 @@ defmodule Geef do
defmacro __using__(_) do
quote do
alias Geef.Repository
alias Geef.Blob
alias Geef.Commit
alias Geef.Config
alias Geef.Index
alias Geef.Index.Tree
alias Geef.Object
alias Geef.Odb
alias Geef.Oid
alias Geef.Reference
alias Geef.Object
alias Geef.Commit
alias Geef.Tree
alias Geef.TreeEntry
alias Geef.Blob
alias Geef.Tag
alias Geef.Repository
alias Geef.Revwalk
alias Geef.Signature
alias Geef.Tree
alias Geef.Tag
alias Geef.TreeEntry
end
end

25
lib/geef/config.ex Normal file
View File

@@ -0,0 +1,25 @@
defmodule Geef.Config do
import Geef
alias Geef.Repository
def stop(config), do: :geef_config.stop(config)
def open(repo) when is_pid(repo), do: Repository.config(repo)
def open(path), do: :geef_config.open(path)
def open!(arg), do: open(arg) |> assert_ok
def set(config, key, value) do
:geef_config.set(config, make_config_key(key), value)
end
def get_bool(config, key) do
:geef_config.get_bool(config, make_config_key(key))
end
def get_string(config, key) do
:geef_config.get_string(config, make_config_key(key))
end
defp make_config_key(key) when is_binary(key), do: String.to_char_list(key)
defp make_config_key(key), do: key
end

View File

@@ -16,6 +16,8 @@ defmodule Geef.Object do
case lookup(repo, id) do
{:ok, obj = %Geef.Object{type: ^type}} ->
{:ok, obj}
{:ok, _obj} ->
{:error, :type_mismatch}
error ->
error
end

View File

@@ -8,8 +8,8 @@ defmodule Geef.Pkt do
def parse_request(str) do
case :geef_pkt.parse_request(str) do
{:ok, req} ->
{:ok, Geef.Request.new req}
{:ok, {:geef_request, service, path, host}} ->
{:ok, %Geef.Request{service: service, path: path, host: host}}
error ->
error
end

View File

@@ -15,7 +15,10 @@ defmodule Geef.Repository do
def discover(path), do: :geef_repo.discover(path)
def bare?(repo), do: :geef_repo.is_bare(repo)
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
View 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

View File

@@ -10,8 +10,12 @@ defmodule Geef.Signature do
defp maybe_sig({:ok, sig}), do: from_record(sig)
defp maybe_sig(error = {:error, _}), do: error
def from_record({:geef_signature}) do
%Geef.Signature{}
def from_record({:geef_signature, name, email, time}) do
%Geef.Signature{name: name, email: email, time: time}
end
def to_record(%Geef.Signature{name: name, email: email, time: time}) do
{:geef_signature, name, email, time}
end
end

View File

@@ -66,30 +66,31 @@ defmodule Geef.TreeError do
end
end
defimpl Enumerable, for: Geef.Tree do
defimpl Enumerable, for: Geef.Object do
alias Geef.Object
alias Geef.Tree
alias Geef.TreeError
def count(tree) do
Tree.count(tree)
def count(tree = %Object{type: :tree}) do
{:ok, Tree.count(tree)}
end
def member?(tree, key) do
def member?(tree = %Object{type: :tree}, key) do
case Tree.get(tree, key) do
{:ok, _} -> true
_ -> false
{:ok, _} -> {:ok, true}
_ -> {:ok, false}
end
end
def reduce(tree, acc, fun) do
def reduce(tree = %Object{type: :tree}, acc, fun) do
reduce(tree, 0, Tree.count(tree), acc, fun)
end
# We're done when the index is equal to the number of entries
defp reduce(_, idx, idx, acc, _), do: acc
defp reduce(_, idx, idx, {:cont, acc}, _), do: {:done, acc}
# Call the user-passed function and recurse with the next index
defp reduce(tree, idx, count, acc, fun) do
defp reduce(tree, idx, count, {:cont, acc}, fun) do
case Tree.nth(tree, idx) do
{:ok, entry} ->
reduce(tree, idx + 1, count, fun.(entry, acc), fun)
@@ -98,4 +99,9 @@ defimpl Enumerable, for: Geef.Tree do
end
end
# Almost default Enumerable implementation
defp reduce(_, _, _, {:halt, acc}, _), do: {:halted, acc}
defp reduce(tree, idx, count, {:suspend, acc}, fun) do
{:suspended, acc, &reduce(tree, idx, count, &1, fun)}
end
end

12
mix.exs
View File

@@ -37,6 +37,9 @@ defmodule Mix.Tasks.Compile.Nif do
def run(_) do
project = Mix.Project.get!
Mix.shell.info("* Running make...")
Mix.shell.info(:os.cmd('make'))
if function_exported?(project, :nif, 0) do
do_run(project.nif)
else
@@ -110,7 +113,8 @@ defmodule Geef.Mixfile do
[ app: :geef,
version: "0.0.1",
compilers: [:nif, :erlang, :elixir, :app],
deps: deps ]
deps: deps,
dialyzer: dialyzer ]
end
def nif do
@@ -128,4 +132,10 @@ defmodule Geef.Mixfile do
defp deps do
[]
end
def dialyzer do
[ plt_apps: [:erts, :kernel, :stdlib, :mnesia],
flags: ["-Wunmatched_returns","-Werror_handling","-Wrace_conditions", "-Wno_opaque"]]
end
end

View File

@@ -16,6 +16,7 @@
-export([set/3]).
-export([get_bool/2]).
-export([get_string/2]).
-export([stop/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
@@ -60,6 +61,9 @@ get_bool(Pid, Name) ->
get_string(Pid, Name) ->
gen_server:call(Pid, {get_string, Name}).
stop(Pid) ->
gen_server:call(Pid, stop).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
@@ -96,7 +100,10 @@ handle_call({set_string, Name, Val}, _From, State = #state{handle=Handle}) ->
handle_call({get_string, Name}, _From, State = #state{handle=Handle}) ->
Reply = geef_nif:config_get_string(Handle, Name),
{reply, Reply, State}.
{reply, Reply, State};
handle_call(stop, _From, State) ->
{stop, normal, ok, State}.
%%--------------------------------------------------------------------
%% @private

View File

@@ -115,7 +115,7 @@ commit_tree(_Handle) ->
commit_create(_RepoHandle, _Ref, _Author, _Committer, _Encoding, _Message, _Tree, _Parents) ->
?NIF_FN.
-spec commit_message(term) -> binary().
-spec commit_message(term) -> {ok, binary()} | {error, term()}.
commit_message(_CommitHandle) ->
?NIF_FN.
@@ -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.

View File

@@ -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,21 +37,21 @@ 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
end.
{ok, Handle} ->
start_link(Handle);
Other ->
Other
end.
%% @doc The repository's git-dir path
-spec path(pid()) -> binary().
@@ -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) ->

View File

@@ -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};

30
test/config_test.exs Normal file
View File

@@ -0,0 +1,30 @@
defmodule ConfigTest do
use ExUnit.Case
use Geef
import RepoHelpers
setup do
{repo, path} = tmp_bare
Process.link(repo)
{:ok, config} = Repository.config(repo)
on_exit(fn -> File.rm_rf!(path) end)
{:ok, [config: config, path: path]}
end
test "write and get a boolean", meta do
config = meta[:config]
var = "core.logallrefupdates"
assert :ok = Config.set(config, var, true)
assert {:ok, true} = Config.get_bool(config, var)
end
test "write and get a string", meta do
config = meta[:config]
var = "user.name"
val = "Random J. Hacker"
assert :ok = Config.set(config, var, val)
assert {:ok, ^val} = Config.get_string(config, var)
end
end

View File

@@ -2,7 +2,6 @@ defmodule IndexTest do
use ExUnit.Case
use Geef
alias Geef.Index
alias Geef.Index.Entry
import RepoHelpers

View File

@@ -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
View 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

View File

@@ -1,12 +1,33 @@
ExUnit.start
defmodule RepoHelpers do
use Geef
def tmp_bare do
{a, b, c} = :erlang.now()
{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