Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow copy all files without timestamp checking by DirectoryArchiver #304

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}