First resolver

This commit is contained in:
Alejandro R. Mosteo
2018-01-30 01:31:07 +01:00
parent 8d30da8959
commit 87118c979b
12 changed files with 361 additions and 47 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ project Alire is
end Compiler;
package Binder is
for Switches ("ada") use ("-Es", "-shared");
for Switches ("ada") use ("-Es");
end Binder;
package Ide is
Vendored
+1 -1
+21
View File
@@ -0,0 +1,21 @@
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Containers.Indefinite_Ordered_Sets;
with Ada.Containers.Indefinite_Vectors;
with Alire.Releases;
package Alire.Containers with Preelaborate is
package Release_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Releases.Release,
Releases."<",
Releases."=");
subtype Release_Set is Release_Sets.Set;
package Milestone_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Milestone);
subtype Milestone_Set is Milestone_Sets.Set;
package Project_Version_Maps is new Ada.Containers.Indefinite_Ordered_Maps
(Project_Name, Semantic_Versioning.Version, "<", Semantic_Versioning."<");
subtype Version_Map is Project_Version_Maps.Map;
end Alire.Containers;
+28
View File
@@ -0,0 +1,28 @@
with Ada.Containers.Indefinite_Vectors;
package Alire.Depends with Preelaborate is
package Dependency_Vectors is new Ada.Containers.Indefinite_Vectors
(Positive, Dependency);
subtype Dependencies is Dependency_Vectors.Vector;
function Nothing return Dependencies is (Dependency_Vectors.Empty_Vector);
function New_Dependency (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies;
function Depends_On (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies renames New_Dependency;
function "and" (Dep1, Dep2 : Dependencies) return Dependencies;
private
use all type Dependencies;
function New_Dependency (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies
is (To_Vector ((Name'Length, Name, To_Holder (Versions)), 1));
function "and" (Dep1, Dep2 : Dependencies) return Dependencies is (Dep1 & Dep2);
end Alire.Depends;
+105
View File
@@ -0,0 +1,105 @@
package body Alire.Index.Query is
------------
-- 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 (Solution : Containers.Version_Map) is
use Containers.Project_Version_Maps;
begin
for I in Solution.Iterate loop
Log (" " & Key (I) & "=" & Image (Element (I)));
end loop;
end Print_Solution;
-------------
-- Resolve --
-------------
function Fail return Containers.Version_Map is (Containers.Project_Version_Maps.Empty_Map);
function Resolve (Unresolved : Dependencies;
Frozen : Containers.Version_Map) return Containers.Version_Map
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 Dependency := Unresolved.First_Element;
Remain : Dependencies := Unresolved;
function Go_Deeper (Unresolved : Dependencies;
Frozen : Containers.Version_Map) return Containers.Version_Map
is
begin
if Unresolved.Is_Empty then
Log ("Dependency solution found.");
Print_Solution (Frozen);
return Frozen;
else
return Resolve (Unresolved, Frozen);
end if;
end Go_Deeper;
begin
Remain.Delete_First;
if Frozen.Contains (Dep.Project) then
if Satisfies (Frozen.Element (Dep.Project), 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 Satisfies (R.Version, Dep.Versions) then
declare
New_Frozen : Containers.Version_Map := Frozen;
New_Remain : Dependencies := Remain;
Solution : Containers.Version_Map;
begin
New_Frozen.Insert (R.Project, R.Version);
New_Remain.Append (R.Depends);
Solution := Go_Deeper (New_Remain, New_Frozen);
if not Solution.Is_Empty then
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 : Dependencies) return Containers.Version_Map is
begin
return Resolve (Deps, Containers.Project_Version_Maps.Empty_Map);
end Resolve;
end Alire.Index.Query;
+11
View File
@@ -0,0 +1,11 @@
with Alire.Containers;
package Alire.Index.Query with Preelaborate is
function Exists (Project : Project_Name) return Boolean;
function Resolve (Deps : Dependencies) return Containers.Version_Map;
procedure Print_Solution (Solution : Containers.Version_Map);
end Alire.Index.Query;
+20 -2
View File
@@ -1,13 +1,31 @@
package body Alire.Index is
--------------
-- Register --
--------------
function Register (Project : Project_Name;
Version : Semantic_Versioning.Version;
Hosting : Repositories.Repository'Class;
Id : Repositories.Release_Id;
Depends_On : Dependencies := Nothing;
License : Licenses := Unknown) return Release is
License : Licenses := Unknown) return Release
is
pragma Unreferenced (License);
begin
return (null record);
Log ("Registering " & Project & ": " & Semantic_Versioning.Image (Version));
-- Milestones.Include (New_Milestone (Project, Version));
return Rel : constant Alire.Releases.Release :=
Alire.Releases.New_Release (Project,
Version,
Hosting,
Id,
Depends_On)
do
Releases.Insert (Rel);
end return;
end Register;
end Alire.Index;
+44 -22
View File
@@ -1,38 +1,47 @@
with Alire.Containers;
with Alire.Depends;
with Alire.Releases;
with Alire.Repositories.Git;
with Semantic_Versioning;
package Alire.Index with Preelaborate is
-- Milestones : Containers.Milestone_Set;
-- FIXME: Milestones seem entirely unused, wipe all cruft out
Releases : Containers.Release_Set;
subtype Dependencies is Depends.Dependencies;
subtype Release is Alire.Releases.Release;
function V (Semantic_Version : String) return Semantic_Versioning.Version
renames Semantic_Versioning.New_Version;
type Release (<>) is private;
function Register (Project : Project_Name;
Version : Semantic_Versioning.Version;
Hosting : Repositories.Repository'Class;
Id : Repositories.Release_Id;
Depends_On : Dependencies := Nothing;
Depends_On : Dependencies := Depends.Nothing;
License : Licenses := Unknown) return Release;
function Register_Git (Project : Project_Name;
Version : Semantic_Versioning.Version;
Hosting : URL;
Commit : Repositories.Git.Commit_ID;
Depends_On : Dependencies := Nothing;
License : Licenses := Unknown) return Release;
Depends_On : Dependencies := Depends.Nothing;
License : Licenses := Unknown) return Release;
-- Shortcuts to give dependencies:
function At_Least_Within_Major (R : Release) return Dependencies;
function At_Least (V : Release) return Dependencies;
function At_Most (V : Release) return Dependencies;
function Less_Than (V : Release) return Dependencies;
function More_Than (V : Release) return Dependencies;
function Exactly (V : Release) return Dependencies;
function Except (V : Release) return Dependencies;
function At_Least (R : Release) return Dependencies;
function At_Most (R : Release) return Dependencies;
function Less_Than (R : Release) return Dependencies;
function More_Than (R : Release) return Dependencies;
function Exactly (R : Release) return Dependencies;
function Except (R : Release) return Dependencies;
subtype Version is Semantic_Versioning.Version;
subtype Version_Set is Semantic_Versioning.Version_Set;
@@ -44,17 +53,15 @@ package Alire.Index with Preelaborate is
function Less_Than (V : Version) return Version_Set renames Semantic_Versioning.Less_Than;
function More_Than (V : Version) return Version_Set renames Semantic_Versioning.More_Than;
function Exactly (V : Version) return Version_Set renames Semantic_Versioning.Exactly;
function Except (V : Version) return Version_Set renames Semantic_Versioning.Except;
function Except (V : Version) return Version_Set renames Semantic_Versioning.Except;
private
type Release is null record;
function Register_Git (Project : Project_Name;
Version : Semantic_Versioning.Version;
Hosting : URL;
Commit : Repositories.Git.Commit_ID;
Depends_On : Dependencies := Nothing;
Depends_On : Dependencies := Depends.Nothing;
License : Licenses := Unknown) return Release
is (Register (Project,
Version,
@@ -63,14 +70,29 @@ private
Depends_On,
License));
function At_Least_Within_Major (R : Release) return Dependencies is (null record);
use Depends;
use Semantic_Versioning;
function At_Least (V : Release) return Dependencies is (null record);
function At_Most (V : Release) return Dependencies is (null record);
function Less_Than (V : Release) return Dependencies is (null record);
function More_Than (V : Release) return Dependencies is (null record);
function Exactly (V : Release) return Dependencies is (null record);
function Except (V : Release) return Dependencies is (null record);
function At_Least_Within_Major (R : Release) return Dependencies is
(New_Dependency (R.Project, At_Least_Within_Major (R.Version)));
function At_Least (R : Release) return Dependencies is
(New_Dependency (R.Project, At_Least (R.Version)));
function At_Most (R : Release) return Dependencies is
(New_Dependency (R.Project, At_Most (R.Version)));
function Less_Than (R : Release) return Dependencies is
(New_Dependency (R.Project, Less_Than (R.Version)));
function More_Than (R : Release) return Dependencies is
(New_Dependency (R.Project, More_Than (R.Version)));
function Exactly (R : Release) return Dependencies is
(New_Dependency (R.Project, Exactly (R.Version)));
function Except (R : Release) return Dependencies is
(New_Dependency (R.Project, Except (R.Version)));
end Alire.Index;
+55
View File
@@ -0,0 +1,55 @@
with Alire.Depends;
with Alire.Repositories;
package Alire.Releases with Preelaborate is
subtype Dependencies is Depends.Dependencies;
type Release (<>) is tagged private;
function New_Release (Project : Project_Name;
Version : Semantic_Versioning.Version;
Repository : Repositories.Repository'Class;
Id : Repositories.Release_Id;
Depends_On : Dependencies) return Release;
function "<" (L, R : Release) return Boolean;
function Project (R : Release) return Project_Name;
function Version (R : Release) return Semantic_Versioning.Version;
function Depends (R : Release) return Dependencies;
private
type Release (Name_Len, Id_Len : Positive) is tagged record
Project : Project_Name (1 .. Name_Len);
Version : Semantic_Versioning.Version;
Repository : Repositories.Repository_H;
Id : Repositories.Release_Id (1 .. Id_Len);
Depends_On : Dependencies;
end record;
function New_Release (Project : Project_Name;
Version : Semantic_Versioning.Version;
Repository : Repositories.Repository'Class;
Id : Repositories.Release_Id;
Depends_On : Dependencies) return Release is
(Project'Length, Id'Length,
Project,
Version,
Repositories.To_Holder (Repository),
Id,
Depends_On);
function "<" (L, R : Release) return Boolean is
(L.Project < R.Project or else
(L.Project = R.Project and then L.Version < R.Version) or else
(L.Project = R.Project and then
L.Version = R.Version and then
L.Repository.Element.Image < R.Repository.Element.Image));
function Project (R : Release) return Project_Name is (R.Project);
function Version (R : Release) return Semantic_Versioning.Version is (R.Version);
function Depends (R : Release) return Dependencies is (R.Depends_On);
end Alire.Releases;
+5 -1
View File
@@ -2,7 +2,9 @@ package Alire.Repositories.Git with Preelaborate is
type Repository (<>) is new Repositories.Repository with private;
function New_Repository(URL : String) return Repository;
function New_Repository (URL : String) return Repository;
function Image (Repo : Repository) return String;
subtype Commit_ID is String (1 .. 40);
@@ -15,5 +17,7 @@ private
function New_Repository (URL : String) return Repository
is (URL_Length => Url'Length,
URL => URL);
function Image (Repo : Repository) return String is (Repo.URL);
end Alire.Repositories.Git;
+12
View File
@@ -1,7 +1,19 @@
with Ada.Containers.Indefinite_Holders;
package Alire.Repositories with Preelaborate is
type Repository is interface;
function Image (Repo : Repository) return String is abstract;
function "<" (L, R : Repository'Class) return Boolean is (L.Image < R.Image);
function "=" (L, R : Repository'Class) return Boolean is (L.Image = R.Image);
type Release_Id is new String;
package Repository_Holders is new Ada.Containers.Indefinite_Holders (Repository'Class);
type Repository_H is new Repository_Holders.Holder with null record;
end Alire.Repositories;
+58 -20
View File
@@ -1,3 +1,7 @@
private with Ada.Containers.Indefinite_Holders;
private with GNAT.IO; -- For debugging purposes, FIXME getting rid of it and using some proper Trace lib
with Semantic_Versioning;
package Alire with Preelaborate is
@@ -6,34 +10,68 @@ package Alire with Preelaborate is
type Project_Name is new String;
subtype Project_Name is String;
type Licenses is (Unknown);
type Dependencies (<>) is private;
type Dependency (<>) is tagged private;
function Project (Dep : Dependency) return Project_Name;
Nothing : constant Dependencies;
function New_Dependency (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies;
function Depends_On (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies renames New_Dependency;
function "and" (Dep1, Dep2 : Dependencies) return Dependencies;
private
type Dependencies is null record;
Nothing : constant Dependencies := (null record);
function Versions (Dep : Dependency) return Semantic_Versioning.Version_Set;
function New_Dependency (Name : Project_Name;
Versions : Semantic_Versioning.Version_Set) return Dependencies
is (null record);
type Milestone (<>) is tagged private;
function "and" (Dep1, Dep2 : Dependencies) return Dependencies is (null record);
function "<" (L, R : Milestone) return Boolean;
function New_Milestone (Name : Project_Name;
Version : Semantic_Versioning.Version) return Milestone;
function Project (M : Milestone) return Project_Name;
function Version (M : Milestone) return Semantic_Versioning.Version;
private
use all type Semantic_Versioning.Version;
package Version_Holders is new Ada.Containers.Indefinite_Holders
(Semantic_Versioning.Version_Set, Semantic_Versioning."=");
type Version_Set_Holder is new Version_Holders.Holder with null record;
type Dependency (Name_Len : Positive) is tagged record
Project : Project_Name (1 .. Name_Len);
Versions_H : Version_Set_holder;
end record;
function Project (Dep : Dependency) return Project_Name is (Dep.Project);
function Versions (Dep : Dependency) return Semantic_Versioning.Version_Set is
(Dep.Versions_H.Element);
type Milestone (Name_Len : Positive) is tagged record
Name : Project_Name (1 .. Name_Len);
Version : Semantic_Versioning.Version;
end record;
function "<" (L, R : Milestone) return Boolean is
(L.Name < R.Name or else (L.Name = R.Name and then L.Version < R.Version));
function New_Milestone (Name : Project_Name;
Version : Semantic_Versioning.Version) return Milestone is
(Name'Length, Name, Version);
function Project (M : Milestone) return Project_Name is (M.Name);
function Version (M : Milestone) return Semantic_Versioning.Version is (M.Version);
procedure Log (S : String) renames GNAT.IO.Put_Line;
end Alire;