From 124f121d38322a3db50458caeac47e84dccee45c Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 6 May 2016 23:18:55 -0400 Subject: Support package hashes in structure and lockfile - the internal representation for package locks moves from `{Name, {pkg, PkgName, Vsn}, Lvl}` to `{Name, {pkg, PkgName, Vsn, Hash}, Lvl}` - the internal representation for packages moves from `{pkg, PkgName, Vsn}` to `{pkg, PkgName, Vsn, Hash}` - the hash can be `undefined`, meaning no check will be done - no checking is done yet. --- src/rebar_config.erl | 66 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 14 deletions(-) (limited to 'src/rebar_config.erl') diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 8d7bcf4..031df8b 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -56,35 +56,73 @@ consult_lock_file(File) -> [] -> []; [Locks] when is_list(Locks) -> % beta lock file - Locks; + read_attrs(beta, Locks, []); [{Vsn, Locks}|Attrs] when is_list(Locks) -> % versioned lock file - %% Make sure the warning above is to be shown whenever a version - %% newer than the current one is being used, as we can't parse - %% all the contents of the lock file properly. - ?WARN("Rebar3 detected a lock file from a newer version. " - "It will be loaded in compatibility mode, but important " - "information may be missing or lost. It is recommended to " - "upgrade Rebar3.", []), + case Vsn of + ?CONFIG_VERSION -> + ok; + _ -> + %% Make sure the warning below is to be shown whenever a version + %% newer than the current one is being used, as we can't parse + %% all the contents of the lock file properly. + ?WARN("Rebar3 detected a lock file from a newer version. " + "It will be loaded in compatibility mode, but important " + "information may be missing or lost. It is recommended to " + "upgrade Rebar3.", []) + end, read_attrs(Vsn, Locks, Attrs) end. write_lock_file(LockFile, Locks) -> - NewLocks = write_attrs(Locks), + {NewLocks, Attrs} = write_attrs(Locks), %% Write locks in the beta format, at least until it's been long %% enough we can start modifying the lock format. - file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])). + case Attrs of + [] -> % write the old beta copy to avoid changes + file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])); + _ -> + file:write_file(LockFile, + io_lib:format("{~p,~p}.~n~p.~n", + [?CONFIG_VERSION, NewLocks, Attrs])) + end. -read_attrs(_Vsn, Locks, _Attrs) -> +read_attrs(_Vsn, Locks, Attrs) -> %% Beta copy does not know how to expand attributes, but %% is ready to support it. - Locks. + expand_locks(Locks, extract_pkg_hashes(Attrs)). + +extract_pkg_hashes(Attrs) -> + Props = case Attrs of + [First|_] -> First; + [] -> [] + end, + proplists:get_value(pkg_hash, Props, []). + +expand_locks([], _Hashes) -> + []; +expand_locks([{Name, {pkg,PkgName,Vsn}, Lvl} | Locks], Hashes) -> + Hash = proplists:get_value(Name, Hashes), + [{Name, {pkg,PkgName,Vsn,Hash}, Lvl} | expand_locks(Locks, Hashes)]; +expand_locks([Lock|Locks], Hashes) -> + [Lock | expand_locks(Locks, Hashes)]. write_attrs(Locks) -> %% No attribute known that needs to be taken out of the structure, %% just return terms as is. - Locks. - + {NewLocks, Hashes} = split_locks(Locks, [], []), + case Hashes of + [] -> {NewLocks, []}; + _ -> {NewLocks, [{pkg_hash, lists:sort(Hashes)}]} + end. +split_locks([], Locks, Hashes) -> + {lists:reverse(Locks), Hashes}; +split_locks([{Name, {pkg,PkgName,Vsn,undefined}, Lvl} | Locks], LAcc, HAcc) -> + split_locks(Locks, [{Name,{pkg,PkgName,Vsn},Lvl}|LAcc], HAcc); +split_locks([{Name, {pkg,PkgName,Vsn,Hash}, Lvl} | Locks], LAcc, HAcc) -> + split_locks(Locks, [{Name,{pkg,PkgName,Vsn},Lvl}|LAcc], [{Name, Hash}|HAcc]); +split_locks([Lock|Locks], LAcc, HAcc) -> + split_locks(Locks, [Lock|LAcc], HAcc). consult_file(File) -> Terms = consult_file_(File), -- cgit v1.1 From 589eaf13e1de55695cea4f34719c22c4b6467734 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 9 Jun 2016 21:30:42 -0400 Subject: Hashes in lockfile are diff friendly This reworks the version and hash printing in the lockfile to minimize diff changes: - the version is on its own line so that the locks are mostly the same aside from the last line - the hashes are each printed on one line with the package name for simpler diffing too. --- src/rebar_config.erl | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/rebar_config.erl') diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 031df8b..828c45d 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -82,10 +82,29 @@ write_lock_file(LockFile, Locks) -> file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])); _ -> file:write_file(LockFile, - io_lib:format("{~p,~p}.~n~p.~n", - [?CONFIG_VERSION, NewLocks, Attrs])) + io_lib:format("{~p,~n~p}.~n[~n~s~n].~n", + [?CONFIG_VERSION, NewLocks, + format_attrs(Attrs)])) end. +%% Attributes have a special formatting to ensure there's only one per +%% line in terms of pkg_hash, so we disturb source diffing as little +%% as possible. +format_attrs([]) -> []; +format_attrs([{pkg_hash, Vals}|T]) -> + [io_lib:format("{pkg_hash,[~n",[]), format_hashes(Vals), "]}", + maybe_comma(T) | format_attrs(T)]; +format_attrs([H|T]) -> + [io_lib:format("~p~s", [H, maybe_comma(T)]) | format_attrs(T)]. + +format_hashes([]) -> []; +format_hashes([{Pkg,Hash}|T]) -> + [" {", io_lib:format("~p",[Pkg]), ", ", io_lib:format("~p", [Hash]), "}", + maybe_comma(T) | format_hashes(T)]. + +maybe_comma([]) -> ""; +maybe_comma([_|_]) -> io_lib:format(",~n", []). + read_attrs(_Vsn, Locks, Attrs) -> %% Beta copy does not know how to expand attributes, but %% is ready to support it. -- cgit v1.1 From 71df9bf1411c04e2f7dae7e9f0352180664b9365 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 10 Jun 2016 08:43:13 -0400 Subject: Only display old version warning once This uses the env variable as a global store for variables. It's not the cleanest thing, but it sounded nicer than pdicts. --- src/rebar_config.erl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/rebar_config.erl') diff --git a/src/rebar_config.erl b/src/rebar_config.erl index 828c45d..9e13d46 100644 --- a/src/rebar_config.erl +++ b/src/rebar_config.erl @@ -58,6 +58,9 @@ consult_lock_file(File) -> [Locks] when is_list(Locks) -> % beta lock file read_attrs(beta, Locks, []); [{Vsn, Locks}|Attrs] when is_list(Locks) -> % versioned lock file + %% Because this is the first version of rebar3 to introduce a lock + %% file, all versionned lock files with a different versions have + %% to be newer. case Vsn of ?CONFIG_VERSION -> ok; @@ -65,14 +68,24 @@ consult_lock_file(File) -> %% Make sure the warning below is to be shown whenever a version %% newer than the current one is being used, as we can't parse %% all the contents of the lock file properly. - ?WARN("Rebar3 detected a lock file from a newer version. " - "It will be loaded in compatibility mode, but important " - "information may be missing or lost. It is recommended to " - "upgrade Rebar3.", []) + warn_vsn_once() end, read_attrs(Vsn, Locks, Attrs) end. +warn_vsn_once() -> + Warn = application:get_env(rebar, warn_config_vsn) =/= {ok, false}, + application:set_env(rebar, warn_config_vsn, false), + case Warn of + false -> ok; + true -> + ?WARN("Rebar3 detected a lock file from a newer version. " + "It will be loaded in compatibility mode, but important " + "information may be missing or lost. It is recommended to " + "upgrade Rebar3.", []) + end. + + write_lock_file(LockFile, Locks) -> {NewLocks, Attrs} = write_attrs(Locks), %% Write locks in the beta format, at least until it's been long -- cgit v1.1