Repository: GoogleContainerTools/jib
File: jib-core/src/main/java/com/google/cloud/tools/jib/cache/CacheStorageReader.java (Java)

Code before:
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
      if (metadata.getManifestList() != null
          && manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifestDigest() == null)) {
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
    } else {
      throw new CacheCorruptedException(
          metadataCacheDirectory, "Unknown manifest type: " + firstManifest);
    }
  }

  private final CacheStorageFiles cacheStorageFiles;

  CacheStorageReader(CacheStorageFiles cacheStorageFiles) {
    this.cacheStorageFiles = cacheStorageFiles;
  }

  /**
   * Returns {@code true} if all image layers described in a manifest have a corresponding file
   * entry in the cache.
   *
   * @param manifest the image manifest
   * @return a boolean
   */
  boolean allLayersCached(ManifestTemplate manifest) {

    List<DescriptorDigest> layerDigests;

    if (manifest instanceof V21ManifestTemplate) {
      layerDigests = ((V21ManifestTemplate) manifest).getLayerDigests();
    } else if (manifest instanceof BuildableManifestTemplate) {
      layerDigests =
          ((BuildableManifestTemplate) manifest)
              .getLayers().stream()
                  .map(BuildableManifestTemplate.ContentDescriptorTemplate::getDigest)
                  .collect(Collectors.toList());
    } else {
      throw new IllegalArgumentException("Unknown manifest type: " + manifest);
    }

    for (DescriptorDigest layerDigest : layerDigests) {
      Path layerDirectory = cacheStorageFiles.getLayerDirectory(layerDigest);
      if (!Files.exists(layerDirectory)) {
        return false;
      }
    }
    return true;
  }

  /**

Review comment (performance):
Would it possible to move this method directly to PullBaseImageStep? Since that is the only class where this is used and it could help us avoid having to go through an extra layer of classes to reach this method. Or does this method require any variables that are specific to `CacheStorageReader`?

Code after:
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
      if (metadata.getManifestList() != null
          && manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifestDigest() == null)) {
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
    } else {
      throw new CacheCorruptedException(
          metadataCacheDirectory, "Unknown manifest type: " + firstManifest);
    }
  }

  private final CacheStorageFiles cacheStorageFiles;

  CacheStorageReader(CacheStorageFiles cacheStorageFiles) {
    this.cacheStorageFiles = cacheStorageFiles;
  }

  /**
   * Returns {@code true} if all image layers described in a manifest have a corresponding file
   * entry in the cache.
   *
   * @param manifest the image manifest
   * @return a boolean
   */
  boolean areAllLayersCached(ManifestTemplate manifest) {

    List<DescriptorDigest> layerDigests;

    if (manifest instanceof V21ManifestTemplate) {
      layerDigests = ((V21ManifestTemplate) manifest).getLayerDigests();
    } else if (manifest instanceof BuildableManifestTemplate) {
      layerDigests =
          ((BuildableManifestTemplate) manifest)
              .getLayers().stream()
                  .map(BuildableManifestTemplate.ContentDescriptorTemplate::getDigest)
                  .collect(Collectors.toList());
    } else {
      throw new IllegalArgumentException("Unknown manifest type: " + manifest);
    }

    for (DescriptorDigest layerDigest : layerDigests) {
      Path layerDirectory = cacheStorageFiles.getLayerDirectory(layerDigest);
      if (!Files.exists(layerDirectory)) {
        return false;
      }
    }
    return true;
  }

  /**