[updater] getting rid of long unused ZIP-aware mode

GitOrigin-RevId: 2189f626b1bd25c950c4d7cb0eb287743163557c
This commit is contained in:
Roman Shevchenko
2023-09-01 18:33:11 +00:00
committed by intellij-monorepo-bot
parent a3c76f4a2a
commit ff203c76f7
22 changed files with 88 additions and 647 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -56,7 +56,7 @@ public class CreateAction extends PatchAction {
ValidationResult.Option[] options = myPatch.isStrict()
? new ValidationResult.Option[]{ValidationResult.Option.REPLACE}
: new ValidationResult.Option[]{ValidationResult.Option.REPLACE, ValidationResult.Option.KEEP};
String message = ValidationResult.ALREADY_EXISTS_MESSAGE, details = "checksum 0x" + Long.toHexString(myPatch.digestFile(toFile, myPatch.isNormalized()));
String message = ValidationResult.ALREADY_EXISTS_MESSAGE, details = "checksum 0x" + Long.toHexString(myPatch.digestFile(toFile));
return new ValidationResult(ValidationResult.Kind.CONFLICT, getPath(), ValidationResult.Action.CREATE, message, details, options);
}
return null;
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.DataInputStream;
@@ -39,12 +39,12 @@ public class DeleteAction extends PatchAction {
: new ValidationResult.Option[]{ValidationResult.Option.DELETE, ValidationResult.Option.KEEP};
if (getChecksum() == Digester.INVALID) {
ValidationResult.Action action = ValidationResult.Action.VALIDATE;
String details = "checksum 0x" + Long.toHexString(myPatch.digestFile(toFile, myPatch.isNormalized()));
String details = "checksum 0x" + Long.toHexString(myPatch.digestFile(toFile));
return new ValidationResult(ValidationResult.Kind.CONFLICT, getPath(), action, "Unexpected file", details, options);
}
else {
ValidationResult.Action action = ValidationResult.Action.DELETE;
String details = "expected 0x" + Long.toHexString(getChecksum()) + ", actual 0x" + Long.toHexString(myPatch.digestFile(toFile, myPatch.isNormalized()));
String details = "expected 0x" + Long.toHexString(getChecksum()) + ", actual 0x" + Long.toHexString(myPatch.digestFile(toFile));
return new ValidationResult(ValidationResult.Kind.CONFLICT, getPath(), action, ValidationResult.MODIFIED_MESSAGE, details, options);
}
}
+6 -52
View File
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -7,17 +7,10 @@ import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public final class Digester {
/* CRC32 uses the lower 32bits of a long, never returning negative values */
/* CRC32 uses the lower 32 bits of the {@code long} type, never returning negative values */
public static final long INVALID = 0x8000_0000_0000_0000L;
public static final long DIRECTORY = 0x4000_0000_0000_0000L;
public static final long SYM_LINK = 0x2000_0000_0000_0000L;
@@ -32,7 +25,7 @@ public final class Digester {
return (digest & SYM_LINK) == SYM_LINK;
}
public static long digestRegularFile(File file, boolean normalize) throws IOException {
public static long digestRegularFile(File file) throws IOException {
Path path = file.toPath();
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
@@ -45,7 +38,7 @@ public final class Digester {
if (attrs.isDirectory()) return DIRECTORY;
long executable = !Utils.IS_WINDOWS && file.canExecute() ? EXECUTABLE : 0;
try (InputStream in = new BufferedInputStream(Utils.newFileInputStream(file, normalize))) {
try (InputStream in = new BufferedInputStream(Utils.newFileInputStream(file))) {
return digestStream(in) | executable;
}
catch (IOException e) {
@@ -53,52 +46,13 @@ public final class Digester {
}
}
public static long digestZipFile(File file) throws IOException {
ZipFile zipFile;
try {
zipFile = new ZipFile(file);
}
catch (ZipException e) {
// This was not a zip file...
return digestRegularFile(file, false);
}
try {
List<ZipEntry> sorted = new ArrayList<>();
Enumeration<? extends ZipEntry> temp = zipFile.entries();
while (temp.hasMoreElements()) {
ZipEntry each = temp.nextElement();
if (!each.isDirectory()) {
sorted.add(each);
}
}
sorted.sort(Comparator.comparing(ZipEntry::getName));
CRC32 crc = new CRC32();
for (ZipEntry each : sorted) {
try (InputStream in = zipFile.getInputStream(each)) {
doDigestStream(in, crc);
}
}
return crc.getValue();
}
finally {
zipFile.close();
}
}
public static long digestStream(InputStream in) throws IOException {
CRC32 crc = new CRC32();
doDigestStream(in, crc);
return crc.getValue();
}
private static void doDigestStream(InputStream in, CRC32 crc) throws IOException {
byte[] BUFFER = new byte[8192];
int size;
while ((size = in.read(BUFFER)) != -1) {
crc.update(BUFFER, 0, size);
}
return crc.getValue();
}
}
}
+13 -36
View File
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -15,16 +15,13 @@ import static com.intellij.updater.Runner.*;
public class Patch {
private static final int CREATE_ACTION_KEY = 1;
private static final int UPDATE_ACTION_KEY = 2;
private static final int UPDATE_ZIP_ACTION_KEY = 3;
private static final int DELETE_ACTION_KEY = 4;
private static final int VALIDATE_ACTION_KEY = 5;
private final String myOldBuild;
private final String myNewBuild;
private final String myRoot;
private final boolean myIsBinary;
private final boolean myIsStrict;
private final boolean myIsNormalized;
private final Map<String, String> myWarnings;
private final List<String> myDeleteFiles;
private final int myTimeout;
@@ -34,9 +31,7 @@ public class Patch {
myOldBuild = spec.getOldVersionDescription();
myNewBuild = spec.getNewVersionDescription();
myRoot = spec.getRoot();
myIsBinary = spec.isBinary();
myIsStrict = spec.isStrict();
myIsNormalized = spec.isNormalized();
myWarnings = spec.getWarnings();
myDeleteFiles = spec.getDeleteFiles();
myTimeout = spec.getTimeout();
@@ -48,9 +43,9 @@ public class Patch {
myOldBuild = in.readUTF();
myNewBuild = in.readUTF();
myRoot = in.readUTF();
myIsBinary = in.readBoolean();
/*myIsBinary =*/ in.readBoolean();
myIsStrict = in.readBoolean();
myIsNormalized = in.readBoolean();
/*myIsNormalized =*/ in.readBoolean();
myWarnings = readMap(in);
myDeleteFiles = readList(in);
myTimeout = 0;
@@ -69,8 +64,8 @@ public class Patch {
Set<String> optional = new HashSet<>(spec.getOptionalFiles());
Set<String> strict = new HashSet<>(spec.getStrictFiles());
Map<String, Long> oldChecksums = digestFiles(olderDir, ignored, isNormalized());
Map<String, Long> newChecksums = digestFiles(newerDir, ignored, false);
Map<String, Long> oldChecksums = digestFiles(olderDir, ignored);
Map<String, Long> newChecksums = digestFiles(newerDir, ignored);
DiffCalculator.Result diff = DiffCalculator.calculate(oldChecksums, newChecksums, critical, optional, true);
LOG.info("Preparing actions...");
@@ -78,7 +73,7 @@ public class Patch {
List<PatchAction> tempActions = new ArrayList<>();
// 'delete' actions before 'create' actions to prevent newly created files to be deleted if the names differ only on case.
// 'delete' actions before 'create' actions to prevent newly created files to be deleted if the names differ only in case.
for (Map.Entry<String, Long> each : diff.filesToDelete.entrySet()) {
// Add them in reverse order so directory structures start deleting the files before the directory itself.
tempActions.add(0, new DeleteAction(this, each.getKey(), each.getValue()));
@@ -90,12 +85,7 @@ public class Patch {
for (Map.Entry<String, DiffCalculator.Update> each : diff.filesToUpdate.entrySet()) {
DiffCalculator.Update update = each.getValue();
if (!spec.isBinary() && !update.move && Utils.isZipFile(each.getKey())) {
tempActions.add(new UpdateZipAction(this, each.getKey(), update.source, update.checksum));
}
else {
tempActions.add(new UpdateAction(this, each.getKey(), update.source, update.checksum, update.move));
}
tempActions.add(new UpdateAction(this, each.getKey(), update.source, update.checksum, update.move));
}
if (spec.isStrict()) {
@@ -127,9 +117,9 @@ public class Patch {
dataOut.writeUTF(myOldBuild);
dataOut.writeUTF(myNewBuild);
dataOut.writeUTF(myRoot);
dataOut.writeBoolean(myIsBinary);
dataOut.writeBoolean(/*myIsBinary*/ true);
dataOut.writeBoolean(myIsStrict);
dataOut.writeBoolean(myIsNormalized);
dataOut.writeBoolean(/*myIsNormalized*/ false);
writeMap(dataOut, myWarnings);
writeList(dataOut, myDeleteFiles);
writeActions(dataOut, myActions);
@@ -161,7 +151,6 @@ public class Patch {
Class<?> clazz = each.getClass();
if (clazz == CreateAction.class) key = CREATE_ACTION_KEY;
else if (clazz == UpdateAction.class) key = UPDATE_ACTION_KEY;
else if (clazz == UpdateZipAction.class) key = UPDATE_ZIP_ACTION_KEY;
else if (clazz == DeleteAction.class) key = DELETE_ACTION_KEY;
else if (clazz == ValidateAction.class) key = VALIDATE_ACTION_KEY;
else throw new RuntimeException("Unknown action " + each);
@@ -202,9 +191,6 @@ public class Patch {
case UPDATE_ACTION_KEY:
a = new UpdateAction(this, in);
break;
case UPDATE_ZIP_ACTION_KEY:
a = new UpdateZipAction(this, in);
break;
case DELETE_ACTION_KEY:
a = new DeleteAction(this, in);
break;
@@ -412,21 +398,16 @@ public class Patch {
ui.checkCancelled();
}
public long digestFile(File toFile, boolean normalize) throws IOException {
if (!myIsBinary && Utils.isZipFile(toFile.getName())) {
return Digester.digestZipFile(toFile);
}
else {
return Digester.digestRegularFile(toFile, normalize);
}
public long digestFile(File toFile) throws IOException {
return Digester.digestRegularFile(toFile);
}
public Map<String, Long> digestFiles(File dir, Set<String> ignoredFiles, boolean normalize) throws IOException {
public Map<String, Long> digestFiles(File dir, Set<String> ignoredFiles) throws IOException {
Map<String, Long> result = new LinkedHashMap<>();
Utils.collectRelativePaths(dir.toPath()).parallelStream().forEachOrdered(path -> {
if (!ignoredFiles.contains(path)) {
try {
long hash = digestFile(new File(dir, path), normalize);
long hash = digestFile(new File(dir, path));
synchronized (result) {
result.put(path, hash);
}
@@ -449,10 +430,6 @@ public class Patch {
return myIsStrict;
}
public boolean isNormalized() {
return myIsNormalized;
}
public boolean validateDeletion(String path) {
for (String delete : myDeleteFiles) {
if (path.matches(delete)) {
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -191,7 +191,7 @@ public abstract class PatchAction {
if (toFile.exists()) {
if (isModified(toFile)) {
ValidationResult.Option[] options = calculateOptions();
String details = "expected 0x" + Long.toHexString(myChecksum) + ", actual 0x" + Long.toHexString(myPatch.digestFile(toFile, myPatch.isNormalized()));
String details = "expected 0x" + Long.toHexString(myChecksum) + ", actual 0x" + Long.toHexString(myPatch.digestFile(toFile));
return new ValidationResult(ValidationResult.Kind.ERROR, getReportPath(), action, ValidationResult.MODIFIED_MESSAGE, details, options);
}
}
@@ -225,7 +225,7 @@ public abstract class PatchAction {
}
protected boolean isModified(File toFile) throws IOException {
return myChecksum == Digester.INVALID || myChecksum != myPatch.digestFile(toFile, myPatch.isNormalized());
return myChecksum == Digester.INVALID || myChecksum != myPatch.digestFile(toFile);
}
public boolean mandatoryBackup() {
@@ -120,7 +120,7 @@ public final class PatchFileCreator {
'-' +
Long.toHexString(action.getChecksum()) +
'-' +
Long.toHexString(Digester.digestRegularFile(action.getFile(newerDir), false));
Long.toHexString(Digester.digestRegularFile(action.getFile(newerDir)));
}
catch (IOException ignored) {
return null;
@@ -26,14 +26,12 @@ public class PatchSpec {
private String myNewFolder;
private String myPatchFile;
private String myJarFile;
private boolean myIsBinary;
private boolean myIsStrict;
private List<String> myIgnoredFiles = Collections.emptyList();
private List<String> myCriticalFiles = Collections.emptyList();
// A conflict in an essential file makes a patch update impossible; the IDE must be reinstalled from scratch.
private List<String> myStrictFiles = Collections.emptyList();
private List<String> myOptionalFiles = Collections.emptyList();
private boolean myIsNormalized;
private Map<String, String> myWarnings = Collections.emptyMap();
private List<String> myDeleteFiles = Collections.emptyList();
private String myRoot = "";
@@ -138,24 +136,6 @@ public class PatchSpec {
return this;
}
public PatchSpec setBinary(boolean binary) {
myIsBinary = binary;
return this;
}
public boolean isBinary() {
return myIsBinary;
}
public boolean isNormalized() {
return myIsNormalized;
}
public PatchSpec setNormalized(boolean normalized) {
myIsNormalized = normalized;
return this;
}
public PatchSpec setWarnings(Map<String, String> warnings) {
myWarnings = warnings;
return this;
@@ -123,9 +123,7 @@ public final class Runner {
LOG.info("case-sensitive: " + ourCaseSensitiveFs);
boolean binary = hasArgument(args, "zip_as_binary");
boolean strict = hasArgument(args, "strict");
boolean normalized = hasArgument(args, "normalized");
String root = getArgument(args, "root");
if (root == null) {
@@ -156,8 +154,6 @@ public final class Runner {
.setPatchFile(patchFile)
.setJarFile(jarFile)
.setStrict(strict)
.setBinary(binary)
.setNormalized(normalized)
.setIgnoredFiles(ignoredFiles)
.setCriticalFiles(criticalFiles)
.setStrictFiles(strictFiles)
@@ -286,7 +282,6 @@ public final class Runner {
" optional: A set of files that is okay for them not to exist when applying the patch.\n" +
" delete: A set of regular expressions for paths that is safe to delete without user confirmation.\n" +
" <flags>: Can be:\n" +
" --zip_as_binary: Zip and jar files will be treated as binary files and not inspected internally.\n" +
" --strict: The created patch will contain extra information to fully validate an installation. A strict\n" +
" patch will only be applied if it is guaranteed that the patched version will match exactly\n" +
" the source of the patch. This means that unexpected files will be deleted and all existing files\n" +
@@ -296,11 +291,6 @@ public final class Runner {
" --root=<dir>: Sets dir as the root directory of the patch. The root directory is the directory where the patch should be\n" +
" applied to. For example on Mac, you can diff the two .app folders and set Contents as the root.\n" +
" The root directory is relative to <old_folder> and uses forwards-slashes as separators.\n" +
" --normalized: This creates a normalized patch. This flag only makes sense in addition to --zip_as_binary\n" +
" A normalized patch must be used to move from an installation that was patched\n" +
" in a non-binary way to a fully binary patch. This will yield a larger patch, but\n" +
" the generated patch can be applied on versions where non-binary patches have been applied to and it\n" +
" guarantees that the patched version will match exactly the original one.\n" +
" --timeout=<T> A time budget for building a 'bsdiff' patch between a pair of files, in seconds.\n" +
" If exceeded, the new version is included into the patch as a whole.\n" +
" <folder>: The folder where product was installed. For example: c:/Program Files/JetBrains/IntelliJ IDEA 2017.3.4");
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -40,7 +40,7 @@ public class UpdateAction extends BaseUpdateAction {
FileType type = getFileType(newerFile);
if (type == FileType.SYMLINK) throw new IOException("Unexpected symlink: " + newerFile);
writeFileType(patchOutput, type);
try (InputStream olderFileIn = new BufferedInputStream(Utils.newFileInputStream(olderFile, myPatch.isNormalized()));
try (InputStream olderFileIn = new BufferedInputStream(Utils.newFileInputStream(olderFile));
InputStream newerFileIn = new BufferedInputStream(new FileInputStream(newerFile))) {
writeDiff(olderFileIn, newerFileIn, patchOutput);
}
@@ -70,7 +70,7 @@ public class UpdateAction extends BaseUpdateAction {
}
else {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
InputStream oldFileIn = source.exists() ? Utils.newFileInputStream(source, myPatch.isNormalized()) : null) {
InputStream oldFileIn = source.exists() ? Utils.newFileInputStream(source) : null) {
applyDiff(in, oldFileIn, out);
}
}
@@ -1,231 +0,0 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.updater;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class UpdateZipAction extends BaseUpdateAction {
private Set<String> myFilesToCreate;
private Set<String> myFilesToUpdate;
private Set<String> myFilesToDelete;
public UpdateZipAction(Patch patch, String path, String source, long checksum) {
super(patch, path, source, checksum, false);
}
public UpdateZipAction(Patch patch, DataInputStream in) throws IOException {
super(patch, in);
int count = in.readInt();
myFilesToCreate = new HashSet<>(count);
while (count-- > 0) {
myFilesToCreate.add(in.readUTF());
}
count = in.readInt();
myFilesToUpdate = new HashSet<>(count);
while (count-- > 0) {
myFilesToUpdate.add(in.readUTF());
}
count = in.readInt();
myFilesToDelete = new HashSet<>(count);
while (count-- > 0) {
myFilesToDelete.add(in.readUTF());
}
}
/* for tests */
UpdateZipAction(Patch patch, String path, Collection<String> toCreate, Collection<String> toUpdate, Collection<String> toDelete, long checksum) {
this(patch, path, path, toCreate, toUpdate, toDelete, checksum);
}
/* for tests */
UpdateZipAction(Patch patch, String path, String source, Collection<String> toCreate, Collection<String> toUpdate, Collection<String> toDelete, long checksum) {
super(patch, path, source, checksum, false);
myFilesToCreate = new HashSet<>(toCreate);
myFilesToUpdate = new HashSet<>(toUpdate);
myFilesToDelete = new HashSet<>(toDelete);
}
@Override
public void write(DataOutputStream out) throws IOException {
super.write(out);
out.writeInt(myFilesToCreate.size());
for (String each : myFilesToCreate) {
out.writeUTF(each);
}
out.writeInt(myFilesToUpdate.size());
for (String each : myFilesToUpdate) {
out.writeUTF(each);
}
out.writeInt(myFilesToDelete.size());
for (String each : myFilesToDelete) {
out.writeUTF(each);
}
}
@Override
public ValidationResult validate(File toDir) throws IOException {
// Firstly we check if the zip file exists at all.
if (!isOptional() && !getSource(toDir).exists()) {
ValidationResult.Option solution;
if (isStrict() || myPatch.isStrict()) {
solution = ValidationResult.Option.NONE;
}
else if (isCritical()) {
solution = ValidationResult.Option.NONE;
}
else {
solution = ValidationResult.Option.IGNORE;
}
return new ValidationResult(ValidationResult.Kind.ERROR, getReportPath(), ValidationResult.Action.UPDATE,
ValidationResult.ABSENT_MESSAGE, solution);
}
return super.validate(toDir);
}
@Override
protected boolean doCalculate(File olderFile, File newerFile) throws IOException {
Map<String, Long> oldCheckSums = new HashMap<>(), newCheckSums = new HashMap<>();
processZipFile(olderFile, (entry, in) -> oldCheckSums.put(entry.getName(), Digester.digestStream(in)));
processZipFile(newerFile, (entry, in) -> newCheckSums.put(entry.getName(), Digester.digestStream(in)));
DiffCalculator.Result diff = DiffCalculator.calculate(oldCheckSums, newCheckSums);
myFilesToCreate = diff.filesToCreate.keySet();
myFilesToUpdate = diff.filesToUpdate.keySet();
myFilesToDelete = diff.filesToDelete.keySet();
return !(myFilesToCreate.isEmpty() && myFilesToUpdate.isEmpty() && myFilesToDelete.isEmpty());
}
@Override
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
int changes = myFilesToCreate.size() + myFilesToUpdate.size();
if (changes == 0) return;
Set<String> filesToProcess = new HashSet<>(changes);
filesToProcess.addAll(myFilesToCreate);
filesToProcess.addAll(myFilesToUpdate);
try (ZipFile olderZip = new ZipFile(olderFile)) {
processZipFile(newerFile, (newerEntry, newerEntryIn) -> {
String name = newerEntry.getName();
if (filesToProcess.contains(name)) {
try {
patchOutput.putNextEntry(new ZipEntry(getPath() + "/" + name));
InputStream olderEntryIn = Utils.findEntryInputStream(olderZip, name);
if (olderEntryIn == null) {
Utils.copyStream(newerEntryIn, patchOutput);
}
else {
writeDiff(olderEntryIn, newerEntryIn, patchOutput);
}
patchOutput.closeEntry();
}
catch (IOException e) {
throw new IOException("Error building patch for .zip entry " + name, e);
}
}
});
}
}
@Override
protected void doApply(ZipFile patchFile, File backupDir, File toFile) throws IOException {
File temp = Utils.getTempFile(toFile.getName());
File source = mandatoryBackup() ? getSource(Objects.requireNonNull(backupDir)) : toFile;
try (ZipOutputWrapper out = new ZipOutputWrapper(new FileOutputStream(temp), 0)) {
processZipFile(source, (entry, in) -> {
String path = entry.getName();
if (myFilesToUpdate.contains(path)) {
try (OutputStream entryOut = out.zipStream(path)) {
applyDiff(Utils.findEntryInputStream(patchFile, getPath() + "/" + path), in, entryOut);
}
}
else if (!myFilesToDelete.contains(path)) {
out.zipEntry(entry, in);
}
});
for (String each : myFilesToCreate) {
try (InputStream in = Utils.getEntryInputStream(patchFile, getPath() + "/" + each)) {
out.zipEntry(each, in);
}
}
out.finish();
}
replaceUpdated(temp, toFile);
}
private static void processZipFile(File file, Processor processor) throws IOException {
ZipFile zip;
try {
zip = new ZipFile(file);
}
catch (IOException e) {
throw new IOException("Corrupted file: " + file, e);
}
try {
Set<String> processed = new HashSet<>();
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry inEntry = entries.nextElement();
if (inEntry.isDirectory()) continue;
if (processed.contains(inEntry.getName())) {
throw new IOException("Duplicate entry '" + inEntry.getName() + "' in " + file.getPath());
}
try (InputStream in = new BufferedInputStream(zip.getInputStream(inEntry))) {
processor.process(inEntry, new BufferedInputStream(in));
processed.add(inEntry.getName());
}
}
}
finally {
zip.close();
}
}
@FunctionalInterface
private interface Processor {
void process(ZipEntry entry, InputStream in) throws IOException;
}
@Override
public String toString() {
return super.toString() + myFilesToCreate + " " + myFilesToUpdate + " " + myFilesToDelete;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!super.equals(o)) return false;
UpdateZipAction that = (UpdateZipAction)o;
if (!Objects.equals(myFilesToCreate, that.myFilesToCreate)) return false;
if (!Objects.equals(myFilesToUpdate, that.myFilesToUpdate)) return false;
if (!Objects.equals(myFilesToDelete, that.myFilesToDelete)) return false;
return true;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Objects.hashCode(myFilesToCreate);
result = 31 * result + Objects.hashCode(myFilesToDelete);
result = 31 * result + Objects.hashCode(myFilesToUpdate);
return result;
}
}
+3 -59
View File
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import java.io.*;
@@ -27,10 +27,6 @@ public final class Utils {
private static File myTempDir;
public static boolean isZipFile(String fileName) {
return fileName.endsWith(".zip") || fileName.endsWith(".jar");
}
public synchronized static File getTempFile(String name) throws IOException {
if (myTempDir == null) {
String path = System.getProperty("java.io.tmpdir");
@@ -298,60 +294,8 @@ public final class Utils {
return result;
}
public static InputStream newFileInputStream(File file, boolean normalize) throws IOException {
return normalize && isZipFile(file.getName()) ? new NormalizedZipInputStream(file) : new FileInputStream(file);
}
private static final class NormalizedZipInputStream extends InputStream {
private final ZipFile myZip;
private final List<? extends ZipEntry> myEntries;
private InputStream myStream = null;
private int myNextEntry = 0;
private final byte[] myByte = new byte[1];
private NormalizedZipInputStream(File file) throws IOException {
myZip = new ZipFile(file);
myEntries = Collections.list(myZip.entries());
myEntries.sort(Comparator.comparing(ZipEntry::getName));
loadNextEntry();
}
private void loadNextEntry() throws IOException {
if (myStream != null) {
myStream.close();
myStream = null;
}
while (myNextEntry < myEntries.size() && myStream == null) {
myStream = findEntryInputStreamForEntry(myZip, myEntries.get(myNextEntry++));
}
}
@Override
public int read(byte[] bytes, int off, int len) throws IOException {
if (myStream == null) {
return -1;
}
int b = myStream.read(bytes, off, len);
if (b == -1) {
loadNextEntry();
return read(bytes, off, len);
}
return b;
}
@Override
public int read() throws IOException {
int b = read(myByte, 0, 1);
return b == -1 ? -1 : myByte[0];
}
@Override
public void close() throws IOException {
if (myStream != null) {
myStream.close();
}
myZip.close();
}
public static InputStream newFileInputStream(File file) throws IOException {
return new FileInputStream(file);
}
public static class OpenByteArrayOutputStream extends ByteArrayOutputStream {
Binary file not shown.
@@ -1,14 +0,0 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.updater;
public class BinaryNoBackupPatchApplyingRevertingTest extends PatchApplyingRevertingTest {
@Override
protected boolean isBinary() {
return true;
}
@Override
protected boolean isBackup() {
return false;
}
}
@@ -1,23 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.intellij.updater;
public class BinaryPatchApplyingRevertingTest extends PatchApplyingRevertingTest {
@Override
protected boolean isBinary() {
return true;
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import com.intellij.openapi.util.io.IoTestUtil;
@@ -20,21 +20,17 @@ public class DigesterTest extends UpdaterTestCase {
public void testBasics() throws Exception {
File binDir = new File(dataDir, "bin"), libDir = new File(dataDir, "lib");
assertEquals(Digester.DIRECTORY, Digester.digestRegularFile(binDir, false));
assertEquals(Digester.DIRECTORY, Digester.digestRegularFile(libDir, true));
assertEquals(Digester.DIRECTORY, Digester.digestRegularFile(binDir));
assertEquals(Digester.DIRECTORY, Digester.digestRegularFile(libDir));
assertEquals(CHECKSUMS.README_TXT, Digester.digestRegularFile(new File(dataDir, "Readme.txt"), false));
assertEquals(CHECKSUMS.BOOTSTRAP_JAR_BIN, Digester.digestRegularFile(new File(libDir, "bootstrap.jar"), false));
assertEquals(CHECKSUMS.ANNOTATIONS_JAR, Digester.digestRegularFile(new File(libDir, "annotations.jar"), true));
assertEquals(CHECKSUMS.ANNOTATIONS_CHANGED_JAR, Digester.digestRegularFile(new File(libDir, "annotations_changed.jar"), true));
assertEquals(CHECKSUMS.BOOT_JAR, Digester.digestRegularFile(new File(libDir, "boot.jar"), true));
assertEquals(CHECKSUMS.BOOT2_JAR, Digester.digestRegularFile(new File(libDir, "boot2.jar"), true));
assertEquals(CHECKSUMS.BOOT2_CHANGED_WITH_UNCHANGED_CONTENT_JAR, Digester.digestRegularFile(new File(libDir, "boot2_changed_with_unchanged_content.jar"), true));
assertEquals(CHECKSUMS.BOOT_WITH_DIRECTORY_BECOMES_FILE_JAR, Digester.digestRegularFile(new File(libDir, "boot_with_directory_becomes_file.jar"), true));
assertEquals(CHECKSUMS.BOOTSTRAP_JAR, Digester.digestRegularFile(new File(libDir, "bootstrap.jar"), true));
assertEquals(CHECKSUMS.BOOTSTRAP_DELETED_JAR, Digester.digestRegularFile(new File(libDir, "bootstrap_deleted.jar"), true));
assertEquals(CHECKSUMS.BOOTSTRAP_JAR, Digester.digestZipFile(new File(libDir, "bootstrap.jar")));
assertEquals(CHECKSUMS.README_TXT, Digester.digestRegularFile(new File(dataDir, "Readme.txt")));
assertEquals(CHECKSUMS.BOOTSTRAP_JAR, Digester.digestRegularFile(new File(libDir, "bootstrap.jar")));
assertEquals(CHECKSUMS.ANNOTATIONS_JAR, Digester.digestRegularFile(new File(libDir, "annotations.jar")));
assertEquals(CHECKSUMS.ANNOTATIONS_CHANGED_JAR, Digester.digestRegularFile(new File(libDir, "annotations_changed.jar")));
assertEquals(CHECKSUMS.BOOT_JAR, Digester.digestRegularFile(new File(libDir, "boot.jar")));
assertEquals(CHECKSUMS.BOOT_CHANGED_JAR, Digester.digestRegularFile(new File(libDir, "boot_with_directory_becomes_file.jar")));
assertEquals(CHECKSUMS.BOOTSTRAP_JAR, Digester.digestRegularFile(new File(libDir, "bootstrap.jar")));
assertEquals(CHECKSUMS.BOOTSTRAP_DELETED_JAR, Digester.digestRegularFile(new File(libDir, "bootstrap_deleted.jar")));
}
@Test
@@ -67,11 +63,11 @@ public class DigesterTest extends UpdaterTestCase {
@NotNull Path target = Paths.get(dataDir.getPath() + "/Readme.txt");
Files.createSymbolicLink(link, target);
assertEquals(CHECKSUMS.LINK_TO_README_TXT, Digester.digestRegularFile(simpleLink, false));
assertEquals(CHECKSUMS.LINK_TO_DOT_README_TXT, Digester.digestRegularFile(relativeLink, false));
assertEquals(CHECKSUMS.LINK_TO_README_TXT, Digester.digestRegularFile(simpleLink));
assertEquals(CHECKSUMS.LINK_TO_DOT_README_TXT, Digester.digestRegularFile(relativeLink));
try {
Digester.digestRegularFile(absoluteLink, false);
Digester.digestRegularFile(absoluteLink);
fail("Absolute links should cause indigestion");
}
catch (IOException e) {
@@ -85,8 +81,8 @@ public class DigesterTest extends UpdaterTestCase {
File testFile = new File(tempDir.getRoot(), "idea.bat");
Utils.copy(new File(dataDir, "bin/idea.bat"), testFile, false);
assertEquals(CHECKSUMS.IDEA_BAT, Digester.digestRegularFile(testFile, false));
assertEquals(CHECKSUMS.IDEA_BAT, Digester.digestRegularFile(testFile));
Utils.setExecutable(testFile);
assertEquals(CHECKSUMS.IDEA_BAT | Digester.EXECUTABLE, Digester.digestRegularFile(testFile, false));
assertEquals(CHECKSUMS.IDEA_BAT | Digester.EXECUTABLE, Digester.digestRegularFile(testFile));
}
}
@@ -3,7 +3,6 @@ package com.intellij.updater;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.IoTestUtil;
import com.intellij.testFramework.RunFirst;
import com.intellij.util.containers.ContainerUtil;
import org.junit.Before;
import org.junit.Test;
@@ -28,12 +27,20 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeFalse;
@RunFirst
@SuppressWarnings("JUnit3StyleTestMethodInJUnit4Class")
public abstract class PatchApplyingRevertingTest extends PatchTestCase {
@SuppressWarnings("JUnitTestCaseWithNoTests")
public static final class StandardModeTest extends PatchApplyingRevertingTest { }
@SuppressWarnings("JUnitTestCaseWithNoTests")
public static final class NoBackupTest extends PatchApplyingRevertingTest { }
private File myFile;
private PatchSpec myPatchSpec;
private boolean myDoBackup;
private PatchApplyingRevertingTest() { }
@Before
@Override
public void before() throws Exception {
@@ -41,17 +48,8 @@ public abstract class PatchApplyingRevertingTest extends PatchTestCase {
myFile = getTempFile("patch.zip");
myPatchSpec = new PatchSpec()
.setOldFolder(myOlderDir.getAbsolutePath())
.setNewFolder(myNewerDir.getAbsolutePath())
.setBinary(isBinary());
myDoBackup = isBackup();
}
protected boolean isBinary() {
return false;
}
protected boolean isBackup() {
return true;
.setNewFolder(myNewerDir.getAbsolutePath());
myDoBackup = !(this instanceof NoBackupTest);
}
@Test
@@ -286,18 +284,7 @@ public abstract class PatchApplyingRevertingTest extends PatchTestCase {
FileUtil.delete(new File(myOlderDir, "lib/annotations.jar"));
if (isBinary()) {
assertAppliedAndReverted();
}
else {
PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
assertThat(preparationResult.validationResults).containsExactly(
new ValidationResult(ValidationResult.Kind.ERROR,
"lib/annotations.jar",
ValidationResult.Action.UPDATE,
ValidationResult.ABSENT_MESSAGE,
ValidationResult.Option.NONE));
}
assertAppliedAndReverted();
}
@Test
@@ -392,8 +379,7 @@ public abstract class PatchApplyingRevertingTest extends PatchTestCase {
PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
assertThat(preparationResult.validationResults).isEmpty();
long hash = myPatchSpec.isBinary() ? CHECKSUMS.BOOTSTRAP_JAR_BIN : CHECKSUMS.BOOTSTRAP_JAR;
assertAppliedAndReverted(preparationResult, expected -> expected.put("lib/boot.jar", hash));
assertAppliedAndReverted(preparationResult, expected -> expected.put("lib/boot.jar", CHECKSUMS.BOOTSTRAP_JAR));
}
@Test
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import com.intellij.openapi.util.SystemInfo;
@@ -13,7 +13,6 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -27,7 +26,7 @@ public class PatchCreationTest extends PatchTestCase {
public void testDigestFiles() throws Exception {
Patch patch = createPatch();
Map<String, Long> checkSums = digest(patch, myOlderDir);
assertThat(checkSums).hasSize(11);
assertThat(checkSums).hasSize(10);
}
@Test
@@ -38,16 +37,8 @@ public class PatchCreationTest extends PatchTestCase {
new CreateAction(patch, "newDir/"),
new CreateAction(patch, "newDir/newFile.txt"),
new UpdateAction(patch, "Readme.txt", CHECKSUMS.README_TXT),
new UpdateZipAction(patch, "lib/annotations.jar",
singletonList("org/jetbrains/annotations/NewClass.class"),
singletonList("org/jetbrains/annotations/Nullable.class"),
singletonList("org/jetbrains/annotations/TestOnly.class"),
CHECKSUMS.ANNOTATIONS_JAR),
new UpdateZipAction(patch, "lib/bootstrap.jar",
Collections.emptyList(),
Collections.emptyList(),
singletonList("com/intellij/ide/ClassloaderUtil.class"),
CHECKSUMS.BOOTSTRAP_JAR));
new UpdateAction(patch, "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR),
new UpdateAction(patch, "lib/bootstrap.jar", CHECKSUMS.BOOTSTRAP_JAR));
}
@Test
@@ -61,16 +52,8 @@ public class PatchCreationTest extends PatchTestCase {
assertThat(sortActions(patch.getActions())).containsExactly(
new CreateAction(patch, "newDir/"),
new CreateAction(patch, "newDir/newFile.txt"),
new UpdateZipAction(patch, "lib/annotations.jar",
singletonList("org/jetbrains/annotations/NewClass.class"),
singletonList("org/jetbrains/annotations/Nullable.class"),
singletonList("org/jetbrains/annotations/TestOnly.class"),
CHECKSUMS.ANNOTATIONS_JAR),
new UpdateZipAction(patch, "lib/bootstrap.jar",
Collections.emptyList(),
Collections.emptyList(),
singletonList("com/intellij/ide/ClassloaderUtil.class"),
CHECKSUMS.BOOTSTRAP_JAR));
new UpdateAction(patch, "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR),
new UpdateAction(patch, "lib/bootstrap.jar", CHECKSUMS.BOOTSTRAP_JAR));
}
@Test
@@ -218,11 +201,7 @@ public class PatchCreationTest extends PatchTestCase {
assertThat(sortActions(patch.getActions())).containsExactly(
new DeleteAction(patch, "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR),
new CreateAction(patch, "lib/redist/"),
new UpdateZipAction(patch, "lib/redist/annotations.jar", "lib/annotations.jar",
singletonList("org/jetbrains/annotations/NewClass.class"),
singletonList("org/jetbrains/annotations/Nullable.class"),
singletonList("org/jetbrains/annotations/TestOnly.class"),
CHECKSUMS.ANNOTATIONS_JAR));
new UpdateAction(patch, "lib/redist/annotations.jar", "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR, false));
}
@Test
@@ -252,12 +231,12 @@ public class PatchCreationTest extends PatchTestCase {
Patch patch = createPatch(spec -> spec.setOptionalFiles(asList("lib/annotations.bin", "lib/redist/annotations.bin")));
assertThat(sortActions(patch.getActions())).containsExactly(
new DeleteAction(patch, "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR_BIN),
new DeleteAction(patch, "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR_BIN),
new DeleteAction(patch, "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR),
new DeleteAction(patch, "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR),
new CreateAction(patch, "lib/redist/"),
new CreateAction(patch, "lib64/redist/"),
new UpdateAction(patch, "lib/redist/annotations.bin", "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR_BIN, true),
new UpdateAction(patch, "lib64/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR_BIN, false));
new UpdateAction(patch, "lib/redist/annotations.bin", "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR, true),
new UpdateAction(patch, "lib64/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR, false));
}
@Test
@@ -270,12 +249,12 @@ public class PatchCreationTest extends PatchTestCase {
Patch patch = createPatch(spec -> spec.setOptionalFiles(asList("lib/annotations.bin", "lib/redist/annotations.bin")));
assertThat(sortActions(patch.getActions())).containsExactly(
new DeleteAction(patch, "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR_BIN),
new DeleteAction(patch, "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR_BIN),
new DeleteAction(patch, "lib/annotations.bin", CHECKSUMS.ANNOTATIONS_CHANGED_JAR),
new DeleteAction(patch, "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR),
new CreateAction(patch, "lib/redist/"),
new CreateAction(patch, "lib64/redist/"),
new UpdateAction(patch, "lib/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR_BIN, true),
new UpdateAction(patch, "lib64/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR_BIN, true));
new UpdateAction(patch, "lib/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR, true),
new UpdateAction(patch, "lib64/redist/annotations.bin", "lib64/annotations.bin", CHECKSUMS.ANNOTATIONS_JAR, true));
}
@Test
@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import com.intellij.openapi.util.io.FileUtil;
@@ -41,11 +41,6 @@ public abstract class PatchTestCase extends UpdaterTestCase {
FileUtil.delete(new File(myNewerDir, "lib/bootstrap.jar"));
FileUtil.rename(new File(myNewerDir, "lib/bootstrap_deleted.jar"),
new File(myNewerDir, "lib/bootstrap.jar"));
FileUtil.delete(new File(myOlderDir, "lib/boot2_changed_with_unchanged_content.jar"));
FileUtil.delete(new File(myNewerDir, "lib/boot2.jar"));
FileUtil.rename(new File(myNewerDir, "lib/boot2_changed_with_unchanged_content.jar"),
new File(myNewerDir, "lib/boot2.jar"));
}
protected Patch createPatch() throws IOException {
@@ -65,7 +60,7 @@ public abstract class PatchTestCase extends UpdaterTestCase {
}
protected static Map<String, Long> digest(Patch patch, File dir) throws IOException {
return new TreeMap<>(patch.digestFiles(dir, Collections.emptySet(), false));
return new TreeMap<>(patch.digestFiles(dir, Collections.emptySet()));
}
protected static List<PatchAction> sortActions(List<PatchAction> actions) {
@@ -100,4 +95,4 @@ public abstract class PatchTestCase extends UpdaterTestCase {
crc32.update(data);
return crc32.getValue();
}
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.updater;
import com.intellij.openapi.application.ex.PathManagerEx;
@@ -55,17 +55,12 @@ public abstract class UpdaterTestCase {
protected static final class CheckSums {
public final long README_TXT;
public final long IDEA_BAT;
public final long ANNOTATIONS_JAR = 2119442657L;
public final long ANNOTATIONS_JAR_BIN = 2525796836L;
public final long ANNOTATIONS_CHANGED_JAR = 4088078858L;
public final long ANNOTATIONS_CHANGED_JAR_BIN = 2587736223L;
public final long BOOT_JAR = 3018038682L;
public final long BOOT_WITH_DIRECTORY_BECOMES_FILE_JAR = 1972168924;
public final long BOOT2_JAR = 2406818996L;
public final long BOOT2_CHANGED_WITH_UNCHANGED_CONTENT_JAR = 2406818996L;
public final long BOOTSTRAP_JAR = 2082851308L;
public final long BOOTSTRAP_JAR_BIN = 2745721972L;
public final long BOOTSTRAP_DELETED_JAR = 544883981L;
public final long ANNOTATIONS_JAR = 2525796836L;
public final long ANNOTATIONS_CHANGED_JAR = 2587736223L;
public final long BOOT_JAR = 2697993201L;
public final long BOOT_CHANGED_JAR = 2957038758L;
public final long BOOTSTRAP_JAR = 2745721972L;
public final long BOOTSTRAP_DELETED_JAR = 811764767L;
public final long LINK_TO_README_TXT = 2305843011042707672L;
public final long LINK_TO_DOT_README_TXT;
@@ -1,9 +0,0 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.updater;
public class ZipAwareNoBackupPatchApplyingRevertingTest extends PatchApplyingRevertingTest {
@Override
protected boolean isBackup() {
return false;
}
}
@@ -1,78 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.intellij.updater;
import com.intellij.openapi.util.io.FileUtil;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
public class ZipAwarePatchApplyingRevertingTest extends PatchApplyingRevertingTest {
@Test
public void failOnEmptyTargetJar() throws Exception {
File sourceJar = new File(myOlderDir, "lib/empty.jar");
FileUtil.copy(new File(myOlderDir, "lib/annotations.jar"), sourceJar);
try {
File targetJar = new File(myNewerDir, "lib/empty.jar");
FileUtil.writeToFile(targetJar, "x");
try {
createPatch();
fail("Should have failed to create a patch against empty .jar");
}
catch (IOException | UncheckedIOException e) {
assertThat(e.getMessage()).endsWith("Corrupted file: " + targetJar);
}
finally {
FileUtil.delete(targetJar);
}
}
finally {
FileUtil.delete(sourceJar);
}
}
@Test
public void failOnEmptySourceJar() throws Exception {
File sourceJar = new File(myOlderDir, "lib/empty.jar");
FileUtil.writeToFile(sourceJar, "x");
try {
File targetJar = new File(myNewerDir, "lib/empty.jar");
FileUtil.copy(new File(myNewerDir, "lib/annotations.jar"), targetJar);
try {
createPatch();
fail("Should have failed to create a patch from empty .jar");
}
catch (IOException | UncheckedIOException e) {
assertThat(e.getMessage()).endsWith("Corrupted file: " + sourceJar);
}
finally {
FileUtil.delete(targetJar);
}
}
finally {
FileUtil.delete(sourceJar);
}
}
}