diff --git a/src/alire/alire-dependencies-states.adb b/src/alire/alire-dependencies-states.adb index 159f429a7..34ff68a02 100644 --- a/src/alire/alire-dependencies-states.adb +++ b/src/alire/alire-dependencies-states.adb @@ -52,7 +52,18 @@ package body Alire.Dependencies.States is begin if Opt_Root.Is_Valid then if Opt_Root.Value.Release.Name = Crate then + + -- Simple case in which the release corresponds with the crate return To_Holder (Opt_Root.Value.Release); + + elsif Opt_Root.Value.Release.Provides (Crate) then + + -- But also, the release may be providing the crate instead + Trace.Debug ("Created optional release " + & Opt_Root.Value.Release.Milestone.Image + & " providing crate " & Crate.As_String); + return To_Holder (Opt_Root.Value.Release); + else Raise_Checked_Error ("crate mismatch: expected " & Crate.TTY_Image diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 5b60531da..8e6100c3c 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -1057,7 +1057,9 @@ package body Alire.Roots is if Target.Is_Valid then Trace.Debug ("Crate found at pin location " & Pin.Relative_Path); - if Target.Value.Name /= Crate then + if Target.Value.Name /= Crate and then + not Target.Value.Release.Element.Provides (Crate) + then Raise_Checked_Error ("Mismatched crates for pin linking to " & TTY.URL (Pin.Path) & ": expected " & diff --git a/testsuite/tests/pin/crate-with-provides/test.py b/testsuite/tests/pin/crate-with-provides/test.py new file mode 100644 index 000000000..c5e63c803 --- /dev/null +++ b/testsuite/tests/pin/crate-with-provides/test.py @@ -0,0 +1,40 @@ +""" +Verify that we can link-pin a crate that has "provides" in a variety of ways. +""" + +import os +from drivers.alr import run_alr, init_local_crate, alr_manifest +from drivers.asserts import assert_eq, assert_match, match_solution + +# Create the target crate +init_local_crate(name="mylib") +# Update its manifest +with open(alr_manifest(), "a") as f: + f.write('provides=["coollib=1.0.0"]') +os.chdir("..") + +tests = [ + ["with", "--use=../mylib"], + ["with", "coollib", "--use=../mylib"], +] + +matches = [ + "mylib=0.1.0-dev (pinned) (origin: ../mylib)", + "coollib=0.1.0-dev (mylib) (pinned) (origin: ../mylib)" +] + +for target, test, id in zip(matches, tests, range(len(tests))): + # Create a new dependent crate + init_local_crate(f"myapp{id}") + run_alr(*test) + match_solution(target, escape=True) + os.chdir("..") + +# For the final test we need an extra step to force-add the dependency before +# pinning. +init_local_crate("myapp_final") +run_alr("--force", "with", "coollib") # Force because not in index +run_alr("pin", "coollib", "--use=../mylib") +match_solution(matches[-1], escape=True) + +print("SUCCESS") diff --git a/testsuite/tests/pin/crate-with-provides/test.yaml b/testsuite/tests/pin/crate-with-provides/test.yaml new file mode 100644 index 000000000..702010525 --- /dev/null +++ b/testsuite/tests/pin/crate-with-provides/test.yaml @@ -0,0 +1,4 @@ +driver: python-script +build_mode: both +indexes: + compiler_only_index: {}