Skip to content

Commit a77f39c

Browse files
committed
Added support for git-libraries in profiles
1 parent b1f3a84 commit a77f39c

File tree

4 files changed

+112
-10
lines changed

4 files changed

+112
-10
lines changed

commands/instances.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,39 @@ func (s *arduinoCoreServerImpl) Init(req *rpc.InitRequest, stream rpc.ArduinoCor
388388
continue
389389
}
390390

391+
if libraryRef.GitURL != nil {
392+
uid := libraryRef.InternalUniqueIdentifier()
393+
libRoot := s.settings.ProfilesCacheDir().Join(uid)
394+
libDir := libRoot.Join(libraryRef.Library)
395+
396+
if !libDir.IsDir() {
397+
// Clone repo and install
398+
tmpDir, err := librariesmanager.CloneLibraryGitRepository(ctx, libraryRef.GitURL.String())
399+
if err != nil {
400+
taskCallback(&rpc.TaskProgress{Name: i18n.Tr("Error downloading library %s", libraryRef)})
401+
e := &cmderrors.FailedLibraryInstallError{Cause: err}
402+
responseError(e.GRPCStatus())
403+
continue
404+
}
405+
defer tmpDir.RemoveAll()
406+
407+
// Install library into profile cache
408+
if err := tmpDir.CopyDirTo(libDir); err != nil {
409+
taskCallback(&rpc.TaskProgress{Name: i18n.Tr("Error installing library %s", libraryRef)})
410+
e := &cmderrors.FailedLibraryInstallError{Cause: fmt.Errorf("copying library to profile cache: %w", err)}
411+
responseError(e.GRPCStatus())
412+
continue
413+
}
414+
}
415+
416+
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
417+
Path: libDir,
418+
Location: libraries.Profile,
419+
IsSingleLibrary: true,
420+
})
421+
continue
422+
}
423+
391424
uid := libraryRef.InternalUniqueIdentifier()
392425
libRoot := s.settings.ProfilesCacheDir().Join(uid)
393426
libDir := libRoot.Join(libraryRef.Library)

internal/arduino/sketch/profiles.go

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"net/url"
24+
"path/filepath"
2425
"regexp"
2526
"strings"
2627

@@ -325,23 +326,39 @@ func (p *ProfilePlatformReference) UnmarshalYAML(unmarshal func(interface{}) err
325326
// ProfileLibraryReference is a reference to a library
326327
type ProfileLibraryReference struct {
327328
Library string
328-
InstallDir *paths.Path
329329
Version *semver.Version
330+
InstallDir *paths.Path
331+
GitURL *url.URL
330332
}
331333

332334
// UnmarshalYAML decodes a ProfileLibraryReference from YAML source.
333335
func (l *ProfileLibraryReference) UnmarshalYAML(unmarshal func(interface{}) error) error {
334336
var dataMap map[string]any
335337
if err := unmarshal(&dataMap); err == nil {
336-
if installDir, ok := dataMap["dir"]; !ok {
337-
return errors.New(i18n.Tr("invalid library reference: %s", dataMap))
338-
} else if installDir, ok := installDir.(string); !ok {
339-
return fmt.Errorf("%s: %s", i18n.Tr("invalid library reference: %s"), dataMap)
340-
} else {
341-
l.InstallDir = paths.New(installDir)
342-
l.Library = l.InstallDir.Base()
343-
return nil
338+
if installDir, ok := dataMap["dir"]; ok {
339+
if installDir, ok := installDir.(string); !ok {
340+
return fmt.Errorf("%s: %s", i18n.Tr("invalid library reference: %s"), dataMap)
341+
} else {
342+
l.InstallDir = paths.New(installDir)
343+
l.Library = l.InstallDir.Base()
344+
return nil
345+
}
346+
}
347+
if gitUrl, ok := dataMap["git"]; ok {
348+
if gitUrlStr, ok := gitUrl.(string); !ok {
349+
return fmt.Errorf("%s: %s", i18n.Tr("invalid git library reference: %s"), dataMap)
350+
} else if parsedUrl, err := url.Parse(gitUrlStr); err != nil {
351+
return fmt.Errorf("%s: %w", i18n.Tr("invalid git library URL:"), err)
352+
} else {
353+
l.GitURL = parsedUrl
354+
if l.Library = filepath.Base(parsedUrl.Path); l.Library == "" {
355+
l.Library = "lib"
356+
}
357+
l.Library = strings.TrimSuffix(l.Library, ".git")
358+
return nil
359+
}
344360
}
361+
return errors.New(i18n.Tr("invalid library reference: %s", dataMap))
345362
}
346363

347364
var data string
@@ -364,12 +381,18 @@ func (l *ProfileLibraryReference) AsYaml() string {
364381
if l.InstallDir != nil {
365382
return fmt.Sprintf(" - dir: %s\n", l.InstallDir)
366383
}
384+
if l.GitURL != nil {
385+
return fmt.Sprintf(" - git: %s\n", l.GitURL)
386+
}
367387
return fmt.Sprintf(" - %s (%s)\n", l.Library, l.Version)
368388
}
369389

370390
func (l *ProfileLibraryReference) String() string {
371391
if l.InstallDir != nil {
372-
return fmt.Sprintf("%s@dir:%s", l.Library, l.InstallDir)
392+
return "@dir:" + l.InstallDir.String()
393+
}
394+
if l.GitURL != nil {
395+
return "@git:" + l.GitURL.String()
373396
}
374397
return fmt.Sprintf("%s@%s", l.Library, l.Version)
375398
}
@@ -378,6 +401,16 @@ func (l *ProfileLibraryReference) String() string {
378401
func (l *ProfileLibraryReference) InternalUniqueIdentifier() string {
379402
f.Assert(l.InstallDir == nil,
380403
"InternalUniqueIdentifier should not be called for library references with an install directory")
404+
405+
if l.GitURL != nil {
406+
id := "git-" + utils.SanitizeName(l.GitURL.Host+l.GitURL.Path+"#"+l.GitURL.Fragment)
407+
if len(id) > 50 {
408+
id = id[:50]
409+
}
410+
h := sha256.Sum256([]byte(l.GitURL.String()))
411+
return id + "-" + hex.EncodeToString(h[:])[:8]
412+
}
413+
381414
id := l.String()
382415
h := sha256.Sum256([]byte(id))
383416
res := fmt.Sprintf("%s_%s", id, hex.EncodeToString(h[:])[:16])

internal/arduino/sketch/profiles_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,26 @@ func TestProjectFileLoading(t *testing.T) {
5353
require.Error(t, err)
5454
}
5555
}
56+
57+
func TestProjectFileLibraries(t *testing.T) {
58+
sketchProj := paths.New("testdata", "profiles", "profile_with_libraries.yml")
59+
proj, err := LoadProjectFile(sketchProj)
60+
require.NoError(t, err)
61+
require.Len(t, proj.Profiles, 1)
62+
prof := proj.Profiles[0]
63+
require.Len(t, prof.Libraries, 5)
64+
require.Equal(t, "FlashStorage@1.2.3", prof.Libraries[0].String())
65+
require.Equal(t, "@dir:/path/to/system/lib", prof.Libraries[1].String())
66+
require.Equal(t, "@dir:path/to/sketch/lib", prof.Libraries[2].String())
67+
require.Equal(t, "@git:https://github.com/username/HelloWorld.git#v2.13", prof.Libraries[3].String())
68+
require.Equal(t, "@git:https://github.com/username/HelloWorld.git#v2.14", prof.Libraries[4].String())
69+
require.Equal(t, "FlashStorage_1.2.3_e525d7c96b27788f", prof.Libraries[0].InternalUniqueIdentifier())
70+
require.Panics(t, func() { prof.Libraries[1].InternalUniqueIdentifier() })
71+
require.Panics(t, func() { prof.Libraries[2].InternalUniqueIdentifier() })
72+
require.Equal(t, "git-github.com_username_HelloWorld.git_v2.13-0c146203", prof.Libraries[3].InternalUniqueIdentifier())
73+
require.Equal(t, "git-github.com_username_HelloWorld.git_v2.14-49f5df7f", prof.Libraries[4].InternalUniqueIdentifier())
74+
75+
orig, err := sketchProj.ReadFile()
76+
require.NoError(t, err)
77+
require.Equal(t, string(orig), proj.AsYaml())
78+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
profiles:
2+
giga:
3+
fqbn: arduino:mbed_giga:giga
4+
platforms:
5+
- platform: arduino:mbed_giga (4.3.1)
6+
libraries:
7+
- FlashStorage (1.2.3)
8+
- dir: /path/to/system/lib
9+
- dir: path/to/sketch/lib
10+
- git: https://github.com/username/HelloWorld.git#v2.13
11+
- git: https://github.com/username/HelloWorld.git#v2.14
12+
13+
default_profile: giga_any

0 commit comments

Comments
 (0)