Browse files

Whitespace and other mundane changes.

  • Loading branch information...
1 parent f696291 commit 36abb62998562223c1127bfd49f45b5ac314890d Gregory Burd committed Nov 5, 2011
Showing with 462 additions and 333 deletions.
  1. +12 −0 rebar.config
  2. +4 −2 src/erlangit.app.src
  3. +23 −0 src/erlangit_sup.erl
  4. +127 −111 src/git.erl
  5. +38 −20 src/git_io.erl
  6. +66 −48 src/git_object.erl
  7. +35 −13 src/hex.erl
  8. +157 −139 src/packfile.erl
View
12 rebar.config
@@ -0,0 +1,12 @@
+%% -*- erlang-indent-level: 2 -*-
+
+{cover_enabled, true}.
+
+{erl_opts, [debug_info, warnings_as_errors]}.
+
+{deps, [
+%%{lets, ".*", {git, "git://github.com/norton/lets.git", {branch, "master"}}},
+ {ebloom, ".*", {git, "git://github.com/basho/ebloom", {branch, "master"}}},
+ {lager, ".*", {git, "git://github.com/basho/lager", {branch, "master"}}},
+ {webmachine, ".*", {git, "git://github.com/basho/webmachine", {branch, "master"}}}
+]}.
View
6 src/erlangit.app.src
@@ -1,7 +1,9 @@
+%% -*- erlang -*-
+
{application, erlangit,
[
- {description, ""},
- {vsn, "1"},
+ {description, "ErlanGit: an implementation of the Git in Erlang"},
+ {vsn, "0.0.1"},
{registered, []},
{applications, [
kernel,
View
23 src/erlangit_sup.erl
@@ -1,5 +1,28 @@
+%% -*- erlang -*-
+%%
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
+%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc
-module(erlangit_sup).
+-author('Greg Burd <greg@basho.com>').
-behaviour(supervisor).
View
238 src/git.erl
@@ -1,7 +1,25 @@
-%% -*- erlang-indent-level: 2 -*-
+%% -*- erlang -*-
%%
-%% Partial Git Implementation
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc
-module(git).
-export([open/1, object_data/2, object/2, object_exists/2, rev_list/2]).
@@ -12,151 +30,149 @@
-include("git.hrl").
-%%-define(cassandra_ZERO, 0).
-
+%% @doc Normalize the path (look for .git, etc)
open(Path) ->
- % normalize the path (look for .git, etc)
- #git{path = Path}.
+ #git{path = Path}.
-%references(Git) ->
- % read all the refs from disk/packed-refs and return an array
- %{Git}.
+%% @doc Read all the refs from disk/packed-refs and return an array
+% references(Git) ->
+% {Git}.
rev_list(Git, Shas) ->
- Graph = digraph:new(),
- rev_list(Git, Graph, Shas),
- digraph_utils:topsort(Graph).
+ Graph = digraph:new(),
+ rev_list(Git, Graph, Shas),
+ digraph_utils:topsort(Graph).
rev_list(Git, Graph, [Sha|Shas]) ->
- {ok, Commit} = object(Git, Sha),
- digraph:add_vertex(Graph, Sha),
- Parents = Commit#commit.parents,
- AddParents = rev_list_add_edges(Graph, Sha, Parents),
- rev_list(Git, Graph, AddParents ++ Shas);
+ {ok, Commit} = object(Git, Sha),
+ digraph:add_vertex(Graph, Sha),
+ Parents = Commit#commit.parents,
+ AddParents = rev_list_add_edges(Graph, Sha, Parents),
+ rev_list(Git, Graph, AddParents ++ Shas);
rev_list(_Git, _Graph, []) ->
- ok.
+ ok.
rev_list_add_edges(Graph, Sha, [Parent|Rest]) ->
- Vertex = case digraph:vertex(Graph, Parent) of
- false ->
- digraph:add_vertex(Graph, Parent);
- _Else ->
- []
- end,
- digraph:add_edge(Graph, Sha, Parent),
- [Vertex|rev_list_add_edges(Graph, Sha, Rest)];
+ Vertex = case digraph:vertex(Graph, Parent) of
+ false ->
+ digraph:add_vertex(Graph, Parent);
+ _Else ->
+ []
+ end,
+ digraph:add_edge(Graph, Sha, Parent),
+ [Vertex|rev_list_add_edges(Graph, Sha, Rest)];
rev_list_add_edges(_Graph, _Commit, []) ->
- [].
+ [].
object(Git, Sha) ->
- {Type, _Size, Data} = object_data(Git, Sha),
- git_object:parse_object(Sha, Data, Type).
+ {Type, _Size, Data} = object_data(Git, Sha),
+ git_object:parse_object(Sha, Data, Type).
git_dir(Git) ->
- Git#git.path.
+ Git#git.path.
object_exists(Git, ObjectSha) ->
- LoosePath = get_loose_object_path(Git, ObjectSha),
- case filelib:is_file(LoosePath) of
- true ->
- true;
- false ->
- case find_packfile_with_object(Git, ObjectSha) of
- {ok, _PackFilePath, _Offset} ->
- true;
- _Else ->
- false
- end
- end.
-
-% 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
-% TODO: cache calls to this (at least for commit/tree objects)
+ LoosePath = get_loose_object_path(Git, ObjectSha),
+ case filelib:is_file(LoosePath) of
+ true ->
+ true;
+ false ->
+ case find_packfile_with_object(Git, ObjectSha) of
+ {ok, _PackFilePath, _Offset} ->
+ true;
+ _Else ->
+ false
+ end
+ end.
+
+
+%% @doc 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.
+%% 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} ->
- extract_loose_object_data(Data);
- _Else ->
- get_packfile_object_data(Git, ObjectSha)
- end.
+ LoosePath = get_loose_object_path(Git, ObjectSha),
+ case file:read_file(LoosePath) of
+ {ok, Data} ->
+ extract_loose_object_data(Data);
+ _Else ->
+ get_packfile_object_data(Git, ObjectSha)
+ end.
get_loose_object_path(Git, ObjectSha) ->
- First = string:substr(ObjectSha, 1, 2),
- Second = string:substr(ObjectSha, 3, 38),
- git_dir(Git) ++ "/objects/" ++ First ++ "/" ++ Second.
+ First = string:substr(ObjectSha, 1, 2),
+ Second = string:substr(ObjectSha, 3, 38),
+ git_dir(Git) ++ "/objects/" ++ First ++ "/" ++ Second.
extract_loose_object_data(CompData) ->
- extract_loose_object_1(zlib:uncompress(CompData), []).
+ extract_loose_object_1(zlib:uncompress(CompData), []).
extract_loose_object_1(<<$\s,T/binary>>, Type0) ->
- Type = list_to_atom(lists:reverse(Type0)),
- extract_loose_object_2(T, Type, 0);
+ Type = list_to_atom(lists:reverse(Type0)),
+ extract_loose_object_2(T, Type, 0);
extract_loose_object_1(<<C,T/binary>>, Type) ->
- extract_loose_object_1(T, [C|Type]).
+ extract_loose_object_1(T, [C|Type]).
extract_loose_object_2(<<0,Data/binary>>, Type, Sz) ->
- {Type, Sz, Data};
+ {Type, Sz, Data};
extract_loose_object_2(<<Digit,T/binary>>, Type, Sz) ->
- extract_loose_object_2(T, Type, Sz*10+Digit-$0).
+ extract_loose_object_2(T, Type, Sz*10+Digit-$0).
get_packfile_object_data(Git, ObjectSha) ->
- case find_packfile_with_object(Git, ObjectSha) of
- {ok, PackFilePath, Offset} ->
- packfile:get_packfile_data(Git, PackFilePath, Offset);
- _Else ->
- invalid
- end.
+ case find_packfile_with_object(Git, ObjectSha) of
+ {ok, PackFilePath, Offset} ->
+ packfile:get_packfile_data(Git, PackFilePath, Offset);
+ _Else ->
+ invalid
+ end.
find_packfile_with_object(Git, ObjectSha) ->
- %io:fwrite("SHA:~p~n", [ObjectSha]),
- PackIndex = git_dir(Git) ++ "/objects/pack",
- case file:list_dir(PackIndex) of
- {ok, Filenames} ->
- Indexes = lists:filter(fun(X) -> string_ends_with(X, ".idx") end, Filenames),
- case get_packfile_with_object(Git, Indexes, ObjectSha) of
- {ok, Packfile, Offset} ->
- PackFilePath = git_dir(Git) ++ "/objects/pack/" ++ Packfile,
- {ok, PackFilePath, Offset};
+ %io:fwrite("SHA:~p~n", [ObjectSha]),
+ PackIndex = git_dir(Git) ++ "/objects/pack",
+ case file:list_dir(PackIndex) of
+ {ok, Filenames} ->
+ Indexes = lists:filter(fun(X) -> string_ends_with(X, ".idx") end, Filenames),
+ case get_packfile_with_object(Git, Indexes, ObjectSha) of
+ {ok, Packfile, Offset} ->
+ PackFilePath = git_dir(Git) ++ "/objects/pack/" ++ Packfile,
+ {ok, PackFilePath, Offset};
+ _Else ->
+ invalid
+ end;
_Else ->
- invalid
- end;
- _Else ->
- invalid
- end.
+ invalid
+ end.
get_packfile_with_object(Git, [Index|Rest], ObjectSha) ->
- PackIndex = git_dir(Git) ++ "/objects/pack/" ++ Index,
- %io:fwrite("Looking for ~p in ~p~n", [ObjectSha, PackIndex]),
- case file:read_file(PackIndex) of
- {ok, Data} ->
- case packindex:extract_packfile_index(Data) of
- {ok, IndexData} ->
- %io:fwrite("PackIndex Size:~p~n", [IndexData#index.size]),
- %io:fwrite("IndexData:~p~n", [IndexData]),
- case packindex:object_offset(IndexData, ObjectSha) of
- {ok, Offset} ->
- Packfile = replace_string_ending(Index, ".idx", ".pack"),
- {ok, Packfile, Offset};
- not_found ->
- get_packfile_with_object(Git, Rest, ObjectSha)
- end;
- Else ->
- io:fwrite("Invalid, Biatch~p~n", [Else]),
- invalid
- end;
- _Else ->
- invalid
- end;
+ PackIndex = git_dir(Git) ++ "/objects/pack/" ++ Index,
+ %io:fwrite("Looking for ~p in ~p~n", [ObjectSha, PackIndex]),
+ case file:read_file(PackIndex) of
+ {ok, Data} ->
+ case packindex:extract_packfile_index(Data) of
+ {ok, IndexData} ->
+ %io:fwrite("PackIndex Size:~p~n", [IndexData#index.size]),
+ %io:fwrite("IndexData:~p~n", [IndexData]),
+ case packindex:object_offset(IndexData, ObjectSha) of
+ {ok, Offset} ->
+ Packfile = replace_string_ending(Index, ".idx", ".pack"),
+ {ok, Packfile, Offset};
+ not_found ->
+ get_packfile_with_object(Git, Rest, ObjectSha)
+ end;
+ Else ->
+ io:fwrite("Invalid, Biatch~p~n", [Else]),
+ invalid
+ end;
+ _Else ->
+ invalid
+ end;
get_packfile_with_object(_Git, [], _ObjectSha) ->
- not_found.
+ not_found.
replace_string_ending(String, Ending, NewEnding) ->
- Base = string:substr(String, 1, length(String) - length(Ending)),
- Base ++ NewEnding.
+ Base = string:substr(String, 1, length(String) - length(Ending)),
+ Base ++ NewEnding.
string_ends_with(File, Ending) ->
- FileEnding = string:substr(File, length(File) - length(Ending) + 1, length(Ending)),
- FileEnding =:= Ending.
-
+ FileEnding = string:substr(File, length(File) - length(Ending) + 1, length(Ending)),
+ FileEnding =:= Ending.
View
58 src/git_io.erl
@@ -1,6 +1,25 @@
+%% -*- erlang -*-
%%
-%% Git Output Printing Functions
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc Git Output Printing Functions
-module(git_io).
-export([print_log/2, print_tree/1]).
@@ -11,32 +30,31 @@
-include("git.hrl").
+%% @doc Print branches out to stdout
%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);
+ 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.
+ ok.
+%% @doc Traverse the reference, printing out all the log information to stdout
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).
+ 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:object(Git, Sha),
- io:fwrite("commit ~s~n", [Commit#commit.sha]),
- io:fwrite("Author: ~s~n", [Commit#commit.author]),
- io:fwrite("~n"),
- io:fwrite("~s~n", [Commit#commit.message]),
- io:fwrite("~n"),
- print_log_entries(Git, Rest);
+ {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"),
+ io:fwrite("~s~n", [Commit#commit.message]),
+ io:fwrite("~n"),
+ print_log_entries(Git, Rest);
print_log_entries(_Git, []) ->
- ok.
-
+ ok.
View
114 src/git_object.erl
@@ -1,6 +1,25 @@
+%% -*- erlang -*-
%%
-%% Git Object Parsers
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc Git Object Parsers
%% TODO: replace regexp:first_match with re
@@ -10,68 +29,67 @@
-include("git.hrl").
parse_object(_Sha, Data, blob) ->
- binary_to_list(Data);
+ 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};
+ % 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}]} = re:run(CommitString, "\n\n"),
- {Meta, Message} = lists:split(Offset + Len - 1, CommitString),
- Parents = parse_commit_parents(Meta),
- Tree = extract_one(Meta, "tree (.*)"),
- Author = extract_one(Meta, "author (.*)"),
- Committer = extract_one(Meta, "committer (.*)"),
- Encoding = extract_one(Meta, "encoding (.*)"),
- %io:format("Parents:~p~nTree:~p~nAuthor:~p~nMessage:~p~n~n", [Parents, Tree, Author, Message]),
- Commit = #commit{sha=Sha, tree=Tree, parents=Parents,
- author=Author, committer=Committer,
- encoding=Encoding, message=Message},
- {ok, Commit}.
+ CommitString = binary_to_list(Data),
+ {match, [{Offset, Len}]} = re:run(CommitString, "\n\n"),
+ {Meta, Message} = lists:split(Offset + Len - 1, CommitString),
+ Parents = parse_commit_parents(Meta),
+ Tree = extract_one(Meta, "tree (.*)"),
+ Author = extract_one(Meta, "author (.*)"),
+ Committer = extract_one(Meta, "committer (.*)"),
+ Encoding = extract_one(Meta, "encoding (.*)"),
+ %io:format("Parents:~p~nTree:~p~nAuthor:~p~nMessage:~p~n~n", [Parents, Tree, Author, Message]),
+ Commit = #commit{sha=Sha, tree=Tree, parents=Parents,
+ author=Author, committer=Committer,
+ encoding=Encoding, message=Message},
+ {ok, Commit}.
parse_commit_parents(Data) ->
- Parents = extract_multi(Data, "parent (.*)"),
- extract_matches(Parents).
+ 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)].
+ {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}.
+ {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)];
+ [_Full, Data] = Match,
+ [Data|extract_matches(Rest)];
extract_matches([]) ->
- [].
+ [].
extract_multi(Data, Regex) ->
- case re:run(Data, Regex, [global, {capture, all, list}]) of
- {match, Captured} ->
- Captured;
- _Else ->
- ""
- end.
+ case re:run(Data, Regex, [global, {capture, all, list}]) of
+ {match, Captured} ->
+ Captured;
+ _Else ->
+ ""
+ end.
extract_one(Data, Regex) ->
- case re:run(Data, Regex, [{capture, all, list}]) of
- {match, Captured} ->
- [_Full, Value] = Captured,
- Value;
- _Else ->
- ""
- end.
-
+ case re:run(Data, Regex, [{capture, all, list}]) of
+ {match, Captured} ->
+ [_Full, Value] = Captured,
+ Value;
+ _Else ->
+ ""
+ end.
View
48 src/hex.erl
@@ -1,23 +1,45 @@
-%
-% via Steve Vinoski
-% http://necrobious.blogspot.com/2008/03/binary-to-hex-string-back-to-binary-in.html
-%
+%% -*- erlang -*-
+%%
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
+%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc
+%% via Steve Vinoski
+%% http://necrobious.blogspot.com/2008/03/binary-to-hex-string-back-to-binary-in.html
+
-module(hex).
+-author('Steve Vinoski <steve@basho.com>').
+
-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)]).
+ 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]).
+ lists:flatten([io_lib:format("~2.16.0b", [X]) ||
+ X <- Bin]).
hexstr_to_bin(S) ->
- hexstr_to_bin(S, []).
+ hexstr_to_bin(S, []).
hexstr_to_bin([], Acc) ->
- list_to_binary(lists:reverse(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]).
-
+ {ok, [V], []} = io_lib:fread("~16u", [X,Y]),
+ hexstr_to_bin(T, [V | Acc]).
View
296 src/packfile.erl
@@ -1,181 +1,199 @@
+%% -*- erlang -*-
%%
-%% Partial Git Implementation
+%% ErlanGit: an implementation of the Git in Erlang
+%% created by Scott Chacon https://github.com/schacon/erlangit
%%
+%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
+%%
+%% This file is provided to you under the Apache License,
+%% Version 2.0 (the "License"); you may not use this file
+%% except in compliance with the License. You may obtain
+%% a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+
+%% @doc
-module(packfile).
-export([get_packfile_data/3]).
get_packfile_data(Git, PackFilePath, Offset) ->
- case file:open(PackFilePath, [read, binary]) of
- {ok, IoDevice} ->
- read_packfile_object_offset(Git, IoDevice, Offset);
- {error, _Reason} ->
- error
- end.
+ case file:open(PackFilePath, [read, binary]) of
+ {ok, IoDevice} ->
+ read_packfile_object_offset(Git, IoDevice, Offset);
+ {error, _Reason} ->
+ error
+ end.
read_packfile_object_offset(Git, IoDevice, Offset) ->
- file:position(IoDevice, Offset),
- {ok, Byte} = file:read(IoDevice, 1),
- <<ContinueBit:1, Type:3, InitSize:4>> = Byte,
- TypeTerm = type_int_to_term(Type),
- %io:fwrite("Object Data: ~p ~p ~p~n", [ContinueBit, Type, InitSize]),
- {FinalType, Size, Data} = read_object_data(Git, IoDevice, ContinueBit, InitSize, 4, Offset, Offset + 1, TypeTerm),
- %io:fwrite("Final Object Data: ~p ~p ~p~n", [Size, FinalType, Data]),
- {FinalType, Size, Data}.
+ file:position(IoDevice, Offset),
+ {ok, Byte} = file:read(IoDevice, 1),
+ <<ContinueBit:1, Type:3, InitSize:4>> = Byte,
+ TypeTerm = type_int_to_term(Type),
+ %io:fwrite("Object Data: ~p ~p ~p~n", [ContinueBit, Type, InitSize]),
+ {FinalType, Size, Data} = read_object_data(Git, IoDevice, ContinueBit, InitSize, 4, Offset, Offset + 1, TypeTerm),
+ %io:fwrite("Final Object Data: ~p ~p ~p~n", [Size, FinalType, Data]),
+ {FinalType, Size, Data}.
read_object_data(Git, IoDevice, 1, Size, Shift, OrigOffset, FileOffset, TypeTerm) ->
- {ok, Byte} = file:read(IoDevice, 1),
- <<ContinueBit:1, NextSize:7>> = Byte,
- % bit shift the size
- SizeOr = NextSize bsl Shift,
- NewSize = Size bor SizeOr,
- NextShift = Shift + 7,
- %io:fwrite("Object Data: [~p] ~p ~p (~p)~n", [FileOffset, ContinueBit, NextSize, NewSize]),
- read_object_data(Git, IoDevice, ContinueBit, NewSize, NextShift, OrigOffset, FileOffset + 1, TypeTerm);
+ {ok, Byte} = file:read(IoDevice, 1),
+ <<ContinueBit:1, NextSize:7>> = Byte,
+ % bit shift the size
+ SizeOr = NextSize bsl Shift,
+ NewSize = Size bor SizeOr,
+ NextShift = Shift + 7,
+ %io:fwrite("Object Data: [~p] ~p ~p (~p)~n", [FileOffset, ContinueBit, NextSize, NewSize]),
+ read_object_data(Git, IoDevice, ContinueBit, NewSize, NextShift, OrigOffset, FileOffset + 1, TypeTerm);
read_object_data(Git, IoDevice, 0, Size, Shift, OrigOffset, FileOffset, ofs_delta) ->
- read_ofs_deltified_object_data(Git, IoDevice, Size, Shift, FileOffset, OrigOffset);
+ read_ofs_deltified_object_data(Git, IoDevice, Size, Shift, FileOffset, OrigOffset);
read_object_data(Git, IoDevice, 0, Size, Shift, OrigOffset, FileOffset, ref_delta) ->
- read_ref_deltified_object_data(Git, IoDevice, Size, Shift, FileOffset, OrigOffset);
+ read_ref_deltified_object_data(Git, IoDevice, Size, Shift, FileOffset, OrigOffset);
read_object_data(_Git, IoDevice, 0, Size, _Shift, _OrigOffset, FileOffset, NormalType) ->
- %io:fwrite("File Offset:~p~n", [FileOffset]),
- file:position(IoDevice, FileOffset),
- Z = zlib:open(),
- ok = zlib:inflateInit(Z),
- Data = inflate_object_data(Z, IoDevice, []),
- %io:fwrite("Bits:~p~n", [Data]),
- ok = zlib:inflateEnd(Z),
- zlib:close(Z),
- {NormalType, Size, Data}.
+ %io:fwrite("File Offset:~p~n", [FileOffset]),
+ file:position(IoDevice, FileOffset),
+ Z = zlib:open(),
+ ok = zlib:inflateInit(Z),
+ Data = inflate_object_data(Z, IoDevice, []),
+ %io:fwrite("Bits:~p~n", [Data]),
+ ok = zlib:inflateEnd(Z),
+ zlib:close(Z),
+ {NormalType, Size, Data}.
% git rev-list --objects --all | git pack-objects --window=250 --depth=250 --stdout > #{packfile_pack}
% git index-pack -o #{packfile_idx} #{packfile_pack}
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: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]),
- PatchedData = patch_delta(DeltaData, BaseData),
- {TypeTerm, length(PatchedData), list_to_binary(PatchedData)}.
+ {ok, Sha} = file:read(IoDevice, 20),
+ HexSha = hex:bin_to_hexstr(Sha),
+ {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]),
+ PatchedData = patch_delta(DeltaData, BaseData),
+ {TypeTerm, length(PatchedData), list_to_binary(PatchedData)}.
read_ofs_deltified_object_data(Git, IoDevice, Size, Offset, FileOffset, OrigOffset) ->
- {ok, BaseOffset, BytesRead} = get_base_offset(IoDevice),
- NewOffset = OrigOffset - BaseOffset,
- %io:fwrite("BaseOffset: ~p:~p:~p~n", [NewOffset, OrigOffset, BaseOffset]),
- {TypeTerm, _BaseSize, BaseData} = read_packfile_object_offset(Git, IoDevice, NewOffset),
- file:position(IoDevice, FileOffset + BytesRead),
- {TypeTerm, _DeltaSize, DeltaData} = read_object_data(Git, IoDevice, 0, Size, Offset, OrigOffset, FileOffset + BytesRead, TypeTerm),
- %io:fwrite("DeltaData: ~p:~p:~p~n", [TypeTerm, DeltaSize, DeltaData]),
- PatchedData = patch_delta(DeltaData, BaseData),
- {TypeTerm, length(PatchedData), list_to_binary(PatchedData)}.
+ {ok, BaseOffset, BytesRead} = get_base_offset(IoDevice),
+ NewOffset = OrigOffset - BaseOffset,
+ %io:fwrite("BaseOffset: ~p:~p:~p~n", [NewOffset, OrigOffset, BaseOffset]),
+ {TypeTerm, _BaseSize, BaseData} = read_packfile_object_offset(Git, IoDevice, NewOffset),
+ file:position(IoDevice, FileOffset + BytesRead),
+ {TypeTerm, _DeltaSize, DeltaData} = read_object_data(Git, IoDevice, 0, Size, Offset, OrigOffset, FileOffset + BytesRead, TypeTerm),
+ %io:fwrite("DeltaData: ~p:~p:~p~n", [TypeTerm, DeltaSize, DeltaData]),
+ PatchedData = patch_delta(DeltaData, BaseData),
+ {TypeTerm, length(PatchedData), list_to_binary(PatchedData)}.
patch_delta(DeltaData, BaseData) ->
- DeltaList = binary_to_list(DeltaData),
- BaseList = binary_to_list(BaseData),
- {ok, _SrcSize, PosA} = patch_delta_header_size(DeltaList, 1),
- % SrcSize should == BaseData.size
- %io:fwrite("Patch:SrcSize : ~p:~p~n", [SrcSize, PosA]),
- {ok, _DestSize, PosB} = patch_delta_header_size(DeltaList, PosA),
- %io:fwrite("Patch:DestSize: ~p:~p~n", [DestSize, PosB]),
- PatchedData = patch_delta([], BaseList, DeltaList, PosB, length(DeltaList) + 1),
- %io:fwrite("PatchData: ~p~n", [length(PatchedData)]),
- PatchedData.
+ DeltaList = binary_to_list(DeltaData),
+ BaseList = binary_to_list(BaseData),
+ {ok, _SrcSize, PosA} = patch_delta_header_size(DeltaList, 1),
+ % SrcSize should == BaseData.size
+ %io:fwrite("Patch:SrcSize : ~p:~p~n", [SrcSize, PosA]),
+ {ok, _DestSize, PosB} = patch_delta_header_size(DeltaList, PosA),
+ %io:fwrite("Patch:DestSize: ~p:~p~n", [DestSize, PosB]),
+ PatchedData = patch_delta([], BaseList, DeltaList, PosB, length(DeltaList) + 1),
+ %io:fwrite("PatchData: ~p~n", [length(PatchedData)]),
+ PatchedData.
patch_delta(PatchedList, _BaseList, _DeltaList, _DeltaPos, _DeltaPos) ->
- PatchedList;
+ PatchedList;
patch_delta(PatchedList, BaseList, DeltaList, DeltaPos, Size) ->
- Byte = lists:nth(DeltaPos, DeltaList),
- StartPos = DeltaPos + 1,
- <<PatchBit:1, PatchData:7>> = <<Byte>>,
- %io:fwrite("Patch: ~p:~p:~p~n", [PatchBit, DeltaPos, Size]),
- case PatchBit of
- 1 ->
- % append data from base list
- <<_Pb:1, S16:1, S8:1, S0:1, Of24:1, Of16:1, Of8:1, Of0:1>> = <<Byte>>,
- {CpOffA, DeltaOffA} = calc_cp(DeltaList, StartPos, Of0, 0, 0),
- {CpOffB, DeltaOffB} = calc_cp(DeltaList, DeltaOffA, Of8, 8, CpOffA),
- {CpOffC, DeltaOffC} = calc_cp(DeltaList, DeltaOffB, Of16, 16, CpOffB),
- {CpOff, DeltaOffD} = calc_cp(DeltaList, DeltaOffC, Of24, 24, CpOffC),
- {CpSizeA, DeltaOffE} = calc_cp(DeltaList, DeltaOffD, S0, 0, 0),
- {CpSizeB, DeltaOffF} = calc_cp(DeltaList, DeltaOffE, S8, 8, CpSizeA),
- {CpSize, DeltaOff} = calc_cp(DeltaList, DeltaOffF, S16, 16, CpSizeB),
- %io:fwrite("Off/Size: ~p:~p:~p~n", [CpOff, CpSize, DeltaOff]),
- PatchDataList = lists:sublist(BaseList, CpOff + 1, CpSize),
- patch_delta(PatchedList ++ PatchDataList, BaseList, DeltaList, DeltaOff, Size);
- 0 ->
- % append data from delta list
- %io:fwrite("Patch Delta Data (~p:~p)~n", [StartPos, PatchData]),
- PatchDataList = lists:sublist(DeltaList, StartPos, PatchData),
- patch_delta(PatchedList ++ PatchDataList, BaseList, DeltaList, StartPos + PatchData, Size)
- end.
+ Byte = lists:nth(DeltaPos, DeltaList),
+ StartPos = DeltaPos + 1,
+ <<PatchBit:1, PatchData:7>> = <<Byte>>,
+ %io:fwrite("Patch: ~p:~p:~p~n", [PatchBit, DeltaPos, Size]),
+ case PatchBit of
+ 1 ->
+ % append data from base list
+ <<_Pb:1, S16:1, S8:1, S0:1, Of24:1, Of16:1, Of8:1, Of0:1>> = <<Byte>>,
+ {CpOffA, DeltaOffA} = calc_cp(DeltaList, StartPos, Of0, 0, 0),
+ {CpOffB, DeltaOffB} = calc_cp(DeltaList, DeltaOffA, Of8, 8, CpOffA),
+ {CpOffC, DeltaOffC} = calc_cp(DeltaList, DeltaOffB, Of16, 16, CpOffB),
+ {CpOff, DeltaOffD} = calc_cp(DeltaList, DeltaOffC, Of24, 24, CpOffC),
+ {CpSizeA, DeltaOffE} = calc_cp(DeltaList, DeltaOffD, S0, 0, 0),
+ {CpSizeB, DeltaOffF} = calc_cp(DeltaList, DeltaOffE, S8, 8, CpSizeA),
+ {CpSize, DeltaOff} = calc_cp(DeltaList, DeltaOffF, S16, 16, CpSizeB),
+ %io:fwrite("Off/Size: ~p:~p:~p~n", [CpOff, CpSize, DeltaOff]),
+ PatchDataList = lists:sublist(BaseList, CpOff + 1, CpSize),
+ patch_delta(PatchedList ++ PatchDataList, BaseList, DeltaList, DeltaOff, Size);
+ 0 ->
+ % append data from delta list
+ %io:fwrite("Patch Delta Data (~p:~p)~n", [StartPos, PatchData]),
+ PatchDataList = lists:sublist(DeltaList, StartPos, PatchData),
+ patch_delta(PatchedList ++ PatchDataList, BaseList, DeltaList, StartPos + PatchData, Size)
+ end.
calc_cp(DList, DPos, 1, Shift, Cp) ->
- Data = lists:nth(DPos, DList),
- ShiftCp = Data bsl Shift,
- NewCp = Cp bor ShiftCp,
- {NewCp, DPos + 1};
+ Data = lists:nth(DPos, DList),
+ ShiftCp = Data bsl Shift,
+ NewCp = Cp bor ShiftCp,
+ {NewCp, DPos + 1};
calc_cp(_DList, DPos, 0, _Shift, Cp) ->
- {Cp, DPos}.
+ {Cp, DPos}.
patch_delta_header_size(DeltaData, Pos) ->
- patch_delta_header_size(DeltaData, Pos, 0, 1, 0).
+ patch_delta_header_size(DeltaData, Pos, 0, 1, 0).
patch_delta_header_size(DeltaData, Pos, Shift, 1, Size) ->
- Byte = lists:nth(Pos, DeltaData),
- <<ContinueBit:1, NextSize:7>> = <<Byte>>,
- %io:fwrite("Byte: ~p:~p:~p:~p:~p:~p~n", [Byte, Pos, Shift, Size, ContinueBit, NextSize]),
- SizeOr = NextSize bsl Shift,
- NewSize = Size bor SizeOr,
- patch_delta_header_size(DeltaData, Pos + 1, Shift + 7, ContinueBit, NewSize);
+ Byte = lists:nth(Pos, DeltaData),
+ <<ContinueBit:1, NextSize:7>> = <<Byte>>,
+ %io:fwrite("Byte: ~p:~p:~p:~p:~p:~p~n", [Byte, Pos, Shift, Size, ContinueBit, NextSize]),
+ SizeOr = NextSize bsl Shift,
+ NewSize = Size bor SizeOr,
+ patch_delta_header_size(DeltaData, Pos + 1, Shift + 7, ContinueBit, NewSize);
patch_delta_header_size(_DeltaData, Pos, _Shift, 0, Size) ->
- {ok, Size, Pos}.
+ {ok, Size, Pos}.
get_base_offset(IoDevice) ->
- {ok, Byte} = file:read(IoDevice, 1),
- <<ContinueBit:1, NextData:7>> = Byte,
- get_base_offset(IoDevice, ContinueBit, NextData, 1).
+ {ok, Byte} = file:read(IoDevice, 1),
+ <<ContinueBit:1, NextData:7>> = Byte,
+ get_base_offset(IoDevice, ContinueBit, NextData, 1).
get_base_offset(IoDevice, 1, Offset, BytesRead) ->
- {ok, Byte} = file:read(IoDevice, 1),
- <<ContinueBit:1, NextData:7>> = Byte,
- %io:fwrite("Data:~p:~p~n", [ContinueBit, NextData]),
- Offset2 = Offset + 1,
- Offset3 = Offset2 bsl 7,
- NewOffset = Offset3 bor NextData,
- get_base_offset(IoDevice, ContinueBit, NewOffset, BytesRead + 1);
+ {ok, Byte} = file:read(IoDevice, 1),
+ <<ContinueBit:1, NextData:7>> = Byte,
+ %io:fwrite("Data:~p:~p~n", [ContinueBit, NextData]),
+ Offset2 = Offset + 1,
+ Offset3 = Offset2 bsl 7,
+ NewOffset = Offset3 bor NextData,
+ get_base_offset(IoDevice, ContinueBit, NewOffset, BytesRead + 1);
get_base_offset(_IoDevice, 0, Offset, BytesRead) ->
- {ok, Offset, BytesRead}.
+ {ok, Offset, BytesRead}.
inflate_object_data(Z, IoDevice, SoFar) ->
- case file:read(IoDevice, 4096) of
- {ok, Bytes} ->
- _Inflated = case catch zlib:inflate(Z, Bytes) of
- {'EXIT', {'data_error', _Backtrace} } ->
- %io:format("zlib:inflate data_error,~n"),
- SoFar;
- {'EXIT', _Reason} ->
- %io:format("zlib:inflate error -> [~p]~n", [Reason]),
- SoFar;
- [] ->
- SoFar;
- Iolist ->
- [Data] = Iolist,
- ListData = list_to_binary([binary_to_list(Data)|SoFar]),
- %io:fwrite("Size: ~p~n", [size(ListData)]),
- inflate_object_data(Z, IoDevice, ListData)
- end;
- _Else ->
- SoFar
- end.
+ case file:read(IoDevice, 4096) of
+ {ok, Bytes} ->
+ _Inflated = case catch zlib:inflate(Z, Bytes) of
+ {'EXIT', {'data_error', _Backtrace} } ->
+ lager:error("zlib:inflate data_error,~n"),
+ SoFar;
+ {'EXIT', Reason} ->
+ lager:error("zlib:inflate error -> [~p]~n", [Reason]),
+ SoFar;
+ [] ->
+ SoFar;
+ Iolist ->
+ [Data] = Iolist,
+ ListData = list_to_binary([binary_to_list(Data)|SoFar]),
+ %io:fwrite("Size: ~p~n", [size(ListData)]),
+ inflate_object_data(Z, IoDevice, ListData)
+ end;
+ _Else ->
+ SoFar
+ end.
type_int_to_term(ObjInt) ->
- case ObjInt of
- 1 -> commit;
- 2 -> tree;
- 3 -> blob;
- 4 -> tag;
- 6 -> ofs_delta;
- 7 -> ref_delta
- end.
-
+ case ObjInt of
+ 1 -> commit;
+ 2 -> tree;
+ 3 -> blob;
+ 4 -> tag;
+ 6 -> ofs_delta;
+ 7 -> ref_delta
+ end.

0 comments on commit 36abb62

Please sign in to comment.