[updater] removing recursive symlink visiting (no file overwrites on apply; smaller patch)

GitOrigin-RevId: 373d9cc82a65f3878c732940f7d09fdd1d7e5a3f
This commit is contained in:
Roman Shevchenko
2020-01-23 14:38:44 +00:00
committed by intellij-monorepo-bot
parent dfb2cf303c
commit 9aed61ebd3
3 changed files with 70 additions and 25 deletions
+3 -5
View File
@@ -1,4 +1,4 @@
// Copyright 2000-2019 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-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.
package com.intellij.updater;
import java.io.*;
@@ -220,8 +220,7 @@ public class Patch {
File toDir = toBaseDir(rootDir);
boolean checkWarnings = true;
while (checkWarnings) {
// always collect files and folders - to avoid cases such as IDEA-152249
files = Utils.collectRelativePaths(toDir);
files = Utils.collectRelativePaths(toDir.toPath());
checkWarnings = false;
for (String file : files) {
String warning = myWarnings.get(file);
@@ -416,8 +415,7 @@ public class Patch {
public Map<String, Long> digestFiles(File dir, List<String> ignoredFiles, boolean normalize) throws IOException {
Map<String, Long> result = new LinkedHashMap<>();
//always collect files and folders to avoid cases such as IDEA-152249
LinkedHashSet<String> paths = Utils.collectRelativePaths(dir);
LinkedHashSet<String> paths = Utils.collectRelativePaths(dir.toPath());
for (String each : paths) {
if (!ignoredFiles.contains(each)) {
result.put(each, digestFile(new File(dir, each), normalize));
+20 -19
View File
@@ -1,4 +1,4 @@
// Copyright 2000-2019 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-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.
package com.intellij.updater;
import java.io.*;
@@ -272,28 +272,29 @@ public class Utils {
return new BufferedInputStream(zipFile.getInputStream(entry));
}
public static LinkedHashSet<String> collectRelativePaths(File dir) {
// always collect files and folders - to avoid cases such as IDEA-152249
public static LinkedHashSet<String> collectRelativePaths(Path root) throws IOException {
LinkedHashSet<String> result = new LinkedHashSet<>();
collectRelativePaths(dir, result, null);
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (dir != root) {
result.add(root.relativize(dir).toString() + '/');
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
result.add(root.relativize(file).toString());
return FileVisitResult.CONTINUE;
}
});
return result;
}
private static void collectRelativePaths(File dir, LinkedHashSet<? super String> result, String parentPath) {
File[] children = dir.listFiles();
if (children == null) return;
for (File each : children) {
String relativePath = (parentPath == null ? "" : parentPath + '/') + each.getName();
if (each.isDirectory()) {
result.add(relativePath + '/'); // the trailing slash is used by .zip to determine whether it is a directory
collectRelativePaths(each, result, relativePath);
}
else {
result.add(relativePath);
}
}
}
public static InputStream newFileInputStream(File file, boolean normalize) throws IOException {
return normalize && isZipFile(file.getName()) ? new NormalizedZipInputStream(file) : new FileInputStream(file);
}
@@ -1,10 +1,16 @@
// 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.
// 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.
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.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import java.util.zip.CRC32;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeFalse;
@@ -77,4 +83,44 @@ public class SymlinkPatchTest extends PatchTestCase {
new DeleteAction(patch, "Readme.lnk", CHECKSUMS.LINK_TO_DOT_README_TXT),
new CreateAction(patch, "Readme.link"));
}
@Test
public void multipleDirectorySymlinks() throws Exception {
long l1 = randomFile(myOlderDir.toPath().resolve("A.framework/Versions/A/Libraries/lib1.dylib"));
long l2 = randomFile(myOlderDir.toPath().resolve("A.framework/Versions/A/Libraries/lib2.dylib"));
long r1 = randomFile(myOlderDir.toPath().resolve("A.framework/Versions/A/Resources/r1.bin"));
long r2 = randomFile(myOlderDir.toPath().resolve("A.framework/Versions/A/Resources/r2.bin"));
Files.createSymbolicLink(myOlderDir.toPath().resolve("A.framework/Versions/Current"), Paths.get("A"));
Files.createSymbolicLink(myOlderDir.toPath().resolve("A.framework/Libraries"), Paths.get("Versions/Current/Libraries"));
Files.createSymbolicLink(myOlderDir.toPath().resolve("A.framework/Resources"), Paths.get("Versions/Current/Resources"));
randomFile(myNewerDir.toPath().resolve("A.framework/Versions/A/Libraries/lib1.dylib"));
randomFile(myNewerDir.toPath().resolve("A.framework/Versions/A/Libraries/lib2.dylib"));
randomFile(myNewerDir.toPath().resolve("A.framework/Versions/A/Resources/r1.bin"));
randomFile(myNewerDir.toPath().resolve("A.framework/Versions/A/Resources/r2.bin"));
Files.createSymbolicLink(myNewerDir.toPath().resolve("A.framework/Versions/Current"), Paths.get("A"));
Files.createSymbolicLink(myNewerDir.toPath().resolve("A.framework/Libraries"), Paths.get("Versions/Current/Libraries"));
Files.createSymbolicLink(myNewerDir.toPath().resolve("A.framework/Resources"), Paths.get("Versions/Current/Resources"));
Patch patch = createPatch();
assertThat(sortActions(patch.getActions())).containsExactly(
new UpdateAction(patch, "A.framework/Versions/A/Libraries/lib1.dylib", l1),
new UpdateAction(patch, "A.framework/Versions/A/Libraries/lib2.dylib", l2),
new UpdateAction(patch, "A.framework/Versions/A/Resources/r1.bin", r1),
new UpdateAction(patch, "A.framework/Versions/A/Resources/r2.bin", r2));
}
private static long randomFile(Path file) throws IOException {
Random rnd = new Random();
int size = (1 + rnd.nextInt(1023)) * 1024;
byte[] data = new byte[size];
rnd.nextBytes(data);
Files.createDirectories(file.getParent());
Files.write(file, data);
CRC32 crc32 = new CRC32();
crc32.update(data);
return crc32.getValue();
}
}