Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To utilize the GitLab API for Java in your project, simply add the following dep
```java
dependencies {
...
compile group: 'org.gitlab4j', name: 'gitlab4j-api', version: '4.8.50'
compile group: 'org.gitlab4j', name: 'gitlab4j-api', version: '4.8.53'
}
```

Expand All @@ -22,7 +22,7 @@ dependencies {
<dependency>
<groupId>org.gitlab4j</groupId>
<artifactId>gitlab4j-api</artifactId>
<version>4.8.50</version>
<version>4.8.53</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>org.gitlab4j</groupId>
<artifactId>gitlab4j-api</artifactId>
<packaging>jar</packaging>
<version>4.8.51-SNAPSHOT</version>
<version>4.8.54-SNAPSHOT</version>
<name>GitLab API Java Client</name>
<description>GitLab API for Java (gitlab4j-api) provides a full featured Java API for working with GitLab repositories via the GitLab REST API.</description>
<url>https://github.com/gmessner/gitlab4j-api</url>
Expand Down
101 changes: 92 additions & 9 deletions src/main/java/org/gitlab4j/api/GitLabApiException.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package org.gitlab4j.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.StatusType;

import org.gitlab4j.api.models.ErrorMessage;
import org.gitlab4j.api.utils.JacksonJson;

import com.fasterxml.jackson.databind.JsonNode;

/**
* This is the exception that will be thrown if any exception occurs while communicating
Expand All @@ -15,6 +25,7 @@ public class GitLabApiException extends Exception {
private StatusType statusInfo;
private int httpStatus;
private String message;
private Map<String, List<String>> validationErrors;

/**
* Create a GitLabApiException instance with the specified message.
Expand All @@ -28,7 +39,7 @@ public GitLabApiException(String message) {

/**
* Create a GitLabApiException instance based on the ClientResponse.
*
*
* @param response the JAX-RS response that caused the exception
*/
public GitLabApiException(Response response) {
Expand All @@ -38,10 +49,60 @@ public GitLabApiException(Response response) {
httpStatus = response.getStatus();

if (response.hasEntity()) {

try {

ErrorMessage errorMessage = response.readEntity(ErrorMessage.class);
message = errorMessage.getMessage();
String message = response.readEntity(String.class);
this.message = message;

// Determine what is in the content of the response and process it accordingly
MediaType mediaType = response.getMediaType();
if (mediaType != null && "json".equals(mediaType.getSubtype())) {

JsonNode json = JacksonJson.toJsonNode(message);

// First see if it is a "message", if so it is either a simple message,
// or a Map<String, List<String>> of validation errors
JsonNode jsonMessage = json.get("message");
if (jsonMessage != null) {

// If the node is an object, then it is validation errors
if (jsonMessage.isObject()) {

StringBuilder buf = new StringBuilder();
validationErrors = new HashMap<>();
Iterator<Entry<String, JsonNode>> fields = jsonMessage.fields();
while(fields.hasNext()) {

Entry<String, JsonNode> field = fields.next();
String fieldName = field.getKey();
List<String> values = new ArrayList<>();
validationErrors.put(fieldName, values);
for (JsonNode value : field.getValue()) {
values.add(value.asText());
}

if (values.size() > 0) {
buf.append((buf.length() > 0 ? ", " : "")).append(fieldName);
}
}

if (buf.length() > 0) {
this.message = "The following fields have validation errors: " + buf.toString();
}

} else {
this.message = jsonMessage.asText();
}

} else {

JsonNode jsonError = json.get("error");
if (jsonError != null) {
this.message = jsonError.asText();
}
}
}

} catch (Exception ignore) {
}
Expand All @@ -50,7 +111,7 @@ public GitLabApiException(Response response) {

/**
* Create a GitLabApiException instance based on the exception.
*
*
* @param e the Exception to wrap
*/
public GitLabApiException(Exception e) {
Expand All @@ -60,7 +121,7 @@ public GitLabApiException(Exception e) {

/**
* Get the message associated with the exception.
*
*
* @return the message associated with the exception
*/
@Override
Expand All @@ -71,7 +132,7 @@ public final String getMessage() {
/**
* Returns the HTTP status reason message, returns null if the
* causing error was not an HTTP related exception.
*
*
* @return the HTTP status reason message
*/
public final String getReason() {
Expand All @@ -80,11 +141,33 @@ public final String getReason() {

/**
* Returns the HTTP status code that was the cause of the exception. returns 0 if the
* causing error was not an HTTP related exception.
*
* causing error was not an HTTP related exception
*
* @return the HTTP status code, returns 0 if the causing error was not an HTTP related exception
*/
public final int getHttpStatus() {
return (httpStatus);
}

/**
* Returns true if this GitLabApiException was caused by validation errors on the GitLab server,
* otherwise returns false.
*
* @return true if this GitLabApiException was caused by validation errors on the GitLab server,
* otherwise returns false
*/
public boolean hasValidationErrors() {
return (validationErrors != null);
}

/**
* Returns a Map&lt;String, List&lt;String&gt;&gt; instance containing validation errors if this GitLabApiException
* was caused by validation errors on the GitLab server, otherwise returns null.
*
* @return a Map&lt;String, List&lt;String&gt;&gt; instance containing validation errors if this GitLabApiException
* was caused by validation errors on the GitLab server, otherwise returns null
*/
public Map<String, List<String>> getValidationErrors() {
return (validationErrors);
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/gitlab4j/api/GroupApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public Group addGroup(Group group) throws GitLabApiException {
.withParam("name", group.getName())
.withParam("path", group.getPath())
.withParam("description", group.getDescription())
.withParam("visibility", group.getDescription())
.withParam("visibility", group.getVisibility())
.withParam("lfs_enabled", group.getLfsEnabled())
.withParam("request_access_enabled", group.getRequestAccessEnabled())
.withParam("parent_id", isApiVersion(ApiVersion.V3) ? null : group.getParentId());
Expand Down
49 changes: 49 additions & 0 deletions src/main/java/org/gitlab4j/api/IssuesApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.gitlab4j.api.models.Duration;
import org.gitlab4j.api.models.Issue;
import org.gitlab4j.api.models.IssueFilter;
import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.TimeStats;
import org.gitlab4j.api.utils.DurationUtils;

Expand Down Expand Up @@ -621,4 +622,52 @@ public Optional<TimeStats> getOptionalTimeTrackingStats(Integer projectId, Integ
return (GitLabApi.createOptionalFromException(glae));
}
}

/**
* Get list containing all the merge requests that will close issue when merged.
*
* GET /projects/:id/issues/:issue_iid/closed_by
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param issueIid the internal ID of a project's issue
* @return a List containing all the merge requests what will close the issue when merged.
* @throws GitLabApiException if any exception occurs
*/
public List<MergeRequest> getClosedByMergeRequests(Object projectIdOrPath, Integer issueIid) throws GitLabApiException {
return (getClosedByMergeRequests(projectIdOrPath, issueIid, 1, getDefaultPerPage()));
}

/**
* Get list containing all the merge requests that will close issue when merged.
*
* GET /projects/:id/issues/:issue_iid/closed_by
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param issueIid the internal ID of a project's issue
* @param page the page to get
* @param perPage the number of issues per page
* @return a List containing all the merge requests what will close the issue when merged.
* @throws GitLabApiException if any exception occurs
*/
public List<MergeRequest> getClosedByMergeRequests(Object projectIdOrPath, Integer issueIid, int page, int perPage) throws GitLabApiException {
Response response = get(Response.Status.OK, getPageQueryParams(page, perPage),
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "closed_by");
return (response.readEntity(new GenericType<List<MergeRequest>>() { }));
}

/**
* Get a Pager containing all the merge requests that will close issue when merged.
*
* GET /projects/:id/issues/:issue_iid/closed_by
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param issueIid the internal ID of a project's issue
* @param itemsPerPage the number of Issue instances that will be fetched per page
* @return a Pager containing all the issues that would be closed by merging the provided merge request
* @throws GitLabApiException if any exception occurs
*/
public Pager<MergeRequest> getClosedByMergeRequests(Object projectIdOrPath, Integer issueIid, int itemsPerPage) throws GitLabApiException {
return new Pager<MergeRequest>(this, MergeRequest.class, itemsPerPage, null,
"projects", getProjectIdOrPath(projectIdOrPath), "issues", issueIid, "closed_by");
}
}
64 changes: 57 additions & 7 deletions src/main/java/org/gitlab4j/api/MergeRequestApi.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package org.gitlab4j.api;

import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.MergeRequestFilter;
import org.gitlab4j.api.models.Participant;
import java.util.List;
import java.util.Optional;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Optional;

import org.gitlab4j.api.GitLabApi.ApiVersion;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.Issue;
import org.gitlab4j.api.models.MergeRequest;
import org.gitlab4j.api.models.MergeRequestFilter;
import org.gitlab4j.api.models.Participant;

/**
* This class implements the client side API for the GitLab merge request calls.
Expand Down Expand Up @@ -785,4 +787,52 @@ public List<Participant> getParticipants(Integer projectId, Integer mergeRequest
public Pager<Participant> getParticipants(Integer projectId, Integer mergeRequestIid, int itemsPerPage) throws GitLabApiException {
return new Pager<Participant>(this, Participant.class, itemsPerPage, null, "projects", projectId, "merge_requests", mergeRequestIid, "participants");
}

/**
* Get list containing all the issues that would be closed by merging the provided merge requestt.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/merge_requests/:merge_request_iid/closes_issues</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param mergeRequestIid the IID of the merge request to get the closes issues for
* @return a List containing all the issues that would be closed by merging the provided merge request
* @throws GitLabApiException if any exception occurs
*/
public List<Issue> getClosesIssues(Object projectIdOrPath, Integer mergeRequestIid) throws GitLabApiException {
return (getClosesIssues(projectIdOrPath, mergeRequestIid, 1, getDefaultPerPage()));
}

/**
* Get list containing all the issues that would be closed by merging the provided merge request.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/merge_requests/:merge_request_iid/closes_issues</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param mergeRequestIid the IID of the merge request to get the closes issues for
* @param page the page to get
* @param perPage the number of issues per page
* @return a List containing all the issues that would be closed by merging the provided merge request
* @throws GitLabApiException if any exception occurs
*/
public List<Issue> getClosesIssues(Object projectIdOrPath, Integer mergeRequestIid, int page, int perPage) throws GitLabApiException {
Response response = get(Response.Status.OK, getPageQueryParams(page, perPage),
"projects", getProjectIdOrPath(projectIdOrPath), "merge_requests", mergeRequestIid, "closes_issues");
return (response.readEntity(new GenericType<List<Issue>>() { }));
}

/**
* Get a Pager containing all the issues that would be closed by merging the provided merge request.
*
* <pre><code>GitLab Endpoint: GET /projects/:id/merge_requests/:merge_request_iid/closes_issues</code></pre>
*
* @param projectIdOrPath id, path of the project, or a Project instance holding the project ID or path
* @param mergeRequestIid the IID of the merge request to get the closes issues for
* @param itemsPerPage the number of Issue instances that will be fetched per page
* @return a Pager containing all the issues that would be closed by merging the provided merge request
* @throws GitLabApiException if any exception occurs
*/
public Pager<Issue> getClosesIssues(Object projectIdOrPath, Integer mergeRequestIid, int itemsPerPage) throws GitLabApiException {
return new Pager<Issue>(this, Issue.class, itemsPerPage, null,
"projects", getProjectIdOrPath(projectIdOrPath), "merge_requests", mergeRequestIid, "closes_issues");
}
}
11 changes: 9 additions & 2 deletions src/main/java/org/gitlab4j/api/ProjectApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,8 @@ public Project createProject(Project project) throws GitLabApiException {
* repositoryStorage (optional) - Which storage shard the repository is on. Available only to admins
* approvalsBeforeMerge (optional) - How many approvers should approve merge request by default
* printingMergeRequestLinkEnabled (optional) - Show link to create/view merge request when pushing from the command line
* resolveOutdatedDiffDiscussions (optional) - Automatically resolve merge request diffs discussions on lines changed with a push
* initialize_with_readme (optional) - Initialize project with README file
*
* @param project the Project instance with the configuration for the new project
* @param importUrl the URL to import the repository from
Expand Down Expand Up @@ -696,7 +698,9 @@ public Project createProject(Project project, String importUrl) throws GitLabApi
.withParam("repository_storage", project.getRepositoryStorage())
.withParam("approvals_before_merge", project.getApprovalsBeforeMerge())
.withParam("import_url", importUrl)
.withParam("printing_merge_request_link_enabled", project.getPrintingMergeRequestLinkEnabled());
.withParam("printing_merge_request_link_enabled", project.getPrintingMergeRequestLinkEnabled())
.withParam("resolve_outdated_diff_discussions", project.getResolveOutdatedDiffDiscussions())
.withParam("initialize_with_readme", project.getInitializeWithReadme());

if (isApiVersion(ApiVersion.V3)) {
boolean isPublic = (project.getPublic() != null ? project.getPublic() : project.getVisibility() == Visibility.PUBLIC);
Expand Down Expand Up @@ -889,12 +893,14 @@ public Project createProject(String name, Integer namespaceId, String descriptio
* repositoryStorage (optional) - Which storage shard the repository is on. Available only to admins
* approvalsBeforeMerge (optional) - How many approvers should approve merge request by default
* printingMergeRequestLinkEnabled (optional) - Show link to create/view merge request when pushing from the command line
* resolveOutdatedDiffDiscussions (optional) - Automatically resolve merge request diffs discussions on lines changed with a push
*
* NOTE: The following parameters specified by the GitLab API edit project are not supported:
* import_url
* tag_list array
* avatar
* ci_config_path
* initialize_with_readme
*
* @param project the Project instance with the configuration for the new project
* @return a Project instance with the newly updated project info
Expand Down Expand Up @@ -936,7 +942,8 @@ public Project updateProject(Project project) throws GitLabApiException {
.withParam("request_access_enabled", project.getRequestAccessEnabled())
.withParam("repository_storage", project.getRepositoryStorage())
.withParam("approvals_before_merge", project.getApprovalsBeforeMerge())
.withParam("printing_merge_request_link_enabled", project.getPrintingMergeRequestLinkEnabled());
.withParam("printing_merge_request_link_enabled", project.getPrintingMergeRequestLinkEnabled())
.withParam("resolve_outdated_diff_discussions", project.getResolveOutdatedDiffDiscussions());

if (isApiVersion(ApiVersion.V3)) {
formData.withParam("visibility_level", project.getVisibilityLevel());
Expand Down
Loading