Skip to content

Commit 7579697

Browse files
committed
Make Package.filter(by: [URL]) case-insensitive and normalise the input URLs
1 parent a949e12 commit 7579697

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

Sources/App/Models/Package.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,13 @@ extension QueryBuilder where Model == Package {
273273
}
274274

275275
func filter(by urls: some Collection<URL>) -> Self {
276-
// TODO: make case-insensitive and canonicalise incoming URLs
277-
filter(\.$url ~~ urls.map(\.absoluteString))
276+
let urls = urls
277+
.compactMap(\.normalized)
278+
.map { $0.absoluteString.lowercased() }
279+
// Fluent cannot chain `lowercased()` onto `\.$url but the following is essentially
280+
// filter(\.$url.lowercased() ~~ urls)
281+
// by dropping down to SQLKit
282+
return filter(.sql(embed: "LOWER(\(ident: Model.schemaOrAlias).\(ident: Model.path(for: \.$url)[0].description)) IN \(SQLBind.group(urls))"))
278283
}
279284
}
280285

Tests/AppTests/PackageTests.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,24 @@ final class PackageTests: AppTestCase {
137137
}
138138

139139
func test_filter_by_urls() async throws {
140-
for url in ["https://foo.com/1", "https://foo.com/2", "https://foo.com/a", "https://foo.com/A"] {
140+
for url in ["https://foo.com/1.git", "https://foo.com/2.git", "https://foo.com/a.git", "https://foo.com/A.git"] {
141141
try await Package(url: url.url).save(on: app.db)
142142
}
143-
let res = try await Package.query(on: app.db).filter(by: ["https://foo.com/2", "https://foo.com/a"]).all()
144-
XCTAssertEqual(res.map(\.url), ["https://foo.com/2", "https://foo.com/a"])
143+
do { // single match
144+
let res = try await Package.query(on: app.db).filter(by: ["https://foo.com/2.git"]).all()
145+
XCTAssertEqual(res.map(\.url), ["https://foo.com/2.git"])
146+
}
147+
do { // case insensitive match
148+
let res = try await Package.query(on: app.db).filter(by: ["https://foo.com/2.git", "https://foo.com/a.git"]).all()
149+
XCTAssertEqual(
150+
res.map(\.url),
151+
["https://foo.com/2.git", "https://foo.com/a.git", "https://foo.com/A.git"]
152+
)
153+
}
154+
do { // input URLs are normalised
155+
let res = try await Package.query(on: app.db).filter(by: ["http://foo.com/2"]).all()
156+
XCTAssertEqual(res.map(\.url), ["https://foo.com/2.git"])
157+
}
145158
}
146159

147160
func test_repository() async throws {

0 commit comments

Comments
 (0)