Merge branch 'stable-2.14'

* stable-2.14:
  Enable OAuth token setting when gitBasicAuthPolicy equals OAUTH
  Enable HTTP password setting based upon gitBasicAuthPolicy
  Fix file_name column size in H2AccountPatchReviewStore
  GET files?reviewed: Don't fire N+1 selects for N patch sets
  Use lower case table/column/constraint names in H2AccountPatchReviewStore
  Fix clear methods in H2AccountPatchReviewStore
  JestClientBuilder: Format with google-java-format
  ES: Extract Jest client builder into separate class
  Remove unused import and apply formatting in AbstractElasticIndex
  Fix: Default values for Elastic index.* config values

Change-Id: I9e4ff0bd290df5b65ced77c541dec3b2b42a714a
This commit is contained in:
David Pursehouse
2017-04-25 13:52:55 +02:00
5 changed files with 83 additions and 55 deletions

View File

@@ -84,7 +84,8 @@ public class AuthInfo extends JavaScriptObject {
} }
public final boolean isHttpPasswordSettingsEnabled() { public final boolean isHttpPasswordSettingsEnabled() {
return gitBasicAuthPolicy() != GitBasicAuthPolicy.LDAP; return gitBasicAuthPolicy() == GitBasicAuthPolicy.HTTP
|| gitBasicAuthPolicy() == GitBasicAuthPolicy.HTTP_LDAP;
} }
public final GitBasicAuthPolicy gitBasicAuthPolicy() { public final GitBasicAuthPolicy gitBasicAuthPolicy() {

View File

@@ -21,6 +21,7 @@ import com.google.gerrit.client.api.ExtensionSettingsScreen;
import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.MenuScreen; import com.google.gerrit.client.ui.MenuScreen;
import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.client.GitBasicAuthPolicy;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -46,7 +47,8 @@ public abstract class SettingsScreen extends MenuScreen {
if (Gerrit.info().auth().isHttpPasswordSettingsEnabled()) { if (Gerrit.info().auth().isHttpPasswordSettingsEnabled()) {
linkByGerrit(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD); linkByGerrit(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD);
} }
if (Gerrit.info().auth().isOAuth()) { if (Gerrit.info().auth().isOAuth()
&& Gerrit.info().auth().gitBasicAuthPolicy() == GitBasicAuthPolicy.OAUTH) {
linkByGerrit(Util.C.tabOAuthToken(), PageLinks.SETTINGS_OAUTH_TOKEN); linkByGerrit(Util.C.tabOAuthToken(), PageLinks.SETTINGS_OAUTH_TOKEN);
} }
if (Gerrit.info().gerrit().editGpgKeys()) { if (Gerrit.info().gerrit().editGpgKeys()) {

View File

@@ -14,10 +14,13 @@
package com.google.gerrit.server.change; package com.google.gerrit.server.change;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import java.util.Collection; import java.util.Collection;
import java.util.Optional;
/** /**
* Store for reviewed flags on changes. * Store for reviewed flags on changes.
@@ -30,6 +33,19 @@ import java.util.Collection;
* <p>For a multi-master setup the store must replicate the data between the masters. * <p>For a multi-master setup the store must replicate the data between the masters.
*/ */
public interface AccountPatchReviewStore { public interface AccountPatchReviewStore {
/** Represents patch set id with reviewed files. */
@AutoValue
abstract class PatchSetWithReviewedFiles {
abstract PatchSet.Id patchSetId();
abstract ImmutableSet<String> files();
public static PatchSetWithReviewedFiles create(PatchSet.Id id, ImmutableSet<String> files) {
return new AutoValue_AccountPatchReviewStore_PatchSetWithReviewedFiles(id, files);
}
}
/** /**
* Marks the given file in the given patch set as reviewed by the given user. * Marks the given file in the given patch set as reviewed by the given user.
* *
@@ -72,12 +88,15 @@ public interface AccountPatchReviewStore {
void clearReviewed(PatchSet.Id psId) throws OrmException; void clearReviewed(PatchSet.Id psId) throws OrmException;
/** /**
* Returns the paths of all files in the given patch set the have been reviewed by the given user. * Find the latest patch set, that is smaller or equals to the given patch set, where at least,
* one file has been reviewed by the given user.
* *
* @param psId patch set ID * @param psId patch set ID
* @param accountId account ID of the user * @param accountId account ID of the user
* @return the paths of all files in the given patch set the have been reviewed by the given user * @return optionally, all files the have been reviewed by the given user that belong to the patch
* set that is smaller or equals to the given patch set
* @throws OrmException thrown if accessing the reviewed flags failed * @throws OrmException thrown if accessing the reviewed flags failed
*/ */
Collection<String> findReviewed(PatchSet.Id psId, Account.Id accountId) throws OrmException; Optional<PatchSetWithReviewedFiles> findReviewed(PatchSet.Id psId, Account.Id accountId)
throws OrmException;
} }

View File

@@ -15,7 +15,6 @@
package com.google.gerrit.server.change; package com.google.gerrit.server.change;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.extensions.common.FileInfo; import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
@@ -34,6 +33,7 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.PatchSetUtil; import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.change.AccountPatchReviewStore.PatchSetWithReviewedFiles;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchList; import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache; import com.google.gerrit.server.patch.PatchListCache;
@@ -45,8 +45,10 @@ import com.google.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -222,31 +224,24 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
} }
Account.Id userId = user.getAccountId(); Account.Id userId = user.getAccountId();
Collection<String> r = PatchSet patchSetId = resource.getPatchSet();
accountPatchReviewStore.get().findReviewed(resource.getPatchSet().getId(), userId); Optional<PatchSetWithReviewedFiles> o =
accountPatchReviewStore.get().findReviewed(patchSetId.getId(), userId);
if (o.isPresent()) {
PatchSetWithReviewedFiles res = o.get();
if (res.patchSetId().equals(patchSetId.getId())) {
return res.files();
}
if (r.isEmpty() && 1 < resource.getPatchSet().getPatchSetId()) {
for (PatchSet ps : reversePatchSets(resource)) {
Collection<String> o = accountPatchReviewStore.get().findReviewed(ps.getId(), userId);
if (!o.isEmpty()) {
try { try {
r = copy(Sets.newHashSet(o), ps.getId(), resource, userId); return copy(res.files(), res.patchSetId(), resource, userId);
} catch (IOException | PatchListNotAvailableException e) { } catch (IOException | PatchListNotAvailableException e) {
log.warn("Cannot copy patch review flags", e); log.warn("Cannot copy patch review flags", e);
} }
break;
}
}
} }
return r; return Collections.emptyList();
}
private List<PatchSet> reversePatchSets(RevisionResource resource) throws OrmException {
Collection<PatchSet> patchSets = psUtil.byChange(db.get(), resource.getNotes());
List<PatchSet> list =
(patchSets instanceof List) ? (List<PatchSet>) patchSets : new ArrayList<>(patchSets);
return Lists.reverse(list);
} }
private List<String> copy( private List<String> copy(

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.schema; package com.google.gerrit.server.schema;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.extensions.registration.DynamicItem;
@@ -34,9 +35,8 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.Optional;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSource;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
@@ -130,20 +130,20 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
private static void doCreateTable(Statement stmt) throws SQLException { private static void doCreateTable(Statement stmt) throws SQLException {
stmt.executeUpdate( stmt.executeUpdate(
"CREATE TABLE IF NOT EXISTS ACCOUNT_PATCH_REVIEWS (" "CREATE TABLE IF NOT EXISTS account_patch_reviews ("
+ "ACCOUNT_ID INTEGER DEFAULT 0 NOT NULL, " + "account_id INTEGER DEFAULT 0 NOT NULL, "
+ "CHANGE_ID INTEGER DEFAULT 0 NOT NULL, " + "change_id INTEGER DEFAULT 0 NOT NULL, "
+ "PATCH_SET_ID INTEGER DEFAULT 0 NOT NULL, " + "patch_set_id INTEGER DEFAULT 0 NOT NULL, "
+ "FILE_NAME VARCHAR(255) DEFAULT '' NOT NULL, " + "file_name VARCHAR(4096) DEFAULT '' NOT NULL, "
+ "CONSTRAINT PRIMARY_KEY_ACCOUNT_PATCH_REVIEWS " + "CONSTRAINT primary_key_account_patch_reviews "
+ "PRIMARY KEY (ACCOUNT_ID, CHANGE_ID, PATCH_SET_ID, FILE_NAME)" + "PRIMARY KEY (account_id, change_id, patch_set_id, file_name)"
+ ")"); + ")");
} }
public static void dropTableIfExists(String url) throws OrmException { public static void dropTableIfExists(String url) throws OrmException {
try (Connection con = DriverManager.getConnection(url); try (Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement()) { Statement stmt = con.createStatement()) {
stmt.executeUpdate("DROP TABLE IF EXISTS ACCOUNT_PATCH_REVIEWS"); stmt.executeUpdate("DROP TABLE IF EXISTS account_patch_reviews");
} catch (SQLException e) { } catch (SQLException e) {
throw convertError("create", e); throw convertError("create", e);
} }
@@ -158,8 +158,8 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
try (Connection con = ds.getConnection(); try (Connection con = ds.getConnection();
PreparedStatement stmt = PreparedStatement stmt =
con.prepareStatement( con.prepareStatement(
"INSERT INTO ACCOUNT_PATCH_REVIEWS " "INSERT INTO account_patch_reviews "
+ "(ACCOUNT_ID, CHANGE_ID, PATCH_SET_ID, FILE_NAME) VALUES " + "(account_id, change_id, patch_set_id, file_name) VALUES "
+ "(?, ?, ?, ?)")) { + "(?, ?, ?, ?)")) {
stmt.setInt(1, accountId.get()); stmt.setInt(1, accountId.get());
stmt.setInt(2, psId.getParentKey().get()); stmt.setInt(2, psId.getParentKey().get());
@@ -186,8 +186,8 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
try (Connection con = ds.getConnection(); try (Connection con = ds.getConnection();
PreparedStatement stmt = PreparedStatement stmt =
con.prepareStatement( con.prepareStatement(
"INSERT INTO ACCOUNT_PATCH_REVIEWS " "INSERT INTO account_patch_reviews "
+ "(ACCOUNT_ID, CHANGE_ID, PATCH_SET_ID, FILE_NAME) VALUES " + "(account_id, change_id, patch_set_id, file_name) VALUES "
+ "(?, ?, ?, ?)")) { + "(?, ?, ?, ?)")) {
for (String path : paths) { for (String path : paths) {
stmt.setInt(1, accountId.get()); stmt.setInt(1, accountId.get());
@@ -212,9 +212,9 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
try (Connection con = ds.getConnection(); try (Connection con = ds.getConnection();
PreparedStatement stmt = PreparedStatement stmt =
con.prepareStatement( con.prepareStatement(
"DELETE FROM ACCOUNT_PATCH_REVIEWS " "DELETE FROM account_patch_reviews "
+ "WHERE ACCOUNT_ID = ? AND CHANGE_ID + ? AND " + "WHERE account_id = ? AND change_id = ? AND "
+ "PATCH_SET_ID = ? AND FILE_NAME = ?")) { + "patch_set_id = ? AND file_name = ?")) {
stmt.setInt(1, accountId.get()); stmt.setInt(1, accountId.get());
stmt.setInt(2, psId.getParentKey().get()); stmt.setInt(2, psId.getParentKey().get());
stmt.setInt(3, psId.get()); stmt.setInt(3, psId.get());
@@ -230,8 +230,8 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
try (Connection con = ds.getConnection(); try (Connection con = ds.getConnection();
PreparedStatement stmt = PreparedStatement stmt =
con.prepareStatement( con.prepareStatement(
"DELETE FROM ACCOUNT_PATCH_REVIEWS " "DELETE FROM account_patch_reviews "
+ "WHERE CHANGE_ID + ? AND PATCH_SET_ID = ?")) { + "WHERE change_id = ? AND patch_set_id = ?")) {
stmt.setInt(1, psId.getParentKey().get()); stmt.setInt(1, psId.getParentKey().get());
stmt.setInt(2, psId.get()); stmt.setInt(2, psId.get());
stmt.executeUpdate(); stmt.executeUpdate();
@@ -241,22 +241,33 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
} }
@Override @Override
public Collection<String> findReviewed(PatchSet.Id psId, Account.Id accountId) public Optional<PatchSetWithReviewedFiles> findReviewed(PatchSet.Id psId, Account.Id accountId)
throws OrmException { throws OrmException {
try (Connection con = ds.getConnection(); try (Connection con = ds.getConnection();
PreparedStatement stmt = PreparedStatement stmt =
con.prepareStatement( con.prepareStatement(
"SELECT FILE_NAME FROM ACCOUNT_PATCH_REVIEWS " "SELECT patch_set_id, file_name FROM account_patch_reviews APR1 "
+ "WHERE ACCOUNT_ID = ? AND CHANGE_ID = ? AND PATCH_SET_ID = ?")) { + "WHERE account_id = ? AND change_id = ? AND patch_set_id = "
+ "(SELECT MAX(patch_set_id) FROM account_patch_reviews APR2 WHERE "
+ "APR1.account_id = APR2.account_id "
+ "AND APR1.change_id = APR2.change_id "
+ "AND patch_set_id <= ?)")) {
stmt.setInt(1, accountId.get()); stmt.setInt(1, accountId.get());
stmt.setInt(2, psId.getParentKey().get()); stmt.setInt(2, psId.getParentKey().get());
stmt.setInt(3, psId.get()); stmt.setInt(3, psId.get());
try (ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
List<String> files = new ArrayList<>(); if (rs.next()) {
while (rs.next()) { PatchSet.Id id = new PatchSet.Id(psId.getParentKey(), rs.getInt("PATCH_SET_ID"));
files.add(rs.getString("FILE_NAME")); ImmutableSet.Builder<String> builder = ImmutableSet.builder();
do {
builder.add(rs.getString("FILE_NAME"));
} while (rs.next());
return Optional.of(
AccountPatchReviewStore.PatchSetWithReviewedFiles.create(id, builder.build()));
} }
return files;
return Optional.empty();
} }
} catch (SQLException e) { } catch (SQLException e) {
throw convertError("select", e); throw convertError("select", e);
@@ -267,13 +278,13 @@ public class H2AccountPatchReviewStore implements AccountPatchReviewStore, Lifec
switch (getSQLStateInt(err)) { switch (getSQLStateInt(err)) {
case 23001: // UNIQUE CONSTRAINT VIOLATION case 23001: // UNIQUE CONSTRAINT VIOLATION
case 23505: // DUPLICATE_KEY_1 case 23505: // DUPLICATE_KEY_1
return new OrmDuplicateKeyException("ACCOUNT_PATCH_REVIEWS", err); return new OrmDuplicateKeyException("account_patch_reviews", err);
default: default:
if (err.getCause() == null && err.getNextException() != null) { if (err.getCause() == null && err.getNextException() != null) {
err.initCause(err.getNextException()); err.initCause(err.getNextException());
} }
return new OrmException(op + " failure on ACCOUNT_PATCH_REVIEWS", err); return new OrmException(op + " failure on account_patch_reviews", err);
} }
} }