From cf0760f62e090fb2ea8bf87468898762878902c0 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 7 Mar 2017 12:56:32 +0100 Subject: [PATCH] [updater] finds a nearest candidate for move (improves over IDEA-CR-18874) --- .../com/intellij/updater/DiffCalculator.java | 37 +++++++++++-------- .../com/intellij/updater/PatchTest.java | 18 +++++++++ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/updater/src/com/intellij/updater/DiffCalculator.java b/updater/src/com/intellij/updater/DiffCalculator.java index 0cb201386ba9..db6d6c721342 100644 --- a/updater/src/com/intellij/updater/DiffCalculator.java +++ b/updater/src/com/intellij/updater/DiffCalculator.java @@ -44,20 +44,19 @@ public class DiffCalculator { } if (lookForMoved) { - Map byContent = inverse(result.filesToDelete); + Map> byContent = groupFilesByContent(result.filesToDelete); Map> byName = groupFilesByName(result.filesToDelete); for (Map.Entry create : toCreate.entrySet()) { if (Digester.isFile(create.getValue())) { - String source = byContent.get(create.getValue()); + List sameContent = byContent.get(create.getValue()); + String source = findBestCandidateForMove(sameContent, create.getKey()); boolean move = true; - if (source == null || create.getKey().startsWith("jre")) { + if (source == null) { List sameName = byName.get(new File(create.getKey()).getName()); - if (sameName != null) { - source = findBestCandidateForMove(sameName, create.getKey()); - move = false; - } + source = findBestCandidateForMove(sameName, create.getKey()); + move = false; } if (source != null && !critical.contains(source)) { @@ -87,6 +86,8 @@ public class DiffCalculator { } private static String findBestCandidateForMove(List paths, String path) { + if (paths == null) return null; + String best = ""; String[] dirs = path.split("/"); @@ -113,6 +114,20 @@ public class DiffCalculator { return best; } + public static Map> groupFilesByContent(Map map) { + Map> result = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + String path = entry.getKey(); + if (!path.endsWith("/")) { + Long hash = entry.getValue(); + List paths = result.get(hash); + if (paths == null) result.put(hash, (paths = new LinkedList<>())); + paths.add(path); + } + } + return result; + } + private static Map> groupFilesByName(Map toDelete) { Map> result = new HashMap<>(); for (String path : toDelete.keySet()) { @@ -126,14 +141,6 @@ public class DiffCalculator { return result; } - public static Map inverse(Map map) { - Map inv = new LinkedHashMap<>(); - for (Map.Entry entry : map.entrySet()) { - inv.put(entry.getValue(), entry.getKey()); - } - return inv; - } - private static Map withAllRemoved(Map from, Map toRemove) { Map result = new LinkedHashMap<>(from); for (String each : toRemove.keySet()) { diff --git a/updater/testSrc/com/intellij/updater/PatchTest.java b/updater/testSrc/com/intellij/updater/PatchTest.java index 9196415d73fb..333a4e54f434 100644 --- a/updater/testSrc/com/intellij/updater/PatchTest.java +++ b/updater/testSrc/com/intellij/updater/PatchTest.java @@ -225,6 +225,24 @@ public class PatchTest extends PatchTestCase { CHECKSUMS.ANNOTATIONS_JAR)); } + @Test + public void testZipFileMoveWithAlternatives() throws Exception { + FileUtil.copy(new File(myOlderDir, "lib/annotations.jar"), new File(myOlderDir, "lib64/annotations.jar")); + FileUtil.delete(myNewerDir); + FileUtil.copyDir(myOlderDir, myNewerDir); + FileUtil.rename(new File(myNewerDir, "lib/annotations.jar"), new File(myNewerDir, "lib/redist/annotations.jar")); + FileUtil.rename(new File(myNewerDir, "lib64/annotations.jar"), new File(myNewerDir, "lib64/redist/annotations.jar")); + + Patch patch = createPatch(); + assertThat(sortActions(patch.getActions())).containsExactly( + new DeleteAction(patch, "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR), + new DeleteAction(patch, "lib64/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR), + new CreateAction(patch, "lib/redist/"), + new CreateAction(patch, "lib64/redist/"), + new UpdateAction(patch, "lib/redist/annotations.jar", "lib/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR, true), + new UpdateAction(patch, "lib64/redist/annotations.jar", "lib64/annotations.jar", CHECKSUMS.ANNOTATIONS_JAR, true)); + } + @Test public void testSaveLoad() throws Exception { Patch original = createPatch();