blob: 041c3559aee2bdad528fe437c36f73a1db5ad2ef [file] [log] [blame]
/*
* Copyright (C) 2015 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.remote;
import com.android.annotations.NonNull;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.descriptors.IPkgDesc;
import com.android.sdklib.repository.descriptors.PkgDesc;
import com.android.sdklib.repository.local.LocalPkgInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Represents a (revisionless) package, either local, remote, or both. If both a local and remote package are specified,
* they should represent exactly the same package, excepting the revision. That is, the result of installing the remote package
* should be (a possibly updated version of) the local package.
*/
public class UpdatablePkgInfo implements Comparable<UpdatablePkgInfo> {
private LocalPkgInfo myLocalInfo;
private RemotePkgInfo myRemoteInfo;
private RemotePkgInfo myRemotePreviewInfo;
private final Logger LOG = Logger.getInstance(getClass());
public UpdatablePkgInfo(@NonNull LocalPkgInfo localInfo) {
init(localInfo, null);
}
public UpdatablePkgInfo(@NonNull RemotePkgInfo remoteInfo) {
init(null, remoteInfo);
}
public UpdatablePkgInfo(@NonNull LocalPkgInfo localInfo, @NonNull RemotePkgInfo remoteInfo) {
init(localInfo, remoteInfo);
}
private void init(@Nullable LocalPkgInfo localPkg, @Nullable RemotePkgInfo remotePkg) {
assert localPkg != null || remotePkg != null;
myLocalInfo = localPkg;
if (remotePkg != null) {
addRemote(remotePkg);
}
}
/**
* Adds the given remote package if this package doesn't already have a remote, or if the given remote is more recent.
* If it is a preview, it will be returned by {@link #getRemote()} only if it is specified that preview packages are desired.
*
* @param remote The remote package.
*/
public void addRemote(@NonNull RemotePkgInfo remote) {
checkInstallId(remote);
if (remote.getPkgDesc().isPreview()) {
if (myRemotePreviewInfo == null ||
remote.getPkgDesc().isUpdateFor(myRemotePreviewInfo.getPkgDesc(), FullRevision.PreviewComparison.IGNORE)) {
myRemotePreviewInfo = remote;
}
}
else {
if (myRemoteInfo == null || remote.getPkgDesc().isUpdateFor(myRemoteInfo.getPkgDesc(), FullRevision.PreviewComparison.IGNORE)) {
myRemoteInfo = remote;
}
}
}
private void checkInstallId(RemotePkgInfo remote) {
if (myLocalInfo == null) {
return;
}
String localIid = myLocalInfo.getDesc().getInstallId();
String remoteIid = remote.getPkgDesc().getInstallId();
if (remoteIid.equals(localIid)) {
return;
}
if (!myLocalInfo.getDesc().isPreview() && remote.getPkgDesc().isPreview() &&
remoteIid.equals(localIid + PkgDesc.PREVIEW_SUFFIX)) {
return;
}
assert false : String.format("%s doesn't match %s", remoteIid, localIid);
}
@Nullable
public LocalPkgInfo getLocalInfo() {
return myLocalInfo;
}
public RemotePkgInfo getRemote(boolean includePreview) {
// If includePreview is true, and we don't have a non-preview remote or the preview is newer than
// the non-preview, return the preview.
if (includePreview &&
(!hasRemote(false) ||
(hasPreview() &&
myRemotePreviewInfo.getPkgDesc().isUpdateFor(myRemoteInfo.getPkgDesc(), FullRevision.PreviewComparison.IGNORE)))) {
return myRemotePreviewInfo;
}
// Else return the non-preview, possibly null.
return myRemoteInfo;
}
public boolean hasPreview() {
return myRemotePreviewInfo != null;
}
public boolean hasRemote(boolean includePreview) {
return myRemoteInfo != null || (includePreview && myRemotePreviewInfo != null);
}
public boolean hasLocal() {
return myLocalInfo != null;
}
@Override
public int compareTo(UpdatablePkgInfo o) {
return getPkgDesc(true).compareTo(o.getPkgDesc(true));
}
/**
* Gets a IPkgDesc corresponding to this updatable package. This will be:
* - The local pkg desc if the package is installed
* - The remote preview package if there is a remote preview and includePreview is true
* - The remote package otherwise, or null if there is no non-preview remote.
* @param includePreview
*/
public IPkgDesc getPkgDesc(boolean includePreview) {
if (hasLocal()) {
return myLocalInfo.getDesc();
}
if (includePreview && hasPreview()) {
return myRemotePreviewInfo.getPkgDesc();
}
if (hasRemote(false)) {
return getRemote(false).getPkgDesc();
}
return null;
}
public boolean isUpdate(boolean includePreview) {
RemotePkgInfo remote = getRemote(includePreview);
return myLocalInfo != null && remote != null &&
remote.getPkgDesc().getPreciseRevision().compareTo(myLocalInfo.getDesc().getPreciseRevision()) > 0;
}
public List<RemotePkgInfo> getAllRemotes() {
List<RemotePkgInfo> result = new SmartList<RemotePkgInfo>();
if (myRemoteInfo != null) {
result.add(myRemoteInfo);
}
if (myRemotePreviewInfo != null) {
result.add(myRemotePreviewInfo);
}
return result;
}
}