Skip to content

Commit b3dd26f

Browse files
facchinmcmaglie
authored andcommitted
Allow zip sketches with embedded libraries
1 parent 0d042f0 commit b3dd26f

File tree

6 files changed

+121
-1
lines changed

6 files changed

+121
-1
lines changed

Diff for: container_setup.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ func (s *ContainerSetupHardwareToolsLibsSketchAndProps) Run(ctx *types.Context)
4646
&ToolsLoader{},
4747
&TargetBoardResolver{},
4848
&AddBuildBoardPropertyIfMissing{},
49-
&LibrariesLoader{},
5049
&SketchLoader{},
50+
&LibrariesLoader{},
5151
&SetupBuildProperties{},
5252
&LoadVIDPIDSpecificProperties{},
5353
&SetCustomBuildProperties{},

Diff for: libraries_loader.go

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ func (s *LibrariesLoader) Run(ctx *types.Context) error {
6363

6464
sortedLibrariesFolders = appendPathToLibrariesFolders(sortedLibrariesFolders, filepath.Join(platform.Folder, constants.FOLDER_LIBRARIES))
6565

66+
if ctx.SketchZipped {
67+
sortedLibrariesFolders = appendPathToLibrariesFolders(sortedLibrariesFolders, filepath.Join(filepath.Dir(ctx.SketchLocation), constants.FOLDER_LIBRARIES))
68+
}
69+
6670
librariesFolders := ctx.OtherLibrariesFolders
6771
librariesFolders, err = utils.AbsolutizePaths(librariesFolders)
6872
if err != nil {

Diff for: resolve_library.go

+14
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ func ResolveLibrary(ctx *types.Context, header string) *types.Library {
8484

8585
library = useAlreadyImportedLibraryWithSameNameIfExists(library, importedLibraries)
8686

87+
if ctx.SketchZipped {
88+
// select embedded library, in any case
89+
library = libraryContainedInSketchFolder(libraries, filepath.Dir(ctx.SketchLocation))
90+
}
91+
8792
libraryResolutionResults[header] = types.LibraryResolutionResult{
8893
Library: library,
8994
NotUsedLibraries: filterOutLibraryFrom(libraries, library),
@@ -119,6 +124,15 @@ func useAlreadyImportedLibraryWithSameNameIfExists(library *types.Library, impor
119124
return library
120125
}
121126

127+
func libraryContainedInSketchFolder(libraries []*types.Library, sketchFolder string) *types.Library {
128+
for _, lib := range libraries {
129+
if strings.Contains(lib.Folder, sketchFolder) {
130+
return lib
131+
}
132+
}
133+
return libraries[0]
134+
}
135+
122136
func filterOutLibraryFrom(libraries []*types.Library, libraryToRemove *types.Library) []*types.Library {
123137
filteredOutLibraries := []*types.Library{}
124138
for _, lib := range libraries {

Diff for: sketch_loader.go

+29
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
package builder
3131

3232
import (
33+
"bufio"
3334
"io/ioutil"
35+
"net/http"
3436
"os"
3537
"path/filepath"
3638
"sort"
@@ -63,6 +65,17 @@ func (s *SketchLoader) Run(ctx *types.Context) error {
6365
sketchLocation = filepath.Join(sketchLocation, mainSketchStat.Name()+".ino")
6466
}
6567

68+
if mimeType(sketchLocation) == "application/zip" {
69+
dir, _ := ioutil.TempDir("", "arduino_sketch_zip_temp")
70+
sketchLocation, err = utils.ExtractZip(sketchLocation, dir)
71+
if err != nil {
72+
return nil
73+
}
74+
mainSketchFileName := filepath.Base(sketchLocation) + ".ino"
75+
sketchLocation = filepath.Join(sketchLocation, mainSketchFileName)
76+
ctx.SketchZipped = true
77+
}
78+
6679
ctx.SketchLocation = sketchLocation
6780

6881
allSketchFilePaths, err := collectAllSketchFiles(filepath.Dir(sketchLocation))
@@ -87,6 +100,22 @@ func (s *SketchLoader) Run(ctx *types.Context) error {
87100
return nil
88101
}
89102

103+
func mimeType(fileName string) string {
104+
fs, err := os.Open(fileName)
105+
106+
if err != nil {
107+
return ""
108+
}
109+
110+
defer fs.Close()
111+
112+
reader := bufio.NewReader(fs)
113+
114+
buf := make([]byte, 512)
115+
reader.Read(buf)
116+
return http.DetectContentType(buf)
117+
}
118+
90119
func collectAllSketchFiles(from string) ([]string, error) {
91120
filePaths := []string{}
92121
// Source files in the root are compiled, non-recursively. This

Diff for: types/context.go

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ type Context struct {
7979
Verbose bool
8080
DebugPreprocessor bool
8181

82+
// inoz handling
83+
SketchZipped bool
84+
8285
// Contents of a custom build properties file (line by line)
8386
CustomBuildProperties []string
8487

Diff for: utils/utils.go

+70
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
package utils
3131

3232
import (
33+
"archive/zip"
3334
"crypto/md5"
3435
"encoding/hex"
36+
"io"
3537
"io/ioutil"
3638
"os"
3739
"os/exec"
@@ -488,3 +490,71 @@ func ParseCppString(line string) (string, string, bool) {
488490
i += width
489491
}
490492
}
493+
494+
func ExtractZip(filePath string, location string) (string, error) {
495+
r, err := zip.OpenReader(filePath)
496+
if err != nil {
497+
return location, err
498+
}
499+
500+
var dirList []string
501+
502+
for _, f := range r.File {
503+
dirList = append(dirList, f.Name)
504+
}
505+
506+
basedir := findBaseDir(dirList)
507+
508+
for _, f := range r.File {
509+
fullname := filepath.Join(location, strings.Replace(f.Name, "", "", -1))
510+
if f.FileInfo().IsDir() {
511+
os.MkdirAll(fullname, f.FileInfo().Mode().Perm())
512+
} else {
513+
os.MkdirAll(filepath.Dir(fullname), 0755)
514+
perms := f.FileInfo().Mode().Perm()
515+
out, err := os.OpenFile(fullname, os.O_CREATE|os.O_RDWR, perms)
516+
if err != nil {
517+
return location, err
518+
}
519+
rc, err := f.Open()
520+
if err != nil {
521+
return location, err
522+
}
523+
_, err = io.CopyN(out, rc, f.FileInfo().Size())
524+
if err != nil {
525+
return location, err
526+
}
527+
rc.Close()
528+
out.Close()
529+
530+
mtime := f.FileInfo().ModTime()
531+
err = os.Chtimes(fullname, mtime, mtime)
532+
if err != nil {
533+
return location, err
534+
}
535+
}
536+
}
537+
return filepath.Join(location, basedir), nil
538+
}
539+
540+
func findBaseDir(dirList []string) string {
541+
baseDir := ""
542+
// https://github.com/backdrop-ops/contrib/issues/55#issuecomment-73814500
543+
dontdiff := []string{"pax_global_header"}
544+
for index := range dirList {
545+
if SliceContains(dontdiff, dirList[index]) {
546+
continue
547+
}
548+
candidateBaseDir := dirList[index]
549+
for i := index; i < len(dirList); i++ {
550+
if !strings.Contains(dirList[i], candidateBaseDir) {
551+
return baseDir
552+
}
553+
}
554+
// avoid setting the candidate if it is the last file
555+
if dirList[len(dirList)-1] != candidateBaseDir {
556+
baseDir = candidateBaseDir
557+
}
558+
}
559+
return baseDir
560+
}

0 commit comments

Comments
 (0)