Skip to content

Commit 15264b2

Browse files
committed
cli: use cached index with lib search (#1624)
1 parent 6ac5f7a commit 15264b2

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

cli/lib/search.go

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ import (
2121
"os"
2222
"sort"
2323
"strings"
24+
"time"
2425

2526
"github.com/arduino/arduino-cli/cli/errorcodes"
2627
"github.com/arduino/arduino-cli/cli/feedback"
2728
"github.com/arduino/arduino-cli/cli/instance"
2829
"github.com/arduino/arduino-cli/cli/output"
2930
"github.com/arduino/arduino-cli/commands"
3031
"github.com/arduino/arduino-cli/commands/lib"
32+
"github.com/arduino/arduino-cli/configuration"
3133
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
34+
"github.com/arduino/go-paths-helper"
3235
"github.com/sirupsen/logrus"
3336
"github.com/spf13/cobra"
3437
semver "go.bug.st/relaxed-semver"
@@ -51,6 +54,9 @@ func initSearchCommand() *cobra.Command {
5154
return searchCommand
5255
}
5356

57+
// indexUpdateInterval specifies the time threshold over which indexes are updated
58+
const indexUpdateInterval = "60m"
59+
5460
func runSearchCommand(cmd *cobra.Command, args []string) {
5561
inst, status := instance.Create()
5662
logrus.Info("Executing `arduino-cli lib search`")
@@ -60,13 +66,15 @@ func runSearchCommand(cmd *cobra.Command, args []string) {
6066
os.Exit(errorcodes.ErrGeneric)
6167
}
6268

63-
if err := commands.UpdateLibrariesIndex(
64-
context.Background(),
65-
&rpc.UpdateLibrariesIndexRequest{Instance: inst},
66-
output.ProgressBar(),
67-
); err != nil {
68-
feedback.Errorf(tr("Error updating library index: %v"), err)
69-
os.Exit(errorcodes.ErrGeneric)
69+
if indexNeedsUpdating(indexUpdateInterval) {
70+
if err := commands.UpdateLibrariesIndex(
71+
context.Background(),
72+
&rpc.UpdateLibrariesIndexRequest{Instance: inst},
73+
output.ProgressBar(),
74+
); err != nil {
75+
feedback.Errorf(tr("Error updating library index: %v"), err)
76+
os.Exit(errorcodes.ErrGeneric)
77+
}
7078
}
7179

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

0 commit comments

Comments
 (0)