diff --git a/cmd/download.go b/cmd/download.go index 9e5575a..812bb9b 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -3,10 +3,12 @@ package cmd import ( "fmt" "log" + "slices" "strings" "time" "github.com/cavaliergopher/grab/v3" + "github.com/hashicorp/go-version" "github.com/schollz/progressbar/v3" "github.com/spf13/cobra" "github.com/timsutton/speedwagon/util" @@ -80,26 +82,60 @@ working directory, named '.(dmg|pkg)'.`, // 3. bool: whether auth is required func findMatchingRuntime(runtimeName string, data util.DVTDownloadablePlist) (string, string, bool) { - var runtimeFilename string - var runtimeUrl string - authRequired := false + var matchingRuntimes []util.PlatformDownloadable + var matchedRuntime util.PlatformDownloadable - foundMatchingRuntime := false for _, v := range data.Downloadables { if strings.HasPrefix(v.Name, runtimeName) { - foundMatchingRuntime = true - runtimeFilename = v.Name + ".dmg" - runtimeUrl = v.Source + + foundRuntime := util.PlatformDownloadable{ + Identifier: v.Identifier, + Source: v.Source, + Name: v.Name, + Platform: v.Platform, + } + + ver, _ := version.NewVersion(v.Version) + foundRuntime.Version = *ver + if v.Authentication != "" { - authRequired = true + foundRuntime.AuthRequired = true } + foundRuntime.DownloadFileName = v.Name + ".dmg" + matchingRuntimes = append(matchingRuntimes, foundRuntime) } - if foundMatchingRuntime { - break - } } - return runtimeFilename, runtimeUrl, authRequired + // TODO: If there's 'Simulator' somewhere in the provided name, just try and match an exact slice elem + // and bypass the + // if strings.Contains(runtimeName, "Simulator") { + + // } + + // If there are multiple matches, take the highest-versioned one + if len(matchingRuntimes) > 1 { + slices.SortFunc(matchingRuntimes, func(a, b util.PlatformDownloadable) int { + return a.Version.Compare(&b.Version) + }) + matchedRuntime = matchingRuntimes[len(matchingRuntimes)-1] + } + + idx := slices.IndexFunc(matchingRuntimes, + func(r util.PlatformDownloadable) bool { + // Every entry contains the words 'Simulator' or 'Simulator Runtime', and we + // only care about the words leading up to that + normalizedName := strings.Split(r.Name, " Simulator")[0] + return normalizedName == runtimeName + }) + if idx >= 0 { + matchedRuntime = matchingRuntimes[idx] + } + + fmt.Println(matchedRuntime) + + return matchedRuntime.DownloadFileName, + matchedRuntime.Source, + matchedRuntime.AuthRequired } func init() { diff --git a/go.mod b/go.mod index f403418..981c832 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/dustin/go-humanize v1.0.1 + github.com/hashicorp/go-version v1.6.0 github.com/jedib0t/go-pretty/v6 v6.4.9 github.com/schollz/progressbar/v3 v3.14.1 github.com/spf13/cobra v1.8.0 @@ -21,7 +22,7 @@ require ( require ( github.com/cavaliergopher/grab/v3 v3.0.1 github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index f6dcf84..dbdc226 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc= @@ -14,8 +16,8 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= diff --git a/util/dvt.go b/util/dvt.go index aa95144..dd21a19 100644 --- a/util/dvt.go +++ b/util/dvt.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" + "github.com/hashicorp/go-version" "howett.net/plist" ) @@ -62,6 +63,16 @@ type DVTDownloadablePlist struct { Version string `plist:"version"` } +type PlatformDownloadable struct { + Name string + Platform string + Identifier string + Version version.Version + Source string + DownloadFileName string + AuthRequired bool +} + func RefreshDVTMetadata() { file, err := os.Create(DVTCacheFilePath()) if err != nil {