From ac57eabcb65f0225d48c1fab0990a38acc5fa205 Mon Sep 17 00:00:00 2001
From: baizg1107 <preloyalwhite@163.com>
Date: Wed, 23 Mar 2022 17:25:38 +0800
Subject: [PATCH] make archives reproducible

---
 pom.xml                                       |  8 +-
 .../projects/reproducible/invoker.properties  | 18 +++++
 src/it/projects/reproducible/pom.xml          | 71 ++++++++++++++++++
 .../reproducible/src/assemble/src.xml         | 47 ++++++++++++
 .../src/main/resources/Uppercase.txt          | 17 +++++
 .../src/main/resources/dir-A/A2.txt           | 17 +++++
 .../src/main/resources/dir-A/A4.txt           | 17 +++++
 .../src/main/resources/dir-A/a1.txt           | 34 +++++++++
 .../src/main/resources/dir-A/a3.txt           | 17 +++++
 .../src/main/resources/dir-C/C.txt            | 17 +++++
 .../src/main/resources/dir-b/B2/B2.txt        | 17 +++++
 .../src/main/resources/dir-b/B4/B4.txt        | 17 +++++
 .../src/main/resources/dir-b/b.txt            | 17 +++++
 .../src/main/resources/dir-b/b1/b1.txt        | 17 +++++
 .../src/main/resources/dir-b/b3/b3.txt        | 17 +++++
 .../src/main/resources/dir-d/d.txt            | 17 +++++
 .../src/main/resources/executable.txt         | 17 +++++
 .../src/main/resources/lowercase.txt          | 17 +++++
 src/it/projects/reproducible/verify.groovy    | 30 ++++++++
 .../assembly/archive/AssemblyArchiver.java    |  6 +-
 .../archive/DefaultAssemblyArchiver.java      | 14 +++-
 .../archiver/AssemblyProxyArchiver.java       | 74 +++++++++++++++++++
 .../assembly/mojos/AbstractAssemblyMojo.java  | 17 ++++-
 .../archive/DefaultAssemblyArchiverTest.java  | 12 +--
 24 files changed, 536 insertions(+), 16 deletions(-)
 create mode 100644 src/it/projects/reproducible/invoker.properties
 create mode 100644 src/it/projects/reproducible/pom.xml
 create mode 100644 src/it/projects/reproducible/src/assemble/src.xml
 create mode 100644 src/it/projects/reproducible/src/main/resources/Uppercase.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-A/A2.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-A/A4.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-A/a1.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-A/a3.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-C/C.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-b/B2/B2.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-b/B4/B4.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-b/b.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-b/b1/b1.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-b/b3/b3.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/dir-d/d.txt
 create mode 100755 src/it/projects/reproducible/src/main/resources/executable.txt
 create mode 100644 src/it/projects/reproducible/src/main/resources/lowercase.txt
 create mode 100644 src/it/projects/reproducible/verify.groovy

diff --git a/pom.xml b/pom.xml
index 477c9a5..fc2ec39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,7 +59,7 @@ under the License.
   <properties>
     <javaVersion>7</javaVersion>
     <mdoVersion>2.0.0</mdoVersion>
-    <mavenArchiverVersion>3.2.0</mavenArchiverVersion>
+    <mavenArchiverVersion>3.5.0</mavenArchiverVersion>
     <mavenFilteringVersion>3.1.1</mavenFilteringVersion>
     <mavenVersion>3.0</mavenVersion>
     <testOutputToFile>true</testOutputToFile>
@@ -157,7 +157,7 @@ under the License.
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-io</artifactId>
-      <version>3.0.0</version>
+      <version>3.2.0</version>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
@@ -167,7 +167,7 @@ under the License.
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
-      <version>3.1.0</version>
+      <version>3.3.0</version>
     </dependency>
     <dependency>
       <groupId>commons-codec</groupId>
@@ -262,7 +262,6 @@ under the License.
       <plugin>
         <groupId>org.codehaus.plexus</groupId>
         <artifactId>plexus-component-metadata</artifactId>
-        <version>1.7</version>
         <executions>
           <execution>
             <id>descriptors</id>
@@ -403,6 +402,7 @@ under the License.
                     <pomInclude>projects/*/*/pom.xml</pomInclude>
                     <pomInclude>projects/descriptor-refs/*/*/pom.xml</pomInclude>
                     <pomInclude>projects/multimodule/multimodule-siblingParent/parent/pom.xml</pomInclude>
+                    <pomInclude>projects/reproducible/pom.xml</pomInclude>
                   </pomIncludes>
                   <streamLogs>${it.streamLogs}</streamLogs>
                   <pomExcludes>
diff --git a/src/it/projects/reproducible/invoker.properties b/src/it/projects/reproducible/invoker.properties
new file mode 100644
index 0000000..cec67fc
--- /dev/null
+++ b/src/it/projects/reproducible/invoker.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.goals=org.apache.maven.plugins:maven-assembly-plugin:${testVersion}:single deploy:deploy
diff --git a/src/it/projects/reproducible/pom.xml b/src/it/projects/reproducible/pom.xml
new file mode 100644
index 0000000..e21fba1
--- /dev/null
+++ b/src/it/projects/reproducible/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.plugin.assembly.test</groupId>
+    <artifactId>it-project-parent</artifactId>
+    <version>1</version>
+  </parent>
+
+  <groupId>org.apache.maven.its</groupId>
+  <artifactId>reproducible</artifactId>
+  <version>1.0</version>
+
+  <name>Test for reproducibility of assembly archives</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.build.outputTimestamp>2019-08-21T18:28:52Z</project.build.outputTimestamp>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <configuration>
+          <tarLongFileMode>posix</tarLongFileMode>
+          <descriptors>
+            <descriptor>src/assemble/src.xml</descriptor>
+          </descriptors>
+          <archive>
+            <manifest>
+              <!-- remove default entries since it contains "Created-By: Maven Source Plugin <current plugin version>"
+                   which varies over time in this IT -->
+              <addDefaultEntries>false</addDefaultEntries>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <version>2.8.2</version>
+        <configuration>
+          <!-- Deployments will be written to ${basedir}/target -->
+          <altDeploymentRepository>mine::default::file://${basedir}/target/repo</altDeploymentRepository>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/src/it/projects/reproducible/src/assemble/src.xml b/src/it/projects/reproducible/src/assemble/src.xml
new file mode 100644
index 0000000..3f4ab15
--- /dev/null
+++ b/src/it/projects/reproducible/src/assemble/src.xml
@@ -0,0 +1,47 @@
+<?xml version='1.0'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+  <id>src</id>
+  <formats>
+    <format>zip</format>
+    <format>tar</format>
+    <format>jar</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <fileSets>
+    <fileSet>
+      <outputDirectory></outputDirectory>
+      <directory>src</directory>
+      <filtered>true</filtered>
+      <lineEnding>lf</lineEnding>
+    </fileSet>
+  </fileSets>
+  <files>
+    <file>
+      <source>src/main/resources/executable.txt</source>
+      <fileMode>0755</fileMode>
+      <filtered>true</filtered>
+      <lineEnding>lf</lineEnding>
+    </file>
+  </files>
+</assembly>
diff --git a/src/it/projects/reproducible/src/main/resources/Uppercase.txt b/src/it/projects/reproducible/src/main/resources/Uppercase.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/Uppercase.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-A/A2.txt b/src/it/projects/reproducible/src/main/resources/dir-A/A2.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-A/A2.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-A/A4.txt b/src/it/projects/reproducible/src/main/resources/dir-A/A4.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-A/A4.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-A/a1.txt b/src/it/projects/reproducible/src/main/resources/dir-A/a1.txt
new file mode 100644
index 0000000..ca0e172
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-A/a1.txt
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-A/a3.txt b/src/it/projects/reproducible/src/main/resources/dir-A/a3.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-A/a3.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-C/C.txt b/src/it/projects/reproducible/src/main/resources/dir-C/C.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-C/C.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-b/B2/B2.txt b/src/it/projects/reproducible/src/main/resources/dir-b/B2/B2.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-b/B2/B2.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-b/B4/B4.txt b/src/it/projects/reproducible/src/main/resources/dir-b/B4/B4.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-b/B4/B4.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-b/b.txt b/src/it/projects/reproducible/src/main/resources/dir-b/b.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-b/b.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-b/b1/b1.txt b/src/it/projects/reproducible/src/main/resources/dir-b/b1/b1.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-b/b1/b1.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-b/b3/b3.txt b/src/it/projects/reproducible/src/main/resources/dir-b/b3/b3.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-b/b3/b3.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/dir-d/d.txt b/src/it/projects/reproducible/src/main/resources/dir-d/d.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/dir-d/d.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/executable.txt b/src/it/projects/reproducible/src/main/resources/executable.txt
new file mode 100755
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/executable.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/src/main/resources/lowercase.txt b/src/it/projects/reproducible/src/main/resources/lowercase.txt
new file mode 100644
index 0000000..00ae6c0
--- /dev/null
+++ b/src/it/projects/reproducible/src/main/resources/lowercase.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
diff --git a/src/it/projects/reproducible/verify.groovy b/src/it/projects/reproducible/verify.groovy
new file mode 100644
index 0000000..2693e3a
--- /dev/null
+++ b/src/it/projects/reproducible/verify.groovy
@@ -0,0 +1,30 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+//import java.util.zip.*;
+import org.apache.commons.compress.archivers.zip.*;
+
+File deployDir = new File( basedir, 'target/repo/org/apache/maven/its/reproducible/1.0' )
+
+assert deployDir.exists()
+
+assert new File( deployDir, 'reproducible-1.0-src.zip.sha1' ).text == '5ce34fc133d47cbc9c81195877dbe10b9ec7d864'
+assert new File( deployDir, 'reproducible-1.0-src.tar.sha1' ).text == '0b9dc1da069705a93b4954a198c18bd248822bf8'
+assert new File( deployDir, 'reproducible-1.0-src.jar.sha1' ).text == '9b41cf2a80bc91c1f56b769bbef61c5dfd57974c'
diff --git a/src/main/java/org/apache/maven/plugins/assembly/archive/AssemblyArchiver.java b/src/main/java/org/apache/maven/plugins/assembly/archive/AssemblyArchiver.java
index e13cf16..4e2a83e 100644
--- a/src/main/java/org/apache/maven/plugins/assembly/archive/AssemblyArchiver.java
+++ b/src/main/java/org/apache/maven/plugins/assembly/archive/AssemblyArchiver.java
@@ -25,6 +25,7 @@ import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
 import org.apache.maven.plugins.assembly.model.Assembly;
 
 import java.io.File;
+import java.util.Date;
 
 /**
  * Creates an archive
@@ -55,12 +56,13 @@ public interface AssemblyArchiver
      * @param configSource          The {@link org.apache.maven.plugins.assembly.AssemblerConfigurationSource}
      * @param recompressZippedFiles recompress zipped files.
      * @param mergeManifestMode     How to handle already existing Manifest files (skip, merge, mergewithoutmain)
+     * @param sourceDateEpoch       Timestamp for reproducible archive entries
      * @return The resulting archive file.
      * @throws ArchiveCreationException                                                 when creation fails
      * @throws org.apache.maven.plugins.assembly.format.AssemblyFormattingException     when formatting fails
-     * @throws org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException when the configurationis bad
+     * @throws org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException when the configuration is bad
      */
     File createArchive( Assembly assembly, String fullName, String format, AssemblerConfigurationSource configSource,
-                        boolean recompressZippedFiles, String mergeManifestMode )
+                        boolean recompressZippedFiles, String mergeManifestMode, Date outputTimestamp )
         throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException;
 }
diff --git a/src/main/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiver.java b/src/main/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiver.java
index 2aa2c90..4f4b0de 100644
--- a/src/main/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiver.java
+++ b/src/main/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiver.java
@@ -73,6 +73,8 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -134,7 +136,7 @@ public class DefaultAssemblyArchiver
     @Override
     public File createArchive( final Assembly assembly, final String fullName, final String format,
                                final AssemblerConfigurationSource configSource, boolean recompressZippedFiles,
-                               String mergeManifestMode )
+                               String mergeManifestMode, Date outputTimestamp )
         throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException
     {
         validate( assembly );
@@ -172,7 +174,7 @@ public class DefaultAssemblyArchiver
 
             final Archiver archiver =
                 createArchiver( format, assembly.isIncludeBaseDirectory(), basedir, configSource, containerHandlers,
-                                recompressZippedFiles, mergeManifestMode );
+                                recompressZippedFiles, mergeManifestMode, outputTimestamp );
 
             archiver.setDestFile( destFile );
 
@@ -289,7 +291,7 @@ public class DefaultAssemblyArchiver
     protected Archiver createArchiver( final String format, final boolean includeBaseDir, final String finalName,
                                        final AssemblerConfigurationSource configSource,
                                        final List<ContainerDescriptorHandler> containerHandlers,
-                                       boolean recompressZippedFiles, String mergeManifestMode )
+                                       boolean recompressZippedFiles, String mergeManifestMode, Date outputTimestamp )
         throws NoSuchArchiverException
     {
         Archiver archiver;
@@ -351,6 +353,12 @@ public class DefaultAssemblyArchiver
         archiver.setIgnorePermissions( configSource.isIgnorePermissions() );
         archiver.setForced( !configSource.isUpdateOnly() );
 
+        // configure for Reproducible Builds based on outputTimestamp value
+        if ( outputTimestamp != null )
+        {
+            archiver.configureReproducible( outputTimestamp );
+        }
+
         return archiver;
     }
 
diff --git a/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java b/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java
index fe0c72e..1507920 100644
--- a/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java
+++ b/src/main/java/org/apache/maven/plugins/assembly/archive/archiver/AssemblyProxyArchiver.java
@@ -44,6 +44,8 @@ import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -1032,4 +1034,76 @@ public class AssemblyProxyArchiver
         }
     }
 
+    @Override
+    public void setLastModifiedDate( Date lastModifiedDate )
+    {
+        delegate.setLastModifiedDate( lastModifiedDate );
+    }
+
+    @Override
+    public Date getLastModifiedDate()
+    {
+        return delegate.getLastModifiedDate();
+    }
+
+    @Override
+    public void setFilenameComparator( Comparator<String> filenameComparator )
+    {
+        delegate.setFilenameComparator( filenameComparator );
+    }
+
+    @Override
+    public void configureReproducible( Date outputTimestamp )
+    {
+        delegate.configureReproducible( outputTimestamp );
+    }
+
+    @Override
+    public void setOverrideUid( int uid )
+    {
+        delegate.setOverrideUid( uid );
+    }
+
+    @Override
+    public void setOverrideUserName( String userName )
+    {
+        delegate.setOverrideUserName( userName );
+    }
+
+    @Override
+    public int getOverrideUid()
+    {
+        return delegate.getOverrideUid();
+    }
+
+    @Override
+    public String getOverrideUserName()
+    {
+        return delegate.getOverrideUserName();
+    }
+
+    @Override
+    public void setOverrideGid( int gid )
+    {
+        delegate.setOverrideGid( gid );
+    }
+
+    @Override
+    public void setOverrideGroupName( String groupName )
+    {
+        delegate.setOverrideGroupName( groupName );
+    }
+
+    @Override
+    public int getOverrideGid()
+    {
+        return delegate.getOverrideGid();
+    }
+
+    @Override
+    public String getOverrideGroupName()
+    {
+        return delegate.getOverrideGroupName();
+    }
+
 }
diff --git a/src/main/java/org/apache/maven/plugins/assembly/mojos/AbstractAssemblyMojo.java b/src/main/java/org/apache/maven/plugins/assembly/mojos/AbstractAssemblyMojo.java
index 26c0087..8a3e7cf 100644
--- a/src/main/java/org/apache/maven/plugins/assembly/mojos/AbstractAssemblyMojo.java
+++ b/src/main/java/org/apache/maven/plugins/assembly/mojos/AbstractAssemblyMojo.java
@@ -20,6 +20,7 @@ package org.apache.maven.plugins.assembly.mojos;
  */
 
 import org.apache.maven.archiver.MavenArchiveConfiguration;
+import org.apache.maven.archiver.MavenArchiver;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
@@ -50,6 +51,7 @@ import org.codehaus.plexus.interpolation.fixed.PropertiesBasedValueSource;
 import javax.annotation.Nonnull;
 import java.io.File;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.Properties;
 
@@ -395,6 +397,16 @@ public abstract class AbstractAssemblyMojo
     @Parameter
     private List<String> delimiters;
 
+    /**
+     * Timestamp for reproducible output archive entries, either formatted as ISO 8601
+     * <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
+     * <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
+     *
+     * @since 3.2.0
+     */
+    @Parameter( defaultValue = "${project.build.outputTimestamp}" )
+    private String outputTimestamp;
+
     public static FixedStringSearchInterpolator mainProjectInterpolator( MavenProject mainProject )
     {
         if ( mainProject != null )
@@ -455,6 +467,9 @@ public abstract class AbstractAssemblyMojo
         // TODO: include dependencies marked for distribution under certain formats
         // TODO: how, might we plug this into an installer, such as NSIS?
 
+        MavenArchiver mavenArchiver = new MavenArchiver();
+        Date outputDate = mavenArchiver.parseOutputTimestamp( outputTimestamp );
+
         boolean warnedAboutMainProjectArtifact = false;
         for ( final Assembly assembly : assemblies )
         {
@@ -477,7 +492,7 @@ public abstract class AbstractAssemblyMojo
                 {
                     final File destFile =
                         assemblyArchiver.createArchive( assembly, fullName, format,
-                            this, isRecompressZippedFiles(), getMergeManifestMode() );
+                            this, isRecompressZippedFiles(), getMergeManifestMode(), outputDate );
 
                     final MavenProject project = getProject();
                     final String type = project.getArtifact().getType();
diff --git a/src/test/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiverTest.java b/src/test/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiverTest.java
index b404ab3..3e07c6e 100644
--- a/src/test/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiverTest.java
+++ b/src/test/java/org/apache/maven/plugins/assembly/archive/DefaultAssemblyArchiverTest.java
@@ -127,7 +127,7 @@ public class DefaultAssemblyArchiverTest
         mm.replayAll();
 
         final DefaultAssemblyArchiver archiver = createSubject( macMgr, null, null );
-        archiver.createArchive( new Assembly(), "full-name", "zip", configSource, false, null );
+        archiver.createArchive( new Assembly(), "full-name", "zip", configSource, false, null, null );
 
         mm.verifyAll();
     }
@@ -200,7 +200,7 @@ public class DefaultAssemblyArchiverTest
 
         final DefaultAssemblyArchiver subject = createSubject( macMgr, Collections.singletonList( phase ), null );
 
-        subject.createArchive( assembly, "full-name", "zip", configSource, false, null );
+        subject.createArchive( assembly, "full-name", "zip", configSource, false, null, null );
 
         mm.verifyAll();
     }
@@ -249,7 +249,7 @@ public class DefaultAssemblyArchiverTest
         final DefaultAssemblyArchiver subject =
             createSubject( macArchiverManager, new ArrayList<AssemblyArchiverPhase>(), null );
 
-        subject.createArchiver( "dummy", false, "finalName", configSource, null, false, null );
+        subject.createArchiver( "dummy", false, "finalName", configSource, null, false, null, null );
 
         assertEquals( simpleConfig, archiver.getSimpleConfig() );
 
@@ -277,7 +277,7 @@ public class DefaultAssemblyArchiverTest
 
         final DefaultAssemblyArchiver subject = setupStdExpectations( mm, macArchiverManager, configSource );
 
-        subject.createArchiver( "tar", false, "finalName", configSource, null, false, null );
+        subject.createArchiver( "tar", false, "finalName", configSource, null, false, null, null );
 
         assertNull( ttArchiver.compressionMethod );
         assertEquals( TarLongFileMode.fail, ttArchiver.longFileMode );
@@ -323,7 +323,7 @@ public class DefaultAssemblyArchiverTest
         expect( configSource.getMavenSession() ).andReturn( null ).anyTimes();
         final DefaultAssemblyArchiver subject = setupStdExpectations( mm, macArchiverManager, configSource );
 
-        subject.createArchiver( "war", false, null, configSource, null, false, null );
+        subject.createArchiver( "war", false, null, configSource, null, false, null, null );
 
         assertFalse( twArchiver.ignoreWebxml );
     }
@@ -354,7 +354,7 @@ public class DefaultAssemblyArchiverTest
         final DefaultAssemblyArchiver subject =
             createSubject( macArchiverManager, new ArrayList<AssemblyArchiverPhase>(), null );
 
-        subject.createArchiver( "zip", false, null, configSource, null, false, null );
+        subject.createArchiver( "zip", false, null, configSource, null, false, null, null );
     }
 
     @Test
-- 
2.27.0

