diff --git a/doc/user-changes.md b/doc/user-changes.md index f2ff8201c..fad51ad73 100644 --- a/doc/user-changes.md +++ b/doc/user-changes.md @@ -4,6 +4,19 @@ 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. +## Use crate metadata when pinning to a directory + +PR [#450](https://github.com/alire-project/alire/pull/450). + +When pinning a dependency to a directory (`alr pin|with --url`), detect +if the target contains Alire metadata (as usual, in an `alire` subdir). In that +case, use it to determine further dependencies and project file scopes. Also, +the target dependency name is verified. + +For such a target directory, a shortcut `with` command is available since the +crate name can be determined from the metadata: `alr with --url +/path/to/target` (note the absence of a crate name). + ## Allow working with incomplete solutions PR [#447](https://github.com/alire-project/alire/pull/447). diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index ee081a70d..8f46b5bef 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -1,3 +1,5 @@ +with Ada.Directories; + with Alire.Directories; with Alire.Root; with Alire.TOML_Index; @@ -33,7 +35,7 @@ package body Alire.Roots is -- Crate loaded properly, we can return a valid root here Trace.Debug ("Valid root found at " & Path); return New_Root (R => Release, - Path => Path, + Path => Ada.Directories.Full_Name (Path), Env => Alire.Root.Platform_Properties); end; else diff --git a/src/alr/alr-commands-withing.adb b/src/alr/alr-commands-withing.adb index 958d8e8f2..cf55aa67e 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -73,17 +73,13 @@ package body Alr.Commands.Withing is -- Add_Softlink -- ------------------ - procedure Add_Softlink (Cmd : Command) is + procedure Add_Softlink (Dep_Spec : String; + Path : String) is Requested : constant Alire.Milestones.Allowed_Milestones := - Alire.Milestones.Crate_Versions (Argument (1)); + Alire.Milestones.Crate_Versions (Dep_Spec); New_Dep : constant Alire.Dependencies.Dependency := Alire.Dependencies.From_Milestones (Requested); begin - if Num_Arguments /= 1 then - Reportaise_Wrong_Arguments - ("Exactly one crate needed for external pinning."); - end if; - declare use Alire; use type Conditional.Dependencies; @@ -94,7 +90,7 @@ package body Alr.Commands.Withing is Old_Solution .Depending_On (New_Dep) .Linking (Crate => New_Dep.Crate, - Path => Cmd.URL.all); + Path => Path); begin -- Prevent double-add @@ -124,6 +120,25 @@ package body Alr.Commands.Withing is end; end Add_Softlink; + --------------------- + -- Detect_Softlink -- + --------------------- + + procedure Detect_Softlink (Path : String) is + Root : constant Alire.Roots.Root := Alire.Roots.Detect_Root (Path); + begin + if Root.Is_Valid then + -- Add a dependency on ^(detected version) (i.e., safely upgradable) + Add_Softlink + (Dep_Spec => Root.Release.Name_Str + & "^" & Root.Release.Version.Image, + Path => Path); + else + Reportaise_Command_Failed + ("cannot add target: " & Root.Invalid_Reason); + end if; + end Detect_Softlink; + --------- -- Del -- --------- @@ -432,10 +447,10 @@ package body Alr.Commands.Withing is if Cmd.URL.all /= "" then if Num_Arguments = 1 then - Add_Softlink (Cmd); + Add_Softlink (Dep_Spec => Argument (1), + Path => Cmd.URL.all); else - raise Alire.Unimplemented; - -- TODO: detect crate at given path, and use it + Detect_Softlink (Cmd.URL.all); end if; else Requires_Full_Index; diff --git a/testsuite/tests/with/pin-dir-crate-autodetect/test.py b/testsuite/tests/with/pin-dir-crate-autodetect/test.py new file mode 100644 index 000000000..644a8f551 --- /dev/null +++ b/testsuite/tests/with/pin-dir-crate-autodetect/test.py @@ -0,0 +1,36 @@ +""" +Test that `alr with --url` without explicit crate autodetects the target crate +and correctly adds the pinned dependency +""" + +import os +import re + +from drivers.alr import run_alr +from drivers.asserts import assert_match +from drivers.helpers import path_separator +from glob import glob + +# Retrieve a crate +run_alr('get', 'hello=1') +target = glob('hello*')[0] + +# Initialize a workspace +run_alr('init', '--bin', 'xxx') +os.chdir('xxx') + +# Add the directory as pinned crate, with autodetection (no crate given, +# inferred from the crate metadata found at target). +run_alr('with', '--url', '..' + path_separator() + target) + +# Verify that hello^1 is a new dependency and also that hello dependencies are +# in the solution. +p = run_alr('with', '--solve') +assert_match('''Dependencies \(direct\): + hello\^1\.0\.0 +.*Dependencies \(solution\): + hello=1\.0\.0 .* + libhello=1\.1\.0 .*''', # we skip non-relevant details + p.out, flags=re.S) + +print('SUCCESS') diff --git a/testsuite/tests/with/pin-dir-crate-autodetect/test.yaml b/testsuite/tests/with/pin-dir-crate-autodetect/test.yaml new file mode 100644 index 000000000..e0a82ba80 --- /dev/null +++ b/testsuite/tests/with/pin-dir-crate-autodetect/test.yaml @@ -0,0 +1,4 @@ +driver: python-script +indexes: + solver_index: + in_fixtures: true