Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show linked paths and per-release dependencies in --solve solutions #453

Merged
merged 1 commit into from Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions doc/user-changes.md
Expand Up @@ -4,6 +4,20 @@ This document is a development diary summarizing changes in `alr` that notably
affect the user experience. It is intended as a one-stop point for users to
stay on top of `alr` new features.

### Show release-specific dependency sets in solutions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW @mosteo, this is now live on the website: https://alire.ada.dev/docs/#user-facing-changes-log

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! I had indeed forgotten about updating the website... :S


PR [#453](https://github.com/alire-project/alire/pull/453).

The dependency solution shown with the `--solve` switch now details for each
release the particular version set with which a dependency is brought into the
dependency closure. For example:

```
Dependencies (graph):
hello=1.0.1 --> libhello=1.0.1 (^1.0)
superhello=1.0.0 --> libhello=1.0.1 (~1.0)
```

### Use crate metadata when pinning to a directory

PR [#450](https://github.com/alire-project/alire/pull/450).
Expand Down
84 changes: 62 additions & 22 deletions src/alire/alire-dependencies-graphs.adb
Expand Up @@ -2,6 +2,7 @@ with Alire.Conditional;
with Alire.Directories;
with Alire.OS_Lib.Subprocess;
with Alire.Paths;
with Alire.Root;
with Alire.Utils.Tables;

package body Alire.Dependencies.Graphs is
Expand Down Expand Up @@ -87,21 +88,51 @@ package body Alire.Dependencies.Graphs is
-- Label --
-----------

function Label (Crate : Crate_Name;
Solution : Solutions.Solution;
TTY : Boolean := False)
return String
function Label_Dependee (Dependent : Crate_Name;
Dependee : Crate_Name;
Solution : Solutions.Solution;
For_Plot : Boolean)
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.Depends_On (Crate)
then (if TTY
then Solution.Dependency (Crate).TTY_Image
else Solution.Dependency (Crate).Image)
else raise Program_Error with "crate should appear as release or hint");
is
begin

-- For a solved dependency, return "crate=version (original dependency)"
-- For an unsolved dependency, return "crate^dependency". In the case of
-- For_Plot, omit the (original dependency).

if Solution.State (Dependee).Has_Release then
if For_Plot then
return Solution.State (Dependee).Release.Milestone.Image;
else
return Solution.State (Dependee).Release.Milestone.TTY_Image
& " ("
& TTY.Version
(Solution.Dependency (Dependent, Dependee).Versions.Image)
& ")";
end if;
else
if For_Plot then
return Solution.Dependency (Dependent, Dependee).Image;
else
return Solution.Dependency (Dependent, Dependee).TTY_Image;
end if;
end if;
end Label_Dependee;

---------------------
-- Label_Dependent --
---------------------

function Label_Dependent (Crate : Crate_Name;
Solution : Solutions.Solution;
TTY : Boolean := False)
return String
is (if TTY then
Solution.State (Crate).Release.Milestone.TTY_Image
else
Solution.State (Crate).Release.Milestone.Image);

----------
-- Plot --
Expand All @@ -121,13 +152,19 @@ package body Alire.Dependencies.Graphs is
Alt.Append ("graph dependencies {");

for Dep of Filtered loop
Alt.Append (Q (Label (+Dep.Dependent, Solution)) &
" -> " &
Q (Label (+Dep.Dependee, Solution)) & "; ");

Source.Append (B (Label (+Dep.Dependent, Solution)) &
" -> " &
B (Label (+Dep.Dependee, Solution)));
Alt.Append (Q (Label_Dependent (+Dep.Dependent, Solution))
& " -> "
& Q (Label_Dependee (+Dep.Dependent,
+Dep.Dependee,
Solution,
For_Plot => True)) & "; ");

Source.Append (B (Label_Dependent (+Dep.Dependent, Solution))
& " -> "
& B (Label_Dependee (+Dep.Dependent,
+Dep.Dependee,
Solution,
For_Plot => True)));
end loop;
Alt.Append (" }");

Expand All @@ -154,9 +191,12 @@ package body Alire.Dependencies.Graphs is
Filtered : constant Graph := This.Filtering_Unused (Solution.Crates);
begin
for Dep of Filtered loop
Table.Append (Prefix & Label (+Dep.Dependent, Solution, TTY => True));
Table.Append
(Prefix & Label_Dependent (+Dep.Dependent, Solution, TTY => True));
Table.Append ("-->");
Table.Append (Label (+Dep.Dependee, Solution, TTY => True));
Table.Append
(Label_Dependee
(+Dep.Dependent, +Dep.Dependee, Solution, For_Plot => False));
Table.New_Row;
end loop;

Expand Down
49 changes: 41 additions & 8 deletions src/alire/alire-solutions.adb
Expand Up @@ -5,6 +5,7 @@ with Alire.Dependencies.Graphs;
with Alire.Index;
with Alire.OS_Lib.Subprocess;
with Alire.Paths;
with Alire.Root;
with Alire.Solutions.Diffs;
with Alire.Utils.Tables;
with Alire.Utils.TTY;
Expand Down Expand Up @@ -37,6 +38,33 @@ package body Alire.Solutions is
end return;
end Dependencies_That;

----------------
-- Dependency --
----------------

function Dependency (This : Solution;
Dependent : Crate_Name;
Dependee : Crate_Name)
return Dependencies.Dependency
is
begin
-- This is not particularly efficient. An Enumerate version that
-- returned a map would serve better here if this proves to be a
-- bottleneck in the future.

for Dep of
Conditional.Enumerate
(This.State (Dependent)
.Release.Dependencies (Root.Platform_Properties))
loop
if Dep.Crate = Dependee then
return Dep;
end if;
end loop;

raise Program_Error with "invalid dependency request (body)";
end Dependency;

-------------
-- Changes --
-------------
Expand Down Expand Up @@ -331,26 +359,31 @@ package body Alire.Solutions is

if not This.Releases.Is_Empty then
Trace.Log ("Dependencies (solution):", Level);

for Rel of This.Releases loop
Trace.Log (" " & Rel.Milestone.TTY_Image
& (if This.State (Rel.Name).Is_Pinned
& (if This.State (Rel.Name).Is_Pinned or else
This.State (Rel.Name).Is_Linked
then TTY.Emph (" (pinned)")
else "")
& (if Detailed then
" (origin: " &
Utils.To_Lower_Case (Rel.Origin.Kind'Img) & ")"
else
""),
& (if Detailed
then " (origin: "
& (if This.State (Rel.Name).Is_Linked
then TTY.URL (This.State (Rel.Name).Link.Path)
else Utils.To_Lower_Case (Rel.Origin.Kind'Img))
& ")"
else ""),
Level);
end loop;
end if;

-- Show other dependencies with their status and hints

if (for some Dep of This.Dependencies => not Dep.Is_Solved) then
if (for some Dep of This.Dependencies => not Dep.Has_Release) then
Trace.Log ("Dependencies (external):", Level);
for Dep of This.Dependencies loop
if not This.State (Dep.Crate).Is_Solved then
if not This.State (Dep.Crate).Has_Release
then
Trace.Log (" " & Dep.TTY_Image, Level);

-- Look for hints. If we are relying on workspace information
Expand Down
11 changes: 11 additions & 0 deletions src/alire/alire-solutions.ads
Expand Up @@ -184,6 +184,17 @@ package Alire.Solutions is
with Pre => This.Depends_On (Crate);
-- Return the specific dependency versions as currently stored

function Dependency (This : Solution;
Dependent : Crate_Name;
Dependee : Crate_Name)
return Dependencies.Dependency
with Pre =>
(This.State (Dependent).Has_Release and then This.Depends_On (Dependee))
or else raise Program_Error with "invalid dependency request";
-- The solver groups dependencies on a same crate by several dependents.
-- This function allows identifying the concrete dependency that a solved
-- release introduced in the solution.

function Depends_On (This : Solution;
Name : Crate_Name) return Boolean;
-- Says if the solution depends on the crate in some way
Expand Down
14 changes: 14 additions & 0 deletions testsuite/fixtures/solver_index/su/superhello.toml
@@ -0,0 +1,14 @@
[general]
description = "A better hello"
licenses = ["GPL 3.0", "MIT"]
website = "example.com"
maintainers = ["bob@example.com"]
maintainers-logins = ["mylogin"]
authors = ["Bob", "Alice"]


['1.0.0']
origin = "file://."

['1.0.0'.depends-on]
libhello = "~1.0"
35 changes: 35 additions & 0 deletions testsuite/tests/solver/one-dep-two-constraints/test.py
@@ -0,0 +1,35 @@
"""
Test that a dependency that is introduced by two dependents with different
constraints is properly solved and shown.
"""

import os
import re

from drivers.alr import run_alr
from drivers.asserts import assert_match

# Initialize project
run_alr('init', '--bin', 'xxx')
os.chdir('xxx')

# Add dependency on hello^1. Solution is hello=1.0.1 --> libhello=1.1.0
run_alr('with', 'hello^1')
p = run_alr('with', '--solve')
assert_match('.*' # skip solution
'Dependencies \(graph\):\n'
' hello=1.0.1 --> libhello=1.1.0 \(\^1.0\).*',
p.out, flags=re.S)

# Add dependency on superhello*. Solution is superhello=1.0 --> libhello=1.0.1
# This implies a downgrade from libhello=1.1.0 to libhello=1.0.1, which is the
# only possible combination of libhello^1.0 & libhello~1.0
run_alr('with', 'superhello')
p = run_alr('with', '--solve')
assert_match('.*' # skip solution
'Dependencies \(graph\):\n'
' hello=1.0.1 --> libhello=1.0.1 \(\^1.0\)\n'
' superhello=1.0.0 --> libhello=1.0.1 \(~1.0\).*',
p.out, flags=re.S)

print('SUCCESS')
3 changes: 3 additions & 0 deletions testsuite/tests/solver/one-dep-two-constraints/test.yaml
@@ -0,0 +1,3 @@
driver: python-script
indexes:
solver_index: {}