Skip to content

Use fs2-io library for file and process handling#23

Merged
rochala merged 6 commits intoVirtusLab:mainfrom
yhefamly:use-fs2-io
Apr 8, 2026
Merged

Use fs2-io library for file and process handling#23
rochala merged 6 commits intoVirtusLab:mainfrom
yhefamly:use-fs2-io

Conversation

@yhefamly
Copy link
Copy Markdown
Contributor

@yhefamly yhefamly commented Apr 3, 2026

To ensure exactly the right operations are executed on blocking threads (which doesn't seem to be the case yet, see #21) and to reduce the maintenance burden, swap in fs2-io for 90% of the I/O-related code. The remaining 10% are deeply involved with virtual file systems and ZIP files, hence I left them as-is for now.

Also use fs2 for spawning external processes and hashing to profit from its safe and easy-to-use APIs.

Tested locally, everything passed just fine. In my brief test, also the hashes were consistent with the previous implementation (which is generally expected as fs2 delegates to MessageDigest).

This PR is a proposal, I'm totally fine if it ends up getting discarded. I just fell into the rabbit hole of "let me quickly try to optimise ProcessRunner" 🫣.

To ensure exactly the right operations are executed on blocking threads and to reduce the maintenance burden, swap in fs2-io for 90% of the I/O-related code. Also use fs2 for spawning external processes and hashing.
Copy link
Copy Markdown
Contributor

@rochala rochala left a comment

Choose a reason for hiding this comment

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

Great PR, thanks for doing this. 2 small comments left.

process.stderr.through(fs2.text.utf8.decode).compile.string
).parMapN(ProcessResult.apply)
}.adaptError { case e: java.io.IOException =>
val cmd = command.headOption.getOrElse("")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Claude review:

Bug in ProcessRunner.adaptError (ProcessRunner.scala)

  def run(command: String, args: List[String], ...) = {
    ...
    }.adaptError { case e: java.io.IOException =>
      val cmd = command.headOption.getOrElse("")  // BUG

command is now a String, not List[String]. String.headOption returns Option[Char], so cmd will be a single Char
(the first character of the binary name). The error message would print Failed to start 'n': ... instead of
Failed to start 'nonexistent-command-xyz': .... Should just be command directly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 4900c39.

IO.blocking {
val millMarker = millMarkers.find(m => Files.exists(dir.resolve(m)))
val hasSbt = Files.exists(dir.resolve("build.sbt"))
val hasScalaBuild = Files.isDirectory(dir.resolve(".scala-build"))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets restore .scala-build detection. It is duplicated for now with the fallback but in the future if we want to add support for any other build tool, the fallback may no longer apply

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-added and refactored the code using findM for better readability.

@yhefamly yhefamly requested a review from rochala April 6, 2026 15:45
yhefamly added 3 commits April 8, 2026 09:36
# Conflicts:
#	lib/src/cellar/build/MillBuildTool.scala
#	lib/src/cellar/build/ProjectClasspathProvider.scala
#	lib/src/cellar/build/SbtBuildTool.scala
#	lib/src/cellar/handlers/ProjectHandler.scala
#	lib/test/src/cellar/ProjectAwareIntegrationTest.scala
Copy link
Copy Markdown
Contributor

@rochala rochala left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the contribution :D

@rochala rochala merged commit 2f95d8a into VirtusLab:main Apr 8, 2026
2 checks passed
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.

2 participants