diff --git a/src/alire/alire-config-builtins.ads b/src/alire/alire-config-builtins.ads index 10f740979..86414bcf4 100644 --- a/src/alire/alire-config-builtins.ads +++ b/src/alire/alire-config-builtins.ads @@ -42,15 +42,21 @@ 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_Refresh : constant Builtin := New_Builtin - (Key => "index.auto_refresh", + 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_Last_Refresh : constant Builtin := New_Builtin - (Key => "index.last_refresh", + 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 diff --git a/src/alire/alire-index_on_disk-loading.adb b/src/alire/alire-index_on_disk-loading.adb index bc49ab12a..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; @@ -192,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 @@ -208,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; @@ -224,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); @@ -368,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 -- ---------- diff --git a/src/alire/alire-index_on_disk-loading.ads b/src/alire/alire-index_on_disk-loading.ads index 51ae1b30a..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 diff --git a/src/alire/alire-index_on_disk-updates.adb b/src/alire/alire-index_on_disk-updates.adb index 86872855a..b21dd9011 100644 --- a/src/alire/alire-index_on_disk-updates.adb +++ b/src/alire/alire-index_on_disk-updates.adb @@ -3,9 +3,12 @@ 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, @@ -20,35 +23,84 @@ package body Alire.Index_On_Disk.Updates is procedure Auto_Update (Under : Absolute_Path := Config.Edit.Indexes_Directory) is - subtype Int is Config.Config_Int; + 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; - Wait : constant Int := Builtins.Index_Auto_Refresh.Get; 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_Refresh.Get; + - 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; begin Update_All (Under).Assert; - - Builtins.Index_Last_Refresh.Set (Config.Global, - Int (Clock - Epoch)); end; else Trace.Debug ("Index auto-refresh not needed:" & Hours_Elapsed'Image @@ -90,7 +142,21 @@ package body Alire.Index_On_Disk.Updates is 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 index 916754ac0..ceac9389a 100644 --- a/src/alire/alire-index_on_disk-updates.ads +++ b/src/alire/alire-index_on_disk-updates.ads @@ -10,4 +10,7 @@ package Alire.Index_On_Disk.Updates is (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/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index 8a86e2b22..4a98d8854 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/tests/index/auto-update/test.py b/testsuite/tests/index/auto-update/test.py new file mode 100644 index 000000000..bc8dabd8a --- /dev/null +++ b/testsuite/tests/index/auto-update/test.py @@ -0,0 +1,30 @@ +""" +Check that index auto-update works as expected +""" + +import os +from drivers.alr import run_alr +# from drivers.asserts import assert_eq, assert_match +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",