am 630f7df1: Merge change 4575 into donut
Merge commit '630f7df118eb813891752821c239f853ff540a4f' * commit '630f7df118eb813891752821c239f853ff540a4f': SDK Updater: Better guess for the addon folder name.
This commit is contained in:
committed by
The Android Open Source Project
commit
74f4ae3861
@@ -182,26 +182,47 @@ public class AddonPackage extends Package {
|
||||
* has this add-ons installed, we'll use that one.
|
||||
*
|
||||
* @param osSdkRoot The OS path of the SDK root folder.
|
||||
* @param suggestedDir A suggestion for the installation folder name, based on the root
|
||||
* folder used in the zip archive.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return A new {@link File} corresponding to the directory to use to install this package.
|
||||
*/
|
||||
@Override
|
||||
public File getInstallFolder(String osSdkRoot) {
|
||||
public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
|
||||
File addons = new File(osSdkRoot, SdkConstants.FD_ADDONS);
|
||||
|
||||
String name = String.format("%s-%d", getName(), getApiLevel()); // $NON-NLS-1$
|
||||
// First find if this add-on is already installed. If so, reuse the same directory.
|
||||
for (IAndroidTarget target : sdkManager.getTargets()) {
|
||||
if (!target.isPlatform() &&
|
||||
target.getApiVersionNumber() == getApiLevel() &&
|
||||
target.getName().equals(getName()) &&
|
||||
target.getVendor().equals(getVendor())) {
|
||||
return new File(target.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME this will fail if the name is not ASCII compatible. This could easily
|
||||
// happen: a Chinese or Japanese name etc for example,
|
||||
// to name a few.
|
||||
// Otherwise, see about reusing the suggestedDir. It must not be already used or
|
||||
// add some index to it, or we try to make up one.
|
||||
String name = suggestedDir;
|
||||
|
||||
if (suggestedDir == null || suggestedDir.length() == 0) {
|
||||
name = String.format("addon-%s-%s-%d", getName(), getVendor(), getApiLevel()); //$NON-NLS-1$
|
||||
name = name.toLowerCase();
|
||||
name = name.replaceAll("[^a-zA-Z0-9_-]+", "_"); // $NON-NLS-1$
|
||||
name = name.replaceAll("_+", "_"); // $NON-NLS-1$
|
||||
name = name.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
name = name.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
File folder = new File(addons, name);
|
||||
|
||||
// TODO find similar existing addon in addons folder
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String name2 = i == 0 ? name : String.format("%s-%d", name, i); //$NON-NLS-1$
|
||||
File folder = new File(addons, name2);
|
||||
if (!folder.exists()) {
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
// We shouldn't really get here. I mean, seriously, we tried hard enough.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes whether the given addon package is a suitable update for the current package.
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.SdkManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -341,7 +343,10 @@ public class Archive implements IDescription {
|
||||
*
|
||||
* @return True if the archive was installed, false otherwise.
|
||||
*/
|
||||
public boolean install(String osSdkRoot, boolean forceHttp, ITaskMonitor monitor) {
|
||||
public boolean install(String osSdkRoot,
|
||||
boolean forceHttp,
|
||||
SdkManager sdkManager,
|
||||
ITaskMonitor monitor) {
|
||||
|
||||
File archiveFile = null;
|
||||
try {
|
||||
@@ -364,7 +369,7 @@ public class Archive implements IDescription {
|
||||
|
||||
archiveFile = downloadFile(monitor, forceHttp);
|
||||
if (archiveFile != null) {
|
||||
if (unarchive(osSdkRoot, archiveFile, monitor)) {
|
||||
if (unarchive(osSdkRoot, archiveFile, sdkManager, monitor)) {
|
||||
monitor.setResult("Installed: %1$s", name);
|
||||
return true;
|
||||
}
|
||||
@@ -568,48 +573,63 @@ public class Archive implements IDescription {
|
||||
/**
|
||||
* Install the given archive in the given folder.
|
||||
*/
|
||||
private boolean unarchive(String osSdkRoot, File archiveFile, ITaskMonitor monitor) {
|
||||
String name = getParentPackage().getShortDescription();
|
||||
String desc = String.format("Installing %1$s", name);
|
||||
monitor.setDescription(desc);
|
||||
private boolean unarchive(String osSdkRoot,
|
||||
File archiveFile,
|
||||
SdkManager sdkManager,
|
||||
ITaskMonitor monitor) {
|
||||
String pkgName = getParentPackage().getShortDescription();
|
||||
String pkgDesc = String.format("Installing %1$s", pkgName);
|
||||
monitor.setDescription(pkgDesc);
|
||||
|
||||
File destFolder = getParentPackage().getInstallFolder(osSdkRoot);
|
||||
// We always unzip in a temp folder which name depends on the package type
|
||||
// (e.g. addon, tools, etc.) and then move the folder to the destination folder.
|
||||
// If the destination folder exists, it will be renamed and deleted at the very
|
||||
// end if everything succeeded.
|
||||
|
||||
File unzipDestFolder = destFolder;
|
||||
String pkgKind = getParentPackage().getClass().getSimpleName();
|
||||
|
||||
File destFolder = null;
|
||||
File unzipDestFolder = null;
|
||||
File renamedDestFolder = null;
|
||||
|
||||
try {
|
||||
// If this folder already exists, unzip in a temporary folder and then move/unlink.
|
||||
if (destFolder.exists()) {
|
||||
// Find a new temp folder that doesn't exist yet
|
||||
unzipDestFolder = findTempFolder(destFolder, "new"); //$NON-NLS-1$
|
||||
unzipDestFolder = findTempFolder(osSdkRoot, pkgKind, "new"); //$NON-NLS-1$
|
||||
|
||||
if (unzipDestFolder == null) {
|
||||
// this should not seriously happen.
|
||||
monitor.setResult("Failed to find a suitable temp directory similar to %1$s.",
|
||||
destFolder.getPath());
|
||||
monitor.setResult("Failed to find a temp directory in %1$s.", osSdkRoot);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unzipDestFolder.mkdirs()) {
|
||||
monitor.setResult("Failed to create directory %1$s",
|
||||
unzipDestFolder.getPath());
|
||||
monitor.setResult("Failed to create directory %1$s", unzipDestFolder.getPath());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unzipFolder(archiveFile, getSize(), unzipDestFolder, desc, monitor)) {
|
||||
String[] zipRootFolder = new String[] { null };
|
||||
if (!unzipFolder(archiveFile, getSize(),
|
||||
unzipDestFolder, pkgDesc,
|
||||
zipRootFolder, monitor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute destination directory
|
||||
destFolder = getParentPackage().getInstallFolder(
|
||||
osSdkRoot, zipRootFolder[0], sdkManager);
|
||||
|
||||
if (destFolder == null) {
|
||||
// this should not seriously happen.
|
||||
monitor.setResult("Failed to compute installation directory for %1$s.", pkgName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unzipDestFolder != destFolder) {
|
||||
// Swap the old folder by the new one.
|
||||
// Both original folders will be deleted in the finally clause below.
|
||||
renamedDestFolder = findTempFolder(destFolder, "old"); //$NON-NLS-1$
|
||||
if (destFolder.isDirectory()) {
|
||||
renamedDestFolder = findTempFolder(osSdkRoot, pkgKind, "old"); //$NON-NLS-1$
|
||||
if (renamedDestFolder == null) {
|
||||
// this should not seriously happen.
|
||||
monitor.setResult("Failed to find a suitable temp directory similar to %1$s.",
|
||||
destFolder.getPath());
|
||||
monitor.setResult("Failed to find a temp directory in %1$s.", osSdkRoot);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -619,28 +639,36 @@ public class Archive implements IDescription {
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!unzipDestFolder.renameTo(destFolder)) {
|
||||
monitor.setResult("Failed to rename directory %1$s to %2$s",
|
||||
unzipDestFolder.getPath(), destFolder.getPath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unzipDestFolder = null;
|
||||
return true;
|
||||
|
||||
} finally {
|
||||
// Cleanup if the unzip folder is still set.
|
||||
deleteFileOrFolder(renamedDestFolder);
|
||||
if (unzipDestFolder != destFolder) {
|
||||
deleteFileOrFolder(unzipDestFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzips a zip file into the given destination directory.
|
||||
*
|
||||
* The archive file MUST have a unique "root" folder. This root folder is skipped when
|
||||
* unarchiving. However we return that root folder name to the caller, as it can be used
|
||||
* as a template to know what destination directory to use in the Add-on case.
|
||||
*/
|
||||
private boolean unzipFolder(File archiveFile,
|
||||
long compressedSize,
|
||||
File unzipDestFolder,
|
||||
String description,
|
||||
String[] outZipRootFolder,
|
||||
ITaskMonitor monitor) {
|
||||
|
||||
description += " (%1$d%%)";
|
||||
@@ -678,6 +706,9 @@ public class Archive implements IDescription {
|
||||
if (pos < 0 || pos == name.length() - 1) {
|
||||
continue;
|
||||
} else {
|
||||
if (outZipRootFolder[0] == null && pos > 0) {
|
||||
outZipRootFolder[0] = name.substring(0, pos);
|
||||
}
|
||||
name = name.substring(pos + 1);
|
||||
}
|
||||
|
||||
@@ -762,21 +793,27 @@ public class Archive implements IDescription {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a temp folder which name is similar to the one of the ideal folder
|
||||
* and with a ".tmpN" appended.
|
||||
* Finds a temp folder in the form of osBasePath/temp/prefix.suffixNNN.
|
||||
* <p/>
|
||||
* This operation is not atomic so there's no guarantee the folder can't get
|
||||
* created in between. This is however unlikely and the caller can assume the
|
||||
* returned folder does not exist yet.
|
||||
* <p/>
|
||||
* Returns null if no such folder can be found (e.g. if all candidates exist),
|
||||
* which is rather unlikely.
|
||||
* Returns null if no such folder can be found (e.g. if all candidates exist,
|
||||
* which is rather unlikely) or if the base temp folder cannot be created.
|
||||
*/
|
||||
private File findTempFolder(File idealFolder, String suffix) {
|
||||
String basePath = idealFolder.getPath();
|
||||
private File findTempFolder(String osBasePath, String prefix, String suffix) {
|
||||
File baseTempFolder = new File(osBasePath, "temp");
|
||||
|
||||
if (!baseTempFolder.isDirectory()) {
|
||||
if (!baseTempFolder.mkdirs()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < 100; i++) {
|
||||
File folder = new File(String.format("%1$s.%2$s%3$02d", basePath, suffix, i)); //$NON-NLS-1$
|
||||
File folder = new File(baseTempFolder,
|
||||
String.format("%1$s.%2$s%3$02d", prefix, suffix, i)); //$NON-NLS-1$
|
||||
if (!folder.exists()) {
|
||||
return folder;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||
import com.android.sdklib.internal.repository.Archive.Os;
|
||||
import com.android.sdklib.repository.SdkRepository;
|
||||
@@ -98,10 +99,13 @@ public class DocPackage extends Package {
|
||||
* A "doc" package should always be located in SDK/docs.
|
||||
*
|
||||
* @param osSdkRoot The OS path of the SDK root folder.
|
||||
* @param suggestedDir A suggestion for the installation folder name, based on the root
|
||||
* folder used in the zip archive.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return A new {@link File} corresponding to the directory to use to install this package.
|
||||
*/
|
||||
@Override
|
||||
public File getInstallFolder(String osSdkRoot) {
|
||||
public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
|
||||
return new File(osSdkRoot, SdkConstants.FD_DOCS);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||
@@ -63,7 +62,7 @@ public class LocalSdkParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the packages found by the last call to {@link #parseSdk(String)}.
|
||||
* Returns the packages found by the last call to {@link #parseSdk(String, SdkManager)}.
|
||||
*/
|
||||
public Package[] getPackages() {
|
||||
return mPackages;
|
||||
@@ -71,7 +70,7 @@ public class LocalSdkParser {
|
||||
|
||||
/**
|
||||
* Clear the internal packages list. After this call, {@link #getPackages()} will return
|
||||
* null till {@link #parseSdk(String)} is called.
|
||||
* null till {@link #parseSdk(String, SdkManager)} is called.
|
||||
*/
|
||||
public void clearPackages() {
|
||||
mPackages = null;
|
||||
@@ -84,9 +83,10 @@ public class LocalSdkParser {
|
||||
* at any time later.
|
||||
*
|
||||
* @param osSdkRoot The path to the SDK folder.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return The packages found. Can be retrieved later using {@link #getPackages()}.
|
||||
*/
|
||||
public Package[] parseSdk(String osSdkRoot) {
|
||||
public Package[] parseSdk(String osSdkRoot, SdkManager sdkManager) {
|
||||
ArrayList<Package> packages = new ArrayList<Package>();
|
||||
|
||||
Package pkg = scanDoc(new File(osSdkRoot, SdkConstants.FD_DOCS));
|
||||
@@ -100,20 +100,7 @@ public class LocalSdkParser {
|
||||
}
|
||||
|
||||
// for platforms and add-ons, rely on the SdkManager parser
|
||||
SdkManager sdkman = SdkManager.createManager(osSdkRoot, new ISdkLog() {
|
||||
// A dummy sdk logger that doesn't log anything.
|
||||
public void error(Throwable t, String errorFormat, Object... args) {
|
||||
// pass
|
||||
}
|
||||
public void printf(String msgFormat, Object... args) {
|
||||
// pass
|
||||
}
|
||||
public void warning(String warningFormat, Object... args) {
|
||||
// pass
|
||||
}
|
||||
});
|
||||
|
||||
for(IAndroidTarget target : sdkman.getTargets()) {
|
||||
for(IAndroidTarget target : sdkManager.getTargets()) {
|
||||
pkg = null;
|
||||
|
||||
if (target.isPlatform()) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||
import com.android.sdklib.internal.repository.Archive.Os;
|
||||
import com.android.sdklib.repository.SdkRepository;
|
||||
@@ -198,9 +199,13 @@ public abstract class Package implements IDescription {
|
||||
* existing or new folder depending on the current content of the SDK.
|
||||
*
|
||||
* @param osSdkRoot The OS path of the SDK root folder.
|
||||
* @param suggestedDir A suggestion for the installation folder name, based on the root
|
||||
* folder used in the zip archive.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return A new {@link File} corresponding to the directory to use to install this package.
|
||||
*/
|
||||
public abstract File getInstallFolder(String osSdkRoot);
|
||||
public abstract File getInstallFolder(
|
||||
String osSdkRoot, String suggestedDir, SdkManager sdkManager);
|
||||
|
||||
/**
|
||||
* Computes whether the given package is a suitable update for the current package.
|
||||
|
||||
@@ -102,10 +102,23 @@ public class PlatformPackage extends Package {
|
||||
* has this platform version installed, we'll use that one.
|
||||
*
|
||||
* @param osSdkRoot The OS path of the SDK root folder.
|
||||
* @param suggestedDir A suggestion for the installation folder name, based on the root
|
||||
* folder used in the zip archive.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return A new {@link File} corresponding to the directory to use to install this package.
|
||||
*/
|
||||
@Override
|
||||
public File getInstallFolder(String osSdkRoot) {
|
||||
public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
|
||||
|
||||
// First find if this add-on is already installed. If so, reuse the same directory.
|
||||
for (IAndroidTarget target : sdkManager.getTargets()) {
|
||||
if (target.isPlatform() &&
|
||||
target.getApiVersionNumber() == getApiLevel() &&
|
||||
target.getApiVersionName().equals(getVersion())) {
|
||||
return new File(target.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
File platforms = new File(osSdkRoot, SdkConstants.FD_PLATFORMS);
|
||||
File folder = new File(platforms, String.format("android-%s", getVersion())); //$NON-NLS-1$
|
||||
// TODO find similar existing platform in platforms folder
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||
import com.android.sdklib.internal.repository.Archive.Os;
|
||||
|
||||
@@ -82,10 +83,13 @@ public class ToolPackage extends Package {
|
||||
* A "tool" package should always be located in SDK/tools.
|
||||
*
|
||||
* @param osSdkRoot The OS path of the SDK root folder.
|
||||
* @param suggestedDir A suggestion for the installation folder name, based on the root
|
||||
* folder used in the zip archive.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @return A new {@link File} corresponding to the directory to use to install this package.
|
||||
*/
|
||||
@Override
|
||||
public File getInstallFolder(String osSdkRoot) {
|
||||
public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
|
||||
return new File(osSdkRoot, SdkConstants.FD_TOOLS);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,8 @@ class LocalSdkAdapter {
|
||||
|
||||
if (packages == null) {
|
||||
// load on demand the first time
|
||||
packages = parser.parseSdk(mUpdaterData.getOsSdkRoot());
|
||||
packages = parser.parseSdk(mUpdaterData.getOsSdkRoot(),
|
||||
mUpdaterData.getSdkManager());
|
||||
}
|
||||
|
||||
if (packages != null) {
|
||||
|
||||
@@ -273,7 +273,7 @@ class UpdaterData {
|
||||
break;
|
||||
}
|
||||
|
||||
if (archive.install(mOsSdkRoot, forceHttp, monitor)) {
|
||||
if (archive.install(mOsSdkRoot, forceHttp, mSdkManager, monitor)) {
|
||||
numInstalled++;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user