blob: 6884cd7cd890be87293f3010d6d52ba81347bd60 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.sdk;
import com.android.sdklib.SdkManager;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.MajorRevision;
import com.android.sdklib.repository.descriptors.IPkgDesc;
import com.android.sdklib.repository.descriptors.PkgType;
import com.android.sdklib.repository.local.LocalPkgInfo;
import com.android.sdklib.repository.local.LocalSdk;
import com.android.tools.idea.rendering.LogWrapper;
import com.android.utils.ILogger;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;
public class SdkMerger {
private static final Logger LOG = Logger.getInstance(SdkMerger.class);
public static void mergeSdks(@NotNull File srcDir, @NotNull File destDir, @Nullable ProgressIndicator indicator) {
Collection<MergeablePackage> packages = compareSdks(srcDir, destDir);
int numPackages = packages.size();
int i = 0;
for (MergeablePackage pkg : packages) {
if (indicator != null) {
if (indicator.isCanceled()) {
return;
}
indicator.setFraction((double)i++ / numPackages);
indicator.setText(String.format("Copying SDK package %1s", pkg.srcPkg.getDesc().getInstallId()));
}
if (pkg.destPkg != null) {
// Destination package exists but is older; delete the old and replace with the new.
File destPkgDir = pkg.destPkg.getLocalDir();
try {
FileUtil.delete(destPkgDir);
}
catch (RuntimeException e) {
LOG.warn("Failed to delete destination directory " + destPkgDir.getPath(), e);
}
}
try {
FileUtil.copyDir(pkg.srcPkg.getLocalDir(),
pkg.srcPkg.getDesc().getCanonicalInstallFolder(pkg.destLocation));
}
catch (IOException e) {
LOG.error("Unable to copy package " + pkg.srcPkg.getDesc().getInstallId(), e);
}
}
if (indicator != null) {
indicator.setFraction(1.0);
}
}
public static boolean hasMergeableContent(@NotNull File srcDir, @NotNull File destDir) {
return !compareSdks(srcDir, destDir).isEmpty();
}
@NotNull
private static Collection<MergeablePackage> compareSdks(@NotNull File srcDir, @NotNull File destDir) {
Collection<MergeablePackage> results = Lists.newArrayList();
ILogger logger = new LogWrapper(LOG);
SdkManager destManager = SdkManager.createManager(destDir.getPath(), logger);
SdkManager srcManager = SdkManager.createManager(srcDir.getPath(), logger);
if (srcManager == null || destManager == null) {
return results;
}
LocalSdk srcSdk = srcManager.getLocalSdk();
LocalSdk destSdk = destManager.getLocalSdk();
LocalPkgInfo[] srcPkgs = srcSdk.getPkgsInfos(EnumSet.allOf(PkgType.class));
File destLocation = destSdk.getLocation();
if (destLocation == null) {
return results;
}
Map<String, LocalPkgInfo> destPackages = Maps.newHashMap();
for (LocalPkgInfo pkg : destSdk.getPkgsInfos(EnumSet.allOf(PkgType.class))) {
destPackages.put(pkg.getDesc().getInstallId(), pkg);
}
for (LocalPkgInfo srcPkg : srcPkgs) {
IPkgDesc srcPkgDesc = srcPkg.getDesc();
LocalPkgInfo destPkg = destPackages.get(srcPkg.getDesc().getInstallId());
if (destPkg != null) {
IPkgDesc destPkgDesc = destPkg.getDesc();
FullRevision srcFullRevision = srcPkgDesc.getFullRevision();
FullRevision destFullRevision = destPkgDesc.getFullRevision();
MajorRevision srcMajorRevision = srcPkgDesc.getMajorRevision();
MajorRevision destMajorRevision = destPkgDesc.getMajorRevision();
if ((srcFullRevision != null && destFullRevision != null && srcFullRevision.compareTo(destFullRevision) > 0) ||
(srcMajorRevision != null && destMajorRevision != null && srcMajorRevision.compareTo(destMajorRevision) > 0)) {
// Package exists in destination but is old; replace it.
results.add(new MergeablePackage(srcPkg, destPkg, destLocation));
}
} else {
// Package doesn't exist in destination; copy it over.
results.add(new MergeablePackage(srcPkg, null, destLocation));
}
}
return results;
}
private static class MergeablePackage {
@NotNull private final LocalPkgInfo srcPkg;
@Nullable private final LocalPkgInfo destPkg;
@NotNull private final File destLocation;
private MergeablePackage(@NotNull LocalPkgInfo srcPkg, @Nullable LocalPkgInfo destPkg, @NotNull File destLocation) {
this.srcPkg = srcPkg;
this.destPkg = destPkg;
this.destLocation = destLocation;
}
}
}