Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,35 @@ import org.ossreviewtoolkit.model.Package
import org.ossreviewtoolkit.model.Project

/**
* A data class storing information about a specific NPM module and its dependencies.
* A data class storing information about a specific Node module and its dependencies.
*
* Instances of this class are used as the dependency node type when constructing a dependency graph for NPM. They
* Instances of this class are used as the dependency node type when constructing a dependency graph for Yarn. They
* contain all the information required to identify a module, construct a [Package] from it, and traverse its
* dependency tree.
*/
data class NpmModuleInfo(
data class ModuleInfo(
/** The identifier for the represented module. */
val id: Identifier,

/** The working directory of the NPM project. */
/** The working directory of the Yarn project. */
val workingDir: File,

/** The file pointing to the package.json for this module. */
val packageFile: File,

/** A set with information about the modules this module depends on. */
val dependencies: Set<NpmModuleInfo>,
val dependencies: Set<ModuleInfo>,

/** A flag indicating whether this module is a [Project] or a [Package]. */
val isProject: Boolean
) {
/**
* [workingDir] and [packageFile] are not relevant when adding this [NpmModuleInfo] to the dependency graph.
* [workingDir] and [packageFile] are not relevant when adding this [ModuleInfo] to the dependency graph.
* However, if these values differ the same dependencies are added as duplicates to the set which is used to create
* the dependency graph. Therefore, remove them from the equals check.
*/
override fun equals(other: Any?): Boolean =
(other === this) || (other is NpmModuleInfo && other.id == id && other.dependencies == dependencies)
(other === this) || (other is ModuleInfo && other.id == id && other.dependencies == dependencies)

override fun hashCode() = 31 * id.hashCode() + dependencies.hashCode()
}
30 changes: 16 additions & 14 deletions plugins/package-managers/node/src/main/kotlin/yarn/Yarn.kt
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@

/**
* An internally used data class with information about a module retrieved from the module's package.json. This
* information is further processed and eventually converted to an [NpmModuleInfo] object containing everything
* required by the Npm package manager.
* information is further processed and eventually converted to an [ModuleInfo] object containing everything
* required by the Yarn package manager.
*/
private data class RawModuleInfo(
val name: String,
Expand All @@ -168,7 +168,7 @@
val workingDir = definitionFile.parentFile
installDependencies(workingDir)

val projectDirs = findWorkspaceSubmodules(workingDir).toSet() + definitionFile.parentFile
val projectDirs = findWorkspaceSubmodules(workingDir) + definitionFile.parentFile

Check warning on line 171 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#L171

Added line #L171 was not covered by tests

return projectDirs.map { projectDir ->
val issues = mutableListOf<Issue>()
Expand All @@ -186,9 +186,9 @@
}

val scopeNames = setOfNotNull(
// Optional dependencies are just like regular dependencies except that NPM ignores failures when
// installing them (see https://docs.npmjs.com/files/package.json#optionaldependencies), i.e. they are
// not a separate scope in ORT semantics.
// Optional dependencies are just like regular dependencies except that Yarn ignores failures when
// installing them (see https://classic.yarnpkg.com/en/docs/package-json#toc-optionaldependencies), i.e.
// they are not a separate scope in ORT semantics.
buildDependencyGraphForScopes(
project,
projectDir,
Expand Down Expand Up @@ -223,10 +223,12 @@
projectDirs: Set<File>,
ancestorModuleDirs: List<File> = emptyList(),
ancestorModuleIds: List<Identifier> = emptyList()
): NpmModuleInfo? {
): ModuleInfo? {
val moduleInfo = parsePackageJson(moduleDir, scopes)
val dependencies = mutableSetOf<NpmModuleInfo>()
val packageType = if (moduleDir.realFile() in projectDirs) projectType else "NPM"
val dependencies = mutableSetOf<ModuleInfo>()

Check warning on line 228 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#L228

Added line #L228 was not covered by tests

val isProject = moduleDir.realFile() in projectDirs

Check warning on line 230 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#L230

Added line #L230 was not covered by tests
val packageType = if (isProject) projectType else "NPM"

val moduleId = splitNamespaceAndName(moduleInfo.name).let { (namespace, name) ->
Identifier(packageType, namespace, name, moduleInfo.version)
Expand All @@ -249,11 +251,11 @@

getModuleInfo(
moduleDir = dependencyModuleDir,
scopes = setOf("dependencies", "optionalDependencies"),
scopes = setOf(DEPENDENCIES_SCOPE, OPTIONAL_DEPENDENCIES_SCOPE),

Check warning on line 254 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#L254

Added line #L254 was not covered by tests
projectDirs,
ancestorModuleDirs = dependencyModuleDirPath.subList(1, dependencyModuleDirPath.size),
ancestorModuleIds = ancestorModuleIds + moduleId
)?.let { dependencies += it }
)?.also { dependencies += it }

return@forEach
}
Expand All @@ -265,12 +267,12 @@
}
}

return NpmModuleInfo(
return ModuleInfo(

Check warning on line 270 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#L270

Added line #L270 was not covered by tests
id = moduleId,
workingDir = moduleDir,
packageFile = moduleInfo.packageJson,
dependencies = dependencies,
isProject = moduleDir.realFile() in projectDirs
isProject = isProject

Check warning on line 275 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#L275

Added line #L275 was not covered by tests
)
}

Expand Down Expand Up @@ -343,7 +345,7 @@
}

internal fun getRemotePackageDetails(packageName: String): PackageJson? {
yarnInfoCache.read(packageName)?.let { return parsePackageJson(it) }
yarnInfoCache.read(packageName)?.also { return parsePackageJson(it) }

val process = YarnCommand.run("info", "--json", packageName).requireSuccess()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,14 @@ import org.ossreviewtoolkit.model.PackageLinkage
import org.ossreviewtoolkit.model.utils.DependencyHandler
import org.ossreviewtoolkit.plugins.packagemanagers.node.parsePackage

internal class YarnDependencyHandler(private val yarn: Yarn) : DependencyHandler<NpmModuleInfo> {
override fun identifierFor(dependency: NpmModuleInfo): Identifier = dependency.id
internal class YarnDependencyHandler(private val yarn: Yarn) : DependencyHandler<ModuleInfo> {
override fun identifierFor(dependency: ModuleInfo): Identifier = dependency.id

override fun dependenciesFor(dependency: NpmModuleInfo): List<NpmModuleInfo> = dependency.dependencies.toList()
override fun dependenciesFor(dependency: ModuleInfo): List<ModuleInfo> = dependency.dependencies.toList()

override fun linkageFor(dependency: NpmModuleInfo): PackageLinkage =
override fun linkageFor(dependency: ModuleInfo): PackageLinkage =
PackageLinkage.DYNAMIC.takeUnless { dependency.isProject } ?: PackageLinkage.PROJECT_DYNAMIC

override fun createPackage(dependency: NpmModuleInfo, issues: MutableCollection<Issue>): Package? =
yarn.takeUnless { dependency.isProject }?.let {
parsePackage(dependency.packageFile, it::getRemotePackageDetails)
}
override fun createPackage(dependency: ModuleInfo, issues: MutableCollection<Issue>): Package? =
if (dependency.isProject) null else parsePackage(dependency.packageFile, yarn::getRemotePackageDetails)
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ private fun createIdentifier(name: String): Identifier =
Identifier(type = "NPM", namespace = "test", name = name, version = "1.2.3")

/**
* Convenience function to create an [NpmModuleInfo] instance with default values based on the provided [id],
* Convenience function to create an [ModuleInfo] instance with default values based on the provided [id],
* [packageFile], and [dependencies].
*/
private fun createModuleInfo(
id: Identifier,
packageFile: File = File("project/package.json"),
dependencies: Set<NpmModuleInfo> = emptySet(),
dependencies: Set<ModuleInfo> = emptySet(),
isProject: Boolean = false
): NpmModuleInfo = NpmModuleInfo(id, packageFile.parentFile, packageFile, dependencies, isProject)
): ModuleInfo = ModuleInfo(id, packageFile.parentFile, packageFile, dependencies, isProject)

/**
* Creates an [YarnDependencyHandler] instance to be used by test cases.
Expand Down
Loading