Skip to content

Commit fa79873

Browse files
committed
fix(forge): explicit zip directories and entry metadata
Fixes gh-15186
1 parent 0d7ab7d commit fa79873

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

grails-forge/grails-forge-core/src/main/java/org/grails/forge/io/ZipOutputHandler.java

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,17 @@
3131
import java.nio.file.Files;
3232
import java.nio.file.Path;
3333
import java.nio.file.Paths;
34+
import java.nio.file.attribute.FileTime;
35+
import java.time.Instant;
36+
import java.util.HashSet;
37+
import java.util.Set;
3438

3539
public class ZipOutputHandler implements OutputHandler {
3640

3741
private final ZipArchiveOutputStream zipOutputStream;
3842
private final File zip;
3943
private final String directory;
44+
private final Set<String> createdDirs = new HashSet<>();
4045

4146
public ZipOutputHandler(Project project) throws IOException {
4247
File baseDirectory = new File(".").getCanonicalFile();
@@ -78,10 +83,19 @@ public boolean exists(String path) {
7883

7984
@Override
8085
public void write(String path, Template contents) throws IOException {
81-
ZipArchiveEntry zipEntry = new ZipArchiveEntry(directory != null ? StringUtils.prependUri(directory, path) : path);
82-
if (contents.isExecutable()) {
83-
zipEntry.setUnixMode(UnixStat.FILE_FLAG | 0755);
84-
}
86+
String entryName = (directory != null ? StringUtils.prependUri(directory, path) : path);
87+
FileTime lastModified = FileTime.from(Instant.now());
88+
89+
// ensure parent directories exist as explicit dir entries
90+
// https://github.com/apache/grails-core/issues/15186
91+
createParentDirs(entryName, lastModified);
92+
93+
ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
94+
setZipEntryMetadata(
95+
zipEntry,
96+
lastModified,
97+
UnixStat.FILE_FLAG | (contents.isExecutable() ? 0755 : 0644)
98+
);
8599
zipOutputStream.putArchiveEntry(zipEntry);
86100
contents.write(zipOutputStream);
87101
zipOutputStream.closeArchiveEntry();
@@ -92,4 +106,27 @@ public void close() throws IOException {
92106
zipOutputStream.finish();
93107
zipOutputStream.close();
94108
}
109+
110+
private void createParentDirs(String entryName, FileTime lastModified) throws IOException {
111+
int slash = entryName.lastIndexOf('/');
112+
if (slash < 0) return;
113+
114+
int i = 0;
115+
while ((i = entryName.indexOf('/', i)) >= 0) {
116+
String dir = entryName.substring(0, i + 1);
117+
if (createdDirs.add(dir)) {
118+
ZipArchiveEntry directoryEntry = new ZipArchiveEntry(dir);
119+
setZipEntryMetadata(directoryEntry, lastModified, UnixStat.DIR_FLAG | 0755);
120+
zipOutputStream.putArchiveEntry(directoryEntry);
121+
zipOutputStream.closeArchiveEntry();
122+
}
123+
i++;
124+
}
125+
}
126+
127+
private void setZipEntryMetadata(ZipArchiveEntry zipEntry, FileTime lastModified, int unixMode) {
128+
zipEntry.setLastModifiedTime(lastModified);
129+
zipEntry.setTime(lastModified.toMillis());
130+
zipEntry.setUnixMode(unixMode);
131+
}
95132
}

0 commit comments

Comments
 (0)