This commit is contained in:
crschnick 2025-03-05 18:24:41 +00:00
parent 3c0d06eccc
commit 1d70663dce
29 changed files with 76 additions and 72 deletions

View file

@ -79,7 +79,7 @@ public class BrowserFileSystemHelper {
return path;
}
var resolved = new FilePath(shell.get()
var resolved = FilePath.of(shell.get()
.getShellDialect()
.resolveDirectory(shell.get(), path.toString())
.readStdoutOrThrow());

View file

@ -322,7 +322,7 @@ public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<File
// Evaluate optional links
FilePath resolvedPath;
try {
resolvedPath = BrowserFileSystemHelper.resolveDirectoryPath(this, new FilePath(evaluatedPath), customInput);
resolvedPath = BrowserFileSystemHelper.resolveDirectoryPath(this, FilePath.of(evaluatedPath), customInput);
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();
return Optional.ofNullable(cps);

View file

@ -231,7 +231,7 @@ public class BrowserFileTransferOperation {
}
var noExt = target.getFileName().equals(target.getExtension());
return new FilePath(target.getBaseName() + " (" + 1 + ")" + (noExt ? "" : "." + target.getExtension()));
return FilePath.of(target.getBaseName() + " (" + 1 + ")" + (noExt ? "" : "." + target.getExtension()));
}
private void handleSingleAcrossFileSystems(FileEntry source) throws Exception {
@ -292,7 +292,7 @@ public class BrowserFileTransferOperation {
}
var sourceFile = e.getKey();
var fixedRelPath = new FilePath(e.getValue())
var fixedRelPath = FilePath.of(e.getValue())
.fileSystemCompatible(
target.getFileSystem().getShell().orElseThrow().getOsType());
var targetFile = target.getPath().join(fixedRelPath.toString());

View file

@ -34,7 +34,7 @@ public class BrowserLocalFileSystem {
return new FileEntry(
localFileSystem.open(),
new FilePath(file),
FilePath.of(file),
Files.getLastModifiedTime(file).toInstant(),
Files.size(file),
null,

View file

@ -111,7 +111,7 @@ public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>>
var syncedTarget = handler.addDataFile(
source, target, sync.getPerUser().test(source));
Platform.runLater(() -> {
filePath.setValue(new FilePath(syncedTarget));
filePath.setValue(FilePath.of(syncedTarget));
});
}
} catch (Exception e) {
@ -155,7 +155,7 @@ public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>>
prop.set(s != null ? s.toString() : null);
}));
prop.addListener((observable, oldValue, newValue) -> {
filePath.setValue(newValue != null ? new FilePath(newValue) : null);
filePath.setValue(newValue != null ? FilePath.of(newValue) : null);
});
var combo = new ComboTextFieldComp(prop, items, param -> {
return new ListCell<>() {
@ -187,7 +187,7 @@ public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>>
prop.set(s != null ? s.toString() : null);
}));
prop.addListener((observable, oldValue, newValue) -> {
filePath.setValue(newValue != null ? new FilePath(newValue) : null);
filePath.setValue(newValue != null ? FilePath.of(newValue) : null);
});
var fileNameComp = new TextFieldComp(prop)
.apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS))

View file

@ -133,7 +133,7 @@ public class AppOpenArguments {
var dir = Files.isDirectory(file) ? file : file.getParent();
AppLayoutModel.get().selectBrowser();
BrowserFullSessionModel.DEFAULT.openFileSystemAsync(
DataStorage.get().local().ref(), model -> new FilePath(dir.toString()), null);
DataStorage.get().local().ref(), model -> FilePath.of(dir.toString()), null);
}
}
}

View file

@ -167,7 +167,7 @@ public class ConnectionFileSystem implements FileSystem {
@Override
public List<FilePath> listRoots() throws Exception {
return shellControl.getShellDialect().listRoots(shellControl).map(s -> new FilePath(s)).toList();
return shellControl.getShellDialect().listRoots(shellControl).map(s -> FilePath.of(s)).toList();
}
@Override

View file

@ -81,7 +81,7 @@ public interface SystemIconSource {
if (!Files.exists(dir)) {
sc.command(CommandBuilder.of().add("git", "clone").addQuoted(remote).addFile(dir.toString())).execute();
} else {
sc.command(CommandBuilder.of().add("git", "pull")).withWorkingDirectory(new FilePath(dir)).execute();
sc.command(CommandBuilder.of().add("git", "pull")).withWorkingDirectory(FilePath.of(dir)).execute();
}
}
}

View file

@ -26,10 +26,10 @@ public class ContextualFileReference {
private static FilePath getDataDir() {
if (DataStorage.get() == null) {
return lastDataDir != null ? lastDataDir : new FilePath(AppPrefs.DEFAULT_STORAGE_DIR.resolve("data")).toUnix();
return lastDataDir != null ? lastDataDir : FilePath.of(AppPrefs.DEFAULT_STORAGE_DIR.resolve("data")).toUnix();
}
return lastDataDir = new FilePath(DataStorage.get().getDataDir()).toUnix();
return lastDataDir = FilePath.of(DataStorage.get().getDataDir()).toUnix();
}
public static Optional<FilePath> resolveIfInDataDirectory(ShellControl shellControl, String s) {
@ -47,7 +47,7 @@ public class ContextualFileReference {
}
var ns = p.normalize().toUnix();
var home = new FilePath(System.getProperty("user.home")).normalize().toUnix();
var home = FilePath.of(System.getProperty("user.home")).normalize().toUnix();
String replaced;
var withHomeResolved = ns.toString().replace("~", home.toString());
@ -61,11 +61,11 @@ public class ContextualFileReference {
}
public static ContextualFileReference of(String s) {
return of(s != null ? new FilePath(s) : null);
return of(s != null ? FilePath.of(s) : null);
}
public FilePath toAbsoluteFilePath(ShellControl sc) {
return new FilePath(path.replaceAll("/", Matcher.quoteReplacement(sc != null ? sc.getOsType().getFileSystemSeparator() : "/")));
return FilePath.of(path.replaceAll("/", Matcher.quoteReplacement(sc != null ? sc.getOsType().getFileSystemSeparator() : "/")));
}
public boolean isInDataDirectory() {
@ -74,7 +74,7 @@ public class ContextualFileReference {
public String serialize() {
var start = getDataDir();
var normalizedPath = new FilePath(path).normalize().toUnix();
var normalizedPath = FilePath.of(path).normalize().toUnix();
if (normalizedPath.startsWith(start) && !normalizedPath.equals(start)) {
return "<DATA>" + "/" + start.relativize(normalizedPath);
}

View file

@ -63,7 +63,7 @@ public class TerminalLaunchConfiguration {
var logDir = AppProperties.get().getDataDir().resolve("sessions");
Files.createDirectories(logDir);
var logFile = logDir.resolve(new FilePath(DataStorage.get().getStoreEntryDisplayName(entry) + " ("
var logFile = logDir.resolve(FilePath.of(DataStorage.get().getStoreEntryDisplayName(entry) + " ("
+ DATE_FORMATTER.format(Instant.now()) + ").log")
.fileSystemCompatible(OsType.getLocal())
.toString()

View file

@ -15,7 +15,7 @@ public class CommandSupport {
var out = processControl
.command(processControl.getShellDialect().getWhichCommand(name))
.readStdoutIfPossible();
return out.flatMap(s -> s.lines().findFirst()).map(String::trim).map(FilePath::new);
return out.flatMap(s -> s.lines().findFirst()).map(String::trim).map(FilePath::of);
}
public static boolean isInPath(ShellControl processControl, String executable) throws Exception {

View file

@ -66,13 +66,13 @@ public class DesktopShortcuts {
pc.executeSimpleCommand(pc.getShellDialect().getMkdirsCommand(base + "/Contents/Resources"));
var macExec = base + "/Contents/MacOS/" + name;
pc.view().writeScriptFile(new FilePath(macExec), content);
pc.view().writeScriptFile(FilePath.of(macExec), content);
pc.executeSimpleCommand("chmod ugo+x \"" + macExec + "\"");
pc.view().writeTextFile(new FilePath(base + "/Contents/PkgInfo"), "APPL????");
pc.view().writeTextFile(FilePath.of(base + "/Contents/PkgInfo"), "APPL????");
pc.view()
.writeTextFile(
new FilePath(base + "/Contents/Info.plist"),
FilePath.of(base + "/Contents/Info.plist"),
"""
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

View file

@ -29,7 +29,7 @@ public class FileReference {
}
public static FileReference local(Path p) {
return new FileReference(DataStorage.get().local().ref(), new FilePath(p.toString()));
return new FileReference(DataStorage.get().local().ref(), FilePath.of(p.toString()));
}
public static FileReference local(FilePath p) {

View file

@ -73,7 +73,7 @@ public class ScriptHelper {
content += nl + t.getPassthroughExitCommand();
}
return createExecScript(t, processControl, new FilePath(t.initFileName(processControl)), content);
return createExecScript(t, processControl, FilePath.of(t.initFileName(processControl)), content);
}
@SneakyThrows

View file

@ -102,9 +102,9 @@ public interface OsType {
home,
home.join("Downloads"),
home.join("Documents"),
new FilePath("/etc"),
new FilePath("/tmp"),
new FilePath("/var")));
FilePath.of("/etc"),
FilePath.of("/tmp"),
FilePath.of("/var")));
var parentHome = home.getParent();
if (parentHome != null && !parentHome.toString().equals("/")) {
list.add(3, parentHome);
@ -176,11 +176,11 @@ public interface OsType {
home.join("Downloads"),
home.join("Documents"),
home.join("Desktop"),
new FilePath("/Applications"),
new FilePath("/Library"),
new FilePath("/System"),
new FilePath("/etc"),
new FilePath("/tmp")
FilePath.of("/Applications"),
FilePath.of("/Library"),
FilePath.of("/System"),
FilePath.of("/etc"),
FilePath.of("/tmp")
);
return list;
}

View file

@ -36,7 +36,7 @@ public class ShellView {
}
public FilePath userHome() throws Exception {
return new FilePath(shellControl.getOsType().getUserHomeDirectory(shellControl));
return FilePath.of(shellControl.getOsType().getUserHomeDirectory(shellControl));
}
public boolean fileExists(FilePath path) throws Exception {

View file

@ -33,7 +33,7 @@ public class FileEntry {
@NonNull FileKind kind) {
this.fileSystem = fileSystem;
this.kind = kind;
this.path = kind == FileKind.DIRECTORY ? new FilePath(path.toDirectory().toString()) : path;
this.path = kind == FileKind.DIRECTORY ? FilePath.of(path.toDirectory().toString()) : path;
this.date = date;
this.info = info;
this.size = size;

View file

@ -22,23 +22,27 @@ public final class FilePath {
return s.startsWith("/");
}
public static FilePath of(String path) {
return path != null ? new FilePath(path) : null;
}
public static FilePath of(Path path) {
return path != null ? new FilePath(path.toString()) : null;
}
@NonNull
private final String value;
public FilePath(@NonNull String value) {
private FilePath(@NonNull String value) {
this.value = value;
if (value.isBlank()) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("Path is blank");
}
if (!value.equals(value.trim())) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("Path contains trailing whitespace");
}
}
public FilePath(@NonNull Path value) {
this.value = value.toString();
}
public FilePath fileSystemCompatible(OsType osType) {
var split = split();
var needsReplacement = split.stream().anyMatch(s -> !s.equals(osType.makeFileSystemCompatible(s)));
@ -49,19 +53,19 @@ public final class FilePath {
var p = Pattern.compile("[^/\\\\]+");
var m = p.matcher(value);
var replaced = m.replaceAll(matchResult -> osType.makeFileSystemCompatible(matchResult.group()));
return new FilePath(replaced);
return FilePath.of(replaced);
}
public FilePath getRoot() {
if (value.startsWith("/")) {
return new FilePath("/");
return FilePath.of("/");
} else if (value.length() >= 2 && value.charAt(1) == ':') {
// Without the trailing slash, many programs struggle with this
return new FilePath(value.substring(0, 2) + "\\");
return FilePath.of(value.substring(0, 2) + "\\");
} else if (value.startsWith("\\\\")) {
var split = split();
if (split.size() > 0) {
return new FilePath("\\\\" + split.getFirst());
return FilePath.of("\\\\" + split.getFirst());
}
}
@ -78,25 +82,25 @@ public final class FilePath {
public FilePath toDirectory() {
if (value.endsWith("/") || value.endsWith("\\")) {
return new FilePath(value);
return FilePath.of(value);
}
if (value.contains("\\")) {
return new FilePath(value + "\\");
return FilePath.of(value + "\\");
}
return new FilePath(value + "/");
return FilePath.of(value + "/");
}
public FilePath removeTrailingSlash() {
if (value.equals("/")) {
return new FilePath(value);
return FilePath.of(value);
}
if (value.endsWith("/") || value.endsWith("\\")) {
return new FilePath(value.substring(0, value.length() - 1));
return FilePath.of(value.substring(0, value.length() - 1));
}
return new FilePath(value);
return FilePath.of(value);
}
public String getFileName() {
@ -147,7 +151,7 @@ public final class FilePath {
public FilePath join(String... parts) {
var joined = String.join("/", parts);
return new FilePath(value + "/" + joined).normalize();
return FilePath.of(value + "/" + joined).normalize();
}
public boolean isAbsolute() {
@ -168,14 +172,14 @@ public final class FilePath {
}
if (split().size() == 1) {
return value.startsWith("/") && !value.equals("/") ? new FilePath("/") : null;
return value.startsWith("/") && !value.equals("/") ? FilePath.of("/") : null;
}
return new FilePath(value.substring(0, value.length() - getFileName().length() - 1));
return FilePath.of(value.substring(0, value.length() - getFileName().length() - 1));
}
public boolean startsWith(String start) {
return startsWith(new FilePath(start));
return startsWith(FilePath.of(start));
}
public boolean startsWith(FilePath start) {
@ -183,7 +187,7 @@ public final class FilePath {
}
public FilePath relativize(FilePath base) {
return new FilePath(normalize()
return FilePath.of(normalize()
.toString()
.substring(base.normalize().toDirectory().toString().length()));
}
@ -194,7 +198,7 @@ public final class FilePath {
}
public FilePath resolveTildeHome(String dir) {
return value.startsWith("~") ? new FilePath(value.replace("~", dir)) : this;
return value.startsWith("~") ? FilePath.of(value.replace("~", dir)) : this;
}
private List<String> split() {
@ -206,12 +210,12 @@ public final class FilePath {
var joined = String.join("/", split());
var prefix = value.startsWith("/") ? "/" : "";
var suffix = value.endsWith("/") || value.endsWith("\\") ? "/" : "";
return new FilePath(prefix + joined + suffix);
return FilePath.of(prefix + joined + suffix);
}
public FilePath toWindows() {
var suffix = value.endsWith("/") || value.endsWith("\\") ? "\\" : "";
return new FilePath(String.join("\\", split()) + suffix);
return FilePath.of(String.join("\\", split()) + suffix);
}
public Path asLocalPath() {

View file

@ -124,7 +124,7 @@ public class CoreJacksonModule extends SimpleModule {
@Override
public FilePath deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return new FilePath(p.getValueAsString());
return FilePath.of(p.getValueAsString());
}
}

View file

@ -112,7 +112,7 @@ public class SampleStoreAction implements ActionProvider {
// You can also set a custom working directory.
try (CommandControl cc = sc.command("kill <pid>")
.elevated(ElevationFunction.elevated("kill"))
.withWorkingDirectory(new FilePath("/"))
.withWorkingDirectory(FilePath.of("/"))
.start()) {
// Discard any output but throw an exception with the stderr contents if the exit code is not 0
cc.discardOrThrow();

View file

@ -129,7 +129,7 @@ public class NewItemAction implements BrowserAction, BrowserBranchAction {
.buildComp()
.prefWidth(350));
modal.withDefaultButtons(() -> {
model.createLinkAsync(linkName.getValue(), new FilePath(target.getValue()));
model.createLinkAsync(linkName.getValue(), FilePath.of(target.getValue()));
});
modal.show();
}

View file

@ -48,7 +48,7 @@ public abstract class BaseCompressAction implements BrowserAction, BrowserBranch
var pf = sc.command(sc.getShellDialect().getPrintEnvironmentVariableCommand("ProgramFiles"))
.readStdoutOrThrow();
var loc = new FilePath(pf).join("7-Zip", "7z.exe").toWindows();
var loc = FilePath.of(pf).join("7-Zip", "7z.exe").toWindows();
if (model.getFileSystem().fileExists(loc)) {
model.getCache().getMultiPurposeCache().put("7zExecutable", loc);
}

View file

@ -74,7 +74,7 @@ public class BaseUntarAction implements BrowserApplicationPathAction, BrowserLea
}
private FilePath getTarget(FilePath name) {
return new FilePath(name.toString().replaceAll("\\.tar$", "").replaceAll("\\.tar.gz$", "").replaceAll("\\.tgz$", ""));
return FilePath.of(name.toString().replaceAll("\\.tar$", "").replaceAll("\\.tar.gz$", "").replaceAll("\\.tgz$", ""));
}
@Override

View file

@ -62,7 +62,7 @@ public abstract class BaseUnzipUnixAction extends ExecuteApplicationAction {
}
private FilePath getTarget(FilePath name) {
return new FilePath(name.toString().replaceAll("\\.zip$", ""));
return FilePath.of(name.toString().replaceAll("\\.zip$", ""));
}
@Override

View file

@ -75,7 +75,7 @@ public abstract class BaseUnzipWindowsAction implements BrowserLeafAction {
}
private FilePath getTarget(FilePath name) {
return new FilePath(name.toString().replaceAll("\\.zip$", ""));
return FilePath.of(name.toString().replaceAll("\\.zip$", ""));
}
@Override

View file

@ -114,7 +114,7 @@ public class SshIdentityStateManager {
if (sc.getOsType() == OsType.WINDOWS) {
if (!content.contains("enable-win32-openssh-support")) {
content += "\nenable-win32-openssh-support\n";
sc.view().writeTextFile(new FilePath(confFile), content);
sc.view().writeTextFile(FilePath.of(confFile), content);
// reloadagent does not work correctly, so kill it
handleWindowsGpgAgentStop(sc);
}
@ -122,7 +122,7 @@ public class SshIdentityStateManager {
} else {
if (!content.contains("enable-ssh-support")) {
content += "\nenable-ssh-support\n";
sc.view().writeTextFile(new FilePath(confFile), content);
sc.view().writeTextFile(FilePath.of(confFile), content);
sc.executeSimpleCommand(CommandBuilder.of().add("gpg-connect-agent", "reloadagent", "/bye"));
} else {
sc.executeSimpleCommand(CommandBuilder.of().add("gpg-connect-agent", "/bye"));

View file

@ -136,10 +136,10 @@ public abstract class ScriptStore implements DataStore, StatefulDataStore<Enable
.makeFileSystemCompatible(
scriptStore.get().getName().toLowerCase(Locale.ROOT).replaceAll(" ", "_"));
var scriptFile = FileNames.join(targetDir, fileName + "." + d.getScriptFileEnding());
proc.view().writeScriptFile(new FilePath(scriptFile), content);
proc.view().writeScriptFile(FilePath.of(scriptFile), content);
}
proc.view().writeTextFile(new FilePath(hashFile), String.valueOf(hash));
proc.view().writeTextFile(FilePath.of(hashFile), String.valueOf(hash));
return targetDir;
}

View file

@ -57,7 +57,7 @@ public class IncusContainerEditRunConfigAction implements ActionProvider {
var d = (IncusContainerStore) store.getStore();
var elevatedRef = ProcessControlProvider.get()
.elevated(d.getInstall().getStore().getHost().get().ref());
var file = new FilePath("/run/incus/" + d.getContainerName() + "/lxc.conf");
var file = FilePath.of("/run/incus/" + d.getContainerName() + "/lxc.conf");
var model = BrowserFullSessionModel.DEFAULT.openFileSystemSync(
elevatedRef, m -> file.getParent(), null, true);
var found = model.findFile(file.toString());

View file

@ -57,7 +57,7 @@ public class LxdContainerEditRunConfigAction implements ActionProvider {
var d = (LxdContainerStore) store.getStore();
var elevatedRef = ProcessControlProvider.get()
.elevated(d.getCmd().getStore().getHost().get().ref());
var file = new FilePath("/run/lxd/" + d.getContainerName() + "/lxc.conf");
var file = FilePath.of("/run/lxd/" + d.getContainerName() + "/lxc.conf");
var model = BrowserFullSessionModel.DEFAULT.openFileSystemSync(
elevatedRef, m -> file.getParent(), null, true);
var found = model.findFile(file.toString());