Skip to content

Implement resource mapping support (#2592)#2834

Open
krrish175-byte wants to merge 2 commits intoscalacenter:mainfrom
krrish175-byte:feature/resource-mapping
Open

Implement resource mapping support (#2592)#2834
krrish175-byte wants to merge 2 commits intoscalacenter:mainfrom
krrish175-byte:feature/resource-mapping

Conversation

@krrish175-byte
Copy link

Description

This PR implements support for file mapping of resources in Bloop, allowing resources to be copied to custom locations in the classes directory (jar-relative paths). This feature enables Bloop to support build configurations similar to SBT's mappings setting, where resources need to be placed at specific paths in the output jar/directory.

Changes

  • Project Model: Added resourceMappings field to the Project data structure.
  • ResourceMapper: Implemented ResourceMapper utility to handle efficient copying of files and directories with validation for duplicate targets and path traversal.
  • Compile Integration: Integrated resource copying into CompileTask. Mapped resources are copied:
    • During CopyResourcesOnly tasks (when no sources change).
    • As a background task after successful compilation.

Testing:

  • Added ResourceMapperSpec for comprehensive unit testing of the utility.
  • Added ResourceMappingIntegrationSpec for end-to-end verification of the feature during compilation.

Verification:

  • Unit Tests: Verified recursive directory copying, empty mapping handling, and validation logic.

  • Integration Tests: Verified that:

    • Single files are copied to the correct target path.
    • Entire directories are recursively copied.
    • Resources are updated even during no-op compilations.
  • Manual Verification: Confirmed that resources appear in the client-visible classes directory (bloop-bsp-clients-classes).

Dependencies / Notes:

  • This implementation relies on a schema update in bloop-config (to version 2.3.4 or higher) to parse the resourceMapping field from the JSON configuration.

  • The parsing logic in Project.scala is currently commented out and marked with a TODO, pending the release and upgrade of bloop-config. The internal infrastructure is fully functional and tested via manual injection in tests.

Closing Issue:

Closes #2592

@tgodzik

Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure we should start with updating bloop-config

* @param logger Logger for warnings
* @return List of validation errors
*/
def validateMappings(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this adds a lot, we should just show clearly if any copy attempt failed

Comment on lines +137 to +147
private def hasDirectoryChanged(dir: AbsolutePath, lastModified: Long): Boolean = {
if (!dir.exists) return false

val stream = Files.walk(dir.underlying)
try {
stream.anyMatch(path => Files.getLastModifiedTime(path).toMillis > lastModified)
} finally {
stream.close()
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private def hasDirectoryChanged(dir: AbsolutePath, lastModified: Long): Boolean = {
if (!dir.exists) return false
val stream = Files.walk(dir.underlying)
try {
stream.anyMatch(path => Files.getLastModifiedTime(path).toMillis > lastModified)
} finally {
stream.close()
}
}
}
private def hasDirectoryChanged(dir: AbsolutePath, lastModified: Long): Boolean = {
if (dir.exists) {
val stream = Files.walk(dir.underlying)
try {
stream.anyMatch(path => Files.getLastModifiedTime(path).toMillis > lastModified)
} finally {
stream.close()
}
}
} else {
false
}

val projectDirectory = AbsolutePath(project.directory)

// Parse resource mappings if available (requires bloop-config 2.3.4+)
// TODO: Uncomment parsing logic once bloop-config is updated with resourceMapping field
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to fist change bloop-config, otherwise this will mostly be dead code. We should also make sure that Bloop's sbt plugin properly fills the newly added field

postCompilationTasks.runAsync(ExecutionContext.ioScheduler)

// Copy mapped resources after compilation
val copyMappedResourcesTask =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably put it alongside the normal copyResources in updateExternalClassesDirWithReadOnly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add support for file mapping of resources

2 participants