Files
alire-index-community/src/alire-query.adb
T
2018-02-16 19:58:27 +01:00

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;