Skip to content

Commit a25ce6e

Browse files
authored
Added additional Commit Discussion methods and fixed URL construction. (#359)
* Mods ti fix issue related to commit ID vs. commit SHA and commit discussion URL corrections (#358).
1 parent 18e3d63 commit a25ce6e

File tree

3 files changed

+197
-27
lines changed

3 files changed

+197
-27
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To utilize GitLab4J™ API in your Java project, simply add the following de
1212
```java
1313
dependencies {
1414
...
15-
compile group: 'org.gitlab4j', name: 'gitlab4j-api', version: '4.11.1'
15+
compile group: 'org.gitlab4j', name: 'gitlab4j-api', version: '4.11.2'
1616
}
1717
```
1818

@@ -23,7 +23,7 @@ dependencies {
2323
<dependency>
2424
<groupId>org.gitlab4j</groupId>
2525
<artifactId>gitlab4j-api</artifactId>
26-
<version>4.11.1</version>
26+
<version>4.11.2</version>
2727
</dependency>
2828
```
2929

src/main/java/org/gitlab4j/api/DiscussionsApi.java

Lines changed: 189 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import java.util.Date;
44
import java.util.List;
5+
import java.util.Optional;
56
import java.util.stream.Stream;
67

78
import javax.ws.rs.core.GenericType;
89
import javax.ws.rs.core.Response;
910

1011
import org.gitlab4j.api.models.Discussion;
12+
import org.gitlab4j.api.models.Note;
1113
import org.gitlab4j.api.models.Position;
1214

1315
/**
@@ -20,7 +22,6 @@ public DiscussionsApi(GitLabApi gitLabApi) {
2022
super(gitLabApi);
2123
}
2224

23-
2425
/**
2526
* Get a list of all discussions for the specified issue.
2627
*
@@ -347,7 +348,7 @@ public Discussion createMergeRequestDiscussion(Object projectIdOrPath, Integer m
347348
* @throws GitLabApiException if any exception occurs during execution
348349
*/
349350
public Discussion resolveMergeRequestDiscussion(Object projectIdOrPath, Integer mergeRequestIid,
350-
Integer discussionId, Boolean resolved) throws GitLabApiException {
351+
String discussionId, Boolean resolved) throws GitLabApiException {
351352
GitLabApiForm formData = new GitLabApiForm().withParam("resolved", resolved, true);
352353
Response response = put(Response.Status.OK, formData.asMap(),
353354
"projects", getProjectIdOrPath(projectIdOrPath), "merge_requests", mergeRequestIid, "discussions");
@@ -366,75 +367,243 @@ public Discussion resolveMergeRequestDiscussion(Object projectIdOrPath, Integer
366367
* @throws GitLabApiException if any exception occurs during execution
367368
*/
368369
public void deleteMergeRequestDiscussionNote(Object projectIdOrPath, Integer mergeRequestIid,
369-
Integer discussionId, Integer noteId) throws GitLabApiException {
370+
String discussionId, Integer noteId) throws GitLabApiException {
370371
delete(Response.Status.OK, null, "projects", getProjectIdOrPath(projectIdOrPath),
371372
"merge_requests", mergeRequestIid, "discussions", noteId);
372373
}
373374

374375
/**
375376
* Get a list of all discussions for the specified commit.
376377
*
377-
* <pre><code>GitLab Endpoint: GET /projects/:id/commits/:commit_id/discussions</code></pre>
378+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions</code></pre>
378379
*
379380
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
380-
* @param commitId the internal ID of the commit
381+
* @param commitSha the SHA of the commit to get discussions for
381382
* @return a list containing all the discussions for the specified commit
382383
* @throws GitLabApiException if any exception occurs during execution
383384
*/
384-
public List<Discussion> getCommitDiscussions(Object projectIdOrPath, Integer commitId) throws GitLabApiException {
385-
Pager<Discussion> pager = getCommitDiscussionsPager(projectIdOrPath, commitId, getDefaultPerPage());
385+
public List<Discussion> getCommitDiscussions(Object projectIdOrPath, String commitSha) throws GitLabApiException {
386+
Pager<Discussion> pager = getCommitDiscussionsPager(projectIdOrPath, commitSha, getDefaultPerPage());
386387
return (pager.all());
387388
}
388389

389390
/**
390391
* Get a list of discussions for the specified commit.
391392
*
392-
* <pre><code>GitLab Endpoint: GET /projects/:id/commits/:commit_id/discussions</code></pre>
393+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions</code></pre>
393394
*
394395
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
395-
* @param commitId the internal ID of the commit
396+
* @param commitSha the SHA of the commit to get discussions for
396397
* @param maxItems the maximum number of Discussion instances to get, if &lt; 1 will fetch all Discussion instances for the commit
397398
* @return a list containing the discussions for the specified commit
398399
* @throws GitLabApiException if any exception occurs during execution
399400
*/
400-
public List<Discussion> getCommitDiscussions(Object projectIdOrPath, Integer commitId, int maxItems) throws GitLabApiException {
401+
public List<Discussion> getCommitDiscussions(Object projectIdOrPath, String commitSha, int maxItems) throws GitLabApiException {
401402
if (maxItems < 1) {
402-
return (getCommitDiscussions(projectIdOrPath, commitId));
403+
return (getCommitDiscussions(projectIdOrPath, commitSha));
403404
} else {
404405
Response response = get(Response.Status.OK, getPerPageQueryParam(maxItems),
405-
"projects", getProjectIdOrPath(projectIdOrPath), "commits", commitId, "discussions");
406+
"projects", getProjectIdOrPath(projectIdOrPath), "repository", "commits", commitSha, "discussions");
406407
return (response.readEntity(new GenericType<List<Discussion>>() {}));
407408
}
408409
}
409410

410411
/**
411412
* Get a Pager of Discussion instances for the specified commit.
412413
*
413-
* <pre><code>GitLab Endpoint: GET /projects/:id/commits/:commit_id/discussions</code></pre>
414+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions</code></pre>
414415
*
415416
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
416-
* @param commitId the internal ID of the commit
417+
* @param commitSha the SHA of the commit to get discussions for
417418
* @param itemsPerPage the number of Discussion instances that will be fetched per page
418419
* @return a Pager containing the Discussion instances for the specified commit
419420
* @throws GitLabApiException if any exception occurs during execution
420421
*/
421-
public Pager<Discussion> getCommitDiscussionsPager(Object projectIdOrPath, Integer commitId, int itemsPerPage) throws GitLabApiException {
422+
public Pager<Discussion> getCommitDiscussionsPager(Object projectIdOrPath, String commitSha, int itemsPerPage) throws GitLabApiException {
422423
return (new Pager<Discussion>(this, Discussion.class, itemsPerPage, null,
423-
"projects", getProjectIdOrPath(projectIdOrPath), "commits", commitId, "discussions"));
424+
"projects", getProjectIdOrPath(projectIdOrPath), "repository", "commits", commitSha, "discussions"));
424425
}
425426

426427
/**
427428
* Get a Stream of Discussion instances for the specified commit.
428429
*
429-
* <pre><code>GitLab Endpoint: GET /projects/:id/commits/:commit_id/discussions</code></pre>
430+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions</code></pre>
430431
*
431432
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
432-
* @param commitId the internal ID of the commit
433+
* @param commitSha the SHA of the commit to get discussions for
433434
* @return a Stream instance containing the Discussion instances for the specified commit
434435
* @throws GitLabApiException if any exception occurs during execution
435436
*/
436-
public Stream<Discussion> getCommitDiscussionsStream(Object projectIdOrPath, Integer commitId) throws GitLabApiException {
437-
Pager<Discussion> pager = getCommitDiscussionsPager(projectIdOrPath, commitId, getDefaultPerPage());
437+
public Stream<Discussion> getCommitDiscussionsStream(Object projectIdOrPath, String commitSha) throws GitLabApiException {
438+
Pager<Discussion> pager = getCommitDiscussionsPager(projectIdOrPath, commitSha, getDefaultPerPage());
438439
return (pager.stream());
439440
}
441+
442+
/**
443+
* Get a single discussion for the specified commit.
444+
*
445+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id</code></pre>
446+
*
447+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
448+
* @param commitSha the SHA of the commit to get discussions for
449+
* @param discussionId the ID of the discussion
450+
* @return the Discussion instance specified by discussionId for the specified commit
451+
* @throws GitLabApiException if any exception occurs during execution
452+
*/
453+
public Discussion getCommitDiscussion(Object projectIdOrPath, String commitSha, String discussionId) throws GitLabApiException {
454+
Response response = get(Response.Status.OK, null,
455+
"projects", getProjectIdOrPath(projectIdOrPath), "repository", "commits", commitSha, "discussions", discussionId);
456+
return (response.readEntity(Discussion.class));
457+
}
458+
459+
/**
460+
* Get an Optional instance of a single discussion for the specified commit.
461+
*
462+
* <pre><code>GitLab Endpoint: GET /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id</code></pre>
463+
*
464+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
465+
* @param commitSha the SHA of the commit to get discussions for
466+
* @param discussionId the ID of the discussion
467+
* @return an Optional instance with the specified Discussion instance as a value
468+
*/
469+
public Optional<Discussion> getOptionalCommitDiscussion(Object projectIdOrPath, String commitSha, String discussionId) {
470+
try {
471+
return (Optional.ofNullable(getCommitDiscussion(projectIdOrPath, commitSha, discussionId)));
472+
} catch (GitLabApiException glae) {
473+
return (GitLabApi.createOptionalFromException(glae));
474+
}
475+
}
476+
477+
/**
478+
* Creates a new discussion to a single project commit. This is similar to creating
479+
* a note but other comments (replies) can be added to it later.
480+
*
481+
* <pre><code>GitLab Endpoint: POST /projects/:id/repository/commits/:commit_sha/discussions</code></pre>
482+
*
483+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
484+
* @param commitSha the commit SHA to create the discussion for
485+
* @param body the content of a discussion
486+
* @param createdAt date the discussion was created (requires admin or project/group owner rights)
487+
* @param positionHash position when creating a diff note
488+
* @param position a Position instance holding the position attributes
489+
* @return a Discussion instance containing the newly created discussion
490+
* @throws GitLabApiException if any exception occurs during execution
491+
*/
492+
public Discussion createCommitDiscussion(Object projectIdOrPath, String commitSha,
493+
String body, Date createdAt, String positionHash, Position position) throws GitLabApiException {
494+
495+
if (position == null) {
496+
throw new GitLabApiException("position instance can not be null");
497+
}
498+
499+
GitLabApiForm formData = new GitLabApiForm()
500+
.withParam("body", body, true)
501+
.withParam("created_at", createdAt)
502+
.withParam("position", positionHash)
503+
.withParam("position[base_sha]", position.getBaseSha(), true)
504+
.withParam("position[start_sha]", position.getStartSha(), true)
505+
.withParam("position[head_sha]", position.getHeadSha(), true)
506+
.withParam("position[position_type]", position.getPositionType(), true)
507+
.withParam("position[new_path]", position.getNewPath())
508+
.withParam("position[new_line]", position.getNewLine())
509+
.withParam("position[old_path]", position.getOldPath())
510+
.withParam("position[old_line]", position.getOldLine())
511+
.withParam("position[width]", position.getWidth())
512+
.withParam("position[height]", position.getHeight())
513+
.withParam("position[x]", position.getX())
514+
.withParam("position[y]", position.getY());
515+
516+
Response response = post(Response.Status.CREATED, formData,
517+
"projects", getProjectIdOrPath(projectIdOrPath), "repository", "commits", commitSha, "discussions");
518+
return (response.readEntity(Discussion.class));
519+
}
520+
521+
/**
522+
* Adds a note to an existing commit discussion.
523+
*
524+
* <pre><code>GitLab Endpoint: POST /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id/notes</code></pre>
525+
*
526+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
527+
* @param commitSha the commit SHA to create the discussion for
528+
* @param discussionId the ID of a discussion
529+
* @param body the content of a discussion
530+
* @param createdAt date the discussion was created (requires admin or project/group owner rights)
531+
* @return a Note instance containing the newly created discussion note
532+
* @throws GitLabApiException if any exception occurs during execution
533+
*/
534+
public Note addCommitDiscussionNote(Object projectIdOrPath, String commitSha, String discussionId,
535+
String body, Date createdAt) throws GitLabApiException {
536+
537+
GitLabApiForm formData = new GitLabApiForm()
538+
.withParam("body", body, true)
539+
.withParam("created_at", createdAt);
540+
541+
Response response = post(Response.Status.CREATED, formData,
542+
"projects", getProjectIdOrPath(projectIdOrPath),
543+
"repository", "commits", commitSha, "discussions", discussionId, "notes");
544+
return (response.readEntity(Note.class));
545+
}
546+
547+
/**
548+
* Modify an existing discussion note of a commit.
549+
*
550+
* <pre><code>GitLab Endpoint: PUT /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id/notes</code></pre>
551+
*
552+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
553+
* @param commitSha the commit SHA to delete the discussion from
554+
* @param discussionId the ID of a discussion
555+
* @param noteId the note ID to delete
556+
* @param body the content of a discussion
557+
* @return a Note instance containing the updated discussion note
558+
* @throws GitLabApiException if any exception occurs during execution
559+
*/
560+
public Note modifyCommitDiscussionNote(Object projectIdOrPath,
561+
String commitSha, String discussionId, Integer noteId, String body) throws GitLabApiException {
562+
563+
GitLabApiForm formData = new GitLabApiForm().withParam("body", body, true);
564+
Response response = this.putWithFormData(Response.Status.OK, formData,
565+
"projects", getProjectIdOrPath(projectIdOrPath),
566+
"repository", "commits", commitSha, "discussions", discussionId, "notes", noteId);
567+
return (response.readEntity(Note.class));
568+
}
569+
570+
/**
571+
*Resolve or unresolve an existing discussion note of a commit.
572+
*
573+
* <pre><code>GitLab Endpoint: PUT /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id/notes</code></pre>
574+
*
575+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
576+
* @param commitSha the commit SHA to delete the discussion from
577+
* @param discussionId the ID of a discussion
578+
* @param noteId the note ID to delete
579+
* @param resolved if true will resolve the note, false will unresolve the note
580+
* @return a Note instance containing the updated discussion note
581+
* @throws GitLabApiException if any exception occurs during execution
582+
*/
583+
public Note resolveCommitDiscussionNote(Object projectIdOrPath,
584+
String commitSha, String discussionId, Integer noteId, Boolean resolved) throws GitLabApiException {
585+
586+
GitLabApiForm queryParams = new GitLabApiForm().withParam("resolved", resolved);
587+
Response response = this.put(Response.Status.OK, queryParams.asMap(),
588+
"projects", getProjectIdOrPath(projectIdOrPath),
589+
"repository", "commits", commitSha, "discussions", discussionId, "notes", noteId);
590+
return (response.readEntity(Note.class));
591+
}
592+
593+
/**
594+
* Deletes an existing discussion note of a commit.
595+
*
596+
* <pre><code>GitLab Endpoint: DELETE /projects/:id/repository/commits/:commit_sha/discussions/:discussion_id/notes/:note_id</code></pre>
597+
*
598+
* @param projectIdOrPath projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
599+
* @param commitSha the commit SHA to delete the discussion from
600+
* @param discussionId the ID of a discussion
601+
* @param noteId the note ID to delete
602+
* @throws GitLabApiException if any exception occurs during execution
603+
*/
604+
public void deleteCommitDiscussionNote(Object projectIdOrPath, String commitSha,
605+
String discussionId, Integer noteId) throws GitLabApiException {
606+
delete(Response.Status.OK, null, "projects", getProjectIdOrPath(projectIdOrPath),
607+
"repository", commitSha, "discussions", discussionId, "notes", noteId);
608+
}
440609
}

src/test/java/org/gitlab4j/api/TestCommitDiscussionsApi.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
public class TestCommitDiscussionsApi implements Constants {
2626

27+
private static final String COMMIT_SHA = "abcdef1234567890";
2728
@Mock private GitLabApi gitLabApi;
2829
@Mock private GitLabApiClient gitLabApiClient;
2930
@Spy private FakeResponse response;
@@ -32,36 +33,36 @@ public class TestCommitDiscussionsApi implements Constants {
3233
@Before
3334
public void setUp() throws Exception {
3435
initMocks(this);
35-
response.init(Discussion.class, null, "commit-discussions.json");
36+
response.init(Discussion.class, null, "commit-discussions.json");
3637
when(gitLabApi.getApiClient()).thenReturn(gitLabApiClient);
3738
when(gitLabApiClient.validateSecretToken(any())).thenReturn(true);
3839
when(gitLabApiClient.get(attributeCaptor.capture(), Mockito.<Object>any())).thenReturn(response);
3940
}
4041

4142
@Test
4243
public void testGetCommitDiscussionsByList() throws Exception {
43-
List<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussions(1, 1);
44+
List<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussions(1, COMMIT_SHA);
4445
assertNotNull(discussions);
4546
assertTrue(compareJson(discussions, "commit-discussions.json"));
4647
}
4748

4849
@Test
4950
public void testGetCommitDiscussionsByListWithMaxItems() throws Exception {
50-
List<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussions(1, 1, 20);
51+
List<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussions(1, COMMIT_SHA, 20);
5152
assertNotNull(discussions);
5253
assertTrue(compareJson(discussions, "commit-discussions.json"));
5354
}
5455

5556
@Test
5657
public void testGetCommitDiscussionsByPager() throws Exception {
57-
Pager<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussionsPager(1, 1, 20);
58+
Pager<Discussion> discussions = new DiscussionsApi(gitLabApi).getCommitDiscussionsPager(1, COMMIT_SHA, 20);
5859
assertNotNull(discussions);
5960
assertTrue(compareJson(discussions.all(), "commit-discussions.json"));
6061
}
6162

6263
@Test
6364
public void testGetCommitDiscussionsByStream() throws Exception {
64-
Stream<Discussion> stream = new DiscussionsApi(gitLabApi).getCommitDiscussionsStream(1, 1);
65+
Stream<Discussion> stream = new DiscussionsApi(gitLabApi).getCommitDiscussionsStream(1, COMMIT_SHA);
6566
assertNotNull(stream);
6667
List<Discussion> discussions = stream.collect(Collectors.toList());
6768
assertTrue(compareJson(discussions, "commit-discussions.json"));

0 commit comments

Comments
 (0)