mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-16 11:21:18 +03:00
Library installer UI
This commit is contained in:
committed by
Federico Fissore
parent
0b9223c158
commit
0755c7c004
@ -28,6 +28,8 @@
|
||||
*/
|
||||
package cc.arduino.libraries.contributions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class LibrariesIndex {
|
||||
@ -49,4 +51,19 @@ public abstract class LibrariesIndex {
|
||||
res += l.toString();
|
||||
return res;
|
||||
}
|
||||
|
||||
private List<String> categories = new ArrayList<String>();
|
||||
|
||||
public List<String> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
public void fillCategories() {
|
||||
categories.clear();
|
||||
for (ContributedLibrary lib : getLibraries()) {
|
||||
if (!categories.contains(lib.getCategory()))
|
||||
categories.add(lib.getCategory());
|
||||
}
|
||||
Collections.sort(categories);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import java.util.List;
|
||||
|
||||
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;
|
||||
@ -51,16 +52,23 @@ import com.fasterxml.jackson.module.mrbean.MrBeanModule;
|
||||
public class LibrariesIndexer {
|
||||
|
||||
private LibrariesIndex index;
|
||||
private LibraryList installedLibraries = new LibraryList();
|
||||
private List<File> librariesFolders;
|
||||
private File indexFile;
|
||||
private File stagingFolder;
|
||||
private File sketchbookLibrariesFolder;
|
||||
|
||||
public LibrariesIndexer(File _settingsFolder) {
|
||||
indexFile = new File(_settingsFolder, "library_index.json");
|
||||
public LibrariesIndexer(File preferencesFolder) {
|
||||
indexFile = new File(preferencesFolder, "library_index.json");
|
||||
stagingFolder = new File(preferencesFolder, "staging" + File.separator +
|
||||
"libraries");
|
||||
}
|
||||
|
||||
public void parseIndex() throws JsonParseException, IOException {
|
||||
parseIndex(indexFile);
|
||||
System.out.println(index);
|
||||
|
||||
index.fillCategories();
|
||||
// TODO: resolve libraries inner references
|
||||
}
|
||||
|
||||
@ -75,75 +83,108 @@ public class LibrariesIndexer {
|
||||
index = mapper.readValue(indexIn, LibrariesIndex.class);
|
||||
}
|
||||
|
||||
public LibraryList scanLibraries(List<File> folders) throws IOException {
|
||||
LibraryList res = new LibraryList();
|
||||
for (File folder : folders)
|
||||
res.addOrReplaceAll(scanLibraries(folder));
|
||||
return res;
|
||||
public void setLibrariesFolders(List<File> _librariesFolders)
|
||||
throws IOException {
|
||||
librariesFolders = _librariesFolders;
|
||||
rescanLibraries();
|
||||
}
|
||||
|
||||
private LibraryList scanLibraries(File folder) throws IOException {
|
||||
LibraryList res = new LibraryList();
|
||||
public void rescanLibraries() throws IOException {
|
||||
// Clear all installed flags
|
||||
installedLibraries.clear();
|
||||
for (ContributedLibrary lib : index.getLibraries())
|
||||
lib.setInstalled(false);
|
||||
|
||||
File list[] = folder.listFiles(new OnlyDirs());
|
||||
// Rescan libraries
|
||||
for (File folder : librariesFolders)
|
||||
scanInstalledLibraries(folder);
|
||||
}
|
||||
|
||||
private void scanInstalledLibraries(File folder) {
|
||||
File list[] = folder.listFiles(OnlyDirs.ONLY_DIRS);
|
||||
// if a bad folder or something like that, this might come back null
|
||||
if (list == null)
|
||||
return res;
|
||||
return;
|
||||
|
||||
for (File subfolder : list) {
|
||||
if (!BaseNoGui.isSanitaryName(subfolder.getName())) {
|
||||
String mess = I18n
|
||||
.format(_("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());
|
||||
String mess = I18n.format(_("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());
|
||||
BaseNoGui.showMessage(_("Ignoring bad library name"), mess);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
ContributedLibrary lib = scanLibrary(subfolder);
|
||||
|
||||
// (also replace previously found libs with the same name)
|
||||
if (lib != null)
|
||||
res.addOrReplace(lib);
|
||||
scanLibrary(subfolder);
|
||||
} catch (IOException e) {
|
||||
System.out.println(I18n.format(_("Invalid library found in {0}: {1}"),
|
||||
subfolder, e.getMessage()));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private ContributedLibrary scanLibrary(File subfolder) throws IOException {
|
||||
// A library is considered non-Legacy if it contains
|
||||
// a file called "library.properties"
|
||||
File check = new File(subfolder, "library.properties");
|
||||
if (!check.exists() || !check.isFile())
|
||||
return LegacyUserLibrary.create(subfolder);
|
||||
private void scanLibrary(File folder) throws IOException {
|
||||
boolean readOnly = !FileUtils
|
||||
.isSubDirectory(sketchbookLibrariesFolder, folder);
|
||||
|
||||
ContributedLibrary lib = UserLibrary.create(subfolder);
|
||||
// A library is considered "legacy" if it doesn't contains
|
||||
// a file called "library.properties"
|
||||
File check = new File(folder, "library.properties");
|
||||
if (!check.exists() || !check.isFile()) {
|
||||
|
||||
// Create a legacy library and exit
|
||||
LegacyUserLibrary lib = LegacyUserLibrary.create(folder);
|
||||
lib.setReadOnly(readOnly);
|
||||
installedLibraries.addOrReplace(lib);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a regular library
|
||||
UserLibrary lib = UserLibrary.create(folder);
|
||||
lib.setReadOnly(readOnly);
|
||||
installedLibraries.addOrReplace(lib);
|
||||
|
||||
// Check if we can find the same library in the index
|
||||
// String libName = subfolder.getName(); // XXX: lib.getName()?
|
||||
// ContributedLibrary foundLib = index.find(libName, lib.getVersion());
|
||||
// if (foundLib != null) {
|
||||
// foundLib.setInstalled(true);
|
||||
// foundLib.setInstalledFolder(subfolder);
|
||||
// return foundLib;
|
||||
// }
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws JsonParseException, IOException {
|
||||
LibrariesIndexer indexer = new LibrariesIndexer(new File(
|
||||
"/home/megabug/.arduino15"));
|
||||
indexer.parseIndex();
|
||||
LibraryList libs = indexer.scanLibraries(new File(
|
||||
"/home/megabug/sketchbook/libraries"));
|
||||
for (ContributedLibrary lib : libs) {
|
||||
System.out.println(lib);
|
||||
// and mark it as installed
|
||||
String libName = folder.getName(); // XXX: lib.getName()?
|
||||
ContributedLibrary foundLib = index.find(libName, lib.getVersion());
|
||||
if (foundLib != null) {
|
||||
foundLib.setInstalled(true);
|
||||
foundLib.setInstalledFolder(folder);
|
||||
foundLib.setReadOnly(readOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public LibrariesIndex getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public LibraryList getInstalledLibraries() {
|
||||
return installedLibraries;
|
||||
}
|
||||
|
||||
public File getStagingFolder() {
|
||||
return stagingFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sketchbook library folder. <br />
|
||||
* New libraries will be installed here. <br />
|
||||
* Libraries not found on this folder will be marked as read-only.
|
||||
*
|
||||
* @param folder
|
||||
*/
|
||||
public void setSketchbookLibrariesFolder(File folder) {
|
||||
this.sketchbookLibrariesFolder = folder;
|
||||
}
|
||||
|
||||
public File getSketchbookLibrariesFolder() {
|
||||
return sketchbookLibrariesFolder;
|
||||
}
|
||||
|
||||
public File getIndexFile() {
|
||||
return indexFile;
|
||||
}
|
||||
}
|
||||
|
@ -42,42 +42,15 @@ import java.util.Observer;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import cc.arduino.utils.ArchiveExtractor;
|
||||
import cc.arduino.utils.FileHash;
|
||||
import cc.arduino.utils.MultiStepProgress;
|
||||
import cc.arduino.utils.Progress;
|
||||
import cc.arduino.utils.network.FileDownloader;
|
||||
|
||||
public class ContributionInstaller {
|
||||
|
||||
/**
|
||||
* Listener for installation progress.
|
||||
*/
|
||||
public static interface Listener {
|
||||
/**
|
||||
* Receive the latest progress update.
|
||||
*
|
||||
* @param progress
|
||||
* Actual progress in the range 0...100
|
||||
* @param message
|
||||
* A verbose description message of the actual operation
|
||||
*/
|
||||
void onProgress(double progress, String message);
|
||||
}
|
||||
|
||||
private Listener listener = null;
|
||||
|
||||
private File stagingFolder;
|
||||
private ContributionsIndexer indexer;
|
||||
|
||||
private double progress;
|
||||
private double progressStepsDelta;
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private void updateProgress(double progress, String message) {
|
||||
if (listener != null)
|
||||
listener.onProgress(progress, message);
|
||||
}
|
||||
|
||||
public ContributionInstaller(ContributionsIndexer contributionsIndexer) {
|
||||
stagingFolder = contributionsIndexer.getStagingFolder();
|
||||
indexer = contributionsIndexer;
|
||||
@ -102,19 +75,18 @@ public class ContributionInstaller {
|
||||
}
|
||||
|
||||
// Calculate progress increases
|
||||
progress = 0.0;
|
||||
progressStepsDelta = 100.0 / (tools.size() + 1) / 2.0;
|
||||
MultiStepProgress progress = new MultiStepProgress((tools.size() + 1) * 2);
|
||||
|
||||
// Download all
|
||||
try {
|
||||
// Download platform
|
||||
download(platform, _("Downloading boards definitions."));
|
||||
download(platform, progress, _("Downloading boards definitions."));
|
||||
|
||||
// Download tools
|
||||
int i = 1;
|
||||
for (ContributedTool tool : tools) {
|
||||
String msg = format(_("Downloading tools ({0}/{1})."), i, tools.size());
|
||||
download(tool.getDownloadableContribution(), msg);
|
||||
download(tool.getDownloadableContribution(), progress, msg);
|
||||
i++;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@ -133,8 +105,9 @@ public class ContributionInstaller {
|
||||
File toolsFolder = new File(packageFolder, "tools");
|
||||
int i = 1;
|
||||
for (ContributedTool tool : platform.getResolvedTools()) {
|
||||
String msg = format(_("Installing tools ({0}/{1})..."), i, tools.size());
|
||||
updateProgress(progress, msg);
|
||||
progress.setStatus(format(_("Installing tools ({0}/{1})..."), i,
|
||||
tools.size()));
|
||||
onProgress(progress);
|
||||
i++;
|
||||
DownloadableContribution toolContrib = tool.getDownloadableContribution();
|
||||
File destFolder = new File(toolsFolder, tool.getName() + File.separator +
|
||||
@ -144,11 +117,12 @@ public class ContributionInstaller {
|
||||
ArchiveExtractor.extract(toolContrib.getDownloadedFile(), destFolder, 1);
|
||||
toolContrib.setInstalled(true);
|
||||
toolContrib.setInstalledFolder(destFolder);
|
||||
progress += progressStepsDelta;
|
||||
progress.stepDone();
|
||||
}
|
||||
|
||||
// Unpack platform on the correct location
|
||||
updateProgress(progress, _("Installing boards..."));
|
||||
progress.setStatus(_("Installing boards..."));
|
||||
onProgress(progress);
|
||||
File platformFolder = new File(packageFolder, "hardware" + File.separator +
|
||||
platform.getArchitecture());
|
||||
File destFolder = new File(platformFolder, platform.getVersion());
|
||||
@ -156,13 +130,15 @@ public class ContributionInstaller {
|
||||
ArchiveExtractor.extract(platform.getDownloadedFile(), destFolder, 1);
|
||||
platform.setInstalled(true);
|
||||
platform.setInstalledFolder(destFolder);
|
||||
progress += progressStepsDelta;
|
||||
progress.stepDone();
|
||||
|
||||
updateProgress(100.0, _("Installation completed!"));
|
||||
progress.setStatus(_("Installation completed!"));
|
||||
onProgress(progress);
|
||||
}
|
||||
|
||||
public File download(DownloadableContribution contribution,
|
||||
final String statusText) throws Exception {
|
||||
final MultiStepProgress progress, final String statusText)
|
||||
throws Exception {
|
||||
URL url = new URL(contribution.getUrl());
|
||||
String path = url.getPath();
|
||||
String fileName = path.substring(path.lastIndexOf('/') + 1);
|
||||
@ -186,18 +162,20 @@ public class ContributionInstaller {
|
||||
long total = me.getInitialSize() + me.getDownloadSize() / 1000;
|
||||
msg = format(_("Downloaded {0}kb of {1}kb."), downloaded, total);
|
||||
}
|
||||
updateProgress((int) progress + progressStepsDelta *
|
||||
me.getProgress() / 100.0, statusText + " " + msg);
|
||||
progress.setStatus(statusText + " " + msg);
|
||||
progress.setProgress(me.getProgress());
|
||||
onProgress(progress);
|
||||
}
|
||||
});
|
||||
downloader.download();
|
||||
if (!downloader.isCompleted())
|
||||
throw new Exception("Error dowloading " + url, downloader.getError());
|
||||
}
|
||||
progress += progressStepsDelta;
|
||||
progress.stepDone();
|
||||
|
||||
// Test checksum
|
||||
updateProgress(progress, _("Verifying archive integrity..."));
|
||||
progress.setStatus(_("Verifying archive integrity..."));
|
||||
onProgress(progress);
|
||||
String checksum = contribution.getChecksum();
|
||||
String algo = checksum.split(":")[0];
|
||||
if (!FileHash.hash(outputFile, algo).equals(checksum))
|
||||
@ -236,8 +214,8 @@ public class ContributionInstaller {
|
||||
}
|
||||
|
||||
public void updateIndex() throws Exception {
|
||||
final MultiStepProgress progress = new MultiStepProgress(2);
|
||||
final String statusText = _("Downloading platforms index...");
|
||||
updateProgress(0, statusText);
|
||||
|
||||
URL url = new URL("http://arduino.cc/package_index.json");
|
||||
File tmpFile = File.createTempFile("package_index", ".json");
|
||||
@ -252,13 +230,15 @@ public class ContributionInstaller {
|
||||
long total = me.getInitialSize() + me.getDownloadSize() / 1000;
|
||||
msg = format(_("Downloaded {0}kb of {1}kb."), downloaded, total);
|
||||
}
|
||||
updateProgress((int) progress + progressStepsDelta * me.getProgress() /
|
||||
100.0, statusText + " " + msg);
|
||||
progress.setStatus(statusText + " " + msg);
|
||||
progress.setProgress(me.getProgress());
|
||||
onProgress(progress);
|
||||
}
|
||||
});
|
||||
downloader.download();
|
||||
if (!downloader.isCompleted())
|
||||
throw new Exception("Error dowloading " + url, downloader.getError());
|
||||
progress.stepDone();
|
||||
|
||||
// TODO: Check downloaded index
|
||||
|
||||
@ -269,4 +249,8 @@ public class ContributionInstaller {
|
||||
if (!tmpFile.renameTo(outputFile))
|
||||
throw new Exception("An error occurred while updating platforms index!");
|
||||
}
|
||||
|
||||
protected void onProgress(Progress progress) {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,21 @@ import java.util.Comparator;
|
||||
|
||||
public class VersionComparator implements Comparator<String> {
|
||||
|
||||
// An handy pre-instatiated object
|
||||
public static final VersionComparator VERSION_COMPARATOR = new VersionComparator();
|
||||
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
// TODO: do a proper version compare
|
||||
return o1.compareTo(o2);
|
||||
public int compare(String a, String b) {
|
||||
// null is always less than any other value
|
||||
if (a == null && b == null)
|
||||
return 0;
|
||||
if (a == null)
|
||||
return -1;
|
||||
if (b == null)
|
||||
return 1;
|
||||
|
||||
// TODO: do a proper version compare. Look also http://semver.org/
|
||||
return a.compareTo(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ public class BaseNoGui {
|
||||
// maps library name to their library folder
|
||||
static private LibraryList libraries;
|
||||
|
||||
// XXX: Remove this field
|
||||
static private List<File> librariesFolders;
|
||||
|
||||
static UserNotifier notifier = new BasicUserNotifier();
|
||||
@ -410,9 +411,8 @@ public class BaseNoGui {
|
||||
}
|
||||
|
||||
static public LibraryList getUserLibs() {
|
||||
if (libraries == null)
|
||||
return new LibraryList();
|
||||
return libraries.filterLibrariesInSubfolder(getSketchbookFolder());
|
||||
LibraryList libs = BaseNoGui.librariesIndexer.getInstalledLibraries();
|
||||
return libs.filterLibrariesInSubfolder(getSketchbookFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -727,12 +727,14 @@ public class BaseNoGui {
|
||||
if (referencedPlatform != null) {
|
||||
File referencedPlatformFolder = referencedPlatform.getFolder();
|
||||
// Add libraries folder for the referenced platform
|
||||
librariesFolders.add(new File(referencedPlatformFolder, "libraries"));
|
||||
File folder = new File(referencedPlatformFolder, "libraries");
|
||||
librariesFolders.add(folder);
|
||||
}
|
||||
}
|
||||
File platformFolder = targetPlatform.getFolder();
|
||||
// Add libraries folder for the selected platform
|
||||
librariesFolders.add(new File(platformFolder, "libraries"));
|
||||
File folder = new File(platformFolder, "libraries");
|
||||
librariesFolders.add(folder);
|
||||
}
|
||||
|
||||
// Add libraries folder for the sketchbook
|
||||
@ -742,7 +744,9 @@ public class BaseNoGui {
|
||||
// Libraries located in the latest folders on the list can override
|
||||
// other libraries with the same name.
|
||||
try {
|
||||
scanAndUpdateLibraries(librariesFolders);
|
||||
BaseNoGui.librariesIndexer.setSketchbookLibrariesFolder(getSketchbookLibrariesFolder());
|
||||
BaseNoGui.librariesIndexer.setLibrariesFolders(librariesFolders);
|
||||
BaseNoGui.librariesIndexer.rescanLibraries();
|
||||
} catch (IOException e) {
|
||||
showWarning(_("Error"), _("Error loading libraries"), e);
|
||||
}
|
||||
@ -759,7 +763,7 @@ public class BaseNoGui {
|
||||
static public void populateImportToLibraryTable() {
|
||||
// Populate importToLibraryTable
|
||||
importToLibraryTable = new HashMap<String, UserLibrary>();
|
||||
for (UserLibrary lib : getLibraries()) {
|
||||
for (UserLibrary lib : librariesIndexer.getInstalledLibraries()) {
|
||||
try {
|
||||
String headers[] = headerListFromIncludePath(lib.getSrcFolder());
|
||||
for (String header : headers) {
|
||||
@ -968,14 +972,6 @@ public class BaseNoGui {
|
||||
}
|
||||
}
|
||||
|
||||
static public void scanAndUpdateLibraries(List<File> folders) throws IOException {
|
||||
libraries = scanLibraries(folders);
|
||||
}
|
||||
|
||||
static public LibraryList scanLibraries(List<File> folders) throws IOException {
|
||||
return librariesIndexer.scanLibraries(folders);
|
||||
}
|
||||
|
||||
static public void selectBoard(TargetBoard targetBoard) {
|
||||
TargetPlatform targetPlatform = targetBoard.getContainerPlatform();
|
||||
TargetPackage targetPackage = targetPlatform.getContainerPackage();
|
||||
|
@ -120,9 +120,7 @@ public class LegacyUserLibrary extends UserLibrary {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "LegacyLibrary:";
|
||||
res += " (name=" + name + ")";
|
||||
return res;
|
||||
return "LegacyLibrary:" + name + "\n";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +30,6 @@ package processing.app.packages;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import processing.app.helpers.FileUtils;
|
||||
@ -54,15 +53,14 @@ public class LibraryList extends ArrayList<UserLibrary> {
|
||||
}
|
||||
|
||||
public void addOrReplace(UserLibrary lib) {
|
||||
UserLibrary l = getByName(lib.getName());
|
||||
if (l != null)
|
||||
remove(l);
|
||||
remove(lib);
|
||||
add(lib);
|
||||
}
|
||||
|
||||
public void addOrReplaceAll(Collection<? extends UserLibrary> c) {
|
||||
for (UserLibrary l : c)
|
||||
addOrReplace(l);
|
||||
|
||||
public void remove(UserLibrary lib) {
|
||||
UserLibrary l = getByName(lib.getName());
|
||||
if (l != null)
|
||||
super.remove(l);
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
|
@ -257,15 +257,14 @@ public class UserLibrary extends ContributedLibrary {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = "Library:";
|
||||
res += " (name=" + name + ")";
|
||||
res += " (version=" + version + ")";
|
||||
res += " (author=" + author + ")";
|
||||
res += " (maintainer=" + maintainer + ")";
|
||||
res += " (sentence=" + sentence + ")";
|
||||
res += " (paragraph=" + paragraph + ")";
|
||||
res += " (url=" + website + ")";
|
||||
res += " (architectures=" + architectures + ")";
|
||||
String res = "Library: " + name + "\n";
|
||||
res += " (version=" + version + ")\n";
|
||||
res += " (author=" + author + ")\n";
|
||||
res += " (maintainer=" + maintainer + ")\n";
|
||||
res += " (sentence=" + sentence + ")\n";
|
||||
res += " (paragraph=" + paragraph + ")\n";
|
||||
res += " (url=" + website + ")\n";
|
||||
res += " (architectures=" + architectures + ")\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user