1111 ,resolve_version /6 ]).
1212
1313-ifdef (TEST ).
14- -export ([new_package_table /0 , find_highest_matching_ /5 , cmp_ / 4 , cmpl_ / 4 , valid_vsn /1 ]).
14+ -export ([new_package_table /0 , find_highest_matching_ /5 , valid_vsn /1 ]).
1515-endif .
1616
1717-export_type ([package / 0 ]).
@@ -55,31 +55,37 @@ get_all_names(State) ->
5555 _ = '_' },
5656 [], ['$1' ]}])).
5757
58- -spec get_package_versions (unicode :unicode_binary (), ec_semver :semver (),
58+ -spec get_package_versions (unicode :unicode_binary (), verl :semver (),
5959 unicode :unicode_binary (),
6060 ets :tid (), rebar_state :t ()) -> [vsn ()].
61- get_package_versions (Dep , {_ , AlphaInfo }, Repo , Table , State ) ->
62- ? MODULE :verify_table (State ),
63- AllowPreRelease = rebar_state :get (State , deps_allow_prerelease , false )
64- orelse AlphaInfo =/= {[],[]},
65- ets :select (Table , [{# package {key = {Dep , {'$1' , '$2' }, Repo },
66- _ = '_' },
67- [{'==' , '$2' , {{[],[]}}} || not AllowPreRelease ], [{{'$1' , '$2' }}]}]).
61+ get_package_versions (Dep , DepVsn , Repo , Table , State ) ->
62+ _AllowPreRelease = rebar_state :get (State , deps_allow_prerelease , false ),
63+ case rebar_verl :parse_requirement (DepVsn ) of
64+ {error , _ } ->
65+ none ;
66+ {ok , #{matchspec := [{Head , [Match ], _ }]}} ->
67+ ? MODULE :verify_table (State ),
68+ Vsns = ets :select (Table , [{# package {key = {Dep , Head , Repo }, _ = '_' },
69+ [Match ], [{Head }]}]),
70+ handle_vsns (Vsns )
71+ end .
6872
6973-spec get_package (unicode :unicode_binary (), unicode :unicode_binary (),
7074 binary () | undefined | '_' ,
7175 [unicode :unicode_binary ()] | ['_' ], ets :tab (), rebar_state :t ())
7276 -> {ok , # package {}} | not_found .
7377get_package (Dep , Vsn , undefined , Repos , Table , State ) ->
7478 get_package (Dep , Vsn , '_' , Repos , Table , State );
79+ get_package (Dep , Vsn , Hash , Repos , Table , State ) when is_binary (Vsn ) ->
80+ get_package (Dep , r3_verl :parse (Vsn ), Hash , Repos , Table , State );
7581get_package (Dep , Vsn , Hash , Repos , Table , State ) ->
7682 ? MODULE :verify_table (State ),
77- MatchingPackages = ets :select (Table , [{# package {key = {Dep , ec_semver : parse ( Vsn ) , Repo },
83+ MatchingPackages = ets :select (Table , [{# package {key = {Dep , Vsn , Repo },
7884 _ = '_' }, [], ['$_' ]} || Repo <- Repos ]),
7985 PackagesWithProperHash = lists :filter (
8086 fun (# package {key = {_Dep , _Vsn , Repo }, outer_checksum = PkgChecksum }) ->
8187 if (PkgChecksum =/= Hash ) andalso (Hash =/= '_' ) ->
82- ? WARN (" Checksum mismatch for package ~ts -~ts from repo ~ts " , [Dep , Vsn , Repo ]),
88+ ? WARN (" Checksum mismatch for package ~ts -~ts from repo ~ts " , [Dep , rebar_verl : format_version ( Vsn ) , Repo ]),
8389 false ;
8490 true ->
8591 true
@@ -174,7 +180,8 @@ package_dir(Repo, State) ->
174180% % `~> 2.1.3-dev` | `>= 2.1.3-dev and < 2.2.0`
175181% % `~> 2.0` | `>= 2.0.0 and < 3.0.0`
176182% % `~> 2.1` | `>= 2.1.0 and < 3.0.0`
177- find_highest_matching (Dep , Constraint , Repo , Table , State ) ->
183+ find_highest_matching (Dep , Version , Repo , Table , State ) ->
184+ Constraint = verl :add_highest_matching_prefix (Version ),
178185 try find_highest_matching_ (Dep , Constraint , Repo , Table , State ) of
179186 none ->
180187 handle_missing_package (Dep , Repo , State ,
@@ -192,39 +199,26 @@ find_highest_matching(Dep, Constraint, Repo, Table, State) ->
192199 end .
193200
194201find_highest_matching_ (Dep , Constraint , #{name := Repo }, Table , State ) ->
195- try get_package_versions (Dep , Constraint , Repo , Table , State ) of
196- [Vsn ] ->
197- handle_single_vsn (Vsn , Constraint );
198- Vsns ->
199- case handle_vsns (Constraint , Vsns ) of
200- none ->
201- none ;
202- FoundVsn ->
203- {ok , FoundVsn }
204- end
202+ try
203+ get_package_versions (Dep , Constraint , Repo , Table , State )
205204 catch
206205 error :badarg ->
207206 none
208207 end .
209208
210- handle_vsns (Constraint , Vsns ) ->
211- lists :foldl (fun (Version , Highest ) ->
212- case ec_semver :pes (Version , Constraint ) andalso
213- (Highest =:= none orelse ec_semver :gt (Version , Highest )) of
214- true ->
215- Version ;
216- false ->
217- Highest
218- end
219- end , none , Vsns ).
220-
221- handle_single_vsn (Vsn , Constraint ) ->
222- case ec_semver :pes (Vsn , Constraint ) of
223- true ->
224- {ok , Vsn };
225- false ->
226- none
227- end .
209+ handle_vsns ([]) -> none ;
210+ handle_vsns (Vsns ) ->
211+ Vsn =
212+ lists :foldl (
213+ fun (Version , Highest ) ->
214+ case (Highest =:= none orelse r3_verl :compare (Version , Highest ) =:= gt ) of
215+ true ->
216+ Version ;
217+ false ->
218+ Highest
219+ end
220+ end , none , Vsns ),
221+ {ok , Vsn }.
228222
229223verify_table (State ) ->
230224 ets :info (? PACKAGE_TABLE , named_table ) =:= true orelse load_and_verify_version (State ).
@@ -282,8 +276,12 @@ unverified_repo_message() ->
282276 " You can disable this check by setting REBAR_NO_VERIFY_REPO_ORIGIN=1" .
283277
284278insert_releases (Name , Releases , Repo , Table ) ->
279+ Parse = fun (V ) ->
280+ {ok , Res } = verl :parse (V ),
281+ Res
282+ end ,
285283 [true = ets :insert (Table ,
286- # package {key = {Name , ec_semver : parse (Version ), Repo },
284+ # package {key = {Name , Parse (Version ), Repo },
287285 inner_checksum = parse_checksum (InnerChecksum ),
288286 outer_checksum = parse_checksum (OuterChecksum ),
289287 retired = maps :get (retired , Release , false ),
@@ -313,7 +311,7 @@ resolve_version(Dep, DepVsn, _OldHash, Hash, HexRegistry, State) when is_binary(
313311 {ok , Package , RepoConfig };
314312 _ ->
315313 Fun = fun (Repo ) ->
316- case resolve_version_ (Dep , DepVsn , Repo , HexRegistry , State ) of
314+ case get_package_versions (Dep , DepVsn , Repo , HexRegistry , State ) of
317315 none ->
318316 not_found ;
319317 {ok , Vsn } ->
@@ -324,7 +322,7 @@ resolve_version(Dep, DepVsn, _OldHash, Hash, HexRegistry, State) when is_binary(
324322 end ;
325323resolve_version (Dep , undefined , _OldHash , Hash , HexRegistry , State ) ->
326324 Fun = fun (Repo ) ->
327- case highest_matching (Dep , { 0 ,{[],[]}} , Repo , HexRegistry , State ) of
325+ case get_latest_version (Dep , Repo , HexRegistry , State ) of
328326 none ->
329327 not_found ;
330328 {ok , Vsn } ->
@@ -338,7 +336,7 @@ resolve_version(Dep, DepVsn, _OldHash, Hash, HexRegistry, State) ->
338336 {error , {invalid_vsn , DepVsn }};
339337 _ ->
340338 Fun = fun (Repo ) ->
341- case resolve_version_ (Dep , DepVsn , Repo , HexRegistry , State ) of
339+ case get_package_versions (Dep , DepVsn , Repo , HexRegistry , State ) of
342340 none ->
343341 not_found ;
344342 {ok , Vsn } ->
@@ -373,92 +371,11 @@ handle_missing_no_exception(Fun, Dep, State) ->
373371 Result
374372 end .
375373
376- resolve_version_ (Dep , DepVsn , Repo , HexRegistry , State ) ->
377- case DepVsn of
378- <<" ~> " , Vsn /binary >> ->
379- highest_matching (Dep , rm_ws (Vsn ), Repo , HexRegistry , State );
380- <<" >=" , Vsn /binary >> ->
381- cmp (Dep , rm_ws (Vsn ), Repo , HexRegistry , State , fun ec_semver :gte /2 );
382- <<" >" , Vsn /binary >> ->
383- cmp (Dep , rm_ws (Vsn ), Repo , HexRegistry , State , fun ec_semver :gt /2 );
384- <<" <=" , Vsn /binary >> ->
385- cmpl (Dep , rm_ws (Vsn ), Repo , HexRegistry , State , fun ec_semver :lte /2 );
386- <<" <" , Vsn /binary >> ->
387- cmpl (Dep , rm_ws (Vsn ), Repo , HexRegistry , State , fun ec_semver :lt /2 );
388- <<" ==" , Vsn /binary >> ->
389- {ok , Vsn };
390- Vsn ->
391- {ok , Vsn }
392- end .
393-
394- rm_ws (<<" " , R /binary >>) ->
395- ec_semver :parse (rm_ws (R ));
396- rm_ws (R ) ->
397- ec_semver :parse (R ).
398-
399374valid_vsn (Vsn ) ->
400- % % Regepx from https://github.com/sindresorhus/semver-regex/blob/master/index.js
401- SemVerRegExp = " v?(0|[1-9][0-9]*)\\ .(0|[1-9][0-9]*)(\\ .(0|[1-9][0-9]*))?"
402- " (-[0-9a-z-]+(\\ .[0-9a-z-]+)*)?(\\ +[0-9a-z-]+(\\ .[0-9a-z-]+)*)?" ,
403- SupportedVersions = " ^(>=?|<=?|~> |==)?\\ s*" ++ SemVerRegExp ++ " $" ,
404- re :run (Vsn , SupportedVersions , [unicode ]) =/= nomatch .
405-
406- highest_matching (Dep , Vsn , Repo , HexRegistry , State ) ->
407- find_highest_matching_ (Dep , Vsn , #{name => Repo }, HexRegistry , State ).
408-
409- cmp (Dep , Vsn , Repo , HexRegistry , State , CmpFun ) ->
410- case get_package_versions (Dep , Vsn , Repo , HexRegistry , State ) of
411- [] ->
412- none ;
413- Vsns ->
414- cmp_ (undefined , Vsn , Vsns , CmpFun )
415- end .
416-
417- cmp_ (undefined , MinVsn , [], _CmpFun ) ->
418- {ok , MinVsn };
419- cmp_ (HighestDepVsn , _MinVsn , [], _CmpFun ) ->
420- {ok , HighestDepVsn };
421-
422- cmp_ (BestMatch , MinVsn , [Vsn | R ], CmpFun ) ->
423- case CmpFun (Vsn , MinVsn ) of
424- true ->
425- cmp_ (Vsn , Vsn , R , CmpFun );
426- false ->
427- cmp_ (BestMatch , MinVsn , R , CmpFun )
428- end .
429-
430- % % We need to treat this differently since we want a version that is LOWER but
431- % % the highest possible one.
432- cmpl (Dep , Vsn , Repo , HexRegistry , State , CmpFun ) ->
433- case get_package_versions (Dep , Vsn , Repo , HexRegistry , State ) of
434- [] ->
435- none ;
436- Vsns ->
437- cmpl_ (undefined , Vsn , Vsns , CmpFun )
438- end .
439-
440- cmpl_ (undefined , MaxVsn , [], _CmpFun ) ->
441- {ok , MaxVsn };
442- cmpl_ (HighestDepVsn , _MaxVsn , [], _CmpFun ) ->
443- {ok , HighestDepVsn };
444-
445- cmpl_ (undefined , MaxVsn , [Vsn | R ], CmpFun ) ->
446- case CmpFun (Vsn , MaxVsn ) of
447- true ->
448- cmpl_ (Vsn , MaxVsn , R , CmpFun );
449- false ->
450- cmpl_ (undefined , MaxVsn , R , CmpFun )
451- end ;
375+ rebar_verl :valid_requirement (Vsn ).
452376
453- cmpl_ (BestMatch , MaxVsn , [Vsn | R ], CmpFun ) ->
454- case CmpFun (Vsn , MaxVsn ) of
455- true ->
456- case ec_semver :gte (Vsn , BestMatch ) of
457- true ->
458- cmpl_ (Vsn , MaxVsn , R , CmpFun );
459- false ->
460- cmpl_ (BestMatch , MaxVsn , R , CmpFun )
461- end ;
462- false ->
463- cmpl_ (BestMatch , MaxVsn , R , CmpFun )
464- end .
377+ get_latest_version (Dep , Repo , HexRegistry , State ) ->
378+ verify_table (State ),
379+ Vsns = ets :select (HexRegistry , [{# package {key = {'$1' , '$2' , '$3' }, _ = '_' },
380+ [{'==' , '$1' , Dep }, {'==' , '$3' , Repo }], ['$2' ]}]),
381+ handle_vsns (Vsns ).
0 commit comments