From b537f9925b8cea4f7736c8f7b80093033c36b795 Mon Sep 17 00:00:00 2001 From: Serban Iordache Date: Fri, 7 Jul 2017 16:21:11 +0200 Subject: [PATCH] issue #360: Add support for committing multiple files --- .../org/kohsuke/github/GHBlobBuilder.java | 50 ++++++++++ .../org/kohsuke/github/GHCommitBuilder.java | 92 +++++++++++++++++++ .../org/kohsuke/github/GHTreeBuilder.java | 86 +++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHBlobBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GHCommitBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GHTreeBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHBlobBuilder.java b/src/main/java/org/kohsuke/github/GHBlobBuilder.java new file mode 100644 index 0000000000..321e88191d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBlobBuilder.java @@ -0,0 +1,50 @@ +package org.kohsuke.github; + +import org.apache.commons.codec.binary.Base64; + +import java.io.IOException; + +/** + * Builder pattern for creating a new blob. + * Based on https://developer.github.com/v3/git/blobs/#create-a-blob + */ +public class GHBlobBuilder { + private final GHRepository repo; + private final Requester req; + + public GHBlobBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * Configures a blob with the specified text {@code content}. + */ + public GHBlobBuilder textContent(String content) { + req.with("content", content); + req.with("encoding", "utf-8"); + return this; + } + + /** + * Configures a blob with the specified binary {@code content}. + */ + public GHBlobBuilder binaryContent(byte[] content) { + new String(content); + String base64Content = Base64.encodeBase64String(content); + req.with("content", base64Content); + req.with("encoding", "base64"); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/blobs", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a blob based on the parameters specified thus far. + */ + public GHBlob create() throws IOException { + return req.method("POST").to(getApiTail(), GHBlob.class); + } +} diff --git a/src/main/java/org/kohsuke/github/GHCommitBuilder.java b/src/main/java/org/kohsuke/github/GHCommitBuilder.java new file mode 100644 index 0000000000..5f5b268a63 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHCommitBuilder.java @@ -0,0 +1,92 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +/** + * Builder pattern for creating a new commit. + * Based on https://developer.github.com/v3/git/commits/#create-a-commit + */ +public class GHCommitBuilder { + private final GHRepository repo; + private final Requester req; + + private final List parents = new ArrayList(); + + private static final class UserInfo { + private final String name; + private final String email; + private final String date; + + private UserInfo(String name, String email, Date date) { + this.name = name; + this.email = email; + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + df.setTimeZone(tz); + this.date = df.format((date != null) ? date : new Date()); + } + } + + public GHCommitBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * @param message the commit message + */ + public GHCommitBuilder message(String message) { + req.with("message", message); + return this; + } + + /** + * @param tree the SHA of the tree object this commit points to + */ + public GHCommitBuilder tree(String tree) { + req.with("tree", tree); + return this; + } + + /** + * @param parent the SHA of a parent commit. + */ + public GHCommitBuilder parent(String parent) { + parents.add(parent); + return this; + } + + /** + * Configures the author of this commit. + */ + public GHCommitBuilder author(String name, String email, Date date) { + req._with("author", new UserInfo(name, email, date)); + return this; + } + + /** + * Configures the committer of this commit. + */ + public GHCommitBuilder committer(String name, String email, Date date) { + req._with("committer", new UserInfo(name, email, date)); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/commits", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a blob based on the parameters specified thus far. + */ + public GHCommit create() throws IOException { + req._with("parents", parents); + return req.method("POST").to(getApiTail(), GHCommit.class).wrapUp(repo); + } +} diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java new file mode 100644 index 0000000000..05c04ef9c1 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -0,0 +1,86 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.util.*; + +/** + * Builder pattern for creating a new tree. + * Based on https://developer.github.com/v3/git/trees/#create-a-tree + */ +public class GHTreeBuilder { + private final GHRepository repo; + private final Requester req; + + private final List treeEntries = new ArrayList(); + + private static final class TreeEntry { + private final String path; + private final String mode; + private final String type; + private String sha; + private String content; + + private TreeEntry(String path, String mode, String type) { + this.path = path; + this.mode = mode; + this.type = type; + } + } + + public GHTreeBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * @param baseTree the SHA of tree you want to update with new data + */ + public GHTreeBuilder baseTree(String baseTree) { + req.with("base_tree", baseTree); + return this; + } + + /** + * Adds a new entry to the tree. + * Exactly one of the parameters {@code sha} and {@code content} must be non-null. + */ + public GHTreeBuilder entry(String path, String mode, String type, String sha, String content) { + TreeEntry entry = new TreeEntry(path, mode, type); + entry.sha = sha; + entry.content = content; + treeEntries.add(entry); + return this; + } + + /** + * Specialized version of {@link #entry(String, String, String, String, String)} for adding an existing blob referred by its SHA. + */ + public GHTreeBuilder shaEntry(String path, String sha, boolean executable) { + TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob"); + entry.sha = sha; + treeEntries.add(entry); + return this; + } + + /** + * Specialized version of {@link #entry(String, String, String, String, String)} for adding a text file with the specified {@code content}. + */ + public GHTreeBuilder textEntry(String path, String content, boolean executable) { + TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob"); + entry.content = content; + treeEntries.add(entry); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/trees", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a tree based on the parameters specified thus far. + */ + public GHTree create() throws IOException { + req._with("tree", treeEntries); + return req.method("POST").to(getApiTail(), GHTree.class).wrap(repo); + } +}