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

Enable lenient parsing of Git version tags #3649

Merged
merged 1 commit into from
Aug 9, 2021
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ Note: This is in reverse chronological order, so newer entries are added to the

Swift v.Next
-----------
* [#3649]
Semantic version dependencies can now be resolved against Git tag names that contain only major and minor version identifiers. A tag with the form `X.Y` will be treated as `X.Y.0`. This improves compatibility with existing repositories.



Expand Down
4 changes: 2 additions & 2 deletions Sources/Basics/Version+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ extension Version {
/// - Parameter tag: A version string possibly prepended with "v".
public init?(tag: String) {
if tag.first == "v" {
self.init(string: String(tag.dropFirst()))
try? self.init(versionString: String(tag.dropFirst()), usesLenientParsing: true)
} else {
self.init(string: tag)
try? self.init(versionString: tag, usesLenientParsing: true)
}
}
}
18 changes: 16 additions & 2 deletions Sources/PackageGraph/RepositoryPackageContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,23 @@ public class RepositoryPackageContainer: PackageContainer, CustomStringConvertib
let knownVersionsWithDuplicates = Git.convertTagsToVersionMap(try repository.getTags())

return knownVersionsWithDuplicates.mapValues({ tags -> String in
if tags.count == 2 {
if tags.count > 1 {
// FIXME: Warn if the two tags point to different git references.
return tags.first(where: { !$0.hasPrefix("v") })!

// If multiple tags are present with the same semantic version (e.g. v1.0.0, 1.0.0, 1.0) reconcile which one we prefer.
// Prefer the most specific tag, e.g. 1.0.0 is preferred over 1.0.
// Sort the tags so the most specific tag is first, order is ascending so the most specific tag will be last
let tagsSortedBySpecificity = tags.sorted {
let componentCounts = ($0.components(separatedBy: ".").count, $1.components(separatedBy: ".").count)
if componentCounts.0 == componentCounts.1 {
//if they are both have the same number of components, favor the one without a v prefix.
//this matches previously defined behavior
//this assumes we can only enter this situation because one tag has a v prefix and the other does not.
return $0.hasPrefix("v")
}
return componentCounts.0 < componentCounts.1
}
return tagsSortedBySpecificity.last!
}
assert(tags.count == 1, "Unexpected number of tags")
return tags[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@ class RepositoryPackageContainerProviderTests: XCTestCase {
try repo.commit()
try repo.tag(name: "v1.0.0")
try repo.tag(name: "1.0.0")
try repo.tag(name: "v1.1.0")
try repo.tag(name: "1.1.0")
try repo.tag(name: "1.1")
try repo.tag(name: "1.2")
try repo.tag(name: "1.3")
try repo.tag(name: "1.3.0")
try repo.tag(name: "1.0.1")
try repo.tag(name: "v1.0.2")
try repo.tag(name: "1.0.4")
Expand All @@ -366,7 +372,7 @@ class RepositoryPackageContainerProviderTests: XCTestCase {
let ref = PackageReference.remote(identity: PackageIdentity(path: repoPath), location: repoPath.pathString)
let container = try provider.getContainer(for: ref, skipUpdate: false)
let v = try container.toolsVersionsAppropriateVersionsDescending().map { $0 }
XCTAssertEqual(v, ["2.0.1", "1.0.4", "1.0.2", "1.0.1", "1.0.0"])
XCTAssertEqual(v, ["2.0.1", "1.3.0", "1.2.0", "1.1.0", "1.0.4", "1.0.2", "1.0.1", "1.0.0"])
}

func testDependencyConstraints() throws {
Expand Down