Add --path parameter to GetPatch
Adds path parameter to GetPatch.java for fetching a diff of a specific file. Also includes a unit test for the path parameter. Feature: Issue 4669 Change-Id: Id211fff3b6d9ba6ae16835253f2d328ccf7b5020
This commit is contained in:
@@ -3477,6 +3477,9 @@ Query parameter `download` (e.g. `/changes/.../patch?download`)
|
|||||||
will suggest the browser save the patch as `commitsha1.diff.base64`,
|
will suggest the browser save the patch as `commitsha1.diff.base64`,
|
||||||
for later processing by command line tools.
|
for later processing by command line tools.
|
||||||
|
|
||||||
|
If the `path` parameter is set, the returned content is a diff of the single
|
||||||
|
file that the path refers to.
|
||||||
|
|
||||||
[[submit-preview]]
|
[[submit-preview]]
|
||||||
=== Submit Preview
|
=== Submit Preview
|
||||||
--
|
--
|
||||||
|
@@ -52,15 +52,7 @@ public class PushOneCommit {
|
|||||||
public static final String SUBJECT = "test commit";
|
public static final String SUBJECT = "test commit";
|
||||||
public static final String FILE_NAME = "a.txt";
|
public static final String FILE_NAME = "a.txt";
|
||||||
public static final String FILE_CONTENT = "some content";
|
public static final String FILE_CONTENT = "some content";
|
||||||
public static final String PATCH =
|
public static final String PATCH_FILE_ONLY =
|
||||||
"From %s Mon Sep 17 00:00:00 2001\n" +
|
|
||||||
"From: Administrator <admin@example.com>\n" +
|
|
||||||
"Date: %s\n" +
|
|
||||||
"Subject: [PATCH] test commit\n" +
|
|
||||||
"\n" +
|
|
||||||
"Change-Id: %s\n" +
|
|
||||||
"---\n" +
|
|
||||||
"\n" +
|
|
||||||
"diff --git a/a.txt b/a.txt\n" +
|
"diff --git a/a.txt b/a.txt\n" +
|
||||||
"new file mode 100644\n" +
|
"new file mode 100644\n" +
|
||||||
"index 0000000..f0eec86\n" +
|
"index 0000000..f0eec86\n" +
|
||||||
@@ -69,6 +61,15 @@ public class PushOneCommit {
|
|||||||
"@@ -0,0 +1 @@\n" +
|
"@@ -0,0 +1 @@\n" +
|
||||||
"+some content\n" +
|
"+some content\n" +
|
||||||
"\\ No newline at end of file\n";
|
"\\ No newline at end of file\n";
|
||||||
|
public static final String PATCH =
|
||||||
|
"From %s Mon Sep 17 00:00:00 2001\n" +
|
||||||
|
"From: Administrator <admin@example.com>\n" +
|
||||||
|
"Date: %s\n" +
|
||||||
|
"Subject: [PATCH] test commit\n" +
|
||||||
|
"\n" +
|
||||||
|
"Change-Id: %s\n" +
|
||||||
|
"---\n" +
|
||||||
|
"\n" + PATCH_FILE_ONLY;
|
||||||
|
|
||||||
public interface Factory {
|
public interface Factory {
|
||||||
PushOneCommit create(
|
PushOneCommit create(
|
||||||
|
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
|
import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
|
||||||
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
|
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
|
||||||
import static com.google.gerrit.acceptance.PushOneCommit.PATCH;
|
import static com.google.gerrit.acceptance.PushOneCommit.PATCH;
|
||||||
|
import static com.google.gerrit.acceptance.PushOneCommit.PATCH_FILE_ONLY;
|
||||||
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
|
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
|
||||||
import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
|
import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
|
||||||
import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
|
import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
|
||||||
@@ -58,6 +59,7 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
|
|||||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||||
import com.google.gerrit.extensions.restapi.ETagView;
|
import com.google.gerrit.extensions.restapi.ETagView;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
import com.google.gerrit.reviewdb.client.Branch;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
import com.google.gerrit.reviewdb.client.PatchSetApproval;
|
import com.google.gerrit.reviewdb.client.PatchSetApproval;
|
||||||
@@ -922,6 +924,24 @@ public class RevisionIT extends AbstractDaemonTest {
|
|||||||
String.format(PATCH, r.getCommit().name(), date, r.getChangeId()));
|
String.format(PATCH, r.getCommit().name(), date, r.getChangeId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void patchWithPath() throws Exception {
|
||||||
|
PushOneCommit.Result r = createChange();
|
||||||
|
ChangeApi changeApi = gApi.changes()
|
||||||
|
.id(r.getChangeId());
|
||||||
|
BinaryResult bin = changeApi
|
||||||
|
.revision(r.getCommit().name())
|
||||||
|
.patch(FILE_NAME);
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
bin.writeTo(os);
|
||||||
|
String res = new String(os.toByteArray(), UTF_8);
|
||||||
|
assertThat(res).isEqualTo(PATCH_FILE_ONLY);
|
||||||
|
|
||||||
|
exception.expect(ResourceNotFoundException.class);
|
||||||
|
exception.expectMessage("File not found: nonexistent-file.");
|
||||||
|
changeApi.revision(r.getCommit().name()).patch("nonexistent-file");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void actions() throws Exception {
|
public void actions() throws Exception {
|
||||||
PushOneCommit.Result r = createChange();
|
PushOneCommit.Result r = createChange();
|
||||||
|
@@ -72,6 +72,7 @@ public interface RevisionApi {
|
|||||||
* Returns patch of revision.
|
* Returns patch of revision.
|
||||||
*/
|
*/
|
||||||
BinaryResult patch() throws RestApiException;
|
BinaryResult patch() throws RestApiException;
|
||||||
|
BinaryResult patch(String path) throws RestApiException;
|
||||||
|
|
||||||
Map<String, ActionInfo> actions() throws RestApiException;
|
Map<String, ActionInfo> actions() throws RestApiException;
|
||||||
|
|
||||||
@@ -252,6 +253,11 @@ public interface RevisionApi {
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BinaryResult patch(String path) throws RestApiException {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ActionInfo> actions() throws RestApiException {
|
public Map<String, ActionInfo> actions() throws RestApiException {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
@@ -462,6 +462,15 @@ class RevisionApiImpl implements RevisionApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BinaryResult patch(String path) throws RestApiException {
|
||||||
|
try {
|
||||||
|
return getPatch.setPath(path).apply(revision);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RestApiException("Cannot get patch", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ActionInfo> actions() throws RestApiException {
|
public Map<String, ActionInfo> actions() throws RestApiException {
|
||||||
return revisionActions.apply(revision).value();
|
return revisionActions.apply(revision).value();
|
||||||
|
@@ -18,6 +18,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||||||
|
|
||||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
@@ -30,6 +31,7 @@ import org.eclipse.jgit.lib.PersonIdent;
|
|||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||||
import org.kohsuke.args4j.Option;
|
import org.kohsuke.args4j.Option;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -43,20 +45,25 @@ import java.util.zip.ZipOutputStream;
|
|||||||
public class GetPatch implements RestReadView<RevisionResource> {
|
public class GetPatch implements RestReadView<RevisionResource> {
|
||||||
private final GitRepositoryManager repoManager;
|
private final GitRepositoryManager repoManager;
|
||||||
|
|
||||||
|
private final String FILE_NOT_FOUND = "File not found: %s.";
|
||||||
|
|
||||||
@Option(name = "--zip")
|
@Option(name = "--zip")
|
||||||
private boolean zip;
|
private boolean zip;
|
||||||
|
|
||||||
@Option(name = "--download")
|
@Option(name = "--download")
|
||||||
private boolean download;
|
private boolean download;
|
||||||
|
|
||||||
|
@Option(name = "--path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetPatch(GitRepositoryManager repoManager) {
|
GetPatch(GitRepositoryManager repoManager) {
|
||||||
this.repoManager = repoManager;
|
this.repoManager = repoManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BinaryResult apply(RevisionResource rsrc)
|
public BinaryResult apply(RevisionResource rsrc) throws
|
||||||
throws ResourceConflictException, IOException {
|
ResourceConflictException, IOException, ResourceNotFoundException {
|
||||||
Project.NameKey project = rsrc.getControl().getProject().getNameKey();
|
Project.NameKey project = rsrc.getControl().getProject().getNameKey();
|
||||||
final Repository repo = repoManager.openRepository(project);
|
final Repository repo = repoManager.openRepository(project);
|
||||||
boolean close = true;
|
boolean close = true;
|
||||||
@@ -93,9 +100,15 @@ public class GetPatch implements RestReadView<RevisionResource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void format(OutputStream out) throws IOException {
|
private void format(OutputStream out) throws IOException {
|
||||||
|
// Only add header if no path is specified
|
||||||
|
if (path == null) {
|
||||||
out.write(formatEmailHeader(commit).getBytes(UTF_8));
|
out.write(formatEmailHeader(commit).getBytes(UTF_8));
|
||||||
|
}
|
||||||
try (DiffFormatter fmt = new DiffFormatter(out)) {
|
try (DiffFormatter fmt = new DiffFormatter(out)) {
|
||||||
fmt.setRepository(repo);
|
fmt.setRepository(repo);
|
||||||
|
if (path != null) {
|
||||||
|
fmt.setPathFilter(PathFilter.create(path));
|
||||||
|
}
|
||||||
fmt.format(base.getTree(), commit.getTree());
|
fmt.format(base.getTree(), commit.getTree());
|
||||||
fmt.flush();
|
fmt.flush();
|
||||||
}
|
}
|
||||||
@@ -108,6 +121,11 @@ public class GetPatch implements RestReadView<RevisionResource> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (path != null && bin.asString().isEmpty()) {
|
||||||
|
throw new ResourceNotFoundException(
|
||||||
|
String.format(FILE_NOT_FOUND, path));
|
||||||
|
}
|
||||||
|
|
||||||
if (zip) {
|
if (zip) {
|
||||||
bin.disableGzip()
|
bin.disableGzip()
|
||||||
.setContentType("application/zip")
|
.setContentType("application/zip")
|
||||||
@@ -134,6 +152,11 @@ public class GetPatch implements RestReadView<RevisionResource> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GetPatch setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private static String formatEmailHeader(RevCommit commit) {
|
private static String formatEmailHeader(RevCommit commit) {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
PersonIdent author = commit.getAuthorIdent();
|
PersonIdent author = commit.getAuthorIdent();
|
||||||
|
Reference in New Issue
Block a user