/
GithubAliasResolver.php
117 lines (94 loc) · 3.36 KB
/
GithubAliasResolver.php
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
<?php declare(strict_types=1);
/*
* This file is part of Phive.
*
* Copyright (c) Arne Blankerts <arne@blankerts.de>, Sebastian Heuer <sebastian@phpeople.de> and contributors
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace PharIo\Phive;
use function explode;
use function sprintf;
use function strpos;
class GithubAliasResolver extends AbstractRequestedPharResolver {
/** @var FileDownloader */
private $fileDownloader;
/** @var null|RateLimit */
private $rateLimit;
/** @var HttpClient */
private $httpClient;
/** @var Cli\Output */
private $output;
public function __construct(HttpClient $httpClient, FileDownloader $fileDownloader, Cli\Output $output) {
$this->fileDownloader = $fileDownloader;
$this->httpClient = $httpClient;
$this->output = $output;
}
public function resolve(RequestedPhar $requestedPhar): SourceRepository {
if (!$requestedPhar->hasAlias()) {
return $this->tryNext($requestedPhar);
}
$name = $requestedPhar->getAlias()->asString();
if (strpos($name, '/') === false) {
return $this->tryNext($requestedPhar);
}
try {
return $this->localResolve($name);
} catch (DownloadFailedException $e) {
return $this->tryNext($requestedPhar);
} catch (GithubAliasResolverException $e) {
$this->output->writeWarning(
sprintf('GitHub API Rate Limit exceeded - cannot resolve "%s"', $name)
);
return $this->tryNext($requestedPhar);
}
}
private function localResolve(string $name): GithubRepository {
[$username, $project] = explode('/', $name);
$url = new Url(
sprintf('https://api.github.com/repos/%s/%s/releases?per_page=100', $username, $project)
);
$this->ensureWithinRateLimit();
try {
$file = $this->fileDownloader->download($url);
} catch (DownloadFailedException $e) {
$this->updateRateLimit($this->rateLimit);
throw $e;
}
return new GithubRepository(
new JsonData($file->getContent())
);
}
/**
* @throws GithubAliasResolverException
*
* @psalm-assert !null $this->rateLimit
*/
private function ensureWithinRateLimit(): void {
$this->initRateLimit();
if ($this->rateLimit->getRemaining() === 0) {
throw new GithubAliasResolverException('GitHub API over rate limit');
}
}
/** @psalm-assert !null $this->rateLimit */
private function initRateLimit(): void {
if ($this->rateLimit !== null) {
return;
}
$response = $this->httpClient->get(new Url('https://api.github.com/rate_limit'));
$this->rateLimit = $response->getRateLimit();
}
private function updateRateLimit(RateLimit $previousRateLimit): void {
if ($this->fileDownloader->hasRateLimit()) {
$this->rateLimit = $this->fileDownloader->getRateLimit();
return;
}
$this->rateLimit = new RateLimit(
$previousRateLimit->getLimit(),
$previousRateLimit->getRemaining() - 1,
$previousRateLimit->getResetTime()
);
}
}