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",