Skip to content

Commit

Permalink
Improve ForkedFrom to reflect more info in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
supersonicbyte committed Sep 10, 2024
1 parent 30c4baf commit 25bb923
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright Dave Verwer, Sven A. Schmidt, and other contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Fluent
import SQLKit
import Vapor

extension API.PackageController {
enum ForkedFromResult {
case fromSPI(repository: String, owner: String, ownerName: String, packageName: String)
case fromGitHub(url: String)

static func query(on database: Database, packageId: Package.Id) async throws -> ForkedFromResult? {
let model = try await Joined3<Package, Repository, Version>.query(on: database, packageId: packageId).first()

guard let repoName = model?.repository.name,
let ownerName = model?.repository.ownerName,
let owner = model?.repository.owner,
let packageName = model?.version.packageName else {
return nil
}

return ForkedFromResult.fromSPI(
repository: repoName,
owner: owner,
ownerName: ownerName,
packageName: packageName
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Vapor
extension API.PackageController.GetRoute {
struct Model: Content, Equatable {
var packageId: Package.Id
var packageName: String
var repositoryOwner: String
var repositoryOwnerName: String
var repositoryName: String
Expand Down Expand Up @@ -50,9 +51,10 @@ extension API.PackageController.GetRoute {
var releaseReferences: [App.Version.Kind: App.Reference]
var fundingLinks: [FundingLink]
var swift6Readiness: Swift6Readiness?
var forkedFromURL: String?
var forkedFromInfo: ForkedFromInfo?

internal init(packageId: Package.Id,
packageName: String,
repositoryOwner: String,
repositoryOwnerName: String,
repositoryName: String,
Expand Down Expand Up @@ -83,9 +85,10 @@ extension API.PackageController.GetRoute {
preReleaseReference: App.Reference?,
fundingLinks: [FundingLink] = [],
swift6Readiness: Swift6Readiness?,
forkedFromURL: String?
forkedFromResult: API.PackageController.ForkedFromResult?
) {
self.packageId = packageId
self.packageName = packageName
self.repositoryOwner = repositoryOwner
self.repositoryOwnerName = repositoryOwnerName
self.repositoryName = repositoryName
Expand Down Expand Up @@ -125,7 +128,22 @@ extension API.PackageController.GetRoute {
}()
self.fundingLinks = fundingLinks
self.swift6Readiness = swift6Readiness
self.forkedFromURL = forkedFromURL
if let forkedFromResult {
switch forkedFromResult {
case .fromSPI(let repo, let owner, let ownerName, let packageName):
self.forkedFromInfo = ForkedFromInfo.fromSPI(
packageName: packageName,
originalOwner: owner,
originalOwnerName: ownerName,
originalRepo: repo,
originalPackageName: packageName
)
case .fromGitHub(let url):
self.forkedFromInfo = ForkedFromInfo.fromGitHub(url: url)
}
} else {
self.forkedFromInfo = nil
}
}

init?(result: API.PackageController.PackageResult,
Expand All @@ -136,18 +154,20 @@ extension API.PackageController.GetRoute {
platformBuildInfo: BuildInfo<CompatibilityMatrix.PlatformCompatibility>?,
weightedKeywords: [WeightedKeyword] = [],
swift6Readiness: Swift6Readiness?,
forkedFromURL: String?) {
forkedFromResult: API.PackageController.ForkedFromResult?) {
// we consider certain attributes as essential and return nil (raising .notFound)
let repository = result.repository
guard
let repositoryOwner = repository.owner,
let repositoryOwnerName = repository.ownerDisplayName,
let repositoryName = repository.name,
let packageId = result.package.id
let packageId = result.package.id,
let packageName = result.defaultBranchVersion.packageName
else { return nil }

self.init(
packageId: packageId,
packageName: packageName,
repositoryOwner: repositoryOwner,
repositoryOwnerName: repositoryOwnerName,
repositoryName: repositoryName,
Expand Down Expand Up @@ -182,7 +202,7 @@ extension API.PackageController.GetRoute {
preReleaseReference: result.preReleaseVersion?.reference,
fundingLinks: result.repository.fundingLinks,
swift6Readiness: swift6Readiness,
forkedFromURL: forkedFromURL
forkedFromResult: forkedFromResult
)

}
Expand Down Expand Up @@ -353,6 +373,26 @@ extension API.PackageController.GetRoute.Model {
}
}
}

enum ForkedFromInfo: Codable, Equatable {
case fromSPI(
packageName: String,
originalOwner: String,
originalOwnerName: String,
originalRepo: String,
originalPackageName: String
)
case fromGitHub(url: String)

var url: String {
switch self {
case .fromSPI(_, let originalOwner, _, let originalRepo, _):
return SiteURL.package(.value(originalOwner), .value(originalRepo), nil).absoluteURL()
case .fromGitHub(let url):
return url
}
}
}

}

Expand Down
15 changes: 7 additions & 8 deletions Sources/App/Controllers/API/API+PackageController+GetRoute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension API.PackageController {
owner: owner,
repository: repository)

let forkedFromURL = try await self.fetchForkedFromURL(on: database,
let forkedFromResult = try? await self.fetchForkedFromResult(on: database,
repository: packageResult.repository)

async let weightedKeywords = WeightedKeyword.query(
Expand Down Expand Up @@ -60,7 +60,7 @@ extension API.PackageController {
platformBuildInfo: buildInfo.platform,
weightedKeywords: weightedKeywords,
swift6Readiness: buildInfo.swift6Readiness,
forkedFromURL: forkedFromURL
forkedFromResult: forkedFromResult
),
let schema = API.PackageSchema(result: packageResult)
else {
Expand All @@ -70,15 +70,14 @@ extension API.PackageController {
return (model, schema)
}

private static func fetchForkedFromURL(on database: Database, repository: Repository) async throws -> String? {
private static func fetchForkedFromResult(on database: Database, repository: Repository) async throws -> ForkedFromResult? {
if let forkedFrom = repository.forkedFrom {
switch forkedFrom {
case .parentId(let id):
let repo = try await Repository.find(on: database, for: id)
guard let owner = repo?.owner, let name = repo?.name else { return nil }
return SiteURL.package(.value(owner), .value(name), nil).absoluteURL()
case .parentURL(let string):
return string
let info = try await ForkedFromResult.query(on: database, packageId: id)
return info
case .parentURL(let url):
return .fromGitHub(url: url)
}
}
return nil
Expand Down
3 changes: 2 additions & 1 deletion Sources/App/Controllers/API/Types+WithExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ extension API.PackageController.GetRoute.Model.History: WithExample {
extension API.PackageController.GetRoute.Model: WithExample {
static var example: Self {
.init(packageId: .example,
packageName: "Mona",
repositoryOwner: "mona",
repositoryOwnerName: "Mona",
repositoryName: "LinkedList",
Expand Down Expand Up @@ -248,7 +249,7 @@ extension API.PackageController.GetRoute.Model: WithExample {
releaseReference: .tag(1, 2, 3, "1.2.3"),
preReleaseReference: nil,
swift6Readiness: nil,
forkedFromURL: nil)
forkedFromResult: nil)
}
}

Expand Down
8 changes: 8 additions & 0 deletions Sources/App/Core/Query+Support/Joined3+Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ extension Joined3 where M == Package, R1 == Repository, R2 == Version {
.filter(Repository.self, \.$owner, .custom("ilike"), owner)
.filter(Repository.self, \.$name, .custom("ilike"), repository)
}

static func query(on database: Database, packageId: Package.Id) -> JoinedQueryBuilder<Self> {
query(on: database,
join: \Package.$id == \Repository.$package.$id, method: .inner,
join: \Version.$package.$id == \Package.$id, method: .inner)
.filter(Version.self, \Version.$latest == .defaultBranch)
.filter(Package.self, \Package.$id == packageId)
}
}
47 changes: 37 additions & 10 deletions Sources/App/Views/PackageController/GetRoute.Model+ext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,45 @@ extension API.PackageController.GetRoute.Model {
}

func forkedListItem() -> Node<HTML.ListContext> {
if let forkedFromURL {
let repoURLNode: Node<HTML.BodyContext> = .a(
.href(forkedFromURL),
.text("repository")
)
if let forkedFromInfo {
let item: Node<HTML.BodyContext> = {
switch forkedFromInfo {
case .fromGitHub(let url):
let repoURLNode: Node<HTML.BodyContext> = .a(
.href(url),
.text("repository")
)
return .group(
.text("Forked from "),
repoURLNode,
.text(".")
)
case .fromSPI(let packageName, let owner, let ownerName, let repo, let originalPackageName):
let repoURLNode: Node<HTML.BodyContext>
if packageName == originalPackageName {
repoURLNode = .a(
.href(forkedFromInfo.url),
.text(ownerName)
)

} else {
repoURLNode = .a(
.href(forkedFromInfo.url),
.text("\(originalPackageName) by \(ownerName)")
)
}

return .group(
.text("Forked from "),
repoURLNode,
.text(".")
)
}
}()

return .li(
.class("forked"),
.group(
.text("Forked from "),
repoURLNode,
.text(".")
)
item
)
} else {
return .empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extension API.PackageController.GetRoute.Model {
static var mock: Self {
.init(
packageId: UUID("cafecafe-cafe-cafe-cafe-cafecafecafe")!,
packageName: "Alamofire",
repositoryOwner: "Alamo",
repositoryOwnerName: "Alamofire",
repositoryName: "Alamofire",
Expand Down Expand Up @@ -126,7 +127,7 @@ extension API.PackageController.GetRoute.Model {
releaseReference: .tag(5, 2, 0),
preReleaseReference: .tag(5, 3, 0, "beta.1"),
swift6Readiness: nil,
forkedFromURL: nil
forkedFromResult: nil
)
}
}

0 comments on commit 25bb923

Please sign in to comment.