瀏覽代碼

Actually fix tuple merging.

Full rewrite, code should be understandable now.
pull/965/head
Fred Hebert 9 年之前
父節點
當前提交
769e14c542
共有 2 個檔案被更改,包括 60 行新增30 行删除
  1. +53
    -30
      src/rebar_utils.erl
  2. +7
    -0
      test/rebar_utils_SUITE.erl

+ 53
- 30
src/rebar_utils.erl 查看文件

@ -285,7 +285,7 @@ tup_umerge(NewList, OldList) ->
tup_umerge_([], Olds) -> tup_umerge_([], Olds) ->
Olds; Olds;
tup_umerge_([New|News], Olds) -> tup_umerge_([New|News], Olds) ->
tup_umerge_dedup_(umerge(News, Olds, [], New), []).
tup_umerge_dedup_(umerge(new, News, Olds, [], New), []).
%% removes 100% identical duplicate elements so that %% removes 100% identical duplicate elements so that
%% `[a,{a,b},a,{a,c},a]' returns `[a,{a,b},{a,c}]'. %% `[a,{a,b},a,{a,c},a]' returns `[a,{a,b},{a,c}]'.
@ -312,35 +312,58 @@ tup_find(Elem, [Elem1 | Elems]) when is_tuple(Elem1) ->
tup_find(Elem, [_Elem | Elems]) -> tup_find(Elem, [_Elem | Elems]) ->
tup_find(Elem, Elems). tup_find(Elem, Elems).
%% This is equivalent to umerge2_2 in the stdlib, except we use the expanded
%% value/key only to compare
umerge(News, [Old|Olds], Merged, Cmp) when element(1, Cmp) == element(1, Old);
element(1, Cmp) == Old andalso not is_tuple(Old);
Cmp == element(1, Old) andalso not is_tuple(Cmp);
Cmp =< Old andalso not is_tuple(Cmp) andalso not is_tuple(Old) ->
umerge(News, Olds, [Cmp | Merged], Cmp, Old);
umerge(News, [Old|Olds], Merged, Cmp) ->
umerge(News, Olds, [Old | Merged], Cmp);
umerge(News, [], Merged, Cmp) ->
lists:reverse(News, [Cmp | Merged]).
%% Similar to stdlib's umerge2_1 in the stdlib, except that when the expanded
%% value/keys compare equal, we check if the element is a full dupe to clear it
%% (like the stdlib function does) or otherwise keep the duplicate around in
%% an order that prioritizes 'New' elements.
umerge([New|News], Olds, Merged, CmpMerged, Cmp) when CmpMerged == Cmp ->
umerge(News, Olds, Merged, New);
umerge([New|News], Olds, Merged, _CmpMerged, Cmp) when element(1,New) == element(1, Cmp);
element(1,New) == Cmp andalso not is_tuple(Cmp);
New == element(1, Cmp) andalso not is_tuple(New);
New =< Cmp andalso not is_tuple(New) andalso not is_tuple(Cmp) ->
umerge(News, Olds, [New | Merged], New, Cmp);
umerge([New|News], Olds, Merged, _CmpMerged, Cmp) -> % >
umerge(News, Olds, [Cmp | Merged], New);
umerge([], Olds, Merged, CmpMerged, Cmp) when CmpMerged == Cmp ->
lists:reverse(Olds, Merged);
umerge([], Olds, Merged, _CmpMerged, Cmp) ->
lists:reverse(Olds, [Cmp | Merged]).
-spec umerge(new|old, News, Olds, Acc, Current) -> Merged when
News :: [term()],
Olds :: [term()],
Acc :: [term()],
Current :: term(),
Merged :: [term()].
umerge(_, [], [], Acc, Current) ->
[Current | Acc];
umerge(new, News, [], Acc, Current) ->
%% only news left
lists:reverse(News, [Current|Acc]);
umerge(old, [], Olds, Acc, Current) ->
%% only olds left
lists:reverse(Olds, [Current|Acc]);
umerge(new, News, [Old|Olds], Acc, Current) ->
{Dir, Merged, NewCurrent} = compare({new, Current}, {old, Old}),
umerge(Dir, News, Olds, [Merged|Acc], NewCurrent);
umerge(old, [New|News], Olds, Acc, Current) ->
{Dir, Merged, NewCurrent} = compare({new, New}, {old, Current}),
umerge(Dir, News, Olds, [Merged|Acc], NewCurrent).
-spec compare({Priority, term()}, {Secondary, term()}) ->
{NextPriority, Merged, Larger} when
Priority :: new | old,
Secondary :: new | old,
NextPriority :: new | old,
Merged :: term(),
Larger :: term().
compare({Priority, A}, {Secondary, B}) when is_tuple(A), is_tuple(B) ->
KA = element(1,A),
KB = element(1,B),
if KA == KB -> {Secondary, A, B};
KA < KB -> {Secondary, A, B};
KA > KB -> {Priority, B, A}
end;
compare({Priority, A}, {Secondary, B}) when not is_tuple(A), not is_tuple(B) ->
if A == B -> {Secondary, A, B};
A < B -> {Secondary, A, B};
A > B -> {Priority, B, A}
end;
compare({Priority, A}, {Secondary, B}) when is_tuple(A), not is_tuple(B) ->
KA = element(1,A),
if KA == B -> {Secondary, A, B};
KA < B -> {Secondary, A, B};
KA > B -> {Priority, B, A}
end;
compare({Priority, A}, {Secondary, B}) when not is_tuple(A), is_tuple(B) ->
KB = element(1,B),
if A == KB -> {Secondary, A, B};
A < KB -> {Secondary, A, B};
A > KB -> {Priority, B, A}
end.
%% Implements wc -l functionality used to determine patchcount from git output %% Implements wc -l functionality used to determine patchcount from git output
line_count(PatchLines) -> line_count(PatchLines) ->

+ 7
- 0
test/rebar_utils_SUITE.erl 查看文件

@ -258,6 +258,13 @@ tup_merge(_Config) ->
rebar_utils:tup_sort([{a,a},{a,b},{a,a,a},{a,b,b},a,{b,a},{b,a,a},b,{z,a},{z,a,a},z]) rebar_utils:tup_sort([{a,a},{a,b},{a,a,a},{a,b,b},a,{b,a},{b,a,a},b,{z,a},{z,a,a},z])
) )
), ),
?assertEqual(
[{l, a}, {r, a, b}, {s, a}, {s, b}],
rebar_utils:tup_umerge(
rebar_utils:tup_sort([{r, a, b}, {s, a}, {l, a}]),
rebar_utils:tup_sort([{s, b}])
)
),
?assertEqual( ?assertEqual(
[{a,b,b},{a,b},a,{a,a},{a,a,a},{b,b},{b,b,b},b,{b,a,a},{b,a},{z,b},{z,b,b},z,{z,a},{z,a,a}], [{a,b,b},{a,b},a,{a,a},{a,a,a},{b,b},{b,b,b},b,{b,a,a},{b,a},{z,b},{z,b,b},z,{z,a},{z,a,a}],
rebar_utils:tup_umerge( rebar_utils:tup_umerge(

Loading…
取消
儲存