mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 23:05:47 +02:00
Improve robustness of downloads and add license confirmation.
Bad things were happening when the downloads of the tools and sdk failed. Added retries and changed the order of the downloads so that partial downloads aren't registered as complete. Also added license confirmation dialog to make sure the user agrees to the Arduino licenses before installing the tools and sdk. Change-Id: Ie8f4fcd041d8e89195bc7d3551c63fd3270881ef
This commit is contained in:
parent
b5b941ab33
commit
063ab089db
4 changed files with 118 additions and 88 deletions
|
@ -21,7 +21,8 @@ public class ArduinoPreferences {
|
||||||
|
|
||||||
private static final String defaultHome = Paths.get(System.getProperty("user.home"), ".arduinocdt").toString(); //$NON-NLS-1$ //$NON-NLS-2$
|
private static final String defaultHome = Paths.get(System.getProperty("user.home"), ".arduinocdt").toString(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
private static final String defaultBoardUrls = "http://downloads.arduino.cc/packages/package_index.json" //$NON-NLS-1$
|
private static final String defaultBoardUrls = "http://downloads.arduino.cc/packages/package_index.json" //$NON-NLS-1$
|
||||||
+ "\nhttp://arduino.esp8266.com/stable/package_esp8266com_index.json"; //$NON-NLS-1$
|
+ "\r\nhttp://arduino.esp8266.com/stable/package_esp8266com_index.json" //$NON-NLS-1$
|
||||||
|
+ "\r\nhttps://adafruit.github.io/arduino-board-index/package_adafruit_index.json"; //$NON-NLS-1$
|
||||||
|
|
||||||
private static IEclipsePreferences getPrefs() {
|
private static IEclipsePreferences getPrefs() {
|
||||||
return InstanceScope.INSTANCE.getNode(Activator.getId());
|
return InstanceScope.INSTANCE.getNode(Activator.getId());
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
@ -68,20 +69,23 @@ public class ArduinoManager {
|
||||||
public static final String AVR_TOOLCHAIN_ID = "org.eclipse.cdt.arduino.toolChain.avr"; //$NON-NLS-1$
|
public static final String AVR_TOOLCHAIN_ID = "org.eclipse.cdt.arduino.toolChain.avr"; //$NON-NLS-1$
|
||||||
|
|
||||||
public static final String LIBRARIES_URL = "http://downloads.arduino.cc/libraries/library_index.json"; //$NON-NLS-1$
|
public static final String LIBRARIES_URL = "http://downloads.arduino.cc/libraries/library_index.json"; //$NON-NLS-1$
|
||||||
|
|
||||||
private List<PackageIndex> packageIndices;
|
private List<PackageIndex> packageIndices;
|
||||||
private LibraryIndex libraryIndex;
|
private LibraryIndex libraryIndex;
|
||||||
|
|
||||||
public void loadIndices() {
|
public void loadIndices() {
|
||||||
new Job(Messages.ArduinoBoardManager_0) {
|
new Job(Messages.ArduinoBoardManager_0) {
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
String[] boardUrls = ArduinoPreferences.getBoardUrls().split("\n"); //$NON-NLS-1$
|
synchronized (ArduinoManager.this) {
|
||||||
packageIndices = new ArrayList<>(boardUrls.length);
|
String[] boardUrls = ArduinoPreferences.getBoardUrls().split("\n"); //$NON-NLS-1$
|
||||||
for (String boardUrl : boardUrls) {
|
packageIndices = new ArrayList<>(boardUrls.length);
|
||||||
loadPackageIndex(boardUrl, true);
|
for (String boardUrl : boardUrls) {
|
||||||
}
|
loadPackageIndex(boardUrl, true);
|
||||||
|
}
|
||||||
|
|
||||||
loadLibraryIndex(true);
|
loadLibraryIndex(true);
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.schedule();
|
}.schedule();
|
||||||
}
|
}
|
||||||
|
@ -270,83 +274,93 @@ public class ArduinoManager {
|
||||||
|
|
||||||
public static IStatus downloadAndInstall(String url, String archiveFileName, Path installPath,
|
public static IStatus downloadAndInstall(String url, String archiveFileName, Path installPath,
|
||||||
IProgressMonitor monitor) {
|
IProgressMonitor monitor) {
|
||||||
try {
|
Exception error = null;
|
||||||
URL dl = new URL(url);
|
for (int retries = 3; retries > 0 && !monitor.isCanceled(); --retries) {
|
||||||
Path dlDir = ArduinoPreferences.getArduinoHome().resolve("downloads"); //$NON-NLS-1$
|
|
||||||
Files.createDirectories(dlDir);
|
|
||||||
Path archivePath = dlDir.resolve(archiveFileName);
|
|
||||||
Files.copy(dl.openStream(), archivePath, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
|
|
||||||
boolean isWin = Platform.getOS().equals(Platform.OS_WIN32);
|
|
||||||
|
|
||||||
// extract
|
|
||||||
ArchiveInputStream archiveIn = null;
|
|
||||||
try {
|
try {
|
||||||
String compressor = null;
|
URL dl = new URL(url);
|
||||||
String archiver = null;
|
Path dlDir = ArduinoPreferences.getArduinoHome().resolve("downloads"); //$NON-NLS-1$
|
||||||
if (archiveFileName.endsWith("tar.bz2")) { //$NON-NLS-1$
|
Files.createDirectories(dlDir);
|
||||||
compressor = CompressorStreamFactory.BZIP2;
|
Path archivePath = dlDir.resolve(archiveFileName);
|
||||||
archiver = ArchiveStreamFactory.TAR;
|
URLConnection conn = dl.openConnection();
|
||||||
} else if (archiveFileName.endsWith(".tar.gz") || archiveFileName.endsWith(".tgz")) { //$NON-NLS-1$ //$NON-NLS-2$
|
conn.setConnectTimeout(10000);
|
||||||
compressor = CompressorStreamFactory.GZIP;
|
conn.setReadTimeout(10000);
|
||||||
archiver = ArchiveStreamFactory.TAR;
|
Files.copy(conn.getInputStream(), archivePath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
} else if (archiveFileName.endsWith(".tar.xz")) { //$NON-NLS-1$
|
|
||||||
compressor = CompressorStreamFactory.XZ;
|
|
||||||
archiver = ArchiveStreamFactory.TAR;
|
|
||||||
} else if (archiveFileName.endsWith(".zip")) { //$NON-NLS-1$
|
|
||||||
archiver = ArchiveStreamFactory.ZIP;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream in = new BufferedInputStream(new FileInputStream(archivePath.toFile()));
|
boolean isWin = Platform.getOS().equals(Platform.OS_WIN32);
|
||||||
if (compressor != null) {
|
|
||||||
in = new CompressorStreamFactory().createCompressorInputStream(compressor, in);
|
|
||||||
}
|
|
||||||
archiveIn = new ArchiveStreamFactory().createArchiveInputStream(archiver, in);
|
|
||||||
|
|
||||||
for (ArchiveEntry entry = archiveIn.getNextEntry(); entry != null; entry = archiveIn.getNextEntry()) {
|
// extract
|
||||||
if (entry.isDirectory()) {
|
ArchiveInputStream archiveIn = null;
|
||||||
continue;
|
try {
|
||||||
|
String compressor = null;
|
||||||
|
String archiver = null;
|
||||||
|
if (archiveFileName.endsWith("tar.bz2")) { //$NON-NLS-1$
|
||||||
|
compressor = CompressorStreamFactory.BZIP2;
|
||||||
|
archiver = ArchiveStreamFactory.TAR;
|
||||||
|
} else if (archiveFileName.endsWith(".tar.gz") || archiveFileName.endsWith(".tgz")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
compressor = CompressorStreamFactory.GZIP;
|
||||||
|
archiver = ArchiveStreamFactory.TAR;
|
||||||
|
} else if (archiveFileName.endsWith(".tar.xz")) { //$NON-NLS-1$
|
||||||
|
compressor = CompressorStreamFactory.XZ;
|
||||||
|
archiver = ArchiveStreamFactory.TAR;
|
||||||
|
} else if (archiveFileName.endsWith(".zip")) { //$NON-NLS-1$
|
||||||
|
archiver = ArchiveStreamFactory.ZIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path entryPath = installPath.resolve(entry.getName());
|
InputStream in = new BufferedInputStream(new FileInputStream(archivePath.toFile()));
|
||||||
Files.createDirectories(entryPath.getParent());
|
if (compressor != null) {
|
||||||
|
in = new CompressorStreamFactory().createCompressorInputStream(compressor, in);
|
||||||
|
}
|
||||||
|
archiveIn = new ArchiveStreamFactory().createArchiveInputStream(archiver, in);
|
||||||
|
|
||||||
if (entry instanceof TarArchiveEntry) {
|
for (ArchiveEntry entry = archiveIn.getNextEntry(); entry != null; entry = archiveIn
|
||||||
TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
|
.getNextEntry()) {
|
||||||
if (tarEntry.isLink()) {
|
if (entry.isDirectory()) {
|
||||||
Path linkPath = installPath.resolve(tarEntry.getLinkName());
|
continue;
|
||||||
Files.createSymbolicLink(entryPath, entryPath.getParent().relativize(linkPath));
|
}
|
||||||
|
|
||||||
|
Path entryPath = installPath.resolve(entry.getName());
|
||||||
|
Files.createDirectories(entryPath.getParent());
|
||||||
|
|
||||||
|
if (entry instanceof TarArchiveEntry) {
|
||||||
|
TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
|
||||||
|
if (tarEntry.isLink()) {
|
||||||
|
Path linkPath = installPath.resolve(tarEntry.getLinkName());
|
||||||
|
Files.createSymbolicLink(entryPath, entryPath.getParent().relativize(linkPath));
|
||||||
|
} else {
|
||||||
|
Files.copy(archiveIn, entryPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
if (!isWin) {
|
||||||
|
int mode = tarEntry.getMode();
|
||||||
|
Files.setPosixFilePermissions(entryPath, toPerms(mode));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Files.copy(archiveIn, entryPath, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(archiveIn, entryPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
if (!isWin) {
|
}
|
||||||
int mode = tarEntry.getMode();
|
} finally {
|
||||||
Files.setPosixFilePermissions(entryPath, toPerms(mode));
|
if (archiveIn != null) {
|
||||||
}
|
archiveIn.close();
|
||||||
} else {
|
|
||||||
Files.copy(archiveIn, entryPath, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
if (archiveIn != null) {
|
|
||||||
archiveIn.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix up directory
|
// Fix up directory
|
||||||
File[] children = installPath.toFile().listFiles();
|
File[] children = installPath.toFile().listFiles();
|
||||||
if (children.length == 1 && children[0].isDirectory()) {
|
if (children.length == 1 && children[0].isDirectory()) {
|
||||||
// make that directory the install path
|
// make that directory the install path
|
||||||
Path childPath = children[0].toPath();
|
Path childPath = children[0].toPath();
|
||||||
Path tmpPath = installPath.getParent().resolve("_t"); //$NON-NLS-1$
|
Path tmpPath = installPath.getParent().resolve("_t"); //$NON-NLS-1$
|
||||||
Files.move(childPath, tmpPath);
|
Files.move(childPath, tmpPath);
|
||||||
Files.delete(installPath);
|
Files.delete(installPath);
|
||||||
Files.move(tmpPath, installPath);
|
Files.move(tmpPath, installPath);
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
} catch (IOException | CompressorException | ArchiveException e) {
|
||||||
|
error = e;
|
||||||
|
// retry
|
||||||
}
|
}
|
||||||
return Status.OK_STATUS;
|
|
||||||
} catch (IOException | CompressorException | ArchiveException e) {
|
|
||||||
return new Status(IStatus.ERROR, Activator.getId(), "Installing Platform", e);
|
|
||||||
}
|
}
|
||||||
|
// out of retries
|
||||||
|
return new Status(IStatus.ERROR, Activator.getId(), "Download failed, please try again.", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<PosixFilePermission> toPerms(int mode) {
|
private static Set<PosixFilePermission> toPerms(int mode) {
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.MultiStatus;
|
|
||||||
import org.eclipse.core.runtime.Platform;
|
import org.eclipse.core.runtime.Platform;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
@ -225,23 +224,11 @@ public class ArduinoPlatform {
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download platform archive
|
|
||||||
IStatus status = ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor);
|
|
||||||
if (!status.isOK()) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install the tools
|
// Install the tools
|
||||||
MultiStatus mstatus = null;
|
|
||||||
for (ToolDependency toolDep : toolsDependencies) {
|
for (ToolDependency toolDep : toolsDependencies) {
|
||||||
status = toolDep.install(monitor);
|
IStatus status = toolDep.install(monitor);
|
||||||
if (!status.isOK()) {
|
if (!status.isOK()) {
|
||||||
if (mstatus == null) {
|
return status;
|
||||||
mstatus = new MultiStatus(status.getPlugin(), status.getCode(), status.getMessage(),
|
|
||||||
status.getException());
|
|
||||||
} else {
|
|
||||||
mstatus.add(status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,14 +243,20 @@ public class ArduinoPlatform {
|
||||||
makePath.toFile().setExecutable(true, false);
|
makePath.toFile().setExecutable(true, false);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
mstatus.add(new Status(IStatus.ERROR, Activator.getId(), "downloading make.exe", e)); //$NON-NLS-1$
|
return new Status(IStatus.ERROR, Activator.getId(), "Download failed, please try again.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Download platform archive
|
||||||
|
IStatus status = ArduinoManager.downloadAndInstall(url, archiveFileName, getInstallPath(), monitor);
|
||||||
|
if (!status.isOK()) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// Reload the library index to pick up platform libraries
|
// Reload the library index to pick up platform libraries
|
||||||
ArduinoManager.instance.loadLibraryIndex(false);
|
ArduinoManager.instance.loadLibraryIndex(false);
|
||||||
|
|
||||||
return mstatus != null ? mstatus : Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,12 +7,15 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.arduino.ui.internal.preferences;
|
package org.eclipse.cdt.arduino.ui.internal.preferences;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences;
|
||||||
import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard;
|
import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard;
|
||||||
import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager;
|
import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager;
|
||||||
import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform;
|
import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform;
|
||||||
|
@ -23,6 +26,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.MultiStatus;
|
import org.eclipse.core.runtime.MultiStatus;
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.layout.TableColumnLayout;
|
import org.eclipse.jface.layout.TableColumnLayout;
|
||||||
import org.eclipse.jface.preference.PreferencePage;
|
import org.eclipse.jface.preference.PreferencePage;
|
||||||
import org.eclipse.jface.viewers.ColumnWeightData;
|
import org.eclipse.jface.viewers.ColumnWeightData;
|
||||||
|
@ -178,6 +182,24 @@ public class ArduinoBoardsPreferencePage extends PreferencePage implements IWork
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean performOk() {
|
public boolean performOk() {
|
||||||
|
File acceptedFile = ArduinoPreferences.getArduinoHome().resolve(".accepted").toFile(); //$NON-NLS-1$
|
||||||
|
if (!acceptedFile.exists()) {
|
||||||
|
String message = "Do you accept the licenses for the Arduino SDK and libraries? "
|
||||||
|
+ "Information on the licenses can be found at arduino.cc web site.";
|
||||||
|
MessageDialog dialog = new MessageDialog(getShell(), "Arduino License", null, message,
|
||||||
|
MessageDialog.QUESTION, new String[] { "Accept", "Decline" }, 0);
|
||||||
|
int rc = dialog.open();
|
||||||
|
if (rc == 0) {
|
||||||
|
try {
|
||||||
|
acceptedFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Activator.log(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
new Job("Installing Arduino Board Platforms") {
|
new Job("Installing Arduino Board Platforms") {
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue