Skip to content

Commit

Permalink
Add comments to make erl_prim_loader primary archive handling more re…
Browse files Browse the repository at this point in the history
…adable

This commit introduces no functional change. It only adds comments and
changes some function/variable names.
  • Loading branch information
sirihansen committed Jul 9, 2012
1 parent e029c2d commit 13d1355
Showing 1 changed file with 74 additions and 52 deletions.
126 changes: 74 additions & 52 deletions erts/preloaded/src/erl_prim_loader.erl
Expand Up @@ -833,8 +833,8 @@ prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin, #file_info{} = FileInfo)
case PS#prim_state.primary_archive of
undefined ->
Fun =
fun({Funny, _GI, _GB}, A) ->
case Funny of
fun({Components, _GI, _GB}, A) ->
case Components of
["", "nibe", RevApp] -> % Reverse ebin
%% Collect ebin directories in archive
Ebin = reverse(RevApp) ++ "/ebin",
Expand Down Expand Up @@ -874,11 +874,11 @@ prim_get_file(PS, File) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_get_file, ArchiveFile, FileInArchive}),
FunnyFile = funny_split(FileInArchive, $/),
FileComponents = path_split(FileInArchive),
Fun =
fun({Funny, _GetInfo, GetBin}, Acc) ->
fun({Components, _GetInfo, GetBin}, Acc) ->
if
Funny =:= FunnyFile ->
Components =:= FileComponents ->
{false, {ok, GetBin()}};
true ->
{true, Acc}
Expand All @@ -901,11 +901,11 @@ prim_list_dir(PS, Dir) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_list_dir, ArchiveFile, FileInArchive}),
FunnyDir = funny_split(FileInArchive, $/),
DirComponents = path_split(FileInArchive),
Fun =
fun({Funny, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
case Funny of
[RevName | FD] when FD =:= FunnyDir ->
fun({Components, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
case Components of
[RevName | DC] when DC =:= DirComponents ->
case RevName of
"" ->
%% The listed directory
Expand All @@ -915,16 +915,16 @@ prim_list_dir(PS, Dir) ->
Name = reverse(RevName),
{true, {Status, [Name | Names]}}
end;
["", RevName | FD] when FD =:= FunnyDir ->
["", RevName | DC] when DC =:= DirComponents ->
%% Directory
Name = reverse(RevName),
{true, {Status, [Name | Names]}};
[RevName] when FunnyDir =:= [""] ->
%% Top file
[RevName] when DirComponents =:= [""] ->
%% File in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
["", RevName] when FunnyDir =:= [""] ->
%% Top file
["", RevName] when DirComponents =:= [""] ->
%% Directory in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
_ ->
Expand Down Expand Up @@ -963,15 +963,14 @@ prim_read_file_info(PS, File) ->
end;
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_read_file_info, File}),
FunnyFile = funny_split(FileInArchive, $/),
FileComponents = path_split(FileInArchive),
Fun =
fun({Funny, GetInfo, _GetBin}, Acc) ->
case Funny of
[H | T] when H =:= "",
T =:= FunnyFile ->
fun({Components, GetInfo, _GetBin}, Acc) ->
case Components of
["" | F] when F =:= FileComponents ->
%% Directory
{false, {ok, GetInfo()}};
F when F =:= FunnyFile ->
F when F =:= FileComponents ->
%% Plain file
{false, {ok, GetInfo()}};
_ ->
Expand Down Expand Up @@ -1064,50 +1063,69 @@ open_archive(Archive, Acc, Fun) ->
{error, Reason}
end.

%% Open the given archive and iterate through all files with an own
%% wrapper fun in order to identify each file as a component list as
%% returned from path_split/1.
%%
%% In the archive (zip) file, directory elements might or might not be
%% present. To ensure consistency, a directory element is added if it
%% does not already exist (ensure_virual_dir/6). NOTE that there will
%% be no such directory element for the top directory of the archive.
open_archive(Archive, FileInfo, Acc, Fun) ->
FakeFI = FileInfo#file_info{type = directory},
Wrapper =
fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
Funny = funny_split(N, $/),
FunnyDirs2 =
case Funny of
["" | FunnyDir] ->
[FunnyDir | FunnyDirs];
fun({N, GI, GB}, {A, I, Dirs}) ->
Components = path_split(N),
Dirs2 =
case Components of
["" | Dir] ->
%% This is a directory
[Dir | Dirs];
_ ->
FunnyDirs
%% This is a regular file
Dirs
end,
{Includes, FunnyDirs3, A2} =
ensure_virtual_dirs(Funny, Fun, FakeFI, [{true, Funny}], FunnyDirs2, A),
{_Continue, A3} = Fun({Funny, GI, GB}, A2),
{true, Includes, {A3, I, FunnyDirs3}}
{Includes, Dirs3, A2} =
ensure_virtual_dirs(Components, Fun, FakeFI,
[{true, Components}], Dirs2, A),
{_Continue, A3} = Fun({Components, GI, GB}, A2),
{true, Includes, {A3, I, Dirs3}}
end,
prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive).

ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
case Funny of
ensure_virtual_dirs(Components, Fun, FakeFI, Includes, Dirs, Acc) ->
case Components of
[_] ->
{Includes, FunnyDirs, Acc};
[_ | FunnyDir] ->
case lists:member(FunnyDir, FunnyDirs) of % BIF
%% Don't add virtual dir for top directory
{Includes, Dirs, Acc};
[_ | Dir] ->
case lists:member(Dir, Dirs) of % BIF
false ->
%% The directory does not yet exist - add it
GetInfo = fun() -> FakeFI end,
GetBin = fun() -> <<>> end,
VirtualDir = ["" | FunnyDir],
VirtualDir = ["" | Dir],
Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
FunnyDirs2 = [FunnyDir | FunnyDirs],
{I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
Dirs2 = [Dir | Dirs],

%% Recursively ensure dir elements on all levels
{I, F, Acc2} = ensure_virtual_dirs(Dir, Fun, FakeFI,
Includes2, Dirs2, Acc),

{_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
{I, F, Acc3};
true ->
ensure_virtual_dirs(FunnyDir,Fun,FakeFI,Includes,FunnyDirs,Acc)
%% The directory element does already exist
%% Recursivly ensure dir elements on all levels
ensure_virtual_dirs(Dir,Fun,FakeFI,Includes,Dirs,Acc)
end
end.
end.

foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
fun({Funny, GI, GB}, A) ->
fun({Components, GI, GB}, A) ->
%% Allow partial iteration at foldl
{Continue, A2} = Fun({Funny, GI, GB}, A),
{Continue, A2} = Fun({Components, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
Expand Down Expand Up @@ -1203,15 +1221,19 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF

%% Returns all lists in reverse order
funny_split(List, Sep) ->
funny_split(List, Sep, [], []).

funny_split([Sep | Tail], Sep, Path, Paths) ->
funny_split(Tail, Sep, [], [Path | Paths]);
funny_split([Head | Tail], Sep, Path, Paths) ->
funny_split(Tail, Sep, [Head | Path], Paths);
funny_split([], _Sep, Path, Paths) ->
%% Returns a reversed list of path components, each component itself a
%% reversed list (string), e.g.
%% /path/to/file -> ["elif","ot","htap",""]
%% /path/to/dir/ -> ["","rid","ot","htap",""]
%% Note the "" marking leading and trailing / (slash).
path_split(List) ->
path_split(List, [], []).

path_split([$/ | Tail], Path, Paths) ->
path_split(Tail, [], [Path | Paths]);
path_split([Head | Tail], Path, Paths) ->
path_split(Tail, [Head | Path], Paths);
path_split([], Path, Paths) ->
[Path | Paths].

name_split(ArchiveFile, File0) ->
Expand Down

0 comments on commit 13d1355

Please sign in to comment.