From 56bd77928873da194329e422464a25656dd5b5f5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 5 Dec 2019 10:52:43 +0100 Subject: [PATCH] Installed libraries are now detected via GPRC calls --- app/src/processing/app/Base.java | 1 + .../DownloadableContribution.java | 2 +- .../libraries/LibrariesIndexer.java | 217 ++++++++++-------- .../app/packages/LegacyUserLibrary.java | 65 ------ .../processing/app/packages/UserLibrary.java | 90 ++++++-- 5 files changed, 190 insertions(+), 185 deletions(-) delete mode 100644 arduino-core/src/processing/app/packages/LegacyUserLibrary.java diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 675c2053d..359c74f86 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -32,6 +32,7 @@ import cc.arduino.contributions.libraries.ContributedLibraryRelease; import cc.arduino.contributions.libraries.LibrariesIndexer; import cc.arduino.contributions.libraries.LibraryInstaller; import cc.arduino.contributions.libraries.LibraryOfSameTypeComparator; +import cc.arduino.contributions.libraries.LibraryTypeComparator; import cc.arduino.contributions.libraries.ui.LibraryManagerUI; import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.packages.ContributionInstaller; diff --git a/arduino-core/src/cc/arduino/contributions/DownloadableContribution.java b/arduino-core/src/cc/arduino/contributions/DownloadableContribution.java index 87ef9cee4..dd47f76f5 100644 --- a/arduino-core/src/cc/arduino/contributions/DownloadableContribution.java +++ b/arduino-core/src/cc/arduino/contributions/DownloadableContribution.java @@ -38,7 +38,7 @@ public abstract class DownloadableContribution { public abstract String getUrl(); - public abstract String getVersion(); + public abstract String getVersion(); // TODO: Move outside of DownloadableContribution public abstract String getChecksum(); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index 83ac683b6..c9e2f90a1 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -34,18 +34,19 @@ import static processing.app.I18n.tr; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Optional; import cc.arduino.cli.ArduinoCoreInstance; +import cc.arduino.cli.commands.Lib.InstalledLibrary; +import cc.arduino.cli.commands.Lib.Library; import cc.arduino.contributions.packages.ContributedPlatform; import io.grpc.StatusException; import processing.app.BaseNoGui; -import processing.app.I18n; -import processing.app.helpers.filefilters.OnlyDirs; -import processing.app.packages.LegacyUserLibrary; +import processing.app.debug.TargetPlatform; +import processing.app.helpers.FileUtils; import processing.app.packages.LibraryList; import processing.app.packages.UserLibrary; import processing.app.packages.UserLibraryFolder; @@ -58,7 +59,6 @@ public class LibrariesIndexer { private final LibraryList installedLibraries = new LibraryList(); private List librariesFolders; - private final List badLibNotified = new ArrayList<>(); private ArduinoCoreInstance core; public LibrariesIndexer(ArduinoCoreInstance core) { @@ -100,6 +100,7 @@ public class LibrariesIndexer { // format(tr("Error parsing libraries index: {0}\nTry to open the Library Manager to update the libraries index."), // System.err.println(format(tr("Error reading libraries index: {0}"), + rescanLibraries(); } public void setLibrariesFolders(List folders) { @@ -118,18 +119,16 @@ public class LibrariesIndexer { private Comparator priorityComparator = new UserLibraryPriorityComparator( null); - public void addToInstalledLibraries(UserLibrary lib) { + public void addToInstalledLibraries(UserLibrary lib) throws IOException { UserLibrary toReplace = installedLibraries.getByName(lib.getName()); if (toReplace == null) { installedLibraries.add(lib); - return; - } - if (priorityComparator.compare(toReplace, lib) >= 0) { + } else if (priorityComparator.compare(toReplace, lib) >= 0) { // The current lib has priority, do nothing - return; + } else { + installedLibraries.remove(toReplace); + installedLibraries.add(lib); } - installedLibraries.remove(toReplace); - installedLibraries.add(lib); } public void setArchitecturePriority(String arch) { @@ -144,17 +143,109 @@ public class LibrariesIndexer { return; } - for (ContributedLibrary lib : index.getLibraries()) { - for (ContributedLibraryRelease libRelease : lib.getReleases()) { - libRelease.unsetInstalledUserLibrary(); + index.getLibraries().forEach(l -> { + l.getReleases().forEach(r -> { + r.unsetInstalledUserLibrary(); + }); + }); + + // Rescan libraries + List installedLibsMeta; + try { + installedLibsMeta = core.libraryList(true); + } catch (StatusException e) { + e.printStackTrace(); + return; + } + + File coreLibsDir = null; + File refcoreLibsDir = null; + Optional targetPlatform = BaseNoGui.getTargetPlatform(); + if (targetPlatform.isPresent()) { + String buildCore = BaseNoGui.getBoardPreferences().get("build.core", "arduino"); + if (buildCore.contains(":")) { + String referencedCore = buildCore.split(":")[0]; + Optional referencedPlatform = BaseNoGui.getTargetPlatform(referencedCore, targetPlatform.get().getId()); + if (referencedPlatform.isPresent()) { + File referencedPlatformFolder = referencedPlatform.get().getFolder(); + // Add libraries folder for the referenced platform + refcoreLibsDir = new File(referencedPlatformFolder, "libraries"); + } + } + File platformFolder = targetPlatform.get().getFolder(); + // Add libraries folder for the selected platform + coreLibsDir = new File(platformFolder, "libraries"); + } + + for (InstalledLibrary meta : installedLibsMeta) { + Library l = meta.getLibrary(); + + // Skip platform-related libraries that are not part of the currently + // selected platform/board. + if (l.getLocation().equals("platform")) { + File libDir = new File(l.getInstallDir()); + boolean isCoreLib = (coreLibsDir != null) + && FileUtils.isSubDirectory(coreLibsDir, libDir); + boolean isRefCoreLib = (refcoreLibsDir != null) // + && FileUtils.isSubDirectory(refcoreLibsDir, + libDir); + if (!isCoreLib && !isRefCoreLib) { + continue; + } + } + + UserLibrary lib = new UserLibrary( // + new File(l.getInstallDir()), // + l.getName(), // + l.getVersion(), // + l.getAuthor(), // + l.getMaintainer(), // + l.getSentence(), // + l.getParagraph(), // + l.getWebsite(), // + l.getCategory(), // + l.getLicense(), // + l.getArchitecturesList(), // + l.getLayout(), // + l.getTypesList(), // + false, // TODO: onGoingDevelopment + null, // TODO: includes + l.getLocation() // + ); + + try { + String[] headers = BaseNoGui + .headerListFromIncludePath(lib.getSrcFolder()); // TODO: Obtain from the CLI? + if (headers.length == 0) { + throw new IOException(format(tr("no headers files (.h) found in {0}"), + lib.getSrcFolder())); + } + + Location loc = lib.getLocation(); + if (loc != Location.CORE && loc != Location.REFERENCED_CORE) { + // Check if we can find the same library in the index + // and mark it as installed + index.find(lib.getName(), lib.getVersion()).ifPresent(foundLib -> { + foundLib.setInstalledUserLibrary(lib); + lib.setTypes(foundLib.getTypes()); + }); + } + + if (lib.getTypes().isEmpty() && loc == Location.SKETCHBOOK) { + lib.setTypes(lib.getDeclaredTypes()); + } + + if (lib.getTypes().isEmpty()) { + lib.setTypes(Collections.singletonList("Contributed")); + } + + addToInstalledLibraries(lib); + } catch (Exception e) { + e.printStackTrace(); } } - // Rescan libraries - for (UserLibraryFolder folderDesc : librariesFolders) { - scanInstalledLibraries(folderDesc); - } - + // TODO: Should be done on the CLI? installedLibraries.stream() // .filter(l -> l.getTypes().contains("Contributed")) // .filter(l -> l.getLocation() == Location.CORE @@ -169,85 +260,15 @@ public class LibrariesIndexer { }); } - private void scanInstalledLibraries(UserLibraryFolder folderDesc) { - File list[] = folderDesc.folder.listFiles(OnlyDirs.ONLY_DIRS); - // if a bad folder or something like that, this might come back null - if (list == null) - return; +// String mess = I18n.format( +// tr("The library \"{0}\" cannot be used.\n" +// + "Library folder names must start with a letter or number, followed by letters,\n" +// + "numbers, dashes, dots and underscores. Maximum length is 63 characters."), +// subfolderName); +// BaseNoGui.showMessage(tr("Ignoring library with bad name"), mess); - for (File subfolder : list) { - String subfolderName = subfolder.getName(); - if (!BaseNoGui.isSanitaryName(subfolderName)) { - - // Detect whether the current folder name has already had a - // notification. - if (!badLibNotified.contains(subfolderName)) { - - badLibNotified.add(subfolderName); - - String mess = I18n.format( - tr("The library \"{0}\" cannot be used.\n" - + "Library folder names must start with a letter or number, followed by letters,\n" - + "numbers, dashes, dots and underscores. Maximum length is 63 characters."), - subfolderName); - BaseNoGui.showMessage(tr("Ignoring library with bad name"), mess); - } - continue; - } - - try { - scanLibrary(new UserLibraryFolder(subfolder, folderDesc.location)); - } catch (IOException e) { - System.out.println(I18n.format(tr("Invalid library found in {0}: {1}"), - subfolder, e.getMessage())); - } - } - } - - private void scanLibrary(UserLibraryFolder folderDesc) throws IOException { - // A library is considered "legacy" if it doesn't contains - // a file called "library.properties" - File check = new File(folderDesc.folder, "library.properties"); - if (!check.exists() || !check.isFile()) { - // Create a legacy library and exit - LegacyUserLibrary lib = LegacyUserLibrary.create(folderDesc); - String[] headers = BaseNoGui - .headerListFromIncludePath(lib.getSrcFolder()); - if (headers.length == 0) { - throw new IOException(format(tr("no headers files (.h) found in {0}"), - lib.getSrcFolder())); - } - addToInstalledLibraries(lib); - return; - } - - // Create a regular library - UserLibrary lib = UserLibrary.create(folderDesc); - String[] headers = BaseNoGui.headerListFromIncludePath(lib.getSrcFolder()); - if (headers.length == 0) { - throw new IOException( - format(tr("no headers files (.h) found in {0}"), lib.getSrcFolder())); - } - addToInstalledLibraries(lib); - - Location loc = lib.getLocation(); - if (loc != Location.CORE && loc != Location.REFERENCED_CORE) { - // Check if we can find the same library in the index - // and mark it as installed - index.find(lib.getName(), lib.getVersion()).ifPresent(foundLib -> { - foundLib.setInstalledUserLibrary(lib); - lib.setTypes(foundLib.getTypes()); - }); - } - - if (lib.getTypes().isEmpty() && loc == Location.SKETCHBOOK) { - lib.setTypes(lib.getDeclaredTypes()); - } - - if (lib.getTypes().isEmpty()) { - lib.setTypes(Collections.singletonList("Contributed")); - } - } +// System.out.println(I18n.format(tr("Invalid library found in {0}: {1}"), +// subfolder, e.getMessage())); public LibrariesIndex getIndex() { return index; diff --git a/arduino-core/src/processing/app/packages/LegacyUserLibrary.java b/arduino-core/src/processing/app/packages/LegacyUserLibrary.java deleted file mode 100644 index a62b942eb..000000000 --- a/arduino-core/src/processing/app/packages/LegacyUserLibrary.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of Arduino. - * - * Copyright 2014 Arduino LLC (http://www.arduino.cc/) - * - * Arduino 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. - */ -package processing.app.packages; - -import java.util.Arrays; -import java.util.List; - -public class LegacyUserLibrary extends UserLibrary { - - private String name; - - public static LegacyUserLibrary create(UserLibraryFolder folderDesc) { - // construct an old style library - LegacyUserLibrary res = new LegacyUserLibrary(); - res.installedFolder = folderDesc.folder; - res.layout = LibraryLayout.FLAT; - res.name = folderDesc.folder.getName(); - res.setTypes(Arrays.asList("Contributed")); - res.setCategory("Uncategorized"); - res.location = folderDesc.location; - return res; - } - - @Override - public String getName() { - return name; - } - - @Override - public List getArchitectures() { - return Arrays.asList("*"); - } - - @Override - public String toString() { - return "LegacyLibrary:" + name + "\n"; - } - -} diff --git a/arduino-core/src/processing/app/packages/UserLibrary.java b/arduino-core/src/processing/app/packages/UserLibrary.java index c1a40bf2e..0eec3fbb3 100644 --- a/arduino-core/src/processing/app/packages/UserLibrary.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -70,7 +70,7 @@ public class UserLibrary { public static UserLibrary create(UserLibraryFolder libFolderDesc) throws IOException { File libFolder = libFolderDesc.folder; - Location location = libFolderDesc.location; + String location = libFolderDesc.location.toString(); // Parse metadata File propertiesFile = new File(libFolder, "library.properties"); @@ -98,15 +98,15 @@ public class UserLibrary { throw new IOException("Missing '" + p + "' from library"); // Check layout - LibraryLayout layout; + String layout; File srcFolder = new File(libFolder, "src"); if (srcFolder.exists() && srcFolder.isDirectory()) { // Layout with a single "src" folder and recursive compilation - layout = LibraryLayout.RECURSIVE; + layout = "recursive"; } else { // Layout with source code on library's root and "utility" folders - layout = LibraryLayout.FLAT; + layout = "flat"; } // Warn if root folder contains development leftovers @@ -159,26 +159,74 @@ public class UserLibrary { format(tr("Invalid version '{0}' for library in: {1}"), declaredVersion, libFolder.getAbsolutePath())); } - UserLibrary res = new UserLibrary(); - res.installedFolder = libFolder; - res.name = properties.get("name").trim(); - res.version = version.isPresent() ? version.get().toString() : declaredVersion; - res.author = properties.get("author").trim(); - res.maintainer = properties.get("maintainer").trim(); - res.sentence = properties.get("sentence").trim(); - res.paragraph = properties.get("paragraph").trim(); - res.website = properties.get("url").trim(); - res.category = category.trim(); - res.license = license.trim(); - res.architectures = archs; - res.layout = layout; - res.declaredTypes = typesList; - res.onGoingDevelopment = Files.exists(Paths.get(libFolder.getAbsolutePath(), Constants.LIBRARY_DEVELOPMENT_FLAG_FILE)); - res.includes = includes; - res.location = location; + UserLibrary res = new UserLibrary( // + libFolder, // + properties.get("name").trim(), // + version.isPresent() ? version.get().toString() : declaredVersion, // + properties.get("author").trim(), // + properties.get("maintainer").trim(), // + properties.get("sentence").trim(), // + properties.get("paragraph").trim(), // + properties.get("url").trim(), // + category.trim(), // + license.trim(), // + archs, // + layout, // + typesList, // + Files.exists(Paths.get(libFolder.getAbsolutePath(), Constants.LIBRARY_DEVELOPMENT_FLAG_FILE)), // + includes, // + location // + ); return res; } + public UserLibrary(File installedFolder, String name, String version, + String author, String maintainer, String sentence, + String paraghraph, String website, String category, + String license, Collection architectures, + String layout, Collection declaredTypes, + boolean onGoingDevelopment, Collection includes, + String location) { + this.installedFolder = installedFolder; + this.name = name; + this.version = version; + this.author = author; + this.maintainer = maintainer; + this.sentence = sentence; + this.paragraph = paraghraph; + this.website = website; + this.category = category; + this.license = license; + this.architectures = architectures; + switch (layout) { + case "recursive": + this.layout = LibraryLayout.RECURSIVE; + break; + case "flat": + this.layout = LibraryLayout.FLAT; + break; + default: + throw new IllegalArgumentException("Invalid library layout: " + layout); + } + this.declaredTypes = declaredTypes; + this.onGoingDevelopment = onGoingDevelopment; + this.includes = includes; + switch (location) { + case "ide": + this.location = Location.IDE_BUILTIN; + break; + case "sketchbook": + this.location = Location.SKETCHBOOK; + break; + case "platform": + this.location = Location.CORE; + break; + default: + throw new IllegalArgumentException( + "Invalid library location: " + location); + } + } + public String getName() { return name; }