Skip to content

Commit

Permalink
Allow copy all files without timestamp checking by DirectoryArchiver
Browse files Browse the repository at this point in the history
Implements forced options.
  • Loading branch information
slawekjaranowski committed Nov 2, 2023
1 parent 991aa4c commit 25ed6df
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
Expand All @@ -42,6 +43,15 @@
public class DirectoryArchiver extends AbstractArchiver {

private final List<Runnable> directoryChmods = new ArrayList<>();
private long filesCopied;

/**
* Default constructor.
*/
public DirectoryArchiver() {
// preserver default behavior
setForced(false);
}

public void resetArchiver() throws IOException {
cleanUp();
Expand All @@ -67,7 +77,7 @@ public void execute() throws ArchiverException, IOException {
throw new ArchiverException(destDirectory + " is not writable.");
}

getLogger().info("Copying files to " + destDirectory.getAbsolutePath());
getLogger().info("Copying files to {}", destDirectory.getAbsolutePath());

try {
while (iter.hasNext()) {
Expand All @@ -93,6 +103,20 @@ public void execute() throws ArchiverException, IOException {

directoryChmods.forEach(Runnable::run);
directoryChmods.clear();

if (filesCopied > 0) {
getLogger()
.info(
"{} file{} copied to {}",
filesCopied,
filesCopied > 0 ? "s" : "",
destDirectory.getAbsolutePath());
} else {
getLogger().info("All files are uptodate in {}", destDirectory.getAbsolutePath());
}

filesCopied = 0;

} catch (final IOException ioe) {
final String message = "Problem copying files : " + ioe.getMessage();
throw new ArchiverException(message, ioe);
Expand All @@ -118,15 +142,20 @@ protected void copyFile(final ArchiveEntry entry, final String vPath) throws Arc
final File outFile = new File(vPath);

final long inLastModified = in.getLastModified();
final long outLastModified = outFile.lastModified();
if (ResourceUtils.isUptodate(inLastModified, outLastModified)) {
return;

if (!isForced()) {
final long outLastModified = outFile.lastModified();
if (ResourceUtils.isUptodate(inLastModified, outLastModified)) {
return;
}
}

if (!in.isDirectory()) {
makeParentDirectories(outFile);
ResourceUtils.copyFile(entry.getInputStream(), outFile);

try (InputStream input = entry.getInputStream()) {
ResourceUtils.copyFile(input, outFile);
}
filesCopied++;
setFileModes(entry, outFile, inLastModified);
} else { // file is a directory
if (outFile.exists()) {
Expand Down Expand Up @@ -191,4 +220,9 @@ protected void close() throws IOException {}
protected String getArchiveType() {
return "directory";
}

@Override
public boolean isSupportingForced() {
return true;
}
}
35 changes: 7 additions & 28 deletions src/main/java/org/codehaus/plexus/archiver/util/ResourceUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;

import org.codehaus.plexus.components.io.functions.FileSupplier;
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
import org.codehaus.plexus.util.IOUtil;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
* Utility class for work with {@link PlexusIoResource} instances.
Expand All @@ -35,16 +35,7 @@ public static boolean isUptodate(PlexusIoResource source, File destination) {
* the given modification date.
*/
public static boolean isUptodate(PlexusIoResource source, long destinationDate) {
final long s = source.getLastModified();
if (s == PlexusIoResource.UNKNOWN_MODIFICATION_DATE) {
return false;
}

if (destinationDate == 0) {
return false;
}

return destinationDate > s;
return isUptodate(source.getLastModified(), destinationDate);
}

/**
Expand All @@ -60,35 +51,23 @@ public static boolean isUptodate(long sourceDate, long destinationDate) {
return false;
}

return destinationDate > sourceDate;
return destinationDate >= sourceDate;
}

/**
* Copies the sources contents to the given destination file.
*/
public static void copyFile(PlexusIoResource in, File outFile) throws IOException {
try (InputStream input = in.getContents();
OutputStream output = Files.newOutputStream(outFile.toPath())) {
IOUtil.copy(input, output);
try (InputStream input = in.getContents()) {
Files.copy(input, outFile.toPath(), REPLACE_EXISTING);
}
}

/**
* Copies the sources contents to the given destination file.
*/
public static void copyFile(InputStream input, File outFile) throws IOException {
OutputStream output = null;
try {
output = Files.newOutputStream(outFile.toPath());
IOUtil.copy(input, output);
output.close();
output = null;
input.close();
input = null;
} finally {
IOUtil.close(input);
IOUtil.close(output);
}
Files.copy(input, outFile.toPath(), REPLACE_EXISTING);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

import javax.annotation.Nonnull;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.FileTime;

import org.apache.commons.io.FileUtils;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.TestSupport;
import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
Expand All @@ -15,7 +21,7 @@
import org.codehaus.plexus.components.io.resources.PlexusIoResource;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;

class DirectoryArchiverUnpackJarTest extends TestSupport {

Expand All @@ -36,25 +42,94 @@ public InputStream transform(@Nonnull PlexusIoResource resource, @Nonnull InputS
@Test
void test_dependency_sets_depSet_unpacked_rdonly() throws Exception {
File src = new File("src/test/resources/unpack_issue.jar");
assertTrue(src.exists());
File dest = new File("target/depset_unpack");
FileUtils.deleteDirectory(dest);
assertThat(src).isFile();

Archiver archiver = createArchiver(src, dest);
archiver.setDefaultDirectoryMode(0555);
archiver.setDirectoryMode(0555); // causes permission denied if bug is not fixed.
archiver.createArchive();
assertThat(new File(dest, "child-1/META-INF/MANIFEST.MF")).isFile();

// make them writeable or mvn clean will fail
ArchiveEntryUtils.chmod(new File(dest, "child-1/META-INF"), 0777);
ArchiveEntryUtils.chmod(new File(dest, "child-1/META-INF/maven"), 0777);
ArchiveEntryUtils.chmod(new File(dest, "child-1/META-INF/maven/test"), 0777);
ArchiveEntryUtils.chmod(new File(dest, "child-1/META-INF/maven/test/child1"), 0777);
ArchiveEntryUtils.chmod(new File(dest, "child-1/assembly-resources"), 0777);
}

@Test
void test_dependency_sets_depSet_unpacked_by_default_dont_override() throws Exception {

File src = new File("src/test/resources/unpack_issue.jar");
File dest = new File("target/depset_unpack_dont_override");
FileUtils.deleteDirectory(dest);

Archiver archiver = createArchiver(src, dest);
archiver.createArchive();

File manifestFile = new File(dest, "child-1/META-INF/MANIFEST.MF");
assertThat(manifestFile).content().hasLineCount(6);

// change content of one file
overwriteFileContent(manifestFile.toPath());
assertThat(manifestFile).content().hasLineCount(1);

archiver = createArchiver(src, dest);
archiver.createArchive();

// content was not changed
assertThat(manifestFile).content().hasLineCount(1);
}

@Test
void test_dependency_sets_depSet_force_unpacked() throws Exception {

File src = new File("src/test/resources/unpack_issue.jar");
File dest = new File("target/depset_unpack_force");
FileUtils.deleteDirectory(dest);

Archiver archiver = createArchiver(src, dest);
archiver.createArchive();

File manifestFile = new File(dest, "child-1/META-INF/MANIFEST.MF");
assertThat(manifestFile).content().hasLineCount(6);

// change content of one file
overwriteFileContent(manifestFile.toPath());
assertThat(manifestFile).content().hasLineCount(1);

archiver = createArchiver(src, dest);
archiver.setForced(true);
archiver.createArchive();

// content was changed
assertThat(manifestFile).content().hasLineCount(6);
}

private Archiver createArchiver(File src, File dest) {
assertThat(src).isFile();
DefaultArchivedFileSet afs = DefaultArchivedFileSet.archivedFileSet(src);
afs.setIncludes(DEFAULT_INCLUDES_ARRAY);
afs.setExcludes(null);
afs.setPrefix("child-1/");
afs.setStreamTransformer(new IdentityTransformer());
Archiver archiver = (Archiver) lookup(Archiver.class, "dir");
archiver.setDefaultDirectoryMode(0555);
archiver.setDirectoryMode(0555); // causes permission denied if bug is not fixed.
archiver.setDestFile(new File("target/depset_unpack"));
archiver.addArchivedFileSet(afs, Charset.forName("UTF-8"));
archiver.createArchive();
assertTrue(new File("target/depset_unpack/child-1/META-INF/MANIFEST.MF").exists());
Archiver archiver = lookup(Archiver.class, "dir");
archiver.setDestFile(dest);
archiver.addArchivedFileSet(afs, StandardCharsets.UTF_8);
return archiver;
}

// make them writeable or mvn clean will fail
ArchiveEntryUtils.chmod(new File("target/depset_unpack/child-1/META-INF"), 0777);
ArchiveEntryUtils.chmod(new File("target/depset_unpack/child-1/META-INF/maven"), 0777);
ArchiveEntryUtils.chmod(new File("target/depset_unpack/child-1/META-INF/maven/test"), 0777);
ArchiveEntryUtils.chmod(new File("target/depset_unpack/child-1/META-INF/maven/test/child1"), 0777);
ArchiveEntryUtils.chmod(new File("target/depset_unpack/child-1/assembly-resources"), 0777);
private void overwriteFileContent(Path path) throws IOException {
FileTime lastModifiedTime = Files.getLastModifiedTime(path);

try (BufferedWriter writer =
Files.newBufferedWriter(path, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING)) {
writer.write("TEST123");
}

Files.setLastModifiedTime(path, lastModifiedTime);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright The Plexus developers.
*
* Licensed 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.
*/
package org.codehaus.plexus.archiver.util;

import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import static org.assertj.core.api.Assertions.assertThat;

class ResourceUtilsTest {

public static Stream<Arguments> testIsUpToDate() {
return Stream.of(
Arguments.of(0, 0, false), // dest and src 0
Arguments.of(100, 0, false), // dest 0
Arguments.of(0, 100, false), // src 0
Arguments.of(100, 200, true),
Arguments.of(200, 100, false),
Arguments.of(100, 100, true));
}

@ParameterizedTest
@MethodSource
void testIsUpToDate(long source, long destination, boolean expected) {
assertThat(ResourceUtils.isUptodate(source, destination)).isEqualTo(expected);
}
}

0 comments on commit 25ed6df

Please sign in to comment.