From 52a9a1f4aa61175fe68690e946c2e608c72edbc3 Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Thu, 7 Nov 2019 17:06:17 +0100 Subject: [PATCH 1/7] [MDEP-651] Warn on duplicate archive entries If there's an file system entry for the archive entry, a warning is logged. If overwrite is false, extraction is aborted. --- .../org/codehaus/plexus/archiver/AbstractUnArchiver.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index 41f6c8cbe..cfb80461f 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -343,9 +343,13 @@ protected void extractFile( final File srcF, final File dir, final InputStream c try { - if ( !isOverwrite() && f.exists() && ( f.lastModified() >= entryDate.getTime() ) ) + if ( f.exists() && ( f.lastModified() >= entryDate.getTime() ) ) { - return; + String message = String.format( "Archive entry %s already exists on disk and is newer", entryName ); + getLogger().warn( message ); + if ( !isOverwrite() ) { + return; + } } // create intermediary directories - sometimes zip don't add them From 9b0980842c8fe11fe336e9910259316d652bb52c Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Sat, 3 Oct 2020 20:47:22 +0200 Subject: [PATCH 2/7] [MDEP-651] Warn on casing conflicts between archive entries and files on disk --- .../org/codehaus/plexus/archiver/AbstractUnArchiver.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index cfb80461f..c6676d2a3 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -343,9 +343,10 @@ protected void extractFile( final File srcF, final File dir, final InputStream c try { - if ( f.exists() && ( f.lastModified() >= entryDate.getTime() ) ) + if ( f.exists() && !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ) ) { - String message = String.format( "Archive entry %s already exists on disk and is newer", entryName ); + String message = String.format( "Archive entry %s and existing file %s names differ only by case." + + " This may cause issues on case insensitive file systems.", entryName, canonicalDestPath ); getLogger().warn( message ); if ( !isOverwrite() ) { return; From e2f6f4ca5973c1659c65bbb4c100819ecdb18678 Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Sun, 4 Oct 2020 12:08:07 +0200 Subject: [PATCH 3/7] [MDEP-651] Tweaks in warning message --- .../java/org/codehaus/plexus/archiver/AbstractUnArchiver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index c6676d2a3..ebd3283a4 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -345,8 +345,8 @@ protected void extractFile( final File srcF, final File dir, final InputStream c { if ( f.exists() && !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ) ) { - String message = String.format( "Archive entry %s and existing file %s names differ only by case." - + " This may cause issues on case insensitive file systems.", entryName, canonicalDestPath ); + String message = String.format( "Archive entry '%s' and existing file '%s' names differ only by case." + + " This may cause issues on case-insensitive filesystems.", entryName, canonicalDestPath ); getLogger().warn( message ); if ( !isOverwrite() ) { return; From e5a465c6398a4547dc7df6a67d69fdec57b34b9b Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Sun, 4 Oct 2020 16:15:36 +0200 Subject: [PATCH 4/7] [MDEP-651] Restore check on timestamps Also verify warning log message. --- .../plexus/archiver/AbstractUnArchiver.java | 44 ++++++-- .../archiver/AbstractUnArchiverTest.java | 106 +++++++++++++++++- .../plexus/archiver/CapturingLog.java | 99 ++++++++++++++++ 3 files changed, 241 insertions(+), 8 deletions(-) create mode 100644 src/test/java/org/codehaus/plexus/archiver/CapturingLog.java diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index ebd3283a4..57ec2f1be 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -343,14 +343,9 @@ protected void extractFile( final File srcF, final File dir, final InputStream c try { - if ( f.exists() && !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ) ) + if ( !shouldExtractEntry( f, entryName, entryDate ) ) { - String message = String.format( "Archive entry '%s' and existing file '%s' names differ only by case." - + " This may cause issues on case-insensitive filesystems.", entryName, canonicalDestPath ); - getLogger().warn( message ); - if ( !isOverwrite() ) { - return; - } + return; } // create intermediary directories - sometimes zip don't add them @@ -389,4 +384,39 @@ else if ( isDirectory ) } } + // Visible for testing + protected boolean shouldExtractEntry( File file, String entryName, Date entryDate ) throws IOException + { + String canonicalDestPath = file.getCanonicalPath(); + boolean fileOnDiskIsNewerThanEntry = ( file.lastModified() >= entryDate.getTime() ); + boolean differentCasing = !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ); + + String casingMessage = String.format( "Archive entry '%s' and existing file '%s' names differ only by case." + + " This may cause issues on case-insensitive filesystems.", entryName, canonicalDestPath ); + + // Optimise for situation where we need no checks + if ( !file.exists() ) + { + return true; + } + + // (1) + if ( fileOnDiskIsNewerThanEntry ) + { + // (3) + if ( differentCasing ) + { + getLogger().warn( casingMessage ); + } + return false; + } + + // (4) + if ( differentCasing ) + { + getLogger().warn( casingMessage ); + } + return isOverwrite(); + } + } diff --git a/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java index 0fd224ba5..cf3c82b32 100644 --- a/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java @@ -19,13 +19,23 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.util.Date; import org.codehaus.plexus.components.io.filemappers.FileMapper; +import org.hamcrest.BaseMatcher; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Description; +import org.hamcrest.core.StringContains; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; /** * Unit test for {@link AbstractUnArchiver} @@ -37,7 +47,11 @@ public class AbstractUnArchiverTest @Rule public ExpectedException thrown = ExpectedException.none(); + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private AbstractUnArchiver abstractUnArchiver; + private CapturingLog log = new CapturingLog( 0 /*debug*/, "AbstractUnArchiver" ); @Before public void setUp() @@ -58,6 +72,7 @@ protected void execute() // unused } }; + this.abstractUnArchiver.enableLogging( log ); } @After @@ -72,7 +87,7 @@ public void shouldThrowExceptionBecauseRewrittenPathIsOutOfDirectory() { // given this.thrown.expectMessage( "Entry is outside of the target directory (../PREFIX/ENTRYNAME.SUFFIX)" ); - final File targetFolder = Files.createTempDirectory( null ).toFile(); + final File targetFolder = temporaryFolder.newFolder(); final FileMapper[] fileMappers = new FileMapper[] { new FileMapper() { @Override @@ -97,4 +112,93 @@ public String getMappedFileName( String pName ) // ArchiverException is thrown providing the rewritten path } + @Test + public void shouldNotExtractWhenFileOnDiskIsNewerThanEntryInArchive() throws IOException + { + // given + File file = temporaryFolder.newFile( "readme.txt" ); + file.setLastModified( System.currentTimeMillis() ); + String entryname = "readme.txt"; + Date entryDate = new Date( 0 ); + + // when & then + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is ( false ) ); + } + + @Test + public void shouldNotExtractWhenFileOnDiskIsNewerThanEntryInArchive_andWarnAboutDifferentCasing() throws IOException + { + // given + File file = temporaryFolder.newFile( "readme.txt" ); + file.setLastModified( System.currentTimeMillis() ); + String entryname = "README.txt"; + Date entryDate = new Date( 0 ); + + // when & then + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is ( false ) ); + assertThat( this.log.getWarns(), hasItem( new LogMessageMatcher( "names differ only by case" ) ) ); + } + + @Test + public void shouldExtractWhenEntryInArchiveIsNewerThanFileOnDisk() throws IOException + { + // given + File file = temporaryFolder.newFile( "readme.txt" ); + file.setLastModified( 0 ); + String entryname = "readme.txt"; + Date entryDate = new Date( System.currentTimeMillis() ); + + // when & then + this.abstractUnArchiver.setOverwrite( true ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( true ) ); + + // when & then + this.abstractUnArchiver.setOverwrite( false ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( false ) ); + } + + @Test + public void shouldExtractWhenEntryInArchiveIsNewerThanFileOnDiskAndWarnAboutDifferentCasing() throws IOException + { + // given + File file = temporaryFolder.newFile( "readme.txt" ); + file.setLastModified( 0 ); + String entryname = "README.txt"; + Date entryDate = new Date( System.currentTimeMillis() ); + + // when & then + this.abstractUnArchiver.setOverwrite( true ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( true ) ); + this.abstractUnArchiver.setOverwrite( false ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( false ) ); + assertThat( this.log.getWarns(), hasItem( new LogMessageMatcher( "names differ only by case" ) ) ); + } + + static class LogMessageMatcher extends BaseMatcher { + private final StringContains delegateMatcher; + + LogMessageMatcher( String needle ) + { + this.delegateMatcher = new StringContains( needle ); + } + + @Override + public void describeTo( Description description ) + { + description.appendText( "a log message with " ); + delegateMatcher.describeTo( description ); + } + + @Override + public boolean matches( Object item ) + { + if ( item instanceof CapturingLog.Message ) + { + CapturingLog.Message message = (CapturingLog.Message) item; + String haystack = message.message; + return delegateMatcher.matches( haystack ); + } + return false; + } + } } diff --git a/src/test/java/org/codehaus/plexus/archiver/CapturingLog.java b/src/test/java/org/codehaus/plexus/archiver/CapturingLog.java new file mode 100644 index 000000000..320566d3e --- /dev/null +++ b/src/test/java/org/codehaus/plexus/archiver/CapturingLog.java @@ -0,0 +1,99 @@ +package org.codehaus.plexus.archiver; + +import org.codehaus.plexus.logging.AbstractLogger; +import org.codehaus.plexus.logging.Logger; + +import java.util.ArrayList; +import java.util.List; + +public class CapturingLog extends AbstractLogger +{ + public CapturingLog( int threshold, String name ) + { + super( threshold, name ); + } + + static class Message { + public final String message; + public final Throwable throwable; + + public Message( String message, Throwable throwable ) + { + this.message = message; + this.throwable = throwable; + } + + @Override + public String toString() + { + return "Message{" + "message='" + message + '\'' + ", throwable=" + throwable + '}'; + } + } + + private final List debugs = new ArrayList<>(); + @Override + public void debug( String s, Throwable throwable ) + { + debugs.add( new Message( s, throwable ) ); + } + + public List getDebugs() + { + return debugs; + } + + + private final List infos = new ArrayList<>(); + @Override + public void info( String s, Throwable throwable ) + { + infos.add( new Message( s, throwable ) ); + } + + public List getInfos() + { + return infos; + } + + private final List warns = new ArrayList<>(); + @Override + public void warn( String s, Throwable throwable ) + { + warns.add( new Message( s, throwable ) ); + } + + public List getWarns() + { + return warns; + } + + private final List errors = new ArrayList<>(); + @Override + public void error( String s, Throwable throwable ) + { + errors.add( new Message( s, throwable ) ); + } + + public List getErors() + { + return errors; + } + + private final List fatals = new ArrayList<>(); + @Override + public void fatalError( String s, Throwable throwable ) + { + fatals.add( new Message( s, throwable ) ); + } + + public List getFatals() + { + return fatals; + } + + @Override + public Logger getChildLogger( String s ) + { + return null; + } +} From 6b03a0e86af7bf1e9c2fcf5f441dc1c0640be5fc Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Mon, 5 Oct 2020 21:48:12 +0200 Subject: [PATCH 5/7] [MDEP-651] Add specification table --- .../org/codehaus/plexus/archiver/AbstractUnArchiver.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index 57ec2f1be..798d2bc76 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -387,6 +387,12 @@ else if ( isDirectory ) // Visible for testing protected boolean shouldExtractEntry( File file, String entryName, Date entryDate ) throws IOException { + // entryname | entrydate | filename | filedate | behavior + // (1) readme.txt | 1970 | readme.txt | 2020 | never overwrite + // (2) readme.txt | 2020 | readme.txt | 1970 | only overwrite when isOverWrite() + // (3) README.txt | 1970 | readme.txt | 2020 | warn + never overwrite + // (4) README.txt | 2020 | readme.txt | 1970 | warn + only overwrite when isOverWrite() + String canonicalDestPath = file.getCanonicalPath(); boolean fileOnDiskIsNewerThanEntry = ( file.lastModified() >= entryDate.getTime() ); boolean differentCasing = !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ); @@ -416,6 +422,8 @@ protected boolean shouldExtractEntry( File file, String entryName, Date entryDat { getLogger().warn( casingMessage ); } + + // (2) return isOverwrite(); } From b6f549919d0ad8fab6d8a95074fca470c80c2658 Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Fri, 9 Oct 2020 14:53:21 +0200 Subject: [PATCH 6/7] [MDEP-651] Rename variables --- .../plexus/archiver/AbstractUnArchiver.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index 798d2bc76..937a17180 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -330,11 +330,11 @@ protected void extractFile( final File srcF, final File dir, final InputStream c } // Hmm. Symlinks re-evaluate back to the original file here. Unsure if this is a good thing... - final File f = FileUtils.resolveFile( dir, entryName ); + final File targetFileName = FileUtils.resolveFile( dir, entryName ); // Make sure that the resolved path of the extracted file doesn't escape the destination directory String canonicalDirPath = dir.getCanonicalPath(); - String canonicalDestPath = f.getCanonicalPath(); + String canonicalDestPath = targetFileName.getCanonicalPath(); if ( !canonicalDestPath.startsWith( canonicalDirPath ) ) { @@ -343,13 +343,13 @@ protected void extractFile( final File srcF, final File dir, final InputStream c try { - if ( !shouldExtractEntry( f, entryName, entryDate ) ) + if ( !shouldExtractEntry( targetFileName, entryName, entryDate ) ) { return; } // create intermediary directories - sometimes zip don't add them - final File dirF = f.getParentFile(); + final File dirF = targetFileName.getParentFile(); if ( dirF != null ) { dirF.mkdirs(); @@ -357,11 +357,11 @@ protected void extractFile( final File srcF, final File dir, final InputStream c if ( !StringUtils.isEmpty( symlinkDestination ) ) { - SymlinkUtils.createSymbolicLink( f, new File( symlinkDestination ) ); + SymlinkUtils.createSymbolicLink( targetFileName, new File( symlinkDestination ) ); } else if ( isDirectory ) { - f.mkdirs(); + targetFileName.mkdirs(); } else { @@ -371,21 +371,21 @@ else if ( isDirectory ) } } - f.setLastModified( entryDate.getTime() ); + targetFileName.setLastModified( entryDate.getTime() ); if ( !isIgnorePermissions() && mode != null && !isDirectory ) { - ArchiveEntryUtils.chmod( f, mode ); + ArchiveEntryUtils.chmod( targetFileName, mode ); } } catch ( final FileNotFoundException ex ) { - getLogger().warn( "Unable to expand to file " + f.getPath() ); + getLogger().warn( "Unable to expand to file " + targetFileName.getPath() ); } } // Visible for testing - protected boolean shouldExtractEntry( File file, String entryName, Date entryDate ) throws IOException + protected boolean shouldExtractEntry( File targetFileName, String entryName, Date entryDate ) throws IOException { // entryname | entrydate | filename | filedate | behavior // (1) readme.txt | 1970 | readme.txt | 2020 | never overwrite @@ -393,15 +393,15 @@ protected boolean shouldExtractEntry( File file, String entryName, Date entryDat // (3) README.txt | 1970 | readme.txt | 2020 | warn + never overwrite // (4) README.txt | 2020 | readme.txt | 1970 | warn + only overwrite when isOverWrite() - String canonicalDestPath = file.getCanonicalPath(); - boolean fileOnDiskIsNewerThanEntry = ( file.lastModified() >= entryDate.getTime() ); + String canonicalDestPath = targetFileName.getCanonicalPath(); + boolean fileOnDiskIsNewerThanEntry = targetFileName.lastModified() >= entryDate.getTime(); boolean differentCasing = !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ); String casingMessage = String.format( "Archive entry '%s' and existing file '%s' names differ only by case." + " This may cause issues on case-insensitive filesystems.", entryName, canonicalDestPath ); // Optimise for situation where we need no checks - if ( !file.exists() ) + if ( !targetFileName.exists() ) { return true; } From cf7c6d0de6e49029cc864daee9ade72ca67a9924 Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Fri, 9 Oct 2020 16:22:23 +0200 Subject: [PATCH 7/7] [MDEP-651] Optimise for situations where there is no conflict, and fix detecting of casing conflicts --- .../plexus/archiver/AbstractUnArchiver.java | 33 +++++++++------ .../archiver/AbstractUnArchiverTest.java | 42 ++++++++++++------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java index 937a17180..bfb4b8fa4 100644 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -343,7 +345,7 @@ protected void extractFile( final File srcF, final File dir, final InputStream c try { - if ( !shouldExtractEntry( targetFileName, entryName, entryDate ) ) + if ( !shouldExtractEntry( dir, targetFileName, entryName, entryDate ) ) { return; } @@ -365,7 +367,7 @@ else if ( isDirectory ) } else { - try ( OutputStream out = new FileOutputStream( f ) ) + try ( OutputStream out = new FileOutputStream( targetFileName ) ) { IOUtil.copy( compressedInputStream, out ); } @@ -385,26 +387,31 @@ else if ( isDirectory ) } // Visible for testing - protected boolean shouldExtractEntry( File targetFileName, String entryName, Date entryDate ) throws IOException + protected boolean shouldExtractEntry( File targetDirectory, File targetFileName, String entryName, Date entryDate ) throws IOException { // entryname | entrydate | filename | filedate | behavior // (1) readme.txt | 1970 | readme.txt | 2020 | never overwrite // (2) readme.txt | 2020 | readme.txt | 1970 | only overwrite when isOverWrite() - // (3) README.txt | 1970 | readme.txt | 2020 | warn + never overwrite - // (4) README.txt | 2020 | readme.txt | 1970 | warn + only overwrite when isOverWrite() + // (3) README.txt | 1970 | readme.txt | 2020 | case-insensitive filesystem: warn + never overwrite + // case-sensitive filesystem: extract without warning + // (4) README.txt | 2020 | readme.txt | 1970 | case-insensitive filesystem: warn + only overwrite when isOverWrite() + // case-sensitive filesystem: extract without warning + + // The canonical file name follows the name of the archive entry, but takes into account the case- + // sensitivity of the filesystem. So on a case-sensitive file system, file.exists() returns false for + // scenario (3) and (4). + if ( !targetFileName.exists() ) + { + return true; + } String canonicalDestPath = targetFileName.getCanonicalPath(); + String relativeCanonicalDestPath = canonicalDestPath.replace( targetDirectory.getCanonicalPath() + File.separatorChar, "" ); boolean fileOnDiskIsNewerThanEntry = targetFileName.lastModified() >= entryDate.getTime(); - boolean differentCasing = !StringUtils.equalsIgnoreCase( entryName, canonicalDestPath ); + boolean differentCasing = !entryName.equals( relativeCanonicalDestPath ); String casingMessage = String.format( "Archive entry '%s' and existing file '%s' names differ only by case." - + " This may cause issues on case-insensitive filesystems.", entryName, canonicalDestPath ); - - // Optimise for situation where we need no checks - if ( !targetFileName.exists() ) - { - return true; - } + + " This may lead to an unexpected outcome on case-insensitive filesystems.", entryName, canonicalDestPath ); // (1) if ( fileOnDiskIsNewerThanEntry ) diff --git a/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java index cf3c82b32..b7870adb5 100644 --- a/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/AbstractUnArchiverTest.java @@ -18,12 +18,10 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.Date; import org.codehaus.plexus.components.io.filemappers.FileMapper; import org.hamcrest.BaseMatcher; -import org.hamcrest.CoreMatchers; import org.hamcrest.Description; import org.hamcrest.core.StringContains; import org.junit.After; @@ -112,30 +110,42 @@ public String getMappedFileName( String pName ) // ArchiverException is thrown providing the rewritten path } + @Test + public void shouldExtractWhenFileOnDiskDoesNotExist() throws IOException + { + // given + File file = new File( temporaryFolder.getRoot(), "whatever.txt" ); // does not create the file! + String entryname = file.getName(); + Date entryDate = new Date(); + + // when & then + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is ( true ) ); + } + @Test public void shouldNotExtractWhenFileOnDiskIsNewerThanEntryInArchive() throws IOException { // given - File file = temporaryFolder.newFile( "readme.txt" ); + File file = temporaryFolder.newFile(); file.setLastModified( System.currentTimeMillis() ); - String entryname = "readme.txt"; + String entryname = file.getName(); Date entryDate = new Date( 0 ); // when & then - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is ( false ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is ( false ) ); } @Test public void shouldNotExtractWhenFileOnDiskIsNewerThanEntryInArchive_andWarnAboutDifferentCasing() throws IOException { // given - File file = temporaryFolder.newFile( "readme.txt" ); + File file = temporaryFolder.newFile(); file.setLastModified( System.currentTimeMillis() ); - String entryname = "README.txt"; + String entryname = file.getName().toUpperCase(); Date entryDate = new Date( 0 ); // when & then - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is ( false ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is ( false ) ); assertThat( this.log.getWarns(), hasItem( new LogMessageMatcher( "names differ only by case" ) ) ); } @@ -143,34 +153,34 @@ public void shouldNotExtractWhenFileOnDiskIsNewerThanEntryInArchive_andWarnAbout public void shouldExtractWhenEntryInArchiveIsNewerThanFileOnDisk() throws IOException { // given - File file = temporaryFolder.newFile( "readme.txt" ); + File file = temporaryFolder.newFile(); file.setLastModified( 0 ); - String entryname = "readme.txt"; + String entryname = file.getName().toUpperCase(); Date entryDate = new Date( System.currentTimeMillis() ); // when & then this.abstractUnArchiver.setOverwrite( true ); - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( true ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is( true ) ); // when & then this.abstractUnArchiver.setOverwrite( false ); - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( false ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is( false ) ); } @Test public void shouldExtractWhenEntryInArchiveIsNewerThanFileOnDiskAndWarnAboutDifferentCasing() throws IOException { // given - File file = temporaryFolder.newFile( "readme.txt" ); + File file = temporaryFolder.newFile(); file.setLastModified( 0 ); - String entryname = "README.txt"; + String entryname = file.getName().toUpperCase(); Date entryDate = new Date( System.currentTimeMillis() ); // when & then this.abstractUnArchiver.setOverwrite( true ); - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( true ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is( true ) ); this.abstractUnArchiver.setOverwrite( false ); - assertThat( this.abstractUnArchiver.shouldExtractEntry( file, entryname, entryDate ), is( false ) ); + assertThat( this.abstractUnArchiver.shouldExtractEntry( temporaryFolder.getRoot(), file, entryname, entryDate ), is( false ) ); assertThat( this.log.getWarns(), hasItem( new LogMessageMatcher( "names differ only by case" ) ) ); }