Skip to content

Commit a14c037

Browse files
author
vinay-lanka
committed
add zip library imports
have added a --zip-path flag to lib install command takes absolute path to zip file and extracts it to libraries directory
1 parent c076ad3 commit a14c037

File tree

16 files changed

+609
-210
lines changed

16 files changed

+609
-210
lines changed

arduino/libraries/librariesmanager/install.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
package librariesmanager
1717

1818
import (
19+
"archive/zip"
1920
"errors"
2021
"fmt"
22+
"io"
23+
"log"
24+
"os"
25+
"path/filepath"
26+
"strings"
2127

2228
"github.com/arduino/arduino-cli/arduino/libraries"
2329
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
@@ -85,3 +91,73 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error {
8591
lm.Libraries[lib.Name].Remove(lib)
8692
return nil
8793
}
94+
95+
//InstallZipLib installs a Zip library on the specified path.
96+
func (lm *LibrariesManager) InstallZipLib(libPath string) error {
97+
libsDir := lm.getUserLibrariesDir()
98+
if libsDir == nil {
99+
return fmt.Errorf("User directory not set")
100+
}
101+
err := Unzip(libPath, libsDir.String())
102+
if err != nil {
103+
log.Fatal(err)
104+
}
105+
return nil
106+
}
107+
108+
//Unzip takes the ZipLibPath and Extracts it to LibsDir
109+
func Unzip(src string, dest string) error {
110+
111+
var filenames []string
112+
113+
r, err := zip.OpenReader(src)
114+
if err != nil {
115+
return err
116+
}
117+
defer r.Close()
118+
119+
for _, f := range r.File {
120+
121+
// Store filename/path for returning and using later on
122+
fpath := filepath.Join(dest, f.Name)
123+
124+
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
125+
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
126+
return fmt.Errorf("%s: illegal file path", fpath)
127+
}
128+
129+
filenames = append(filenames, fpath)
130+
131+
if f.FileInfo().IsDir() {
132+
// Make Folder
133+
os.MkdirAll(fpath, os.ModePerm)
134+
continue
135+
}
136+
137+
// Make File
138+
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
139+
return err
140+
}
141+
142+
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
143+
if err != nil {
144+
return err
145+
}
146+
147+
rc, err := f.Open()
148+
if err != nil {
149+
return err
150+
}
151+
152+
_, err = io.Copy(outFile, rc)
153+
154+
// Close the file without defer to close before next iteration of loop
155+
outFile.Close()
156+
rc.Close()
157+
158+
if err != nil {
159+
return err
160+
}
161+
}
162+
return nil
163+
}

cli/lib/install.go

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -41,65 +41,81 @@ func initInstallCommand() *cobra.Command {
4141
Run: runInstallCommand,
4242
}
4343
installCommand.Flags().BoolVar(&installFlags.noDeps, "no-deps", false, "Do not install dependencies.")
44+
installCommand.Flags().StringVarP(&installFlags.gitURL, "git-url", "g", "", "Enter git url for libraries hosted on repositories")
45+
installCommand.Flags().StringVarP(&installFlags.zipPath, "zip-path", "z", "", "Enter a path to zip file")
4446
return installCommand
4547
}
4648

4749
var installFlags struct {
48-
noDeps bool
50+
noDeps bool
51+
gitURL string
52+
zipPath string
4953
}
5054

5155
func runInstallCommand(cmd *cobra.Command, args []string) {
5256
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
53-
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
54-
if err != nil {
55-
feedback.Errorf("Arguments error: %v", err)
56-
os.Exit(errorcodes.ErrBadArgument)
57-
}
58-
59-
toInstall := map[string]*rpc.LibraryDependencyStatus{}
60-
if installFlags.noDeps {
61-
for _, libRef := range libRefs {
62-
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
63-
Name: libRef.Name,
64-
VersionRequired: libRef.Version,
65-
}
57+
if installFlags.zipPath != "" {
58+
ZiplibraryInstallReq := &rpc.ZipLibraryInstallReq{
59+
Instance: instance,
60+
Path: installFlags.zipPath,
6661
}
67-
} else {
68-
for _, libRef := range libRefs {
69-
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
70-
Instance: instance,
71-
Name: libRef.Name,
72-
Version: libRef.Version,
73-
})
74-
if err != nil {
75-
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
62+
_, err := lib.ZipLibraryInstall(context.Background(), ZiplibraryInstallReq)
63+
if err != nil {
64+
feedback.Errorf("Error installing Zip Library %v", err)
65+
os.Exit(errorcodes.ErrGeneric)
66+
}
67+
}else{
68+
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
69+
if err != nil {
70+
feedback.Errorf("Arguments error: %v", err)
71+
os.Exit(errorcodes.ErrBadArgument)
72+
}
73+
74+
toInstall := map[string]*rpc.LibraryDependencyStatus{}
75+
if installFlags.noDeps {
76+
for _, libRef := range libRefs {
77+
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
78+
Name: libRef.Name,
79+
VersionRequired: libRef.Version,
80+
}
7681
}
77-
for _, dep := range depsResp.GetDependencies() {
78-
feedback.Printf("%s depends on %s@%s", libRef, dep.GetName(), dep.GetVersionRequired())
79-
if existingDep, has := toInstall[dep.GetName()]; has {
80-
if existingDep.GetVersionRequired() != dep.GetVersionRequired() {
81-
// TODO: make a better error
82-
feedback.Errorf("The library %s is required in two different versions: %s and %s",
83-
dep.GetName(), dep.GetVersionRequired(), existingDep.GetVersionRequired())
84-
os.Exit(errorcodes.ErrGeneric)
82+
} else {
83+
for _, libRef := range libRefs {
84+
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
85+
Instance: instance,
86+
Name: libRef.Name,
87+
Version: libRef.Version,
88+
})
89+
if err != nil {
90+
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
91+
}
92+
for _, dep := range depsResp.GetDependencies() {
93+
feedback.Printf("%s depends on %s@%s", libRef, dep.GetName(), dep.GetVersionRequired())
94+
if existingDep, has := toInstall[dep.GetName()]; has {
95+
if existingDep.GetVersionRequired() != dep.GetVersionRequired() {
96+
// TODO: make a better error
97+
feedback.Errorf("The library %s is required in two different versions: %s and %s",
98+
dep.GetName(), dep.GetVersionRequired(), existingDep.GetVersionRequired())
99+
os.Exit(errorcodes.ErrGeneric)
100+
}
85101
}
102+
toInstall[dep.GetName()] = dep
86103
}
87-
toInstall[dep.GetName()] = dep
88104
}
89105
}
90-
}
91106

92-
for _, library := range toInstall {
93-
libraryInstallReq := &rpc.LibraryInstallReq{
94-
Instance: instance,
95-
Name: library.Name,
96-
Version: library.VersionRequired,
97-
}
98-
err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(),
99-
output.TaskProgress(), globals.NewHTTPClientHeader())
100-
if err != nil {
101-
feedback.Errorf("Error installing %s: %v", library, err)
102-
os.Exit(errorcodes.ErrGeneric)
107+
for _, library := range toInstall {
108+
libraryInstallReq := &rpc.LibraryInstallReq{
109+
Instance: instance,
110+
Name: library.Name,
111+
Version: library.VersionRequired,
112+
}
113+
err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(),
114+
output.TaskProgress(), globals.NewHTTPClientHeader())
115+
if err != nil {
116+
feedback.Errorf("Error installing %s: %v", library, err)
117+
os.Exit(errorcodes.ErrGeneric)
118+
}
103119
}
104120
}
105121
}

commands/daemon/daemon.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,8 @@ func (s *ArduinoCoreServerImpl) LibrarySearch(ctx context.Context, req *rpc.Libr
287287
func (s *ArduinoCoreServerImpl) LibraryList(ctx context.Context, req *rpc.LibraryListReq) (*rpc.LibraryListResp, error) {
288288
return lib.LibraryList(ctx, req)
289289
}
290+
291+
//ZipLibraryInstall FIXMEDOC
292+
func (s *ArduinoCoreServerImpl) ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallReq) (*rpc.ZipLibraryInstallResp, error) {
293+
return lib.ZipLibraryInstall(ctx, req)
294+
}

commands/lib/install.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,23 @@ func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *libraries
7676
taskCB(&rpc.TaskProgress{Message: "Installed " + libRelease.String(), Completed: true})
7777
return nil
7878
}
79+
80+
//ZipLibraryInstall FIXMEDOC
81+
func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallReq) (*rpc.ZipLibraryInstallResp, error) {
82+
res := &rpc.ZipLibraryInstallResp{}
83+
lm := commands.GetLibraryManager(req.GetInstance().GetId())
84+
Path := req.GetPath()
85+
if err := installZipLibrary(lm, Path); err != nil {
86+
res.Status = "Error installing Zip Library"
87+
return res, err
88+
}
89+
res.Status = "Success! Installed Zip Library"
90+
return res, nil
91+
}
92+
93+
func installZipLibrary(lm *librariesmanager.LibrariesManager, libPath string) error {
94+
if err := lm.InstallZipLib(libPath); err != nil {
95+
return err
96+
}
97+
return nil
98+
}

rpc/commands/board.pb.go

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)