Skip to content

Commit b2fad77

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 a9c0a97 commit b2fad77

File tree

18 files changed

+4601
-7885
lines changed

18 files changed

+4601
-7885
lines changed

Diff for: arduino/libraries/librariesmanager/install.go

+103
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@
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"
2430
"github.com/arduino/arduino-cli/arduino/utils"
2531
paths "github.com/arduino/go-paths-helper"
32+
"gopkg.in/src-d/go-git.v4"
2633
)
2734

2835
var (
@@ -85,3 +92,99 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error {
8592
lm.Libraries[lib.Name].Remove(lib)
8693
return nil
8794
}
95+
96+
//InstallZipLib installs a Zip library on the specified path.
97+
func (lm *LibrariesManager) InstallZipLib(libPath string) error {
98+
libsDir := lm.getUserLibrariesDir()
99+
if libsDir == nil {
100+
return fmt.Errorf("User directory not set")
101+
}
102+
err := Unzip(libPath, libsDir.String())
103+
if err != nil {
104+
log.Fatal(err)
105+
}
106+
return nil
107+
}
108+
109+
//Unzip takes the ZipLibPath and Extracts it to LibsDir
110+
func Unzip(src string, dest string) error {
111+
112+
var filenames []string
113+
114+
r, err := zip.OpenReader(src)
115+
if err != nil {
116+
return err
117+
}
118+
defer r.Close()
119+
120+
for _, f := range r.File {
121+
122+
// Store filename/path for returning and using later on
123+
fpath := filepath.Join(dest, f.Name)
124+
125+
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
126+
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
127+
return fmt.Errorf("%s: illegal file path", fpath)
128+
}
129+
130+
filenames = append(filenames, fpath)
131+
132+
if f.FileInfo().IsDir() {
133+
// Make Folder
134+
os.MkdirAll(fpath, os.ModePerm)
135+
continue
136+
}
137+
138+
// Make File
139+
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
140+
return err
141+
}
142+
143+
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
144+
if err != nil {
145+
return err
146+
}
147+
148+
rc, err := f.Open()
149+
if err != nil {
150+
return err
151+
}
152+
153+
_, err = io.Copy(outFile, rc)
154+
155+
// Close the file without defer to close before next iteration of loop
156+
outFile.Close()
157+
rc.Close()
158+
159+
if err != nil {
160+
return err
161+
}
162+
}
163+
return nil
164+
}
165+
166+
//InstallGitLib installs a library hosted on a git repository on the specified path.
167+
func (lm *LibrariesManager) InstallGitLib(Name string, gitURL string) error {
168+
libsDir := lm.getUserLibrariesDir()
169+
if libsDir == nil {
170+
return fmt.Errorf("User directory not set")
171+
}
172+
err := Fetch(Name, gitURL, libsDir.String())
173+
if err != nil {
174+
return err
175+
}
176+
return nil
177+
}
178+
179+
//Fetch Clones the repository to LibsDir
180+
func Fetch(name string, url string, dest string) error {
181+
directory := dest + "/" + name
182+
_, err := git.PlainClone(directory, false, &git.CloneOptions{
183+
URL: url,
184+
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
185+
})
186+
if err != nil {
187+
return err
188+
}
189+
return nil
190+
}

Diff for: cli/lib/install.go

+70-43
Original file line numberDiff line numberDiff line change
@@ -40,65 +40,92 @@ func initInstallCommand() *cobra.Command {
4040
Run: runInstallCommand,
4141
}
4242
installCommand.Flags().BoolVar(&installFlags.noDeps, "no-deps", false, "Do not install dependencies.")
43+
installCommand.Flags().StringVarP(&installFlags.gitURL, "git-url", "g", "", "Enter git url for libraries hosted on repositories")
44+
installCommand.Flags().StringVarP(&installFlags.zipPath, "zip-path", "z", "", "Enter a path to zip file")
4345
return installCommand
4446
}
4547

4648
var installFlags struct {
47-
noDeps bool
49+
noDeps bool
50+
gitURL string
51+
zipPath string
4852
}
4953

5054
func runInstallCommand(cmd *cobra.Command, args []string) {
5155
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
52-
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
53-
if err != nil {
54-
feedback.Errorf("Arguments error: %v", err)
55-
os.Exit(errorcodes.ErrBadArgument)
56-
}
57-
58-
toInstall := map[string]*rpc.LibraryDependencyStatus{}
59-
if installFlags.noDeps {
60-
for _, libRef := range libRefs {
61-
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
62-
Name: libRef.Name,
63-
VersionRequired: libRef.Version,
64-
}
56+
if installFlags.zipPath != "" {
57+
ZiplibraryInstallReq := &rpc.ZipLibraryInstallReq{
58+
Instance: instance,
59+
Path: installFlags.zipPath,
60+
}
61+
_, err := lib.ZipLibraryInstall(context.Background(), ZiplibraryInstallReq)
62+
if err != nil {
63+
feedback.Errorf("Error installing Zip Library %v", err)
64+
os.Exit(errorcodes.ErrGeneric)
65+
}
66+
} else if installFlags.gitURL != "" {
67+
GitlibraryInstallReq := &rpc.GitLibraryInstallReq{
68+
Instance: instance,
69+
Name: args[0],
70+
Url: installFlags.gitURL,
71+
}
72+
_, err := lib.GitLibraryInstall(context.Background(), GitlibraryInstallReq)
73+
if err != nil {
74+
feedback.Errorf("Error installing Git Library %v", err)
75+
os.Exit(errorcodes.ErrGeneric)
6576
}
6677
} else {
67-
for _, libRef := range libRefs {
68-
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
69-
Instance: instance,
70-
Name: libRef.Name,
71-
Version: libRef.Version,
72-
})
73-
if err != nil {
74-
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
75-
os.Exit(errorcodes.ErrGeneric)
78+
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
79+
if err != nil {
80+
feedback.Errorf("Arguments error: %v", err)
81+
os.Exit(errorcodes.ErrBadArgument)
82+
}
83+
84+
toInstall := map[string]*rpc.LibraryDependencyStatus{}
85+
if installFlags.noDeps {
86+
for _, libRef := range libRefs {
87+
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
88+
Name: libRef.Name,
89+
VersionRequired: libRef.Version,
90+
}
7691
}
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)
92+
} else {
93+
for _, libRef := range libRefs {
94+
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
95+
Instance: instance,
96+
Name: libRef.Name,
97+
Version: libRef.Version,
98+
})
99+
if err != nil {
100+
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
101+
os.Exit(errorcodes.ErrGeneric)
102+
}
103+
for _, dep := range depsResp.GetDependencies() {
104+
feedback.Printf("%s depends on %s@%s", libRef, dep.GetName(), dep.GetVersionRequired())
105+
if existingDep, has := toInstall[dep.GetName()]; has {
106+
if existingDep.GetVersionRequired() != dep.GetVersionRequired() {
107+
// TODO: make a better error
108+
feedback.Errorf("The library %s is required in two different versions: %s and %s",
109+
dep.GetName(), dep.GetVersionRequired(), existingDep.GetVersionRequired())
110+
os.Exit(errorcodes.ErrGeneric)
111+
}
85112
}
113+
toInstall[dep.GetName()] = dep
86114
}
87-
toInstall[dep.GetName()] = dep
88115
}
89116
}
90-
}
91117

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(), output.TaskProgress())
99-
if err != nil {
100-
feedback.Errorf("Error installing %s: %v", library, err)
101-
os.Exit(errorcodes.ErrGeneric)
118+
for _, library := range toInstall {
119+
libraryInstallReq := &rpc.LibraryInstallReq{
120+
Instance: instance,
121+
Name: library.Name,
122+
Version: library.VersionRequired,
123+
}
124+
err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(), output.TaskProgress())
125+
if err != nil {
126+
feedback.Errorf("Error installing %s: %v", library, err)
127+
os.Exit(errorcodes.ErrGeneric)
128+
}
102129
}
103130
}
104131
}

Diff for: commands/daemon/daemon.go

+10
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,13 @@ func (s *ArduinoCoreServerImpl) LibraryList(ctx context.Context, req *rpc.Librar
343343
func (s *ArduinoCoreServerImpl) ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.ArchiveSketchResp, error) {
344344
return sketch.ArchiveSketch(ctx, req)
345345
}
346+
347+
//ZipLibraryInstall FIXMEDOC
348+
func (s *ArduinoCoreServerImpl) ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallReq) (*rpc.ZipLibraryInstallResp, error) {
349+
return lib.ZipLibraryInstall(ctx, req)
350+
}
351+
352+
//GitLibraryInstall FIXMEDOC
353+
func (s *ArduinoCoreServerImpl) GitLibraryInstall(ctx context.Context, req *rpc.GitLibraryInstallReq) (*rpc.GitLibraryInstallResp, error) {
354+
return lib.GitLibraryInstall(ctx, req)
355+
}

Diff for: commands/lib/install.go

+41
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,44 @@ func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *libraries
7575
taskCB(&rpc.TaskProgress{Message: "Installed " + libRelease.String(), Completed: true})
7676
return nil
7777
}
78+
79+
//ZipLibraryInstall FIXMEDOC
80+
func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallReq) (*rpc.ZipLibraryInstallResp, error) {
81+
res := &rpc.ZipLibraryInstallResp{}
82+
lm := commands.GetLibraryManager(req.GetInstance().GetId())
83+
Path := req.GetPath()
84+
if err := installZipLibrary(lm, Path); err != nil {
85+
res.Status = "Error installing Zip Library"
86+
return res, err
87+
}
88+
res.Status = "Success! Installed Zip Library"
89+
return res, nil
90+
}
91+
92+
func installZipLibrary(lm *librariesmanager.LibrariesManager, libPath string) error {
93+
if err := lm.InstallZipLib(libPath); err != nil {
94+
return err
95+
}
96+
return nil
97+
}
98+
99+
//GitLibraryInstall FIXMEDOC
100+
func GitLibraryInstall(ctx context.Context, req *rpc.GitLibraryInstallReq) (*rpc.GitLibraryInstallResp, error) {
101+
res := &rpc.GitLibraryInstallResp{}
102+
lm := commands.GetLibraryManager(req.GetInstance().GetId())
103+
URL := req.GetUrl()
104+
Name := req.GetName()
105+
if err := installGitLibrary(lm, Name, URL); err != nil {
106+
res.Status = "Error installing Git Library"
107+
return res, err
108+
}
109+
res.Status = "Success! Installed Git Library"
110+
return res, nil
111+
}
112+
113+
func installGitLibrary(lm *librariesmanager.LibrariesManager, Name string, gitURL string) error {
114+
if err := lm.InstallGitLib(Name, gitURL); err != nil {
115+
return err
116+
}
117+
return nil
118+
}

Diff for: go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ require (
4242
go.bug.st/relaxed-semver v0.0.0-20190922224835-391e10178d18
4343
go.bug.st/serial v1.1.1
4444
go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 // indirect
45-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
45+
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
4646
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
4747
golang.org/x/text v0.3.2
4848
google.golang.org/grpc v1.27.0
4949
google.golang.org/protobuf v1.25.0
5050
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
51+
gopkg.in/src-d/go-git.v4 v4.13.1
5152
gopkg.in/yaml.v2 v2.3.0
5253
)

0 commit comments

Comments
 (0)