diff options
| author | Fred Hebert <mononcqc@ferd.ca> | 2015-08-27 07:29:08 +1200 | 
|---|---|---|
| committer | Fred Hebert <mononcqc@ferd.ca> | 2015-08-27 07:29:08 +1200 | 
| commit | bb14f2425763857e40aba9d8ce8299e5cc96a9a2 (patch) | |
| tree | 4483b595fa49e92829f7b25994e22382040af146 | |
| parent | 79d66de59c7a1673ce7374d45f5853a9f4aa3d91 (diff) | |
| parent | a27fd22c3fe1f71091dce27be3c71dc5b75ae2f0 (diff) | |
Merge pull request #748 from tsloughter/pkg_attribute
support pkg attribute on dep to declare package name different from app name
| -rw-r--r-- | src/rebar_app_discover.erl | 2 | ||||
| -rw-r--r-- | src/rebar_app_info.erl | 16 | ||||
| -rw-r--r-- | src/rebar_app_utils.erl | 73 | ||||
| -rw-r--r-- | src/rebar_config.erl | 9 | ||||
| -rw-r--r-- | src/rebar_prv_install_deps.erl | 26 | ||||
| -rw-r--r-- | src/rebar_prv_plugins_upgrade.erl | 2 | ||||
| -rw-r--r-- | src/rebar_state.erl | 44 | ||||
| -rw-r--r-- | test/rebar_pkg_alias_SUITE.erl | 121 | ||||
| -rw-r--r-- | test/rebar_test_utils.erl | 25 | 
9 files changed, 236 insertions, 82 deletions
| diff --git a/src/rebar_app_discover.erl b/src/rebar_app_discover.erl index 2b1c767..5a25a9e 100644 --- a/src/rebar_app_discover.erl +++ b/src/rebar_app_discover.erl @@ -198,7 +198,7 @@ create_app_info(AppDir, AppFile) ->      AppVsn = proplists:get_value(vsn, AppDetails),      Applications = proplists:get_value(applications, AppDetails, []),      IncludedApplications = proplists:get_value(included_applications, AppDetails, []), -    {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir, []), +    {ok, AppInfo} = rebar_app_info:new(AppName, AppVsn, AppDir),      AppInfo1 = rebar_app_info:applications(                   rebar_app_info:app_details(AppInfo, AppDetails),                   IncludedApplications++Applications), diff --git a/src/rebar_app_info.erl b/src/rebar_app_info.erl index bb99584..bb5104e 100644 --- a/src/rebar_app_info.erl +++ b/src/rebar_app_info.erl @@ -4,6 +4,7 @@           new/2,           new/3,           new/4, +         new/5,           discover/1,           name/1,           name/2, @@ -58,7 +59,7 @@                       app_file           :: file:filename_all() | undefined,                       config             :: rebar_state:t() | undefined,                       original_vsn       :: binary() | string() | undefined, -                     parent             :: binary() | root, +                     parent=root        :: binary() | root,                       app_details=[]     :: list(),                       applications=[]    :: list(),                       deps=[]            :: list(), @@ -113,6 +114,17 @@ new(AppName, Vsn, Dir, Deps) ->                       out_dir=ec_cnv:to_list(Dir),                       deps=Deps}}. +%% @doc build a complete version of the app info with all fields set. +-spec new(atom() | binary(), atom() | binary() | string(), binary() | string(), file:name(), list()) -> +                 {ok, t()}. +new(Parent, AppName, Vsn, Dir, Deps) -> +    {ok, #app_info_t{name=ec_cnv:to_binary(AppName), +                     parent=Parent, +                     original_vsn=Vsn, +                     dir=ec_cnv:to_list(Dir), +                     out_dir=ec_cnv:to_list(Dir), +                     deps=Deps}}. +  %% @doc discover a complete version of the app info with all fields set.  -spec discover(file:filename_all()) -> {ok, t()} | not_found.  discover(Dir) -> @@ -305,7 +317,7 @@ state(#app_info_t{state=State}) ->  state_or_new(State, AppInfo=#app_info_t{state=undefined}) ->      AppDir = dir(AppInfo),      C = rebar_config:consult(AppDir), -    rebar_state:new(State, C, AppDir); +    rebar_state:new(State, C, AppInfo);  state_or_new(_State, #app_info_t{state=State}) ->      State. diff --git a/src/rebar_app_utils.erl b/src/rebar_app_utils.erl index 7239fe7..88b75ac 100644 --- a/src/rebar_app_utils.erl +++ b/src/rebar_app_utils.erl @@ -117,33 +117,21 @@ parse_dep(Dep, Parent, DepsDir, State, Locks, Level) ->              end      end. +parse_dep(Parent, {Name, Vsn, {pkg, PkgName}}, DepsDir, IsLock, State) -> +    {PkgName1, PkgVsn} = parse_goal(ec_cnv:to_binary(PkgName), ec_cnv:to_binary(Vsn)), +    pkg_to_app(Parent, DepsDir, Name, PkgName1, PkgVsn, IsLock, State); +parse_dep(Parent, {Name, {pkg, PkgName}}, DepsDir, IsLock, State) -> +    %% Package dependency with different package name from app name +    {PkgName1, PkgVsn} = get_package(ec_cnv:to_binary(PkgName), State), +    pkg_to_app(Parent, DepsDir, Name, PkgName1, PkgVsn, IsLock, State);  parse_dep(Parent, {Name, Vsn}, DepsDir, IsLock, State) when is_list(Vsn); is_binary(Vsn) ->      %% Versioned Package dependency -    CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)), -    case rebar_app_info:discover(CheckoutsDir) of -        {ok, _App} -> -            dep_to_app(root, DepsDir, Name, [], [], IsLock, State); -        not_found -> -            {PkgName, PkgVsn} = parse_goal(ec_cnv:to_binary(Name) -                                          ,ec_cnv:to_binary(Vsn)), -            %% Verify package actually exists. This will throw a missing_package exception -            rebar_packages:deps(PkgName, PkgVsn, State), -            Source = {pkg, PkgName, PkgVsn}, -            rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, PkgName, PkgVsn, Source, IsLock, State), pkg) -    end; +    {PkgName, PkgVsn} = parse_goal(ec_cnv:to_binary(Name), ec_cnv:to_binary(Vsn)), +    pkg_to_app(Parent, DepsDir, PkgName, PkgName, PkgVsn, IsLock, State);  parse_dep(Parent, Name, DepsDir, IsLock, State) when is_atom(Name); is_binary(Name) ->      %% Unversioned package dependency      {PkgName, PkgVsn} = get_package(ec_cnv:to_binary(Name), State), -    CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)), -    case rebar_app_info:discover(CheckoutsDir) of -        {ok, _App} -> -            dep_to_app(root, DepsDir, Name, [], [], IsLock, State); -        not_found -> -            %% Verify package actually exists. This will throw a missing_package exception -            rebar_packages:deps(PkgName, PkgVsn, State), -            Source = {pkg, PkgName, PkgVsn}, -            rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, PkgName, PkgVsn, Source, IsLock, State), pkg) -    end; +    pkg_to_app(Parent, DepsDir, PkgName, PkgName, PkgVsn, IsLock, State);  parse_dep(Parent, {Name, Source}, DepsDir, IsLock, State) when is_tuple(Source) ->      dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);  parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(Source) -> @@ -151,27 +139,26 @@ parse_dep(Parent, {Name, _Vsn, Source}, DepsDir, IsLock, State) when is_tuple(So  parse_dep(Parent, {Name, _Vsn, Source, Opts}, DepsDir, IsLock, State) when is_tuple(Source) ->      ?WARN("Dependency option list ~p in ~p is not supported and will be ignored", [Opts, Name]),      dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State); -parse_dep(Parent, {_Name, {pkg, Name, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) -> -    CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)), -    case rebar_app_info:discover(CheckoutsDir) of -        {ok, _App} -> -            dep_to_app(root, DepsDir, Name, [], [], IsLock, State); -        not_found -> -            %% Verify package actually exists. This will throw a missing_package exception -            rebar_packages:deps(Name, Vsn, State), -            Source = {pkg, Name, Vsn}, -            rebar_app_info:resource_type(dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State), pkg) -    end; +parse_dep(Parent, {Name, {pkg, PkgName, Vsn}, Level}, DepsDir, IsLock, State) when is_integer(Level) -> +    pkg_to_app(Parent, DepsDir, Name, PkgName, Vsn, IsLock, State);  parse_dep(Parent, {Name, Source, Level}, DepsDir, IsLock, State) when is_tuple(Source)                                                                      , is_integer(Level) ->      dep_to_app(Parent, DepsDir, Name, [], Source, IsLock, State);  parse_dep(_, Dep, _, _, _) ->      throw(?PRV_ERROR({parse_dep, Dep})). +%% Verify package exists and create the AppInfo record +pkg_to_app(Parent, DepsDir, AppName, PkgName, PkgVsn, IsLock, State) -> +    %% Verify package actually exists. This will throw a missing_package exception +    Deps = rebar_packages:deps(PkgName, PkgVsn, State), +    Source = {pkg, PkgName, PkgVsn}, +    AppInfo = dep_to_app(Parent, DepsDir, AppName, PkgVsn, Source, IsLock, State), +    rebar_app_info:resource_type(rebar_app_info:deps(AppInfo, Deps), pkg). +  dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->      CheckoutsDir = ec_cnv:to_list(rebar_dir:checkouts_dir(State, Name)),      BaseDir = rebar_state:get(State, base_dir, []), -    {ok, Dep} = case rebar_app_info:discover(CheckoutsDir) of +    {ok, App1} = case rebar_app_info:discover(CheckoutsDir) of                      {ok, App} ->                          {ok, rebar_app_info:is_checkout(App, true)};                      not_found -> @@ -180,24 +167,16 @@ dep_to_app(Parent, DepsDir, Name, Vsn, Source, IsLock, State) ->                              {ok, App} ->                                  {ok, App};                              not_found -> -                                rebar_app_info:new(Name, Vsn, -                                                   ec_cnv:to_list(filename:join(DepsDir, Name))) +                                rebar_app_info:new(Parent, Name, Vsn, Dir, [])                          end                  end, -    C = rebar_config:consult(rebar_app_info:dir(Dep)), -    S = rebar_state:new(rebar_state:new(), C, rebar_app_info:dir(Dep)), +    C = rebar_config:consult(rebar_app_info:dir(App1)), +    S = rebar_state:new(rebar_state:new(), C, App1),      Overrides = rebar_state:get(State, overrides, []),      ParentOverrides = rebar_state:overrides(State),      S1 = rebar_state:set(rebar_state:overrides(S, ParentOverrides++Overrides), base_dir, BaseDir), -    Dep1 = rebar_app_info:state(Dep, S1), -    AppInfo = rebar_app_info:is_lock(rebar_app_info:source(Dep1, Source), IsLock), -    ResourceType = case Source of -                       {pkg, _, _} -> -                           pkg; -                       _ -> -                           src -                   end, -    rebar_app_info:resource_type(rebar_app_info:parent(AppInfo, Parent), ResourceType). +    App2 = rebar_app_info:state(App1, S1), +    rebar_app_info:is_lock(rebar_app_info:source(App2, Source), IsLock).  format_error({missing_package, Package}) ->      io_lib:format("Package not found in registry: ~s", [Package]); diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 554b399..b9b8b2e 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -128,11 +128,20 @@ find_newly_added(ConfigDeps, LockedDeps) ->  check_newly_added({_, _}=Dep, LockedDeps) ->      check_newly_added_(Dep, LockedDeps); +check_newly_added({_, _, {pkg, _}}=Dep, LockedDeps) -> +    check_newly_added_(Dep, LockedDeps);  check_newly_added({Name, _, Source}, LockedDeps) ->      check_newly_added_({Name, Source}, LockedDeps);  check_newly_added(Dep, LockedDeps) ->      check_newly_added_(Dep, LockedDeps). +check_newly_added_({Name, Vsn, Source}, LockedDeps) -> +    case check_newly_added_(Name, LockedDeps) of +        {true, Name1} -> +            {true, {Name1, Vsn, Source}}; +        false -> +            false +    end;  check_newly_added_({Name, Source}, LockedDeps) ->      case check_newly_added_(Name, LockedDeps) of          {true, Name1} -> diff --git a/src/rebar_prv_install_deps.erl b/src/rebar_prv_install_deps.erl index cc65d30..ca9344b 100644 --- a/src/rebar_prv_install_deps.erl +++ b/src/rebar_prv_install_deps.erl @@ -253,12 +253,11 @@ update_unseen_dep(AppInfo, Profile, Level, Deps, Apps, State, Upgrade, Seen, Loc  handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->      Profiles = rebar_state:current_profiles(State),      Name = rebar_app_info:name(AppInfo), -    Vsn = rebar_app_info:original_vsn(AppInfo),      %% Deps may be under a sub project app, find it and use its state if so      S = rebar_app_info:state(AppInfo),      C = rebar_config:consult(rebar_app_info:dir(AppInfo)), -    S1 = rebar_state:new(S, C, rebar_app_info:dir(AppInfo)), +    S1 = rebar_state:new(S, C, AppInfo),      S2 = rebar_state:apply_overrides(S1, Name),      S3 = rebar_state:apply_profiles(S2, Profiles), @@ -273,17 +272,10 @@ handle_dep(State, Profile, DepsDir, AppInfo, Locks, Level) ->      AppInfo1 = rebar_app_info:state(AppInfo, S5),      %% Upgrade lock level to be the level the dep will have in this dep tree -    case rebar_app_info:resource_type(AppInfo1) of -        pkg -> -            NewDeps = rebar_packages:deps(Name, Vsn, S5), -            NewDeps1 = rebar_app_utils:parse_deps(Name, DepsDir, NewDeps, S5, Locks, Level+1), -            {rebar_app_info:deps(AppInfo1, NewDeps), NewDeps1, State}; -        _ -> -            Deps = rebar_state:get(S5, {deps, default}, []), -            AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)), -            Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, S5, Locks, Level+1), -            {AppInfo2, Deps1, State} -    end. +    Deps = rebar_state:get(S5, {deps, default}, []), +    AppInfo2 = rebar_app_info:deps(AppInfo1, rebar_state:deps_names(Deps)), +    Deps1 = rebar_app_utils:parse_deps(Name, DepsDir, Deps, S5, Locks, Level+1), +    {AppInfo2, Deps1, State}.  -spec maybe_fetch(rebar_app_info:t(), atom(), boolean(),                    sets:set(binary()), rebar_state:t()) -> {boolean(), rebar_app_info:t()}. @@ -384,13 +376,15 @@ update_app_info(AppDir, AppInfo) ->      end.  copy_app_info(OldAppInfo, NewAppInfo) -> +    Deps = rebar_app_info:deps(OldAppInfo),      ResourceType = rebar_app_info:resource_type(OldAppInfo),      Parent = rebar_app_info:parent(OldAppInfo),      Source = rebar_app_info:source(OldAppInfo), -    rebar_app_info:resource_type( -      rebar_app_info:source( -        rebar_app_info:parent(NewAppInfo, Parent), Source), ResourceType). +    rebar_app_info:deps( +      rebar_app_info:resource_type( +        rebar_app_info:source( +          rebar_app_info:parent(NewAppInfo, Parent), Source), ResourceType), Deps).  maybe_upgrade(AppInfo, AppDir, Upgrade, State) ->      Source = rebar_app_info:source(AppInfo), diff --git a/src/rebar_prv_plugins_upgrade.erl b/src/rebar_prv_plugins_upgrade.erl index dfc9990..fabfa5b 100644 --- a/src/rebar_prv_plugins_upgrade.erl +++ b/src/rebar_prv_plugins_upgrade.erl @@ -91,5 +91,5 @@ build_plugin(AppInfo, Apps, State) ->      Providers = rebar_state:providers(State),      AppDir = rebar_app_info:dir(AppInfo),      C = rebar_config:consult(AppDir), -    S = rebar_state:new(rebar_state:all_deps(rebar_state:new(), Apps), C, AppDir), +    S = rebar_state:new(rebar_state:all_deps(rebar_state:new(), Apps), C, AppInfo),      rebar_prv_compile:compile(S, Providers, AppInfo). diff --git a/src/rebar_state.erl b/src/rebar_state.erl index 6feae81..e31b01b 100644 --- a/src/rebar_state.erl +++ b/src/rebar_state.erl @@ -97,21 +97,26 @@ new(ParentState=#state_t{}, Config) ->      Dir = rebar_dir:get_cwd(),      new(ParentState, Config, Dir). --spec new(t(), list(), file:name()) -> t(). -new(ParentState, Config, Dir) -> +-spec new(t(), list(), rebar_app_info:t() | file:filename_all()) -> t(). +new(ParentState, Config, Dir) when is_list(Dir) -> +    new(ParentState, Config, deps_from_config(Dir, Config), Dir); +new(ParentState, Config, AppInfo) -> +    Dir = rebar_app_info:dir(AppInfo), +    DepLocks = case rebar_app_info:resource_type(AppInfo) of +                   pkg -> +                       Deps = rebar_app_info:deps(AppInfo), +                       [{{locks, default}, Deps}, {{deps, default}, Deps}]; +                   _ -> +                       deps_from_config(Dir, Config) +               end, +    new(ParentState, Config, DepLocks, Dir). + +new(ParentState, Config, Deps, Dir) ->      Opts = ParentState#state_t.opts, -    LocalOpts = case rebar_config:consult_lock_file(filename:join(Dir, ?LOCK_FILE)) of -                    [D] -> -                        %% We want the top level deps only from the lock file. -                        %% This ensures deterministic overrides for configs. -                        Deps = [X || X <- D, element(3, X) =:= 0], -                        Plugins = proplists:get_value(plugins, Config, []), -                        Terms = [{{locks, default}, D}, {{deps, default}, Deps}, {{plugins, default}, Plugins} | Config], -                        true = rebar_config:verify_config_format(Terms), -                        dict:from_list(Terms); -                    _ -> -                       base_opts(Config) -                end, +    Plugins = proplists:get_value(plugins, Config, []), +    Terms = Deps++[{{plugins, default}, Plugins} | Config], +    true = rebar_config:verify_config_format(Terms), +    LocalOpts = dict:from_list(Terms),      NewOpts = merge_opts(LocalOpts, Opts), @@ -119,6 +124,17 @@ new(ParentState, Config, Dir) ->                         ,opts=NewOpts                         ,default=NewOpts}. +deps_from_config(Dir, Config) -> +    case rebar_config:consult_lock_file(filename:join(Dir, ?LOCK_FILE)) of +        [D] -> +            %% We want the top level deps only from the lock file. +            %% This ensures deterministic overrides for configs. +            Deps = [X || X <- D, element(3, X) =:= 0], +            [{{locks, default}, D}, {{deps, default}, Deps}]; +        _ -> +            [{{deps, default}, proplists:get_value(deps, Config, [])}] +    end. +  base_state() ->      case application:get_env(rebar, resources) of          undefined -> diff --git a/test/rebar_pkg_alias_SUITE.erl b/test/rebar_pkg_alias_SUITE.erl new file mode 100644 index 0000000..f7fa5d4 --- /dev/null +++ b/test/rebar_pkg_alias_SUITE.erl @@ -0,0 +1,121 @@ +-module(rebar_pkg_alias_SUITE). +-compile(export_all). +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("kernel/include/file.hrl"). + +all() -> [same_alias, diff_alias, diff_alias_vsn]. + +%% {uuid, {pkg, uuid}} = uuid +%% {uuid, {pkg, alias}} = uuid on disk +%% another run should yield the same lock file without error +init_per_suite(Config) -> +    mock_config(?MODULE, Config). + +end_per_suite(Config) -> +    unmock_config(Config). + +init_per_testcase(same_alias, Config0) -> +    Config = rebar_test_utils:init_rebar_state(Config0,"same_alias_"), +    AppDir = ?config(apps, Config), +    rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), +    RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, fakelib}}]}]), +    [{rebarconfig, RebarConf} | Config]; +init_per_testcase(diff_alias, Config0) -> +    Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_"), +    AppDir = ?config(apps, Config), +    rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), +    RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, {pkg, goodpkg}}]}]), +    [{rebarconfig, RebarConf} | Config]; +init_per_testcase(diff_alias_vsn, Config0) -> +    Config = rebar_test_utils:init_rebar_state(Config0,"diff_alias_vsn_"), +    AppDir = ?config(apps, Config), +    rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), +    RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [{fakelib, "1.0.0", {pkg, goodpkg}}]}]), +    [{rebarconfig, RebarConf} | Config]. + +end_per_testcase(_, Config) -> +    Config. + +same_alias(Config) -> +    {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), +    rebar_test_utils:run_and_check( +        Config, RebarConfig, ["lock"], +        {ok, [{lock, "fakelib"}, {dep, "fakelib"}]} +    ). + +diff_alias(Config) -> +    %% even though the dep is 'fakelib' aliased as 'goodpkg' all +    %% internal records use 'fakelib' as a value. Just make sure +    %% the lock actually maintains the proper source as 'goodpkg' +    AppDir = ?config(apps, Config), +    Lockfile = filename:join([AppDir, "rebar.lock"]), +    {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), +    rebar_test_utils:run_and_check( +        Config, RebarConfig, ["lock"], +        {ok, [{lock, "fakelib"},{dep, "fakelib"}]} +    ), +    {ok, [LockData]} = file:consult(Lockfile), +    ?assert(lists:any(fun({<<"fakelib">>,{pkg,<<"goodpkg">>,_},_}) -> true +                      ;  (_) -> false end, LockData)), +    %% An second run yields the same +    rebar_test_utils:run_and_check( +        Config, RebarConfig, ["lock"], +        {ok, [{lock, "fakelib"},{dep, "fakelib"}]} +    ), +    {ok, [LockData]} = file:consult(Lockfile), +    %% So does an upgrade +    rebar_test_utils:run_and_check( +        Config, RebarConfig, ["upgrade"], +        {ok, [{lock, "fakelib"},{dep, "fakelib"}]} +    ), +    {ok, [LockData]} = file:consult(Lockfile). + +diff_alias_vsn(Config) -> diff_alias(Config). + +mock_config(Name, Config) -> +    Priv = ?config(priv_dir, Config), +    AppDir = filename:join([Priv, "fakelib"]), +    CacheRoot = filename:join([Priv, "cache", atom_to_list(Name)]), +    TmpDir = filename:join([Priv, "tmp", atom_to_list(Name)]), +    CacheDir = filename:join([CacheRoot, "hex", "com", "test", "packages"]), +    filelib:ensure_dir(filename:join([CacheDir, "registry"])), +    rebar_test_utils:create_app(AppDir, "fakelib", "1.0.0", [kernel, stdlib]), +    {Chk,Etag} = rebar_test_utils:package_app(AppDir, CacheDir, "fakelib-1.0.0"), +    {Chk,Etag} = rebar_test_utils:package_app(AppDir, CacheDir, "goodpkg-1.0.0"), + +    Tid = ets:new(registry_table, [public]), +    ets:insert_new(Tid, [ +        {<<"fakelib">>,[[<<"1.0.0">>]]}, +        {<<"goodpkg">>,[[<<"1.0.0">>]]}, +        {{<<"fakelib">>,<<"1.0.0">>}, [[], Chk, [<<"rebar3">>]]}, +        {{<<"goodpkg">>,<<"1.0.0">>}, [[], Chk, [<<"rebar3">>]]} +    ]), +    ok = ets:tab2file(Tid, filename:join([CacheDir, "registry"])), +    ets:delete(Tid), +    %% The state returns us a fake registry +    meck:new(rebar_dir, [passthrough, no_link]), +    meck:expect(rebar_dir, global_cache_dir, fun(_) -> CacheRoot end), + +    meck:new(rebar_packages, [passthrough, no_link]), +    meck:expect(rebar_packages, registry_dir, fun(_) -> CacheDir end), +    meck:expect(rebar_packages, package_dir, fun(_) -> CacheDir end), +    rebar_prv_update:hex_to_index(rebar_state:new()), + +    %% Cache fetches are mocked -- we assume the server and clients are +    %% correctly used. +    meck:new(httpc, [passthrough, unsticky, no_link]), +    meck:expect(httpc, request, +            fun(get, {_Url, _Opts}, _, _, _) -> +                {ok, {{<<"1.0.0">>, 304, <<"Not Modified">>}, [{"etag", Etag}], <<>>}} +            end), +    %% Move all packages to cache +    NewConf = [{cache_root, CacheRoot}, +               {cache_dir, CacheDir}, +               {tmp_dir, TmpDir}, +               {mock_table, Tid} | Config], +    NewConf. + +unmock_config(Config) -> +    meck:unload(), +    Config. diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl index c07df68..8d1d408 100644 --- a/test/rebar_test_utils.erl +++ b/test/rebar_test_utils.erl @@ -3,7 +3,8 @@  -include_lib("eunit/include/eunit.hrl").  -export([init_rebar_state/1, init_rebar_state/2, run_and_check/4]).  -export([expand_deps/2, flat_deps/1, top_level_deps/1]). --export([create_app/4, create_eunit_app/4, create_empty_app/4, create_config/2]). +-export([create_app/4, create_eunit_app/4, create_empty_app/4, create_config/2, +         package_app/3]).  -export([create_random_name/1, create_random_vsn/0, write_src_file/2]).  %%%%%%%%%%%%%% @@ -418,3 +419,25 @@ get_app_metadata(Name, Vsn, Deps) ->        {included_applications, []},        {registered, []},        {applications, Deps}]}. + +package_app(AppDir, DestDir, PkgName) -> +    Name = PkgName++".tar", +    {ok, Fs} = file:list_dir(AppDir), +    ok = erl_tar:create(filename:join(DestDir, "contents.tar.gz"), +                        lists:zip(Fs, [filename:join(AppDir,F) || F <- Fs]), +                        [compressed]), +    ok = file:write_file(filename:join(DestDir, "metadata.config"), "who cares"), +    ok = file:write_file(filename:join(DestDir, "VERSION"), "3"), +    {ok, Contents} = file:read_file(filename:join(DestDir, "contents.tar.gz")), +    Blob = <<"3who cares", Contents/binary>>, +    <<X:256/big-unsigned>> = crypto:hash(sha256, Blob), +    BinChecksum = list_to_binary(string:to_upper(lists:flatten(io_lib:format("~64.16.0b", [X])))), +    ok = file:write_file(filename:join(DestDir, "CHECKSUM"), BinChecksum), +    PkgFiles = ["contents.tar.gz", "VERSION", "metadata.config", "CHECKSUM"], +    Archive = filename:join(DestDir, Name), +    ok = erl_tar:create(Archive, +                        lists:zip(PkgFiles, [filename:join(DestDir,F) || F <- PkgFiles])), +    {ok, BinFull} = file:read_file(Archive), +    <<E:128/big-unsigned-integer>> = crypto:hash(md5, BinFull), +    Etag = string:to_lower(lists:flatten(io_lib:format("~32.16.0b", [E]))), +    {BinChecksum, Etag}. | 
