Skip to content

Commit

Permalink
Make changes file reproducible (#712)
Browse files Browse the repository at this point in the history
  • Loading branch information
norrisjeremy authored and tcurdt committed Nov 1, 2024
1 parent 7d59333 commit 12fea7b
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/it/project-build-outputTimestamp/verify.groovy
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import java.nio.file.Files
import org.apache.commons.compress.archivers.ar.ArArchiveEntry
import org.apache.commons.compress.archivers.ar.ArArchiveInputStream

Expand All @@ -8,3 +9,8 @@ ArArchiveEntry entry
while ((entry = is.getNextEntry()) != null) {
assert entry.getLastModifiedDate().getTime() == 1724680800000L
}

File changes = new File( basedir, 'target/jdeb-it_1.0_all.changes' )
assert changes.exists();
List<String> lines = Files.readAllLines(changes.toPath())
assert "Date: Mon, 26 Aug 2024 14:00:00 +0000".equals(lines.get(1))
8 changes: 7 additions & 1 deletion src/main/java/org/vafer/jdeb/ChangesFileBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@
*/
class ChangesFileBuilder {

private final Long outputTimestampMs;

ChangesFileBuilder(Long outputTimestampMs) {
this.outputTimestampMs = outputTimestampMs;
}

public ChangesFile createChanges(BinaryPackageControlFile packageControlFile, File binaryPackage, ChangesProvider changesProvider) throws IOException, PackagingException {

ChangesFile changesFile = new ChangesFile();
changesFile.setChanges(changesProvider.getChangesSets());
changesFile.initialize(packageControlFile);

changesFile.set("Date", ChangesFile.formatDate(new Date()));
changesFile.set("Date", outputTimestampMs == null ? ChangesFile.formatDate(new Date()) : ChangesFile.formatDateUTC(new Date(outputTimestampMs)));

try {
// compute the checksums of the binary package
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/vafer/jdeb/DebMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -359,15 +359,15 @@ private void makeChangesFiles(final BinaryPackageControlFile packageControlFile)

if (changesIn != null && changesIn.exists()) {
// read the changes form a textfile provider
changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageControlFile);
changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageControlFile, outputTimestampMs);
} else {
// create an empty changelog
changesProvider = new ChangesProvider() {
public ChangeSet[] getChangesSets() {
return new ChangeSet[] {
new ChangeSet(packageControlFile.get("Package"),
packageControlFile.get("Version"),
new Date(),
outputTimestampMs == null ? new Date() : new Date(outputTimestampMs),
packageControlFile.get("Distribution"),
packageControlFile.get("Urgency"),
packageControlFile.get("Maintainer"),
Expand All @@ -377,7 +377,7 @@ public ChangeSet[] getChangesSets() {
};
}

ChangesFileBuilder builder = new ChangesFileBuilder();
ChangesFileBuilder builder = new ChangesFileBuilder(outputTimestampMs);
ChangesFile changesFile = builder.createChanges(packageControlFile, deb, changesProvider);

final int digestCode = PGPSigner.getDigestCode(signDigest);
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.TimeZone;

import org.vafer.jdeb.debian.BinaryPackageControlFile;

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

private final ChangeSet[] changeSets;

private DateFormat fmt = new SimpleDateFormat("HH:mm dd.MM.yyyy");
private final DateFormat fmt;

public TextfileChangesProvider( final InputStream pInput, final BinaryPackageControlFile packageControlFile ) throws IOException, ParseException {
this(pInput, packageControlFile, null);
}

public TextfileChangesProvider( final InputStream pInput, final BinaryPackageControlFile packageControlFile, final Long outputTimestampMs ) throws IOException, ParseException {

fmt = new SimpleDateFormat("HH:mm dd.MM.yyyy");
if (outputTimestampMs != null) {
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
}

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

String packageName = packageControlFile.get("Package");
String version = packageControlFile.get("Version");
Date date = new Date();
Date date = outputTimestampMs == null ? new Date() : new Date(outputTimestampMs);
String distribution = packageControlFile.get("Distribution");
String urgency = packageControlFile.get("Urgency");
String changedBy = packageControlFile.get("Maintainer");
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/org/vafer/jdeb/debian/ChangesFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Date;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.TimeZone;

/**
* Reflecting a changes file
Expand Down Expand Up @@ -109,7 +110,17 @@ protected char getUserDefinedFieldLetter() {
}

public static String formatDate(Date date) {
final DateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
final DateFormat format = createDateFormat();
return format.format(date);
}

public static String formatDateUTC(Date date) {
final DateFormat format = createDateFormat();
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.format(date);
}

private static DateFormat createDateFormat() {
return new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,34 @@
package org.vafer.jdeb.changes;

import java.io.ByteArrayInputStream;
import java.util.TimeZone;

import static java.nio.charset.StandardCharsets.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.vafer.jdeb.debian.BinaryPackageControlFile;
import org.vafer.jdeb.debian.ChangesFile;

public class ChangesFileBuilderTestCase {

private TimeZone defaultTimeZone;

@Before
public void before() {
defaultTimeZone = TimeZone.getDefault();
}

@After
public void after() {
TimeZone.setDefault(defaultTimeZone);
}

@Test
public void testChangedByNotSet() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

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

assertNotNull(changeSets);
assertEquals(1, changeSets.length);
assertEquals(1168718400000L, changeSets[0].getDate().getTime());

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

@Test
public void testChangedByFromControl() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

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

assertNotNull(changeSets);
assertEquals(1, changeSets.length);
assertEquals(1168718400000L, changeSets[0].getDate().getTime());

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

@Test
public void testChangedByFromChangesProvider() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

final String input =
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low, [email protected]\n" +
Expand All @@ -100,6 +120,7 @@ public void testChangedByFromChangesProvider() throws Exception {

assertNotNull(changeSets);
assertEquals(1, changeSets.length);
assertEquals(1168718400000L, changeSets[0].getDate().getTime());

ChangesFile changesFile = new ChangesFile();
changesFile.setChanges(provider.getChangesSets());
Expand All @@ -108,4 +129,33 @@ public void testChangedByFromChangesProvider() throws Exception {
assertNotNull(changesFile);
assertEquals("[email protected]", changesFile.get("Changed-By"));
}

@Test
public void testReproducible() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

final String input =
"release distribution=production, date=14:00 13.01.2007, version=12324, urgency=low\n" +
" * change1\n" +
" * change2\n";

BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
packageControlFile.set("Package", "package");
packageControlFile.set("Version", "version");
packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200");

final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes(UTF_8)), packageControlFile, 1175385600000L);
final ChangeSet[] changeSets = provider.getChangesSets();

assertNotNull(changeSets);
assertEquals(1, changeSets.length);
assertEquals(1168696800000L, changeSets[0].getDate().getTime());

ChangesFile changesFile = new ChangesFile();
changesFile.setChanges(provider.getChangesSets());
changesFile.initialize(packageControlFile);

assertNotNull(changesFile);
assertEquals(null, changesFile.get("Changed-By"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
package org.vafer.jdeb.changes;

import java.io.ByteArrayInputStream;
import java.util.TimeZone;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.Assert;

Expand All @@ -26,8 +29,21 @@

public final class TextfileChangesProviderTestCase extends Assert {

private TimeZone defaultTimeZone;

@Before
public void before() {
defaultTimeZone = TimeZone.getDefault();
}

@After
public void after() {
TimeZone.setDefault(defaultTimeZone);
}

@Test
public void testParsing() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

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

assertNotNull(changeSets);
assertEquals(3, changeSets.length);
assertEquals(1168718400000L, changeSets[1].getDate().getTime());
assertEquals(1168452000000L, changeSets[2].getDate().getTime());
}

@Test
public void testDistributionFromChangesProvider() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

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

assertEquals("production", changeSets[0].getDistribution());
assertEquals("staging", changeSets[1].getDistribution());
assertEquals(1168718400000L, changeSets[1].getDate().getTime());
assertEquals("development", changeSets[2].getDistribution());
assertEquals(1168452000000L, changeSets[2].getDate().getTime());
}

@Test
public void testReproducible() throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

final String input =
" * change1\n" +
" * change2\n" +
"release date=14:00 13.01.2007, version=12324, urgency=low, [email protected]\n" +
" * change1\n" +
" * change2\n" +
"release date=12:00 10.01.2007, version=10324, urgency=low, [email protected]\n" +
" * change1\n" +
" * change2\n";

BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
packageControlFile.set("Package", "package");
packageControlFile.set("Version", "version");
packageControlFile.set("Distribution", "distribution");
packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200");

final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes(UTF_8)), packageControlFile, 1175385600000L);
final ChangeSet[] changeSets = provider.getChangesSets();

assertNotNull(changeSets);
assertEquals(3, changeSets.length);
assertEquals(1175385600000L, changeSets[0].getDate().getTime());
assertEquals(1168696800000L, changeSets[1].getDate().getTime());
assertEquals(1168430400000L, changeSets[2].getDate().getTime());
}

}
31 changes: 31 additions & 0 deletions src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,30 @@

package org.vafer.jdeb.debian;

import java.util.Date;
import java.util.TimeZone;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.Assert;

import org.vafer.jdeb.changes.ChangeSet;

public final class ChangesFileTestCase extends Assert {

private TimeZone defaultTimeZone;

@Before
public void before() {
defaultTimeZone = TimeZone.getDefault();
}

@After
public void after() {
TimeZone.setDefault(defaultTimeZone);
}

@Test
public void testToString() throws Exception {
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
Expand All @@ -38,4 +55,18 @@ public void testToString() throws Exception {
assertEquals("1.0", changes.get("Version"));
assertEquals("This is a user defined field.", changes.get("UserDefinedField"));
}

@Test
public void testFormatDate() {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

assertEquals("Mon, 26 Aug 2024 09:00:00 -0500", ChangesFile.formatDate(new Date(1724680800000L)));
}

@Test
public void testFormatDateUTC() {
TimeZone.setDefault(TimeZone.getTimeZone("America/Chicago"));

assertEquals("Mon, 26 Aug 2024 14:00:00 +0000", ChangesFile.formatDateUTC(new Date(1724680800000L)));
}
}

0 comments on commit 12fea7b

Please sign in to comment.