Skip to content

Commit

Permalink
Big refactoring of libraries and librariesmanager (WIP)
Browse files Browse the repository at this point in the history
- removed a lot of redundant code (especially in install/uninstall/list)
- some operations should be reimplemented using the generic functions
  in the `arduino/libraries` module.
- improved output of `lib list` command
- improved indexer
  • Loading branch information
cmaglie committed Aug 1, 2018
1 parent dd84c1a commit 7da6786
Show file tree
Hide file tree
Showing 17 changed files with 294 additions and 639 deletions.
131 changes: 1 addition & 130 deletions arduino/libraries/libraries.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,7 @@
package libraries

import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/arduino/go-paths-helper"
"github.com/bcmi-labs/arduino-cli/arduino/resources"
"github.com/bcmi-labs/arduino-cli/configs"
"github.com/blang/semver"
)

var MandatoryProperties = []string{"name", "version", "author", "maintainer"}
Expand Down Expand Up @@ -78,8 +68,7 @@ type Library struct {
Category string
Architectures []string

Types []string `json:"types,omitempty"`
Releases map[string]*Release `json:"releases,omitempty"`
Types []string `json:"types,omitempty"`

Folder *paths.Path
SrcFolder *paths.Path
Expand Down Expand Up @@ -138,121 +127,3 @@ func (library *Library) SourceDirs() []SourceDir {
}
return dirs
}

// InstalledRelease returns the installed release of the library.
func (library *Library) InstalledRelease() (*Release, error) {
libFolder, err := configs.LibrariesFolder.Get()
if err != nil {
return nil, err
}
files, err := ioutil.ReadDir(libFolder)
if err != nil {
return nil, err
}
// reached := false
// QUESTION : what to do if i find multiple versions installed? @cmaglie
// purpose : use reached variable to create a list of installed versions,
// it may be useful if someone accidentally put in libFolder multiple
// versions, to allow them to be deleted.
for _, file := range files {
name := strings.Replace(file.Name(), "_", " ", -1)
// found
// QUESTION : what to do if i find multiple versions installed? @cmaglie
if file.IsDir() {
// try to read library.properties
content, err := os.Open(filepath.Join(libFolder, file.Name(), "library.properties"))
if err != nil && strings.Contains(name, library.Name) {
// use folder name
version := strings.SplitN(name, "-", 2)[1] // split only once, useful for libName-1.0.0-pre-alpha/beta versions.
return library.Releases[version], nil
}
defer content.Close()

scanner := bufio.NewScanner(content)
fields := make(map[string]string, 20)

for scanner.Scan() {
line := strings.SplitN(scanner.Text(), "=", 1)
if len(line) == 2 {
fields[line[0]] = line[1]
}
}
if scanner.Err() != nil && strings.Contains(name, library.Name) {
// use folder name
version := strings.SplitN(name, "-", 2)[1] // split only once, useful for libName-1.0.0-pre-alpha/beta versions.
return library.Releases[version], nil
}

_, nameExists := fields["name"]
version, versionExists := fields["version"]
if nameExists && versionExists {
return library.GetVersion(version), nil
} else if strings.Contains(name, library.Name) {
// use folder name
version = strings.SplitN(name, "-", 2)[1] // split only once, useful for libName-1.0.0-pre-alpha/beta versions.
return library.Releases[version], nil
}
}
}
return nil, nil // no error, but not found
}

// Release represents a release of a library
type Release struct {
Version string `json:"version"`
Resource *resources.DownloadResource `json:"resource"`
Library *Library `json:"-"`
}

func (r *Release) String() string {
return r.Library.String() + "@" + r.Version
}

// GetVersion returns the Release corresponding to the specified version, or
// nil if not found.
//
// If version == "latest" then release.Version contains the latest version.
func (library Library) GetVersion(version string) *Release {
if version == "latest" {
return library.Releases[library.latestVersion()]
}
return library.Releases[version]
}

// Latest obtains the latest version of a library.
func (library Library) Latest() *Release {
return library.GetVersion(library.latestVersion())
}

// latestVersion obtains latest version number.
//
// It uses lexicographics to compare version strings.
func (library *Library) latestVersion() string {
versions := library.Versions()
if len(versions) == 0 {
return ""
}
max := versions[0]

for i := 1; i < len(versions); i++ {
if versions[i].GT(max) {
max = versions[i]
}
}
return fmt.Sprint(max)
}

// Versions returns an array of all versions available of the library
func (library Library) Versions() semver.Versions {
res := make(semver.Versions, len(library.Releases))
i := 0
for version := range library.Releases {
temp, err := semver.Make(version)
if err == nil {
res[i] = temp
i++
}
}
//sortutil.CiAsc(res)
return res
}
111 changes: 23 additions & 88 deletions arduino/libraries/librariesindex/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@
package librariesindex

import (
"encoding/json"
"fmt"
"io/ioutil"
"sort"

"github.com/bcmi-labs/arduino-cli/arduino/resources"
"github.com/blang/semver"

"github.com/bcmi-labs/arduino-cli/configs"
"github.com/bcmi-labs/arduino-cli/arduino/resources"
)

// Index represents the list of libraries available for download
Expand All @@ -48,8 +46,8 @@ type Index struct {
type Library struct {
Name string
Releases map[string]*Release

Index *Index `json:"-"`
Latest *Release `json:"-"`
Index *Index `json:"-"`
}

// Release is a release of a library available for download
Expand All @@ -69,92 +67,29 @@ type Release struct {
Library *Library `json:"-"`
}

type indexJSON struct {
Libraries []indexRelease `json:"libraries"`
}

type indexRelease struct {
Name string `json:"name,required"`
Version string `json:"version,required"`
Author string `json:"author"`
Maintainer string `json:"maintainer"`
Sentence string `json:"sentence"`
Paragraph string `json:"paragraph"`
Website string `json:"website"`
Category string `json:"category"`
Architectures []string `json:"architectures"`
Types []string `json:"types"`
URL string `json:"url"`
ArchiveFileName string `json:"archiveFileName"`
Size int64 `json:"size"`
Checksum string `json:"checksum"`
}

// IndexPath is the path of the index file for libraries.
var IndexPath = configs.IndexPath("library_index.json")

// LoadIndex reads a library_index.json and create the corresponding Index
func LoadIndex() (*Index, error) {
libFile, err := IndexPath.Get()
if err != nil {
return nil, fmt.Errorf("getting library_index.json path: %s", err)
}

buff, err := ioutil.ReadFile(libFile)
if err != nil {
return nil, fmt.Errorf("reading library_index.json: %s", err)
}

var i indexJSON
err = json.Unmarshal(buff, &i)
if err != nil {
return nil, fmt.Errorf("parsing library_index.json: %s", err)
}

return i.extractIndex()
func (r *Release) String() string {
return r.Library.Name + "@" + r.Version
}

func (i indexJSON) extractIndex() (*Index, error) {
index := &Index{
Libraries: map[string]*Library{},
// FindRelease search a library Release in the index. Returns nil if the
// release is not found
func (idx *Index) FindRelease(ref *Reference) *Release {
if library, exists := idx.Libraries[ref.Name]; !exists {
return nil
} else {
return library.Releases[ref.Version]
}
for _, indexLib := range i.Libraries {
indexLib.extractLibraryIn(index)
}
return index, nil
}

func (indexLib *indexRelease) extractLibraryIn(index *Index) {
library, exist := index.Libraries[indexLib.Name]
if !exist {
library := &Library{
Name: indexLib.Name,
Releases: map[string]*Release{},
// Versions returns an array of all versions available of the library
func (library *Library) Versions() semver.Versions {
res := semver.Versions{}
for version := range library.Releases {
v, err := semver.Make(version)
if err == nil {
res = append(res, v)
}
index.Libraries[indexLib.Name] = library
}
indexLib.extractReleaseIn(library)
}

func (indexLib *indexRelease) extractReleaseIn(library *Library) {
release := &Release{
Version: indexLib.Version,
Author: indexLib.Author,
Maintainer: indexLib.Maintainer,
Sentence: indexLib.Sentence,
Paragraph: indexLib.Paragraph,
Website: indexLib.Website,
Category: indexLib.Category,
Architectures: indexLib.Architectures,
Types: indexLib.Types,
Resource: &resources.DownloadResource{
URL: indexLib.URL,
ArchiveFileName: indexLib.ArchiveFileName,
Size: indexLib.Size,
Checksum: indexLib.Checksum,
CachePath: "libraries",
},
Library: library,
}
library.Releases[indexLib.Version] = release
sort.Sort(res)
return res
}
Loading

0 comments on commit 7da6786

Please sign in to comment.