Permalink
Browse files

refactored read_object to object_data, got tree parsing working

  • Loading branch information...
1 parent 99420eb commit 9d44cb78177199a95e450cb9177c9fdc48cb0c2b @schacon committed Dec 4, 2009
View
@@ -3,7 +3,7 @@
%%
-module(git).
--export([open/1, read_object/2, object_exists/2, rev_list/2, commit/2]).
+-export([open/1, object_data/2, object/2, object_exists/2, rev_list/2]).
-include("git.hrl").
@@ -23,7 +23,7 @@ rev_list(Git, Shas) ->
digraph_utils:topsort(Graph).
rev_list(Git, Graph, [Sha|Shas]) ->
- {ok, Commit} = commit(Git, Sha),
+ {ok, Commit} = object(Git, Sha),
digraph:add_vertex(Graph, Sha),
Parents = Commit#commit.parents,
AddParents = rev_list_add_edges(Graph, Sha, Parents),
@@ -43,9 +43,9 @@ rev_list_add_edges(Graph, Sha, [Parent|Rest]) ->
rev_list_add_edges(_Graph, _Commit, []) ->
[].
-commit(Git, Sha) ->
- {_Type, _Size, Data} = read_object(Git, Sha),
- git_object:parse_commit(Sha, Data).
+object(Git, Sha) ->
+ {Type, _Size, Data} = object_data(Git, Sha),
+ git_object:parse_object(Sha, Data, Type).
git_dir(Git) ->
{Path} = Git,
@@ -68,7 +68,8 @@ object_exists(Git, ObjectSha) ->
% get the raw object data out of loose or packed formats
% see if the object is loose, read the data
% else check the packfile indexes and get the object out of a packfile
-read_object(Git, ObjectSha) ->
+% TODO: cache calls to this (at least for commit/tree objects)
+object_data(Git, ObjectSha) ->
LoosePath = get_loose_object_path(Git, ObjectSha),
case file:read_file(LoosePath) of
{ok, Data} ->
View
@@ -15,3 +15,6 @@
committer,
encoding,
message}).
+
+-record(tree, {mode, name, sha}).
+
View
@@ -3,22 +3,30 @@
%%
-module(git_io).
--export([print_log/2]).
+-export([print_log/2, print_tree/1]).
-include("git.hrl").
%print_branches(Git) ->
% print branches out to stdout
%io:fwrite("Branches:~n").
+print_tree([Entry|Rest]) ->
+ io:fwrite("~-7.6s", [Entry#tree.mode]),
+ io:fwrite("~s ", [Entry#tree.sha]),
+ io:fwrite("~s~n", [Entry#tree.name]),
+ print_tree(Rest);
+print_tree([]) ->
+ ok.
+
print_log(Git, Refs) ->
% traverse the reference, printing out all the log information to stdout
Shas = Refs, % TODO - revparse these
RevList = git:rev_list(Git, Shas),
print_log_entries(Git, RevList).
print_log_entries(Git, [Sha|Rest]) ->
- {ok, Commit} = git:commit(Git, Sha),
+ {ok, Commit} = git:object(Git, Sha),
io:fwrite("commit ~s~n", [Commit#commit.sha]),
io:fwrite("Author: ~s~n", [Commit#commit.author]),
io:fwrite("~n"),
View
@@ -5,11 +5,20 @@
%% TODO: replace regexp:first_match with re
-module(git_object).
--export([parse_commit/2]).
+-export([parse_object/3]).
-include("git.hrl").
-parse_commit(Sha, Data) ->
+parse_object(Sha, Data, blob) ->
+ binary_to_list(Data);
+
+parse_object(Sha, Data, tree) ->
+ % mode(6) SP Filename \0 SHA(20)
+ TreeString = binary_to_list(Data),
+ Tree = parse_tree_string(TreeString),
+ {ok, Tree};
+
+parse_object(Sha, Data, commit) ->
CommitString = binary_to_list(Data),
{match, Offset, Len} = regexp:first_match(CommitString, "\n\n"),
{Meta, Message} = lists:split(Offset + Len - 1, CommitString),
@@ -28,6 +37,21 @@ parse_commit_parents(Data) ->
Parents = extract_multi(Data, "parent (.*)"),
extract_matches(Parents).
+parse_tree_string([]) ->
+ [];
+parse_tree_string(Tree) ->
+ {Mode, Rest} = read_until(Tree, 32),
+ {FileName, Rest2} = read_until(Rest, 0),
+ {Sha, Rest3} = lists:split(20, Rest2),
+ ShaHex = hex:list_to_hexstr(Sha),
+ TreeObj = #tree{sha=ShaHex, mode=Mode, name=FileName},
+ [TreeObj | parse_tree_string(Rest3)].
+
+read_until(String, Find) ->
+ {Front, Back} = lists:splitwith(fun(A) -> A /= Find end, String),
+ {Found, Rest} = lists:split(1, Back),
+ {Front, Rest}.
+
extract_matches([Match|Rest]) ->
[_Full, Data] = Match,
[Data|extract_matches(Rest)];
@@ -50,3 +74,4 @@ extract_one(Data, Regex) ->
_Else ->
""
end.
+
View
@@ -3,16 +3,21 @@
% http://necrobious.blogspot.com/2008/03/binary-to-hex-string-back-to-binary-in.html
%
-module(hex).
--export([bin_to_hexstr/1,hexstr_to_bin/1]).
+-export([bin_to_hexstr/1, list_to_hexstr/1, hexstr_to_bin/1]).
bin_to_hexstr(Bin) ->
lists:flatten([io_lib:format("~2.16.0b", [X]) ||
X <- binary_to_list(Bin)]).
+list_to_hexstr(Bin) ->
+ lists:flatten([io_lib:format("~2.16.0b", [X]) ||
+ X <- Bin]).
+
hexstr_to_bin(S) ->
hexstr_to_bin(S, []).
hexstr_to_bin([], Acc) ->
list_to_binary(lists:reverse(Acc));
hexstr_to_bin([X,Y|T], Acc) ->
{ok, [V], []} = io_lib:fread("~16u", [X,Y]),
- hexstr_to_bin(T, [V | Acc]).
+ hexstr_to_bin(T, [V | Acc]).
+
View
@@ -52,7 +52,7 @@ read_object_data(_Git, IoDevice, 0, Size, _Shift, _OrigOffset, FileOffset, Norma
read_ref_deltified_object_data(Git, IoDevice, Size, Offset, FileOffset, OrigOffset) ->
{ok, Sha} = file:read(IoDevice, 20),
HexSha = hex:bin_to_hexstr(Sha),
- {TypeTerm, _BaseSize, BaseData} = git:read_object(Git, HexSha),
+ {TypeTerm, _BaseSize, BaseData} = git:object_data(Git, HexSha),
%io:fwrite("Base:~p~n", [BaseSize]),
{TypeTerm, _DeltaSize, DeltaData} = read_object_data(Git, IoDevice, 0, Size, Offset, OrigOffset, FileOffset + 20, TypeTerm),
%io:fwrite("DeltaData: ~p:~p:~p~n", [TypeTerm, DeltaSize, DeltaData]),
View
@@ -4,6 +4,7 @@
main(_) ->
Git = git:open("test_git"),
- {Type, Size, Data} = git:read_object(Git, "8d47f3435ce5dfd0b2ab5758590c2db21b5294b4"), %% blob
- io:fwrite("Data: ~p ~p~n", [Type, Size]),
- io:fwrite("Data: ~p~n", [Data]).
+ {Type, Size, Data} = git:object_data(Git, "8d47f3435ce5dfd0b2ab5758590c2db21b5294b4"), %% blob
+ io:fwrite("Data: ~p ~p~n", [Type, Size]),
+ io:fwrite("Data: ~p~n", [Data]).
+
View
@@ -4,8 +4,9 @@
main(_) ->
Git = git:open("test_git"),
- {Type, Size, Data} = git:read_object(Git, "aa7dfe7c2a634cb9e7a9d5838eb58fe150ebd7fb"), %% tree
- %{Type, Size, Data} = git:read_object(Git, "be62addb149d286893e2ec254e0dc783a871e8af"), %% tree
- io:fwrite("Data: ~p ~p~n", [Type, Size]),
+ {Type, Size, Data} = git:object_data(Git, "aa7dfe7c2a634cb9e7a9d5838eb58fe150ebd7fb"), %% tree
+ %{Type, Size, Data} = git:object_data(Git, "be62addb149d286893e2ec254e0dc783a871e8af"), %% tree
+ io:fwrite("Data: ~p ~p~n", [Type, Size]),
io:fwrite("Data: ~p~n", [Data]),
- io:fwrite("Data: ~s~n", [binary_to_list(Data)]).
+ io:fwrite("Data: ~s~n", [binary_to_list(Data)]).
+
@@ -4,7 +4,8 @@
main(_) ->
Git = git:open("test_git"),
- {Type, Size, Data} = git:read_object(Git, "9cad8d7e8ee5b3b6fcb401ac9dcc557dd808762d"), %% tree
- io:fwrite("Data: ~p ~p~n", [Type, Size]),
+ {Type, Size, Data} = git:object_data(Git, "9cad8d7e8ee5b3b6fcb401ac9dcc557dd808762d"), %% tree
+ io:fwrite("Data: ~p ~p~n", [Type, Size]),
io:fwrite("Data: ~p~n", [Data]),
- io:fwrite("Data: ~s~n", [binary_to_list(Data)]).
+ io:fwrite("Data: ~s~n", [binary_to_list(Data)]).
+
@@ -4,8 +4,7 @@
main(_) ->
Git = git:open("test_git"),
- {Type, Size, Data} = git:read_object(Git, "ff69c3684a18592c741332b290492aa39d980e02"), %% blob
- %{Type, Size, Data} = git:read_object(Git, "fb9ce46625103fd5c208f2a04f0738cc1f449e4d"), %% blob
+ {Type, Size, Data} = git:object_data(Git, "ff69c3684a18592c741332b290492aa39d980e02"), %% blob
io:fwrite("Data: ~p ~p~n", [Type, Size]),
io:fwrite("Data: ~p~n", [Data]),
io:fwrite("Data: ~s~n", [binary_to_list(Data)]).

0 comments on commit 9d44cb7

Please sign in to comment.