1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-07 01:54:26 +01:00

Installed libraries are now detected via GPRC calls

This commit is contained in:
Cristian Maglie 2019-12-05 10:52:43 +01:00
parent 7da6bd91aa
commit 56bd779288
5 changed files with 190 additions and 185 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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<UserLibraryFolder> librariesFolders;
private final List<String> 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<UserLibraryFolder> folders) {
@ -118,18 +119,16 @@ public class LibrariesIndexer {
private Comparator<UserLibrary> 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<InstalledLibrary> installedLibsMeta;
try {
installedLibsMeta = core.libraryList(true);
} catch (StatusException e) {
e.printStackTrace();
return;
}
File coreLibsDir = null;
File refcoreLibsDir = null;
Optional<TargetPlatform> targetPlatform = BaseNoGui.getTargetPlatform();
if (targetPlatform.isPresent()) {
String buildCore = BaseNoGui.getBoardPreferences().get("build.core", "arduino");
if (buildCore.contains(":")) {
String referencedCore = buildCore.split(":")[0];
Optional<TargetPlatform> 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;

View File

@ -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<String> getArchitectures() {
return Arrays.asList("*");
}
@Override
public String toString() {
return "LegacyLibrary:" + name + "\n";
}
}

View File

@ -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<String> architectures,
String layout, Collection<String> declaredTypes,
boolean onGoingDevelopment, Collection<String> 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;
}