mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
zip output builder
GitOrigin-RevId: fff1d7a477652f268392774943026d40d5bd9db4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
99b2fc73cc
commit
89191fbef6
@@ -142,6 +142,10 @@ public class BazelIncBuilder {
|
||||
|
||||
return ExitCode.OK;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
diagnostic.report(Message.create(null, e));
|
||||
return ExitCode.ERROR;
|
||||
}
|
||||
finally {
|
||||
if (diagnostic instanceof PostponedDiagnosticSink) {
|
||||
// report postponed errors, if necessary
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.bazel;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ZipOutputBuilder {
|
||||
|
||||
@@ -15,5 +15,5 @@ public interface ZipOutputBuilder {
|
||||
|
||||
void deleteEntry(String entryName);
|
||||
|
||||
void write(DataOutput out);
|
||||
void close(boolean saveChanges) throws IOException;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,45 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.bazel.impl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.bazel.ZipOutputBuilder;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static org.jetbrains.jps.javac.Iterators.*;
|
||||
|
||||
public class ZipOutputBuilderImpl implements ZipOutputBuilder {
|
||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
||||
|
||||
private final Map<String, EntryData> myEntries = new TreeMap<>();
|
||||
private final Map<String, ZipEntry> myDirectoryEntries = new HashMap<>();
|
||||
private final ZipFile myZipFile;
|
||||
@NotNull
|
||||
private final Path myOutputZip;
|
||||
private boolean myHasChanges;
|
||||
|
||||
public ZipOutputBuilderImpl(Path outputZip) {
|
||||
// todo: init from the previous zip
|
||||
public ZipOutputBuilderImpl(Path outputZip) throws IOException {
|
||||
myZipFile = new ZipFile(outputZip.toFile());
|
||||
myOutputZip = outputZip;
|
||||
Enumeration<? extends ZipEntry> entries = myZipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if (entry.isDirectory()) {
|
||||
myDirectoryEntries.put(entry.getName(), entry);
|
||||
}
|
||||
else {
|
||||
myEntries.put(entry.getName(), EntryData.create(myZipFile, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,7 +55,7 @@ public class ZipOutputBuilderImpl implements ZipOutputBuilder {
|
||||
@Override
|
||||
public byte[] getContent(String entryName) {
|
||||
try {
|
||||
return myEntries.getOrDefault(entryName, EntryData.EMPTY).getContent();
|
||||
return myEntries.getOrDefault(entryName, EntryData.DIR_DATA).getContent();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// todo: diagnostics
|
||||
@@ -45,20 +65,54 @@ public class ZipOutputBuilderImpl implements ZipOutputBuilder {
|
||||
|
||||
@Override
|
||||
public void putEntry(String entryName, byte[] content) {
|
||||
// todo: create intermediate directory entries
|
||||
myEntries.put(entryName, EntryData.create(content));
|
||||
if (isDirectoryName(entryName)) {
|
||||
throw new RuntimeException("Unexpected name with trailing slash for ZIP entry with content: \"" + entryName + "\"");
|
||||
}
|
||||
myEntries.put(entryName, EntryData.create(entryName, content));
|
||||
myHasChanges = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteEntry(String entryName) {
|
||||
if (myEntries.remove(entryName) != null) {
|
||||
// todo: update parent intermediate entry
|
||||
myHasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput out) {
|
||||
// todo
|
||||
public void close(boolean saveChanges) throws IOException {
|
||||
if (!myHasChanges || !saveChanges) {
|
||||
myZipFile.close();
|
||||
}
|
||||
else {
|
||||
// augment entry map with all currently present directory entries
|
||||
for (String dirName : collect(flat(map(myEntries.keySet(), ZipOutputBuilderImpl::allParentNames)), new HashSet<>())) {
|
||||
ZipEntry existingEntry = myDirectoryEntries.get(dirName);
|
||||
myEntries.put(dirName, EntryData.create(myZipFile, existingEntry != null? existingEntry : new ZipEntry(dirName)));
|
||||
}
|
||||
Path newOutputName = getNewOutputName();
|
||||
try (var zos = new ZipOutputStream(Files.newOutputStream(newOutputName))) {
|
||||
for (Iterator<Map.Entry<String, EntryData>> it = myEntries.entrySet().iterator(); it.hasNext(); ) {
|
||||
EntryData data = it.next().getValue();
|
||||
ZipEntry zipEntry = data.getZipEntry();
|
||||
zos.putNextEntry(zipEntry);
|
||||
if (!zipEntry.isDirectory()) {
|
||||
// either new content or the one loaded from the previous file
|
||||
zos.write(data.getContent());
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myZipFile.close();
|
||||
Files.move(newOutputName, myOutputZip, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull Path getNewOutputName() {
|
||||
// todo: handle situation when file exists
|
||||
return myOutputZip.resolveSibling(myOutputZip.getFileName() + ".tmp");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -72,28 +126,90 @@ public class ZipOutputBuilderImpl implements ZipOutputBuilder {
|
||||
}
|
||||
|
||||
private interface EntryData {
|
||||
EntryData EMPTY = () -> EMPTY_BYTES;
|
||||
EntryData DIR_DATA = new EntryData() {
|
||||
@Override
|
||||
public byte[] getContent() {
|
||||
return EMPTY_BYTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipEntry getZipEntry() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
byte[] getContent() throws IOException;
|
||||
|
||||
static EntryData create(byte[] content) {
|
||||
return () -> content;
|
||||
ZipEntry getZipEntry();
|
||||
|
||||
static EntryData create(String entryName, byte[] content) {
|
||||
return new EntryData() {
|
||||
private ZipEntry entry;
|
||||
@Override
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipEntry getZipEntry() {
|
||||
return entry != null? entry : (entry = new ZipEntry(entryName));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static EntryData create(ZipFile zf, ZipEntry ze) {
|
||||
static EntryData create(ZipFile zip, ZipEntry entry) {
|
||||
if (entry.isDirectory()) {
|
||||
return new EntryData() {
|
||||
@Override
|
||||
public byte[] getContent() {
|
||||
return EMPTY_BYTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipEntry getZipEntry() {
|
||||
return entry;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new EntryData() {
|
||||
private byte[] loaded;
|
||||
@Override
|
||||
public byte[] getContent() throws IOException {
|
||||
if (loaded == null) {
|
||||
try (InputStream is = zf.getInputStream(ze)) {
|
||||
try (InputStream is = zip.getInputStream(entry)) {
|
||||
loaded = is.readAllBytes();
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipEntry getZipEntry() {
|
||||
return entry;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static Iterable<String> allParentNames(String entryName) {
|
||||
String parent = getParent(entryName);
|
||||
return parent == null? List.of() : () -> new Iterator<>() {
|
||||
private String next = parent;
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
if (next == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
String result = next;
|
||||
next = getParent(next);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user