Merge "Revert "Additional log on plug-in self-registration and failures.""
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 23f6e72..7027562 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -452,6 +452,9 @@
to projects in Gerrit. It can give permission to abandon a specific
change to a given ref.
+This also grants the permission to restore a change if the change
+can be uploaded.
+
[[category_create]]
Create reference
~~~~~~~~~~~~~~~~
diff --git a/Documentation/cmd-cherry-pick.txt b/Documentation/cmd-cherry-pick.txt
index 568c872..d051a9a 100644
--- a/Documentation/cmd-cherry-pick.txt
+++ b/Documentation/cmd-cherry-pick.txt
@@ -39,7 +39,7 @@
====
$ scp -p -P 29418 john.doe@review.example.com:bin/gerrit-cherry-pick ~/bin/
- $ curl http://review.example.com/tools/bin/gerrit-cherry-pick
+ $ curl -o ~/bin/gerrit-cherry-pick http://review.example.com/tools/bin/gerrit-cherry-pick
====
GERRIT
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt
index 4c0560e..c4f222b 100644
--- a/Documentation/cmd-index.txt
+++ b/Documentation/cmd-index.txt
@@ -12,8 +12,8 @@
$ scp -p -P 29418 john.doe@review.example.com:bin/gerrit-cherry-pick ~/bin/
$ scp -p -P 29418 john.doe@review.example.com:hooks/commit-msg .git/hooks/
- $ curl http://review.example.com/tools/bin/gerrit-cherry-pick
- $ curl http://review.example.com/tools/hooks/commit-msg
+ $ curl -o ~/bin/gerrit-cherry-pick http://review.example.com/tools/bin/gerrit-cherry-pick
+ $ curl -o .git/hooks/commit-msg http://review.example.com/tools/hooks/commit-msg
For more details on how to determine the correct SSH port number,
see link:user-upload.html#test_ssh[Testing Your SSH Connection].
diff --git a/Documentation/cmd-review.txt b/Documentation/cmd-review.txt
index ac613e5..eed6902 100644
--- a/Documentation/cmd-review.txt
+++ b/Documentation/cmd-review.txt
@@ -52,7 +52,7 @@
--force-message::
Option which allows Gerrit to publish the --message, even
- when the labels could not be applied due to change being
+ when the labels could not be applied due to the change being
closed).
+
Used by some scripts/CI-systems, where the results (or links
@@ -69,11 +69,11 @@
complete listing of supported approval categories and values.
--abandon::
- Abandon the specified patch set(s).
+ Abandon the specified change(s).
(option is mutually exclusive with --submit and --restore)
--restore::
- Restore the specified abandoned patch set(s).
+ Restore the specified abandoned change(s).
(option is mutually exclusive with --abandon)
--submit::
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index cb70254..8610dba 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -88,6 +88,12 @@
provider chosen by the end-user. For more information see
http://openid.net/[openid.net].
+
+* `OpenID_SSO`
++
+Supports OpenID from a single provider. There is no registration
+link, and the "Sign In" link sends the user directly to the provider's
+SSO entry point.
++
* `HTTP`
+
Gerrit relies upon data presented in the HTTP request. This includes
@@ -229,6 +235,13 @@
+
Default is 12 hours.
+[[auth.openIdSsoUrl]]auth.openIdSsoUrl::
++
+The SSO entry point URL. Only used if `auth.type` was set to
+OpenID_SSO.
++
+The "Sign In" link will send users directly to this URL.
+
[[auth.httpHeader]]auth.httpHeader::
+
HTTP header to trust the username from, or unset to select HTTP basic
@@ -2237,6 +2250,31 @@
+
By default a shade of yellow, `FFFFCC`.
+[[theme.changeTableOutdatedColor]]theme.changeTableOutdatedColor::
++
+Background color used for patch outdated messages. The value must be
+a valid HTML hex color code, or standard color name.
++
+By default a shade of red, `FF0000`.
+
+[[theme.tableOddRowColor]]theme.tableOddRowColor::
++
+Background color for tables such as lists of open reviews for odd
+rows. This is so you can have a different color for odd and even
+rows of the table. The value must be a valid HTML hex color code,
+or standard color name.
++
+By default transparent.
+
+[[theme.tableEvenRowColor]]theme.tableEvenRowColor::
++
+Background color for tables such as lists of open reviews for even
+rows. This is so you can have a different color for odd and even
+rows of the table. The value must be a valid HTML hex color code,
+or standard color name.
++
+By default transparent.
+
A different theme may be used for signed-in vs. signed-out user status
by using the "signed-in" and "signed-out" theme sections. Variables
not specified in a section are inherited from the default theme.
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 586ae07..7832aa9 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -192,7 +192,7 @@
by PrintHello class will be available to users as:
----
-$ ssh -P 29418 review.example.com helloworld print
+$ ssh -p 29418 review.example.com helloworld print
----
HTTP Servlets
@@ -312,7 +312,7 @@
the plugin from this location to its own site path.
+
----
-$ ssh -P 29418 localhost gerrit plugin install -n name $(pwd)/my-plugin.jar
+$ ssh -p 29418 localhost gerrit plugin install -n name $(pwd)/my-plugin.jar
----
* Valid URL, including any HTTP or FTP site reachable by the
@@ -320,14 +320,14 @@
its own site path.
+
----
-$ ssh -P 29418 localhost gerrit plugin install -n name http://build-server/output/our-plugin.jar
+$ ssh -p 29418 localhost gerrit plugin install -n name http://build-server/output/our-plugin.jar
----
* As piped input to the plugin install command. The server will
copy input until EOF, and save a copy under its own site path.
+
----
-$ ssh -P 29418 localhost gerrit plugin install -n name - <target/name-0.1.jar
+$ ssh -p 29418 localhost gerrit plugin install -n name - <target/name-0.1.jar
----
Plugins can also be copied directly into the server's
diff --git a/Documentation/index.txt b/Documentation/index.txt
index 2b53772..c99d26c 100644
--- a/Documentation/index.txt
+++ b/Documentation/index.txt
@@ -48,6 +48,7 @@
* link:dev-readme.html[Developer Setup]
* link:dev-eclipse.html[Eclipse Setup]
* link:dev-contributing.html[Contributing to Gerrit]
+* link:dev-plugins.html[Developing Plugins]
* link:dev-design.html[System Design]
* link:i18n-readme.html[i18n Support]
* link:dev-release.html[Developer Release]
diff --git a/Documentation/user-changeid.txt b/Documentation/user-changeid.txt
index 409bb32..a3015e1 100644
--- a/Documentation/user-changeid.txt
+++ b/Documentation/user-changeid.txt
@@ -46,11 +46,13 @@
Gerrit Code Review provides a standard 'commit-msg' hook which
can be installed in the local Git repository to automatically
create and insert a unique Change-Id line during `git commit`.
-To install the hook, copy it from Gerrit's daemon:
+To install the hook, copy it from Gerrit's daemon by executing
+one of the following commands while being in the root directory
+of the local Git repository:
$ scp -p -P 29418 john.doe@review.example.com:hooks/commit-msg .git/hooks/
- $ curl http://review.example.com/tools/hooks/commit-msg
+ $ curl -o .git/hooks/commit-msg http://review.example.com/tools/hooks/commit-msg
For more details, see link:cmd-hook-commit-msg.html[commit-msg].
diff --git a/gerrit-antlr/.settings/org.eclipse.core.resources.prefs b/gerrit-antlr/.settings/org.eclipse.core.resources.prefs
index 589908f..e9441bb 100644
--- a/gerrit-antlr/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-antlr/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-cache-h2/.settings/org.eclipse.core.resources.prefs b/gerrit-cache-h2/.settings/org.eclipse.core.resources.prefs
index fc11c3f..f9fe345 100644
--- a/gerrit-cache-h2/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-cache-h2/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
diff --git a/gerrit-common/.settings/org.eclipse.core.resources.prefs b/gerrit-common/.settings/org.eclipse.core.resources.prefs
index fc11c3f..f9fe345 100644
--- a/gerrit-common/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-common/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
index 07a8534..89de3b4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
@@ -28,6 +28,7 @@
public class GerritConfig implements Cloneable {
protected String registerUrl;
protected String httpPasswordUrl;
+ protected String openIdSsoUrl;
protected List<OpenIdProviderPattern> allowedOpenIDs;
protected GitwebConfig gitweb;
@@ -72,6 +73,14 @@
httpPasswordUrl = url;
}
+ public String getOpenIdSsoUrl() {
+ return openIdSsoUrl;
+ }
+
+ public void setOpenIdSsoUrl(final String u) {
+ openIdSsoUrl = u;
+ }
+
public List<OpenIdProviderPattern> getAllowedOpenIDs() {
return allowedOpenIDs;
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
index c3d3f1e..f991f4c 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
@@ -31,5 +31,8 @@
public String textColor;
public String trimColor;
public String selectionColor;
+ public String changeTableOutdatedColor;
+ public String tableOddRowColor;
+ public String tableEvenRowColor;
}
}
diff --git a/gerrit-extension-api/.settings/org.eclipse.core.resources.prefs b/gerrit-extension-api/.settings/org.eclipse.core.resources.prefs
index fc11c3f..f9fe345 100644
--- a/gerrit-extension-api/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-extension-api/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
diff --git a/gerrit-gwtdebug/.settings/org.eclipse.core.resources.prefs b/gerrit-gwtdebug/.settings/org.eclipse.core.resources.prefs
index 36e1448..e9441bb 100644
--- a/gerrit-gwtdebug/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-gwtdebug/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:38 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-gwtui/.settings/org.eclipse.core.resources.prefs b/gerrit-gwtui/.settings/org.eclipse.core.resources.prefs
index c780f44..e9441bb 100644
--- a/gerrit-gwtui/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-gwtui/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index fcc2db1..267419f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -18,6 +18,7 @@
import com.google.gerrit.client.account.AccountCapabilities;
import com.google.gerrit.client.auth.openid.OpenIdSignInDialog;
+import com.google.gerrit.client.auth.openid.OpenIdSsoPanel;
import com.google.gerrit.client.auth.userpass.UserPassSignInDialog;
import com.google.gerrit.client.changes.ChangeConstants;
import com.google.gerrit.client.changes.ChangeListScreen;
@@ -258,6 +259,13 @@
Location.assign(selfRedirect("/become"));
break;
+ case OPENID_SSO:
+ final RootPanel gBody = RootPanel.get("gerrit_body");
+ OpenIdSsoPanel singleSignOnPanel = new OpenIdSsoPanel();
+ gBody.add(singleSignOnPanel);
+ singleSignOnPanel.authenticate(SignInMode.SIGN_IN, token);
+ break;
+
case OPENID:
new OpenIdSignInDialog(SignInMode.SIGN_IN, token, null).center();
break;
@@ -627,6 +635,14 @@
});
break;
+ case OPENID_SSO:
+ menuRight.addItem(C.menuSignIn(), new Command() {
+ public void execute() {
+ doSignIn(History.getToken());
+ }
+ });
+ break;
+
case LDAP:
case LDAP_BIND:
case CUSTOM_EXTENSION:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java
new file mode 100644
index 0000000..3dd54a7
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java
@@ -0,0 +1,70 @@
+// 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.
+
+package com.google.gerrit.client.auth.openid;
+
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.rpc.GerritCallback;
+import com.google.gerrit.client.ui.SmallHeading;
+import com.google.gerrit.common.auth.SignInMode;
+import com.google.gerrit.common.auth.openid.DiscoveryResult;
+import com.google.gerrit.common.auth.openid.OpenIdUrls;
+import com.google.gwt.dom.client.FormElement;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.FormPanel;
+import com.google.gwt.user.client.ui.Hidden;
+
+import java.util.Map;
+
+public class OpenIdSsoPanel extends FlowPanel {
+ private final FormPanel redirectForm;
+ private final FlowPanel redirectBody;
+ private final String ssoUrl;
+
+ public OpenIdSsoPanel() {
+ super();
+ redirectBody = new FlowPanel();
+ redirectBody.setVisible(false);
+ redirectForm = new FormPanel();
+ redirectForm.add(redirectBody);
+
+ add(redirectForm);
+
+ ssoUrl = Gerrit.getConfig().getOpenIdSsoUrl();
+ }
+
+ public void authenticate(SignInMode requestedMode, final String token) {
+ OpenIdUtil.SVC.discover(ssoUrl, requestedMode, /* remember */ false, token,
+ new GerritCallback<DiscoveryResult>() {
+ public void onSuccess(final DiscoveryResult result) {
+ onDiscovery(result);
+ }
+ });
+ }
+
+ private void onDiscovery(final DiscoveryResult result) {
+ switch (result.status) {
+ case VALID:
+ redirectForm.setMethod(FormPanel.METHOD_POST);
+ redirectForm.setAction(result.providerUrl);
+ redirectBody.clear();
+ for (final Map.Entry<String, String> e : result.providerArgs.entrySet()) {
+ redirectBody.add(new Hidden(e.getKey(), e.getValue()));
+ }
+ FormElement.as(redirectForm.getElement()).setTarget("_top");
+ redirectForm.submit();
+ break;
+ }
+ }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 44a49a8..97bb4ca 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -202,10 +202,7 @@
}
table.setWidget(row, C_ID, new TableChangeLink(idstr, c));
- String s = c.getSubject();
- if (s.length() > 80) {
- s = s.substring(0, 80);
- }
+ String s = Util.cropSubject(c.getSubject());
if (c.getStatus() != null && c.getStatus() != Change.Status.NEW) {
s += " (" + c.getStatus().name() + ")";
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
index fc2b418..0dd0b0f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable2.java
@@ -200,10 +200,7 @@
}
table.setWidget(row, C_ID, new TableChangeLink(c.id_abbreviated(), c));
- String subject = c.subject();
- if (subject.length() > 80) {
- subject = subject.substring(0, 80);
- }
+ String subject = Util.cropSubject(c.subject());
Change.Status status = c.status();
if (status != Change.Status.NEW) {
subject += " (" + Util.toLongString(status) + ")";
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index 00baf28..ca8aedf 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -424,7 +424,8 @@
parentsTable.setWidget(row, 0, new InlineLabel(parent.id.get()));
ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().noborder());
ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().monospace());
- parentsTable.setWidget(row, 1, new InlineLabel(parent.shortMessage));
+ parentsTable.setWidget(row, 1,
+ new InlineLabel(Util.cropSubject(parent.shortMessage)));
ptfmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder());
row++;
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
index e84cac8..590ad87 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
@@ -30,6 +30,10 @@
public static final ChangeListService LIST_SVC;
public static final ChangeManageService MANAGE_SVC;
+ private static final int SUBJECT_MAX_LENGTH = 80;
+ private static final String SUBJECT_CROP_APPENDIX = "...";
+ private static final int SUBJECT_CROP_RANGE = 10;
+
static {
DETAIL_SVC = GWT.create(ChangeDetailService.class);
JsonUtil.bind(DETAIL_SVC, "rpc/ChangeDetailService");
@@ -60,4 +64,40 @@
return status.name();
}
}
+
+ /**
+ * Crops the given change subject if needed so that it has at most
+ * {@link #SUBJECT_MAX_LENGTH} characters.
+ *
+ * If the given subject is not longer than {@link #SUBJECT_MAX_LENGTH}
+ * characters it is returned unchanged.
+ *
+ * If the length of the given subject exceeds {@link #SUBJECT_MAX_LENGTH}
+ * characters it is cropped. In this case {@link #SUBJECT_CROP_APPENDIX} is
+ * appended to the cropped subject, the cropped subject including the appendix
+ * has at most {@link #SUBJECT_MAX_LENGTH} characters.
+ *
+ * If cropping is needed, the subject will be cropped after the last space
+ * character that is found within the last {@link #SUBJECT_CROP_RANGE}
+ * characters of the potentially visible characters. If no such space is
+ * found, the subject will be cropped so that the cropped subject including
+ * the appendix has exactly {@link #SUBJECT_MAX_LENGTH} characters.
+ *
+ * @return the subject, cropped if needed
+ */
+ @SuppressWarnings("deprecation")
+ public static String cropSubject(final String subject) {
+ if (subject.length() > SUBJECT_MAX_LENGTH) {
+ final int maxLength = SUBJECT_MAX_LENGTH - SUBJECT_CROP_APPENDIX.length();
+ for (int cropPosition = maxLength; cropPosition > maxLength - SUBJECT_CROP_RANGE; cropPosition--) {
+ // Character.isWhitespace(char) can't be used because this method is not supported by GWT,
+ // see https://developers.google.com/web-toolkit/doc/1.6/RefJreEmulation#Package_java_lang
+ if (Character.isSpace(subject.charAt(cropPosition - 1))) {
+ return subject.substring(0, cropPosition) + SUBJECT_CROP_APPENDIX;
+ }
+ }
+ return subject.substring(0, maxLength) + SUBJECT_CROP_APPENDIX;
+ }
+ return subject;
+ }
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 3789c6a..446b71d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -43,7 +43,9 @@
@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
-
+@eval changeTableOutdatedColor com.google.gerrit.client.Gerrit.getTheme().changeTableOutdatedColor;
+@eval tableOddRowColor com.google.gerrit.client.Gerrit.getTheme().tableOddRowColor;
+@eval tableEvenRowColor com.google.gerrit.client.Gerrit.getTheme().tableEvenRowColor;
@sprite .greenCheckClass {
gwt-image: "greenCheck";
@@ -411,8 +413,16 @@
border-spacing: 0;
}
+.changeTable tr:nth-child\(even\) {
+ background: tableEvenRowColor;
+}
+
+.changeTable tr:nth-child\(odd\) {
+ background: tableOddRowColor;
+}
+
.changeTable .outdated {
- background: red;
+ background: changeTableOutdatedColor;
}
.changeTable .iconCell {
@@ -482,7 +492,6 @@
.accountDashboard.changeTable tr {
color: #444444;
- background: #F6F6F6;
}
.accountDashboard.changeTable tr a {
color: #444444;
@@ -492,13 +501,12 @@
.accountDashboard.changeTable .needsReview a {
font-weight: bold;
color: textColor;
- background: backgroundColor;
}
.changeTable .activeRow,
.accountDashboard.changeTable .activeRow,
.accountDashboard.changeTable .activeRow a {
- background: selectionColor;
+ background: selectionColor !important;
}
.changeTable .cID {
@@ -1042,6 +1050,10 @@
display: table;
}
+.sideBySideScreenSideBySideTable .fileLine {
+ width: 50%;
+}
+
.sideBySideScreenLinkTable {
width: 100%;
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
index fd34729..d76bcca 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
@@ -31,6 +31,7 @@
String patchHeaderPatchSet();
String patchHeaderOld();
String patchHeaderNew();
+ String patchSet();
String patchHistoryTitle();
String disabledOnLargeFiles();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
index 23090a2..24c4140 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
@@ -15,6 +15,7 @@
patchHeaderOld = Old Version
patchHeaderNew = New Version
patchHistoryTitle = Patch History
+patchSet = Patch Set
disabledOnLargeFiles = Disabled on very large source files.
intralineFailure = Intraline difference not available due to server error.
illegalNumberOfColumns = The number of columns cannot be zero or negative
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index 77d8659..7089e2b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -106,6 +106,7 @@
private HistoryTable historyTable;
private FlowPanel topPanel;
private FlowPanel contentPanel;
+ private PatchTableHeader header;
private Label noDifference;
private AbstractPatchContentTable contentTable;
private CommitMessageBlock commitMessageBlock;
@@ -250,6 +251,8 @@
topPanel = new FlowPanel();
add(topPanel);
+ header = new PatchTableHeader(getPatchScreenType());
+
noDifference = new Label(PatchUtil.C.noDifference());
noDifference.setStyleName(Gerrit.RESOURCES.css().patchNoDifference());
noDifference.setVisible(false);
@@ -264,6 +267,7 @@
contentPanel = new FlowPanel();
contentPanel.setStyleName(Gerrit.RESOURCES.css()
.sideBySideScreenSideBySideTable());
+ contentPanel.add(header);
contentPanel.add(noDifference);
contentPanel.add(contentTable);
add(contentPanel);
@@ -439,6 +443,8 @@
setToken(Dispatcher.toPatchUnified(idSideA, patchKey));
}
+ header.display(patchSetDetail, script, patchKey, idSideA, idSideB);
+
if (hasDifferences) {
contentTable.display(patchKey, idSideA, idSideB, script);
contentTable.display(script.getCommentDetail(), script.isExpandAllComments());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.java
new file mode 100644
index 0000000..5dd4e1f
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.java
@@ -0,0 +1,169 @@
+// 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.
+
+package com.google.gerrit.client.patches;
+
+import com.google.gerrit.client.Dispatcher;
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.common.data.PatchScript;
+import com.google.gerrit.common.data.PatchSetDetail;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.SpanElement;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.Anchor;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwtorm.client.KeyUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class PatchSetSelectBox extends Composite {
+ interface Binder extends UiBinder<HTMLPanel, PatchSetSelectBox> {
+ }
+
+ private static Binder uiBinder = GWT.create(Binder.class);
+
+ interface BoxStyle extends CssResource {
+ String selected();
+
+ String hidden();
+ }
+
+ public enum Side {
+ A, B
+ }
+
+ PatchScript script;
+ Patch.Key patchKey;
+ PatchSet.Id idSideA;
+ PatchSet.Id idSideB;
+ PatchSet.Id idActive;
+ Side side;
+ PatchScreen.Type screenType;
+ List<Anchor> links;
+
+ @UiField
+ HTMLPanel linkPanel;
+
+ @UiField
+ BoxStyle style;
+
+ @UiField
+ SpanElement sideMarker;
+
+ public PatchSetSelectBox(Side side, final PatchScreen.Type type) {
+ this.side = side;
+ this.screenType = type;
+
+ initWidget(uiBinder.createAndBindUi(this));
+ }
+
+ public void display(final PatchSetDetail detail, final PatchScript script, Patch.Key key,
+ PatchSet.Id idSideA, PatchSet.Id idSideB) {
+ this.script = script;
+ this.patchKey = key;
+ this.idSideA = idSideA;
+ this.idSideB = idSideB;
+ this.idActive = (side == Side.A) ? idSideA : idSideB;
+ this.links = new LinkedList<Anchor>();
+
+ if (screenType == PatchScreen.Type.UNIFIED) {
+ sideMarker.setInnerText((side == Side.A) ? "(-)" : "(+)");
+ }
+
+ if (detail.getInfo().getParents().size() > 1) {
+ addLink(PatchUtil.C.patchBaseAutoMerge(), null);
+ } else {
+ addLink(PatchUtil.C.patchBase(), null);
+ }
+
+ if (side == Side.B) {
+ links.get(0).setStyleName(style.hidden());
+ }
+
+ for (Patch patch : script.getHistory()) {
+ PatchSet.Id psId = patch.getKey().getParentKey();
+ addLink(Integer.toString(psId.get()), psId);
+ }
+
+ if (idActive == null && side == Side.A) {
+ links.get(0).setStyleName(style.selected());
+ } else {
+ links.get(idActive.get()).setStyleName(style.selected());
+ }
+
+ Anchor downloadLink = getDownloadLink();
+ if (downloadLink != null) {
+ linkPanel.add(new Label(" - "));
+ linkPanel.add(downloadLink);
+ }
+ }
+
+ private void addLink(String label, final PatchSet.Id id) {
+ final Anchor anchor = new Anchor(label);
+ anchor.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ if (side == Side.A) {
+ idSideA = id;
+ } else {
+ idSideB = id;
+ }
+
+ Patch.Key keySideB = new Patch.Key(idSideB, patchKey.get());
+
+ switch (screenType) {
+ case SIDE_BY_SIDE:
+ Gerrit.display(Dispatcher.toPatchSideBySide(idSideA, keySideB));
+ break;
+ case UNIFIED:
+ Gerrit.display(Dispatcher.toPatchUnified(idSideA, keySideB));
+ break;
+ }
+ }
+
+ });
+
+ links.add(anchor);
+ linkPanel.add(anchor);
+ }
+
+ private Anchor getDownloadLink() {
+ boolean isCommitMessage = Patch.COMMIT_MSG.equals(script.getNewName());
+
+ if (isCommitMessage || (side == Side.A && 0 >= script.getA().size())
+ || (side == Side.B && 0 >= script.getB().size())) {
+ return null;
+ }
+
+ Patch.Key key =
+ (idSideA == null) ? patchKey : (new Patch.Key(idSideA, patchKey.get()));
+
+ String sideURL = (side == Side.A) ? "1" : "0";
+ final String base = GWT.getHostPageBaseURL() + "cat/";
+
+ final Anchor anchor = new Anchor(PatchUtil.C.download());
+ anchor.setHref(base + KeyUtil.encode(key.toString()) + "^" + sideURL);
+
+ return anchor;
+ }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.ui.xml
new file mode 100644
index 0000000..2c4bd5d
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchSetSelectBox.ui.xml
@@ -0,0 +1,70 @@
+<?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:with field='res' type='com.google.gerrit.client.GerritResources'/>
+ <ui:with field='cons' type='com.google.gerrit.client.patches.PatchConstants'/>
+ <ui:style type='com.google.gerrit.client.patches.PatchSetSelectBox.BoxStyle'>
+ @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;
+
+ .wrapper {
+ width: 100%;
+ }
+
+ .patchSetLabel {
+ font-weight: bold;
+ }
+
+ .linkPanel > div {
+ display: inline-block;
+ padding: 3px;
+ }
+
+ .linkPanel {
+ font-size: 12px;
+ }
+
+ .linkPanel > a {
+ padding: 3px;
+ display: inline-block;
+ text-decoration: none;
+ }
+
+ .selected {
+ font-weight: bold;
+ background-color: selectionColor;
+ }
+
+ .sideMarker {
+ font-family: monospace;
+ }
+
+ .hidden {
+ visibility: hidden;
+ }
+ </ui:style>
+
+ <g:HTMLPanel styleName='wrapper'>
+ <g:HTMLPanel styleName='{style.linkPanel}' ui:field='linkPanel'><span class='{style.patchSetLabel}'><ui:text from="{cons.patchSet}" /></span> <span class='{style.sideMarker}' ui:field='sideMarker'></span>: </g:HTMLPanel>
+ </g:HTMLPanel>
+</ui:UiBinder>
+
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeader.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeader.java
new file mode 100644
index 0000000..3dd8908
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeader.java
@@ -0,0 +1,71 @@
+// 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.
+
+package com.google.gerrit.client.patches;
+
+import com.google.gerrit.common.data.PatchScript;
+import com.google.gerrit.common.data.PatchSetDetail;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.uibinder.client.UiTemplate;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+
+public class PatchTableHeader extends Composite {
+
+ @UiTemplate("PatchTableHeaderSideBySide.ui.xml")
+ interface SideBySideBinder extends UiBinder<HTMLPanel, PatchTableHeader> {
+ }
+
+ @UiTemplate("PatchTableHeaderUnified.ui.xml")
+ interface UnifiedBinder extends UiBinder<HTMLPanel, PatchTableHeader> {
+ }
+
+ private static SideBySideBinder uiBinderS = GWT.create(SideBySideBinder.class);
+ private static UnifiedBinder uiBinderU = GWT.create(UnifiedBinder.class);
+
+ @UiField
+ SimplePanel sideAPanel;
+
+ @UiField
+ SimplePanel sideBPanel;
+
+ PatchSetSelectBox listA;
+ PatchSetSelectBox listB;
+
+ public PatchTableHeader(PatchScreen.Type type) {
+ listA = new PatchSetSelectBox(PatchSetSelectBox.Side.A, type);
+ listB = new PatchSetSelectBox(PatchSetSelectBox.Side.B, type);
+
+ if (type == PatchScreen.Type.SIDE_BY_SIDE) {
+ initWidget(uiBinderS.createAndBindUi(this));
+ } else {
+ initWidget(uiBinderU.createAndBindUi(this));
+ }
+
+ sideAPanel.add(listA);
+ sideBPanel.add(listB);
+ }
+
+
+ public void display(final PatchSetDetail detail, PatchScript script, final Patch.Key patchKey,
+ final PatchSet.Id idSideA, final PatchSet.Id idSideB) {
+ listA.display(detail, script, patchKey, idSideA, idSideB);
+ listB.display(detail, script, patchKey, idSideA, idSideB);
+ }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderSideBySide.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderSideBySide.ui.xml
new file mode 100644
index 0000000..424e6e5
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderSideBySide.ui.xml
@@ -0,0 +1,64 @@
+<?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 trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
+
+ .wrapper {
+ width: 100%;
+ background-color: trimColor;
+ overflow: hidden;
+ }
+
+ .wrapper .box {
+ width: 100%;
+ text-align: center;
+ }
+
+ .leftWrapper {
+ width: 50%;
+ float: left;
+ }
+
+ .rightWrapper {
+ width: 50%;
+ overflow: hidden;
+ }
+
+ .leftBox {
+ float:left;
+ }
+
+ .rightBox {
+ float: right;
+ }
+ </ui:style>
+
+ <g:HTMLPanel styleName="{style.wrapper}">
+ <div class='{style.leftWrapper}'>
+ <g:SimplePanel addStyleNames='{style.box} {style.leftBox}' ui:field='sideAPanel'/>
+ </div>
+ <div class='{style.rightWrapper}'>
+ <g:SimplePanel addStyleNames='{style.box} {style.rightBox}' ui:field='sideBPanel'/>
+ </div>
+ </g:HTMLPanel>
+</ui:UiBinder>
+
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderUnified.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderUnified.ui.xml
new file mode 100644
index 0000000..e26e96a
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchTableHeaderUnified.ui.xml
@@ -0,0 +1,41 @@
+<?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 trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
+
+ .wrapper {
+ width: 100%;
+ background-color: trimColor;
+ }
+
+ .wrapper .box {
+ width: 100%;
+ text-align: left;
+ margin-left: 3px;
+ }
+ </ui:style>
+
+ <g:HTMLPanel styleName="{style.wrapper}">
+ <g:SimplePanel addStyleNames='{style.box}' ui:field='sideAPanel'/>
+ <g:SimplePanel addStyleNames='{style.box}' ui:field='sideBPanel'/>
+ </g:HTMLPanel>
+</ui:UiBinder>
+
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
index 964ba4b..ec63a83 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
@@ -25,10 +25,7 @@
import com.google.gerrit.common.data.PatchScript.FileMode;
import com.google.gerrit.prettify.common.EditList;
import com.google.gerrit.prettify.common.SparseHtmlFile;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.Patch.ChangeType;
import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Anchor;
@@ -38,8 +35,6 @@
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
-import com.google.gwtorm.client.KeyUtil;
-
import org.eclipse.jgit.diff.Edit;
import java.util.ArrayList;
@@ -89,9 +84,6 @@
script.getDiffPrefs().isIntralineDifference()
&& script.hasIntralineDifference();
- appendHeader(script, nc);
- lines.add(null);
-
if (script.getFileModeA() != FileMode.FILE
|| script.getFileModeB() != FileMode.FILE) {
openLine(nc);
@@ -262,71 +254,6 @@
return row;
}
- private void appendHeader(PatchScript script, final SafeHtmlBuilder m) {
- boolean isCommitMessage = Patch.COMMIT_MSG.equals(script.getNewName());
-
- m.openTr();
-
- m.openTd();
- m.addStyleName(Gerrit.RESOURCES.css().iconCell());
- m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
- m.closeTd();
-
- m.openTd();
- m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
- m.addStyleName(Gerrit.RESOURCES.css().lineNumber());
- m.closeTd();
-
- m.openTd();
- m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
- m.setAttribute("width", "50%");
- if (script.getChangeType() == ChangeType.RENAMED
- || script.getChangeType() == ChangeType.COPIED) {
- m.append(script.getOldName());
- } else {
- m.append(PatchUtil.C.patchHeaderOld());
- }
- if (!isCommitMessage) {
- m.br();
- if (0 < script.getA().size()) {
- if (idSideA == null) {
- downloadLink(m, patchKey, "1");
- } else {
- downloadLink(m, new Patch.Key(idSideA, patchKey.get()), "0");
- }
- }
- }
- m.closeTd();
-
- m.openTd();
- m.setStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
- m.setAttribute("width", "50%");
- m.append(PatchUtil.C.patchHeaderNew());
- if (!isCommitMessage) {
- m.br();
- if (0 < script.getB().size()) {
- downloadLink(m, new Patch.Key(idSideB, patchKey.get()), "0");
- }
- }
- m.closeTd();
-
- m.openTd();
- m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
- m.addStyleName(Gerrit.RESOURCES.css().lineNumber());
- m.closeTd();
-
- m.closeTr();
- }
-
- private void downloadLink(final SafeHtmlBuilder m, final Patch.Key key,
- final String side) {
- final String base = GWT.getHostPageBaseURL() + "cat/";
- m.openAnchor();
- m.setAttribute("href", base + KeyUtil.encode(key.toString()) + "^" + side);
- m.append(PatchUtil.C.download());
- m.closeAnchor();
- }
-
private void appendSkipLine(final SafeHtmlBuilder m, final int skipCnt) {
m.openTr();
diff --git a/gerrit-httpd/.settings/org.eclipse.core.resources.prefs b/gerrit-httpd/.settings/org.eclipse.core.resources.prefs
index 9df523e..839d647 100644
--- a/gerrit-httpd/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-httpd/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
index f92f13d..72bb0c2 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -90,6 +90,10 @@
config.setAllowedOpenIDs(authConfig.getAllowedOpenIDs());
break;
+ case OPENID_SSO:
+ config.setOpenIdSsoUrl(authConfig.getOpenIdSsoUrl());
+ break;
+
case LDAP:
case LDAP_BIND:
config.setRegisterUrl(cfg.getString("auth", null, "registerurl"));
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
index 0d14b79..1a48bb5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
@@ -108,6 +108,7 @@
break;
case OPENID:
+ case OPENID_SSO:
// OpenID support is bound in WebAppInitializer and Daemon.
case CUSTOM_EXTENSION:
break;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java
index 68379d7..a2f4c99 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java
@@ -43,6 +43,9 @@
theme.trimColor = color(name, "trimColor", "#D4E9A9");
theme.selectionColor = color(name, "selectionColor", "#FFFFCC");
theme.topMenuColor = color(name, "topMenuColor", theme.trimColor);
+ theme.changeTableOutdatedColor = color(name, "changeTableOutdatedColor", "#FF0000");
+ theme.tableOddRowColor = color(name, "tableOddRowColor", "transparent");
+ theme.tableEvenRowColor = color(name, "tableEvenRowColor", "transparent");
return theme;
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
index c7b4c79..aca2e05 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
@@ -31,15 +31,20 @@
import com.google.gerrit.reviewdb.client.AccountGroupIncludeAudit;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
+import com.google.gerrit.server.account.AccountException;
+import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountResolver;
+import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupBackends;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.account.GroupIncludeCache;
+import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.VoidResult;
import com.google.gwtorm.server.OrmException;
@@ -54,6 +59,8 @@
GroupAdminService {
private final AccountCache accountCache;
private final AccountResolver accountResolver;
+ private final AccountManager accountManager;
+ private final AuthType authType;
private final GroupCache groupCache;
private final GroupBackend groupBackend;
private final GroupIncludeCache groupIncludeCache;
@@ -70,6 +77,8 @@
final AccountCache accountCache,
final GroupIncludeCache groupIncludeCache,
final AccountResolver accountResolver,
+ final AccountManager accountManager,
+ final AuthConfig authConfig,
final GroupCache groupCache,
final GroupBackend groupBackend,
final GroupControl.Factory groupControlFactory,
@@ -81,6 +90,8 @@
this.accountCache = accountCache;
this.groupIncludeCache = groupIncludeCache;
this.accountResolver = accountResolver;
+ this.accountManager = accountManager;
+ this.authType = authConfig.getAuthType();
this.groupCache = groupCache;
this.groupBackend = groupBackend;
this.groupControlFactory = groupControlFactory;
@@ -366,13 +377,38 @@
private Account findAccount(final String nameOrEmail) throws OrmException,
Failure {
- final Account r = accountResolver.find(nameOrEmail);
+ Account r = accountResolver.find(nameOrEmail);
if (r == null) {
- throw new Failure(new NoSuchAccountException(nameOrEmail));
+ switch (authType) {
+ case HTTP_LDAP:
+ case CLIENT_SSL_CERT_LDAP:
+ case LDAP:
+ r = createAccountByLdap(nameOrEmail);
+ break;
+ default:
+ }
+ if (r == null) {
+ throw new Failure(new NoSuchAccountException(nameOrEmail));
+ }
}
return r;
}
+ private Account createAccountByLdap(String user) {
+ if (!user.matches(Account.USER_NAME_PATTERN)) {
+ return null;
+ }
+
+ try {
+ final AuthRequest req = AuthRequest.forUser(user);
+ req.setSkipAuthentication(true);
+ return accountCache.get(accountManager.authenticate(req).getAccountId())
+ .getAccount();
+ } catch (AccountException e) {
+ return null;
+ }
+ }
+
private AccountGroup findGroup(final String name) throws OrmException,
Failure {
final AccountGroup g = groupCache.get(new AccountGroup.NameKey(name));
diff --git a/gerrit-launcher/.settings/org.eclipse.core.resources.prefs b/gerrit-launcher/.settings/org.eclipse.core.resources.prefs
index c780f44..e9441bb 100644
--- a/gerrit-launcher/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-launcher/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-main/.settings/org.eclipse.core.resources.prefs b/gerrit-main/.settings/org.eclipse.core.resources.prefs
index c780f44..e9441bb 100644
--- a/gerrit-main/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-main/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-openid/.settings/org.eclipse.core.resources.prefs b/gerrit-openid/.settings/org.eclipse.core.resources.prefs
index fc11c3f..f9fe345 100644
--- a/gerrit-openid/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-openid/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
diff --git a/gerrit-patch-commonsnet/.settings/org.eclipse.core.resources.prefs b/gerrit-patch-commonsnet/.settings/org.eclipse.core.resources.prefs
index 589908f..e9441bb 100644
--- a/gerrit-patch-commonsnet/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-patch-commonsnet/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-patch-jgit/.settings/org.eclipse.core.resources.prefs b/gerrit-patch-jgit/.settings/org.eclipse.core.resources.prefs
index 589908f..e9441bb 100644
--- a/gerrit-patch-jgit/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-patch-jgit/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-pgm/.settings/org.eclipse.core.resources.prefs b/gerrit-pgm/.settings/org.eclipse.core.resources.prefs
index 9df523e..839d647 100644
--- a/gerrit-pgm/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-pgm/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
index 282bbc9..02b0a1d 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
@@ -367,7 +367,8 @@
}
AuthConfig authConfig = cfgInjector.getInstance(AuthConfig.class);
- if (authConfig.getAuthType() == AuthType.OPENID) {
+ if (authConfig.getAuthType() == AuthType.OPENID ||
+ authConfig.getAuthType() == AuthType.OPENID_SSO) {
modules.add(new OpenIdModule());
}
modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
index f100372..525360d 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
@@ -21,7 +21,6 @@
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountCacheImpl;
@@ -35,6 +34,7 @@
import com.google.gerrit.server.git.CreateCodeReviewNotes;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
+import com.google.gerrit.server.git.NotesBranchUtil;
import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
@@ -44,7 +44,6 @@
import com.google.inject.Scopes;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.ThreadSafeProgressMonitor;
@@ -104,6 +103,7 @@
@Override
protected void configure() {
factory(CreateCodeReviewNotes.Factory.class);
+ factory(NotesBranchUtil.Factory.class);
}
});
install(new LifecycleModule() {
@@ -172,21 +172,8 @@
}
try {
CreateCodeReviewNotes notes = codeReviewNotesFactory.create(db, git);
- try {
- notes.loadBase();
- for (Change change : changes) {
- monitor.update(1);
- PatchSet ps = db.patchSets().get(change.currentPatchSetId());
- if (ps == null) {
- continue;
- }
- notes.add(change, ObjectId.fromString(ps.getRevision().get()));
- }
- notes.commit("Exported prior reviews from Gerrit Code Review\n");
- notes.updateRef();
- } finally {
- notes.release();
- }
+ notes.create(changes, null,
+ "Exported prior reviews from Gerrit Code Review\n", monitor);
} finally {
git.close();
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
index 2d56453..95b8487f 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
@@ -141,12 +141,12 @@
}
final StringBuilder buf = new StringBuilder();
- buf.append(why.getMessage());
- why = why.getCause();
while (why != null) {
- buf.append("\n caused by ");
- buf.append(why.toString());
+ buf.append(why.getMessage());
why = why.getCause();
+ if (why != null) {
+ buf.append("\n caused by ");
+ }
}
throw die(buf.toString(), new RuntimeException("InitInjector failed", ce));
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
index ee7c794..2d6db63 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
@@ -97,7 +97,7 @@
this.userProvider = userProvider;
this.queue = queue;
this.context = context;
- this.maxWait = getTimeUnit(cfg, "httpd", null, "maxwait", 5, MINUTES);
+ this.maxWait = MINUTES.toMillis(getTimeUnit(cfg, "httpd", null, "maxwait", 5, MINUTES));
}
@Override
diff --git a/gerrit-plugin-archetype/.settings/org.eclipse.core.resources.prefs b/gerrit-plugin-archetype/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..abdea9ac
--- /dev/null
+++ b/gerrit-plugin-archetype/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding/<project>=UTF-8
diff --git a/gerrit-plugin-archetype/.settings/org.eclipse.jdt.core.prefs b/gerrit-plugin-archetype/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..470942d
--- /dev/null
+++ b/gerrit-plugin-archetype/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,269 @@
+#Thu Jul 28 11:02:36 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/gerrit-prettify/.settings/org.eclipse.core.resources.prefs b/gerrit-prettify/.settings/org.eclipse.core.resources.prefs
index e7d6680..abdea9ac 100644
--- a/gerrit-prettify/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-prettify/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-reviewdb/.settings/org.eclipse.core.resources.prefs b/gerrit-reviewdb/.settings/org.eclipse.core.resources.prefs
index e7d6680..abdea9ac 100644
--- a/gerrit-reviewdb/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-reviewdb/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
index 962426b..b615fc5 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
@@ -18,6 +18,9 @@
/** Login relies upon the OpenID standard: {@link "http://openid.net/"} */
OPENID,
+ /** Login relies upon the OpenID standard: {@link "http://openid.net/"} in Single Sign On mode */
+ OPENID_SSO,
+
/**
* Login relies upon the container/web server security.
* <p>
diff --git a/gerrit-server/.settings/org.eclipse.core.resources.prefs b/gerrit-server/.settings/org.eclipse.core.resources.prefs
index 7d5f965..29abf99 100644
--- a/gerrit-server/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-server/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
index 6f1096c..dc36988 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
@@ -39,6 +39,7 @@
private final boolean userNameToLowerCase;
private final boolean gitBasicAuth;
private final String logoutUrl;
+ private final String openIdSsoUrl;
private final List<OpenIdProviderPattern> trustedOpenIDs;
private final List<OpenIdProviderPattern> allowedOpenIDs;
private final String cookiePath;
@@ -53,6 +54,7 @@
authType = toType(cfg);
httpHeader = cfg.getString("auth", null, "httpheader");
logoutUrl = cfg.getString("auth", null, "logouturl");
+ openIdSsoUrl = cfg.getString("auth", null, "openidssourl");
trustedOpenIDs = toPatterns(cfg, "trustedOpenID");
allowedOpenIDs = toPatterns(cfg, "allowedOpenID");
cookiePath = cfg.getString("auth", null, "cookiepath");
@@ -111,6 +113,10 @@
return logoutUrl;
}
+ public String getOpenIdSsoUrl() {
+ return openIdSsoUrl;
+ }
+
public String getCookiePath() {
return cookiePath;
}
@@ -161,6 +167,10 @@
//
return true;
+ case OPENID_SSO:
+ // There's only one provider in SSO mode, so it must be okay.
+ return true;
+
case OPENID:
// All identities must be trusted in order to trust the account.
//
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
index 71676ad..ba54c56 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
@@ -35,6 +35,7 @@
import com.google.gerrit.server.git.CreateCodeReviewNotes;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MetaDataUpdate;
+import com.google.gerrit.server.git.NotesBranchUtil;
import com.google.gerrit.server.git.SubmoduleOp;
import com.google.gerrit.server.mail.AbandonedSender;
import com.google.gerrit.server.mail.AddReviewerSender;
@@ -82,6 +83,7 @@
factory(SubmoduleOp.Factory.class);
factory(MergeOp.Factory.class);
factory(CreateCodeReviewNotes.Factory.class);
+ factory(NotesBranchUtil.Factory.class);
install(new AsyncReceiveCommits.Module());
// Not really per-request, but dammit, I don't know where else to
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
index 4bfee9c..da38573 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
@@ -16,6 +16,7 @@
import static com.google.gerrit.server.git.GitRepositoryManager.REF_REJECT_COMMITS;
+import com.google.common.base.Strings;
import com.google.gerrit.common.errors.PermissionDeniedException;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
@@ -23,34 +24,25 @@
import com.google.inject.Inject;
import com.google.inject.Provider;
-import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.Note;
import org.eclipse.jgit.notes.NoteMap;
-import org.eclipse.jgit.notes.NoteMapMerger;
-import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
public class BanCommit {
-
- private static final int MAX_LOCK_FAILURE_CALLS = 10;
- private static final int SLEEP_ON_LOCK_FAILURE_MS = 25;
-
public interface Factory {
BanCommit create();
}
@@ -58,49 +50,37 @@
private final Provider<IdentifiedUser> currentUser;
private final GitRepositoryManager repoManager;
private final PersonIdent gerritIdent;
+ private NotesBranchUtil.Factory notesBranchUtilFactory;
@Inject
BanCommit(final Provider<IdentifiedUser> currentUser,
final GitRepositoryManager repoManager,
- @GerritPersonIdent final PersonIdent gerritIdent) {
+ @GerritPersonIdent final PersonIdent gerritIdent,
+ final NotesBranchUtil.Factory notesBranchUtilFactory) {
this.currentUser = currentUser;
this.repoManager = repoManager;
this.gerritIdent = gerritIdent;
+ this.notesBranchUtilFactory = notesBranchUtilFactory;
}
public BanCommitResult ban(final ProjectControl projectControl,
final List<ObjectId> commitsToBan, final String reason)
throws PermissionDeniedException, IOException,
- InterruptedException, MergeException {
+ InterruptedException, MergeException, ConcurrentRefUpdateException {
if (!projectControl.isOwner()) {
throw new PermissionDeniedException(
"No project owner: not permitted to ban commits");
}
final BanCommitResult result = new BanCommitResult();
-
- final PersonIdent currentUserIdent = createPersonIdent();
+ NoteMap banCommitNotes = NoteMap.newEmptyMap();
+ // add a note for each banned commit to notes
final Repository repo =
repoManager.openRepository(projectControl.getProject().getNameKey());
try {
final RevWalk revWalk = new RevWalk(repo);
final ObjectInserter inserter = repo.newObjectInserter();
try {
- NoteMap baseNoteMap = null;
- RevCommit baseCommit = null;
- final Ref notesBranch = repo.getRef(REF_REJECT_COMMITS);
- if (notesBranch != null) {
- baseCommit = revWalk.parseCommit(notesBranch.getObjectId());
- baseNoteMap = NoteMap.read(revWalk.getObjectReader(), baseCommit);
- }
-
- final NoteMap ourNoteMap;
- if (baseCommit != null) {
- ourNoteMap = NoteMap.read(repo.newObjectReader(), baseCommit);
- } else {
- ourNoteMap = NoteMap.newEmptyMap();
- }
-
for (final ObjectId commitToBan : commitsToBan) {
try {
revWalk.parseCommit(commitToBan);
@@ -110,31 +90,22 @@
result.notACommit(commitToBan, e.getMessage());
continue;
}
+ banCommitNotes.set(commitToBan, createNoteContent(reason, inserter));
+ }
+ inserter.flush();
+ NotesBranchUtil notesBranchUtil = notesBranchUtilFactory.create(repo);
+ NoteMap newlyCreated =
+ notesBranchUtil.commitNewNotes(banCommitNotes, REF_REJECT_COMMITS,
+ createPersonIdent(), buildCommitMessage(commitsToBan, reason));
- final Note note = ourNoteMap.getNote(commitToBan);
- if (note != null) {
- result.commitAlreadyBanned(commitToBan);
- continue;
+ for (Note n : banCommitNotes) {
+ if (newlyCreated.contains(n)) {
+ result.commitBanned(n);
+ } else {
+ result.commitAlreadyBanned(n);
}
-
- final String noteContent = reason != null ? reason : "";
- final ObjectId noteContentId =
- inserter
- .insert(Constants.OBJ_BLOB, noteContent.getBytes("UTF-8"));
- ourNoteMap.set(commitToBan, noteContentId);
- result.commitBanned(commitToBan);
}
-
- if (result.getNewlyBannedCommits().isEmpty()) {
- return result;
- }
-
- final ObjectId ourCommit =
- commit(ourNoteMap, inserter, currentUserIdent, baseCommit, result,
- reason);
-
- updateRef(repo, revWalk, inserter, ourNoteMap, ourCommit, baseNoteMap,
- baseCommit);
+ return result;
} finally {
revWalk.release();
inserter.release();
@@ -142,8 +113,15 @@
} finally {
repo.close();
}
+ }
- return result;
+ private ObjectId createNoteContent(String reason, ObjectInserter inserter)
+ throws UnsupportedEncodingException, IOException {
+ String noteContent = reason != null ? reason : "";
+ if (noteContent.length() > 0 && !noteContent.endsWith("\n")) {
+ noteContent = noteContent + "\n";
+ }
+ return inserter.insert(Constants.OBJ_BLOB, noteContent.getBytes("UTF-8"));
}
private PersonIdent createPersonIdent() {
@@ -152,35 +130,6 @@
return currentUser.get().newCommitterIdent(now, tz);
}
- private static ObjectId commit(final NoteMap noteMap,
- final ObjectInserter inserter, final PersonIdent personIdent,
- final ObjectId baseCommit, final BanCommitResult result,
- final String reason) throws IOException {
- final String commitMsg =
- buildCommitMessage(result.getNewlyBannedCommits(), reason);
- if (baseCommit != null) {
- return createCommit(noteMap, inserter, personIdent, commitMsg, baseCommit);
- } else {
- return createCommit(noteMap, inserter, personIdent, commitMsg);
- }
- }
-
- private static ObjectId createCommit(final NoteMap noteMap,
- final ObjectInserter inserter, final PersonIdent personIdent,
- final String message, final ObjectId... parents) throws IOException {
- final CommitBuilder b = new CommitBuilder();
- b.setTreeId(noteMap.writeTree(inserter));
- b.setAuthor(personIdent);
- b.setCommitter(personIdent);
- if (parents.length > 0) {
- b.setParentIds(parents);
- }
- b.setMessage(message);
- final ObjectId commitId = inserter.insert(b);
- inserter.flush();
- return commitId;
- }
-
private static String buildCommitMessage(final List<ObjectId> bannedCommits,
final String reason) {
final StringBuilder commitMsg = new StringBuilder();
@@ -205,61 +154,4 @@
commitMsg.append(commitList);
return commitMsg.toString();
}
-
- public void updateRef(final Repository repo, final RevWalk revWalk,
- final ObjectInserter inserter, final NoteMap ourNoteMap,
- final ObjectId oursCommit, final NoteMap baseNoteMap,
- final ObjectId baseCommit) throws IOException, InterruptedException,
- MissingObjectException, IncorrectObjectTypeException,
- CorruptObjectException, MergeException {
-
- int remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
- RefUpdate refUpdate = createRefUpdate(repo, oursCommit, baseCommit);
-
- for (;;) {
- final Result result = refUpdate.update();
-
- if (result == Result.LOCK_FAILURE) {
- if (--remainingLockFailureCalls > 0) {
- Thread.sleep(SLEEP_ON_LOCK_FAILURE_MS);
- } else {
- throw new MergeException("Failed to lock the ref: "
- + REF_REJECT_COMMITS);
- }
-
- } else if (result == Result.REJECTED) {
- final RevCommit theirsCommit =
- revWalk.parseCommit(refUpdate.getOldObjectId());
- final NoteMap theirNoteMap =
- NoteMap.read(revWalk.getObjectReader(), theirsCommit);
- final NoteMapMerger merger = new NoteMapMerger(repo);
- final NoteMap merged =
- merger.merge(baseNoteMap, ourNoteMap, theirNoteMap);
- final ObjectId mergeCommit =
- createCommit(merged, inserter, gerritIdent,
- "Merged note commits\n", oursCommit, theirsCommit);
- refUpdate = createRefUpdate(repo, mergeCommit, theirsCommit);
- remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
-
- } else if (result == Result.IO_FAILURE) {
- throw new IOException(
- "Couldn't create commit reject notes because of IO_FAILURE");
- } else {
- break;
- }
- }
- }
-
- private static RefUpdate createRefUpdate(final Repository repo,
- final ObjectId newObjectId, final ObjectId expectedOldObjectId)
- throws IOException {
- RefUpdate refUpdate = repo.updateRef(REF_REJECT_COMMITS);
- refUpdate.setNewObjectId(newObjectId);
- if (expectedOldObjectId == null) {
- refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
- } else {
- refUpdate.setExpectedOldObjectId(expectedOldObjectId);
- }
- return refUpdate;
- }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
index 6fea8f1..b067a49 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
@@ -20,6 +20,7 @@
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
@@ -31,23 +32,15 @@
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.notes.Note;
import org.eclipse.jgit.notes.NoteMap;
-import org.eclipse.jgit.notes.NoteMapMerger;
-import org.eclipse.jgit.notes.NoteMerger;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -68,30 +61,22 @@
CreateCodeReviewNotes create(ReviewDb reviewDb, Repository db);
}
- private static final int MAX_LOCK_FAILURE_CALLS = 10;
- private static final int SLEEP_ON_LOCK_FAILURE_MS = 25;
private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
- private final ReviewDb schema;
- private final PersonIdent gerritIdent;
private final AccountCache accountCache;
private final ApprovalTypes approvalTypes;
private final String canonicalWebUrl;
private final String anonymousCowardName;
+ private final ReviewDb schema;
private final Repository db;
- private final RevWalk revWalk;
- private final ObjectInserter inserter;
- private final ObjectReader reader;
- private RevCommit baseCommit;
- private NoteMap base;
-
- private RevCommit oursCommit;
- private NoteMap ours;
-
- private List<CodeReviewCommit> commits;
private PersonIdent author;
+ private RevWalk revWalk;
+ private ObjectInserter inserter;
+
+ private final NotesBranchUtil.Factory notesBranchUtilFactory;
+
@Inject
CreateCodeReviewNotes(
@GerritPersonIdent final PersonIdent gerritIdent,
@@ -99,90 +84,87 @@
final ApprovalTypes approvalTypes,
final @Nullable @CanonicalWebUrl String canonicalWebUrl,
final @AnonymousCowardName String anonymousCowardName,
+ final NotesBranchUtil.Factory notesBranchUtilFactory,
final @Assisted ReviewDb reviewDb,
final @Assisted Repository db) {
- schema = reviewDb;
this.author = gerritIdent;
- this.gerritIdent = gerritIdent;
this.accountCache = accountCache;
this.approvalTypes = approvalTypes;
this.canonicalWebUrl = canonicalWebUrl;
this.anonymousCowardName = anonymousCowardName;
+ this.notesBranchUtilFactory = notesBranchUtilFactory;
+ schema = reviewDb;
this.db = db;
-
- revWalk = new RevWalk(db);
- inserter = db.newObjectInserter();
- reader = db.newObjectReader();
}
public void create(List<CodeReviewCommit> commits, PersonIdent author)
throws CodeReviewNoteCreationException {
try {
- this.commits = commits;
- this.author = author;
- loadBase();
- applyNotes();
- updateRef();
+ revWalk = new RevWalk(db);
+ inserter = db.newObjectInserter();
+ if (author != null) {
+ this.author = author;
+ }
+
+ NoteMap notes = NoteMap.newEmptyMap();
+ StringBuilder message =
+ new StringBuilder("Update notes for submitted changes\n\n");
+ for (CodeReviewCommit c : commits) {
+ notes.set(c, createNoteContent(c.change, c));
+ message.append("* ").append(c.getShortMessage()).append("\n");
+ }
+
+ NotesBranchUtil notesBranchUtil = notesBranchUtilFactory.create(db);
+ notesBranchUtil.commitAllNotes(notes, REFS_NOTES_REVIEW, author,
+ message.toString());
} catch (IOException e) {
throw new CodeReviewNoteCreationException(e);
- } catch (InterruptedException e) {
+ } catch (ConcurrentRefUpdateException e) {
throw new CodeReviewNoteCreationException(e);
} finally {
- release();
+ revWalk.release();
+ inserter.release();
}
}
- public void loadBase() throws IOException {
- Ref notesBranch = db.getRef(REFS_NOTES_REVIEW);
- if (notesBranch != null) {
- baseCommit = revWalk.parseCommit(notesBranch.getObjectId());
- base = NoteMap.read(revWalk.getObjectReader(), baseCommit);
- }
- if (baseCommit != null) {
- ours = NoteMap.read(db.newObjectReader(), baseCommit);
- } else {
- ours = NoteMap.newEmptyMap();
+ public void create(List<Change> changes, PersonIdent author,
+ String commitMessage, ProgressMonitor monitor) throws OrmException,
+ IOException, CodeReviewNoteCreationException {
+ try {
+ revWalk = new RevWalk(db);
+ inserter = db.newObjectInserter();
+ if (author != null) {
+ this.author = author;
+ }
+ if (monitor == null) {
+ monitor = NullProgressMonitor.INSTANCE;
+ }
+
+ NoteMap notes = NoteMap.newEmptyMap();
+ for (Change c : changes) {
+ monitor.update(1);
+ PatchSet ps = schema.patchSets().get(c.currentPatchSetId());
+ ObjectId commitId = ObjectId.fromString(ps.getRevision().get());
+ notes.set(commitId, createNoteContent(c, commitId));
+ }
+
+ NotesBranchUtil notesBranchUtil = notesBranchUtilFactory.create(db);
+ notesBranchUtil.commitAllNotes(notes, REFS_NOTES_REVIEW, author,
+ commitMessage);
+ } catch (ConcurrentRefUpdateException e) {
+ throw new CodeReviewNoteCreationException(e);
+ } finally {
+ revWalk.release();
+ inserter.release();
}
}
- private void applyNotes() throws IOException, CodeReviewNoteCreationException {
- StringBuilder message =
- new StringBuilder("Update notes for submitted changes\n\n");
- for (CodeReviewCommit c : commits) {
- add(c.change, c);
- message.append("* ").append(c.getShortMessage()).append("\n");
- }
- commit(message.toString());
- }
-
- public void commit(String message) throws IOException {
- if (baseCommit != null) {
- oursCommit = createCommit(ours, author, message, baseCommit);
- } else {
- oursCommit = createCommit(ours, author, message);
- }
- }
-
- public void add(Change change, ObjectId commit)
- throws MissingObjectException, IncorrectObjectTypeException, IOException,
- CodeReviewNoteCreationException {
+ private ObjectId createNoteContent(Change change, ObjectId commit)
+ throws CodeReviewNoteCreationException, IOException {
if (!(commit instanceof RevCommit)) {
commit = revWalk.parseCommit(commit);
}
-
- RevCommit c = (RevCommit) commit;
- ObjectId noteContent = createNoteContent(change, c);
- if (ours.contains(c)) {
- // merge the existing and the new note as if they are both new
- // means: base == null
- // there is not really a common ancestry for these two note revisions
- // use the same NoteMerger that is used from the NoteMapMerger
- NoteMerger noteMerger = new ReviewNoteMerger();
- Note newNote = new Note(c, noteContent);
- noteContent = noteMerger.merge(null, newNote, ours.getNote(c),
- reader, inserter).getData();
- }
- ours.set(c, noteContent);
+ return createNoteContent(change, (RevCommit) commit);
}
private ObjectId createNoteContent(Change change, RevCommit commit)
@@ -227,83 +209,4 @@
throw new CodeReviewNoteCreationException(commit, e);
}
}
-
- public void updateRef() throws IOException, InterruptedException,
- CodeReviewNoteCreationException, MissingObjectException,
- IncorrectObjectTypeException, CorruptObjectException {
- if (baseCommit != null && oursCommit.getTree().equals(baseCommit.getTree())) {
- // If the trees are identical, there is no change in the notes.
- // Avoid saving this commit as it has no new information.
- return;
- }
-
- int remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
- RefUpdate refUpdate = createRefUpdate(oursCommit, baseCommit);
-
- for (;;) {
- Result result = refUpdate.update();
-
- if (result == Result.LOCK_FAILURE) {
- if (--remainingLockFailureCalls > 0) {
- Thread.sleep(SLEEP_ON_LOCK_FAILURE_MS);
- } else {
- throw new CodeReviewNoteCreationException(
- "Failed to lock the ref: " + REFS_NOTES_REVIEW);
- }
-
- } else if (result == Result.REJECTED) {
- RevCommit theirsCommit =
- revWalk.parseCommit(refUpdate.getOldObjectId());
- NoteMap theirs =
- NoteMap.read(revWalk.getObjectReader(), theirsCommit);
- NoteMapMerger merger = new NoteMapMerger(db);
- NoteMap merged = merger.merge(base, ours, theirs);
- RevCommit mergeCommit =
- createCommit(merged, gerritIdent, "Merged note commits\n",
- theirsCommit, oursCommit);
- refUpdate = createRefUpdate(mergeCommit, theirsCommit);
- remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
-
- } else if (result == Result.IO_FAILURE) {
- throw new CodeReviewNoteCreationException(
- "Couldn't create code review notes because of IO_FAILURE");
- } else {
- break;
- }
- }
- }
-
- public void release() {
- reader.release();
- inserter.release();
- revWalk.release();
- }
-
- private RevCommit createCommit(NoteMap map, PersonIdent author,
- String message, RevCommit... parents) throws IOException {
- CommitBuilder b = new CommitBuilder();
- b.setTreeId(map.writeTree(inserter));
- b.setAuthor(author != null ? author : gerritIdent);
- b.setCommitter(gerritIdent);
- if (parents.length > 0) {
- b.setParentIds(parents);
- }
- b.setMessage(message);
- ObjectId commitId = inserter.insert(b);
- inserter.flush();
- return revWalk.parseCommit(commitId);
- }
-
-
- private RefUpdate createRefUpdate(ObjectId newObjectId,
- ObjectId expectedOldObjectId) throws IOException {
- RefUpdate refUpdate = db.updateRef(REFS_NOTES_REVIEW);
- refUpdate.setNewObjectId(newObjectId);
- if (expectedOldObjectId == null) {
- refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
- } else {
- refUpdate.setExpectedOldObjectId(expectedOldObjectId);
- }
- return refUpdate;
- }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
new file mode 100644
index 0000000..17cfea8
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
@@ -0,0 +1,271 @@
+// 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.
+
+package com.google.gerrit.server.git;
+
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.merge.MergeStrategy;
+import org.eclipse.jgit.notes.Note;
+import org.eclipse.jgit.notes.NoteMap;
+import org.eclipse.jgit.notes.NoteMapMerger;
+import org.eclipse.jgit.notes.NoteMerger;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import java.io.IOException;
+
+/**
+ * A utility class for updating a notes branch with automatic merge of note
+ * trees.
+ */
+public class NotesBranchUtil {
+ public interface Factory {
+ NotesBranchUtil create(Repository db);
+ }
+
+ private static final int MAX_LOCK_FAILURE_CALLS = 10;
+ private static final int SLEEP_ON_LOCK_FAILURE_MS = 25;
+
+ private PersonIdent gerritIdent;
+ private final Repository db;
+
+ private RevCommit baseCommit;
+ private NoteMap base;
+
+ private RevCommit oursCommit;
+ private NoteMap ours;
+
+ private RevWalk revWalk;
+ private ObjectInserter inserter;
+ private ObjectReader reader;
+ private boolean overwrite;
+
+ private ReviewNoteMerger noteMerger;
+
+ @Inject
+ public NotesBranchUtil(@GerritPersonIdent final PersonIdent gerritIdent,
+ @Assisted Repository db) {
+ this.gerritIdent = gerritIdent;
+ this.db = db;
+ }
+
+ /**
+ * Create a new commit in the <code>notesBranch</code> by updating existing
+ * or creating new notes from the <code>notes</code> map.
+ *
+ * @param notes map of notes
+ * @param notesBranch notes branch to update
+ * @param commitAuthor author of the commit in the notes branch
+ * @param commitMessage for the commit in the notes branch
+ * @throws IOException
+ * @throws ConcurrentRefUpdateException
+ */
+ public final void commitAllNotes(NoteMap notes, String notesBranch,
+ PersonIdent commitAuthor, String commitMessage) throws IOException,
+ ConcurrentRefUpdateException {
+ this.overwrite = true;
+ commitNotes(notes, notesBranch, commitAuthor, commitMessage);
+ }
+
+ /**
+ * Create a new commit in the <code>notesBranch</code> by creating not yet
+ * existing notes from the <code>notes</code> map. The notes from the
+ * <code>notes</code> map which already exist in the note-tree of the
+ * tip of the <code>notesBranch</code> will not be updated.
+ *
+ * @param notes map of notes
+ * @param notesBranch notes branch to update
+ * @param commitAuthor author of the commit in the notes branch
+ * @param commitMessage for the commit in the notes branch
+ * @return map with those notes from the <code>notes</code> that were newly
+ * created
+ * @throws IOException
+ * @throws ConcurrentRefUpdateException
+ */
+ public final NoteMap commitNewNotes(NoteMap notes, String notesBranch,
+ PersonIdent commitAuthor, String commitMessage) throws IOException,
+ ConcurrentRefUpdateException {
+ this.overwrite = false;
+ commitNotes(notes, notesBranch, commitAuthor, commitMessage);
+ NoteMap newlyCreated = NoteMap.newEmptyMap();
+ for (Note n : notes) {
+ if (base == null || !base.contains(n)) {
+ newlyCreated.set(n, n.getData());
+ }
+ }
+ return newlyCreated;
+ }
+
+ private void commitNotes(NoteMap notes, String notesBranch,
+ PersonIdent commitAuthor, String commitMessage) throws IOException,
+ ConcurrentRefUpdateException {
+ try {
+ revWalk = new RevWalk(db);
+ inserter = db.newObjectInserter();
+ reader = db.newObjectReader();
+ loadBase(notesBranch);
+ if (overwrite) {
+ addAllNotes(notes);
+ } else {
+ addNewNotes(notes);
+ }
+ if (base != null) {
+ oursCommit = createCommit(ours, commitAuthor, commitMessage, baseCommit);
+ } else {
+ oursCommit = createCommit(ours, commitAuthor, commitMessage);
+ }
+ updateRef(notesBranch);
+ } finally {
+ revWalk.release();
+ inserter.release();
+ reader.release();
+ }
+ }
+
+ private void addNewNotes(NoteMap notes) throws IOException {
+ for (Note n : notes) {
+ if (! ours.contains(n)) {
+ ours.set(n, n.getData());
+ }
+ }
+ }
+
+ private void addAllNotes(NoteMap notes) throws IOException {
+ for (Note n : notes) {
+ if (ours.contains(n)) {
+ // Merge the existing and the new note as if they are both new,
+ // means: base == null
+ // There is no really a common ancestry for these two note revisions
+ ObjectId noteContent = getNoteMerger().merge(null, n, ours.getNote(n),
+ reader, inserter).getData();
+ ours.set(n, noteContent);
+ } else {
+ ours.set(n, n.getData());
+ }
+ }
+ }
+
+ private NoteMerger getNoteMerger() {
+ if (noteMerger == null) {
+ noteMerger = new ReviewNoteMerger();
+ }
+ return noteMerger;
+ }
+
+ private void loadBase(String notesBranch) throws IOException {
+ Ref branch = db.getRef(notesBranch);
+ if (branch != null) {
+ baseCommit = revWalk.parseCommit(branch.getObjectId());
+ base = NoteMap.read(revWalk.getObjectReader(), baseCommit);
+ }
+ if (baseCommit != null) {
+ ours = NoteMap.read(revWalk.getObjectReader(), baseCommit);
+ } else {
+ ours = NoteMap.newEmptyMap();
+ }
+ }
+
+ private RevCommit createCommit(NoteMap map, PersonIdent author,
+ String message, RevCommit... parents) throws IOException {
+ CommitBuilder b = new CommitBuilder();
+ b.setTreeId(map.writeTree(inserter));
+ b.setAuthor(author != null ? author : gerritIdent);
+ b.setCommitter(gerritIdent);
+ if (parents.length > 0) {
+ b.setParentIds(parents);
+ }
+ b.setMessage(message);
+ ObjectId commitId = inserter.insert(b);
+ inserter.flush();
+ return revWalk.parseCommit(commitId);
+ }
+
+ private void updateRef(String notesBranch) throws IOException,
+ MissingObjectException, IncorrectObjectTypeException,
+ CorruptObjectException, ConcurrentRefUpdateException {
+ if (baseCommit != null && oursCommit.getTree().equals(baseCommit.getTree())) {
+ // If the trees are identical, there is no change in the notes.
+ // Avoid saving this commit as it has no new information.
+ return;
+ }
+
+ int remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
+ RefUpdate refUpdate = createRefUpdate(notesBranch, oursCommit, baseCommit);
+
+ for (;;) {
+ Result result = refUpdate.update();
+
+ if (result == Result.LOCK_FAILURE) {
+ if (--remainingLockFailureCalls > 0) {
+ try {
+ Thread.sleep(SLEEP_ON_LOCK_FAILURE_MS);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ } else {
+ throw new ConcurrentRefUpdateException("Failed to lock the ref: "
+ + notesBranch, db.getRef(notesBranch), result);
+ }
+
+ } else if (result == Result.REJECTED) {
+ RevCommit theirsCommit =
+ revWalk.parseCommit(refUpdate.getOldObjectId());
+ NoteMap theirs =
+ NoteMap.read(revWalk.getObjectReader(), theirsCommit);
+ NoteMapMerger merger =
+ new NoteMapMerger(db, getNoteMerger(), MergeStrategy.RESOLVE);
+ NoteMap merged = merger.merge(base, ours, theirs);
+ RevCommit mergeCommit =
+ createCommit(merged, gerritIdent, "Merged note commits\n",
+ theirsCommit, oursCommit);
+ refUpdate = createRefUpdate(notesBranch, mergeCommit, theirsCommit);
+ remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
+
+ } else if (result == Result.IO_FAILURE) {
+ throw new IOException("Couldn't update " + notesBranch + ". "
+ + result.name());
+ } else {
+ break;
+ }
+ }
+ }
+
+ private RefUpdate createRefUpdate(String notesBranch, ObjectId newObjectId,
+ ObjectId expectedOldObjectId) throws IOException {
+ RefUpdate refUpdate = db.updateRef(notesBranch);
+ refUpdate.setNewObjectId(newObjectId);
+ if (expectedOldObjectId == null) {
+ refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
+ } else {
+ refUpdate.setExpectedOldObjectId(expectedOldObjectId);
+ }
+ return refUpdate;
+ }
+}
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 7387fd1..41f2aa6 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
@@ -211,7 +211,8 @@
/** Can this user restore this change? */
public boolean canRestore() {
- return canAbandon(); // Anyone who can abandon the change can restore it back
+ return canAbandon() // Anyone who can abandon the change can restore it back
+ && getRefControl().canUpload(); // as long as you can upload too
}
/** All value ranges of any allowed label permission. */
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm
index a67c38c..bb3c127 100644
--- a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm
@@ -32,6 +32,6 @@
## subject line for ALL emails related to changes.
##
#macro(elipses $length $str)
-#if($str.length() > $length)${str.substring(0,$length)}...#else$str#end
+#if(($str.length()+3) > $length)${str.substring(0,$length)}...#else$str#end
#end
Change in $projectName.replaceAll('/.*/', '...')[$branch.shortName]: #elipses(60, $change.subject)
diff --git a/gerrit-sshd/.settings/org.eclipse.core.resources.prefs b/gerrit-sshd/.settings/org.eclipse.core.resources.prefs
index 0871ea8..839d647 100644
--- a/gerrit-sshd/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-sshd/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Tue May 15 09:21:12 PDT 2012
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/BanCommitCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/BanCommitCommand.java
index 4350d1e..939d68a 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/BanCommitCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/BanCommitCommand.java
@@ -22,6 +22,7 @@
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
+import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.lib.ObjectId;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@@ -80,6 +81,8 @@
throw die(e);
} catch (InterruptedException e) {
throw die(e);
+ } catch (ConcurrentRefUpdateException e) {
+ throw die(e);
}
}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index 8ce1e82..5ebb6c7 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -68,7 +68,8 @@
private final Set<PatchSet.Id> patchSetIds = new HashSet<PatchSet.Id>();
- @Argument(index = 0, required = true, multiValued = true, metaVar = "{COMMIT | CHANGE,PATCHSET}", usage = "patch to review")
+ @Argument(index = 0, required = true, multiValued = true, metaVar = "{COMMIT | CHANGE,PATCHSET}",
+ usage = "list of commits or patch sets to review")
void addPatchSetId(final String token) {
try {
patchSetIds.addAll(parsePatchSetId(token));
@@ -79,29 +80,29 @@
}
}
- @Option(name = "--project", aliases = "-p", usage = "project containing the patch set")
+ @Option(name = "--project", aliases = "-p", usage = "project containing the specified patch set(s)")
private ProjectControl projectControl;
- @Option(name = "--message", aliases = "-m", usage = "cover message to publish on change", metaVar = "MESSAGE")
+ @Option(name = "--message", aliases = "-m", usage = "cover message to publish on change(s)", metaVar = "MESSAGE")
private String changeComment;
- @Option(name = "--abandon", usage = "abandon the patch set")
+ @Option(name = "--abandon", usage = "abandon the specified change(s)")
private boolean abandonChange;
- @Option(name = "--restore", usage = "restore an abandoned the patch set")
+ @Option(name = "--restore", usage = "restore the specified abandoned change(s)")
private boolean restoreChange;
- @Option(name = "--submit", aliases = "-s", usage = "submit the patch set")
+ @Option(name = "--submit", aliases = "-s", usage = "submit the specified patch set(s)")
private boolean submitChange;
@Option(name = "--force-message", usage = "publish the message, "
- + "even if the label score cannot be applied due to change being closed")
+ + "even if the label score cannot be applied due to the change being closed")
private boolean forceMessage = false;
- @Option(name = "--publish", usage = "publish a draft patch set")
+ @Option(name = "--publish", usage = "publish the specified draft patch set(s)")
private boolean publishPatchSet;
- @Option(name = "--delete", usage = "delete a draft patch set")
+ @Option(name = "--delete", usage = "delete the specified draft patch set(s)")
private boolean deleteDraftPatchSet;
@Inject
@@ -266,7 +267,7 @@
errMsg += "rule error";
break;
case NOT_A_DRAFT:
- errMsg += "change is not a draft";
+ errMsg += "change/patch set is not a draft";
break;
case GIT_ERROR:
errMsg += "error writing change to git repository";
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java
old mode 100755
new mode 100644
diff --git a/gerrit-util-cli/.settings/org.eclipse.core.resources.prefs b/gerrit-util-cli/.settings/org.eclipse.core.resources.prefs
index c780f44..e9441bb 100644
--- a/gerrit-util-cli/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-util-cli/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:36 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-util-ssl/.settings/org.eclipse.core.resources.prefs b/gerrit-util-ssl/.settings/org.eclipse.core.resources.prefs
index 589908f..e9441bb 100644
--- a/gerrit-util-ssl/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-util-ssl/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:35 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
diff --git a/gerrit-war/.settings/org.eclipse.core.resources.prefs b/gerrit-war/.settings/org.eclipse.core.resources.prefs
index d404b00..abdea9ac 100644
--- a/gerrit-war/.settings/org.eclipse.core.resources.prefs
+++ b/gerrit-war/.settings/org.eclipse.core.resources.prefs
@@ -1,4 +1,3 @@
-#Thu Jul 28 11:02:37 PDT 2011
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
diff --git a/pom.xml b/pom.xml
index 23c9d09..d7b5988 100644
--- a/pom.xml
+++ b/pom.xml
@@ -478,7 +478,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <version>12.0</version>
+ <version>12.0.1</version>
</dependency>
<dependency>