From 270b861573991fa946a51ffac1f6519383cbd5d7 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Sat, 23 May 2020 21:07:13 +0200 Subject: [PATCH] Improve dependency graphs to display unresolved externals (#422) * Improve dependency graphs to consider externals * Enhance test to check dependency graph with external --- src/alire/alire-containers.ads | 5 +++ src/alire/alire-dependencies-graphs.adb | 48 +++++++++++++++++-------- src/alire/alire-dependencies-graphs.ads | 10 +++--- src/alire/alire-solutions.adb | 22 ++++++++++-- src/alire/alire-solutions.ads | 20 +++++++---- src/alr/alr-checkout.adb | 2 +- testsuite/tests/with/external/test.py | 4 ++- 7 files changed, 82 insertions(+), 29 deletions(-) diff --git a/src/alire/alire-containers.ads b/src/alire/alire-containers.ads index 72cacf83..e84e84cb 100644 --- a/src/alire/alire-containers.ads +++ b/src/alire/alire-containers.ads @@ -26,6 +26,8 @@ package Alire.Containers with Preelaborate is type Dependency_Map is new Dependency_Maps.Map with null record; + Empty_Dependency_Map : constant Dependency_Map; + procedure Merge (This : in out Dependency_Map; Dep : Dependencies.Dependency); -- If the dependency is already in map, create a combined dependency that @@ -95,6 +97,9 @@ package Alire.Containers with Preelaborate is private + Empty_Dependency_Map : constant Dependency_Map := + (Dependency_Maps.Empty_Map with null record); + Empty_Release_Map : constant Release_Map := (Crate_Release_Maps.Empty_Map with null record); diff --git a/src/alire/alire-dependencies-graphs.adb b/src/alire/alire-dependencies-graphs.adb index 58fe37a7..a6c7e1a0 100644 --- a/src/alire/alire-dependencies-graphs.adb +++ b/src/alire/alire-dependencies-graphs.adb @@ -25,7 +25,7 @@ package body Alire.Dependencies.Graphs is Result := Result.Including (Rel, Env); end loop; - Result := Result.Filtering_Unused (Sol.Releases); + Result := Result.Filtering_Unused (Sol.Required); end return; end From_Solution; @@ -56,14 +56,14 @@ package body Alire.Dependencies.Graphs is -- Filtering_Unused -- ---------------------- - function Filtering_Unused (This : Graph; - Instance : Alire.Containers.Release_Map) + function Filtering_Unused (This : Graph; + Used : Alire.Containers.Crate_Name_Sets.Set) return Graph is begin return Result : Graph do for Dep of This loop - if Instance.Contains (+Dep.Dependee) then + if Used.Contains (+Dep.Dependee) then Result.Include (Dep); end if; end loop; @@ -88,12 +88,32 @@ package body Alire.Dependencies.Graphs is return False; end Has_Dependencies; + ----------- + -- Label -- + ----------- + + function Label (Crate : Crate_Name; + Solution : Solutions.Solution; + TTY : Boolean := False) + return String + -- Get the proper label in the graph for a crate: milestone for releases, + -- dependency for hints. + is (if Solution.Releases.Contains (Crate) + then (if TTY + then Solution.Releases.Element (Crate).Milestone.TTY_Image + else Solution.Releases.Element (Crate).Milestone.Image) + elsif Solution.Hints.Contains (Crate) + then (if TTY + then Solution.Hints.Element (Crate).TTY_Image + else Solution.Hints.Element (Crate).Image) + else raise Program_Error with "crate should appear as release or hint"); + ---------- -- Plot -- ---------- procedure Plot (This : Graph; - Instance : Alire.Containers.Release_Map) + Solution : Solutions.Solution) is function B (Str : String) return String is ("[ " & Str & " ]"); function Q (Str : String) return String is ("""" & Str & """"); @@ -101,18 +121,18 @@ package body Alire.Dependencies.Graphs is Source : Utils.String_Vector; Alt : Utils.String_Vector; - Filtered : constant Graph := This.Filtering_Unused (Instance); + Filtered : constant Graph := This.Filtering_Unused (Solution.Required); begin Alt.Append ("graph dependencies {"); for Dep of Filtered loop - Alt.Append (Q (Instance (+Dep.Dependent).Milestone.Image) & + Alt.Append (Q (Label (+Dep.Dependent, Solution)) & " -> " & - Q (Instance (+Dep.Dependee).Milestone.Image) & "; "); + Q (Label (+Dep.Dependee, Solution)) & "; "); - Source.Append (B (Instance (+Dep.Dependent).Milestone.Image) & + Source.Append (B (Label (+Dep.Dependent, Solution)) & " -> " & - B (Instance (+Dep.Dependee).Milestone.Image)); + B (Label (+Dep.Dependee, Solution))); end loop; Alt.Append (" }"); @@ -131,17 +151,17 @@ package body Alire.Dependencies.Graphs is ----------- procedure Print (This : Graph; - Instance : Alire.Containers.Release_Map; + Solution : Solutions.Solution; Prefix : String := "") is Table : Alire.Utils.Tables.Table; - Filtered : constant Graph := This.Filtering_Unused (Instance); + Filtered : constant Graph := This.Filtering_Unused (Solution.Required); begin for Dep of Filtered loop - Table.Append (Prefix & Instance (+Dep.Dependent).Milestone.TTY_Image); + Table.Append (Prefix & Label (+Dep.Dependent, Solution, TTY => True)); Table.Append ("-->"); - Table.Append (Instance (+Dep.Dependee).Milestone.TTY_Image); + Table.Append (Label (+Dep.Dependee, Solution, TTY => True)); Table.New_Row; end loop; diff --git a/src/alire/alire-dependencies-graphs.ads b/src/alire/alire-dependencies-graphs.ads index bb57b56f..4fc6f4e9 100644 --- a/src/alire/alire-dependencies-graphs.ads +++ b/src/alire/alire-dependencies-graphs.ads @@ -20,10 +20,10 @@ package Alire.Dependencies.Graphs is Env : Properties.Vector) return Graph; -- Add a release and ALL its potential direct dependencies (even OR'ed) - function Filtering_Unused (This : Graph; - Instance : Alire.Containers.Release_Map) + function Filtering_Unused (This : Graph; + Used : Alire.Containers.Crate_Name_Sets.Set) return Graph; - -- Remove dependencies that don't appear in the solution + -- Remove dependencies that don't appear in the set of used releases function Has_Dependencies (This : Graph; Crate : Alire.Crate_Name) @@ -36,11 +36,11 @@ package Alire.Dependencies.Graphs is -- Remove all dependencies with Crate as the dependee crate procedure Plot (This : Graph; - Instance : Alire.Containers.Release_Map); + Solution : Solutions.Solution); -- Requires graph-easy in PATH procedure Print (This : Graph; - Instance : Alire.Containers.Release_Map; + Solution : Solutions.Solution; Prefix : String := ""); -- Print to terminal with the milestone info in Instance diff --git a/src/alire/alire-solutions.adb b/src/alire/alire-solutions.adb index 805082a4..3167e308 100644 --- a/src/alire/alire-solutions.adb +++ b/src/alire/alire-solutions.adb @@ -38,6 +38,24 @@ package body Alire.Solutions is end return; end Changing_Pin; + --------------- + -- Including -- + --------------- + + function Including (This : Solution; + Release : Alire.Releases.Release) + return Solution + is + begin + if This.Valid then + return Result : Solution := This do + Result.Releases.Include (Release.Name, Release); + end return; + else + return This; + end if; + end Including; + ---------------------------------- -- Libgraph_Easy_Perl_Installed -- ---------------------------------- @@ -157,10 +175,10 @@ package body Alire.Solutions is Dependencies.Graphs.From_Solution (This, Env) .Including (Root, Env); begin - Graph.Print (This.Releases.Including (Root), Prefix => " "); + Graph.Print (This.Including (Root), Prefix => " "); if Libgraph_Easy_Perl_Installed then - Graph.Plot (This.Releases.Including (Root)); + Graph.Plot (This.Including (Root)); else Trace.Log ("Cannot display graphical graph: " & Paths.Scripts_Graph_Easy & " not in path" & diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index 02328b48..e8dce767 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -25,9 +25,10 @@ package Alire.Solutions is Invalid_Solution : constant Solution; Empty_Valid_Solution : constant Solution; - function New_Solution (Releases : Release_Map; - Hints : Dependency_Map) - return Solution; + function New_Solution + (Releases : Release_Map := Containers.Empty_Release_Map; + Hints : Dependency_Map := Containers.Empty_Dependency_Map) + return Solution; -- A new valid solution function Releases (This : Solution) return Release_Map with @@ -56,6 +57,12 @@ package Alire.Solutions is raise Checked_Error with "Cannot change pins in invalid solution"; -- Return a copy of the solution with the new pinning status of Name + function Including (This : Solution; + Release : Alire.Releases.Release) + return Solution; + -- Add a release to the solution, without doing anything with its + -- dependencies. If not This.Valid, result will also be invalid. + function Pins (This : Solution) return Conditional.Dependencies; -- Return all pinned releases as exact version dependencies. Will return an -- empty list for invalid solutions. @@ -131,9 +138,10 @@ private Invalid_Solution : constant Solution := (Valid => False); Empty_Valid_Solution : constant Solution := (Valid => True, others => <>); - function New_Solution (Releases : Release_Map; - Hints : Dependency_Map) - return Solution + function New_Solution + (Releases : Release_Map := Containers.Empty_Release_Map; + Hints : Dependency_Map := Containers.Empty_Dependency_Map) + return Solution is (Solution'(Valid => True, Releases => Releases, Hints => Hints)); diff --git a/src/alr/alr-checkout.adb b/src/alr/alr-checkout.adb index 53c826a7..6350070a 100644 --- a/src/alr/alr-checkout.adb +++ b/src/alr/alr-checkout.adb @@ -139,7 +139,7 @@ package body Alr.Checkout is Trace.Error ("Remaining releases:" & Pending.Length'Img & "; Dependency graph:"); - Graph.Print (Pending); + Graph.Print (Alire.Solutions.New_Solution (Pending)); raise Program_Error with "No release checked-out in round" & Round'Img; else diff --git a/testsuite/tests/with/external/test.py b/testsuite/tests/with/external/test.py index 86a945fc..a4fe7aef 100644 --- a/testsuite/tests/with/external/test.py +++ b/testsuite/tests/with/external/test.py @@ -24,7 +24,9 @@ assert_match('Dependencies \(direct\):\n' ' make\*\n' 'Dependencies \(external\):\n' ' make\*\n' - '.*', # Skip graph + 'Dependencies \(graph\):\n' + ' xxx=0.0.0 --> make\*\n' + '.*', # skip plot or warning p.out, flags=re.S) -- 2.39.5