Refactor `cache add` check for existing package. (#3872)

diff --git a/lib/src/command/cache_add.dart b/lib/src/command/cache_add.dart
index 763856e..85c2c5d 100644
--- a/lib/src/command/cache_add.dart
+++ b/lib/src/command/cache_add.dart
@@ -72,15 +72,10 @@
     }
 
     Future<void> downloadVersion(id) async {
-      if (cache.contains(id)) {
-        // TODO(rnystrom): Include source and description if not hosted.
-        // See solve_report.dart for code to harvest.
+      final result = await cache.downloadPackage(id);
+      if (!result.didUpdate) {
         log.message('Already cached ${id.name} ${id.version}.');
-        return;
       }
-
-      // Download it.
-      await cache.downloadPackage(id);
     }
 
     if (argResults['all']) {
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index c56f413..0ddf6ef 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -535,7 +535,7 @@
                     // This happens when we resolved a package from a legacy
                     // server not providing archive_sha256. As a side-effect of
                     // downloading the package we compute and store the sha256.
-                    package = await cache.downloadPackage(package);
+                    package = (await cache.downloadPackage(package)).packageId;
                   }
                 }
               } else {
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index bb70ef1..ce841fb 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -67,9 +67,10 @@
         if (id.source is CachedSource) {
           return await withDependencyType(_root.pubspec.dependencyType(id.name),
               () async {
-            return await cache.downloadPackage(
+            return (await cache.downloadPackage(
               id,
-            );
+            ))
+                .packageId;
           });
         }
         return id;
diff --git a/lib/src/source/cached.dart b/lib/src/source/cached.dart
index 9818146..933b08c 100644
--- a/lib/src/source/cached.dart
+++ b/lib/src/source/cached.dart
@@ -52,11 +52,6 @@
   /// the system cache.
   Future<Pubspec> describeUncached(PackageId id, SystemCache cache);
 
-  /// Determines if the package identified by [id] is already downloaded to the
-  /// system cache.
-  bool isInSystemCache(PackageId id, SystemCache cache) =>
-      dirExists(getDirectoryInCache(id, cache));
-
   /// Downloads the package identified by [id] to the system cache.
   Future<DownloadPackageResult> downloadToSystemCache(
     PackageId id,
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 6f6632c..ae034d9 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -9,7 +9,7 @@
 import 'dart:typed_data';
 
 import 'package:collection/collection.dart'
-    show IterableExtension, IterableNullableExtension, ListEquality, maxBy;
+    show IterableExtension, IterableNullableExtension, maxBy;
 import 'package:crypto/crypto.dart';
 import 'package:http/http.dart' as http;
 import 'package:meta/meta.dart';
@@ -857,28 +857,6 @@
     );
   }
 
-  /// Determines if the package identified by [id] is already downloaded to the
-  /// system cache and has the expected content-hash.
-  @override
-  bool isInSystemCache(PackageId id, SystemCache cache) {
-    if ((id.description as ResolvedHostedDescription).sha256 != null) {
-      try {
-        final cachedSha256 = readTextFile(hashPath(id, cache));
-        if (!const ListEquality().equals(
-          hexDecode(cachedSha256),
-          (id.description as ResolvedHostedDescription).sha256,
-        )) {
-          return false;
-        }
-      } on io.IOException {
-        // Most likely the hash file was not written, because we had a legacy
-        // entry.
-        return false;
-      }
-    }
-    return dirExists(getDirectoryInCache(id, cache));
-  }
-
   /// The system cache directory for the hosted source contains subdirectories
   /// for each separate repository URL that's used on the system.
   ///
diff --git a/lib/src/system_cache.dart b/lib/src/system_cache.dart
index 90bd7d5..a83d395 100644
--- a/lib/src/system_cache.dart
+++ b/lib/src/system_cache.dart
@@ -126,16 +126,6 @@
     }
   }
 
-  /// Determines if the system cache contains the package identified by [id].
-  bool contains(PackageId id) {
-    final source = id.source;
-
-    if (source is CachedSource) {
-      return source.isInSystemCache(id, this);
-    }
-    throw ArgumentError('Package $id is not cacheable.');
-  }
-
   /// Create a new temporary directory within the system cache.
   ///
   /// The system cache maintains its own temporary directory that it uses to
@@ -241,7 +231,7 @@
   ///
   /// Returns [id] with an updated [ResolvedDescription], this can be different
   /// if the content-hash changed while downloading.
-  Future<PackageId> downloadPackage(PackageId id) async {
+  Future<DownloadPackageResult> downloadPackage(PackageId id) async {
     final source = id.source;
     assert(source is CachedSource);
     final result = await (source as CachedSource).downloadToSystemCache(
@@ -258,7 +248,7 @@
     if (result.didUpdate) {
       _ensureReadme();
     }
-    return result.packageId;
+    return result;
   }
 
   /// Get the latest version of [package].