Skip to content

Commit

Permalink
feat: add repo topics (#197)
Browse files Browse the repository at this point in the history
* add repo topics

* lint fixes

* actually fix final linter error

---------

Co-authored-by: Andrew McKnight <[email protected]>
  • Loading branch information
armcknight and Andrew McKnight authored Dec 6, 2024
1 parent 61fa132 commit 5721c0b
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
8 changes: 8 additions & 0 deletions OctoKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@
721F73E929889A040064B11A /* latest_release.json in Resources */ = {isa = PBXBuildFile; fileRef = 721F73E829889A040064B11A /* latest_release.json */; };
721F73EA29889A040064B11A /* latest_release.json in Resources */ = {isa = PBXBuildFile; fileRef = 721F73E829889A040064B11A /* latest_release.json */; };
721F73EB29889A040064B11A /* latest_release.json in Resources */ = {isa = PBXBuildFile; fileRef = 721F73E829889A040064B11A /* latest_release.json */; };
849DF07A2D029AF400A202DF /* topics.json in Resources */ = {isa = PBXBuildFile; fileRef = 849DF0792D029AF400A202DF /* topics.json */; };
849DF07B2D029AF400A202DF /* topics.json in Resources */ = {isa = PBXBuildFile; fileRef = 849DF0792D029AF400A202DF /* topics.json */; };
849DF07C2D029AF400A202DF /* topics.json in Resources */ = {isa = PBXBuildFile; fileRef = 849DF0792D029AF400A202DF /* topics.json */; };
84B89D012C814DBC00273C68 /* Organization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B89D002C814DBC00273C68 /* Organization.swift */; };
84B89D032C814DE400273C68 /* forked_repo.json in Resources */ = {isa = PBXBuildFile; fileRef = 84B89D022C814DE400273C68 /* forked_repo.json */; };
84B89D042C814DED00273C68 /* forked_repo.json in Resources */ = {isa = PBXBuildFile; fileRef = 84B89D022C814DE400273C68 /* forked_repo.json */; };
Expand Down Expand Up @@ -340,6 +343,7 @@
665D5D5E24A639D70045E3B4 /* statuses.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = statuses.json; path = Fixtures/statuses.json; sourceTree = "<group>"; };
665D5D5F24A639D70045E3B4 /* status.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = status.json; path = Fixtures/status.json; sourceTree = "<group>"; };
721F73E829889A040064B11A /* latest_release.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = latest_release.json; path = Fixtures/latest_release.json; sourceTree = "<group>"; };
849DF0792D029AF400A202DF /* topics.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = topics.json; path = Fixtures/topics.json; sourceTree = "<group>"; };
84B89D002C814DBC00273C68 /* Organization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Organization.swift; sourceTree = "<group>"; };
84B89D022C814DE400273C68 /* forked_repo.json */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text.json; name = forked_repo.json; path = Fixtures/forked_repo.json; sourceTree = "<group>"; };
9D9ADDDE23EEFD4A000AC34D /* ReviewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -488,6 +492,7 @@
23EA619C25EAE31A001B0964 /* reactions.json */,
23EA619F25EAE31A001B0964 /* releases.json */,
23EA619E25EAE31A001B0964 /* reviews.json */,
849DF0792D029AF400A202DF /* topics.json */,
);
name = Fixtures;
sourceTree = "<group>";
Expand Down Expand Up @@ -831,6 +836,7 @@
234F4BDD1BDDE44600A58EF7 /* public_key.json in Resources */,
5090ED7223E483820062C763 /* issue_comment.json in Resources */,
DABBDE501C8C0C20008F57CD /* issue.json in Resources */,
849DF07B2D029AF400A202DF /* topics.json in Resources */,
234F4BDE1BDDE44600A58EF7 /* repo.json in Resources */,
23EA61B425EAE31A001B0964 /* pull_requests.json in Resources */,
234F4BE11BDDE44600A58EF7 /* user_repos.json in Resources */,
Expand Down Expand Up @@ -880,6 +886,7 @@
23F643461C7AEF63000427B3 /* public_key.json in Resources */,
502C70FC23E8535900384775 /* issue_comment.json in Resources */,
DABBDE511C8C0C20008F57CD /* issue.json in Resources */,
849DF07C2D029AF400A202DF /* topics.json in Resources */,
23F643481C7AEF66000427B3 /* repo.json in Resources */,
23EA61B525EAE31A001B0964 /* pull_requests.json in Resources */,
23F6434E1C7AEF6F000427B3 /* user_repos.json in Resources */,
Expand Down Expand Up @@ -921,6 +928,7 @@
23F643471C7AEF63000427B3 /* public_key.json in Resources */,
502C70FD23E8535A00384775 /* issue_comment.json in Resources */,
DABBDE521C8C0C20008F57CD /* issue.json in Resources */,
849DF07A2D029AF400A202DF /* topics.json in Resources */,
23F643491C7AEF67000427B3 /* repo.json in Resources */,
23EA61B625EAE31A001B0964 /* pull_requests.json in Resources */,
23F6434F1C7AEF70000427B3 /* user_repos.json in Resources */,
Expand Down
48 changes: 48 additions & 0 deletions OctoKit/Repositories.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ public struct SymlinkContent: Codable {
}
}

public struct Topics: Codable {
public let names: [String]

private enum CodingKeys: String, CodingKey {
case names
}
}

public struct SubmoduleContent: Codable {
public let type: String
public let submoduleGitUrl: String
Expand Down Expand Up @@ -291,6 +299,40 @@ public extension Octokit {
}
#endif

/**
* Fetches the topics for the specified repository.
* - parameters:
* - owner: the user or org that owns the repository
* - name: the name of the repository
*/
@discardableResult
func repositoryTopics(owner: String, name: String, completion: @escaping (_ response: Result<Topics, Error>) -> Void) -> URLSessionDataTaskProtocol? {
let router = RepositoryRouter.getRepositoryTopics(configuration, owner: owner, name: name)
return router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Topics.self) { contentResponse, error in
if let error = error {
completion(.failure(error))
} else {
if let contentResponse = contentResponse {
completion(.success(contentResponse))
}
}
}
}

#if compiler(>=5.5.2) && canImport(_Concurrency)
/**
* Fetches the topics for the specified repository.
* - parameters:
* - owner: the user or org that owns the repository
* - name: the name of the repository
*/
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
func repositoryTopics(owner: String, name: String) async throws -> Topics {
let router = RepositoryRouter.getRepositoryTopics(configuration, owner: owner, name: name)
return try await router.load(session, dateDecodingStrategy: .formatted(Time.rfc3339DateFormatter), expectedResultType: Topics.self)
}
#endif

/**
Gets the contents of a file or directory in a repository.
[Github documentation](https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28)
Expand Down Expand Up @@ -342,13 +384,15 @@ enum RepositoryRouter: Router {
case readAuthenticatedRepositories(Configuration, String, String)
case readRepository(Configuration, String, String)
case getRepositoryContent(Configuration, String, String, String?, String?)
case getRepositoryTopics(Configuration, owner: String, name: String)

var configuration: Configuration {
switch self {
case let .readRepositories(config, _, _, _): return config
case let .readAuthenticatedRepositories(config, _, _): return config
case let .readRepository(config, _, _): return config
case let .getRepositoryContent(config, _, _, _, _): return config
case let .getRepositoryTopics(config, _, _): return config
}
}

Expand All @@ -373,6 +417,8 @@ enum RepositoryRouter: Router {
return ["ref": ref]
}
return [:]
case .getRepositoryTopics:
return [:]
}
}

Expand All @@ -388,6 +434,8 @@ enum RepositoryRouter: Router {
var path = "repos/\(owner)/\(repo)/contents"
if let searchPath = searchPath { path.append("/\(searchPath)") }
return path
case let .getRepositoryTopics(_, owner, name):
return "repos/\(owner)/\(name)/topics"
}
}
}
6 changes: 6 additions & 0 deletions Tests/OctoKitTests/Fixtures/topics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"names": [
"swift",
"library"
]
}
26 changes: 26 additions & 0 deletions Tests/OctoKitTests/RepositoryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,32 @@ class RepositoryTests: XCTestCase {
}
#endif

func testGetRepositoryTopics() {
let (owner, name) = ("mietzmithut", "Test")
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/mietzmithut/Test/topics", expectedHTTPMethod: "GET", jsonFile: "topics", statusCode: 200)
let task = Octokit(session: session).repositoryTopics(owner: owner, name: name) { response in
switch response {
case let .success(topics):
XCTAssertEqual(topics.names, ["swift", "library"])
case .failure:
XCTAssert(false, "should not get an error")
}
}
XCTAssertNotNil(task)
XCTAssertTrue(session.wasCalled)
}

#if compiler(>=5.5.2) && canImport(_Concurrency)
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
func testGetRepositoryTopicsAsync() async throws {
let (owner, name) = ("mietzmithut", "Test")
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/mietzmithut/Test/topics", expectedHTTPMethod: "GET", jsonFile: "topics", statusCode: 200)
let topics = try await Octokit(session: session).repositoryTopics(owner: owner, name: name)
XCTAssertEqual(topics.names, ["swift", "library"])
XCTAssertTrue(session.wasCalled)
}
#endif

func testfailureRepositoryContent() {
let session = OctoKitURLTestSession(expectedURL: "https://api.github.com/repos/nerdishbynature/octokit.swift/contents/Package.swift",
expectedHTTPMethod: "GET",
Expand Down

0 comments on commit 5721c0b

Please sign in to comment.