@@ -21,12 +21,16 @@ import (
21
21
"os"
22
22
"sort"
23
23
"strings"
24
+ "time"
24
25
26
+ "github.com/arduino/arduino-cli/cli/errorcodes"
25
27
"github.com/arduino/arduino-cli/commands"
26
28
"github.com/arduino/arduino-cli/commands/lib"
29
+ "github.com/arduino/arduino-cli/configuration"
27
30
"github.com/arduino/arduino-cli/internal/cli/feedback"
28
31
"github.com/arduino/arduino-cli/internal/cli/instance"
29
32
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
33
+ "github.com/arduino/go-paths-helper"
30
34
"github.com/sirupsen/logrus"
31
35
"github.com/spf13/cobra"
32
36
semver "go.bug.st/relaxed-semver"
@@ -48,6 +52,9 @@ func initSearchCommand() *cobra.Command {
48
52
return searchCommand
49
53
}
50
54
55
+ // indexUpdateInterval specifies the time threshold over which indexes are updated
56
+ const indexUpdateInterval = "60m"
57
+
51
58
func runSearchCommand (args []string , namesOnly bool ) {
52
59
inst , status := instance .Create ()
53
60
logrus .Info ("Executing `arduino-cli lib search`" )
@@ -56,12 +63,14 @@ func runSearchCommand(args []string, namesOnly bool) {
56
63
feedback .Fatal (tr ("Error creating instance: %v" , status ), feedback .ErrGeneric )
57
64
}
58
65
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
+ }
65
74
}
66
75
67
76
instance .Init (inst )
@@ -180,3 +189,38 @@ func versionsFromSearchedLibrary(library *rpc.SearchedLibrary) []*semver.Version
180
189
sort .Sort (semver .List (res ))
181
190
return res
182
191
}
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