Skip to content

Commit 25319d6

Browse files
committed
♻️ Synced dbin 📦 <-- misc/cmd/goScrap: add metagen command ⌚
1 parent d552c70 commit 25319d6

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

misc/cmd/goScrap/goScrap.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ package main
22

33
import (
44
"context"
5+
"debug/buildinfo"
56
"encoding/json"
67
"fmt"
78
"os"
89
"path/filepath"
910
"strings"
1011
"sort"
12+
"time"
1113

14+
pkggodev "github.com/guseggert/pkggodev-client"
1215
"github.com/urfave/cli/v3"
1316
)
1417

@@ -25,6 +28,43 @@ type DetectionResult struct {
2528
Directories []*DirectoryInfo `json:"directories"`
2629
}
2730

31+
type DbinItem struct {
32+
Pkg string `json:"pkg,omitempty"`
33+
Name string `json:"pkg_name,omitempty"`
34+
PkgId string `json:"pkg_id,omitempty"`
35+
AppstreamId string `json:"app_id,omitempty"`
36+
Icon string `json:"icon,omitempty"`
37+
Description string `json:"description,omitempty"`
38+
LongDescription string `json:"description_long,omitempty"`
39+
Screenshots []string `json:"screenshots,omitempty"`
40+
Version string `json:"version,omitempty"`
41+
DownloadURL string `json:"download_url,omitempty"`
42+
Size string `json:"size,omitempty"`
43+
Bsum string `json:"bsum,omitempty"`
44+
Shasum string `json:"shasum,omitempty"`
45+
BuildDate string `json:"build_date,omitempty"`
46+
SrcURLs []string `json:"src_urls,omitempty"`
47+
WebURLs []string `json:"web_urls,omitempty"`
48+
BuildScript string `json:"build_script,omitempty"`
49+
BuildLog string `json:"build_log,omitempty"`
50+
Categories string `json:"categories,omitempty"`
51+
Snapshots []snapshot `json:"snapshots,omitempty"`
52+
Provides string `json:"provides,omitempty"`
53+
License []string `json:"license,omitempty"`
54+
Maintainers string `json:"maintainers,omitempty"`
55+
Notes []string `json:"notes,omitempty"`
56+
Appstream string `json:"appstream,omitempty"`
57+
Rank uint `json:"rank,omitempty"`
58+
WebManifest string `json:"web_manifest,omitempty"`
59+
}
60+
61+
type snapshot struct {
62+
Commit string `json:"commit,omitempty"`
63+
Version string `json:"version,omitempty"`
64+
}
65+
66+
type DbinMetadata map[string][]DbinItem
67+
2868
func main() {
2969
app := &cli.Command{
3070
Name: "goScrap",
@@ -79,6 +119,24 @@ func main() {
79119
},
80120
Action: installAction,
81121
},
122+
{
123+
Name: "metagen",
124+
Usage: "Generate metadata.json for Go binaries in the input directory",
125+
Flags: []cli.Flag{
126+
&cli.StringFlag{
127+
Name: "output",
128+
Aliases: []string{"o"},
129+
Usage: "Specify output file for metadata (default: metadata.json in input dir)",
130+
Value: "",
131+
},
132+
&cli.BoolFlag{
133+
Name: "verbose",
134+
Usage: "Enable verbose output to stderr",
135+
Value: false,
136+
},
137+
},
138+
Action: metagenAction,
139+
},
82140
},
83141
}
84142

@@ -88,6 +146,138 @@ func main() {
88146
}
89147
}
90148

149+
func metagenAction(ctx context.Context, c *cli.Command) error {
150+
verbose := c.Bool("verbose")
151+
output := c.String("output")
152+
inputDir := c.Args().First()
153+
if inputDir == "" {
154+
var err error
155+
inputDir, err = os.Getwd()
156+
if err != nil {
157+
return fmt.Errorf("failed to get current directory: %w", err)
158+
}
159+
}
160+
161+
absInputDir, err := filepath.Abs(inputDir)
162+
if err != nil {
163+
return fmt.Errorf("failed to get absolute path: %w", err)
164+
}
165+
166+
info, err := os.Stat(absInputDir)
167+
if err != nil {
168+
return fmt.Errorf("invalid input directory: %w", err)
169+
}
170+
if !info.IsDir() {
171+
return fmt.Errorf("%s is not a directory", absInputDir)
172+
}
173+
174+
if output == "" {
175+
output = "metadata.json"
176+
}
177+
178+
client := pkggodev.New()
179+
metadata := make(DbinMetadata)
180+
binaries := make([]DbinItem, 0)
181+
182+
err = filepath.Walk(absInputDir, func(path string, info os.FileInfo, err error) error {
183+
if err != nil {
184+
return err
185+
}
186+
if info.IsDir() {
187+
return nil
188+
}
189+
if filepath.Ext(path) != "" {
190+
return nil
191+
}
192+
193+
buildInfo, err := buildinfo.ReadFile(path)
194+
if err != nil {
195+
if verbose {
196+
fmt.Fprintf(os.Stderr, "Warning: could not read build info for %s: %v\n", path, err)
197+
}
198+
return nil
199+
}
200+
201+
if buildInfo.Path == "" || buildInfo.Main.Version == "" {
202+
if verbose {
203+
fmt.Fprintf(os.Stderr, "Warning: incomplete build info for %s\n", path)
204+
}
205+
return nil
206+
}
207+
208+
pkgInfo, err := client.DescribePackage(pkggodev.DescribePackageRequest{Package: buildInfo.Path})
209+
if err != nil {
210+
if verbose {
211+
fmt.Fprintf(os.Stderr, "Warning: could not fetch package info for %s: %v\n", buildInfo.Path, err)
212+
}
213+
return nil
214+
}
215+
216+
size := fmt.Sprintf("%d", info.Size())
217+
218+
buildDate := ""
219+
for _, setting := range buildInfo.Settings {
220+
if setting.Key == "vcs.time" {
221+
buildDate = setting.Value
222+
if parsedTime, err := time.Parse(time.RFC3339, buildDate); err == nil {
223+
buildDate = parsedTime.Format("2006-01-02")
224+
}
225+
break
226+
}
227+
}
228+
if buildDate == "" {
229+
if verbose {
230+
fmt.Fprintf(os.Stderr, "Warning: no build date found for %s, using file mod time\n", path)
231+
}
232+
buildDate = info.ModTime().Format("2006-01-02")
233+
}
234+
235+
item := DbinItem{
236+
Pkg: filepath.Base(path),
237+
Name: filepath.Base(path),
238+
PkgId: buildInfo.Path,
239+
Description: "",
240+
Version: buildInfo.Main.Version,
241+
Size: size,
242+
BuildDate: buildDate,
243+
SrcURLs: []string{pkgInfo.Repository},
244+
License: []string{pkgInfo.License},
245+
}
246+
247+
binaries = append(binaries, item)
248+
return nil
249+
})
250+
251+
if err != nil {
252+
return fmt.Errorf("error walking directory: %w", err)
253+
}
254+
255+
if len(binaries) == 0 {
256+
return fmt.Errorf("no valid Go binaries found in %s", absInputDir)
257+
}
258+
259+
sort.Slice(binaries, func(i, j int) bool {
260+
return binaries[i].PkgId < binaries[j].PkgId
261+
})
262+
263+
metadata["go"] = binaries
264+
265+
jsonData, err := json.MarshalIndent(metadata, "", " ")
266+
if err != nil {
267+
return fmt.Errorf("failed to marshal JSON: %w", err)
268+
}
269+
270+
if err := os.WriteFile(output, jsonData, 0644); err != nil {
271+
return fmt.Errorf("failed to write metadata to %s: %w", output, err)
272+
}
273+
274+
if verbose {
275+
fmt.Fprintf(os.Stderr, "Successfully generated metadata.json with %d binaries\n", len(binaries))
276+
}
277+
278+
return nil
279+
}
280+
91281
func detectAction(ctx context.Context, c *cli.Command) error {
92282
verbose := c.Bool("verbose")
93283
output := c.String("output")

0 commit comments

Comments
 (0)