From 8e7f59ae8c1f8621a951d4e48516c1ed193dce6f Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 28 Jun 2021 15:21:46 +0200 Subject: [PATCH] Re-enable pin removal option and related tests (#759) * Completed Roots.Editable commands for removal * Completed Alr.Commands.Pin * Reinstated all `alr pin` functionality * Reinstated remaining disabled pin tests * Reinstated remaining disabled tests * Testsuite: fix platform-independent path on Windows --- .gitmodules | 3 + alire.gpr | 1 + alr_env.gpr | 1 + deps/aaa | 2 +- deps/toml_slicer | 1 + src/alire/alire-dependencies-states.ads | 20 +- src/alire/alire-manifest.adb | 197 ++---------------- src/alire/alire-roots-editable.adb | 24 ++- src/alire/alire-roots-editable.ads | 4 +- src/alire/alire-user_pins.adb | 13 +- src/alr/alr-commands-pin.adb | 168 ++++++--------- src/alr/alr-commands-pin.ads | 4 - src/alr/alr-commands-withing.adb | 14 +- .../indirect-link/my_index/index/index.toml | 0 .../my_index/index/ti/tier1/tier1-1.0.0.toml | 0 .../my_index/index/ti/tier2/tier2-1.0.0.toml | 0 .../my_index/index/ti/tier3/tier3-1.0.0.toml | 0 .../get/indirect-link/test.py | 12 +- .../get/indirect-link/test.yaml | 0 .../index/he/hello1/hello1-0.1.0.toml | 0 .../index/he/hello2/hello2-0.1.0.toml | 0 .../pin/all/my_index/index/index.toml | 0 testsuite/{disabled => tests}/pin/all/test.py | 0 .../{disabled => tests}/pin/all/test.yaml | 0 .../pin/dir-mismatch/test.py | 10 +- .../pin/dir-mismatch/test.yaml | 0 testsuite/tests/pin/post-update/test.py | 3 + .../{disabled => tests}/pin/remote/test.py | 17 +- .../{disabled => tests}/pin/remote/test.yaml | 0 testsuite/tests/pin/unpin/test.py | 3 + .../my_index/crates/crate_1234/.emptydir | 0 .../my_index/crates/crate_1234/alire.toml | 0 .../crates/crate_1234/alire/.emptydir | 0 .../linked-paths/my_index/index/index.toml | 0 .../printenv/linked-paths/test.py | 4 +- .../printenv/linked-paths/test.yaml | 0 .../with/changes-info/test.py | 0 .../with/changes-info/test.yaml | 0 .../tests/with/dynamic-dependencies/test.py | 4 +- .../crates/libhello_1.0.0/libhello.gpr | 0 .../crates/libhello_1.0.0/src/libhello.ads | 0 .../with/pin-dir/my_index/index/index.toml | 0 .../index/li/libhello/libhello-1.0.0.toml | 0 .../{disabled => tests}/with/pin-dir/test.py | 0 .../with/pin-dir/test.yaml | 0 .../with/pin-transitive/test.py | 0 .../with/pin-transitive/test.yaml | 0 .../tests/workflows/init-with-pin/test.py | 2 +- 48 files changed, 174 insertions(+), 333 deletions(-) create mode 160000 deps/toml_slicer rename testsuite/{disabled => tests}/get/indirect-link/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml (100%) rename testsuite/{disabled => tests}/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml (100%) rename testsuite/{disabled => tests}/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml (100%) rename testsuite/{disabled => tests}/get/indirect-link/test.py (72%) rename testsuite/{disabled => tests}/get/indirect-link/test.yaml (100%) rename testsuite/{disabled => tests}/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml (100%) rename testsuite/{disabled => tests}/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml (100%) rename testsuite/{disabled => tests}/pin/all/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/pin/all/test.py (100%) rename testsuite/{disabled => tests}/pin/all/test.yaml (100%) rename testsuite/{disabled => tests}/pin/dir-mismatch/test.py (74%) rename testsuite/{disabled => tests}/pin/dir-mismatch/test.yaml (100%) rename testsuite/{disabled => tests}/pin/remote/test.py (82%) rename testsuite/{disabled => tests}/pin/remote/test.yaml (100%) rename testsuite/{disabled => tests}/printenv/linked-paths/my_index/crates/crate_1234/.emptydir (100%) rename testsuite/{disabled => tests}/printenv/linked-paths/my_index/crates/crate_1234/alire.toml (100%) rename testsuite/{disabled => tests}/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir (100%) rename testsuite/{disabled => tests}/printenv/linked-paths/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/printenv/linked-paths/test.py (90%) rename testsuite/{disabled => tests}/printenv/linked-paths/test.yaml (100%) rename testsuite/{disabled => tests}/with/changes-info/test.py (100%) rename testsuite/{disabled => tests}/with/changes-info/test.yaml (100%) rename testsuite/{disabled => tests}/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr (100%) rename testsuite/{disabled => tests}/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads (100%) rename testsuite/{disabled => tests}/with/pin-dir/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{disabled => tests}/with/pin-dir/test.py (100%) rename testsuite/{disabled => tests}/with/pin-dir/test.yaml (100%) rename testsuite/{disabled => tests}/with/pin-transitive/test.py (100%) rename testsuite/{disabled => tests}/with/pin-transitive/test.yaml (100%) diff --git a/.gitmodules b/.gitmodules index df753f7f..d67ac924 100644 --- a/.gitmodules +++ b/.gitmodules @@ -39,3 +39,6 @@ [submodule "deps/optional"] path = deps/optional url = https://github.com/mosteo/optional +[submodule "deps/toml_slicer"] + path = deps/toml_slicer + url = https://github.com/mosteo/toml_slicer diff --git a/alire.gpr b/alire.gpr index 91785fd5..32084138 100644 --- a/alire.gpr +++ b/alire.gpr @@ -8,6 +8,7 @@ with "minirest"; with "optional"; with "semantic_versioning"; with "simple_logging"; +with "toml_slicer"; with "uri"; with "xml_ez_out"; with "spdx"; diff --git a/alr_env.gpr b/alr_env.gpr index 64b70b39..e1e5e9a6 100644 --- a/alr_env.gpr +++ b/alr_env.gpr @@ -12,6 +12,7 @@ aggregate project Alr_Env is "deps/optional", "deps/semantic_versioning", "deps/simple_logging", + "deps/toml_slicer", "deps/uri-ada", "deps/xmlezout", "deps/spdx"); diff --git a/deps/aaa b/deps/aaa index ccb78861..594a7d58 160000 --- a/deps/aaa +++ b/deps/aaa @@ -1 +1 @@ -Subproject commit ccb78861bd7589dfcce08a70b69cdc72169bbf4a +Subproject commit 594a7d58350ce7e7eb8dbc25fa1c1d0cb1ef4477 diff --git a/deps/toml_slicer b/deps/toml_slicer new file mode 160000 index 00000000..1c0286bd --- /dev/null +++ b/deps/toml_slicer @@ -0,0 +1 @@ +Subproject commit 1c0286bd724c6f257a36fc89412fcefd4f555228 diff --git a/src/alire/alire-dependencies-states.ads b/src/alire/alire-dependencies-states.ads index a092b960..d8573a77 100644 --- a/src/alire/alire-dependencies-states.ads +++ b/src/alire/alire-dependencies-states.ads @@ -281,16 +281,16 @@ private else "") & Utils.To_Lower_Case (This.Fulfilled.Fulfillment'Img) & (if This.Fulfilled.Fulfillment = Linked - then This.Fulfilled.Target.Element.Image (User => True) - & (if not This.Fulfilled.Target.Element.Is_Broken - then "" - else ",broken") - & (if This.Fulfilled.Target.Element.Is_Remote - then ",url=" & This.Fulfilled.Target.Element.URL - else "") - & (if This.Has_Release - then ",release" - else "") + then "," & This.Fulfilled.Target.Element.Image (User => True) + & (if not This.Fulfilled.Target.Element.Is_Broken + then "" + else ",broken") + & (if This.Fulfilled.Target.Element.Is_Remote + then ",url=" & This.Fulfilled.Target.Element.URL + else "") + & (if This.Has_Release + then ",release" + else "") else "") & (if This.Pinning.Pinned then ",pin=" & This.Pinning.Version.Image diff --git a/src/alire/alire-manifest.adb b/src/alire/alire-manifest.adb index 25ae460b..63e52b64 100644 --- a/src/alire/alire-manifest.adb +++ b/src/alire/alire-manifest.adb @@ -1,13 +1,13 @@ -with Alire.Directories; -with Alire.Errors; with Alire.Paths; with Alire.Releases; with Alire.TOML_Keys; with Alire.Utils.Text_Files; +with TOML_Slicer; + package body Alire.Manifest is - Warning : constant String := " # This line was added by `alr with`"; + Warning : constant String := " # Added by alr"; ------------ -- Append -- @@ -77,183 +77,14 @@ package body Alire.Manifest is procedure Remove (Name : Any_Path; Dep : Crate_Name) is - - ------------ - -- Remove -- - ------------ - - procedure Remove (Dep : Crate_Name; - Lines : in out Utils.String_Vector) - -- Remove given Dep from Lines, or warn if impossible - is - Enter_Marker : constant String := "[[" & TOML_Keys.Depends_On & "]]"; - -- We must see a line like this before being able to remove a dep. - - Target : constant String := Dep.As_String & "="""; - -- A line starting with Target is a candidate for deletion - - Armed : Boolean := False; - -- True when we are inside [[depends-on]] - - Found : Boolean := False; -- True when the dependency was found - - use Utils; - - ------------------- - -- Remove_Target -- - ------------------- - - procedure Remove_Target is - begin - for I in Lines.First_Index .. Lines.Last_Index loop - declare - Line : constant String := Replace (Lines (I), " ", ""); - begin - - if Armed and then Starts_With (Line, Target) then - -- Remove the target dependency - Trace.Debug ("Dependency to remove found at manifest line" - & I'Img); - Found := True; - Lines.Delete (I); - exit; - - elsif Starts_With (Line, "[[") then - -- Detect a plain [[depends-on]] with optional comment - Armed := - Line = Enter_Marker or else - Starts_With (Line, Enter_Marker & '#'); - - elsif Armed and then Line /= "" and then - Line (Line'First) /= '[' -- not a table or different array - then - -- We are seeing a different dependency in the same array - -- entry; we can still remove our target if later found - -- in this entry. This can happen if the user edited and - -- reused a previous [[depends-on]] added by `alr with`. - null; - - elsif Line = "" or else Starts_With (Line, "#") then - -- We still can remove a dependency found in this context - null; - - else - -- Any other sighting complicates matters and we won't - -- touch it. - Armed := False; - end if; - end; - end loop; - - if not Found then - Raise_Checked_Error - ("Could not find dependency in manifest: " & Dep.TTY_Image); - return; - end if; - end Remove_Target; - - ----------------------- - -- Remove_Empty_Deps -- - ----------------------- - - procedure Remove_Empty_Deps is - -- This might probably be done with multiline regular expressions - - Deletable : Natural := 0; - -- Tracks how many empty lines we have seen since the last [[ - - Can_Delete : Boolean := True; - -- We can delete as long as we are only seeing empty lines - begin - - -- Traverse lines backwards - - for I in reverse Lines.First_Index .. Lines.Last_Index loop - declare - Line : constant String := Replace (Lines (I), " ", ""); - begin - if Can_Delete then - -- Look for empty lines or the opening [[depends-on]] - if Line = "" then - Deletable := Deletable + 1; - - elsif - Line = Enter_Marker or else - Starts_With (Line, Enter_Marker & '#') - then - -- Now we can delete the empty [[depends-on]] plus any - -- following empty lines. - for J in 0 .. Deletable loop -- 0 for the current line - Trace.Debug ("Removing meaningless manifest line: " - & Lines (I)); - Lines.Delete (I); - end loop; - - -- Restart, we can still delete previous entries - Deletable := 0; - - else - -- We found something else, so do not remove entry - Can_Delete := False; - Deletable := 0; - end if; - - else - -- Look for a [[ that starts another array entry. We - -- cannot rely on simply [ for tables, these could be - -- nested array tables. - if Starts_With (Line, "[[") then - Can_Delete := True; - Deletable := 0; - -- We will look in next iterations for a precedent - -- empty array entry. - end if; - end if; - end; - end loop; - end Remove_Empty_Deps; - - begin - - -- First pass, remove a detected dependency in the proper location. - -- Note that this only removes the dependency line, but not the - -- enclosing [[depends-on]]. It is ok to have such an empty array - -- entry. Empty array entries are cleaned up afterwards. - - Remove_Target; - - -- Second pass, remove empty [[depends-on]] array entries. This - -- ensures that trivial add/remove of dependencies cannot grow - -- the file indefinitely with empty [[]] entries. - - Remove_Empty_Deps; - - end Remove; - - Replacer : constant Directories.Replacer := - Directories.New_Replacement - (Name, - Backup => True, - Backup_Dir => Paths.Working_Folder_Inside_Root); begin - - declare - File : constant Utils.Text_Files.File := - Utils.Text_Files.Load (Replacer.Editable_Name, - Backup => False); - -- Replacer takes care of backup - begin - Remove (Dep, File.Lines.all); - end; - - -- Attempt loading of the new file as a double check. This should never - -- fail because we won't touch anything that's clearly removable. - if not Is_Valid (Replacer.Editable_Name, Local) then - raise Program_Error - with Errors.Set ("Removal of dependencies in manifest failed"); - end if; - - Replacer.Replace; -- All went well, keep the changes + TOML_Slicer.Remove_Line_From_Array + (File_Name => Name, + Array_Name => TOML_Keys.Depends_On, + Entry_Name => Dep.As_String, + Cleanup => True, + Backup => True, + Backup_Dir => Paths.Working_Folder_Inside_Root); end Remove; ---------------- @@ -264,7 +95,13 @@ package body Alire.Manifest is Pin : Crate_Name) is begin - raise Unimplemented; + TOML_Slicer.Remove_Line_From_Array + (File_Name => File, + Array_Name => TOML_Keys.Pins, + Entry_Name => Pin.As_String, + Cleanup => True, + Backup => True, + Backup_Dir => Paths.Working_Folder_Inside_Root); end Remove_Pin; end Alire.Manifest; diff --git a/src/alire/alire-roots-editable.adb b/src/alire/alire-roots-editable.adb index 1dd3cd5e..ed3c21ac 100644 --- a/src/alire/alire-roots-editable.adb +++ b/src/alire/alire-roots-editable.adb @@ -152,11 +152,8 @@ package body Alire.Roots.Editable is Crate : Crate_Name; Unpin : Boolean := True) is - pragma Unreferenced (Unpin); begin - -- TODO: remove pin if existing too (next PR) - -- If dependency is not among dependencies at all, nothing to do if not (for some Dep of Release (This.Edit).Flat_Dependencies => @@ -184,6 +181,10 @@ package body Alire.Roots.Editable is Alire.Manifest.Remove (This.Edit.Crate_File, Crate); This.Reload_Manifest; + if Unpin then + This.Remove_Pin (Crate); + end if; + end Remove_Dependency; --------------------- @@ -192,15 +193,14 @@ package body Alire.Roots.Editable is procedure Add_Version_Pin (This : in out Root; Crate : Crate_Name; - Version : String) + Version : Semver.Version) is - V : constant Semver.Version := Semver.Parse (Version); begin if not This.Solution.Depends_On (Crate) then This.Add_Dependency (Dependencies.New_Dependency (Crate, - Semver.Updatable (V))); + Semver.Updatable (Version))); end if; -- Remove any previous pin for this crate @@ -211,10 +211,10 @@ package body Alire.Roots.Editable is Alire.Manifest.Append (Crate_File (This.Edit), Crate, - User_Pins.New_Version (V)); + User_Pins.New_Version (Version)); This.Reload_Manifest; - This.Edit.Set (This.Solution.Pinning (Crate, V)); + This.Edit.Set (This.Solution.Pinning (Crate, Version)); end Add_Version_Pin; -------------------------- @@ -246,6 +246,12 @@ package body Alire.Roots.Editable is else Pin_Root.Value.Name); begin + -- If nothing in the solution depends on the crate (that is why we + -- check the Solution and not the top-level dependencies) requested + -- to be pinned, we assume a top-level dependency on the crate would + -- be wanted, and add it too. If this is not wanted, the user can + -- easily remove the dependency by hand afterwards. + if not This.Solution.Depends_On (Crate) then This.Add_Dependency (Dependencies.New_Dependency @@ -387,7 +393,7 @@ package body Alire.Roots.Editable is if This.Solution.Depends_On (Crate) and then This.Solution.State (Crate).Is_User_Pinned then - Alire.Manifest.Remove_Pin (Lock_File (This.Edit), + Alire.Manifest.Remove_Pin (This.Edit.Crate_File, Crate); This.Edit.Set (This.Solution.User_Unpinning (Crate)); end if; diff --git a/src/alire/alire-roots-editable.ads b/src/alire/alire-roots-editable.ads index e8b849c4..0893beb4 100644 --- a/src/alire/alire-roots-editable.ads +++ b/src/alire/alire-roots-editable.ads @@ -5,6 +5,8 @@ with Alire.Errors; with Alire.Optional; with Alire.TTY; +with Semantic_Versioning; + package Alire.Roots.Editable is -- This type mimics manual edition of the manifest. All operations in here @@ -64,7 +66,7 @@ package Alire.Roots.Editable is procedure Add_Version_Pin (This : in out Root; Crate : Crate_Name; - Version : String) + Version : Semantic_Versioning.Version) with Pre => This.Can_Be_Pinned (Crate); -- Add a version pin; if the root doesn't depend on it previously, the -- dependency will be added too. diff --git a/src/alire/alire-user_pins.adb b/src/alire/alire-user_pins.adb index 9ea8d094..c0f42e2d 100644 --- a/src/alire/alire-user_pins.adb +++ b/src/alire/alire-user_pins.adb @@ -83,8 +83,10 @@ package body Alire.User_Pins is is (Crate.As_String & " = { " & (case This.Kind is - when To_Version => "version='" & This.Version.Image & "'", - when To_Path => "path='" & Path (This) & "'", + when To_Version => + "version='" & This.Version.Image & "'", + when To_Path => + "path='" & VFS.Attempt_Portable (Path (This)) & "'", when To_Git => "url='" & (+This.URL) & "'" & (if This.Branch /= "" @@ -150,6 +152,13 @@ package body Alire.User_Pins is Temp : Directories.Temp_File; begin + -- Skip checkout of existing commit + + if Commit /= "" and then Adirs.Exists (Destination) then + Trace.Debug ("Skipping checkout of commit pin at " & Destination); + return; + end if; + -- Check out the branch or commit if not diff --git a/src/alr/alr-commands-pin.adb b/src/alr/alr-commands-pin.adb index c225e6bd..1ba2b362 100644 --- a/src/alr/alr-commands-pin.adb +++ b/src/alr/alr-commands-pin.adb @@ -1,5 +1,7 @@ -with Alire.Releases; -with Alire.Solutions.Diffs; +with Alire.Dependencies; +with Alire.Optional; +with Alire.Roots.Editable; +with Alire.Solutions; with Alire.URI; with Alire.Utils.TTY; with Alire.Utils.User_Input; @@ -8,35 +10,26 @@ with Alr.Commands.User_Input; with Semantic_Versioning; +with TOML_Slicer; + package body Alr.Commands.Pin is package Semver renames Semantic_Versioning; package TTY renames Alire.Utils.TTY; - ---------------------- - -- Warn_Manual_Only -- - ---------------------- - - procedure Warn_Manual_Only is - begin - Reportaise_Command_Failed - ("Pin adition/removal is currently not implemented via command-line. " - & "Please edit the manifest manually to add/remove pins. " - & "Find the syntax for pins at " - & TTY.URL ("https://github.com/alire-project/alire/blob/master/" - & "doc/catalog-format-spec.md")); - end Warn_Manual_Only; - -------------------- -- Change_One_Pin -- -------------------- - procedure Change_One_Pin (Cmd : in out Command; - Solution : in out Alire.Solutions.Solution; - Target : String) + procedure Change_One_Pin (Cmd : in out Command; + Root : in out Alire.Roots.Editable.Root; + Target : String) is - Version : Semver.Version; - Name : constant Alire.Crate_Name := +Utils.Head (Target, '='); + Version : Semver.Version; + Solution : constant Alire.Solutions.Solution := Root.Solution; + Dep : constant Alire.Dependencies.Dependency := + Alire.Dependencies.From_String (Target); + -- Only crate=version should be allowed here, we check it shortly --------- -- Pin -- @@ -50,13 +43,7 @@ package body Alr.Commands.Pin is Cmd.Requires_Full_Index; - -- To be removed in upcoming PR, kept momentarily for reference - -- Solution := Alire.Pinning.Pin - -- (Crate => Name, - -- Version => Version, - -- Dependencies => Cmd.Root.Release.Dependencies, - -- Environment => Platform.Properties, - -- Solution => Solution); + Root.Add_Version_Pin (Dep.Crate, Version); end Pin; @@ -66,29 +53,24 @@ package body Alr.Commands.Pin is procedure Unpin is begin - if not (Solution.State (Name).Is_Linked or else - Solution.State (Name).Is_Pinned) - then + if not Solution.State (Dep.Crate).Is_User_Pinned then Reportaise_Command_Failed ("Requested crate is already unpinned"); end if; Cmd.Requires_Full_Index; - -- To be removed in upcoming PR, kept momentarily for reference - -- Solution := Alire.Pinning.Unpin - -- (Crate => Name, - -- Dependencies => Cmd.Root.Release.Dependencies, - -- Environment => Platform.Properties, - -- Solution => Solution); + Root.Remove_Pin (Dep.Crate); end Unpin; begin -- Sanity checks - if not Solution.Depends_On (Name) then - Reportaise_Command_Failed ("Cannot pin dependency not in solution: " - & (+Name)); + if not Solution.Depends_On (Dep.Crate) then + Reportaise_Command_Failed + ("Cannot " & (if Cmd.Unpin then "unpin" else "pin") + & " dependency not in solution: " + & TTY.Name (Dep.Crate)); end if; -- Check if we are given a particular version @@ -99,17 +81,19 @@ package body Alr.Commands.Pin is Reportaise_Wrong_Arguments ("Unpinning does not require version"); end if; - Version := Semver.Parse (Utils.Tail (Target, '='), + Version := Semver.Parse (Utils.Tail (Dep.Image, '='), Relaxed => False); - Trace.Debug ("Pin requested for exact version: " & Version.Image); - elsif Solution.State (Name).Is_Solved then - Version := Solution.State (Name).Release.Version; + Trace.Debug ("Pin requested for exact version: " + & Version.Image); + + elsif Solution.State (Dep.Crate).Is_Solved then + Version := Solution.State (Dep.Crate).Release.Version; elsif not Cmd.Unpin then - Trace.Warning ("An explicit version is required to pin a crate with" - & " no release in the current solution: " - & TTY.Name (Name)); - return; + Reportaise_Wrong_Arguments + ("An explicit version is required to pin a crate with" + & " no release in the current solution: " + & TTY.Name (Dep.Crate)); end if; -- Proceed to pin/unpin @@ -127,25 +111,6 @@ package body Alr.Commands.Pin is overriding procedure Execute (Cmd : in out Command) is - - ------------- - -- Confirm -- - ------------- - - procedure Confirm (Old_Sol, New_Sol : Alire.Solutions.Solution) is - Diff : constant Alire.Solutions.Diffs.Diff := - Old_Sol.Changes (New_Sol); - begin - if Diff.Contains_Changes then - if Alire.Utils.User_Input.Confirm_Solution_Changes (Diff) then - Cmd.Root.Set (Solution => New_Sol); - Cmd.Root.Deploy_Dependencies; - end if; - else - Trace.Info ("No changes to apply."); - end if; - end Confirm; - begin -- Argument validation @@ -171,46 +136,40 @@ package body Alr.Commands.Pin is ("Pin expects a single crate or crate=version argument"); end if; - -- Anything beyond this point is modifying pins, which is currently - -- unimplemented. - - Warn_Manual_Only; - -- Apply changes; declare - New_Sol : Alire.Solutions.Solution := Cmd.Root.Solution; - Old_Sol : constant Alire.Solutions.Solution := New_Sol; + New_Root : Alire.Roots.Editable.Root := + Alire.Roots.Editable.New_Root (Original => Cmd.Root); + Optional_Crate : constant Alire.Optional.Crate_Name := + (if Num_Arguments = 1 + then Alire.Optional.Crate_Names.Unit + (Alire.To_Name (Argument (1))) + else Alire.Optional.Crate_Names.Empty); begin if Cmd.Pin_All then -- Change all pins - for Crate of New_Sol.Crates loop - if New_Sol.State (Crate).Is_Pinned = Cmd.Unpin then - Change_One_Pin (Cmd, New_Sol, +Crate); - end if; + for Crate of Cmd.Root.Solution.Crates loop + Change_One_Pin (Cmd, New_Root, Crate.As_String); end loop; elsif Cmd.URL.all /= "" then - -- Pin to remote commit - if Cmd.Commit.all /= "" or else Alire.URI.Is_HTTP_Or_Git (Cmd.URL.all) then - null; - -- This is slated for removal in the immediate future; kept for - -- reference for the replacement implementation - - -- New_Sol := Cmd.Root.Pinned_To_Remote - -- (Dependency => Alire.Conditional.New_Dependency - -- (Alire.Dependencies.From_String (Argument (1))), - -- URL => Cmd.URL.all, - -- Commit => Cmd.Commit.all, - -- Must_Depend => True) - -- .Solution; + + -- Pin to remote commit + + New_Root.Add_Remote_Pin + (Crate => Optional_Crate, + Origin => Cmd.URL.all, + Commit => Cmd.Commit.all, + Branch => ""); -- TODO: allow passing --branch + else -- Pin to dir @@ -222,38 +181,37 @@ package body Alr.Commands.Pin is Cmd.Requires_Full_Index; -- Next statement recomputes a solution - -- This is slated for removal in the immediate future; kept for - -- reference for the replacement implementation - - -- New_Sol := Alire.Pinning.Pin_To - -- (+Argument (1), - -- Cmd.URL.all, - -- Cmd.Root.Release.Dependencies, - -- Platform.Properties, - -- Old_Sol); + New_Root.Add_Path_Pin (Crate => Optional_Crate, + Path => Cmd.URL.all); end if; -- Report crate detection at target destination - User_Input.Report_Pinned_Crate_Detection (+Argument (1), - New_Sol); + User_Input.Report_Pinned_Crate_Detection (Optional_Crate.Element, + New_Root.Solution); else -- Change a single pin - Change_One_Pin (Cmd, New_Sol, Argument (1)); + Change_One_Pin (Cmd, New_Root, Argument (1)); end if; -- Consolidate changes - Confirm (Old_Sol, New_Sol); + New_Root.Confirm_And_Commit; end; exception - when Semver.Malformed_Input => + when E : Semver.Malformed_Input => + Alire.Log_Exception (E); Reportaise_Wrong_Arguments ("Improper version string"); + when E : TOML_Slicer.Slicing_Error => + Alire.Log_Exception (E); + Reportaise_Command_Failed + ("alr was unable to apply your request; " + & "please edit the manifest manually."); end Execute; ---------------------- diff --git a/src/alr/alr-commands-pin.ads b/src/alr/alr-commands-pin.ads index 6dffb875..ffb27997 100644 --- a/src/alr/alr-commands-pin.ads +++ b/src/alr/alr-commands-pin.ads @@ -26,10 +26,6 @@ package Alr.Commands.Pin is & " | crate --use= [--commit=REF]" & " | --all]"); - procedure Warn_Manual_Only; - -- For the time being, we do not allow creating pins via command line. - -- Warn the user that pins have to be added manually to the manifest. - private type Command is new Commands.Command with record diff --git a/src/alr/alr-commands-withing.adb b/src/alr/alr-commands-withing.adb index 8f48b2a8..2e6c925d 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -15,6 +15,8 @@ with Alr.Platform; with Semantic_Versioning.Extended; +with TOML_Slicer; + package body Alr.Commands.Withing is Switch_URL : constant String := "--use"; @@ -155,7 +157,7 @@ package body Alr.Commands.Withing is -- Add_With_Pin -- ------------------ - procedure Add_With_Pin (Cmd : Command; + procedure Add_With_Pin (Cmd : in out Command; Root : in out Alire.Roots.Editable.Root) is Crate : constant Alire.Optional.Crate_Name := @@ -173,7 +175,9 @@ package body Alr.Commands.Withing is Dep : constant Alire.Dependencies.Dependency := Alire.Dependencies.From_String (Argument (1)); begin - if Dep.Versions /= Semantic_Versioning.Extended.Any then + if Dep.Versions /= Semantic_Versioning.Extended.Any and then + not Cmd.Root.Solution.Depends_On (Dep.Crate) + then Root.Add_Dependency (Dep); end if; end; @@ -299,6 +303,12 @@ package body Alr.Commands.Withing is New_Root.Confirm_And_Commit; end; + exception + when E : TOML_Slicer.Slicing_Error => + Alire.Log_Exception (E); + Reportaise_Command_Failed + ("alr was unable to apply your request; " + & "please edit the manifest manually."); end Execute; ---------------------- diff --git a/testsuite/disabled/get/indirect-link/my_index/index/index.toml b/testsuite/tests/get/indirect-link/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/get/indirect-link/my_index/index/index.toml rename to testsuite/tests/get/indirect-link/my_index/index/index.toml diff --git a/testsuite/disabled/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml b/testsuite/tests/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml similarity index 100% rename from testsuite/disabled/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml rename to testsuite/tests/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml diff --git a/testsuite/disabled/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml b/testsuite/tests/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml similarity index 100% rename from testsuite/disabled/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml rename to testsuite/tests/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml diff --git a/testsuite/disabled/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml b/testsuite/tests/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml similarity index 100% rename from testsuite/disabled/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml rename to testsuite/tests/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml diff --git a/testsuite/disabled/get/indirect-link/test.py b/testsuite/tests/get/indirect-link/test.py similarity index 72% rename from testsuite/disabled/get/indirect-link/test.py rename to testsuite/tests/get/indirect-link/test.py index b1a61186..a35e5b1b 100644 --- a/testsuite/disabled/get/indirect-link/test.py +++ b/testsuite/tests/get/indirect-link/test.py @@ -22,17 +22,19 @@ run_alr('init', '--bin', 'xxx') os.chdir('xxx') # Depend on tier2, as a linked idr -run_alr('with', 'tier2', '--use', '/') # path is irrelevant +os.mkdir('tier2') +run_alr('with', 'tier2', '--use', 'tier2') # Add tier1 (this is where the bug manifests pre- fix) run_alr('with', 'tier1') # Verify the solution graph looks as expected p = run_alr('with', '--solve') -assert_match('.*Dependencies \(graph\):\n' - ' tier1=1\.0\.0 --> tier2\*.*' - ' xxx=0\.0\.0 --> tier1=1\.0\.0.*' - ' xxx=0\.0\.0 --> tier2\*.*', +assert_match('.*' + + re.escape('Dependencies (graph):\n' + ' tier1=1.0.0 --> tier2* \n' + ' xxx=0.0.0 --> tier1=1.0.0 (^1.0.0)\n' + ' xxx=0.0.0 --> tier2^1.0.0 ') + '.*', p.out, flags=re.S) diff --git a/testsuite/disabled/get/indirect-link/test.yaml b/testsuite/tests/get/indirect-link/test.yaml similarity index 100% rename from testsuite/disabled/get/indirect-link/test.yaml rename to testsuite/tests/get/indirect-link/test.yaml diff --git a/testsuite/disabled/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml b/testsuite/tests/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml similarity index 100% rename from testsuite/disabled/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml rename to testsuite/tests/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml diff --git a/testsuite/disabled/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml b/testsuite/tests/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml similarity index 100% rename from testsuite/disabled/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml rename to testsuite/tests/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml diff --git a/testsuite/disabled/pin/all/my_index/index/index.toml b/testsuite/tests/pin/all/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/pin/all/my_index/index/index.toml rename to testsuite/tests/pin/all/my_index/index/index.toml diff --git a/testsuite/disabled/pin/all/test.py b/testsuite/tests/pin/all/test.py similarity index 100% rename from testsuite/disabled/pin/all/test.py rename to testsuite/tests/pin/all/test.py diff --git a/testsuite/disabled/pin/all/test.yaml b/testsuite/tests/pin/all/test.yaml similarity index 100% rename from testsuite/disabled/pin/all/test.yaml rename to testsuite/tests/pin/all/test.yaml diff --git a/testsuite/disabled/pin/dir-mismatch/test.py b/testsuite/tests/pin/dir-mismatch/test.py similarity index 74% rename from testsuite/disabled/pin/dir-mismatch/test.py rename to testsuite/tests/pin/dir-mismatch/test.py index 5481a69f..78d9d580 100644 --- a/testsuite/disabled/pin/dir-mismatch/test.py +++ b/testsuite/tests/pin/dir-mismatch/test.py @@ -10,6 +10,9 @@ from drivers.asserts import assert_match from drivers.helpers import dir_separator from glob import glob +# Prepare an empty dir +os.mkdir("nothello") + # Retrieve a crate run_alr('get', 'hello=1') target = glob('hello*')[0] @@ -21,9 +24,14 @@ os.chdir('xxx') # Add a dependency as pinned dir without metadata; this should succeed run_alr('with', 'nothello', '--use', '..') -# Try to repin to a dir with valid crate metadata +# Detect a repin is rejected unless forced p = run_alr('with', 'nothello', '--use', '..' + dir_separator() + target, complain_on_error=False) +assert_match(".*nothello is already pinned to.*", p.out) + +# Try to repin to a dir with valid crate metadata +p = run_alr('with', 'nothello', '--use', '..' + dir_separator() + target, + complain_on_error=False, force=True) # Expected error assert_match('.*crate mismatch: expected nothello but found hello at.*', p.out) diff --git a/testsuite/disabled/pin/dir-mismatch/test.yaml b/testsuite/tests/pin/dir-mismatch/test.yaml similarity index 100% rename from testsuite/disabled/pin/dir-mismatch/test.yaml rename to testsuite/tests/pin/dir-mismatch/test.yaml diff --git a/testsuite/tests/pin/post-update/test.py b/testsuite/tests/pin/post-update/test.py index bfdb104b..898c9ee0 100644 --- a/testsuite/tests/pin/post-update/test.py +++ b/testsuite/tests/pin/post-update/test.py @@ -45,6 +45,9 @@ run_alr('with', 'libparent') # Remove child dependency run_alr('with', '--del', 'libchild') +# But keeping the pin (alr with --del will remove also the pin) +alr_pin('libchild', version="0.1") + # Verify pinned version is still in the solution, pre-update: p = run_alr('show', '--solve') check_child('0.1.0', p.out, pinned=True) diff --git a/testsuite/disabled/pin/remote/test.py b/testsuite/tests/pin/remote/test.py similarity index 82% rename from testsuite/disabled/pin/remote/test.py rename to testsuite/tests/pin/remote/test.py index 756a520b..f48d40ca 100644 --- a/testsuite/disabled/pin/remote/test.py +++ b/testsuite/tests/pin/remote/test.py @@ -6,20 +6,21 @@ import os import shutil from drivers.alr import run_alr, init_local_crate -from drivers.helpers import init_git_repo +from drivers.helpers import init_git_repo, git_branch from drivers.asserts import assert_eq -s = os.sep - -def verify(head): +def verify(head=""): # Either head or branch /= "" # Check that the linked dir exists at the expected location - pin_path = f"alire{s}cache{s}pins{s}upstream_0.0.0_{head[:8]}" + pin_path = (f"alire/cache/pins/upstream" + + ("" if head == "" else f"_{head[:8]}")) assert os.path.isdir(pin_path) # Verify info reported by alr p = run_alr("pin") - assert_eq(f"upstream file:{pin_path} ../upstream.git#{head}\n", p.out) + assert_eq(f"upstream file:{pin_path} ../upstream.git" + + ("" if head == "" else f"#{head[0:8]}") + "\n", + p.out) # Verify building with pinned dependency run_alr("build") @@ -53,7 +54,7 @@ verify(head) # Add using with, without head commit run_alr("with", "--use", "../upstream.git") -verify(head) +verify() # Pin afterwards, with commit run_alr("with", "upstream", force=True) # force, as it is unsolvable @@ -63,6 +64,6 @@ verify(head) # Pin afterwards, without commit run_alr("with", "upstream", force=True) run_alr("pin", "upstream", "--use", "../upstream.git") -verify(head) +verify() print('SUCCESS') diff --git a/testsuite/disabled/pin/remote/test.yaml b/testsuite/tests/pin/remote/test.yaml similarity index 100% rename from testsuite/disabled/pin/remote/test.yaml rename to testsuite/tests/pin/remote/test.yaml diff --git a/testsuite/tests/pin/unpin/test.py b/testsuite/tests/pin/unpin/test.py index ee8b1a15..3baa6b3e 100644 --- a/testsuite/tests/pin/unpin/test.py +++ b/testsuite/tests/pin/unpin/test.py @@ -27,6 +27,9 @@ p = run_alr('pin') assert_eq('libhello 1.0.0\n', p.out) # Delete lockfile and verify the pin has survived +os.remove('alire.lock') +p = run_alr('pin') +assert_eq('libhello 1.0.0\n', p.out) # Unpin and verify pin is not there alr_unpin('libhello') diff --git a/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/.emptydir b/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/.emptydir similarity index 100% rename from testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/.emptydir rename to testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/.emptydir diff --git a/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire.toml b/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire.toml similarity index 100% rename from testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire.toml rename to testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire.toml diff --git a/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir b/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir similarity index 100% rename from testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir rename to testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir diff --git a/testsuite/disabled/printenv/linked-paths/my_index/index/index.toml b/testsuite/tests/printenv/linked-paths/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/printenv/linked-paths/my_index/index/index.toml rename to testsuite/tests/printenv/linked-paths/my_index/index/index.toml diff --git a/testsuite/disabled/printenv/linked-paths/test.py b/testsuite/tests/printenv/linked-paths/test.py similarity index 90% rename from testsuite/disabled/printenv/linked-paths/test.py rename to testsuite/tests/printenv/linked-paths/test.py index 405004ef..9f9231fb 100644 --- a/testsuite/disabled/printenv/linked-paths/test.py +++ b/testsuite/tests/printenv/linked-paths/test.py @@ -15,11 +15,11 @@ from drivers.helpers import dir_separator, path_separator run_alr("init", "--bin", "xxx") os.chdir("xxx") -# Link a folder which also contains crate metadata +# Link a folder which also contains crate metadata for a project file inside a +# 'nested'-named folder run_alr("with", "--use=../my_index/crates/crate_1234") expected_gpr_path = [] -expected_gpr_path += [['.*', 'my_index', 'crates', 'crate_1234']] expected_gpr_path += [['.*', 'my_index', 'crates', 'crate_1234', 'nested']] expected_gpr_path += [['.*', 'xxx']] diff --git a/testsuite/disabled/printenv/linked-paths/test.yaml b/testsuite/tests/printenv/linked-paths/test.yaml similarity index 100% rename from testsuite/disabled/printenv/linked-paths/test.yaml rename to testsuite/tests/printenv/linked-paths/test.yaml diff --git a/testsuite/disabled/with/changes-info/test.py b/testsuite/tests/with/changes-info/test.py similarity index 100% rename from testsuite/disabled/with/changes-info/test.py rename to testsuite/tests/with/changes-info/test.py diff --git a/testsuite/disabled/with/changes-info/test.yaml b/testsuite/tests/with/changes-info/test.yaml similarity index 100% rename from testsuite/disabled/with/changes-info/test.yaml rename to testsuite/tests/with/changes-info/test.yaml diff --git a/testsuite/tests/with/dynamic-dependencies/test.py b/testsuite/tests/with/dynamic-dependencies/test.py index eb28005f..93213302 100644 --- a/testsuite/tests/with/dynamic-dependencies/test.py +++ b/testsuite/tests/with/dynamic-dependencies/test.py @@ -24,12 +24,12 @@ with open(manifest, 'a') as file: # Check adding a dependency run_alr('with', 'hello^1') -assert 'hello = "^1" # This line was added by `alr with`' \ +assert 'hello = "^1" # Added by alr' \ in content_of(manifest) # Check removal run_alr('with', '--del', 'hello') -assert 'hello = "^1" # This line was added by `alr with`' \ +assert 'hello = "^1" # Added by alr' \ not in content_of(manifest) # Check that the dependency that precedes the dynamic expression is removable diff --git a/testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr b/testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr similarity index 100% rename from testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr rename to testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr diff --git a/testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads b/testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads similarity index 100% rename from testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads rename to testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads diff --git a/testsuite/disabled/with/pin-dir/my_index/index/index.toml b/testsuite/tests/with/pin-dir/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/with/pin-dir/my_index/index/index.toml rename to testsuite/tests/with/pin-dir/my_index/index/index.toml diff --git a/testsuite/disabled/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml b/testsuite/tests/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/disabled/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml rename to testsuite/tests/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/disabled/with/pin-dir/test.py b/testsuite/tests/with/pin-dir/test.py similarity index 100% rename from testsuite/disabled/with/pin-dir/test.py rename to testsuite/tests/with/pin-dir/test.py diff --git a/testsuite/disabled/with/pin-dir/test.yaml b/testsuite/tests/with/pin-dir/test.yaml similarity index 100% rename from testsuite/disabled/with/pin-dir/test.yaml rename to testsuite/tests/with/pin-dir/test.yaml diff --git a/testsuite/disabled/with/pin-transitive/test.py b/testsuite/tests/with/pin-transitive/test.py similarity index 100% rename from testsuite/disabled/with/pin-transitive/test.py rename to testsuite/tests/with/pin-transitive/test.py diff --git a/testsuite/disabled/with/pin-transitive/test.yaml b/testsuite/tests/with/pin-transitive/test.yaml similarity index 100% rename from testsuite/disabled/with/pin-transitive/test.yaml rename to testsuite/tests/with/pin-transitive/test.yaml diff --git a/testsuite/tests/workflows/init-with-pin/test.py b/testsuite/tests/workflows/init-with-pin/test.py index d823f966..e7dfe5ea 100644 --- a/testsuite/tests/workflows/init-with-pin/test.py +++ b/testsuite/tests/workflows/init-with-pin/test.py @@ -17,7 +17,7 @@ os.chdir('xxx') session_file = os.path.join('alire.toml') run_alr('with', 'libhello') check_line_in(session_file, - 'libhello = "^1.0.0" # This line was added by `alr with`') + 'libhello = "^1.0.0" # Added by alr') # Add the corresponding "with" line in xxx.gpr. # -- 2.39.5