mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-17 06:52:18 +01:00
Merge branch 'master' of github.com:arduino/Arduino
This commit is contained in:
commit
bd240670ba
@ -28,9 +28,12 @@ import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import processing.app.debug.Compiler;
|
||||
import processing.app.debug.Target;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.tools.ZipDeflater;
|
||||
import processing.core.*;
|
||||
import static processing.app.I18n._;
|
||||
@ -949,9 +952,10 @@ public class Base {
|
||||
JMenuItem addLibraryMenuItem = new JMenuItem(_("Add Library..."));
|
||||
addLibraryMenuItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Base.this.handleAddZipLibrary(editor);
|
||||
Base.this.handleAddLibrary(editor);
|
||||
Base.this.onBoardOrPortChange();
|
||||
Base.this.rebuildImportMenu(Editor.importMenu, editor);
|
||||
Base.this.rebuildExamplesMenu(Editor.examplesMenu);
|
||||
}
|
||||
});
|
||||
importMenu.add(addLibraryMenuItem);
|
||||
@ -2374,24 +2378,70 @@ public class Base {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddLibrary(Editor editor) {
|
||||
JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home"));
|
||||
fileChooser.setDialogTitle(_("Select a zip file or a folder containing the library you'd like to add"));
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
fileChooser.setFileFilter(new FileNameExtensionFilter(_("ZIP files or folders"), "zip"));
|
||||
|
||||
public void handleAddZipLibrary(Editor editor) {
|
||||
String prompt = _("Select a zip file containing the library you'd like to add");
|
||||
FileDialog fd = new FileDialog(editor, prompt, FileDialog.LOAD);
|
||||
fd.setDirectory(System.getProperty("user.home"));
|
||||
fd.setVisible(true);
|
||||
Dimension preferredSize = fileChooser.getPreferredSize();
|
||||
fileChooser.setPreferredSize(new Dimension(preferredSize.width + 200, preferredSize.height + 200));
|
||||
|
||||
String directory = fd.getDirectory();
|
||||
String filename = fd.getFile();
|
||||
if (filename == null) return;
|
||||
int returnVal = fileChooser.showOpenDialog(editor);
|
||||
|
||||
if (returnVal != JFileChooser.APPROVE_OPTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
File sourceFile = fileChooser.getSelectedFile();
|
||||
File tmpFolder = null;
|
||||
|
||||
File sourceFile = new File(directory, filename);
|
||||
try {
|
||||
ZipDeflater zipDeflater = new ZipDeflater(sourceFile, getSketchbookLibrariesFolder());
|
||||
// unpack ZIP
|
||||
if (!sourceFile.isDirectory()) {
|
||||
try {
|
||||
tmpFolder = FileUtils.createTempFolder();
|
||||
ZipDeflater zipDeflater = new ZipDeflater(sourceFile, tmpFolder);
|
||||
zipDeflater.deflate();
|
||||
editor.statusNotice(_("Library added to your libraries. Check \"Import library\" menu"));
|
||||
File[] foldersInTmpFolder = tmpFolder.listFiles(new OnlyDirs());
|
||||
if (foldersInTmpFolder.length != 1) {
|
||||
throw new IOException(_("Zip doesn't contain a library"));
|
||||
}
|
||||
sourceFile = foldersInTmpFolder[0];
|
||||
} catch (IOException e) {
|
||||
editor.statusError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// is there a valid library?
|
||||
File libFolder = sourceFile;
|
||||
String libName = libFolder.getName();
|
||||
if (!Sketch.isSanitaryName(libName)) {
|
||||
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)"),
|
||||
libName);
|
||||
editor.statusError(mess);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy folder
|
||||
File destinationFolder = new File(getSketchbookLibrariesFolder(), sourceFile.getName());
|
||||
if (!destinationFolder.mkdir()) {
|
||||
editor.statusError(I18n.format(_("A library named {0} already exists"), sourceFile.getName()));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
FileUtils.copy(sourceFile, destinationFolder);
|
||||
} catch (IOException e) {
|
||||
editor.statusError(e);
|
||||
return;
|
||||
}
|
||||
editor.statusNotice(_("Library added to your libraries. Check \"Import library\" menu"));
|
||||
} finally {
|
||||
// delete zip created temp folder, if exists
|
||||
FileUtils.recursiveDelete(tmpFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// re-add the sub-menus that are shared by all windows
|
||||
fileMenu.insert(sketchbookMenu, 2);
|
||||
fileMenu.insert(examplesMenu, 3);
|
||||
//sketchMenu.insert(importMenu, 4);
|
||||
sketchMenu.insert(importMenu, 4);
|
||||
toolsMenu.insert(boardsMenu, numTools);
|
||||
toolsMenu.insert(serialMenu, numTools + 1);
|
||||
}
|
||||
@ -188,7 +188,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// System.err.println("deactivate"); // not coming through
|
||||
fileMenu.remove(sketchbookMenu);
|
||||
fileMenu.remove(examplesMenu);
|
||||
//sketchMenu.remove(importMenu);
|
||||
sketchMenu.remove(importMenu);
|
||||
toolsMenu.remove(boardsMenu);
|
||||
toolsMenu.remove(serialMenu);
|
||||
}
|
||||
|
93
app/src/processing/app/helpers/FileUtils.java
Normal file
93
app/src/processing/app/helpers/FileUtils.java
Normal file
@ -0,0 +1,93 @@
|
||||
package processing.app.helpers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
/**
|
||||
* Checks, whether the child directory is a subdirectory of the base directory.
|
||||
*
|
||||
* @param base
|
||||
* the base directory.
|
||||
* @param child
|
||||
* the suspected child directory.
|
||||
* @return true, if the child is a subdirectory of the base directory.
|
||||
*/
|
||||
public static boolean isSubDirectory(File base, File child) {
|
||||
try {
|
||||
base = base.getCanonicalFile();
|
||||
child = child.getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File parentFile = child;
|
||||
while (parentFile != null) {
|
||||
if (base.equals(parentFile)) {
|
||||
return true;
|
||||
}
|
||||
parentFile = parentFile.getParentFile();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void copy(File sourceFolder, File destFolder) throws IOException {
|
||||
for (File file : sourceFolder.listFiles()) {
|
||||
File destFile = new File(destFolder, file.getName());
|
||||
if (file.isDirectory()) {
|
||||
if (!destFile.mkdir()) {
|
||||
throw new IOException("Unable to create folder: " + destFile);
|
||||
}
|
||||
copy(file, destFile);
|
||||
} else {
|
||||
FileInputStream fis = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
fos = new FileOutputStream(destFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int readBytes = -1;
|
||||
while ((readBytes = fis.read(buf, 0, buf.length)) != -1) {
|
||||
fos.write(buf, 0, readBytes);
|
||||
}
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
fis.close();
|
||||
}
|
||||
if (fos != null) {
|
||||
fos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void recursiveDelete(File file) {
|
||||
if (file == null) {
|
||||
return;
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
for (File current : file.listFiles()) {
|
||||
if (current.isDirectory()) {
|
||||
recursiveDelete(current);
|
||||
} else {
|
||||
current.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
public static File createTempFolder() throws IOException {
|
||||
File tmpFolder = new File(System.getProperty("java.io.tmpdir"), "arduino_" + new Random().nextInt(1000000));
|
||||
if (!tmpFolder.mkdir()) {
|
||||
throw new IOException("Unable to create temp folder " + tmpFolder);
|
||||
}
|
||||
return tmpFolder;
|
||||
}
|
||||
|
||||
}
|
42
app/src/processing/app/helpers/filefilters/OnlyDirs.java
Normal file
42
app/src/processing/app/helpers/filefilters/OnlyDirs.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
OnlyDirs - FilenameFilter that accepts only directories (CVS, .svn,
|
||||
.DS_Store files are excluded as well)
|
||||
Part of the Arduino project - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2011 Cristian Maglie
|
||||
|
||||
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package processing.app.helpers.filefilters;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
|
||||
/**
|
||||
* This filter accepts only directories (excluding .DS_Store files, .svn
|
||||
* folders, etc)
|
||||
*
|
||||
* @author Cristian Maglie
|
||||
*/
|
||||
public class OnlyDirs implements FilenameFilter {
|
||||
|
||||
public boolean accept(File dir, String name) {
|
||||
if (name.charAt(0) == '.')
|
||||
return false;
|
||||
if (name.equals("CVS"))
|
||||
return false;
|
||||
return new File(dir, name).isDirectory();
|
||||
}
|
||||
}
|
@ -10,30 +10,36 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import processing.app.helpers.FileUtils;
|
||||
|
||||
public class ZipDeflater {
|
||||
|
||||
private final ZipFile zipFile;
|
||||
private final File destFolder;
|
||||
private final Random random;
|
||||
private final File file;
|
||||
|
||||
public ZipDeflater(File file, File destFolder) throws ZipException, IOException {
|
||||
this.file = file;
|
||||
this.destFolder = destFolder;
|
||||
this.zipFile = new ZipFile(file);
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
public void deflate() throws IOException {
|
||||
String folderName = tempFolderNameFromZip();
|
||||
String tmpFolderName = folderNameFromZip() + random.nextInt(1000000);
|
||||
|
||||
File folder = new File(destFolder, folderName);
|
||||
File tmpFolder = new File(destFolder, tmpFolderName);
|
||||
|
||||
if (!folder.mkdir()) {
|
||||
throw new IOException("Unable to create folder " + folderName);
|
||||
if (!tmpFolder.mkdir()) {
|
||||
throw new IOException("Unable to create folder " + tmpFolderName);
|
||||
}
|
||||
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
ensureFoldersOfEntryExist(folder, entry);
|
||||
File entryFile = new File(folder, entry.getName());
|
||||
ensureFoldersOfEntryExist(tmpFolder, entry);
|
||||
File entryFile = new File(tmpFolder, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
entryFile.mkdir();
|
||||
} else {
|
||||
@ -58,8 +64,20 @@ public class ZipDeflater {
|
||||
}
|
||||
}
|
||||
|
||||
// Test.zip may or may not contain Test folder. We use zip name to create libraries folder. Therefore, a contained Test folder is useless and must be removed
|
||||
ensureOneLevelFolder(folder);
|
||||
deleteUndesiredFoldersAndFiles(tmpFolder);
|
||||
|
||||
// Test.zip may or may not contain Test folder. If it does, we keep it. If not, we use zip name.
|
||||
ensureOneLevelFolder(tmpFolder);
|
||||
}
|
||||
|
||||
private void deleteUndesiredFoldersAndFiles(File folder) {
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.isDirectory() && "__MACOSX".equals(file.getName())) {
|
||||
FileUtils.recursiveDelete(file);
|
||||
} else if (file.getName().startsWith(".")) {
|
||||
FileUtils.recursiveDelete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureFoldersOfEntryExist(File folder, ZipEntry entry) {
|
||||
@ -73,25 +91,22 @@ public class ZipDeflater {
|
||||
|
||||
private void ensureOneLevelFolder(File folder) {
|
||||
File[] files = folder.listFiles();
|
||||
if (files.length == 1 && files[0].isDirectory()) {
|
||||
File tempFile = new File(files[0].getPath() + new Random().nextInt(1000));
|
||||
files[0].renameTo(tempFile);
|
||||
for (File file : tempFile.listFiles()) {
|
||||
file.renameTo(new File(folder, file.getName()));
|
||||
}
|
||||
tempFile.delete();
|
||||
}
|
||||
|
||||
if (files.length != 1) {
|
||||
folder.renameTo(new File(folder.getParentFile(), folderNameFromZip()));
|
||||
return;
|
||||
}
|
||||
|
||||
private String tempFolderNameFromZip() {
|
||||
String folderName = zipFile.getName();
|
||||
if (folderName.lastIndexOf(".") != -1) {
|
||||
folderName = folderName.substring(0, folderName.lastIndexOf("."));
|
||||
files[0].renameTo(new File(folder.getParentFile(), files[0].getName()));
|
||||
FileUtils.recursiveDelete(folder);
|
||||
}
|
||||
if (folderName.lastIndexOf(File.separator) != -1) {
|
||||
folderName = folderName.substring(folderName.lastIndexOf(File.separator) + 1);
|
||||
|
||||
private String folderNameFromZip() {
|
||||
String filename = file.getName();
|
||||
if (filename.lastIndexOf(".") != -1) {
|
||||
filename = filename.substring(0, filename.lastIndexOf("."));
|
||||
}
|
||||
return folderName;
|
||||
return filename;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
|
||||
ARDUINO 1.0.5 - 2013.04.08
|
||||
ARDUINO 1.0.5 - 2013.05.15
|
||||
|
||||
[core]
|
||||
|
||||
* [avr] malloc bug: backported avr-libc 1.8.0 implementation
|
||||
* [avr] removed deprecated interrupt handlers causing compiler issues
|
||||
with newer avr-gcc.
|
||||
* [avr] added c_str() method to String
|
||||
* [avr] Stream "_timeout" field and related methods are now protected
|
||||
|
||||
[libraries]
|
||||
|
||||
* Upgrades to WiFi library
|
||||
* Fixed a bunch of examples
|
||||
|
||||
[firmwares]
|
||||
|
||||
@ -17,7 +20,10 @@ ARDUINO 1.0.5 - 2013.04.08
|
||||
|
||||
[ide]
|
||||
|
||||
* Backport from 1.5: install Library from file
|
||||
* Backport from 1.5: install Library from .zip file or folder
|
||||
* Added button "Copy error to clipboard" (Paul Stoffregen)
|
||||
* Updated windows drivers
|
||||
* Added Windows installer
|
||||
|
||||
ARDUINO 1.0.4 - 2013.03.11
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user