Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(analyzer): Support uppercase-letters in Go module version #7888

Merged
merged 1 commit into from
Nov 20, 2023
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
19 changes: 18 additions & 1 deletion plugins/package-managers/go/src/main/kotlin/GoMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,8 @@ private fun ModuleInfo.toSourceArtifact(): RemoteArtifact {
}

private fun ModuleInfo.toVcsInfo(): VcsInfo? {
val infoFile = goMod?.let { File(it).resolveSibling("$version.info") } ?: return null
val escapedVersion = escapeVersion(version)
fviernau marked this conversation as resolved.
Show resolved Hide resolved
val infoFile = goMod?.let { File(it).resolveSibling("$escapedVersion.info") } ?: return null
val info = infoFile.inputStream().use { JSON.decodeFromStream<ModuleInfoFile>(it) }
val type = info.origin.vcs?.let { VcsType.forName(it) }.takeIf { it == VcsType.GIT } ?: return null

Expand Down Expand Up @@ -484,3 +485,19 @@ internal fun parseWhyOutput(output: String): Set<String> {

return usedModules
}

/**
* Module paths appear as substrings of file system paths in the module cache on the file system.
* Go does not rely on the file system to be case-sensitive. For this reason, Go has decided to
* replace every uppercase letter in file system paths with an exclamation mark followed by the
* letter's lowercase equivalent.
*
* Details behind the reasoning and implementation in Go can be found in the Go source code at
* [module.go](https://github.com/golang/go/blob/5b6d3dea8744311825fd544a73edb8d26d9c7e98/src/cmd/vendor/golang.org/x/mod/module/module.go#L33-L42C64)
*/
fviernau marked this conversation as resolved.
Show resolved Hide resolved
internal fun escapeVersion(version: String): String {
require("!" !in version) { "Module versions must not contain exclamation marks: $version" }
return version.replace(upperCaseCharRegex) { "!${it.value.lowercase()}" }
}

private val upperCaseCharRegex = Regex("[A-Z]")
19 changes: 19 additions & 0 deletions plugins/package-managers/go/src/test/kotlin/GoModTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

package org.ossreviewtoolkit.plugins.packagemanagers.go

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.WordSpec
import io.kotest.matchers.collections.beEmpty
import io.kotest.matchers.collections.containExactlyInAnyOrder
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe

class GoModTest : WordSpec({
"parseWhyOutput" should {
Expand Down Expand Up @@ -69,4 +71,21 @@ class GoModTest : WordSpec({
)
}
}

"escapeVersion" should {
fviernau marked this conversation as resolved.
Show resolved Hide resolved
"escape uppercase letters" {
val version = "v0.1.0-MS4.0.20231102094829-08e0c3cd016c"
val escapedVersion = escapeVersion(version)
Copy link
Member

Choose a reason for hiding this comment

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

Nit: The empty line before this one is still missing (the code that performs the action to test should stand by its own).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


escapedVersion shouldBe "v0.1.0-!m!s4.0.20231102094829-08e0c3cd016c"
}

"throw exception if version string contains an exclamation mark" {
val version = "v1.0.0!"

shouldThrow<IllegalArgumentException> {
escapeVersion(version)
}
}
}
})