From 3c074503850c654876d9b2fc1c7347abfceec1cb Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 12 May 2021 19:19:41 +0200 Subject: [PATCH 01/25] Added data structures --- .../alire-externals-softlinks-holders.ads | 4 ++ src/alire/alire-milestones-holders.ads | 4 ++ src/alire/alire-roots.adb | 1 + src/alire/alire-roots.ads | 2 + src/alire/alire-user_pins.adb | 10 +++++ src/alire/alire-user_pins.ads | 39 +++++++++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 src/alire/alire-externals-softlinks-holders.ads create mode 100644 src/alire/alire-milestones-holders.ads create mode 100644 src/alire/alire-user_pins.adb create mode 100644 src/alire/alire-user_pins.ads diff --git a/src/alire/alire-externals-softlinks-holders.ads b/src/alire/alire-externals-softlinks-holders.ads new file mode 100644 index 000000000..adb75baab --- /dev/null +++ b/src/alire/alire-externals-softlinks-holders.ads @@ -0,0 +1,4 @@ +with Ada.Containers.Indefinite_Holders; + +package Alire.Externals.Softlinks.Holders is + new Ada.Containers.Indefinite_Holders (Softlinks.External); diff --git a/src/alire/alire-milestones-holders.ads b/src/alire/alire-milestones-holders.ads new file mode 100644 index 000000000..331f11b33 --- /dev/null +++ b/src/alire/alire-milestones-holders.ads @@ -0,0 +1,4 @@ +with Ada.Containers.Indefinite_Holders; + +package Alire.Milestones.Holders is + new Ada.Containers.Indefinite_Holders (Milestone); diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 34b3ca515..d949a5080 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -430,6 +430,7 @@ package body Alire.Roots is Env : Properties.Vector) return Root is (Environment => Env, Path => +Path, + Pins => <>, -- No pins in a fresh root Release => Containers.To_Release_H (R), Cached_Solution => <>); diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index bdc43ef61..6a0db51ec 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -9,6 +9,7 @@ with Alire.Properties; with Alire.Releases; with Alire.Solutions; with Alire.Solver; +with Alire.User_Pins; with Alire.Utils.User_Input; package Alire.Roots is @@ -225,6 +226,7 @@ private type Root is tagged record Environment : Properties.Vector; Path : UString; + Pins : User_Pins.Map; Release : Containers.Release_H; Cached_Solution : Cached_Solutions.Cache; end record; diff --git a/src/alire/alire-user_pins.adb b/src/alire/alire-user_pins.adb new file mode 100644 index 000000000..e5903e624 --- /dev/null +++ b/src/alire/alire-user_pins.adb @@ -0,0 +1,10 @@ +package body Alire.User_Pins is + + --------------- + -- From_TOML -- + --------------- + + function From_TOML (This : TOML_Adapters.Key_Queue) return Pin + is (raise Unimplemented); + +end Alire.User_Pins; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads new file mode 100644 index 000000000..f33bafb9f --- /dev/null +++ b/src/alire/alire-user_pins.ads @@ -0,0 +1,39 @@ +with Ada.Containers.Indefinite_Ordered_Maps; + +with Alire.Externals.Softlinks.Holders; +with Alire.Milestones.Holders; +with Alire.TOML_Adapters; + +package Alire.User_Pins is + + -- User-facing representation of pins. These are loaded from the manifest. + -- Internally, a user pin can be either a pin to a version, or a softlink + -- to a folder. Note that, as they cannot exist in the index (we would not + -- want an indexed crate to depend on unknown folders/remotes), there is no + -- need to generate TOML for them. + + type Kinds is (To_External, To_Version); + + type Pin (Kind : Kinds) is tagged record + case Kind is + when To_External => + Softlink : Externals.Softlinks.Holders.Holder; + when To_Version => + Version : Milestones.Holders.Holder; + end case; + end record; + + function From_TOML (This : TOML_Adapters.Key_Queue) return Pin; + + -- The TOML representation of a pin is similar to a dependency, but instead + -- of a version set, we get either a precise version, or an url + commit: + -- [[pins]] + -- foo = "5.6" + -- bar = { url = "git+https://blah", commit = } + + package Maps is + new Ada.Containers.Indefinite_Ordered_Maps (Crate_Name, Pin); + + subtype Map is Maps.Map; + +end Alire.User_Pins; From 05a7614de6399a9d56be3c3fd2acf540d1dc6aa1 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 13 May 2021 16:58:07 +0200 Subject: [PATCH 02/25] Pins may appear in manifest, being ignored --- alire.toml | 3 ++ config/alr_config.ads | 4 ++ config/alr_config.gpr | 14 ++++++ config/alr_config.h | 5 ++ src/alire/alire-crates.adb | 10 ++++ src/alire/alire-externals.adb | 12 ++++- src/alire/alire-releases.adb | 5 ++ src/alire/alire-releases.ads | 2 + src/alire/alire-roots.adb | 1 - src/alire/alire-roots.ads | 2 - src/alire/alire-toml_adapters.ads | 14 ++++++ src/alire/alire-toml_load.adb | 8 ++++ src/alire/alire-toml_load.ads | 2 + src/alire/alire-user_pins-maps.adb | 13 ++++++ src/alire/alire-user_pins-maps.ads | 12 +++++ src/alire/alire-user_pins.adb | 74 +++++++++++++++++++++++++++++- src/alire/alire-user_pins.ads | 41 ++++++++++------- 17 files changed, 199 insertions(+), 23 deletions(-) create mode 100644 config/alr_config.ads create mode 100644 config/alr_config.gpr create mode 100644 config/alr_config.h create mode 100644 src/alire/alire-user_pins-maps.adb create mode 100644 src/alire/alire-user_pins-maps.ads diff --git a/alire.toml b/alire.toml index 2c4bdfbf6..8cb3af2ea 100644 --- a/alire.toml +++ b/alire.toml @@ -29,3 +29,6 @@ spdx = "~0.2" # Building alr requires the explicit setting of this variable [gpr-set-externals."case(os)"] macos = { OS = "macOS" } + +# Most dependencies require precise versions during the development cycle +[[pins]] diff --git a/config/alr_config.ads b/config/alr_config.ads new file mode 100644 index 000000000..db126edbf --- /dev/null +++ b/config/alr_config.ads @@ -0,0 +1,4 @@ +-- Configuration for alr generated by Alire +package alr_Config is + +end alr_Config; diff --git a/config/alr_config.gpr b/config/alr_config.gpr new file mode 100644 index 000000000..e6b64c4da --- /dev/null +++ b/config/alr_config.gpr @@ -0,0 +1,14 @@ +-- Configuration for alr generated by Alire +with "aaa.gpr"; +with "ada_toml.gpr"; +with "ajunitgen.gpr"; +with "ansi.gpr"; +with "gnatcoll.gpr"; +with "minirest.gpr"; +with "semantic_versioning.gpr"; +with "simple_logging.gpr"; +with "spdx.gpr"; +with "uri.gpr"; +abstract project alr_Config is + +end alr_Config; diff --git a/config/alr_config.h b/config/alr_config.h new file mode 100644 index 000000000..5f67d9ae9 --- /dev/null +++ b/config/alr_config.h @@ -0,0 +1,5 @@ +/* Configuration for alr generated by Alire */ +#ifndef ALR_CONFIG_H +#define ALR_CONFIG_H + +#endif diff --git a/src/alire/alire-crates.adb b/src/alire/alire-crates.adb index 81a0e2dd1..dae448d53 100644 --- a/src/alire/alire-crates.adb +++ b/src/alire/alire-crates.adb @@ -2,6 +2,7 @@ with Alire.Origins; with Alire.Properties.Labeled; with Alire.TOML_Keys; with Alire.TOML_Load; +with Alire.User_Pins.Maps; with Alire.Utils.TTY; with TOML; @@ -144,6 +145,7 @@ package body Alire.Crates is declare Unused_Avail : Conditional.Availability; Unused_Deps : Conditional.Dependencies; + Unused_Pins : User_Pins.Maps.Map; Properties : Conditional.Properties; begin TOML_Load.Load_Crate_Section @@ -152,8 +154,16 @@ package body Alire.Crates is From => From, Props => Properties, Deps => Unused_Deps, + Pins => Unused_Pins, Avail => Unused_Avail); + Assert (Unused_Deps.Is_Empty, + "Unexpected dependencies in external definition"); + Assert (Unused_Pins.Is_Empty, + "Unexpected pins in external definition"); + Assert (Unused_Avail.Is_Empty, + "Unexpected availability in external definition"); + case Policy is when Policies.Merge_Priorizing_Existing => if This.Externals.Properties.Is_Empty then diff --git a/src/alire/alire-externals.adb b/src/alire/alire-externals.adb index 6ea3746d8..10d0309a4 100644 --- a/src/alire/alire-externals.adb +++ b/src/alire/alire-externals.adb @@ -7,6 +7,7 @@ with Alire.Externals.Softlinks; with Alire.Externals.Unindexed; with Alire.TOML_Keys; with Alire.TOML_Load; +with Alire.User_Pins.Maps; with TOML; @@ -61,7 +62,8 @@ package body Alire.Externals is end if; end Validate; - Deps : Conditional.Dependencies; + Unused_Deps : Conditional.Dependencies; + Unused_Pins : User_Pins.Maps.Map; begin @@ -82,9 +84,15 @@ package body Alire.Externals is Section => Crates.External_Private_Section, From => From, Props => Ext.Properties, - Deps => Deps, + Deps => Unused_Deps, + Pins => Unused_Pins, Avail => Ext.Available); + Assert (Unused_Deps.Is_Empty, + "Unexpected dependencies in external definition"); + Assert (Unused_Pins.Is_Empty, + "Unexpected pins in external definition"); + From.Report_Extra_Keys; -- Table must be exhausted at this point end return; diff --git a/src/alire/alire-releases.adb b/src/alire/alire-releases.adb index ca9cf654a..22faf8ac0 100644 --- a/src/alire/alire-releases.adb +++ b/src/alire/alire-releases.adb @@ -234,6 +234,7 @@ package body Alire.Releases is Version => Base.Version, Origin => Base.Origin, Dependencies => Base.Dependencies, + Pins => Base.Pins, Forbidden => Base.Forbidden, Properties => Base.Properties, Available => Base.Available) @@ -288,6 +289,7 @@ package body Alire.Releases is Origin => Origin, Notes => Notes, Dependencies => Dependencies, + Pins => <>, Forbidden => Conditional.For_Dependencies.Empty, Properties => Properties, Available => Available); @@ -320,6 +322,7 @@ package body Alire.Releases is Origin => Origin, Notes => "", Dependencies => Dependencies, + Pins => <>, Forbidden => Conditional.For_Dependencies.Empty, Properties => Properties, Available => Conditional.Empty @@ -728,6 +731,7 @@ package body Alire.Releases is From => From, Props => This.Properties, Deps => This.Dependencies, + Pins => This.Pins, Avail => This.Available); -- Consolidate/validate some properties as fields: @@ -907,6 +911,7 @@ package body Alire.Releases is Origin => R.Origin, Notes => R.Notes, Dependencies => R.Dependencies.Evaluate (P), + Pins => R.Pins, Forbidden => R.Forbidden.Evaluate (P), Properties => R.Properties.Evaluate (P), Available => R.Available.Evaluate (P)); diff --git a/src/alire/alire-releases.ads b/src/alire/alire-releases.ads index 5ce47359f..5ed325e1d 100644 --- a/src/alire/alire-releases.ads +++ b/src/alire/alire-releases.ads @@ -13,6 +13,7 @@ with Alire.Properties.Labeled; with Alire.Properties.Licenses; with Alire.TOML_Adapters; with Alire.TOML_Keys; +with Alire.User_Pins.Maps; with Alire.Utils; with Semantic_Versioning; @@ -336,6 +337,7 @@ private Origin : Origins.Origin; Notes : Description_String (1 .. Notes_Len); Dependencies : Conditional.Dependencies; + Pins : User_Pins.Maps.Map; Forbidden : Conditional.Dependencies; Properties : Conditional.Properties; Available : Conditional.Availability; diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index d949a5080..34b3ca515 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -430,7 +430,6 @@ package body Alire.Roots is Env : Properties.Vector) return Root is (Environment => Env, Path => +Path, - Pins => <>, -- No pins in a fresh root Release => Containers.To_Release_H (R), Cached_Solution => <>); diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 6a0db51ec..bdc43ef61 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -9,7 +9,6 @@ with Alire.Properties; with Alire.Releases; with Alire.Solutions; with Alire.Solver; -with Alire.User_Pins; with Alire.Utils.User_Input; package Alire.Roots is @@ -226,7 +225,6 @@ private type Root is tagged record Environment : Properties.Vector; Path : UString; - Pins : User_Pins.Map; Release : Containers.Release_H; Cached_Solution : Cached_Solutions.Cache; end record; diff --git a/src/alire/alire-toml_adapters.ads b/src/alire/alire-toml_adapters.ads index ddd97c739..5446d7bcc 100644 --- a/src/alire/alire-toml_adapters.ads +++ b/src/alire/alire-toml_adapters.ads @@ -64,6 +64,9 @@ package Alire.TOML_Adapters with Preelaborate is -- Return the requested Key value, checking it matches type Kind. If type -- mismatch or missing key raise a Checked_Error. + function Contains (Queue : Key_Queue; Key : String) return Boolean; + -- Says if one of the keys in the wrapped table is Key + function Pop (Queue : Key_Queue) return TOML.TOML_Value; -- Return a value discarding its key; if no values left No_TOML_Value is -- returned. @@ -158,6 +161,8 @@ package Alire.TOML_Adapters with Preelaborate is private + use type UString; -- Allows comparisons between strings and unbounded + type Key_Queue is new Ada.Finalization.Limited_Controlled with record Value : TOML.TOML_Value; end record; @@ -165,6 +170,15 @@ private overriding procedure Finalize (This : in out Key_Queue); + -------------- + -- Contains -- + -------------- + + function Contains (Queue : Key_Queue; Key : String) return Boolean + is (Queue.Unwrap.Kind in TOML.TOML_Table + and then + (for some Table_Key of Queue.Unwrap.Keys => Key = Table_Key)); + ------------ -- Unwrap -- ------------ diff --git a/src/alire/alire-toml_load.adb b/src/alire/alire-toml_load.adb index 59ffa23cf..38e937f98 100644 --- a/src/alire/alire-toml_load.adb +++ b/src/alire/alire-toml_load.adb @@ -73,8 +73,10 @@ package body Alire.TOML_Load is From : TOML_Adapters.Key_Queue; Props : in out Conditional.Properties; Deps : in out Conditional.Dependencies; + Pins : in out User_Pins.Maps.Map; Avail : in out Conditional.Availability) is + pragma Unreferenced (Pins); use TOML; use type Conditional.Dependencies; use type Conditional.Properties; @@ -124,6 +126,12 @@ package body Alire.TOML_Load is & TOML_Keys.Depends_On); end if; + -- Process user pins + + if From.Contains ("pins") then + From.Unwrap.Unset ("pins"); + end if; + -- TODO: Process Forbidden -- Process Available diff --git a/src/alire/alire-toml_load.ads b/src/alire/alire-toml_load.ads index 775580bb8..1073d95ce 100644 --- a/src/alire/alire-toml_load.ads +++ b/src/alire/alire-toml_load.ads @@ -1,6 +1,7 @@ with Alire.Conditional; with Alire.Crates; with Alire.TOML_Adapters; +with Alire.User_Pins.Maps; with TOML; @@ -21,6 +22,7 @@ package Alire.TOML_Load is From : TOML_Adapters.Key_Queue; Props : in out Conditional.Properties; Deps : in out Conditional.Dependencies; + Pins : in out User_Pins.Maps.Map; Avail : in out Conditional.Availability); -- Loads parts of a manifest, taking into account if we are loading -- a indexed release, a local release, a external shared section or diff --git a/src/alire/alire-user_pins-maps.adb b/src/alire/alire-user_pins-maps.adb new file mode 100644 index 000000000..e86cf71e1 --- /dev/null +++ b/src/alire/alire-user_pins-maps.adb @@ -0,0 +1,13 @@ +package body Alire.User_Pins.Maps is + + --------------- + -- From_TOML -- + --------------- + + function From_TOML (This : TOML_Adapters.Key_Queue) return Map is + begin + raise Unimplemented; + return From_TOML (This); + end From_TOML; + +end Alire.User_Pins.Maps; diff --git a/src/alire/alire-user_pins-maps.ads b/src/alire/alire-user_pins-maps.ads new file mode 100644 index 000000000..b2ac630c0 --- /dev/null +++ b/src/alire/alire-user_pins-maps.ads @@ -0,0 +1,12 @@ +with Ada.Containers.Indefinite_Ordered_Maps; + +package Alire.User_Pins.Maps is + + package Pin_Maps is + new Ada.Containers.Indefinite_Ordered_Maps (Crate_Name, Pin); + + type Map is new Pin_Maps.Map with null record; + + function From_TOML (This : TOML_Adapters.Key_Queue) return Map; + +end Alire.User_Pins.Maps; diff --git a/src/alire/alire-user_pins.adb b/src/alire/alire-user_pins.adb index e5903e624..3cc1e4ca9 100644 --- a/src/alire/alire-user_pins.adb +++ b/src/alire/alire-user_pins.adb @@ -1,10 +1,80 @@ +with Alire.Origins; + +with TOML; + package body Alire.User_Pins is + package Keys is + Commit : constant String := "commit"; + Path : constant String := "path"; + URL : constant String := "url"; + end Keys; + --------------- -- From_TOML -- --------------- - function From_TOML (This : TOML_Adapters.Key_Queue) return Pin - is (raise Unimplemented); + function From_TOML (This : TOML_Adapters.Key_Queue) return Pin is + + ---------------- + -- From_Table -- + ---------------- + + function From_Table (This : TOML_Adapters.Key_Queue) return Pin is + use TOML; + begin + if This.Contains (Keys.Path) then + return Result : constant Pin := + (Kind => To_Path, + Path => +This.Checked_Pop (Keys.Path, TOML_String).As_String) + do + if not GNAT.OS_Lib.Is_Directory (+Result.Path) then + Raise_Checked_Error ("Pin path is not a valid directory: " + & (+Result.Path)); + end if; + This.Report_Extra_Keys; + end return; + + elsif This.Contains (Keys.URL) then + return Result : Pin := + (Kind => To_Git, + URL => +This.Checked_Pop (Keys.URL, TOML_String).As_String, + Commit => <>) + do + if This.Contains (Keys.Commit) then + Result.Commit := + +This.Checked_Pop (Keys.Commit, TOML_String).As_String; + This.Assert (+Result.Commit in Origins.Git_Commit, + "invalid commit: " & (+Result.Commit)); + end if; + + This.Report_Extra_Keys; + end return; + + else + Trace.Error ("Expecting a path or url pin, but got:"); + This.Print; + Raise_Checked_Error ("invalid pin description"); + end if; + end From_Table; + + begin + case This.Unwrap.Kind is + when TOML.TOML_String => + return Pin' + (Kind => To_Version, + Version => Semantic_Versioning.Parse (This.Unwrap.As_String)); + + when TOML.TOML_Table => + return From_Table (This); + + when others => + Raise_Checked_Error + ("improper format for pin, string or table expected but got a " + & This.Unwrap.Kind'Image); + + end case; + + end From_TOML; end Alire.User_Pins; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index f33bafb9f..6fcae44b3 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -1,9 +1,7 @@ -with Ada.Containers.Indefinite_Ordered_Maps; - -with Alire.Externals.Softlinks.Holders; -with Alire.Milestones.Holders; with Alire.TOML_Adapters; +with Semantic_Versioning; + package Alire.User_Pins is -- User-facing representation of pins. These are loaded from the manifest. @@ -12,18 +10,20 @@ package Alire.User_Pins is -- want an indexed crate to depend on unknown folders/remotes), there is no -- need to generate TOML for them. - type Kinds is (To_External, To_Version); + -- The information stored for user pins is still incomplete. The root + -- must check if the pin was already retrieved, and if it matches the + -- user description, or else fetch it, when a change in the manifest + -- is detected. - type Pin (Kind : Kinds) is tagged record - case Kind is - when To_External => - Softlink : Externals.Softlinks.Holders.Holder; - when To_Version => - Version : Milestones.Holders.Holder; - end case; - end record; + type Kinds is (To_Git, + To_Path, + To_Version); + + type Pin (Kind : Kinds) is tagged private; function From_TOML (This : TOML_Adapters.Key_Queue) return Pin; + -- Expects the rhs of a crate = entry. This can be a string (for a + -- version) or a table (for an origin). -- The TOML representation of a pin is similar to a dependency, but instead -- of a version set, we get either a precise version, or an url + commit: @@ -31,9 +31,18 @@ package Alire.User_Pins is -- foo = "5.6" -- bar = { url = "git+https://blah", commit = } - package Maps is - new Ada.Containers.Indefinite_Ordered_Maps (Crate_Name, Pin); +private - subtype Map is Maps.Map; + type Pin (Kind : Kinds) is tagged record + case Kind is + when To_Git => + URL : UString; + Commit : UString; -- Optional + when To_Path => + Path : UString; + when To_Version => + Version : Semantic_Versioning.Version; + end case; + end record; end Alire.User_Pins; From b58d2fac8d695da7cb83b528d03e5ef181413cc7 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 19 May 2021 13:04:46 +0200 Subject: [PATCH 03/25] Loading of user pins complete --- .gitmodules | 3 + alire.gpr | 1 + alire.lock | 14 +++++ alire.toml | 2 + alr_env.gpr | 1 + config/alr_config.gpr | 2 +- deps/optional | 1 + src/alire/alire-dependencies-containers.ads | 6 ++ src/alire/alire-optional.ads | 12 ++++ src/alire/alire-releases.adb | 20 +++++++ src/alire/alire-releases.ads | 13 +++++ src/alire/alire-roots.adb | 61 ++++++++++++++++++--- src/alire/alire-roots.ads | 16 ++++-- src/alire/alire-toml_keys.ads | 1 + src/alire/alire-toml_load.adb | 7 ++- src/alire/alire-user_pins-maps.adb | 33 ++++++++++- src/alire/alire-user_pins-maps.ads | 9 ++- src/alire/alire-user_pins.ads | 34 ++++++++++++ src/alr/alr-commands.adb | 2 +- 19 files changed, 217 insertions(+), 21 deletions(-) create mode 160000 deps/optional create mode 100644 src/alire/alire-optional.ads diff --git a/.gitmodules b/.gitmodules index d5d0af066..df753f7fa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,3 +36,6 @@ path = deps/spdx url = https://github.com/Fabien-Chouteau/spdx_ada branch = 319ca7bcc1e2eb1843aad1f64aca3ecba91a2bcc +[submodule "deps/optional"] + path = deps/optional + url = https://github.com/mosteo/optional diff --git a/alire.gpr b/alire.gpr index 7cb5bd142..91785fd53 100644 --- a/alire.gpr +++ b/alire.gpr @@ -5,6 +5,7 @@ with "ajunitgen"; with "ansi"; with "gnatcoll"; with "minirest"; +with "optional"; with "semantic_versioning"; with "simple_logging"; with "uri"; diff --git a/alire.lock b/alire.lock index 2c84f1a65..b16510374 100644 --- a/alire.lock +++ b/alire.lock @@ -107,6 +107,20 @@ remote = true commit = "4550aa356d55b9cd55f26acd34701f646021c5ff" url = "git+https://github.com/mosteo/minirest.git" [[solution.state]] +crate = "optional" +fulfilment = "linked" +pinned = false +transitivity = "direct" +versions = "*" +[solution.state.link] +kind = "softlink" +path = "file:alire/cache/pins/optional_0.0.0_f3b855d2" +relative = true +remote = true +[solution.state.link.origin] +commit = "f3b855d21c78e6644d1bbb02a8606869ead66cac" +url = "git+https://github.com/mosteo/optional/" +[[solution.state]] crate = "semantic_versioning" fulfilment = "linked" pinned = false diff --git a/alire.toml b/alire.toml index 8cb3af2ea..e78dcafc9 100644 --- a/alire.toml +++ b/alire.toml @@ -21,6 +21,7 @@ ajunitgen = "^1.0.1" ansiada = "~0.1" gnatcoll = "^21" minirest = "~0.2" +optional = "~0.0.0" semantic_versioning = "^2" simple_logging = "^1.2" uri_ada = "^1" @@ -32,3 +33,4 @@ macos = { OS = "macOS" } # Most dependencies require precise versions during the development cycle [[pins]] +aaa = { url = "https://github.com/mosteo/aaa.git", commit = "4b4aa047f29a4270c5b5003468617e153977ab97" } diff --git a/alr_env.gpr b/alr_env.gpr index 16c7f08b6..64b70b390 100644 --- a/alr_env.gpr +++ b/alr_env.gpr @@ -9,6 +9,7 @@ aggregate project Alr_Env is "deps/ansi", "deps/gnatcoll-slim", "deps/minirest", + "deps/optional", "deps/semantic_versioning", "deps/simple_logging", "deps/uri-ada", diff --git a/config/alr_config.gpr b/config/alr_config.gpr index e6b64c4da..802354b4a 100644 --- a/config/alr_config.gpr +++ b/config/alr_config.gpr @@ -1,10 +1,10 @@ -- Configuration for alr generated by Alire with "aaa.gpr"; -with "ada_toml.gpr"; with "ajunitgen.gpr"; with "ansi.gpr"; with "gnatcoll.gpr"; with "minirest.gpr"; +with "optional.gpr"; with "semantic_versioning.gpr"; with "simple_logging.gpr"; with "spdx.gpr"; diff --git a/deps/optional b/deps/optional new file mode 160000 index 000000000..02aa24754 --- /dev/null +++ b/deps/optional @@ -0,0 +1 @@ +Subproject commit 02aa247540da8565ab0529905e68e963dd1cec13 diff --git a/src/alire/alire-dependencies-containers.ads b/src/alire/alire-dependencies-containers.ads index cde3f0992..52b8ce992 100644 --- a/src/alire/alire-dependencies-containers.ads +++ b/src/alire/alire-dependencies-containers.ads @@ -1,6 +1,8 @@ with Ada.Containers.Indefinite_Doubly_Linked_Lists; with Ada.Containers.Indefinite_Ordered_Sets; +with Optional.Values; + package Alire.Dependencies.Containers with Preelaborate is package Lists is new @@ -8,6 +10,10 @@ package Alire.Dependencies.Containers with Preelaborate is type List is new Lists.List with null record; + package Optionals is new Optional.Values (Dependency, Image); + + subtype Optional is Optionals.Optional; + package Sets is new Ada.Containers.Indefinite_Ordered_Sets (Dependency, Lexicographical_Sort); diff --git a/src/alire/alire-optional.ads b/src/alire/alire-optional.ads new file mode 100644 index 000000000..9120113e5 --- /dev/null +++ b/src/alire/alire-optional.ads @@ -0,0 +1,12 @@ +with Optional.Values; + +package Alire.Optional with Preelaborate is + + -- Optional basic types + + function String_Image (Str : Standard.String) + return Standard.String is (Str); + package Strings is new Standard.Optional.Values (String, String_Image); + subtype String is Strings.Optional; + +end Alire.Optional; diff --git a/src/alire/alire-releases.adb b/src/alire/alire-releases.adb index 22faf8ac0..ce2f48180 100644 --- a/src/alire/alire-releases.adb +++ b/src/alire/alire-releases.adb @@ -91,6 +91,26 @@ package body Alire.Releases is return False; end Check_Caret_Warning; + ------------------- + -- Dependency_On -- + ------------------- + + function Dependency_On (R : Release; + Crate : Crate_Name; + P : Alire.Properties.Vector := + Alire.Properties.No_Properties) + return Alire.Dependencies.Containers.Optional + is + begin + for Dep of R.Flat_Dependencies (P) loop + if Dep.Crate = Crate then + return Alire.Dependencies.Containers.Optionals.Unit (Dep); + end if; + end loop; + + return Alire.Dependencies.Containers.Optionals.Empty; + end Dependency_On; + ------------ -- Deploy -- ------------ diff --git a/src/alire/alire-releases.ads b/src/alire/alire-releases.ads index 5ed325e1d..5a4bd299c 100644 --- a/src/alire/alire-releases.ads +++ b/src/alire/alire-releases.ads @@ -145,6 +145,14 @@ package Alire.Releases is return Conditional.Dependencies; -- Retrieve only the dependencies that apply on platform P + function Dependency_On (R : Release; + Crate : Crate_Name; + P : Alire.Properties.Vector := + Alire.Properties.No_Properties) + return Alire.Dependencies.Containers.Optional; + -- If R.Flat_Dependencies contains Crate, that dependency will be returned, + -- Empty otherwise. + function Flat_Dependencies (R : Release; P : Alire.Properties.Vector := Alire.Properties.No_Properties) @@ -186,6 +194,8 @@ package Alire.Releases is -- Only explicitly declared ones -- Under some conditions (usually current platform) + function Pins (R : Release) return User_Pins.Maps.Map; + function Project_Paths (R : Release; P : Alire.Properties.Vector) return Utils.String_Set; @@ -475,4 +485,7 @@ private function Version_Image (R : Release) return String is (Semantic_Versioning.Image (R.Version)); + function Pins (R : Release) return User_Pins.Maps.Map + is (R.Pins); + end Alire.Releases; diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 34b3ca515..e7f743589 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -10,6 +10,7 @@ with Alire.Origins.Deployers; with Alire.OS_Lib; with Alire.Roots.Optional; with Alire.Solutions.Diffs; +with Alire.User_Pins.Maps; with Alire.Utils.TTY; with Alire.VCSs.Git; @@ -288,6 +289,46 @@ package body Alire.Roots is end Deploy_Dependencies; + ----------------- + -- Deploy_Pins -- + ----------------- + + procedure Deploy_Pins (This : in out Root) is + use User_Pins.Maps.Pin_Maps; + Rel : constant Alire.Releases.Release := Release (This); + Pins : constant User_Pins.Maps.Map := Rel.Pins; + begin + if (for some Pin of Pins => Pin.Is_Remote) then + Put_Info ("Checking pins..."); + end if; + + for I in Pins.Iterate loop + if Pins (I).Is_Remote then + + Put_Info ("Deploying pin for crate: " & TTY.Name (Key (I))); + + declare + Crate : constant Crate_Name := Key (I); + Pin : constant User_Pins.Pin := Element (I); + Result : constant Remote_Pin_Result := + This.Pinned_To_Remote + (Dependency => + Conditional.New_Dependency + (Rel.Dependency_On (Crate) + .Or_Else (Dependencies.From_String + ((+Crate) & "*"))), + URL => Pin.URL, + Commit => Pin.Commit.Or_Else (""), + Must_Depend => True); + begin + -- Pin deployed, solution can be stored accordingly + + This.Set (Solution => Result.Solution); + end; + end if; + end loop; + end Deploy_Pins; + --------------- -- Is_Stored -- --------------- @@ -559,14 +600,17 @@ package body Alire.Roots is File_Time_Stamp (This.Crate_File) > File_Time_Stamp (This.Lock_File); end Is_Lockfile_Outdated; - ---------------------------- - -- Sync_Solution_And_Deps -- - ---------------------------- + ------------------------ + -- Sync_From_Manifest -- + ------------------------ - procedure Sync_Solution_And_Deps (This : in out Root) is + procedure Sync_From_Manifest (This : in out Root) is begin if This.Is_Lockfile_Outdated then - Trace.Info ("Detected changes in manifest, updating workspace..."); + Put_Info ("Detected changes in manifest, synchronizing workspace..."); + + This.Deploy_Pins; + This.Update_And_Deploy_Dependencies (Confirm => False); -- Don't ask for confirmation as this is an automatic update in -- reaction to a manually edited manifest, and we need the lockfile @@ -580,8 +624,9 @@ package body Alire.Roots is -- to manually mark the lockfile as older. Trace.Info (""); -- Separate changes from what caused the sync + end if; - elsif (for some Rel of This.Solution.Releases => + if (for some Rel of This.Solution.Releases => This.Solution.State (Rel.Name).Is_Solved and then not GNAT.OS_Lib.Is_Directory (This.Release_Base (Rel.Name))) or else @@ -594,7 +639,7 @@ package body Alire.Roots is This.Deploy_Dependencies; end if; - end Sync_Solution_And_Deps; + end Sync_From_Manifest; ------------------------------------------- -- Sync_Manifest_And_Lockfile_Timestamps -- @@ -748,7 +793,7 @@ package body Alire.Roots is Dep.Crate.As_String = Requested_Crate) then Raise_Checked_Error - ("Cannot continue because the requested crate is not a dependency: " + ("Cannot continue because the requested pin is not a dependency: " & Requested_Crate); end if; diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index bdc43ef61..4e5ef02b3 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -122,12 +122,13 @@ package Alire.Roots is -- conceivably we could use checksums to make it more robust against -- automated changes within the same second. - procedure Sync_Solution_And_Deps (This : in out Root); - -- Ensure that dependencies are up to date in regard to the lockfile and - -- manifest: if the manifest is newer than the lockfile, resolve again, - -- as dependencies may have been edited by hand. Otherwise, ensure that - -- releases in the lockfile are actually on disk (may be missing if cache - -- was deleted, or the crate was just cloned). + procedure Sync_From_Manifest (This : in out Root); + -- 1) Pre-deploy any remote pins in the manifest so they are usable when + -- solving. 2) Ensure that dependencies are up to date in regard to the + -- lockfile and manifest: if the manifest is newer than the lockfile, + -- resolve again, as dependencies may have been edited by hand. 3) Ensure + -- that releases in the lockfile are actually on disk (may be missing if + -- cache was deleted, or the crate was just cloned). procedure Sync_Manifest_And_Lockfile_Timestamps (This : Root) with Post => not This.Is_Lockfile_Outdated; @@ -165,6 +166,9 @@ package Alire.Roots is Confirm : Boolean := not Utils.User_Input.Not_Interactive); -- Call Update and Deploy_Dependencies in succession for the given root + procedure Deploy_Pins (This : in out Root); + -- Download any remote pins in the manifest + procedure Write_Manifest (This : Root); -- Generates the crate.toml manifest at the appropriate location for Root diff --git a/src/alire/alire-toml_keys.ads b/src/alire/alire-toml_keys.ads index 21cd47079..92d90108f 100644 --- a/src/alire/alire-toml_keys.ads +++ b/src/alire/alire-toml_keys.ads @@ -36,6 +36,7 @@ package Alire.TOML_Keys with Preelaborate is OS : constant String := "os"; Path : constant String := "path"; Pinned : constant String := "pinned"; + Pins : constant String := "pins"; Project_File : constant String := "project-files"; Provides : constant String := "provides"; Tag : constant String := "tags"; diff --git a/src/alire/alire-toml_load.adb b/src/alire/alire-toml_load.adb index 38e937f98..53d6561b5 100644 --- a/src/alire/alire-toml_load.adb +++ b/src/alire/alire-toml_load.adb @@ -128,8 +128,11 @@ package body Alire.TOML_Load is -- Process user pins - if From.Contains ("pins") then - From.Unwrap.Unset ("pins"); + if From.Contains (TOML_Keys.Pins) then + Pins := User_Pins.Maps.From_TOML + (From.Descend + (From.Checked_Pop (TOML_Keys.Pins, TOML_Array), + Context => TOML_Keys.Pins)); end if; -- TODO: Process Forbidden diff --git a/src/alire/alire-user_pins-maps.adb b/src/alire/alire-user_pins-maps.adb index e86cf71e1..cb11dd825 100644 --- a/src/alire/alire-user_pins-maps.adb +++ b/src/alire/alire-user_pins-maps.adb @@ -5,9 +5,38 @@ package body Alire.User_Pins.Maps is --------------- function From_TOML (This : TOML_Adapters.Key_Queue) return Map is + Result : Map; begin - raise Unimplemented; - return From_TOML (This); + -- Each array entry may contain several pins (just like dependencies). + -- We pass those one by one to the pin loader. + + for I in 1 .. This.Unwrap.Length loop + declare + Table : constant TOML.TOML_Value := This.Unwrap.Item (I); + begin + This.Assert (Table.Kind in TOML.TOML_Table, + "expected a table with = but got: " + & Table.Kind'Image); + + for Key of Table.Keys loop + if Result.Contains (+(+Key)) then + This.Checked_Error ("pin for crate " & (+Key) + & " is specified more than once"); + end if; + + -- Obtain a single pin + + Result.Insert (+(+Key), + User_Pins.From_TOML + (This.Descend + (Value => Table.Get (Key), + Context => +Key))); + end loop; + end; + end loop; + + return Result; + end From_TOML; end Alire.User_Pins.Maps; diff --git a/src/alire/alire-user_pins-maps.ads b/src/alire/alire-user_pins-maps.ads index b2ac630c0..2b686bb2c 100644 --- a/src/alire/alire-user_pins-maps.ads +++ b/src/alire/alire-user_pins-maps.ads @@ -1,5 +1,9 @@ with Ada.Containers.Indefinite_Ordered_Maps; +with Alire.Errors; + +with TOML; + package Alire.User_Pins.Maps is package Pin_Maps is @@ -7,6 +11,9 @@ package Alire.User_Pins.Maps is type Map is new Pin_Maps.Map with null record; - function From_TOML (This : TOML_Adapters.Key_Queue) return Map; + function From_TOML (This : TOML_Adapters.Key_Queue) return Map + with Pre => This.Unwrap.Kind in TOML.TOML_Array + or else raise Checked_Error + with Errors.Set ("array expected but got a " & This.Unwrap.Kind'Image); end Alire.User_Pins.Maps; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index 6fcae44b3..2d91da63c 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -1,3 +1,4 @@ +with Alire.Optional; with Alire.TOML_Adapters; with Semantic_Versioning; @@ -21,6 +22,16 @@ package Alire.User_Pins is type Pin (Kind : Kinds) is tagged private; + function Is_Remote (This : Pin) return Boolean; + + -- Remote attributes + + function URL (This : Pin) return Alire.URL + with Pre => This.Is_Remote; + + function Commit (This : Pin) return Optional.String + with Pre => This.Is_Remote; + function From_TOML (This : TOML_Adapters.Key_Queue) return Pin; -- Expects the rhs of a crate = entry. This can be a string (for a -- version) or a table (for an origin). @@ -45,4 +56,27 @@ private end case; end record; + ------------ + -- Commit -- + ------------ + + function Commit (This : Pin) return Optional.String + is (if +This.Commit = "" + then Optional.Strings.Empty + else Optional.Strings.Unit (+This.Commit)); + + --------------- + -- Is_Remote -- + --------------- + + function Is_Remote (This : Pin) return Boolean + is (This.Kind in To_Git); + + --------- + -- URL -- + --------- + + function URL (This : Pin) return Alire.URL + is (+This.URL); + end Alire.User_Pins; diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index 6b340eb03..94d0ec0ce 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -610,7 +610,7 @@ package body Alr.Commands is if Checked.Solution.Is_Attempted then -- Check deps on disk match those in lockfile Cmd.Requires_Full_Index (Strict => False); - Checked.Sync_Solution_And_Deps; + Checked.Sync_From_Manifest; return; else Notify_Of_Initialization; From 34c1a40ec1bd24859b211cec0dcc03b866fe643d Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 19 May 2021 18:23:54 +0200 Subject: [PATCH 04/25] Pins are downloaded or skipped as needed --- deps/optional | 2 +- src/alire/alire-roots.adb | 98 ++++++++++++++++++++++++++------- src/alire/alire-roots.ads | 9 ++- src/alr/alr-commands-update.adb | 7 +++ 4 files changed, 92 insertions(+), 24 deletions(-) diff --git a/deps/optional b/deps/optional index 02aa24754..30aaee65d 160000 --- a/deps/optional +++ b/deps/optional @@ -1 +1 @@ -Subproject commit 02aa247540da8565ab0529905e68e963dd1cec13 +Subproject commit 30aaee65d89d5a9ca1c71f6d38e4462fae2ef4ce diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index e7f743589..c5c8372cd 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -6,6 +6,7 @@ with Alire.Directories; with Alire.Environment; with Alire.Externals.Softlinks; with Alire.Manifest; +with Alire.Optional; with Alire.Origins.Deployers; with Alire.OS_Lib; with Alire.Roots.Optional; @@ -293,10 +294,38 @@ package body Alire.Roots is -- Deploy_Pins -- ----------------- - procedure Deploy_Pins (This : in out Root) is + procedure Deploy_Pins (This : in out Root; + Exhaustive : Boolean) is use User_Pins.Maps.Pin_Maps; Rel : constant Alire.Releases.Release := Release (This); Pins : constant User_Pins.Maps.Map := Rel.Pins; + + -------------------- + -- Needs_Updating -- + -------------------- + + function Needs_Updating (Crate : Crate_Name; + Pin : User_Pins.Pin) return Boolean + is + use type Alire.Optional.String; + begin + return + -- Any new pin needs downloading + not This.Solution.Links.Contains (Crate) + + -- Manual update requested for pins without a precise commit + or else (Exhaustive and then not Pin.Commit.Has_Element) + + -- Auto update for pins which weren't remote and now are + or else not This.Solution.State (Crate).Link.Is_Remote + + -- Auto update for pins whose commit has changed in manifest wrt + -- lockfile. + or else (Pin.Commit.Has_Element and then + Pin.Commit /= This.Solution.State (Crate) + .Link.Remote.Commit); + end Needs_Updating; + begin if (for some Pin of Pins => Pin.Is_Remote) then Put_Info ("Checking pins..."); @@ -304,27 +333,37 @@ package body Alire.Roots is for I in Pins.Iterate loop if Pins (I).Is_Remote then + if Needs_Updating (Key (I), Pins (I)) then + + Put_Info ("Deploying pin for crate: " & TTY.Name (Key (I))); + + declare + Crate : constant Crate_Name := Key (I); + Pin : constant User_Pins.Pin := Element (I); + Result : constant Remote_Pin_Result := + This.Pinned_To_Remote + (Dependency => + Conditional.New_Dependency + (Rel.Dependency_On (Crate) + .Or_Else (Dependencies.From_String + ((+Crate) & "*"))), + URL => Pin.URL, + Commit => Pin.Commit.Or_Else (""), + Must_Depend => True); + begin + -- Pin deployed, solution can be stored accordingly + + This.Set (Solution => Result.Solution); + end; + else - Put_Info ("Deploying pin for crate: " & TTY.Name (Key (I))); + Put_Info ("Skipping pre-existing pin for crate: " + & TTY.Name (Key (I))); - declare - Crate : constant Crate_Name := Key (I); - Pin : constant User_Pins.Pin := Element (I); - Result : constant Remote_Pin_Result := - This.Pinned_To_Remote - (Dependency => - Conditional.New_Dependency - (Rel.Dependency_On (Crate) - .Or_Else (Dependencies.From_String - ((+Crate) & "*"))), - URL => Pin.URL, - Commit => Pin.Commit.Or_Else (""), - Must_Depend => True); - begin - -- Pin deployed, solution can be stored accordingly + end if; - This.Set (Solution => Result.Solution); - end; + Trace.Debug ("Skipping local user pin from fetch: " + & TTY.Name (Key (I))); end if; end loop; end Deploy_Pins; @@ -609,7 +648,9 @@ package body Alire.Roots is if This.Is_Lockfile_Outdated then Put_Info ("Detected changes in manifest, synchronizing workspace..."); - This.Deploy_Pins; + This.Deploy_Pins (Exhaustive => False); + -- Pre-fetch any new remote links in the manifest, so they can be + -- used right away for version resolution/recursive dependencies. This.Update_And_Deploy_Dependencies (Confirm => False); -- Don't ask for confirmation as this is an automatic update in @@ -829,7 +870,22 @@ package body Alire.Roots is Origins.Deployers.New_Deployer (Origins.New_Git (URL, Commit)); begin - Depl.Deploy (Temp.Filename).Assert; + + -- Skip checkout if link is already in the solution and with the same + -- commit. + + if Requested_Crate /= "" and then + This.Solution.Depends_On (+Requested_Crate) and then + This.Solution.Links.Contains (+Requested_Crate) and then + This.Solution.State (+Requested_Crate).Link.Remote.Commit = Commit + then + Trace.Debug ("Skipping checkout of remote link " + & TTY.Name (Requested_Crate) + & "#" + & TTY.URL (Commit)); + else + Depl.Deploy (Temp.Filename).Assert; + end if; -- Identify containing release, and if satisfying move it to its -- final location in the release cache. diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 4e5ef02b3..5b6bded6b 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -166,8 +166,13 @@ package Alire.Roots is Confirm : Boolean := not Utils.User_Input.Not_Interactive); -- Call Update and Deploy_Dependencies in succession for the given root - procedure Deploy_Pins (This : in out Root); - -- Download any remote pins in the manifest + procedure Deploy_Pins (This : in out Root; + Exhaustive : Boolean); + -- Download any remote pins in the manifest. When not Exhaustive, a pin + -- that is already in the solution is not re-downloaded. This is to avoid + -- re-fetching all pins after each manifest edition. New pins are always + -- downloaded. An update requested by the user (`alr update`) will be + -- exhaustive. procedure Write_Manifest (This : Root); -- Generates the crate.toml manifest at the appropriate location for Root diff --git a/src/alr/alr-commands-update.adb b/src/alr/alr-commands-update.adb index 64527ff52..0bf1e768d 100644 --- a/src/alr/alr-commands-update.adb +++ b/src/alr/alr-commands-update.adb @@ -43,6 +43,13 @@ package body Alr.Commands.Update is Cmd.Requires_Full_Index; + -- Just in case, retry all pins. This is necessary so pins without an + -- explicit commit are updated to HEAD. + + Cmd.Root.Deploy_Pins (Exhaustive => True); + + -- And look for updates in dependencies + Cmd.Root.Update_Dependencies (Allowed => Parse_Allowed, Options => (Age => Query_Policy, From e01ff27b527a761fb0406b93f38446a01d80fa7f Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 19 May 2021 19:22:03 +0200 Subject: [PATCH 05/25] Pins are properly pruned, and info displayed Minor testsuite tweak for a change in logging format --- src/alire/alire-crate_configuration.adb | 9 +++--- src/alire/alire-dependencies-states.ads | 14 ++++++++ src/alire/alire-environment.adb | 9 ++++-- src/alire/alire-roots.adb | 37 ++++++++++++++++++++-- src/alire/alire-roots.ads | 8 ++++- src/alire/alire-solutions-diffs.adb | 2 +- src/alire/alire-solutions.ads | 30 ++++++++++++++++++ testsuite/tests/update/manual-once/test.py | 4 +-- 8 files changed, 101 insertions(+), 12 deletions(-) diff --git a/src/alire/alire-crate_configuration.adb b/src/alire/alire-crate_configuration.adb index bc6474234..f2c8aa311 100644 --- a/src/alire/alire-crate_configuration.adb +++ b/src/alire/alire-crate_configuration.adb @@ -8,6 +8,7 @@ with Alire.Solutions; with Alire.Releases; with Alire.Roots; with Alire.Origins; +with Alire.Warnings; with Alire.Directories; @@ -28,8 +29,8 @@ package body Alire.Crate_Configuration is begin if not Solution.Is_Complete then - Trace.Warning ("Generating possibly incomplete configuration" - & " because of missing dependencies"); + Warnings.Warn_Once ("Generating possibly incomplete configuration" + & " because of missing dependencies"); end if; for Rel of Solution.Releases.Including (Root.Release) loop @@ -75,8 +76,8 @@ package body Alire.Crate_Configuration is begin if not Solution.Is_Complete then - Trace.Warning ("Generating possibly incomplete configuration" - & " because of missing dependencies"); + Warnings.Warn_Once ("Generating possibly incomplete configuration" + & " because of missing dependencies"); end if; for Rel of Solution.Releases.Including (Root.Release) loop diff --git a/src/alire/alire-dependencies-states.ads b/src/alire/alire-dependencies-states.ads index 5d8e39faa..cb7c0e96f 100644 --- a/src/alire/alire-dependencies-states.ads +++ b/src/alire/alire-dependencies-states.ads @@ -61,6 +61,9 @@ package Alire.Dependencies.States is with Pre => Base.Crate = Using.Name; -- Uses release to fulfill this dependency in a copy of Base + function Unlinking (Base : State) return State; + -- Unlinks the crate in a copy of Base, becoming Missed + function Unpinning (Base : State) return State; -- Removes the pin in a copy of Base @@ -477,6 +480,17 @@ private else "") & ")"); + --------------- + -- Unlinking -- + --------------- + + function Unlinking (Base : State) return State + is (Base.As_Dependency with + Name_Len => Base.Name_Len, + Fulfilled => (Fulfillment => Missed), + Pinning => Base.Pinning, + Transitivity => Base.Transitivity); + --------------- -- Unpinning -- --------------- diff --git a/src/alire/alire-environment.adb b/src/alire/alire-environment.adb index b450869a9..a5268ba68 100644 --- a/src/alire/alire-environment.adb +++ b/src/alire/alire-environment.adb @@ -83,6 +83,8 @@ package body Alire.Environment is -- Load -- ---------- + Already_Warned : Boolean := False; + procedure Load (This : in out Context; Root : in out Alire.Roots.Root) is @@ -95,14 +97,17 @@ package body Alire.Environment is -- Warnings when setting up an incomplete environment if not Solution.Is_Complete then - Trace.Debug ("Generating incomplete environment" + Trace.Debug ("Generating possibly incomplete environment" & " because of missing dependencies"); -- Normally we would generate a warning, but since that will pollute -- the output making it unusable, for once we write directly to -- stderr (unless quiet is in effect): - if not Alire_Early_Elaboration.Switch_Q then + if not Alire_Early_Elaboration.Switch_Q and then not Already_Warned + then + Already_Warned := True; + GNAT.IO.Put_Line (GNAT.IO.Standard_Error, TTY.Warn ("warn:") & " Generating incomplete environment" diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index c5c8372cd..3c2a05ff8 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -368,6 +368,30 @@ package body Alire.Roots is end loop; end Deploy_Pins; + ---------------- + -- Prune_Pins -- + ---------------- + + procedure Prune_Pins (This : in out Root) is + use type Solutions.Solution; + Valid_Pins : constant User_Pins.Maps.Map := Release (This).Pins; + Pruned_Sol : Solutions.Solution := This.Solution; + begin + for State of This.Solution.All_Dependencies loop + if State.Is_User_Pinned and then not Valid_Pins.Contains (State.Crate) + then + Pruned_Sol := Pruned_Sol.Unlinking (State.Crate) + .Unpinning (State.Crate); + Put_Info ("Unpinning crate " & TTY.Name (State.Crate)); + end if; + end loop; + + if Pruned_Sol /= This.Solution then + Trace.Detail ("Pin-pruned solution commited to disk"); + This.Set (Pruned_Sol); + end if; + end Prune_Pins; + --------------- -- Is_Stored -- --------------- @@ -644,6 +668,7 @@ package body Alire.Roots is ------------------------ procedure Sync_From_Manifest (This : in out Root) is + Old_Solution : constant Solutions.Solution := This.Solution; begin if This.Is_Lockfile_Outdated then Put_Info ("Detected changes in manifest, synchronizing workspace..."); @@ -652,7 +677,11 @@ package body Alire.Roots is -- Pre-fetch any new remote links in the manifest, so they can be -- used right away for version resolution/recursive dependencies. - This.Update_And_Deploy_Dependencies (Confirm => False); + This.Prune_Pins; + -- And remove any pins that the user has removed + + This.Update_And_Deploy_Dependencies (Old_Sol => Old_Solution, + Confirm => False); -- Don't ask for confirmation as this is an automatic update in -- reaction to a manually edited manifest, and we need the lockfile -- to match the manifest. As any change in dependencies will be @@ -989,9 +1018,13 @@ package body Alire.Roots is procedure Update_And_Deploy_Dependencies (This : in out Roots.Root; Options : Solver.Query_Options := Solver.Default_Options; + Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; Confirm : Boolean := not Utils.User_Input.Not_Interactive) is - Prev : constant Solutions.Solution := This.Solution; + Prev : constant Solutions.Solution := + (if Old_Sol.Is_Attempted + then Old_Sol + else This.Solution); Next : constant Solutions.Solution := This.Compute_Update (Options => Options); Diff : constant Solutions.Diffs.Diff := Prev.Changes (Next); diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 5b6bded6b..175677e80 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -163,8 +163,11 @@ package Alire.Roots is procedure Update_And_Deploy_Dependencies (This : in out Roots.Root; Options : Solver.Query_Options := Solver.Default_Options; + Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; Confirm : Boolean := not Utils.User_Input.Not_Interactive); - -- Call Update and Deploy_Dependencies in succession for the given root + -- Call Update and Deploy_Dependencies in succession for the given root. + -- Old_Sol is used to present differences, and when left at the default + -- invalid one, Root.Solution will be used as old solution. procedure Deploy_Pins (This : in out Root; Exhaustive : Boolean); @@ -174,6 +177,9 @@ package Alire.Roots is -- downloaded. An update requested by the user (`alr update`) will be -- exhaustive. + procedure Prune_Pins (This : in out Root); + -- Remove any pins in the solution that are not in the manifest + procedure Write_Manifest (This : Root); -- Generates the crate.toml manifest at the appropriate location for Root diff --git a/src/alire/alire-solutions-diffs.adb b/src/alire/alire-solutions-diffs.adb index 6e4fc1b67..d986ea414 100644 --- a/src/alire/alire-solutions-diffs.adb +++ b/src/alire/alire-solutions-diffs.adb @@ -383,7 +383,7 @@ package body Alire.Solutions.Diffs is if Changed then Table.Print (Level); else - Trace.Log (Prefix & "No changes between former an new solution.", + Trace.Log (Prefix & "No changes between former and new solution.", Level); end if; end Print; diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index c6399f269..a3b21d2b6 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -147,6 +147,12 @@ package Alire.Solutions is return Solution; -- Change transitivity + function Unlinking (This : Solution; + Crate : Crate_Name) + return Solution; + -- Unpin a crate. If the crate was not linked or not in the solution + -- nothing will be done. If it was, it is now missing. + function Unpinning (This : Solution; Crate : Crate_Name) return Solution; @@ -173,6 +179,9 @@ package Alire.Solutions is -- Dependency name closure, independent of the status in the solution, as -- found by the solver starting from the direct dependencies. + function All_Dependencies (This : Solution) return State_Map; + -- Get all states in the solution to e.g. iterate over + function Dependencies_That (This : Solution; Check : not null access function (Dep : Dependency_State) return Boolean) @@ -342,6 +351,13 @@ private -- Begin of implementation + ---------------------- + -- All_Dependencies -- + ---------------------- + + function All_Dependencies (This : Solution) return State_Map + is (This.Dependencies); + ----------------- -- Composition -- ----------------- @@ -551,6 +567,20 @@ private return Dependency_State is (This.Dependencies (Crate)); + --------------- + -- Unlinking -- + --------------- + + function Unlinking (This : Solution; + Crate : Crate_Name) + return Solution + is (if This.Dependencies.Contains (Crate) + then (Solved => True, + Dependencies => + This.Dependencies.Including + (This.Dependencies (Crate).Unlinking)) + else This); + --------------- -- Unpinning -- --------------- diff --git a/testsuite/tests/update/manual-once/test.py b/testsuite/tests/update/manual-once/test.py index f93b51672..370710ebf 100644 --- a/testsuite/tests/update/manual-once/test.py +++ b/testsuite/tests/update/manual-once/test.py @@ -21,7 +21,7 @@ def prepare_crate(name): info = os.stat("alire.toml") os.utime("alire.lock", (info.st_atime, info.st_mtime - 1)) -warning_text = "Detected changes in manifest, updating workspace" +warning_text = "Detected changes in manifest, synchronizing workspace" # Test when directly doing an update. Should report no changes. prepare_crate("test1") @@ -34,7 +34,7 @@ def prepare_crate(name): # Test when doing other things. Should warn once of possible changes. prepare_crate("test2") p = run_alr("with", quiet=False) # First run must warn -assert_match(warning_text + ".*", p.out) +assert_match(".*" + warning_text + ".*", p.out) p = run_alr("with", quiet=False) # Second run must not warn assert warning_text not in p.out From 41c2cc58b04f8acb85767298f5e8ebd370f59870 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 19 May 2021 19:43:03 +0200 Subject: [PATCH 06/25] Added new-format pins to alire.toml for self-build --- alire.lock | 8 ++++---- alire.toml | 11 ++++++++++- src/alire/alire-roots.adb | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/alire.lock b/alire.lock index b16510374..e3203f1f4 100644 --- a/alire.lock +++ b/alire.lock @@ -111,15 +111,15 @@ crate = "optional" fulfilment = "linked" pinned = false transitivity = "direct" -versions = "*" +versions = "~0.0.0" [solution.state.link] kind = "softlink" -path = "file:alire/cache/pins/optional_0.0.0_f3b855d2" +path = "file:alire/cache/pins/optional_0.1.0-rc1_30aaee65" relative = true remote = true [solution.state.link.origin] -commit = "f3b855d21c78e6644d1bbb02a8606869ead66cac" -url = "git+https://github.com/mosteo/optional/" +commit = "30aaee65d89d5a9ca1c71f6d38e4462fae2ef4ce" +url = "git+https://github.com/mosteo/optional.git" [[solution.state]] crate = "semantic_versioning" fulfilment = "linked" diff --git a/alire.toml b/alire.toml index e78dcafc9..c8677d0e0 100644 --- a/alire.toml +++ b/alire.toml @@ -31,6 +31,15 @@ spdx = "~0.2" [gpr-set-externals."case(os)"] macos = { OS = "macOS" } -# Most dependencies require precise versions during the development cycle +# Most dependencies require precise versions during the development cycle: [[pins]] aaa = { url = "https://github.com/mosteo/aaa.git", commit = "4b4aa047f29a4270c5b5003468617e153977ab97" } +ada_toml = { url = "https://github.com/pmderodat/ada-toml.git", commit = "ade3cc905cef405dbf53e16a54f6fb458482710f" } +ajunitgen = { url = "https://github.com/mosteo/ajunitgen.git", commit = "e5d01db5e7834d15c4066f0a8e33d780deae3cc9" } +ansiada = { url = "https://github.com/mosteo/ansi-ada.git", commit = "acf9afca3afe1f8b8843c061f3cef860d7567307" } +gnatcoll = { url = "https://github.com/alire-project/gnatcoll-core.git", commit = "f3bd1c51d12962879f52733e790b394f5bbfe05f" } +minirest = { url = "https://github.com/mosteo/minirest.git", commit = "4550aa356d55b9cd55f26acd34701f646021c5ff" } +optional = { url = "https://github.com/mosteo/optional.git", commit = "30aaee65d89d5a9ca1c71f6d38e4462fae2ef4ce" } +semantic_versioning = { url = "https://github.com/alire-project/semantic_versioning.git", commit = "82c28f773d0e3126d7cdf6e4ded228d2b733441e" } +simple_logging = { url = "https://github.com/alire-project/simple_logging.git", commit = "02a7de7568af6af7cedd1048901fae8e9477b1d9" } +uri_ada = { url = "https://github.com/mosteo/uri-ada.git", commit = "b61eba59099b3ab39e59e228fe4529927f9e849e" } diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 3c2a05ff8..2913da5b2 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -357,7 +357,7 @@ package body Alire.Roots is end; else - Put_Info ("Skipping pre-existing pin for crate: " + Trace.Detail ("Skipping pre-existing pin for crate: " & TTY.Name (Key (I))); end if; From 6f6627be708af1f9c55be0093764a8a4a29fb5d7 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 20 May 2021 11:54:14 +0200 Subject: [PATCH 07/25] Allow selective update of pins as for regular deps --- src/alire/alire-roots.adb | 47 +++++++++++++++++-- src/alire/alire-roots.ads | 20 ++++++-- src/alr/alr-commands-update.adb | 14 +----- testsuite/tests/pin/unpin/test.py | 7 +++ testsuite/tests/with/pin-transitive/test.yaml | 3 ++ 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 2913da5b2..23e253223 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -295,7 +295,9 @@ package body Alire.Roots is ----------------- procedure Deploy_Pins (This : in out Root; - Exhaustive : Boolean) is + Exhaustive : Boolean; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set) is use User_Pins.Maps.Pin_Maps; Rel : constant Alire.Releases.Release := Release (This); Pins : constant User_Pins.Maps.Map := Rel.Pins; @@ -309,6 +311,15 @@ package body Alire.Roots is is use type Alire.Optional.String; begin + + -- Early reject if the crate is not among the allowed ones + + if not Allowed.Is_Empty and then not Allowed.Contains (Crate) then + return False; + end if; + + -- Regular checks if the crate is in the update set + return -- Any new pin needs downloading not This.Solution.Links.Contains (Crate) @@ -372,13 +383,17 @@ package body Alire.Roots is -- Prune_Pins -- ---------------- - procedure Prune_Pins (This : in out Root) is + procedure Prune_Pins (This : in out Root; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set) is use type Solutions.Solution; Valid_Pins : constant User_Pins.Maps.Map := Release (This).Pins; Pruned_Sol : Solutions.Solution := This.Solution; begin for State of This.Solution.All_Dependencies loop - if State.Is_User_Pinned and then not Valid_Pins.Contains (State.Crate) + if State.Is_User_Pinned and then + not Valid_Pins.Contains (State.Crate) and then + (Allowed.Is_Empty or else Allowed.Contains (State.Crate)) then Pruned_Sol := Pruned_Sol.Unlinking (State.Crate) .Unpinning (State.Crate); @@ -726,6 +741,32 @@ package body Alire.Roots is end if; end Sync_Manifest_And_Lockfile_Timestamps; + ------------ + -- Update -- + ------------ + + procedure Update (This : in out Root; + Allowed : Containers.Crate_Name_Sets.Set) + is + begin + -- Just in case, retry all pins. This is necessary so pins without an + -- explicit commit are updated to HEAD. + + This.Deploy_Pins (Exhaustive => True, + Allowed => Allowed); + + -- Prune pins, as otherwise they would remain even if removed from the + -- manifest. + + This.Prune_Pins (Allowed); + + -- And look for updates in dependencies + + This.Update_Dependencies + (Allowed => Allowed, + Silent => Alire.Utils.User_Input.Not_Interactive); + end Update; + -------------------- -- Compute_Update -- -------------------- diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 175677e80..2e08ede9c 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -151,6 +151,13 @@ package Alire.Roots is procedure Deploy_Dependencies (This : in out Root); -- Download all dependencies not already on disk from This.Solution + procedure Update (This : in out Root; + Allowed : Containers.Crate_Name_Sets.Set); + -- Full update, explicitly requested. Will fetch/prune pins, update any + -- updatable crates. Equivalent to `alr update`. Allowed is an optionally + -- empty set of crates to which the update will be limited. Everything is + -- updatable if Allowed.Is_Empty. + procedure Update_Dependencies (This : in out Root; Silent : Boolean; @@ -170,15 +177,20 @@ package Alire.Roots is -- invalid one, Root.Solution will be used as old solution. procedure Deploy_Pins (This : in out Root; - Exhaustive : Boolean); + Exhaustive : Boolean; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set); -- Download any remote pins in the manifest. When not Exhaustive, a pin -- that is already in the solution is not re-downloaded. This is to avoid -- re-fetching all pins after each manifest edition. New pins are always -- downloaded. An update requested by the user (`alr update`) will be - -- exhaustive. + -- exhaustive. Allowed restricts which crates are affected - procedure Prune_Pins (This : in out Root); - -- Remove any pins in the solution that are not in the manifest + procedure Prune_Pins (This : in out Root; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set); + -- Remove any pins in the solution that are not in the manifest. Allowed + -- restricts which crates are affected. procedure Write_Manifest (This : Root); -- Generates the crate.toml manifest at the appropriate location for Root diff --git a/src/alr/alr-commands-update.adb b/src/alr/alr-commands-update.adb index 0bf1e768d..55c3c9159 100644 --- a/src/alr/alr-commands-update.adb +++ b/src/alr/alr-commands-update.adb @@ -1,6 +1,5 @@ with Alire.Containers; with Alire.Errors; -with Alire.Utils.User_Input; with Alr.Commands.Index; @@ -43,18 +42,7 @@ package body Alr.Commands.Update is Cmd.Requires_Full_Index; - -- Just in case, retry all pins. This is necessary so pins without an - -- explicit commit are updated to HEAD. - - Cmd.Root.Deploy_Pins (Exhaustive => True); - - -- And look for updates in dependencies - - Cmd.Root.Update_Dependencies - (Allowed => Parse_Allowed, - Options => (Age => Query_Policy, - others => <>), - Silent => Alire.Utils.User_Input.Not_Interactive); + Cmd.Root.Update (Parse_Allowed); end Execute; ---------------------- diff --git a/testsuite/tests/pin/unpin/test.py b/testsuite/tests/pin/unpin/test.py index 824d135ec..3cd9fbd03 100644 --- a/testsuite/tests/pin/unpin/test.py +++ b/testsuite/tests/pin/unpin/test.py @@ -21,6 +21,13 @@ p = run_alr('pin') assert_eq('libhello 1.0.0\n', p.out) +# Update and verify that the pin has survived +run_alr('update') +p = run_alr('pin') +assert_eq('libhello 1.0.0\n', p.out) + +# Delete lockfile and verify the pin has survived + # Unpin and verify pin is not there run_alr('pin', '--unpin', 'libhello') p = run_alr('pin') diff --git a/testsuite/tests/with/pin-transitive/test.yaml b/testsuite/tests/with/pin-transitive/test.yaml index 32c747b3f..648ca9d14 100644 --- a/testsuite/tests/with/pin-transitive/test.yaml +++ b/testsuite/tests/with/pin-transitive/test.yaml @@ -1 +1,4 @@ driver: python-script +indexes: + basic_index: + in_fixtures: true \ No newline at end of file From b7d66057c3796dca06194ca51223b81fc0647a0d Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 20 May 2021 13:45:12 +0200 Subject: [PATCH 08/25] Local pins work with new manifest syntax --- src/alire/alire-roots.adb | 97 ++++++++++++++++++++++++++--------- src/alire/alire-roots.ads | 57 ++++++++++++-------- src/alire/alire-solutions.ads | 20 ++++++++ src/alire/alire-user_pins.ads | 23 +++++++++ 4 files changed, 151 insertions(+), 46 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 23e253223..0e5ce43c1 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -290,6 +290,41 @@ package body Alire.Roots is end Deploy_Dependencies; + ---------------------- + -- Apply_Local_Pins -- + ---------------------- + + procedure Apply_Local_Pins (This : in out Root) is + use type Solutions.Solution; + Sol : Solutions.Solution := This.Solution; + begin + for I in Release (This).Pins.Iterate loop + declare + use all type User_Pins.Kinds; + use User_Pins.Maps.Pin_Maps; + Crate : constant Crate_Name := Key (I); + Pin : constant User_Pins.Pin := Element (I); + begin + case Pin.Kind is + when To_Version => + Sol := Sol.Missing (Crate).Pinning (Crate, Pin.Version); + when To_Path => + Sol := Sol.Missing (Crate).Linking (Crate, Pin.Path); + when To_Git => + null; -- Not considered here + end case; + end; + end loop; + + if Sol /= This.Solution then + Solutions.Diffs.Between (This.Solution, Sol).Print + (Changed_Only => True, + Level => Trace.Detail); + Trace.Detail ("Local pins updated and commited to disk"); + This.Set (Solution => Sol); + end if; + end Apply_Local_Pins; + ----------------- -- Deploy_Pins -- ----------------- @@ -339,7 +374,7 @@ package body Alire.Roots is begin if (for some Pin of Pins => Pin.Is_Remote) then - Put_Info ("Checking pins..."); + Put_Info ("Checking remote pins..."); end if; for I in Pins.Iterate loop @@ -349,6 +384,7 @@ package body Alire.Roots is Put_Info ("Deploying pin for crate: " & TTY.Name (Key (I))); declare + use type Solutions.Solution; Crate : constant Crate_Name := Key (I); Pin : constant User_Pins.Pin := Element (I); Result : constant Remote_Pin_Result := @@ -363,8 +399,14 @@ package body Alire.Roots is Must_Depend => True); begin -- Pin deployed, solution can be stored accordingly - - This.Set (Solution => Result.Solution); + if This.Solution /= Result.Solution then + Solutions + .Diffs.Between (This.Solution, Result.Solution) + .Print (Changed_Only => True, + Level => Trace.Detail); + This.Set (Solution => Result.Solution); + Trace.Detail ("Remote pins commited to disk"); + end if; end; else @@ -372,9 +414,6 @@ package body Alire.Roots is & TTY.Name (Key (I))); end if; - - Trace.Debug ("Skipping local user pin from fetch: " - & TTY.Name (Key (I))); end if; end loop; end Deploy_Pins; @@ -383,17 +422,14 @@ package body Alire.Roots is -- Prune_Pins -- ---------------- - procedure Prune_Pins (This : in out Root; - Allowed : Containers.Crate_Name_Sets.Set := - Containers.Crate_Name_Sets.Empty_Set) is + procedure Prune_Pins (This : in out Root) is use type Solutions.Solution; Valid_Pins : constant User_Pins.Maps.Map := Release (This).Pins; Pruned_Sol : Solutions.Solution := This.Solution; begin for State of This.Solution.All_Dependencies loop if State.Is_User_Pinned and then - not Valid_Pins.Contains (State.Crate) and then - (Allowed.Is_Empty or else Allowed.Contains (State.Crate)) + not Valid_Pins.Contains (State.Crate) then Pruned_Sol := Pruned_Sol.Unlinking (State.Crate) .Unpinning (State.Crate); @@ -402,11 +438,30 @@ package body Alire.Roots is end loop; if Pruned_Sol /= This.Solution then + Solutions.Diffs.Between (This.Solution, Pruned_Sol).Print + (Changed_Only => True, + Level => Trace.Detail); Trace.Detail ("Pin-pruned solution commited to disk"); This.Set (Pruned_Sol); end if; end Prune_Pins; + ----------------------------- + -- Sync_Pins_From_Manifest -- + ----------------------------- + + procedure Sync_Pins_From_Manifest + (This : in out Root; + Exhaustive : Boolean; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set) + is + begin + This.Deploy_Pins (Exhaustive, Allowed); + This.Prune_Pins; + This.Apply_Local_Pins; + end Sync_Pins_From_Manifest; + --------------- -- Is_Stored -- --------------- @@ -688,12 +743,10 @@ package body Alire.Roots is if This.Is_Lockfile_Outdated then Put_Info ("Detected changes in manifest, synchronizing workspace..."); - This.Deploy_Pins (Exhaustive => False); - -- Pre-fetch any new remote links in the manifest, so they can be - -- used right away for version resolution/recursive dependencies. - - This.Prune_Pins; - -- And remove any pins that the user has removed + This.Sync_Pins_From_Manifest (Exhaustive => False); + -- Normally we do not want to re-fetch remote pins, so we request + -- a non-exhaustive sync of pins, that will anyway detect evident + -- changes (new/removed pins, changed explicit commits). This.Update_And_Deploy_Dependencies (Old_Sol => Old_Solution, Confirm => False); @@ -749,17 +802,11 @@ package body Alire.Roots is Allowed : Containers.Crate_Name_Sets.Set) is begin + This.Sync_Pins_From_Manifest (Exhaustive => True, + Allowed => Allowed); -- Just in case, retry all pins. This is necessary so pins without an -- explicit commit are updated to HEAD. - This.Deploy_Pins (Exhaustive => True, - Allowed => Allowed); - - -- Prune pins, as otherwise they would remain even if removed from the - -- manifest. - - This.Prune_Pins (Allowed); - -- And look for updates in dependencies This.Update_Dependencies diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 2e08ede9c..32db1457c 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -124,11 +124,12 @@ package Alire.Roots is procedure Sync_From_Manifest (This : in out Root); -- 1) Pre-deploy any remote pins in the manifest so they are usable when - -- solving. 2) Ensure that dependencies are up to date in regard to the - -- lockfile and manifest: if the manifest is newer than the lockfile, - -- resolve again, as dependencies may have been edited by hand. 3) Ensure - -- that releases in the lockfile are actually on disk (may be missing if - -- cache was deleted, or the crate was just cloned). + -- solving, and apply any local/version pins. 2) Ensure that dependencies + -- are up to date in regard to the lockfile and manifest: if the manifest + -- is newer than the lockfile, resolve again, as dependencies may have been + -- edited by hand. 3) Ensure that releases in the lockfile are actually + -- on disk (may be missing if cache was deleted, or the crate was just + -- cloned). procedure Sync_Manifest_And_Lockfile_Timestamps (This : Root) with Post => not This.Is_Lockfile_Outdated; @@ -174,22 +175,18 @@ package Alire.Roots is Confirm : Boolean := not Utils.User_Input.Not_Interactive); -- Call Update and Deploy_Dependencies in succession for the given root. -- Old_Sol is used to present differences, and when left at the default - -- invalid one, Root.Solution will be used as old solution. - - procedure Deploy_Pins (This : in out Root; - Exhaustive : Boolean; - Allowed : Containers.Crate_Name_Sets.Set := - Containers.Crate_Name_Sets.Empty_Set); - -- Download any remote pins in the manifest. When not Exhaustive, a pin - -- that is already in the solution is not re-downloaded. This is to avoid - -- re-fetching all pins after each manifest edition. New pins are always - -- downloaded. An update requested by the user (`alr update`) will be - -- exhaustive. Allowed restricts which crates are affected - - procedure Prune_Pins (This : in out Root; - Allowed : Containers.Crate_Name_Sets.Set := - Containers.Crate_Name_Sets.Empty_Set); - -- Remove any pins in the solution that are not in the manifest. Allowed + -- invalid argument value, Root.Solution will be used as old solution. + + procedure Sync_Pins_From_Manifest + (This : in out Root; + Exhaustive : Boolean; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set); + -- Checks additions/removals of pins, and fetches remote pins. When not + -- Exhaustive, a pin that is already in the solution is not re-downloaded. + -- This is to avoid re-fetching all pins after each manifest edition. + -- New pins, or pins with a changed commit are always downloaded. An update + -- requested by the user (`alr update`) will be exhaustive. Allowed -- restricts which crates are affected. procedure Write_Manifest (This : Root); @@ -256,4 +253,22 @@ private Cached_Solution : Cached_Solutions.Cache; end record; + procedure Apply_Local_Pins (This : in out Root); + -- Apply version/path pins from the manifest. Remote pins are dealt with by + -- Deploy_Pins, as they are costlier and have more involved processing. + + procedure Deploy_Pins (This : in out Root; + Exhaustive : Boolean; + Allowed : Containers.Crate_Name_Sets.Set := + Containers.Crate_Name_Sets.Empty_Set); + -- Download any remote pins in the manifest. When not Exhaustive, a pin + -- that is already in the solution is not re-downloaded. This is to avoid + -- re-fetching all pins after each manifest edition. New pins are always + -- downloaded. An update requested by the user (`alr update`) will be + -- exhaustive. Allowed restricts which crates are affected + + procedure Prune_Pins (This : in out Root); + -- Remove any pins in the solution that are not in the manifest. Allowed + -- restricts which crates are affected. + end Alire.Roots; diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index a3b21d2b6..e1e8ebc21 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -159,6 +159,12 @@ package Alire.Solutions is -- Unpin a crate. If the crate was not pinned or not in the solution -- nothing will be done. + function Unsolving (This : Solution; + Crate : Crate_Name) + return Solution; + -- Remove links, pins, releases... and mark the crate as missing. If not in + -- the solution, nothing will be done. + function With_Pins (This, Src : Solution) return Solution; -- Copy pins from Src to This and return it @@ -595,4 +601,18 @@ private (This.Dependencies (Crate).Unpinning)) else This); + --------------- + -- Unsolving -- + --------------- + + function Unsolving (This : Solution; + Crate : Crate_Name) + return Solution + is (if This.Dependencies.Contains (Crate) + then (Solved => True, + Dependencies => + This.Dependencies.Including + (This.Dependencies (Crate).Unlinking.Unpinning.Missing)) + else This); + end Alire.Solutions; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index 2d91da63c..5237aa339 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -24,6 +24,16 @@ package Alire.User_Pins is function Is_Remote (This : Pin) return Boolean; + -- Version attributes + + function Version (This : Pin) return Semantic_Versioning.Version + with Pre => This.Kind = To_Version; + + -- Local path attributes + + function Path (This : Pin) return Any_Path + with Pre => This.Kind = To_Path; + -- Remote attributes function URL (This : Pin) return Alire.URL @@ -72,6 +82,12 @@ private function Is_Remote (This : Pin) return Boolean is (This.Kind in To_Git); + ---------- + -- Path -- + ---------- + + function Path (This : Pin) return Any_Path is (+This.Path); + --------- -- URL -- --------- @@ -79,4 +95,11 @@ private function URL (This : Pin) return Alire.URL is (+This.URL); + ------------- + -- Version -- + ------------- + + function Version (This : Pin) return Semantic_Versioning.Version + is (This.Version); + end Alire.User_Pins; From 575e795c9854f2a7b190f2689ca5fc3ab0361761 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Fri, 21 May 2021 11:27:39 +0200 Subject: [PATCH 09/25] Fixed bug in which version pins were not used --- src/alire/alire-environment.adb | 3 ++- src/alire/alire-solutions.adb | 22 +++++++++++++++++++++- src/alire/alire-solutions.ads | 15 +++++---------- src/alire/alire-solver.adb | 24 ++++++++++++++++++++++++ src/alire/alire-solver.ads | 7 ++++--- src/alire/alire-user_pins.ads | 1 + 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/alire/alire-environment.adb b/src/alire/alire-environment.adb index a5268ba68..00d2c83e9 100644 --- a/src/alire/alire-environment.adb +++ b/src/alire/alire-environment.adb @@ -110,7 +110,8 @@ package body Alire.Environment is GNAT.IO.Put_Line (GNAT.IO.Standard_Error, - TTY.Warn ("warn:") & " Generating incomplete environment" + TTY.Warn ("warn:") + & " Generating possibly incomplete environment" & " because of missing dependencies"); end if; end if; diff --git a/src/alire/alire-solutions.adb b/src/alire/alire-solutions.adb index 841027ee4..15a8a4e79 100644 --- a/src/alire/alire-solutions.adb +++ b/src/alire/alire-solutions.adb @@ -380,7 +380,27 @@ package body Alire.Solutions is if Dep.Is_Pinned then Dependencies := Dependencies and - Conditional.New_Dependency (Dep.Crate, Dep.Versions); + Conditional.New_Dependency (Dep.Crate, + Dep.Pin_Version); + end if; + end loop; + end return; + end Pins; + + ---------- + -- Pins -- + ---------- + + function Pins (This : Solution) return Dependency_Map + is + begin + return Result : Dependency_Map do + for State of This.Dependencies loop + if State.Is_Pinned then + Result.Insert (State.Crate, + Alire.Dependencies.New_Dependency + (State.Crate, + State.Pin_Version)); end if; end loop; end return; diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index e1e8ebc21..5cc5fdf15 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -248,11 +248,13 @@ package Alire.Solutions is -- Return crates for which there is neither hint nor proper versions function Pins (This : Solution) return Conditional.Dependencies; - -- Return all pinned dependencies as a dependency tree containing exact - -- versions. + -- Return all version-pinned dependencies as a dependency tree containing + -- exact versions. NOTE that the original dependency is thus lost in this + -- info. function Pins (This : Solution) return Dependency_Map; - -- return all pinned dependencies as plain dependencies for a exact version + -- return all version-pinned dependencies as plain dependencies for a exact + -- version. NOTE that the original dependency is thus lost. function Releases (This : Solution) return Release_Map; -- Returns the proper releases in the solution (regular and detected @@ -537,13 +539,6 @@ private This.Dependencies.Including (This.Dependencies (Crate).Pinning (Version))); - ---------- - -- Pins -- - ---------- - - function Pins (This : Solution) return Dependency_Map - is (This.Dependencies_That (States.Is_Pinned'Access)); - -------------- -- Required -- -------------- diff --git a/src/alire/alire-solver.adb b/src/alire/alire-solver.adb index 336199706..943d5cfb4 100644 --- a/src/alire/alire-solver.adb +++ b/src/alire/alire-solver.adb @@ -699,6 +699,26 @@ package body Alire.Solver is end if; end Detect_Unavailable_Direct_Dependencies; + ---------------- + -- Trace_Pins -- + ---------------- + + procedure Trace_Pins is + begin + if (for some State of Current.All_Dependencies => + State.Is_User_Pinned) + then + Trace.Detail ("User pins to apply:"); + for State of Current.All_Dependencies loop + if State.Is_User_Pinned then + Trace.Detail (" " & State.TTY_Image); + end if; + end loop; + else + Trace.Detail ("No user pins to apply"); + end if; + end Trace_Pins; + Full_Dependencies : constant Conditional.Dependencies := Tree'(Current.Pins and Deps).Evaluate (Props); -- Include pins before other dependencies. This ensures their dependency @@ -713,6 +733,10 @@ package body Alire.Solver is Trace.Detail ("Solving dependencies with options: " & Image (Options)); + Trace.Detail ("Root dependency tree is: " + & Full_Dependencies.Image_One_Line); + Trace_Pins; + -- Warn if we foresee things taking a loong time... if Options.Completeness = All_Incomplete then diff --git a/src/alire/alire-solver.ads b/src/alire/alire-solver.ads index 9270eb5ef..c8db29eda 100644 --- a/src/alire/alire-solver.ads +++ b/src/alire/alire-solver.ads @@ -3,6 +3,7 @@ with Alire.Index; with Alire.Properties; with Alire.Solutions; with Alire.Types; +with Alire.User_Pins.Maps; with Semantic_Versioning.Extended; @@ -53,8 +54,8 @@ package Alire.Solver is -- releases will be used normally; otherwise a crate with only externals -- will always cause failure. + subtype Pin_Map is User_Pins.Maps.Map; subtype Release is Types.Release; - subtype Solution is Solutions.Solution; -- The dependency solver (Resolve subprogram, below) receives a @@ -132,8 +133,8 @@ package Alire.Solver is Options : Query_Options := Default_Options) return Solution; -- Exhaustively look for a solution to the given dependencies, under the - -- given platform properties and lookup options. A current solution may - -- be given and pinned releases will be reused. + -- given platform properties and lookup options. Pins can be supplied to + -- override Deps. function Is_Resolvable (Deps : Types.Abstract_Dependencies; Props : Properties.Vector; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index 5237aa339..8cd9b6729 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -23,6 +23,7 @@ package Alire.User_Pins is type Pin (Kind : Kinds) is tagged private; function Is_Remote (This : Pin) return Boolean; + -- A pin to a remote source such as git, source archives, etc -- Version attributes From 09ca58959ad2bf7299e302338db70e5505a3989d Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Fri, 21 May 2021 11:35:21 +0200 Subject: [PATCH 10/25] Make version explicit key in user pin --- src/alire/alire-user_pins.adb | 17 ++++++++++++----- src/alire/alire-user_pins.ads | 7 +++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/alire/alire-user_pins.adb b/src/alire/alire-user_pins.adb index 3cc1e4ca9..0581cc240 100644 --- a/src/alire/alire-user_pins.adb +++ b/src/alire/alire-user_pins.adb @@ -5,9 +5,10 @@ with TOML; package body Alire.User_Pins is package Keys is - Commit : constant String := "commit"; - Path : constant String := "path"; - URL : constant String := "url"; + Commit : constant String := "commit"; + Path : constant String := "path"; + URL : constant String := "url"; + Version : constant String := "version"; end Keys; --------------- @@ -23,7 +24,13 @@ package body Alire.User_Pins is function From_Table (This : TOML_Adapters.Key_Queue) return Pin is use TOML; begin - if This.Contains (Keys.Path) then + if This.Contains (Keys.Version) then + return Pin' + (Kind => To_Version, + Version => Semantic_Versioning.Parse + (This.Checked_Pop (Keys.Version, TOML_String).As_String)); + + elsif This.Contains (Keys.Path) then return Result : constant Pin := (Kind => To_Path, Path => +This.Checked_Pop (Keys.Path, TOML_String).As_String) @@ -52,7 +59,7 @@ package body Alire.User_Pins is end return; else - Trace.Error ("Expecting a path or url pin, but got:"); + Trace.Error ("Unexpected key in pin, got:"); This.Print; Raise_Checked_Error ("invalid pin description"); end if; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index 8cd9b6729..bc5fa13ea 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -44,14 +44,13 @@ package Alire.User_Pins is with Pre => This.Is_Remote; function From_TOML (This : TOML_Adapters.Key_Queue) return Pin; - -- Expects the rhs of a crate = entry. This can be a string (for a - -- version) or a table (for an origin). + -- Expects the rhs of a crate = entry. The rhs is always a table. -- The TOML representation of a pin is similar to a dependency, but instead -- of a version set, we get either a precise version, or an url + commit: -- [[pins]] - -- foo = "5.6" - -- bar = { url = "git+https://blah", commit = } + -- foo = { version = "5.6" } + -- bar = { url = "git+https://blah", [commit = "deadbeef"] } private From 254b5a30aa557978158caf4f938b5a23280ba661 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Fri, 21 May 2021 12:12:07 +0200 Subject: [PATCH 11/25] Fix bug about confirming empty updates --- src/alire/alire-dependencies-states.ads | 13 +++++++++++++ src/alire/alire-solutions-diffs.adb | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/alire/alire-dependencies-states.ads b/src/alire/alire-dependencies-states.ads index cb7c0e96f..c889838ee 100644 --- a/src/alire/alire-dependencies-states.ads +++ b/src/alire/alire-dependencies-states.ads @@ -22,6 +22,12 @@ package Alire.Dependencies.States is type State (<>) is new Dependency with private; + overriding function "=" (L, R : State) return Boolean; + -- For some unclear reason, the default implementation reports differences + -- for identical states. Suspecting the Indefinite_Holders therein to be + -- the culprits. We override to rely on the same information the user sees, + -- thus avoiding any inconsistent "want to confirm?" empty updates. + ------------------ -- Constructors -- ------------------ @@ -205,6 +211,13 @@ private Transitivity : Transitivities := Unknown; end record; + --------- + -- "=" -- + --------- + + overriding function "=" (L, R : State) return Boolean + is (L.Image = R.Image); + ------------------- -- As_Dependency -- ------------------- diff --git a/src/alire/alire-solutions-diffs.adb b/src/alire/alire-solutions-diffs.adb index d986ea414..c0219a962 100644 --- a/src/alire/alire-solutions-diffs.adb +++ b/src/alire/alire-solutions-diffs.adb @@ -383,6 +383,9 @@ package body Alire.Solutions.Diffs is if Changed then Table.Print (Level); else + Trace.Warning (Boolean'(This.Former = This.Latter)'Image); + Trace.Warning (Boolean'(This.Former /= This.Latter)'Image); + Trace.Log (Prefix & "No changes between former and new solution.", Level); end if; From 5298c1a09ba7b2145199da4ce65b2d1c6da9d661 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Fri, 21 May 2021 12:37:12 +0200 Subject: [PATCH 12/25] Roots: Conflated dep updating into single Sync We had two confusing Update_Dependencies and Update_And_Deploy_Dependencies that were in practice doing almost the same. There is now a single Sync_Dependencies. --- src/alire/alire-roots.adb | 189 ++++++++++++++++++++------------------ src/alire/alire-roots.ads | 37 ++++---- src/alr/alr-commands.adb | 8 +- 3 files changed, 127 insertions(+), 107 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 0e5ce43c1..c09139b04 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -13,6 +13,7 @@ with Alire.Roots.Optional; with Alire.Solutions.Diffs; with Alire.User_Pins.Maps; with Alire.Utils.TTY; +with Alire.Utils.User_Input; with Alire.VCSs.Git; with GNAT.OS_Lib; @@ -737,7 +738,8 @@ package body Alire.Roots is -- Sync_From_Manifest -- ------------------------ - procedure Sync_From_Manifest (This : in out Root) is + procedure Sync_From_Manifest (This : in out Root; + Silent : Boolean) is Old_Solution : constant Solutions.Solution := This.Solution; begin if This.Is_Lockfile_Outdated then @@ -748,8 +750,9 @@ package body Alire.Roots is -- a non-exhaustive sync of pins, that will anyway detect evident -- changes (new/removed pins, changed explicit commits). - This.Update_And_Deploy_Dependencies (Old_Sol => Old_Solution, - Confirm => False); + This.Sync_Dependencies (Old => Old_Solution, + Silent => Silent); + -- Don't ask for confirmation as this is an automatic update in -- reaction to a manually edited manifest, and we need the lockfile -- to match the manifest. As any change in dependencies will be @@ -801,6 +804,7 @@ package body Alire.Roots is procedure Update (This : in out Root; Allowed : Containers.Crate_Name_Sets.Set) is + Old : constant Solutions.Solution := This.Solution; begin This.Sync_Pins_From_Manifest (Exhaustive => True, Allowed => Allowed); @@ -809,8 +813,9 @@ package body Alire.Roots is -- And look for updates in dependencies - This.Update_Dependencies + This.Sync_Dependencies (Allowed => Allowed, + Old => Old, Silent => Alire.Utils.User_Input.Not_Interactive); end Update; @@ -852,80 +857,90 @@ package body Alire.Roots is Options => Options); end Compute_Update; - ------------------------- - -- Update_Dependencies -- - ------------------------- + ----------------------- + -- Sync_Dependencies -- + ----------------------- - procedure Update_Dependencies + procedure Sync_Dependencies (This : in out Root; Silent : Boolean; + Old : Solutions.Solution := Solutions.Empty_Invalid_Solution; Options : Solver.Query_Options := Solver.Default_Options; Allowed : Containers.Crate_Name_Sets.Set := Alire.Containers.Crate_Name_Sets.Empty_Set) is - Old : constant Solutions.Solution := This.Solution; begin + declare + -- Shadow the argument with the one we want to use everywhere + Old : constant Solutions.Solution := + (if Sync_Dependencies.Old.Is_Attempted + then Sync_Dependencies.Old + else This.Solution); - -- Ensure requested crates are in solution first. - - for Crate of Allowed loop - if not Old.Depends_On (Crate) then - Raise_Checked_Error ("Requested crate is not a dependency: " - & TTY.Name (Crate)); - end if; + begin - if Old.Pins.Contains (Crate) then - -- The solver will never update a pinned crate, so we may allow - -- this to be attempted but it will have no effect. - Recoverable_Error - ("Requested crate is pinned and cannot be updated: " - & Alire.Utils.TTY.Name (Crate)); - end if; - end loop; + -- Ensure requested crates are in solution first. - declare - Needed : constant Solutions.Solution := This.Compute_Update - (Allowed, Options); - Diff : constant Solutions.Diffs.Diff := Old.Changes (Needed); - begin - -- Early exit when there are no changes + for Crate of Allowed loop + if not Old.Depends_On (Crate) then + Raise_Checked_Error ("Requested crate is not a dependency: " + & TTY.Name (Crate)); + end if; - if not Alire.Force and not Diff.Contains_Changes then - if not Needed.Is_Complete then - Trace.Warning - ("There are missing dependencies" - & " (use `alr with --solve` for details)."); + if Old.Pins.Contains (Crate) then + -- The solver will never update a pinned crate, so we may allow + -- this to be attempted but it will have no effect. + Recoverable_Error + ("Requested crate is pinned and cannot be updated: " + & Alire.Utils.TTY.Name (Crate)); end if; + end loop; - This.Sync_Manifest_And_Lockfile_Timestamps; - -- Just in case manual changes in manifest don't modify solution + declare + Needed : constant Solutions.Solution := This.Compute_Update + (Allowed, Options); + Diff : constant Solutions.Diffs.Diff := Old.Changes (Needed); + begin + -- Early exit when there are no changes - Trace.Info ("Nothing to update."); + if not Alire.Force and not Diff.Contains_Changes then + if not Needed.Is_Complete then + Trace.Warning + ("There are missing dependencies" + & " (use `alr with --solve` for details)."); + end if; - return; - end if; + This.Sync_Manifest_And_Lockfile_Timestamps; + -- In case manual changes in manifest do not modify the + -- solution. - -- Show changes and optionally ask user to apply them + Trace.Info ("Nothing to update."); - if Silent then - Trace.Info ("Dependencies automatically updated as follows:"); - Diff.Print; - elsif not Utils.User_Input.Confirm_Solution_Changes (Diff) then - Trace.Detail ("Update abandoned."); - return; - end if; + return; + end if; - -- Apply the update + -- Show changes and optionally ask user to apply them - This.Set (Solution => Needed); - This.Deploy_Dependencies; + if Silent then + Trace.Info ("Dependencies automatically updated as follows:"); + Diff.Print; + elsif not Utils.User_Input.Confirm_Solution_Changes (Diff) then + Trace.Detail ("Update abandoned."); + return; + end if; + + -- Apply the update + + This.Set (Solution => Needed); + This.Deploy_Dependencies; - -- Update/Create configuration files - This.Generate_Configuration; + -- Update/Create configuration files + This.Generate_Configuration; - Trace.Detail ("Update completed"); + Trace.Detail ("Update completed"); + end; end; - end Update_Dependencies; + end Sync_Dependencies; ---------------------- -- Pinned_To_Remote -- @@ -1103,38 +1118,38 @@ package body Alire.Roots is -- Update_And_Deploy_Dependencies -- ------------------------------------ - procedure Update_And_Deploy_Dependencies - (This : in out Roots.Root; - Options : Solver.Query_Options := Solver.Default_Options; - Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; - Confirm : Boolean := not Utils.User_Input.Not_Interactive) - is - Prev : constant Solutions.Solution := - (if Old_Sol.Is_Attempted - then Old_Sol - else This.Solution); - Next : constant Solutions.Solution := - This.Compute_Update (Options => Options); - Diff : constant Solutions.Diffs.Diff := Prev.Changes (Next); - begin - if Diff.Contains_Changes then - if not Confirm or else - Utils.User_Input.Confirm_Solution_Changes (Diff) - then - if not Confirm then - Trace.Info ("Changes to dependency solution:"); - Diff.Print (Changed_Only => not Alire.Detailed); - end if; - - This.Set (Solution => Next); - This.Deploy_Dependencies; - end if; - end if; - - -- Update/Create configuration files - This.Generate_Configuration; - - end Update_And_Deploy_Dependencies; + -- procedure Update_And_Deploy_Dependencies + -- (This : in out Roots.Root; + -- Options : Solver.Query_Options := Solver.Default_Options; + -- Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; +-- Confirm : Boolean := not Utils.User_Input.Not_Interactive) + -- is + -- Prev : constant Solutions.Solution := + -- (if Old_Sol.Is_Attempted + -- then Old_Sol + -- else This.Solution); + -- Next : constant Solutions.Solution := + -- This.Compute_Update (Options => Options); + -- Diff : constant Solutions.Diffs.Diff := Prev.Changes (Next); + -- begin + -- if Diff.Contains_Changes then + -- if not Confirm or else + -- Utils.User_Input.Confirm_Solution_Changes (Diff) + -- then + -- if not Confirm then + -- Trace.Info ("Changes to dependency solution:"); + -- Diff.Print (Changed_Only => not Alire.Detailed); + -- end if; + -- + -- This.Set (Solution => Next); + -- This.Deploy_Dependencies; + -- end if; + -- end if; + -- + -- -- Update/Create configuration files + -- This.Generate_Configuration; + -- + -- end Update_And_Deploy_Dependencies; -------------------- -- Write_Manifest -- diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 32db1457c..0b66dfd72 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -9,7 +9,7 @@ with Alire.Properties; with Alire.Releases; with Alire.Solutions; with Alire.Solver; -with Alire.Utils.User_Input; +with Alire.Utils; package Alire.Roots is @@ -122,14 +122,15 @@ package Alire.Roots is -- conceivably we could use checksums to make it more robust against -- automated changes within the same second. - procedure Sync_From_Manifest (This : in out Root); + procedure Sync_From_Manifest (This : in out Root; + Silent : Boolean); -- 1) Pre-deploy any remote pins in the manifest so they are usable when -- solving, and apply any local/version pins. 2) Ensure that dependencies -- are up to date in regard to the lockfile and manifest: if the manifest -- is newer than the lockfile, resolve again, as dependencies may have been -- edited by hand. 3) Ensure that releases in the lockfile are actually -- on disk (may be missing if cache was deleted, or the crate was just - -- cloned). + -- cloned). When Silent, run as in non-interactive mode. procedure Sync_Manifest_And_Lockfile_Timestamps (This : Root) with Post => not This.Is_Lockfile_Outdated; @@ -149,9 +150,6 @@ package Alire.Roots is -- This function loads configured indexes from disk. No changes are -- applied to This root. - procedure Deploy_Dependencies (This : in out Root); - -- Download all dependencies not already on disk from This.Solution - procedure Update (This : in out Root; Allowed : Containers.Crate_Name_Sets.Set); -- Full update, explicitly requested. Will fetch/prune pins, update any @@ -159,21 +157,28 @@ package Alire.Roots is -- empty set of crates to which the update will be limited. Everything is -- updatable if Allowed.Is_Empty. - procedure Update_Dependencies + procedure Deploy_Dependencies (This : in out Root); + -- Download all dependencies not already on disk from This.Solution + + procedure Sync_Dependencies (This : in out Root; Silent : Boolean; + Old : Solutions.Solution := Solutions.Empty_Invalid_Solution; Options : Solver.Query_Options := Solver.Default_Options; Allowed : Containers.Crate_Name_Sets.Set := Alire.Containers.Crate_Name_Sets.Empty_Set); - -- Resolve and update all or given crates in a root. When silent, run - -- as in non-interactive mode as this is an automatically-triggered update. - - procedure Update_And_Deploy_Dependencies - (This : in out Roots.Root; - Options : Solver.Query_Options := Solver.Default_Options; - Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; - Confirm : Boolean := not Utils.User_Input.Not_Interactive); - -- Call Update and Deploy_Dependencies in succession for the given root. + -- Resolve and update all or given crates in a root, and regenerate + -- configuration. When Silent, run as in non-interactive mode as this is an + -- automatically-triggered update. Old_Sol is used to present differences, + -- and when left at the default invalid argument value, This.Solution will + -- be used as old solution. + +-- procedure Update_And_Deploy_Dependencies + -- (This : in out Roots.Root; + -- Options : Solver.Query_Options := Solver.Default_Options; + -- Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; +-- Confirm : Boolean := not Utils.User_Input.Not_Interactive); +-- -- Call Update and Deploy_Dependencies in succession for the given root. -- Old_Sol is used to present differences, and when left at the default -- invalid argument value, Root.Solution will be used as old solution. diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index 94d0ec0ce..c55e5ec0f 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -610,7 +610,7 @@ package body Alr.Commands is if Checked.Solution.Is_Attempted then -- Check deps on disk match those in lockfile Cmd.Requires_Full_Index (Strict => False); - Checked.Sync_From_Manifest; + Checked.Sync_From_Manifest (Silent => True); return; else Notify_Of_Initialization; @@ -627,8 +627,8 @@ package body Alr.Commands is Trace.Warning ("This workspace was created with a previous alr version." & " Internal data is going to be updated and, as a result," - & " any existing pins will be unpinned and will need to be" - & " manually recreated."); + & " a fresh solution will be computed that may result in" + & " crate upgrades"); Alire.Directories.Backup_If_Existing (Checked.Lock_File, Base_Dir => Alire.Paths.Working_Folder_Inside_Root); @@ -668,7 +668,7 @@ package body Alr.Commands is if Sync then Cmd.Requires_Full_Index (Strict => False); - Checked.Update_Dependencies (Silent => True); + Checked.Sync_Dependencies (Silent => True); end if; end; end Requires_Valid_Session; From d622f05d9ef63372e7b2a646aa6ee4a2e71d4e55 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 14 Jun 2021 16:12:33 +0200 Subject: [PATCH 13/25] Disable tests that rely on `alr pin` For now, these cannot work as we are going to remove the ability to edit pins via `alr with`/`alr pin`. This functionality could be reintroduced at a later time. --- src/alire/alire-solutions-diffs.adb | 3 --- .../pin/post-update/my_index/index/index.toml | 0 .../my_index/index/li/libchild/libchild-0.1.0.toml | 0 .../my_index/index/li/libchild/libchild-0.2.0.toml | 0 .../my_index/index/li/libparent/libparent-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/post-update/test.py | 0 testsuite/{tests => disabled}/pin/post-update/test.yaml | 0 testsuite/{tests => disabled}/pin/unpin/test.py | 0 testsuite/{tests => disabled}/pin/unpin/test.yaml | 0 testsuite/{tests => disabled}/update/missing-deps/test.py | 0 .../{tests => disabled}/update/missing-deps/test.yaml | 0 testsuite/{tests => disabled}/update/pinned/test.py | 0 testsuite/{tests => disabled}/update/pinned/test.yaml | 0 testsuite/{tests => disabled}/with/pin-transitive/test.py | 2 +- .../{tests => disabled}/with/pin-transitive/test.yaml | 0 testsuite/tests/printenv/with-external/test.py | 7 ++++--- 16 files changed, 5 insertions(+), 7 deletions(-) rename testsuite/{tests => disabled}/pin/post-update/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{tests => disabled}/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{tests => disabled}/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/post-update/test.py (100%) rename testsuite/{tests => disabled}/pin/post-update/test.yaml (100%) rename testsuite/{tests => disabled}/pin/unpin/test.py (100%) rename testsuite/{tests => disabled}/pin/unpin/test.yaml (100%) rename testsuite/{tests => disabled}/update/missing-deps/test.py (100%) rename testsuite/{tests => disabled}/update/missing-deps/test.yaml (100%) rename testsuite/{tests => disabled}/update/pinned/test.py (100%) rename testsuite/{tests => disabled}/update/pinned/test.yaml (100%) rename testsuite/{tests => disabled}/with/pin-transitive/test.py (94%) rename testsuite/{tests => disabled}/with/pin-transitive/test.yaml (100%) diff --git a/src/alire/alire-solutions-diffs.adb b/src/alire/alire-solutions-diffs.adb index c0219a962..d986ea414 100644 --- a/src/alire/alire-solutions-diffs.adb +++ b/src/alire/alire-solutions-diffs.adb @@ -383,9 +383,6 @@ package body Alire.Solutions.Diffs is if Changed then Table.Print (Level); else - Trace.Warning (Boolean'(This.Former = This.Latter)'Image); - Trace.Warning (Boolean'(This.Former /= This.Latter)'Image); - Trace.Log (Prefix & "No changes between former and new solution.", Level); end if; diff --git a/testsuite/tests/pin/post-update/my_index/index/index.toml b/testsuite/disabled/pin/post-update/my_index/index/index.toml similarity index 100% rename from testsuite/tests/pin/post-update/my_index/index/index.toml rename to testsuite/disabled/pin/post-update/my_index/index/index.toml diff --git a/testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/tests/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/disabled/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/disabled/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/tests/pin/post-update/test.py b/testsuite/disabled/pin/post-update/test.py similarity index 100% rename from testsuite/tests/pin/post-update/test.py rename to testsuite/disabled/pin/post-update/test.py diff --git a/testsuite/tests/pin/post-update/test.yaml b/testsuite/disabled/pin/post-update/test.yaml similarity index 100% rename from testsuite/tests/pin/post-update/test.yaml rename to testsuite/disabled/pin/post-update/test.yaml diff --git a/testsuite/tests/pin/unpin/test.py b/testsuite/disabled/pin/unpin/test.py similarity index 100% rename from testsuite/tests/pin/unpin/test.py rename to testsuite/disabled/pin/unpin/test.py diff --git a/testsuite/tests/pin/unpin/test.yaml b/testsuite/disabled/pin/unpin/test.yaml similarity index 100% rename from testsuite/tests/pin/unpin/test.yaml rename to testsuite/disabled/pin/unpin/test.yaml diff --git a/testsuite/tests/update/missing-deps/test.py b/testsuite/disabled/update/missing-deps/test.py similarity index 100% rename from testsuite/tests/update/missing-deps/test.py rename to testsuite/disabled/update/missing-deps/test.py diff --git a/testsuite/tests/update/missing-deps/test.yaml b/testsuite/disabled/update/missing-deps/test.yaml similarity index 100% rename from testsuite/tests/update/missing-deps/test.yaml rename to testsuite/disabled/update/missing-deps/test.yaml diff --git a/testsuite/tests/update/pinned/test.py b/testsuite/disabled/update/pinned/test.py similarity index 100% rename from testsuite/tests/update/pinned/test.py rename to testsuite/disabled/update/pinned/test.py diff --git a/testsuite/tests/update/pinned/test.yaml b/testsuite/disabled/update/pinned/test.yaml similarity index 100% rename from testsuite/tests/update/pinned/test.yaml rename to testsuite/disabled/update/pinned/test.yaml diff --git a/testsuite/tests/with/pin-transitive/test.py b/testsuite/disabled/with/pin-transitive/test.py similarity index 94% rename from testsuite/tests/with/pin-transitive/test.py rename to testsuite/disabled/with/pin-transitive/test.py index ba8df7456..69f7a1a05 100644 --- a/testsuite/tests/with/pin-transitive/test.py +++ b/testsuite/disabled/with/pin-transitive/test.py @@ -10,7 +10,7 @@ # The test will create ./indirect, ./direct, and ./nest/base crates. # Then they are pinned as base -> direct -> indirect. As "base" has a different -# relative path to "indirect" that "direct", this is also checked. +# relative path to "indirect" than "direct", this is also checked. init_local_crate(name="indirect", binary=False, enter=False) diff --git a/testsuite/tests/with/pin-transitive/test.yaml b/testsuite/disabled/with/pin-transitive/test.yaml similarity index 100% rename from testsuite/tests/with/pin-transitive/test.yaml rename to testsuite/disabled/with/pin-transitive/test.yaml diff --git a/testsuite/tests/printenv/with-external/test.py b/testsuite/tests/printenv/with-external/test.py index ab8072ea4..6a8163840 100644 --- a/testsuite/tests/printenv/with-external/test.py +++ b/testsuite/tests/printenv/with-external/test.py @@ -21,15 +21,16 @@ p = run_alr('printenv', quiet=False) assert_eq(0, p.status) -expected_gpr_path="" +expected_gpr_path = "" if platform.system() == 'Windows': expected_gpr_path = '.*\\\\libhello_0.9.0_filesystem' else: expected_gpr_path = '.*/libhello_0.9.0_filesystem' # Check the printenv output -assert_match('warn: Generating incomplete environment' # Note: this warning is - ' because of missing dependencies\n' # via stderr so it's OK +assert_match('warn: Generating possibly incomplete environment' + ' because of missing dependencies\n' + # Note: this warning is via stderr so it's OK '.*' 'export ALIRE="True"\n' '.*' From aeb52cdaaf36617c4d3eb5b88bba90000a784898 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 14 Jun 2021 16:54:19 +0200 Subject: [PATCH 14/25] More tests temporarily disabled Most of those should be reimplemented in their manual edition alternative --- .../get/indirect-link/my_index/index/index.toml | 0 .../get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml | 0 .../get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml | 0 .../get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml | 0 testsuite/{tests => disabled}/get/indirect-link/test.py | 0 testsuite/{tests => disabled}/get/indirect-link/test.yaml | 0 .../pin/all/my_index/index/he/hello1/hello1-0.1.0.toml | 0 .../pin/all/my_index/index/he/hello2/hello2-0.1.0.toml | 0 testsuite/{tests => disabled}/pin/all/my_index/index/index.toml | 0 testsuite/{tests => disabled}/pin/all/test.py | 0 testsuite/{tests => disabled}/pin/all/test.yaml | 0 testsuite/{tests => disabled}/pin/change-type/my_index/index.toml | 0 .../pin/change-type/my_index/li/libhello/libhello-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/change-type/test.py | 0 testsuite/{tests => disabled}/pin/change-type/test.yaml | 0 testsuite/{tests => disabled}/pin/dir-crate/test.py | 0 testsuite/{tests => disabled}/pin/dir-crate/test.yaml | 0 testsuite/{tests => disabled}/pin/dir-mismatch/test.py | 0 testsuite/{tests => disabled}/pin/dir-mismatch/test.yaml | 0 .../{tests => disabled}/pin/downgrade/my_index/index/index.toml | 0 .../pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml | 0 .../pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml | 0 .../downgrade/my_index/index/li/libparent/libparent-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/downgrade/test.py | 0 testsuite/{tests => disabled}/pin/downgrade/test.yaml | 0 testsuite/{tests => disabled}/pin/missing-version/test.py | 0 testsuite/{tests => disabled}/pin/missing-version/test.yaml | 0 .../pin/pin-dir-with-regular/my_index/index.toml | 0 .../pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/pin-dir-with-regular/test.py | 0 testsuite/{tests => disabled}/pin/pin-dir-with-regular/test.yaml | 0 testsuite/{tests => disabled}/pin/pin-dir/my_index/index.toml | 0 .../pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/pin-dir/test.py | 0 testsuite/{tests => disabled}/pin/pin-dir/test.yaml | 0 testsuite/{tests => disabled}/pin/remote/test.py | 0 testsuite/{tests => disabled}/pin/remote/test.yaml | 0 .../pin/unneeded-held/my_index/index/index.toml | 0 .../unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml | 0 .../unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml | 0 .../my_index/index/li/libparent/libparent-1.0.0.toml | 0 testsuite/{tests => disabled}/pin/unneeded-held/test.py | 0 testsuite/{tests => disabled}/pin/unneeded-held/test.yaml | 0 .../printenv/linked-paths/my_index/crates/crate_1234/.emptydir | 0 .../printenv/linked-paths/my_index/crates/crate_1234/alire.toml | 0 .../linked-paths/my_index/crates/crate_1234/alire/.emptydir | 0 .../printenv/linked-paths/my_index/index/index.toml | 0 testsuite/{tests => disabled}/printenv/linked-paths/test.py | 0 testsuite/{tests => disabled}/printenv/linked-paths/test.yaml | 0 testsuite/{tests => disabled}/with/changes-info/test.py | 0 testsuite/{tests => disabled}/with/changes-info/test.yaml | 0 .../{tests => disabled}/with/pin-dir-crate-autodetect/test.py | 0 .../{tests => disabled}/with/pin-dir-crate-autodetect/test.yaml | 0 testsuite/{tests => disabled}/with/pin-dir-crate/test.py | 0 testsuite/{tests => disabled}/with/pin-dir-crate/test.yaml | 0 testsuite/{tests => disabled}/with/pin-dir-mismatch/test.py | 0 testsuite/{tests => disabled}/with/pin-dir-mismatch/test.yaml | 0 .../with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr | 0 .../with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads | 0 .../{tests => disabled}/with/pin-dir/my_index/index/index.toml | 0 .../with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml | 0 testsuite/{tests => disabled}/with/pin-dir/test.py | 0 testsuite/{tests => disabled}/with/pin-dir/test.yaml | 0 testsuite/{tests => disabled}/with/tree-switch/test.py | 0 testsuite/{tests => disabled}/with/tree-switch/test.yaml | 0 testsuite/{tests => disabled}/with/versions-switch/test.py | 0 testsuite/{tests => disabled}/with/versions-switch/test.yaml | 0 testsuite/{tests => disabled}/workflows/init-with-pin/test.py | 0 testsuite/{tests => disabled}/workflows/init-with-pin/test.yaml | 0 69 files changed, 0 insertions(+), 0 deletions(-) rename testsuite/{tests => disabled}/get/indirect-link/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml (100%) rename testsuite/{tests => disabled}/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml (100%) rename testsuite/{tests => disabled}/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml (100%) rename testsuite/{tests => disabled}/get/indirect-link/test.py (100%) rename testsuite/{tests => disabled}/get/indirect-link/test.yaml (100%) rename testsuite/{tests => disabled}/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml (100%) rename testsuite/{tests => disabled}/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml (100%) rename testsuite/{tests => disabled}/pin/all/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/pin/all/test.py (100%) rename testsuite/{tests => disabled}/pin/all/test.yaml (100%) rename testsuite/{tests => disabled}/pin/change-type/my_index/index.toml (100%) rename testsuite/{tests => disabled}/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/change-type/test.py (100%) rename testsuite/{tests => disabled}/pin/change-type/test.yaml (100%) rename testsuite/{tests => disabled}/pin/dir-crate/test.py (100%) rename testsuite/{tests => disabled}/pin/dir-crate/test.yaml (100%) rename testsuite/{tests => disabled}/pin/dir-mismatch/test.py (100%) rename testsuite/{tests => disabled}/pin/dir-mismatch/test.yaml (100%) rename testsuite/{tests => disabled}/pin/downgrade/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{tests => disabled}/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{tests => disabled}/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/downgrade/test.py (100%) rename testsuite/{tests => disabled}/pin/downgrade/test.yaml (100%) rename testsuite/{tests => disabled}/pin/missing-version/test.py (100%) rename testsuite/{tests => disabled}/pin/missing-version/test.yaml (100%) rename testsuite/{tests => disabled}/pin/pin-dir-with-regular/my_index/index.toml (100%) rename testsuite/{tests => disabled}/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/pin-dir-with-regular/test.py (100%) rename testsuite/{tests => disabled}/pin/pin-dir-with-regular/test.yaml (100%) rename testsuite/{tests => disabled}/pin/pin-dir/my_index/index.toml (100%) rename testsuite/{tests => disabled}/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/pin-dir/test.py (100%) rename testsuite/{tests => disabled}/pin/pin-dir/test.yaml (100%) rename testsuite/{tests => disabled}/pin/remote/test.py (100%) rename testsuite/{tests => disabled}/pin/remote/test.yaml (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/test.py (100%) rename testsuite/{tests => disabled}/pin/unneeded-held/test.yaml (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/my_index/crates/crate_1234/.emptydir (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/my_index/crates/crate_1234/alire.toml (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/test.py (100%) rename testsuite/{tests => disabled}/printenv/linked-paths/test.yaml (100%) rename testsuite/{tests => disabled}/with/changes-info/test.py (100%) rename testsuite/{tests => disabled}/with/changes-info/test.yaml (100%) rename testsuite/{tests => disabled}/with/pin-dir-crate-autodetect/test.py (100%) rename testsuite/{tests => disabled}/with/pin-dir-crate-autodetect/test.yaml (100%) rename testsuite/{tests => disabled}/with/pin-dir-crate/test.py (100%) rename testsuite/{tests => disabled}/with/pin-dir-crate/test.yaml (100%) rename testsuite/{tests => disabled}/with/pin-dir-mismatch/test.py (100%) rename testsuite/{tests => disabled}/with/pin-dir-mismatch/test.yaml (100%) rename testsuite/{tests => disabled}/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr (100%) rename testsuite/{tests => disabled}/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads (100%) rename testsuite/{tests => disabled}/with/pin-dir/my_index/index/index.toml (100%) rename testsuite/{tests => disabled}/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{tests => disabled}/with/pin-dir/test.py (100%) rename testsuite/{tests => disabled}/with/pin-dir/test.yaml (100%) rename testsuite/{tests => disabled}/with/tree-switch/test.py (100%) rename testsuite/{tests => disabled}/with/tree-switch/test.yaml (100%) rename testsuite/{tests => disabled}/with/versions-switch/test.py (100%) rename testsuite/{tests => disabled}/with/versions-switch/test.yaml (100%) rename testsuite/{tests => disabled}/workflows/init-with-pin/test.py (100%) rename testsuite/{tests => disabled}/workflows/init-with-pin/test.yaml (100%) diff --git a/testsuite/tests/get/indirect-link/my_index/index/index.toml b/testsuite/disabled/get/indirect-link/my_index/index/index.toml similarity index 100% rename from testsuite/tests/get/indirect-link/my_index/index/index.toml rename to testsuite/disabled/get/indirect-link/my_index/index/index.toml diff --git a/testsuite/tests/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml b/testsuite/disabled/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml similarity index 100% rename from testsuite/tests/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml rename to testsuite/disabled/get/indirect-link/my_index/index/ti/tier1/tier1-1.0.0.toml diff --git a/testsuite/tests/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml b/testsuite/disabled/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml similarity index 100% rename from testsuite/tests/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml rename to testsuite/disabled/get/indirect-link/my_index/index/ti/tier2/tier2-1.0.0.toml diff --git a/testsuite/tests/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml b/testsuite/disabled/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml similarity index 100% rename from testsuite/tests/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml rename to testsuite/disabled/get/indirect-link/my_index/index/ti/tier3/tier3-1.0.0.toml diff --git a/testsuite/tests/get/indirect-link/test.py b/testsuite/disabled/get/indirect-link/test.py similarity index 100% rename from testsuite/tests/get/indirect-link/test.py rename to testsuite/disabled/get/indirect-link/test.py diff --git a/testsuite/tests/get/indirect-link/test.yaml b/testsuite/disabled/get/indirect-link/test.yaml similarity index 100% rename from testsuite/tests/get/indirect-link/test.yaml rename to testsuite/disabled/get/indirect-link/test.yaml diff --git a/testsuite/tests/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml b/testsuite/disabled/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml similarity index 100% rename from testsuite/tests/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml rename to testsuite/disabled/pin/all/my_index/index/he/hello1/hello1-0.1.0.toml diff --git a/testsuite/tests/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml b/testsuite/disabled/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml similarity index 100% rename from testsuite/tests/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml rename to testsuite/disabled/pin/all/my_index/index/he/hello2/hello2-0.1.0.toml diff --git a/testsuite/tests/pin/all/my_index/index/index.toml b/testsuite/disabled/pin/all/my_index/index/index.toml similarity index 100% rename from testsuite/tests/pin/all/my_index/index/index.toml rename to testsuite/disabled/pin/all/my_index/index/index.toml diff --git a/testsuite/tests/pin/all/test.py b/testsuite/disabled/pin/all/test.py similarity index 100% rename from testsuite/tests/pin/all/test.py rename to testsuite/disabled/pin/all/test.py diff --git a/testsuite/tests/pin/all/test.yaml b/testsuite/disabled/pin/all/test.yaml similarity index 100% rename from testsuite/tests/pin/all/test.yaml rename to testsuite/disabled/pin/all/test.yaml diff --git a/testsuite/tests/pin/change-type/my_index/index.toml b/testsuite/disabled/pin/change-type/my_index/index.toml similarity index 100% rename from testsuite/tests/pin/change-type/my_index/index.toml rename to testsuite/disabled/pin/change-type/my_index/index.toml diff --git a/testsuite/tests/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/disabled/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/disabled/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/tests/pin/change-type/test.py b/testsuite/disabled/pin/change-type/test.py similarity index 100% rename from testsuite/tests/pin/change-type/test.py rename to testsuite/disabled/pin/change-type/test.py diff --git a/testsuite/tests/pin/change-type/test.yaml b/testsuite/disabled/pin/change-type/test.yaml similarity index 100% rename from testsuite/tests/pin/change-type/test.yaml rename to testsuite/disabled/pin/change-type/test.yaml diff --git a/testsuite/tests/pin/dir-crate/test.py b/testsuite/disabled/pin/dir-crate/test.py similarity index 100% rename from testsuite/tests/pin/dir-crate/test.py rename to testsuite/disabled/pin/dir-crate/test.py diff --git a/testsuite/tests/pin/dir-crate/test.yaml b/testsuite/disabled/pin/dir-crate/test.yaml similarity index 100% rename from testsuite/tests/pin/dir-crate/test.yaml rename to testsuite/disabled/pin/dir-crate/test.yaml diff --git a/testsuite/tests/pin/dir-mismatch/test.py b/testsuite/disabled/pin/dir-mismatch/test.py similarity index 100% rename from testsuite/tests/pin/dir-mismatch/test.py rename to testsuite/disabled/pin/dir-mismatch/test.py diff --git a/testsuite/tests/pin/dir-mismatch/test.yaml b/testsuite/disabled/pin/dir-mismatch/test.yaml similarity index 100% rename from testsuite/tests/pin/dir-mismatch/test.yaml rename to testsuite/disabled/pin/dir-mismatch/test.yaml diff --git a/testsuite/tests/pin/downgrade/my_index/index/index.toml b/testsuite/disabled/pin/downgrade/my_index/index/index.toml similarity index 100% rename from testsuite/tests/pin/downgrade/my_index/index/index.toml rename to testsuite/disabled/pin/downgrade/my_index/index/index.toml diff --git a/testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/tests/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/disabled/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/disabled/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/tests/pin/downgrade/test.py b/testsuite/disabled/pin/downgrade/test.py similarity index 100% rename from testsuite/tests/pin/downgrade/test.py rename to testsuite/disabled/pin/downgrade/test.py diff --git a/testsuite/tests/pin/downgrade/test.yaml b/testsuite/disabled/pin/downgrade/test.yaml similarity index 100% rename from testsuite/tests/pin/downgrade/test.yaml rename to testsuite/disabled/pin/downgrade/test.yaml diff --git a/testsuite/tests/pin/missing-version/test.py b/testsuite/disabled/pin/missing-version/test.py similarity index 100% rename from testsuite/tests/pin/missing-version/test.py rename to testsuite/disabled/pin/missing-version/test.py diff --git a/testsuite/tests/pin/missing-version/test.yaml b/testsuite/disabled/pin/missing-version/test.yaml similarity index 100% rename from testsuite/tests/pin/missing-version/test.yaml rename to testsuite/disabled/pin/missing-version/test.yaml diff --git a/testsuite/tests/pin/pin-dir-with-regular/my_index/index.toml b/testsuite/disabled/pin/pin-dir-with-regular/my_index/index.toml similarity index 100% rename from testsuite/tests/pin/pin-dir-with-regular/my_index/index.toml rename to testsuite/disabled/pin/pin-dir-with-regular/my_index/index.toml diff --git a/testsuite/tests/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/disabled/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/disabled/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/tests/pin/pin-dir-with-regular/test.py b/testsuite/disabled/pin/pin-dir-with-regular/test.py similarity index 100% rename from testsuite/tests/pin/pin-dir-with-regular/test.py rename to testsuite/disabled/pin/pin-dir-with-regular/test.py diff --git a/testsuite/tests/pin/pin-dir-with-regular/test.yaml b/testsuite/disabled/pin/pin-dir-with-regular/test.yaml similarity index 100% rename from testsuite/tests/pin/pin-dir-with-regular/test.yaml rename to testsuite/disabled/pin/pin-dir-with-regular/test.yaml diff --git a/testsuite/tests/pin/pin-dir/my_index/index.toml b/testsuite/disabled/pin/pin-dir/my_index/index.toml similarity index 100% rename from testsuite/tests/pin/pin-dir/my_index/index.toml rename to testsuite/disabled/pin/pin-dir/my_index/index.toml diff --git a/testsuite/tests/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/disabled/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/disabled/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/tests/pin/pin-dir/test.py b/testsuite/disabled/pin/pin-dir/test.py similarity index 100% rename from testsuite/tests/pin/pin-dir/test.py rename to testsuite/disabled/pin/pin-dir/test.py diff --git a/testsuite/tests/pin/pin-dir/test.yaml b/testsuite/disabled/pin/pin-dir/test.yaml similarity index 100% rename from testsuite/tests/pin/pin-dir/test.yaml rename to testsuite/disabled/pin/pin-dir/test.yaml diff --git a/testsuite/tests/pin/remote/test.py b/testsuite/disabled/pin/remote/test.py similarity index 100% rename from testsuite/tests/pin/remote/test.py rename to testsuite/disabled/pin/remote/test.py diff --git a/testsuite/tests/pin/remote/test.yaml b/testsuite/disabled/pin/remote/test.yaml similarity index 100% rename from testsuite/tests/pin/remote/test.yaml rename to testsuite/disabled/pin/remote/test.yaml diff --git a/testsuite/tests/pin/unneeded-held/my_index/index/index.toml b/testsuite/disabled/pin/unneeded-held/my_index/index/index.toml similarity index 100% rename from testsuite/tests/pin/unneeded-held/my_index/index/index.toml rename to testsuite/disabled/pin/unneeded-held/my_index/index/index.toml diff --git a/testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/tests/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/disabled/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/tests/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/disabled/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/tests/pin/unneeded-held/test.py b/testsuite/disabled/pin/unneeded-held/test.py similarity index 100% rename from testsuite/tests/pin/unneeded-held/test.py rename to testsuite/disabled/pin/unneeded-held/test.py diff --git a/testsuite/tests/pin/unneeded-held/test.yaml b/testsuite/disabled/pin/unneeded-held/test.yaml similarity index 100% rename from testsuite/tests/pin/unneeded-held/test.yaml rename to testsuite/disabled/pin/unneeded-held/test.yaml diff --git a/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/.emptydir b/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/.emptydir similarity index 100% rename from testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/.emptydir rename to testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/.emptydir diff --git a/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire.toml b/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire.toml similarity index 100% rename from testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire.toml rename to testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire.toml diff --git a/testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir b/testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir similarity index 100% rename from testsuite/tests/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir rename to testsuite/disabled/printenv/linked-paths/my_index/crates/crate_1234/alire/.emptydir diff --git a/testsuite/tests/printenv/linked-paths/my_index/index/index.toml b/testsuite/disabled/printenv/linked-paths/my_index/index/index.toml similarity index 100% rename from testsuite/tests/printenv/linked-paths/my_index/index/index.toml rename to testsuite/disabled/printenv/linked-paths/my_index/index/index.toml diff --git a/testsuite/tests/printenv/linked-paths/test.py b/testsuite/disabled/printenv/linked-paths/test.py similarity index 100% rename from testsuite/tests/printenv/linked-paths/test.py rename to testsuite/disabled/printenv/linked-paths/test.py diff --git a/testsuite/tests/printenv/linked-paths/test.yaml b/testsuite/disabled/printenv/linked-paths/test.yaml similarity index 100% rename from testsuite/tests/printenv/linked-paths/test.yaml rename to testsuite/disabled/printenv/linked-paths/test.yaml diff --git a/testsuite/tests/with/changes-info/test.py b/testsuite/disabled/with/changes-info/test.py similarity index 100% rename from testsuite/tests/with/changes-info/test.py rename to testsuite/disabled/with/changes-info/test.py diff --git a/testsuite/tests/with/changes-info/test.yaml b/testsuite/disabled/with/changes-info/test.yaml similarity index 100% rename from testsuite/tests/with/changes-info/test.yaml rename to testsuite/disabled/with/changes-info/test.yaml diff --git a/testsuite/tests/with/pin-dir-crate-autodetect/test.py b/testsuite/disabled/with/pin-dir-crate-autodetect/test.py similarity index 100% rename from testsuite/tests/with/pin-dir-crate-autodetect/test.py rename to testsuite/disabled/with/pin-dir-crate-autodetect/test.py diff --git a/testsuite/tests/with/pin-dir-crate-autodetect/test.yaml b/testsuite/disabled/with/pin-dir-crate-autodetect/test.yaml similarity index 100% rename from testsuite/tests/with/pin-dir-crate-autodetect/test.yaml rename to testsuite/disabled/with/pin-dir-crate-autodetect/test.yaml diff --git a/testsuite/tests/with/pin-dir-crate/test.py b/testsuite/disabled/with/pin-dir-crate/test.py similarity index 100% rename from testsuite/tests/with/pin-dir-crate/test.py rename to testsuite/disabled/with/pin-dir-crate/test.py diff --git a/testsuite/tests/with/pin-dir-crate/test.yaml b/testsuite/disabled/with/pin-dir-crate/test.yaml similarity index 100% rename from testsuite/tests/with/pin-dir-crate/test.yaml rename to testsuite/disabled/with/pin-dir-crate/test.yaml diff --git a/testsuite/tests/with/pin-dir-mismatch/test.py b/testsuite/disabled/with/pin-dir-mismatch/test.py similarity index 100% rename from testsuite/tests/with/pin-dir-mismatch/test.py rename to testsuite/disabled/with/pin-dir-mismatch/test.py diff --git a/testsuite/tests/with/pin-dir-mismatch/test.yaml b/testsuite/disabled/with/pin-dir-mismatch/test.yaml similarity index 100% rename from testsuite/tests/with/pin-dir-mismatch/test.yaml rename to testsuite/disabled/with/pin-dir-mismatch/test.yaml diff --git a/testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr b/testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr similarity index 100% rename from testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr rename to testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/libhello.gpr diff --git a/testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads b/testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads similarity index 100% rename from testsuite/tests/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads rename to testsuite/disabled/with/pin-dir/my_index/crates/libhello_1.0.0/src/libhello.ads diff --git a/testsuite/tests/with/pin-dir/my_index/index/index.toml b/testsuite/disabled/with/pin-dir/my_index/index/index.toml similarity index 100% rename from testsuite/tests/with/pin-dir/my_index/index/index.toml rename to testsuite/disabled/with/pin-dir/my_index/index/index.toml diff --git a/testsuite/tests/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml b/testsuite/disabled/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/tests/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml rename to testsuite/disabled/with/pin-dir/my_index/index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/tests/with/pin-dir/test.py b/testsuite/disabled/with/pin-dir/test.py similarity index 100% rename from testsuite/tests/with/pin-dir/test.py rename to testsuite/disabled/with/pin-dir/test.py diff --git a/testsuite/tests/with/pin-dir/test.yaml b/testsuite/disabled/with/pin-dir/test.yaml similarity index 100% rename from testsuite/tests/with/pin-dir/test.yaml rename to testsuite/disabled/with/pin-dir/test.yaml diff --git a/testsuite/tests/with/tree-switch/test.py b/testsuite/disabled/with/tree-switch/test.py similarity index 100% rename from testsuite/tests/with/tree-switch/test.py rename to testsuite/disabled/with/tree-switch/test.py diff --git a/testsuite/tests/with/tree-switch/test.yaml b/testsuite/disabled/with/tree-switch/test.yaml similarity index 100% rename from testsuite/tests/with/tree-switch/test.yaml rename to testsuite/disabled/with/tree-switch/test.yaml diff --git a/testsuite/tests/with/versions-switch/test.py b/testsuite/disabled/with/versions-switch/test.py similarity index 100% rename from testsuite/tests/with/versions-switch/test.py rename to testsuite/disabled/with/versions-switch/test.py diff --git a/testsuite/tests/with/versions-switch/test.yaml b/testsuite/disabled/with/versions-switch/test.yaml similarity index 100% rename from testsuite/tests/with/versions-switch/test.yaml rename to testsuite/disabled/with/versions-switch/test.yaml diff --git a/testsuite/tests/workflows/init-with-pin/test.py b/testsuite/disabled/workflows/init-with-pin/test.py similarity index 100% rename from testsuite/tests/workflows/init-with-pin/test.py rename to testsuite/disabled/workflows/init-with-pin/test.py diff --git a/testsuite/tests/workflows/init-with-pin/test.yaml b/testsuite/disabled/workflows/init-with-pin/test.yaml similarity index 100% rename from testsuite/tests/workflows/init-with-pin/test.yaml rename to testsuite/disabled/workflows/init-with-pin/test.yaml From d71b7aa9dcab240370c075efa27b47f85cf0e106 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 14 Jun 2021 16:59:00 +0200 Subject: [PATCH 15/25] Disable code for pin edition in command-line --- deps/optional | 2 +- src/alr/alr-commands-pin.adb | 19 ++++++++++ src/alr/alr-commands-pin.ads | 4 +++ src/alr/alr-commands-withing.adb | 61 +++++++++++++++++--------------- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/deps/optional b/deps/optional index 30aaee65d..eb929e67c 160000 --- a/deps/optional +++ b/deps/optional @@ -1 +1 @@ -Subproject commit 30aaee65d89d5a9ca1c71f6d38e4462fae2ef4ce +Subproject commit eb929e67ccd357881997d4eed5e4477144923d7c diff --git a/src/alr/alr-commands-pin.adb b/src/alr/alr-commands-pin.adb index 386204fb0..31b62fe1c 100644 --- a/src/alr/alr-commands-pin.adb +++ b/src/alr/alr-commands-pin.adb @@ -17,6 +17,20 @@ 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 -- -------------------- @@ -159,6 +173,11 @@ 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 diff --git a/src/alr/alr-commands-pin.ads b/src/alr/alr-commands-pin.ads index ffb279974..6dffb875b 100644 --- a/src/alr/alr-commands-pin.ads +++ b/src/alr/alr-commands-pin.ads @@ -26,6 +26,10 @@ 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 e5bd33659..8ed005ce7 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -8,12 +8,11 @@ with Alire.Dependencies.Diffs; with Alire.Index; with Alire.Manifest; with Alire.Releases; -with Alire.Roots.Optional; with Alire.Solutions; with Alire.Solver; -with Alire.URI; with Alire.Utils.User_Input; +with Alr.Commands.Pin; with Alr.Commands.User_Input; with Alr.OS_Lib; with Alr.Platform; @@ -111,6 +110,7 @@ package body Alr.Commands.Withing is -- We use the New_Solution with the softlink as previous solution, so -- the pinned directory is used by the solver. end Add_Remote_Link; + pragma Unreferenced (Add_Remote_Link); ------------------ -- Add_Softlink -- @@ -204,6 +204,7 @@ package body Alr.Commands.Withing is & " GNAT project as dependency)"); end if; end Detect_Softlink; + pragma Unreferenced (Detect_Softlink); --------- -- Del -- @@ -522,9 +523,9 @@ package body Alr.Commands.Withing is begin Cmd.Requires_Valid_Session; - if Cmd.URL.all /= "" then - Flags := Flags + 1; - end if; + -- if Cmd.URL.all /= "" then + -- Flags := Flags + 1; + -- end if; Check (Cmd.Del); Check (Cmd.From); @@ -567,30 +568,32 @@ package body Alr.Commands.Withing is -- Must be Add, but it could be regular or softlink if Cmd.URL.all /= "" then - if Cmd.Commit.all /= "" - or else Alire.URI.Is_HTTP_Or_Git (Cmd.URL.all) - then - - -- Pin to remote repo - - Add_Remote_Link (Cmd, - Dep => (if Num_Arguments = 1 - then Argument (1) - else "")); - - else - - -- Pin to local folder - - if Num_Arguments = 1 then - Add_Softlink (Cmd, - Dep_Spec => Argument (1), - Path => Cmd.URL.all); - else - Detect_Softlink (Cmd, - Cmd.URL.all); - end if; - end if; + Pin.Warn_Manual_Only; + + -- if Cmd.Commit.all /= "" + -- or else Alire.URI.Is_HTTP_Or_Git (Cmd.URL.all) + -- then + -- + -- -- Pin to remote repo + -- + -- Add_Remote_Link (Cmd, + -- Dep => (if Num_Arguments = 1 + -- then Argument (1) + -- else "")); + -- + -- else + -- + -- -- Pin to local folder + -- + -- if Num_Arguments = 1 then + -- Add_Softlink (Cmd, + -- Dep_Spec => Argument (1), + -- Path => Cmd.URL.all); + -- else + -- Detect_Softlink (Cmd, + -- Cmd.URL.all); + -- end if; + -- end if; else Cmd.Requires_Full_Index; Cmd.Add; From f293ec1d9202b5bdec19b897a2998df072ca5283 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 14 Jun 2021 17:51:55 +0200 Subject: [PATCH 16/25] Changes to allow pins to non-dependencies This is purely for user comfort and will probably result in dependencies having to be added at publish time. However, if we manage to restore command-line pinning, we can remove that pain by adding missing dependencies at that time. --- src/alire/alire-roots.adb | 14 +++++++++++--- src/alire/alire-roots.ads | 3 +-- src/alire/alire-solutions.adb | 16 ++++++++++++++++ src/alire/alire-solutions.ads | 21 +++++++++++++++++++++ src/alire/alire-solver.adb | 2 +- src/alr/alr-commands-withing.adb | 6 +++--- 6 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index c09139b04..1b936ad8d 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -306,6 +306,15 @@ package body Alire.Roots is Crate : constant Crate_Name := Key (I); Pin : constant User_Pins.Pin := Element (I); begin + + -- A pin for a non-dependency requires that we add a generic + -- dependency to the solution first. + + if not Sol.Depends_On (Crate) then + Sol := Sol.Depending_On + (Dependencies.New_Dependency (Crate, Semver.Extended.Any)); + end if; + case Pin.Kind is when To_Version => Sol := Sol.Missing (Crate).Pinning (Crate, Pin.Version); @@ -432,8 +441,7 @@ package body Alire.Roots is if State.Is_User_Pinned and then not Valid_Pins.Contains (State.Crate) then - Pruned_Sol := Pruned_Sol.Unlinking (State.Crate) - .Unpinning (State.Crate); + Pruned_Sol := Pruned_Sol.User_Unpinning (State.Crate); Put_Info ("Unpinning crate " & TTY.Name (State.Crate)); end if; end loop; @@ -459,8 +467,8 @@ package body Alire.Roots is is begin This.Deploy_Pins (Exhaustive, Allowed); - This.Prune_Pins; This.Apply_Local_Pins; + This.Prune_Pins; end Sync_Pins_From_Manifest; --------------- diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 0b66dfd72..714d085ec 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -273,7 +273,6 @@ private -- exhaustive. Allowed restricts which crates are affected procedure Prune_Pins (This : in out Root); - -- Remove any pins in the solution that are not in the manifest. Allowed - -- restricts which crates are affected. + -- Remove any pins in the solution that are not in the manifest end Alire.Roots; diff --git a/src/alire/alire-solutions.adb b/src/alire/alire-solutions.adb index 15a8a4e79..9500a686c 100644 --- a/src/alire/alire-solutions.adb +++ b/src/alire/alire-solutions.adb @@ -387,6 +387,22 @@ package body Alire.Solutions is end return; end Pins; + --------------- + -- User_Pins -- + --------------- + + function User_Pins (This : Solution) return Conditional.Dependencies is + begin + return Dependencies : Conditional.Dependencies := This.Pins do + for Dep of This.Dependencies loop + if Dep.Is_Linked then + Dependencies + .Append (Conditional.New_Dependency (Dep.As_Dependency)); + end if; + end loop; + end return; + end User_Pins; + ---------- -- Pins -- ---------- diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index 5cc5fdf15..9919df618 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -159,6 +159,13 @@ package Alire.Solutions is -- Unpin a crate. If the crate was not pinned or not in the solution -- nothing will be done. + function User_Unpinning (This : Solution; + Crate : Crate_Name) + return Solution; + -- Remove either a pin or a link for a crate; e.g. same as calling + -- Unpinning and Unlinking in succession. Nothing will be done if + -- crate wasn't in the solution. + function Unsolving (This : Solution; Crate : Crate_Name) return Solution; @@ -256,6 +263,11 @@ package Alire.Solutions is -- return all version-pinned dependencies as plain dependencies for a exact -- version. NOTE that the original dependency is thus lost. + function User_Pins (This : Solution) return Conditional.Dependencies; + -- Return all version- or link-pinned dependencies; equivalent to Pins and + -- Links. NOTE that the original dependency is lost for the case of version + -- pins, as only the pinned version is returned. + function Releases (This : Solution) return Release_Map; -- Returns the proper releases in the solution (regular and detected -- externals). This also includes releases found at a linked folder. @@ -610,4 +622,13 @@ private (This.Dependencies (Crate).Unlinking.Unpinning.Missing)) else This); + -------------------- + -- User_Unpinning -- + -------------------- + + function User_Unpinning (This : Solution; + Crate : Crate_Name) + return Solution + is (This.Unpinning (Crate).Unlinking (Crate)); + end Alire.Solutions; diff --git a/src/alire/alire-solver.adb b/src/alire/alire-solver.adb index 943d5cfb4..c4f4a14b0 100644 --- a/src/alire/alire-solver.adb +++ b/src/alire/alire-solver.adb @@ -720,7 +720,7 @@ package body Alire.Solver is end Trace_Pins; Full_Dependencies : constant Conditional.Dependencies := - Tree'(Current.Pins and Deps).Evaluate (Props); + Tree'(Current.User_Pins and Deps).Evaluate (Props); -- Include pins before other dependencies. This ensures their dependency -- can only be solved with the pinned version, and they are attempted -- first to avoid wasteful trial-and-error with other versions. diff --git a/src/alr/alr-commands-withing.adb b/src/alr/alr-commands-withing.adb index 8ed005ce7..8e2d54cdc 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -523,9 +523,9 @@ package body Alr.Commands.Withing is begin Cmd.Requires_Valid_Session; - -- if Cmd.URL.all /= "" then - -- Flags := Flags + 1; - -- end if; + if Cmd.URL.all /= "" then + Flags := Flags + 1; + end if; Check (Cmd.Del); Check (Cmd.From); From 00f1a34e4f4da5f89dc526af12f99eafbd1db205 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Mon, 14 Jun 2021 21:36:23 +0200 Subject: [PATCH 17/25] Tests in tests/pin using new pins Some tests are not easily portable without support from `alr with --use`. Since that should be easy to implement later, they are disabled for now and will be enabled in a subsequent patch. --- dev/edit.sh | 1 + src/alire/alire-roots.adb | 34 +++++---- src/alire/alire-solutions.adb | 7 +- src/alire/alire-solutions.ads | 15 ++++ testsuite/disabled/pin/remote/test.py | 6 +- testsuite/drivers/alr.py | 69 +++++++++++++++++++ .../pin/change-type/my_index/index.toml | 0 .../my_index/li/libhello/libhello-1.0.0.toml | 0 .../pin/change-type/test.py | 10 +-- .../pin/change-type/test.yaml | 0 .../{disabled => tests}/pin/dir-crate/test.py | 4 +- .../pin/dir-crate/test.yaml | 0 .../pin/downgrade/my_index/index/index.toml | 0 .../index/li/libchild/libchild-0.1.0.toml | 0 .../index/li/libchild/libchild-0.2.0.toml | 0 .../index/li/libparent/libparent-1.0.0.toml | 0 .../{disabled => tests}/pin/downgrade/test.py | 4 +- .../pin/downgrade/test.yaml | 0 .../pin/missing-version/test.py | 8 +-- .../pin/missing-version/test.yaml | 0 .../pin-dir-with-regular/my_index/index.toml | 0 .../my_index/li/libhello/libhello-1.0.0.toml | 0 .../pin/pin-dir-with-regular/test.py | 4 +- .../pin/pin-dir-with-regular/test.yaml | 0 .../pin/pin-dir/my_index/index.toml | 0 .../my_index/li/libhello/libhello-1.0.0.toml | 0 .../{disabled => tests}/pin/pin-dir/test.py | 6 +- .../{disabled => tests}/pin/pin-dir/test.yaml | 0 .../pin/post-update/my_index/index/index.toml | 0 .../index/li/libchild/libchild-0.1.0.toml | 0 .../index/li/libchild/libchild-0.2.0.toml | 0 .../index/li/libparent/libparent-1.0.0.toml | 0 .../pin/post-update/test.py | 8 +-- .../pin/post-update/test.yaml | 0 .../twice-in-manifest/my_index}/index.toml | 0 .../my_index/li/libhello/libhello-1.0.0.toml | 9 +++ testsuite/tests/pin/twice-in-manifest/test.py | 32 +++++++++ .../tests/pin/twice-in-manifest/test.yaml | 5 ++ .../unneeded-held/my_index/index/index.toml | 1 + .../index/li/libchild/libchild-0.1.0.toml | 0 .../index/li/libchild/libchild-0.2.0.toml | 0 .../index/li/libparent/libparent-1.0.0.toml | 0 .../pin/unneeded-held/test.py | 4 +- .../pin/unneeded-held/test.yaml | 0 .../{disabled => tests}/pin/unpin/test.py | 6 +- .../{disabled => tests}/pin/unpin/test.yaml | 0 .../update/missing-deps/test.py | 7 +- .../update/missing-deps/test.yaml | 0 .../{disabled => tests}/update/pinned/test.py | 8 +-- .../update/pinned/test.yaml | 0 .../workflows/init-with-pin/test.py | 4 +- .../workflows/init-with-pin/test.yaml | 0 52 files changed, 200 insertions(+), 52 deletions(-) create mode 100755 dev/edit.sh rename testsuite/{disabled => tests}/pin/change-type/my_index/index.toml (100%) rename testsuite/{disabled => tests}/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/change-type/test.py (80%) rename testsuite/{disabled => tests}/pin/change-type/test.yaml (100%) rename testsuite/{disabled => tests}/pin/dir-crate/test.py (91%) rename testsuite/{disabled => tests}/pin/dir-crate/test.yaml (100%) rename testsuite/{disabled => tests}/pin/downgrade/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{disabled => tests}/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{disabled => tests}/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/downgrade/test.py (94%) rename testsuite/{disabled => tests}/pin/downgrade/test.yaml (100%) rename testsuite/{disabled => tests}/pin/missing-version/test.py (87%) rename testsuite/{disabled => tests}/pin/missing-version/test.yaml (100%) rename testsuite/{disabled => tests}/pin/pin-dir-with-regular/my_index/index.toml (100%) rename testsuite/{disabled => tests}/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/pin-dir-with-regular/test.py (91%) rename testsuite/{disabled => tests}/pin/pin-dir-with-regular/test.yaml (100%) rename testsuite/{disabled => tests}/pin/pin-dir/my_index/index.toml (100%) rename testsuite/{disabled => tests}/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/pin-dir/test.py (90%) rename testsuite/{disabled => tests}/pin/pin-dir/test.yaml (100%) rename testsuite/{disabled => tests}/pin/post-update/my_index/index/index.toml (100%) rename testsuite/{disabled => tests}/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{disabled => tests}/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{disabled => tests}/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/post-update/test.py (89%) rename testsuite/{disabled => tests}/pin/post-update/test.yaml (100%) rename testsuite/{disabled/pin/unneeded-held/my_index/index => tests/pin/twice-in-manifest/my_index}/index.toml (100%) create mode 100644 testsuite/tests/pin/twice-in-manifest/my_index/li/libhello/libhello-1.0.0.toml create mode 100644 testsuite/tests/pin/twice-in-manifest/test.py create mode 100644 testsuite/tests/pin/twice-in-manifest/test.yaml create mode 100644 testsuite/tests/pin/unneeded-held/my_index/index/index.toml rename testsuite/{disabled => tests}/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml (100%) rename testsuite/{disabled => tests}/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml (100%) rename testsuite/{disabled => tests}/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml (100%) rename testsuite/{disabled => tests}/pin/unneeded-held/test.py (93%) rename testsuite/{disabled => tests}/pin/unneeded-held/test.yaml (100%) rename testsuite/{disabled => tests}/pin/unpin/test.py (86%) rename testsuite/{disabled => tests}/pin/unpin/test.yaml (100%) rename testsuite/{disabled => tests}/update/missing-deps/test.py (81%) rename testsuite/{disabled => tests}/update/missing-deps/test.yaml (100%) rename testsuite/{disabled => tests}/update/pinned/test.py (77%) rename testsuite/{disabled => tests}/update/pinned/test.yaml (100%) rename testsuite/{disabled => tests}/workflows/init-with-pin/test.py (93%) rename testsuite/{disabled => tests}/workflows/init-with-pin/test.yaml (100%) diff --git a/dev/edit.sh b/dev/edit.sh new file mode 100755 index 000000000..dcc39a496 --- /dev/null +++ b/dev/edit.sh @@ -0,0 +1 @@ +gnatstudio -P alr_env & diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 1b936ad8d..df3aaa80b 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -317,9 +317,9 @@ package body Alire.Roots is case Pin.Kind is when To_Version => - Sol := Sol.Missing (Crate).Pinning (Crate, Pin.Version); + Sol := Sol.Resetting (Crate).Pinning (Crate, Pin.Version); when To_Path => - Sol := Sol.Missing (Crate).Linking (Crate, Pin.Path); + Sol := Sol.Resetting (Crate).Linking (Crate, Pin.Path); when To_Git => null; -- Not considered here end case; @@ -879,7 +879,11 @@ package body Alire.Roots is is begin declare - -- Shadow the argument with the one we want to use everywhere + -- Shadow the argument with the one we want to use everywhere. Note + -- that this old is only used for comparison, as the stored solution + -- may already include changes caused by pin preparations, and + -- furthermore the stored root is the one we need to pass to the + -- solver (as it contains the pins). Old : constant Solutions.Solution := (if Sync_Dependencies.Old.Is_Attempted then Sync_Dependencies.Old @@ -924,20 +928,24 @@ package body Alire.Roots is Trace.Info ("Nothing to update."); - return; - end if; + else - -- Show changes and optionally ask user to apply them + -- Show changes and optionally ask user to apply them + + if Silent then + Trace.Info + ("Dependencies automatically updated as follows:"); + Diff.Print; + elsif not Utils.User_Input.Confirm_Solution_Changes (Diff) then + Trace.Detail ("Update abandoned."); + return; + end if; - if Silent then - Trace.Info ("Dependencies automatically updated as follows:"); - Diff.Print; - elsif not Utils.User_Input.Confirm_Solution_Changes (Diff) then - Trace.Detail ("Update abandoned."); - return; end if; - -- Apply the update + -- Apply the update. We do this even when no changes were + -- detected, as pin evaluation may have temporarily stored + -- unsolved dependencies which have been re-solved now. This.Set (Solution => Needed); This.Deploy_Dependencies; diff --git a/src/alire/alire-solutions.adb b/src/alire/alire-solutions.adb index 9500a686c..c49c70e98 100644 --- a/src/alire/alire-solutions.adb +++ b/src/alire/alire-solutions.adb @@ -842,7 +842,12 @@ package body Alire.Solutions is return Result : Solution := This do for Dep of Src.Dependencies loop if Dep.Is_Pinned then - Result.Dependencies.Include (Dep.Crate, Dep); + + -- We need to copy the pin version; the solving status might + -- have changed, so we do not just blindly copy the old pin + -- into the new solution. + + Result := Result.Pinning (Dep.Crate, Dep.Pin_Version); end if; end loop; end return; diff --git a/src/alire/alire-solutions.ads b/src/alire/alire-solutions.ads index 9919df618..91d5bba62 100644 --- a/src/alire/alire-solutions.ads +++ b/src/alire/alire-solutions.ads @@ -110,6 +110,12 @@ package Alire.Solutions is -- release is fulfilling, by default we don't create its dependency (it -- must exist previously). + function Resetting (This : Solution; + Crate : Crate_Name) + return Solution; + -- Equivalent to .Missing (Crate).User_Unpinning (Crate). That is, remove + -- any fulfillment and any pinning. + function Linking (This : Solution; Crate : Crate_Name; Link : Externals.Softlinks.External) @@ -558,6 +564,15 @@ private function Required (This : Solution) return State_Map'Class is (This.Dependencies); + --------------- + -- Resetting -- + --------------- + + function Resetting (This : Solution; + Crate : Crate_Name) + return Solution + is (This.Missing (Crate).User_Unpinning (Crate)); + ------------- -- Setting -- ------------- diff --git a/testsuite/disabled/pin/remote/test.py b/testsuite/disabled/pin/remote/test.py index d26f6f56f..756a520b9 100644 --- a/testsuite/disabled/pin/remote/test.py +++ b/testsuite/disabled/pin/remote/test.py @@ -32,8 +32,10 @@ def verify(head): run_alr("build") # Prepare for next test - run_alr("with", "--del", "upstream") # Remove dependency - shutil.rmtree("alire") # Total cleanup not relying on alr + run_alr("with", "--del", "upstream") # Remove dependency + p = run_alr("pin") + assert_eq(f"There are no pins\n", p.out) # Ensure pin is gone + shutil.rmtree("alire") # Total cleanup outside of alr # Initialize a git repo that will act as the "online" remote diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index 953de28bf..9b6d466b8 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -2,6 +2,7 @@ Helpers to run alr in the testsuite. """ +import os import os.path from shutil import copytree @@ -201,3 +202,71 @@ def init_local_crate(name="xxx", binary=True, enter=True): run_alr("init", name, "--bin" if binary else "--lib") if enter: os.chdir(name) + + +def alr_unpin(crate, manual=True, fail_if_missing=True): + """ + Unpin a crate, if pinned, or no-op otherwise. Will edit the manifest or use + the command-line, according to manual. Must be run in a crate root. + """ + + if manual: + # Locate and remove the lines with the pin + with open("alire.toml", "rt") as manifest: + found = False + lines = manifest.readlines() + orig = lines + for i in range(1, len(lines)): + if lines[i].startswith(f"{crate} =") \ + and lines[i-1] == "[[pins]]\n": + lines.pop(i) + lines.pop(i-1) + found = True + break + + # Write the new manifest + if found: + with open("alire.toml", "wt") as manifest: + manifest.writelines(lines) + + # Make the lockfile "older" (otherwise timestamp is identical) + os.utime("alire.lock", (0, 0)) + run_alr("pin") # Ensure changes don't affect next command output + elif fail_if_missing: + raise RuntimeError + (f"Could not unpin crate {crate} in lines:\n" + str(orig)) + + else: + raise NotImplementedError("Unimplemented") + + +def alr_pin(crate, version="", path="", url="", commit="", manual=True): + """ + Pin a crate, either manually or using the command-line interface. Use only + one of version, path, url. Must be run in a crate root. + """ + + if manual: + alr_unpin(crate, fail_if_missing=False) # Just in case + + if version != "": + pin_line = f'{crate} = {{ version = "{version}" }}' + elif path != "": + pin_line = f'{crate} = {{ path = "{path}" }}' + elif url != "" and commit != "": + pin_line = f'{crate} = {{ url = "{path}", commit = "{commit}" }}' + elif url != "": + pin_line = f'{crate} = {{ url = "{path}" }}' + else: + raise ValueError("Specify either version, path or url") + + with open("alire.toml", "at") as manifest: + manifest.writelines(["\n[[pins]]\n", pin_line + "\n"]) + + # Make the lockfile "older" (otherwise timestamp is identical) + os.utime("alire.lock", (0, 0)) + + run_alr("pin") # so the changes in the manifest are applied + + else: + raise NotImplementedError("Unimplemented") diff --git a/testsuite/disabled/pin/change-type/my_index/index.toml b/testsuite/tests/pin/change-type/my_index/index.toml similarity index 100% rename from testsuite/disabled/pin/change-type/my_index/index.toml rename to testsuite/tests/pin/change-type/my_index/index.toml diff --git a/testsuite/disabled/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/tests/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/tests/pin/change-type/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/disabled/pin/change-type/test.py b/testsuite/tests/pin/change-type/test.py similarity index 80% rename from testsuite/disabled/pin/change-type/test.py rename to testsuite/tests/pin/change-type/test.py index 7b12e4903..957f28117 100644 --- a/testsuite/disabled/pin/change-type/test.py +++ b/testsuite/tests/pin/change-type/test.py @@ -1,11 +1,11 @@ """ -Change a pinned dependency from a version to a folder and back +Change a pinned dependency from a version to a folder and back, using manifest """ import os import re -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match from drivers.helpers import dir_separator @@ -23,13 +23,13 @@ def check_version_pin(): run_alr('with', 'libhello^1') # Pin to a version -p = run_alr('pin', 'libhello=1.0') +alr_pin('libhello', version='1.0') # Check that it shows as such in the solution check_version_pin() # Repin to a folder -run_alr('pin', 'libhello', '--use', '../crates/libhello_1.0.0') +alr_pin('libhello', path='../crates/libhello_1.0.0') # Check that it shows as such in the solution p = run_alr('show', '--solve') @@ -41,7 +41,7 @@ def check_version_pin(): p.out, flags=re.S) # Repin to a version and check again -p = run_alr('pin', 'libhello=1.0') +alr_pin('libhello', version='1.0') check_version_pin() diff --git a/testsuite/disabled/pin/change-type/test.yaml b/testsuite/tests/pin/change-type/test.yaml similarity index 100% rename from testsuite/disabled/pin/change-type/test.yaml rename to testsuite/tests/pin/change-type/test.yaml diff --git a/testsuite/disabled/pin/dir-crate/test.py b/testsuite/tests/pin/dir-crate/test.py similarity index 91% rename from testsuite/disabled/pin/dir-crate/test.py rename to testsuite/tests/pin/dir-crate/test.py index 938c16fa7..7227ca107 100644 --- a/testsuite/disabled/pin/dir-crate/test.py +++ b/testsuite/tests/pin/dir-crate/test.py @@ -5,7 +5,7 @@ import os import re -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match from drivers.helpers import dir_separator from glob import glob @@ -25,7 +25,7 @@ # Pin the hello crate as local dir dependency. The version in the folder is # different to the one we had in the solution, so this should cause a downgrade # but with complete solution. Now hello=1 --> libhello=1.1. -run_alr('pin', 'hello', '--use', '..' + dir_separator() + target) +alr_pin('hello', path='..' + dir_separator() + target) # Verify that hello dependencies are detected and used, and are the ones # corresponding to the linked dir versions. diff --git a/testsuite/disabled/pin/dir-crate/test.yaml b/testsuite/tests/pin/dir-crate/test.yaml similarity index 100% rename from testsuite/disabled/pin/dir-crate/test.yaml rename to testsuite/tests/pin/dir-crate/test.yaml diff --git a/testsuite/disabled/pin/downgrade/my_index/index/index.toml b/testsuite/tests/pin/downgrade/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/pin/downgrade/my_index/index/index.toml rename to testsuite/tests/pin/downgrade/my_index/index/index.toml diff --git a/testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/disabled/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/tests/pin/downgrade/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/disabled/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/tests/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/tests/pin/downgrade/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/disabled/pin/downgrade/test.py b/testsuite/tests/pin/downgrade/test.py similarity index 94% rename from testsuite/disabled/pin/downgrade/test.py rename to testsuite/tests/pin/downgrade/test.py index 9b1f13639..0e264667d 100644 --- a/testsuite/disabled/pin/downgrade/test.py +++ b/testsuite/tests/pin/downgrade/test.py @@ -4,7 +4,7 @@ import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_eq, assert_match from drivers.helpers import check_line_in @@ -40,7 +40,7 @@ def check_child(version, output, pinned): check_child('0.2.0', p.out, pinned=False) # Pin it to a downgrade -run_alr('pin', 'libchild=0.1') +alr_pin('libchild', version='0.1') # Verify new version p = run_alr('show', '--solve') diff --git a/testsuite/disabled/pin/downgrade/test.yaml b/testsuite/tests/pin/downgrade/test.yaml similarity index 100% rename from testsuite/disabled/pin/downgrade/test.yaml rename to testsuite/tests/pin/downgrade/test.yaml diff --git a/testsuite/disabled/pin/missing-version/test.py b/testsuite/tests/pin/missing-version/test.py similarity index 87% rename from testsuite/disabled/pin/missing-version/test.py rename to testsuite/tests/pin/missing-version/test.py index 119b2bd22..137eb9b4a 100644 --- a/testsuite/disabled/pin/missing-version/test.py +++ b/testsuite/tests/pin/missing-version/test.py @@ -1,11 +1,11 @@ """ -Pin forcibly a dependencies that cause missing dependencies +Pin forcibly a dependency that cause missing dependencies """ import re import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match from glob import glob @@ -19,7 +19,7 @@ # 1st test: pin to an existing version that brings in missing dependencies. # Pinning hello=3 brings in a libhello^3 dependency that is unavailable, so: # xxx=0.0.0 -> hello=3.0.0 --> libhello^3 (missing) -run_alr('pin', '--force', 'hello=3') +alr_pin('hello', version='3') # Check solution is as expected p = run_alr('with', '--solve') @@ -32,7 +32,7 @@ # 2nd test: directly pin to a missing version (hello=5). This causes libhello # to disappear from the solution, since hello's dependencies are now unknown: # xxx=0.0.0 -> hello=5 (missing) -run_alr('pin', '--force', 'hello=5') +alr_pin('hello', version='5') # Check solution is as expected p = run_alr('with', '--solve') diff --git a/testsuite/disabled/pin/missing-version/test.yaml b/testsuite/tests/pin/missing-version/test.yaml similarity index 100% rename from testsuite/disabled/pin/missing-version/test.yaml rename to testsuite/tests/pin/missing-version/test.yaml diff --git a/testsuite/disabled/pin/pin-dir-with-regular/my_index/index.toml b/testsuite/tests/pin/pin-dir-with-regular/my_index/index.toml similarity index 100% rename from testsuite/disabled/pin/pin-dir-with-regular/my_index/index.toml rename to testsuite/tests/pin/pin-dir-with-regular/my_index/index.toml diff --git a/testsuite/disabled/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/tests/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/tests/pin/pin-dir-with-regular/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/disabled/pin/pin-dir-with-regular/test.py b/testsuite/tests/pin/pin-dir-with-regular/test.py similarity index 91% rename from testsuite/disabled/pin/pin-dir-with-regular/test.py rename to testsuite/tests/pin/pin-dir-with-regular/test.py index 31f25b11c..d6511d251 100644 --- a/testsuite/disabled/pin/pin-dir-with-regular/test.py +++ b/testsuite/tests/pin/pin-dir-with-regular/test.py @@ -5,7 +5,7 @@ import os import re -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match # Initialize a workspace, enter, and add a regular dependency @@ -19,7 +19,7 @@ run_alr('with', 'unobtanium', '--force') # Pin the missing crate -run_alr('pin', 'unobtanium', '--use', '/') +alr_pin('unobtanium', path='/') # Check the solution shows both pinned dir and regular dependency p = run_alr('with', '--solve') diff --git a/testsuite/disabled/pin/pin-dir-with-regular/test.yaml b/testsuite/tests/pin/pin-dir-with-regular/test.yaml similarity index 100% rename from testsuite/disabled/pin/pin-dir-with-regular/test.yaml rename to testsuite/tests/pin/pin-dir-with-regular/test.yaml diff --git a/testsuite/disabled/pin/pin-dir/my_index/index.toml b/testsuite/tests/pin/pin-dir/my_index/index.toml similarity index 100% rename from testsuite/disabled/pin/pin-dir/my_index/index.toml rename to testsuite/tests/pin/pin-dir/my_index/index.toml diff --git a/testsuite/disabled/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/tests/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml rename to testsuite/tests/pin/pin-dir/my_index/li/libhello/libhello-1.0.0.toml diff --git a/testsuite/disabled/pin/pin-dir/test.py b/testsuite/tests/pin/pin-dir/test.py similarity index 90% rename from testsuite/disabled/pin/pin-dir/test.py rename to testsuite/tests/pin/pin-dir/test.py index dfab92dfe..39103b277 100644 --- a/testsuite/disabled/pin/pin-dir/test.py +++ b/testsuite/tests/pin/pin-dir/test.py @@ -5,7 +5,7 @@ import os import re -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin, alr_unpin from drivers.asserts import assert_match from drivers.helpers import dir_separator, with_project @@ -22,7 +22,7 @@ # Add normally and then pin, check that it builds run_alr('with', 'libhello') -run_alr('pin', 'libhello', '--use', '../crates/libhello_1.0.0') +alr_pin('libhello', path='../crates/libhello_1.0.0') run_alr('build') # Check the pin shows in the solution @@ -38,7 +38,7 @@ # Check that unpinning the dependency works and now the dependency is show # as a regular one from the index -run_alr('pin', '--unpin', 'libhello') +alr_unpin('libhello') p = run_alr('show', '--solve') assert_match('.*Dependencies \(solution\):' '.*libhello=1.0.0.*', diff --git a/testsuite/disabled/pin/pin-dir/test.yaml b/testsuite/tests/pin/pin-dir/test.yaml similarity index 100% rename from testsuite/disabled/pin/pin-dir/test.yaml rename to testsuite/tests/pin/pin-dir/test.yaml diff --git a/testsuite/disabled/pin/post-update/my_index/index/index.toml b/testsuite/tests/pin/post-update/my_index/index/index.toml similarity index 100% rename from testsuite/disabled/pin/post-update/my_index/index/index.toml rename to testsuite/tests/pin/post-update/my_index/index/index.toml diff --git a/testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/disabled/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/tests/pin/post-update/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/disabled/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/tests/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/tests/pin/post-update/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/disabled/pin/post-update/test.py b/testsuite/tests/pin/post-update/test.py similarity index 89% rename from testsuite/disabled/pin/post-update/test.py rename to testsuite/tests/pin/post-update/test.py index 988a310d3..bfdb104b0 100644 --- a/testsuite/disabled/pin/post-update/test.py +++ b/testsuite/tests/pin/post-update/test.py @@ -4,7 +4,7 @@ import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin, alr_unpin from drivers.asserts import assert_eq, assert_match from drivers.helpers import check_line_in @@ -35,10 +35,10 @@ def check_child(version, output, pinned): run_alr('with', 'libchild=0.1') # Pin it -run_alr('pin', 'libchild') +alr_pin('libchild', version="0.1") # To avoid pinning and downgrading (that's a different test), we depend on -# a crate that indirectly depends on libchild. This way we can remove the exact +# a crate that also depends on libchild. This way we can remove the exact # libchild dependency and verify the pin holds run_alr('with', 'libparent') @@ -55,7 +55,7 @@ def check_child(version, output, pinned): check_child('0.1.0', p.out, pinned=True) # Unpin and check upgraded solution -run_alr('pin', '--unpin', 'libchild') +alr_unpin('libchild') p = run_alr('show', '--solve') check_child('0.2.0', p.out, pinned=False) diff --git a/testsuite/disabled/pin/post-update/test.yaml b/testsuite/tests/pin/post-update/test.yaml similarity index 100% rename from testsuite/disabled/pin/post-update/test.yaml rename to testsuite/tests/pin/post-update/test.yaml diff --git a/testsuite/disabled/pin/unneeded-held/my_index/index/index.toml b/testsuite/tests/pin/twice-in-manifest/my_index/index.toml similarity index 100% rename from testsuite/disabled/pin/unneeded-held/my_index/index/index.toml rename to testsuite/tests/pin/twice-in-manifest/my_index/index.toml diff --git a/testsuite/tests/pin/twice-in-manifest/my_index/li/libhello/libhello-1.0.0.toml b/testsuite/tests/pin/twice-in-manifest/my_index/li/libhello/libhello-1.0.0.toml new file mode 100644 index 000000000..f1eb7f5e6 --- /dev/null +++ b/testsuite/tests/pin/twice-in-manifest/my_index/li/libhello/libhello-1.0.0.toml @@ -0,0 +1,9 @@ +description = "libhello" +name = "libhello" +version = "1.0.0" +licenses = "GPL-3.0-only" +maintainers = ["some@one.com"] +maintainers-logins = ["mylogin"] + +[origin] +url = "file:../../../crates/libhello_1.0.0" diff --git a/testsuite/tests/pin/twice-in-manifest/test.py b/testsuite/tests/pin/twice-in-manifest/test.py new file mode 100644 index 000000000..f4e440be3 --- /dev/null +++ b/testsuite/tests/pin/twice-in-manifest/test.py @@ -0,0 +1,32 @@ +""" +Detect a crate with two pins in the manifest +""" + +import os +import re + +from drivers.alr import run_alr, alr_pin +from drivers.asserts import assert_match +from drivers.helpers import dir_separator + + +# Initialize a workspace, enter, and add a regular dependency +run_alr('init', '--bin', 'xxx') +os.chdir('xxx') +run_alr('with', 'libhello^1') + +# Pin to a version +alr_pin('libhello', version='1.0') + +# Manually force a second pin +with open("alire.toml", "at") as manifest: + manifest.write("[[pins]]\n") + manifest.write("libhello = { path = '.' }\n") + +# Check that the second pin is rejected +p = run_alr('pin', complain_on_error=False) +assert_match('.*pin for crate libhello is specified more than once.*', + p.out) + + +print('SUCCESS') diff --git a/testsuite/tests/pin/twice-in-manifest/test.yaml b/testsuite/tests/pin/twice-in-manifest/test.yaml new file mode 100644 index 000000000..b7da6fe78 --- /dev/null +++ b/testsuite/tests/pin/twice-in-manifest/test.yaml @@ -0,0 +1,5 @@ +driver: python-script +indexes: + my_index: + in_fixtures: false + copy_crates_src: true diff --git a/testsuite/tests/pin/unneeded-held/my_index/index/index.toml b/testsuite/tests/pin/unneeded-held/my_index/index/index.toml new file mode 100644 index 000000000..346c93fc5 --- /dev/null +++ b/testsuite/tests/pin/unneeded-held/my_index/index/index.toml @@ -0,0 +1 @@ +version = "1.0" diff --git a/testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml b/testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml similarity index 100% rename from testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml rename to testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.1.0.toml diff --git a/testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml b/testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml similarity index 100% rename from testsuite/disabled/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml rename to testsuite/tests/pin/unneeded-held/my_index/index/li/libchild/libchild-0.2.0.toml diff --git a/testsuite/disabled/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml b/testsuite/tests/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml similarity index 100% rename from testsuite/disabled/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml rename to testsuite/tests/pin/unneeded-held/my_index/index/li/libparent/libparent-1.0.0.toml diff --git a/testsuite/disabled/pin/unneeded-held/test.py b/testsuite/tests/pin/unneeded-held/test.py similarity index 93% rename from testsuite/disabled/pin/unneeded-held/test.py rename to testsuite/tests/pin/unneeded-held/test.py index 8ff3c8b4b..1d9612c2d 100644 --- a/testsuite/disabled/pin/unneeded-held/test.py +++ b/testsuite/tests/pin/unneeded-held/test.py @@ -4,7 +4,7 @@ import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_eq, assert_match from drivers.helpers import check_line_in @@ -21,7 +21,7 @@ run_alr('with', 'libparent') # Pin the child -run_alr('pin', 'libchild') +alr_pin('libchild', version='0.2') # Remove parent run_alr('with', '--del', 'libparent') diff --git a/testsuite/disabled/pin/unneeded-held/test.yaml b/testsuite/tests/pin/unneeded-held/test.yaml similarity index 100% rename from testsuite/disabled/pin/unneeded-held/test.yaml rename to testsuite/tests/pin/unneeded-held/test.yaml diff --git a/testsuite/disabled/pin/unpin/test.py b/testsuite/tests/pin/unpin/test.py similarity index 86% rename from testsuite/disabled/pin/unpin/test.py rename to testsuite/tests/pin/unpin/test.py index 3cd9fbd03..ee8b1a15d 100644 --- a/testsuite/disabled/pin/unpin/test.py +++ b/testsuite/tests/pin/unpin/test.py @@ -4,7 +4,7 @@ import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin, alr_unpin from drivers.asserts import assert_eq from drivers.helpers import check_line_in @@ -17,7 +17,7 @@ run_alr('with', 'libhello') # Pin the version of libhello and verify pin is there -run_alr('pin', 'libhello') +alr_pin('libhello', version="1") p = run_alr('pin') assert_eq('libhello 1.0.0\n', p.out) @@ -29,7 +29,7 @@ # Delete lockfile and verify the pin has survived # Unpin and verify pin is not there -run_alr('pin', '--unpin', 'libhello') +alr_unpin('libhello') p = run_alr('pin') assert_eq('There are no pins\n', p.out) diff --git a/testsuite/disabled/pin/unpin/test.yaml b/testsuite/tests/pin/unpin/test.yaml similarity index 100% rename from testsuite/disabled/pin/unpin/test.yaml rename to testsuite/tests/pin/unpin/test.yaml diff --git a/testsuite/disabled/update/missing-deps/test.py b/testsuite/tests/update/missing-deps/test.py similarity index 81% rename from testsuite/disabled/update/missing-deps/test.py rename to testsuite/tests/update/missing-deps/test.py index 30b6b9a28..560bde380 100644 --- a/testsuite/disabled/update/missing-deps/test.py +++ b/testsuite/tests/update/missing-deps/test.py @@ -1,11 +1,12 @@ """ -Check that updating an incomplete solution is doable resulting in no changes +Check that updating an incomplete solution is doable resulting in no changes. +This is labeled manual because the pin is added through the manifest. """ import re import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match from glob import glob @@ -14,7 +15,7 @@ run_alr('init', '--bin', 'xxx') os.chdir('xxx') run_alr('with', 'libhello') -run_alr('pin', '--force', 'libhello=3') +alr_pin('libhello', version="3") # See that updating succeeds run_alr('update') diff --git a/testsuite/disabled/update/missing-deps/test.yaml b/testsuite/tests/update/missing-deps/test.yaml similarity index 100% rename from testsuite/disabled/update/missing-deps/test.yaml rename to testsuite/tests/update/missing-deps/test.yaml diff --git a/testsuite/disabled/update/pinned/test.py b/testsuite/tests/update/pinned/test.py similarity index 77% rename from testsuite/disabled/update/pinned/test.py rename to testsuite/tests/update/pinned/test.py index 03e455a83..a0ddabba9 100644 --- a/testsuite/disabled/update/pinned/test.py +++ b/testsuite/tests/update/pinned/test.py @@ -1,11 +1,11 @@ """ -Check that updating a pinned crate results in a recoverable error +Check that updating a manifest-pinned crate results in a recoverable error """ import re import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_match from glob import glob @@ -13,8 +13,8 @@ # Add a dependency and force it missing by pinning it to non-existing version run_alr('init', '--bin', 'xxx') os.chdir('xxx') -run_alr('with', 'libhello^1') # This causes libhello=1.1 -run_alr('pin', 'libhello=1') # Downgrade to 1.0 +run_alr('with', 'libhello^1') # This causes libhello=1.1 +alr_pin('libhello', version='1') # Downgrade to 1.0 # Check that updating without specific crate does not err run_alr('update') diff --git a/testsuite/disabled/update/pinned/test.yaml b/testsuite/tests/update/pinned/test.yaml similarity index 100% rename from testsuite/disabled/update/pinned/test.yaml rename to testsuite/tests/update/pinned/test.yaml diff --git a/testsuite/disabled/workflows/init-with-pin/test.py b/testsuite/tests/workflows/init-with-pin/test.py similarity index 93% rename from testsuite/disabled/workflows/init-with-pin/test.py rename to testsuite/tests/workflows/init-with-pin/test.py index 6828f1cdf..d823f9666 100644 --- a/testsuite/disabled/workflows/init-with-pin/test.py +++ b/testsuite/tests/workflows/init-with-pin/test.py @@ -4,7 +4,7 @@ import os -from drivers.alr import run_alr +from drivers.alr import run_alr, alr_pin from drivers.asserts import assert_eq from drivers.helpers import check_line_in @@ -29,7 +29,7 @@ f.write(content) # Pin the version of libhello and verify pin is there -run_alr('pin', 'libhello') +alr_pin('libhello', version='1.0') p = run_alr('pin') assert_eq('libhello 1.0.0\n', p.out) diff --git a/testsuite/disabled/workflows/init-with-pin/test.yaml b/testsuite/tests/workflows/init-with-pin/test.yaml similarity index 100% rename from testsuite/disabled/workflows/init-with-pin/test.yaml rename to testsuite/tests/workflows/init-with-pin/test.yaml From 6d1a2e2aec7e8772bb0a33592f1fa2c350431f20 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 16 Jun 2021 09:59:40 +0200 Subject: [PATCH 18/25] Documentation on new pins --- doc/catalog-format-spec.md | 65 +++++++++++++++++++++++++++++++++++--- doc/user-changes.md | 17 ++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/doc/catalog-format-spec.md b/doc/catalog-format-spec.md index 8775e95c5..5fe6393a1 100644 --- a/doc/catalog-format-spec.md +++ b/doc/catalog-format-spec.md @@ -267,7 +267,7 @@ static, i.e. they cannot depend on the context. ```toml project-files = ["my_project.gpr", "utils/utils_for_my_project.gpr"] - + [project-files.'case(word-size)'] bits-64 = ["my_project.gpr"] bits-32 = ["my_project32.gpr"] @@ -291,7 +291,7 @@ static, i.e. they cannot depend on the context. ```toml [gpr-set-externals] BUILD_MODE = "release" - + [gpr-set-externals.'case(os)'] linux = { OS = "gnu-linux" } # Compact table syntax is convenient in this case windows = { OS = "ms-linux" } # to see all enumeration values, one per row. @@ -365,11 +365,11 @@ static, i.e. they cannot depend on the context. [[actions.'case(os)'.linux]] type = "post-fetch" command = ["make"] - + [[actions.'case(os)'.windows]] type = "post-fetch" command = ["cmd", "build"] - + [[actions.'case(os)'.'...']] # An explicit empty case alternative, which is not mandatory ``` @@ -508,6 +508,63 @@ static, i.e. they cannot depend on the context. crate_2.var1 = "Debug" ``` +## Work-in-progress dependency overrides + +It is usual to develop several interdependent crates at the same time. In this scenario, it is often impractical to rely on indexed releases which are not intended to be modified. Instead, one would prefer to use a work-in-progress version of a crate to fulfill some dependency. + +Alire provides *pins* to support this use case. Pins are overrides to dependencies, are intended to be used locally, and to be fulfilled by proper dependencies once a crate is ready to be published. The use of pins is based on two ideas: + +* Dependencies are given, as normally, in the `depends-on` array of the manifest, even for those dependencies to be pinned. This way, once the release is ready, pins are simply removed and the actual dependencies are used in their place. +* Dependency overrides, aka *pins*, are given under the `[[pins]]` array of the manifest. + +Three kinds of pins are available, all of them with the syntax: + +`crate_name = { pin_attributes }` + +The specific pin kinds and their attributes are: + +* Pins to versions: used to force the use of a particular version of an indexed crate. + + * `version`: a string containing a single version to be used. + * `crate_name = { version = "1.2+hotfix-1" }` + +* Pins to local crates: a local directory will fulfill the crate dependency, no matter what version is given in its local manifest. "Raw" Ada projects without an Alire manifest can be used too, as long as their project file matches the crate name and it is located in the directory given as override. + + * `path`: an absolute or relative path to the crate directory. + * `crate_name = { path = "../my/wip/crate" }` + + For the common case of directories containing an Alire manifest, dependencies and pins will be included recursively in the build context. + +* Pins to git repositories: the repository will be cloned locally and its directory will be used as in the previous case. Currently, this pin may optionally include a commit to fix the checkout to be used. Otherwise, the default branch will be used, and running `alr update` will refresh the checkout. + + * `url`: the URL of a git repository + * `commit` (optional): a complete git commit hash. + * `crate_name = { url = "https://my/repo.git" } # Updatable pin` + * `crate_name = { url = "https://my/repo.git", commit="abcdef..." } # Fixed pin` + +### Using pins for crate testing + +Pins are also useful to have a separate test project that depends on your main crate. The recommended setup is as follows: + +``` +/path/to/my_crate +├── alire.toml +└── my_crate_test + └── alire.toml +``` + +I.e., a `my_crate_test` crate is initialized within the main `my_crate`. In the `my_crate_test` manifest, you have a dependency and local relative path pin for `my_crate`: + +```toml +# my_crate_test/alire.toml +[[depends-on]] +my_crate = "*" # Any version of the main crate +[[pins]] +my_crate = { path = ".." } # Overriden by the latest sources +``` + + Then, `my_crate` is published normally, and `my_crate_test` can be used locally for any kind of testing needed on `my_crate` without polluting `my_crate` manifest with test specifics. + ## External releases The above information applies to regular releases distributed from sources diff --git a/doc/user-changes.md b/doc/user-changes.md index 14245ecc9..ef80bac31 100644 --- a/doc/user-changes.md +++ b/doc/user-changes.md @@ -6,6 +6,23 @@ stay on top of `alr` new features. ## Release `1.1` +### Pins stored in the manifest + +PR [#743](https://github.com/alire-project/alire/pull/743). + +The options to modify pins through the command-line (`with --use`, `alr pin +[--unpin] crate` have been disabled in favor of direct edition of the manifest. +This way, pins are more robust against lockfile format changes. These kinds of +pins exist: + +``` +[[pins]] +foo = { version = "1.3.2+bugfix" } # Require a specific version +bar = { path = "../my/bar" } # Use a local crate to override a dependency +baz = { url = "https://github.com/baz.git" } # No commit, will use HEAD, will update on `alr update` +gru = { url = "https://gitlab.com/gru.git" commit="123456890abcdef..." } # Explicit commit, won't update +``` + ### Automatic GPR 'with' now in crate configuration PR [#740](https://github.com/alire-project/alire/pull/740). From 674582e9b07da8a72d9068cd5291841798520009 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 16 Jun 2021 10:07:26 +0200 Subject: [PATCH 19/25] Fix for testcase on Windows using path separators --- testsuite/tests/pin/dir-crate/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/pin/dir-crate/test.py b/testsuite/tests/pin/dir-crate/test.py index 7227ca107..8b0c6ff05 100644 --- a/testsuite/tests/pin/dir-crate/test.py +++ b/testsuite/tests/pin/dir-crate/test.py @@ -25,7 +25,7 @@ # Pin the hello crate as local dir dependency. The version in the folder is # different to the one we had in the solution, so this should cause a downgrade # but with complete solution. Now hello=1 --> libhello=1.1. -alr_pin('hello', path='..' + dir_separator() + target) +alr_pin('hello', path='../' + target) # Verify that hello dependencies are detected and used, and are the ones # corresponding to the linked dir versions. From 02152020978fb38eeec6ff724ed816b34d5ddc7b Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 16 Jun 2021 10:18:34 +0200 Subject: [PATCH 20/25] Spelling fixes, and exclude lockfiles from check --- .github/workflows/spellcheck.yml | 1 + doc/catalog-format-spec.md | 2 +- src/alire/alire-roots.adb | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index c59640023..88d010e25 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -15,3 +15,4 @@ jobs: github_token: ${{ secrets.github_token }} reporter: github-pr-review locale: "US" + exclude: "*.lock* diff --git a/doc/catalog-format-spec.md b/doc/catalog-format-spec.md index 5fe6393a1..1df01706f 100644 --- a/doc/catalog-format-spec.md +++ b/doc/catalog-format-spec.md @@ -560,7 +560,7 @@ I.e., a `my_crate_test` crate is initialized within the main `my_crate`. In the [[depends-on]] my_crate = "*" # Any version of the main crate [[pins]] -my_crate = { path = ".." } # Overriden by the latest sources +my_crate = { path = ".." } # Overridden by the latest sources ``` Then, `my_crate` is published normally, and `my_crate_test` can be used locally for any kind of testing needed on `my_crate` without polluting `my_crate` manifest with test specifics. diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index df3aaa80b..e697e6f3f 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -330,7 +330,7 @@ package body Alire.Roots is Solutions.Diffs.Between (This.Solution, Sol).Print (Changed_Only => True, Level => Trace.Detail); - Trace.Detail ("Local pins updated and commited to disk"); + Trace.Detail ("Local pins updated and committed to lockfile"); This.Set (Solution => Sol); end if; end Apply_Local_Pins; @@ -450,7 +450,7 @@ package body Alire.Roots is Solutions.Diffs.Between (This.Solution, Pruned_Sol).Print (Changed_Only => True, Level => Trace.Detail); - Trace.Detail ("Pin-pruned solution commited to disk"); + Trace.Detail ("Pin-pruned solution committed to disk"); This.Set (Pruned_Sol); end if; end Prune_Pins; From ebaba3a7909833f45eb96ad9ac81c7f355100480 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 16 Jun 2021 18:25:02 +0200 Subject: [PATCH 21/25] New test for various invalid pin entries in manifest Also the required code changes to pass the test --- src/alire/alire-user_pins.adb | 9 +- testsuite/drivers/alr.py | 8 ++ .../my_index/crates/crate/.emptydir | 0 .../my_index/index/cr/crate/crate-1.0.0.toml | 9 ++ .../my_index/index/index.toml | 1 + .../tests/pin/manifest-invalid-pins/test.py | 83 +++++++++++++++++++ .../tests/pin/manifest-invalid-pins/test.yaml | 4 + 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/pin/manifest-invalid-pins/my_index/crates/crate/.emptydir create mode 100644 testsuite/tests/pin/manifest-invalid-pins/my_index/index/cr/crate/crate-1.0.0.toml create mode 100644 testsuite/tests/pin/manifest-invalid-pins/my_index/index/index.toml create mode 100644 testsuite/tests/pin/manifest-invalid-pins/test.py create mode 100644 testsuite/tests/pin/manifest-invalid-pins/test.yaml diff --git a/src/alire/alire-user_pins.adb b/src/alire/alire-user_pins.adb index 0581cc240..14e4d63a4 100644 --- a/src/alire/alire-user_pins.adb +++ b/src/alire/alire-user_pins.adb @@ -73,7 +73,9 @@ package body Alire.User_Pins is Version => Semantic_Versioning.Parse (This.Unwrap.As_String)); when TOML.TOML_Table => - return From_Table (This); + return Result : constant Pin := From_Table (This) do + This.Report_Extra_Keys; + end return; when others => Raise_Checked_Error @@ -81,7 +83,10 @@ package body Alire.User_Pins is & This.Unwrap.Kind'Image); end case; - + exception + when E : Semantic_Versioning.Malformed_Input => + Log_Exception (E); + Raise_Checked_Error ("Malformed semantic version in pin"); end From_TOML; end Alire.User_Pins; diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index 9b6d466b8..379c097ed 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -204,6 +204,14 @@ def init_local_crate(name="xxx", binary=True, enter=True): os.chdir(name) +def alr_lockfile(): + return "alire.lock" + + +def alr_manifest(): + return "alire.toml" + + def alr_unpin(crate, manual=True, fail_if_missing=True): """ Unpin a crate, if pinned, or no-op otherwise. Will edit the manifest or use diff --git a/testsuite/tests/pin/manifest-invalid-pins/my_index/crates/crate/.emptydir b/testsuite/tests/pin/manifest-invalid-pins/my_index/crates/crate/.emptydir new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/pin/manifest-invalid-pins/my_index/index/cr/crate/crate-1.0.0.toml b/testsuite/tests/pin/manifest-invalid-pins/my_index/index/cr/crate/crate-1.0.0.toml new file mode 100644 index 000000000..97fb716e6 --- /dev/null +++ b/testsuite/tests/pin/manifest-invalid-pins/my_index/index/cr/crate/crate-1.0.0.toml @@ -0,0 +1,9 @@ +description = "Sample crate" +name = "crate" +version = "1.0.0" +licenses = [] +maintainers = ["any@bo.dy"] +maintainers-logins = ["someone"] + +[origin] +url = "file:../../../crates/crate" diff --git a/testsuite/tests/pin/manifest-invalid-pins/my_index/index/index.toml b/testsuite/tests/pin/manifest-invalid-pins/my_index/index/index.toml new file mode 100644 index 000000000..346c93fc5 --- /dev/null +++ b/testsuite/tests/pin/manifest-invalid-pins/my_index/index/index.toml @@ -0,0 +1 @@ +version = "1.0" diff --git a/testsuite/tests/pin/manifest-invalid-pins/test.py b/testsuite/tests/pin/manifest-invalid-pins/test.py new file mode 100644 index 000000000..ed1faafc9 --- /dev/null +++ b/testsuite/tests/pin/manifest-invalid-pins/test.py @@ -0,0 +1,83 @@ +""" +Verify various bad pins in the manifest are rejected +""" + +from drivers.alr import run_alr, init_local_crate, alr_lockfile, alr_manifest +from drivers.helpers import lines_of +from drivers.asserts import assert_match + +import os.path + + +def check(pin, error): + """ + Insert a pin at the end of the manifest, verify that it is rejected, and + remove it from the manifest. Check the error produced against the one given + """ + with open(alr_manifest(), "a") as manifest: + manifest.write("\n[[pins]]\n" + pin + "\n") + + # Remove lockfile to ensure reload + if os.path.exists(alr_lockfile()): + os.remove(alr_lockfile()) + + p = run_alr("pin", complain_on_error=False) + assert p.status != 0, "Unexpected success for pin: " + pin + assert_match(".*Cannot continue with invalid session.*" + + error + ".*\n", + p.out) + + # Restore the manifest + lines = lines_of(alr_manifest()) + lines.pop() + with open(alr_manifest(), "w") as manifest: + manifest.write("".join(lines)) + + # Verify the manifest is OK again + run_alr("pin") + + +init_local_crate() + +# Invalid empty pins +check("foo = { }", "invalid pin description") +check("foo = ''", "Malformed semantic version in pin") + +# Single string must be a version +check("foo = 'https://github.com/alire-project/alire.git'", + "Malformed semantic version in pin") + +# Mixed incompatible fields +check("foo = { version = '3', url='https://' }", + "forbidden extra entries") +check("foo = { path = '/', url='https://' }", + "forbidden extra entries") +check("foo = { path = '/', version='6976' }", + "forbidden extra entries") +check("foo = { path = '/', " + "commit = '0123456789012345678901234567890123456789' }", + "forbidden extra entries") + +# Extraneous field +check("foo = { wont_ever_exist='' }", "invalid pin description") + +# Commit without url +check("foo = { commit = '0123456789012345678901234567890123456789' }", + "invalid pin description") + +# Invalid commit +check("foo = { url = 'https://', commit = '1234abcd' }", + "invalid commit") + +# Extra unknown field +check("foo = { version = '3', wont_exist='' }", + "forbidden extra entries") +check("foo = { path = '/', wont_exist='' }", + "forbidden extra entries") +check("foo = { url = 'https://', wont_exist='' }", + "forbidden extra entries") +check("foo = { url = 'https://', wont_exist='', " + "commit = '0123456789012345678901234567890123456789' }", + "forbidden extra entries") + +print('SUCCESS') diff --git a/testsuite/tests/pin/manifest-invalid-pins/test.yaml b/testsuite/tests/pin/manifest-invalid-pins/test.yaml new file mode 100644 index 000000000..0a859639c --- /dev/null +++ b/testsuite/tests/pin/manifest-invalid-pins/test.yaml @@ -0,0 +1,4 @@ +driver: python-script +indexes: + my_index: + in_fixtures: false From b90150c1c0ce2a621cddc5b4e9b29d3b013af088 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Wed, 16 Jun 2021 18:53:55 +0200 Subject: [PATCH 22/25] Fixes from code self-review --- src/alire/alire-roots.adb | 39 +----------------------- src/alire/alire-roots.ads | 9 ------ src/alire/alire-user_pins.ads | 10 ++++--- src/alr/alr-commands-withing.adb | 51 ++++++++++++++++---------------- 4 files changed, 32 insertions(+), 77 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index e697e6f3f..190e9c11b 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -415,7 +415,7 @@ package body Alire.Roots is .Print (Changed_Only => True, Level => Trace.Detail); This.Set (Solution => Result.Solution); - Trace.Detail ("Remote pins commited to disk"); + Trace.Detail ("Remote pins committed to disk"); end if; end; else @@ -1130,43 +1130,6 @@ package body Alire.Roots is end; end Pinned_To_Remote; - ------------------------------------ - -- Update_And_Deploy_Dependencies -- - ------------------------------------ - - -- procedure Update_And_Deploy_Dependencies - -- (This : in out Roots.Root; - -- Options : Solver.Query_Options := Solver.Default_Options; - -- Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; --- Confirm : Boolean := not Utils.User_Input.Not_Interactive) - -- is - -- Prev : constant Solutions.Solution := - -- (if Old_Sol.Is_Attempted - -- then Old_Sol - -- else This.Solution); - -- Next : constant Solutions.Solution := - -- This.Compute_Update (Options => Options); - -- Diff : constant Solutions.Diffs.Diff := Prev.Changes (Next); - -- begin - -- if Diff.Contains_Changes then - -- if not Confirm or else - -- Utils.User_Input.Confirm_Solution_Changes (Diff) - -- then - -- if not Confirm then - -- Trace.Info ("Changes to dependency solution:"); - -- Diff.Print (Changed_Only => not Alire.Detailed); - -- end if; - -- - -- This.Set (Solution => Next); - -- This.Deploy_Dependencies; - -- end if; - -- end if; - -- - -- -- Update/Create configuration files - -- This.Generate_Configuration; - -- - -- end Update_And_Deploy_Dependencies; - -------------------- -- Write_Manifest -- -------------------- diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 714d085ec..2506799e1 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -173,15 +173,6 @@ package Alire.Roots is -- and when left at the default invalid argument value, This.Solution will -- be used as old solution. --- procedure Update_And_Deploy_Dependencies - -- (This : in out Roots.Root; - -- Options : Solver.Query_Options := Solver.Default_Options; - -- Old_Sol : Solutions.Solution := Solutions.Empty_Invalid_Solution; --- Confirm : Boolean := not Utils.User_Input.Not_Interactive); --- -- Call Update and Deploy_Dependencies in succession for the given root. - -- Old_Sol is used to present differences, and when left at the default - -- invalid argument value, Root.Solution will be used as old solution. - procedure Sync_Pins_From_Manifest (This : in out Root; Exhaustive : Boolean; diff --git a/src/alire/alire-user_pins.ads b/src/alire/alire-user_pins.ads index bc5fa13ea..637d2eefa 100644 --- a/src/alire/alire-user_pins.ads +++ b/src/alire/alire-user_pins.ads @@ -11,10 +11,10 @@ package Alire.User_Pins is -- want an indexed crate to depend on unknown folders/remotes), there is no -- need to generate TOML for them. - -- The information stored for user pins is still incomplete. The root - -- must check if the pin was already retrieved, and if it matches the - -- user description, or else fetch it, when a change in the manifest - -- is detected. + -- The information provided by the user in the pin is not complete to work + -- with. The root must check if a remote pin was already retrieved, and if + -- it matches the user description, or else fetch it, when a change in the + -- manifest is detected. type Kinds is (To_Git, To_Path, @@ -49,7 +49,9 @@ package Alire.User_Pins is -- The TOML representation of a pin is similar to a dependency, but instead -- of a version set, we get either a precise version, or an url + commit: -- [[pins]] + -- foo = "3.4" -- OR: -- foo = { version = "5.6" } + -- foo = { path = "/path/to/folder" } -- bar = { url = "git+https://blah", [commit = "deadbeef"] } private diff --git a/src/alr/alr-commands-withing.adb b/src/alr/alr-commands-withing.adb index 8e2d54cdc..d8ddce653 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -10,6 +10,7 @@ with Alire.Manifest; with Alire.Releases; with Alire.Solutions; with Alire.Solver; +with Alire.URI; with Alire.Utils.User_Input; with Alr.Commands.Pin; @@ -110,7 +111,6 @@ package body Alr.Commands.Withing is -- We use the New_Solution with the softlink as previous solution, so -- the pinned directory is used by the solver. end Add_Remote_Link; - pragma Unreferenced (Add_Remote_Link); ------------------ -- Add_Softlink -- @@ -204,7 +204,6 @@ package body Alr.Commands.Withing is & " GNAT project as dependency)"); end if; end Detect_Softlink; - pragma Unreferenced (Detect_Softlink); --------- -- Del -- @@ -570,30 +569,30 @@ package body Alr.Commands.Withing is if Cmd.URL.all /= "" then Pin.Warn_Manual_Only; - -- if Cmd.Commit.all /= "" - -- or else Alire.URI.Is_HTTP_Or_Git (Cmd.URL.all) - -- then - -- - -- -- Pin to remote repo - -- - -- Add_Remote_Link (Cmd, - -- Dep => (if Num_Arguments = 1 - -- then Argument (1) - -- else "")); - -- - -- else - -- - -- -- Pin to local folder - -- - -- if Num_Arguments = 1 then - -- Add_Softlink (Cmd, - -- Dep_Spec => Argument (1), - -- Path => Cmd.URL.all); - -- else - -- Detect_Softlink (Cmd, - -- Cmd.URL.all); - -- end if; - -- end if; + if Cmd.Commit.all /= "" + or else Alire.URI.Is_HTTP_Or_Git (Cmd.URL.all) + then + + -- Pin to remote repo + + Add_Remote_Link (Cmd, + Dep => (if Num_Arguments = 1 + then Argument (1) + else "")); + + else + + -- Pin to local folder + + if Num_Arguments = 1 then + Add_Softlink (Cmd, + Dep_Spec => Argument (1), + Path => Cmd.URL.all); + else + Detect_Softlink (Cmd, + Cmd.URL.all); + end if; + end if; else Cmd.Requires_Full_Index; Cmd.Add; From 9a3174e7f5a183131369e9a9424571a9fe4866b6 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 17 Jun 2021 16:25:44 +0200 Subject: [PATCH 23/25] Fixes suggested during code review --- doc/catalog-format-spec.md | 29 +++++++++++++------------ src/alire/alire-dependencies-states.ads | 2 ++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/doc/catalog-format-spec.md b/doc/catalog-format-spec.md index 1df01706f..24d39c3de 100644 --- a/doc/catalog-format-spec.md +++ b/doc/catalog-format-spec.md @@ -14,7 +14,7 @@ appear, or are optional, in a local manifest). These differences are highlighted in the following descriptions, where necessary. Each TOML description file contains exactly one release, except for the special -external definitions that are described in their own section. +external definitions that are described in their own section. ## Information encoding @@ -247,7 +247,7 @@ static, i.e. they cannot depend on the context. Available constraint operators are the usual Ada relationals (`=`, `/=`, `>`, `>=`, `<`, `<=`) plus caret (`^`, any upwards version within the same major point) - and tilde (\~, any upwards version within the same minor point). + and tilde (\~, any upwards version within the same minor point). **Note that caret and tilde do not have any special behavior for pre-1 versions.** This means, for example, that `^0.2` will still mean any release @@ -267,7 +267,7 @@ static, i.e. they cannot depend on the context. ```toml project-files = ["my_project.gpr", "utils/utils_for_my_project.gpr"] - + [project-files.'case(word-size)'] bits-64 = ["my_project.gpr"] bits-32 = ["my_project32.gpr"] @@ -283,7 +283,7 @@ static, i.e. they cannot depend on the context. TAG = "" ``` - - `gpr-set-externals`: optional dynamic table, setting values of project + - `gpr-set-externals`: optional dynamic table, setting values of project external variables when building the project. This should not be used to specify default values, the default values must be specified in the `.gpr` project file. Expressions are accepted before the mapping. For instance: @@ -291,7 +291,7 @@ static, i.e. they cannot depend on the context. ```toml [gpr-set-externals] BUILD_MODE = "release" - + [gpr-set-externals.'case(os)'] linux = { OS = "gnu-linux" } # Compact table syntax is convenient in this case windows = { OS = "ms-linux" } # to see all enumeration values, one per row. @@ -355,7 +355,7 @@ static, i.e. they cannot depend on the context. - `post-build`: the command is to be run right after GPRbuild has been run. This kind of action is run only for the root crate in a workspace. - - `test`: the command is run on demand for crate testing within the Alire + - `test`: the command is run on demand for crate testing within the Alire ecosystem (using `alr test`). This kind of action is fun only for the root crate being tested. @@ -365,11 +365,11 @@ static, i.e. they cannot depend on the context. [[actions.'case(os)'.linux]] type = "post-fetch" command = ["make"] - + [[actions.'case(os)'.windows]] type = "post-fetch" command = ["cmd", "build"] - + [[actions.'case(os)'.'...']] # An explicit empty case alternative, which is not mandatory ``` @@ -512,7 +512,7 @@ static, i.e. they cannot depend on the context. It is usual to develop several interdependent crates at the same time. In this scenario, it is often impractical to rely on indexed releases which are not intended to be modified. Instead, one would prefer to use a work-in-progress version of a crate to fulfill some dependency. -Alire provides *pins* to support this use case. Pins are overrides to dependencies, are intended to be used locally, and to be fulfilled by proper dependencies once a crate is ready to be published. The use of pins is based on two ideas: +Alire provides *pins* to support this use case. Pins override dependencies, they are intended to be used locally, and to be fulfilled by proper dependencies once a crate is ready to be published. The use of pins is based on two ideas: * Dependencies are given, as normally, in the `depends-on` array of the manifest, even for those dependencies to be pinned. This way, once the release is ready, pins are simply removed and the actual dependencies are used in their place. * Dependency overrides, aka *pins*, are given under the `[[pins]]` array of the manifest. @@ -549,21 +549,22 @@ Pins are also useful to have a separate test project that depends on your main c ``` /path/to/my_crate ├── alire.toml -└── my_crate_test +└── tests └── alire.toml ``` -I.e., a `my_crate_test` crate is initialized within the main `my_crate`. In the `my_crate_test` manifest, you have a dependency and local relative path pin for `my_crate`: +I.e., a `tests` crate is initialized within the main `my_crate`. In `tests` manifest, you have a dependency and local relative path pin for `my_crate`: ```toml -# my_crate_test/alire.toml +# tests/alire.toml [[depends-on]] my_crate = "*" # Any version of the main crate +aunit = "*" # We can have dependencies for testing only [[pins]] my_crate = { path = ".." } # Overridden by the latest sources ``` - Then, `my_crate` is published normally, and `my_crate_test` can be used locally for any kind of testing needed on `my_crate` without polluting `my_crate` manifest with test specifics. + Then, `my_crate` is published normally, and `tests` can be used locally for any kind of testing needed on `my_crate` without polluting `my_crate` manifest with test specifics (like extra dependencies used by the test setup). ## External releases @@ -790,7 +791,7 @@ String variables can be used to define the URL of a website or service: URL_Name = {type = "String", default = "example.com"} ``` -#### PID coefficients +#### PID coefficients Real variables can be used for PID coefficients: ```toml diff --git a/src/alire/alire-dependencies-states.ads b/src/alire/alire-dependencies-states.ads index c889838ee..3c6ea412e 100644 --- a/src/alire/alire-dependencies-states.ads +++ b/src/alire/alire-dependencies-states.ads @@ -217,6 +217,8 @@ private overriding function "=" (L, R : State) return Boolean is (L.Image = R.Image); + -- TODO: this is likely not efficient. We should dig more to find why some + -- apparently identical states are reported as different. ------------------- -- As_Dependency -- From 472a849d1c02ef07678aefc0726bf99473e1777b Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 17 Jun 2021 17:09:18 +0200 Subject: [PATCH 24/25] Fix for missed update when there is no lockfile We were creating an empty lockfile, which was newer than the manifest, and thus not triggering the expected automatic update. --- src/alire/alire-roots.adb | 5 +++-- src/alire/alire-roots.ads | 18 ++++++++++-------- src/alr/alr-commands.adb | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 190e9c11b..56d16c5c3 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -747,10 +747,11 @@ package body Alire.Roots is ------------------------ procedure Sync_From_Manifest (This : in out Root; - Silent : Boolean) is + Silent : Boolean; + Force : Boolean := False) is Old_Solution : constant Solutions.Solution := This.Solution; begin - if This.Is_Lockfile_Outdated then + if Force or else This.Is_Lockfile_Outdated then Put_Info ("Detected changes in manifest, synchronizing workspace..."); This.Sync_Pins_From_Manifest (Exhaustive => False); diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index 2506799e1..4853f6821 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -123,14 +123,16 @@ package Alire.Roots is -- automated changes within the same second. procedure Sync_From_Manifest (This : in out Root; - Silent : Boolean); - -- 1) Pre-deploy any remote pins in the manifest so they are usable when - -- solving, and apply any local/version pins. 2) Ensure that dependencies - -- are up to date in regard to the lockfile and manifest: if the manifest - -- is newer than the lockfile, resolve again, as dependencies may have been - -- edited by hand. 3) Ensure that releases in the lockfile are actually - -- on disk (may be missing if cache was deleted, or the crate was just - -- cloned). When Silent, run as in non-interactive mode. + Silent : Boolean; + Force : Boolean := False); + -- If the lockfile timestamp is outdated w.r.t the manifest, or Force, do + -- as follows: 1) Pre-deploy any remote pins in the manifest so they are + -- usable when solving, and apply any local/version pins. 2) Ensure that + -- dependencies are up to date in regard to the lockfile and manifest: if + -- the manifest is newer than the lockfile, resolve again, as dependencies + -- may have been edited by hand. 3) Ensure that releases in the lockfile + -- are actually on disk (may be missing if cache was deleted, or the crate + -- was just cloned). When Silent, run as in non-interactive mode. procedure Sync_Manifest_And_Lockfile_Timestamps (This : Root) with Post => not This.Is_Lockfile_Outdated; diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index c55e5ec0f..fe27ddd11 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -668,7 +668,8 @@ package body Alr.Commands is if Sync then Cmd.Requires_Full_Index (Strict => False); - Checked.Sync_Dependencies (Silent => True); + Checked.Sync_From_Manifest (Silent => True, Force => True); + -- As we just created the empty lockfile, we force the update end if; end; end Requires_Valid_Session; From e3fb579b3da44bb2ebacf8c13f06b4dac8380832 Mon Sep 17 00:00:00 2001 From: "Alejandro R. Mosteo" Date: Thu, 17 Jun 2021 17:25:26 +0200 Subject: [PATCH 25/25] Test to check pins are applied with no prior lockfile This was a bug detected and corrected in the previous commit --- testsuite/tests/pin/without-lockfile/test.py | 31 +++++++++++++++++++ .../tests/pin/without-lockfile/test.yaml | 4 +++ 2 files changed, 35 insertions(+) create mode 100644 testsuite/tests/pin/without-lockfile/test.py create mode 100644 testsuite/tests/pin/without-lockfile/test.yaml diff --git a/testsuite/tests/pin/without-lockfile/test.py b/testsuite/tests/pin/without-lockfile/test.py new file mode 100644 index 000000000..c5ce1f55c --- /dev/null +++ b/testsuite/tests/pin/without-lockfile/test.py @@ -0,0 +1,31 @@ +""" +Verify that pins when there is no lockfile are correctly applied on first run +""" + +from drivers.alr import run_alr, alr_pin, init_local_crate, alr_lockfile +from drivers.asserts import assert_eq + +import os + + +fake_dep = "unobtainium" + +# Create a crate +init_local_crate() + +# Add a dependency +run_alr("with", fake_dep, "--force") + +# Pin to a local folder +os.mkdir(fake_dep) +alr_pin(fake_dep, path=fake_dep) + +# Remove the lockfile +os.remove(alr_lockfile()) + +# Check that the pin is applied on next command run +p = run_alr("pin") +assert_eq(f"{fake_dep} file:{fake_dep} \n", p.out) + + +print('SUCCESS') diff --git a/testsuite/tests/pin/without-lockfile/test.yaml b/testsuite/tests/pin/without-lockfile/test.yaml new file mode 100644 index 000000000..8929d590a --- /dev/null +++ b/testsuite/tests/pin/without-lockfile/test.yaml @@ -0,0 +1,4 @@ +driver: python-script +indexes: + basic_index: + in_fixtures: true