This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathSimpleApiClient.cs
More file actions
148 lines (129 loc) · 4.71 KB
/
Copy pathSimpleApiClient.cs
File metadata and controls
148 lines (129 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Primitives;
using GitHub.Services;
using Octokit;
using GitHub.Extensions;
namespace GitHub.Api
{
public class SimpleApiClient : ISimpleApiClient
{
public HostAddress HostAddress { get; }
public UriString OriginalUrl { get; }
readonly Lazy<IEnterpriseProbe> enterpriseProbe;
readonly Lazy<IWikiProbe> wikiProbe;
static readonly SemaphoreSlim sem = new SemaphoreSlim(1);
Repository repositoryCache = new Repository();
string owner;
bool? isEnterprise;
bool? hasWiki;
public SimpleApiClient(UriString repoUrl, IGitHubClient githubClient,
Lazy<IEnterpriseProbe> enterpriseProbe, Lazy<IWikiProbe> wikiProbe)
{
Guard.ArgumentNotNull(repoUrl, nameof(repoUrl));
Guard.ArgumentNotNull(githubClient, nameof(githubClient));
HostAddress = HostAddress.Create(repoUrl);
OriginalUrl = repoUrl;
Client = githubClient;
this.enterpriseProbe = enterpriseProbe;
this.wikiProbe = wikiProbe;
}
public IGitHubClient Client { get; }
public async Task<Repository> GetRepository()
{
// fast path to avoid locking when the cache has already been set
// once it's been set, it's never going to be touched again, so it's safe
// to read. This way, lock queues will only form once on first load
if (owner != null)
return repositoryCache;
return await GetRepositoryInternal();
}
public bool IsAuthenticated()
{
// this doesn't account for auth revoke on the server but its much faster
// than doing the API hit.
var authType = Client.Connection.Credentials?.AuthenticationType ?? AuthenticationType.Anonymous;
return authType != AuthenticationType.Anonymous;
}
async Task<Repository> GetRepositoryInternal()
{
await sem.WaitAsync();
try
{
if (owner == null)
{
var ownerLogin = OriginalUrl.Owner;
var repositoryName = OriginalUrl.RepositoryName;
if (ownerLogin != null && repositoryName != null)
{
var repo = await Client.Repository.Get(ownerLogin, repositoryName);
if (repo != null)
{
hasWiki = await HasWikiInternal(repo);
isEnterprise = isEnterprise ?? await IsEnterpriseInternal();
repositoryCache = repo;
}
owner = ownerLogin;
}
}
}
// it'll throw if it's private or an enterprise instance requiring authentication
catch (ApiException apiex)
{
if (!HostAddress.IsGitHubDotComUri(OriginalUrl.ToRepositoryUrl()))
isEnterprise = apiex.IsGitHubApiException();
}
catch {}
finally
{
sem.Release();
}
return repositoryCache;
}
public bool HasWiki()
{
return hasWiki.HasValue && hasWiki.Value;
}
public async Task<bool> IsEnterprise()
{
if (!isEnterprise.HasValue)
{
isEnterprise = await IsEnterpriseInternal();
}
return isEnterprise ?? false;
}
async Task<bool> HasWikiInternal(Repository repo)
{
if (repo == null)
return false;
if (!repo.HasWiki)
{
hasWiki = false;
return false;
}
var probe = wikiProbe.Value;
Debug.Assert(probe != null, "Lazy<Wiki> probe is not set, something is wrong.");
#if !DEBUG
if (probe == null)
return false;
#endif
var ret = await probe.ProbeAsync(repo);
return (ret == WikiProbeResult.Ok);
}
async Task<bool> IsEnterpriseInternal()
{
if (HostAddress == HostAddress.GitHubDotComHostAddress)
return false;
var probe = enterpriseProbe.Value;
Debug.Assert(probe != null, "Lazy<Enterprise> probe is not set, something is wrong.");
#if !DEBUG
if (probe == null)
return false;
#endif
var ret = await probe.Probe(HostAddress.WebUri);
return (ret == EnterpriseProbeResult.Ok);
}
}
}