From 428064ec45ec21fe729584e69209e4bfb423f44c Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 18 Sep 2023 10:22:01 +0200 Subject: [PATCH 1/9] Remove spurious -g (#1454) --- alire_common.gpr | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/alire_common.gpr b/alire_common.gpr index ef341d56e..f1a2c2694 100644 --- a/alire_common.gpr +++ b/alire_common.gpr @@ -81,12 +81,18 @@ abstract project Alire_Common is end Compiler; package Builder is - for Switches ("Ada") use ("-s", "-j0", "-g"); + for Switches ("Ada") use + ("-s", -- Recompile if switches changed + "-j0" -- Full parallelism + ); end Builder; package Binder is for Switches ("Ada") use - ( "-Es", "-g", "-static"); + ("-Es", -- Symbolic tracebacks + "-g", -- Keep binder generated files (for debugging?) + "-static" -- Static linking + ); end Binder; package Ide is From 2e3a5209bbccd42c88c41512109e0f1722a8ba4c Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 19 Sep 2023 11:46:13 +0200 Subject: [PATCH 2/9] Print UTF-8 strings using `GNAT.IO` in `Alr.Commands` subsystem (#1458) Supersedes #1457 Fixes #1456 --- src/alr/alr-commands-init.adb | 18 +++++++++--------- src/alr/alr-commands-run.adb | 1 - src/alr/alr-commands.adb | 1 - src/alr/alr-commands.ads | 15 +++++++++------ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/alr/alr-commands-init.adb b/src/alr/alr-commands-init.adb index 30438c76e..f7e083178 100644 --- a/src/alr/alr-commands-init.adb +++ b/src/alr/alr-commands-init.adb @@ -368,7 +368,7 @@ package body Alr.Commands.Init is Info.Name := To_Unbounded_String (Tentative_Name); exit; else - Ada.Text_IO.Put_Line + Put_Line ("Invalid crate name '" & Tentative_Name & "': " & Alire.Error_In_Name (Tentative_Name)); @@ -406,13 +406,13 @@ package body Alr.Commands.Init is if SPDX.Valid (SP) then return True; else - Ada.Text_IO.Put_Line + Put_Line ("Invalid SPDX license expression '" & Str & "': " & SPDX.Error (SP)); - Ada.Text_IO.Put_Line + Put_Line ("SPDX expression expected (https://spdx.org/licenses/)."); - Ada.Text_IO.Put_Line ("(Use 'custom-' prefix for custom" - & " license identifier)"); + Put_Line ("(Use 'custom-' prefix for custom" + & " license identifier)"); return False; end if; @@ -487,9 +487,9 @@ package body Alr.Commands.Init is function Description_Validation (Str : String) return Boolean is begin if Str'Length > Alire.Max_Description_Length then - Ada.Text_IO.Put_Line ("Description too long:" - & Str'Length'Img & " (max" - & Alire.Max_Description_Length'Img & ")"); + Put_Line ("Description too long:" + & Str'Length'Img & " (max" + & Alire.Max_Description_Length'Img & ")"); return False; else return True; @@ -527,7 +527,7 @@ package body Alr.Commands.Init is Tag_Error : constant String := Alire.Utils.Error_In_Tag (Elt); begin if Tag_Error /= "" then - Ada.Text_IO.Put_Line (Tag_Error); + Put_Line (Tag_Error); Tags_Ok := False; end if; end; diff --git a/src/alr/alr-commands-run.adb b/src/alr/alr-commands-run.adb index a001e4f5b..51a752283 100644 --- a/src/alr/alr-commands-run.adb +++ b/src/alr/alr-commands-run.adb @@ -24,7 +24,6 @@ package body Alr.Commands.Run is procedure Check_Report (Cmd : in out Command; Exe_Name : String) is - use Ada.Text_IO; Found_At : constant AAA.Strings.Vector := Files.Locate_File_Under (Cmd.Root.Path, diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index a4690fd57..62facdfda 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -2,7 +2,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Directories; with Ada.Environment_Variables; -with Ada.Text_IO; use Ada.Text_IO; with CLIC.TTY; with CLIC.User_Input; diff --git a/src/alr/alr-commands.ads b/src/alr/alr-commands.ads index 4f65c4bd7..0857684ad 100644 --- a/src/alr/alr-commands.ads +++ b/src/alr/alr-commands.ads @@ -7,7 +7,7 @@ with Alire.Version; with CLIC.Subcommand; -private with Ada.Text_IO; +private with GNAT.IO; private with CLIC.Subcommand.Instance; private with Alr.OS_Lib; -- For the benefit of many child packages that use it @@ -122,11 +122,14 @@ private -- Common generalities - procedure New_Line (Spacing : Ada.Text_IO.Positive_Count := 1) - renames Ada.Text_IO.New_Line; + procedure New_Line (Spacing : Positive := 1) + renames GNAT.IO.New_Line; procedure Put_Line (S : String) - renames Ada.Text_IO.Put_Line; + renames GNAT.IO.Put_Line; + + procedure Put (S : String) + renames GNAT.IO.Put; procedure Put_Error (Str : String); procedure Set_Global_Switches @@ -135,8 +138,8 @@ private package Sub_Cmd is new CLIC.Subcommand.Instance (Main_Command_Name => "alr", Version => Alire.Version.Current, - Put => Ada.Text_IO.Put, - Put_Line => Ada.Text_IO.Put_Line, + Put => GNAT.IO.Put, + Put_Line => GNAT.IO.Put_Line, Put_Error => Put_Error, Error_Exit => OS_Lib.Bailout, Set_Global_Switches => Set_Global_Switches, From c6b6474ae8734f456e5042e7e6af29067b2ad2ef Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 25 Sep 2023 12:46:17 +0200 Subject: [PATCH 3/9] Fix location of default install prefix (#1461) --- src/alire/alire-install.ads | 7 +++++-- src/alr/alr-commands-install.adb | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/alire/alire-install.ads b/src/alire/alire-install.ads index b684dd099..0b5c13cad 100644 --- a/src/alire/alire-install.ads +++ b/src/alire/alire-install.ads @@ -8,8 +8,11 @@ package Alire.Install is -- Support for installation prefixes - Default_Prefix : constant Absolute_Path - := Platforms.Folders.Home / ".alire"; + Default_Prefix_Basename : constant Relative_Path := ".alire"; + Default_Prefix_Dirname : constant Absolute_Path := Platforms.Folders.Home; + + Default_Prefix : constant Absolute_Path := + Default_Prefix_Dirname / Default_Prefix_Basename; procedure Add (Prefix : Any_Path; Deps : Dependencies.Containers.List); diff --git a/src/alr/alr-commands-install.adb b/src/alr/alr-commands-install.adb index 3bcf17019..7143f0413 100644 --- a/src/alr/alr-commands-install.adb +++ b/src/alr/alr-commands-install.adb @@ -136,7 +136,8 @@ package body Alr.Commands.Install is Cmd.Prefix'Access, "", "--prefix=", "Override installation prefix (default is " - & TTY.URL ("${CRATE_ROOT}/alire/prefix)") & ")"); + & TTY.URL ("${HOME}/" & + Alire.Install.Default_Prefix_Basename) & ")"); Define_Switch (Config, Cmd.Info'Access, From d6d9a06901bde124edc891e33ca4290f3ee6cad5 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 25 Sep 2023 16:09:51 +0200 Subject: [PATCH 4/9] Omit global switches in subcommand-specific help (#1462) * Omit global switches in subcmd-specific help * Update clic dependency --- alire.toml | 2 +- deps/clic | 2 +- src/alr/alr-commands.ads | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/alire.toml b/alire.toml index 0647d91cc..32bda836b 100644 --- a/alire.toml +++ b/alire.toml @@ -49,7 +49,7 @@ windows = { ALIRE_OS = "windows" } [[pins]] aaa = { url = "https://github.com/mosteo/aaa", commit = "ecc38772bd4a6b469b54c62363766ea1c0e9f912" } ada_toml = { url = "https://github.com/mosteo/ada-toml", commit = "da4e59c382ceb0de6733d571ecbab7ea4919b33d" } -clic = { url = "https://github.com/alire-project/clic", commit = "6879b90876a1c918b4e112f59c6db0e25b713f52" } +clic = { url = "https://github.com/alire-project/clic", commit = "b40b170b1561adfa99910c69e3897cc2ca441730" } dirty_booleans = { url = "https://github.com/mosteo/dirty_booleans", branch = "main" } diskflags = { url = "https://github.com/mosteo/diskflags", branch = "main" } gnatcoll = { url = "https://github.com/alire-project/gnatcoll-core.git", commit = "4e663b87a028252e7e074f054f8f453661397166" } diff --git a/deps/clic b/deps/clic index 6879b9087..b40b170b1 160000 --- a/deps/clic +++ b/deps/clic @@ -1 +1 @@ -Subproject commit 6879b90876a1c918b4e112f59c6db0e25b713f52 +Subproject commit b40b170b1561adfa99910c69e3897cc2ca441730 diff --git a/src/alr/alr-commands.ads b/src/alr/alr-commands.ads index 0857684ad..d5e329fa8 100644 --- a/src/alr/alr-commands.ads +++ b/src/alr/alr-commands.ads @@ -147,7 +147,8 @@ private TTY_Description => Alire.TTY.Description, TTY_Version => Alire.TTY.Version, TTY_Underline => Alire.TTY.Underline, - TTY_Emph => Alire.TTY.Emph); + TTY_Emph => Alire.TTY.Emph, + Global_Options_In_Subcommand_Help => False); Unset : constant String := "unset"; -- Canary for when a string switch is given without value From b3e996603ca6dd60f9fdb67d36b65ba7fbb3839e Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 25 Sep 2023 19:16:51 +0200 Subject: [PATCH 5/9] Fix corner case related to git+file:// URLs (#1465) --- .vscode/launch.json | 24 +++++++++++++++++++ src/alire/alire-origins.adb | 6 +++-- testsuite/tests/get/git-local/test.py | 5 +++- testsuite/tests/publish/bad-arguments/test.py | 2 +- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 87585ec9b..7f4572754 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,6 +23,30 @@ ], "console": "integratedTerminal", "justMyCode": false + }, + { + "name": "(gdb) Launch alr at /tmp/a/xxx", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/bin/alr", + "args": ["-d", "-vv", "with", "libfoo"], + "stopAtEntry": true, + "cwd": "/tmp/a/xxx", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] } ] } \ No newline at end of file diff --git a/src/alire/alire-origins.adb b/src/alire/alire-origins.adb index 53378ebd2..9fa6be0f1 100644 --- a/src/alire/alire-origins.adb +++ b/src/alire/alire-origins.adb @@ -402,8 +402,10 @@ package body Alire.Origins is Scheme : constant URI.Schemes := URI.Scheme (URL); Transformed : constant Alire.URL := VCSs.Git.Transform_To_Public (URL); VCS_URL : constant String := - (if Contains (URL, "file:") then - Tail (URL, ':') -- Remove file: that confuses git + (if Contains (URL, "+file://") then + Tail (URL, '+') -- strip the VCS proto only + elsif Contains (URL, "+file:") then + Tail (URL, ':') -- Remove file: w.o. // that confuses git elsif Has_Prefix (URL, "git@") and then Transformed /= URL -- known and transformable then diff --git a/testsuite/tests/get/git-local/test.py b/testsuite/tests/get/git-local/test.py index a1ecf5436..edd30a0bf 100644 --- a/testsuite/tests/get/git-local/test.py +++ b/testsuite/tests/get/git-local/test.py @@ -4,7 +4,7 @@ from glob import glob -from drivers.alr import run_alr +from drivers.alr import init_local_crate, run_alr from drivers.asserts import assert_match from drivers.helpers import compare, contents @@ -36,5 +36,8 @@ 'libfoo_1.0.0_9ddda32b/config/libfoo_config.h' ]) +# Check as dependency +init_local_crate() +run_alr("with", "libfoo") # should succeed print('SUCCESS') diff --git a/testsuite/tests/publish/bad-arguments/test.py b/testsuite/tests/publish/bad-arguments/test.py index 1846e392c..4c6f13b7b 100644 --- a/testsuite/tests/publish/bad-arguments/test.py +++ b/testsuite/tests/publish/bad-arguments/test.py @@ -11,7 +11,7 @@ # Bad combo, explicit file + commit p = run_alr("publish", "file:/fake.zip", "deadbeef", complain_on_error=False) -assert_match(".*Expected a VCS origin but got.*", p.out) +assert_match(".*unknown VCS URL", p.out) # Bad combo, implicit file + commit p = run_alr("publish", "fake.zip", "deadbeef", complain_on_error=False) From 7fe652908a0e1342db5cd06abbba522e44a355e6 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 25 Sep 2023 20:40:57 +0200 Subject: [PATCH 6/9] Remove ".git" after cloning, with option to disable (#1463) * Remove ".git" after cloning, with option to disable Also make clones shallow (they already were for pins) * Fix test --- src/alire/alire-config-builtins.ads | 9 +++++ src/alire/alire-origins-deployers-git.adb | 19 +++++++++- src/alire/alire-publish-submit.adb | 4 ++- src/alire/alire-vcss-git.adb | 10 +++++- src/alire/alire-vcss-git.ads | 5 +++ testsuite/drivers/alr.py | 7 ++++ testsuite/drivers/asserts.py | 7 ++-- testsuite/tests/get/git-local/test.py | 5 +-- testsuite/tests/misc/git-ungit/test.py | 43 +++++++++++++++++++++++ testsuite/tests/misc/git-ungit/test.yaml | 3 ++ 10 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/misc/git-ungit/test.py create mode 100644 testsuite/tests/misc/git-ungit/test.yaml diff --git a/src/alire/alire-config-builtins.ads b/src/alire/alire-config-builtins.ads index 2212837dc..889aefe4d 100644 --- a/src/alire/alire-config-builtins.ads +++ b/src/alire/alire-config-builtins.ads @@ -6,6 +6,15 @@ package Alire.Config.Builtins is -- Builtins -- -------------- + -- DEPENDENCIES + + Dependencies_Git_Keep_Repository : constant Builtin := New_Builtin + (Key => "dependencies.git.keep_repository", + Def => False, + Help => + "When true, git origins are a proper git repository after deployment. " + & "Otherwise they are deployed as a plain directory."); + Dependencies_Shared : constant Builtin := New_Builtin (Key => "dependencies.shared", Def => False, diff --git a/src/alire/alire-origins-deployers-git.adb b/src/alire/alire-origins-deployers-git.adb index 5e60238f8..e3a4d1d57 100644 --- a/src/alire/alire-origins-deployers-git.adb +++ b/src/alire/alire-origins-deployers-git.adb @@ -1,7 +1,11 @@ +with Alire.Config.Builtins; +with Alire.Directories; with Alire.VCSs.Git; package body Alire.Origins.Deployers.Git is + use Directories.Operators; + ------------ -- Deploy -- ------------ @@ -9,7 +13,20 @@ package body Alire.Origins.Deployers.Git is overriding function Deploy (This : Deployer; Folder : String) return Outcome is begin - return VCSs.Git.Handler.Clone (This.Base.URL_With_Commit, Folder); + VCSs.Git.Handler.Clone (This.Base.URL_With_Commit, Folder).Assert; + + if Config.Builtins.Dependencies_Git_Keep_Repository.Get then + + Trace.Debug ("Keeping git repo from " & This.Base.TTY_URL_With_Commit + & " at " & TTY.URL (Folder)); + + else + + Directories.Delete_Tree (Folder / VCSs.Git.Git_Dir); + + end if; + + return Outcome_Success; end Deploy; ----------- diff --git a/src/alire/alire-publish-submit.adb b/src/alire/alire-publish-submit.adb index f3bc478fe..c4735899a 100644 --- a/src/alire/alire-publish-submit.adb +++ b/src/alire/alire-publish-submit.adb @@ -248,7 +248,9 @@ package body Alire.Publish.Submit is (From => Index.Community_Host / User_Info.User_GitHub_Login / Index.Community_Repo_Name, - Into => Local_Repo_Path).Assert; + Into => Local_Repo_Path, + Branch => "", + Depth => 1).Assert; -- We can reuse the pull logic now to set up the local branch Pull; diff --git a/src/alire/alire-vcss-git.adb b/src/alire/alire-vcss-git.adb index cc63c8029..890374b04 100644 --- a/src/alire/alire-vcss-git.adb +++ b/src/alire/alire-vcss-git.adb @@ -129,7 +129,7 @@ package body Alire.VCSs.Git is From : URL; Into : Directory_Path) return Outcome - is (This.Clone (From, Into, Branch => "")); + is (This.Clone (From, Into, Branch => "", Depth => 1)); ----------- -- Clone -- @@ -732,6 +732,14 @@ package body Alire.VCSs.Git is end return; end Worktree; + ------------- + -- Git_Dir -- + ------------- + + function Git_Dir return Any_Path + is (OS_Lib.Getenv (Name => "GIT_DIR", + Default => ".git")); + ----------------- -- Head_Commit -- ----------------- diff --git a/src/alire/alire-vcss-git.ads b/src/alire/alire-vcss-git.ads index 765c154f0..30c52113a 100644 --- a/src/alire/alire-vcss-git.ads +++ b/src/alire/alire-vcss-git.ads @@ -19,6 +19,9 @@ package Alire.VCSs.Git is -- This is actually returned by e.g. `git worktree`, even if it could be a -- real commit. I guess the chances are deemed too low. + function Git_Dir return Any_Path; + -- ".git" unless overridden by GIT_DIR + type VCS (<>) is new VCSs.VCS with private; function Handler return VCS; @@ -44,6 +47,8 @@ package Alire.VCSs.Git is From : URL; Into : Directory_Path) return Outcome; + -- Make a shallow clone of the given URL (that may include '#commit). For + -- more precise control, use the following Clone signature. not overriding function Clone (This : VCS; diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index 8a86e2b22..60366b4f7 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -531,6 +531,13 @@ def alr_builds_dir() -> str: return os.path.join(alr_config_dir(), "cache", "builds") +def crate_dirname(crate): + """ + Return the deployment dir of a crate, obtained with `alr get --dirname` + """ + return run_alr("get", "--dirname", crate).out.strip() + + def external_compiler_version() -> str: """ Return the version of the external compiler diff --git a/testsuite/drivers/asserts.py b/testsuite/drivers/asserts.py index e5bc3a02f..a62f1d5b3 100644 --- a/testsuite/drivers/asserts.py +++ b/testsuite/drivers/asserts.py @@ -104,11 +104,14 @@ def assert_installed(prefix : str, milestones : List[str]): p.out) -def assert_file_exists(path : str): +def assert_file_exists(path : str, wanted : bool = True): """ Check that a file exists """ - assert os.path.exists(path), f"Missing expected file {path}" + if wanted: + assert os.path.exists(path), f"Missing expected file {path}" + else: + assert not os.path.exists(path), f"Unexpected file {path}" def assert_in_file(path : str, expected : str): diff --git a/testsuite/tests/get/git-local/test.py b/testsuite/tests/get/git-local/test.py index edd30a0bf..d4a441ab3 100644 --- a/testsuite/tests/get/git-local/test.py +++ b/testsuite/tests/get/git-local/test.py @@ -2,10 +2,7 @@ Retrieve a release from a local git repository """ -from glob import glob - -from drivers.alr import init_local_crate, run_alr -from drivers.asserts import assert_match +from drivers.alr import alr_with, init_local_crate, run_alr from drivers.helpers import compare, contents # Get the release diff --git a/testsuite/tests/misc/git-ungit/test.py b/testsuite/tests/misc/git-ungit/test.py new file mode 100644 index 000000000..88ddb010d --- /dev/null +++ b/testsuite/tests/misc/git-ungit/test.py @@ -0,0 +1,43 @@ +""" +Verify the proper "ungitting" of git origins +""" + +import os +import shutil + +from drivers.alr import alr_with, crate_dirname, init_local_crate, run_alr +from drivers.asserts import assert_file_exists + +# By default, git deployments are shallow and see their .git directory removed +# Check that and that enabling legacy behavior works + +cwd = os.getcwd() +foo_dir = crate_dirname("libfoo") + +# By default .git should not be there +for wanted in [False, True]: + run_alr("get", "libfoo") + + # Check root gotten crate + assert_file_exists(os.path.join(foo_dir, ".git"), + wanted=wanted) + + # Check as dependency + init_local_crate() + alr_with("libfoo") + + assert_file_exists(os.path.join("alire", "cache", "dependencies", + foo_dir, ".git"), + wanted=wanted) + + if not wanted: + # Enable for next round + run_alr("config", "--global", "--set", + "dependencies.git.keep_repository", "true") + + # Cleanup for next round + os.chdir(cwd) + shutil.rmtree(crate_dirname("libfoo")) + shutil.rmtree("xxx") + +print('SUCCESS') diff --git a/testsuite/tests/misc/git-ungit/test.yaml b/testsuite/tests/misc/git-ungit/test.yaml new file mode 100644 index 000000000..8293fdcee --- /dev/null +++ b/testsuite/tests/misc/git-ungit/test.yaml @@ -0,0 +1,3 @@ +driver: python-script +indexes: + git_index: {} From 2753a7c9696f49ea6568244526b4b0065f4b797e Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Wed, 27 Sep 2023 16:46:09 +0200 Subject: [PATCH 7/9] Comprehensive shared builds tests and related tweaks (#1459) * Added `shared-build` driver * Added `build_mode` key to the Python driver * Fix config generation in `alr update` in shared mode * Remove need for compiler in absence of dependencies * Fixed monorepo tests and base dir * Delay config generation in sandboxed mode too * Include explicit switches in build hash inputs This is necessary because for shared builds we're never regenerating the configuration, so changes in switches went undetected * Require complete config for sandboxed build * Self-review * Update new tests --- src/alire/alire-builds-hashes.adb | 34 ++++- src/alire/alire-builds.adb | 26 +++- src/alire/alire-builds.ads | 7 +- src/alire/alire-crate_configuration.adb | 22 ++++ src/alire/alire-crate_configuration.ads | 8 ++ .../alire-properties-actions-executor.adb | 3 +- src/alire/alire-roots.adb | 93 +++++++------ src/alire/alire-roots.ads | 14 ++ src/alr/alr-commands-action.adb | 4 + testsuite/README.md | 7 + testsuite/drivers/builds.py | 18 +++ testsuite/drivers/driver/python_script.py | 122 ++++++++++++++++-- .../gnat_external/gnat_external-external.toml | 12 ++ .../he/hello/hello-1.0.0.toml | 16 +++ .../he/hello/hello-1.0.1.toml | 29 +++++ .../basic_no_compiler_index/index.toml | 1 + .../li/libhello/libhello-1.0.0.toml | 23 ++++ .../ma/make/make-external.toml | 8 ++ .../gnat_external/gnat_external-external.toml | 12 ++ .../fixtures/compiler_only_index/index.toml | 1 + .../gnat_external/gnat_external-external.toml | 12 ++ testsuite/run.py | 10 +- testsuite/skels/global-index/test.yaml | 4 +- testsuite/skels/local-index/test.yaml | 4 + testsuite/skels/no-index/test.yaml | 6 + testsuite/tests/action/trigger/test.yaml | 1 + testsuite/tests/alias/basic/test.yaml | 1 + .../tests/build/hashes/compiler-input/test.py | 3 - .../build/hashes/compiler-input/test.yaml | 1 + .../build/hashes/compiler-missing/test.py | 10 +- .../build/hashes/compiler-missing/test.yaml | 4 +- .../tests/build/hashes/config-types/test.py | 3 +- .../tests/build/hashes/config-types/test.yaml | 1 + .../tests/build/hashes/hashing-inputs/test.py | 17 ++- .../build/hashes/hashing-inputs/test.yaml | 1 + .../build/hashes/incomplete-config/test.py | 9 +- .../build/hashes/incomplete-config/test.yaml | 1 + .../build_profile/alr_build_switches/test.py | 10 +- .../alr_build_switches/test.yaml | 2 + .../build_profile/custom_profiles/test.yaml | 2 + .../build_profile/custom_switches/test.yaml | 2 + .../tests/build_profile/default/test.yaml | 2 + .../build_profile/get-build-profile/test.yaml | 1 + .../tests/build_profile/recursive/test.py | 3 + .../tests/build_profile/recursive/test.yaml | 2 + .../config/missing-config-default/test.py | 17 +-- .../config/missing-config-default/test.yaml | 1 + testsuite/tests/config/shared-deps/test.py | 3 - testsuite/tests/config/shared-deps/test.yaml | 1 + testsuite/tests/crate_config/basic/test.yaml | 1 + .../tests/crate_config/gen_control/test.yaml | 1 + .../tests/crate_config/value_conflict/test.py | 2 +- .../dockerized/misc/default-cache/test.py | 5 +- testsuite/tests/exec/basic/test.py | 13 +- testsuite/tests/exec/with_project/test.yaml | 1 + .../get/external-tool-dependency/test.py | 36 +++--- testsuite/tests/get/git-local/test.py | 6 - testsuite/tests/get/unpack-in-place/test.py | 6 - testsuite/tests/index/bad-config-vars/test.py | 8 +- .../tests/install/dynamic-linking/test.yaml | 2 + .../install/executable-dependency/test.yaml | 2 + .../tests/install/static-linking/test.yaml | 2 + testsuite/tests/misc/git-ungit/test.py | 11 +- testsuite/tests/misc/sync-manual-edit/test.py | 6 +- .../tests/misc/sync-manual-edit/test.yaml | 1 + .../tests/misc/sync-missing-deps/test.py | 3 +- .../tests/misc/sync-missing-deps/test.yaml | 1 + testsuite/tests/monorepo/basic/test.py | 14 +- testsuite/tests/monorepo/basic/test.yaml | 1 + .../tests/monorepo/doubly-nested/test.py | 11 +- .../tests/monorepo/doubly-nested/test.yaml | 1 + testsuite/tests/monorepo/multi-commit/test.py | 35 +++-- .../tests/monorepo/multi-commit/test.yaml | 1 + testsuite/tests/pin/downgrade/test.py | 17 ++- testsuite/tests/pin/downgrade/test.yaml | 1 + testsuite/tests/pin/equivalent/test.py | 2 +- testsuite/tests/pin/equivalent/test.yaml | 1 + testsuite/tests/pin/from-subdir/test.yaml | 2 + testsuite/tests/pin/post-update/test.yaml | 1 + testsuite/tests/pin/remote/test.yaml | 1 + testsuite/tests/pin/to-parent/test.yaml | 2 + testsuite/tests/printenv/basic/test.py | 17 ++- .../tests/printenv/env-during-fetch/test.py | 24 +++- .../tests/printenv/env-during-fetch/test.yaml | 1 + .../tests/printenv/linked-paths/test.yaml | 1 + .../tests/publish/check-properties/test.yaml | 1 + testsuite/tests/publish/pin-removal/test.yaml | 1 + .../publish/remote-origin-nonstd/test.py | 3 + testsuite/tests/publish/remote-origin/test.py | 3 + .../tests/solver/compiler-installed/test.py | 3 +- testsuite/tests/update/selective/test.yaml | 1 + .../with/auto-gpr-with/gpr_in_subdir/test.py | 5 + .../auto-gpr-with/gpr_in_subdir/test.yaml | 2 + testsuite/tests/with/changes-info/test.yaml | 4 +- testsuite/tests/with/equivalent/test.yaml | 1 + .../workflows/actions-as-dependency/test.py | 64 ++++----- .../workflows/actions-as-dependency/test.yaml | 2 + .../tests/workflows/actions-as-root/test.yaml | 1 + .../workflows/get-build-run-clean/test.yaml | 1 + 99 files changed, 711 insertions(+), 215 deletions(-) create mode 100644 testsuite/fixtures/basic_index/gn/gnat_external/gnat_external-external.toml create mode 100644 testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.0.toml create mode 100644 testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.1.toml create mode 100644 testsuite/fixtures/basic_no_compiler_index/index.toml create mode 100644 testsuite/fixtures/basic_no_compiler_index/li/libhello/libhello-1.0.0.toml create mode 100644 testsuite/fixtures/basic_no_compiler_index/ma/make/make-external.toml create mode 100644 testsuite/fixtures/compiler_only_index/gn/gnat_external/gnat_external-external.toml create mode 100644 testsuite/fixtures/compiler_only_index/index.toml create mode 100644 testsuite/fixtures/solver_index/gn/gnat_external/gnat_external-external.toml diff --git a/src/alire/alire-builds-hashes.adb b/src/alire/alire-builds-hashes.adb index 16692c29f..012f0f588 100644 --- a/src/alire/alire-builds-hashes.adb +++ b/src/alire/alire-builds-hashes.adb @@ -104,6 +104,27 @@ package body Alire.Builds.Hashes is Root.Configuration.Build_Profile (Rel.Name)'Image); end Add_Profile; + ------------------ + -- Add_Switches -- + ------------------ + + procedure Add_Switches is + -- List the exact switches used for compilation due to Alire, as + -- any changes in those will require regen of configuration files. + -- We add a single entry, alphabetically sorted. + Switches : AAA.Strings.Set; + Config : Crate_Configuration.Global_Config := + Root.Configuration.all; + begin + for Switch of Config.Build_Switches (Root, Rel.Name) + loop + Switches.Include (Switch); + end loop; + Add ("switches", + Rel.Name.As_String, + Switches.To_Vector.Flatten (",")); + end Add_Switches; + ------------------- -- Add_Externals -- ------------------- @@ -214,6 +235,7 @@ package body Alire.Builds.Hashes is -- Add individual contributors to the hash input Add_Profile; -- Build profile + Add_Switches; -- Exact list of build switches Add_Configuration; -- Crate configuration variables -- These are only relevant for shared dependencies, as they don't @@ -222,7 +244,17 @@ package body Alire.Builds.Hashes is if not Builds.Sandboxed_Dependencies then Add_Externals; -- GPR externals Add_Environment; -- Environment variables - Add_Compiler; -- Compiler version + + -- In the root crate we can skip compiler detection, as it has no + -- bearing on the hash or config regeneration. This allows most + -- operations in a crate without dependencies to succeed even in + -- absence of a configured compiler. Note that for linked crates, + -- even if they don't have a proper build dir, the hash is + -- important for dependents. + if not Root.Is_Root_Release (Rel.Name) then + Add_Compiler; -- Compiler version + end if; + Add_Dependencies; -- Hash of dependencies end if; diff --git a/src/alire/alire-builds.adb b/src/alire/alire-builds.adb index 73ddf0f4d..f632b95f1 100644 --- a/src/alire/alire-builds.adb +++ b/src/alire/alire-builds.adb @@ -30,7 +30,11 @@ package body Alire.Builds is is Src : constant Absolute_Path := Paths.Vault.Path / Release.Deployment_Folder; - Dst : constant Absolute_Path := Builds.Path (Root, Release); + Dst : constant Absolute_Path := Builds.Path (Root, + Release, + Subdir => False); + -- In case of monorepo, the first time the repo is deployed, it will be + -- synced in its entirety. Synced : Flags.Flag := Flags.Complete_Copy (Dst); begin Was_There := False; @@ -87,11 +91,21 @@ package body Alire.Builds is ---------- function Path (Root : in out Roots.Root; - Release : Releases.Release) + Release : Releases.Release; + Subdir : Boolean) return Absolute_Path - is (Builds.Path - / (Release.Deployment_Folder - & "_" - & Root.Build_Hash (Release.Name))); + is + Base : constant Absolute_Path := + Builds.Path + / (Release.Deployment_Folder + & "_" + & Root.Build_Hash (Release.Name)); + begin + if Subdir and then Release.Origin.Is_Monorepo then + return Base / Release.Origin.Subdir; + else + return Base; + end if; + end Path; end Alire.Builds; diff --git a/src/alire/alire-builds.ads b/src/alire/alire-builds.ads index 0735f6167..c84316812 100644 --- a/src/alire/alire-builds.ads +++ b/src/alire/alire-builds.ads @@ -39,8 +39,11 @@ package Alire.Builds is -- Location of shared builds function Path (Root : in out Roots.Root; - Release : Releases.Release) + Release : Releases.Release; + Subdir : Boolean) return Absolute_Path; - -- Computes the complete path in which the release is going to be built + -- Computes the complete path in which the release is going to be built. + -- If Subdir and Release is in monorepo, include the extra path inside the + -- monorepo. Has no effect for ordinary releases. end Alire.Builds; diff --git a/src/alire/alire-crate_configuration.adb b/src/alire/alire-crate_configuration.adb index ebcf24bf5..e96776531 100644 --- a/src/alire/alire-crate_configuration.adb +++ b/src/alire/alire-crate_configuration.adb @@ -40,6 +40,11 @@ package body Alire.Crate_Configuration is subtype Crate_Name_Set is Containers.Crate_Name_Sets.Set; + procedure Make_Switches_Map (This : in out Global_Config; + Root : in out Alire.Roots.Root; + Rel_Vect : Crate_Name_Set); + -- Prepare the list of switches that apply to a release + -- The Host info types below could be Enums instead of Strings. This would -- have the advantage of providing users the entire list of potential -- values. However, using enums in Ada would have a very high risk of @@ -89,6 +94,23 @@ package body Alire.Crate_Configuration is return Utils.Switches.Profile_Kind is (This.Profile_Map (Crate)); + -------------------- + -- Build_Switches -- + -------------------- + + function Build_Switches (This : in out Global_Config; + Root : in out Roots.Root; + Crate : Crate_Name) + return Utils.Switches.Switch_List + is + begin + -- Ensure they're up to date + Make_Switches_Map (This, Root, + Containers.Crate_Name_Sets.To_Set (Crate)); + + return This.Switches_Map (Crate); + end Build_Switches; + ----------------------- -- Build_Profile_Key -- ----------------------- diff --git a/src/alire/alire-crate_configuration.ads b/src/alire/alire-crate_configuration.ads index 2bc654614..e05b48e8e 100644 --- a/src/alire/alire-crate_configuration.ads +++ b/src/alire/alire-crate_configuration.ads @@ -46,6 +46,14 @@ package Alire.Crate_Configuration is return Utils.Switches.Profile_Kind with Pre => This.Is_Valid; + function Build_Switches (This : in out Global_Config; + Root : in out Roots.Root; + Crate : Crate_Name) + return Utils.Switches.Switch_List + with Pre => This.Is_Valid; + -- The exact switches that apply to a crate (the ones that will be written + -- to their config .gpr files) + function Is_Default_Profile (This : Global_Config; Crate : Crate_Name) return Boolean; diff --git a/src/alire/alire-properties-actions-executor.adb b/src/alire/alire-properties-actions-executor.adb index e6b56035b..6fc40d9e8 100644 --- a/src/alire/alire-properties-actions-executor.adb +++ b/src/alire/alire-properties-actions-executor.adb @@ -143,7 +143,8 @@ package body Alire.Properties.Actions.Executor is end if; for Act of Release.On_Platform_Actions (Env, Now) loop - Trace.Detail ("Running action: " & Act.Image); + Trace.Detail ("Running action: " & Act.Image + & " (cwd:" & Directories.Current & ")"); Execute_Run (This => Runners.Run (Act), Capture => Capture, Err_To_Out => Err_To_Out, diff --git a/src/alire/alire-roots.adb b/src/alire/alire-roots.adb index 2184c42da..c7a9b2d7d 100644 --- a/src/alire/alire-roots.adb +++ b/src/alire/alire-roots.adb @@ -33,6 +33,41 @@ package body Alire.Roots is use type UString; + ------------------- + -- Build_Prepare -- + ------------------- + + procedure Build_Prepare (This : in out Root; + Saved_Profiles : Boolean; + Force_Regen : Boolean) is + begin + -- Check whether we should override configuration with the last one used + -- and stored on disk. Since the first time the one from disk will be be + -- empty, we may still have to generate files in the next step. + + if Saved_Profiles then + This.Set_Build_Profiles (Crate_Configuration.Last_Build_Profiles); + end if; + + This.Load_Configuration; + This.Configuration.Ensure_Complete; + -- For proceeding to build, the configuration must be complete + + -- Ensure sources are up to date + + if not Builds.Sandboxed_Dependencies then + This.Sync_Builds; + -- Changes in configuration may require new build dirs. + end if; + + -- Ensure configurations are in place and up-to-date + + This.Generate_Configuration (Full => Force or else Force_Regen); + -- Will regenerate on demand only those changed. For shared + -- dependencies, will also generate any missing configs not generated + -- during sync, such as for linked releases and the root release. + end Build_Prepare; + ----------- -- Build -- ----------- @@ -182,31 +217,8 @@ package body Alire.Roots is begin - -- Check whether we should override configuration with the last one used - -- and stored on disk. Since the first time the one from disk will be be - -- empty, we may still have to generate files in the next step. - - if Saved_Profiles then - This.Set_Build_Profiles (Crate_Configuration.Last_Build_Profiles); - end if; - - This.Load_Configuration; - This.Configuration.Ensure_Complete; - -- For proceeding to build, the configuration must be complete - - -- Ensure sources are up to date - - if not Builds.Sandboxed_Dependencies then - This.Sync_Builds; - -- Changes in configuration may require new build dirs. - end if; - - -- Ensure configurations are in place and up-to-date - - This.Generate_Configuration (Full => Force); - -- Will regenerate on demand only those changed. For shared - -- dependencies, will also generate any missing configs not generated - -- during sync, such as for linked releases and the root release. + This.Build_Prepare (Saved_Profiles => Saved_Profiles, + Force_Regen => False); This.Export_Build_Environment; @@ -766,11 +778,10 @@ package body Alire.Roots is This.Solution.Print_Hints (This.Environment); - -- Update/Create configuration files - - if Builds.Sandboxed_Dependencies then - This.Generate_Configuration (Full => Force); - end if; + -- For sandboxed deps we could already generate config files, but for + -- shared builds we cannot yet until we are sure the configuration is + -- complete. To have the same behavior in both cases, we also delay + -- configuration generation to build time for sandboxed dependencies. -- Check that the solution does not contain suspicious dependencies, -- taking advantage that this procedure is called whenever a change @@ -1431,7 +1442,7 @@ package body Alire.Roots is return This.Release_Parent (Rel, For_Deploy) / Rel.Base_Folder; when For_Build => - return Builds.Path (This, Rel); + return Builds.Path (This, Rel, Subdir => True); end case; end if; end; @@ -1591,6 +1602,15 @@ package body Alire.Roots is return Boolean is (Dep.Has_Release and then Dep.Crate = This.Release.Reference.Name); + --------------------- + -- Is_Root_Release -- + --------------------- + + function Is_Root_Release (This : in out Root; + Name : Crate_Name) + return Boolean + is (This.Release.Reference.Name = Name); + ------------------------ -- Sync_From_Manifest -- ------------------------ @@ -1716,6 +1736,12 @@ package body Alire.Roots is begin This.Traverse (Removing_Post_Fetch_Flag'Access); end; + + -- Regenerate config files to avoid the unintuitive behavior that after + -- an update they may still not exist (or use old switches). + + This.Build_Prepare (Saved_Profiles => False, + Force_Regen => True); end Update; -------------------- @@ -1845,11 +1871,6 @@ package body Alire.Roots is This.Set (Solution => Needed); This.Deploy_Dependencies; - -- Update/Create configuration files - if Builds.Sandboxed_Dependencies then - This.Generate_Configuration (Full => True); - end if; - Trace.Detail ("Update completed"); end; end Update_Dependencies; diff --git a/src/alire/alire-roots.ads b/src/alire/alire-roots.ads index c55a5985e..57b3bc01c 100644 --- a/src/alire/alire-roots.ads +++ b/src/alire/alire-roots.ads @@ -179,6 +179,11 @@ package Alire.Roots is return Boolean; -- Say if a state during Traverse is the Root release itself + function Is_Root_Release (This : in out Root; + Name : Crate_Name) + return Boolean; + -- Say if the root release matches the given name + procedure Sync_From_Manifest (This : in out Root; Silent : Boolean; Interact : Boolean; @@ -278,6 +283,15 @@ package Alire.Roots is return String; -- Returns the build hash of a crate if the solution; computes on demand. + procedure Build_Prepare (This : in out Root; + Saved_Profiles : Boolean; + Force_Regen : Boolean); + -- Perform all preparations but the building step itself. This will require + -- complete configuration, and will leave all files on disk as if an actual + -- build were attempted. May optionally use saved profiles from the command + -- line (instead of manifests) and force full regeneration (for example, + -- during `alr update`) + function Config_Outdated (This : in out Root; Name : Crate_Name) return Boolean; diff --git a/src/alr/alr-commands-action.adb b/src/alr/alr-commands-action.adb index 7755d920c..fb62cef0b 100644 --- a/src/alr/alr-commands-action.adb +++ b/src/alr/alr-commands-action.adb @@ -160,6 +160,10 @@ package body Alr.Commands.Action is Reportaise_Wrong_Arguments ("Invalid action: " & Arg); end if; + -- Ensure that all directories are ready + Cmd.Root.Build_Prepare (Saved_Profiles => False, + Force_Regen => False); + Cmd.Root.Traverse (Doing => Run_One'Access); if not Some_Output then Put_Line ("No actions to run."); diff --git a/testsuite/README.md b/testsuite/README.md index 14c014001..5a212dbe0 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -34,3 +34,10 @@ $ pip install e3-testsuite # made it available with your PATH): $ ./run.py ``` + +# Creating tests +All tests are based on running a Python script. There are three test drivers: + +- `python-script`: run in host in both sandboxed and shared build mode. + - The build mode can be narrowed down with the `build_mode` attribute. +- `docker-wrapper`: run in a pristine docker Ubuntu image in shared build mode. diff --git a/testsuite/drivers/builds.py b/testsuite/drivers/builds.py index d8479df71..9de84a282 100644 --- a/testsuite/drivers/builds.py +++ b/testsuite/drivers/builds.py @@ -16,6 +16,17 @@ def enable_shared() -> None: run_alr("config", "--global", "--set", "dependencies.shared", "true") +def are_shared() -> bool: + """ + Return True if shared builds are enabled + """ + try: + return run_alr("config", "--global", "--get", + "dependencies.shared").out.strip().lower() == "true" + except: + return False + + def clear_builds_dir() -> None: """ Clear the shared build directory @@ -56,6 +67,13 @@ def path() -> str: return alr_builds_dir() +def vault_path() -> str: + """ + Return the path to the read-only release vault. + """ + return os.path.join(path(), "..", "releases") + + def sync() -> None: """ Sync the shared build directory diff --git a/testsuite/drivers/driver/python_script.py b/testsuite/drivers/driver/python_script.py index 29fc90e57..4e86be460 100644 --- a/testsuite/drivers/driver/python_script.py +++ b/testsuite/drivers/driver/python_script.py @@ -1,7 +1,9 @@ +import copy import os +import shutil import sys -from drivers.alr import prepare_env, prepare_indexes +from drivers.alr import prepare_env, prepare_indexes, run_alr from e3.testsuite.driver.classic import (ClassicTestDriver, TestAbortWithFailure, TestSkip) @@ -14,7 +16,8 @@ class PythonScriptDriver(ClassicTestDriver): This test driver runs a Python script. For a testcase to succeeds, the script expects it to exit with status code 0, its standard error stream to be empty and its standard output stream to end with a line that contains - "SUCCESS". Anything else results in the test failing. + "SUCCESS". If a test must be skipped, it should print "SKIP: ". + Anything else results in the test failing. """ # This is a workaround for Windows, where attempting to use rlimit by e3-core @@ -23,10 +26,11 @@ class PythonScriptDriver(ClassicTestDriver): def default_process_timeout(self): return None - def run(self): + def prepare(self) -> dict: + # prepare a private environment for Python scripts to run "alr". + env = dict(os.environ) - # prepare a private environment for Python scripts to run "alr". config_dir = os.path.join(self.test_env['working_dir'], 'alr-config') prepare_env(config_dir, env) @@ -45,13 +49,19 @@ def run(self): path_for_drivers, os.path.pathsep, python_path ) if python_path else path_for_drivers + return env + + + def run_script(self, env): # Run the Python script with the current interpreter. check_call aborts # the test if the interpreter exits with non-zero status code. - p = self.shell([sys.executable, 'test.py'], - env=env, - cwd=self.test_env['working_dir']) + return self.shell([sys.executable, 'test.py'], + env=env, + cwd=self.test_env['working_dir']) + - # Check that the last line in stdout is "SUCCESS" or "SKIP" + def check_result(self, p): + # Check that the test output is proper (no missing status) out_lines = p.out.splitlines() if out_lines and out_lines[-1] == 'SUCCESS': pass @@ -60,3 +70,99 @@ def run(self): else: self.result.log += 'missing SUCCESS output line' raise TestAbortWithFailure('missing SUCCESS output line') + + + def save_working_dir(self): + # Save the working directory state for later restoration. + + base = self.test_env['working_dir'] + orig_name = ".orig" + orig = os.path.join(base, orig_name) + + # Save the original files under ".orig" folder + os.mkdir(orig) + for f in os.listdir(base): + if f == orig_name: + continue + path = os.path.join(base, f) + if os.path.isfile(path): + shutil.copy(path, orig) + else: + shutil.copytree(path, os.path.join(orig, f)) + + + def restore_working_dir(self): + # Restore the working directory to its initial state, by deleting + # everything and copying originals back from .orig dir + + def make_writable(path): + # Make everything inside a directory writable recursively + for root, dirs, files in os.walk(path): + for d in dirs: + os.chmod(os.path.join(root, d), 0o777) + for f in files: + os.chmod(os.path.join(root, f), 0o666) + + base = self.test_env['working_dir'] + orig_name = ".orig" + + # Delete anything not called ".orig" + for f in os.listdir(base): + if f != orig_name: + path = os.path.join(base, f) + if os.path.isfile(path): + os.remove(path) + else: + # Git marks some files read-only, so make them writable + make_writable(path) + shutil.rmtree(path) + + # Restore the original files + orig = os.path.join(base, orig_name) + for f in os.listdir(orig): + path = os.path.join(orig, f) + if os.path.isfile(path): + shutil.copy(path, base) + else: + shutil.copytree(path, os.path.join(base, f)) + + + def run(self): + # Run the test itself. Depending on the build mode, it may be run + # twice. + DEFAULT_MODE = "both" + + pristine_env = self.prepare() + + # Obtain the build mode for the test + mode = self.test_env.get('build_mode', + self.test_env.get('build-mode', + DEFAULT_MODE)) + # One of 'shared', 'sandboxed', or 'both' + + # If mode is "both", track original files for later + if mode == "both": + self.save_working_dir() + + # First run with shared builds disabled + + if mode in ["sandboxed", "both"]: + self.result.log.log += "Build mode: SANDBOXED\n" + p = self.run_script(copy.deepcopy(pristine_env)) + self.check_result(p) + + # Second run with shared builds enabled + + # Start by cleaning up anything the 1st run may have left behind + if mode == "both": + self.restore_working_dir() + + if mode in ["shared", "both"]: + self.result.log.log += "Build mode: SHARED\n" + # Activate shared builds. Using "-c" is needed as the environment + # still isn't activated at the driver script level. + run_alr("-c", pristine_env["ALR_CONFIG"], + "config", "--global", "--set", + "dependencies.shared", "true") + p = self.run_script(copy.deepcopy(pristine_env)) + self.check_result(p) diff --git a/testsuite/fixtures/basic_index/gn/gnat_external/gnat_external-external.toml b/testsuite/fixtures/basic_index/gn/gnat_external/gnat_external-external.toml new file mode 100644 index 000000000..f1171a6ba --- /dev/null +++ b/testsuite/fixtures/basic_index/gn/gnat_external/gnat_external-external.toml @@ -0,0 +1,12 @@ +description = "GNAT is a compiler for the Ada programming language" +name = "gnat_external" + +maintainers = ["alejandro@mosteo.com"] +maintainers-logins = ["mosteo"] + +[[external]] +kind = "version-output" +# We look for make instead that should be always installed. +version-command = ["make", "--version"] +version-regexp = ".*Make ([\\d\\.]+).*" +provides = "gnat" diff --git a/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.0.toml b/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.0.toml new file mode 100644 index 000000000..bf47cfcae --- /dev/null +++ b/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.0.toml @@ -0,0 +1,16 @@ +description = "\"Hello, world!\" demonstration project" +long-description = "This is an example of long description in a multi-line string.\n\nMarkdown formating `can` be used to have \"nice\" display on the website.\n" +name = "hello" +version = "1.0.0" +website = "example.com" +authors = ["Bob", "Alice"] +licenses = "GPL-3.0-only OR MIT" +maintainers = ["alejandro@mosteo.com", "bob@example.com"] +maintainers-logins = ["mylogin"] +tags = ["tag1", "other-tag"] + +[[depends-on]] +libhello = "^1.0" + +[origin] +url = "file:../../../crates/hello_1.0.0" diff --git a/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.1.toml b/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.1.toml new file mode 100644 index 000000000..e67e218c6 --- /dev/null +++ b/testsuite/fixtures/basic_no_compiler_index/he/hello/hello-1.0.1.toml @@ -0,0 +1,29 @@ +description = "\"Hello, world!\" demonstration project" +long-description = "This is an example of long description in a multi-line string.\n\nMarkdown formating `can` be used to have \"nice\" display on the website.\n" +name = "hello" +version = "1.0.1" +website = "example.com" +authors = ["Bob", "Alice"] +licenses = "GPL-3.0-only OR MIT" +maintainers = ["alejandro@mosteo.com", "bob@example.com"] +maintainers-logins = ["mylogin"] +tags = ["tag1", "other-tag"] + +[[depends-on]] +libhello = "^1.0" + +[configuration.variables] +Var1={type="Boolean"} +Var2={type="String", default="str"} +Var3={type="Enum", values=["A", "B"], default="A"} +Var4={type="Integer", default=0} +Var5={type="Integer", first=-1, last=1, default=0} +Var7={type="Real", default=0.0} +Var6={type="Real", first=-1.0, last=1.0, default=0.0} + +[configuration.values] +hello.Var1=true # So far it is possible for a crate to set its own var +libhello.Var1=false + +[origin] +url = "file:../../../crates/hello_1.0.1" diff --git a/testsuite/fixtures/basic_no_compiler_index/index.toml b/testsuite/fixtures/basic_no_compiler_index/index.toml new file mode 100644 index 000000000..bad265e4f --- /dev/null +++ b/testsuite/fixtures/basic_no_compiler_index/index.toml @@ -0,0 +1 @@ +version = "1.1" diff --git a/testsuite/fixtures/basic_no_compiler_index/li/libhello/libhello-1.0.0.toml b/testsuite/fixtures/basic_no_compiler_index/li/libhello/libhello-1.0.0.toml new file mode 100644 index 000000000..c46f09fab --- /dev/null +++ b/testsuite/fixtures/basic_no_compiler_index/li/libhello/libhello-1.0.0.toml @@ -0,0 +1,23 @@ +description = "\"Hello, world!\" demonstration project support library" +name = "libhello" +version = "1.0.0" +maintainers = ["alejandro@mosteo.com"] +maintainers-logins = ["mylogin"] +tags = ["libhello-tag1"] + +[configuration.variables] +Var1={type="Boolean", default=true} + +[gpr-externals] +TEST_GPR_EXTERNAL = ["gpr_ext_A", "gpr_ext_B", "gpr_ext_C"] +TEST_FREEFORM_UNSET = "" # to test build hashing with an unset var + +[gpr-set-externals] +TEST_GPR_EXTERNAL = "gpr_ext_B" +TEST_UNDECLARED = "used_by_another_crate" + +[environment] +TEST_ENV.set = "myenv" + +[origin] +url = "file:../../../crates/libhello_1.0.0" diff --git a/testsuite/fixtures/basic_no_compiler_index/ma/make/make-external.toml b/testsuite/fixtures/basic_no_compiler_index/ma/make/make-external.toml new file mode 100644 index 000000000..eaf4b23eb --- /dev/null +++ b/testsuite/fixtures/basic_no_compiler_index/ma/make/make-external.toml @@ -0,0 +1,8 @@ +description = "Utility for directing compilation" +name = "make" +maintainers = ["alejandro@mosteo.com"] +maintainers-logins = ["mylogin"] + +[[external]] +kind = "system" +origin = [] # Empty on purpose to ensure unavailable in tests diff --git a/testsuite/fixtures/compiler_only_index/gn/gnat_external/gnat_external-external.toml b/testsuite/fixtures/compiler_only_index/gn/gnat_external/gnat_external-external.toml new file mode 100644 index 000000000..f1171a6ba --- /dev/null +++ b/testsuite/fixtures/compiler_only_index/gn/gnat_external/gnat_external-external.toml @@ -0,0 +1,12 @@ +description = "GNAT is a compiler for the Ada programming language" +name = "gnat_external" + +maintainers = ["alejandro@mosteo.com"] +maintainers-logins = ["mosteo"] + +[[external]] +kind = "version-output" +# We look for make instead that should be always installed. +version-command = ["make", "--version"] +version-regexp = ".*Make ([\\d\\.]+).*" +provides = "gnat" diff --git a/testsuite/fixtures/compiler_only_index/index.toml b/testsuite/fixtures/compiler_only_index/index.toml new file mode 100644 index 000000000..bad265e4f --- /dev/null +++ b/testsuite/fixtures/compiler_only_index/index.toml @@ -0,0 +1 @@ +version = "1.1" diff --git a/testsuite/fixtures/solver_index/gn/gnat_external/gnat_external-external.toml b/testsuite/fixtures/solver_index/gn/gnat_external/gnat_external-external.toml new file mode 100644 index 000000000..f1171a6ba --- /dev/null +++ b/testsuite/fixtures/solver_index/gn/gnat_external/gnat_external-external.toml @@ -0,0 +1,12 @@ +description = "GNAT is a compiler for the Ada programming language" +name = "gnat_external" + +maintainers = ["alejandro@mosteo.com"] +maintainers-logins = ["mosteo"] + +[[external]] +kind = "version-output" +# We look for make instead that should be always installed. +version-command = ["make", "--version"] +version-regexp = ".*Make ([\\d\\.]+).*" +provides = "gnat" diff --git a/testsuite/run.py b/testsuite/run.py index 43843648e..8254dbbad 100755 --- a/testsuite/run.py +++ b/testsuite/run.py @@ -9,17 +9,15 @@ from __future__ import absolute_import, print_function -from argparse import ArgumentTypeError -import sys import os.path +import sys +from argparse import ArgumentTypeError import e3.testsuite import e3.testsuite.driver -from e3.testsuite.result import TestStatus - -from drivers.helpers import on_windows -from drivers.driver.python_script import PythonScriptDriver from drivers.driver.docker_wrapper import DockerWrapperDriver +from drivers.driver.python_script import PythonScriptDriver +from drivers.helpers import on_windows class Testsuite(e3.testsuite.Testsuite): diff --git a/testsuite/skels/global-index/test.yaml b/testsuite/skels/global-index/test.yaml index 872fc1274..1a71b1b05 100644 --- a/testsuite/skels/global-index/test.yaml +++ b/testsuite/skels/global-index/test.yaml @@ -1,3 +1,5 @@ driver: python-script +build_mode: both # one of shared, sandboxed, both (default) indexes: - basic_index: {} + basic_index: + in_fixtures: true diff --git a/testsuite/skels/local-index/test.yaml b/testsuite/skels/local-index/test.yaml index 0a859639c..a0ce9ba5e 100644 --- a/testsuite/skels/local-index/test.yaml +++ b/testsuite/skels/local-index/test.yaml @@ -1,4 +1,8 @@ driver: python-script +build_mode: both # one of shared, sandboxed, both (default) indexes: my_index: in_fixtures: false +# Note that shared builds require a detected compiler to be able to compute +# build hashes, which is needed for many subcommands: build, get, printenv, +# update... See compiler_only_index for an example of mock compiler detector. diff --git a/testsuite/skels/no-index/test.yaml b/testsuite/skels/no-index/test.yaml index 32c747b3f..45e528c23 100644 --- a/testsuite/skels/no-index/test.yaml +++ b/testsuite/skels/no-index/test.yaml @@ -1 +1,7 @@ driver: python-script +build_mode: both # one of shared, sandboxed, both (default) +indexes: + compiler_only_index: {} + # Note that shared builds require a detected compiler to be able to compute + # build hashes, which is needed for many subcommands: build, get, printenv, + # update... \ No newline at end of file diff --git a/testsuite/tests/action/trigger/test.yaml b/testsuite/tests/action/trigger/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/action/trigger/test.yaml +++ b/testsuite/tests/action/trigger/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/alias/basic/test.yaml b/testsuite/tests/alias/basic/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/alias/basic/test.yaml +++ b/testsuite/tests/alias/basic/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/build/hashes/compiler-input/test.py b/testsuite/tests/build/hashes/compiler-input/test.py index 377bd9ae9..14a7f4c9a 100644 --- a/testsuite/tests/build/hashes/compiler-input/test.py +++ b/testsuite/tests/build/hashes/compiler-input/test.py @@ -23,9 +23,6 @@ def check_hash(signature: str) -> None: # Disable compiler selection, so the external is used run_alr("toolchain", "--disable-assistant") -# Enable shared dependencies -run_alr("config", "--set", "--global", "dependencies.shared", "true") - # Init a crate without explicit compiler dependency init_local_crate("xxx") alr_with("crate_real") # A regular crate in the index diff --git a/testsuite/tests/build/hashes/compiler-input/test.yaml b/testsuite/tests/build/hashes/compiler-input/test.yaml index 8185c03b5..80973aefa 100644 --- a/testsuite/tests/build/hashes/compiler-input/test.yaml +++ b/testsuite/tests/build/hashes/compiler-input/test.yaml @@ -1,4 +1,5 @@ driver: python-script +build_mode: shared indexes: toolchain_index: in_fixtures: true diff --git a/testsuite/tests/build/hashes/compiler-missing/test.py b/testsuite/tests/build/hashes/compiler-missing/test.py index 55e943291..13b372fe1 100644 --- a/testsuite/tests/build/hashes/compiler-missing/test.py +++ b/testsuite/tests/build/hashes/compiler-missing/test.py @@ -9,14 +9,18 @@ # The index in this test has no compilers configured; hence we cannot locate # even the default external compiler. -run_alr("config", "--set", "--global", "dependencies.shared", "true") - # Init a crate without explicit compiler dependency # This does not fail because hashes are not computed until build time init_local_crate("xxx") + +# A standalone crate can be built because the compiler isn't used for the root +# crate hash inputs +run_alr("build") + +# Adding a dependency works because this doen't yet trigger an update/build run_alr("with", "libhello") -# The build fails because we cannot compute the build hash without a compiler +# The build fails because we cannot compute the dependency hash without a compiler p = run_alr("build", complain_on_error=False) assert_match(".*Unable to determine compiler version", p.out) diff --git a/testsuite/tests/build/hashes/compiler-missing/test.yaml b/testsuite/tests/build/hashes/compiler-missing/test.yaml index 8929d590a..42e4f842f 100644 --- a/testsuite/tests/build/hashes/compiler-missing/test.yaml +++ b/testsuite/tests/build/hashes/compiler-missing/test.yaml @@ -1,4 +1,4 @@ driver: python-script +build_mode: shared indexes: - basic_index: - in_fixtures: true + basic_no_compiler_index: {} diff --git a/testsuite/tests/build/hashes/config-types/test.py b/testsuite/tests/build/hashes/config-types/test.py index 2df2bb4ff..45a044dae 100644 --- a/testsuite/tests/build/hashes/config-types/test.py +++ b/testsuite/tests/build/hashes/config-types/test.py @@ -7,8 +7,6 @@ from drivers.asserts import assert_eq from drivers import builds -run_alr("config", "--set", "--global", "dependencies.shared", "true") - init_local_crate() alr_with("hello=1.0.1") builds.sync() @@ -27,6 +25,7 @@ 'external:HELLO_LIBRARY_TYPE=default\n' 'external:LIBRARY_TYPE=default\n' 'profile:hello=RELEASE\n' + 'switches:hello=-O3,-fdata-sections,-ffunction-sections,-gnatW8,-gnatn\n' f'version:gnat_external={external_compiler_version()}\n', hash_input("hello")) diff --git a/testsuite/tests/build/hashes/config-types/test.yaml b/testsuite/tests/build/hashes/config-types/test.yaml index 8e25447d9..90efa1f5a 100644 --- a/testsuite/tests/build/hashes/config-types/test.yaml +++ b/testsuite/tests/build/hashes/config-types/test.yaml @@ -1,3 +1,4 @@ driver: python-script +build_mode: shared indexes: build_hash_index: {} diff --git a/testsuite/tests/build/hashes/hashing-inputs/test.py b/testsuite/tests/build/hashes/hashing-inputs/test.py index d56eb55fc..22006a6d7 100644 --- a/testsuite/tests/build/hashes/hashing-inputs/test.py +++ b/testsuite/tests/build/hashes/hashing-inputs/test.py @@ -11,7 +11,6 @@ from drivers import builds from drivers.helpers import content_of -run_alr("config", "--set", "--global", "dependencies.shared", "true") init_local_crate() alr_with("hello") @@ -45,6 +44,11 @@ 'external:TEST_GPR_EXTERNAL=gpr_ext_B\n' # declared set GPR external 'external:TEST_UNDECLARED=used_by_another_crate\n' # modified GPR external 'profile:libhello=VALIDATION\n' # build profile + 'switches:libhello=-O3,-fdata-sections,-ffunction-sections,-g,-gnatVa,' + '-gnatW8,-gnata,-gnatn,-gnato,-gnatw.X,-gnatwa,-gnatwe,-gnaty-d,-gnaty3,' + '-gnatyA,-gnatyB,-gnatyI,-gnatyO,-gnatyS,-gnatya,-gnatyb,-gnatyc,-gnatye,' + '-gnatyf,-gnatyh,-gnatyi,-gnatyk,-gnatyl,-gnatym,-gnatyn,-gnatyp,-gnatyr,' + '-gnatyt,-gnatyu,-gnatyx\n' f'version:gnat_external={external_compiler_version()}\n', # compiler version hash_input("libhello")) @@ -63,6 +67,11 @@ 'external:HELLO_LIBRARY_TYPE=default\n' 'external:LIBRARY_TYPE=default\n' 'profile:hello=VALIDATION\n' + 'switches:hello=-O3,-fdata-sections,-ffunction-sections,-g,-gnatVa,' + '-gnatW8,-gnata,-gnatn,-gnato,-gnatw.X,-gnatwa,-gnatwe,-gnaty-d,-gnaty3,' + '-gnatyA,-gnatyB,-gnatyI,-gnatyO,-gnatyS,-gnatya,-gnatyb,-gnatyc,-gnatye,' + '-gnatyf,-gnatyh,-gnatyi,-gnatyk,-gnatyl,-gnatym,-gnatyn,-gnatyp,-gnatyr,' + '-gnatyt,-gnatyu,-gnatyx\n' f'version:gnat_external={external_compiler_version()}\n', hash_input("hello")) @@ -74,7 +83,11 @@ 'external:LIBRARY_TYPE=default\n' 'external:XXX_LIBRARY_TYPE=default\n' 'profile:xxx=VALIDATION\n' - f'version:gnat_external={external_compiler_version()}\n', + 'switches:xxx=-O3,-fdata-sections,-ffunction-sections,-g,-gnatVa,' + '-gnatW8,-gnata,-gnatn,-gnato,-gnatw.X,-gnatwa,-gnatwe,-gnaty-d,-gnaty3,' + '-gnatyA,-gnatyB,-gnatyI,-gnatyO,-gnatyS,-gnatya,-gnatyb,-gnatyc,-gnatye,' + '-gnatyf,-gnatyh,-gnatyi,-gnatyk,-gnatyl,-gnatym,-gnatyn,-gnatyp,-gnatyr,' + '-gnatyt,-gnatyu,-gnatyx\n', content_of(os.path.join("alire", "build_hash_inputs")) ) diff --git a/testsuite/tests/build/hashes/hashing-inputs/test.yaml b/testsuite/tests/build/hashes/hashing-inputs/test.yaml index 8e25447d9..90efa1f5a 100644 --- a/testsuite/tests/build/hashes/hashing-inputs/test.yaml +++ b/testsuite/tests/build/hashes/hashing-inputs/test.yaml @@ -1,3 +1,4 @@ driver: python-script +build_mode: shared indexes: build_hash_index: {} diff --git a/testsuite/tests/build/hashes/incomplete-config/test.py b/testsuite/tests/build/hashes/incomplete-config/test.py index c649ea5a9..430de6684 100644 --- a/testsuite/tests/build/hashes/incomplete-config/test.py +++ b/testsuite/tests/build/hashes/incomplete-config/test.py @@ -3,13 +3,8 @@ built/hashed """ -import shutil -from drivers.alr import alr_with, external_compiler_version, init_local_crate, run_alr -from drivers.builds import find_hash, hash_input -from drivers.asserts import assert_eq, assert_match -from drivers import builds - -run_alr("config", "--set", "--global", "dependencies.shared", "true") +from drivers.alr import alr_with, init_local_crate, run_alr +from drivers.builds import hash_input init_local_crate() alr_with("libhello=0.9") diff --git a/testsuite/tests/build/hashes/incomplete-config/test.yaml b/testsuite/tests/build/hashes/incomplete-config/test.yaml index 8e25447d9..90efa1f5a 100644 --- a/testsuite/tests/build/hashes/incomplete-config/test.yaml +++ b/testsuite/tests/build/hashes/incomplete-config/test.yaml @@ -1,3 +1,4 @@ driver: python-script +build_mode: shared indexes: build_hash_index: {} diff --git a/testsuite/tests/build_profile/alr_build_switches/test.py b/testsuite/tests/build_profile/alr_build_switches/test.py index b97b559c6..8b6ec7a29 100644 --- a/testsuite/tests/build_profile/alr_build_switches/test.py +++ b/testsuite/tests/build_profile/alr_build_switches/test.py @@ -71,13 +71,13 @@ def check_config_not_changed(): check_config_changed() check_config(bin_config, 'release') -# Alr with will re-generate the crate config and default to DEVELOPMENT +# Alr with does not touch config, that happens at build time alr_with('lib_1', path='../lib_1') -check_config_changed() -check_config(bin_config, 'development') +check_config_not_changed() -# Build with default profile, the config should not change +# Build with default profile, the config should change and revert to development run_alr('build') -check_config_not_changed() +check_config_changed() +check_config(bin_config, 'development') print('SUCCESS') diff --git a/testsuite/tests/build_profile/alr_build_switches/test.yaml b/testsuite/tests/build_profile/alr_build_switches/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/build_profile/alr_build_switches/test.yaml +++ b/testsuite/tests/build_profile/alr_build_switches/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/build_profile/custom_profiles/test.yaml b/testsuite/tests/build_profile/custom_profiles/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/build_profile/custom_profiles/test.yaml +++ b/testsuite/tests/build_profile/custom_profiles/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/build_profile/custom_switches/test.yaml b/testsuite/tests/build_profile/custom_switches/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/build_profile/custom_switches/test.yaml +++ b/testsuite/tests/build_profile/custom_switches/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/build_profile/default/test.yaml b/testsuite/tests/build_profile/default/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/build_profile/default/test.yaml +++ b/testsuite/tests/build_profile/default/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/build_profile/get-build-profile/test.yaml b/testsuite/tests/build_profile/get-build-profile/test.yaml index 872fc1274..a1bd56a2e 100644 --- a/testsuite/tests/build_profile/get-build-profile/test.yaml +++ b/testsuite/tests/build_profile/get-build-profile/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} \ No newline at end of file diff --git a/testsuite/tests/build_profile/recursive/test.py b/testsuite/tests/build_profile/recursive/test.py index f0c314d53..3f6448850 100644 --- a/testsuite/tests/build_profile/recursive/test.py +++ b/testsuite/tests/build_profile/recursive/test.py @@ -2,11 +2,14 @@ Check build --profiles switch """ +from drivers import builds from drivers.alr import run_alr, init_local_crate, alr_pin, alr_manifest from drivers.helpers import lines_of, content_of import os +from drivers.asserts import assert_contents, assert_match + def check_profile(profile: str, file: str): line = f' Build_Profile : Build_Profile_Kind := "{profile}";\n' diff --git a/testsuite/tests/build_profile/recursive/test.yaml b/testsuite/tests/build_profile/recursive/test.yaml index 32c747b3f..7654732d6 100644 --- a/testsuite/tests/build_profile/recursive/test.yaml +++ b/testsuite/tests/build_profile/recursive/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} \ No newline at end of file diff --git a/testsuite/tests/config/missing-config-default/test.py b/testsuite/tests/config/missing-config-default/test.py index b334cd5d8..554bcf8a3 100644 --- a/testsuite/tests/config/missing-config-default/test.py +++ b/testsuite/tests/config/missing-config-default/test.py @@ -30,9 +30,12 @@ assert_match('.*Configuration variables without a default remain unset\n', p.out) -# Get without build must succeed with the missing values as warnings +# Get without build succeeds as no config is needed yet p = run_alr("get", "hello=1.0.0", quiet=False) +# Building must fail and complaint about missing variables +os.chdir(glob("hello_1.0.0_*")[0]) +p = run_alr("build", complain_on_error=False, quiet=False) assert_match('.*Configuration variable \'hello.var1\' not set and has no default value.\n' '.*Configuration variable \'hello.var2\' not set and has no default value.\n' '.*Configuration variable \'hello.var3\' not set and has no default value.\n' @@ -43,17 +46,7 @@ '.*Configuration variable \'libhello.var3\' not set and has no default value.\n' '.*Configuration variable \'libhello.var4\' not set and has no default value.\n' '.*Configuration variable \'libhello.var5\' not set and has no default value.\n' - '.*Skipping generation of incomplete configuration files for crate hello\n' - '.*Skipping generation of incomplete configuration files for crate libhello\n' - '\n' - 'hello=1.0.0 successfully retrieved.', - p.out) - -# Attempting to build now should fail -os.chdir(glob("hello_1.0.0_*")[0]) -p = run_alr("build", complain_on_error=False) -assert p.status != 0, "Build should have failed" -assert_match('.*Configuration variables without a default remain unset\n', + '.*Configuration variables without a default remain unset\n', p.out) # Verify that providing the values in the manifest allows the build to work diff --git a/testsuite/tests/config/missing-config-default/test.yaml b/testsuite/tests/config/missing-config-default/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/config/missing-config-default/test.yaml +++ b/testsuite/tests/config/missing-config-default/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/config/shared-deps/test.py b/testsuite/tests/config/shared-deps/test.py index ed458638e..84291e547 100644 --- a/testsuite/tests/config/shared-deps/test.py +++ b/testsuite/tests/config/shared-deps/test.py @@ -19,9 +19,6 @@ def check_in(file : str, expected : str) -> bool: vault_dir = alr_vault_dir() build_dir = alr_builds_dir() -# Enable shared builds -run_alr("config", "--global", "--set", "dependencies.shared", "true") - # Create a crate with a dependency init_local_crate() alr_with("hello") diff --git a/testsuite/tests/config/shared-deps/test.yaml b/testsuite/tests/config/shared-deps/test.yaml index 8e25447d9..90efa1f5a 100644 --- a/testsuite/tests/config/shared-deps/test.yaml +++ b/testsuite/tests/config/shared-deps/test.yaml @@ -1,3 +1,4 @@ driver: python-script +build_mode: shared indexes: build_hash_index: {} diff --git a/testsuite/tests/crate_config/basic/test.yaml b/testsuite/tests/crate_config/basic/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/crate_config/basic/test.yaml +++ b/testsuite/tests/crate_config/basic/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/crate_config/gen_control/test.yaml b/testsuite/tests/crate_config/gen_control/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/crate_config/gen_control/test.yaml +++ b/testsuite/tests/crate_config/gen_control/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/crate_config/value_conflict/test.py b/testsuite/tests/crate_config/value_conflict/test.py index 69ad4cc11..b54bcadff 100644 --- a/testsuite/tests/crate_config/value_conflict/test.py +++ b/testsuite/tests/crate_config/value_conflict/test.py @@ -9,7 +9,7 @@ import os import platform -p = run_alr('get', 'hello_world', complain_on_error=False) +p = run_alr('get', '--build', 'hello_world', complain_on_error=False) assert p.status != 0, "alr should have errored" print(p.out) diff --git a/testsuite/tests/dockerized/misc/default-cache/test.py b/testsuite/tests/dockerized/misc/default-cache/test.py index b97356f0d..f8afc0222 100644 --- a/testsuite/tests/dockerized/misc/default-cache/test.py +++ b/testsuite/tests/dockerized/misc/default-cache/test.py @@ -5,6 +5,7 @@ import os +from drivers import builds from drivers.alr import alr_with, init_local_crate, run_alr from drivers.helpers import contents @@ -26,7 +27,7 @@ # First, prevent an attempt at downloading a real compiler run_alr("toolchain", "--disable-assistant") -run_alr("config", "--global", "--set", "dependencies.shared", "true") +builds.enable_shared() # Enabled here as we are using the Docker driver alr_with("crate_real") # This release will go in the cache # Read-only vault @@ -43,7 +44,7 @@ # We hardcode this hash so we detect unwilling changes to our hashing scheme. # Every time this hash changes we must know the reason (changes in the hashing # procedures) -hash = "cc2adb8312e543d98d36736d6220023a47a4508f547109334ee36916280e73ac" +hash = "0774083df8ff003084c32cabdec6090a58b41c6be317cec0475df5eacbca0d23" assert \ os.path.isdir(f"{base}/builds/crate_real_1.0.0_filesystem_{hash}"), \ f"Shared build not found at the expected location: f{contents(base)}" diff --git a/testsuite/tests/exec/basic/test.py b/testsuite/tests/exec/basic/test.py index 0e5e1db73..a0eca167f 100644 --- a/testsuite/tests/exec/basic/test.py +++ b/testsuite/tests/exec/basic/test.py @@ -27,9 +27,16 @@ ' alire context:" ${GPR_PROJECT_PATH}', quiet=False) # -q will hide the output of the exec command -assert_match('.* GPR_PROJECT_PATH from alire context.*' - 'hello_[0-9\.]*_filesystem.*' - 'libhello_[0-9\.]*_filesystem.*', +# These may appear in both orders depending on the cache location +try: + assert_match('.* GPR_PROJECT_PATH from alire context.*' + 'hello_[0-9\.]*_filesystem.*' + 'libhello_[0-9\.]*_filesystem.*', + p.out, flags=re.S) +except: + assert_match('.* GPR_PROJECT_PATH from alire context.*' + 'libhello_[0-9\.]*_filesystem.*' + 'hello_[0-9\.]*_filesystem.*', p.out, flags=re.S) print('SUCCESS') diff --git a/testsuite/tests/exec/with_project/test.yaml b/testsuite/tests/exec/with_project/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/exec/with_project/test.yaml +++ b/testsuite/tests/exec/with_project/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/get/external-tool-dependency/test.py b/testsuite/tests/get/external-tool-dependency/test.py index 8ac1efb32..6509127bf 100644 --- a/testsuite/tests/get/external-tool-dependency/test.py +++ b/testsuite/tests/get/external-tool-dependency/test.py @@ -4,6 +4,7 @@ import re +from drivers import builds from drivers.alr import run_alr from drivers.asserts import assert_eq from drivers.helpers import compare, contents @@ -16,7 +17,7 @@ dir_content = contents('main_1.0.0_filesystem/') -# The directrory for the external dependencies 'make' contains a version number +# The directory for the external dependencies 'make' contains a version number # that can be different depending on the platform or version of the # distribution. We search through the content to find that directory and use it # in the expected output. @@ -25,28 +26,33 @@ if re.match('^.*/alire/cache/dependencies/make_.*_external$', elt): make_dep_dir = elt -# Check folder contents -compare(dir_content, - ['main_1.0.0_filesystem/alire', - 'main_1.0.0_filesystem/alire.toml', - 'main_1.0.0_filesystem/alire/alire.lock', - 'main_1.0.0_filesystem/alire/build_hash_inputs', - 'main_1.0.0_filesystem/alire/cache', +# These only appear if dependencies are sandboxed +extra = ['main_1.0.0_filesystem/alire/cache', 'main_1.0.0_filesystem/alire/cache/dependencies', make_dep_dir, make_dep_dir + "/alire", make_dep_dir + "/alire/flags", - make_dep_dir + "/alire/flags/complete_copy", - 'main_1.0.0_filesystem/alire/config.toml', - 'main_1.0.0_filesystem/alire/flags', + make_dep_dir + "/alire/flags/complete_copy"] + +# Check folder contents +compare(dir_content, + ['main_1.0.0_filesystem/alire', + 'main_1.0.0_filesystem/alire.toml', + 'main_1.0.0_filesystem/alire/alire.lock'] + + (extra if not builds.are_shared() else []) + + ['main_1.0.0_filesystem/alire/flags', 'main_1.0.0_filesystem/alire/flags/complete_copy', - 'main_1.0.0_filesystem/config', - 'main_1.0.0_filesystem/config/main_config.ads', - 'main_1.0.0_filesystem/config/main_config.gpr', - 'main_1.0.0_filesystem/config/main_config.h', 'main_1.0.0_filesystem/noop.gpr', 'main_1.0.0_filesystem/src', 'main_1.0.0_filesystem/src/noop.adb' ]) +if builds.are_shared(): + # External tools that have no sources don't have a shared build dir: + try: + assert builds.find_dir("make") # This should raise + raise Exception("Should not have found make build dir") + except: + pass + print('SUCCESS') diff --git a/testsuite/tests/get/git-local/test.py b/testsuite/tests/get/git-local/test.py index d4a441ab3..86fb1ab6a 100644 --- a/testsuite/tests/get/git-local/test.py +++ b/testsuite/tests/get/git-local/test.py @@ -16,8 +16,6 @@ 'libfoo_1.0.0_9ddda32b/alire', 'libfoo_1.0.0_9ddda32b/alire.toml', 'libfoo_1.0.0_9ddda32b/alire/alire.lock', - 'libfoo_1.0.0_9ddda32b/alire/build_hash_inputs', - 'libfoo_1.0.0_9ddda32b/alire/config.toml', 'libfoo_1.0.0_9ddda32b/alire/flags', 'libfoo_1.0.0_9ddda32b/alire/flags/complete_copy', 'libfoo_1.0.0_9ddda32b/b', @@ -27,10 +25,6 @@ 'libfoo_1.0.0_9ddda32b/b/y/q', 'libfoo_1.0.0_9ddda32b/b/z', 'libfoo_1.0.0_9ddda32b/c', - 'libfoo_1.0.0_9ddda32b/config', - 'libfoo_1.0.0_9ddda32b/config/libfoo_config.ads', - 'libfoo_1.0.0_9ddda32b/config/libfoo_config.gpr', - 'libfoo_1.0.0_9ddda32b/config/libfoo_config.h' ]) # Check as dependency diff --git a/testsuite/tests/get/unpack-in-place/test.py b/testsuite/tests/get/unpack-in-place/test.py index 18d72a6a3..afe1909bf 100644 --- a/testsuite/tests/get/unpack-in-place/test.py +++ b/testsuite/tests/get/unpack-in-place/test.py @@ -12,14 +12,8 @@ ['libhello_1.0.0_filesystem/alire', 'libhello_1.0.0_filesystem/alire.toml', 'libhello_1.0.0_filesystem/alire/alire.lock', - 'libhello_1.0.0_filesystem/alire/build_hash_inputs', - 'libhello_1.0.0_filesystem/alire/config.toml', 'libhello_1.0.0_filesystem/alire/flags', 'libhello_1.0.0_filesystem/alire/flags/complete_copy', - 'libhello_1.0.0_filesystem/config', - 'libhello_1.0.0_filesystem/config/libhello_config.ads', - 'libhello_1.0.0_filesystem/config/libhello_config.gpr', - 'libhello_1.0.0_filesystem/config/libhello_config.h', 'libhello_1.0.0_filesystem/libhello.gpr', 'libhello_1.0.0_filesystem/src', 'libhello_1.0.0_filesystem/src/libhello.adb', diff --git a/testsuite/tests/index/bad-config-vars/test.py b/testsuite/tests/index/bad-config-vars/test.py index 47bba445b..6ffa78423 100644 --- a/testsuite/tests/index/bad-config-vars/test.py +++ b/testsuite/tests/index/bad-config-vars/test.py @@ -42,9 +42,11 @@ def check_ok(var_def): p = run_alr('show', 'hello_world', complain_on_error=True, debug=False, quiet=True) - -os.remove(os.path.join("my_index", "index", "he", "hello_world", - ".gitignore")) +try: + os.remove(os.path.join("my_index", "index", "he", "hello_world", + ".gitignore")) +except: + pass # Will have been removed by 1st test run check_error('var1=["plop"]', 'variable definition must be a table') check_error('var1={}', "configuration.variables.var1:") diff --git a/testsuite/tests/install/dynamic-linking/test.yaml b/testsuite/tests/install/dynamic-linking/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/install/dynamic-linking/test.yaml +++ b/testsuite/tests/install/dynamic-linking/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/install/executable-dependency/test.yaml b/testsuite/tests/install/executable-dependency/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/install/executable-dependency/test.yaml +++ b/testsuite/tests/install/executable-dependency/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/install/static-linking/test.yaml b/testsuite/tests/install/static-linking/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/install/static-linking/test.yaml +++ b/testsuite/tests/install/static-linking/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/misc/git-ungit/test.py b/testsuite/tests/misc/git-ungit/test.py index 88ddb010d..4054d27cd 100644 --- a/testsuite/tests/misc/git-ungit/test.py +++ b/testsuite/tests/misc/git-ungit/test.py @@ -5,6 +5,7 @@ import os import shutil +from drivers import builds from drivers.alr import alr_with, crate_dirname, init_local_crate, run_alr from drivers.asserts import assert_file_exists @@ -26,9 +27,13 @@ init_local_crate() alr_with("libfoo") - assert_file_exists(os.path.join("alire", "cache", "dependencies", - foo_dir, ".git"), - wanted=wanted) + if builds.are_shared(): + assert_file_exists(os.path.join(builds.vault_path(), foo_dir, ".git"), + wanted=False) + else: + assert_file_exists(os.path.join("alire", "cache", "dependencies", + foo_dir, ".git"), + wanted=wanted) if not wanted: # Enable for next round diff --git a/testsuite/tests/misc/sync-manual-edit/test.py b/testsuite/tests/misc/sync-manual-edit/test.py index fe355f208..85179752b 100644 --- a/testsuite/tests/misc/sync-manual-edit/test.py +++ b/testsuite/tests/misc/sync-manual-edit/test.py @@ -5,6 +5,7 @@ import os.path +from drivers import builds from drivers.alr import run_alr, alr_touch_manifest from shutil import rmtree # from drivers.asserts import assert_eq, assert_match @@ -31,7 +32,10 @@ run_alr(cmd) # Check dependency folder is at the expected location: - assert os.path.isdir(target), "Directory missing at expected location" + if builds.are_shared(): + assert builds.find_dir("libhello") + else: + assert os.path.isdir(target), "Directory missing at expected location" # Go back up and clean up for next command os.chdir("..") diff --git a/testsuite/tests/misc/sync-manual-edit/test.yaml b/testsuite/tests/misc/sync-manual-edit/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/misc/sync-manual-edit/test.yaml +++ b/testsuite/tests/misc/sync-manual-edit/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/misc/sync-missing-deps/test.py b/testsuite/tests/misc/sync-missing-deps/test.py index ba91edda1..1ce92b910 100644 --- a/testsuite/tests/misc/sync-missing-deps/test.py +++ b/testsuite/tests/misc/sync-missing-deps/test.py @@ -7,6 +7,7 @@ from drivers.alr import run_alr from drivers.builds import find_hash +from drivers import builds # Create a new project and set up dependencies run_alr('init', '--bin', 'xxx') @@ -24,7 +25,7 @@ for round in range(2): if round == 2: # Prepare same test for shared dependencies - run_alr("config", "--set", "--global", "dependencies.shared", "true") + builds.enable_shared() run_alr("update") target = f"builds.path()/hello_1.0.1_filesystem_{find_hash('hello')}" diff --git a/testsuite/tests/misc/sync-missing-deps/test.yaml b/testsuite/tests/misc/sync-missing-deps/test.yaml index 872fc1274..5ccb3287e 100644 --- a/testsuite/tests/misc/sync-missing-deps/test.yaml +++ b/testsuite/tests/misc/sync-missing-deps/test.yaml @@ -1,3 +1,4 @@ driver: python-script +build_mode: sandboxed indexes: basic_index: {} diff --git a/testsuite/tests/monorepo/basic/test.py b/testsuite/tests/monorepo/basic/test.py index 16d4bf8a0..4d5137170 100644 --- a/testsuite/tests/monorepo/basic/test.py +++ b/testsuite/tests/monorepo/basic/test.py @@ -4,8 +4,8 @@ """ import os -import shutil +from drivers import builds from drivers.alr import run_alr, init_local_crate, alr_with, alr_publish from drivers.helpers import init_git_repo, on_windows # from drivers.asserts import assert_eq, assert_match @@ -49,16 +49,18 @@ init_local_crate("top") alr_with("mycrate") run_alr("build") +base = (builds.find_dir("monoproject") if builds.are_shared() + else os.path.join("alire", "cache", "dependencies", f"monoproject_{commit[:8]}")) assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", - f"monoproject_{commit[:8]}", "mycrate", "bin", + base, "mycrate", "bin", f"mycrate{'.exe' if on_windows() else ''}")), \ "Expected binary does not exist" # Also that the info file is there -assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", - f"mycrate_0.1.0_in_monoproject_{commit[:8]}")), \ +deps_dir = (builds.vault_path() if builds.are_shared() + else os.path.dirname(base)) +infofile = f"mycrate_0.1.0_in_monoproject_{commit[:8]}" +assert os.path.isfile(os.path.join(deps_dir, infofile)), \ "Expected info file does not exist" print('SUCCESS') diff --git a/testsuite/tests/monorepo/basic/test.yaml b/testsuite/tests/monorepo/basic/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/monorepo/basic/test.yaml +++ b/testsuite/tests/monorepo/basic/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/monorepo/doubly-nested/test.py b/testsuite/tests/monorepo/doubly-nested/test.py index 0c51634c9..6995e796a 100644 --- a/testsuite/tests/monorepo/doubly-nested/test.py +++ b/testsuite/tests/monorepo/doubly-nested/test.py @@ -3,8 +3,8 @@ """ import os -import shutil +from drivers import builds from drivers.alr import run_alr, init_local_crate, alr_with, alr_publish from drivers.helpers import init_git_repo from subprocess import run @@ -46,9 +46,12 @@ init_local_crate("top") alr_with("mychild") run_alr("build") -assert os.path.isdir(os.path.join("alire", "cache", "dependencies", - f"monoproject_{commit[:8]}", - "myparent", "mychild")), \ +if builds.are_shared(): + path = builds.find_dir("monoproject") +else: + path = os.path.join("alire", "cache", "dependencies", + f"monoproject_{commit[:8]}") +assert os.path.isdir(os.path.join(path, "myparent", "mychild")), \ "Expected directory does not exist" # Verify that "with"ing the parent does not result in a new checkout diff --git a/testsuite/tests/monorepo/doubly-nested/test.yaml b/testsuite/tests/monorepo/doubly-nested/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/monorepo/doubly-nested/test.yaml +++ b/testsuite/tests/monorepo/doubly-nested/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/monorepo/multi-commit/test.py b/testsuite/tests/monorepo/multi-commit/test.py index 41a54621e..344948c85 100644 --- a/testsuite/tests/monorepo/multi-commit/test.py +++ b/testsuite/tests/monorepo/multi-commit/test.py @@ -5,13 +5,12 @@ """ import os -import shutil - -from drivers.alr import run_alr, init_local_crate, alr_with, alr_publish -from drivers.helpers import init_git_repo, on_windows, commit_all -# from drivers.asserts import assert_eq, assert_match from subprocess import run +from drivers import builds +from drivers.alr import alr_publish, alr_with, init_local_crate, run_alr +from drivers.helpers import commit_all, init_git_repo, on_windows + # We create a repository with two nested crates that will act as the upstream # remote repository: start_dir = os.getcwd() @@ -50,24 +49,36 @@ alr_with("crate2") run_alr("build") + +def release_base(commit: str) -> str: + if builds.are_shared(): + return builds.find_dir(f"monoproject_{commit[:8]}") + else: + return os.path.join("alire", "cache", "dependencies", + f"monoproject_{commit[:8]}") + + assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", - f"monoproject_{commit1[:8]}", "crate1", "bin", + release_base(commit1), "crate1", "bin", f"crate1{'.exe' if on_windows() else ''}")), \ "Expected binary does not exist" assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", - f"monoproject_{commit2[:8]}", "crate2", "bin", + release_base(commit2), "crate2", "bin", f"crate2{'.exe' if on_windows() else ''}")), \ "Expected binary does not exist" # Also that the info files are there +if builds.are_shared(): + deps_dir = builds.vault_path() +else: + deps_dir = os.path.join("alire", "cache", "dependencies") + assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", + deps_dir, f"crate1_0.1.0_in_monoproject_{commit1[:8]}")), \ - "Expected info file does not exist" + f"Expected info file does not exist" assert os.path.isfile(os.path.join( - "alire", "cache", "dependencies", + deps_dir, f"crate2_0.1.0_in_monoproject_{commit2[:8]}")), \ "Expected info file does not exist" diff --git a/testsuite/tests/monorepo/multi-commit/test.yaml b/testsuite/tests/monorepo/multi-commit/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/monorepo/multi-commit/test.yaml +++ b/testsuite/tests/monorepo/multi-commit/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/pin/downgrade/test.py b/testsuite/tests/pin/downgrade/test.py index 736779c78..5255dbee3 100644 --- a/testsuite/tests/pin/downgrade/test.py +++ b/testsuite/tests/pin/downgrade/test.py @@ -3,14 +3,13 @@ """ import os +import re -from drivers.alr import run_alr, alr_pin, alr_lockfile -from drivers.asserts import assert_eq, assert_match +from drivers import builds +from drivers.alr import alr_lockfile, alr_pin, run_alr +from drivers.asserts import assert_match from drivers.helpers import check_line_in -import os -import re - # Verify that proper version of libchild is in the printed and disk solution def check_child(version, output, pinned): @@ -26,8 +25,12 @@ def check_child(version, output, pinned): check_line_in(alr_lockfile(), f'version = "{version}"') # Verify dependency folders - assert os.path.exists('alire/cache/dependencies/libchild_' + version + - '_filesystem') + if builds.are_shared(): + run_alr('update') # force hash computation + assert builds.find_dir('libchild_' + version + '_filesystem') + else: + assert os.path.exists('alire/cache/dependencies/libchild_' + version + + '_filesystem') # Create a new "xxx" program project diff --git a/testsuite/tests/pin/downgrade/test.yaml b/testsuite/tests/pin/downgrade/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/pin/downgrade/test.yaml +++ b/testsuite/tests/pin/downgrade/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/pin/equivalent/test.py b/testsuite/tests/pin/equivalent/test.py index b6695240d..0c74e2cf3 100644 --- a/testsuite/tests/pin/equivalent/test.py +++ b/testsuite/tests/pin/equivalent/test.py @@ -3,7 +3,7 @@ """ from drivers.alr import run_alr, alr_pin, init_local_crate -from drivers.asserts import assert_eq, assert_match +from drivers.asserts import assert_eq from drivers.helpers import init_git_repo, git_branch import os diff --git a/testsuite/tests/pin/equivalent/test.yaml b/testsuite/tests/pin/equivalent/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/pin/equivalent/test.yaml +++ b/testsuite/tests/pin/equivalent/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/pin/from-subdir/test.yaml b/testsuite/tests/pin/from-subdir/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/pin/from-subdir/test.yaml +++ b/testsuite/tests/pin/from-subdir/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/pin/post-update/test.yaml b/testsuite/tests/pin/post-update/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/pin/post-update/test.yaml +++ b/testsuite/tests/pin/post-update/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/pin/remote/test.yaml b/testsuite/tests/pin/remote/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/pin/remote/test.yaml +++ b/testsuite/tests/pin/remote/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/pin/to-parent/test.yaml b/testsuite/tests/pin/to-parent/test.yaml index 32c747b3f..fa855459b 100644 --- a/testsuite/tests/pin/to-parent/test.yaml +++ b/testsuite/tests/pin/to-parent/test.yaml @@ -1 +1,3 @@ driver: python-script +indexes: + compiler_only_index: {} diff --git a/testsuite/tests/printenv/basic/test.py b/testsuite/tests/printenv/basic/test.py index 2f4d711a7..10f91e8b8 100644 --- a/testsuite/tests/printenv/basic/test.py +++ b/testsuite/tests/printenv/basic/test.py @@ -5,6 +5,7 @@ from glob import glob import os +from drivers import builds from drivers.alr import run_alr from drivers.asserts import assert_eq, assert_match @@ -27,10 +28,22 @@ def make_path(list): else: return "/".join(list) +# Force dependency syncing for the shared case +run_alr("update") + expected_hello_path = make_path(['.*', 'hello_1.0.1_filesystem']) -expected_libhello_path = make_path(['.*', 'alire', 'cache', 'dependencies', 'libhello_1\.0\.0_filesystem']) +expected_libhello_path = \ +make_path(['.*', os.path.basename(builds.find_dir('libhello'))]) \ +if builds.are_shared() else \ +make_path(['.*', 'alire', 'cache', 'dependencies', 'libhello_1\.0\.0_filesystem']) -expected_gpr_path = os.pathsep.join([expected_hello_path, expected_libhello_path]) +# Depending on the dependency location, both orders may occur +expected_gpr_path = \ + "(" \ + f"{os.pathsep.join([expected_hello_path, expected_libhello_path])}" \ + "|" \ + f"{os.pathsep.join([expected_libhello_path, expected_hello_path])}" \ + ")" assert_match('export ALIRE="True"\n' '.*' diff --git a/testsuite/tests/printenv/env-during-fetch/test.py b/testsuite/tests/printenv/env-during-fetch/test.py index 2ccf9daa0..5c57bfe0d 100644 --- a/testsuite/tests/printenv/env-during-fetch/test.py +++ b/testsuite/tests/printenv/env-during-fetch/test.py @@ -2,17 +2,22 @@ Check that an env var is defined during dependency retrieval (get and with) """ -from glob import glob import os import re +from glob import glob +from drivers import builds from drivers.alr import run_alr from drivers.asserts import assert_match -def verify_output(text): - assert_match('.*CHECKENV_TEST_VAR exists\n.*', - text, flags=re.S) +def verify_output(text, exists: bool): + if exists: + assert_match('.*CHECKENV_TEST_VAR exists\n.*', + text, flags=re.S) + else: + assert "CHECKENV_TEST_VAR exists" not in text, \ + "Unexpected output: " + text # The "checkenv" crate defines CHECKENV_TEST_VAR. Also, its executable prints # "CHECKENV_TEST_VAR exists" or "CHECKENV_TEST_VAR does NOT exist" when run. @@ -24,14 +29,21 @@ def verify_output(text): # Build the crate to trigger the post-fetch action os.chdir(glob("checkparent*")[0]) p = run_alr("build", complain_on_error=False) -verify_output(p.out) +verify_output(p.out, exists=True) # Create a crate from scratch and add the same dependency to perform the check # during retrieval by `with` + run_alr("init", "--bin", "xxx") os.chdir("xxx") run_alr("with", "checkenv") p = run_alr("build") -verify_output(p.out) +# For shared builds, the crate has been already fetched as a dependency of +# checkparent, so it should not emit anything. For sandboxed builds, it should +# emit as expected. +if builds.are_shared(): + verify_output(p.out, exists=False) +else: + verify_output(p.out, exists=True) print('SUCCESS') diff --git a/testsuite/tests/printenv/env-during-fetch/test.yaml b/testsuite/tests/printenv/env-during-fetch/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/printenv/env-during-fetch/test.yaml +++ b/testsuite/tests/printenv/env-during-fetch/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/printenv/linked-paths/test.yaml b/testsuite/tests/printenv/linked-paths/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/printenv/linked-paths/test.yaml +++ b/testsuite/tests/printenv/linked-paths/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/publish/check-properties/test.yaml b/testsuite/tests/publish/check-properties/test.yaml index 8929d590a..0415476b1 100644 --- a/testsuite/tests/publish/check-properties/test.yaml +++ b/testsuite/tests/publish/check-properties/test.yaml @@ -1,4 +1,5 @@ driver: python-script +build_mode: sandboxed indexes: basic_index: in_fixtures: true diff --git a/testsuite/tests/publish/pin-removal/test.yaml b/testsuite/tests/publish/pin-removal/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/publish/pin-removal/test.yaml +++ b/testsuite/tests/publish/pin-removal/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/publish/remote-origin-nonstd/test.py b/testsuite/tests/publish/remote-origin-nonstd/test.py index f891f7e88..2651efc2d 100644 --- a/testsuite/tests/publish/remote-origin-nonstd/test.py +++ b/testsuite/tests/publish/remote-origin-nonstd/test.py @@ -59,4 +59,7 @@ def verify_manifest(): p = run_alr("search", "--crates") assert "xxx" in p.out, "Crate not found in index contents" +# Remove the index for the next test +run_alr("index", "--del", "my_index") + print('SUCCESS') diff --git a/testsuite/tests/publish/remote-origin/test.py b/testsuite/tests/publish/remote-origin/test.py index 0e87ece07..f35c29510 100644 --- a/testsuite/tests/publish/remote-origin/test.py +++ b/testsuite/tests/publish/remote-origin/test.py @@ -56,4 +56,7 @@ def verify_manifest(): p = run_alr("search", "--crates") assert "xxx" in p.out, "Crate not found in index contents" +# Remove the index for the next test +run_alr("index", "--del", "my_index") + print('SUCCESS') diff --git a/testsuite/tests/solver/compiler-installed/test.py b/testsuite/tests/solver/compiler-installed/test.py index 2b2e95373..e5c16fcab 100644 --- a/testsuite/tests/solver/compiler-installed/test.py +++ b/testsuite/tests/solver/compiler-installed/test.py @@ -3,11 +3,10 @@ locally available one is used). """ -import subprocess import re from drivers.alr import run_alr, init_local_crate, alr_with -from drivers.asserts import assert_eq, assert_match, match_solution +from drivers.asserts import assert_match, match_solution # With no compiler selected, the external compiler in the environment should be # the only one available. We will verify this and capture its version (which is diff --git a/testsuite/tests/update/selective/test.yaml b/testsuite/tests/update/selective/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/update/selective/test.yaml +++ b/testsuite/tests/update/selective/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.py b/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.py index 33a88b19b..bb2ea243e 100644 --- a/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.py +++ b/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.py @@ -20,6 +20,11 @@ run_alr('with', 'libhello') run_alr('with', 'gpr_in_subdir') +# In shared mode, a "with" won't generate config files yet (which is desirable +# in case the withed crate has configuration variables without defaults). So we +# need to trigger the generation of the config files. +run_alr("update") + check_line_in('config/myhello_config.gpr', 'with "libhello.gpr";') # When the crate declares a project file: `dir1/dir2/dir3/prj.gpr`, the with diff --git a/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.yaml b/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.yaml index 496a1d1a7..ea8ef3a20 100644 --- a/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.yaml +++ b/testsuite/tests/with/auto-gpr-with/gpr_in_subdir/test.yaml @@ -5,3 +5,5 @@ indexes: my_index: in_fixtures: false copy_crates_src: true + compiler_only_index: + in_fixtures: true diff --git a/testsuite/tests/with/changes-info/test.yaml b/testsuite/tests/with/changes-info/test.yaml index e0a82ba80..028a69369 100644 --- a/testsuite/tests/with/changes-info/test.yaml +++ b/testsuite/tests/with/changes-info/test.yaml @@ -1,4 +1,4 @@ driver: python-script indexes: - solver_index: - in_fixtures: true + solver_index: {} + compiler_only_index: {} \ No newline at end of file diff --git a/testsuite/tests/with/equivalent/test.yaml b/testsuite/tests/with/equivalent/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/with/equivalent/test.yaml +++ b/testsuite/tests/with/equivalent/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} diff --git a/testsuite/tests/workflows/actions-as-dependency/test.py b/testsuite/tests/workflows/actions-as-dependency/test.py index 8f56f5b20..69d1166f2 100644 --- a/testsuite/tests/workflows/actions-as-dependency/test.py +++ b/testsuite/tests/workflows/actions-as-dependency/test.py @@ -2,33 +2,34 @@ Test pre-build/post-build/post-fetch executions in a crate that is a dependency """ -from drivers.alr import run_alr, init_local_crate, add_action, alr_with -from drivers.asserts import assert_match -from drivers.helpers import compare, contents, on_windows +import os from glob import glob from pathlib import Path from shutil import rmtree -import os +from drivers import builds +from drivers.alr import alr_with, init_local_crate, run_alr +from drivers.asserts import assert_match +from drivers.helpers import contents, neutral_path -def check_expected(expected): - if not (expected in contents('.')): +def check_expected(expected, path): + if not (expected in contents(path)): assert False, "%s expected in %s\n Got: %s" % \ - (expected, '.', str(contents('.'))) + (expected, path, str(contents(path))) -def check_not_expected(expected): - if expected in contents('.'): +def check_not_expected(expected, path): + if expected in contents(path): assert False, "%s is unexpected in %s\n Got: %s" % \ - (expected, '.', str(contents('.'))) + (expected, path, str(contents(path))) -def check(file, to_be_or_not_to_be): +def check(file, to_be_or_not_to_be, path): if to_be_or_not_to_be: - check_expected(file) + check_expected(file, path) else: - check_not_expected(file) + check_not_expected(file, path) def do_checks(path_to_dependency): @@ -37,9 +38,9 @@ def do_checks(path_to_dependency): flag_post_build = path_to_dependency + "/test_post_build" # Immediately after adding the dependency, this is the situation: - check(flag_post_fetch, False) - check(flag_pre_build, False) - check(flag_post_build, False) + check(flag_post_fetch, False, path_to_dependency) + check(flag_pre_build, False, path_to_dependency) + check(flag_post_build, False, path_to_dependency) # Build with error, so only pre-build runs but not post-build Path(f"{path_to_dependency}/src/empty.adb").touch() @@ -49,17 +50,17 @@ def do_checks(path_to_dependency): # Post build shouldn't be here because of build failure; post-fetch should # however now exist because a build has been attempted and post-fetch # succeeded (even if the build failed at a later stage) - check(flag_post_fetch, True) - check(flag_pre_build, True) - check(flag_post_build, False) + check(flag_post_fetch, True, path_to_dependency) + check(flag_pre_build, True, path_to_dependency) + check(flag_post_build, False, path_to_dependency) # Remove post-fetch to check it doesn't come back unexpectedly os.remove(flag_post_fetch) # Post build shouldn't be here because of build failure - check(flag_post_fetch, False) - check(flag_pre_build, True) - check(flag_post_build, False) + check(flag_post_fetch, False, path_to_dependency) + check(flag_pre_build, True, path_to_dependency) + check(flag_post_build, False, path_to_dependency) os.remove(flag_pre_build) os.remove(f"{path_to_dependency}/src/empty.adb") @@ -68,23 +69,22 @@ def do_checks(path_to_dependency): run_alr('build') # pre/post-build expected for successful build - check(flag_post_fetch, False) - check(flag_pre_build, True) - check(flag_post_build, True) + check(flag_post_fetch, False, path_to_dependency) + check(flag_pre_build, True, path_to_dependency) + check(flag_post_build, True, path_to_dependency) return - # updating dependencies causes the post-fetch action to run: - run_alr('update') - check(flag_post_fetch, True) - check(flag_pre_build, True) - check(flag_post_build, True) - # Initialize a crate and add as dependency the crate that contains the triggers init_local_crate("root", binary=False) # Lib so all contents are compiled alr_with("hello_world") +run_alr("update") # Test all triggers -do_checks(glob("./alire/cache/dependencies/hello*")[0].replace('\\', '/')) +if builds.are_shared(): + base = neutral_path(builds.find_dir("hello_world")) +else: + base = neutral_path(glob("./alire/cache/dependencies/hello*")[0]) +do_checks(base) # Repeat tests, for a crate that has been added as a linked dependency os.chdir("..") diff --git a/testsuite/tests/workflows/actions-as-dependency/test.yaml b/testsuite/tests/workflows/actions-as-dependency/test.yaml index 0a859639c..b3537ee9a 100644 --- a/testsuite/tests/workflows/actions-as-dependency/test.yaml +++ b/testsuite/tests/workflows/actions-as-dependency/test.yaml @@ -1,4 +1,6 @@ driver: python-script +build_mode: shared indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/workflows/actions-as-root/test.yaml b/testsuite/tests/workflows/actions-as-root/test.yaml index 0a859639c..d6aa8a36d 100644 --- a/testsuite/tests/workflows/actions-as-root/test.yaml +++ b/testsuite/tests/workflows/actions-as-root/test.yaml @@ -2,3 +2,4 @@ driver: python-script indexes: my_index: in_fixtures: false + compiler_only_index: {} diff --git a/testsuite/tests/workflows/get-build-run-clean/test.yaml b/testsuite/tests/workflows/get-build-run-clean/test.yaml index 872fc1274..e2c5af220 100644 --- a/testsuite/tests/workflows/get-build-run-clean/test.yaml +++ b/testsuite/tests/workflows/get-build-run-clean/test.yaml @@ -1,3 +1,4 @@ driver: python-script indexes: basic_index: {} + compiler_only_index: {} From ffc5659ce864740b62fc1ab89b4ea7e93b6f23d1 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Tue, 3 Oct 2023 18:30:58 +0200 Subject: [PATCH 8/9] New `alr printenv --last-build` (#1444) * New `alr printenv --last-build` This may be useful when no direct editing of manifests is convenient, as otherwise `printenv` will always use the manifest's configuration. * make new behavior the default with fallback * CI fixes --- src/alr/alr-commands-config.adb | 28 +++++-------- src/alr/alr-commands-edit.adb | 1 - src/alr/alr-commands-index.adb | 2 - src/alr/alr-commands-printenv.adb | 13 ++++++ src/alr/alr-commands-printenv.ads | 1 + src/alr/alr-commands.adb | 25 +++++++++++ src/alr/alr-commands.ads | 22 +++++++++- testsuite/drivers/builds.py | 9 +++- testsuite/drivers/driver/python_script.py | 3 ++ testsuite/tests/misc/env-traceback/test.py | 3 ++ testsuite/tests/printenv/last-build/test.py | 41 +++++++++++++++++++ testsuite/tests/printenv/last-build/test.yaml | 3 ++ .../tests/printenv/with-external/test.py | 2 +- 13 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 testsuite/tests/printenv/last-build/test.py create mode 100644 testsuite/tests/printenv/last-build/test.yaml diff --git a/src/alr/alr-commands-config.adb b/src/alr/alr-commands-config.adb index b990a089e..00087dd3c 100644 --- a/src/alr/alr-commands-config.adb +++ b/src/alr/alr-commands-config.adb @@ -1,5 +1,3 @@ -with AAA.Enum_Tools; - with Alire.Config; with Alire.Config.Edit; with Alire.Root; @@ -109,21 +107,17 @@ package body Alr.Commands.Config is -- Check explicitly for booleans to store the proper TOML type -- regardless of the capitalization used by the user. - declare - function Is_Boolean is new AAA.Enum_Tools.Is_Valid (Boolean); - begin - if Is_Boolean (Val) then - Alire.Config.Edit.Set_Boolean - (Lvl, - Key, Boolean'Value (Val), - Check => Alire.Config.Edit.Valid_Builtin'Access); - else - Alire.Config.Edit.Set - (Lvl, - Key, Val, - Check => Alire.Config.Edit.Valid_Builtin'Access); - end if; - end; + if Is_Boolean (Val) then + Alire.Config.Edit.Set_Boolean + (Lvl, + Key, Boolean'Value (Val), + Check => Alire.Config.Edit.Valid_Builtin'Access); + else + Alire.Config.Edit.Set + (Lvl, + Key, Val, + Check => Alire.Config.Edit.Valid_Builtin'Access); + end if; end; elsif Cmd.Unset then diff --git a/src/alr/alr-commands-edit.adb b/src/alr/alr-commands-edit.adb index 4dbdd4250..7b2b22c8d 100644 --- a/src/alr/alr-commands-edit.adb +++ b/src/alr/alr-commands-edit.adb @@ -96,7 +96,6 @@ package body Alr.Commands.Edit is Reportaise_Command_Failed ("'" & Exec & "' not available or not in PATH."); end if; - return; end if; end; diff --git a/src/alr/alr-commands-index.adb b/src/alr/alr-commands-index.adb index 47d21ac08..a3c3b8e20 100644 --- a/src/alr/alr-commands-index.adb +++ b/src/alr/alr-commands-index.adb @@ -53,7 +53,6 @@ package body Alr.Commands.Index is begin if not Result.Success then Reportaise_Command_Failed (Alire.Message (Result)); - return; end if; -- Find matching index and delete @@ -159,7 +158,6 @@ package body Alr.Commands.Index is begin if not Result.Success then Reportaise_Command_Failed (Alire.Message (Result)); - return; end if; Table diff --git a/src/alr/alr-commands-printenv.adb b/src/alr/alr-commands-printenv.adb index 2a765de1d..89d06be86 100644 --- a/src/alr/alr-commands-printenv.adb +++ b/src/alr/alr-commands-printenv.adb @@ -1,8 +1,11 @@ +with Alire.Crate_Configuration; with Alire.Environment; with Alire.Platforms; package body Alr.Commands.Printenv is + Last_Build_Switch : constant String := "--last-build"; + ------------- -- Execute -- ------------- @@ -29,6 +32,11 @@ package body Alr.Commands.Printenv is Cmd.Requires_Workspace; + if To_Boolean (Cmd.Last_Build, "--last-build", True) then + Cmd.Root.Set_Build_Profiles + (Alire.Crate_Configuration.Last_Build_Profiles); + end if; + declare Context : constant Alire.Environment.Context := Cmd.Root.Build_Context; @@ -89,6 +97,11 @@ package body Alr.Commands.Printenv is Cmd.Cmd_Shell'Access, "", "--wincmd", "Use a Windows CMD shell format for the export"); + Define_Switch (Config, + Cmd.Last_Build'Access, + "", Last_Build_Switch & "?", + "Use last build profiles (default) or manifest profiles", + Argument => "=BOOLEAN"); end Setup_Switches; end Alr.Commands.Printenv; diff --git a/src/alr/alr-commands-printenv.ads b/src/alr/alr-commands-printenv.ads index 891fb6cb1..4f2263c4d 100644 --- a/src/alr/alr-commands-printenv.ads +++ b/src/alr/alr-commands-printenv.ads @@ -36,5 +36,6 @@ private Unix_Shell : aliased Boolean := False; Power_Shell : aliased Boolean := False; Cmd_Shell : aliased Boolean := False; + Last_Build : aliased GNAT_String := new String'(Unset); end record; end Alr.Commands.Printenv; diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index 62facdfda..a6ee20eb4 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -579,6 +579,31 @@ package body Alr.Commands is Cmd.Optional_Root := Alire.Roots.Optional.Outcome_Success (Root); end Set; + ---------------- + -- To_Boolean -- + ---------------- + + function To_Boolean (Image : GNAT_String; + Switch : String; + Default : Boolean) + return Boolean + is + begin + if Image in null or else Image.all = "" or else Image.all = Unset then + return Default; + elsif Is_Boolean (Image.all) then + return Boolean'Value (Image.all); + elsif Image (Image'First) = '=' then + return To_Boolean (new String'(Image (Image'First + 1 .. Image'Last)), + Switch => Switch, + Default => Default); + else + Reportaise_Wrong_Arguments + ("Value for switch " & Switch & " is not a proper boolean: " + & Image.all); + end if; + end To_Boolean; + begin -- Commands -- diff --git a/src/alr/alr-commands.ads b/src/alr/alr-commands.ads index d5e329fa8..7e115185d 100644 --- a/src/alr/alr-commands.ads +++ b/src/alr/alr-commands.ads @@ -1,3 +1,4 @@ +private with AAA.Enum_Tools; with AAA.Strings; with Alire.Directories; @@ -8,6 +9,7 @@ with Alire.Version; with CLIC.Subcommand; private with GNAT.IO; +private with GNAT.Strings; private with CLIC.Subcommand.Instance; private with Alr.OS_Lib; -- For the benefit of many child packages that use it @@ -109,8 +111,8 @@ private -- Facilities for command/argument identification. These are available to -- commands. - procedure Reportaise_Command_Failed (Message : String); - procedure Reportaise_Wrong_Arguments (Message : String); + procedure Reportaise_Command_Failed (Message : String) with No_Return; + procedure Reportaise_Wrong_Arguments (Message : String) with No_Return; -- Report and Raise :P -- Folder guards conveniences for commands: @@ -153,4 +155,20 @@ private Unset : constant String := "unset"; -- Canary for when a string switch is given without value + subtype GNAT_String is GNAT.Strings.String_Access; + -- Convenience for commands that use string arguments + + function Is_Boolean is new AAA.Enum_Tools.Is_Valid (Boolean); + + function To_Boolean (Image : GNAT_String; + Switch : String; + Default : Boolean) + return Boolean + with Post => + (if Image in null or else Image.all = "" or else Image.all = Unset + then To_Boolean'Result = Default); + -- Convert a switch value to a boolean, if explicitly given, or use the + -- default otherwise. If not a valid boolean or empty, raise Checked_Error + -- with an appropriate error message. + end Alr.Commands; diff --git a/testsuite/drivers/builds.py b/testsuite/drivers/builds.py index 9de84a282..bfbb5fbc5 100644 --- a/testsuite/drivers/builds.py +++ b/testsuite/drivers/builds.py @@ -9,6 +9,13 @@ from drivers.alr import alr_builds_dir, run_alr +def clear_builds_dir() -> None: + """ + Clear the shared build directory + """ + rmtree(path()) + + def enable_shared() -> None: """ Enable shared builds @@ -88,4 +95,4 @@ def sync() -> None: pass def sync_builds() -> None: - sync() \ No newline at end of file + sync() diff --git a/testsuite/drivers/driver/python_script.py b/testsuite/drivers/driver/python_script.py index 4e86be460..b646b301a 100644 --- a/testsuite/drivers/driver/python_script.py +++ b/testsuite/drivers/driver/python_script.py @@ -31,6 +31,9 @@ def prepare(self) -> dict: env = dict(os.environ) + # disable traceback from parent environment if it existed + env.pop('ALR_TRACEBACK_ENABLED', None) + config_dir = os.path.join(self.test_env['working_dir'], 'alr-config') prepare_env(config_dir, env) diff --git a/testsuite/tests/misc/env-traceback/test.py b/testsuite/tests/misc/env-traceback/test.py index fb2dceaea..8e4506e0a 100644 --- a/testsuite/tests/misc/env-traceback/test.py +++ b/testsuite/tests/misc/env-traceback/test.py @@ -23,6 +23,9 @@ def check_traceback(): # By default (no `-d` or ALR_TRACEBACK_ENABLED) we don't get a backtrace check_no_traceback() + +# Explicit disable + for val in ["", "0", "false", "no"]: os.environ['ALR_TRACEBACK_ENABLED'] = val check_no_traceback() diff --git a/testsuite/tests/printenv/last-build/test.py b/testsuite/tests/printenv/last-build/test.py new file mode 100644 index 000000000..04006e93c --- /dev/null +++ b/testsuite/tests/printenv/last-build/test.py @@ -0,0 +1,41 @@ +""" +Test that `alr printenv --last-build` works as expected. +""" + +from drivers import builds +from drivers.alr import alr_with, init_local_crate, run_alr +from drivers.asserts import assert_match + +builds.enable_shared() + +init_local_crate() +alr_with("libhello") +run_alr("build") + +# After a default build, we obtain the hash of the build in release mode +hash_release = builds.find_hash("libhello") + +builds.clear_builds_dir() + +# Now obtain the hash of the build in development mode +run_alr("build", "--profiles=*=development") +hash_devel = builds.find_hash("libhello") + +assert hash_release != hash_devel, "Hashes should be different" + +# Check default printenv behavior, which is to repeat last build settings +p = run_alr("printenv") +assert_match(f".*LIBHELLO_ALIRE_PREFIX=[^\n]*{hash_devel}", p.out) + +# Check printenv --last-build behaviors + +p = run_alr("printenv", "--last-build") +assert_match(f".*LIBHELLO_ALIRE_PREFIX=[^\n]*{hash_devel}", p.out) + +p = run_alr("printenv", "--last-build=true") +assert_match(f".*LIBHELLO_ALIRE_PREFIX=[^\n]*{hash_devel}", p.out) + +p = run_alr("printenv", "--last-build=false") +assert_match(f".*LIBHELLO_ALIRE_PREFIX=[^\n]*{hash_release}", p.out) + +print("SUCCESS") diff --git a/testsuite/tests/printenv/last-build/test.yaml b/testsuite/tests/printenv/last-build/test.yaml new file mode 100644 index 000000000..8e25447d9 --- /dev/null +++ b/testsuite/tests/printenv/last-build/test.yaml @@ -0,0 +1,3 @@ +driver: python-script +indexes: + build_hash_index: {} diff --git a/testsuite/tests/printenv/with-external/test.py b/testsuite/tests/printenv/with-external/test.py index 2528782b8..88c034c66 100644 --- a/testsuite/tests/printenv/with-external/test.py +++ b/testsuite/tests/printenv/with-external/test.py @@ -28,7 +28,7 @@ expected_gpr_path = '.*/libhello_0.9.0_filesystem' # Check the printenv output -assert_match('warn: Generating possibly incomplete environment' +assert_match('.*warn: Generating possibly incomplete environment' ' because of missing dependencies\n' # Note: this warning is via stderr so it's OK '.*' From aab567a4f317521f6a2a9ac0450447ad4a23d6aa Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Wed, 4 Oct 2023 11:01:52 +0200 Subject: [PATCH 9/9] Auto-update index periodically (#1447) * Auto-refresh indexes after some time (default 24h) * ask user on first autoupdate * User changes * Test behavior on network failure --- doc/user-changes.md | 12 ++ src/alire/alire-config-builtins.ads | 20 +++ src/alire/alire-config.adb | 20 +++ src/alire/alire-config.ads | 7 + src/alire/alire-index_on_disk-loading.adb | 84 ++++----- src/alire/alire-index_on_disk-loading.ads | 11 +- src/alire/alire-index_on_disk-updates.adb | 170 ++++++++++++++++++ src/alire/alire-index_on_disk-updates.ads | 16 ++ src/alr/alr-commands-get.adb | 2 + src/alr/alr-commands-index.adb | 6 +- src/alr/alr-commands-install.adb | 42 +++-- src/alr/alr-commands-publish.adb | 2 + src/alr/alr-commands-search.adb | 2 + src/alr/alr-commands-show.adb | 6 + src/alr/alr-commands-toolchain.adb | 4 + src/alr/alr-commands-update.adb | 2 + src/alr/alr-commands-withing.adb | 2 + src/alr/alr-commands.adb | 11 ++ src/alr/alr-commands.ads | 2 + testsuite/Dockerfile | 13 +- testsuite/drivers/alr.py | 4 + testsuite/drivers/driver/docker_wrapper.py | 4 +- .../misc/failed-auto-update/test.py | 58 ++++++ .../misc/failed-auto-update/test.yaml | 2 + testsuite/tests/index/auto-update/test.py | 29 +++ testsuite/tests/index/auto-update/test.yaml | 3 + testsuite/tests/monorepo/get-dirname/test.py | 5 +- 27 files changed, 458 insertions(+), 81 deletions(-) create mode 100644 src/alire/alire-index_on_disk-updates.adb create mode 100644 src/alire/alire-index_on_disk-updates.ads create mode 100644 testsuite/tests/dockerized/misc/failed-auto-update/test.py create mode 100644 testsuite/tests/dockerized/misc/failed-auto-update/test.yaml create mode 100644 testsuite/tests/index/auto-update/test.py create mode 100644 testsuite/tests/index/auto-update/test.yaml diff --git a/doc/user-changes.md b/doc/user-changes.md index c3e57fe61..971b282ed 100644 --- a/doc/user-changes.md +++ b/doc/user-changes.md @@ -6,6 +6,18 @@ stay on top of `alr` new features. ## Release `2.0-dev` +### Automatic index updates + +PR [#1447](https://github.com/alire-project/alire/pull/1447) + +A new configuration option, `index.auto_update`, allows setting the refresh +period of indexes. It defaults to 24 hours and the user will be asked the first +time to allow automatic updates. Setting this option to 0 will also disable +automatic updates. + +When enabled, updates may happen before executing commands that rely on +indexes: `get`, `search`, `with`, etc. + ### Deprecation of `dependencies.dir` in favor of `dependencies.shared` PR [#1419](https://github.com/alire-project/alire/pull/1419) diff --git a/src/alire/alire-config-builtins.ads b/src/alire/alire-config-builtins.ads index 889aefe4d..befaf089c 100644 --- a/src/alire/alire-config-builtins.ads +++ b/src/alire/alire-config-builtins.ads @@ -51,6 +51,26 @@ package Alire.Config.Builtins is "When unset or true, the community index will be added " & "automatically when required if no other index is configured."); + Index_Auto_Update : constant Builtin := New_Builtin + (Key => "index.auto_update", + Kind => Cfg_Int, + Def => "24", -- hours + Help => + "Hours between automatic index refresh. Set to 0 to disable."); + + Index_Auto_Update_Asked : constant Builtin := New_Builtin + (Key => "index.auto_update_asked", + Def => False, + Public => False, + Help => "First time we must autoupdate, we ask the user to approve"); + + Index_Last_Update : constant Builtin := New_Builtin + (Key => "index.last_update", + Public => False, + Kind => Cfg_Int, + Def => "0", -- seconds since epoch + Help => "Timestamp of last index auto-refresh (seconds)"); + Index_Host : constant Builtin := New_Builtin (Key => "index.host", Kind => Cfg_String, diff --git a/src/alire/alire-config.adb b/src/alire/alire-config.adb index faba1b59c..a24f78b39 100644 --- a/src/alire/alire-config.adb +++ b/src/alire/alire-config.adb @@ -16,6 +16,14 @@ package body Alire.Config is function Get (This : Builtin_Option) return Boolean is (DB.Get (+This.Key, Boolean'Value (+This.Def))); + --------- + -- Get -- + --------- + + function Get (This : Builtin_Option) return Config_Int + is (Config_Int'Value + (DB.Get_As_String (+This.Key, +This.Def))); + ----------------- -- Set_Locally -- ----------------- @@ -58,6 +66,18 @@ package body Alire.Config is Edit.Set_Boolean (Level, +This.Key, Value); end Set; + --------- + -- Set -- + --------- + + procedure Set (This : Builtin_Option; + Level : Config.Level; + Value : Config_Int) + is + begin + Edit.Set (Level, +This.Key, Value'Image, This.Check); + end Set; + ----------- -- Unset -- ----------- diff --git a/src/alire/alire-config.ads b/src/alire/alire-config.ads index fd361de5c..5ce5ac1ef 100644 --- a/src/alire/alire-config.ads +++ b/src/alire/alire-config.ads @@ -15,6 +15,8 @@ package Alire.Config is -- Ordering is important, as Globals are loaded first and overridden by any -- Local definition loaded later. + subtype Config_Int is Long_Long_Integer; + --------------- -- Built-ins -- --------------- @@ -41,6 +43,7 @@ package Alire.Config is function Get (This : Builtin_Option) return String; function Get (This : Builtin_Option) return Boolean; + function Get (This : Builtin_Option) return Config_Int; procedure Set_Locally (This : Builtin_Option; Value : String); @@ -54,6 +57,10 @@ package Alire.Config is Level : Config.Level; Value : Boolean); + procedure Set (This : Builtin_Option; + Level : Config.Level; + Value : Config_Int); + procedure Unset (This : Builtin_Option; Level : Config.Level); diff --git a/src/alire/alire-index_on_disk-loading.adb b/src/alire/alire-index_on_disk-loading.adb index 3053ddb9d..1051bac15 100644 --- a/src/alire/alire-index_on_disk-loading.adb +++ b/src/alire/alire-index_on_disk-loading.adb @@ -5,6 +5,7 @@ with Alire.Config.Builtins; with Alire.Config.Edit; with Alire.Containers; with Alire.Index; +with Alire.Index_On_Disk.Updates; with Alire.Platforms.Current; with Alire.Provides; with Alire.TOML_Adapters; @@ -46,10 +47,6 @@ package body Alire.Index_On_Disk.Loading is -- metadata file doesn't exist, a full index load will be triggered and -- the file will be rebuilt. - procedure Invalidate_Providers (Indexes_Dir : Any_Path); - -- Whenever an index is added or updated, we must invalidate the cache on - -- disk containing crate virtual providers. - procedure Save_Providers (Indexes_Dir : Any_Path); -- Write to disk the providers info already in memory (generated after a -- full load). @@ -196,6 +193,22 @@ package body Alire.Index_On_Disk.Loading is Result, Cached => False); use Sets; + + ------------------ + -- Actually_Add -- + ------------------ + + function Actually_Add (Before : String := "") return Outcome is + begin + Updates.Reset_Update_Time; + + return Add (Origin => Alire.Index.Community_Repo & + "#" & Alire.Index.Community_Branch, + Name => Alire.Index.Community_Name, + Under => Config.Edit.Indexes_Directory, + Before => Before); + end Actually_Add; + begin if not Config.Builtins.Index_Auto_Community.Get then Warnings.Warn_Once @@ -212,13 +225,9 @@ package body Alire.Index_On_Disk.Loading is Trace.Debug ("Index was already set, deleting and re-adding..."); Assert (Indexes (I).Delete); - return Add (Origin => Alire.Index.Community_Repo & - "#" & Alire.Index.Community_Branch, - Name => Alire.Index.Community_Name, - Under => Config.Edit.Indexes_Directory, - Before => (if Has_Element (Next (I)) - then Indexes (Next (I)).Name - else "")); + return Actually_Add (Before => (if Has_Element (Next (I)) + then Indexes (Next (I)).Name + else "")); end if; end loop; @@ -228,10 +237,7 @@ package body Alire.Index_On_Disk.Loading is -- Reset cache so next detection finds the new index Trace.Debug ("Index was not set, adding it..."); - return Add (Origin => Alire.Index.Community_Repo & - "#" & Alire.Index.Community_Branch, - Name => Alire.Index.Community_Name, - Under => Config.Edit.Indexes_Directory); + return Actually_Add; exception when E : Checked_Error => return Outcome_From_Exception (E); @@ -372,6 +378,20 @@ package body Alire.Index_On_Disk.Loading is return Indexes; end Find_All; + --------------------- + -- Index_Available -- + --------------------- + + function Index_Available (Under : Absolute_Path := Default_Path) + return Boolean + is + Result : Outcome; + Index : constant Set := Find_All (Under, Result); + begin + Result.Assert; + return not Index.Is_Empty; + end Index_Available; + ---------- -- Load -- ---------- @@ -628,38 +648,4 @@ package body Alire.Index_On_Disk.Loading is end if; end Save_Providers; - ---------------- - -- Update_All -- - ---------------- - - function Update_All (Under : Absolute_Path) return Outcome is - Result : Outcome; - Indexes : constant Set := Find_All (Under, Result); - begin - if not Result.Success then - return Result; - end if; - - -- First, invalidate providers metadata as this may change with the - -- update. - - Invalidate_Providers (Under); - - -- Now update normally - - for Index of Indexes loop - declare - Result : constant Outcome := Index.Update; - begin - if Result.Success then - Trace.Detail ("Updated successfully: " & Index.Origin); - else - return Result; - end if; - end; - end loop; - - return Outcome_Success; - end Update_All; - end Alire.Index_On_Disk.Loading; diff --git a/src/alire/alire-index_on_disk-loading.ads b/src/alire/alire-index_on_disk-loading.ads index 8c7a3d3f9..24e56beaf 100644 --- a/src/alire/alire-index_on_disk-loading.ads +++ b/src/alire/alire-index_on_disk-loading.ads @@ -31,6 +31,10 @@ package Alire.Index_On_Disk.Loading is -- instead of proceeding with default behaviors, such as getting the -- community index. + function Index_Available (Under : Absolute_Path := Default_Path) + return Boolean; + -- Says if there's any available index configured + procedure Setup (From : Absolute_Path := Default_Path); -- If no index is configured, set up the default community index @@ -51,9 +55,6 @@ package Alire.Index_On_Disk.Loading is -- If no path for detection is given, default one is used. -- May raise Checked_Error. Loading twice the same crate is idempotent. - function Update_All (Under : Absolute_Path) return Outcome; - -- Find and update all indexes at given location - function Add (Origin : URL; Name : String; Under : Absolute_Path; @@ -70,6 +71,10 @@ package Alire.Index_On_Disk.Loading is procedure Drop_Index_Cache; -- Force detection of indexes on disk on next call to Find_All + procedure Invalidate_Providers (Indexes_Dir : Any_Path); + -- Whenever an index is added or updated, we must invalidate the cache on + -- disk containing crate virtual providers. + private function Default return Set is (Sets.Empty_Set with null record); diff --git a/src/alire/alire-index_on_disk-updates.adb b/src/alire/alire-index_on_disk-updates.adb new file mode 100644 index 000000000..c22ec9594 --- /dev/null +++ b/src/alire/alire-index_on_disk-updates.adb @@ -0,0 +1,170 @@ +with Ada.Calendar; + +with Alire.Config.Builtins; +with Alire.Index_On_Disk.Loading; + +with CLIC.User_Input; + +package body Alire.Index_On_Disk.Updates is + + package Builtins renames Config.Builtins; + subtype Int is Config.Config_Int; + + Epoch : constant Ada.Calendar.Time := Ada.Calendar.Time_Of + (Year => 2017, + Month => 6, + Day => 23); + -- First Alire commit + + ----------------- + -- Auto_Update -- + ----------------- + + procedure Auto_Update + (Under : Absolute_Path := Config.Edit.Indexes_Directory) + is + Wait : constant Int := Builtins.Index_Auto_Update.Get; + + ------------------- + -- User_Approves -- + ------------------- + + function User_Approves return Boolean is + use CLIC.User_Input; + begin + if Builtins.Index_Auto_Update_Asked.Get then + -- If we reached here and already asked, it means the user already + -- approved it. + return True; + end if; + + if Query (Question => + "The index can be periodically refreshed to make " + & "available recently published crates. " & New_Line + + & "Do you want Alire to go online without asking in the " + & "future? " & New_Line + + & "(You can update manually with `" + & TTY.Terminal ("alr index --update-all") + & "` at any time.)", + + Valid => (Yes | No => True, others => False), + Default => Yes) = Yes + then + Builtins.Index_Auto_Update_Asked.Set (Config.Global, True); + return True; + else + Put_Info ("Understood, Alire will not perform automatic updates."); + Trace.Debug ("Index auto-refresh disabled by user"); + Builtins.Index_Auto_Update.Set (Config.Global, 0); + Builtins.Index_Auto_Update_Asked.Set (Config.Global, True); + return False; + end if; + end User_Approves; + + begin + if Wait = 0 then + Trace.Debug ("Index auto-refresh disabled, skipping"); + return; + end if; + + if not Loading.Index_Available then + Trace.Debug ("Index auto-refresh skipped: no index configured"); + return; + end if; + + declare + use Ada.Calendar; + Seconds_Elapsed : constant Int := + Int (Clock - Epoch) + - Builtins.Index_Last_Update.Get; + Hours_Elapsed : constant Int := Seconds_Elapsed / 60 / 60; + begin + if Hours_Elapsed >= Wait then + + Trace.Debug ("Index auto-refresh triggered," & Hours_Elapsed'Image + & " elapsed is more than wait period of" + & Wait'Image & "h"); + + -- The first time around we ask the user to use auto-updates + + if not User_Approves then + return; + end if; + + -- Proceed with update + + declare + Busy : constant Simple_Logging.Ongoing + := Simple_Logging.Activity ("Updating index") + with Unreferenced; + Result : constant Outcome := Update_All (Under); + begin + if not Result.Success then + Put_Warning + ("Index auto-refresh failed, will try again in" + & Wait'Image & "h"); + Put_Warning + ("Error information: " & Message (Result)); + Reset_Update_Time; + end if; + end; + else + Trace.Debug ("Index auto-refresh not needed:" & Hours_Elapsed'Image + & "h of" & Wait'Image & "h elapsed"); + end if; + end; + end Auto_Update; + + ---------------- + -- Update_All -- + ---------------- + + function Update_All + (Under : Absolute_Path := Config.Edit.Indexes_Directory) return Outcome + is + Result : Outcome; + Indexes : constant Loading.Set := Loading.Find_All (Under, Result); + begin + if not Result.Success then + return Result; + end if; + + -- First, invalidate providers metadata as this may change with the + -- update. + + Loading.Invalidate_Providers (Under); + + -- Now update normally + + for Index of Indexes loop + declare + Result : constant Outcome := Index.Update; + begin + if Result.Success then + Trace.Detail ("Updated successfully: " & Index.Origin); + else + return Result; + end if; + end; + end loop; + + Reset_Update_Time; + + return Outcome_Success; + end Update_All; + + ----------------------- + -- Reset_Update_Time -- + ----------------------- + + procedure Reset_Update_Time is + use Ada.Calendar; + begin + Trace.Debug ("Index auto-refresh timestamp updated"); + Builtins.Index_Last_Update.Set (Config.Global, + Int (Clock - Epoch)); + end Reset_Update_Time; + +end Alire.Index_On_Disk.Updates; diff --git a/src/alire/alire-index_on_disk-updates.ads b/src/alire/alire-index_on_disk-updates.ads new file mode 100644 index 000000000..ceac9389a --- /dev/null +++ b/src/alire/alire-index_on_disk-updates.ads @@ -0,0 +1,16 @@ +with Alire.Config.Edit; + +package Alire.Index_On_Disk.Updates is + + procedure Auto_Update + (Under : Absolute_Path := Config.Edit.Indexes_Directory); + -- Check last update timestamp and update if necessary + + function Update_All + (Under : Absolute_Path := Config.Edit.Indexes_Directory) return Outcome; + -- Find and update all indexes at given location + + procedure Reset_Update_Time; + -- Store that NOW we have just updated our indices + +end Alire.Index_On_Disk.Updates; diff --git a/src/alr/alr-commands-get.adb b/src/alr/alr-commands-get.adb index 70a7aff38..8daa34980 100644 --- a/src/alr/alr-commands-get.adb +++ b/src/alr/alr-commands-get.adb @@ -338,6 +338,8 @@ package body Alr.Commands.Get is ("--dirname is incompatible with other switches"); end if; + Cmd.Auto_Update_Index; + if not Alire.Index.Exists (Allowed.Crate) then Reportaise_Command_Failed ("Crate [" & Args (1) & "] does not exist in the index."); diff --git a/src/alr/alr-commands-index.adb b/src/alr/alr-commands-index.adb index a3c3b8e20..6908e469b 100644 --- a/src/alr/alr-commands-index.adb +++ b/src/alr/alr-commands-index.adb @@ -3,11 +3,13 @@ with AAA.Table_IO; with Alire.Config.Edit; with Alire.Index; with Alire.Index_On_Disk.Loading; +with Alire.Index_On_Disk.Updates; with Alire.Utils; package body Alr.Commands.Index is - package Index_Load renames Alire.Index_On_Disk.Loading; + package Index_Load renames Alire.Index_On_Disk.Loading; + package Index_Updates renames Alire.Index_On_Disk.Updates; -- Forward declarations @@ -291,7 +293,7 @@ package body Alr.Commands.Index is procedure Update_All is Result : constant Alire.Outcome := - Index_Load.Update_All + Index_Updates.Update_All (Alire.Config.Edit.Indexes_Directory); begin if not Result.Success then diff --git a/src/alr/alr-commands-install.adb b/src/alr/alr-commands-install.adb index 7143f0413..941c4c53b 100644 --- a/src/alr/alr-commands-install.adb +++ b/src/alr/alr-commands-install.adb @@ -54,36 +54,41 @@ package body Alr.Commands.Install is Alire.Install.Info (Prefix); - elsif Args.Is_Empty then + else + + Cmd.Auto_Update_Index; - case Alire.Install.Check_Conflicts (Prefix, Cmd.Root.Release) is + if Args.Is_Empty then + + case Alire.Install.Check_Conflicts (Prefix, Cmd.Root.Release) is when Skip => Trace.Info (Cmd.Root.Release.Milestone.TTY_Image & " is already installed, use " & TTY.Terminal ("--force") & " to reinstall"); when New_Install | Reinstall | Replace => - Cmd.Root.Install (Prefix => Prefix); - end case; + Cmd.Root.Install (Prefix => Prefix); + end case; - else + else - -- Install every given dependency + -- Install every given dependency - declare - Deps : Alire.Dependencies.Containers.List; - begin - for Img of Args loop - Deps.Append (Alire.Dependencies.From_String (Img)); - end loop; + declare + Deps : Alire.Dependencies.Containers.List; + begin + for Img of Args loop + Deps.Append (Alire.Dependencies.From_String (Img)); + end loop; - Alire.Install.Add (Prefix, Deps); - end; + Alire.Install.Add (Prefix, Deps); + end; - Alire.Put_Success ("Install to " & TTY.URL (Prefix) - & " finished successfully in " - & TTY.Bold (Timer.Image) & " seconds."); + Alire.Put_Success ("Install to " & TTY.URL (Prefix) + & " finished successfully in " + & TTY.Bold (Timer.Image) & " seconds."); + end if; end if; end Execute; @@ -136,8 +141,7 @@ package body Alr.Commands.Install is Cmd.Prefix'Access, "", "--prefix=", "Override installation prefix (default is " - & TTY.URL ("${HOME}/" & - Alire.Install.Default_Prefix_Basename) & ")"); + & TTY.URL ("${CRATE_ROOT}/alire/prefix)") & ")"); Define_Switch (Config, Cmd.Info'Access, diff --git a/src/alr/alr-commands-publish.adb b/src/alr/alr-commands-publish.adb index 887a1a599..67c3455d9 100644 --- a/src/alr/alr-commands-publish.adb +++ b/src/alr/alr-commands-publish.adb @@ -47,6 +47,8 @@ package body Alr.Commands.Publish is ("Given switches cannot be simultaneously set"); end if; + Cmd.Auto_Update_Index; + if Cmd.Print_Trusted then Alire.Publish.Print_Trusted_Sites; diff --git a/src/alr/alr-commands-search.adb b/src/alr/alr-commands-search.adb index 4332cbb67..71a36b24c 100644 --- a/src/alr/alr-commands-search.adb +++ b/src/alr/alr-commands-search.adb @@ -94,6 +94,8 @@ package body Alr.Commands.Search is begin + Cmd.Auto_Update_Index; + -- First, simpler case of search into crates if Cmd.Crates then diff --git a/src/alr/alr-commands-show.adb b/src/alr/alr-commands-show.adb index 4730cd8a3..20785413b 100644 --- a/src/alr/alr-commands-show.adb +++ b/src/alr/alr-commands-show.adb @@ -296,6 +296,12 @@ package body Alr.Commands.Show is else Alire.Dependencies.From_String (Cmd.Root.Release.Milestone.Image)); begin + + -- Update if asked about remote crates + if Args.Count = 1 then + Cmd.Auto_Update_Index; + end if; + if Args.Count = 1 and then not Alire.Index.Exists (Allowed.Crate, Opts => (Detect_Externals => Cmd.Detect, diff --git a/src/alr/alr-commands-toolchain.adb b/src/alr/alr-commands-toolchain.adb index 9a5516238..e828e7deb 100644 --- a/src/alr/alr-commands-toolchain.adb +++ b/src/alr/alr-commands-toolchain.adb @@ -454,6 +454,8 @@ package body Alr.Commands.Toolchain is if Cmd.S_Select then + Cmd.Auto_Update_Index; + Alire.Toolchains.Detect_Externals; if Cmd.Local then @@ -495,6 +497,8 @@ package body Alr.Commands.Toolchain is elsif Cmd.Install then + Cmd.Auto_Update_Index; + Alire.Toolchains.Detect_Externals; for Elt of Args loop diff --git a/src/alr/alr-commands-update.adb b/src/alr/alr-commands-update.adb index 1afeee218..ba141d2ad 100644 --- a/src/alr/alr-commands-update.adb +++ b/src/alr/alr-commands-update.adb @@ -41,6 +41,8 @@ package body Alr.Commands.Update is if Cmd.Online then Index.Update_All; + else + Cmd.Auto_Update_Index; end if; Cmd.Root.Update (Parse_Allowed, diff --git a/src/alr/alr-commands-withing.adb b/src/alr/alr-commands-withing.adb index bce6f55f8..bd500daec 100644 --- a/src/alr/alr-commands-withing.adb +++ b/src/alr/alr-commands-withing.adb @@ -307,12 +307,14 @@ package body Alr.Commands.Withing is if Cmd.URL.all /= "" then Cmd.Add_With_Pin (New_Root, Args); else + Cmd.Auto_Update_Index; Add (New_Root, Args); end if; elsif Cmd.Del then Del (New_Root, Args); elsif Cmd.From then + Cmd.Auto_Update_Index; From (New_Root, Args); else raise Program_Error with "List should have already happened"; diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index a6ee20eb4..4fcbb3c6a 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -12,6 +12,7 @@ with Alire.Config.Builtins; with Alire.Config.Edit; with Alire.Errors; with Alire.Index_On_Disk.Loading; +with Alire.Index_On_Disk.Updates; with Alire.Lockfiles; with Alire.Paths; with Alire.Platforms.Current; @@ -82,6 +83,16 @@ package body Alr.Commands is Version_Only : aliased Boolean := False; -- Just display the current version and exit + ----------------------- + -- Auto_Update_Index -- + ----------------------- + + procedure Auto_Update_Index (This : Command) is + pragma Unreferenced (This); + begin + Alire.Index_On_Disk.Updates.Auto_Update; + end Auto_Update_Index; + --------------- -- Put_Error -- --------------- diff --git a/src/alr/alr-commands.ads b/src/alr/alr-commands.ads index 7e115185d..54cfcf24a 100644 --- a/src/alr/alr-commands.ads +++ b/src/alr/alr-commands.ads @@ -152,6 +152,8 @@ private TTY_Emph => Alire.TTY.Emph, Global_Options_In_Subcommand_Help => False); + procedure Auto_Update_Index (This : Command); + Unset : constant String := "unset"; -- Canary for when a string switch is given without value diff --git a/testsuite/Dockerfile b/testsuite/Dockerfile index ef064d3dd..6eaae2bcc 100644 --- a/testsuite/Dockerfile +++ b/testsuite/Dockerfile @@ -3,9 +3,18 @@ FROM alire/gnat:ubuntu-lts RUN useradd -m -s /bin/bash user && \ - chown user:user /home/user + chown user:user /home/user && \ + echo "user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +# We need sudo permission to run `unshare` + +RUN apt-get update && apt-get install -y \ + gnat \ + gprbuild \ + libcap2-bin # for `setcap` \ + rsync \ + sudo \ + util-linux # for `unshare` -RUN apt-get update && apt-get install -y gnat gprbuild rsync RUN pip3 install e3-testsuite WORKDIR /testsuite diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index 60366b4f7..6ddc8dee0 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -63,6 +63,10 @@ def prepare_env(config_dir, env): run_alr("-c", config_dir, "config", "--global", "--set", "dependencies.shared", "false") + # Disable index auto-updates, which is not expected by most tests + run_alr("-c", config_dir, "config", "--global", + "--set", "index.auto_update", "0") + # If distro detection is disabled via environment, configure so in alr if "ALIRE_DISABLE_DISTRO" in env: if env["ALIRE_DISABLE_DISTRO"] == "true": diff --git a/testsuite/drivers/driver/docker_wrapper.py b/testsuite/drivers/driver/docker_wrapper.py index e3f013bfa..7b73ebb10 100644 --- a/testsuite/drivers/driver/docker_wrapper.py +++ b/testsuite/drivers/driver/docker_wrapper.py @@ -105,8 +105,8 @@ def run(self): # Run our things try: container = get_client().containers.run( - # Regular image launching - image=TAG, tty=True, stdin_open=True, detach=True, + # Regular image launching (priviledged to allow unshare) + image=TAG, tty=True, stdin_open=True, detach=True, privileged=True, # Pass the test environment to the container as JSON environment={"ALIRE_TEST_ENV": json.dumps(self.test_env)}, diff --git a/testsuite/tests/dockerized/misc/failed-auto-update/test.py b/testsuite/tests/dockerized/misc/failed-auto-update/test.py new file mode 100644 index 000000000..57a6416ba --- /dev/null +++ b/testsuite/tests/dockerized/misc/failed-auto-update/test.py @@ -0,0 +1,58 @@ +""" +Check proper behavior when an index auto-update fails due to a network error +""" + +import os +import subprocess +from subprocess import run +import sys + +from drivers.alr import run_alr +from drivers.asserts import assert_match + +# Skip this test in non-networked environments +if "ALIRE_DISABLE_NETWORK_TESTS" in os.environ: + print("SKIP: network tests disabled") + sys.exit(0) + +# Configure our online test index +# An alternative might be to launch a local git server in bg +INDEX = "git+https://github.com/alire-project/test-index" +run_alr("index", "--name", "test", "--add", INDEX) + +# Check that everything works as expected without index auto-update +run_alr("show", "libhello") + +# Enable autoupdate +run_alr("config", "--global", "--set", "index.auto_update", "1") + +# Ensure next `alr show` will trigger an update +run_alr("config", "--global", "--unset", "index.last_update") +run_alr("config", "--global", "--set", "index.auto_update_asked", "true") + +# Prepare a copy of `unshare` that can be run as regular user +run(["cp", "/usr/bin/unshare", "/tmp"]).check_returncode() +run(["sudo", "setcap", "cap_sys_admin+ep", "/tmp/unshare"]).check_returncode() + +# This command should not fail, but print a warning. Unshare makes the network +# unavailable to alr, so the community index update will fail. +p = run(["/tmp/unshare", "-n", "alr", "-n", "show", "libhello"], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) + +assert p.returncode == 0, f"UNEXPECTED EXIT CODE: {p.returncode}: {p.stdout}" +assert_match(".*Warning: Index auto-refresh failed, will try again in 1h" + , p.stdout) + +# Running again should not produce the warning +p = run(["/tmp/unshare", "-n", "alr", "-n", "show", "libhello"], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True) +assert p.returncode == 0, f"UNEXPECTED EXIT CODE: {p.returncode}: {p.stdout}" +assert "Index auto-refresh failed" not in p.stdout, \ + f"UNEXPECTED OUTPUT: {p.stdout}" + + +print('SUCCESS') diff --git a/testsuite/tests/dockerized/misc/failed-auto-update/test.yaml b/testsuite/tests/dockerized/misc/failed-auto-update/test.yaml new file mode 100644 index 000000000..d05564735 --- /dev/null +++ b/testsuite/tests/dockerized/misc/failed-auto-update/test.yaml @@ -0,0 +1,2 @@ +driver: docker-wrapper +indexes: {} diff --git a/testsuite/tests/index/auto-update/test.py b/testsuite/tests/index/auto-update/test.py new file mode 100644 index 000000000..525191e4e --- /dev/null +++ b/testsuite/tests/index/auto-update/test.py @@ -0,0 +1,29 @@ +""" +Check that index auto-update works as expected +""" + +import os +from drivers.alr import run_alr +from drivers.helpers import content_of, lines_of + +CONFIG_FILE = os.path.join("alr-config", "config.toml") + +# First, we check no related configuration exists + +assert "auto_update_asked = true\n" not in lines_of(CONFIG_FILE), \ + "UNEXPECTED:\n" + content_of(CONFIG_FILE) + +# Auto updates are disabled by default by the python harness, to maintain +# compatibility of older tests. We disable the disabling now. + +run_alr("config", "--global", "--unset", "index.auto_update") +# This was set to 0 to disable updates + +# After using the index, the user will have been asked + +run_alr("search", "hello") + +assert "auto_update_asked = true\n" in lines_of(CONFIG_FILE), \ + "UNEXPECTED:\n" + content_of(CONFIG_FILE) + +print('SUCCESS') diff --git a/testsuite/tests/index/auto-update/test.yaml b/testsuite/tests/index/auto-update/test.yaml new file mode 100644 index 000000000..872fc1274 --- /dev/null +++ b/testsuite/tests/index/auto-update/test.yaml @@ -0,0 +1,3 @@ +driver: python-script +indexes: + basic_index: {} diff --git a/testsuite/tests/monorepo/get-dirname/test.py b/testsuite/tests/monorepo/get-dirname/test.py index c1d31ed6a..36da24376 100644 --- a/testsuite/tests/monorepo/get-dirname/test.py +++ b/testsuite/tests/monorepo/get-dirname/test.py @@ -2,11 +2,8 @@ Verify the output of `alr get --dirname` when the crate is in a monorepo """ -import os -import shutil - from drivers.alr import run_alr -from drivers.asserts import assert_eq, assert_match +from drivers.asserts import assert_eq from drivers.helpers import dir_separator assert_eq(f"crate_12345678{dir_separator()}nested\n",