Skip to content

Commit 0d924c3

Browse files
authored
Merge pull request #3 from HexmosTech/rijul/cli-enhancements
Enhance CLI commands with export support and Ollama startup handling
2 parents ab14a85 + 016e925 commit 0d924c3

File tree

8 files changed

+765
-33
lines changed

8 files changed

+765
-33
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
dprompts
1+
dprompts
2+
dprompts_exports

export.go

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"os"
8+
"path/filepath"
9+
"strconv"
10+
"strings"
11+
"time"
12+
13+
"github.com/jackc/pgx/v5/pgxpool"
14+
)
15+
16+
type ExportOptions struct {
17+
Format string
18+
OutDir string
19+
FromDate string
20+
FullExport bool
21+
DryRun bool
22+
Overwrite bool
23+
}
24+
25+
type ExportResult struct {
26+
JobID int64
27+
Response []byte
28+
GroupName *string
29+
CreatedAt time.Time
30+
}
31+
32+
func ExportResults(
33+
ctx context.Context,
34+
dbPool *pgxpool.Pool,
35+
opts ExportOptions,
36+
) (int, error) {
37+
if opts.FullExport && opts.FromDate != "" {
38+
return 0, fmt.Errorf("--full-export cannot be used with --from-date")
39+
}
40+
41+
start := time.Now()
42+
43+
// Ensure directory exists
44+
if err := os.MkdirAll(opts.OutDir, 0755); err != nil {
45+
return 0, err
46+
}
47+
48+
// Handle overwrite
49+
if opts.Overwrite {
50+
if err := clearDirectory(opts.OutDir); err != nil {
51+
return 0, err
52+
}
53+
}
54+
55+
// Scan existing exports (unless overwrite)
56+
existing := map[int64]struct{}{}
57+
if !opts.Overwrite {
58+
existing = scanExistingExports(opts.OutDir, opts.Format)
59+
}
60+
61+
var (
62+
query string
63+
args []any
64+
)
65+
66+
if opts.FullExport {
67+
fmt.Println("Mode: full-export (no date filter)")
68+
query = `
69+
SELECT
70+
r.job_id,
71+
r.response,
72+
r.created_at,
73+
g.group_name
74+
FROM dprompts_results r
75+
LEFT JOIN dprompt_groups g
76+
ON r.group_id = g.id
77+
ORDER BY r.created_at ASC
78+
`
79+
} else {
80+
var fromTime time.Time
81+
82+
if opts.FromDate != "" {
83+
fmt.Println("Mode: from-date", opts.FromDate)
84+
t, err := time.Parse("2006-01-02", opts.FromDate)
85+
if err != nil {
86+
return 0, fmt.Errorf("invalid --from-date format (expected YYYY-MM-DD)")
87+
}
88+
fromTime = t
89+
} else {
90+
fmt.Println("Mode: last-24-hours")
91+
fromTime = time.Now().Add(-24 * time.Hour)
92+
}
93+
94+
query = `
95+
SELECT
96+
r.job_id,
97+
r.response,
98+
r.created_at,
99+
g.group_name
100+
FROM dprompts_results r
101+
LEFT JOIN dprompt_groups g
102+
ON r.group_id = g.id
103+
WHERE r.created_at >= $1
104+
ORDER BY r.created_at ASC
105+
`
106+
args = []any{fromTime}
107+
}
108+
109+
// ---- count total matching rows ----
110+
countQuery := fmt.Sprintf("SELECT COUNT(*) FROM (%s) q", query)
111+
var totalMatched int
112+
if err := dbPool.QueryRow(ctx, countQuery, args...).Scan(&totalMatched); err != nil {
113+
return 0, err
114+
}
115+
116+
skipped := len(existing)
117+
toExport := totalMatched - skipped
118+
if toExport < 0 {
119+
toExport = 0
120+
}
121+
122+
fmt.Println("Matched jobs in DB:", totalMatched)
123+
fmt.Println("Already exported (skipped):", skipped)
124+
fmt.Println("Jobs to export:", toExport)
125+
fmt.Println()
126+
127+
rows, err := dbPool.Query(ctx, query, args...)
128+
if err != nil {
129+
return 0, err
130+
}
131+
defer rows.Close()
132+
133+
exported := 0
134+
135+
for rows.Next() {
136+
var r ExportResult
137+
if err := rows.Scan(
138+
&r.JobID,
139+
&r.Response,
140+
&r.CreatedAt,
141+
&r.GroupName,
142+
); err != nil {
143+
return exported, err
144+
}
145+
146+
if _, ok := existing[r.JobID]; ok {
147+
continue
148+
}
149+
150+
exported++
151+
152+
if exported == 1 || exported%50 == 0 || exported == toExport {
153+
fmt.Printf(
154+
"Exporting %d/%d (job_id=%d)\n",
155+
exported,
156+
toExport,
157+
r.JobID,
158+
)
159+
}
160+
161+
if !opts.DryRun {
162+
if err := writeExportFile(opts, r); err != nil {
163+
return exported, err
164+
}
165+
}
166+
}
167+
168+
duration := time.Since(start)
169+
170+
fmt.Println()
171+
fmt.Println("Export completed")
172+
fmt.Println("Exported:", exported)
173+
fmt.Println("Skipped:", skipped)
174+
fmt.Println("Duration:", duration.Round(time.Millisecond))
175+
176+
return exported, rows.Err()
177+
}
178+
179+
func writeExportFile(opts ExportOptions, r ExportResult) error {
180+
filename := fmt.Sprintf("%d.json", r.JobID)
181+
path := filepath.Join(opts.OutDir, filename)
182+
183+
var resultValue any
184+
185+
// Try JSON first
186+
var parsed any
187+
if err := json.Unmarshal(r.Response, &parsed); err == nil {
188+
resultValue = normalizeJSON(parsed)
189+
} else {
190+
// Not JSON → keep as text
191+
resultValue = string(r.Response)
192+
}
193+
194+
out := map[string]any{
195+
"job_id": r.JobID,
196+
"created_at": r.CreatedAt,
197+
"result": resultValue,
198+
"metadata": map[string]any{
199+
"group_name": r.GroupName,
200+
},
201+
}
202+
203+
data, err := json.MarshalIndent(out, "", " ")
204+
if err != nil {
205+
return err
206+
}
207+
208+
return os.WriteFile(path, data, 0644)
209+
}
210+
211+
func scanExistingExports(dir, format string) map[int64]struct{} {
212+
result := make(map[int64]struct{})
213+
214+
entries, err := os.ReadDir(dir)
215+
if err != nil {
216+
return result
217+
}
218+
219+
for _, e := range entries {
220+
if e.IsDir() {
221+
continue
222+
}
223+
224+
name := e.Name()
225+
if !strings.HasSuffix(name, "."+format) {
226+
continue
227+
}
228+
229+
base := strings.TrimSuffix(name, "."+format)
230+
jobID, err := strconv.ParseInt(base, 10, 64)
231+
if err == nil {
232+
result[jobID] = struct{}{}
233+
}
234+
}
235+
236+
return result
237+
}
238+
239+
func clearDirectory(dir string) error {
240+
entries, err := os.ReadDir(dir)
241+
if err != nil {
242+
return err
243+
}
244+
245+
for _, e := range entries {
246+
if err := os.RemoveAll(filepath.Join(dir, e.Name())); err != nil {
247+
return err
248+
}
249+
}
250+
return nil
251+
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@ require (
1111
)
1212

1313
require (
14+
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
1415
github.com/davecgh/go-spew v1.1.1 // indirect
16+
github.com/dustin/go-humanize v1.0.1 // indirect
1517
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1618
github.com/jackc/pgpassfile v1.0.0 // indirect
1719
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
1820
github.com/jackc/puddle/v2 v2.2.2 // indirect
21+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
1922
github.com/mattn/go-colorable v0.1.13 // indirect
2023
github.com/mattn/go-isatty v0.0.19 // indirect
24+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
2125
github.com/pmezard/go-difflib v1.0.0 // indirect
2226
github.com/riverqueue/river/riverdriver v0.26.0 // indirect
2327
github.com/riverqueue/river/rivershared v0.26.0 // indirect
@@ -33,6 +37,7 @@ require (
3337
golang.org/x/crypto v0.37.0 // indirect
3438
golang.org/x/sync v0.17.0 // indirect
3539
golang.org/x/sys v0.32.0 // indirect
40+
golang.org/x/term v0.31.0 // indirect
3641
golang.org/x/text v0.29.0 // indirect
3742
gopkg.in/yaml.v3 v3.0.1 // indirect
3843
)

go.sum

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
2+
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
13
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
24
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
5+
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
36
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
47
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
8+
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
59
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
610
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
711
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
13+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
814
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
15+
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
916
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
1017
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
1118
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0=
@@ -18,15 +25,21 @@ github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
1825
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
1926
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
2027
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
28+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
29+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
2130
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
2231
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
2332
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2433
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
34+
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
2535
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
2636
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
37+
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
2738
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
2839
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
2940
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
41+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
42+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
3043
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3144
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3245
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -54,6 +67,7 @@ github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
5467
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
5568
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
5669
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
70+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
5771
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
5872
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
5973
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
@@ -67,20 +81,47 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
6781
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
6882
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
6983
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
84+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
7085
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
7186
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
7287
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
88+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
89+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
7390
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
7491
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
92+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
93+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
94+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
95+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
96+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
97+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
7598
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
7699
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
100+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
101+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
102+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
103+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
104+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
105+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
77106
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
78107
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
79108
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
80109
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
81110
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
111+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
112+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
113+
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
114+
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
115+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
116+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
117+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
118+
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
82119
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
83120
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
121+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
122+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
123+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
124+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
84125
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
85126
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
86127
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

0 commit comments

Comments
 (0)