diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java index f896692aa7..14dca0bd1b 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java @@ -57,7 +57,7 @@ import java.util.Set; public class PushOneCommit { public static final String SUBJECT = "test commit"; public static final String FILE_NAME = "a.txt"; - private static final String FILE_CONTENT = "some content"; + public static final String FILE_CONTENT = "some content"; public interface Factory { PushOneCommit create( diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java index 11ed309288..3f72c28223 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java @@ -15,9 +15,12 @@ package com.google.gerrit.acceptance.api.revision; 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_NAME; import static org.eclipse.jgit.lib.Constants.HEAD; import static org.junit.Assert.fail; +import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.NoHttpd; @@ -29,10 +32,13 @@ import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.api.changes.SubmitInput; import com.google.gerrit.extensions.api.projects.BranchInput; import com.google.gerrit.extensions.common.ChangeInfo; +import com.google.gerrit.extensions.common.DiffInfo; import com.google.gerrit.extensions.common.MergeableInfo; import com.google.gerrit.extensions.common.SubmitType; import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.BinaryResult; import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.reviewdb.client.Patch; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.ObjectId; @@ -40,7 +46,9 @@ import org.eclipse.jgit.lib.RefUpdate; import org.junit.Before; import org.junit.Test; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; @NoHttpd public class RevisionIT extends AbstractDaemonTest { @@ -280,6 +288,48 @@ public class RevisionIT extends AbstractDaemonTest { // TODO(dborowitz): Test for other-branches. } + @Test + public void files() throws Exception { + PushOneCommit.Result r = createChange(); + assertThat(Iterables.all(gApi.changes() + .id(r.getChangeId()) + .revision(r.getCommit().name()) + .files() + .keySet(), new Predicate() { + @Override + public boolean apply(String file) { + return file.matches(FILE_NAME + '|' + Patch.COMMIT_MSG); + } + })) + .isTrue(); + } + + @Test + public void diff() throws Exception { + PushOneCommit.Result r = createChange(); + DiffInfo diff = gApi.changes() + .id(r.getChangeId()) + .revision(r.getCommit().name()) + .file(FILE_NAME) + .diff(); + assertThat(diff.metaA).isNull(); + assertThat(diff.metaB.lines).isEqualTo(1); + } + + @Test + public void content() throws Exception { + PushOneCommit.Result r = createChange(); + BinaryResult bin = gApi.changes() + .id(r.getChangeId()) + .revision(r.getCommit().name()) + .file(FILE_NAME) + .content(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + bin.writeTo(os); + String res = new String(os.toByteArray(), StandardCharsets.UTF_8); + assertThat(res).isEqualTo(FILE_CONTENT); + } + private void assertMergeable(String id, boolean expected) throws Exception { MergeableInfo m = gApi.changes().id(id).current().mergeable(); assertThat(m.mergeable).isEqualTo(expected); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java new file mode 100644 index 0000000000..42c1e237cb --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/FileApiImpl.java @@ -0,0 +1,77 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.api.changes; + +import com.google.gerrit.extensions.api.changes.FileApi; +import com.google.gerrit.extensions.common.DiffInfo; +import com.google.gerrit.extensions.restapi.BinaryResult; +import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.server.change.FileResource; +import com.google.gerrit.server.change.GetContent; +import com.google.gerrit.server.change.GetDiff; +import com.google.gerrit.server.project.InvalidChangeOperationException; +import com.google.gerrit.server.project.NoSuchChangeException; +import com.google.gwtorm.server.OrmException; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.assistedinject.Assisted; + +import java.io.IOException; + +class FileApiImpl extends FileApi.NotImplemented implements FileApi { + interface Factory { + FileApiImpl create(FileResource r); + } + + private final GetContent getContent; + private final Provider getDiff; + private final FileResource file; + + @Inject + FileApiImpl(GetContent getContent, + Provider getDiff, + @Assisted FileResource file) { + this.getContent = getContent; + this.getDiff = getDiff; + this.file = file; + } + + @Override + public BinaryResult content() throws RestApiException { + try { + return getContent.apply(file); + } catch (NoSuchChangeException | IOException | OrmException e) { + throw new RestApiException("Cannot retrieve file content", e); + } + } + + @Override + public DiffInfo diff() throws RestApiException { + try { + return getDiff.get().apply(file).value(); + } catch (IOException | InvalidChangeOperationException | OrmException e) { + throw new RestApiException("Cannot retrieve diff", e); + } + } + + @Override + public DiffInfo diff(String base) throws RestApiException { + try { + return getDiff.get().setBase(base).apply(file).value(); + } catch (IOException | InvalidChangeOperationException | OrmException e) { + throw new RestApiException("Cannot retrieve diff", e); + } + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/Module.java index dbf5f2740a..aa63996a5b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/Module.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/Module.java @@ -24,5 +24,6 @@ public class Module extends FactoryModule { factory(ChangeApiImpl.Factory.class); factory(RevisionApiImpl.Factory.class); + factory(FileApiImpl.Factory.class); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java index ab788c945e..65b4f053b3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/RevisionApiImpl.java @@ -19,9 +19,11 @@ import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.extensions.api.changes.ChangeApi; import com.google.gerrit.extensions.api.changes.Changes; import com.google.gerrit.extensions.api.changes.CherryPickInput; +import com.google.gerrit.extensions.api.changes.FileApi; import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.api.changes.RevisionApi; import com.google.gerrit.extensions.api.changes.SubmitInput; +import com.google.gerrit.extensions.common.FileInfo; import com.google.gerrit.extensions.common.MergeableInfo; import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.RestApiException; @@ -44,6 +46,7 @@ import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; import java.io.IOException; +import java.util.Map; import java.util.Set; class RevisionApiImpl extends RevisionApi.NotImplemented implements RevisionApi { @@ -65,6 +68,7 @@ class RevisionApiImpl extends RevisionApi.NotImplemented implements RevisionApi private final Provider listFiles; private final Provider review; private final Provider mergeable; + private final FileApiImpl.Factory fileApi; @Inject RevisionApiImpl(Changes changes, @@ -80,6 +84,7 @@ class RevisionApiImpl extends RevisionApi.NotImplemented implements RevisionApi Provider listFiles, Provider review, Provider mergeable, + FileApiImpl.Factory fileApi, @Assisted RevisionResource r) { this.changes = changes; this.cherryPick = cherryPick; @@ -94,6 +99,7 @@ class RevisionApiImpl extends RevisionApi.NotImplemented implements RevisionApi this.deleteReviewed = deleteReviewed; this.listFiles = listFiles; this.mergeable = mergeable; + this.fileApi = fileApi; this.revision = r; } @@ -211,4 +217,31 @@ class RevisionApiImpl extends RevisionApi.NotImplemented implements RevisionApi throw new RestApiException("Cannot check mergeability", e); } } + + @SuppressWarnings("unchecked") + @Override + public Map files() throws RestApiException { + try { + return (Map)listFiles.get().apply(revision).value(); + } catch (OrmException | IOException e) { + throw new RestApiException("Cannot retrieve files", e); + } + } + + @SuppressWarnings("unchecked") + @Override + public Map files(String base) throws RestApiException { + try { + return (Map) listFiles.get().setBase(base) + .apply(revision).value(); + } catch (OrmException | IOException e) { + throw new RestApiException("Cannot retrieve files", e); + } + } + + @Override + public FileApi file(String path) { + return fileApi.create(files.get().parse(revision, + IdString.fromDecoded(path))); + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java index 4a3082c8c3..1c0b0a4eac 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java @@ -86,8 +86,7 @@ public class Files implements ChildCollection { } @Override - public FileResource parse(RevisionResource rev, IdString id) - throws ResourceNotFoundException, OrmException, AuthException { + public FileResource parse(RevisionResource rev, IdString id) { return new FileResource(rev, id.get()); } @@ -334,5 +333,10 @@ public class Files implements ChildCollection { git.close(); } } + + public ListFiles setBase(String base) { + this.base = base; + return this; + } } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java index 7c7bcdae08..f731b5ff91 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java @@ -251,6 +251,11 @@ public class GetDiff implements RestReadView { return links.isEmpty() ? null : links.toList(); } + public GetDiff setBase(String base) { + this.base = base; + return this; + } + private static class Content { final List lines; final SparseFileContent fileA;