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

Code before:
        }
        if (entry.isDirectory()) {
          Files.createDirectories(entryPath);
        } else {
          if (entryPath.getParent() != null) {
            Files.createDirectories(entryPath.getParent());
          }

          if (entry.isSymbolicLink()) {
            Files.createSymbolicLink(entryPath, Paths.get(entry.getLinkName()));
          } else {
            try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(entryPath))) {
              ByteStreams.copy(tarArchiveInputStream, out);
            }
          }
        }
      }
      preserveModificationTimes(destination, entries);
    }
  }

  private static void preserveModificationTimes(Path destination, List<TarArchiveEntry> entries)
      throws IOException {
    new DirectoryWalker(destination)
        .filter(path -> Files.isDirectory(path))
        .walk(path -> Files.setLastModifiedTime(path, FileTime.from(Instant.ofEpochSecond(1L))));
    for (TarArchiveEntry entry : entries) {
      Files.setLastModifiedTime(
          destination.resolve(entry.getName()), FileTime.from(entry.getModTime().toInstant()));
    }
  }
}


Review comment (refactor):
As this is an unconventional behavior, I think we should apply this only when enabled. `TarExtractor` and `ZipUtil` are deemed general and isolated.

And maybe we can create an instance of `FileTime.fromMillis(1000L)` (I think it's equivalent) at the start of the method and avoid re-creating the instance everytime.

Code after:
    if (enableReproducibleTimestamps
        && Files.isDirectory(destination)
        && destination.toFile().list().length != 0) {
      throw new IllegalStateException(
          "Cannot enable reproducible timestamps. They can only be enabled when the target root doesn't exist or is an empty directory");
    }
    String canonicalDestination = destination.toFile().getCanonicalPath();
    List<TarArchiveEntry> entries = new ArrayList<>();
    try (InputStream in = new BufferedInputStream(Files.newInputStream(source));
        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(in)) {
      for (TarArchiveEntry entry = tarArchiveInputStream.getNextTarEntry();
          entry != null;
          entry = tarArchiveInputStream.getNextTarEntry()) {
        entries.add(entry);
        Path entryPath = destination.resolve(entry.getName());

        String canonicalTarget = entryPath.toFile().getCanonicalPath();
        if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
          String offender = entry.getName() + " from " + source;
          throw new IOException("Blocked unzipping files outside destination: " + offender);
        }
        if (entry.isDirectory()) {
          Files.createDirectories(entryPath);
        } else {
          if (entryPath.getParent() != null) {
            Files.createDirectories(entryPath.getParent());
          }

          if (entry.isSymbolicLink()) {
            Files.createSymbolicLink(entryPath, Paths.get(entry.getLinkName()));
          } else {
            try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(entryPath))) {
              ByteStreams.copy(tarArchiveInputStream, out);
            }
          }
        }
      }
    }
    preserveModificationTimes(destination, entries, enableReproducibleTimestamps);
  }

  /**
   * Preserve modification timestamps of files and directories in a tar file. If a directory is not
   * an entry in the tar file and reproducible timestamps are enabled then its modification
   * timestamp is set to a constant value. Note that the modification timestamps of symbolic links
   * are not preserved even with reproducible timestamps enabled.
   *
   * @param destination target root for unzipping
   * @param entries list of entries in tar file
   * @param enableReproducibleTimestamps whether or not reproducible timestamps should be used
   * @throws IOException when I/O error occurs