[FIX] Vfs bug fixes

This commit is contained in:
Gravita 2025-07-18 14:03:28 +07:00
parent 9d3b3031cc
commit 2c74375bd3
5 changed files with 123 additions and 9 deletions

View file

@ -415,6 +415,9 @@ public Path initVfsDirectory() {
} }
} }
} }
if(LogHelper.isDevEnabled()) {
Vfs.get().debugPrint(LogHelper.Level.DEV);
}
return defaultPath; return defaultPath;
} }
} }

View file

@ -4,11 +4,13 @@
import pro.gravit.launcher.base.vfs.VfsDirectory; import pro.gravit.launcher.base.vfs.VfsDirectory;
import pro.gravit.launcher.base.vfs.directory.OverlayVfsDirectory; import pro.gravit.launcher.base.vfs.directory.OverlayVfsDirectory;
import pro.gravit.launcher.core.backend.LauncherBackendAPI; import pro.gravit.launcher.core.backend.LauncherBackendAPI;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper; import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -21,14 +23,23 @@ public ResourceLayerImpl(Path basePath, List<Path> overlayList) {
vfsPath = basePath; vfsPath = basePath;
return; return;
} }
List<VfsDirectory> overlays = Stream.concat(overlayList.stream(), Stream.of(Path.of(""))) List<VfsDirectory> overlays = new ArrayList<>();
.map(basePath::resolve) overlays.add((VfsDirectory) Vfs.get().resolve(basePath));
.map(x -> (VfsDirectory) Vfs.get().resolve(x)) for(var e : overlayList) {
.filter(Objects::nonNull) var dir = (VfsDirectory) Vfs.get().resolve(basePath.resolve(e));
.toList(); if(dir != null) {
overlays.add(dir);
}
}
OverlayVfsDirectory directory = new OverlayVfsDirectory(overlays); OverlayVfsDirectory directory = new OverlayVfsDirectory(overlays);
String randomName = SecurityHelper.randomStringToken(); String randomName = SecurityHelper.randomStringToken();
vfsPath = Path.of(randomName); vfsPath = Path.of(randomName);
if(LogHelper.isDevEnabled()) {
LogHelper.dev("Make overlay %s from %s", vfsPath, basePath);
for(var e : overlays) {
LogHelper.dev("Layer %s", e.getClass().getSimpleName());
}
}
Vfs.get().put(vfsPath, directory); Vfs.get().put(vfsPath, directory);
} }

View file

@ -3,6 +3,7 @@
import pro.gravit.launcher.base.vfs.directory.SimpleVfsDirectory; import pro.gravit.launcher.base.vfs.directory.SimpleVfsDirectory;
import pro.gravit.launcher.base.vfs.protocol.vfs.VfsURLStreamHandlerProvider; import pro.gravit.launcher.base.vfs.protocol.vfs.VfsURLStreamHandlerProvider;
import pro.gravit.utils.helper.LogHelper;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
@ -17,6 +18,7 @@
public class Vfs { public class Vfs {
private final VfsDirectory directory; private final VfsDirectory directory;
private volatile String name;
private static final Map<String, Vfs> map = new HashMap<>(); private static final Map<String, Vfs> map = new HashMap<>();
private static final Vfs defaultImpl = new Vfs(); private static final Vfs defaultImpl = new Vfs();
static { static {
@ -36,8 +38,33 @@ public VfsEntry resolve(Path path) {
return directory.resolve(path); return directory.resolve(path);
} }
public VfsEntry createDirectories(Path path) {
VfsDirectory current = directory;
for(int i=0;i<path.getNameCount();++i) {
String s = path.getName(i).toString();
var value = current.find(s);
if(value == null) {
value = new SimpleVfsDirectory();
if(current instanceof SimpleVfsDirectory simpleVfsDirectory) {
simpleVfsDirectory.put(s, value);
} else {
throw new VfsException(String.format("%s not support add new files", path.getParent()));
}
}
if(value instanceof VfsDirectory vfsDirectory) {
current = vfsDirectory;
} else {
throw new VfsException(String.format("%s not a directory", path.getParent()));
}
}
return current;
}
public void put(Path path, VfsEntry entry) { public void put(Path path, VfsEntry entry) {
VfsEntry parent = resolve(path.getParent()); VfsEntry parent = resolve(path.getParent());
if(parent == null) {
parent = createDirectories(path.getParent());
}
if(parent instanceof SimpleVfsDirectory dir) { if(parent instanceof SimpleVfsDirectory dir) {
dir.put(path.getFileName().toString(), entry); dir.put(path.getFileName().toString(), entry);
} else { } else {
@ -45,12 +72,29 @@ public void put(Path path, VfsEntry entry) {
} }
} }
public void debugPrint(LogHelper.Level level) {
debugPrint(level, directory, Path.of(""));
}
private void debugPrint(LogHelper.Level level, VfsDirectory vfsDirectory, Path path) {
try(var stream = vfsDirectory.getFiles()) {
for(var e : stream.toList()) {
VfsEntry entry = vfsDirectory.find(e);
LogHelper.log(level, String.format("%s - %s", path.resolve(e), entry.getClass().getSimpleName()), false);
if(entry instanceof VfsDirectory nextDirectory) {
debugPrint(level, nextDirectory, path.resolve(e));
}
}
}
}
public static void register(String name, Vfs vfs) { public static void register(String name, Vfs vfs) {
map.put(name, vfs); map.put(name, vfs);
vfs.name = name;
} }
public static Vfs getByName(String name) { public static Vfs getByName(String name) {
if(name == null) { if(name == null || name.isEmpty()) {
return defaultImpl; return defaultImpl;
} }
return map.get(name); return map.get(name);
@ -74,8 +118,8 @@ public URL getURL(String path) throws IOException {
} }
public URL getURL(Path name) throws IOException { public URL getURL(Path name) throws IOException {
try (InputStream stream = defaultImpl.getInputStream(name)) { try (InputStream stream = getInputStream(name)) {
return new URI("vfs", null, "/"+name, null).toURL(); return new URI("vfs", this.name, "/"+name, null).toURL();
} catch (UnsupportedOperationException ex) { } catch (UnsupportedOperationException ex) {
throw new FileNotFoundException(name.toString()); throw new FileNotFoundException(name.toString());
} catch (URISyntaxException e) { } catch (URISyntaxException e) {

View file

@ -40,7 +40,7 @@ public VfsEntry resolve(Path path) {
return entity; return entity;
} }
} }
return null; return current;
} }
public VfsEntry remove(String name) { public VfsEntry remove(String name) {

View file

@ -0,0 +1,56 @@
package pro.gravit.launcher;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import pro.gravit.launcher.base.vfs.Vfs;
import pro.gravit.launcher.base.vfs.VfsDirectory;
import pro.gravit.launcher.base.vfs.VfsEntry;
import pro.gravit.launcher.base.vfs.directory.OverlayVfsDirectory;
import pro.gravit.launcher.base.vfs.file.UrlVfsFile;
import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class VfsTest {
@Test
public void testVfs() throws Exception {
List<Path> paths = List.of(
Path.of("test/testfile.txt"),
Path.of("test/dir/testfile2.txt")
);
Map<Path, VfsEntry> testPaths = new HashMap<>();
for(var path : paths) {
var file = new UrlVfsFile(URI.create("https://example.com").toURL());
Vfs.get().put(path, file);
testPaths.put(path, file);
}
for(var path : testPaths.entrySet()) {
Assertions.assertSame(Vfs.get().resolve(path.getKey()), path.getValue());
}
}
@Test
public void testVfsWithOverlay() throws Exception {
List<Path> paths = List.of(
Path.of("test/testfile.txt"),
Path.of("test/dir/testfile2.txt")
);
Path prefix = Path.of("base");
Map<Path, VfsEntry> testPaths = new HashMap<>();
for(var path : paths) {
var file = new UrlVfsFile(URI.create("https://example.com").toURL());
Vfs.get().put(prefix.resolve(path), file);
testPaths.put(path, file);
}
Path overlayPrefix = Path.of("oveerlay");
OverlayVfsDirectory vfsDirectory = new OverlayVfsDirectory(List.of((VfsDirectory) Vfs.get().resolve(prefix)));
Vfs.get().put(overlayPrefix, vfsDirectory);
for(var path : testPaths.entrySet()) {
Assertions.assertSame(Vfs.get().resolve(overlayPrefix.resolve(path.getKey())), path.getValue());
}
}
}