1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-17 22:23:10 +03:00

Library installer UI

This commit is contained in:
Cristian Maglie
2014-05-16 01:11:47 +02:00
committed by Federico Fissore
parent 0b9223c158
commit 0755c7c004
15 changed files with 1314 additions and 166 deletions

View File

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

View File

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

View File

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

View File

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