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 20, 2025
1 parent 5dae580 commit 5882fb9
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()

Check warning on line 95 in plugins/package-managers/node/src/main/kotlin/npm/Npm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/npm/Npm.kt#L95

Added line #L95 was not covered by tests

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

Check warning on line 99 in plugins/package-managers/node/src/main/kotlin/npm/Npm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/npm/Npm.kt#L97-L99

Added lines #L97 - L99 were not covered by tests

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

Check warning on line 103 in plugins/package-managers/node/src/main/kotlin/npm/Npm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/npm/Npm.kt#L102-L103

Added lines #L102 - L103 were not covered by tests

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()

Check warning on line 75 in plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt#L75

Added line #L75 was not covered by tests

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

Check warning on line 79 in plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt#L77-L79

Added lines #L77 - L79 were not covered by tests

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

Check warning on line 83 in plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/pnpm/Pnpm.kt#L82-L83

Added lines #L82 - L83 were not covered by tests

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)
}

Check warning on line 141 in plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt#L139-L141

Added lines #L139 - L141 were not covered by tests

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

Check warning on line 145 in plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt#L144-L145

Added lines #L144 - L145 were not covered by tests

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

Check warning on line 149 in plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt

View check run for this annotation

Codecov / codecov/patch

plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt#L148-L149

Added lines #L148 - L149 were not covered by tests
} 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 5882fb9

Please sign in to comment.