diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java index abcdf3fea1..39bbab338f 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java @@ -59,6 +59,7 @@ import com.google.inject.Inject; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.StringUtils; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.RefUpdate; import org.joda.time.DateTime; @@ -194,10 +195,10 @@ public class ChangeEditIT extends AbstractDaemonTest { Date beforeRebase = edit.getEditCommit().getCommitterIdent().getWhen(); modifier.rebaseEdit(edit, current); edit = editUtil.byChange(change).get(); - assertByteArray(fileUtil.getContent(edit.getChange().getProject(), edit - .getRevision().get(), FILE_NAME), CONTENT_NEW); - assertByteArray(fileUtil.getContent(edit.getChange().getProject(), edit - .getRevision().get(), FILE_NAME2), CONTENT_NEW2); + assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()), + ObjectId.fromString(edit.getRevision().get()), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()), + ObjectId.fromString(edit.getRevision().get()), FILE_NAME2), CONTENT_NEW2); assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo( current.getPatchSetId()); Date afterRebase = edit.getEditCommit().getCommitterIdent().getWhen(); @@ -218,10 +219,10 @@ public class ChangeEditIT extends AbstractDaemonTest { RestResponse r = adminSession.post(urlRebase()); assertThat(r.getStatusCode()).isEqualTo(SC_NO_CONTENT); edit = editUtil.byChange(change).get(); - assertByteArray(fileUtil.getContent(edit.getChange().getProject(), edit - .getRevision().get(), FILE_NAME), CONTENT_NEW); - assertByteArray(fileUtil.getContent(edit.getChange().getProject(), edit - .getRevision().get(), FILE_NAME2), CONTENT_NEW2); + assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()), + ObjectId.fromString(edit.getRevision().get()), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.getChange().getProject()), + ObjectId.fromString(edit.getRevision().get()), FILE_NAME2), CONTENT_NEW2); assertThat(edit.getBasePatchSet().getPatchSetId()).isEqualTo( current.getPatchSetId()); Date afterRebase = edit.getEditCommit().getCommitterIdent().getWhen(); @@ -235,9 +236,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RestSession.newRawInput(CONTENT_NEW))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW); editUtil.delete(edit.get()); edit = editUtil.byChange(change); assertThat(edit.isPresent()).isFalse(); @@ -364,8 +364,8 @@ public class ChangeEditIT extends AbstractDaemonTest { RefUpdate.Result.FORCED); edit = editUtil.byChange(change); try { - fileUtil.getContent(edit.get().getChange().getProject(), - edit.get().getRevision().get(), FILE_NAME); + fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME); fail("ResourceNotFoundException expected"); } catch (ResourceNotFoundException rnfe) { } @@ -377,8 +377,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(r.getStatusCode()).isEqualTo(SC_NO_CONTENT); Optional edit = editUtil.byChange(change); try { - fileUtil.getContent(edit.get().getChange().getProject(), - edit.get().getRevision().get(), FILE_NAME); + fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME); fail("ResourceNotFoundException expected"); } catch (ResourceNotFoundException rnfe) { } @@ -397,8 +397,8 @@ public class ChangeEditIT extends AbstractDaemonTest { SC_NO_CONTENT); Optional edit = editUtil.byChange(change); try { - fileUtil.getContent(edit.get().getChange().getProject(), - edit.get().getRevision().get(), FILE_NAME); + fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME); fail("ResourceNotFoundException expected"); } catch (ResourceNotFoundException rnfe) { } @@ -412,9 +412,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(modifier.restoreFile(edit.get(), FILE_NAME)).isEqualTo( RefUpdate.Result.FORCED); edit = editUtil.byChange(change2); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_OLD); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD); } @Test @@ -424,9 +423,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(adminSession.post(urlEdit2(), in).getStatusCode()).isEqualTo( SC_NO_CONTENT); Optional edit = editUtil.byChange(change2); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_OLD); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD); } @Test @@ -436,15 +434,13 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RestSession.newRawInput(CONTENT_NEW))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW); assertThat(modifier.modifyFile(edit.get(), FILE_NAME, RestSession.newRawInput(CONTENT_NEW2))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW2); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW2); } @Test @@ -454,16 +450,14 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(adminSession.putRaw(urlEditFile(), in.content).getStatusCode()) .isEqualTo(SC_NO_CONTENT); Optional edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW); in.content = RestSession.newRawInput(CONTENT_NEW2); assertThat(adminSession.putRaw(urlEditFile(), in.content).getStatusCode()) .isEqualTo(SC_NO_CONTENT); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW2); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW2); } @Test @@ -474,9 +468,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(adminSession.putRaw(urlEditFile(), in.content).getStatusCode()) .isEqualTo(SC_NO_CONTENT); Optional edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_NEW); } @Test @@ -485,9 +478,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(adminSession.put(urlEditFile()).getStatusCode()).isEqualTo( SC_NO_CONTENT); Optional edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), "".getBytes()); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), "".getBytes()); } @Test @@ -495,9 +487,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(adminSession.post(urlEdit()).getStatusCode()).isEqualTo( SC_NO_CONTENT); Optional edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME), CONTENT_OLD); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME), CONTENT_OLD); } @Test @@ -536,8 +527,8 @@ public class ChangeEditIT extends AbstractDaemonTest { SC_NO_CONTENT); Optional edit = editUtil.byChange(change); try { - fileUtil.getContent(edit.get().getChange().getProject(), - edit.get().getRevision().get(), FILE_NAME); + fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME); fail("ResourceNotFoundException expected"); } catch (ResourceNotFoundException rnfe) { } @@ -552,9 +543,8 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RestSession.newRawInput(CONTENT_NEW))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME2), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW); } @Test @@ -564,15 +554,13 @@ public class ChangeEditIT extends AbstractDaemonTest { assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RestSession.newRawInput(CONTENT_NEW))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME2), CONTENT_NEW); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW); assertThat(modifier.modifyFile(edit.get(), FILE_NAME2, RestSession.newRawInput(CONTENT_NEW2))) .isEqualTo(RefUpdate.Result.FORCED); edit = editUtil.byChange(change); - assertByteArray( - fileUtil.getContent(edit.get().getChange().getProject(), edit.get() - .getRevision().get(), FILE_NAME2), CONTENT_NEW2); + assertByteArray(fileUtil.getContent(projectCache.get(edit.get().getChange().getProject()), + ObjectId.fromString(edit.get().getRevision().get()), FILE_NAME2), CONTENT_NEW2); } @Test diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTextBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTextBox.java index 52d2a259f9..136998de68 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTextBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTextBox.java @@ -16,6 +16,9 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.changes.ChangeFileApi; import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.HttpCallback; +import com.google.gerrit.client.rpc.HttpResponse; +import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gwt.event.dom.client.BlurEvent; @@ -51,10 +54,10 @@ class FileTextBox extends NpTextBox { } private void loadFileContent() { - ChangeFileApi.getContent(id, getText(), new GerritCallback() { + ChangeFileApi.getContent(id, getText(), new HttpCallback() { @Override - public void onSuccess(String result) { - textArea.setText(result); + public void onSuccess(HttpResponse result) { + textArea.setText(result.getResult().asString()); } @Override @@ -62,7 +65,7 @@ class FileTextBox extends NpTextBox { if (RestApi.isNotFound(caught)) { // that means that the file doesn't exist in the repository } else { - super.onFailure(caught); + GerritCallback.showFailure(caught); } } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeFileApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeFileApi.java index c25f0cfee0..9ac11e4a52 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeFileApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeFileApi.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.changes; import com.google.gerrit.client.VoidResult; import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.HttpCallback; import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.reviewdb.client.Change; @@ -29,52 +30,10 @@ import com.google.gwt.user.client.rpc.AsyncCallback; * files in a change. */ public class ChangeFileApi { - static abstract class CallbackWrapper implements AsyncCallback { - protected AsyncCallback wrapped; - - public CallbackWrapper(AsyncCallback callback) { - wrapped = callback; - } - - @Override - public abstract void onSuccess(I result); - - @Override - public void onFailure(Throwable caught) { - wrapped.onFailure(caught); - } - } - - private static CallbackWrapper wrapper( - AsyncCallback cb) { - return new CallbackWrapper(cb) { - @Override - public void onSuccess(NativeString b64) { - if (b64 != null) { - wrapped.onSuccess(b64decode(b64.asString())); - } - } - }; - } - /** Get the contents of a File in a PatchSet or change edit. */ public static void getContent(PatchSet.Id id, String filename, - AsyncCallback cb) { - contentEditOrPs(id, filename).get(wrapper(cb)); - } - - /** Get the content type of a File in a PatchSet or change edit. */ - public static void getContentType(PatchSet.Id id, String filename, - AsyncCallback cb) { - contentTypeEditOrPs(id, filename).get( - new CallbackWrapper(cb) { - @Override - public void onSuccess(NativeString str) { - if (str != null) { - wrapped.onSuccess(str.asString()); - } - } - }); + HttpCallback cb) { + contentEditOrPs(id, filename).get(cb); } /** @@ -82,11 +41,11 @@ public class ChangeFileApi { * edit. **/ public static void getContentOrMessage(PatchSet.Id id, String path, - AsyncCallback cb) { + HttpCallback cb) { RestApi api = (Patch.COMMIT_MSG.equals(path) && id.get() == 0) ? messageEdit(id) : contentEditOrPs(id, path); - api.get(wrapper(cb)); + api.get(cb); } /** Put contents into a File in a change edit. */ @@ -141,18 +100,10 @@ public class ChangeFileApi { return ChangeApi.change(id.getParentKey().get()).view("edit:message"); } - private static RestApi contentTypeEditOrPs(PatchSet.Id id, String filename) { - return id.get() == 0 - ? contentEdit(id.getParentKey(), filename).view("type") - : ChangeApi.revision(id).view("files").id(filename).view("type"); - } - private static RestApi contentEdit(Change.Id id, String filename) { return ChangeApi.edit(id.get()).id(filename); } - private static native String b64decode(String a) /*-{ return window.atob(a); }-*/; - private static class Input extends JavaScriptObject { final native void restore_path(String p) /*-{ if(p)this.restore_path=p; }-*/; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java index 70855ce8c7..ee77e02370 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java @@ -25,6 +25,9 @@ import com.google.gerrit.client.diff.FileInfo; import com.google.gerrit.client.diff.Header; import com.google.gerrit.client.rpc.CallbackGroup; import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.HttpCallback; +import com.google.gerrit.client.rpc.HttpResponse; +import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.Screen; import com.google.gerrit.common.PageLinks; @@ -68,7 +71,7 @@ public class EditScreen extends Screen { private final String path; private DiffPreferences prefs; private CodeMirror cm; - private String type; + private HttpResponse content; @UiField Element header; @UiField Element project; @@ -116,20 +119,6 @@ public class EditScreen extends Screen { } })); - if (prefs.syntaxHighlighting() && !Patch.COMMIT_MSG.equals(path)) { - final AsyncCallback modeInjectorCb = group.addEmpty(); - ChangeFileApi.getContentType(revision, path, - cmGroup.add(new GerritCallback() { - @Override - public void onSuccess(String result) { - ModeInfo mode = ModeInfo.findMode(result, path); - type = mode != null ? mode.mime() : null; - injectMode(result, modeInjectorCb); - } - })); - } - cmGroup.done(); - ChangeApi.detail(revision.getParentKey().get(), group.add(new GerritCallback() { @Override @@ -140,12 +129,34 @@ public class EditScreen extends Screen { })); ChangeFileApi.getContentOrMessage(revision, path, - group.addFinal(new ScreenLoadCallback(this) { + cmGroup.add(new HttpCallback() { + final AsyncCallback modeCallback = group.addEmpty(); + @Override - protected void preDisplay(String content) { - initEditor(content); + public void onSuccess(HttpResponse fc) { + content = fc; + if (prefs.syntaxHighlighting()) { + injectMode(fc.getContentType(), modeCallback); + } else { + modeCallback.onSuccess(null); + } + } + + @Override + public void onFailure(Throwable e) { + GerritCallback.showFailure(e); } })); + + group.addListener(new ScreenLoadCallback(this) { + @Override + protected void preDisplay(Void result) { + initEditor(content); + content = null; + } + }); + cmGroup.done(); + group.done(); } @Override @@ -223,12 +234,12 @@ public class EditScreen extends Screen { Gerrit.display(PageLinks.toChangeInEditMode(revision.getParentKey())); } - private void initEditor(String content) { + private void initEditor(HttpResponse file) { ModeInfo mode = prefs.syntaxHighlighting() - ? ModeInfo.findMode(type, path) + ? ModeInfo.findMode(file.getContentType(), path) : null; cm = CodeMirror.create(editor, Configuration.create() - .set("value", content) + .set("value", file.getResult().asString()) .set("readOnly", false) .set("cursorBlinkRate", 0) .set("cursorHeight", 0.85) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java index 6a9ddb5fe5..071ca72376 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/CallbackGroup.java @@ -42,8 +42,8 @@ import java.util.Set; * processing it. */ public class CallbackGroup { - private final List> callbacks; - private final Set> remaining; + private final List callbacks; + private final Set remaining; private boolean finalAdded; private boolean failed; @@ -76,6 +76,27 @@ public class CallbackGroup { return handleAdd(cb); } + public HttpCallback add(HttpCallback cb) { + checkFinalAdded(); + if (failed) { + cb.onFailure(failedThrowable); + return new HttpCallback() { + @Override + public void onSuccess(HttpResponse result) { + } + + @Override + public void onFailure(Throwable caught) { + } + }; + } + + HttpCallbackImpl w = new HttpCallbackImpl<>(cb); + callbacks.add(w); + remaining.add(w); + return w; + } + public Callback addFinal(final AsyncCallback cb) { checkFinalAdded(); finalAdded = true; @@ -84,7 +105,7 @@ public class CallbackGroup { public void done() { finalAdded = true; - applyAllSuccess(); + apply(); } public void addListener(AsyncCallback cb) { @@ -99,19 +120,30 @@ public class CallbackGroup { addListener(group. addEmpty()); } - private void applyAllSuccess() { - if (!failed && finalAdded && remaining.isEmpty()) { - for (CallbackImpl cb : callbacks) { - cb.applySuccess(); - } - callbacks.clear(); - } + private void success(CallbackGlue cb) { + remaining.remove(cb); + apply(); } - private void applyAllFailed() { - if (failed && finalAdded && remaining.isEmpty()) { - for (CallbackImpl cb : callbacks) { - cb.applyFailed(); + private void failure(CallbackGlue w, Throwable caught) { + if (!failed) { + failed = true; + failedThrowable = caught; + } + remaining.remove(w); + apply(); + } + + private void apply() { + if (finalAdded && remaining.isEmpty()) { + if (failed) { + for (CallbackGlue cb : callbacks) { + cb.applyFailed(); + } + } else { + for (CallbackGlue cb : callbacks) { + cb.applySuccess(); + } } callbacks.clear(); } @@ -139,7 +171,12 @@ public class CallbackGroup { extends AsyncCallback, com.google.gwtjsonrpc.common.AsyncCallback { } - private class CallbackImpl implements Callback { + private interface CallbackGlue { + void applySuccess(); + void applyFailed(); + } + + private class CallbackImpl implements Callback, CallbackGlue { AsyncCallback delegate; T result; @@ -150,21 +187,16 @@ public class CallbackGroup { @Override public void onSuccess(T value) { this.result = value; - remaining.remove(this); - CallbackGroup.this.applyAllSuccess(); + success(this); } @Override public void onFailure(Throwable caught) { - if (!failed) { - failed = true; - failedThrowable = caught; - } - remaining.remove(this); - CallbackGroup.this.applyAllFailed(); + failure(this, caught); } - void applySuccess() { + @Override + public void applySuccess() { AsyncCallback cb = delegate; if (cb != null) { delegate = null; @@ -173,7 +205,8 @@ public class CallbackGroup { } } - void applyFailed() { + @Override + public void applyFailed() { AsyncCallback cb = delegate; if (cb != null) { delegate = null; @@ -182,4 +215,44 @@ public class CallbackGroup { } } } + + private class HttpCallbackImpl implements HttpCallback, CallbackGlue { + private HttpCallback delegate; + private HttpResponse result; + + HttpCallbackImpl(HttpCallback delegate) { + this.delegate = delegate; + } + + @Override + public void onSuccess(HttpResponse result) { + this.result = result; + success(this); + } + + @Override + public void onFailure(Throwable caught) { + failure(this, caught); + } + + @Override + public void applySuccess() { + HttpCallback cb = delegate; + if (cb != null) { + delegate = null; + cb.onSuccess(result); + result = null; + } + } + + @Override + public void applyFailed() { + HttpCallback cb = delegate; + if (cb != null) { + delegate = null; + result = null; + cb.onFailure(failedThrowable); + } + } + } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java index 08ff7d9575..bccd237bff 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java @@ -23,7 +23,6 @@ import com.google.gerrit.common.errors.NoSuchAccountException; import com.google.gerrit.common.errors.NoSuchEntityException; import com.google.gerrit.common.errors.NoSuchGroupException; import com.google.gerrit.common.errors.NotSignedInException; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.InvocationException; import com.google.gwtjsonrpc.client.RemoteJsonException; import com.google.gwtjsonrpc.client.ServerUnavailableException; @@ -35,6 +34,10 @@ public abstract class GerritCallback implements com.google.gwt.user.client.rpc.AsyncCallback { @Override public void onFailure(final Throwable caught) { + showFailure(caught); + } + + public static void showFailure(Throwable caught) { if (isNotSignedIn(caught) || isInvalidXSRF(caught)) { new NotSignedInDialog().center(); @@ -70,7 +73,6 @@ public abstract class GerritCallback implements new ErrorDialog(RpcConstants.C.errorServerUnavailable()).center(); } else { - GWT.log(getClass().getName() + " caught " + caught, caught); new ErrorDialog(caught).center(); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java new file mode 100644 index 0000000000..a97642edd1 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpCallback.java @@ -0,0 +1,21 @@ +// Copyright (C) 2015 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.client.rpc; + +/** AsyncCallback supplied with HTTP response headers. */ +public interface HttpCallback { + void onSuccess(HttpResponse result); + void onFailure(Throwable caught); +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java new file mode 100644 index 0000000000..969dd30931 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/HttpResponse.java @@ -0,0 +1,56 @@ +// Copyright (C) 2015 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.client.rpc; + +import com.google.gwt.http.client.Response; + +/** Wraps decoded server reply with HTTP headers. */ +public class HttpResponse { + private final Response httpResponse; + private final String contentType; + private final T result; + + HttpResponse(Response httpResponse, String contentType, T result) { + this.httpResponse = httpResponse; + this.contentType = contentType; + this.result = result; + } + + /** HTTP status code, always in the 2xx family. */ + public int getStatusCode() { + return httpResponse.getStatusCode(); + } + + /** + * Content type supplied by the server. + * + * This helper simplifies the common {@code getHeader("Content-Type")} case. + */ + public String getContentType() { + return contentType; + } + + /** Lookup an arbitrary reply header. */ + public String getHeader(String header) { + if ("Content-Type".equals(header)) { + return contentType; + } + return httpResponse.getHeader(header); + } + + public T getResult() { + return result; + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java index b677276d49..e87853bff5 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java @@ -104,21 +104,21 @@ public class RestApi { } } - private static class HttpCallback + private static class HttpImpl implements RequestCallback { private final boolean background; - private final AsyncCallback cb; + private final HttpCallback cb; - HttpCallback(boolean bg, AsyncCallback cb) { + HttpImpl(boolean bg, HttpCallback cb) { this.background = bg; this.cb = cb; } @Override - public void onResponseReceived(Request req, Response res) { + public void onResponseReceived(Request req, final Response res) { int status = res.getStatusCode(); if (status == Response.SC_NO_CONTENT) { - cb.onSuccess(null); + cb.onSuccess(new HttpResponse(res, null, null)); if (!background) { RpcStatus.INSTANCE.onRpcComplete(); } @@ -126,12 +126,12 @@ public class RestApi { } else if (200 <= status && status < 300) { long start = System.currentTimeMillis(); final T data; - if (isTextBody(res)) { - data = NativeString.wrap(res.getText()).cast(); - } else if (isJsonBody(res)) { + final String type; + if (isJsonBody(res)) { try { // javac generics bug - data = RestApi.cast(parseJson(res)); + data = RestApi. cast(parseJson(res)); + type = JSON_TYPE; } catch (JSONException e) { if (!background) { RpcStatus.INSTANCE.onRpcComplete(); @@ -140,6 +140,12 @@ public class RestApi { "Invalid JSON: " + e.getMessage())); return; } + } else if (isEncodedBase64(res)) { + data = NativeString.wrap(decodeBase64(res.getText())).cast(); + type = simpleType(res.getHeader("X-FYI-Content-Type")); + } else if (isTextBody(res)) { + data = NativeString.wrap(res.getText()).cast(); + type = TEXT_TYPE; } else { if (!background) { RpcStatus.INSTANCE.onRpcComplete(); @@ -154,7 +160,7 @@ public class RestApi { @Override public void execute() { try { - cb.onSuccess(data); + cb.onSuccess(new HttpResponse<>(res, type, data)); } finally { if (!background) { RpcStatus.INSTANCE.onRpcComplete(); @@ -318,21 +324,24 @@ public class RestApi { } public void get(AsyncCallback cb) { + get(wrap(cb)); + } + + public void get(HttpCallback cb) { send(GET, cb); } public void delete(AsyncCallback cb) { + delete(wrap(cb)); + } + + public void delete(HttpCallback cb) { send(DELETE, cb); } - public void delete(JavaScriptObject content, - AsyncCallback cb) { - sendJSON(DELETE, content, cb); - } - - private void send( - Method method, AsyncCallback cb) { - HttpCallback httpCallback = new HttpCallback<>(background, cb); + private void send(Method method, + HttpCallback cb) { + HttpImpl httpCallback = new HttpImpl<>(background, cb); try { if (!background) { RpcStatus.INSTANCE.onRpcStart(); @@ -346,33 +355,59 @@ public class RestApi { public void post( JavaScriptObject content, AsyncCallback cb) { + post(content, wrap(cb)); + } + + public void post( + JavaScriptObject content, + HttpCallback cb) { sendJSON(POST, content, cb); } public void post(String content, AsyncCallback cb) { + post(content, wrap(cb)); + } + + public void post(String content, + HttpCallback cb) { sendRaw(POST, content, cb); } public void put(AsyncCallback cb) { + put(wrap(cb)); + } + + public void put(HttpCallback cb) { send(PUT, cb); } public void put(String content, AsyncCallback cb) { + put(content, wrap(cb)); + } + + public void put(String content, + HttpCallback cb) { sendRaw(PUT, content, cb); } public void put( JavaScriptObject content, AsyncCallback cb) { + put(content, wrap(cb)); + } + + public void put( + JavaScriptObject content, + HttpCallback cb) { sendJSON(PUT, content, cb); } private void sendJSON( Method method, JavaScriptObject content, - AsyncCallback cb) { - HttpCallback httpCallback = new HttpCallback<>(background, cb); + HttpCallback cb) { + HttpImpl httpCallback = new HttpImpl<>(background, cb); try { if (!background) { RpcStatus.INSTANCE.onRpcStart(); @@ -385,11 +420,15 @@ public class RestApi { } } - private static native String str(JavaScriptObject jso) /*-{ return JSON.stringify(jso); }-*/; + private static native String str(JavaScriptObject jso) + /*-{ return JSON.stringify(jso) }-*/; + + private static native String decodeBase64(String a) + /*-{ return $wnd.atob(a) }-*/; private void sendRaw(Method method, String body, - AsyncCallback cb) { - HttpCallback httpCallback = new HttpCallback<>(background, cb); + HttpCallback cb) { + HttpImpl httpCallback = new HttpImpl<>(background, cb); try { if (!background) { RpcStatus.INSTANCE.onRpcStart(); @@ -422,16 +461,22 @@ public class RestApi { return isContentType(res, TEXT_TYPE); } + private static boolean isEncodedBase64(Response res) { + return "base64".equals(res.getHeader("X-FYI-Content-Encoding")) + && isTextBody(res); + } + private static boolean isContentType(Response res, String want) { String type = res.getHeader("Content-Type"); - if (type == null) { - return false; - } + return type != null && want.equals(simpleType(type)); + } + + private static String simpleType(String type) { int semi = type.indexOf(';'); if (semi >= 0) { - type = type.substring(0, semi).trim(); + return type.substring(0, semi).trim(); } - return want.equals(type); + return type; } private static JSONValue parseJson(Response res) @@ -464,4 +509,19 @@ public class RestApi { throw new JSONException("unsupported JSON type"); } } + + private static HttpCallback wrap( + final AsyncCallback cb) { + return new HttpCallback() { + @Override + public void onSuccess(HttpResponse r) { + cb.onSuccess(r.getResult()); + } + + @Override + public void onFailure(Throwable e) { + cb.onFailure(e); + } + }; + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java index 54ad1500dc..925c0edb0e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java @@ -52,6 +52,7 @@ import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.assistedinject.Assisted; +import org.eclipse.jgit.lib.ObjectId; import org.kohsuke.args4j.Option; import java.io.IOException; @@ -433,8 +434,8 @@ public class ChangeEdits implements throws ResourceNotFoundException, IOException { try { return Response.ok(fileContentUtil.getContent( - rsrc.getChangeEdit().getChange().getProject(), - rsrc.getChangeEdit().getRevision().get(), + rsrc.getControl().getProjectControl().getProjectState(), + ObjectId.fromString(rsrc.getChangeEdit().getRevision().get()), rsrc.getPath())); } catch (ResourceNotFoundException rnfe) { return Response.none(); @@ -502,8 +503,10 @@ public class ChangeEdits implements IOException, ResourceNotFoundException { Optional edit = editUtil.byChange(rsrc.getChange()); if (edit.isPresent()) { - return BinaryResult.create( - edit.get().getEditCommit().getFullMessage()).base64(); + String msg = edit.get().getEditCommit().getFullMessage(); + return BinaryResult.create(msg) + .setContentType(FileContentUtil.TEXT_X_GERRIT_COMMIT_MESSAGE) + .base64(); } throw new ResourceNotFoundException(); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java index dfa0336582..3968cbf24a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java @@ -20,7 +20,6 @@ import com.google.gerrit.common.data.PatchScript.FileMode; import com.google.gerrit.extensions.restapi.BinaryResult; import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.reviewdb.client.Patch; -import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.FileTypeRegistry; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.project.ProjectState; @@ -28,6 +27,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import org.eclipse.jgit.errors.LargeObjectException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; @@ -44,6 +44,7 @@ public class FileContentUtil { public static final String TEXT_X_GERRIT_COMMIT_MESSAGE = "text/x-gerrit-commit-message"; private static final String X_GIT_SYMLINK = "x-git/symlink"; private static final String X_GIT_GITLINK = "x-git/gitlink"; + private static final int MAX_SIZE = 5 << 20; private final GitRepositoryManager repoManager; private final FileTypeRegistry registry; @@ -55,28 +56,50 @@ public class FileContentUtil { this.registry = ftr; } - public BinaryResult getContent(Project.NameKey project, String revstr, + public BinaryResult getContent(ProjectState project, ObjectId revstr, String path) throws ResourceNotFoundException, IOException { - Repository repo = repoManager.openRepository(project); + Repository repo = openRepository(project); try { RevWalk rw = new RevWalk(repo); try { - RevCommit commit = rw.parseCommit(repo.resolve(revstr)); - TreeWalk tw = - TreeWalk.forPath(rw.getObjectReader(), path, - commit.getTree().getId()); + RevCommit commit = rw.parseCommit(revstr); + ObjectReader reader = rw.getObjectReader(); + TreeWalk tw = TreeWalk.forPath(reader, path, commit.getTree()); if (tw == null) { throw new ResourceNotFoundException(); } - final ObjectLoader object = repo.open(tw.getObjectId(0)); - @SuppressWarnings("resource") - BinaryResult result = new BinaryResult() { - @Override - public void writeTo(OutputStream os) throws IOException { - object.copyTo(os); - } - }; - return result.setContentLength(object.getSize()).base64(); + + org.eclipse.jgit.lib.FileMode mode = tw.getFileMode(0); + ObjectId id = tw.getObjectId(0); + if (mode == org.eclipse.jgit.lib.FileMode.GITLINK) { + return BinaryResult.create(id.name()) + .setContentType(X_GIT_GITLINK) + .base64(); + } + + final ObjectLoader obj = repo.open(id, OBJ_BLOB); + byte[] raw; + try { + raw = obj.getCachedBytes(MAX_SIZE); + } catch (LargeObjectException e) { + raw = null; + } + + BinaryResult result; + if (raw != null) { + result = BinaryResult.create(raw); + } else { + result = asBinaryResult(obj); + } + + String type; + if (mode == org.eclipse.jgit.lib.FileMode.SYMLINK) { + type = X_GIT_SYMLINK; + } else { + type = registry.getMimeType(path, raw).toString(); + type = resolveContentType(project, path, FileMode.FILE, type); + } + return result.setContentType(type).base64(); } finally { rw.release(); } @@ -85,10 +108,20 @@ public class FileContentUtil { } } + private static BinaryResult asBinaryResult(final ObjectLoader obj) { + @SuppressWarnings("resource") + BinaryResult result = new BinaryResult() { + @Override + public void writeTo(OutputStream os) throws IOException { + obj.copyTo(os); + } + }.setContentLength(obj.getSize()); + return result; + } + public String getContentType(ProjectState project, ObjectId rev, String path) throws ResourceNotFoundException, IOException { - Repository repo = - repoManager.openRepository(project.getProject().getNameKey()); + Repository repo = openRepository(project); try { RevWalk rw = new RevWalk(repo); try { @@ -109,7 +142,7 @@ public class FileContentUtil { ObjectLoader blob = reader.open(tw.getObjectId(0), OBJ_BLOB); byte[] raw; try { - raw = blob.getCachedBytes(5 << 20); + raw = blob.getCachedBytes(MAX_SIZE); } catch (LargeObjectException e) { raw = null; } @@ -147,4 +180,9 @@ public class FileContentUtil { throw new IllegalStateException("file mode: " + fileMode); } } + + private Repository openRepository(ProjectState project) + throws RepositoryNotFoundException, IOException { + return repoManager.openRepository(project.getProject().getNameKey()); + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java index 67c68fcdc3..810a3a6358 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetContent.java @@ -24,6 +24,8 @@ import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.eclipse.jgit.lib.ObjectId; + import java.io.IOException; @Singleton @@ -44,12 +46,14 @@ public class GetContent implements RestReadView { OrmException { String path = rsrc.getPatchKey().get(); if (Patch.COMMIT_MSG.equals(path)) { - return BinaryResult.create( - changeUtil.getMessage(rsrc.getRevision().getChange())).base64(); + String msg = changeUtil.getMessage(rsrc.getRevision().getChange()); + return BinaryResult.create(msg) + .setContentType(FileContentUtil.TEXT_X_GERRIT_COMMIT_MESSAGE) + .base64(); } return fileContentUtil.getContent( - rsrc.getRevision().getControl().getProject().getNameKey(), - rsrc.getRevision().getPatchSet().getRevision().get(), + rsrc.getRevision().getControl().getProjectControl().getProjectState(), + ObjectId.fromString(rsrc.getRevision().getPatchSet().getRevision().get()), path); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java index 6681d946f1..98531cec9f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java @@ -41,4 +41,8 @@ public class BranchResource extends ProjectResource { public String getRef() { return branchInfo.ref; } + + public String getRevision() { + return branchInfo.revision; + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitResource.java index 2543818685..36186a436d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitResource.java @@ -16,7 +16,6 @@ package com.google.gerrit.server.project; import com.google.gerrit.extensions.restapi.RestResource; import com.google.gerrit.extensions.restapi.RestView; -import com.google.gerrit.reviewdb.client.Project; import com.google.inject.TypeLiteral; import org.eclipse.jgit.revwalk.RevCommit; @@ -33,8 +32,8 @@ public class CommitResource implements RestResource { this.commit = commit; } - public Project.NameKey getProject() { - return project.getNameKey(); + public ProjectControl getProject() { + return project.getControl(); } public RevCommit getCommit() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java index c7c66759a7..47942be9f4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/FileResource.java @@ -16,28 +16,29 @@ package com.google.gerrit.server.project; import com.google.gerrit.extensions.restapi.RestResource; import com.google.gerrit.extensions.restapi.RestView; -import com.google.gerrit.reviewdb.client.Project; import com.google.inject.TypeLiteral; +import org.eclipse.jgit.lib.ObjectId; + public class FileResource implements RestResource { public static final TypeLiteral> FILE_KIND = new TypeLiteral>() {}; - private final Project.NameKey project; - private final String rev; + private final ProjectControl project; + private final ObjectId rev; private final String path; - public FileResource(Project.NameKey project, String rev, String path) { + public FileResource(ProjectControl project, ObjectId rev, String path) { this.project = project; this.rev = rev; this.path = path; } - public Project.NameKey getProject() { + public ProjectControl getProject() { return project; } - public String getRev() { + public ObjectId getRev() { return rev; } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java index f0544fef49..d0460d5652 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesCollection.java @@ -22,6 +22,8 @@ import com.google.gerrit.extensions.restapi.RestView; import com.google.inject.Inject; import com.google.inject.Singleton; +import org.eclipse.jgit.lib.ObjectId; + @Singleton public class FilesCollection implements ChildCollection { @@ -39,7 +41,10 @@ public class FilesCollection implements @Override public FileResource parse(BranchResource parent, IdString id) { - return new FileResource(parent.getNameKey(), parent.getRef(), id.get()); + return new FileResource( + parent.getControl(), + ObjectId.fromString(parent.getRevision()), + id.get()); } @Override diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesInCommitCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesInCommitCollection.java index f3832307a1..8e0aab8eb5 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesInCommitCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/FilesInCommitCollection.java @@ -40,8 +40,7 @@ public class FilesInCommitCollection implements @Override public FileResource parse(CommitResource parent, IdString id) throws ResourceNotFoundException { - return new FileResource(parent.getProject(), parent.getCommit().getName(), - id.get()); + return new FileResource(parent.getProject(), parent.getCommit(), id.get()); } @Override diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java index 00f25bc0f5..23e9e30f21 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetContent.java @@ -35,7 +35,9 @@ public class GetContent implements RestReadView { @Override public BinaryResult apply(FileResource rsrc) throws ResourceNotFoundException, IOException { - return fileContentUtil.getContent(rsrc.getProject(), rsrc.getRev(), + return fileContentUtil.getContent( + rsrc.getProject().getProjectState(), + rsrc.getRev(), rsrc.getPath()); } }