Commit 9f3bc78f authored by Andy Wilkinson's avatar Andy Wilkinson

Update extract to write files to their original, unlayered location

parent 44f75088
...@@ -83,7 +83,7 @@ class ExtractCommand extends Command { ...@@ -83,7 +83,7 @@ class ExtractCommand extends Command {
} }
private void write(ZipInputStream zip, ZipEntry entry, File destination) throws IOException { private void write(ZipInputStream zip, ZipEntry entry, File destination) throws IOException {
String path = StringUtils.cleanPath(entry.getName()); String path = StringUtils.cleanPath(this.layers.getOriginalLocation(entry));
File file = new File(destination, path); File file = new File(destination, path);
if (file.getAbsolutePath().startsWith(destination.getAbsolutePath())) { if (file.getAbsolutePath().startsWith(destination.getAbsolutePath())) {
mkParentDirs(file); mkParentDirs(file);
......
...@@ -44,7 +44,7 @@ class IndexedLayers implements Layers { ...@@ -44,7 +44,7 @@ class IndexedLayers implements Layers {
private static final String SPRING_BOOT_APPLICATION_LAYER = "springbootapplication"; private static final String SPRING_BOOT_APPLICATION_LAYER = "springbootapplication";
private static final Pattern LAYER_PATTERN = Pattern.compile("^BOOT-INF\\/layers\\/([a-zA-Z0-9-]+)\\/.*$"); private static final Pattern LAYER_PATTERN = Pattern.compile("^BOOT-INF\\/layers\\/([a-zA-Z0-9-]+)\\/(.*$)");
private List<String> layers; private List<String> layers;
...@@ -75,6 +75,18 @@ class IndexedLayers implements Layers { ...@@ -75,6 +75,18 @@ class IndexedLayers implements Layers {
return this.layers.contains(APPLICATION_LAYER) ? APPLICATION_LAYER : SPRING_BOOT_APPLICATION_LAYER; return this.layers.contains(APPLICATION_LAYER) ? APPLICATION_LAYER : SPRING_BOOT_APPLICATION_LAYER;
} }
@Override
public String getOriginalLocation(ZipEntry entry) {
String name = entry.getName();
Matcher matcher = LAYER_PATTERN.matcher(name);
if (matcher.matches()) {
String layer = matcher.group(1);
Assert.state(this.layers.contains(layer), () -> "Unexpected layer '" + layer + "'");
return "BOOT-INF/" + matcher.group(2);
}
return name;
}
/** /**
* Get an {@link IndexedLayers} instance of possible. * Get an {@link IndexedLayers} instance of possible.
* @param context the context * @param context the context
......
...@@ -42,6 +42,13 @@ interface Layers extends Iterable<String> { ...@@ -42,6 +42,13 @@ interface Layers extends Iterable<String> {
*/ */
String getLayer(ZipEntry entry); String getLayer(ZipEntry entry);
/**
* Returns the original, unlayered location of the given entry.
* @param entry the entry for which the original location is required
* @return the original location
*/
String getOriginalLocation(ZipEntry entry);
/** /**
* Return a {@link Layers} instance for the currently running application. * Return a {@link Layers} instance for the currently running application.
* @param context the command context * @param context the command context
......
...@@ -70,9 +70,9 @@ class ExtractCommandTests { ...@@ -70,9 +70,9 @@ class ExtractCommandTests {
void runExtractsLayers() throws Exception { void runExtractsLayers() throws Exception {
this.command.run(Collections.emptyMap(), Collections.emptyList()); this.command.run(Collections.emptyMap(), Collections.emptyList());
assertThat(this.extract.list()).containsOnly("a", "b", "c"); assertThat(this.extract.list()).containsOnly("a", "b", "c");
assertThat(new File(this.extract, "a/a/a.jar")).exists(); assertThat(new File(this.extract, "a/a.jar")).exists();
assertThat(new File(this.extract, "b/b/b.jar")).exists(); assertThat(new File(this.extract, "b/b.jar")).exists();
assertThat(new File(this.extract, "c/c/c.jar")).exists(); assertThat(new File(this.extract, "c/c.jar")).exists();
} }
@Test @Test
...@@ -81,17 +81,17 @@ class ExtractCommandTests { ...@@ -81,17 +81,17 @@ class ExtractCommandTests {
this.command.run(Collections.singletonMap(ExtractCommand.DESTINATION_OPTION, out.getAbsolutePath()), this.command.run(Collections.singletonMap(ExtractCommand.DESTINATION_OPTION, out.getAbsolutePath()),
Collections.emptyList()); Collections.emptyList());
assertThat(this.extract.list()).containsOnly("out"); assertThat(this.extract.list()).containsOnly("out");
assertThat(new File(this.extract, "out/a/a/a.jar")).exists(); assertThat(new File(this.extract, "out/a/a.jar")).exists();
assertThat(new File(this.extract, "out/b/b/b.jar")).exists(); assertThat(new File(this.extract, "out/b/b.jar")).exists();
assertThat(new File(this.extract, "out/c/c/c.jar")).exists(); assertThat(new File(this.extract, "out/c/c.jar")).exists();
} }
@Test @Test
void runWhenHasLayerParamsExtractsLimitedLayers() { void runWhenHasLayerParamsExtractsLimitedLayers() {
this.command.run(Collections.emptyMap(), Arrays.asList("a", "c")); this.command.run(Collections.emptyMap(), Arrays.asList("a", "c"));
assertThat(this.extract.list()).containsOnly("a", "c"); assertThat(this.extract.list()).containsOnly("a", "c");
assertThat(new File(this.extract, "a/a/a.jar")).exists(); assertThat(new File(this.extract, "a/a.jar")).exists();
assertThat(new File(this.extract, "c/c/c.jar")).exists(); assertThat(new File(this.extract, "c/c.jar")).exists();
} }
private File createJarFile(String name) throws IOException { private File createJarFile(String name) throws IOException {
...@@ -133,6 +133,11 @@ class ExtractCommandTests { ...@@ -133,6 +133,11 @@ class ExtractCommandTests {
return "c"; return "c";
} }
@Override
public String getOriginalLocation(ZipEntry entry) {
return entry.getName().substring(2);
}
} }
} }
...@@ -76,6 +76,24 @@ class IndexedLayersTests { ...@@ -76,6 +76,24 @@ class IndexedLayersTests {
assertThat(layers.getLayer(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("springbootapplication"); assertThat(layers.getLayer(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("springbootapplication");
} }
@Test
void getOriginalLocationWithLibJarReturnsBootInfLibLocation() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers.getOriginalLocation(mockEntry("BOOT-INF/layers/test/lib/file.jar"))).isEqualTo("BOOT-INF/lib/file.jar");
}
@Test
void getOriginalLocationWithClassesEntryReturnsBootInfClassesLocation() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers.getOriginalLocation(mockEntry("BOOT-INF/layers/test/classes/com/example/Test.class"))).isEqualTo("BOOT-INF/classes/com/example/Test.class");
}
@Test
void getOriginalLocationWhenDoesNotMatchLayerPatternsReturnsEntryLocationAsIs() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers.getOriginalLocation(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("META-INF/MANIFEST.MF");
}
private ZipEntry mockEntry(String name) { private ZipEntry mockEntry(String name) {
ZipEntry entry = mock(ZipEntry.class); ZipEntry entry = mock(ZipEntry.class);
given(entry.getName()).willReturn(name); given(entry.getName()).willReturn(name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment