Skip to content

Commit 12fea7b

Browse files
norrisjeremytcurdt
authored andcommitted
Make changes file reproducible (#712)
1 parent 7d59333 commit 12fea7b

File tree

8 files changed

+172
-7
lines changed

8 files changed

+172
-7
lines changed

src/it/project-build-outputTimestamp/verify.groovy

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import java.nio.file.Files
12
import org.apache.commons.compress.archivers.ar.ArArchiveEntry
23
import org.apache.commons.compress.archivers.ar.ArArchiveInputStream
34

@@ -8,3 +9,8 @@ ArArchiveEntry entry
89
while ((entry = is.getNextEntry()) != null) {
910
assert entry.getLastModifiedDate().getTime() == 1724680800000L
1011
}
12+
13+
File changes = new File( basedir, 'target/jdeb-it_1.0_all.changes' )
14+
assert changes.exists();
15+
List<String> lines = Files.readAllLines(changes.toPath())
16+
assert "Date: Mon, 26 Aug 2024 14:00:00 +0000".equals(lines.get(1))

src/main/java/org/vafer/jdeb/ChangesFileBuilder.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,19 @@
3434
*/
3535
class ChangesFileBuilder {
3636

37+
private final Long outputTimestampMs;
38+
39+
ChangesFileBuilder(Long outputTimestampMs) {
40+
this.outputTimestampMs = outputTimestampMs;
41+
}
42+
3743
public ChangesFile createChanges(BinaryPackageControlFile packageControlFile, File binaryPackage, ChangesProvider changesProvider) throws IOException, PackagingException {
3844

3945
ChangesFile changesFile = new ChangesFile();
4046
changesFile.setChanges(changesProvider.getChangesSets());
4147
changesFile.initialize(packageControlFile);
4248

43-
changesFile.set("Date", ChangesFile.formatDate(new Date()));
49+
changesFile.set("Date", outputTimestampMs == null ? ChangesFile.formatDate(new Date()) : ChangesFile.formatDateUTC(new Date(outputTimestampMs)));
4450

4551
try {
4652
// compute the checksums of the binary package

src/main/java/org/vafer/jdeb/DebMaker.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,15 @@ private void makeChangesFiles(final BinaryPackageControlFile packageControlFile)
359359

360360
if (changesIn != null && changesIn.exists()) {
361361
// read the changes form a textfile provider
362-
changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageControlFile);
362+
changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageControlFile, outputTimestampMs);
363363
} else {
364364
// create an empty changelog
365365
changesProvider = new ChangesProvider() {
366366
public ChangeSet[] getChangesSets() {
367367
return new ChangeSet[] {
368368
new ChangeSet(packageControlFile.get("Package"),
369369
packageControlFile.get("Version"),
370-
new Date(),
370+
outputTimestampMs == null ? new Date() : new Date(outputTimestampMs),
371371
packageControlFile.get("Distribution"),
372372
packageControlFile.get("Urgency"),
373373
packageControlFile.get("Maintainer"),
@@ -377,7 +377,7 @@ public ChangeSet[] getChangesSets() {
377377
};
378378
}
379379

380-
ChangesFileBuilder builder = new ChangesFileBuilder();
380+
ChangesFileBuilder builder = new ChangesFileBuilder(outputTimestampMs);
381381
ChangesFile changesFile = builder.createChanges(packageControlFile, deb, changesProvider);
382382

383383
final int digestCode = PGPSigner.getDigestCode(signDigest);

src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.ArrayList;
3030
import java.util.Collection;
3131
import java.util.Date;
32+
import java.util.TimeZone;
3233

3334
import org.vafer.jdeb.debian.BinaryPackageControlFile;
3435

@@ -46,15 +47,24 @@ public final class TextfileChangesProvider implements ChangesProvider {
4647

4748
private final ChangeSet[] changeSets;
4849

49-
private DateFormat fmt = new SimpleDateFormat("HH:mm dd.MM.yyyy");
50+
private final DateFormat fmt;
5051

5152
public TextfileChangesProvider( final InputStream pInput, final BinaryPackageControlFile packageControlFile ) throws IOException, ParseException {
53+
this(pInput, packageControlFile, null);
54+
}
55+
56+
public TextfileChangesProvider( final InputStream pInput, final BinaryPackageControlFile packageControlFile, final Long outputTimestampMs ) throws IOException, ParseException {
57+
58+
fmt = new SimpleDateFormat("HH:mm dd.MM.yyyy");
59+
if (outputTimestampMs != null) {
60+
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
61+
}
5262

5363
final BufferedReader reader = new BufferedReader(new InputStreamReader(pInput));
5464

5565
String packageName = packageControlFile.get("Package");
5666
String version = packageControlFile.get("Version");
57-
Date date = new Date();
67+
Date date = outputTimestampMs == null ? new Date() : new Date(outputTimestampMs);
5868
String distribution = packageControlFile.get("Distribution");
5969
String urgency = packageControlFile.get("Urgency");
6070
String changedBy = packageControlFile.get("Maintainer");

src/main/java/org/vafer/jdeb/debian/ChangesFile.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Date;
2525
import java.util.Locale;
2626
import java.util.Map.Entry;
27+
import java.util.TimeZone;
2728

2829
/**
2930
* Reflecting a changes file
@@ -109,7 +110,17 @@ protected char getUserDefinedFieldLetter() {
109110
}
110111

111112
public static String formatDate(Date date) {
112-
final DateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
113+
final DateFormat format = createDateFormat();
113114
return format.format(date);
114115
}
116+
117+
public static String formatDateUTC(Date date) {
118+
final DateFormat format = createDateFormat();
119+
format.setTimeZone(TimeZone.getTimeZone("UTC"));
120+
return format.format(date);
121+
}
122+
123+
private static DateFormat createDateFormat() {
124+
return new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
125+
}
115126
}

src/test/java/org/vafer/jdeb/changes/ChangesFileBuilderTestCase.java

+50
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,34 @@
1616
package org.vafer.jdeb.changes;
1717

1818
import java.io.ByteArrayInputStream;
19+
import java.util.TimeZone;
1920

2021
import static java.nio.charset.StandardCharsets.*;
2122
import static org.junit.Assert.assertEquals;
2223
import static org.junit.Assert.assertNotNull;
24+
import org.junit.After;
25+
import org.junit.Before;
2326
import org.junit.Test;
2427
import org.vafer.jdeb.debian.BinaryPackageControlFile;
2528
import org.vafer.jdeb.debian.ChangesFile;
2629

2730
public class ChangesFileBuilderTestCase {
2831

32+
private TimeZone defaultTimeZone;
33+
34+
@Before
35+
public void before() {
36+
defaultTimeZone = TimeZone.getDefault();
37+
}
38+
39+
@After
40+
public void after() {
41+
TimeZone.setDefault(defaultTimeZone);
42+
}
43+
2944
@Test
3045
public void testChangedByNotSet() throws Exception {
46+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
3147

3248
final String input =
3349
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low\n" +
@@ -44,6 +60,7 @@ public void testChangedByNotSet() throws Exception {
4460

4561
assertNotNull(changeSets);
4662
assertEquals(1, changeSets.length);
63+
assertEquals(1168718400000L, changeSets[0].getDate().getTime());
4764

4865
ChangesFile changesFile = new ChangesFile();
4966
changesFile.setChanges(provider.getChangesSets());
@@ -55,6 +72,7 @@ public void testChangedByNotSet() throws Exception {
5572

5673
@Test
5774
public void testChangedByFromControl() throws Exception {
75+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
5876

5977
final String input =
6078
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low\n" +
@@ -72,6 +90,7 @@ public void testChangedByFromControl() throws Exception {
7290

7391
assertNotNull(changeSets);
7492
assertEquals(1, changeSets.length);
93+
assertEquals(1168718400000L, changeSets[0].getDate().getTime());
7594

7695
ChangesFile changesFile = new ChangesFile();
7796
changesFile.setChanges(provider.getChangesSets());
@@ -83,6 +102,7 @@ public void testChangedByFromControl() throws Exception {
83102

84103
@Test
85104
public void testChangedByFromChangesProvider() throws Exception {
105+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
86106

87107
final String input =
88108
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low, by=mrasko@test.com\n" +
@@ -100,6 +120,7 @@ public void testChangedByFromChangesProvider() throws Exception {
100120

101121
assertNotNull(changeSets);
102122
assertEquals(1, changeSets.length);
123+
assertEquals(1168718400000L, changeSets[0].getDate().getTime());
103124

104125
ChangesFile changesFile = new ChangesFile();
105126
changesFile.setChanges(provider.getChangesSets());
@@ -108,4 +129,33 @@ public void testChangedByFromChangesProvider() throws Exception {
108129
assertNotNull(changesFile);
109130
assertEquals("mrasko@test.com", changesFile.get("Changed-By"));
110131
}
132+
133+
@Test
134+
public void testReproducible() throws Exception {
135+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
136+
137+
final String input =
138+
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low\n" +
139+
" * change1\n" +
140+
" * change2\n";
141+
142+
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
143+
packageControlFile.set("Package", "package");
144+
packageControlFile.set("Version", "version");
145+
packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200");
146+
147+
final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes(UTF_8)), packageControlFile, 1175385600000L);
148+
final ChangeSet[] changeSets = provider.getChangesSets();
149+
150+
assertNotNull(changeSets);
151+
assertEquals(1, changeSets.length);
152+
assertEquals(1168696800000L, changeSets[0].getDate().getTime());
153+
154+
ChangesFile changesFile = new ChangesFile();
155+
changesFile.setChanges(provider.getChangesSets());
156+
changesFile.initialize(packageControlFile);
157+
158+
assertNotNull(changesFile);
159+
assertEquals(null, changesFile.get("Changed-By"));
160+
}
111161
}

src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java

+51
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
package org.vafer.jdeb.changes;
1717

1818
import java.io.ByteArrayInputStream;
19+
import java.util.TimeZone;
1920

21+
import org.junit.After;
22+
import org.junit.Before;
2023
import org.junit.Test;
2124
import org.junit.Assert;
2225

@@ -26,8 +29,21 @@
2629

2730
public final class TextfileChangesProviderTestCase extends Assert {
2831

32+
private TimeZone defaultTimeZone;
33+
34+
@Before
35+
public void before() {
36+
defaultTimeZone = TimeZone.getDefault();
37+
}
38+
39+
@After
40+
public void after() {
41+
TimeZone.setDefault(defaultTimeZone);
42+
}
43+
2944
@Test
3045
public void testParsing() throws Exception {
46+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
3147

3248
final String input =
3349
" * change1\n" +
@@ -50,10 +66,13 @@ public void testParsing() throws Exception {
5066

5167
assertNotNull(changeSets);
5268
assertEquals(3, changeSets.length);
69+
assertEquals(1168718400000L, changeSets[1].getDate().getTime());
70+
assertEquals(1168452000000L, changeSets[2].getDate().getTime());
5371
}
5472

5573
@Test
5674
public void testDistributionFromChangesProvider() throws Exception {
75+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
5776

5877
final String input =
5978
"release distribution=production\n" +
@@ -79,7 +98,39 @@ public void testDistributionFromChangesProvider() throws Exception {
7998

8099
assertEquals("production", changeSets[0].getDistribution());
81100
assertEquals("staging", changeSets[1].getDistribution());
101+
assertEquals(1168718400000L, changeSets[1].getDate().getTime());
82102
assertEquals("development", changeSets[2].getDistribution());
103+
assertEquals(1168452000000L, changeSets[2].getDate().getTime());
104+
}
105+
106+
@Test
107+
public void testReproducible() throws Exception {
108+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
109+
110+
final String input =
111+
" * change1\n" +
112+
" * change2\n" +
113+
"release date=14:00 13.01.2007, version=12324, urgency=low, by=tcurdt@joost.com\n" +
114+
" * change1\n" +
115+
" * change2\n" +
116+
"release date=12:00 10.01.2007, version=10324, urgency=low, by=tcurdt@joost.com\n" +
117+
" * change1\n" +
118+
" * change2\n";
119+
120+
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
121+
packageControlFile.set("Package", "package");
122+
packageControlFile.set("Version", "version");
123+
packageControlFile.set("Distribution", "distribution");
124+
packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200");
125+
126+
final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes(UTF_8)), packageControlFile, 1175385600000L);
127+
final ChangeSet[] changeSets = provider.getChangesSets();
128+
129+
assertNotNull(changeSets);
130+
assertEquals(3, changeSets.length);
131+
assertEquals(1175385600000L, changeSets[0].getDate().getTime());
132+
assertEquals(1168696800000L, changeSets[1].getDate().getTime());
133+
assertEquals(1168430400000L, changeSets[2].getDate().getTime());
83134
}
84135

85136
}

src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java

+31
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,30 @@
1616

1717
package org.vafer.jdeb.debian;
1818

19+
import java.util.Date;
20+
import java.util.TimeZone;
21+
22+
import org.junit.After;
23+
import org.junit.Before;
1924
import org.junit.Test;
2025
import org.junit.Assert;
2126

2227
import org.vafer.jdeb.changes.ChangeSet;
2328

2429
public final class ChangesFileTestCase extends Assert {
2530

31+
private TimeZone defaultTimeZone;
32+
33+
@Before
34+
public void before() {
35+
defaultTimeZone = TimeZone.getDefault();
36+
}
37+
38+
@After
39+
public void after() {
40+
TimeZone.setDefault(defaultTimeZone);
41+
}
42+
2643
@Test
2744
public void testToString() throws Exception {
2845
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
@@ -38,4 +55,18 @@ public void testToString() throws Exception {
3855
assertEquals("1.0", changes.get("Version"));
3956
assertEquals("This is a user defined field.", changes.get("UserDefinedField"));
4057
}
58+
59+
@Test
60+
public void testFormatDate() {
61+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
62+
63+
assertEquals("Mon, 26 Aug 2024 09:00:00 -0500", ChangesFile.formatDate(new Date(1724680800000L)));
64+
}
65+
66+
@Test
67+
public void testFormatDateUTC() {
68+
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));
69+
70+
assertEquals("Mon, 26 Aug 2024 14:00:00 +0000", ChangesFile.formatDateUTC(new Date(1724680800000L)));
71+
}
4172
}

0 commit comments

Comments
 (0)