From c1de60963beab0ae1961ec3bf301ab83b4b9ad48 Mon Sep 17 00:00:00 2001 From: Alessandro Sanino Date: Wed, 21 Jun 2017 15:22:57 +0200 Subject: [PATCH] Adding some core libraries, command not implemented yet, refactoring String() functions of Core, Release, Library, libraries.Release @mastrolinux --- cmd/arduino.go | 12 ++-- cmd/arduino_core.go | 44 ++++++++++++ cmd/arduino_core_list.go | 50 ++++++++++++++ cmd/pretty_print.go | 4 +- cores/cores.go | 115 +++++++++++++++++++++++++++++++ cores/index.go | 142 +++++++++++++++++++++++++++++++++++++++ cores/status.go | 90 +++++++++++++++++++++++++ 7 files changed, 450 insertions(+), 7 deletions(-) create mode 100644 cmd/arduino_core.go create mode 100644 cmd/arduino_core_list.go create mode 100644 cores/cores.go create mode 100644 cores/index.go create mode 100644 cores/status.go diff --git a/cmd/arduino.go b/cmd/arduino.go index d90e6c717a3..510bfd3438a 100644 --- a/cmd/arduino.go +++ b/cmd/arduino.go @@ -39,13 +39,16 @@ import ( ) const ( - bashAutoCompletionFunction = ` + bashAutoCompletionFunction = ` __arduino_autocomplete() { case $(last_command) in arduino_lib) opts="install uninstall list search version" ;; + arduino_core) + opts="install uninstall list search version" + ;; arduino_lib_list) opts="update" ;; @@ -61,10 +64,9 @@ const ( return 0 fi return 1 - }`, - - // ArduinoVersion represents Arduino CLI version number. - ArduinoVersion string = "0.0.1-pre-alpha" + }` + // ArduinoVersion represents Arduino CLI version number. + ArduinoVersion string = "0.0.1-pre-alpha" ) // GlobalFlags represents flags available in all the program. diff --git a/cmd/arduino_core.go b/cmd/arduino_core.go new file mode 100644 index 00000000000..24b8ef9d951 --- /dev/null +++ b/cmd/arduino_core.go @@ -0,0 +1,44 @@ +/* + * This file is part of arduino-cli. + * + * arduino-cli is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2017 BCMI LABS SA (http://www.arduino.cc/) + */ + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var arduinoCoreCmd = &cobra.Command{ + Use: "core", + Short: "Arduino Core operations", + Long: `Arduino Core operations`, +} + +func init() { + arduinoCmd.AddCommand(arduinoCoreCmd) +} diff --git a/cmd/arduino_core_list.go b/cmd/arduino_core_list.go new file mode 100644 index 00000000000..c97cd8a04c0 --- /dev/null +++ b/cmd/arduino_core_list.go @@ -0,0 +1,50 @@ +/* + * This file is part of arduino-cli. + * + * arduino-cli is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2017 BCMI LABS SA (http://www.arduino.cc/) + */ + +package cmd + +import ( + "github.com/spf13/cobra" +) + +var arduinoCoreListCmd = &cobra.Command{ + Use: "list", + Short: "Shows the list of installed cores", + Long: `Shows the list of installed cores. +With -v tag (up to 2 times) can provide more verbose output.`, + Run: executeCoreListCommand, +} + +func init() { + arduinoCoreCmd.AddCommand(arduinoCoreListCmd) +} + +func executeCoreListCommand(cmd *cobra.Command, args []string) { + +} diff --git a/cmd/pretty_print.go b/cmd/pretty_print.go index 2bce9a059a8..1686bcdbf5e 100644 --- a/cmd/pretty_print.go +++ b/cmd/pretty_print.go @@ -56,7 +56,7 @@ func prettyPrintStatus(status *libraries.StatusContext) { func prettyPrintDownloadFileIndex() error { if GlobalFlags.Verbose > 0 { - fmt.Print("Downloading a new index file from download.arduino.cc ... ") + fmt.Print("Downloading from download.arduino.cc ... ") } err := libraries.DownloadLibrariesFile() @@ -64,7 +64,7 @@ func prettyPrintDownloadFileIndex() error { if GlobalFlags.Verbose > 0 { fmt.Println("ERROR") } - fmt.Println("Cannot download index file, check your network connection.") + fmt.Println("Cannot download file, check your network connection.") return err } diff --git a/cores/cores.go b/cores/cores.go new file mode 100644 index 00000000000..3d1e6da4765 --- /dev/null +++ b/cores/cores.go @@ -0,0 +1,115 @@ +/* + * This file is part of arduino-cli. + * + * arduino-cli is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2017 BCMI LABS SA (http://www.arduino.cc/) + */ + +package cores + +import ( + "fmt" + "strings" + + "github.com/pmylund/sortutil" +) + +// Core represents a core package. +type Core struct { + Name string // The name of the Core Package. + Architecture string // The name of the architecture of this package. + Category string // The category which this core package belongs to. + Releases map[string]*Release // The Releases of this core package, labeled by version. +} + +// Release represents a release of a core package. +type Release struct { + Version string + ArchiveFileName string + Checksum string + Size int64 + Boards []string +} + +// GetVersion returns the specified release corresponding the provided version, +// or nil if not found. +func (core *Core) GetVersion(version string) *Release { + return core.Releases[version] +} + +// Versions returns all the version numbers in this Core Package. +func (core *Core) Versions() []string { + versions := make([]string, len(core.Releases)) + i := 0 + for version := range core.Releases { + versions[i] = version + i++ + } + sortutil.CiAsc(versions) + return versions +} + +// Latest obtains latest version of a core package. +func (core *Core) Latest() *Release { + return core.GetVersion(core.latestVersion()) +} + +// latestVersion obtains latest version number. +// +// It uses lexicographics to compare version strings. +func (core *Core) latestVersion() string { + versions := core.Versions() + if len(versions) > 0 { + return versions[0] + } + return "" +} + +func (core *Core) String(verbosity int) (res string) { + if verbosity > 0 { + res += fmt.Sprintf("Name : %s\n", core.Name) + res += fmt.Sprintf("Architecture: %s\n", core.Architecture) + res += fmt.Sprintf("Category : %s\n", core.Category) + if verbosity > 1 { + res += "Releases:\n" + for _, release := range core.Releases { + res += fmt.Sprintf("%s\n", release.String()) + } + } else { + res += fmt.Sprintf("Releases : %s", core.Versions()) + } + } else { + res = fmt.Sprintf("%s\n", core.Name) + } +} + +func (release *Release) String() string { + res := fmt.Sprintf("Version : %s\n", release.Version) + res += fmt.Sprintf("Boards : \n%s\n", strings.Join(release.Boards, ", ")) + res += fmt.Sprintf("Archive File Name : %s\n", release.ArchiveFileName) + res += fmt.Sprintf("Checksum : %s\n", release.Checksum) + res += fmt.Sprintf("File Size : %d\n", release.Size) + return res +} diff --git a/cores/index.go b/cores/index.go new file mode 100644 index 00000000000..c7a6e0eb01c --- /dev/null +++ b/cores/index.go @@ -0,0 +1,142 @@ +/* + * This file is part of arduino-cli. + * + * arduino-cli is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2017 BCMI LABS SA (http://www.arduino.cc/) + */ + +package cores + +import ( + "encoding/json" + "io/ioutil" + "path/filepath" + + "github.com/bcmi-labs/arduino-cli/common" +) + +// Index represents Cores and Tools struct as seen from package_index.json file. +type Index struct { + Packages []*indexPackage `json:"packages"` +} + +//IndexPath returns the path of the index file for libraries. +func IndexPath() (string, error) { + baseFolder, err := common.GetDefaultArduinoFolder() + if err != nil { + return "", err + } + return filepath.Join(baseFolder, "package_index.json"), nil +} + +//indexPackage represents a single entry from package_index.json file. +type indexPackage struct { + Name string `json:"name"` + Maintainer string `json:"maintainer"` + WebsiteURL string `json:"websiteUrl"` + Email string `json:"email"` + Platforms []*indexCoreRelease `json:"platforms"` + //Tools []*indexToolRelease `json:"tools"` +} //TODO: help : { online : "address" } is not in all package managers + +// indexCoreRelease represents a single Core Platform from package_index.json file. +type indexCoreRelease struct { + Name string `json:"name"` + Architecture string `json:"architecture"` + Version string `json:"version"` + Category string `json:"category"` + URL string `json:"url"` + ArchiveFileName string `json:"archiveFileName"` + Checksum string `json:"checksum"` + Size int64 `json:"size"` + Boards []indexBoardRelease `json:"boards"` +} + +type indexBoardRelease struct { + Name string +} + +func (packag indexPackage) extractPackage() (pm *Package) { + pm = &Package{ + Name: packag.Name, + Maintainer: packag.Maintainer, + WebsiteURL: packag.WebsiteURL, + Email: packag.Email, + Cores: make(map[string]*Core, len(packag.Platforms)), + } + for _, core := range packag.Platforms { + pm.AddCore(core) + } + return +} + +func (release *indexCoreRelease) extractCore() *Core { + return &Core{ + Name: release.Name, + Architecture: release.Architecture, + Category: release.Category, + Releases: map[string]*Release{release.Version: release.extractRelease()}, + } +} + +func (release *indexCoreRelease) extractRelease() *Release { + return &Release{ + Version: release.Version, + ArchiveFileName: release.ArchiveFileName, + Checksum: release.Checksum, + Size: release.Size, + Boards: release.extractBoards(), + } +} + +func (release *indexCoreRelease) extractBoards() []string { + boards := make([]string, 0, len(release.Boards)) + for i, board := range release.Boards { + boards[i] = board.Name + } + return boards +} + +// LoadPackagesIndex reads a package_index.json from a file and returns +// the corresponding Index structure. +func LoadPackagesIndex() (*Index, error) { + libFile, err := IndexPath() + if err != nil { + return nil, err + } + + buff, err := ioutil.ReadFile(libFile) + if err != nil { + return nil, err + } + + var index Index + err = json.Unmarshal(buff, &index) + if err != nil { + return nil, err + } + + return &index, nil +} diff --git a/cores/status.go b/cores/status.go new file mode 100644 index 00000000000..3467ac251ee --- /dev/null +++ b/cores/status.go @@ -0,0 +1,90 @@ +/* + * This file is part of arduino-cli. + * + * arduino-cli is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2017 BCMI LABS SA (http://www.arduino.cc/) + */ + +package cores + +import "github.com/pmylund/sortutil" + +// StatusContext represents the Context of the Cores and Tools in the system. +type StatusContext struct { + Packages map[string]*Package +} + +//Package represents a package in the system. +type Package struct { + Name string + Maintainer string + WebsiteURL string + Email string + Cores map[string]*Core // The cores in the system. + // Tools map[string]*Tool // The tools in the system. +} + +// AddPackage adds a package to a context from an indexPackage. +// +// NOTE: If the package is already in the context, it is overwritten! +func (sc *StatusContext) AddPackage(indexPackage *indexPackage) { + sc.Packages[indexPackage.Name] = indexPackage.extractPackage() +} + +// AddCore adds a core to the context. +func (pm *Package) AddCore(indexCore *indexCoreRelease) { + name := indexCore.Name + if pm.Cores[name] == nil { + pm.Cores[name] = indexCore.extractCore() + } else { + release := indexCore.extractRelease() + core := pm.Cores[name] + core.Releases[release.Version] = release + } +} + +// CoreNames returns an array with all the names of the registered cores. +func (pm *Package) CoreNames() []string { + res := make([]string, len(pm.Cores)) + i := 0 + for n := range pm.Cores { + res[i] = n + i++ + } + sortutil.CiAsc(res) + return res +} + +// CreateStatusContextFromIndex creates a status context from index data. +func CreateStatusContextFromIndex(index *Index) (*StatusContext, error) { + // Start with an empty status context + packages := StatusContext{ + Packages: make(map[string]*Package, len(index.Packages)), + } + for _, packageManager := range index.Packages { + packages.AddPackage(packageManager) + } + return &packages, nil +}