@@ -5,9 +5,12 @@ import (
55 "embed"
66 "fmt"
77 "io/fs"
8+ "net/http"
89 "os"
910 "os/exec"
1011 "path/filepath"
12+ "regexp"
13+ "runtime"
1114 "strings"
1215
1316 "github.com/andreimerlescu/figtree/v2"
@@ -24,23 +27,90 @@ type Application struct {
2427 ctx context.Context
2528 figs figtree.Plant
2629 userHomeDir string
30+ Workspace func () string
2731}
2832
33+ var UserHomeDir = os .UserHomeDir
34+
2935func NewApp () * Application {
30- userHomeDir , err := os . UserHomeDir ()
36+ userHomeDir , err := UserHomeDir ()
3137 capture (err )
32- return & Application {
38+ app := & Application {
3339 ctx : context .Background (),
3440 userHomeDir : userHomeDir ,
3541 }
42+ app .Workspace = func () string {
43+ if * app .figs .Bool (kSystem ) {
44+ return filepath .Join ("/" , "usr" , "go" )
45+ }
46+ return filepath .Join (app .userHomeDir , "go" )
47+ }
48+ app .figs = figtree .With (figtree.Options {
49+ ConfigFile : filepath .Join (app .userHomeDir , ".igo.config.yml" ),
50+ Germinate : true ,
51+ Harvest : 0 ,
52+ })
53+ app .figs .NewBool (kVersion , false , "Display current version" )
54+ app .figs .NewBool (kSystem , false , "Install for system-wide usage (ignore USER HOME directory)" )
55+ app .figs .NewBool (kDebug , false , "Enable debug mode" )
56+ app .figs .NewBool (kVerbose , false , "Enable verbose mode" )
57+ app .figs .NewString (kGoDir , filepath .Join (app .userHomeDir , "go" ), "Path where you want multiple go versions installed" )
58+ app .figs .NewString (kCommand , "" , "Command to run: install uninstall use list" )
59+ app .figs .NewString (kGoVersion , "1.24.3" , "Go Version" )
60+ app .figs .WithValidator (kGoVersion , func (value interface {}) error {
61+ v := figtree .NewFlesh (value ).ToString ()
62+ if err := app .validateVersion (v ); err != nil {
63+ return err
64+ }
65+ return nil
66+ })
67+ app .figs .NewString (kGoos , runtime .GOOS , "Go OS" )
68+ app .figs .NewString (kGoArch , runtime .GOARCH , "Go Architecture" )
69+ app .figs .NewBool (kExtras , true , "Install extra packages" )
70+ app .figs .NewMap (kExtraPackages , packages , "Extra packages to install" )
71+ _ , err = os .Lstat (figtree .ConfigFilePath )
72+ if os .IsNotExist (err ) || os .IsPermission (err ) {
73+ capture (app .figs .Parse ())
74+ } else {
75+ capture (app .figs .Load ())
76+ }
77+ return app
3678}
3779
38- // Workspace provides the path to where igo is installed
39- func (app * Application ) Workspace () string {
40- if * app .figs .Bool (kSystem ) {
41- return filepath .Join ("/" , "usr" , "go" )
80+ // Add this function to application.go to validate Go version formats
81+ func (app * Application ) validateVersion (version string ) error {
82+ // Basic format check with regex
83+ if ! regexp .MustCompile (`^\d+\.\d+\.\d+$` ).MatchString (version ) {
84+ return fmt .Errorf ("invalid go version format: %s (expected format: X.Y.Z)" , version )
85+ }
86+
87+ // Parse version parts to check they're valid numbers
88+ var major , minor , patch int
89+ _ , err := fmt .Sscanf (version , "%d.%d.%d" , & major , & minor , & patch )
90+ if err != nil {
91+ return fmt .Errorf ("error parsing version components: %w" , err )
92+ }
93+
94+ // Optional: Add constraints on minimum supported versions
95+ if major < 1 || (major == 1 && minor < 16 ) {
96+ return fmt .Errorf ("go version %s is not supported (minimum: 1.16.0)" , version )
97+ }
98+
99+ // Verify the version exists on Go's download server before proceeding
100+ // Using a HEAD request to check if the URL exists
101+ resp , err := httpHead (fmt .Sprintf ("https://go.dev/dl/go%s.%s-%s.tar.gz" ,
102+ version , * app .figs .String (kGoos ), * app .figs .String (kGoArch )))
103+ if err != nil {
104+ return fmt .Errorf ("error checking if version exists: %w" , err )
105+ }
106+ defer resp .Body .Close ()
107+
108+ if resp .StatusCode != http .StatusOK {
109+ return fmt .Errorf ("go version %s not found on download server (status: %d)" ,
110+ version , resp .StatusCode )
42111 }
43- return filepath .Join (app .userHomeDir , "go" )
112+
113+ return nil
44114}
45115
46116// CreateShims creates the shims for go and gofmt
0 commit comments