Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(PathManager): working directory should always be a fallback #4895

Merged
merged 1 commit into from
Sep 7, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions engine/src/main/java/org/terasology/engine/core/PathManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

package org.terasology.engine.core;

import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.sun.jna.platform.win32.KnownFolders;
import com.sun.jna.platform.win32.Shell32Util;
Expand All @@ -20,6 +19,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -67,22 +67,43 @@ private PathManager() {
}

private static Path findInstallPath() {
Path codeLocation; // By default, the path should be the code location (where terasology.jar is)
List<Path> installationSearchPaths = new ArrayList<>(2);

try {
// In a normal workspace or distribution, the jar with this code is somewhere near the natives directory.
URI urlToSource = PathManager.class.getProtectionDomain().getCodeSource().getLocation().toURI();
codeLocation = Paths.get(urlToSource);
Path codeLocation = Paths.get(urlToSource);
installationSearchPaths.add(codeLocation);
// Not using logger because it's usually initialized after PathManager.
System.out.println("PathManager: Initial code location is " + codeLocation.toAbsolutePath());
} catch (URISyntaxException e) {
System.err.println("PathManager: Failed to convert code location to path.");
e.printStackTrace();
codeLocation = Paths.get("").toAbsolutePath();
System.out.println("PathManager: Using working dir " + codeLocation);
}

return Verify.verifyNotNull(findNativesHome(codeLocation.getParent(), 5),
"Unable to find the natives directory from %s, unable to launch!",
codeLocation);
// But that's not always true. This jar may be loaded from somewhere else on the classpath.
// For example: CI runs module unit tests in a smaller workspace, and gradle gets engine.jar
// the same as all its other dependencies, disconnected from the natives directory.
//
// Use the current directory as a fallback.
Path currentDirectory = Paths.get("").toAbsolutePath();
installationSearchPaths.add(currentDirectory);
System.out.println("PathManager: Working directory is " + currentDirectory);

for (Path startPath : installationSearchPaths) {
Path installationPath = findNativesHome(startPath, 5);
if (installationPath != null) {
return installationPath;
}
}

System.err.println(
"Native library installation directory not found. %n" +
"Things will almost certainly crash as a result, %n" +
"unless something else installed everything to java.library.path. %n" +
"Searched: %n" + installationSearchPaths
);
return currentDirectory;
}

/**
Expand All @@ -103,13 +124,10 @@ private static Path findNativesHome(Path startPath, int maxDepth) {

checkedPath = checkedPath.getParent();
if (checkedPath.equals(startPath.getRoot())) {
System.err.println("Uh oh, reached the root path, giving up");
return null;
break; // Uh oh, reached the root path, giving up.
}
levelsToSearch--;
}

System.err.println("Failed to find the natives dir within " + maxDepth + " levels of " + startPath);
return null;
}

Expand Down