Skip to content

Commit e66b635

Browse files
committed
Merge pull request #166 from satisious/feature/exists
Add ability to check that a file exists in repo branch/commit
2 parents 39dc9b4 + b4f3acd commit e66b635

File tree

6 files changed

+193
-4
lines changed

6 files changed

+193
-4
lines changed

doc/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ APIs:
1515
* [Pull Requests](pull_requests.md)
1616
* [Comments](pull_request/comments.md)
1717
* [Repositories](repos.md)
18+
* [Contents](repo/contents.md)
1819
* [Releases](repo/releases.md)
1920
* [Assets](repo/assets.md)
2021
* [Users](users.md)

doc/repo/contents.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## Repo / Contents API
2+
[Back to the "Repos API"](../repos.md) | [Back to the navigation](../index.md)
3+
4+
### Get a repository's README
5+
6+
```php
7+
$readme = $client->api('repo')->contents()->readme('knp-labs', 'php-github-api', $reference);
8+
```
9+
10+
### Get information about a repository file or directory
11+
12+
```php
13+
$fileInfo = $client->api('repo')->contents()->show('knp-labs', 'php-github-api', $path, $reference);
14+
```
15+
16+
### Check that a file or directory exists in the repository
17+
```php
18+
$fileExists = $client->api('repo')->contents()->exists('knp-labs', 'php-github-api', $path, $reference);
19+
```
20+
21+
### Create a file
22+
```php
23+
$committer = array('name' => 'KnpLabs', 'email' => '[email protected]');
24+
25+
$fileInfo = $client->api('repo')->contents()->create('knp-labs', 'php-github-api', $path, $content, $commitMessage, $branch, $committer);
26+
```
27+
28+
### Update a file
29+
30+
```php
31+
$committer = array('name' => 'KnpLabs', 'email' => '[email protected]');
32+
$oldFile = $client->api('repo')->contents()->show('knp-labs', 'php-github-api', $path, $branch);
33+
34+
$fileInfo = $client->api('repo')->contents()->create('knp-labs', 'php-github-api', $path, $content, $commitMessage, $oldFile['sha'], $branch, $committer);
35+
```
36+
37+
### Remove a file
38+
39+
```php
40+
$committer = array('name' => 'KnpLabs', 'email' => '[email protected]');
41+
$oldFile = $client->api('repo')->contents()->show('knp-labs', 'php-github-api', $path, $branch);
42+
43+
$fileInfo = $client->api('repo')->contents()->rm('knp-labs', 'php-github-api', $path, $commitMessage, $oldFile['sha'], $branch, $committer);
44+
```
45+
46+
### Get repository archive
47+
48+
```php
49+
// @todo Document
50+
```
51+
52+
### Download a file
53+
54+
```php
55+
$fileContent = $client->api('repo')->contents()->download('knp-labs', 'php-github-api', $path, $reference);
56+
```

lib/Github/Api/AbstractApi.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,27 @@ protected function get($path, array $parameters = array(), $requestHeaders = arr
7777
return ResponseMediator::getContent($response);
7878
}
7979

80+
/**
81+
* Send a HEAD request with query parameters
82+
*
83+
* @param string $path Request path.
84+
* @param array $parameters HEAD parameters.
85+
* @param array $requestHeaders Request headers.
86+
* @return \Guzzle\Http\Message\Response
87+
*/
88+
protected function head($path, array $parameters = array(), $requestHeaders = array())
89+
{
90+
if (array_key_exists('ref', $parameters) && is_null($parameters['ref'])) {
91+
unset($parameters['ref']);
92+
}
93+
94+
$response = $this->client->getHttpClient()->request($path, null, 'HEAD', $requestHeaders, array(
95+
'query' => $parameters
96+
));
97+
98+
return $response;
99+
}
100+
80101
/**
81102
* Send a POST request with JSON-encoded parameters.
82103
*
@@ -112,7 +133,6 @@ protected function postRaw($path, $body, $requestHeaders = array())
112133
return ResponseMediator::getContent($response);
113134
}
114135

115-
116136
/**
117137
* Send a PATCH request with JSON-encoded parameters.
118138
*
@@ -131,7 +151,6 @@ protected function patch($path, array $parameters = array(), $requestHeaders = a
131151
return ResponseMediator::getContent($response);
132152
}
133153

134-
135154
/**
136155
* Send a PUT request with JSON-encoded parameters.
137156
*
@@ -150,7 +169,6 @@ protected function put($path, array $parameters = array(), $requestHeaders = arr
150169
return ResponseMediator::getContent($response);
151170
}
152171

153-
154172
/**
155173
* Send a DELETE request with JSON-encoded parameters.
156174
*

lib/Github/Api/Repository/Contents.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Github\Exception\InvalidArgumentException;
77
use Github\Exception\ErrorException;
88
use Github\Exception\MissingArgumentException;
9+
use Github\Exception\TwoFactorAuthenticationRequiredException;
910

1011
/**
1112
* @link http://developer.github.com/v3/repos/contents/
@@ -92,6 +93,40 @@ public function create($username, $repository, $path, $content, $message, $branc
9293
return $this->put($url, $parameters);
9394
}
9495

96+
/**
97+
* Checks that a given path exists in a repository.
98+
*
99+
* @param string $username the user who owns the repository
100+
* @param string $repository the name of the repository
101+
* @param string $path path of file to check
102+
* @param null|string $reference reference to a branch or commit
103+
* @return boolean
104+
*/
105+
public function exists($username, $repository, $path, $reference = null)
106+
{
107+
$url = 'repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents';
108+
109+
if (null !== $path) {
110+
$url .= '/'.rawurlencode($path);
111+
}
112+
113+
try {
114+
$response = $this->head($url, array(
115+
'ref' => $reference
116+
));
117+
118+
if ($response->getStatusCode() != 200) {
119+
return false;
120+
}
121+
} catch (TwoFactorAuthenticationRequiredException $ex) {
122+
throw $ex;
123+
} catch (\Exception $ex) {
124+
return false;
125+
}
126+
127+
return true;
128+
}
129+
95130
/**
96131
* Updates the contents of a file in a repository
97132
* @link http://developer.github.com/v3/repos/contents/#update-a-file

test/Github/Tests/Api/Repository/ContentsTest.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Github\Tests\Api\Repository;
44

55
use Github\Tests\Api\TestCase;
6+
use Github\Exception\TwoFactorAuthenticationRequiredException;
67

78
class ContentsTest extends TestCase
89
{
@@ -38,6 +39,74 @@ public function shouldShowReadme()
3839
$this->assertEquals($expectedValue, $api->readme('KnpLabs', 'php-github-api'));
3940
}
4041

42+
/**
43+
* @test
44+
*/
45+
public function shouldReturnTrueWhenFileExists()
46+
{
47+
$responseMock = $this->getMockBuilder('\Guzzle\Http\Message\Response')
48+
->disableOriginalConstructor()
49+
->getMock();
50+
51+
$responseMock->expects($this->any())
52+
->method('getStatusCode')
53+
->willReturn(200);
54+
55+
$api = $this->getApiMock();
56+
$api->expects($this->once())
57+
->method('head')
58+
->with('repos/KnpLabs/php-github-api/contents/composer.json', array('ref' => null))
59+
->will($this->returnValue($responseMock));
60+
61+
$this->assertEquals(true, $api->exists('KnpLabs', 'php-github-api', 'composer.json'));
62+
}
63+
64+
public function getFailureStubsForExistsTest()
65+
{
66+
$nonOkResponseMock =$this->getGuzzleResponseMock();
67+
68+
$nonOkResponseMock->expects($this->any())
69+
->method('getStatusCode')
70+
->willReturn(403);
71+
72+
return array(
73+
array($this->throwException(new \ErrorException())),
74+
array($this->returnValue($nonOkResponseMock))
75+
);
76+
}
77+
78+
/**
79+
* @test
80+
* @dataProvider getFailureStubsForExistsTest
81+
*/
82+
public function shouldReturnFalseWhenFileIsNotFound(\PHPUnit_Framework_MockObject_Stub $failureStub)
83+
{
84+
$expectedValue = array('some-header' => 'value');
85+
86+
$api = $this->getApiMock();
87+
$api->expects($this->once())
88+
->method('head')
89+
->with('repos/KnpLabs/php-github-api/contents/composer.json', array('ref' => null))
90+
->will($failureStub);
91+
92+
$this->assertFalse($api->exists('KnpLabs', 'php-github-api', 'composer.json'));
93+
}
94+
95+
/**
96+
* @test
97+
* @expectedException \Github\Exception\TwoFactorAuthenticationRequiredException
98+
*/
99+
public function shouldBubbleTwoFactorAuthenticationRequiredExceptionsWhenCheckingFileRequiringAuth()
100+
{
101+
$api = $this->getApiMock();
102+
$api->expects($this->once())
103+
->method('head')
104+
->with('repos/KnpLabs/php-github-api/contents/composer.json', array('ref' => null))
105+
->will($this->throwException(new TwoFactorAuthenticationRequiredException(0)));
106+
107+
$api->exists('KnpLabs', 'php-github-api', 'composer.json');
108+
}
109+
41110
/**
42111
* @test
43112
*/
@@ -246,4 +315,14 @@ protected function getApiClass()
246315
{
247316
return 'Github\Api\Repository\Contents';
248317
}
318+
319+
320+
private function getGuzzleResponseMock()
321+
{
322+
$responseMock = $this->getMockBuilder('\Guzzle\Http\Message\Response')
323+
->disableOriginalConstructor()
324+
->getMock();
325+
326+
return $responseMock;
327+
}
249328
}

test/Github/Tests/Api/TestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ protected function getApiMock()
1919
$client->setHttpClient($mock);
2020

2121
return $this->getMockBuilder($this->getApiClass())
22-
->setMethods(array('get', 'post', 'postRaw', 'patch', 'delete', 'put'))
22+
->setMethods(array('get', 'post', 'postRaw', 'patch', 'delete', 'put', 'head'))
2323
->setConstructorArgs(array($client))
2424
->getMock();
2525
}

0 commit comments

Comments
 (0)