Skip to content

Commit 38496cb

Browse files
ardnewMatteoPologruto
authored andcommitted
cli: use cached index with lib search (arduino#1624)
1 parent 396718f commit 38496cb

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

internal/cli/lib/search.go

+50-6
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ import (
2121
"os"
2222
"sort"
2323
"strings"
24+
"time"
2425

26+
"github.com/arduino/arduino-cli/cli/errorcodes"
2527
"github.com/arduino/arduino-cli/commands"
2628
"github.com/arduino/arduino-cli/commands/lib"
29+
"github.com/arduino/arduino-cli/configuration"
2730
"github.com/arduino/arduino-cli/internal/cli/feedback"
2831
"github.com/arduino/arduino-cli/internal/cli/instance"
2932
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
33+
"github.com/arduino/go-paths-helper"
3034
"github.com/sirupsen/logrus"
3135
"github.com/spf13/cobra"
3236
semver "go.bug.st/relaxed-semver"
@@ -48,6 +52,9 @@ func initSearchCommand() *cobra.Command {
4852
return searchCommand
4953
}
5054

55+
// indexUpdateInterval specifies the time threshold over which indexes are updated
56+
const indexUpdateInterval = "60m"
57+
5158
func runSearchCommand(args []string, namesOnly bool) {
5259
inst, status := instance.Create()
5360
logrus.Info("Executing `arduino-cli lib search`")
@@ -56,12 +63,14 @@ func runSearchCommand(args []string, namesOnly bool) {
5663
feedback.Fatal(tr("Error creating instance: %v", status), feedback.ErrGeneric)
5764
}
5865

59-
if err := commands.UpdateLibrariesIndex(
60-
context.Background(),
61-
&rpc.UpdateLibrariesIndexRequest{Instance: inst},
62-
feedback.ProgressBar(),
63-
); err != nil {
64-
feedback.Fatal(tr("Error updating library index: %v", err), feedback.ErrGeneric)
66+
if indexNeedsUpdating(indexUpdateInterval) {
67+
if err := commands.UpdateLibrariesIndex(
68+
context.Background(),
69+
&rpc.UpdateLibrariesIndexRequest{Instance: inst},
70+
feedback.ProgressBar(),
71+
); err != nil {
72+
feedback.Fatal(tr("Error updating library index: %v", err), feedback.ErrGeneric)
73+
}
6574
}
6675

6776
instance.Init(inst)
@@ -180,3 +189,38 @@ func versionsFromSearchedLibrary(library *rpc.SearchedLibrary) []*semver.Version
180189
sort.Sort(semver.List(res))
181190
return res
182191
}
192+
193+
// indexNeedsUpdating returns whether library_index.json need updating.
194+
// A positive duration string must be provided to calculate the time threshold
195+
// used to update the index (default: +24 hours).
196+
// Valid duration units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
197+
// Use a duration of 0 to always update the index.
198+
func indexNeedsUpdating(duration string) bool {
199+
// Library index path is constant (relative to the data directory).
200+
// It does not depend on board manager URLs or any other configuration.
201+
dataDir := configuration.Settings.GetString("directories.Data")
202+
indexPath := paths.New(dataDir).Join("library_index.json")
203+
// Verify the index file exists and we can read its fstat attrs.
204+
if indexPath.NotExist() {
205+
return true
206+
}
207+
info, err := indexPath.Stat()
208+
if err != nil {
209+
return true
210+
}
211+
// Sanity check the given threshold duration string.
212+
now := time.Now()
213+
modTimeThreshold, err := time.ParseDuration(duration)
214+
if err != nil {
215+
feedback.Error(tr("Invalid timeout: %s", err))
216+
os.Exit(errorcodes.ErrBadArgument)
217+
}
218+
// The behavior of now.After(T) is confusing if T < 0 and MTIME in the future,
219+
// and is probably not what the user intended. Disallow negative T and inform
220+
// the user that positive thresholds are expected.
221+
if modTimeThreshold < 0 {
222+
feedback.Error(tr("Timeout must be non-negative: %dns (%s)", modTimeThreshold, duration))
223+
os.Exit(errorcodes.ErrBadArgument)
224+
}
225+
return modTimeThreshold == 0 || now.After(info.ModTime().Add(modTimeThreshold))
226+
}

0 commit comments

Comments
 (0)