Merge "Add missing documentation about hook configuration"
diff --git a/Documentation/cmd-stream-events.txt b/Documentation/cmd-stream-events.txt
index bf78051..b3c6037 100644
--- a/Documentation/cmd-stream-events.txt
+++ b/Documentation/cmd-stream-events.txt
@@ -41,9 +41,10 @@
SCHEMA
------
The JSON messages consist of nested objects referencing the *change*,
-*patchset*, *account* involved, and other attributes as appropriate.
+*patchSet*, *account* involved, and other attributes as appropriate.
The currently supported message types are *patchset-created*,
-*comment-added*, *change-merged*, and *change-abandoned*.
+*change-abandoned*, *change-restored*, *change-merged*,
+*comment-added* and *ref-updated*.
Note that any field may be missing in the JSON messages, so consumers of
this JSON stream should deal with that appropriately.
@@ -56,7 +57,7 @@
change:: link:json.html#change[change attribute]
-patchset:: link:json.html#patchset[patchset attribute]
+patchSet:: link:json.html#patchSet[patchSet attribute]
uploader:: link:json.html#account[account attribute]
@@ -66,27 +67,31 @@
change:: link:json.html#change[change attribute]
-patchset:: link:json.html#patchset[patchset attribute]
+patchSet:: link:json.html#patchSet[patchSet attribute]
abandoner:: link:json.html#account[account attribute]
+reason:: Reason for abandoning the change.
+
Change Restored
-^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^
type:: "change-restored"
change:: link:json.html#change[change attribute]
-patchset:: link:json.html#patchset[patchset attribute]
+patchSet:: link:json.html#patchSet[patchSet attribute]
restorer:: link:json.html#account[account attribute]
+reason:: Reason for restoring the change.
+
Change Merged
^^^^^^^^^^^^^
type:: "change-merged"
change:: link:json.html#change[change attribute]
-patchset:: link:json.html#patchset[patchset attribute]
+patchSet:: link:json.html#patchSet[patchSet attribute]
submitter:: link:json.html#account[account attribute]
@@ -96,10 +101,12 @@
change:: link:json.html#change[change attribute]
-patchset:: link:json.html#patchset[patchset attribute]
+patchSet:: link:json.html#patchSet[patchSet attribute]
author:: link:json.html#account[account attribute]
+approvals:: All link:json.html#approval[approval attributes] granted.
+
comment:: Comment text author had written
Ref Updated
@@ -108,7 +115,7 @@
submitter:: link:json.html#account[account attribute]
-refUpdate:: link:json.html#refupdate[refupdate attribute]
+refUpdate:: link:json.html#refUpdate[refUpdate attribute]
SEE ALSO
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 06d2f72..0435f4e 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1953,6 +1953,28 @@
and text results for changes. If false, the URL is disabled and
returns 404 to clients. Default is true, enabling `/query`.
+[[site.upgradeSchemaOnStartup]]site.upgradeSchemaOnStartup::
++
+Control whether schema upgrade should be done on Gerrit startup. The following
+values are supported:
++
+* `OFF`
++
+No automatic schema upgrade on startup.
++
+* `AUTO`
++
+Perform schema migration on startup, if necessary. If, as a result of
+schema migration, there would be any unused database objects they will
+be dropped automatically.
++
+* `AUTO_NO_PRUNE`
++
+Like `AUTO` but unused database objects will not be pruned.
+
++
+The default is `OFF`.
+
[[ssh-alias]] Section ssh-alias
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/dev-eclipse.txt b/Documentation/dev-eclipse.txt
index ca56da3..a19d85e 100644
--- a/Documentation/dev-eclipse.txt
+++ b/Documentation/dev-eclipse.txt
@@ -73,9 +73,15 @@
Running Hosted Mode
~~~~~~~~~~~~~~~~~~~
-Import the gerrit-gwtdebug project:
+To debug the GWT code executing in the web browser, three additional Git
+repositories need to be cloned.
-* Import gerrit-gwtdebug/pom.xml using General -> Maven Projects
+* https://gerrit.googlesource.com/gwtexpui
+* https://gerrit.googlesource.com/gwtjsonrpc
+* https://gerrit.googlesource.com/gwtorm
+
+In Eclipse, import the pom.xml file in the root directory of each of
+these cloned gits via General -> Maven Projects.
Duplicate the existing `gwtui_dbg` launch configuration:
@@ -97,12 +103,17 @@
Known problems
--------------
-When running Gerrit under the Eclipse debugger, code that attempts
+* When running Gerrit under the Eclipse debugger, code that attempts
to load Prolog code may erroneously raise ClassNotFoundException,
claiming that classes in the `Gerrit` package can't be found. The
error can often be resolved by rebuilding Gerrit with `mvn package`
and restarting the debug session.
+* OpenID authentication won't work in hosted mode, so you need to change
+the link:config-gerrit.html#auth.type[auth.type] configuration parameter
+to `DEVELOPMENT_BECOME_ANY_ACCOUNT` to disable OpenID and allow you to
+impersonate whatever account you otherwise would've used.
+
GERRIT
------
diff --git a/Documentation/json.txt b/Documentation/json.txt
index ae7ec63..fac1424 100644
--- a/Documentation/json.txt
+++ b/Documentation/json.txt
@@ -53,9 +53,9 @@
message based on the server's
link:config-gerrit.html#trackingid[trackingid] sections.
-currentPatchSet:: Current <<patchset,patchset attribute>>.
+currentPatchSet:: Current <<patchSet,patchSet attribute>>.
-patchSets:: All <<patchset,patchset attribute>> for this change.
+patchSets:: All <<patchSet,patchSet attribute>> for this change.
[[trackingid]]
trackingid
@@ -76,8 +76,8 @@
email:: User's preferred email address.
-[[patchset]]
-patchset
+[[patchSet]]
+patchSet
--------
Refers to a specific patchset within a <<change,change>>.
@@ -109,8 +109,8 @@
by:: Reviewer of the patch set in <<account,account attribute>>.
-[[refupdate]]
-refupdate
+[[refUpdate]]
+refUpdate
--------
Information about a ref that was updated.
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
index 9efea22..05dd5d9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
@@ -49,6 +49,7 @@
outgoing.setTitleText(Util.C.outgoingReviews());
incoming.setTitleText(Util.C.incomingReviews());
+ incoming.setHighlightUnreviewed(true);
closed.setTitleText(Util.C.recentlyClosed());
table.addSection(outgoing);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
index 52e3bd2..0c8e03e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfo.java
@@ -71,6 +71,7 @@
private final native String createdRaw() /*-{ return this.created; }-*/;
private final native String updatedRaw() /*-{ return this.updated; }-*/;
public final native boolean starred() /*-{ return this.starred ? true : false; }-*/;
+ public final native boolean reviewed() /*-{ return this.reviewed ? true : false; }-*/;
public final native String _sortkey() /*-{ return this._sortkey; }-*/;
private final native JavaScriptObject labels0() /*-{ return this.labels; }-*/;
public final native LabelInfo label(String n) /*-{ return this.labels[n]; }-*/;
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 1b9db39..fc2b418 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
@@ -26,16 +26,19 @@
import com.google.gerrit.client.ui.ProjectLink;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
+import com.google.gwt.user.client.ui.UIObject;
import java.util.ArrayList;
import java.util.Collections;
@@ -188,7 +191,8 @@
}
}
- private void populateChangeRow(final int row, final ChangeInfo c) {
+ private void populateChangeRow(final int row, final ChangeInfo c,
+ boolean highlightUnreviewed) {
if (Gerrit.isSignedIn()) {
table.setWidget(row, C_STAR, StarredChanges.createIcon(
c.legacy_id(),
@@ -284,10 +288,13 @@
}
}
- // TODO(sop): Highlight changes I haven't reviewed on my dashboard.
- // final Element tr = DOM.getParent(fmt.getElement(row, 0));
- // UIObject.setStyleName(tr, Gerrit.RESOURCES.css().needsReview(),
- // !haveReview && highlightUnreviewed);
+ boolean needHighlight = false;
+ if (highlightUnreviewed && !c.reviewed()) {
+ needHighlight = true;
+ }
+ final Element tr = DOM.getParent(fmt.getElement(row, 0));
+ UIObject.setStyleName(tr, Gerrit.RESOURCES.css().needsReview(),
+ needHighlight);
setRowItem(row, c);
}
@@ -368,6 +375,11 @@
int titleRow = -1;
int dataBegin;
int rows;
+ private boolean highlightUnreviewed;
+
+ public void setHighlightUnreviewed(boolean value) {
+ this.highlightUnreviewed = value;
+ }
public void setTitleText(final String text) {
titleText = text;
@@ -399,7 +411,8 @@
rows++;
}
for (int i = 0; i < sz; i++) {
- parent.populateChangeRow(dataBegin + i, changeList.get(i));
+ parent.populateChangeRow(dataBegin + i, changeList.get(i),
+ highlightUnreviewed);
}
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
index 2b87a28..1a6ea3e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java
@@ -14,57 +14,29 @@
package com.google.gerrit.client.changes;
+import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gwt.user.client.ui.Composite;
-
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.dom.client.PreElement;
-import com.google.gwt.dom.client.Style.Display;
-import com.google.gwt.uibinder.client.UiBinder;
-import com.google.gwt.uibinder.client.UiField;
-import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.HTML;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
public class CommitMessageBlock extends Composite {
- interface Binder extends UiBinder<HTMLPanel, CommitMessageBlock> {
- }
-
- private static Binder uiBinder = GWT.create(Binder.class);
-
- @UiField
- PreElement commitSummaryPre;
- @UiField
- PreElement commitBodyPre;
+ private final HTML description;
public CommitMessageBlock() {
- initWidget(uiBinder.createAndBindUi(this));
+ description = new HTML();
+ description.setStyleName(Gerrit.RESOURCES.css().changeScreenDescription());
+ initWidget(description);
}
public void display(final String commitMessage) {
- String commitSummary = "";
- String commitBody = "";
-
- String[] splitCommitMessage = commitMessage.split("\n", 2);
- commitSummary = splitCommitMessage[0];
- commitBody = splitCommitMessage[1];
-
- // Hide commit body if there is no body
- if (commitBody.trim().isEmpty()) {
- commitBodyPre.getStyle().setDisplay(Display.NONE);
- }
-
- // Linkify commit summary
- SafeHtml commitSummaryLinkified = new SafeHtmlBuilder().append(commitSummary);
- commitSummaryLinkified = commitSummaryLinkified.linkify();
- commitSummaryLinkified = CommentLinkProcessor.apply(commitSummaryLinkified);
-
- // Linkify commit body
- SafeHtml commitBodyLinkified = new SafeHtmlBuilder().append(commitBody);
- commitBodyLinkified = commitBodyLinkified.linkify();
- commitBodyLinkified = CommentLinkProcessor.apply(commitBodyLinkified);
-
- commitSummaryPre.setInnerHTML(commitSummaryLinkified.asString());
- commitBodyPre.setInnerHTML(commitBodyLinkified.asString());
+ SafeHtml msg = new SafeHtmlBuilder().append(commitMessage);
+ msg = msg.linkify();
+ msg = CommentLinkProcessor.apply(msg);
+ msg = new SafeHtmlBuilder().openElement("p").append(msg).closeElement("p");
+ msg = msg.replaceAll("\n\n", "</p><p>");
+ msg = msg.replaceAll("\n", "<br />");
+ SafeHtml.set(description, msg);
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml
deleted file mode 100644
index 41d6f83..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.ui.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Copyright (C) 2012 The Android Open Source Project
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
- xmlns:g='urn:import:com.google.gwt.user.client.ui'>
-
-
- <ui:style>
- @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
- @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
- @eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
-
- .commitMessageTable {
- border-collapse: separate;
- border-spacing: 0;
- margin-bottom: 10px;
- }
-
- .header {
- border: 1px solid trimColor;
- padding: 2px 6px 1px;
- background-color: trimColor;
- white-space: nowrap;
- color: textColor;
- font-size: 10pt;
- }
-
- .contents {
- border-bottom: 1px solid trimColor;
- border-left: 1px solid trimColor;
- border-right: 1px solid trimColor;
- padding: 5px;
- }
-
- .contents span {
- font-weight: bold;
- }
-
- .contents pre {
- margin: 0;
- }
-
- .commitSummary {
- font-weight: bold;
- }
-
- .commitBody {
- margin-top: 10px;
- }
- </ui:style>
-
- <g:HTMLPanel>
- <table class='{style.commitMessageTable}'>
- <tr><th class='{style.header}'>Commit Message</th></tr>
- <tr><td class='{style.contents}'>
- <pre class='{style.commitSummary}' ui:field='commitSummaryPre'/>
- <pre class='{style.commitBody}' ui:field='commitBodyPre'/>
- </td></tr>
- </table>
- </g:HTMLPanel>
-</ui:UiBinder>
-
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java
index 79f9011..47eae99 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java
@@ -218,8 +218,12 @@
String uri = req.getRequestURI();
String ctx = req.getContextPath();
- String file = uri.substring(ctx.length() + 1);
+ if (uri.length() <= ctx.length()) {
+ Resource.NOT_FOUND.send(req, res);
+ return;
+ }
+ String file = uri.substring(ctx.length() + 1);
ResourceKey key = new ResourceKey(holder.plugin, file);
Resource rsc = resourceCache.getIfPresent(key);
if (rsc != null) {
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 ff5ee17..282bbc9 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
@@ -35,12 +35,14 @@
import com.google.gerrit.pgm.util.RuntimeShutdown;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.AuthConfigModule;
import com.google.gerrit.server.config.CanonicalWebUrlModule;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
import com.google.gerrit.server.config.GerritGlobalModule;
+import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.MasterNodeStartup;
import com.google.gerrit.server.contact.HttpContactStoreConnection;
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
@@ -49,15 +51,24 @@
import com.google.gerrit.server.mail.SmtpEmailSender;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
import com.google.gerrit.server.plugins.PluginModule;
+import com.google.gerrit.server.schema.SchemaUpdater;
import com.google.gerrit.server.schema.SchemaVersionCheck;
+import com.google.gerrit.server.schema.UpdateUI;
import com.google.gerrit.server.ssh.NoSshModule;
import com.google.gerrit.sshd.SshModule;
import com.google.gerrit.sshd.commands.MasterCommandModule;
import com.google.gerrit.sshd.commands.SlaveCommandModule;
+import com.google.gwtorm.jdbc.JdbcExecutor;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.gwtorm.server.StatementExecutor;
+import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
+import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -145,6 +156,7 @@
sysInjector = createSysInjector();
sysInjector.getInstance(PluginGuiceEnvironment.class)
.setCfgInjector(cfgInjector);
+ sysInjector.getInstance(SchemaUpgrade.class).upgradeSchema();
manager.add(dbInjector, cfgInjector, sysInjector);
if (sshd) {
@@ -192,6 +204,74 @@
}
}
+ static class SchemaUpgrade {
+
+ private final Config config;
+ private final SchemaUpdater updater;
+ private final SchemaFactory<ReviewDb> schema;
+
+ @Inject
+ SchemaUpgrade(@GerritServerConfig Config config, SchemaUpdater updater,
+ SchemaFactory<ReviewDb> schema) {
+ this.config = config;
+ this.updater = updater;
+ this.schema = schema;
+ }
+
+ void upgradeSchema() throws OrmException {
+ SchemaUpgradePolicy policy =
+ config.getEnum("site", null, "upgradeSchemaOnStartup",
+ SchemaUpgradePolicy.OFF);
+ if (policy == SchemaUpgradePolicy.AUTO
+ || policy == SchemaUpgradePolicy.AUTO_NO_PRUNE) {
+ final List<String> pruneList = new ArrayList<String>();
+ updater.update(new UpdateUI() {
+ @Override
+ public void message(String msg) {
+ log.info(msg);
+ }
+
+ @Override
+ public boolean yesno(boolean def, String msg) {
+ return true;
+ }
+
+ @Override
+ public boolean isBatch() {
+ return true;
+ }
+
+ @Override
+ public void pruneSchema(StatementExecutor e, List<String> prune) {
+ for (String p : prune) {
+ if (!pruneList.contains(p)) {
+ pruneList.add(p);
+ }
+ }
+ }
+ });
+
+ if (!pruneList.isEmpty() && policy == SchemaUpgradePolicy.AUTO) {
+ log.info("Pruning: " + pruneList.toString());
+ final JdbcSchema db = (JdbcSchema) schema.open();
+ try {
+ final JdbcExecutor e = new JdbcExecutor(db);
+ try {
+ for (String sql : pruneList) {
+ e.execute(sql);
+ }
+ } finally {
+ e.close();
+ }
+ } finally {
+ db.close();
+ }
+ }
+ }
+ }
+ }
+
+
private String myVersion() {
return com.google.gerrit.common.Version.getVersion();
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SchemaUpgradePolicy.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SchemaUpgradePolicy.java
new file mode 100644
index 0000000..67f5c91
--- /dev/null
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SchemaUpgradePolicy.java
@@ -0,0 +1,28 @@
+// 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.pgm;
+
+/** Policy for auto upgrading schema on server startup */
+public enum SchemaUpgradePolicy {
+
+ /** Perform schema migration if necessary and prune unused objects */
+ AUTO,
+
+ /** Like AUTO but don't prune unused objects */
+ AUTO_NO_PRUNE,
+
+ /** No automatic schema upgrade */
+ OFF
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
index 556ae82..a295c49 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -124,14 +124,14 @@
Account.Id authorId = info.getAuthor() != null
? info.getAuthor().getAccount()
: null;
- if (authorId != null) {
+ if (authorId != null && !ps.isDraft()) {
need.add(authorId);
}
Account.Id committerId = info.getCommitter() != null
? info.getCommitter().getAccount()
: null;
- if (committerId != null) {
+ if (committerId != null && !ps.isDraft()) {
need.add(committerId);
}
need.remove(change.getOwner());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
index eb42921..1524185 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
@@ -83,7 +83,7 @@
|| canAdministrateServer();
}
- /** @return true if the user can create a group. */
+ /** @return true if the user can create a project. */
public boolean canCreateProject() {
return canPerform(GlobalCapability.CREATE_PROJECT)
|| canAdministrateServer();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index 4db9409..ecf98c2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -159,6 +159,7 @@
private CodeReviewCommit mergeTip;
private Set<RevCommit> alreadyAccepted;
private RefUpdate branchUpdate;
+ private ObjectInserter inserter;
private final ChangeHooks hooks;
private final AccountCache accountCache;
@@ -282,6 +283,9 @@
} catch (OrmException e) {
throw new MergeException("Cannot query the database", e);
} finally {
+ if (inserter != null) {
+ inserter.release();
+ }
if (rw != null) {
rw.release();
}
@@ -334,6 +338,8 @@
rw.sort(RevSort.TOPO);
rw.sort(RevSort.COMMIT_TIME_DESC, true);
CAN_MERGE = rw.newFlag("CAN_MERGE");
+
+ inserter = repo.newObjectInserter();
}
private void openBranch() throws MergeException {
@@ -505,21 +511,10 @@
}
private void mergeOneCommit(final CodeReviewCommit n) throws MergeException {
- final ThreeWayMerger m;
- if (destProject.isUseContentMerge()) {
- // Settings for this project allow us to try and
- // automatically resolve conflicts within files if needed.
- // Use ResolveMerge and instruct to operate in core.
- m = MergeStrategy.RESOLVE.newMerger(repo, true);
- } else {
- // No auto conflict resolving allowed. If any of the
- // affected files was modified, merge will fail.
- m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
- }
-
+ final ThreeWayMerger m = newThreeWayMerger();
try {
if (m.merge(new AnyObjectId[] {mergeTip, n})) {
- writeMergeCommit(m, n);
+ writeMergeCommit(m.getResultTreeId(), n);
} else {
failed(n, CommitMergeStatus.PATH_CONFLICT);
@@ -537,6 +532,35 @@
}
}
+ private ThreeWayMerger newThreeWayMerger() {
+ ThreeWayMerger m;
+ if (destProject.isUseContentMerge()) {
+ // Settings for this project allow us to try and
+ // automatically resolve conflicts within files if needed.
+ // Use ResolveMerge and instruct to operate in core.
+ m = MergeStrategy.RESOLVE.newMerger(repo, true);
+ } else {
+ // No auto conflict resolving allowed. If any of the
+ // affected files was modified, merge will fail.
+ m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
+ }
+ m.setObjectInserter(new ObjectInserter.Filter() {
+ @Override
+ protected ObjectInserter delegate() {
+ return inserter;
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void release() {
+ }
+ });
+ return m;
+ }
+
private CodeReviewCommit failed(final CodeReviewCommit n,
final CommitMergeStatus failure) throws MissingObjectException,
IncorrectObjectTypeException, IOException {
@@ -550,7 +574,7 @@
return failed;
}
- private void writeMergeCommit(final Merger m, final CodeReviewCommit n)
+ private void writeMergeCommit(ObjectId treeId, CodeReviewCommit n)
throws IOException, MissingObjectException, IncorrectObjectTypeException {
final List<CodeReviewCommit> merged = new ArrayList<CodeReviewCommit>();
rw.reset();
@@ -599,13 +623,13 @@
PersonIdent authorIdent = computeAuthor(merged);
final CommitBuilder mergeCommit = new CommitBuilder();
- mergeCommit.setTreeId(m.getResultTreeId());
+ mergeCommit.setTreeId(treeId);
mergeCommit.setParentIds(mergeTip, n);
mergeCommit.setAuthor(authorIdent);
mergeCommit.setCommitter(myIdent);
mergeCommit.setMessage(msgbuf.toString());
- mergeTip = (CodeReviewCommit) rw.parseCommit(commit(m, mergeCommit));
+ mergeTip = (CodeReviewCommit) rw.parseCommit(commit(mergeCommit));
}
private PersonIdent computeAuthor(
@@ -691,19 +715,7 @@
private void cherryPickChanges() throws MergeException, OrmException {
while (!toMerge.isEmpty()) {
final CodeReviewCommit n = toMerge.remove(0);
- final ThreeWayMerger m;
-
- if (destProject.isUseContentMerge()) {
- // Settings for this project allow us to try and
- // automatically resolve conflicts within files if needed.
- // Use ResolveMerge and instruct to operate in core.
- m = MergeStrategy.RESOLVE.newMerger(repo, true);
- } else {
- // No auto conflict resolving allowed. If any of the
- // affected files was modified, merge will fail.
- m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
- }
-
+ final ThreeWayMerger m = newThreeWayMerger();
try {
if (mergeTip == null) {
// The branch is unborn. Take a fast-forward resolution to
@@ -898,7 +910,7 @@
mergeCommit.setCommitter(toCommitterIdent(submitAudit));
mergeCommit.setMessage(msgbuf.toString());
- final ObjectId id = commit(m, mergeCommit);
+ final ObjectId id = commit(mergeCommit);
final CodeReviewCommit newCommit = (CodeReviewCommit) rw.parseCommit(id);
final Change oldChange = n.change;
@@ -961,16 +973,11 @@
db.patchSetAncestors().insert(toInsert);
}
- private ObjectId commit(final Merger m, final CommitBuilder mergeCommit)
+ private ObjectId commit(CommitBuilder mergeCommit)
throws IOException, UnsupportedEncodingException {
- ObjectInserter oi = m.getObjectInserter();
- try {
- ObjectId id = oi.insert(mergeCommit);
- oi.flush();
- return id;
- } finally {
- oi.release();
- }
+ ObjectId id = inserter.insert(mergeCommit);
+ inserter.flush();
+ return id;
}
private boolean contains(List<FooterLine> footers, FooterKey key, String val) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index d6e84bb..d27c205 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -255,10 +255,24 @@
ObjectId treeId;
ResolveMerger m = (ResolveMerger) MergeStrategy.RESOLVE.newMerger(repo, true);
- ObjectInserter ins = m.getObjectInserter();
+ final ObjectInserter ins = repo.newObjectInserter();
try {
DirCache dc = DirCache.newInCore();
m.setDirCache(dc);
+ m.setObjectInserter(new ObjectInserter.Filter() {
+ @Override
+ protected ObjectInserter delegate() {
+ return ins;
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void release() {
+ }
+ });
boolean couldMerge = false;
try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ListChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ListChanges.java
index adf4f19..ba4a74e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ListChanges.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ListChanges.java
@@ -22,10 +22,12 @@
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
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.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.events.AccountAttribute;
import com.google.gerrit.server.project.ChangeControl;
@@ -43,6 +45,7 @@
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -200,6 +203,7 @@
out._number = in.getId().get();
out._sortkey = in.getSortKey();
out.starred = user.getStarredChanges().contains(in.getId()) ? true : null;
+ out.reviewed = isChangeReviewed(cd) ? true : null;
out.labels = labelsFor(cd);
return out;
}
@@ -291,6 +295,37 @@
return labels;
}
+ private boolean isChangeReviewed(ChangeData cd) throws OrmException {
+ if (user instanceof IdentifiedUser) {
+ PatchSet.Id patchSetId = cd.currentPatchSet(db).getId();
+ List<ChangeMessage> messages =
+ db.get().changeMessages().byPatchSet(patchSetId).toList();
+
+ if (messages.isEmpty()) {
+ return false;
+ }
+
+ // Sort messages to let the most recent ones at the beginning.
+ Collections.sort(messages, new Comparator<ChangeMessage>() {
+ @Override
+ public int compare(ChangeMessage a, ChangeMessage b) {
+ return b.getWrittenOn().compareTo(a.getWrittenOn());
+ }
+ });
+
+ Account.Id currentUserId = ((IdentifiedUser) user).getAccountId();
+ Account.Id changeOwnerId = cd.change(db).getOwner();
+ for (ChangeMessage cm : messages) {
+ if (currentUserId.equals(cm.getAuthor())) {
+ return true;
+ } else if (changeOwnerId.equals(cm.getAuthor())) {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+
static class ChangeInfo {
String project;
String branch;
@@ -301,6 +336,7 @@
Timestamp created;
Timestamp updated;
Boolean starred;
+ Boolean reviewed;
String _sortkey;
int _number;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_67.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_67.java
index 7c7b880..bec2f3f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_67.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_67.java
@@ -18,7 +18,6 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-import com.google.gerrit.common.data.ContributorAgreement;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.jdbc.JdbcSchema;
@@ -54,7 +53,6 @@
"SELECT group_id, owner_group_id FROM account_groups"
+ " WHERE owner_group_uuid is NULL or owner_group_uuid =''");
try {
- Map<Integer, ContributorAgreement> agreements = Maps.newHashMap();
while (rs.next()) {
AccountGroup.Id groupId = new AccountGroup.Id(rs.getInt(1));
AccountGroup.Id ownerId = new AccountGroup.Id(rs.getInt(2));
diff --git a/pom.xml b/pom.xml
index 2f5a296..440bd1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
</issueManagement>
<properties>
- <jgitVersion>1.3.0.201202151440-r.190-g65f6e06</jgitVersion>
+ <jgitVersion>2.0.0.201206130900-r.23-gb3dbf19</jgitVersion>
<gwtormVersion>1.4</gwtormVersion>
<gwtjsonrpcVersion>1.3</gwtjsonrpcVersion>
<gwtexpuiVersion>1.2.5</gwtexpuiVersion>