Skip to content

Commit

Permalink
feat(swiftpm): Gracefully handle dependencies specified by branch name
Browse files Browse the repository at this point in the history
If a `Package.swift` file specifies a dependency with a branch name,
such as [^1], the result of its analysis based on running [^2] yields
"unspecified" as version string for that particular dependency.

A speciality of this package manger, similar to `GoMod`, is that
creating the dependency tree (via [^2]) includes resolving the
revisions for all dependencies. From investigating various project
setups, it seems that the lockfile entries for `remoteSourceControl`
dependencies (see property `PinV2.kind`) always have a revision / SHA1.
So, for `remoteSourceControl`, which is the only kind currently
handled, the lockfile entry contains all information needed while the
entries from [^2] lack the version / revision.

Fix both, the version string issues as well as the `vcsInfo.revision`
ones, by creating the result from the lockfile entries and only use the
entries from [^2] as a fallback.

Fixes #8167.

[^1]: `.package(url: "git@github.com:my-org/my-project.git", branch: "my-feature")`
[^2]: `swift package show-dependencies`

Signed-off-by: Frank Viernau <frank_viernau@epam.com>
  • Loading branch information
fviernau committed Feb 7, 2024
1 parent 9e71678 commit 227317c
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ project:
- id: "Swift::github.com/apple/swift-atomics:1.2.0"
- id: "Swift::github.com/apple/swift-collections:1.0.6"
- id: "Swift::github.com/apple/swift-system:1.2.1"
- id: "Swift::github.com/vapor/console-kit:unspecified"
- id: "Swift::github.com/vapor/console-kit:revision-a31f44ebfbd15a2cc0fda705279676773ac16355"
dependencies:
- id: "Swift::github.com/apple/swift-log:1.5.4"
- id: "Swift::github.com/apple/swift-nio:2.63.0"
Expand Down Expand Up @@ -199,12 +199,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-algorithms.git"
revision: "1.2.0"
revision: "f6919dfc309e7f1b56224378b11e28bab5bccc42"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-algorithms.git"
revision: "1.2.0"
revision: "f6919dfc309e7f1b56224378b11e28bab5bccc42"
path: ""
- id: "Swift::github.com/apple/swift-atomics:1.2.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-atomics@1.2.0"
Expand All @@ -225,12 +225,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-atomics.git"
revision: "1.2.0"
revision: "cd142fd2f64be2100422d658e7411e39489da985"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-atomics.git"
revision: "1.2.0"
revision: "cd142fd2f64be2100422d658e7411e39489da985"
path: ""
- id: "Swift::github.com/apple/swift-collections:1.0.6"
purl: "pkg:swift/github.com%2Fapple%2Fswift-collections@1.0.6"
Expand All @@ -251,12 +251,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-collections.git"
revision: "1.0.6"
revision: "d029d9d39c87bed85b1c50adee7c41795261a192"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-collections.git"
revision: "1.0.6"
revision: "d029d9d39c87bed85b1c50adee7c41795261a192"
path: ""
- id: "Swift::github.com/apple/swift-crypto:2.6.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-crypto@2.6.0"
Expand All @@ -277,12 +277,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-crypto.git"
revision: "2.6.0"
revision: "60f13f60c4d093691934dc6cfdf5f508ada1f894"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-crypto.git"
revision: "2.6.0"
revision: "60f13f60c4d093691934dc6cfdf5f508ada1f894"
path: ""
- id: "Swift::github.com/apple/swift-http-types:1.0.3"
purl: "pkg:swift/github.com%2Fapple%2Fswift-http-types@1.0.3"
Expand All @@ -303,12 +303,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-http-types.git"
revision: "1.0.3"
revision: "12358d55a3824bd5fed310b999ea8cf83a9a1a65"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-http-types.git"
revision: "1.0.3"
revision: "12358d55a3824bd5fed310b999ea8cf83a9a1a65"
path: ""
- id: "Swift::github.com/apple/swift-log:1.5.4"
purl: "pkg:swift/github.com%2Fapple%2Fswift-log@1.5.4"
Expand All @@ -329,12 +329,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-log.git"
revision: "1.5.4"
revision: "e97a6fcb1ab07462881ac165fdbb37f067e205d5"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-log.git"
revision: "1.5.4"
revision: "e97a6fcb1ab07462881ac165fdbb37f067e205d5"
path: ""
- id: "Swift::github.com/apple/swift-metrics:2.4.1"
purl: "pkg:swift/github.com%2Fapple%2Fswift-metrics@2.4.1"
Expand All @@ -355,12 +355,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-metrics.git"
revision: "2.4.1"
revision: "971ba26378ab69c43737ee7ba967a896cb74c0d1"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-metrics.git"
revision: "2.4.1"
revision: "971ba26378ab69c43737ee7ba967a896cb74c0d1"
path: ""
- id: "Swift::github.com/apple/swift-nio:2.63.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-nio@2.63.0"
Expand All @@ -381,12 +381,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-nio.git"
revision: "2.63.0"
revision: "635b2589494c97e48c62514bc8b37ced762e0a62"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-nio.git"
revision: "2.63.0"
revision: "635b2589494c97e48c62514bc8b37ced762e0a62"
path: ""
- id: "Swift::github.com/apple/swift-nio-extras:1.21.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-nio-extras@1.21.0"
Expand All @@ -407,12 +407,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-nio-extras.git"
revision: "1.21.0"
revision: "363da63c1966405764f380c627409b2f9d9e710b"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-nio-extras.git"
revision: "1.21.0"
revision: "363da63c1966405764f380c627409b2f9d9e710b"
path: ""
- id: "Swift::github.com/apple/swift-nio-http2:1.30.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-nio-http2@1.30.0"
Expand All @@ -433,12 +433,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-nio-http2.git"
revision: "1.30.0"
revision: "0904bf0feb5122b7e5c3f15db7df0eabe623dd87"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-nio-http2.git"
revision: "1.30.0"
revision: "0904bf0feb5122b7e5c3f15db7df0eabe623dd87"
path: ""
- id: "Swift::github.com/apple/swift-nio-ssl:2.26.0"
purl: "pkg:swift/github.com%2Fapple%2Fswift-nio-ssl@2.26.0"
Expand All @@ -459,12 +459,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-nio-ssl.git"
revision: "2.26.0"
revision: "7c381eb6083542b124a6c18fae742f55001dc2b5"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-nio-ssl.git"
revision: "2.26.0"
revision: "7c381eb6083542b124a6c18fae742f55001dc2b5"
path: ""
- id: "Swift::github.com/apple/swift-nio-transport-services:1.20.1"
purl: "pkg:swift/github.com%2Fapple%2Fswift-nio-transport-services@1.20.1"
Expand All @@ -485,12 +485,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-nio-transport-services.git"
revision: "1.20.1"
revision: "6cbe0ed2b394f21ab0d46b9f0c50c6be964968ce"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-nio-transport-services.git"
revision: "1.20.1"
revision: "6cbe0ed2b394f21ab0d46b9f0c50c6be964968ce"
path: ""
- id: "Swift::github.com/apple/swift-numerics:1.0.2"
purl: "pkg:swift/github.com%2Fapple%2Fswift-numerics@1.0.2"
Expand All @@ -511,12 +511,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-numerics.git"
revision: "1.0.2"
revision: "0a5bc04095a675662cf24757cc0640aa2204253b"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-numerics.git"
revision: "1.0.2"
revision: "0a5bc04095a675662cf24757cc0640aa2204253b"
path: ""
- id: "Swift::github.com/apple/swift-system:1.2.1"
purl: "pkg:swift/github.com%2Fapple%2Fswift-system@1.2.1"
Expand All @@ -537,12 +537,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/apple/swift-system.git"
revision: "1.2.1"
revision: "025bcb1165deab2e20d4eaba79967ce73013f496"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/apple/swift-system.git"
revision: "1.2.1"
revision: "025bcb1165deab2e20d4eaba79967ce73013f496"
path: ""
- id: "Swift::github.com/swift-server/async-http-client:1.20.1"
purl: "pkg:swift/github.com%2Fswift-server%2Fasync-http-client@1.20.1"
Expand All @@ -563,12 +563,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/swift-server/async-http-client.git"
revision: "1.20.1"
revision: "291438696abdd48d2a83b52465c176efbd94512b"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/swift-server/async-http-client.git"
revision: "1.20.1"
revision: "291438696abdd48d2a83b52465c176efbd94512b"
path: ""
- id: "Swift::github.com/swift-server/swift-backtrace:1.3.4"
purl: "pkg:swift/github.com%2Fswift-server%2Fswift-backtrace@1.3.4"
Expand All @@ -589,12 +589,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/swift-server/swift-backtrace.git"
revision: "1.3.4"
revision: "80746bdd0ac8a7d83aad5d89dac3cbf15de652e6"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/swift-server/swift-backtrace.git"
revision: "1.3.4"
revision: "80746bdd0ac8a7d83aad5d89dac3cbf15de652e6"
path: ""
- id: "Swift::github.com/vapor/async-kit:1.19.0"
purl: "pkg:swift/github.com%2Fvapor%2Fasync-kit@1.19.0"
Expand All @@ -615,15 +615,15 @@ packages:
vcs:
type: "Git"
url: "https://github.com/vapor/async-kit.git"
revision: "1.19.0"
revision: "7ece208cd401687641c88367a00e3ea2b04311f1"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/vapor/async-kit.git"
revision: "1.19.0"
revision: "7ece208cd401687641c88367a00e3ea2b04311f1"
path: ""
- id: "Swift::github.com/vapor/console-kit:unspecified"
purl: "pkg:swift/github.com%2Fvapor%2Fconsole-kit@unspecified"
- id: "Swift::github.com/vapor/console-kit:revision-a31f44ebfbd15a2cc0fda705279676773ac16355"
purl: "pkg:swift/github.com%2Fvapor%2Fconsole-kit@revision-a31f44ebfbd15a2cc0fda705279676773ac16355"
declared_licenses: []
declared_licenses_processed: {}
description: ""
Expand All @@ -641,12 +641,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/vapor/console-kit.git"
revision: "unspecified"
revision: "a31f44ebfbd15a2cc0fda705279676773ac16355"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/vapor/console-kit.git"
revision: "unspecified"
revision: "a31f44ebfbd15a2cc0fda705279676773ac16355"
path: ""
- id: "Swift::github.com/vapor/multipart-kit:4.6.0"
purl: "pkg:swift/github.com%2Fvapor%2Fmultipart-kit@4.6.0"
Expand All @@ -667,12 +667,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/vapor/multipart-kit.git"
revision: "4.6.0"
revision: "12ee56f25bd3fc4c2d09c2aa16e69de61dc786e8"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/vapor/multipart-kit.git"
revision: "4.6.0"
revision: "12ee56f25bd3fc4c2d09c2aa16e69de61dc786e8"
path: ""
- id: "Swift::github.com/vapor/routing-kit:4.9.0"
purl: "pkg:swift/github.com%2Fvapor%2Frouting-kit@4.9.0"
Expand All @@ -693,12 +693,12 @@ packages:
vcs:
type: "Git"
url: "https://github.com/vapor/routing-kit.git"
revision: "4.9.0"
revision: "2a92a7eac411a82fb3a03731be5e76773ebe1b3e"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/vapor/routing-kit.git"
revision: "4.9.0"
revision: "2a92a7eac411a82fb3a03731be5e76773ebe1b3e"
path: ""
- id: "Swift::github.com/vapor/websocket-kit:2.14.0"
purl: "pkg:swift/github.com%2Fvapor%2Fwebsocket-kit@2.14.0"
Expand All @@ -719,10 +719,10 @@ packages:
vcs:
type: "Git"
url: "https://github.com/vapor/websocket-kit.git"
revision: "2.14.0"
revision: "53fe0639a98903858d0196b699720decb42aee7b"
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/vapor/websocket-kit.git"
revision: "2.14.0"
revision: "53fe0639a98903858d0196b699720decb42aee7b"
path: ""
47 changes: 30 additions & 17 deletions plugins/package-managers/swiftpm/src/main/kotlin/SwiftPm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,27 @@ class SwiftPm(
val project = projectFromDefinitionFile(packageSwiftFile)
val swiftPackage = getSwiftPackage(packageSwiftFile)

val scope = Scope(
name = DEPENDENCIES_SCOPE_NAME,
dependencies = swiftPackage.dependencies.mapTo(mutableSetOf()) { it.toPackageReference() }
)
val issues = mutableListOf<Issue>()
val packages = mutableSetOf<Package>()
val scopeDependencies = mutableSetOf<Scope>()

parseLockfile(packageSwiftFile.resolveSibling(PACKAGE_RESOLVED_NAME)).onSuccess { pins ->
val pinsByIdentity = pins.associateBy { it.identity }

swiftPackage.getTransitiveDependencies().mapTo(packages) { it.toPackage(pinsByIdentity) }
scopeDependencies += Scope(
name = DEPENDENCIES_SCOPE_NAME,
dependencies = swiftPackage.dependencies.mapTo(mutableSetOf()) { it.toPackageReference(pinsByIdentity) }
)
}.onFailure {
issues += Issue(source = managerName, message = it.message.orEmpty())
}

return listOf(
ProjectAnalyzerResult(
project = project.copy(scopeDependencies = setOf(scope)),
packages = swiftPackage.getTransitiveDependencies().mapTo(mutableSetOf()) { it.toPackage() },
issues = emptyList()
project = project.copy(scopeDependencies = scopeDependencies),
packages = packages,
issues = issues
)
)
}
Expand Down Expand Up @@ -165,25 +176,27 @@ class SwiftPm(
}
}

private fun SwiftPackage.toId(): Identifier =
Identifier(
private fun SwiftPackage.toId(pinsByIdentity: Map<String, PinV2>): Identifier =
pinsByIdentity[identity]?.toId() ?: Identifier(
type = PACKAGE_TYPE,
namespace = "",
name = getCanonicalName(url),
version = version
)

private fun SwiftPackage.toVcsInfo(): VcsInfo {
val vcsInfoFromUrl = VcsHost.parseUrl(url)
return vcsInfoFromUrl.takeUnless { it.revision.isBlank() } ?: vcsInfoFromUrl.copy(revision = version)
}
private fun SwiftPackage.toVcsInfo(pinsByIdentity: Map<String, PinV2>): VcsInfo =
pinsByIdentity[identity]?.toVcsInfo() ?: run {
val vcsInfoFromUrl = VcsHost.parseUrl(url)
return vcsInfoFromUrl.takeUnless { it.revision.isBlank() } ?: vcsInfoFromUrl.copy(revision = version)
}

private fun SwiftPackage.toPackage(): Package = createPackage(toId(), toVcsInfo())
private fun SwiftPackage.toPackage(pinsByIdentity: Map<String, PinV2>): Package =
createPackage(toId(pinsByIdentity), toVcsInfo(pinsByIdentity))

private fun SwiftPackage.toPackageReference(): PackageReference =
private fun SwiftPackage.toPackageReference(pinsByIdentity: Map<String, PinV2>): PackageReference =
PackageReference(
id = toId(),
dependencies = dependencies.mapTo(mutableSetOf()) { it.toPackageReference() }
id = toId(pinsByIdentity),
dependencies = dependencies.mapTo(mutableSetOf()) { it.toPackageReference(pinsByIdentity) }
)

private fun SwiftPackage.getTransitiveDependencies(): Set<SwiftPackage> {
Expand Down

0 comments on commit 227317c

Please sign in to comment.