mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
[updater] getting rid of long unused ZIP-aware mode
GitOrigin-RevId: 2189f626b1bd25c950c4d7cb0eb287743163557c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a3c76f4a2a
commit
ff203c76f7
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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.
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user