diff --git a/gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryFileApi.java b/gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryFileApi.java index 39be583fa..a5a05112d 100644 --- a/gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryFileApi.java +++ b/gitlab4j-api/src/main/java/org/gitlab4j/api/RepositoryFileApi.java @@ -15,7 +15,9 @@ import org.gitlab4j.api.models.Blame; import org.gitlab4j.api.models.RepositoryFile; +import org.gitlab4j.api.models.RepositoryFileCreate; import org.gitlab4j.api.models.RepositoryFileResponse; +import org.gitlab4j.api.models.RepositoryFileUpdate; import org.gitlab4j.models.Constants; /** @@ -183,7 +185,7 @@ public RepositoryFile getFile(Object projectIdOrPath, String filePath, String re } /** - * Create new file in repository + * Create new file in repository. * *
GitLab Endpoint: POST /projects/:id/repository/files
*
@@ -194,15 +196,44 @@ public RepositoryFile getFile(Object projectIdOrPath, String filePath, String re
* commit_message (required) - Commit message
*
* @param projectIdOrPath the id, path of the project, or a Project instance holding the project ID or path
- * @param file a ReposityoryFile instance with info for the file to create
+ * @param file a RepositoryFile instance with info for the file to create
* @param branchName the name of branch
* @param commitMessage the commit message
- * @return a RepositoryFile instance with the created file info
+ * @return a RepositoryFileResponse instance with the created file info
* @throws GitLabApiException if any exception occurs
+ * @deprecated Use {@link #createFile(Object, RepositoryFileCreate, String, String)} instead.
+ * {@link RepositoryFile} mixes read-only response fields with write input fields;
+ * {@link RepositoryFileCreate} exposes only the parameters accepted by the endpoint and adds support
+ * for {@code start_branch}, {@code execute_filemode}, {@code author_email} and {@code author_name}.
*/
+ @Deprecated
public RepositoryFileResponse createFile(
Object projectIdOrPath, RepositoryFile file, String branchName, String commitMessage)
throws GitLabApiException {
+ return createFile(projectIdOrPath, toCreate(file), branchName, commitMessage);
+ }
+
+ /**
+ * Create new file in repository.
+ *
+ * GitLab Endpoint: POST /projects/:id/repository/files/:file_path
+ *
+ * file_path (required) - Full path to new file. Ex. lib/class.rb
+ * branch_name (required) - The name of branch
+ * encoding (optional) - 'text' or 'base64'. Text is default.
+ * content (required) - File content
+ * commit_message (required) - Commit message
+ *
+ * @param projectIdOrPath the id, path of the project, or a Project instance holding the project ID or path
+ * @param file a RepositoryFileCreate instance with the input parameters for the file to create
+ * @param branchName the name of branch
+ * @param commitMessage the commit message
+ * @return a RepositoryFileResponse instance with the created file info (path and branch)
+ * @throws GitLabApiException if any exception occurs
+ */
+ public RepositoryFileResponse createFile(
+ Object projectIdOrPath, RepositoryFileCreate file, String branchName, String commitMessage)
+ throws GitLabApiException {
Form formData = createForm(file, branchName, commitMessage);
Response response = post(
@@ -217,7 +248,7 @@ public RepositoryFileResponse createFile(
}
/**
- * Create new file in repository
+ * Create new file in repository.
*
* GitLab Endpoint: POST /projects/:id/repository/files
*
@@ -227,13 +258,13 @@ public RepositoryFileResponse createFile(
* content (required) - File content
* commit_message (required) - Commit message
*
- * @param file a ReposityoryFile instance with info for the file to create
+ * @param file a RepositoryFile instance with info for the file to create
* @param projectId the project ID
* @param branchName the name of branch
* @param commitMessage the commit message
- * @return a RepositoryFile instance with the created file info
+ * @return a RepositoryFileResponse instance with the created file info
* @throws GitLabApiException if any exception occurs
- * @deprecated Will be removed in version 6.0, replaced by {@link #createFile(Object, RepositoryFile, String, String)}
+ * @deprecated Use {@link #createFile(Object, RepositoryFileCreate, String, String)} instead.
*/
@Deprecated
public RepositoryFileResponse createFile(
@@ -242,7 +273,7 @@ public RepositoryFileResponse createFile(
}
/**
- * Update existing file in repository
+ * Update existing file in repository.
*
* GitLab Endpoint: PUT /projects/:id/repository/files
*
@@ -253,15 +284,45 @@ public RepositoryFileResponse createFile(
* commit_message (required) - Commit message
*
* @param projectIdOrPath the id, path of the project, or a Project instance holding the project ID or path
- * @param file a ReposityoryFile instance with info for the file to update
+ * @param file a RepositoryFile instance with info for the file to update
* @param branchName the name of branch
* @param commitMessage the commit message
- * @return a RepositoryFile instance with the updated file info
+ * @return a RepositoryFileResponse instance with the updated file info
* @throws GitLabApiException if any exception occurs
+ * @deprecated Use {@link #updateFile(Object, RepositoryFileUpdate, String, String)} instead.
+ * {@link RepositoryFile} mixes read-only response fields with write input fields;
+ * {@link RepositoryFileUpdate} exposes only the parameters accepted by the endpoint and adds support
+ * for {@code start_branch}, {@code execute_filemode}, {@code last_commit_id}, {@code author_email}
+ * and {@code author_name}.
*/
+ @Deprecated
public RepositoryFileResponse updateFile(
Object projectIdOrPath, RepositoryFile file, String branchName, String commitMessage)
throws GitLabApiException {
+ return updateFile(projectIdOrPath, toUpdate(file), branchName, commitMessage);
+ }
+
+ /**
+ * Update existing file in repository.
+ *
+ * GitLab Endpoint: PUT /projects/:id/repository/files/:file_path
+ *
+ * file_path (required) - Full path to new file. Ex. lib/class.rb
+ * branch_name (required) - The name of branch
+ * encoding (optional) - 'text' or 'base64'. Text is default.
+ * content (required) - File content
+ * commit_message (required) - Commit message
+ *
+ * @param projectIdOrPath the id, path of the project, or a Project instance holding the project ID or path
+ * @param file a RepositoryFileUpdate instance with the input parameters for the file to update
+ * @param branchName the name of branch
+ * @param commitMessage the commit message
+ * @return a RepositoryFileResponse instance with the updated file info (path and branch)
+ * @throws GitLabApiException if any exception occurs
+ */
+ public RepositoryFileResponse updateFile(
+ Object projectIdOrPath, RepositoryFileUpdate file, String branchName, String commitMessage)
+ throws GitLabApiException {
Form formData = createForm(file, branchName, commitMessage);
Response response = put(
@@ -276,23 +337,17 @@ public RepositoryFileResponse updateFile(
}
/**
- * Update existing file in repository
+ * Update existing file in repository.
*
* GitLab Endpoint: PUT /projects/:id/repository/files
*
- * file_path (required) - Full path to new file. Ex. lib/class.rb
- * branch_name (required) - The name of branch
- * encoding (optional) - 'text' or 'base64'. Text is default.
- * content (required) - File content
- * commit_message (required) - Commit message
- *
- * @param file a ReposityoryFile instance with info for the file to update
+ * @param file a RepositoryFile instance with info for the file to update
* @param projectId the project ID
* @param branchName the name of branch
* @param commitMessage the commit message
- * @return a RepositoryFile instance with the updated file info
+ * @return a RepositoryFileResponse instance with the updated file info
* @throws GitLabApiException if any exception occurs
- * @deprecated Will be removed in version 6.0, replaced by {@link #updateFile(Object, RepositoryFile, String, String)}
+ * @deprecated Use {@link #updateFile(Object, RepositoryFileUpdate, String, String)} instead.
*/
@Deprecated
public RepositoryFileResponse updateFile(
@@ -433,18 +488,21 @@ public InputStream getRawFile(Object projectIdOrPath, String ref, String filepat
}
/**
- * Gets the query params based on the API version.
+ * Builds the form payload sent on create/update requests.
*
- * @param file the RepositoryFile instance with the info for the query params
+ * @param file the RepositoryFileCreate (or RepositoryFileUpdate) instance with the input parameters
* @param branchName the branch name
* @param commitMessage the commit message
* @return a Form instance with the correct query params.
*/
- protected Form createForm(RepositoryFile file, String branchName, String commitMessage) {
+ private Form createForm(RepositoryFileCreate file, String branchName, String commitMessage) {
Form form = new Form();
addFormParam(form, "branch", branchName, true);
+ addFormParam(form, "start_branch", file.getStartBranch(), false);
addFormParam(form, "encoding", file.getEncoding(), false);
+ addFormParam(form, "author_email", file.getAuthorEmail(), false);
+ addFormParam(form, "author_name", file.getAuthorName(), false);
// Cannot use addFormParam() as it does not accept an empty or whitespace only string
String content = file.getContent();
@@ -454,9 +512,41 @@ protected Form createForm(RepositoryFile file, String branchName, String commitM
form.param("content", content);
addFormParam(form, "commit_message", commitMessage, true);
+ addFormParam(form, "execute_filemode", file.getExecuteFilemode(), false);
+
+ if (file instanceof RepositoryFileUpdate) {
+ addFormParam(form, "last_commit_id", ((RepositoryFileUpdate) file).getLastCommitId(), false);
+ }
+
return (form);
}
+ /**
+ * Copies the input fields of a {@link RepositoryFile} into a new {@link RepositoryFileCreate}.
+ * Used by the deprecated {@code createFile(Object, RepositoryFile, ...)} overload.
+ */
+ private RepositoryFileCreate toCreate(RepositoryFile file) {
+ RepositoryFileCreate create = new RepositoryFileCreate();
+ create.setFilePath(file.getFilePath());
+ create.setContent(file.getContent());
+ create.setEncoding(file.getEncoding());
+ return create;
+ }
+
+ /**
+ * Copies the input fields of a {@link RepositoryFile} into a new {@link RepositoryFileUpdate},
+ * preserving {@code lastCommitId} as the optimistic-locking hint.
+ * Used by the deprecated {@code updateFile(Object, RepositoryFile, ...)} overload.
+ */
+ private RepositoryFileUpdate toUpdate(RepositoryFile file) {
+ RepositoryFileUpdate update = new RepositoryFileUpdate();
+ update.setFilePath(file.getFilePath());
+ update.setContent(file.getContent());
+ update.setEncoding(file.getEncoding());
+ update.setLastCommitId(file.getLastCommitId());
+ return update;
+ }
+
/**
* Get a List of file blame from repository. Allows you to receive blame information.
* Each blame range contains lines and corresponding commit information.
diff --git a/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileCreate.java b/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileCreate.java
new file mode 100644
index 000000000..d993856c8
--- /dev/null
+++ b/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileCreate.java
@@ -0,0 +1,149 @@
+package org.gitlab4j.api.models;
+
+import java.io.Serializable;
+import java.util.Base64;
+
+import org.gitlab4j.models.Constants.Encoding;
+import org.gitlab4j.models.utils.JacksonJson;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * This class is used as input when creating a file in a repository.
+ *
+ * @see Create a file in a repository
+ */
+public class RepositoryFileCreate implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String filePath;
+ private String startBranch;
+ private Encoding encoding;
+ private String authorEmail;
+ private String authorName;
+ private String content;
+ private Boolean executeFilemode;
+
+ public String getFilePath() {
+ return filePath;
+ }
+
+ public void setFilePath(String filePath) {
+ this.filePath = filePath;
+ }
+
+ public RepositoryFileCreate withFilePath(String filePath) {
+ this.filePath = filePath;
+ return this;
+ }
+
+ public String getStartBranch() {
+ return startBranch;
+ }
+
+ public void setStartBranch(String startBranch) {
+ this.startBranch = startBranch;
+ }
+
+ public RepositoryFileCreate withStartBranch(String startBranch) {
+ this.startBranch = startBranch;
+ return this;
+ }
+
+ public Encoding getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(Encoding encoding) {
+ this.encoding = encoding;
+ }
+
+ public RepositoryFileCreate withEncoding(Encoding encoding) {
+ this.encoding = encoding;
+ return this;
+ }
+
+ public String getAuthorEmail() {
+ return authorEmail;
+ }
+
+ public void setAuthorEmail(String authorEmail) {
+ this.authorEmail = authorEmail;
+ }
+
+ public RepositoryFileCreate withAuthorEmail(String authorEmail) {
+ this.authorEmail = authorEmail;
+ return this;
+ }
+
+ public String getAuthorName() {
+ return authorName;
+ }
+
+ public void setAuthorName(String authorName) {
+ this.authorName = authorName;
+ }
+
+ public RepositoryFileCreate withAuthorName(String authorName) {
+ this.authorName = authorName;
+ return this;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public RepositoryFileCreate withContent(String content) {
+ this.content = content;
+ return this;
+ }
+
+ public Boolean getExecuteFilemode() {
+ return executeFilemode;
+ }
+
+ public void setExecuteFilemode(Boolean executeFilemode) {
+ this.executeFilemode = executeFilemode;
+ }
+
+ public RepositoryFileCreate withExecuteFilemode(Boolean executeFilemode) {
+ this.executeFilemode = executeFilemode;
+ return this;
+ }
+
+ /**
+ * Encodes the provided String using Base64 and sets it as the content.
+ * The encoding property of this instance will be set to base64.
+ *
+ * @param content the String content to encode and set as the base64 encoded String content
+ */
+ @JsonIgnore
+ public void encodeAndSetContent(String content) {
+ encodeAndSetContent(content != null ? content.getBytes() : null);
+ }
+
+ /**
+ * Encodes the provided byte array using Base64 and sets it as the content.
+ * The encoding property of this instance will be set to base64.
+ *
+ * @param byteContent the byte[] content to encode and set as the base64 encoded String content
+ */
+ @JsonIgnore
+ public void encodeAndSetContent(byte[] byteContent) {
+ if (byteContent == null) {
+ this.content = null;
+ return;
+ }
+ this.content = Base64.getEncoder().encodeToString(byteContent);
+ this.encoding = Encoding.BASE64;
+ }
+
+ @Override
+ public String toString() {
+ return (JacksonJson.toJsonString(this));
+ }
+}
diff --git a/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileUpdate.java b/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileUpdate.java
new file mode 100644
index 000000000..77c1da55d
--- /dev/null
+++ b/gitlab4j-models/src/main/java/org/gitlab4j/api/models/RepositoryFileUpdate.java
@@ -0,0 +1,25 @@
+package org.gitlab4j.api.models;
+
+/**
+ * This class is used as input when updating a file in a repository.
+ *
+ * @see Update a file in a repository
+ */
+public class RepositoryFileUpdate extends RepositoryFileCreate {
+ private static final long serialVersionUID = 1L;
+
+ private String lastCommitId;
+
+ public String getLastCommitId() {
+ return lastCommitId;
+ }
+
+ public void setLastCommitId(String lastCommitId) {
+ this.lastCommitId = lastCommitId;
+ }
+
+ public RepositoryFileUpdate withLastCommitId(String lastCommitId) {
+ this.lastCommitId = lastCommitId;
+ return this;
+ }
+}
diff --git a/gitlab4j-models/src/test/java/org/gitlab4j/models/TestGitLabApiBeans.java b/gitlab4j-models/src/test/java/org/gitlab4j/models/TestGitLabApiBeans.java
index f54ca6cb4..c74e39a56 100644
--- a/gitlab4j-models/src/test/java/org/gitlab4j/models/TestGitLabApiBeans.java
+++ b/gitlab4j-models/src/test/java/org/gitlab4j/models/TestGitLabApiBeans.java
@@ -568,6 +568,18 @@ public void testRepositoryFile() throws Exception {
assertTrue(compareJson(file, "repository-file.json"));
}
+ @Test
+ public void testRepositoryFileCreate() throws Exception {
+ RepositoryFileCreate file = unmarshalResource(RepositoryFileCreate.class, "repository-file-create.json");
+ assertTrue(compareJson(file, "repository-file-create.json"));
+ }
+
+ @Test
+ public void testRepositoryFileUpdate() throws Exception {
+ RepositoryFileUpdate file = unmarshalResource(RepositoryFileUpdate.class, "repository-file-update.json");
+ assertTrue(compareJson(file, "repository-file-update.json"));
+ }
+
@Test
public void testRepositoryFileResponse() throws Exception {
RepositoryFileResponse file = unmarshalResource(RepositoryFileResponse.class, "repository-file-response.json");
diff --git a/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-create.json b/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-create.json
new file mode 100644
index 000000000..749da9abd
--- /dev/null
+++ b/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-create.json
@@ -0,0 +1,9 @@
+{
+ "file_path": "app/models/key.rb",
+ "start_branch": "main",
+ "encoding": "base64",
+ "author_email": "author@example.com",
+ "author_name": "Author Name",
+ "content": "IyA9PSBTY2hlbWEgSW5mb3...",
+ "execute_filemode": true
+}
diff --git a/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-update.json b/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-update.json
new file mode 100644
index 000000000..9b64eca22
--- /dev/null
+++ b/gitlab4j-models/src/test/resources/org/gitlab4j/models/repository-file-update.json
@@ -0,0 +1,10 @@
+{
+ "file_path": "app/models/key.rb",
+ "start_branch": "main",
+ "encoding": "base64",
+ "author_email": "author@example.com",
+ "author_name": "Author Name",
+ "content": "IyA9PSBTY2hlbWEgSW5mb3...",
+ "execute_filemode": true,
+ "last_commit_id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d"
+}