diff --git a/app/src/cc/arduino/contributions/ContributionsSelfCheck.java b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java index 7812f62ad7f..92b7490bd22 100644 --- a/app/src/cc/arduino/contributions/ContributionsSelfCheck.java +++ b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java @@ -30,7 +30,6 @@ package cc.arduino.contributions; import cc.arduino.contributions.libraries.LibraryInstaller; -import cc.arduino.contributions.libraries.filters.UpdatableLibraryPredicate; import cc.arduino.contributions.packages.ContributionInstaller; import cc.arduino.contributions.packages.filters.UpdatablePlatformPredicate; import cc.arduino.view.NotificationPopup; @@ -130,7 +129,7 @@ static boolean checkForUpdatablePlatforms() { static boolean checkForUpdatableLibraries() { return BaseNoGui.librariesIndexer.getIndex().getLibraries().stream() - .anyMatch(new UpdatableLibraryPredicate()); + .anyMatch(r -> r.getInstalled().isPresent() && !r.getLatest().isLibraryInstalled()); } @Override diff --git a/app/src/cc/arduino/contributions/libraries/filters/UpdatableLibraryPredicate.java b/app/src/cc/arduino/contributions/libraries/filters/UpdatableLibraryPredicate.java deleted file mode 100644 index e96f1759423..00000000000 --- a/app/src/cc/arduino/contributions/libraries/filters/UpdatableLibraryPredicate.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of Arduino. - * - * Copyright 2015 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 cc.arduino.contributions.libraries.filters; - -import java.util.List; -import java.util.function.Predicate; - -import cc.arduino.contributions.VersionComparator; -import cc.arduino.contributions.libraries.ContributedLibrary; -import cc.arduino.contributions.libraries.LibrariesIndexer; -import processing.app.BaseNoGui; - -public class UpdatableLibraryPredicate implements Predicate { - - LibrariesIndexer librariesIndexer; - - public UpdatableLibraryPredicate() { - librariesIndexer = BaseNoGui.librariesIndexer; - } - - public UpdatableLibraryPredicate(LibrariesIndexer indexer) { - librariesIndexer = indexer; - } - - @Override - public boolean test(ContributedLibrary lib) { - if (!lib.isLibraryInstalled()) { - return false; - } - String libraryName = lib.getName(); - List libraries = librariesIndexer.getIndex().find(libraryName); - ContributedLibrary latest = libraries.stream().reduce(VersionComparator::max).get(); - return !latest.isLibraryInstalled(); - } -} diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java index c5c2e41751c..e8b00549ebe 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellEditor.java @@ -36,17 +36,16 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Optional; import javax.swing.JComboBox; import javax.swing.JTable; -import cc.arduino.contributions.DownloadableContributionVersionComparator; import cc.arduino.contributions.VersionComparator; import cc.arduino.contributions.libraries.ContributedLibrary; import cc.arduino.contributions.libraries.ContributedLibraryReleases; import cc.arduino.contributions.ui.InstallerTableCell; -import cc.arduino.utils.ReverseComparator; @SuppressWarnings("serial") public class ContributedLibraryTableCellEditor extends InstallerTableCell { @@ -67,12 +66,11 @@ public Component getTableCellEditorComponent(JTable table, Object value, editorCell = new ContributedLibraryTableCellJPanel(table, value, true); editorCell.installButton - .addActionListener(e -> onInstall(editorValue.getSelected(), - editorValue.getInstalled())); + .addActionListener(e -> onInstall(editorValue.getSelected())); editorCell.downgradeButton.addActionListener(e -> { JComboBox chooser = editorCell.downgradeChooser; ContributedLibrary lib = (ContributedLibrary) chooser.getSelectedItem(); - onInstall(lib, editorValue.getInstalled()); + onInstall(lib); }); editorCell.versionToInstallChooser.addActionListener(e -> { editorValue.select((ContributedLibrary) editorCell.versionToInstallChooser.getSelectedItem()); @@ -83,16 +81,16 @@ public Component getTableCellEditorComponent(JTable table, Object value, setEnabled(true); - final Optional mayInstalled = editorValue.getInstalled(); + Map releases = editorValue.getReleases(); + List notInstalled = new LinkedList<>(releases.values()); - List releases = editorValue.getReleases(); - List notInstalled = new LinkedList<>(releases); + final Optional mayInstalled = editorValue.getInstalled(); if (mayInstalled.isPresent()) { - notInstalled.remove(editorValue.getInstalled().get()); + notInstalled.remove(mayInstalled.get()); } - Collections.sort(notInstalled, new ReverseComparator<>( - new DownloadableContributionVersionComparator())); + Collections.sort(notInstalled, VersionComparator::compareTo); + Collections.reverse(notInstalled); editorCell.downgradeChooser.removeAllItems(); editorCell.downgradeChooser.addItem(tr("Select version")); @@ -100,7 +98,7 @@ public Component getTableCellEditorComponent(JTable table, Object value, final List notInstalledPrevious = new LinkedList<>(); final List notInstalledNewer = new LinkedList<>(); - notInstalled.stream().forEach(input -> { + notInstalled.forEach(input -> { if (!mayInstalled.isPresent() || VersionComparator.greaterThan(mayInstalled.get(), input)) { notInstalledPrevious.add(input); @@ -142,8 +140,7 @@ protected void onRemove(ContributedLibrary selected) { // Empty } - protected void onInstall(ContributedLibrary selected, - Optional mayInstalled) { + protected void onInstall(ContributedLibrary selected) { // Empty } diff --git a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java index 99d4b66d23e..38ca197a276 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java +++ b/app/src/cc/arduino/contributions/libraries/ui/ContributedLibraryTableCellJPanel.java @@ -23,7 +23,7 @@ import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.StyleSheet; -import cc.arduino.contributions.DownloadableContributionVersionComparator; +import cc.arduino.contributions.VersionComparator; import cc.arduino.contributions.libraries.ContributedLibrary; import cc.arduino.contributions.libraries.ContributedLibraryReleases; import cc.arduino.contributions.ui.InstallerTableCell; @@ -126,8 +126,7 @@ public ContributedLibraryTableCellJPanel(JTable parentTable, Object value, upgradable = false; } else { installable = false; - upgradable = new DownloadableContributionVersionComparator() - .compare(selected, mayInstalled.get()) > 0; + upgradable = VersionComparator.greaterThan(selected, mayInstalled.get()); } if (installable) { installButton.setText(tr("Install")); @@ -165,7 +164,7 @@ public ContributedLibraryTableCellJPanel(JTable parentTable, Object value, // ...version. if (mayInstalled.isPresent()) { - String installedVer = mayInstalled.get().getParsedVersion(); + String installedVer = mayInstalled.get().getVersion(); if (installedVer == null) { desc += " " + tr("Version unknown"); } else { diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java b/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java index ceed4562f8d..59cd793bd71 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibrariesIndexTableModel.java @@ -158,51 +158,8 @@ private boolean filterCondition(ContributedLibraryReleases lib) { return true; } - public void updateLibrary(ContributedLibrary lib) { - // Find the row interested in the change - int row = -1; - for (ContributedLibraryReleases releases : contributions) { - if (releases.shouldContain(lib)) - row = contributions.indexOf(releases); - } - - updateContributions(); - - // If the library is found in the list send update event - // or insert event on the specific row... - for (ContributedLibraryReleases releases : contributions) { - if (releases.shouldContain(lib)) { - if (row == -1) { - row = contributions.indexOf(releases); - fireTableRowsInserted(row, row); - } else { - fireTableRowsUpdated(row, row); - } - return; - } - } - // ...otherwise send a row deleted event - fireTableRowsDeleted(row, row); - } - - private List rebuildContributionsFromIndex() { - List res = new ArrayList<>(); - BaseNoGui.librariesIndexer.getIndex().getLibraries(). // - forEach(lib -> { - for (ContributedLibraryReleases contribution : res) { - if (!contribution.shouldContain(lib)) - continue; - contribution.add(lib); - return; - } - - res.add(new ContributedLibraryReleases(lib)); - }); - return res; - } - private void updateContributions() { - List all = rebuildContributionsFromIndex(); + List all = BaseNoGui.librariesIndexer.getIndex().getLibraries(); contributions.clear(); all.stream().filter(this::filterCondition).forEach(contributions::add); Collections.sort(contributions, diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index 7ff1925878c..21161f04667 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -39,7 +39,6 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import javax.swing.Box; @@ -81,12 +80,8 @@ protected TableCellRenderer createCellRenderer() { protected InstallerTableCell createCellEditor() { return new ContributedLibraryTableCellEditor() { @Override - protected void onInstall(ContributedLibrary selectedLibrary, Optional mayInstalledLibrary) { - if (mayInstalledLibrary.isPresent() && selectedLibrary.isIDEBuiltIn()) { - onRemovePressed(mayInstalledLibrary.get()); - } else { - onInstallPressed(selectedLibrary, mayInstalledLibrary); - } + protected void onInstall(ContributedLibrary selectedLibrary) { + onInstallPressed(selectedLibrary); } @Override @@ -213,12 +208,12 @@ protected void onUpdatePressed() { installerThread.start(); } - public void onInstallPressed(final ContributedLibrary lib, final Optional mayReplaced) { + public void onInstallPressed(final ContributedLibrary lib) { clearErrorMessage(); installerThread = new Thread(() -> { try { setProgressVisible(true, tr("Installing...")); - installer.install(lib, mayReplaced, this::setProgress); + installer.install(lib, this::setProgress); // TODO: Do a better job in refreshing only the needed element if (contribTable.getCellEditor() != null) { contribTable.getCellEditor().stopCellEditing(); diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 3c361538118..a432a3dfbdd 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -285,7 +285,7 @@ public Base(String[] args) throws Exception { pdeKeywords.reload(); contributionInstaller = new ContributionInstaller(BaseNoGui.getPlatform(), new GPGDetachedSignatureVerifier()); - libraryInstaller = new LibraryInstaller(BaseNoGui.getPlatform()); + libraryInstaller = new LibraryInstaller(); parser.parseArgumentsPhase2(); @@ -364,10 +364,9 @@ public Base(String[] args) throws Exception { } selected = indexer.getIndex().find(libraryToInstallParts[0], version.get().toString()); } else if (libraryToInstallParts.length == 1) { - List librariesByName = indexer.getIndex().find(libraryToInstallParts[0]); - Collections.sort(librariesByName, new DownloadableContributionVersionComparator()); - if (!librariesByName.isEmpty()) { - selected = librariesByName.get(librariesByName.size() - 1); + ContributedLibraryReleases releases = indexer.getIndex().find(libraryToInstallParts[0]); + if (releases != null) { + selected = releases.getLatest(); } } if (selected == null) { @@ -375,15 +374,7 @@ public Base(String[] args) throws Exception { System.exit(1); } - Optional mayInstalled = indexer.getIndex().getInstalled(libraryToInstallParts[0]); - if (mayInstalled.isPresent() && selected.isIDEBuiltIn()) { - System.out.println(tr(I18n - .format("Library {0} is available as built-in in the IDE.\nRemoving the other version {1} installed in the sketchbook...", - library, mayInstalled.get().getParsedVersion()))); - libraryInstaller.remove(mayInstalled.get(), progressListener); - } else { - libraryInstaller.install(selected, mayInstalled, progressListener); - } + libraryInstaller.install(selected, progressListener); } System.exit(0); diff --git a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java index e06c12710bf..144db4424ef 100644 --- a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java +++ b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java @@ -41,7 +41,7 @@ public void testUpdatableLibrary() throws Exception { ContributedLibrary sdLib = indexer.getIndex().getInstalled("SD").get(); assertTrue("SD lib is installed", sdLib.isLibraryInstalled()); - assertEquals("SD installed version", "1.1.1", sdLib.getParsedVersion()); + assertEquals("SD installed version", "1.1.1", sdLib.getVersion()); assertTrue(ContributionsSelfCheck.checkForUpdatableLibraries()); @@ -50,7 +50,7 @@ public void testUpdatableLibrary() throws Exception { sdLib = indexer.getIndex().getInstalled("SD").get(); assertTrue("SD lib is installed", sdLib.isLibraryInstalled()); - assertEquals("SD installed version", "1.2.1", sdLib.getParsedVersion()); + assertEquals("SD installed version", "1.2.1", sdLib.getVersion()); assertFalse(ContributionsSelfCheck.checkForUpdatableLibraries()); } @@ -68,7 +68,7 @@ public void testUpdatableLibraryWithBundled() throws Exception { ContributedLibrary l = indexer.getIndex().getInstalled("Bridge").get(); assertTrue("Bridge lib is installed", l.isLibraryInstalled()); - assertEquals("Bridge installed version", "1.6.3", l.getParsedVersion()); + assertEquals("Bridge installed version", "1.6.3", l.getVersion()); assertTrue(ContributionsSelfCheck.checkForUpdatableLibraries()); @@ -77,7 +77,7 @@ public void testUpdatableLibraryWithBundled() throws Exception { l = indexer.getIndex().getInstalled("Bridge").get(); assertTrue("Bridge lib is installed", l.isLibraryInstalled()); - assertEquals("Bridge installed version", "1.7.0", l.getParsedVersion()); + assertEquals("Bridge installed version", "1.7.0", l.getVersion()); assertFalse(ContributionsSelfCheck.checkForUpdatableLibraries()); } diff --git a/arduino-core/src/cc/arduino/contributions/VersionComparator.java b/arduino-core/src/cc/arduino/contributions/VersionComparator.java index af6a1fdb376..df1d4d4a12f 100644 --- a/arduino-core/src/cc/arduino/contributions/VersionComparator.java +++ b/arduino-core/src/cc/arduino/contributions/VersionComparator.java @@ -75,10 +75,10 @@ public static ContributedLibrary max(ContributedLibrary a, ContributedLibrary b) } public static boolean greaterThan(ContributedLibrary a, ContributedLibrary b) { - return greaterThan(a.getParsedVersion(), b.getParsedVersion()); + return greaterThan(a.getVersion(), b.getVersion()); } public static int compareTo(ContributedLibrary a, ContributedLibrary b) { - return compareTo(a.getParsedVersion(), b.getParsedVersion()); + return compareTo(a.getVersion(), b.getVersion()); } } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java index 3aa1198882c..69b270908e9 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibrary.java @@ -29,19 +29,19 @@ package cc.arduino.contributions.libraries; -import cc.arduino.contributions.DownloadableContribution; -import processing.app.I18n; -import processing.app.packages.UserLibrary; +import static processing.app.I18n.tr; -import java.util.Comparator; import java.util.List; import java.util.Optional; -import static processing.app.I18n.tr; +import processing.app.I18n; +import processing.app.packages.UserLibrary; -public abstract class ContributedLibrary extends DownloadableContribution { +public abstract class ContributedLibrary { - public abstract String getName(); + public String getName() { + return releases.getName(); + } public abstract String getMaintainer(); @@ -59,6 +59,8 @@ public abstract class ContributedLibrary extends DownloadableContribution { public abstract String getSentence(); + public abstract String getVersion(); + public abstract List getArchitectures(); public abstract List getTypes(); @@ -67,10 +69,10 @@ public abstract class ContributedLibrary extends DownloadableContribution { public abstract List getProvidesIncludes(); - public static final Comparator CASE_INSENSITIVE_ORDER = (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()); - private Optional installedLib = Optional.empty(); + private ContributedLibraryReleases releases; + public Optional getInstalledLibrary() { return installedLib; } @@ -123,7 +125,7 @@ public boolean supportsArchitecture(List reqArchs) { @Override public String toString() { - return I18n.format(tr("Version {0}"), getParsedVersion()); + return I18n.format(tr("Version {0}"), getVersion()); } public String info() { @@ -131,8 +133,8 @@ public String info() { res += " ContributedLibrary : " + getName() + "\n"; res += " author : " + getAuthor() + "\n"; res += " maintainer : " + getMaintainer() + "\n"; - res += " version : " + getParsedVersion() + "\n"; - res += " website : " + getUrl() + "\n"; + res += " version : " + getVersion() + "\n"; + res += " website : " + getWebsite() + "\n"; res += " category : " + getCategory() + "\n"; res += " license : " + getLicense() + "\n"; res += " descrip : " + getSentence() + "\n"; @@ -150,35 +152,14 @@ public String info() { res += " " + r; } res += "\n"; - - // DownloadableContribution - res += super.toString(); - return res; } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ContributedLibrary)) { - return false; - } - ContributedLibrary other = (ContributedLibrary) obj; - String thisVersion = getParsedVersion(); - String otherVersion = other.getParsedVersion(); - - boolean versionEquals = (thisVersion != null && otherVersion != null - && thisVersion.equals(otherVersion)); - - // Important: for legacy libs, versions are null. Two legacy libs must - // always pass this test. - if (thisVersion == null && otherVersion == null) - versionEquals = true; - - String thisName = getName(); - String otherName = other.getName(); - - boolean nameEquals = thisName == null || otherName == null || thisName.equals(otherName); + public void setReleases(ContributedLibraryReleases releases) { + this.releases = releases; + } - return versionEquals && nameEquals; + public ContributedLibraryReleases getReleases() { + return releases; } } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibraryReleases.java b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibraryReleases.java index 7a2a75a4498..e63521b4391 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibraryReleases.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/ContributedLibraryReleases.java @@ -29,56 +29,23 @@ package cc.arduino.contributions.libraries; +import java.util.Map; +import java.util.Optional; + import cc.arduino.contributions.VersionComparator; import processing.app.packages.UserLibraryFolder.Location; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; +public abstract class ContributedLibraryReleases { -public class ContributedLibraryReleases { + public abstract String getName(); + + public abstract Map getReleases(); - private List releases = new LinkedList<>(); - private List versions = new LinkedList<>(); private ContributedLibrary latest = null; private ContributedLibrary selected = null; - public ContributedLibraryReleases(ContributedLibrary library) { - add(library); - } - - public ContributedLibraryReleases(List libraries) { - libraries.forEach(this::add); - } - - public List getReleases() { - return releases; - } - - public boolean shouldContain(ContributedLibrary lib) { - if (latest == null) { - return true; - } - return lib.getName().equals(latest.getName()); - } - - public void add(ContributedLibrary library) { - if (latest == null) { - latest = library; - } - releases.add(library); - String version = library.getParsedVersion(); - if (version != null) { - versions.add(version); - } - if (VersionComparator.greaterThan(version, latest.getParsedVersion())) { - latest = library; - } - selected = latest; - } - public Optional getInstalled() { - return releases.stream() // + return getReleases().values().stream() // .filter(ContributedLibrary::isLibraryInstalled) // .reduce((x, y) -> { Location lx = x.getInstalledLibrary().get().getLocation(); @@ -91,19 +58,23 @@ public Optional getInstalled() { } public ContributedLibrary getLatest() { + if (latest == null) { + String latestVersion = getReleases().keySet().stream().reduce(VersionComparator::max).orElse(null); + latest = getReleases().get(latestVersion); + } return latest; } public ContributedLibrary getSelected() { + if (selected == null) { + selected = getLatest(); + } return selected; } public void select(ContributedLibrary lib) { - for (ContributedLibrary r : releases) { - if (r == lib) { - selected = r; - return; - } + if (getReleases().containsValue(lib)) { + selected = lib; } } } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/EmptyLibrariesIndex.java b/arduino-core/src/cc/arduino/contributions/libraries/EmptyLibrariesIndex.java index f85ab46ef3c..2b561ed2bc1 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/EmptyLibrariesIndex.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/EmptyLibrariesIndex.java @@ -34,10 +34,10 @@ public class EmptyLibrariesIndex extends LibrariesIndex { - private List list = new ArrayList<>(); + private List list = new ArrayList<>(); @Override - public List getLibraries() { + public List getLibraries() { return list; } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java index 7998525a152..2ae82f27809 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndex.java @@ -29,73 +29,74 @@ package cc.arduino.contributions.libraries; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; public abstract class LibrariesIndex { - public abstract List getLibraries(); + public abstract List getLibraries(); - public List find(final String name) { + public ContributedLibraryReleases find(final String name) { return getLibraries().stream() // - .filter(l -> name.equals(l.getName())) // - .collect(Collectors.toList()); + .filter(l -> l.getName().equals(name)) // + .findAny() // + .orElse(null); } public ContributedLibrary find(String name, String version) { - if (name == null || version == null) { + if (version == null || name == null) { return null; } - for (ContributedLibrary lib : find(name)) { - if (version.equals(lib.getParsedVersion())) { - return lib; - } + ContributedLibraryReleases releases = find(name); + if (releases == null) { + return null; } - return null; + return releases.getReleases().get(version); } @Override public String toString() { StringBuilder sb = new StringBuilder(); - for (ContributedLibrary library : getLibraries()) { + for (ContributedLibraryReleases library : getLibraries()) { sb.append(library.toString()); } return sb.toString(); } public List getCategories() { - List categories = new LinkedList<>(); - for (ContributedLibrary lib : getLibraries()) { - if (lib.getCategory() != null && !categories.contains(lib.getCategory())) { - categories.add(lib.getCategory()); - } - } + List categories = new ArrayList<>(); + getLibraries().forEach(r -> { + r.getReleases().forEach((v, lib) -> { + if (lib.getCategory() != null && !categories.contains(lib.getCategory())) { + categories.add(lib.getCategory()); + } + }); + }); Collections.sort(categories); - return categories; } public List getTypes() { Collection typesAccumulator = new HashSet<>(); - for (ContributedLibrary lib : getLibraries()) { - if (lib.getTypes() != null) { - typesAccumulator.addAll(lib.getTypes()); - } - } + getLibraries().forEach(r -> { + r.getReleases().forEach((v, lib) -> { + if (lib.getTypes() != null) { + typesAccumulator.addAll(lib.getTypes()); + } + }); + }); - List types = new LinkedList<>(typesAccumulator); + List types = new ArrayList<>(typesAccumulator); Collections.sort(types); return types; } public Optional getInstalled(String name) { - ContributedLibraryReleases rel = new ContributedLibraryReleases(find(name)); - return rel.getInstalled(); + return find(name).getInstalled(); } } diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index c43a4a09423..897b9480444 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -29,17 +29,31 @@ package cc.arduino.contributions.libraries; -import cc.arduino.Constants; -import cc.arduino.contributions.packages.ContributedPlatform; +import static processing.app.I18n.format; +import static processing.app.I18n.tr; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.compress.utils.IOUtils; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.module.mrbean.MrBeanModule; -import org.apache.commons.compress.utils.IOUtils; + +import cc.arduino.Constants; +import cc.arduino.contributions.packages.ContributedPlatform; import processing.app.BaseNoGui; import processing.app.I18n; +import processing.app.helpers.ProcessUtils; import processing.app.helpers.filefilters.OnlyDirs; import processing.app.packages.LegacyUserLibrary; import processing.app.packages.LibraryList; @@ -48,62 +62,50 @@ import processing.app.packages.UserLibraryFolder.Location; import processing.app.packages.UserLibraryPriorityComparator; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import static processing.app.I18n.format; -import static processing.app.I18n.tr; - public class LibrariesIndexer { private LibrariesIndex index; private final LibraryList installedLibraries = new LibraryList(); private List librariesFolders; - private final File indexFile; - private final File stagingFolder; private final List badLibNotified = new ArrayList<>(); public LibrariesIndexer(File preferencesFolder) { - indexFile = new File(preferencesFolder, "library_index.json"); - stagingFolder = new File(new File(preferencesFolder, "staging"), "libraries"); + // TODO: use specified preferencesFolder when running cli } public void parseIndex() throws IOException { index = new EmptyLibrariesIndex(); // Fallback - if (!indexFile.exists()) { - return; - } - - parseIndex(indexFile); + Process process = ProcessUtils.exec(new String[] { + BaseNoGui.getArduinoCliPath(), "lib", "search", "--format", "json" }); - // TODO: resolve libraries inner references - } - - private void parseIndex(File file) throws IOException { InputStream indexIn = null; try { - indexIn = new FileInputStream(file); + indexIn = process.getInputStream(); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new MrBeanModule()); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); mapper.configure(DeserializationFeature.EAGER_DESERIALIZER_FETCH, true); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); LibrariesIndex newIndex = mapper.readValue(indexIn, LibrariesIndex.class); - newIndex.getLibraries() - .stream() + newIndex.getLibraries().forEach(r -> { + r.getReleases().values().stream() .filter(library -> library.getCategory() == null || "".equals(library.getCategory()) || !Constants.LIBRARY_CATEGORIES.contains(library.getCategory())) .forEach(library -> library.setCategory("Uncategorized")); + }); + // Populate ContributedLibraries inner cross-references + newIndex.getLibraries().forEach(r -> { + r.getReleases().forEach((v, l) -> { + l.setReleases(r); + }); + }); index = newIndex; + } catch (NullPointerException e) { + e.printStackTrace(); } catch (JsonParseException | JsonMappingException e) { System.err.println( format(tr("Error parsing libraries index: {0}\nTry to open the Library Manager to update the libraries index."), @@ -152,9 +154,9 @@ public void rescanLibraries() { return; } - for (ContributedLibrary lib : index.getLibraries()) { - lib.unsetInstalledUserLibrary(); - } + index.getLibraries().forEach(r -> { + r.getReleases().forEach((v, lib) -> lib.unsetInstalledUserLibrary()); + }); // Rescan libraries for (UserLibraryFolder folderDesc : librariesFolders) { @@ -255,12 +257,4 @@ public LibrariesIndex getIndex() { public LibraryList getInstalledLibraries() { return new LibraryList(installedLibraries); } - - public File getStagingFolder() { - return stagingFolder; - } - - 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 4b4fb7f7dbb..ad3508ab9bf 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibraryInstaller.java @@ -29,55 +29,32 @@ package cc.arduino.contributions.libraries; -import cc.arduino.Constants; -import cc.arduino.contributions.DownloadableContributionsDownloader; -import cc.arduino.contributions.GZippedJsonDownloader; +import static processing.app.I18n.tr; + +import java.util.Optional; + import cc.arduino.contributions.ProgressListener; -import cc.arduino.utils.ArchiveExtractor; import cc.arduino.utils.MultiStepProgress; import processing.app.BaseNoGui; import processing.app.I18n; -import processing.app.Platform; -import processing.app.helpers.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.Optional; - -import static processing.app.I18n.tr; +import processing.app.helpers.ProcessUtils; public class LibraryInstaller { - private final Platform platform; - - public LibraryInstaller(Platform platform) { - this.platform = platform; - } - public synchronized void updateIndex(ProgressListener progressListener) throws Exception { final MultiStepProgress progress = new MultiStepProgress(3); - DownloadableContributionsDownloader downloader = new DownloadableContributionsDownloader(BaseNoGui.librariesIndexer.getStagingFolder()); - // Step 1: Download index - File outputFile = BaseNoGui.librariesIndexer.getIndexFile(); - File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp"); - try { - GZippedJsonDownloader gZippedJsonDownloader = new GZippedJsonDownloader(downloader, new URL(Constants.LIBRARY_INDEX_URL), new URL(Constants.LIBRARY_INDEX_URL_GZ)); - gZippedJsonDownloader.download(tmpFile, progress, tr("Downloading libraries index..."), progressListener); - } catch (InterruptedException e) { - // Download interrupted... just exit - return; - } + progress.setStatus(tr("Updating library index")); progress.stepDone(); + progressListener.onProgress(progress); - // TODO: Check downloaded index - - // Replace old index with the updated one - if (outputFile.exists()) - outputFile.delete(); - if (!tmpFile.renameTo(outputFile)) + Process pr = ProcessUtils.exec(new String[] { // + BaseNoGui.getArduinoCliPath(), "lib", "update-index" }); + int exitCode = pr.waitFor(); + if (exitCode != 0) { throw new Exception(tr("An error occurred while updating libraries index!")); + } + progress.stepDone(); // Step 2: Parse index BaseNoGui.librariesIndexer.parseIndex(); @@ -86,65 +63,55 @@ public synchronized void updateIndex(ProgressListener progressListener) throws E rescanLibraryIndex(progress, progressListener); } - public synchronized void install(ContributedLibrary lib, Optional mayReplacedLib, ProgressListener progressListener) throws Exception { + public synchronized void install(ContributedLibrary lib, ProgressListener progressListener) throws Exception { + if (lib.isIDEBuiltIn()) { + // If the desired library is available as builtin in the IDE just remove + // the other installed in sketchbook... + Optional current = lib.getReleases().getInstalled(); + if (current.isPresent()) { + System.out.println( + I18n.format(tr("Library {0} is available as built-in in the IDE.\nRemoving the other version {1} installed in the sketchbook..."), + lib.getName() + ":" + lib.getVersion(), current.get().getVersion())); + remove(current.get(), progressListener); + return; + } + // ...otherwise output "library already installed" + } + if (lib.isLibraryInstalled()) { - System.out.println(I18n.format(tr("Library is already installed: {0}:{1}"), lib.getName(), lib.getParsedVersion())); + System.out.println(I18n.format(tr("Library is already installed: {0}:{1}"), lib.getName(), lib.getVersion())); return; } - DownloadableContributionsDownloader downloader = new DownloadableContributionsDownloader(BaseNoGui.librariesIndexer.getStagingFolder()); - final MultiStepProgress progress = new MultiStepProgress(3); // Step 1: Download library - try { - downloader.download(lib, progress, I18n.format(tr("Downloading library: {0}"), lib.getName()), progressListener); - } catch (InterruptedException e) { - // Download interrupted... just exit - return; + String libTag = lib.getName() + "@" + lib.getVersion(); + Process pr = ProcessUtils.exec(new String[] { // + BaseNoGui.getArduinoCliPath(), "lib", "install", libTag }); + int exitCode = pr.waitFor(); + if (exitCode != 0) { + throw new Exception(tr("An error occurred while installing library!")); } - // TODO: Extract to temporary folders and move to the final destination only - // once everything is successfully unpacked. If the operation fails remove - // all the temporary folders and abort installation. - // Step 2: Unpack library on the correct location - progress.setStatus(I18n.format(tr("Installing library: {0}:{1}"), lib.getName(), lib.getParsedVersion())); - progressListener.onProgress(progress); - File libsFolder = BaseNoGui.getSketchbookLibrariesFolder().folder; - File tmpFolder = FileUtils.createTempFolder(libsFolder); - try { - new ArchiveExtractor(platform).extract(lib.getDownloadedFile(), tmpFolder, 1); - } catch (Exception e) { - if (tmpFolder.exists()) - FileUtils.recursiveDelete(tmpFolder); - } - progress.stepDone(); - - // Step 3: Remove replaced library and move installed one to the correct location - // TODO: Fix progress bar... - if (mayReplacedLib.isPresent()) { - remove(mayReplacedLib.get(), progressListener); - } - File destFolder = new File(libsFolder, lib.getName().replaceAll(" ", "_")); - tmpFolder.renameTo(destFolder); progress.stepDone(); - // Step 4: Rescan index + // Step 3: Rescan index rescanLibraryIndex(progress, progressListener); } - public synchronized void remove(ContributedLibrary lib, ProgressListener progressListener) throws IOException { - if (lib.isIDEBuiltIn()) { - return; - } - + public synchronized void remove(ContributedLibrary lib, ProgressListener progressListener) throws Exception { final MultiStepProgress progress = new MultiStepProgress(2); // Step 1: Remove library - progress.setStatus(I18n.format(tr("Removing library: {0}:{1}"), lib.getName(), lib.getParsedVersion())); - progressListener.onProgress(progress); - FileUtils.recursiveDelete(lib.getInstalledLibrary().get().getInstalledFolder()); + String libTag = lib.getName() + "@" + lib.getVersion(); + Process pr = ProcessUtils.exec(new String[] { // + BaseNoGui.getArduinoCliPath(), "lib", "uninstall", libTag }); + int exitCode = pr.waitFor(); + if (exitCode != 0) { + throw new Exception(tr("An error occurred while uninstalling library!")); + } progress.stepDone(); // Step 2: Rescan index @@ -157,4 +124,11 @@ private void rescanLibraryIndex(MultiStepProgress progress, ProgressListener pro BaseNoGui.librariesIndexer.rescanLibraries(); progress.stepDone(); } + + // TODO: legacy messages already translated, keeping here until reused + static { + I18n.format(tr("Downloading library: {0}"), "libname"); + I18n.format(tr("Installing library: {0}:{1}"), "libname", "libversion"); + I18n.format(tr("Removing library: {0}:{1}"), "libname", "libversion"); + } } diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index 7ab457dcf1b..5b5f393ef4d 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -205,6 +205,10 @@ static public File getContentFile(String name) { return new File(installationFolder, name); } + static public String getArduinoCliPath() { + return getContentFile("arduino-cli").getAbsolutePath(); + } + static public TargetPlatform getCurrentTargetPlatformFromPackage(String pack) { return getTargetPlatform(pack, PreferencesData.get("target_platform")); } @@ -501,8 +505,7 @@ static public void initPackages() throws Exception { try { librariesIndexer.parseIndex(); } catch (JsonProcessingException e) { - File librariesIndexFile = librariesIndexer.getIndexFile(); - FileUtils.deleteIfExists(librariesIndexFile); + e.printStackTrace(); } if (discoveryManager == null) { diff --git a/build/arduino-cli-0.3.4-alpha.preview-linux32.tar.bz2.sha b/build/arduino-cli-0.3.4-alpha.preview-linux32.tar.bz2.sha new file mode 100644 index 00000000000..d1c9006cd5e --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-linux32.tar.bz2.sha @@ -0,0 +1 @@ +18f6669f8a3c328f6a096eb6709a2c1e4c9cdeae diff --git a/build/arduino-cli-0.3.4-alpha.preview-linux64.tar.bz2.sha b/build/arduino-cli-0.3.4-alpha.preview-linux64.tar.bz2.sha new file mode 100644 index 00000000000..44b29c7491d --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-linux64.tar.bz2.sha @@ -0,0 +1 @@ +1309e3bf1685ec5cefbb46cb6397e7c452ac293a diff --git a/build/arduino-cli-0.3.4-alpha.preview-linuxaarch64.tar.bz2.sha b/build/arduino-cli-0.3.4-alpha.preview-linuxaarch64.tar.bz2.sha new file mode 100644 index 00000000000..461d58a95c0 --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-linuxaarch64.tar.bz2.sha @@ -0,0 +1 @@ +2fd4bd6f4c196e45fa08bb1b6eae27494378708a diff --git a/build/arduino-cli-0.3.4-alpha.preview-linuxarm.tar.bz2.sha b/build/arduino-cli-0.3.4-alpha.preview-linuxarm.tar.bz2.sha new file mode 100644 index 00000000000..52bc08c06d6 --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-linuxarm.tar.bz2.sha @@ -0,0 +1 @@ +a4977a3dffb2268eee3328bfa362aa31e8bfbbe9 diff --git a/build/arduino-cli-0.3.4-alpha.preview-macosx.tar.bz2.sha b/build/arduino-cli-0.3.4-alpha.preview-macosx.tar.bz2.sha new file mode 100644 index 00000000000..d1004f25ae4 --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-macosx.tar.bz2.sha @@ -0,0 +1 @@ +47f1beae490e214d2cbde36089fe45e91cc4bd21 diff --git a/build/arduino-cli-0.3.4-alpha.preview-windows.zip.sha b/build/arduino-cli-0.3.4-alpha.preview-windows.zip.sha new file mode 100644 index 00000000000..01eacd79bf1 --- /dev/null +++ b/build/arduino-cli-0.3.4-alpha.preview-windows.zip.sha @@ -0,0 +1 @@ +30d454fb2d76bf08dd40f61414b809f3538a8d31 diff --git a/build/build.xml b/build/build.xml index 584bad0046f..b957f90d394 100644 --- a/build/build.xml +++ b/build/build.xml @@ -100,6 +100,7 @@ + @@ -487,6 +488,7 @@ + @@ -709,6 +711,7 @@ + @@ -751,6 +754,7 @@ + @@ -769,6 +773,7 @@ + @@ -787,6 +792,7 @@ + @@ -835,6 +841,20 @@ + + + + + + + + + + + + + + @@ -1087,6 +1107,20 @@ + + + + + + + + + + + + + +