返回 DeepSeek-Reasonix
main.go
1 // Command desktopinventory enumerates every desktop shell entry point the
2 // Electron migration must account for and assigns each one a migration class.
3 // It reads the desktop Go package, the frontend sources, the packaging script
4 // and the CI workflows, then writes docs/desktop-migration/{INVENTORY.md,
5 // inventory.json}. -check fails when migration entries drift or remain
6 // unclassified; navigation-only source line changes do not block qualification.
7 package main
8
9 import (
10 "bytes"
11 "flag"
12 "fmt"
13 "os"
14 "path/filepath"
15 "regexp"
16 )
17
18 func main() {
19 root := flag.String("root", ".", "repository root")
20 out := flag.String("out", "docs/desktop-migration", "output directory (relative to root)")
21 check := flag.Bool("check", false, "verify the checked-in inventory is current instead of writing it")
22 flag.Parse()
23
24 inv, err := build(*root)
25 if err != nil {
26 fmt.Fprintln(os.Stderr, "desktopinventory:", err)
27 os.Exit(2)
28 }
29 if unclassified := inv.unclassified(); len(unclassified) > 0 {
30 for _, u := range unclassified {
31 fmt.Fprintf(os.Stderr, "unclassified: %s\n", u)
32 }
33 os.Exit(2)
34 }
35 md, js, err := render(inv)
36 if err != nil {
37 fmt.Fprintln(os.Stderr, "desktopinventory:", err)
38 os.Exit(2)
39 }
40 dir := filepath.Join(*root, *out)
41 mdPath := filepath.Join(dir, "INVENTORY.md")
42 jsPath := filepath.Join(dir, "inventory.json")
43 if *check {
44 stale := false
45 for path, want := range map[string][]byte{mdPath: md, jsPath: js} {
46 have, err := os.ReadFile(path)
47 if err != nil || !sameInventory(have, want) {
48 fmt.Fprintf(os.Stderr, "stale: %s (run: go run ./tools/desktopinventory)\n", path)
49 stale = true
50 }
51 }
52 if stale {
53 os.Exit(1)
54 }
55 fmt.Printf("desktop inventory current: %d entries\n", inv.count())
56 return
57 }
58 if err := os.MkdirAll(dir, 0o755); err != nil {
59 fmt.Fprintln(os.Stderr, "desktopinventory:", err)
60 os.Exit(2)
61 }
62 for path, data := range map[string][]byte{mdPath: md, jsPath: js} {
63 if err := os.WriteFile(path, data, 0o644); err != nil {
64 fmt.Fprintln(os.Stderr, "desktopinventory:", err)
65 os.Exit(2)
66 }
67 }
68 fmt.Printf("wrote %s and %s (%d entries)\n", mdPath, jsPath, inv.count())
69 }
70
71 // Source line numbers are navigation hints, not migration contracts. Moving
72 // unrelated code must not fail qualification; paths, entries, classifications,
73 // ownership, signatures and all other generated content remain exact.
74 var sourceLineHint = regexp.MustCompile(`((?:desktop|scripts|\.github)/[^\s"` + "`" + `|<>]+\.(?:go|[cm]?[jt]sx?|sh|ya?ml)):[0-9]+\b`)
75
76 func sameInventory(have, want []byte) bool {
77 return bytes.Equal(sourceLineHint.ReplaceAll(have, []byte("${1}")), sourceLineHint.ReplaceAll(want, []byte("${1}")))
78 }
79
79 lines GO