From 6e84251445bbe931e5af76dd3508227ced41122b Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 15:54:06 +0100 Subject: [PATCH 1/6] tools-flavor-tests: Some renames and clean up --- arduino/cores/tools.go | 28 +++++++-------- arduino/cores/tools_test.go | 68 +++++++++++++++++++------------------ 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index d4618494dcf..de772684651 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -141,13 +141,13 @@ func (tr *ToolRelease) RuntimeProperties() *properties.Map { } var ( - regexpArmLinux = regexp.MustCompile("arm.*-linux-gnueabihf") - regexpArm64Linux = regexp.MustCompile("(aarch64|arm64)-linux-gnu") - regexpAmd64 = regexp.MustCompile("x86_64-.*linux-gnu") - regexpi386 = regexp.MustCompile("i[3456]86-.*linux-gnu") - regexpWindows = regexp.MustCompile("i[3456]86-.*(mingw32|cygwin)") - regexpMac64Bit = regexp.MustCompile("(i[3456]86|x86_64)-apple-darwin.*") - regexpmac32Bit = regexp.MustCompile("i[3456]86-apple-darwin.*") + regexpLinuxArm = regexp.MustCompile("arm.*-linux-gnueabihf") + regexpLinuxArm64 = regexp.MustCompile("(aarch64|arm64)-linux-gnu") + regexpLinux64 = regexp.MustCompile("x86_64-.*linux-gnu") + regexpLinux32 = regexp.MustCompile("i[3456]86-.*linux-gnu") + regexpWindows32 = regexp.MustCompile("i[3456]86-.*(mingw32|cygwin)") + regexpMac64Bit = regexp.MustCompile("x86_64-apple-darwin.*") + regexpMac32Bit = regexp.MustCompile("i[3456]86-apple-darwin.*") regexpArmBSD = regexp.MustCompile("arm.*-freebsd[0-9]*") ) @@ -162,19 +162,19 @@ func (f *Flavor) isCompatibleWith(osName, osArch string) bool { switch osName + "," + osArch { case "linux,arm", "linux,armbe": - return regexpArmLinux.MatchString(f.OS) + return regexpLinuxArm.MatchString(f.OS) case "linux,arm64": - return regexpArm64Linux.MatchString(f.OS) + return regexpLinuxArm64.MatchString(f.OS) case "linux,amd64": - return regexpAmd64.MatchString(f.OS) + return regexpLinux64.MatchString(f.OS) case "linux,386": - return regexpi386.MatchString(f.OS) + return regexpLinux32.MatchString(f.OS) case "windows,386", "windows,amd64": - return regexpWindows.MatchString(f.OS) + return regexpWindows32.MatchString(f.OS) case "darwin,amd64": - return regexpmac32Bit.MatchString(f.OS) || regexpMac64Bit.MatchString(f.OS) + return regexpMac32Bit.MatchString(f.OS) || regexpMac64Bit.MatchString(f.OS) case "darwin,386": - return regexpmac32Bit.MatchString(f.OS) + return regexpMac32Bit.MatchString(f.OS) case "freebsd,arm": return regexpArmBSD.MatchString(f.OS) case "freebsd,386", "freebsd,amd64": diff --git a/arduino/cores/tools_test.go b/arduino/cores/tools_test.go index 5d03b2ed36e..12192138bed 100644 --- a/arduino/cores/tools_test.go +++ b/arduino/cores/tools_test.go @@ -26,29 +26,29 @@ func TestFlavorCompatibility(t *testing.T) { Os string Arch string } - windowsi386 := &os{"windows", "386"} - windowsx8664 := &os{"windows", "amd64"} - linuxi386 := &os{"linux", "386"} - linuxamd64 := &os{"linux", "amd64"} - linuxarm := &os{"linux", "arm"} - linuxarmbe := &os{"linux", "armbe"} - linuxarm64 := &os{"linux", "arm64"} - darwini386 := &os{"darwin", "386"} - darwinamd64 := &os{"darwin", "amd64"} - freebsdi386 := &os{"freebsd", "386"} - freebsdamd64 := &os{"freebsd", "amd64"} + windows32 := &os{"windows", "386"} + windows64 := &os{"windows", "amd64"} + linux32 := &os{"linux", "386"} + linux64 := &os{"linux", "amd64"} + linuxArm := &os{"linux", "arm"} + linuxArmbe := &os{"linux", "armbe"} + linuxArm64 := &os{"linux", "arm64"} + darwin32 := &os{"darwin", "386"} + darwin64 := &os{"darwin", "amd64"} + freebsd32 := &os{"freebsd", "386"} + freebsd64 := &os{"freebsd", "amd64"} oses := []*os{ - windowsi386, - windowsx8664, - linuxi386, - linuxamd64, - linuxarm, - linuxarmbe, - linuxarm64, - darwini386, - darwinamd64, - freebsdi386, - freebsdamd64, + windows32, + windows64, + linux32, + linux64, + linuxArm, + linuxArmbe, + linuxArm64, + darwin32, + darwin64, + freebsd32, + freebsd64, } type test struct { @@ -56,9 +56,9 @@ func TestFlavorCompatibility(t *testing.T) { Positives []*os } tests := []*test{ - {&Flavor{OS: "i686-mingw32"}, []*os{windowsi386, windowsx8664}}, - {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwini386, darwinamd64}}, - {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwinamd64}}, + {&Flavor{OS: "i686-mingw32"}, []*os{windows32, windows64}}, + {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64}}, + {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64}}, // Raspberry PI, BBB or other ARM based host // PI: "arm-linux-gnueabihf" @@ -66,25 +66,27 @@ func TestFlavorCompatibility(t *testing.T) { // Ubuntu Mate on PI2: "arm-linux-gnueabihf" // Debian 7.9 on BBB: "arm-linux-gnueabihf" // Raspbian on PI Zero: "arm-linux-gnueabihf" - {&Flavor{OS: "arm-linux-gnueabihf"}, []*os{linuxarm, linuxarmbe}}, + {&Flavor{OS: "arm-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}}, // Arch-linux on PI2: "armv7l-unknown-linux-gnueabihf" - {&Flavor{OS: "armv7l-unknown-linux-gnueabihf"}, []*os{linuxarm, linuxarmbe}}, + {&Flavor{OS: "armv7l-unknown-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}}, - {&Flavor{OS: "i686-linux-gnu"}, []*os{linuxi386}}, - {&Flavor{OS: "i686-pc-linux-gnu"}, []*os{linuxi386}}, - {&Flavor{OS: "x86_64-linux-gnu"}, []*os{linuxamd64}}, - {&Flavor{OS: "x86_64-pc-linux-gnu"}, []*os{linuxamd64}}, - {&Flavor{OS: "aarch64-linux-gnu"}, []*os{linuxarm64}}, - {&Flavor{OS: "arm64-linux-gnu"}, []*os{linuxarm64}}, + {&Flavor{OS: "i686-linux-gnu"}, []*os{linux32}}, + {&Flavor{OS: "i686-pc-linux-gnu"}, []*os{linux32}}, + {&Flavor{OS: "x86_64-linux-gnu"}, []*os{linux64}}, + {&Flavor{OS: "x86_64-pc-linux-gnu"}, []*os{linux64}}, + {&Flavor{OS: "aarch64-linux-gnu"}, []*os{linuxArm64}}, + {&Flavor{OS: "arm64-linux-gnu"}, []*os{linuxArm64}}, } check := func(test *test, os *os) { + // if the os is in the "positive" set CompatibleWith must return true... for _, positiveOs := range test.Positives { if positiveOs == os { require.True(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) return } } + // ...otherwise false require.False(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) } From 38029a3b32d6999cebe680d7e775b3393af98e3c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 16:17:46 +0100 Subject: [PATCH 2/6] tools-flavors: Prioritize OS exatch-match over compatible-match --- arduino/cores/tools.go | 29 ++++++++++++++++++++--- arduino/cores/tools_test.go | 47 +++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index de772684651..62794dab6f5 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -151,11 +151,15 @@ var ( regexpArmBSD = regexp.MustCompile("arm.*-freebsd[0-9]*") ) +func (f *Flavor) isExactMatchWithCurrentMachine() bool { + return f.isExactMatchWith(runtime.GOOS, runtime.GOARCH) +} + func (f *Flavor) isCompatibleWithCurrentMachine() bool { return f.isCompatibleWith(runtime.GOOS, runtime.GOARCH) } -func (f *Flavor) isCompatibleWith(osName, osArch string) bool { +func (f *Flavor) isExactMatchWith(osName, osArch string) bool { if f.OS == "all" { return true } @@ -169,10 +173,10 @@ func (f *Flavor) isCompatibleWith(osName, osArch string) bool { return regexpLinux64.MatchString(f.OS) case "linux,386": return regexpLinux32.MatchString(f.OS) - case "windows,386", "windows,amd64": + case "windows,386": return regexpWindows32.MatchString(f.OS) case "darwin,amd64": - return regexpMac32Bit.MatchString(f.OS) || regexpMac64Bit.MatchString(f.OS) + return regexpMac64Bit.MatchString(f.OS) case "darwin,386": return regexpMac32Bit.MatchString(f.OS) case "freebsd,arm": @@ -184,8 +188,27 @@ func (f *Flavor) isCompatibleWith(osName, osArch string) bool { return false } +func (f *Flavor) isCompatibleWith(osName, osArch string) bool { + if f.isExactMatchWith(osName, osArch) { + return true + } + + switch osName + "," + osArch { + case "windows,amd64": + return regexpWindows32.MatchString(f.OS) + case "darwin,amd64": + return regexpMac32Bit.MatchString(f.OS) + } + return false +} + // GetCompatibleFlavour returns the downloadable resource compatible with the running O.S. func (tr *ToolRelease) GetCompatibleFlavour() *resources.DownloadResource { + for _, flavour := range tr.Flavors { + if flavour.isExactMatchWithCurrentMachine() { + return flavour.Resource + } + } for _, flavour := range tr.Flavors { if flavour.isCompatibleWithCurrentMachine() { return flavour.Resource diff --git a/arduino/cores/tools_test.go b/arduino/cores/tools_test.go index 12192138bed..f7452e39abf 100644 --- a/arduino/cores/tools_test.go +++ b/arduino/cores/tools_test.go @@ -52,13 +52,14 @@ func TestFlavorCompatibility(t *testing.T) { } type test struct { - Flavour *Flavor - Positives []*os + Flavour *Flavor + Compatibles []*os + ExactMatch []*os } tests := []*test{ - {&Flavor{OS: "i686-mingw32"}, []*os{windows32, windows64}}, - {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64}}, - {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64}}, + {&Flavor{OS: "i686-mingw32"}, []*os{windows32, windows64}, []*os{windows32}}, + {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64}, []*os{darwin32}}, + {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64}, []*os{darwin64}}, // Raspberry PI, BBB or other ARM based host // PI: "arm-linux-gnueabihf" @@ -66,21 +67,21 @@ func TestFlavorCompatibility(t *testing.T) { // Ubuntu Mate on PI2: "arm-linux-gnueabihf" // Debian 7.9 on BBB: "arm-linux-gnueabihf" // Raspbian on PI Zero: "arm-linux-gnueabihf" - {&Flavor{OS: "arm-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}}, + {&Flavor{OS: "arm-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}, []*os{linuxArm, linuxArmbe}}, // Arch-linux on PI2: "armv7l-unknown-linux-gnueabihf" - {&Flavor{OS: "armv7l-unknown-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}}, + {&Flavor{OS: "armv7l-unknown-linux-gnueabihf"}, []*os{linuxArm, linuxArmbe}, []*os{linuxArm, linuxArmbe}}, - {&Flavor{OS: "i686-linux-gnu"}, []*os{linux32}}, - {&Flavor{OS: "i686-pc-linux-gnu"}, []*os{linux32}}, - {&Flavor{OS: "x86_64-linux-gnu"}, []*os{linux64}}, - {&Flavor{OS: "x86_64-pc-linux-gnu"}, []*os{linux64}}, - {&Flavor{OS: "aarch64-linux-gnu"}, []*os{linuxArm64}}, - {&Flavor{OS: "arm64-linux-gnu"}, []*os{linuxArm64}}, + {&Flavor{OS: "i686-linux-gnu"}, []*os{linux32}, []*os{linux32}}, + {&Flavor{OS: "i686-pc-linux-gnu"}, []*os{linux32}, []*os{linux32}}, + {&Flavor{OS: "x86_64-linux-gnu"}, []*os{linux64}, []*os{linux64}}, + {&Flavor{OS: "x86_64-pc-linux-gnu"}, []*os{linux64}, []*os{linux64}}, + {&Flavor{OS: "aarch64-linux-gnu"}, []*os{linuxArm64}, []*os{linuxArm64}}, + {&Flavor{OS: "arm64-linux-gnu"}, []*os{linuxArm64}, []*os{linuxArm64}}, } - check := func(test *test, os *os) { - // if the os is in the "positive" set CompatibleWith must return true... - for _, positiveOs := range test.Positives { + checkCompatible := func(test *test, os *os) { + // if the os is in the "positive" set iCompatibleWith must return true... + for _, positiveOs := range test.Compatibles { if positiveOs == os { require.True(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) return @@ -89,10 +90,22 @@ func TestFlavorCompatibility(t *testing.T) { // ...otherwise false require.False(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) } + checkExactMatch := func(test *test, os *os) { + // if the os is in the "positive" set iCompatibleWith must return true... + for _, positiveOs := range test.ExactMatch { + if positiveOs == os { + require.True(t, test.Flavour.isExactMatchWith(os.Os, os.Arch), "'%s' tag exact match with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) + return + } + } + // ...otherwise false + require.False(t, test.Flavour.isExactMatchWith(os.Os, os.Arch), "'%s' tag exact match with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) + } for _, test := range tests { for _, os := range oses { - check(test, os) + checkCompatible(test, os) + checkExactMatch(test, os) } } } From 2173861762d418af625c9e12d94a043aaec3919e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 18:10:42 +0100 Subject: [PATCH 3/6] tools-flavors: unrolled freebsd regexps --- arduino/cores/tools.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index 62794dab6f5..81700bf17b0 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -148,7 +148,9 @@ var ( regexpWindows32 = regexp.MustCompile("i[3456]86-.*(mingw32|cygwin)") regexpMac64Bit = regexp.MustCompile("x86_64-apple-darwin.*") regexpMac32Bit = regexp.MustCompile("i[3456]86-apple-darwin.*") - regexpArmBSD = regexp.MustCompile("arm.*-freebsd[0-9]*") + regexpFreeBSDArm = regexp.MustCompile("arm.*-freebsd[0-9]*") + regexpFreeBSD32 = regexp.MustCompile("i?[3456]86-freebsd[0-9]*") + regexpFreeBSD64 = regexp.MustCompile("amd64-freebsd[0-9]*") ) func (f *Flavor) isExactMatchWithCurrentMachine() bool { @@ -180,10 +182,11 @@ func (f *Flavor) isExactMatchWith(osName, osArch string) bool { case "darwin,386": return regexpMac32Bit.MatchString(f.OS) case "freebsd,arm": - return regexpArmBSD.MatchString(f.OS) - case "freebsd,386", "freebsd,amd64": - genericFreeBSDexp := regexp.MustCompile(osArch + "%s-freebsd[0-9]*") - return genericFreeBSDexp.MatchString(f.OS) + return regexpFreeBSDArm.MatchString(f.OS) + case "freebsd,386": + return regexpFreeBSD32.MatchString(f.OS) + case "freebsd,amd64": + return regexpFreeBSD64.MatchString(f.OS) } return false } From ce54d24a439638ba0c62ff1b61137ac3a918e976 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 18:18:50 +0100 Subject: [PATCH 4/6] tools-flavors: Added Apple silicon support --- arduino/cores/tools.go | 17 ++++++++++++----- arduino/cores/tools_test.go | 7 +++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index 81700bf17b0..450c71c9684 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -146,8 +146,10 @@ var ( regexpLinux64 = regexp.MustCompile("x86_64-.*linux-gnu") regexpLinux32 = regexp.MustCompile("i[3456]86-.*linux-gnu") regexpWindows32 = regexp.MustCompile("i[3456]86-.*(mingw32|cygwin)") - regexpMac64Bit = regexp.MustCompile("x86_64-apple-darwin.*") - regexpMac32Bit = regexp.MustCompile("i[3456]86-apple-darwin.*") + regexpWindows64 = regexp.MustCompile("(amd64|x86_64)-.*(mingw32|cygwin)") + regexpMac64 = regexp.MustCompile("x86_64-apple-darwin.*") + regexpMac32 = regexp.MustCompile("i[3456]86-apple-darwin.*") + regexpMacArm64 = regexp.MustCompile("arm64-apple-darwin.*") regexpFreeBSDArm = regexp.MustCompile("arm.*-freebsd[0-9]*") regexpFreeBSD32 = regexp.MustCompile("i?[3456]86-freebsd[0-9]*") regexpFreeBSD64 = regexp.MustCompile("amd64-freebsd[0-9]*") @@ -177,10 +179,12 @@ func (f *Flavor) isExactMatchWith(osName, osArch string) bool { return regexpLinux32.MatchString(f.OS) case "windows,386": return regexpWindows32.MatchString(f.OS) + case "darwin,arm64": + return regexpMacArm64.MatchString(f.OS) case "darwin,amd64": - return regexpMac64Bit.MatchString(f.OS) + return regexpMac64.MatchString(f.OS) case "darwin,386": - return regexpMac32Bit.MatchString(f.OS) + return regexpMac32.MatchString(f.OS) case "freebsd,arm": return regexpFreeBSDArm.MatchString(f.OS) case "freebsd,386": @@ -200,7 +204,10 @@ func (f *Flavor) isCompatibleWith(osName, osArch string) bool { case "windows,amd64": return regexpWindows32.MatchString(f.OS) case "darwin,amd64": - return regexpMac32Bit.MatchString(f.OS) + return regexpMac32.MatchString(f.OS) + case "darwin,arm64": + // Compatibility guaranteed through Rosetta emulation + return regexpMac64.MatchString(f.OS) || regexpMac32.MatchString(f.OS) } return false } diff --git a/arduino/cores/tools_test.go b/arduino/cores/tools_test.go index f7452e39abf..7f1b93b393b 100644 --- a/arduino/cores/tools_test.go +++ b/arduino/cores/tools_test.go @@ -35,6 +35,7 @@ func TestFlavorCompatibility(t *testing.T) { linuxArm64 := &os{"linux", "arm64"} darwin32 := &os{"darwin", "386"} darwin64 := &os{"darwin", "amd64"} + darwinArm64 := &os{"darwin", "arm64"} freebsd32 := &os{"freebsd", "386"} freebsd64 := &os{"freebsd", "amd64"} oses := []*os{ @@ -47,6 +48,7 @@ func TestFlavorCompatibility(t *testing.T) { linuxArm64, darwin32, darwin64, + darwinArm64, freebsd32, freebsd64, } @@ -58,8 +60,9 @@ func TestFlavorCompatibility(t *testing.T) { } tests := []*test{ {&Flavor{OS: "i686-mingw32"}, []*os{windows32, windows64}, []*os{windows32}}, - {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64}, []*os{darwin32}}, - {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64}, []*os{darwin64}}, + {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64, darwinArm64}, []*os{darwin32}}, + {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64, darwinArm64}, []*os{darwin64}}, + {&Flavor{OS: "arm64-apple-darwin"}, []*os{darwinArm64}, []*os{darwinArm64}}, // Raspberry PI, BBB or other ARM based host // PI: "arm-linux-gnueabihf" From 76c717bfcf2769e16b81758b29ab502b440f0ca8 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 18:21:07 +0100 Subject: [PATCH 5/6] tools-flavors: Added support for Windows 64 bit --- arduino/cores/tools.go | 2 ++ arduino/cores/tools_test.go | 1 + 2 files changed, 3 insertions(+) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index 450c71c9684..f9da22a6a0e 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -179,6 +179,8 @@ func (f *Flavor) isExactMatchWith(osName, osArch string) bool { return regexpLinux32.MatchString(f.OS) case "windows,386": return regexpWindows32.MatchString(f.OS) + case "windows,amd64": + return regexpWindows64.MatchString(f.OS) case "darwin,arm64": return regexpMacArm64.MatchString(f.OS) case "darwin,amd64": diff --git a/arduino/cores/tools_test.go b/arduino/cores/tools_test.go index 7f1b93b393b..f42e8002b82 100644 --- a/arduino/cores/tools_test.go +++ b/arduino/cores/tools_test.go @@ -60,6 +60,7 @@ func TestFlavorCompatibility(t *testing.T) { } tests := []*test{ {&Flavor{OS: "i686-mingw32"}, []*os{windows32, windows64}, []*os{windows32}}, + {&Flavor{OS: "x86_64-mingw32"}, []*os{windows64}, []*os{windows64}}, {&Flavor{OS: "i386-apple-darwin11"}, []*os{darwin32, darwin64, darwinArm64}, []*os{darwin32}}, {&Flavor{OS: "x86_64-apple-darwin"}, []*os{darwin64, darwinArm64}, []*os{darwin64}}, {&Flavor{OS: "arm64-apple-darwin"}, []*os{darwinArm64}, []*os{darwinArm64}}, From 358a50a01a7a427f778ad512c14d96f800927d77 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 16 Nov 2020 18:47:39 +0100 Subject: [PATCH 6/6] tools-flavors: give priority to better matching OS --- arduino/cores/tools.go | 44 ++++++++++++------------ arduino/cores/tools_test.go | 68 ++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/arduino/cores/tools.go b/arduino/cores/tools.go index f9da22a6a0e..29bea5fe80d 100644 --- a/arduino/cores/tools.go +++ b/arduino/cores/tools.go @@ -155,14 +155,6 @@ var ( regexpFreeBSD64 = regexp.MustCompile("amd64-freebsd[0-9]*") ) -func (f *Flavor) isExactMatchWithCurrentMachine() bool { - return f.isExactMatchWith(runtime.GOOS, runtime.GOARCH) -} - -func (f *Flavor) isCompatibleWithCurrentMachine() bool { - return f.isCompatibleWith(runtime.GOOS, runtime.GOARCH) -} - func (f *Flavor) isExactMatchWith(osName, osArch string) bool { if f.OS == "all" { return true @@ -197,34 +189,42 @@ func (f *Flavor) isExactMatchWith(osName, osArch string) bool { return false } -func (f *Flavor) isCompatibleWith(osName, osArch string) bool { +func (f *Flavor) isCompatibleWith(osName, osArch string) (bool, int) { if f.isExactMatchWith(osName, osArch) { - return true + return true, 1000 } switch osName + "," + osArch { case "windows,amd64": - return regexpWindows32.MatchString(f.OS) + return regexpWindows32.MatchString(f.OS), 10 case "darwin,amd64": - return regexpMac32.MatchString(f.OS) + return regexpMac32.MatchString(f.OS), 10 case "darwin,arm64": // Compatibility guaranteed through Rosetta emulation - return regexpMac64.MatchString(f.OS) || regexpMac32.MatchString(f.OS) + if regexpMac64.MatchString(f.OS) { + // Prefer amd64 version if available + return true, 20 + } + return regexpMac32.MatchString(f.OS), 10 } - return false + + return false, 0 } // GetCompatibleFlavour returns the downloadable resource compatible with the running O.S. func (tr *ToolRelease) GetCompatibleFlavour() *resources.DownloadResource { + return tr.GetFlavourCompatibleWith(runtime.GOOS, runtime.GOARCH) +} + +// GetFlavourCompatibleWith returns the downloadable resource compatible with the specified O.S. +func (tr *ToolRelease) GetFlavourCompatibleWith(osName, osArch string) *resources.DownloadResource { + var resource *resources.DownloadResource + priority := -1 for _, flavour := range tr.Flavors { - if flavour.isExactMatchWithCurrentMachine() { - return flavour.Resource - } - } - for _, flavour := range tr.Flavors { - if flavour.isCompatibleWithCurrentMachine() { - return flavour.Resource + if comp, p := flavour.isCompatibleWith(osName, osArch); comp && p > priority { + resource = flavour.Resource + priority = p } } - return nil + return resource } diff --git a/arduino/cores/tools_test.go b/arduino/cores/tools_test.go index f42e8002b82..2597e1a9a66 100644 --- a/arduino/cores/tools_test.go +++ b/arduino/cores/tools_test.go @@ -18,6 +18,7 @@ package cores import ( "testing" + "github.com/arduino/arduino-cli/arduino/resources" "github.com/stretchr/testify/require" ) @@ -85,17 +86,18 @@ func TestFlavorCompatibility(t *testing.T) { checkCompatible := func(test *test, os *os) { // if the os is in the "positive" set iCompatibleWith must return true... - for _, positiveOs := range test.Compatibles { - if positiveOs == os { - require.True(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) + res, _ := test.Flavour.isCompatibleWith(os.Os, os.Arch) + for _, compatibleOs := range test.Compatibles { + if compatibleOs == os { + require.True(t, res, "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) return } } // ...otherwise false - require.False(t, test.Flavour.isCompatibleWith(os.Os, os.Arch), "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) + require.False(t, res, "'%s' tag compatible with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) } checkExactMatch := func(test *test, os *os) { - // if the os is in the "positive" set iCompatibleWith must return true... + // if the os is in the "positive" set iExactMatchWith must return true... for _, positiveOs := range test.ExactMatch { if positiveOs == os { require.True(t, test.Flavour.isExactMatchWith(os.Os, os.Arch), "'%s' tag exact match with '%s,%s' pair", test.Flavour.OS, os.Os, os.Arch) @@ -113,3 +115,59 @@ func TestFlavorCompatibility(t *testing.T) { } } } + +func TestFlavorPrioritySelection(t *testing.T) { + res := (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "i386-apple-darwin11", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + {OS: "x86_64-apple-darwin", Resource: &resources.DownloadResource{ArchiveFileName: "2"}}, + {OS: "arm64-apple-darwin", Resource: &resources.DownloadResource{ArchiveFileName: "3"}}, + }, + }).GetFlavourCompatibleWith("darwin", "arm64") + require.NotNil(t, res) + require.Equal(t, "3", res.ArchiveFileName) + + res = (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "i386-apple-darwin11", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + {OS: "x86_64-apple-darwin", Resource: &resources.DownloadResource{ArchiveFileName: "2"}}, + }, + }).GetFlavourCompatibleWith("darwin", "arm64") + require.NotNil(t, res) + require.Equal(t, "2", res.ArchiveFileName) + + res = (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "x86_64-apple-darwin", Resource: &resources.DownloadResource{ArchiveFileName: "2"}}, + {OS: "i386-apple-darwin11", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + }, + }).GetFlavourCompatibleWith("darwin", "arm64") + require.NotNil(t, res) + require.Equal(t, "2", res.ArchiveFileName) + + res = (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "i386-apple-darwin11", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + }, + }).GetFlavourCompatibleWith("darwin", "arm64") + require.NotNil(t, res) + require.Equal(t, "1", res.ArchiveFileName) + + res = (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "i686-mingw32", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + {OS: "x86_64-mingw32", Resource: &resources.DownloadResource{ArchiveFileName: "2"}}, + }, + }).GetFlavourCompatibleWith("windows", "amd64") + require.NotNil(t, res) + require.Equal(t, "2", res.ArchiveFileName) + + res = (&ToolRelease{ + Flavors: []*Flavor{ + {OS: "x86_64-mingw32", Resource: &resources.DownloadResource{ArchiveFileName: "2"}}, + {OS: "i686-mingw32", Resource: &resources.DownloadResource{ArchiveFileName: "1"}}, + }, + }).GetFlavourCompatibleWith("windows", "amd64") + require.NotNil(t, res) + require.Equal(t, "2", res.ArchiveFileName) +}