130 lines
3.7 KiB
Ada
130 lines
3.7 KiB
Ada
with Alire.Dependencies;
|
|
|
|
with Semantic_Versioning;
|
|
|
|
package body Alire.Query is
|
|
|
|
package Semver renames Semantic_Versioning;
|
|
|
|
------------
|
|
-- Exists --
|
|
------------
|
|
|
|
function Exists (Project : Project_Name) return Boolean is
|
|
begin
|
|
for R of Releases loop
|
|
if R.Project = Project then
|
|
return True;
|
|
end if;
|
|
end loop;
|
|
|
|
return False;
|
|
end Exists;
|
|
|
|
--------------------
|
|
-- Print_Solution --
|
|
--------------------
|
|
|
|
procedure Print_Solution (I : Instance) is
|
|
use Containers.Project_Release_Maps;
|
|
begin
|
|
for Rel of I loop
|
|
Log (" " & Rel.Milestone_Image, Detail);
|
|
end loop;
|
|
end Print_Solution;
|
|
|
|
----------
|
|
-- Fail --
|
|
----------
|
|
|
|
function Fail return Instance is (Containers.Project_Release_Maps.Empty_Map);
|
|
|
|
-------------
|
|
-- Resolve --
|
|
-------------
|
|
|
|
function Resolve (Unresolved : Index.Dependencies;
|
|
Frozen : Instance;
|
|
Success : out Boolean) return Instance
|
|
is
|
|
-- FIXME: since this is depth-first, Frozen can be passed in-out and updated on the spot,
|
|
-- thus saving copies. Probably the same applies to Unresolved.
|
|
Dep : constant Alire.Dependencies.Dependency := Unresolved.First_Element;
|
|
Remain : Index.Dependencies := Unresolved;
|
|
|
|
---------------
|
|
-- Go_Deeper --
|
|
---------------
|
|
|
|
function Go_Deeper (Unresolved : Index.Dependencies;
|
|
Frozen : Instance) return Instance
|
|
is
|
|
begin
|
|
if Unresolved.Is_Empty then
|
|
Log ("Dependencies resolved");
|
|
Print_Solution (Frozen);
|
|
return Frozen;
|
|
else
|
|
return Resolve (Unresolved, Frozen, Success);
|
|
end if;
|
|
end Go_Deeper;
|
|
|
|
begin
|
|
|
|
Remain.Delete_First;
|
|
|
|
if Frozen.Contains (Dep.Project) then
|
|
if Semver.Satisfies (Frozen.Element (Dep.Project).Version, Dep.Versions) then
|
|
-- Dependency already met, simply go down...
|
|
return Go_Deeper (Remain, Frozen);
|
|
else
|
|
-- Failure because an already frozen version is incompatible
|
|
return Fail;
|
|
end if;
|
|
else
|
|
-- Need to check all versions for the first one...
|
|
-- FIXME: complexity can be improved not visiting blindly all releases to match by project
|
|
for R of reverse Index.Releases loop
|
|
if Dep.Project = R.Project and then Semver.Satisfies (R.Version, Dep.Versions) then
|
|
declare
|
|
New_Frozen : Instance := Frozen;
|
|
New_Remain : Index.Dependencies := Remain;
|
|
|
|
Solution : Instance;
|
|
begin
|
|
New_Frozen.Insert (R.Project, R);
|
|
New_Remain.Append (R.Depends);
|
|
|
|
Solution := Go_Deeper (New_Remain, New_Frozen);
|
|
|
|
if not Solution.Is_Empty then
|
|
Success := True;
|
|
return Solution; -- Success!
|
|
end if;
|
|
end;
|
|
end if;
|
|
end loop;
|
|
|
|
-- We found no milestone compatible with the first unresolved dependency...
|
|
return Fail;
|
|
end if;
|
|
end Resolve;
|
|
|
|
-------------
|
|
-- Resolve --
|
|
-------------
|
|
|
|
function Resolve (Deps : Index.Dependencies;
|
|
Success : out Boolean) return Instance is
|
|
begin
|
|
Success := False;
|
|
|
|
return I : constant Instance := Resolve (Deps, Containers.Project_Release_Maps.Empty_Map, Success) do
|
|
if not Success then
|
|
Log ("Dependency resolution failed");
|
|
end if;
|
|
end return;
|
|
end Resolve;
|
|
|
|
end Alire.Query;
|