mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-20 14:54:31 +01:00
Some ArchiveExtractor bugs fixed and its code formatted
This commit is contained in:
parent
323458c8d8
commit
6b5244eafe
@ -44,6 +44,17 @@ import cc.arduino.utils.Progress;
|
|||||||
|
|
||||||
public class LibraryInstaller {
|
public class LibraryInstaller {
|
||||||
|
|
||||||
|
private static final String LIBRARY_INDEX_URL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String extenalLibraryIndexUrl = System.getProperty("LIBRARY_INDEX_URL");
|
||||||
|
if (extenalLibraryIndexUrl != null && !"".equals(extenalLibraryIndexUrl)) {
|
||||||
|
LIBRARY_INDEX_URL = extenalLibraryIndexUrl;
|
||||||
|
} else {
|
||||||
|
LIBRARY_INDEX_URL = "http://arduino.cc/download.php?f=/libraries/library_index.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private LibrariesIndexer indexer;
|
private LibrariesIndexer indexer;
|
||||||
private File stagingFolder;
|
private File stagingFolder;
|
||||||
private DownloadableContributionsDownloader downloader;
|
private DownloadableContributionsDownloader downloader;
|
||||||
@ -63,7 +74,7 @@ public class LibraryInstaller {
|
|||||||
final MultiStepProgress progress = new MultiStepProgress(2);
|
final MultiStepProgress progress = new MultiStepProgress(2);
|
||||||
|
|
||||||
// Step 1: Download index
|
// Step 1: Download index
|
||||||
URL url = new URL("http://arduino.cc/download.php?f=/libraries/library_index.json");
|
URL url = new URL(LIBRARY_INDEX_URL);
|
||||||
File outputFile = indexer.getIndexFile();
|
File outputFile = indexer.getIndexFile();
|
||||||
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
||||||
try {
|
try {
|
||||||
|
@ -44,6 +44,17 @@ import static processing.app.I18n.format;
|
|||||||
|
|
||||||
public class ContributionInstaller {
|
public class ContributionInstaller {
|
||||||
|
|
||||||
|
private static final String PACKAGE_INDEX_URL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL");
|
||||||
|
if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) {
|
||||||
|
PACKAGE_INDEX_URL = extenalPackageIndexUrl;
|
||||||
|
} else {
|
||||||
|
PACKAGE_INDEX_URL = "http://arduino.cc/download.php?f=/packages/package_index.json";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private File stagingFolder;
|
private File stagingFolder;
|
||||||
private ContributionsIndexer indexer;
|
private ContributionsIndexer indexer;
|
||||||
private DownloadableContributionsDownloader downloader;
|
private DownloadableContributionsDownloader downloader;
|
||||||
@ -172,7 +183,7 @@ public class ContributionInstaller {
|
|||||||
final MultiStepProgress progress = new MultiStepProgress(1);
|
final MultiStepProgress progress = new MultiStepProgress(1);
|
||||||
final String statusText = _("Downloading platforms index...");
|
final String statusText = _("Downloading platforms index...");
|
||||||
|
|
||||||
URL url = new URL("http://arduino.cc/download.php?f=/packages/package_index.json");
|
URL url = new URL(PACKAGE_INDEX_URL);
|
||||||
File outputFile = indexer.getIndexFile();
|
File outputFile = indexer.getIndexFile();
|
||||||
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
File tmpFile = new File(outputFile.getAbsolutePath() + ".tmp");
|
||||||
downloader.download(url, tmpFile, progress, statusText);
|
downloader.download(url, tmpFile, progress, statusText);
|
||||||
|
@ -44,7 +44,7 @@ public class LinuxFileNativeUtils {
|
|||||||
public static void link(File file, File link) throws IOException {
|
public static void link(File file, File link) throws IOException {
|
||||||
int res = libc.link(file.getAbsolutePath(), link.getAbsolutePath());
|
int res = libc.link(file.getAbsolutePath(), link.getAbsolutePath());
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
throw new IOException("Could not create hard link: " + strerror());
|
throw new IOException("Could not create hard link to " + file + " from " + link + ": " + strerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void symlink(File file, File link) throws IOException {
|
public static void symlink(File file, File link) throws IOException {
|
||||||
|
@ -28,15 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
package cc.arduino.utils;
|
package cc.arduino.utils;
|
||||||
|
|
||||||
import java.io.File;
|
import cc.arduino.os.FileNativeUtils;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||||
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||||
@ -45,7 +37,9 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
|||||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||||
|
|
||||||
import cc.arduino.os.FileNativeUtils;
|
import java.io.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class ArchiveExtractor {
|
public class ArchiveExtractor {
|
||||||
|
|
||||||
@ -57,8 +51,7 @@ public class ArchiveExtractor {
|
|||||||
* @param destFolder
|
* @param destFolder
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static void extract(File archiveFile, File destFolder)
|
public static void extract(File archiveFile, File destFolder) throws IOException {
|
||||||
throws IOException {
|
|
||||||
extract(archiveFile, destFolder, 0);
|
extract(archiveFile, destFolder, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,17 +59,13 @@ public class ArchiveExtractor {
|
|||||||
* Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive
|
* Extract <b>source</b> into <b>destFolder</b>. <b>source</b> file archive
|
||||||
* format is autodetected from file extension.
|
* format is autodetected from file extension.
|
||||||
*
|
*
|
||||||
* @param archiveFile
|
* @param archiveFile Archive file to extract
|
||||||
* Archive file to extract
|
* @param destFolder Destination folder
|
||||||
* @param destFolder
|
* @param stripPath Number of path elements to strip from the paths contained in the
|
||||||
* Destination folder
|
* archived files
|
||||||
* @param stripPath
|
|
||||||
* Number of path elements to strip from the paths contained in the
|
|
||||||
* archived files
|
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static void extract(File archiveFile, File destFolder, int stripPath)
|
public static void extract(File archiveFile, File destFolder, int stripPath) throws IOException {
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
// Folders timestamps must be set at the end of archive extraction
|
// Folders timestamps must be set at the end of archive extraction
|
||||||
// (because creating a file in a folder alters the folder's timestamp)
|
// (because creating a file in a folder alters the folder's timestamp)
|
||||||
@ -106,11 +95,17 @@ public class ArchiveExtractor {
|
|||||||
|
|
||||||
String pathPrefix = "";
|
String pathPrefix = "";
|
||||||
|
|
||||||
|
Map<File, File> hardLinks = new HashMap<File, File>();
|
||||||
|
Map<File, Integer> hardLinksMode = new HashMap<File, Integer>();
|
||||||
|
Map<File, File> symLinks = new HashMap<File, File>();
|
||||||
|
Map<File, Long> symLinksModifiedTimes = new HashMap<File, Long>();
|
||||||
|
|
||||||
// Cycle through all the archive entries
|
// Cycle through all the archive entries
|
||||||
while (true) {
|
while (true) {
|
||||||
ArchiveEntry entry = in.getNextEntry();
|
ArchiveEntry entry = in.getNextEntry();
|
||||||
if (entry == null)
|
if (entry == null) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract entry info
|
// Extract entry info
|
||||||
long size = entry.getSize();
|
long size = entry.getSize();
|
||||||
@ -127,18 +122,21 @@ public class ArchiveExtractor {
|
|||||||
// http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x
|
// http://superuser.com/questions/61185/why-do-i-get-files-like-foo-in-my-tarball-on-os-x
|
||||||
int slash = name.lastIndexOf('/');
|
int slash = name.lastIndexOf('/');
|
||||||
if (slash == -1) {
|
if (slash == -1) {
|
||||||
if (name.startsWith("._"))
|
if (name.startsWith("._")) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (name.substring(slash + 1).startsWith("._"))
|
if (name.substring(slash + 1).startsWith("._")) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip git metadata
|
// Skip git metadata
|
||||||
// http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html
|
// http://www.unix.com/unix-for-dummies-questions-and-answers/124958-file-pax_global_header-means-what.html
|
||||||
if (name.contains("pax_global_header"))
|
if (name.contains("pax_global_header")) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry instanceof TarArchiveEntry) {
|
if (entry instanceof TarArchiveEntry) {
|
||||||
TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
|
TarArchiveEntry tarEntry = (TarArchiveEntry) entry;
|
||||||
@ -154,9 +152,9 @@ public class ArchiveExtractor {
|
|||||||
int slash = 0;
|
int slash = 0;
|
||||||
while (stripPath > 0) {
|
while (stripPath > 0) {
|
||||||
slash = name.indexOf("/", slash);
|
slash = name.indexOf("/", slash);
|
||||||
if (slash == -1)
|
if (slash == -1) {
|
||||||
throw new IOException(
|
throw new IOException("Invalid archive: it must contains a single root folder");
|
||||||
"Invalid archive: it must contains a single root folder");
|
}
|
||||||
slash++;
|
slash++;
|
||||||
stripPath--;
|
stripPath--;
|
||||||
}
|
}
|
||||||
@ -164,21 +162,19 @@ public class ArchiveExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Strip the common path prefix when requested
|
// Strip the common path prefix when requested
|
||||||
if (!name.startsWith(pathPrefix))
|
if (!name.startsWith(pathPrefix)) {
|
||||||
throw new IOException(
|
throw new IOException("Invalid archive: it must contains a single root folder while file " + name + " is outside " + pathPrefix);
|
||||||
"Invalid archive: it must contains a single root folder while file "
|
}
|
||||||
+ name + " is outside " + pathPrefix);
|
|
||||||
name = name.substring(pathPrefix.length());
|
name = name.substring(pathPrefix.length());
|
||||||
if (name.isEmpty())
|
if (name.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
File outputFile = new File(destFolder, name);
|
File outputFile = new File(destFolder, name);
|
||||||
|
|
||||||
File outputLinkFile = null;
|
File outputLinkFile = null;
|
||||||
if (isLink) {
|
if (isLink) {
|
||||||
if (!linkName.startsWith(pathPrefix)) {
|
if (!linkName.startsWith(pathPrefix)) {
|
||||||
throw new IOException(
|
throw new IOException("Invalid archive: it must contains a single root folder while file " + linkName + " is outside " + pathPrefix);
|
||||||
"Invalid archive: it must contains a single root folder while file "
|
|
||||||
+ linkName + " is outside " + pathPrefix);
|
|
||||||
}
|
}
|
||||||
linkName = linkName.substring(pathPrefix.length());
|
linkName = linkName.substring(pathPrefix.length());
|
||||||
outputLinkFile = new File(destFolder, linkName);
|
outputLinkFile = new File(destFolder, linkName);
|
||||||
@ -186,52 +182,69 @@ public class ArchiveExtractor {
|
|||||||
if (isSymLink) {
|
if (isSymLink) {
|
||||||
// Symbolic links are referenced with relative paths
|
// Symbolic links are referenced with relative paths
|
||||||
outputLinkFile = new File(linkName);
|
outputLinkFile = new File(linkName);
|
||||||
if (outputLinkFile.isAbsolute())
|
if (outputLinkFile.isAbsolute()) {
|
||||||
throw new IOException(
|
throw new IOException("Invalid archive: it contains a symbolic link with absolute path '" + outputLinkFile + "'");
|
||||||
"Invalid archive: it contains a symbolic link with absolute path '"
|
}
|
||||||
+ outputLinkFile + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety check
|
// Safety check
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
if (outputFile.isFile())
|
if (outputFile.isFile()) {
|
||||||
throw new IOException("Can't create folder " + outputFile
|
throw new IOException("Can't create folder " + outputFile + ", a file with the same name exists!");
|
||||||
+ ", a file with the same name exists!");
|
}
|
||||||
} else {
|
} else {
|
||||||
// - isLink
|
// - isLink
|
||||||
// - isSymLink
|
// - isSymLink
|
||||||
// - anything else
|
// - anything else
|
||||||
if (outputFile.exists())
|
if (outputFile.exists()) {
|
||||||
throw new IOException("Can't extract file " + outputFile
|
throw new IOException("Can't extract file " + outputFile + ", file already exists!");
|
||||||
+ ", file already exists!");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the entry
|
// Extract the entry
|
||||||
if (isDirectory) {
|
if (isDirectory) {
|
||||||
if (!outputFile.exists())
|
if (!outputFile.exists() && !outputFile.mkdirs()) {
|
||||||
if (!outputFile.mkdirs())
|
throw new IOException("Could not create folder: " + outputFile);
|
||||||
throw new IOException("Could not create folder: " + outputFile);
|
}
|
||||||
foldersTimestamps.put(outputFile, modifiedTime);
|
foldersTimestamps.put(outputFile, modifiedTime);
|
||||||
} else if (isLink) {
|
} else if (isLink) {
|
||||||
FileNativeUtils.link(outputLinkFile, outputFile);
|
hardLinks.put(outputLinkFile, outputFile);
|
||||||
|
hardLinksMode.put(outputFile, mode);
|
||||||
} else if (isSymLink) {
|
} else if (isSymLink) {
|
||||||
FileNativeUtils.symlink(outputLinkFile, outputFile);
|
symLinks.put(outputLinkFile, outputFile);
|
||||||
outputFile.setLastModified(modifiedTime);
|
symLinksModifiedTimes.put(outputFile, modifiedTime);
|
||||||
} else {
|
} else {
|
||||||
// Create the containing folder if not exists
|
// Create the containing folder if not exists
|
||||||
if (!outputFile.getParentFile().isDirectory())
|
if (!outputFile.getParentFile().isDirectory()) {
|
||||||
outputFile.getParentFile().mkdirs();
|
outputFile.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
copyStreamToFile(in, size, outputFile);
|
copyStreamToFile(in, size, outputFile);
|
||||||
outputFile.setLastModified(modifiedTime);
|
outputFile.setLastModified(modifiedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set file/folder permission
|
// Set file/folder permission
|
||||||
if (mode != null && !isSymLink)
|
if (mode != null && !isSymLink && outputFile.exists()) {
|
||||||
FileNativeUtils.chmod(outputFile, mode);
|
FileNativeUtils.chmod(outputFile, mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<File, File> entry : hardLinks.entrySet()) {
|
||||||
|
FileNativeUtils.link(entry.getKey(), entry.getValue());
|
||||||
|
Integer mode = hardLinksMode.get(entry.getValue());
|
||||||
|
if (mode != null) {
|
||||||
|
FileNativeUtils.chmod(entry.getValue(), mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<File, File> entry : symLinks.entrySet()) {
|
||||||
|
FileNativeUtils.symlink(entry.getKey(), entry.getValue());
|
||||||
|
entry.getValue().setLastModified(symLinksModifiedTimes.get(entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (in != null)
|
if (in != null) {
|
||||||
in.close();
|
in.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set folders timestamps
|
// Set folders timestamps
|
||||||
@ -240,17 +253,15 @@ public class ArchiveExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyStreamToFile(InputStream in, long size,
|
private static void copyStreamToFile(InputStream in, long size, File outputFile) throws IOException {
|
||||||
File outputFile)
|
|
||||||
throws FileNotFoundException, IOException {
|
|
||||||
FileOutputStream fos = new FileOutputStream(outputFile);
|
FileOutputStream fos = new FileOutputStream(outputFile);
|
||||||
try {
|
try {
|
||||||
// if size is not available, copy until EOF...
|
// if size is not available, copy until EOF...
|
||||||
if (size == -1) {
|
if (size == -1) {
|
||||||
byte buffer[] = new byte[4096];
|
byte buffer[] = new byte[4096];
|
||||||
int l;
|
int length;
|
||||||
while ((l = in.read(buffer)) != -1) {
|
while ((length = in.read(buffer)) != -1) {
|
||||||
fos.write(buffer, 0, l);
|
fos.write(buffer, 0, length);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -258,12 +269,12 @@ public class ArchiveExtractor {
|
|||||||
// ...else copy just the needed amount of bytes
|
// ...else copy just the needed amount of bytes
|
||||||
byte buffer[] = new byte[4096];
|
byte buffer[] = new byte[4096];
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
int l = in.read(buffer);
|
int length = in.read(buffer);
|
||||||
if (l <= 0)
|
if (length <= 0) {
|
||||||
throw new IOException("Error while extracting file "
|
throw new IOException("Error while extracting file " + outputFile.getAbsolutePath());
|
||||||
+ outputFile.getAbsolutePath());
|
}
|
||||||
fos.write(buffer, 0, l);
|
fos.write(buffer, 0, length);
|
||||||
size -= l;
|
size -= length;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
fos.close();
|
fos.close();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user