diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php
index b9f28f59a..2a9ad6912 100644
--- a/src/Composer/Repository/Vcs/GitHubDriver.php
+++ b/src/Composer/Repository/Vcs/GitHubDriver.php
@@ -304,7 +304,12 @@ class GitHubDriver extends VcsDriver
}
if ($rateLimited) {
- $this->io->write('GitHub API limit exhausted. You are already authorized so you will have to wait a while before doing more requests');
+ $rateLimit = $this->getRateLimit($e->getHeaders());
+ $this->io->write(sprintf(
+ 'GitHub API limit (%d calls/hr) is exhausted. You are already authorized so you have to wait until %s before doing more requests',
+ $rateLimit['limit'],
+ $rateLimit['reset']
+ ));
}
throw $e;
@@ -315,6 +320,39 @@ class GitHubDriver extends VcsDriver
}
}
+ /**
+ * Extract ratelimit from response.
+ *
+ * @param array $headers Headers from Composer\Downloader\TransportException.
+ *
+ * @return array Associative array with the keys limit and reset.
+ */
+ protected function getRateLimit(array $headers)
+ {
+ $rateLimit = array(
+ 'limit' => '?',
+ 'reset' => '?',
+ );
+
+ foreach ($headers as $header) {
+ $header = trim($header);
+ if (false === strpos($header, 'X-RateLimit-')) {
+ continue;
+ }
+ list($type, $value) = explode(':', $header, 2);
+ switch ($type) {
+ case 'X-RateLimit-Limit':
+ $rateLimit['limit'] = (int) trim($value);
+ break;
+ case 'X-RateLimit-Reset':
+ $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
+ break;
+ }
+ }
+
+ return $rateLimit;
+ }
+
/**
* Fetch root identifier from GitHub
*