Merge "Allow unique from address generation."
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index b9fb8b3..ad20cb3 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -444,6 +444,14 @@
 A restart is required after making database changes.
 See <<restart_changes,below>>.
 
+[[category_abandon]]
+Abandon
+~~~~
+
+This category controls whether users are allowed to abandon changes
+to projects in Gerrit. It can give permission to abandon a specific
+change to a given ref.
+
 [[category_create]]
 Create reference
 ~~~~~~~~~~~~~~~~
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
index 20261de..4067349 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/Permission.java
@@ -20,6 +20,7 @@
 
 /** A single permission within an {@link AccessSection} of a project. */
 public class Permission implements Comparable<Permission> {
+  public static final String ABANDON = "abandon";
   public static final String CREATE = "create";
   public static final String FORGE_AUTHOR = "forgeAuthor";
   public static final String FORGE_COMMITTER = "forgeCommitter";
@@ -40,6 +41,7 @@
     NAMES_LC = new ArrayList<String>();
     NAMES_LC.add(OWNER.toLowerCase());
     NAMES_LC.add(READ.toLowerCase());
+    NAMES_LC.add(ABANDON.toLowerCase());
     NAMES_LC.add(CREATE.toLowerCase());
     NAMES_LC.add(FORGE_AUTHOR.toLowerCase());
     NAMES_LC.add(FORGE_COMMITTER.toLowerCase());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index 3b3d0bb..89fc195 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -98,6 +98,7 @@
 
 # Permission Names
 permissionNames = \
+	abandon, \
 	create, \
 	forgeAuthor, \
 	forgeCommitter, \
@@ -109,6 +110,7 @@
 	read, \
 	rebase, \
 	submit
+abandon = Abandon
 create = Create Reference
 forgeAuthor = Forge Author Identity
 forgeCommitter = Forge Committer Identity
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
index 1a6ea3e..3237b83 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
@@ -14,29 +14,56 @@
 
 package com.google.gerrit.client.changes;
 
-import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.ui.CommentLinkProcessor;
 import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTML;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.PreElement;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.HTMLPanel;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
 public class CommitMessageBlock extends Composite {
-  private final HTML description;
+  interface Binder extends UiBinder<HTMLPanel, CommitMessageBlock> {
+  }
+
+  private static Binder uiBinder = GWT.create(Binder.class);
+
+  @UiField
+  PreElement commitSummaryPre;
+  @UiField
+  PreElement commitBodyPre;
 
   public CommitMessageBlock() {
-    description = new HTML();
-    description.setStyleName(Gerrit.RESOURCES.css().changeScreenDescription());
-    initWidget(description);
+    initWidget(uiBinder.createAndBindUi(this));
   }
 
   public void display(final String commitMessage) {
-    SafeHtml msg = new SafeHtmlBuilder().append(commitMessage);
-    msg = msg.linkify();
-    msg = CommentLinkProcessor.apply(msg);
-    msg = new SafeHtmlBuilder().openElement("p").append(msg).closeElement("p");
-    msg = msg.replaceAll("\n\n", "</p><p>");
-    msg = msg.replaceAll("\n", "<br />");
-    SafeHtml.set(description, msg);
+    String commitSummary = "";
+    String commitBody = "";
+
+    String[] splitCommitMessage = commitMessage.split("\n", 2);
+    commitSummary = splitCommitMessage[0];
+    commitBody = splitCommitMessage[1];
+
+    // Hide commit body if there is no body
+    if (commitBody.trim().isEmpty()) {
+      commitBodyPre.setAttribute("style", "display: none;");
+    }
+
+    // Linkify commit summary
+    SafeHtml commitSummaryLinkified = new SafeHtmlBuilder().append(commitSummary);
+    commitSummaryLinkified = commitSummaryLinkified.linkify();
+    commitSummaryLinkified = CommentLinkProcessor.apply(commitSummaryLinkified);
+
+    // Linkify commit body
+    SafeHtml commitBodyLinkified = new SafeHtmlBuilder().append(commitBody);
+    commitBodyLinkified = commitBodyLinkified.linkify();
+    commitBodyLinkified = CommentLinkProcessor.apply(commitBodyLinkified);
+
+    commitSummaryPre.setInnerHTML(commitSummaryLinkified.asString());
+    commitBodyPre.setInnerHTML(commitBodyLinkified.asString());
   }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml
new file mode 100644
index 0000000..41d6f83
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2012 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.
+-->
+
+<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
+    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
+
+
+  <ui:style>
+    @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
+    @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
+    @eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
+
+    .commitMessageTable {
+      border-collapse: separate;
+      border-spacing: 0;
+      margin-bottom: 10px;
+    }
+
+    .header {
+      border: 1px solid trimColor;
+      padding: 2px 6px 1px;
+      background-color: trimColor;
+      white-space: nowrap;
+      color: textColor;
+      font-size: 10pt;
+    }
+
+    .contents {
+      border-bottom: 1px solid trimColor;
+      border-left: 1px solid trimColor;
+      border-right: 1px solid trimColor;
+      padding: 5px;
+    }
+
+    .contents span {
+      font-weight: bold;
+    }
+
+    .contents pre {
+      margin: 0;
+    }
+
+    .commitSummary {
+      font-weight: bold;
+    }
+
+    .commitBody {
+      margin-top: 10px;
+    }
+  </ui:style>
+
+  <g:HTMLPanel>
+    <table class='{style.commitMessageTable}'>
+      <tr><th class='{style.header}'>Commit Message</th></tr>
+      <tr><td class='{style.contents}'>
+        <pre class='{style.commitSummary}' ui:field='commitSummaryPre'/>
+        <pre class='{style.commitBody}' ui:field='commitBodyPre'/>
+      </td></tr>
+    </table>
+  </g:HTMLPanel>
+</ui:UiBinder>
+
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 64f7d97..7387fd1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -189,6 +189,7 @@
         || getRefControl().isOwner() // branch owner can abandon
         || getProjectControl().isOwner() // project owner can abandon
         || getCurrentUser().getCapabilities().canAdministrateServer() // site administers are god
+        || getRefControl().canAbandon() // user can abandon a specific ref
     ;
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index 82c3a6d..2f99271 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -310,6 +310,11 @@
     return canPerform(Permission.FORGE_SERVER);
   }
 
+  /** @return true if this user can abandon a change for this ref */
+  public boolean canAbandon() {
+    return canPerform(Permission.ABANDON);
+  }
+
   /** All value ranges of any allowed label permission. */
   public List<PermissionRange> getLabelRanges() {
     List<PermissionRange> r = new ArrayList<PermissionRange>();