@@ -21,20 +21,33 @@ var (
21
21
count int
22
22
dryRun bool
23
23
githubToken string
24
+ serverName string
24
25
)
25
26
27
+ type serverWithName struct {
28
+ name string
29
+ server * registry.Server
30
+ }
31
+
26
32
var updateCmd = & cobra.Command {
27
33
Use : "update" ,
28
34
Short : "Update registry entries with latest information" ,
29
- Long : `Update the oldest entries in the registry with the latest GitHub stars and pulls information.` ,
30
- RunE : updateCmdFunc ,
35
+ Long : `Update entries in the registry with the latest GitHub stars and pulls information.
36
+ By default, updates the oldest entry. Use --count to update multiple oldest entries,
37
+ or --server to update a specific server by name.` ,
38
+ RunE : updateCmdFunc ,
31
39
}
32
40
33
41
func init () {
34
42
updateCmd .Flags ().IntVarP (& count , "count" , "c" , 1 , "Number of entries to update (default 1)" )
35
43
updateCmd .Flags ().BoolVarP (& dryRun , "dry-run" , "d" , false , "Perform a dry run without making changes" )
36
44
updateCmd .Flags ().StringVarP (& githubToken , "github-token" , "t" , "" ,
37
45
"GitHub token for API authentication (can also be set via GITHUB_TOKEN env var)" )
46
+ updateCmd .Flags ().StringVarP (& serverName , "server" , "s" , "" ,
47
+ "Specific server name to update" )
48
+
49
+ // Mark count and server flags as mutually exclusive
50
+ updateCmd .MarkFlagsMutuallyExclusive ("count" , "server" )
38
51
}
39
52
40
53
func updateCmdFunc (_ * cobra.Command , _ []string ) error {
@@ -43,69 +56,112 @@ func updateCmdFunc(_ *cobra.Command, _ []string) error {
43
56
githubToken = os .Getenv ("GITHUB_TOKEN" )
44
57
}
45
58
46
- // Read the registry file directly
59
+ // Load registry
60
+ reg , err := loadRegistry ()
61
+ if err != nil {
62
+ return err
63
+ }
64
+
65
+ // Select servers to update
66
+ servers , err := selectServersToUpdate (reg )
67
+ if err != nil {
68
+ return err
69
+ }
70
+
71
+ // Update servers
72
+ updatedServers := updateServers (servers )
73
+
74
+ // Save results
75
+ return saveResults (reg , updatedServers )
76
+ }
77
+
78
+ func loadRegistry () (* registry.Registry , error ) {
47
79
registryPath := filepath .Join ("pkg" , "registry" , "data" , "registry.json" )
48
80
// #nosec G304 -- This is a known file path
49
81
data , err := os .ReadFile (registryPath )
50
82
if err != nil {
51
- return fmt .Errorf ("failed to read registry file: %w" , err )
83
+ return nil , fmt .Errorf ("failed to read registry file: %w" , err )
52
84
}
53
85
54
- // Parse the registry
55
86
var reg registry.Registry
56
87
if err := json .Unmarshal (data , & reg ); err != nil {
57
- return fmt .Errorf ("failed to parse registry: %w" , err )
88
+ return nil , fmt .Errorf ("failed to parse registry: %w" , err )
89
+ }
90
+
91
+ return & reg , nil
92
+ }
93
+
94
+ func selectServersToUpdate (reg * registry.Registry ) ([]serverWithName , error ) {
95
+ if serverName != "" {
96
+ return selectSpecificServer (reg , serverName )
58
97
}
59
98
60
- // Create a slice of servers with their names
61
- type serverWithName struct {
62
- name string
63
- server * registry.Server
99
+ return selectOldestServers (reg )
100
+ }
101
+
102
+ func selectSpecificServer (reg * registry.Registry , name string ) ([]serverWithName , error ) {
103
+ server , exists := reg .Servers [name ]
104
+ if ! exists {
105
+ return nil , fmt .Errorf ("server '%s' not found in registry" , name )
64
106
}
107
+ server .Name = name
108
+ return []serverWithName {{name : name , server : server }}, nil
109
+ }
110
+
111
+ func selectOldestServers (reg * registry.Registry ) ([]serverWithName , error ) {
65
112
servers := make ([]serverWithName , 0 , len (reg .Servers ))
66
113
for name , server := range reg .Servers {
67
- // Set the name field on each server
68
114
server .Name = name
69
115
servers = append (servers , serverWithName {name : name , server : server })
70
116
}
71
117
72
118
// Sort servers by last updated time (oldest first)
73
119
sort .Slice (servers , func (i , j int ) bool {
74
- var lastUpdatedI , lastUpdatedJ string
120
+ return isOlder (servers [i ].server , servers [j ].server )
121
+ })
75
122
76
- // Handle nil metadata
77
- if servers [i ].server .Metadata != nil {
78
- lastUpdatedI = servers [i ].server .Metadata .LastUpdated
79
- }
80
- if servers [j ].server .Metadata != nil {
81
- lastUpdatedJ = servers [j ].server .Metadata .LastUpdated
82
- }
123
+ // Limit to the requested count
124
+ limit := count
125
+ if limit > len (servers ) {
126
+ limit = len (servers )
127
+ logger .Warnf ("Requested count %d exceeds available servers, limiting to %d" , count , len (servers ))
128
+ }
83
129
84
- timeI , errI := time . Parse ( time . RFC3339 , lastUpdatedI )
85
- timeJ , errJ := time . Parse ( time . RFC3339 , lastUpdatedJ )
130
+ return servers [: limit ], nil
131
+ }
86
132
87
- // If we can't parse either time, put it at the beginning to ensure it gets updated
88
- if errI != nil {
89
- return true
90
- }
91
- if errJ != nil {
92
- return false
93
- }
133
+ func isOlder (serverI , serverJ * registry.Server ) bool {
134
+ var lastUpdatedI , lastUpdatedJ string
94
135
95
- return timeI .Before (timeJ )
96
- })
136
+ if serverI .Metadata != nil {
137
+ lastUpdatedI = serverI .Metadata .LastUpdated
138
+ }
139
+ if serverJ .Metadata != nil {
140
+ lastUpdatedJ = serverJ .Metadata .LastUpdated
141
+ }
97
142
98
- // Limit to the requested count
99
- if count > len (servers ) {
100
- count = len (servers )
101
- logger .Warnf ("Requested count %d exceeds available servers, limiting to %d" , count , len (servers ))
143
+ timeI , errI := time .Parse (time .RFC3339 , lastUpdatedI )
144
+ timeJ , errJ := time .Parse (time .RFC3339 , lastUpdatedJ )
145
+
146
+ // If both times are invalid or missing, fall back to name comparison for stability
147
+ if errI != nil && errJ != nil {
148
+ return serverI .Name < serverJ .Name
149
+ }
150
+ // If only I is invalid, treat I as older
151
+ if errI != nil {
152
+ return true
102
153
}
103
- servers = servers [:count ]
154
+ // If only J is invalid, treat J as older
155
+ if errJ != nil {
156
+ return false
157
+ }
158
+
159
+ return timeI .Before (timeJ )
160
+ }
104
161
105
- // Keep track of updated servers
106
- updatedServers := make ([]string , 0 , count )
162
+ func updateServers ( servers [] serverWithName ) [] string {
163
+ updatedServers := make ([]string , 0 , len ( servers ) )
107
164
108
- // Update each server
109
165
for _ , s := range servers {
110
166
logger .Infof ("Updating server: %s" , s .name )
111
167
@@ -117,6 +173,10 @@ func updateCmdFunc(_ *cobra.Command, _ []string) error {
117
173
updatedServers = append (updatedServers , s .name )
118
174
}
119
175
176
+ return updatedServers
177
+ }
178
+
179
+ func saveResults (reg * registry.Registry , updatedServers []string ) error {
120
180
// If we're in dry run mode, don't save changes
121
181
if dryRun {
122
182
logger .Info ("Dry run completed, no changes made" )
@@ -129,7 +189,7 @@ func updateCmdFunc(_ *cobra.Command, _ []string) error {
129
189
reg .LastUpdated = time .Now ().Format ("2006-01-02 15:04:05" )
130
190
131
191
// Save the updated registry
132
- if err := saveRegistry (& reg , updatedServers ); err != nil {
192
+ if err := saveRegistry (reg , updatedServers ); err != nil {
133
193
return fmt .Errorf ("failed to save registry: %w" , err )
134
194
}
135
195
0 commit comments