@@ -63,6 +63,13 @@ func (pm *Builder) LoadHardwareFromDirectory(path *paths.Path) []error {
6363 return append (merr , errors .New (i18n .Tr ("%s is not a directory" , path )))
6464 }
6565
66+ // If the hardware directory is inside, or equals, the sketchbook/hardware directory
67+ // it's not a managed package, otherwise it is.
68+ managed := true
69+ if userInstalled , err := path .IsInsideDir (pm .userPackagesDir .Parent ()); err == nil && userInstalled {
70+ managed = false
71+ }
72+
6673 // Scan subdirs
6774 packagersPaths , err := path .ReadDir ()
6875 if err != nil {
@@ -85,43 +92,39 @@ func (pm *Builder) LoadHardwareFromDirectory(path *paths.Path) []error {
8592
8693 for _ , packagerPath := range packagersPaths {
8794 packager := packagerPath .Base ()
88-
8995 // Skip tools, they're not packages and don't contain Platforms
9096 if packager == "tools" {
9197 pm .log .Infof ("Excluding directory: %s" , packagerPath )
9298 continue
9399 }
100+ targetPackage := pm .packages .GetOrCreatePackage (packager )
94101
95102 // Follow symlinks
96- err := packagerPath . FollowSymLink () // ex : .arduino15/packages/arduino/
97- if err != nil {
103+ // (for example : .arduino15/packages/arduino/ could point to a dev directory)
104+ if err := packagerPath . FollowSymLink (); err != nil {
98105 merr = append (merr , fmt .Errorf ("%s: %w" , i18n .Tr ("following symlink %s" , path ), err ))
99106 continue
100107 }
101108
102109 // There are two possible package directory structures:
103- // - PACKAGER/ARCHITECTURE-1/boards.txt... (ex: arduino/avr/...)
104- // PACKAGER/ARCHITECTURE-2/boards.txt... (ex: arduino/sam/...)
105- // PACKAGER/ARCHITECTURE-3/boards.txt... (ex: arduino/samd/...)
106- // or
107- // - PACKAGER/hardware/ARCHITECTURE-1/VERSION/boards.txt... (ex: arduino/hardware/avr/1.6.15/...)
108- // PACKAGER/hardware/ARCHITECTURE-2/VERSION/boards.txt... (ex: arduino/hardware/sam/1.6.6/...)
109- // PACKAGER/hardware/ARCHITECTURE-3/VERSION/boards.txt... (ex: arduino/hardware/samd/1.6.12/...)
110- // PACKAGER/tools/... (ex: arduino/tools/...)
111- // in the latter case we just move into "hardware" directory and continue
112- var architectureParentPath * paths.Path
113- hardwareSubdirPath := packagerPath .Join ("hardware" ) // ex: .arduino15/packages/arduino/hardware
114- if hardwareSubdirPath .IsDir () {
115- // we found the "hardware" directory move down into that
116- architectureParentPath = hardwareSubdirPath // ex: .arduino15/packages/arduino/
110+ if managed {
111+ // 1. Inside the Boards Manager .arduino15/packages directory:
112+ // PACKAGER/hardware/ARCHITECTURE-1/VERSION/boards.txt... (ex: arduino/hardware/avr/1.6.15/...)
113+ // PACKAGER/hardware/ARCHITECTURE-2/VERSION/boards.txt... (ex: arduino/hardware/sam/1.6.6/...)
114+ // PACKAGER/hardware/ARCHITECTURE-3/VERSION/boards.txt... (ex: arduino/hardware/samd/1.6.12/...)
115+ // PACKAGER/tools/... (ex: arduino/tools/...)
116+ if p := packagerPath .Join ("hardware" ); p .IsDir () {
117+ merr = append (merr , pm .loadPlatforms (targetPackage , p , managed )... )
118+ }
117119 } else {
118- // we are already at the correct level
119- architectureParentPath = packagerPath
120+ // 2. Inside the sketchbook/hardware directory:
121+ // PACKAGER/ARCHITECTURE-1/boards.txt... (ex: arduino/avr/...)
122+ // PACKAGER/ARCHITECTURE-2/boards.txt... (ex: arduino/sam/...)
123+ // PACKAGER/ARCHITECTURE-3/boards.txt... (ex: arduino/samd/...)
124+ // ex: .arduino15/packages/arduino/hardware/...
125+ merr = append (merr , pm .loadPlatforms (targetPackage , packagerPath , managed )... )
120126 }
121127
122- targetPackage := pm .packages .GetOrCreatePackage (packager )
123- merr = append (merr , pm .loadPlatforms (targetPackage , architectureParentPath )... )
124-
125128 // Check if we have tools to load, the directory structure is as follows:
126129 // - PACKAGER/tools/TOOL-NAME/TOOL-VERSION/... (ex: arduino/tools/bossac/1.7.0/...)
127130 toolsSubdirPath := packagerPath .Join ("tools" )
@@ -141,8 +144,8 @@ func (pm *Builder) LoadHardwareFromDirectory(path *paths.Path) []error {
141144// loadPlatforms load plaftorms from the specified directory assuming that they belongs
142145// to the targetPackage object passed as parameter.
143146// A list of gRPC Status error is returned for each Platform failed to load.
144- func (pm * Builder ) loadPlatforms (targetPackage * cores.Package , packageDir * paths.Path ) []error {
145- pm .log .Infof ("Loading package %s from: %s" , targetPackage .Name , packageDir )
147+ func (pm * Builder ) loadPlatforms (targetPackage * cores.Package , packageDir * paths.Path , managed bool ) []error {
148+ pm .log .Infof ("Loading package %s from: %s (managed=%v) " , targetPackage .Name , packageDir , managed )
146149
147150 var merr []error
148151
@@ -162,7 +165,7 @@ func (pm *Builder) loadPlatforms(targetPackage *cores.Package, packageDir *paths
162165 if targetArchitecture == "tools" {
163166 continue
164167 }
165- if err := pm .loadPlatform (targetPackage , targetArchitecture , platformPath ); err != nil {
168+ if err := pm .loadPlatform (targetPackage , targetArchitecture , platformPath , managed ); err != nil {
166169 merr = append (merr , err )
167170 }
168171 }
@@ -173,46 +176,18 @@ func (pm *Builder) loadPlatforms(targetPackage *cores.Package, packageDir *paths
173176// loadPlatform loads a single platform and all its installed releases given a platformPath.
174177// platformPath must be a directory.
175178// Returns a gRPC Status error in case of failures.
176- func (pm * Builder ) loadPlatform (targetPackage * cores.Package , architecture string , platformPath * paths.Path ) error {
179+ func (pm * Builder ) loadPlatform (targetPackage * cores.Package , architecture string , platformPath * paths.Path , managed bool ) error {
177180 // This is not a platform
178181 if platformPath .IsNotDir () {
179182 return errors .New (i18n .Tr ("path is not a platform directory: %s" , platformPath ))
180183 }
181184
182185 // There are two possible platform directory structures:
183- // - ARCHITECTURE/boards.txt
184- // - ARCHITECTURE/VERSION/boards.txt
185- // We identify them by checking where is the bords.txt file
186- possibleBoardTxtPath := platformPath .Join ("boards.txt" )
187- if exist , err := possibleBoardTxtPath .ExistCheck (); err != nil {
188- return fmt .Errorf ("%s: %w" , i18n .Tr ("looking for boards.txt in %s" , possibleBoardTxtPath ), err )
189- } else if exist {
190- // case: ARCHITECTURE/boards.txt
186+ if managed {
187+ // 1. Inside the Boards Manager .arduino15/packages/PACKAGER/hardware/ARCHITECTURE directory:
188+ // - ARCHITECTURE/VERSION/boards.txt
191189
192- platformTxtPath := platformPath .Join ("platform.txt" )
193- platformProperties , err := properties .SafeLoad (platformTxtPath .String ())
194- if err != nil {
195- return fmt .Errorf ("%s: %w" , i18n .Tr ("loading platform.txt" ), err )
196- }
197-
198- versionString := platformProperties .ExpandPropsInString (platformProperties .Get ("version" ))
199- version , err := semver .Parse (versionString )
200- if err != nil {
201- return & cmderrors.InvalidVersionError {Cause : fmt .Errorf ("%s: %s" , platformTxtPath , err )}
202- }
203-
204- platform := targetPackage .GetOrCreatePlatform (architecture )
205- platform .ManuallyInstalled = true
206- release := platform .GetOrCreateRelease (version )
207- if err := pm .loadPlatformRelease (release , platformPath ); err != nil {
208- return fmt .Errorf ("%s: %w" , i18n .Tr ("loading platform release %s" , release ), err )
209- }
210- pm .log .WithField ("platform" , release ).Infof ("Loaded platform" )
211-
212- } else {
213- // case: ARCHITECTURE/VERSION/boards.txt
214190 // let's dive into VERSION directories
215-
216191 versionDirs , err := platformPath .ReadDir ()
217192 if err != nil {
218193 return fmt .Errorf ("%s: %w" , i18n .Tr ("reading directory %s" , platformPath ), err )
@@ -237,6 +212,29 @@ func (pm *Builder) loadPlatform(targetPackage *cores.Package, architecture strin
237212 }
238213 pm .log .WithField ("platform" , release ).Infof ("Loaded platform" )
239214 }
215+ } else {
216+ // 2. Inside the sketchbook/hardware/PACKAGER/ARCHITECTURE directory:
217+ // - ARCHITECTURE/boards.txt
218+
219+ // Determine platform version from the platform.txt metadata
220+ platformTxtPath := platformPath .Join ("platform.txt" )
221+ platformProperties , err := properties .SafeLoad (platformTxtPath .String ())
222+ if err != nil {
223+ return fmt .Errorf ("%s: %w" , i18n .Tr ("loading platform.txt" ), err )
224+ }
225+
226+ versionString := platformProperties .ExpandPropsInString (platformProperties .Get ("version" ))
227+ version , err := semver .Parse (versionString )
228+ if err != nil {
229+ return & cmderrors.InvalidVersionError {Cause : fmt .Errorf ("%s: %s" , platformTxtPath , err )}
230+ }
231+
232+ platform := targetPackage .GetOrCreatePlatform (architecture )
233+ release := platform .GetOrCreateRelease (version )
234+ if err := pm .loadPlatformRelease (release , platformPath ); err != nil {
235+ return fmt .Errorf ("%s: %w" , i18n .Tr ("loading platform release %s" , release ), err )
236+ }
237+ pm .log .WithField ("platform" , release ).Infof ("Loaded platform" )
240238 }
241239
242240 return nil
0 commit comments