On Mon, 22 Nov 2021 02:36:00 GMT, John Neffenger <jgn...@openjdk.org> wrote:

>> Add a new --source-date <TIMESTAMP> (epoch milliseconds) option to jar and 
>> jmod to allow specification of time to use for created/updated jar/jmod 
>> entries. This then allows the ability to make the content deterministic.
>> 
>> Signed-off-by: Andrew Leonard <anleo...@redhat.com>
>
> Thank you for this timely pull request, Andrew! I need this pull request and 
> also #6395 to [enable reproducible builds in 
> JavaFX](https://github.com/openjdk/jfx/pull/446). I drove myself crazy this 
> weekend with time zones, and if I understand your proposed changes correctly, 
> it looks as if you're hitting the same problems as I did:
> 
> 1. The [`SOURCE_DATE_EPOCH` environment 
> variable](https://reproducible-builds.org/specs/source-date-epoch/) is 
> defined as the number of **seconds** since the epoch of 1970-01-01T00:00:00Z, 
> but the new command option is defined as the number of milliseconds. That 
> makes it difficult to set `--source-date=$SOURCE_DATE_EPOCH` on the command 
> line.
> 
> 2. Calling the method `ZipEntry.setTime(long)` will not allow for 
> reproducible builds when the builds run in different time zones.
> 
> For the second problem, run the included Java Time program as shown below:
> 
> 
> $ javac Time.java 
> $ echo $SOURCE_DATE_EPOCH
> 1637085342
> $ date --date="@$SOURCE_DATE_EPOCH"
> Tue 16 Nov 2021 09:55:42 AM PST
> $ java Time
> Build timestamp = 2021-11-16T17:55:42Z
> $ for f in *.zip; do zipinfo -v $f | grep -e Archive -e modified; done
> Archive:  FailsInNome.zip
>   file last modified on (DOS date/time):          2021 Nov 16 08:55:42
> Archive:  FailsInRome.zip
>   file last modified on (DOS date/time):          2021 Nov 16 18:55:42
> Archive:  WorksInNome.zip
>   file last modified on (DOS date/time):          2021 Nov 16 17:55:42
> Archive:  WorksInRome.zip
>   file last modified on (DOS date/time):          2021 Nov 16 17:55:42
> 
> 
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.time.Instant;
> import java.time.LocalDateTime;
> import java.time.ZoneOffset;
> import java.time.temporal.ChronoUnit;
> import java.util.TimeZone;
> import java.util.zip.ZipEntry;
> import java.util.zip.ZipOutputStream;
> 
> public class Time {
> 
>     static void writeZipFile(String name, ZipEntry entry) throws IOException {
>         var output = new ZipOutputStream(new FileOutputStream(name));
>         output.putNextEntry(entry);
>         output.closeEntry();
>         output.close();
>     }
> 
>     public static void main(String[] args) throws IOException {
>         var instant = Instant.now().truncatedTo(ChronoUnit.SECONDS);
>         var sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH");
>         if (sourceDateEpoch != null) {
>             long seconds = Long.parseLong(sourceDateEpoch);
>             instant = Instant.ofEpochSecond(seconds);
>         }
>         System.out.println("Build timestamp = " + instant);
> 
>         var entry = new ZipEntry("Entry");
> 
>         long newTime = 1000 * instant.getEpochSecond();
>         TimeZone.setDefault(TimeZone.getTimeZone("America/Nome"));
>         entry.setTime(newTime);
>         writeZipFile("FailsInNome.zip", entry);
>         TimeZone.setDefault(TimeZone.getTimeZone("Europe/Rome"));
>         entry.setTime(newTime);
>         writeZipFile("FailsInRome.zip", entry);
> 
>         var dosTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
>         TimeZone.setDefault(TimeZone.getTimeZone("America/Nome"));
>         entry.setTimeLocal(dosTime);
>         writeZipFile("WorksInNome.zip", entry);
>         TimeZone.setDefault(TimeZone.getTimeZone("Europe/Rome"));
>         entry.setTimeLocal(dosTime);
>         writeZipFile("WorksInRome.zip", entry);
>     }
> }

@jgneff Hi John, thanks for the comment, I hadn't realized that aspect, but 
sort of obvious when you look at the ZIP spec for dostime, which has no 
timezone info.
So with this in mind the --source-date=<timestamp> option I am looking to add 
for jar/jmod, will need to state the timestamp is an "Epoch timestamp", ie. 
seconds since Jan1 1970 in UTC, and that as such the jar/jmod dostime will 
represent UTC "local time", akin to the EPOCH_SOURCE_DATE spec: 
https://reproducible-builds.org/specs/source-date-epoch/
I will update my PR to to use this.
thanks

-------------

PR: https://git.openjdk.java.net/jdk/pull/6481

Reply via email to