OSDN Git Service

SDK Manager: fix suggestions of new platforms.
authorRaphael Moll <ralf@android.com>
Thu, 28 Oct 2010 23:41:49 +0000 (16:41 -0700)
committerRaphael Moll <ralf@android.com>
Thu, 28 Oct 2010 23:47:49 +0000 (16:47 -0700)
I accidentally broke the way the SDK Manager was suggesting
new platforms when I "optimized" the way it was fetching new
sources when resolving dependencies. The fix is that even if
we don't need to refresh or fetch a source, we still need to
report the packages we know it contains.

Also made the Archive and ArchiveInfo implement Comparable
and defer their comparison to the one of Package. This way
we can sort the archives in the install window.

Change-Id: Ic3b39e49e8143541b19b00de09468c1b3f01b0d7

sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ArchiveInfo.java
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterLogic.java

index 8b61637..10e6424 100755 (executable)
@@ -44,7 +44,7 @@ import java.util.Properties;
  * <p/>\r
  * Packages are offered by a {@link SdkSource} (a download site).\r
  */\r
-public class Archive implements IDescription {\r
+public class Archive implements IDescription, Comparable<Archive> {\r
 \r
     public static final int NUM_MONITOR_INC = 100;\r
     private static final String PROP_OS   = "Archive.Os";       //$NON-NLS-1$\r
@@ -1099,4 +1099,16 @@ public class Archive implements IDescription {
            "chmod", "777", file.getAbsolutePath()\r
         });\r
     }\r
+\r
+    /**\r
+     * Archives are compared using their {@link Package} ordering.\r
+     *\r
+     * @see Package#compareTo(Package)\r
+     */\r
+    public int compareTo(Archive rhs) {\r
+        if (mPackage != null && rhs != null) {\r
+            return mPackage.compareTo(rhs.getParentPackage());\r
+        }\r
+        return 0;\r
+    }\r
 }\r
index a6c28a9..438b07b 100755 (executable)
@@ -503,18 +503,18 @@ public abstract class Package implements IDescription, Comparable<Package> {
 \r
 \r
     /**\r
-     * Returns an ordering like this:\r
-     * - Tools.\r
-     * - Platform-Tools.\r
-     * - Docs.\r
-     * - Platform n preview\r
-     * - Platform n\r
-     * - Platform n-1\r
-     * - Samples packages.\r
-     * - Add-on based on n preview\r
-     * - Add-on based on n\r
-     * - Add-on based on n-1\r
-     * - Extra packages.\r
+     * Returns an ordering like this: <br/>\r
+     * - Tools <br/>\r
+     * - Platform-Tools <br/>\r
+     * - Docs. <br/>\r
+     * - Platform n preview <br/>\r
+     * - Platform n <br/>\r
+     * - Platform n-1 <br/>\r
+     * - Samples packages <br/>\r
+     * - Add-on based on n preview <br/>\r
+     * - Add-on based on n <br/>\r
+     * - Add-on based on n-1 <br/>\r
+     * - Extra packages <br/>\r
      */\r
     public int compareTo(Package other) {\r
         int s1 = this.sortingScore();\r
index 15560b7..d01570d 100755 (executable)
@@ -42,7 +42,7 @@ import java.util.Collection;
  *\r
  * @see ArchiveInfo#ArchiveInfo(Archive, Archive, ArchiveInfo[])\r
  */\r
-class ArchiveInfo implements IDescription {\r
+class ArchiveInfo implements IDescription, Comparable<ArchiveInfo> {\r
 \r
     private final Archive mNewArchive;\r
     private final Archive mReplaced;\r
@@ -205,4 +205,17 @@ class ArchiveInfo implements IDescription {
         }\r
         return super.toString();\r
     }\r
+\r
+    /**\r
+     * ArchiveInfos are compared using ther "new archive" ordering.\r
+     *\r
+     * @see Archive#compareTo(Archive)\r
+     */\r
+    public int compareTo(ArchiveInfo rhs) {\r
+        if (mNewArchive != null && rhs != null) {\r
+            return mNewArchive.compareTo(rhs.getNewArchive());\r
+        }\r
+        return 0;\r
+    }\r
+\r
 }\r
index fe51f19..a1c089b 100755 (executable)
@@ -51,6 +51,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;\r
 import java.util.ArrayList;\r
 import java.util.Collection;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.Iterator;\r
@@ -639,6 +640,8 @@ class UpdaterData implements IUpdaterData {
         // TODO if selectedArchives is null and archives.len==0, find if there are\r
         // any new platform we can suggest to install instead.\r
 \r
+        Collections.sort(archives);\r
+\r
         UpdateChooserDialog dialog = new UpdateChooserDialog(getWindowShell(), this, archives);\r
         dialog.open();\r
 \r
@@ -680,6 +683,8 @@ class UpdaterData implements IUpdaterData {
                 getLocalSdkParser().getPackages(),\r
                 includeObsoletes);\r
 \r
+        Collections.sort(archives);\r
+\r
         // Filter the selected archives to only keep the ones matching the filter\r
         if (pkgFilter != null && pkgFilter.size() > 0 && archives != null && archives.size() > 0) {\r
             // Map filter types to an SdkRepository Package type.\r
index 4380ca8..f57213c 100755 (executable)
@@ -962,7 +962,24 @@ class UpdaterLogic {
         return new MissingPlatformArchiveInfo(new AndroidVersion(api, null /*codename*/));\r
     }\r
 \r
-    /** Fetch all remote packages only if really needed. */\r
+    /**\r
+     * Fetch all remote packages only if really needed.\r
+     * <p/>\r
+     * This method takes a list of sources. Each source is only fetched once -- that is each\r
+     * source keeps the list of packages that we fetched from the remote XML file. If the list\r
+     * is null, it means this source has never been fetched so we'll do it once here. Otherwise\r
+     * we rely on the cached list of packages from this source.\r
+     * <p/>\r
+     * This method also takes a remote package list as input, which it will fill out.\r
+     * If a source has already been fetched, we'll add its packages to the remote package list\r
+     * if they are not already present. Otherwise, the source will be fetched and the packages\r
+     * added to the list.\r
+     *\r
+     * @param remotePkgs An in-out list of packages available from remote sources.\r
+     *                   This list must not be null.\r
+     *                   It can be empty or already contain some packages.\r
+     * @param remoteSources A list of available remote sources to fetch from.\r
+     */\r
     protected void fetchRemotePackages(\r
             final ArrayList<Package> remotePkgs,\r
             final SdkSource[] remoteSources) {\r
@@ -975,9 +992,27 @@ class UpdaterLogic {
         // necessary.\r
         boolean needsFetch = false;\r
         for (final SdkSource remoteSrc : remoteSources) {\r
-            needsFetch = remoteSrc.getPackages() == null;\r
-            if (needsFetch) {\r
-                break;\r
+            Package[] pkgs = remoteSrc.getPackages();\r
+            if (pkgs == null) {\r
+                // This source has never been fetched. We'll do it below.\r
+                needsFetch = true;\r
+            } else {\r
+                // This source has already been fetched and we know its package list.\r
+                // We still need to make sure all of its packages are present in the\r
+                // remotePkgs list.\r
+\r
+                nextPackage: for (Package pkg : pkgs) {\r
+                    for (Archive a : pkg.getArchives()) {\r
+                        // Only add a package if it contains at least one compatible archive\r
+                        // and is not already in the remote package list.\r
+                        if (a.isCompatible()) {\r
+                            if (!remotePkgs.contains(pkg)) {\r
+                                remotePkgs.add(pkg);\r
+                                continue nextPackage;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
             }\r
         }\r
 \r
@@ -1000,11 +1035,13 @@ class UpdaterLogic {
                     if (pkgs != null) {\r
                         nextPackage: for (Package pkg : pkgs) {\r
                             for (Archive a : pkg.getArchives()) {\r
-                                // Only add a package if it contains at least\r
-                                // one compatible archive\r
+                                // Only add a package if it contains at least one compatible archive\r
+                                // and is not already in the remote package list.\r
                                 if (a.isCompatible()) {\r
-                                    remotePkgs.add(pkg);\r
-                                    continue nextPackage;\r
+                                    if (!remotePkgs.contains(pkg)) {\r
+                                        remotePkgs.add(pkg);\r
+                                        continue nextPackage;\r
+                                    }\r
                                 }\r
                             }\r
                         }\r