From 4bb522d303c5d296d2365bd3116cb58769705471 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 3 Sep 2023 08:39:23 +1000 Subject: [PATCH] Add doctor. --- v3/cmd/wails3/main.go | 1 + v3/go.mod | 3 - v3/go.sum | 16 +- v3/internal/commands/doctor.go | 11 + v3/internal/commands/version.go | 6 +- v3/internal/doctor/doctor.go | 235 ++++++++++++++++++ v3/internal/doctor/doctor_darwin.go | 8 + v3/internal/doctor/doctor_linux.go | 8 + v3/internal/doctor/doctor_windows.go | 20 ++ v3/internal/version/version.go | 8 + v3/internal/{commands => version}/version.txt | 0 11 files changed, 299 insertions(+), 17 deletions(-) create mode 100644 v3/internal/commands/doctor.go create mode 100644 v3/internal/doctor/doctor.go create mode 100644 v3/internal/doctor/doctor_darwin.go create mode 100644 v3/internal/doctor/doctor_linux.go create mode 100644 v3/internal/doctor/doctor_windows.go create mode 100644 v3/internal/version/version.go rename v3/internal/{commands => version}/version.txt (100%) diff --git a/v3/cmd/wails3/main.go b/v3/cmd/wails3/main.go index 95038b616..590024993 100644 --- a/v3/cmd/wails3/main.go +++ b/v3/cmd/wails3/main.go @@ -27,6 +27,7 @@ func init() { func main() { app := clir.NewCli("wails", "The Wails CLI", "v3") app.NewSubCommandFunction("build", "Build the project", commands.Build) + app.NewSubCommandFunction("doctor", "System status report", commands.Doctor) app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) task := app.NewSubCommand("task", "Run and list tasks") var taskFlags commands.RunTaskOptions diff --git a/v3/go.mod b/v3/go.mod index ed2e80db1..fd25b3877 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -30,7 +30,6 @@ require ( github.com/tc-hib/winres v0.1.6 github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3 github.com/wailsapp/mimetype v1.4.1 - github.com/wailsapp/wails/v3/cmd/wails3/ui v0.0.0-20210706143420-7d21f8c997e2 golang.org/x/net v0.10.0 golang.org/x/sys v0.11.0 modernc.org/sqlite v1.21.0 @@ -100,5 +99,3 @@ require ( ) replace github.com/ebitengine/purego v0.4.0-alpha.4 => github.com/tmclane/purego v0.0.0-20230601213035-1f25e70d7b01 - -replace github.com/wailsapp/wails/v3/cmd/wails3/ui => D:\GolandProjects\wails\v3\cmd\wails3\ui diff --git a/v3/go.sum b/v3/go.sum index 296fd4c96..67cc0f040 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -299,16 +299,15 @@ github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= -github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw= -github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= @@ -335,8 +334,7 @@ github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= github.com/tmclane/purego v0.0.0-20230601213035-1f25e70d7b01 h1:oQwu3iNDywGp1Hry+PDvz+grwbCGpzY+ckSnWKCnX5Y= github.com/tmclane/purego v0.0.0-20230601213035-1f25e70d7b01/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= -github.com/wailsapp/go-webview2 v1.0.5 h1:VtPABYX2Zwpi0BxGy0vpZ9mTOGDHxCDLZa0gvgJWhhI= -github.com/wailsapp/go-webview2 v1.0.5/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= +github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3 h1:lN7ATT1NZrwKjn2F/VSRJxJeWQZvuypzRHeLwr2No4Q= github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= @@ -437,8 +435,7 @@ golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5o golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -516,8 +513,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -565,8 +562,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/v3/internal/commands/doctor.go b/v3/internal/commands/doctor.go new file mode 100644 index 000000000..08a3da2a2 --- /dev/null +++ b/v3/internal/commands/doctor.go @@ -0,0 +1,11 @@ +package commands + +import ( + "github.com/wailsapp/wails/v3/internal/doctor" +) + +type DoctorOptions struct{} + +func Doctor(_ *DoctorOptions) error { + return doctor.Run() +} diff --git a/v3/internal/commands/version.go b/v3/internal/commands/version.go index 0c6f56153..e4f9cb028 100644 --- a/v3/internal/commands/version.go +++ b/v3/internal/commands/version.go @@ -2,14 +2,12 @@ package commands import ( _ "embed" + "github.com/wailsapp/wails/v3/internal/version" ) -//go:embed version.txt -var VersionString string - type VersionOptions struct{} func Version(_ *VersionOptions) error { - println(VersionString) + println(version.VersionString) return nil } diff --git a/v3/internal/doctor/doctor.go b/v3/internal/doctor/doctor.go new file mode 100644 index 000000000..43f8e8cbc --- /dev/null +++ b/v3/internal/doctor/doctor.go @@ -0,0 +1,235 @@ +package doctor + +import ( + "fmt" + "github.com/go-git/go-git/v5" + "github.com/pterm/pterm" + "github.com/samber/lo" + "github.com/wailsapp/wails/v3/internal/operatingsystem" + "github.com/wailsapp/wails/v3/internal/version" + "path/filepath" + "runtime" + "runtime/debug" + "slices" +) + +func Run() (err error) { + + pterm.DefaultSection = *pterm.DefaultSection. + WithBottomPadding(0). + WithStyle(pterm.NewStyle(pterm.FgBlue, pterm.Bold)) + + pterm.Println() // Spacer + pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Println("Wails Doctor") + pterm.Println() // Spacer + + spinner, _ := pterm.DefaultSpinner.WithRemoveWhenDone().Start("Scanning system - Please wait (this may take a long time)...") + + defer func() { + if err != nil { + spinner.Fail() + } + }() + + /** Build **/ + + // BuildSettings contains the build settings for the application + var BuildSettings map[string]string + + // BuildInfo contains the build info for the application + var BuildInfo *debug.BuildInfo + + var ok bool + BuildInfo, ok = debug.ReadBuildInfo() + if !ok { + return fmt.Errorf("could not read build info from binary") + } + BuildSettings = lo.Associate(BuildInfo.Settings, func(setting debug.BuildSetting) (string, string) { + return setting.Key, setting.Value + }) + + /** Operating System **/ + + // Get system info + info, err := operatingsystem.Info() + if err != nil { + pterm.Error.Println("Failed to get system information") + return err + } + + /** Wails **/ + wailsPackage, _ := lo.Find(BuildInfo.Deps, func(dep *debug.Module) bool { + return dep.Path == "github.com/wailsapp/wails/v3" + }) + + wailsVersion := version.VersionString + if wailsPackage != nil && wailsPackage.Replace != nil { + wailsVersion = "(local) => " + filepath.ToSlash(wailsPackage.Replace.Path) + // Get the latest commit hash + repo, err := git.PlainOpen(filepath.Join(wailsPackage.Replace.Path, "..")) + if err == nil { + head, err := repo.Head() + if err == nil { + wailsVersion += " (" + head.Hash().String()[:8] + ")" + } + } + } + + platformExtras := getInfo() + + spinner.Success() + + /** Output **/ + + pterm.DefaultSection.Println("Build Environment") + + tableData := pterm.TableData{ + {"Wails CLI", wailsVersion}, + {"Go Version", runtime.Version()}, + } + + if buildInfo, _ := debug.ReadBuildInfo(); buildInfo != nil { + buildSettingToName := map[string]string{ + "vcs.revision": "Revision", + "vcs.modified": "Modified", + } + for _, buildSetting := range buildInfo.Settings { + name := buildSettingToName[buildSetting.Key] + if name == "" { + continue + } + tableData = append(tableData, []string{name, buildSetting.Value}) + } + } + + mapKeys := lo.Keys(BuildSettings) + slices.Sort(mapKeys) + for _, key := range mapKeys { + tableData = append(tableData, []string{key, BuildSettings[key]}) + } + + //// Exit early if PM not found + //if info.PM != nil { + // wailsTableData = append(wailsTableData, []string{"Package Manager", info.PM.Name()}) + //} + + err = pterm.DefaultTable.WithData(tableData).Render() + if err != nil { + return err + } + + pterm.DefaultSection.Println("Operating System") + + systemTabledata := pterm.TableData{ + {pterm.Sprint("Name"), info.Name}, + {pterm.Sprint("Version"), info.Version}, + {pterm.Sprint("ID"), info.ID}, + {pterm.Sprint("Branding"), info.Branding}, + + {pterm.Sprint("Platform"), runtime.GOOS}, + {pterm.Sprint("Architecture"), runtime.GOARCH}, + } + + mapKeys = lo.Keys(platformExtras) + slices.Sort(mapKeys) + for _, key := range mapKeys { + systemTabledata = append(systemTabledata, []string{key, platformExtras[key]}) + } + + err = pterm.DefaultTable.WithData(systemTabledata).Render() + if err != nil { + return err + } + /* + pterm.DefaultSection.Println("Dependencies") + + // Output Dependencies Status + var dependenciesMissing []string + var externalPackages []*packagemanager.Dependency + var dependenciesAvailableRequired = 0 + var dependenciesAvailableOptional = 0 + + dependenciesTableData := pterm.TableData{ + {"Dependency", "Package Name", "Status", "Version"}, + } + + hasOptionalDependencies := false + // Loop over dependencies + for _, dependency := range info.Dependencies { + name := dependency.Name + + if dependency.Optional { + name = pterm.Gray("*") + name + hasOptionalDependencies = true + } + + packageName := "Unknown" + status := pterm.LightRed("Not Found") + + // If we found the package + if dependency.PackageName != "" { + packageName = dependency.PackageName + + // If it's installed, update the status + if dependency.Installed { + status = pterm.LightGreen("Installed") + } else { + // Generate meaningful status text + status = pterm.LightMagenta("Available") + + if dependency.Optional { + dependenciesAvailableOptional++ + } else { + dependenciesAvailableRequired++ + } + } + } else { + if !dependency.Optional { + dependenciesMissing = append(dependenciesMissing, dependency.Name) + } + + if dependency.External { + externalPackages = append(externalPackages, dependency) + } + } + + dependenciesTableData = append(dependenciesTableData, []string{name, packageName, status, dependency.Version}) + } + + dependenciesTableString, _ := pterm.DefaultTable.WithHasHeader(true).WithData(dependenciesTableData).Srender() + dependenciesBox := pterm.DefaultBox.WithTitleBottomCenter() + + if hasOptionalDependencies { + dependenciesBox = dependenciesBox.WithTitle(pterm.Gray("*") + " - Optional Dependency") + } + + dependenciesBox.Println(dependenciesTableString) + + pterm.DefaultSection.Println("Diagnosis") + + // Generate an appropriate diagnosis + + if dependenciesAvailableRequired != 0 { + pterm.Println("Required package(s) installation details: \n" + info.Dependencies.InstallAllRequiredCommand()) + } + + if dependenciesAvailableOptional != 0 { + pterm.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand()) + } + + if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 { + pterm.Success.Println("Your system is ready for Wails development!") + } else { + pterm.Warning.Println("Your system has missing dependencies!") + } + + if len(dependenciesMissing) != 0 { + pterm.Println("Fatal:") + pterm.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " ")) + pterm.Println("Please read this article on how to resolve this: https://wails.io/guides/resolving-missing-packages") + } + + pterm.Println() // Spacer for sponsor message + */ + return nil +} diff --git a/v3/internal/doctor/doctor_darwin.go b/v3/internal/doctor/doctor_darwin.go new file mode 100644 index 000000000..bf2634916 --- /dev/null +++ b/v3/internal/doctor/doctor_darwin.go @@ -0,0 +1,8 @@ +//go:build darwin + +package doctor + +func getInfo() map[string]string { + result := make(map[string]string) + return result +} diff --git a/v3/internal/doctor/doctor_linux.go b/v3/internal/doctor/doctor_linux.go new file mode 100644 index 000000000..54655a763 --- /dev/null +++ b/v3/internal/doctor/doctor_linux.go @@ -0,0 +1,8 @@ +//go:build linux + +package doctor + +func getInfo() map[string]string { + result := make(map[string]string) + return result +} diff --git a/v3/internal/doctor/doctor_windows.go b/v3/internal/doctor/doctor_windows.go new file mode 100644 index 000000000..905932011 --- /dev/null +++ b/v3/internal/doctor/doctor_windows.go @@ -0,0 +1,20 @@ +//go:build windows + +package doctor + +import ( + "github.com/samber/lo" + "github.com/wailsapp/go-webview2/webviewloader" +) + +func getInfo() map[string]string { + result := make(map[string]string) + result["Go WebView2Loader"] = lo.Ternary(webviewloader.UsingGoWebview2Loader, "true", "false") + webviewVersion, err := webviewloader.GetAvailableCoreWebView2BrowserVersionString("") + if err != nil { + webviewVersion = "Error:" + err.Error() + } + result["WebView2 Version"] = webviewVersion + + return result +} diff --git a/v3/internal/version/version.go b/v3/internal/version/version.go new file mode 100644 index 000000000..d8b4b0c2b --- /dev/null +++ b/v3/internal/version/version.go @@ -0,0 +1,8 @@ +package version + +import ( + _ "embed" +) + +//go:embed version.txt +var VersionString string diff --git a/v3/internal/commands/version.txt b/v3/internal/version/version.txt similarity index 100% rename from v3/internal/commands/version.txt rename to v3/internal/version/version.txt