返回 DeepSeek-Reasonix
platform.go
根目录 / internal / remote / bootstrap / platform.go
1 package bootstrap
2
3 import (
4 "fmt"
5 "strings"
6 )
7
8 // ParseUname maps `uname -sm` output to Go GOOS/GOARCH. V1 supports Linux and
9 // macOS remotes; anything else (including Windows shells) is an error.
10 func ParseUname(out string) (goos, goarch string, err error) {
11 fields := strings.Fields(strings.TrimSpace(out))
12 if len(fields) < 2 {
13 return "", "", fmt.Errorf("bootstrap: cannot parse `uname -sm` output %q", out)
14 }
15 sys, machine := fields[0], fields[1]
16 switch strings.ToLower(sys) {
17 case "linux":
18 goos = "linux"
19 case "darwin":
20 goos = "darwin"
21 default:
22 return "", "", fmt.Errorf("bootstrap: unsupported remote OS %q (V1 supports Linux and macOS)", sys)
23 }
24 switch strings.ToLower(machine) {
25 case "x86_64", "amd64":
26 goarch = "amd64"
27 case "aarch64", "arm64":
28 goarch = "arm64"
29 case "armv7l", "armv6l", "arm":
30 goarch = "arm"
31 default:
32 return "", "", fmt.Errorf("bootstrap: unsupported remote architecture %q", machine)
33 }
34 return goos, goarch, nil
35 }
36
37 // ParseVersion extracts a semver-ish string from `reasonix --version` output
38 // like "reasonix v1.9.0" or "1.9.0".
39 func ParseVersion(out string) (string, error) {
40 for _, field := range strings.Fields(strings.TrimSpace(out)) {
41 v := strings.TrimPrefix(field, "v")
42 if looksLikeSemver(v) {
43 return v, nil
44 }
45 }
46 return "", fmt.Errorf("bootstrap: no version found in %q", out)
47 }
48
49 func looksLikeSemver(v string) bool {
50 parts := strings.SplitN(v, "-", 2)[0]
51 seg := strings.Split(parts, ".")
52 if len(seg) < 2 {
53 return false
54 }
55 for _, s := range seg {
56 if s == "" {
57 return false
58 }
59 for _, r := range s {
60 if r < '0' || r > '9' {
61 return false
62 }
63 }
64 }
65 return true
66 }
67
68 // CompareVersions returns -1, 0, or 1 comparing dotted numeric versions.
69 // Pre-release suffixes (after '-') are ignored for ordering. Non-numeric or
70 // missing segments compare as 0.
71 func CompareVersions(a, b string) int {
72 as := versionSegments(a)
73 bs := versionSegments(b)
74 for i := 0; i < len(as) || i < len(bs); i++ {
75 var av, bv int
76 if i < len(as) {
77 av = as[i]
78 }
79 if i < len(bs) {
80 bv = bs[i]
81 }
82 if av < bv {
83 return -1
84 }
85 if av > bv {
86 return 1
87 }
88 }
89 return 0
90 }
91
92 func versionSegments(v string) []int {
93 v = strings.TrimPrefix(strings.TrimSpace(v), "v")
94 v = strings.SplitN(v, "-", 2)[0]
95 parts := strings.Split(v, ".")
96 out := make([]int, 0, len(parts))
97 for _, p := range parts {
98 n := 0
99 for _, r := range p {
100 if r < '0' || r > '9' {
101 n = 0
102 break
103 }
104 n = n*10 + int(r-'0')
105 }
106 out = append(out, n)
107 }
108 return out
109 }
110
110 lines GO