diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java index b3bda52c1..3901ec46a 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java @@ -152,7 +152,7 @@ public class ContributedLibraryTableCellJPanel extends JPanel { // Library name... desc += format("{0}", name); - if (mayInstalled.isPresent() && mayInstalled.get().isReadOnly()) { + if (mayInstalled.isPresent() && mayInstalled.get().isIDEBuiltIn()) { desc += " Built-In "; } diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index 245c23461..1c2e06412 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -81,7 +81,7 @@ public class LibraryManagerUI extends InstallerJDialog mayInstalledLibrary) { - if (selectedLibrary.isReadOnly() && mayInstalledLibrary.isPresent()) { + if (mayInstalledLibrary.isPresent() && selectedLibrary.isIDEBuiltIn()) { onRemovePressed(mayInstalledLibrary.get()); } else { onInstallPressed(selectedLibrary, mayInstalledLibrary); diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index baf7ab387..cf31b3458 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -52,6 +52,7 @@ import processing.app.legacy.PApplet; import processing.app.macosx.ThinkDifferent; import processing.app.packages.LibraryList; import processing.app.packages.UserLibrary; +import processing.app.packages.UserLibraryFolder.Location; import processing.app.syntax.PdeKeywords; import processing.app.syntax.SketchTextAreaDefaultInputMap; import processing.app.tools.MenuScroller; @@ -337,8 +338,7 @@ public class Base { LibrariesIndexer indexer = new LibrariesIndexer(BaseNoGui.getSettingsFolder()); indexer.parseIndex(); - indexer.setSketchbookLibrariesFolder(BaseNoGui.getSketchbookLibrariesFolder()); - indexer.setLibrariesFolders(BaseNoGui.getLibrariesPath()); + indexer.setLibrariesFolders(BaseNoGui.getLibrariesFolders()); for (String library : parser.getLibraryToInstall().split(",")) { String[] libraryToInstallParts = library.split(":"); @@ -359,7 +359,7 @@ public class Base { } Optional mayInstalled = indexer.getIndex().getInstalled(libraryToInstallParts[0]); - if (selected.isReadOnly() && mayInstalled.isPresent()) { + if (mayInstalled.isPresent() && mayInstalled.get().isIDEBuiltIn()) { libraryInstaller.remove(mayInstalled.get(), progressListener); } else { libraryInstaller.install(selected, mayInstalled, progressListener); @@ -1148,10 +1148,6 @@ public class Base { } // Libraries can come from 4 locations: collect info about all four - File ideLibraryPath = BaseNoGui.getContentFile("libraries"); - File sketchbookLibraryPath = BaseNoGui.getSketchbookLibrariesFolder(); - File platformLibraryPath = null; - File referencedPlatformLibraryPath = null; String boardId = null; String referencedPlatformName = null; String myArch = null; @@ -1159,14 +1155,12 @@ public class Base { if (targetPlatform != null) { myArch = targetPlatform.getId(); boardId = BaseNoGui.getTargetBoard().getName(); - platformLibraryPath = new File(targetPlatform.getFolder(), "libraries"); String core = BaseNoGui.getBoardPreferences().get("build.core", "arduino"); if (core.contains(":")) { String refcore = core.split(":")[0]; TargetPlatform referencedPlatform = BaseNoGui.getTargetPlatform(refcore, myArch); if (referencedPlatform != null) { referencedPlatformName = referencedPlatform.getPreferences().get("name"); - referencedPlatformLibraryPath = new File(referencedPlatform.getFolder(), "libraries"); } } } @@ -1186,7 +1180,7 @@ public class Base { LibraryList otherLibs = new LibraryList(); for (UserLibrary lib : allLibraries) { // Get the library's location - used for sorting into categories - File libraryLocation = lib.getInstalledFolder().getParentFile(); + Location location = lib.getLocation(); // Is this library compatible? List arch = lib.getArchitectures(); boolean compatible; @@ -1196,7 +1190,7 @@ public class Base { compatible = arch.contains(myArch); } // IDE Libaries (including retired) - if (libraryLocation.equals(ideLibraryPath)) { + if (location == Location.IDE_BUILTIN) { if (compatible) { // only compatible IDE libs are shown boolean retired = false; @@ -1209,15 +1203,15 @@ public class Base { } } // Platform Libraries - } else if (libraryLocation.equals(platformLibraryPath)) { + } else if (location == Location.CORE) { // all platform libs are assumed to be compatible platformLibs.add(lib); // Referenced Platform Libraries - } else if (libraryLocation.equals(referencedPlatformLibraryPath)) { + } else if (location == Location.REFERENCED_CORE) { // all referenced platform libs are assumed to be compatible referencedPlatformLibs.add(lib); // Sketchbook Libraries (including incompatible) - } else if (libraryLocation.equals(sketchbookLibraryPath)) { + } else if (location == Location.SKETCHBOOK) { if (compatible) { // libraries promoted from sketchbook (behave as builtin) if (lib.getTypes() != null && lib.getTypes().contains("Arduino") @@ -2321,7 +2315,7 @@ public class Base { } // copy folder - File destinationFolder = new File(BaseNoGui.getSketchbookLibrariesFolder(), sourceFile.getName()); + File destinationFolder = new File(BaseNoGui.getSketchbookLibrariesFolder().folder, sourceFile.getName()); if (!destinationFolder.mkdir()) { activeEditor.statusError(I18n.format(tr("A library named {0} already exists"), sourceFile.getName())); return; diff --git a/arduino-core/src/cc/arduino/Compiler.java b/arduino-core/src/cc/arduino/Compiler.java index 464686cf9..89879ac80 100644 --- a/arduino-core/src/cc/arduino/Compiler.java +++ b/arduino-core/src/cc/arduino/Compiler.java @@ -247,7 +247,7 @@ public class Compiler implements MessageConsumer { addPathFlagIfPathExists(cmd, "-tools", installedPackagesFolder); addPathFlagIfPathExists(cmd, "-built-in-libraries", BaseNoGui.getContentFile("libraries")); - addPathFlagIfPathExists(cmd, "-libraries", BaseNoGui.getSketchbookLibrariesFolder()); + addPathFlagIfPathExists(cmd, "-libraries", BaseNoGui.getSketchbookLibrariesFolder().folder); String fqbn = Stream.of(aPackage.getId(), platform.getId(), board.getId(), boardOptions(board)).filter(s -> !s.isEmpty()).collect(Collectors.joining(":")); cmd.add("-fqbn=" + fqbn); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java index 0f6d70e9f..acffd02ef 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java @@ -85,6 +85,13 @@ public abstract class ContributedLibrary extends DownloadableContribution { installedLib = Optional.empty(); } + public boolean isIDEBuiltIn() { + if (!installedLib.isPresent()) { + return false; + } + return installedLib.get().isIDEBuiltIn(); + } + /** * Returns true if the library declares to support the specified * architecture (through the "architectures" property field). diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index cda20e814..788b2c4ac 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -39,11 +39,12 @@ import com.fasterxml.jackson.module.mrbean.MrBeanModule; import org.apache.commons.compress.utils.IOUtils; import processing.app.BaseNoGui; import processing.app.I18n; -import processing.app.helpers.FileUtils; import processing.app.helpers.filefilters.OnlyDirs; import processing.app.packages.LegacyUserLibrary; import processing.app.packages.LibraryList; import processing.app.packages.UserLibrary; +import processing.app.packages.UserLibraryFolder; +import processing.app.packages.UserLibraryFolder.Location; import java.io.File; import java.io.FileInputStream; @@ -59,10 +60,9 @@ public class LibrariesIndexer { private LibrariesIndex index; private final LibraryList installedLibraries = new LibraryList(); - private List librariesFolders; + private List librariesFolders; private final File indexFile; private final File stagingFolder; - private File sketchbookLibrariesFolder; private final List badLibNotified = new ArrayList<>(); @@ -104,12 +104,12 @@ public class LibrariesIndexer { } } - public void setLibrariesFolders(List _librariesFolders) { - librariesFolders = _librariesFolders; + public void setLibrariesFolders(List folders) { + librariesFolders = folders; rescanLibraries(); } - public List getLibrariesFolders() { + public List getLibrariesFolders() { return librariesFolders; } @@ -126,8 +126,8 @@ public class LibrariesIndexer { } // Rescan libraries - for (File folder : librariesFolders) { - scanInstalledLibraries(folder, folder.equals(sketchbookLibrariesFolder)); + for (UserLibraryFolder folderDesc : librariesFolders) { + scanInstalledLibraries(folderDesc); } installedLibraries.stream().filter(new TypePredicate("Contributed")).filter(new LibraryInstalledInsideCore()).forEach(userLibrary -> { @@ -136,46 +136,47 @@ public class LibrariesIndexer { }); } - private void scanInstalledLibraries(File folder, boolean isSketchbook) { - File list[] = folder.listFiles(OnlyDirs.ONLY_DIRS); + 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; for (File subfolder : list) { - if (!BaseNoGui.isSanitaryName(subfolder.getName())) { + String subfolderName = subfolder.getName(); + if (!BaseNoGui.isSanitaryName(subfolderName)) { // Detect whether the current folder name has already had a notification. - if (!badLibNotified.contains(subfolder.getName())) { + if (!badLibNotified.contains(subfolderName)) { - badLibNotified.add(subfolder.getName()); + badLibNotified.add(subfolderName); String mess = I18n.format(tr("The library \"{0}\" cannot be used.\n" + "Library names must contain only basic letters and numbers.\n" + "(ASCII only and no spaces, and it cannot start with a number)"), - subfolder.getName()); + subfolderName); BaseNoGui.showMessage(tr("Ignoring bad library name"), mess); } continue; } try { - scanLibrary(subfolder, isSketchbook); + 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(File folder, boolean isSketchbook) throws IOException { - boolean readOnly = !FileUtils.isSubDirectory(sketchbookLibrariesFolder, folder); + private void scanLibrary(UserLibraryFolder folderDesc) throws IOException { + boolean readOnly = (folderDesc.location == Location.SKETCHBOOK); // A library is considered "legacy" if it doesn't contains // a file called "library.properties" - File check = new File(folder, "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(folder); + LegacyUserLibrary lib = LegacyUserLibrary.create(folderDesc); String[] headers = BaseNoGui.headerListFromIncludePath(lib.getSrcFolder()); if (headers.length == 0) { throw new IOException(lib.getSrcFolder().getAbsolutePath()); @@ -185,7 +186,7 @@ public class LibrariesIndexer { } // Create a regular library - UserLibrary lib = UserLibrary.create(folder); + UserLibrary lib = UserLibrary.create(folderDesc); String[] headers = BaseNoGui.headerListFromIncludePath(lib.getSrcFolder()); if (headers.length == 0) { throw new IOException(lib.getSrcFolder().getAbsolutePath()); @@ -221,19 +222,6 @@ public class LibrariesIndexer { return stagingFolder; } - /** - * Set the sketchbook library folder.
- * New libraries will be installed here.
- * Libraries not found on this folder will be marked as read-only. - */ - public void setSketchbookLibrariesFolder(File folder) { - this.sketchbookLibrariesFolder = folder; - } - - public File getSketchbookLibrariesFolder() { - return sketchbookLibrariesFolder; - } - public File getIndexFile() { return indexFile; } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java b/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java index 22c01ae22..7699fd6fa 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java @@ -108,7 +108,7 @@ public class LibraryInstaller { // Step 2: Unpack library on the correct location progress.setStatus(I18n.format(tr("Installing library: {0}"), lib.getName())); progressListener.onProgress(progress); - File libsFolder = BaseNoGui.librariesIndexer.getSketchbookLibrariesFolder(); + File libsFolder = BaseNoGui.getSketchbookLibrariesFolder().folder; File tmpFolder = FileUtils.createTempFolder(libsFolder); try { new ArchiveExtractor(platform).extract(lib.getDownloadedFile(), tmpFolder, 1); @@ -132,7 +132,7 @@ public class LibraryInstaller { } public synchronized void remove(ContributedLibrary lib, ProgressListener progressListener) throws IOException { - if (lib.isReadOnly()) { + if (lib.isIDEBuiltIn()) { return; } diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index f27f1bd32..af23294af 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -20,7 +20,8 @@ import processing.app.helpers.filefilters.OnlyFilesWithExtension; import processing.app.legacy.PApplet; import processing.app.packages.LibraryList; import processing.app.packages.UserLibrary; - +import processing.app.packages.UserLibraryFolder; +import processing.app.packages.UserLibraryFolder.Location; import cc.arduino.files.DeleteFilesOnShutdown; import processing.app.helpers.FileUtils; @@ -87,7 +88,7 @@ public class BaseNoGui { public static Map importToLibraryTable; // XXX: Remove this field - static private List librariesFolders; + static private List librariesFolders; static UserNotifier notifier = new BasicUserNotifier(); @@ -245,7 +246,7 @@ public class BaseNoGui { return getHardwareFolder().getAbsolutePath(); } - static public List getLibrariesPath() { + static public List getLibrariesFolders() { return librariesFolders; } @@ -326,7 +327,7 @@ public class BaseNoGui { return new File(getSketchbookFolder(), "hardware"); } - static public File getSketchbookLibrariesFolder() { + static public UserLibraryFolder getSketchbookLibrariesFolder() { File libdir = new File(getSketchbookFolder(), "libraries"); if (!libdir.exists()) { FileWriter freadme = null; @@ -340,7 +341,7 @@ public class BaseNoGui { IOUtils.closeQuietly(freadme); } } - return libdir; + return new UserLibraryFolder(libdir, Location.SKETCHBOOK); } static public String getSketchbookPath() { @@ -651,7 +652,7 @@ public class BaseNoGui { librariesFolders = new ArrayList<>(); // Add IDE libraries folder - librariesFolders.add(getContentFile("libraries")); + librariesFolders.add(new UserLibraryFolder(getContentFile("libraries"), Location.IDE_BUILTIN)); TargetPlatform targetPlatform = getTargetPlatform(); if (targetPlatform != null) { @@ -663,13 +664,13 @@ public class BaseNoGui { File referencedPlatformFolder = referencedPlatform.getFolder(); // Add libraries folder for the referenced platform File folder = new File(referencedPlatformFolder, "libraries"); - librariesFolders.add(folder); + librariesFolders.add(new UserLibraryFolder(folder, Location.REFERENCED_CORE)); } } File platformFolder = targetPlatform.getFolder(); // Add libraries folder for the selected platform File folder = new File(platformFolder, "libraries"); - librariesFolders.add(folder); + librariesFolders.add(new UserLibraryFolder(folder, Location.CORE)); } // Add libraries folder for the sketchbook @@ -678,10 +679,7 @@ public class BaseNoGui { // Scan for libraries in each library folder. // Libraries located in the latest folders on the list can override // other libraries with the same name. - librariesIndexer.setSketchbookLibrariesFolder(getSketchbookLibrariesFolder()); - if (librariesIndexer.getLibrariesFolders() == null || !librariesIndexer.getLibrariesFolders().equals(librariesFolders)) { - librariesIndexer.setLibrariesFolders(librariesFolders); - } + librariesIndexer.setLibrariesFolders(librariesFolders); populateImportToLibraryTable(); } diff --git a/arduino-core/src/processing/app/packages/LegacyUserLibrary.java b/arduino-core/src/processing/app/packages/LegacyUserLibrary.java index be8b641c1..a62b942eb 100644 --- a/arduino-core/src/processing/app/packages/LegacyUserLibrary.java +++ b/arduino-core/src/processing/app/packages/LegacyUserLibrary.java @@ -28,7 +28,6 @@ */ package processing.app.packages; -import java.io.File; import java.util.Arrays; import java.util.List; @@ -36,14 +35,15 @@ public class LegacyUserLibrary extends UserLibrary { private String name; - public static LegacyUserLibrary create(File libFolder) { + public static LegacyUserLibrary create(UserLibraryFolder folderDesc) { // construct an old style library LegacyUserLibrary res = new LegacyUserLibrary(); - res.installedFolder = libFolder; + res.installedFolder = folderDesc.folder; res.layout = LibraryLayout.FLAT; - res.name = libFolder.getName(); + res.name = folderDesc.folder.getName(); res.setTypes(Arrays.asList("Contributed")); res.setCategory("Uncategorized"); + res.location = folderDesc.location; return res; } diff --git a/arduino-core/src/processing/app/packages/UserLibrary.java b/arduino-core/src/processing/app/packages/UserLibrary.java index a49837f40..dceeeb41c 100644 --- a/arduino-core/src/processing/app/packages/UserLibrary.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -32,6 +32,7 @@ import cc.arduino.Constants; import cc.arduino.contributions.VersionHelper; import cc.arduino.contributions.libraries.ContributedLibraryReference; import processing.app.helpers.PreferencesMap; +import processing.app.packages.UserLibraryFolder.Location; import java.io.File; import java.io.IOException; @@ -60,8 +61,12 @@ public class UserLibrary { private boolean onGoingDevelopment; private List includes; protected File installedFolder; + protected Location location; + + public static UserLibrary create(UserLibraryFolder libFolderDesc) throws IOException { + File libFolder = libFolderDesc.folder; + Location location = libFolderDesc.location; - public static UserLibrary create(File libFolder) throws IOException { // Parse metadata File propertiesFile = new File(libFolder, "library.properties"); PreferencesMap properties = new PreferencesMap(); @@ -161,6 +166,7 @@ public class UserLibrary { res.declaredTypes = typesList; res.onGoingDevelopment = Files.exists(Paths.get(libFolder.getAbsolutePath(), Constants.LIBRARY_DEVELOPMENT_FLAG_FILE)); res.includes = includes; + res.location = location; return res; } @@ -253,9 +259,17 @@ public class UserLibrary { return (layout == LibraryLayout.RECURSIVE); } + public Location getLocation() { + return location; + } + + public boolean isIDEBuiltIn() { + return getLocation() == Location.IDE_BUILTIN; + } + @Override public String toString() { - return name + ":" + version + " " + architectures + " " + installedFolder.getAbsolutePath(); + return name + ":" + version + " " + architectures + " " + location; } public File getInstalledFolder() { diff --git a/arduino-core/src/processing/app/packages/UserLibraryFolder.java b/arduino-core/src/processing/app/packages/UserLibraryFolder.java new file mode 100644 index 000000000..53371a213 --- /dev/null +++ b/arduino-core/src/processing/app/packages/UserLibraryFolder.java @@ -0,0 +1,49 @@ +/* + * This file is part of Arduino. + * + * Copyright 2017 Arduino AG (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.io.File; + +public class UserLibraryFolder { + + public enum Location { + SKETCHBOOK, CORE, REFERENCED_CORE, IDE_BUILTIN, + } + + public File folder; + + public Location location; + + public UserLibraryFolder(File folder, Location location) { + this.folder = folder; + this.location = location; + } + +}