mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 11:53:49 +07:00
[updater] reuse diffs from sibling patches
When building several patches for different OS/Arch pairs of IDE distributions, we could reuse diffs since IDE distributions contains a lot of exactly the same files. Fixes IJI-319 GitOrigin-RevId: 7a74330a8467121106de5b74e7443dc96d0ebfb7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0a2276866a
commit
00c7b23d67
@@ -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.File;
|
||||
@@ -20,7 +20,7 @@ import static com.intellij.updater.Runner.LOG;
|
||||
public final class PatchFileCreator {
|
||||
private static final String PATCH_INFO_FILE_NAME = ".patch-info";
|
||||
|
||||
public static Patch create(PatchSpec spec, File patchFile, UpdaterUI ui) throws IOException {
|
||||
public static Patch create(PatchSpec spec, File patchFile, UpdaterUI ui, Path cacheDir) throws IOException {
|
||||
LOG.info("Creating the patch file '" + patchFile + "'...");
|
||||
ui.startProcess("Creating the patch file '" + patchFile + "'...");
|
||||
|
||||
@@ -40,11 +40,27 @@ public final class PatchFileCreator {
|
||||
if (action instanceof UpdateAction && !action.isCritical()) {
|
||||
int _i = i;
|
||||
tasks.put(action, executor.submit(() -> {
|
||||
Path cached = null;
|
||||
if (cacheDir != null) {
|
||||
String cachedName = getCachedFileName((UpdateAction)action, newerDir);
|
||||
if (cachedName != null) {
|
||||
cached = cacheDir.resolve(cachedName);
|
||||
if (Files.exists(cached) && Files.isRegularFile(cached)) {
|
||||
LOG.info("Reusing diff for " + action.getPath() + " : " + cachedName);
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
}
|
||||
Path temp = Utils.getTempFile("diff_" + _i).toPath();
|
||||
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(temp))) {
|
||||
out.setLevel(0);
|
||||
action.buildPatchFile(olderDir, newerDir, out);
|
||||
}
|
||||
if (cached != null) {
|
||||
Files.createDirectories(cached.getParent());
|
||||
Files.copy(temp, cached);
|
||||
LOG.info("Caching diff for " + action.getPath() + " : " + cached.getFileName());
|
||||
}
|
||||
return temp;
|
||||
}));
|
||||
}
|
||||
@@ -93,6 +109,24 @@ public final class PatchFileCreator {
|
||||
return patchInfo;
|
||||
}
|
||||
|
||||
private static String getCachedFileName(UpdateAction action, File newerDir) {
|
||||
if (action.isMove()) return null;
|
||||
if (!Digester.isFile(action.getChecksum())) return null;
|
||||
// Single file diff is a zip file with single entry corresponding to target file name, so entry name should be part of caching key
|
||||
// Also both source and target digests are part of key
|
||||
try {
|
||||
return "diff-v1-" +
|
||||
action.getPath().replaceAll("[^A-Za-z0-9_\\-]","_") +
|
||||
'-' +
|
||||
Long.toHexString(action.getChecksum()) +
|
||||
'-' +
|
||||
Long.toHexString(Digester.digestRegularFile(action.getFile(newerDir), false));
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static PreparationResult prepareAndValidate(File patchFile,
|
||||
File toDir,
|
||||
UpdaterUI ui) throws IOException, OperationCancelledException {
|
||||
|
||||
@@ -145,6 +145,8 @@ public final class Runner {
|
||||
String timeoutStr = getArgument(args, "timeout");
|
||||
int timeout = timeoutStr != null ? Integer.parseInt(timeoutStr) : 0;
|
||||
|
||||
String cacheDir = getArgument(args, "cache-dir");
|
||||
|
||||
PatchSpec spec = new PatchSpec()
|
||||
.setOldVersionDescription(oldVersionDesc)
|
||||
.setNewVersionDescription(newVersionDesc)
|
||||
@@ -164,7 +166,7 @@ public final class Runner {
|
||||
.setWarnings(warnings)
|
||||
.setTimeout(timeout);
|
||||
|
||||
boolean success = create(spec);
|
||||
boolean success = create(spec, cacheDir != null ? Paths.get(cacheDir) : null);
|
||||
System.exit(success ? 0 : 1);
|
||||
}
|
||||
else if (args.length >= 2 && ("install".equals(args[0]) || "apply".equals(args[0])) ||
|
||||
@@ -289,6 +291,8 @@ public final class Runner {
|
||||
" 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" +
|
||||
" will be validated\n" +
|
||||
" --cache-dir=<dir>: Sets directory where diffs can be cached.\n" +
|
||||
" Useful when building several patches on folders with common files.\n" +
|
||||
" --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" +
|
||||
@@ -302,13 +306,13 @@ public final class Runner {
|
||||
" <folder>: The folder where product was installed. For example: c:/Program Files/JetBrains/IntelliJ IDEA 2017.3.4");
|
||||
}
|
||||
|
||||
private static boolean create(PatchSpec spec) {
|
||||
private static boolean create(PatchSpec spec, Path cacheDir) {
|
||||
ConsoleUpdaterUI ui = new ConsoleUpdaterUI();
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
File tempPatchFile = Utils.getTempFile("patch");
|
||||
PatchFileCreator.create(spec, tempPatchFile, ui);
|
||||
PatchFileCreator.create(spec, tempPatchFile, ui, cacheDir);
|
||||
|
||||
LOG.info("Packing JAR file: " + spec.getPatchFile());
|
||||
ui.startProcess("Packing JAR file '" + spec.getPatchFile() + "'...");
|
||||
|
||||
@@ -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.FileUtil;
|
||||
@@ -15,7 +15,10 @@ import java.io.RandomAccessFile;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipFile;
|
||||
@@ -664,7 +667,7 @@ public abstract class PatchApplyingRevertingTest extends PatchTestCase {
|
||||
@Override
|
||||
protected Patch createPatch() throws IOException {
|
||||
assertFalse(myFile.exists());
|
||||
Patch patch = PatchFileCreator.create(myPatchSpec, myFile, TEST_UI);
|
||||
Patch patch = PatchFileCreator.create(myPatchSpec, myFile, TEST_UI, null);
|
||||
assertTrue(myFile.exists());
|
||||
return patch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user