diff --git a/src/main/java/org/gitlab4j/api/GitLabApi.java b/src/main/java/org/gitlab4j/api/GitLabApi.java index c03defb7b..17ffc22c3 100644 --- a/src/main/java/org/gitlab4j/api/GitLabApi.java +++ b/src/main/java/org/gitlab4j/api/GitLabApi.java @@ -96,6 +96,7 @@ public String getApiNamespace() { private SystemHooksApi systemHooksApi; private TagsApi tagsApi; private TodosApi todosApi; + private TopicsApi topicsApi; private UserApi userApi; private WikisApi wikisApi; private KeysApi keysApi; @@ -1463,7 +1464,7 @@ public ReleaseLinksApi getReleaseLinksApi() { return releaseLinksApi; } - + /** * Gets the ReleasesApi instance owned by this GitLabApi instance. The ReleasesApi is used * to perform all release related API calls. @@ -1654,6 +1655,25 @@ public TagsApi getTagsApi() { return (tagsApi); } + /** + * Gets the TagsApi instance owned by this GitLabApi instance. The TagsApi is used + * to perform all tag and release related API calls. + * + * @return the TagsApi instance owned by this GitLabApi instance + */ + public TopicsApi getTopicsApi() { + + if (topicsApi == null) { + synchronized (this) { + if (topicsApi == null) { + topicsApi = new TopicsApi(this); + } + } + } + + return (topicsApi); + } + /** * Gets the SnippetsApi instance owned by this GitLabApi instance. The SnippetsApi is used * to perform all snippet related API calls. diff --git a/src/main/java/org/gitlab4j/api/GitLabApiClient.java b/src/main/java/org/gitlab4j/api/GitLabApiClient.java index 169e185ce..ea11c8119 100755 --- a/src/main/java/org/gitlab4j/api/GitLabApiClient.java +++ b/src/main/java/org/gitlab4j/api/GitLabApiClient.java @@ -41,6 +41,7 @@ import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.media.multipart.BodyPart; import org.glassfish.jersey.media.multipart.Boundary; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.MultiPart; import org.glassfish.jersey.media.multipart.MultiPartFeature; @@ -264,7 +265,7 @@ public void close() { * * @param logger the Logger instance to log to * @param level the logging level (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST) - * @param maxEntitySize maximum number of entity bytes to be logged. When logging if the maxEntitySize + * @param maxEntityLength maximum number of entity bytes to be logged. When logging if the maxEntitySize * is reached, the entity logging will be truncated at maxEntitySize and "...more..." will be added at * the end of the log entry. If maxEntitySize is <= 0, entity logging will be disabled * @param maskedHeaderNames a list of header names that should have the values masked @@ -691,7 +692,11 @@ protected Response putUpload(String name, File fileToUpload, Object... pathArgs) protected Response putUpload(String name, File fileToUpload, URL url) throws IOException { try (MultiPart multiPart = new FormDataMultiPart()) { - multiPart.bodyPart(new FileDataBodyPart(name, fileToUpload, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + if(fileToUpload == null) { + multiPart.bodyPart(new FormDataBodyPart(name, "", MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } else { + multiPart.bodyPart(new FileDataBodyPart(name, fileToUpload, MediaType.APPLICATION_OCTET_STREAM_TYPE)); + } final Entity> entity = Entity.entity(multiPart, Boundary.addBoundary(multiPart.getMediaType())); return (invocation(url, null).put(entity)); } diff --git a/src/main/java/org/gitlab4j/api/ProjectApi.java b/src/main/java/org/gitlab4j/api/ProjectApi.java index 848f6bdca..45ce7c710 100644 --- a/src/main/java/org/gitlab4j/api/ProjectApi.java +++ b/src/main/java/org/gitlab4j/api/ProjectApi.java @@ -1043,6 +1043,10 @@ public Project createProject(Project project, String importUrl) throws GitLabApi if (project.getTagList() != null && !project.getTagList().isEmpty()) { throw new IllegalArgumentException("GitLab API v3 does not support tag lists when creating projects"); } + + if (project.getTopics() != null && !project.getTopics().isEmpty()) { + throw new IllegalArgumentException("GitLab API v3 does not support topics when creating projects"); + } } else { Visibility visibility = (project.getVisibility() != null ? project.getVisibility() : project.getPublic() == Boolean.TRUE ? Visibility.PUBLIC : null); @@ -1051,6 +1055,10 @@ public Project createProject(Project project, String importUrl) throws GitLabApi if (project.getTagList() != null && !project.getTagList().isEmpty()) { formData.withParam("tag_list", String.join(",", project.getTagList())); } + + if (project.getTopics() != null && !project.getTopics().isEmpty()) { + formData.withParam("topics", String.join(",", project.getTopics())); + } } Response response = post(Response.Status.CREATED, formData, "projects"); @@ -1314,6 +1322,10 @@ public Project updateProject(Project project) throws GitLabApiException { if (project.getTagList() != null && !project.getTagList().isEmpty()) { throw new IllegalArgumentException("GitLab API v3 does not support tag lists when updating projects"); } + + if (project.getTopics() != null && !project.getTopics().isEmpty()) { + throw new IllegalArgumentException("GitLab API v3 does not support topics when updating projects"); + } } else { Visibility visibility = (project.getVisibility() != null ? project.getVisibility() : project.getPublic() == Boolean.TRUE ? Visibility.PUBLIC : null); @@ -1322,6 +1334,10 @@ public Project updateProject(Project project) throws GitLabApiException { if (project.getTagList() != null && !project.getTagList().isEmpty()) { formData.withParam("tag_list", String.join(",", project.getTagList())); } + + if (project.getTopics() != null && !project.getTopics().isEmpty()) { + formData.withParam("topics", String.join(",", project.getTopics())); + } } Response response = putWithFormData(Response.Status.OK, formData, "projects", projectIdentifier); diff --git a/src/main/java/org/gitlab4j/api/TopicsApi.java b/src/main/java/org/gitlab4j/api/TopicsApi.java new file mode 100644 index 000000000..c6d41ca93 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/TopicsApi.java @@ -0,0 +1,193 @@ +package org.gitlab4j.api; + +import org.gitlab4j.api.models.Topic; +import org.gitlab4j.api.models.TopicParams; + +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.File; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +public class TopicsApi extends AbstractApi{ + + public TopicsApi(GitLabApi gitLabApi) { + super(gitLabApi); + } + + /** + *
Get a list of Topics.
+ * + * WARNING: Do not use this method to fetch Topics from https://gitlab.com, + * gitlab.com has many 1,000's of public topics and it will a long time to fetch all of them. + * Instead use {@link #getTopics(int itemsPerPage)} which will return a Pager of Topic instances. + * + *GitLab Endpoint: GET /topics
+ *
+ * @return the list of topics viewable by the authenticated user
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ListGitLab Endpoint: GET /topics
+ *
+ * @param page the page to get
+ * @param perPage the number of Topic instances per page
+ * @return the list of topics
+ * @throws GitLabApiException if any exception occurs
+ */
+ public ListGitLab Endpoint: GET /topics
+ *
+ * @param itemsPerPage the number of Topic instances that will be fetched per page
+ * @return the pager of topics
+ * @throws GitLabApiException if any exception occurs
+ */
+ public PagerGitLab Endpoint: GET /topics
+ *
+ * @return the stream of topics
+ * @throws GitLabApiException if any exception occurs
+ */
+ public StreamGitLab Endpoint: GET /topics/:id
+ *
+ * @param id the topic ID
+ * @return the topic for the specified topic id
+ * @throws GitLabApiException if any exception occurs
+ */
+ public Topic getTopic(Integer id) throws GitLabApiException {
+ Response response = get(Response.Status.OK, null, "topics", id);
+ return (response.readEntity(Topic.class));
+ }
+
+ /**
+ * Get all details of a topic as an Optional instance.
+ *
+ * GitLab Endpoint: GET /topics/:id
+ *
+ * @param id the topic ID
+ * @return the Topic for the specified topic id as an Optional instance
+ */
+ public OptionalGitLab Endpoint: POST /topics
+ *
+ * @param params a TopicParams instance holding the parameters for the topic creation
+ * @return the created Topic instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public Topic createTopic(TopicParams params) throws GitLabApiException {
+ Response response = post(Response.Status.CREATED, params.getForm(true), "topics");
+ return (response.readEntity(Topic.class));
+ }
+
+ /**
+ * Update a project topic.
+ *
+ * GitLab Endpoint: PUT /topics/:id
+ *
+ * @param id the topic id
+ * @param params a TopicParams instance holding the properties to Update
+ * @return the updated Topic instance
+ * @throws GitLabApiException at any exception
+ */
+ public Topic updateTopic(Integer id, TopicParams params) throws GitLabApiException {
+ Response response = putWithFormData(Response.Status.OK,
+ params.getForm(false), "topics", id);
+ return (response.readEntity(Topic.class));
+ }
+
+ /**
+ * Uploads and sets the topic's avatar for the specified topic.
+ *
+ * GitLab Endpoint: PUT /topics/:id
+ *
+ * @param id the topic in the form of an Integer
+ * @param avatarFile the File instance of the avatar file to upload
+ * @return the updated Topic instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public Topic updateTopicAvatar(final Integer id, File avatarFile) throws GitLabApiException {
+ Response response = putUpload(Response.Status.OK, "avatar", avatarFile, "topics", id);
+ return (response.readEntity(Topic.class));
+ }
+
+ /**
+ * Delete the topic's avatar for the specified topic.
+ *
+ * GitLab Endpoint: PUT /topics/:id
+ *
+ * @param id the topic in the form of an Integer
+ * @return the updated Topic instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public Topic deleteTopicAvatar(final Integer id) throws GitLabApiException {
+ Response response = putUpload(Response.Status.OK, "avatar", null, "topics", id);
+ return (response.readEntity(Topic.class));
+ }
+
+ /**
+ * Delete a topic. You must be an administrator to delete a project topic. When you delete a project topic, you also delete the topic assignment for projects.
+ *
+ * GitLab Endpoint: DELETE /topics/:id
+ *
+ * @param id the topic to deleted in the form of an Integer
+ * @throws GitLabApiException if any exception occurs
+ */
+ public void deleteTopic(Integer id) throws GitLabApiException {
+ if(isApiVersion(GitLabApi.ApiVersion.V3)){
+ throw new GitLabApiException("Topics need api v4+");
+ }
+ delete(Response.Status.NO_CONTENT,null, "topics", id);
+ }
+
+ /**
+ * Merge two topics together. You must be an administrator to merge a source topic into a target topic. When you merge topics, you delete the source topic and move all assigned projects to the target topic.
+ *
+ * GitLab Endpoint: POST /topics/merge
+ *
+ * @param sourceTopicId ID of source project topic
+ * @param targetTopicId ID of target project topic
+ * @return the merged Topic instance
+ * @throws GitLabApiException if any exception occurs
+ */
+ public Topic mergeTopics(Integer sourceTopicId, Integer targetTopicId) throws GitLabApiException {
+ Response response = post(Response.Status.OK,new GitLabApiForm().withParam("source_topic_id",sourceTopicId).withParam("target_topic_id",targetTopicId),"topics/merge");
+ return (response.readEntity(Topic.class));
+ }
+}
diff --git a/src/main/java/org/gitlab4j/api/models/Project.java b/src/main/java/org/gitlab4j/api/models/Project.java
index 4533ca9c1..55c9f5748 100644
--- a/src/main/java/org/gitlab4j/api/models/Project.java
+++ b/src/main/java/org/gitlab4j/api/models/Project.java
@@ -80,7 +80,9 @@ public String toString() {
private Boolean snippetsEnabled;
private String sshUrlToRepo;
private Integer starCount;
+
private List