Skip to content

Commit

Permalink
feat(node): Keep created node_modules directories until after resol…
Browse files Browse the repository at this point in the history
…ution

This fixes the case where a Gradle analysis (that is configured to run
after e.g. a Yarn analysis) needs to access Gradle projects inside the
`node_modules` directory created by a React-Native build.

Signed-off-by: Sebastian Schuberth <[email protected]>
  • Loading branch information
sschuberth committed Jan 24, 2025
1 parent b040129 commit 78ac845
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 26 deletions.
22 changes: 14 additions & 8 deletions plugins/package-managers/node/src/main/kotlin/npm/Npm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ import org.ossreviewtoolkit.plugins.packagemanagers.node.NodePackageManagerType
import org.ossreviewtoolkit.plugins.packagemanagers.node.PackageJson
import org.ossreviewtoolkit.plugins.packagemanagers.node.parsePackageJson
import org.ossreviewtoolkit.utils.common.CommandLineTool
import org.ossreviewtoolkit.utils.common.DirectoryStash
import org.ossreviewtoolkit.utils.common.Os
import org.ossreviewtoolkit.utils.common.ProcessCapture
import org.ossreviewtoolkit.utils.common.collectMessages
import org.ossreviewtoolkit.utils.common.stashDirectories
import org.ossreviewtoolkit.utils.common.withoutPrefix

import org.semver4j.RangesList
Expand Down Expand Up @@ -83,18 +83,26 @@ class Npm(
) = Npm(type, analysisRoot, analyzerConfig, repoConfig)
}

private lateinit var stash: DirectoryStash

private val legacyPeerDeps = options[OPTION_LEGACY_PEER_DEPS].toBoolean()
private val npmViewCache = mutableMapOf<String, PackageJson>()
private val handler = NpmDependencyHandler(projectType, this::getRemotePackageDetails)

override val graphBuilder by lazy { DependencyGraphBuilder(handler) }

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
stashDirectories(definitionFile.resolveSibling("node_modules")).use {
resolveDependencies(definitionFile)
}
override fun beforeResolution(definitionFiles: List<File>) {
NpmCommand.checkVersion()

val directories = definitionFiles.mapTo(mutableSetOf()) { it.resolveSibling("node_modules") }
stash = DirectoryStash(directories)
}

private fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun afterResolution(definitionFiles: List<File>) {
stash.close()
}

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile
val issues = installDependencies(workingDir).toMutableList()

Expand Down Expand Up @@ -129,8 +137,6 @@ class Npm(
).let { listOf(it) }
}

override fun beforeResolution(definitionFiles: List<File>) = NpmCommand.checkVersion()

private fun listModules(workingDir: File, issues: MutableList<Issue>): ModuleInfo {
val listProcess = NpmCommand.run(workingDir, "list", "--depth", "Infinity", "--json", "--long")
issues += listProcess.extractNpmIssues()
Expand Down
22 changes: 14 additions & 8 deletions plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import org.ossreviewtoolkit.plugins.packagemanagers.node.NodePackageManagerType
import org.ossreviewtoolkit.plugins.packagemanagers.node.PackageJson
import org.ossreviewtoolkit.plugins.packagemanagers.node.parsePackageJson
import org.ossreviewtoolkit.utils.common.CommandLineTool
import org.ossreviewtoolkit.utils.common.DirectoryStash
import org.ossreviewtoolkit.utils.common.Os
import org.ossreviewtoolkit.utils.common.stashDirectories

import org.semver4j.RangesList
import org.semver4j.RangesListFactory
Expand Down Expand Up @@ -64,17 +64,25 @@ class Pnpm(
) = Pnpm(type, analysisRoot, analyzerConfig, repoConfig)
}

private lateinit var stash: DirectoryStash

private val packageDetailsCache = mutableMapOf<String, PackageJson>()
private val handler = PnpmDependencyHandler(projectType, this::getRemotePackageDetails)

override val graphBuilder by lazy { DependencyGraphBuilder(handler) }

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
stashDirectories(definitionFile.resolveSibling("node_modules")).use {
resolveDependencies(definitionFile)
}
override fun beforeResolution(definitionFiles: List<File>) {
PnpmCommand.checkVersion()

val directories = definitionFiles.mapTo(mutableSetOf()) { it.resolveSibling("node_modules") }
stash = DirectoryStash(directories)
}

private fun resolveDependencies(definitionFile: File): List<ProjectAnalyzerResult> {
override fun afterResolution(definitionFiles: List<File>) {
stash.close()
}

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile
installDependencies(workingDir)

Expand Down Expand Up @@ -133,8 +141,6 @@ class Pnpm(
workingDir = workingDir
).requireSuccess()

override fun beforeResolution(definitionFiles: List<File>) = PnpmCommand.checkVersion()

internal fun getRemotePackageDetails(packageName: String): PackageJson? {
packageDetailsCache[packageName]?.let { return it }

Expand Down
24 changes: 15 additions & 9 deletions plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import org.ossreviewtoolkit.plugins.packagemanagers.node.PackageJson
import org.ossreviewtoolkit.plugins.packagemanagers.node.parsePackageJson
import org.ossreviewtoolkit.plugins.packagemanagers.node.splitNamespaceAndName
import org.ossreviewtoolkit.utils.common.CommandLineTool
import org.ossreviewtoolkit.utils.common.DirectoryStash
import org.ossreviewtoolkit.utils.common.DiskCache
import org.ossreviewtoolkit.utils.common.Os
import org.ossreviewtoolkit.utils.common.alsoIfNull
Expand All @@ -59,7 +60,6 @@ import org.ossreviewtoolkit.utils.common.fieldNamesOrEmpty
import org.ossreviewtoolkit.utils.common.isSymbolicLink
import org.ossreviewtoolkit.utils.common.mebibytes
import org.ossreviewtoolkit.utils.common.realFile
import org.ossreviewtoolkit.utils.common.stashDirectories
import org.ossreviewtoolkit.utils.common.textValueOrEmpty
import org.ossreviewtoolkit.utils.ort.ortDataDirectory

Expand Down Expand Up @@ -106,6 +106,8 @@ open class Yarn(
) = Yarn(type, analysisRoot, analyzerConfig, repoConfig)
}

private lateinit var stash: DirectoryStash

/** Cache for submodules identified by its moduleDir absolutePath */
private val submodulesCache = ConcurrentHashMap<String, Set<File>>()

Expand All @@ -131,19 +133,23 @@ open class Yarn(
}
}

override fun beforeResolution(definitionFiles: List<File>) = YarnCommand.checkVersion()
override fun beforeResolution(definitionFiles: List<File>) {
YarnCommand.checkVersion()

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> {
val workingDir = definitionFile.parentFile
val directories = definitionFiles.mapTo(mutableSetOf()) { it.resolveSibling("node_modules") }
stash = DirectoryStash(directories)
}

return try {
stashDirectories(workingDir.resolve("node_modules")).use {
resolveDependenciesInternal(definitionFile)
}
override fun afterResolution(definitionFiles: List<File>) {
stash.close()
}

override fun resolveDependencies(definitionFile: File, labels: Map<String, String>): List<ProjectAnalyzerResult> =
try {
resolveDependenciesInternal(definitionFile)
} finally {
rawModuleInfoCache.clear()
}
}

/**
* An internally used data class with information about a module retrieved from the module's package.json. This
Expand Down
2 changes: 1 addition & 1 deletion utils/common/src/main/kotlin/DirectoryStash.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun stashDirectories(vararg directories: File): Closeable = DirectoryStash(setOf
* created at the location of an original directory is deleted before the original state is restored. If a specified
* directory did not exist on initialization, it will also not exist on close.
*/
private class DirectoryStash(directories: Set<File>) : Closeable {
class DirectoryStash(directories: Set<File>) : Closeable {
private val stashedDirectories: Map<File, File?> = directories.associateWith { originalDir ->
// Check this on each iteration instead of filtering beforehand to properly handle parent / child directories.
if (originalDir.isDirectory) {
Expand Down

0 comments on commit 78ac845

Please sign in to comment.