diff --git a/src/main/java/org/gitlab4j/api/RepositoryApi.java b/src/main/java/org/gitlab4j/api/RepositoryApi.java index 65d037798b9ca4a05fd8b6f667dd317d23e71c2d..d61f674e2294837286a8c448803c3cdb0c9ae369 100644 --- a/src/main/java/org/gitlab4j/api/RepositoryApi.java +++ b/src/main/java/org/gitlab4j/api/RepositoryApi.java @@ -22,6 +22,7 @@ import org.gitlab4j.api.models.ChangelogPayload; import org.gitlab4j.api.models.Commit; import org.gitlab4j.api.models.CompareResults; import org.gitlab4j.api.models.Contributor; +import org.gitlab4j.api.models.RepositoryArchiveParams; import org.gitlab4j.api.models.TreeItem; import org.gitlab4j.api.utils.FileUtils; @@ -443,7 +444,9 @@ public class RepositoryApi extends AbstractApi { * @return an input stream that can be used to save as a file * or to read the content of the archive * @throws GitLabApiException if any exception occurs + * @deprecated Use {@link #getRepositoryArchive(Object, RepositoryArchiveParams)} */ + @Deprecated public InputStream getRepositoryArchive(Object projectIdOrPath, String sha) throws GitLabApiException { Form formData = new GitLabApiForm().withParam("sha", sha); Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, @@ -451,6 +454,23 @@ public class RepositoryApi extends AbstractApi { return (response.readEntity(InputStream.class)); } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional). + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @return an input stream that can be used to save as a file or to read the content of the archive + * @throws GitLabApiException if any exception occurs + */ + public InputStream getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params) throws GitLabApiException { + GitLabApiForm formData = params.getForm(); + Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, + "projects", getProjectIdOrPath(projectIdOrPath), "repository", "archive"); + return (response.readEntity(InputStream.class)); + } + /** * Get an archive of the complete repository by SHA (optional). * @@ -461,12 +481,30 @@ public class RepositoryApi extends AbstractApi { * @param format The archive format, defaults to "tar.gz" if null * @return an input stream that can be used to save as a file or to read the content of the archive * @throws GitLabApiException if format is not a valid archive format or any exception occurs + * @deprecated Use {@link #getRepositoryArchive(Object, RepositoryArchiveParams, String)} */ + @Deprecated public InputStream getRepositoryArchive(Object projectIdOrPath, String sha, String format) throws GitLabApiException { ArchiveFormat archiveFormat = ArchiveFormat.forValue(format); return (getRepositoryArchive(projectIdOrPath, sha, archiveFormat)); } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional). + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @param format The archive format, defaults to "tar.gz" if null + * @return an input stream that can be used to save as a file or to read the content of the archive + * @throws GitLabApiException if format is not a valid archive format or any exception occurs + */ + public InputStream getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params, String format) throws GitLabApiException { + ArchiveFormat archiveFormat = ArchiveFormat.forValue(format); + return (getRepositoryArchive(projectIdOrPath, params, archiveFormat)); + } + /** * Get an archive of the complete repository by SHA (optional). * @@ -477,7 +515,9 @@ public class RepositoryApi extends AbstractApi { * @param format The archive format, defaults to TAR_GZ if null * @return an input stream that can be used to save as a file or to read the content of the archive * @throws GitLabApiException if any exception occurs + * @deprecated User {@link #getRepositoryArchive(Object, RepositoryArchiveParams, ArchiveFormat)} */ + @Deprecated public InputStream getRepositoryArchive(Object projectIdOrPath, String sha, ArchiveFormat format) throws GitLabApiException { if (format == null) { @@ -497,6 +537,36 @@ public class RepositoryApi extends AbstractApi { return (response.readEntity(InputStream.class)); } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional). + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @param format The archive format, defaults to TAR_GZ if null + * @return an input stream that can be used to save as a file or to read the content of the archive + * @throws GitLabApiException if any exception occurs + */ + public InputStream getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params, ArchiveFormat format) throws GitLabApiException { + + if (format == null) { + format = ArchiveFormat.TAR_GZ; + } + + /* + * Gitlab-ce has a bug when you try to download file archives with format by using "&format=zip(or tar... etc.)", + * there is a solution to request .../archive.:format instead of .../archive?format=:format. + * + * Issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/45992 + * https://gitlab.com/gitlab-com/support-forum/issues/3067 + */ + Form formData = params.getForm(); + Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, + "projects", getProjectIdOrPath(projectIdOrPath), "repository", "archive" + "." + format); + return (response.readEntity(InputStream.class)); + } + /** * Get an archive of the complete repository by SHA (optional) and saves to the specified directory. * If the archive already exists in the directory it will be overwritten. @@ -508,7 +578,9 @@ public class RepositoryApi extends AbstractApi { * @param directory the File instance of the directory to save the archive to, if null will use "java.io.tmpdir" * @return a File instance pointing to the downloaded instance * @throws GitLabApiException if any exception occurs + * @deprecated Use {@link #getRepositoryArchive(Object, RepositoryArchiveParams, File)} */ + @Deprecated public File getRepositoryArchive(Object projectIdOrPath, String sha, File directory) throws GitLabApiException { Form formData = new GitLabApiForm().withParam("sha", sha); @@ -532,6 +604,41 @@ public class RepositoryApi extends AbstractApi { } } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional) and saves to the specified directory. + * If the archive already exists in the directory it will be overwritten. + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @param directory the File instance of the directory to save the archive to, if null will use "java.io.tmpdir" + * @return a File instance pointing to the downloaded instance + * @throws GitLabApiException if any exception occurs + */ + public File getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params, File directory) throws GitLabApiException { + + Form formData = params.getForm(); + Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, + "projects", getProjectIdOrPath(projectIdOrPath), "repository", "archive"); + + try { + + if (directory == null) + directory = new File(System.getProperty("java.io.tmpdir")); + + String filename = FileUtils.getFilenameFromContentDisposition(response); + File file = new File(directory, filename); + + InputStream in = response.readEntity(InputStream.class); + Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING); + return (file); + + } catch (IOException ioe) { + throw new GitLabApiException(ioe); + } + } + /** * Get an archive of the complete repository by SHA (optional) and saves to the specified directory. * If the archive already exists in the directory it will be overwritten. @@ -544,12 +651,32 @@ public class RepositoryApi extends AbstractApi { * @param format The archive format, defaults to "tar.gz" if null * @return a File instance pointing to the downloaded instance * @throws GitLabApiException if format is not a valid archive format or any exception occurs + * @deprecated Use {@link #getRepositoryArchive(Object, RepositoryArchiveParams, File, String)} */ + @Deprecated public File getRepositoryArchive(Object projectIdOrPath, String sha, File directory, String format) throws GitLabApiException { ArchiveFormat archiveFormat = ArchiveFormat.forValue(format); return (getRepositoryArchive(projectIdOrPath, sha, directory, archiveFormat)); } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional) and saves to the specified directory. + * If the archive already exists in the directory it will be overwritten. + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @param directory the File instance of the directory to save the archive to, if null will use "java.io.tmpdir" + * @param format The archive format, defaults to "tar.gz" if null + * @return a File instance pointing to the downloaded instance + * @throws GitLabApiException if format is not a valid archive format or any exception occurs + */ + public File getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params, File directory, String format) throws GitLabApiException { + ArchiveFormat archiveFormat = ArchiveFormat.forValue(format); + return (getRepositoryArchive(projectIdOrPath, params, directory, archiveFormat)); + } + /** * Get an archive of the complete repository by SHA (optional) and saves to the specified directory. * If the archive already exists in the directory it will be overwritten. @@ -562,7 +689,9 @@ public class RepositoryApi extends AbstractApi { * @param format The archive format, defaults to TAR_GZ if null * @return a File instance pointing to the downloaded instance * @throws GitLabApiException if any exception occurs + * @deprecated Use {@link #getRepositoryArchive(Object, RepositoryArchiveParams, File, ArchiveFormat)} */ + @Deprecated public File getRepositoryArchive(Object projectIdOrPath, String sha, File directory, ArchiveFormat format) throws GitLabApiException { if (format == null) { @@ -597,6 +726,53 @@ public class RepositoryApi extends AbstractApi { } } + /** + * Get an archive of the complete repository by SHA (optional) and Path (optional) and saves to the specified directory. + * If the archive already exists in the directory it will be overwritten. + * + *
GitLab Endpoint: GET /projects/:id/repository/archive
+ * + * @param projectIdOrPath the project in the form of an Long(ID), String(path), or Project instance + * @param params params for getting file archive of the repository + * @param directory the File instance of the directory to save the archive to, if null will use "java.io.tmpdir" + * @param format The archive format, defaults to TAR_GZ if null + * @return a File instance pointing to the downloaded instance + * @throws GitLabApiException if any exception occurs + */ + public File getRepositoryArchive(Object projectIdOrPath, RepositoryArchiveParams params, File directory, ArchiveFormat format) throws GitLabApiException { + + if (format == null) { + format = ArchiveFormat.TAR_GZ; + } + + /* + * Gitlab-ce has a bug when you try to download file archives with format by using "&format=zip(or tar... etc.)", + * there is a solution to request .../archive.:format instead of .../archive?format=:format. + * + * Issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/45992 + * https://gitlab.com/gitlab-com/support-forum/issues/3067 + */ + Form formData = params.getForm(); + Response response = getWithAccepts(Response.Status.OK, formData.asMap(), MediaType.WILDCARD, + "projects", getProjectIdOrPath(projectIdOrPath), "repository", "archive" + "." + format.toString()); + + try { + + if (directory == null) + directory = new File(System.getProperty("java.io.tmpdir")); + + String filename = FileUtils.getFilenameFromContentDisposition(response); + File file = new File(directory, filename); + + InputStream in = response.readEntity(InputStream.class); + Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING); + return (file); + + } catch (IOException ioe) { + throw new GitLabApiException(ioe); + } + } + /** * Compare branches, tags or commits. This can be accessed without authentication * if the repository is publicly accessible. diff --git a/src/main/java/org/gitlab4j/api/models/RepositoryArchiveParams.java b/src/main/java/org/gitlab4j/api/models/RepositoryArchiveParams.java new file mode 100644 index 0000000000000000000000000000000000000000..2a70718f899c48184e7383ea3f069fbe1bac0f15 --- /dev/null +++ b/src/main/java/org/gitlab4j/api/models/RepositoryArchiveParams.java @@ -0,0 +1,47 @@ +package org.gitlab4j.api.models; + +import org.gitlab4j.api.GitLabApiForm; + +/** + * Params for getting file archive of the repository. + */ +public class RepositoryArchiveParams { + + private String sha; + private String path; + + /** + * Add param "The commit SHA to download". + * + * @param sha the commit SHA to download + * @return current params with sha + */ + public RepositoryArchiveParams withSha(String sha) { + this.sha = sha; + return this; + } + + /** + * Add param "The subpath of the repository to download". + * + * @param path the subpath of the repository to download + * @return current params with path + */ + public RepositoryArchiveParams withPath(String path) { + this.path = path; + return this; + } + + /** + * Get form with params. + * + * @return form with params + */ + public GitLabApiForm getForm() { + return new GitLabApiForm() + .withParam("sha", sha) + .withParam("path", path); + } + + +} diff --git a/src/test/java/org/gitlab4j/api/TestRepositoryApi.java b/src/test/java/org/gitlab4j/api/TestRepositoryApi.java index 9587c15ae55080e331e6d0d6d0e6ed4c662e2d75..2925128ad2a0c5e790d7183ec014e6cf636bc672 100644 --- a/src/test/java/org/gitlab4j/api/TestRepositoryApi.java +++ b/src/test/java/org/gitlab4j/api/TestRepositoryApi.java @@ -15,10 +15,12 @@ import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.List; +import org.gitlab4j.api.Constants.ArchiveFormat; import org.gitlab4j.api.models.Branch; import org.gitlab4j.api.models.Commit; import org.gitlab4j.api.models.CompareResults; import org.gitlab4j.api.models.Project; +import org.gitlab4j.api.models.RepositoryArchiveParams; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -142,6 +144,47 @@ public class TestRepositoryApi extends AbstractIntegrationTest { Files.delete(target); } + @Test + public void testRepositoryArchiveByPathAndSha() throws IOException, GitLabApiException { + + Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME); + assertNotNull(project); + + RepositoryArchiveParams params = new RepositoryArchiveParams() + .withPath(project.getPath()) + .withSha("master"); + + InputStream in = gitLabApi.getRepositoryApi() + .getRepositoryArchive(project.getId(), params); + + Path target = Files.createTempFile(TEST_PROJECT_NAME + "-", ".tar.gz"); + Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); + + assertTrue(target.toFile().length() > 0); + Files.delete(target); + + } + + @Test + public void testRepositoryArchiveByPathAndShaAndFormat() throws GitLabApiException, IOException { + + Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME); + assertNotNull(project); + + RepositoryArchiveParams params = new RepositoryArchiveParams() + .withPath(project.getPath()) + .withSha("master"); + + InputStream in = gitLabApi.getRepositoryApi() + .getRepositoryArchive(project.getId(), params, ArchiveFormat.TAR_GZ.toString()); + + Path target = Files.createTempFile(TEST_PROJECT_NAME + "-", ".tar.gz"); + Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); + + assertTrue(target.toFile().length() > 0); + Files.delete(target); + } + @Test public void testRepositoryArchiveViaFile() throws GitLabApiException, IOException { @@ -157,6 +200,44 @@ public class TestRepositoryApi extends AbstractIntegrationTest { file.delete(); } + @Test + public void testRepositoryArchiveByPathAndShaViaFile() throws GitLabApiException { + + Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME); + assertNotNull(project); + + RepositoryArchiveParams params = new RepositoryArchiveParams() + .withPath(project.getPath()) + .withSha("master"); + + File file = gitLabApi.getRepositoryApi().getRepositoryArchive(project.getId(), params, (File)null); + assertTrue(file.length() > 0); + file.delete(); + + file = gitLabApi.getRepositoryApi().getRepositoryArchive(project.getId(), params, new File(".")); + assertTrue(file.length() > 0); + file.delete(); + } + + @Test + public void testRepositoryArchiveByPathAndShaAndFormatViaFile() throws GitLabApiException { + + Project project = gitLabApi.getProjectApi().getProject(TEST_NAMESPACE, TEST_PROJECT_NAME); + assertNotNull(project); + + RepositoryArchiveParams params = new RepositoryArchiveParams() + .withPath(project.getPath()) + .withSha("master"); + + File file = gitLabApi.getRepositoryApi().getRepositoryArchive(project.getId(), params, null, ArchiveFormat.TAR_GZ.toString()); + assertTrue(file.length() > 0); + file.delete(); + + file = gitLabApi.getRepositoryApi().getRepositoryArchive(project.getId(), params, new File("."), ArchiveFormat.TAR_GZ.toString()); + assertTrue(file.length() > 0); + file.delete(); + } + @Test public void testCompare() throws GitLabApiException {