Merge "ls-projects command can show the project hierarchy"
diff --git a/ReleaseNotes/ReleaseNotes-2.1.2.5.txt b/ReleaseNotes/ReleaseNotes-2.1.2.5.txt
new file mode 100644
index 0000000..1cd5ae8
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.1.2.5.txt
@@ -0,0 +1,24 @@
+Release notes for Gerrit 2.1.2.5
+================================
+
+Gerrit 2.1.2.5 is now available in the usual location:
+
+link:http://code.google.com/p/gerrit/downloads/list[http://code.google.com/p/gerrit/downloads/list]
+
+Bug Fixes
+---------
+
+* issue 390 Resolve objects going missing
++
+Clients disconnecting from the SSH server sometimes caused an
+interrupt to be delivered to their corresponding server work thread.
+That interrupt delivered at the wrong time caused a file to be
+closed unexpectedly, resulting in JGit marking the file as invalid
+and thereby losing access to its contents.  Fixed by serializing
+access to the file.
+
+* ps: Fix implementation to alias to gerrit show-queue
++
+The SSH command `ps` was meant to be an alias for `gerrit show-queue`
+but due to a copy-and-paste error was actually an alias for a
+different command.  Fixed.
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index acf20a3..4a9cc3f 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -4,6 +4,7 @@
 [[2_1]]
 Version 2.1.x
 -------------
+* link:ReleaseNotes-2.1.2.5.html[2.1.2.5]
 * link:ReleaseNotes-2.1.2.4.html[2.1.2.4]
 * link:ReleaseNotes-2.1.2.3.html[2.1.2.3]
 * link:ReleaseNotes-2.1.2.2.html[2.1.2.2]
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/InheritedRefRight.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/InheritedRefRight.java
index 7fafcb7..4dc998b 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/InheritedRefRight.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/InheritedRefRight.java
@@ -23,6 +23,7 @@
 public class InheritedRefRight {
   private RefRight right;
   private boolean inherited;
+  private boolean owner;
 
   /**
    * Creates a instance of a {@link RefRight} with data about inheritance
@@ -35,10 +36,12 @@
    *
    * @param right the right
    * @param inherited true if the right is inherited, false otherwise
+   * @param owner true if right is owned by current user, false otherwise
    */
-  public InheritedRefRight(RefRight right, boolean inherited) {
+  public InheritedRefRight(RefRight right, boolean inherited, boolean owner) {
     this.right = right;
     this.inherited = inherited;
+    this.owner = owner;
   }
 
   public RefRight getRight() {
@@ -49,6 +52,10 @@
     return inherited;
   }
 
+  public boolean isOwner() {
+    return owner;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (o instanceof InheritedRefRight) {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java
new file mode 100644
index 0000000..56c31ad
--- /dev/null
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java
@@ -0,0 +1,53 @@
+// 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 com.google.gerrit.reviewdb.Branch;
+
+import java.util.List;
+
+/**
+ * It holds list of branches and boolean to indicate
+ * if it is allowed to add new branches.
+ */
+public final class ListBranchesResult {
+  protected boolean canAdd;
+
+  protected List<Branch> branches;
+
+  protected ListBranchesResult() {
+  }
+
+  public ListBranchesResult(final List<Branch> branches, boolean canAdd) {
+    this.branches = branches;
+    this.canAdd = canAdd;
+  }
+
+  public boolean getCanAdd() {
+    return canAdd;
+  }
+
+  public void setCanAdd(boolean canAdd) {
+    this.canAdd = canAdd;
+  }
+
+  public List<Branch> getBranches() {
+    return branches;
+  }
+
+  public void setBranches(List<Branch> branches) {
+    this.branches = branches;
+  }
+}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
index b3c7183..b5a986f 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
@@ -22,7 +22,6 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwtjsonrpc.client.RemoteJsonService;
 import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
 import com.google.gwtjsonrpc.client.RpcImpl.Version;
 
 import java.util.List;
@@ -30,10 +29,8 @@
 
 @RpcImpl(version = Version.V2_0)
 public interface ProjectAdminService extends RemoteJsonService {
-  @SignInRequired
-  void ownedProjects(AsyncCallback<List<Project>> callback);
+  void visibleProjects(AsyncCallback<List<Project>> callback);
 
-  @SignInRequired
   void projectDetail(Project.NameKey projectName,
       AsyncCallback<ProjectDetail> callback);
 
@@ -43,20 +40,19 @@
 
   @SignInRequired
   void deleteRight(Project.NameKey projectName, Set<RefRight.Key> ids,
-      AsyncCallback<VoidResult> callback);
+      AsyncCallback<ProjectDetail> callback);
 
   @SignInRequired
   void addRight(Project.NameKey projectName, ApprovalCategory.Id categoryId,
       String groupName, String refName, short min, short max,
       AsyncCallback<ProjectDetail> callback);
 
-  @SignInRequired
   void listBranches(Project.NameKey projectName,
-      AsyncCallback<List<Branch>> callback);
+      AsyncCallback<ListBranchesResult> callback);
 
   @SignInRequired
   void addBranch(Project.NameKey projectName, String branchName,
-      String startingRevision, AsyncCallback<List<Branch>> callback);
+      String startingRevision, AsyncCallback<ListBranchesResult> callback);
 
   @SignInRequired
   void deleteBranch(Project.NameKey projectName, Set<Branch.NameKey> ids,
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
index ac5c63c..2aa8c62 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
@@ -24,6 +24,10 @@
   public Project project;
   public Map<AccountGroup.Id, AccountGroup> groups;
   public List<InheritedRefRight> rights;
+  public boolean canModifyDescription;
+  public boolean canModifyMergeType;
+  public boolean canModifyAgreements;
+  public boolean canModifyAccess;
 
   public ProjectDetail() {
   }
@@ -39,4 +43,20 @@
   public void setRights(final List<InheritedRefRight> r) {
     rights = r;
   }
+
+  public void setCanModifyDescription(final boolean cmd) {
+    canModifyDescription = cmd;
+  }
+
+  public void setCanModifyMergeType(final boolean cmmt) {
+    canModifyMergeType = cmmt;
+  }
+
+  public void setCanModifyAgreements(final boolean cma) {
+    canModifyAgreements = cma;
+  }
+
+  public void setCanModifyAccess(final boolean cma) {
+    canModifyAccess = cma;
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java
index 1d310c3..6be8657 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.AccountScreen;
+import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.reviewdb.Project;
 import com.google.gwt.event.logical.shared.SelectionEvent;
@@ -28,7 +28,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public class ProjectAdminScreen extends AccountScreen {
+public class ProjectAdminScreen extends Screen {
   static final String INFO_TAB = "info";
   static final String BRANCH_TAB = "branches";
   static final String ACCESS_TAB = "access";
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java
index 865135a..090b000 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.FancyFlexTable;
+import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.common.data.GitwebLink;
 import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.common.errors.InvalidRevisionException;
@@ -57,6 +58,8 @@
   private NpTextBox nameTxtBox;
   private NpTextBox irevTxtBox;
 
+  private final FlowPanel addPanel = new FlowPanel();
+
   public ProjectBranchesPanel(final Project.NameKey toShow) {
     final FlowPanel body = new FlowPanel();
     initBranches(body);
@@ -71,14 +74,20 @@
     super.onLoad();
 
     Util.PROJECT_SVC.listBranches(projectName,
-        new GerritCallback<List<Branch>>() {
-          public void onSuccess(final List<Branch> result) {
+        new GerritCallback<ListBranchesResult>() {
+          public void onSuccess(final ListBranchesResult result) {
             enableForm(true);
-            branches.display(result);
+            display(result.getBranches());
+            addPanel.setVisible(result.getCanAdd());
           }
         });
   }
 
+  private void display(final List<Branch> listBranches) {
+    branches.display(listBranches);
+    delBranch.setVisible(branches.hasBranchCanDelete());
+  }
+
   private void enableForm(final boolean on) {
     delBranch.setEnabled(on);
     addBranch.setEnabled(on);
@@ -87,7 +96,6 @@
   }
 
   private void initBranches(final Panel body) {
-    final FlowPanel addPanel = new FlowPanel();
     addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
 
     final Grid addGrid = new Grid(2, 2);
@@ -209,12 +217,12 @@
 
     addBranch.setEnabled(false);
     Util.PROJECT_SVC.addBranch(projectName, branchName, rev,
-        new GerritCallback<List<Branch>>() {
-          public void onSuccess(final List<Branch> result) {
+        new GerritCallback<ListBranchesResult>() {
+          public void onSuccess(final ListBranchesResult result) {
             addBranch.setEnabled(true);
             nameTxtBox.setText("");
             irevTxtBox.setText("");
-            branches.display(result);
+            display(result.getBranches());
           }
 
           @Override
@@ -239,6 +247,8 @@
   }
 
   private class BranchesTable extends FancyFlexTable<Branch> {
+    boolean canDelete;
+
     BranchesTable() {
       table.setWidth("");
       table.setText(0, 2, Util.C.columnBranchName());
@@ -282,6 +292,8 @@
     }
 
     void display(final List<Branch> result) {
+      canDelete = false;
+
       while (1 < table.getRowCount())
         table.removeRow(table.getRowCount() - 1);
 
@@ -296,7 +308,13 @@
     void populate(final int row, final Branch k) {
       final GitwebLink c = Gerrit.getConfig().getGitwebLink();
 
-      table.setWidget(row, 1, new CheckBox());
+      if (k.getCanDelete()) {
+        table.setWidget(row, 1, new CheckBox());
+        canDelete = true;
+      } else {
+        table.setText(row, 1, "");
+      }
+
       table.setText(row, 2, k.getShortName());
 
       if (k.getRevision() != null) {
@@ -320,5 +338,9 @@
 
       setRowItem(row, k);
     }
+
+    boolean hasBranchCanDelete() {
+      return canDelete;
+    }
   }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java
index ea5fba6..49566ba 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java
@@ -70,7 +70,7 @@
 
   @Override
   protected void onLoad() {
-    enableForm(false);
+    enableForm(false, false, false);
     saveProject.setEnabled(false);
     super.onLoad();
     refresh();
@@ -80,18 +80,26 @@
     Util.PROJECT_SVC.projectDetail(projectName,
         new GerritCallback<ProjectDetail>() {
           public void onSuccess(final ProjectDetail result) {
-            enableForm(true);
+            enableForm(result.canModifyAgreements,
+                result.canModifyDescription, result.canModifyMergeType);
+            saveProject.setVisible(
+                result.canModifyAgreements ||
+                result.canModifyDescription ||
+                result.canModifyMergeType);
             saveProject.setEnabled(false);
             display(result);
           }
         });
   }
 
-  private void enableForm(final boolean on) {
-    submitType.setEnabled(on);
-    descTxt.setEnabled(on);
-    useContributorAgreements.setEnabled(on);
-    useSignedOffBy.setEnabled(on);
+  private void enableForm(final boolean canModifyAgreements,
+      final boolean canModifyDescription, final boolean canModifyMergeType) {
+    submitType.setEnabled(canModifyMergeType);
+    descTxt.setEnabled(canModifyDescription);
+    useContributorAgreements.setEnabled(canModifyAgreements);
+    useSignedOffBy.setEnabled(canModifyAgreements);
+    saveProject.setEnabled(
+        canModifyAgreements || canModifyDescription || canModifyMergeType);
   }
 
   private void initDescription(final Panel body) {
@@ -185,13 +193,14 @@
           .getValue(submitType.getSelectedIndex())));
     }
 
-    enableForm(false);
+    enableForm(false, false, false);
     saveProject.setEnabled(false);
 
     Util.PROJECT_SVC.changeProjectSettings(project,
         new GerritCallback<ProjectDetail>() {
           public void onSuccess(final ProjectDetail result) {
-            enableForm(true);
+            enableForm(result.canModifyAgreements,
+                result.canModifyDescription, result.canModifyMergeType);
             display(result);
           }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
index 04d7038..642712a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
@@ -17,9 +17,9 @@
 import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.AccountScreen;
 import com.google.gerrit.client.ui.Hyperlink;
 import com.google.gerrit.client.ui.NavigationTable;
+import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.reviewdb.Project;
@@ -33,13 +33,13 @@
 
 import java.util.List;
 
-public class ProjectListScreen extends AccountScreen {
+public class ProjectListScreen extends Screen {
   private ProjectTable projects;
 
   @Override
   protected void onLoad() {
     super.onLoad();
-    Util.PROJECT_SVC.ownedProjects(new ScreenLoadCallback<List<Project>>(this) {
+    Util.PROJECT_SVC.visibleProjects(new ScreenLoadCallback<List<Project>>(this) {
       @Override
       protected void preDisplay(final List<Project> result) {
         projects.display(result);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java
index 58b076f..80f1c38 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java
@@ -54,7 +54,6 @@
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import com.google.gwtjsonrpc.client.VoidResult;
 
 import java.util.HashSet;
 import java.util.List;
@@ -76,6 +75,8 @@
   private SuggestBox nameTxt;
   private NpTextBox referenceTxt;
 
+  private final FlowPanel addPanel = new FlowPanel();
+
   public ProjectRightsPanel(final Project.NameKey toShow) {
     projectName = toShow;
 
@@ -121,7 +122,6 @@
   }
 
   private void initRights(final Panel body) {
-    final FlowPanel addPanel = new FlowPanel();
     addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
 
     final Grid addGrid = new Grid(5, 2);
@@ -223,7 +223,8 @@
     delRight.addClickHandler(new ClickHandler() {
       @Override
       public void onClick(final ClickEvent event) {
-        rights.deleteChecked();
+        final HashSet<RefRight.Key> refRightIds = rights.getRefRightIdsChecked();
+        doDeleteRefRights(refRightIds);
       }
     });
 
@@ -254,6 +255,22 @@
     parentName.setText(parent.get());
 
     rights.display(result.groups, result.rights);
+
+    addPanel.setVisible(result.canModifyAccess);
+    delRight.setVisible(rights.getCanDelete());
+  }
+
+  private void doDeleteRefRights(final HashSet<RefRight.Key> refRightIds) {
+    if (!refRightIds.isEmpty()) {
+      Util.PROJECT_SVC.deleteRight(projectName, refRightIds,
+          new GerritCallback<ProjectDetail>() {
+        @Override
+        public void onSuccess(final ProjectDetail result) {
+          //The user could no longer modify access after deleting a ref right.
+          display(result);
+        }
+      });
+    }
   }
 
   private void doAddNewRight() {
@@ -393,6 +410,8 @@
   }
 
   private class RightsTable extends FancyFlexTable<RefRight> {
+    boolean canDelete;
+
     RightsTable() {
       table.setWidth("");
       table.setText(0, 2, Util.C.columnApprovalCategory());
@@ -408,7 +427,7 @@
       fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
     }
 
-    void deleteChecked() {
+    HashSet<RefRight.Key> getRefRightIdsChecked() {
       final HashSet<RefRight.Key> refRightIds = new HashSet<RefRight.Key>();
       for (int row = 1; row < table.getRowCount(); row++) {
         RefRight r = getRowItem(row);
@@ -417,28 +436,13 @@
           refRightIds.add(r.getKey());
         }
       }
-
-      GerritCallback<VoidResult> updateTable =
-          new GerritCallback<VoidResult>() {
-            @Override
-            public void onSuccess(final VoidResult result) {
-              for (int row = 1; row < table.getRowCount();) {
-                RefRight r = getRowItem(row);
-                if (r != null && refRightIds.contains(r.getKey())) {
-                  table.removeRow(row);
-                } else {
-                  row++;
-                }
-              }
-            }
-          };
-      if (!refRightIds.isEmpty()) {
-        Util.PROJECT_SVC.deleteRight(projectName, refRightIds, updateTable);
-      }
+      return refRightIds;
     }
 
     void display(final Map<AccountGroup.Id, AccountGroup> groups,
         final List<InheritedRefRight> refRights) {
+      canDelete = false;
+
       while (1 < table.getRowCount())
         table.removeRow(table.getRowCount() - 1);
 
@@ -450,8 +454,7 @@
       }
     }
 
-    void populate(final int row,
-        final Map<AccountGroup.Id, AccountGroup> groups,
+    void populate(final int row, final Map<AccountGroup.Id, AccountGroup> groups,
         final InheritedRefRight r) {
       final GerritConfig config = Gerrit.getConfig();
       final RefRight right = r.getRight();
@@ -460,10 +463,11 @@
               right.getApprovalCategoryId());
       final AccountGroup group = groups.get(right.getAccountGroupId());
 
-      if (r.isInherited()) {
+      if (r.isInherited() || !r.isOwner()) {
         table.setText(row, 1, "");
       } else {
         table.setWidget(row, 1, new CheckBox());
+        canDelete = true;
       }
 
       if (ar != null) {
@@ -525,5 +529,9 @@
         m.append(e.getName());
       }
     }
+
+    private boolean getCanDelete() {
+      return canDelete;
+    }
   }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
index 8e22741..f638d48 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
@@ -25,6 +25,7 @@
 import com.google.inject.Inject;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,11 +50,18 @@
   public AgreementInfo call() throws Exception {
     final List<AccountAgreement> userAccepted =
         db.accountAgreements().byAccount(user.getAccountId()).toList();
+
+    Collections.reverse(userAccepted);
+
     final List<AccountGroupAgreement> groupAccepted =
         new ArrayList<AccountGroupAgreement>();
     for (final AccountGroup.Id groupId : user.getEffectiveGroups()) {
-      groupAccepted.addAll(db.accountGroupAgreements().byGroup(groupId)
-          .toList());
+      final List<AccountGroupAgreement> temp =
+          db.accountGroupAgreements().byGroup(groupId).toList();
+
+      Collections.reverse(temp);
+
+      groupAccepted.addAll(temp);
     }
 
     final Map<ContributorAgreement.Id, ContributorAgreement> agreements =
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
index 69eb7b8..4fc775e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.common.errors.InvalidRevisionException;
 import com.google.gerrit.httpd.rpc.Handler;
@@ -42,9 +43,8 @@
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.util.List;
 
-class AddBranch extends Handler<List<Branch>> {
+class AddBranch extends Handler<ListBranchesResult> {
   private static final Logger log = LoggerFactory.getLogger(AddBranch.class);
 
   interface Factory {
@@ -85,7 +85,7 @@
   }
 
   @Override
-  public List<Branch> call() throws NoSuchProjectException,
+  public ListBranchesResult call() throws NoSuchProjectException,
       InvalidNameException, InvalidRevisionException, IOException {
     final ProjectControl projectControl =
         projectControlFactory.controlFor(projectName);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteRefRights.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteRefRights.java
index 2d0ab4e..db179ed 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteRefRights.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteRefRights.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.reviewdb.RefRight;
@@ -23,7 +24,6 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.RefControl;
-import com.google.gwtjsonrpc.client.VoidResult;
 import com.google.gwtorm.client.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -31,12 +31,13 @@
 import java.util.Collections;
 import java.util.Set;
 
-class DeleteRefRights extends Handler<VoidResult> {
+class DeleteRefRights extends Handler<ProjectDetail> {
   interface Factory {
     DeleteRefRights create(@Assisted Project.NameKey projectName,
         @Assisted Set<RefRight.Key> toRemove);
   }
 
+  private final ProjectDetailFactory.Factory projectDetailFactory;
   private final ProjectControl.Factory projectControlFactory;
   private final ProjectCache projectCache;
   private final ReviewDb db;
@@ -45,11 +46,13 @@
   private final Set<RefRight.Key> toRemove;
 
   @Inject
-  DeleteRefRights(final ProjectControl.Factory projectControlFactory,
+  DeleteRefRights(final ProjectDetailFactory.Factory projectDetailFactory,
+      final ProjectControl.Factory projectControlFactory,
       final ProjectCache projectCache, final ReviewDb db,
 
       @Assisted final Project.NameKey projectName,
       @Assisted final Set<RefRight.Key> toRemove) {
+    this.projectDetailFactory = projectDetailFactory;
     this.projectControlFactory = projectControlFactory;
     this.projectCache = projectCache;
     this.db = db;
@@ -59,7 +62,7 @@
   }
 
   @Override
-  public VoidResult call() throws NoSuchProjectException, OrmException,
+  public ProjectDetail call() throws NoSuchProjectException, OrmException,
       NoSuchRefException {
     final ProjectControl projectControl =
         projectControlFactory.controlFor(projectName);
@@ -80,7 +83,7 @@
       }
     }
     projectCache.evictAll();
-    return VoidResult.INSTANCE;
+    return projectDetailFactory.create(projectName).call();
   }
 
   private RefControl controlForRef(ProjectControl p, String ref) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
index 158bed1..c02af37 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.reviewdb.Branch;
 import com.google.gerrit.reviewdb.Project;
@@ -21,6 +22,7 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.project.RefControl;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -36,7 +38,7 @@
 import java.util.List;
 import java.util.Map;
 
-class ListBranches extends Handler<List<Branch>> {
+class ListBranches extends Handler<ListBranchesResult> {
   interface Factory {
     ListBranches create(@Assisted Project.NameKey name);
   }
@@ -58,7 +60,7 @@
   }
 
   @Override
-  public List<Branch> call() throws NoSuchProjectException,
+  public ListBranchesResult call() throws NoSuchProjectException,
       RepositoryNotFoundException {
     final ProjectControl pctl = projectControlFactory.validateFor( //
         projectName, //
@@ -91,7 +93,8 @@
           // showing the resolved value, show the name it references.
           //
           String target = ref.getTarget().getName();
-          if (!pctl.controlForRef(target).isVisible()) {
+          RefControl targetRefControl = pctl.controlForRef(target);
+          if (!targetRefControl.isVisible()) {
             continue;
           }
           if (target.startsWith(Constants.R_HEADS)) {
@@ -100,6 +103,8 @@
 
           Branch b = createBranch(Constants.HEAD);
           b.setRevision(new RevId(target));
+          b.setCanDelete(targetRefControl.canDelete());
+
           if (Constants.HEAD.equals(ref.getName())) {
             headBranch = b;
           } else {
@@ -108,12 +113,17 @@
           continue;
         }
 
+        RefControl refControl = pctl.controlForRef(ref.getName());
+
         if (ref.getName().startsWith(Constants.R_HEADS)
-            && pctl.controlForRef(ref.getName()).isVisible()) {
+            && refControl.isVisible()) {
           final Branch b = createBranch(ref.getName());
           if (ref.getObjectId() != null) {
             b.setRevision(new RevId(ref.getObjectId().name()));
           }
+
+          b.setCanDelete(refControl.canDelete());
+
           branches.add(b);
         }
       }
@@ -129,7 +139,7 @@
     if (headBranch != null) {
       branches.add(0, headBranch);
     }
-    return branches;
+    return new ListBranchesResult(branches, pctl.canAddRefs());
   }
 
   private Branch createBranch(final String name) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
index 80e1949..9b06dd9 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.common.data.ProjectAdminService;
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.reviewdb.ApprovalCategory;
@@ -21,7 +22,6 @@
 import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.reviewdb.RefRight;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
 import com.google.inject.Inject;
 
 import java.util.List;
@@ -32,7 +32,7 @@
   private final ChangeProjectSettings.Factory changeProjectSettingsFactory;
   private final DeleteBranches.Factory deleteBranchesFactory;
   private final ListBranches.Factory listBranchesFactory;
-  private final OwnedProjects.Factory ownedProjectsFactory;
+  private final VisibleProjects.Factory visibleProjectsFactory;
   private final ProjectDetailFactory.Factory projectDetailFactory;
   private final AddRefRight.Factory addRefRightFactory;
   private final DeleteRefRights.Factory deleteRefRightsFactory;
@@ -42,7 +42,7 @@
       final ChangeProjectSettings.Factory changeProjectSettingsFactory,
       final DeleteBranches.Factory deleteBranchesFactory,
       final ListBranches.Factory listBranchesFactory,
-      final OwnedProjects.Factory ownedProjectsFactory,
+      final VisibleProjects.Factory visibleProjectsFactory,
       final ProjectDetailFactory.Factory projectDetailFactory,
       final AddRefRight.Factory addRefRightFactory,
       final DeleteRefRights.Factory deleteRefRightsFactory) {
@@ -50,15 +50,15 @@
     this.changeProjectSettingsFactory = changeProjectSettingsFactory;
     this.deleteBranchesFactory = deleteBranchesFactory;
     this.listBranchesFactory = listBranchesFactory;
-    this.ownedProjectsFactory = ownedProjectsFactory;
+    this.visibleProjectsFactory = visibleProjectsFactory;
     this.projectDetailFactory = projectDetailFactory;
     this.addRefRightFactory = addRefRightFactory;
     this.deleteRefRightsFactory = deleteRefRightsFactory;
   }
 
   @Override
-  public void ownedProjects(final AsyncCallback<List<Project>> callback) {
-    ownedProjectsFactory.create().to(callback);
+  public void visibleProjects(final AsyncCallback<List<Project>> callback) {
+    visibleProjectsFactory.create().to(callback);
   }
 
   @Override
@@ -75,7 +75,7 @@
 
   @Override
   public void deleteRight(final Project.NameKey projectName,
-      final Set<RefRight.Key> toRemove, final AsyncCallback<VoidResult> callback) {
+      final Set<RefRight.Key> toRemove, final AsyncCallback<ProjectDetail> callback) {
     deleteRefRightsFactory.create(projectName, toRemove).to(callback);
   }
 
@@ -90,7 +90,7 @@
 
   @Override
   public void listBranches(final Project.NameKey projectName,
-      final AsyncCallback<List<Branch>> callback) {
+      final AsyncCallback<ListBranchesResult> callback) {
     listBranchesFactory.create(projectName).to(callback);
   }
 
@@ -104,7 +104,7 @@
   @Override
   public void addBranch(final Project.NameKey projectName,
       final String branchName, final String startingRevision,
-      final AsyncCallback<List<Branch>> callback) {
+      final AsyncCallback<ListBranchesResult> callback) {
     addBranchFactory.create(projectName, branchName, startingRevision).to(
         callback);
   }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
index bf1ef61..cdd535b 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.server.project.RefControl;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -64,10 +65,10 @@
 
   @Override
   public ProjectDetail call() throws NoSuchProjectException {
-    final ProjectState projectState =
-        projectControlFactory.validateFor(projectName,
-            ProjectControl.OWNER | ProjectControl.VISIBLE).getProjectState();
-
+    final ProjectControl pc =
+        projectControlFactory.validateFor(projectName, ProjectControl.OWNER
+            | ProjectControl.VISIBLE);
+    final ProjectState projectState = pc.getProjectState();
     final ProjectDetail detail = new ProjectDetail();
     detail.setProject(projectState.getProject());
 
@@ -75,7 +76,8 @@
     final List<InheritedRefRight> refRights = new ArrayList<InheritedRefRight>();
 
     for (final RefRight r : projectState.getInheritedRights()) {
-      InheritedRefRight refRight = new InheritedRefRight(r, true);
+      InheritedRefRight refRight = new InheritedRefRight(
+          r, true, controlForRef(pc, r.getRefPattern()).isOwner());
       if (!refRights.contains(refRight)) {
         refRights.add(refRight);
         wantGroup(r.getAccountGroupId());
@@ -83,7 +85,8 @@
     }
 
     for (final RefRight r : projectState.getLocalRights()) {
-      refRights.add(new InheritedRefRight(r, false));
+      refRights.add(new InheritedRefRight(
+          r, false, controlForRef(pc, r.getRefPattern()).isOwner()));
       wantGroup(r.getAccountGroupId());
     }
 
@@ -118,8 +121,15 @@
       }
     });
 
+    final boolean userIsOwner = pc.isOwner();
+    final boolean userIsOwnerAnyRef = pc.isOwnerAnyRef();
+
     detail.setRights(refRights);
     detail.setGroups(groups);
+    detail.setCanModifyAccess(userIsOwnerAnyRef);
+    detail.setCanModifyAgreements(userIsOwner);
+    detail.setCanModifyDescription(userIsOwner);
+    detail.setCanModifyMergeType(userIsOwner);
     return detail;
   }
 
@@ -134,4 +144,11 @@
       groups.put(groupId, groupCache.get(groupId));
     }
   }
+
+  private RefControl controlForRef(ProjectControl p, String ref) {
+    if (ref.endsWith("/*")) {
+      ref = ref.substring(0, ref.length() - 1);
+    }
+    return p.controlForRef(ref);
+  }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
index 9c8affd..7932c79 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
@@ -34,7 +34,7 @@
         factory(DeleteBranches.Factory.class);
         factory(DeleteRefRights.Factory.class);
         factory(ListBranches.Factory.class);
-        factory(OwnedProjects.Factory.class);
+        factory(VisibleProjects.Factory.class);
         factory(ProjectDetailFactory.Factory.class);
       }
     });
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/OwnedProjects.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
similarity index 62%
rename from gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/OwnedProjects.java
rename to gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
index 2bf7530..2588350 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/OwnedProjects.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
@@ -14,13 +14,11 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ApprovalCategory;
 import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RefRight;
 import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gwtorm.client.OrmException;
@@ -29,21 +27,20 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 
-class OwnedProjects extends Handler<List<Project>> {
+class VisibleProjects extends Handler<List<Project>> {
   interface Factory {
-    OwnedProjects create();
+    VisibleProjects create();
   }
 
   private final ProjectControl.Factory projectControlFactory;
-  private final IdentifiedUser user;
+  private final CurrentUser user;
   private final ReviewDb db;
 
   @Inject
-  OwnedProjects(final ProjectControl.Factory projectControlFactory,
-      final IdentifiedUser user, final ReviewDb db) {
+  VisibleProjects(final ProjectControl.Factory projectControlFactory,
+      final CurrentUser user, final ReviewDb db) {
     this.projectControlFactory = projectControlFactory;
     this.user = user;
     this.db = db;
@@ -54,25 +51,16 @@
     final List<Project> result;
     if (user.isAdministrator()) {
       result = db.projects().all().toList();
-
     } else {
-      final HashSet<Project.NameKey> seen = new HashSet<Project.NameKey>();
       result = new ArrayList<Project>();
-      for (final AccountGroup.Id groupId : user.getEffectiveGroups()) {
-        for (final RefRight r : db.refRights().byCategoryGroup(
-            ApprovalCategory.OWN, groupId)) {
-          final Project.NameKey name = r.getProjectNameKey();
-          if (!seen.add(name)) {
-            continue;
+      for (Project p : db.projects().all().toList()) {
+        try {
+          ProjectControl c = projectControlFactory.controlFor(p.getNameKey());
+          if (c.isVisible() || c.isOwner()) {
+            result.add(p);
           }
-          try {
-            ProjectControl c = projectControlFactory.controlFor(name);
-            if (c.isOwnerAnyRef()) {
-              result.add(c.getProject());
-            }
-          } catch (NoSuchProjectException e) {
-            continue;
-          }
+        } catch (NoSuchProjectException e) {
+          continue;
         }
       }
     }
diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
index 1a1e9a7..4c482d4 100644
--- a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
+++ b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
@@ -24,6 +24,7 @@
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
 
+import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.reviewdb.Branch;
 import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
@@ -121,11 +122,12 @@
   }
 
 
-  private List<Branch> permitted(boolean getHead)
+  private ListBranchesResult permitted(boolean getHead)
       throws NoSuchProjectException, IOException {
     Map<String, Ref> refs = realDb.getAllRefs();
 
     validate().andReturn(pc);
+
     expect(grm.openRepository(eq(name.get()))).andReturn(mockDb);
     expect(mockDb.getAllRefs()).andDelegateTo(realDb);
     if (getHead) {
@@ -140,12 +142,16 @@
     }
 
     mockDb.close();
+
+    expect(pc.canAddRefs()).andReturn(true);
+
     expectLastCall();
 
     doReplay();
-    final List<Branch> r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
     doVerify();
     assertNotNull(r);
+    assertNotNull(r.getBranches());
     return r;
   }
 
@@ -153,6 +159,9 @@
     RefControl rc = createStrictMock(RefControl.class);
     refMocks.add(rc);
     expect(rc.isVisible()).andReturn(visible);
+    if (visible) {
+      expect(rc.canDelete()).andReturn(true);
+    }
 
     if (ref.isSymbolic()) {
       expect(pc.controlForRef(ref.getTarget().getName())).andReturn(rc);
@@ -162,10 +171,11 @@
   }
 
   public void testEmptyProject() throws Exception {
-    List<Branch> r = permitted(true);
-    assertEquals(1, r.size());
+    ListBranchesResult r = permitted(true);
 
-    Branch b = r.get(0);
+    assertEquals(1, r.getBranches().size());
+
+    Branch b = r.getBranches().get(0);
     assertNotNull(b);
 
     assertNotNull(b.getNameKey());
@@ -182,10 +192,10 @@
   public void testMasterBranch() throws Exception {
     set("master", idA);
 
-    List<Branch> r = permitted(false);
-    assertEquals(2, r.size());
+    ListBranchesResult r = permitted(false);
+    assertEquals(2, r.getBranches().size());
 
-    Branch b = r.get(0);
+    Branch b = r.getBranches().get(0);
     assertNotNull(b);
 
     assertNotNull(b.getNameKey());
@@ -198,7 +208,7 @@
     assertNotNull(b.getRevision());
     assertEquals("master", b.getRevision().get());
 
-    b = r.get(1);
+    b = r.getBranches().get(1);
     assertNotNull(b);
 
     assertNotNull(b.getNameKey());
@@ -215,10 +225,10 @@
   public void testBranchNotHead() throws Exception {
     set("foo", idA);
 
-    List<Branch> r = permitted(true);
-    assertEquals(2, r.size());
+    ListBranchesResult r = permitted(true);
+    assertEquals(2, r.getBranches().size());
 
-    Branch b = r.get(0);
+    Branch b = r.getBranches().get(0);
     assertNotNull(b);
 
     assertNotNull(b.getNameKey());
@@ -231,7 +241,7 @@
     assertNotNull(b.getRevision());
     assertEquals("master", b.getRevision().get());
 
-    b = r.get(1);
+    b = r.getBranches().get(1);
     assertNotNull(b);
 
     assertNotNull(b.getNameKey());
@@ -258,18 +268,19 @@
     for (Ref ref : u.values()) {
       assumeVisible(ref, true);
     }
+    expect(pc.canAddRefs()).andReturn(true);
     mockDb.close();
     expectLastCall();
 
     doReplay();
-    final List<Branch> r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
     doVerify();
     assertNotNull(r);
 
-    assertEquals(3, r.size());
-    assertEquals(HEAD, r.get(0).getShortName());
-    assertEquals("bar", r.get(1).getShortName());
-    assertEquals("foo", r.get(2).getShortName());
+    assertEquals(3, r.getBranches().size());
+    assertEquals(HEAD, r.getBranches().get(0).getShortName());
+    assertEquals("bar", r.getBranches().get(1).getShortName());
+    assertEquals("foo", r.getBranches().get(2).getShortName());
   }
 
   public void testHeadNotVisible() throws Exception {
@@ -284,14 +295,15 @@
     expect(mockDb.getAllRefs()).andReturn(u);
     assumeVisible(bar, false);
     assumeVisible(bar, false);
+    expect(pc.canAddRefs()).andReturn(true);
     mockDb.close();
     expectLastCall();
 
     doReplay();
-    final List<Branch> r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
     doVerify();
     assertNotNull(r);
-    assertTrue(r.isEmpty());
+    assertTrue(r.getBranches().isEmpty());
   }
 
   public void testHeadVisibleButBranchHidden() throws Exception {
@@ -311,16 +323,17 @@
     assumeVisible(bar, true);
     assumeVisible(bar, true);
     assumeVisible(foo, false);
+    expect(pc.canAddRefs()).andReturn(true);
     mockDb.close();
     expectLastCall();
 
     doReplay();
-    final List<Branch> r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
     doVerify();
     assertNotNull(r);
 
-    assertEquals(2, r.size());
-    assertEquals(HEAD, r.get(0).getShortName());
-    assertEquals("bar", r.get(1).getShortName());
+    assertEquals(2, r.getBranches().size());
+    assertEquals(HEAD, r.getBranches().get(0).getShortName());
+    assertEquals("bar", r.getBranches().get(1).getShortName());
   }
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java
index b9f8905..f65af5e 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java
@@ -25,6 +25,6 @@
   @PrimaryKey("key")
   AccountAgreement get(AccountAgreement.Key key) throws OrmException;
 
-  @Query("WHERE key.accountId = ? ORDER BY acceptedOn DESC")
+  @Query("WHERE key.accountId = ? ORDER BY acceptedOn")
   ResultSet<AccountAgreement> byAccount(Account.Id id) throws OrmException;
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java
index d471934..d4a1fcd 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java
@@ -25,7 +25,7 @@
   @PrimaryKey("key")
   AccountGroupAgreement get(AccountGroupAgreement.Key key) throws OrmException;
 
-  @Query("WHERE key.groupId = ? ORDER BY acceptedOn DESC")
+  @Query("WHERE key.groupId = ? ORDER BY acceptedOn")
   ResultSet<AccountGroupAgreement> byGroup(AccountGroup.Id id)
       throws OrmException;
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java
index 2bacc63..27716a8 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java
@@ -71,6 +71,7 @@
 
   protected NameKey name;
   protected RevId revision;
+  protected boolean canDelete;
 
   protected Branch() {
   }
@@ -98,4 +99,12 @@
   public void setRevision(final RevId id) {
     revision = id;
   }
+
+  public boolean getCanDelete() {
+    return canDelete;
+  }
+
+  public void setCanDelete(boolean canDelete) {
+    this.canDelete = canDelete;
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
index fadd445..ac53830 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
@@ -181,8 +181,15 @@
           break;
 
         case REJECTED_OTHER_REASON:
-          log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
-              + ", reason: " + u.getMessage());
+          if ("non-fast-forward".equals(u.getMessage())) {
+            log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
+                + ", remote rejected non-fast-forward push."
+                + "  Check receive.denyNonFastForwards variable in config file"
+                + " of destination repository.");
+          } else {
+            log.error("Failed replicate of " + u.getRemoteName() + " to " + uri
+                + ", reason: " + u.getMessage());
+          }
           break;
       }
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 6e8ae14..4ae0304 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -291,8 +291,12 @@
     ContributorAgreement bestCla = null;
 
     OUTER: for (AccountGroup.Id groupId : currentUser.getEffectiveGroups()) {
-      for (final AccountGroupAgreement a : db.accountGroupAgreements().byGroup(
-          groupId)) {
+      final List<AccountGroupAgreement> temp =
+          db.accountGroupAgreements().byGroup(groupId).toList();
+
+      Collections.reverse(temp);
+
+      for (final AccountGroupAgreement a : temp) {
         final ContributorAgreement cla =
             db.contributorAgreements().get(a.getAgreementId());
         if (cla == null) {
@@ -306,8 +310,12 @@
     }
 
     if (bestAgreement == null) {
-      for (final AccountAgreement a : db.accountAgreements().byAccount(
-          currentUser.getAccountId()).toList()) {
+      final List<AccountAgreement> temp =
+          db.accountAgreements().byAccount(currentUser.getAccountId()).toList();
+
+      Collections.reverse(temp);
+
+      for (final AccountAgreement a : temp) {
         final ContributorAgreement cla =
             db.contributorAgreements().get(a.getAgreementId());
         if (cla == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
index d8e2069..24fe3f0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
@@ -121,6 +121,11 @@
         || canPerformOnAnyRef(ApprovalCategory.READ, (short) 1);
   }
 
+  public boolean canAddRefs() {
+    return (canPerformOnAnyRef(ApprovalCategory.PUSH_HEAD, ApprovalCategory.PUSH_HEAD_CREATE)
+        || isOwnerAnyRef());
+  }
+
   /** Can this user see all the refs in this projects? */
   public boolean allRefsAreVisible() {
     return visibleForReplication()
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
index 0b776b4..f44eff5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
@@ -53,7 +53,7 @@
 
       } else {
         try {
-          u.check(ui, version, db);
+          u.check(ui, version, db, true);
         } catch (SQLException e) {
           throw new OrmException("Cannot upgrade schema", e);
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
index ad6f7a3..2be0d49 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
@@ -68,22 +68,22 @@
     return versionNbr;
   }
 
-  public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
+  public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db, boolean toTargetVersion)
       throws OrmException, SQLException {
     if (curr.versionNbr == versionNbr) {
       // Nothing to do, we are at the correct schema.
       //
     } else {
-      upgradeFrom(ui, curr, db);
+      upgradeFrom(ui, curr, db, toTargetVersion);
     }
   }
 
   /** Runs check on the prior schema version, and then upgrades. */
-  protected void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
+  protected void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db, boolean toTargetVersion)
       throws OrmException, SQLException {
     final JdbcSchema s = (JdbcSchema) db;
 
-    prior.get().check(ui, curr, db);
+    prior.get().check(ui, curr, db, false);
 
     ui.message("Upgrading database schema from version " + curr.versionNbr
         + " to " + versionNbr + " ...");
@@ -94,15 +94,17 @@
       s.updateSchema(e);
       migrateData(db, ui);
 
-      final List<String> pruneList = new ArrayList<String>();
-      s.pruneSchema(new StatementExecutor() {
-        public void execute(String sql) {
-          pruneList.add(sql);
-        }
-      });
+      if (toTargetVersion) {
+        final List<String> pruneList = new ArrayList<String>();
+        s.pruneSchema(new StatementExecutor() {
+          public void execute(String sql) {
+            pruneList.add(sql);
+          }
+        });
 
-      if (!pruneList.isEmpty()) {
-        ui.pruneSchema(e, pruneList);
+        if (!pruneList.isEmpty()) {
+          ui.pruneSchema(e, pruneList);
+        }
       }
     } finally {
       e.close();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_19.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_19.java
index dfe595c..7ad91ff 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_19.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_19.java
@@ -33,7 +33,7 @@
 
   @Override
   protected void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr,
-      ReviewDb db) throws OrmException {
+      ReviewDb db, boolean toTargetVersion) throws OrmException {
     throw new OrmException("Cannot upgrade from " + curr.versionNbr
         + "; manually run scripts from"
         + " http://gerrit.googlecode.com/files/schema-upgrades003_019.zip"
diff --git a/pom.xml b/pom.xml
index 235045b..9cbb673 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
   </issueManagement>
 
   <properties>
-    <jgitVersion>0.7.1.46-gdd63f5c</jgitVersion>
+    <jgitVersion>0.7.1.74-g16419da</jgitVersion>
     <gwtormVersion>1.1.4</gwtormVersion>
     <gwtjsonrpcVersion>1.2.2</gwtjsonrpcVersion>
     <gwtexpuiVersion>1.2.1</gwtexpuiVersion>
@@ -770,11 +770,4 @@
       <url>http://maven.objectweb.org/maven2/</url>
     </repository>
   </repositories>
-
-  <pluginRepositories>
-    <pluginRepository>
-      <id>gwt-maven-plugins</id>
-      <url>http://snapshots.repository.codehaus.org/</url>
-    </pluginRepository>
-  </pluginRepositories>
 </project>