diff --git a/alire.gpr b/alire.gpr index 2c55676d..41c71667 100644 --- a/alire.gpr +++ b/alire.gpr @@ -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 diff --git a/deps/semver b/deps/semver index 3c50e076..4f9dd639 160000 --- a/deps/semver +++ b/deps/semver @@ -1 +1 @@ -Subproject commit 3c50e076d45e19aafc7c2484d2cfaee394d3b363 +Subproject commit 4f9dd63960cb4040e3aa561019d79e6f9d5f5818 diff --git a/src/alire-containers.ads b/src/alire-containers.ads new file mode 100644 index 00000000..a216b83c --- /dev/null +++ b/src/alire-containers.ads @@ -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; diff --git a/src/alire-depends.ads b/src/alire-depends.ads new file mode 100644 index 00000000..c0e799b0 --- /dev/null +++ b/src/alire-depends.ads @@ -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; diff --git a/src/alire-index-query.adb b/src/alire-index-query.adb new file mode 100644 index 00000000..c994eaa6 --- /dev/null +++ b/src/alire-index-query.adb @@ -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; diff --git a/src/alire-index-query.ads b/src/alire-index-query.ads new file mode 100644 index 00000000..0834c85c --- /dev/null +++ b/src/alire-index-query.ads @@ -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; diff --git a/src/alire-index.adb b/src/alire-index.adb index a520722d..514b4521 100644 --- a/src/alire-index.adb +++ b/src/alire-index.adb @@ -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; diff --git a/src/alire-index.ads b/src/alire-index.ads index 7862d7fe..67bbce26 100644 --- a/src/alire-index.ads +++ b/src/alire-index.ads @@ -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; diff --git a/src/alire-releases.ads b/src/alire-releases.ads new file mode 100644 index 00000000..ade68fa2 --- /dev/null +++ b/src/alire-releases.ads @@ -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; diff --git a/src/alire-repositories-git.ads b/src/alire-repositories-git.ads index f5cc2cd8..41a8a465 100644 --- a/src/alire-repositories-git.ads +++ b/src/alire-repositories-git.ads @@ -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; diff --git a/src/alire-repositories.ads b/src/alire-repositories.ads index 6aabf38f..6cac69c3 100644 --- a/src/alire-repositories.ads +++ b/src/alire-repositories.ads @@ -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; diff --git a/src/alire.ads b/src/alire.ads index 369b9edc..77b50783 100644 --- a/src/alire.ads +++ b/src/alire.ads @@ -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;