Skip to content

Commit 832fe33

Browse files
authored
1 parent 012a8c3 commit 832fe33

File tree

9 files changed

+344
-0
lines changed

9 files changed

+344
-0
lines changed

src/main/java/com/spotify/github/v3/clients/RepositoryClient.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@
4242
import com.spotify.github.v3.repos.CommitComparison;
4343
import com.spotify.github.v3.repos.CommitItem;
4444
import com.spotify.github.v3.repos.CommitStatus;
45+
import com.spotify.github.v3.repos.CommitWithFolderContent;
4546
import com.spotify.github.v3.repos.Content;
47+
import com.spotify.github.v3.repos.requests.FileCreate;
48+
import com.spotify.github.v3.repos.requests.FileUpdate;
4649
import com.spotify.github.v3.repos.FolderContent;
4750
import com.spotify.github.v3.repos.Languages;
4851
import com.spotify.github.v3.repos.Repository;
@@ -447,6 +450,32 @@ public CompletableFuture<Content> getFileContent(final String path, final String
447450
return github.request(getContentPath(path, "?ref=" + ref), Content.class);
448451
}
449452

453+
/**
454+
* Create a file
455+
*
456+
* @param path path to a file
457+
* @param request file creation request
458+
* @return commit with content
459+
*/
460+
public CompletableFuture<CommitWithFolderContent> createFileContent(final String path, final FileCreate request) {
461+
final String contentPath = getContentPath(path, "");
462+
final String requestBody = github.json().toJsonUnchecked(request);
463+
return github.put(contentPath, requestBody, CommitWithFolderContent.class);
464+
}
465+
466+
/**
467+
* Update file contents
468+
*
469+
* @param path path to a file
470+
* @param request file update request
471+
* @return commit with content
472+
*/
473+
public CompletableFuture<CommitWithFolderContent> updateFileContent(final String path, final FileUpdate request) {
474+
final String contentPath = getContentPath(path, "");
475+
final String requestBody = github.json().toJsonUnchecked(request);
476+
return github.put(contentPath, requestBody, CommitWithFolderContent.class);
477+
}
478+
450479
/**
451480
* Get repository contents of a folder.
452481
*
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*-
2+
* -\-\-
3+
* github-api
4+
* --
5+
* Copyright (C) 2016 - 2023 Spotify AB
6+
* --
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* -/-/-
19+
*/
20+
21+
package com.spotify.github.v3.repos;
22+
23+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
24+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
25+
import com.spotify.github.GithubStyle;
26+
import com.spotify.github.v3.git.Commit;
27+
import org.immutables.value.Value;
28+
29+
@Value.Immutable
30+
@GithubStyle
31+
@JsonSerialize(as = ImmutableCommitWithFolderContent.class)
32+
@JsonDeserialize(as = ImmutableCommitWithFolderContent.class)
33+
public interface CommitWithFolderContent {
34+
35+
/** Repository content resource */
36+
FolderContent content();
37+
38+
/** Commit resource */
39+
Commit commit();
40+
41+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*-
2+
* -\-\-
3+
* github-api
4+
* --
5+
* Copyright (C) 2016 - 2023 Spotify AB
6+
* --
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* -/-/-
19+
*/
20+
21+
package com.spotify.github.v3.repos.requests;
22+
23+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
24+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
25+
import com.spotify.github.GithubStyle;
26+
import org.immutables.value.Value;
27+
28+
import javax.annotation.Nullable;
29+
30+
/**
31+
* Request to create a file.
32+
*/
33+
@Value.Immutable
34+
@GithubStyle
35+
@JsonSerialize(as = ImmutableFileCreate.class)
36+
@JsonDeserialize(as = ImmutableFileCreate.class)
37+
public interface FileCreate {
38+
39+
/** The commit message */
40+
String message();
41+
42+
/** The new file content, using Base64 encoding */
43+
String content();
44+
45+
/** The branch name. Default: the repository’s default branch */
46+
@Nullable
47+
String branch();
48+
49+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*-
2+
* -\-\-
3+
* github-api
4+
* --
5+
* Copyright (C) 2016 - 2023 Spotify AB
6+
* --
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
* -/-/-
19+
*/
20+
21+
package com.spotify.github.v3.repos.requests;
22+
23+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
24+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
25+
import com.spotify.github.GithubStyle;
26+
import org.immutables.value.Value;
27+
28+
import javax.annotation.Nullable;
29+
30+
/**
31+
* Request to update file content.
32+
*/
33+
@Value.Immutable
34+
@GithubStyle
35+
@JsonSerialize(as = ImmutableFileUpdate.class)
36+
@JsonDeserialize(as = ImmutableFileUpdate.class)
37+
public interface FileUpdate {
38+
39+
/** The commit message */
40+
String message();
41+
42+
/** The new file content, using Base64 encoding */
43+
String content();
44+
45+
/** The SHA of the file being replaced. */
46+
String sha();
47+
48+
/** The branch name. Default: the repository’s default branch */
49+
@Nullable
50+
String branch();
51+
52+
}

src/test/java/com/spotify/github/v3/clients/RepositoryClientTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import static org.junit.jupiter.api.Assertions.assertFalse;
4141
import static org.junit.jupiter.api.Assertions.assertTrue;
4242
import static org.mockito.ArgumentMatchers.any;
43+
import static org.mockito.ArgumentMatchers.argThat;
4344
import static org.mockito.ArgumentMatchers.eq;
4445
import static org.mockito.Mockito.mock;
4546
import static org.mockito.Mockito.when;
@@ -56,14 +57,19 @@
5657
import com.spotify.github.v3.repos.CommitComparison;
5758
import com.spotify.github.v3.repos.CommitItem;
5859
import com.spotify.github.v3.repos.CommitStatus;
60+
import com.spotify.github.v3.repos.CommitWithFolderContent;
5961
import com.spotify.github.v3.repos.Content;
6062
import com.spotify.github.v3.repos.FolderContent;
6163
import com.spotify.github.v3.repos.Repository;
6264
import com.spotify.github.v3.repos.RepositoryInvitation;
6365
import com.spotify.github.v3.repos.RepositoryPermission;
6466
import com.spotify.github.v3.repos.RepositoryTest;
6567
import com.spotify.github.v3.repos.Status;
68+
import com.spotify.github.v3.repos.requests.FileCreate;
69+
import com.spotify.github.v3.repos.requests.FileUpdate;
6670
import com.spotify.github.v3.repos.requests.ImmutableAuthenticatedUserRepositoriesFilter;
71+
import com.spotify.github.v3.repos.requests.ImmutableFileCreate;
72+
import com.spotify.github.v3.repos.requests.ImmutableFileUpdate;
6773
import java.io.IOException;
6874
import java.io.InputStream;
6975
import java.nio.charset.StandardCharsets;
@@ -79,6 +85,7 @@
7985
import org.junit.jupiter.api.BeforeEach;
8086
import org.junit.jupiter.api.Test;
8187
import org.mockito.ArgumentCaptor;
88+
import uk.co.datumedge.hamcrest.json.SameJSONAs;
8289

8390
public class RepositoryClientTest {
8491

@@ -294,6 +301,58 @@ public void getFileContent() throws Exception {
294301
assertThat(fileContent.content(), is("encoded content ..."));
295302
}
296303

304+
@Test
305+
public void createFileContent() throws Exception {
306+
String rawFileCreateRequest = getFixture("create-content-request.json");
307+
final CompletableFuture<CommitWithFolderContent> fixture = completedFuture(
308+
json.fromJson(getFixture("create-content-repsonse.json"), CommitWithFolderContent.class)
309+
);
310+
when(github.put(
311+
eq("/repos/someowner/somerepo/contents/test/README.md"),
312+
argThat(body -> SameJSONAs.sameJSONAs(rawFileCreateRequest).matches(body)),
313+
eq(CommitWithFolderContent.class)
314+
)).thenReturn(fixture);
315+
316+
FileCreate fileCreateRequest = ImmutableFileCreate.builder()
317+
.message("my commit message")
318+
.content("encoded content ...")
319+
.build();
320+
321+
final CommitWithFolderContent commitWithFolderContent =
322+
repoClient.createFileContent("test/README.md", fileCreateRequest).get();
323+
assertThat(commitWithFolderContent.commit().message(), is("my commit message"));
324+
assertThat(commitWithFolderContent.content().type(), is("file"));
325+
assertThat(commitWithFolderContent.content().name(), is("README.md"));
326+
assertThat(commitWithFolderContent.content().path(), is("test/README.md"));
327+
}
328+
329+
@Test
330+
public void updateFileContent() throws Exception {
331+
String rawFileUpdateRequest = getFixture("update-content-request.json");
332+
final CompletableFuture<CommitWithFolderContent> fixture = completedFuture(
333+
json.fromJson(getFixture("create-content-repsonse.json"), CommitWithFolderContent.class)
334+
);
335+
when(github.put(
336+
eq("/repos/someowner/somerepo/contents/test/README.md"),
337+
argThat(body -> SameJSONAs.sameJSONAs(rawFileUpdateRequest).matches(body)),
338+
eq(CommitWithFolderContent.class)
339+
)).thenReturn(fixture);
340+
341+
FileUpdate fileUpdateRequest = ImmutableFileUpdate.builder()
342+
.message("my commit message")
343+
.content("encoded content ...")
344+
.branch("test-branch")
345+
.sha("12345")
346+
.build();
347+
348+
final CommitWithFolderContent commitWithFolderContent =
349+
repoClient.updateFileContent("test/README.md", fileUpdateRequest).get();
350+
assertThat(commitWithFolderContent.commit().message(), is("my commit message"));
351+
assertThat(commitWithFolderContent.content().type(), is("file"));
352+
assertThat(commitWithFolderContent.content().name(), is("README.md"));
353+
assertThat(commitWithFolderContent.content().path(), is("test/README.md"));
354+
}
355+
297356
@Test
298357
public void getFolderContent() throws Exception {
299358
final CompletableFuture<List<FolderContent>> fixture =
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"content": {
3+
"name": "README.md",
4+
"path": "test/README.md",
5+
"sha": "95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
6+
"size": 9,
7+
"url": "https://api.github.com/repos/someowner/somerepo/contents/test/README.md",
8+
"html_url": "https://github.com/someowner/somerepo/blob/master/test/README.md",
9+
"git_url": "https://api.github.com/repos/someowner/somerepo/git/blobs/95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
10+
"download_url": "https://raw.githubusercontent.com/someowner/HelloWorld/master/test/README.md",
11+
"type": "file",
12+
"_links": {
13+
"self": "https://api.github.com/repos/someowner/somerepo/contents/test/README.md",
14+
"git": "https://api.github.com/repos/someowner/somerepo/git/blobs/95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
15+
"html": "https://github.com/someowner/somerepo/blob/master/test/README.md"
16+
}
17+
},
18+
"commit": {
19+
"sha": "7638417db6d59f3c431d3e1f261cc637155684cd",
20+
"node_id": "MDY6Q29tbWl0NzYzODQxN2RiNmQ1OWYzYzQzMWQzZTFmMjYxY2M2MzcxNTU2ODRjZA==",
21+
"url": "https://api.github.com/repos/someowner/somerepo/git/commits/7638417db6d59f3c431d3e1f261cc637155684cd",
22+
"html_url": "https://github.com/someowner/somerepo/git/commit/7638417db6d59f3c431d3e1f261cc637155684cd",
23+
"author": {
24+
"date": "2014-11-07T22:01:45Z",
25+
"name": "Monalisa Octocat",
26+
"email": "[email protected]"
27+
},
28+
"committer": {
29+
"date": "2014-11-07T22:01:45Z",
30+
"name": "Monalisa Octocat",
31+
"email": "[email protected]"
32+
},
33+
"message": "my commit message",
34+
"tree": {
35+
"url": "https://api.github.com/repos/someowner/somerepo/git/trees/691272480426f78a0138979dd3ce63b77f706feb",
36+
"sha": "691272480426f78a0138979dd3ce63b77f706feb"
37+
},
38+
"parents": [
39+
{
40+
"url": "https://api.github.com/repos/someowner/somerepo/git/commits/1acc419d4d6a9ce985db7be48c6349a0475975b5",
41+
"html_url": "https://github.com/someowner/somerepo/git/commit/1acc419d4d6a9ce985db7be48c6349a0475975b5",
42+
"sha": "1acc419d4d6a9ce985db7be48c6349a0475975b5"
43+
}
44+
],
45+
"verification": {
46+
"verified": false,
47+
"reason": "unsigned",
48+
"signature": null,
49+
"payload": null
50+
}
51+
}
52+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"message": "my commit message",
3+
"content": "encoded content ..."
4+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"content": {
3+
"name": "README.md",
4+
"path": "test/README.md",
5+
"sha": "95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
6+
"size": 9,
7+
"url": "https://api.github.com/repos/someowner/somerepo/contents/test/README.md",
8+
"html_url": "https://github.com/someowner/somerepo/blob/master/test/README.md",
9+
"git_url": "https://api.github.com/repos/someowner/somerepo/git/blobs/95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
10+
"download_url": "https://raw.githubusercontent.com/someowner/HelloWorld/master/test/README.md",
11+
"type": "file",
12+
"_links": {
13+
"self": "https://api.github.com/repos/someowner/somerepo/contents/test/README.md",
14+
"git": "https://api.github.com/repos/someowner/somerepo/git/blobs/95b966ae1c166bd92f8ae7d1c313e738c731dfc3",
15+
"html": "https://github.com/someowner/somerepo/blob/master/test/README.md"
16+
}
17+
},
18+
"commit": {
19+
"sha": "7638417db6d59f3c431d3e1f261cc637155684cd",
20+
"node_id": "MDY6Q29tbWl0NzYzODQxN2RiNmQ1OWYzYzQzMWQzZTFmMjYxY2M2MzcxNTU2ODRjZA==",
21+
"url": "https://api.github.com/repos/someowner/somerepo/git/commits/7638417db6d59f3c431d3e1f261cc637155684cd",
22+
"html_url": "https://github.com/someowner/somerepo/git/commit/7638417db6d59f3c431d3e1f261cc637155684cd",
23+
"author": {
24+
"date": "2014-11-07T22:01:45Z",
25+
"name": "Monalisa Octocat",
26+
"email": "[email protected]"
27+
},
28+
"committer": {
29+
"date": "2014-11-07T22:01:45Z",
30+
"name": "Monalisa Octocat",
31+
"email": "[email protected]"
32+
},
33+
"message": "my commit message",
34+
"tree": {
35+
"url": "https://api.github.com/repos/someowner/somerepo/git/trees/691272480426f78a0138979dd3ce63b77f706feb",
36+
"sha": "691272480426f78a0138979dd3ce63b77f706feb"
37+
},
38+
"parents": [
39+
{
40+
"url": "https://api.github.com/repos/someowner/somerepo/git/commits/1acc419d4d6a9ce985db7be48c6349a0475975b5",
41+
"html_url": "https://github.com/someowner/somerepo/git/commit/1acc419d4d6a9ce985db7be48c6349a0475975b5",
42+
"sha": "1acc419d4d6a9ce985db7be48c6349a0475975b5"
43+
}
44+
],
45+
"verification": {
46+
"verified": false,
47+
"reason": "unsigned",
48+
"signature": null,
49+
"payload": null
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)