Skip to content

Commit

Permalink
Merge remote-tracking branch 'FabricMC/dev/1.6' into dev/1.6
Browse files Browse the repository at this point in the history
  • Loading branch information
shedaniel committed Apr 28, 2024
2 parents 6508030 + bd00951 commit ff3546e
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 44 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mapping-io = "0.5.1"
lorenz-tiny = "4.0.2"
mercury = "0.1.4.17"
kotlinx-metadata = "0.9.0"
loom-native = "0.1.1"
loom-native = "0.2.0"

# Plugins
spotless = "6.25.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,16 @@ public void run() {

try {
setupMinecraft(configContext);

LoomDependencyManager dependencyManager = new LoomDependencyManager();
extension.setDependencyManager(dependencyManager);
dependencyManager.handleDependencies(getProject(), serviceManager);
} catch (Exception e) {
ExceptionUtil.printFileLocks(e, getProject());
disownLock();
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to setup Minecraft", e);
}

LoomDependencyManager dependencyManager = new LoomDependencyManager();
extension.setDependencyManager(dependencyManager);
dependencyManager.handleDependencies(getProject(), serviceManager);

releaseLock();
extension.setRefreshDeps(previousRefreshDeps);

Expand Down Expand Up @@ -364,12 +365,14 @@ enum LockResult {
// already owned by current pid
ACQUIRED_ALREADY_OWNED,
// acquired due to current owner not existing
ACQUIRED_PREVIOUS_OWNER_MISSING
ACQUIRED_PREVIOUS_OWNER_MISSING,
// acquired due to previous owner disowning the lock
ACQUIRED_PREVIOUS_OWNER_DISOWNED
}

private LockResult acquireProcessLockWaiting(LockFile lockFile) {
// one hour
return this.acquireProcessLockWaiting(lockFile, Duration.ofHours(1));
return this.acquireProcessLockWaiting(lockFile, getDefaultTimeout());
}

private LockResult acquireProcessLockWaiting(LockFile lockFile, Duration timeout) {
Expand All @@ -387,25 +390,34 @@ private LockResult acquireProcessLockWaiting_(LockFile lockFile, Duration timeou
final Logger logger = Logging.getLogger("loom_acquireProcessLockWaiting");
final long currentPid = ProcessHandle.current().pid();
boolean abrupt = false;
boolean disowned = false;

if (Files.exists(lockFile.file)) {
long lockingProcessId;
long lockingProcessId = -1;

try {
lockingProcessId = Long.parseLong(Files.readString(lockFile.file));
} catch (final Exception e) {
lockingProcessId = -1;
String lockValue = Files.readString(lockFile.file);

if ("disowned".equals(lockValue)) {
disowned = true;
} else {
lockingProcessId = Long.parseLong(lockValue);
logger.lifecycle("\"{}\" is currently held by pid '{}'.", lockFile, lockingProcessId);
}
} catch (final Exception ignored) {
// ignored
}

if (lockingProcessId == currentPid) {
return LockResult.ACQUIRED_ALREADY_OWNED;
}

logger.lifecycle("\"{}\" is currently held by pid '{}'.", lockFile, lockingProcessId);

Optional<ProcessHandle> handle = ProcessHandle.of(lockingProcessId);

if (handle.isEmpty()) {
if (disowned) {
logger.lifecycle("Previous process has disowned the lock due to abrupt termination.");
Files.deleteIfExists(lockFile.file);
} else if (handle.isEmpty()) {
logger.lifecycle("Locking process does not exist, assuming abrupt termination and deleting lock file.");
Files.deleteIfExists(lockFile.file);
abrupt = true;
Expand Down Expand Up @@ -446,7 +458,35 @@ private LockResult acquireProcessLockWaiting_(LockFile lockFile, Duration timeou
}

Files.writeString(lockFile.file, String.valueOf(currentPid));
return abrupt ? LockResult.ACQUIRED_PREVIOUS_OWNER_MISSING : LockResult.ACQUIRED_CLEAN;

if (disowned) {
return LockResult.ACQUIRED_PREVIOUS_OWNER_DISOWNED;
} else if (abrupt) {
return LockResult.ACQUIRED_PREVIOUS_OWNER_MISSING;
}

return LockResult.ACQUIRED_CLEAN;
}

private static Duration getDefaultTimeout() {
if (System.getenv("CI") != null) {
// Set a small timeout on CI, as it's unlikely going to unlock.
return Duration.ofMinutes(1);
}

return Duration.ofHours(1);
}

// When we fail to configure, write "disowned" to the lock file to release it from this process
// This allows the next run to rebuild without waiting for this process to exit
private void disownLock() {
final Path lock = getLockFile().file;

try {
Files.writeString(lock, "disowned");
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private void releaseLock() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public record ClassLineNumbers(Map<String, ClassLineNumbers.Entry> lineMap) {
if (lineMap.isEmpty()) {
throw new IllegalArgumentException("lineMap is empty");
}

for (Map.Entry<String, Entry> entry : lineMap.entrySet()) {
Objects.requireNonNull(entry.getKey(), "lineMap key");
Objects.requireNonNull(entry.getValue(), "lineMap value");
}
}

public static ClassLineNumbers readMappings(Path lineMappingsPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,11 @@ public void processEntryAsync(Path file, Path dst) throws IOException {
}
}

String fileName = file.getFileName().toString();
String fileName = file.toAbsolutePath().toString();

if (fileName.endsWith(".class")) {
String idx = fileName.substring(0, fileName.length() - 6);

LOGGER.debug("Remapping line numbers for class: " + idx);
// Strip the leading slash and the .class extension
String idx = fileName.substring(1, fileName.length() - 6);

int dollarPos = idx.indexOf('$'); //This makes the assumption that only Java classes are to be remapped.

Expand All @@ -74,6 +73,8 @@ public void processEntryAsync(Path file, Path dst) throws IOException {
}

if (lineNumbers.lineMap().containsKey(idx)) {
LOGGER.debug("Remapping line numbers for class: {}", idx);

try (InputStream is = Files.newInputStream(file)) {
ClassReader reader = new ClassReader(is);
ClassWriter writer = new ClassWriter(0);
Expand All @@ -82,6 +83,8 @@ public void processEntryAsync(Path file, Path dst) throws IOException {
Files.write(dst, writer.toByteArray());
return;
}
} else {
LOGGER.debug("No linemap found for: {}", idx);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ public WorkRequest prepareJob(Path inputJar) throws IOException {
final Path outputPath = existingFs.getPath(outputFileName);
Files.createDirectories(outputPath.getParent());
Files.writeString(outputPath, entryData.sources());
lineNumbersMap.put(entryData.className(), entryData.lineNumbers());

if (entryData.lineNumbers() != null) {
lineNumbersMap.put(entryData.className(), entryData.lineNumbers());
} else {
LOGGER.info("Cached entry ({}) does not have line numbers", outputFileName);
}

hasSomeExisting = true;

LOGGER.debug("Cached entry ({}) found: {}", fullHash, outputFileName);
Expand Down Expand Up @@ -166,6 +172,10 @@ public void completeJob(Path output, WorkJob workJob, ClassLineNumbers lineNumbe
lineMapEntry = lineNumbers.lineMap().get(className);
}

if (lineMapEntry == null) {
LOGGER.info("No line numbers generated for class: {}", className);
}

final var cachedData = new CachedData(className, sources, lineMapEntry);
fileStore.putEntry(hash, cachedData);

Expand Down
16 changes: 15 additions & 1 deletion src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package net.fabricmc.loom.task;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -204,6 +205,9 @@ public void run() throws IOException {
if (!getUseCache().get()) {
try (var timer = new Timer("Decompiled sources")) {
runWithoutCache();
} catch (Exception e) {
ExceptionUtil.printFileLocks(e, getProject());
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to decompile", e);
}

return;
Expand All @@ -221,6 +225,9 @@ public void run() throws IOException {
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(cacheFile, true)) {
runWithCache(fs.getRoot());
}
} catch (Exception e) {
ExceptionUtil.printFileLocks(e, getProject());
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to decompile", e);
}
}

Expand Down Expand Up @@ -492,7 +499,6 @@ private MinecraftJar rebuildInputJar() {
final var provideContext = new AbstractMappedMinecraftProvider.ProvideContext(false, true, configContext);
minecraftJars = getExtension().getNamedMinecraftProvider().provide(provideContext);
} catch (Exception e) {
ExceptionUtil.printFileLocks(e, getProject());
throw ExceptionUtil.createDescriptiveWrapper(RuntimeException::new, "Failed to rebuild input jars", e);
}

Expand Down Expand Up @@ -567,6 +573,14 @@ private void remapLineNumbers(ClassLineNumbers lineNumbers, Path inputJar, Path
Objects.requireNonNull(lineNumbers, "lineNumbers");
final var remapper = new LineNumberRemapper(lineNumbers);
remapper.process(inputJar, outputJar);

final Path lineMap = inputJar.resolveSibling(inputJar.getFileName() + ".linemap.txt");

try (BufferedWriter writer = Files.newBufferedWriter(lineMap)) {
lineNumbers.write(writer);
}

LOGGER.info("Wrote linemap to {}", lineMap);
}

private void doWork(@Nullable IPCServer ipcServer, Path inputJar, Path outputJar, Path linemapFile, @Nullable Path existingJar) {
Expand Down
45 changes: 25 additions & 20 deletions src/main/java/net/fabricmc/loom/task/RemapTaskConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,45 +143,50 @@ public void run() {

private void trySetupSourceRemapping() {
final LoomGradleExtension extension = LoomGradleExtension.get(getProject());
final String sourcesJarTaskName = SourceSetHelper.getMainSourceSet(getProject()).getSourcesJarTaskName();

TaskProvider<RemapSourcesJarTask> remapSourcesTask = getTasks().register(REMAP_SOURCES_JAR_TASK_NAME, RemapSourcesJarTask.class, task -> {
task.setDescription("Remaps the default sources jar to intermediary mappings.");
task.setGroup(Constants.TaskGroup.FABRIC);
task.getIncludesClientOnlyClasses().set(getProject().provider(extension::areEnvironmentSourceSetsSplit));
});

getTasks().named(BasePlugin.ASSEMBLE_TASK_NAME).configure(task -> task.dependsOn(remapSourcesTask));

GradleUtils.afterSuccessfulEvaluation(getProject(), () -> {
final String sourcesJarTaskName = SourceSetHelper.getMainSourceSet(getProject()).getSourcesJarTaskName();
final Task sourcesTask = getTasks().findByName(sourcesJarTaskName);

boolean canRemap = true;

if (sourcesTask == null) {
getProject().getLogger().info("{} task was not found, not remapping sources", sourcesJarTaskName);
task.setEnabled(false);
return;
canRemap = false;
}

if (!(sourcesTask instanceof Jar sourcesJarTask)) {
if (canRemap && !(sourcesTask instanceof Jar)) {
getProject().getLogger().info("{} task is not a Jar task, not remapping sources", sourcesJarTaskName);
task.setEnabled(false);
return;
canRemap = false;
}

sourcesJarTask.getArchiveClassifier().convention("dev-sources");
sourcesJarTask.getDestinationDirectory().set(getProject().getLayout().getBuildDirectory().map(directory -> directory.dir("devlibs")));
task.getArchiveClassifier().convention("sources");
boolean finalCanRemap = canRemap;

task.dependsOn(sourcesJarTask);
task.getInputFile().convention(sourcesJarTask.getArchiveFile());
task.getIncludesClientOnlyClasses().set(getProject().provider(extension::areEnvironmentSourceSetsSplit));
});
remapSourcesTask.configure(task -> {
if (!finalCanRemap) {
task.setEnabled(false);
return;
}

getTasks().named(BasePlugin.ASSEMBLE_TASK_NAME).configure(task -> task.dependsOn(remapSourcesTask));
final Jar sourcesJarTask = (Jar) sourcesTask;

if (GradleUtils.getBooleanProperty(getProject(), "fabric.loom.disableRemappedVariants")) {
return;
}
sourcesJarTask.getArchiveClassifier().convention("dev-sources");
sourcesJarTask.getDestinationDirectory().set(getProject().getLayout().getBuildDirectory().map(directory -> directory.dir("devlibs")));
task.getArchiveClassifier().convention("sources");

GradleUtils.afterSuccessfulEvaluation(getProject(), () -> {
final Task sourcesTask = getTasks().findByName(sourcesJarTaskName);
task.dependsOn(sourcesJarTask);
task.getInputFile().convention(sourcesJarTask.getArchiveFile());
});

if (!(sourcesTask instanceof Jar sourcesJarTask)) {
if (GradleUtils.getBooleanProperty(getProject(), "fabric.loom.disableRemappedVariants")) {
return;
}

Expand Down
14 changes: 13 additions & 1 deletion src/main/java/net/fabricmc/loom/util/ExceptionUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@
import java.util.function.BiFunction;

import org.gradle.api.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.fabricmc.loom.nativeplatform.LoomNativePlatform;
import net.fabricmc.loom.nativeplatform.LoomNativePlatformException;

public final class ExceptionUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionUtil.class);

/**
* Creates a descriptive user-facing wrapper exception for an underlying cause.
*
Expand Down Expand Up @@ -74,7 +79,14 @@ private static void printFileLocks(String filename, Project project) {
return;
}

final List<ProcessHandle> processes = LoomNativePlatform.getProcessesWithLockOn(path);
final List<ProcessHandle> processes;

try {
processes = LoomNativePlatform.getProcessesWithLockOn(path);
} catch (LoomNativePlatformException e) {
LOGGER.error("{}, Failed to query processes holding a lock on {}", e.getMessage(), path);
return;
}

if (processes.isEmpty()) {
return;
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/net/fabricmc/loom/util/ProcessUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@

import org.gradle.api.Project;
import org.gradle.api.logging.LogLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.fabricmc.loom.nativeplatform.LoomNativePlatform;
import net.fabricmc.loom.nativeplatform.LoomNativePlatformException;

public record ProcessUtil(LogLevel logLevel) {
private static final String EXPLORER_COMMAND = "C:\\Windows\\explorer.exe";
private static final Logger LOGGER = LoggerFactory.getLogger(ProcessUtil.class);

public static ProcessUtil create(Project project) {
return new ProcessUtil(project.getGradle().getStartParameter().getLogLevel());
Expand Down Expand Up @@ -92,7 +96,14 @@ private Optional<String> getWindowTitles(ProcessHandle processHandle) {
return Optional.empty();
}

List<String> titles = LoomNativePlatform.getWindowTitlesForPid(processHandle.pid());
List<String> titles;

try {
titles = LoomNativePlatform.getWindowTitlesForPid(processHandle.pid());
} catch (LoomNativePlatformException e) {
LOGGER.error("{}, Failed to query window title for pid {}", e.getMessage(), processHandle.pid());
return Optional.empty();
}

if (titles.isEmpty()) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class DebugLineNumbersTest extends Specification implements GradleProjectTestTra
def result = it.get()
println("Breakpoint triggered: ${result.location()}")
}

println("All breakpoints triggered")
} finally {
// Close the debugger and target process
debugger.close()
Expand Down
Loading

0 comments on commit ff3546e

Please sign in to comment.