tangled
alpha
login
or
join now
atscan.net
/
plcbundle-go
1
fork
atom
[DEPRECATED] Go implementation of plcbundle
1
fork
atom
overview
issues
pulls
pipelines
query cmd
tree.fail
4 months ago
21a48e40
866286c0
+478
-9
6 changed files
expand all
collapse all
unified
split
cmd
plcbundle
commands
progress_helper.go
query.go
main.go
ui
progress.go
go.mod
go.sum
+56
cmd/plcbundle/commands/progress_helper.go
···
1
1
+
package commands
2
2
+
3
3
+
import (
4
4
+
"tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui"
5
5
+
)
6
6
+
7
7
+
// NewBundleProgressBar creates a progress bar with auto-calculated bytes from bundles
8
8
+
func NewBundleProgressBar(mgr BundleManager, start, end int) *ui.ProgressBar {
9
9
+
total := end - start + 1
10
10
+
11
11
+
// Calculate total bytes from bundle metadata
12
12
+
index := mgr.GetIndex()
13
13
+
totalBytes := int64(0)
14
14
+
15
15
+
for bundleNum := start; bundleNum <= end; bundleNum++ {
16
16
+
if meta, err := index.GetBundle(bundleNum); err == nil {
17
17
+
totalBytes += meta.UncompressedSize
18
18
+
}
19
19
+
}
20
20
+
21
21
+
if totalBytes > 0 {
22
22
+
return ui.NewProgressBarWithBytes(total, totalBytes)
23
23
+
}
24
24
+
25
25
+
// Fallback: estimate based on average
26
26
+
stats := index.GetStats()
27
27
+
if avgBytes := estimateAvgBundleSize(stats); avgBytes > 0 {
28
28
+
return ui.NewProgressBarWithBytesAuto(total, avgBytes)
29
29
+
}
30
30
+
31
31
+
return ui.NewProgressBar(total)
32
32
+
}
33
33
+
34
34
+
// estimateAvgBundleSize estimates average uncompressed bundle size
35
35
+
func estimateAvgBundleSize(stats map[string]interface{}) int64 {
36
36
+
if totalUncompressed, ok := stats["total_uncompressed_size"].(int64); ok {
37
37
+
if bundleCount, ok := stats["bundle_count"].(int); ok && bundleCount > 0 {
38
38
+
return totalUncompressed / int64(bundleCount)
39
39
+
}
40
40
+
}
41
41
+
return 0
42
42
+
}
43
43
+
44
44
+
// UpdateBundleProgress updates progress with bundle's actual size
45
45
+
func UpdateBundleProgress(pb *ui.ProgressBar, current int, bundle interface{}) {
46
46
+
// Try to extract size from bundle if available
47
47
+
type sizer interface {
48
48
+
GetUncompressedSize() int64
49
49
+
}
50
50
+
51
51
+
if b, ok := bundle.(sizer); ok {
52
52
+
pb.SetWithBytes(current, b.GetUncompressedSize())
53
53
+
} else {
54
54
+
pb.Set(current)
55
55
+
}
56
56
+
}
+357
cmd/plcbundle/commands/query.go
···
1
1
+
package commands
2
2
+
3
3
+
import (
4
4
+
"context"
5
5
+
"fmt"
6
6
+
"os"
7
7
+
"runtime"
8
8
+
"sync"
9
9
+
"sync/atomic"
10
10
+
11
11
+
"github.com/goccy/go-json"
12
12
+
"github.com/jmespath/go-jmespath"
13
13
+
"github.com/spf13/cobra"
14
14
+
"tangled.org/atscan.net/plcbundle/cmd/plcbundle/ui"
15
15
+
)
16
16
+
17
17
+
func NewQueryCommand() *cobra.Command {
18
18
+
var (
19
19
+
bundleRange string
20
20
+
threads int
21
21
+
format string
22
22
+
limit int
23
23
+
noProgress bool
24
24
+
)
25
25
+
26
26
+
cmd := &cobra.Command{
27
27
+
Use: "query <expression> [flags]",
28
28
+
Aliases: []string{"q", "history"},
29
29
+
Short: "Query ops using JMESPath",
30
30
+
Long: `Query operations using JMESPath expressions
31
31
+
32
32
+
Stream through operations in bundles and evaluate JMESPath expressions
33
33
+
on each operation. Supports parallel processing for better performance.
34
34
+
35
35
+
The JMESPath expression is evaluated against each operation's JSON structure.
36
36
+
Only operations where the expression returns a non-null value are output.
37
37
+
38
38
+
Output formats:
39
39
+
jsonl - Output matching operations as JSONL (default)
40
40
+
count - Only output count of matches`,
41
41
+
42
42
+
Example: ` # Extract DID field from all operations
43
43
+
plcbundle query 'did' --bundles 1-10
44
44
+
45
45
+
# Extract PDS endpoints
46
46
+
plcbundle query 'operation.services.atproto_pds.endpoint' --bundles 1-100
47
47
+
48
48
+
# Wildcard service endpoints
49
49
+
plcbundle query 'operation.services.*.endpoint' --bundles 1-100
50
50
+
51
51
+
# Filter with conditions
52
52
+
plcbundle query 'operation.alsoKnownAs[?contains(@, ` + "`bsky`" + `)]' --bundles 1-100
53
53
+
54
54
+
# Complex queries
55
55
+
plcbundle query 'operation | {did: did, handle: operation.handle}' --bundles 1-10
56
56
+
57
57
+
# Count matches only
58
58
+
plcbundle query 'operation.services.atproto_pds' --bundles 1-1000 --format count
59
59
+
60
60
+
# Parallel processing with 8 workers
61
61
+
plcbundle query 'did' --bundles 1-1000 --threads 8
62
62
+
63
63
+
# Limit results
64
64
+
plcbundle query 'did' --bundles 1-100 --limit 1000
65
65
+
66
66
+
# Disable progress bar (for scripting)
67
67
+
plcbundle query 'operation.handle' --bundles 1-100 --no-progress
68
68
+
69
69
+
# Auto-detect CPU cores
70
70
+
plcbundle query 'did' --bundles 1-1000 --threads 0`,
71
71
+
72
72
+
Args: cobra.ExactArgs(1),
73
73
+
74
74
+
RunE: func(cmd *cobra.Command, args []string) error {
75
75
+
expression := args[0]
76
76
+
77
77
+
// Auto-detect threads
78
78
+
if threads <= 0 {
79
79
+
threads = runtime.NumCPU()
80
80
+
if threads < 1 {
81
81
+
threads = 1
82
82
+
}
83
83
+
}
84
84
+
85
85
+
mgr, _, err := getManager(&ManagerOptions{Cmd: cmd})
86
86
+
if err != nil {
87
87
+
return err
88
88
+
}
89
89
+
defer mgr.Close()
90
90
+
91
91
+
// Determine bundle range
92
92
+
var start, end int
93
93
+
if bundleRange == "" {
94
94
+
index := mgr.GetIndex()
95
95
+
bundles := index.GetBundles()
96
96
+
if len(bundles) == 0 {
97
97
+
return fmt.Errorf("no bundles available")
98
98
+
}
99
99
+
start = bundles[0].BundleNumber
100
100
+
end = bundles[len(bundles)-1].BundleNumber
101
101
+
} else {
102
102
+
start, end, err = parseBundleRange(bundleRange)
103
103
+
if err != nil {
104
104
+
return err
105
105
+
}
106
106
+
}
107
107
+
108
108
+
return runQuery(cmd.Context(), mgr, queryOptions{
109
109
+
expression: expression,
110
110
+
start: start,
111
111
+
end: end,
112
112
+
threads: threads,
113
113
+
format: format,
114
114
+
limit: limit,
115
115
+
noProgress: noProgress,
116
116
+
})
117
117
+
},
118
118
+
}
119
119
+
120
120
+
cmd.Flags().StringVar(&bundleRange, "bundles", "", "Bundle selection: number (42) or range (1-50)")
121
121
+
cmd.Flags().IntVar(&threads, "threads", 0, "Number of worker threads (0 = auto-detect CPU cores)")
122
122
+
cmd.Flags().StringVar(&format, "format", "jsonl", "Output format: jsonl|count")
123
123
+
cmd.Flags().IntVar(&limit, "limit", 0, "Limit number of results (0 = unlimited)")
124
124
+
cmd.Flags().BoolVar(&noProgress, "no-progress", false, "Disable progress output")
125
125
+
126
126
+
return cmd
127
127
+
}
128
128
+
129
129
+
type queryOptions struct {
130
130
+
expression string
131
131
+
start int
132
132
+
end int
133
133
+
threads int
134
134
+
format string
135
135
+
limit int
136
136
+
noProgress bool
137
137
+
}
138
138
+
139
139
+
func runQuery(ctx context.Context, mgr BundleManager, opts queryOptions) error {
140
140
+
// Compile JMESPath expression once
141
141
+
compiled, err := jmespath.Compile(opts.expression)
142
142
+
if err != nil {
143
143
+
return fmt.Errorf("invalid JMESPath expression: %w", err)
144
144
+
}
145
145
+
146
146
+
totalBundles := opts.end - opts.start + 1
147
147
+
148
148
+
// Adjust threads if more than bundles
149
149
+
if opts.threads > totalBundles {
150
150
+
opts.threads = totalBundles
151
151
+
}
152
152
+
153
153
+
fmt.Fprintf(os.Stderr, "Query: %s\n", opts.expression)
154
154
+
fmt.Fprintf(os.Stderr, "Bundles: %d-%d (%d total)\n", opts.start, opts.end, totalBundles)
155
155
+
fmt.Fprintf(os.Stderr, "Threads: %d\n", opts.threads)
156
156
+
fmt.Fprintf(os.Stderr, "Format: %s\n", opts.format)
157
157
+
if opts.limit > 0 {
158
158
+
fmt.Fprintf(os.Stderr, "Limit: %d\n", opts.limit)
159
159
+
}
160
160
+
fmt.Fprintf(os.Stderr, "\n")
161
161
+
162
162
+
// Shared counters
163
163
+
var (
164
164
+
totalOps int64
165
165
+
matchCount int64
166
166
+
bytesProcessed int64
167
167
+
)
168
168
+
169
169
+
// Progress tracking with bytes
170
170
+
var progress *ui.ProgressBar
171
171
+
if !opts.noProgress {
172
172
+
// Use bundle-aware progress bar with byte tracking
173
173
+
progress = NewBundleProgressBar(mgr, opts.start, opts.end)
174
174
+
}
175
175
+
176
176
+
// Setup channels
177
177
+
jobs := make(chan int, opts.threads*2)
178
178
+
results := make(chan queryResult, opts.threads*2)
179
179
+
180
180
+
// Start workers
181
181
+
var wg sync.WaitGroup
182
182
+
for w := 0; w < opts.threads; w++ {
183
183
+
wg.Add(1)
184
184
+
go func() {
185
185
+
defer wg.Done()
186
186
+
for bundleNum := range jobs {
187
187
+
select {
188
188
+
case <-ctx.Done():
189
189
+
return
190
190
+
default:
191
191
+
}
192
192
+
193
193
+
res := processBundleQuery(ctx, mgr, bundleNum, compiled, opts.limit > 0, &matchCount, int64(opts.limit))
194
194
+
results <- res
195
195
+
}
196
196
+
}()
197
197
+
}
198
198
+
199
199
+
// Result collector
200
200
+
go func() {
201
201
+
wg.Wait()
202
202
+
close(results)
203
203
+
}()
204
204
+
205
205
+
// Send jobs
206
206
+
go func() {
207
207
+
defer close(jobs)
208
208
+
for bundleNum := opts.start; bundleNum <= opts.end; bundleNum++ {
209
209
+
select {
210
210
+
case jobs <- bundleNum:
211
211
+
case <-ctx.Done():
212
212
+
return
213
213
+
}
214
214
+
}
215
215
+
}()
216
216
+
217
217
+
// Collect and output results
218
218
+
processed := 0
219
219
+
for res := range results {
220
220
+
processed++
221
221
+
222
222
+
if res.err != nil {
223
223
+
fmt.Fprintf(os.Stderr, "\nWarning: bundle %06d failed: %v\n", res.bundleNum, res.err)
224
224
+
} else {
225
225
+
atomic.AddInt64(&totalOps, int64(res.opsProcessed))
226
226
+
atomic.AddInt64(&bytesProcessed, res.bytesProcessed)
227
227
+
228
228
+
// Output matches (unless count-only mode)
229
229
+
if opts.format != "count" {
230
230
+
for _, match := range res.matches {
231
231
+
// Check if limit reached
232
232
+
if opts.limit > 0 && atomic.LoadInt64(&matchCount) >= int64(opts.limit) {
233
233
+
break
234
234
+
}
235
235
+
fmt.Println(match)
236
236
+
}
237
237
+
}
238
238
+
}
239
239
+
240
240
+
if progress != nil {
241
241
+
progress.SetWithBytes(processed, atomic.LoadInt64(&bytesProcessed))
242
242
+
}
243
243
+
244
244
+
// Early exit if limit reached
245
245
+
if opts.limit > 0 && atomic.LoadInt64(&matchCount) >= int64(opts.limit) {
246
246
+
break
247
247
+
}
248
248
+
}
249
249
+
250
250
+
if progress != nil {
251
251
+
progress.Finish()
252
252
+
}
253
253
+
254
254
+
// Output summary
255
255
+
finalMatchCount := atomic.LoadInt64(&matchCount)
256
256
+
finalTotalOps := atomic.LoadInt64(&totalOps)
257
257
+
finalBytes := atomic.LoadInt64(&bytesProcessed)
258
258
+
259
259
+
fmt.Fprintf(os.Stderr, "\n")
260
260
+
if opts.format == "count" {
261
261
+
fmt.Println(finalMatchCount)
262
262
+
}
263
263
+
264
264
+
fmt.Fprintf(os.Stderr, "✓ Query complete\n")
265
265
+
fmt.Fprintf(os.Stderr, " Total operations: %s\n", formatNumber(int(finalTotalOps)))
266
266
+
fmt.Fprintf(os.Stderr, " Matches: %s", formatNumber(int(finalMatchCount)))
267
267
+
if finalTotalOps > 0 {
268
268
+
fmt.Fprintf(os.Stderr, " (%.2f%%)", float64(finalMatchCount)/float64(finalTotalOps)*100)
269
269
+
}
270
270
+
fmt.Fprintf(os.Stderr, "\n")
271
271
+
if finalBytes > 0 {
272
272
+
fmt.Fprintf(os.Stderr, " Data processed: %s\n", formatBytes(finalBytes))
273
273
+
}
274
274
+
275
275
+
return nil
276
276
+
}
277
277
+
278
278
+
type queryResult struct {
279
279
+
bundleNum int
280
280
+
matches []string
281
281
+
opsProcessed int
282
282
+
bytesProcessed int64
283
283
+
err error
284
284
+
}
285
285
+
286
286
+
func processBundleQuery(
287
287
+
ctx context.Context,
288
288
+
mgr BundleManager,
289
289
+
bundleNum int,
290
290
+
compiled *jmespath.JMESPath,
291
291
+
checkLimit bool,
292
292
+
matchCount *int64,
293
293
+
limit int64,
294
294
+
) queryResult {
295
295
+
res := queryResult{bundleNum: bundleNum}
296
296
+
297
297
+
bundle, err := mgr.LoadBundle(ctx, bundleNum)
298
298
+
if err != nil {
299
299
+
res.err = err
300
300
+
return res
301
301
+
}
302
302
+
303
303
+
res.opsProcessed = len(bundle.Operations)
304
304
+
matches := make([]string, 0)
305
305
+
306
306
+
// Track bytes processed
307
307
+
for _, op := range bundle.Operations {
308
308
+
// Early exit if limit reached
309
309
+
if checkLimit && atomic.LoadInt64(matchCount) >= limit {
310
310
+
break
311
311
+
}
312
312
+
313
313
+
// Track bytes
314
314
+
opSize := int64(len(op.RawJSON))
315
315
+
if opSize == 0 {
316
316
+
data, _ := json.Marshal(op)
317
317
+
opSize = int64(len(data))
318
318
+
}
319
319
+
res.bytesProcessed += opSize
320
320
+
321
321
+
// Convert operation to map for JMESPath
322
322
+
var opData map[string]interface{}
323
323
+
if len(op.RawJSON) > 0 {
324
324
+
if err := json.Unmarshal(op.RawJSON, &opData); err != nil {
325
325
+
continue
326
326
+
}
327
327
+
} else {
328
328
+
data, _ := json.Marshal(op)
329
329
+
json.Unmarshal(data, &opData)
330
330
+
}
331
331
+
332
332
+
// Evaluate JMESPath expression
333
333
+
result, err := compiled.Search(opData)
334
334
+
if err != nil {
335
335
+
continue
336
336
+
}
337
337
+
338
338
+
// Skip null results
339
339
+
if result == nil {
340
340
+
continue
341
341
+
}
342
342
+
343
343
+
// Increment match counter
344
344
+
atomic.AddInt64(matchCount, 1)
345
345
+
346
346
+
// Convert result to JSON string
347
347
+
resultJSON, err := json.Marshal(result)
348
348
+
if err != nil {
349
349
+
continue
350
350
+
}
351
351
+
352
352
+
matches = append(matches, string(resultJSON))
353
353
+
}
354
354
+
355
355
+
res.matches = matches
356
356
+
return res
357
357
+
}
+1
cmd/plcbundle/main.go
···
60
60
cmd.AddCommand(commands.NewDiffCommand())
61
61
//cmd.AddCommand(commands.NewStatsCommand())
62
62
cmd.AddCommand(commands.NewInspectCommand())
63
63
+
cmd.AddCommand(commands.NewQueryCommand())
63
64
64
65
// Namespaced commands
65
66
cmd.AddCommand(commands.NewDIDCommand())
+41
-9
cmd/plcbundle/ui/progress.go
···
19
19
width int
20
20
lastPrint time.Time
21
21
showBytes bool
22
22
+
autoBytes bool // Auto-calculate bytes from items
23
23
+
bytesPerItem int64
22
24
}
23
25
24
24
-
// NewProgressBar creates a new progress bar
26
26
+
// NewProgressBar creates a simple progress bar
25
27
func NewProgressBar(total int) *ProgressBar {
26
28
return &ProgressBar{
27
29
total: total,
···
32
34
}
33
35
}
34
36
35
35
-
// NewProgressBarWithBytes creates a new progress bar that tracks bytes
37
37
+
// NewProgressBarWithBytes creates a progress bar that tracks bytes
36
38
func NewProgressBarWithBytes(total int, totalBytes int64) *ProgressBar {
37
39
return &ProgressBar{
38
40
total: total,
···
44
46
}
45
47
}
46
48
47
47
-
// Set sets the current progress
49
49
+
// NewProgressBarWithBytesAuto creates a progress bar that auto-estimates bytes
50
50
+
// avgBytesPerItem is the estimated bytes per item (e.g., avg bundle size)
51
51
+
func NewProgressBarWithBytesAuto(total int, avgBytesPerItem int64) *ProgressBar {
52
52
+
return &ProgressBar{
53
53
+
total: total,
54
54
+
totalBytes: int64(total) * avgBytesPerItem,
55
55
+
startTime: time.Now(),
56
56
+
width: 40,
57
57
+
lastPrint: time.Now(),
58
58
+
showBytes: true,
59
59
+
autoBytes: true,
60
60
+
bytesPerItem: avgBytesPerItem,
61
61
+
}
62
62
+
}
63
63
+
64
64
+
// Set sets the current progress (auto-estimates bytes if enabled)
48
65
func (pb *ProgressBar) Set(current int) {
49
66
pb.mu.Lock()
50
67
defer pb.mu.Unlock()
51
68
pb.current = current
69
69
+
70
70
+
// Auto-calculate bytes if enabled
71
71
+
if pb.autoBytes && pb.bytesPerItem > 0 {
72
72
+
pb.currentBytes = int64(current) * pb.bytesPerItem
73
73
+
}
74
74
+
52
75
pb.print()
53
76
}
54
77
55
55
-
// SetWithBytes sets progress with byte tracking
78
78
+
// SetWithBytes sets progress with exact byte tracking
56
79
func (pb *ProgressBar) SetWithBytes(current int, bytesProcessed int64) {
57
80
pb.mu.Lock()
58
81
defer pb.mu.Unlock()
···
62
85
pb.print()
63
86
}
64
87
88
88
+
// AddBytes increments current progress and adds bytes
89
89
+
func (pb *ProgressBar) AddBytes(increment int, bytes int64) {
90
90
+
pb.mu.Lock()
91
91
+
defer pb.mu.Unlock()
92
92
+
pb.current += increment
93
93
+
pb.currentBytes += bytes
94
94
+
pb.showBytes = true
95
95
+
pb.print()
96
96
+
}
97
97
+
65
98
// Finish completes the progress bar
66
99
func (pb *ProgressBar) Finish() {
67
100
pb.mu.Lock()
···
106
139
eta = time.Duration(float64(remaining)/speed) * time.Second
107
140
}
108
141
109
109
-
// FIX: Check if complete
110
142
isComplete := pb.current >= pb.total
111
143
112
144
if pb.showBytes && pb.currentBytes > 0 {
113
145
mbProcessed := float64(pb.currentBytes) / (1000 * 1000)
114
114
-
mbPerSec := mbProcessed / elapsed.Seconds()
146
146
+
mbPerSec := 0.0
147
147
+
if elapsed.Seconds() > 0 {
148
148
+
mbPerSec = mbProcessed / elapsed.Seconds()
149
149
+
}
115
150
116
151
if isComplete {
117
117
-
// Don't show ETA when done
118
152
fmt.Fprintf(os.Stderr, "\r [%s] %6.2f%% | %d/%d | %.1f/s | %.1f MB/s | Done ",
119
153
bar, percent, pb.current, pb.total, speed, mbPerSec)
120
154
} else {
···
123
157
}
124
158
} else {
125
159
if isComplete {
126
126
-
// Don't show ETA when done
127
160
fmt.Fprintf(os.Stderr, "\r [%s] %6.2f%% | %d/%d | %.1f/s | Done ",
128
161
bar, percent, pb.current, pb.total, speed)
129
162
} else {
···
134
167
}
135
168
136
169
func formatETA(d time.Duration) string {
137
137
-
// This should never be called with 0 now, but keep as fallback
138
170
if d == 0 {
139
171
return "0s"
140
172
}
+6
go.mod
···
13
13
14
14
require (
15
15
github.com/inconshreveable/mousetrap v1.1.0 // indirect
16
16
+
github.com/jmespath-community/go-jmespath v1.1.1 // indirect
17
17
+
github.com/jmespath/go-jmespath v0.4.0 // indirect
16
18
github.com/spf13/pflag v1.0.9 // indirect
19
19
+
github.com/tidwall/gjson v1.18.0 // indirect
20
20
+
github.com/tidwall/match v1.1.1 // indirect
21
21
+
github.com/tidwall/pretty v1.2.0 // indirect
22
22
+
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec // indirect
17
23
)
+17
go.sum
···
1
1
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
2
2
+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2
3
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
3
4
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
4
5
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
5
6
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
6
7
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
7
8
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
9
9
+
github.com/jmespath-community/go-jmespath v1.1.1 h1:bFikPhsi/FdmlZhVgSCd2jj1e7G/rw+zyQfyg5UF+L4=
10
10
+
github.com/jmespath-community/go-jmespath v1.1.1/go.mod h1:4gOyFJsR/Gk+05RgTKYrifT7tBPWD8Lubtb5jRrfy9I=
11
11
+
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
12
12
+
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
13
13
+
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
14
14
+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
8
15
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
9
16
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
10
17
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
11
18
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
12
19
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
20
20
+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
21
21
+
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
22
22
+
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
23
23
+
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
24
24
+
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
25
25
+
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
26
26
+
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
13
27
github.com/valyala/gozstd v1.23.2 h1:S3rRsskaDvBCM2XJzQFYIDAO6txxmvTc1arA/9Wgi9o=
14
28
github.com/valyala/gozstd v1.23.2/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
29
29
+
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0=
30
30
+
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
15
31
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
16
32
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
17
33
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
18
34
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
19
35
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
36
36
+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
20
37
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=