class IncrementalRelativeFileSets {

    @NonNull
    public static ImmutableMap<RelativeFile, FileStatus> makeFromBaseFiles(
            @NonNull Collection<File> baseFiles,
            @NonNull Map<File, FileStatus> updates,
            @NonNull FileCacheByPath cache,
            @NonNull Set<Runnable> cacheUpdates,
            @NonNull FileDeletionPolicy fileDeletionPolicy)
            throws IOException {
        for (File f : baseFiles) {
            Preconditions.checkArgument(f.exists(), "!f.exists()");
        }

        Map<RelativeFile, FileStatus> relativeUpdates = Maps.newHashMap();
        for (Map.Entry<File, FileStatus> fileUpdate : updates.entrySet()) {

            File file = fileUpdate.getKey();
            FileStatus status = fileUpdate.getValue();

            if (fileDeletionPolicy == FileDeletionPolicy.DISALLOW_FILE_DELETIONS) {
                Preconditions.checkState(
                        status != FileStatus.REMOVED,
                        String.format(
                                "Changes include a deleted file ('%s'), which is not allowed.",
                                file.getAbsolutePath()));
            }

            if (baseFiles.contains(file)) {
                relativeUpdates.putAll(fromZip(file, cache, cacheUpdates));
            } else {
                /*
                 * We ignore directories because there are no relative files for directories.
                 */
                if (file.isDirectory()) {
                    continue;
                }

                /*
                 * If the file does not exist in the set of base files, assume it is a file in a
                 * directory. If we don't find the base directory, ignore it.
                 */
                File possibleBaseDirectory = file.getParentFile();
                while (possibleBaseDirectory != null) {
                    if (baseFiles.contains(possibleBaseDirectory)) {
                        relativeUpdates.put(new RelativeFile(possibleBaseDirectory, file), status);
                        break;
                    }

                    possibleBaseDirectory = possibleBaseDirectory.getParentFile();
                }
            }
        }

        return ImmutableMap.copyOf(relativeUpdates);
    }

    private  IncrementalRelativeFileSets();

}