Skip to content

Commit 746f96c

Browse files
authored
Merge pull request #17 from tayloraswift/tag-crawling-2
Tag crawling
2 parents 8270688 + cdc4e80 commit 746f96c

File tree

69 files changed

+1002
-414
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1002
-414
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ jobs:
1414
strategy:
1515
matrix:
1616
image:
17-
- swift:5.8.1-amazonlinux2
18-
- swift:5.8.1-jammy
17+
- swift:5.9.0-amazonlinux2
18+
- swift:5.9.0-jammy
1919
steps:
2020
- name: checkout repository
2121
uses: actions/checkout@v3

Package.swift

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ let package:Package = .init(
1414
.library(name: "DoclinkResolution", targets: ["DoclinkResolution"]),
1515
.library(name: "FNV1", targets: ["FNV1"]),
1616

17-
.library(name: "GitHubIntegration", targets: ["GitHubIntegration"]),
17+
.library(name: "GitHubAPI", targets: ["GitHubAPI"]),
18+
.library(name: "GitHubClient", targets: ["GitHubClient"]),
1819

1920
.library(name: "HTML", targets: ["HTML"]),
2021

@@ -68,13 +69,15 @@ let package:Package = .init(
6869
],
6970
dependencies:
7071
[
71-
//.package(url: "https://github.com/tayloraswift/swift-json", .upToNextMinor(
72-
// from: "0.6.0")),
7372
.package(url: "https://github.com/tayloraswift/swift-grammar", .upToNextMinor(
7473
from: "0.3.2")),
74+
.package(url: "https://github.com/tayloraswift/swift-hash", .upToNextMinor(
75+
from: "0.5.0")),
7576
.package(url: "https://github.com/tayloraswift/swift-mongodb", .upToNextMinor(
7677
from: "0.8.2")),
7778

79+
.package(url: "https://github.com/apple/swift-atomics", .upToNextMinor(
80+
from: "1.1.0")),
7881
.package(url: "https://github.com/apple/swift-nio", .upToNextMinor(
7982
from: "2.57.0")),
8083
.package(url: "https://github.com/apple/swift-nio-http2", .upToNextMinor(
@@ -125,13 +128,16 @@ let package:Package = .init(
125128

126129
.target(name: "GitHubClient", dependencies:
127130
[
128-
.target(name: "GitHubIntegration"),
131+
.target(name: "GitHubAPI"),
129132
.target(name: "HTTPClient"),
133+
134+
.product(name: "Base64", package: "swift-hash"),
130135
]),
131136

132-
.target(name: "GitHubIntegration", dependencies:
137+
.target(name: "GitHubAPI", dependencies:
133138
[
134139
.target(name: "JSON"),
140+
.target(name: "UnixTime"),
135141
]),
136142

137143
.target(name: "HTML", dependencies:
@@ -376,9 +382,10 @@ let package:Package = .init(
376382

377383
.target(name: "UnidocDB", dependencies:
378384
[
379-
.target(name: "GitHubIntegration"),
385+
.target(name: "GitHubAPI"),
380386
.target(name: "UnidocAnalysis"),
381387
.target(name: "UnidocLinker"),
388+
.target(name: "UnixTime"),
382389
.product(name: "MongoDB", package: "swift-mongodb"),
383390
]),
384391

@@ -398,7 +405,7 @@ let package:Package = .init(
398405

399406
.target(name: "UnidocPages", dependencies:
400407
[
401-
.target(name: "GitHubIntegration"),
408+
.target(name: "GitHubAPI"),
402409
.target(name: "HTTP"),
403410
.target(name: "MarkdownRendering"),
404411
.target(name: "UnidocQueries"),
@@ -425,10 +432,7 @@ let package:Package = .init(
425432
.target(name: "URI"),
426433
]),
427434

428-
.target(name: "UnixTime", dependencies:
429-
[
430-
.product(name: "BSON", package: "swift-mongodb"),
431-
]),
435+
.target(name: "UnixTime"),
432436

433437
.target(name: "URI", dependencies:
434438
[
@@ -454,6 +458,8 @@ let package:Package = .init(
454458
.target(name: "Multiparts"),
455459
.target(name: "System"),
456460
.target(name: "UnidocPages"),
461+
462+
.product(name: "Atomics", package: "swift-atomics"),
457463
]),
458464

459465

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div align="center">
22

3-
<strong><em><code>unidoc</code></em></strong><br><small><code>0.2.2</code></small>
3+
<strong><em><code>unidoc</code></em></strong><br><small><code>0.2.3</code></small>
44

55
[![ci build status](https://github.com/kelvin13/swift-unidoc/actions/workflows/build.yml/badge.svg)](https://github.com/kelvin13/swift-unidoc/actions/workflows/build.yml)
66

Sources/GitHubIntegration/GitHubAPI.Repo.License.swift renamed to Sources/GitHubAPI/GitHub.Repo.License.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import JSON
22

3-
extension GitHubAPI.Repo
3+
extension GitHub.Repo
44
{
55
@frozen public
66
struct License:Identifiable, Equatable, Sendable
@@ -20,7 +20,7 @@ extension GitHubAPI.Repo
2020
}
2121
}
2222
}
23-
extension GitHubAPI.Repo.License:JSONObjectDecodable
23+
extension GitHub.Repo.License:JSONObjectDecodable
2424
{
2525
public
2626
enum CodingKey:String

Sources/GitHubIntegration/GitHubAPI.Repo.Owner.swift renamed to Sources/GitHubAPI/GitHub.Repo.Owner.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import JSON
22

3-
extension GitHubAPI.Repo
3+
extension GitHub.Repo
44
{
55
@frozen public
66
struct Owner:Identifiable, Equatable, Sendable
@@ -21,7 +21,7 @@ extension GitHubAPI.Repo
2121
}
2222
}
2323
}
24-
extension GitHubAPI.Repo.Owner:JSONObjectDecodable
24+
extension GitHub.Repo.Owner:JSONObjectDecodable
2525
{
2626
public
2727
enum CodingKey:String

Sources/GitHubIntegration/GitHubAPI.Repo.swift renamed to Sources/GitHubAPI/GitHub.Repo.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import JSON
22

3-
extension GitHubAPI
3+
extension GitHub
44
{
55
@frozen public
66
struct Repo:Identifiable, Equatable, Sendable
@@ -109,7 +109,7 @@ extension GitHubAPI
109109
}
110110
}
111111
}
112-
extension GitHubAPI.Repo:JSONObjectDecodable
112+
extension GitHub.Repo:JSONObjectDecodable
113113
{
114114
public
115115
enum CodingKey:String

Sources/GitHubIntegration/GitHubAPI.Tag.Commit.swift renamed to Sources/GitHubAPI/GitHub.Tag.Commit.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import JSON
22
import SHA1
33

4-
extension GitHubAPI.Tag
4+
extension GitHub.Tag
55
{
66
struct Commit
77
{
@@ -13,7 +13,7 @@ extension GitHubAPI.Tag
1313
}
1414
}
1515
}
16-
extension GitHubAPI.Tag.Commit:JSONObjectDecodable
16+
extension GitHub.Tag.Commit:JSONObjectDecodable
1717
{
1818
enum CodingKey:String
1919
{

Sources/GitHubIntegration/GitHubAPI.Tag.swift renamed to Sources/GitHubAPI/GitHub.Tag.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import JSON
22
import SHA1
33

4-
extension GitHubAPI
4+
extension GitHub
55
{
66
@frozen public
77
struct Tag:Equatable, Sendable
@@ -22,7 +22,7 @@ extension GitHubAPI
2222
}
2323
}
2424
}
25-
extension GitHubAPI.Tag:JSONObjectDecodable
25+
extension GitHub.Tag:JSONObjectDecodable
2626
{
2727
public
2828
enum CodingKey:String

Sources/GitHubIntegration/GitHubAPI.User.swift renamed to Sources/GitHubAPI/GitHub.User.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import JSON
22

3-
extension GitHubAPI
3+
extension GitHub
44
{
55
@frozen public
66
struct User:Identifiable, Equatable, Sendable
@@ -97,7 +97,7 @@ extension GitHubAPI
9797
}
9898
}
9999
}
100-
extension GitHubAPI.User:JSONObjectDecodable
100+
extension GitHub.User:JSONObjectDecodable
101101
{
102102
public
103103
enum CodingKey:String

Sources/GitHubAPI/GitHub.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// A namespace for GitHub API types.
2+
@frozen public
3+
enum GitHub
4+
{
5+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
extension GitHubOAuth
2+
{
3+
@frozen public
4+
struct API
5+
{
6+
public
7+
let agent:String
8+
public
9+
let oauth:GitHubOAuth?
10+
11+
@inlinable internal
12+
init(agent:String, oauth:GitHubOAuth?)
13+
{
14+
self.agent = agent
15+
self.oauth = oauth
16+
}
17+
}
18+
}

Sources/GitHubIntegration/GitHubOAuth.swift renamed to Sources/GitHubAPI/GitHubOAuth.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/// The essence of a GitHub OAuth application.
2+
///
3+
/// A `GitHubOAuth` instance is just a ``client`` ID and ``secret``.
24
@frozen public
35
struct GitHubOAuth:GitHubApplication
46
{
@@ -14,3 +16,9 @@ struct GitHubOAuth:GitHubApplication
1416
self.secret = secret
1517
}
1618
}
19+
extension GitHubOAuth
20+
{
21+
/// The GitHub API.
22+
@inlinable public
23+
var api:API { .init(agent: "swift-unidoc (by tayloraswift)", oauth: self) }
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import UnixTime
2+
3+
public
4+
protocol GitHubRateLimitError:Error, Equatable, Sendable
5+
{
6+
/// The UTC epoch second when the rate limit will reset.
7+
var until:UnixTime { get }
8+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import Base64
2+
import GitHubAPI
3+
import HTTPClient
4+
import JSON
5+
import NIOCore
6+
import NIOHPACK
7+
import UnixTime
8+
9+
extension GitHubClient
10+
{
11+
@frozen public
12+
struct Connection
13+
{
14+
@usableFromInline internal
15+
let http2:HTTP2Client.Connection
16+
@usableFromInline internal
17+
let app:Application
18+
19+
@inlinable internal
20+
init(http2:HTTP2Client.Connection, app:Application)
21+
{
22+
self.http2 = http2
23+
self.app = app
24+
}
25+
}
26+
}
27+
extension GitHubClient<GitHubOAuth.API>.Connection
28+
{
29+
@inlinable public
30+
func get<Response>(_:Response.Type = Response.self,
31+
from endpoint:String,
32+
with token:String? = nil) async throws -> Response where Response:JSONDecodable
33+
{
34+
var endpoint:String = endpoint
35+
var status:UInt? = nil
36+
37+
following:
38+
for _:Int in 0 ... 1
39+
{
40+
var request:HPACKHeaders =
41+
[
42+
":method": "GET",
43+
":scheme": "https",
44+
":authority": "api.github.com",
45+
":path": endpoint,
46+
47+
// GitHub will reject the API request if the user-agent is not set.
48+
"user-agent": self.app.agent,
49+
"accept": "application/vnd.github+json"
50+
]
51+
if let token:String
52+
{
53+
request.add(name: "authorization", value: "Bearer \(token)")
54+
}
55+
else if
56+
let oauth:GitHubOAuth = self.app.oauth
57+
{
58+
let credentials:String = "\(oauth.client):\(oauth.secret)"
59+
request.add(name: "authorization",
60+
value: "Basic \(Base64.encode(credentials.utf8))")
61+
}
62+
63+
let response:HTTP2Client.Facet = try await self.http2.fetch(request)
64+
65+
// TODO: support If-None-Match
66+
switch response.status
67+
{
68+
case 200?:
69+
var json:JSON = .init(utf8: [])
70+
for buffer:ByteBuffer in response.buffers
71+
{
72+
json.utf8 += buffer.readableBytesView
73+
}
74+
75+
return try json.decode()
76+
77+
case 301?:
78+
if let location:String = response.headers?["location"].first
79+
{
80+
endpoint = String.init(location.trimmingPrefix("https://api.github.com"))
81+
continue following
82+
}
83+
84+
case 403?:
85+
if let second:String = response.headers?["x-ratelimit-reset"].first,
86+
let second:Int64 = .init(second)
87+
{
88+
throw GitHubClient<GitHubOAuth.API>.RateLimitError.init(
89+
until: .second(second))
90+
}
91+
92+
case _:
93+
break
94+
}
95+
96+
status = response.status
97+
break
98+
}
99+
100+
throw GitHubClient<GitHubOAuth.API>.StatusError.init(code: status)
101+
}
102+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import GitHubAPI
2+
import UnixTime
3+
4+
extension GitHubClient
5+
{
6+
@frozen public
7+
struct RateLimitError:GitHubRateLimitError, Equatable, Sendable
8+
{
9+
public
10+
let until:UnixTime
11+
12+
@inlinable internal
13+
init(until:UnixTime)
14+
{
15+
self.until = until
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)