summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGoran Lungberg <goeran.lungberg@sonyericsson.com>2010-05-25 08:49:00 +0200
committerShawn O. Pearce <sop@google.com>2010-06-15 18:26:56 -0700
commit56f76b2bd01bc95fbcfa5cb9cbb3afa2c75eb9a6 (patch)
tree93529db7b7a7bf9b9e4f31738344d14a2e268b12
parent04132a143f91fa0fc1df54cb7caced6d75f7ded8 (diff)
Visualize in which revisions a merged change is included
Introduced a new "Included in" panel on merged changes. The panel will produce sorted lists all branches and tags which contains the merged change. Provides a simple way for users to determine in which revisions of the project the change is included. Change-Id: If94b2604607f53a2e45330b56d55cc5de8288054
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java2
-rw-r--r--gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java44
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java4
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties4
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java16
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java85
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java9
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java1
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java111
9 files changed, 276 insertions, 0 deletions
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
index 1f63adf7b1..4d362fe0b8 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
@@ -26,6 +26,8 @@ import com.google.gwtjsonrpc.client.RpcImpl.Version;
public interface ChangeDetailService extends RemoteJsonService {
void changeDetail(Change.Id id, AsyncCallback<ChangeDetail> callback);
+ void includedInDetail(Change.Id id, AsyncCallback<IncludedInDetail> callback);
+
void patchSetDetail(PatchSet.Id key, AsyncCallback<PatchSetDetail> callback);
@SignInRequired
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java
new file mode 100644
index 0000000000..9365db8416
--- /dev/null
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java
@@ -0,0 +1,44 @@
+// Copyright (C) 2010 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.common.data;
+
+import java.util.Collections;
+import java.util.List;
+
+public class IncludedInDetail {
+ private List<String> branches;
+ private List<String> tags;
+
+ public IncludedInDetail() {
+ }
+
+ public void setBranches(final List<String> b) {
+ Collections.sort(b);
+ branches = b;
+ }
+
+ public List<String> getBranches() {
+ return branches;
+ }
+
+ public void setTags(final List<String> t) {
+ Collections.sort(t);
+ tags = t;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index fed0927ca6..4e34d25f13 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -63,6 +63,7 @@ public interface ChangeConstants extends Constants {
String prevPatchLinkIcon();
String nextPatchLinkIcon();
+ String changeScreenIncludedIn();
String changeScreenDependencies();
String changeScreenDependsOn();
String changeScreenNeededBy();
@@ -79,6 +80,9 @@ public interface ChangeConstants extends Constants {
String changeInfoBlockStatus();
String changePermalink();
+ String includedInTableBranch();
+ String includedInTableTag();
+
String messageNoAuthor();
String messageExpandRecent();
String messageExpandAll();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 155d6575e7..7211c9498f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -40,6 +40,7 @@ patchTablePrev = Previous file
patchTableNext = Next file
patchTableOpen = Open file
+changeScreenIncludedIn = Included in
changeScreenDependencies = Dependencies
changeScreenDependsOn = Depends On
changeScreenNeededBy = Needed By
@@ -56,6 +57,9 @@ changeInfoBlockUpdated = Updated
changeInfoBlockStatus = Status
changePermalink = Permalink
+includedInTableBranch = Branch Name
+includedInTableTag = Tag Name
+
messageNoAuthor = Gerrit Code Review
messageExpandRecent = Expand Recent
messageExpandAll = Expand All
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
index 9288788d50..a700dd8ea2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
@@ -34,6 +34,7 @@ import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.Change.Status;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -64,6 +65,8 @@ public class ChangeScreen extends Screen {
private ChangeDescriptionBlock descriptionBlock;
private ApprovalTable approvals;
+ private IncludedInTable includedInTable;
+ private DisclosurePanel includedInPanel;
private DisclosurePanel dependenciesPanel;
private ChangeTable dependencies;
private ChangeTable.Section dependsOn;
@@ -171,6 +174,12 @@ public class ChangeScreen extends Screen {
approvals = new ApprovalTable();
add(approvals);
+ includedInPanel = new DisclosurePanel(Util.C.changeScreenIncludedIn());
+ includedInTable = new IncludedInTable(changeId);
+
+ includedInPanel.setContent(includedInTable);
+ add(includedInPanel);
+
dependencies = new ChangeTable() {
{
table.setWidth("98%");
@@ -219,6 +228,13 @@ public class ChangeScreen extends Screen {
setStarred(detail.isStarred());
}
+ if (Status.MERGED == detail.getChange().getStatus()) {
+ includedInPanel.setVisible(true);
+ includedInPanel.addOpenHandler(includedInTable);
+ } else {
+ includedInPanel.setVisible(false);
+ }
+
dependencies.setAccountInfoCache(detail.getAccounts());
approvals.setAccountInfoCache(detail.getAccounts());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java
new file mode 100644
index 0000000000..533999d326
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java
@@ -0,0 +1,85 @@
+// Copyright (C) 2010 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.changes;
+
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.rpc.GerritCallback;
+import com.google.gerrit.common.data.IncludedInDetail;
+import com.google.gerrit.reviewdb.Change;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+
+
+/** Displays a table of Branches and Tags containing the change record. */
+public class IncludedInTable extends Composite implements
+ OpenHandler<DisclosurePanel> {
+ private final Grid table;
+ private final Change.Id changeId;
+ private boolean loaded = false;
+
+ public IncludedInTable(final Change.Id chId) {
+ changeId = chId;
+ table = new Grid(1, 1);
+ initWidget(table);
+ }
+
+ public void loadTable(final IncludedInDetail detail) {
+ int row = 0;
+ table.resizeRows(detail.getBranches().size() + 1);
+ table.addStyleName(Gerrit.RESOURCES.css().changeTable());
+ final CellFormatter fmt = table.getCellFormatter();
+ fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().dataHeader());
+ table.setText(row, 0, Util.C.includedInTableBranch());
+
+ for (final String branch : detail.getBranches()) {
+ fmt.addStyleName(++row, 0, Gerrit.RESOURCES.css().dataCell());
+ fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().leftMostCell());
+ table.setText(row, 0, branch);
+ }
+
+ if (!detail.getTags().isEmpty()) {
+ table.resizeRows(table.getRowCount() + 2 + detail.getTags().size());
+ row++;
+ fmt.addStyleName(++row, 0, Gerrit.RESOURCES.css().dataHeader());
+ table.setText(row, 0, Util.C.includedInTableTag());
+
+ for (final String tag : detail.getTags()) {
+ fmt.addStyleName(++row, 0, Gerrit.RESOURCES.css().dataCell());
+ fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().leftMostCell());
+ table.setText(row, 0, tag);
+ }
+ }
+
+ table.setVisible(true);
+ loaded = true;
+ }
+
+ @Override
+ public void onOpen(OpenEvent<DisclosurePanel> event) {
+ if (!loaded) {
+ Util.DETAIL_SVC.includedInDetail(changeId,
+ new GerritCallback<IncludedInDetail>() {
+ @Override
+ public void onSuccess(final IncludedInDetail result) {
+ loadTable(result);
+ }
+ });
+ }
+ }
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
index 12fc41d5fc..ebb4502933 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
@@ -16,6 +16,7 @@ package com.google.gerrit.httpd.rpc.changedetail;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ChangeDetailService;
+import com.google.gerrit.common.data.IncludedInDetail;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.common.data.PatchSetPublishDetail;
import com.google.gerrit.reviewdb.Change;
@@ -25,14 +26,17 @@ import com.google.inject.Inject;
class ChangeDetailServiceImpl implements ChangeDetailService {
private final ChangeDetailFactory.Factory changeDetail;
+ private final IncludedInDetailFactory.Factory includedInDetail;
private final PatchSetDetailFactory.Factory patchSetDetail;
private final PatchSetPublishDetailFactory.Factory patchSetPublishDetail;
@Inject
ChangeDetailServiceImpl(final ChangeDetailFactory.Factory changeDetail,
+ final IncludedInDetailFactory.Factory includedInDetail,
final PatchSetDetailFactory.Factory patchSetDetail,
final PatchSetPublishDetailFactory.Factory patchSetPublishDetail) {
this.changeDetail = changeDetail;
+ this.includedInDetail = includedInDetail;
this.patchSetDetail = patchSetDetail;
this.patchSetPublishDetail = patchSetPublishDetail;
}
@@ -42,6 +46,11 @@ class ChangeDetailServiceImpl implements ChangeDetailService {
changeDetail.create(id).to(callback);
}
+ public void includedInDetail(final Change.Id id,
+ final AsyncCallback<IncludedInDetail> callback) {
+ includedInDetail.create(id).to(callback);
+ }
+
public void patchSetDetail(final PatchSet.Id id,
final AsyncCallback<PatchSetDetail> callback) {
patchSetDetail.create(id).to(callback);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
index 211f505337..8605de398c 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
@@ -30,6 +30,7 @@ public class ChangeModule extends RpcServletModule {
protected void configure() {
factory(AbandonChange.Factory.class);
factory(ChangeDetailFactory.Factory.class);
+ factory(IncludedInDetailFactory.Factory.class);
factory(PatchSetDetailFactory.Factory.class);
factory(PatchSetPublishDetailFactory.Factory.class);
factory(SubmitAction.Factory.class);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java
new file mode 100644
index 0000000000..b49a07871f
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java
@@ -0,0 +1,111 @@
+// Copyright (C) 2010 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.httpd.rpc.changedetail;
+
+import com.google.gerrit.common.data.IncludedInDetail;
+import com.google.gerrit.common.errors.InvalidRevisionException;
+import com.google.gerrit.common.errors.NoSuchEntityException;
+import com.google.gerrit.httpd.rpc.Handler;
+import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.client.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/** Creates a {@link IncludedInDetail} of a {@link Change}. */
+class IncludedInDetailFactory extends Handler<IncludedInDetail> {
+ interface Factory {
+ IncludedInDetailFactory create(Change.Id id);
+ }
+
+ private final ReviewDb db;
+ private final ChangeControl.Factory changeControlFactory;
+ private final GitRepositoryManager repoManager;
+ private final Change.Id changeId;
+
+ private IncludedInDetail detail;
+ private ChangeControl control;
+
+ @Inject
+ IncludedInDetailFactory(final ReviewDb db,
+ final ChangeControl.Factory changeControlFactory,
+ final GitRepositoryManager repoManager, @Assisted final Change.Id changeId) {
+ this.changeControlFactory = changeControlFactory;
+ this.repoManager = repoManager;
+ this.changeId = changeId;
+ this.db = db;
+ }
+
+ @Override
+ public IncludedInDetail call() throws OrmException, NoSuchChangeException,
+ NoSuchEntityException, IOException, InvalidRevisionException {
+ control = changeControlFactory.validateFor(changeId);
+ final PatchSet patch =
+ db.patchSets().get(control.getChange().currentPatchSetId());
+ final Repository repo =
+ repoManager.openRepository(control.getProject().getName());
+ final Map<String, Ref> refsHeads =
+ repo.getRefDatabase().getRefs(Constants.R_HEADS);
+ final Map<String, Ref> refsTags =
+ repo.getRefDatabase().getRefs(Constants.R_TAGS);
+ RevWalk rw = new RevWalk(repo);
+
+ try {
+ final RevCommit rev =
+ rw.parseCommit(ObjectId.fromString(patch.getRevision().get()));
+ final List<String> branches = new ArrayList<String>();
+ for (final String branch : refsHeads.keySet()) {
+ if (rw.isMergedInto(rev, rw.parseCommit(refsHeads.get(branch)
+ .getObjectId()))) {
+ branches.add(branch);
+ }
+ }
+ final List<String> tags = new ArrayList<String>();
+ for (final String tag : refsTags.keySet()) {
+ if (rw.isMergedInto(rev, rw
+ .parseCommit(refsTags.get(tag).getObjectId()))) {
+ tags.add(tag);
+ }
+ }
+ detail = new IncludedInDetail();
+ detail.setBranches(branches);
+ detail.setTags(tags);
+
+ return detail;
+ } catch (IncorrectObjectTypeException err) {
+ throw new InvalidRevisionException();
+ } catch (MissingObjectException err) {
+ throw new InvalidRevisionException();
+ }
+ }
+}