Merge branch 'stable-2.12'

* stable-2.12:
  Update cookbook submodule
  MergeValidationListener: Expose the caller in onPreMerge() method
  Correctly detect symlinked log directory on startup
  RebaseIfNecessary: Use submitter identity as the committer
  Fix schema migration (115) when updating from Gerrit < 2.11
  Hide avatar image when there are no avatars available
  Add back ListChangesOption.DRAFT_COMMENTS

Change-Id: Ibaf1264332fdc30db0f0f548121db728f78927ae
This commit is contained in:
David Pursehouse 2016-01-08 15:21:28 +09:00
commit 394e6345ab
10 changed files with 114 additions and 59 deletions

View File

@ -68,7 +68,7 @@ public class SubmitByRebaseIfNecessaryIT extends AbstractSubmit {
assertSubmitter(change2.getChangeId(), 1); assertSubmitter(change2.getChangeId(), 1);
assertSubmitter(change2.getChangeId(), 2); assertSubmitter(change2.getChangeId(), 2);
assertPersonEquals(admin.getIdent(), head.getAuthorIdent()); assertPersonEquals(admin.getIdent(), head.getAuthorIdent());
assertPersonEquals(serverIdent.get(), head.getCommitterIdent()); assertPersonEquals(admin.getIdent(), head.getCommitterIdent());
} }
@Test @Test

View File

@ -88,7 +88,9 @@ public class FileUtil {
public static Path mkdirsOrDie(Path p, String errMsg) { public static Path mkdirsOrDie(Path p, String errMsg) {
try { try {
Files.createDirectories(p); if (!Files.isDirectory(p)) {
Files.createDirectories(p);
}
return p; return p;
} catch (IOException e) { } catch (IOException e) {
throw new Die(errMsg + ": " + p, e); throw new Die(errMsg + ": " + p, e);

View File

@ -46,6 +46,10 @@ public enum ListChangesOption {
/** Set the reviewed boolean for the caller. */ /** Set the reviewed boolean for the caller. */
REVIEWED(11), REVIEWED(11),
/** Not used anymore, kept for backward compatibility */
@Deprecated
DRAFT_COMMENTS(12),
/** Include download commands for the caller. */ /** Include download commands for the caller. */
DOWNLOAD_COMMANDS(13), DOWNLOAD_COMMANDS(13),

View File

@ -92,6 +92,7 @@ public class AvatarImage extends Image implements LoadHandler {
private void loadAvatar(AccountInfo account, int size, boolean addPopup) { private void loadAvatar(AccountInfo account, int size, boolean addPopup) {
if (!Gerrit.info().plugin().hasAvatars()) { if (!Gerrit.info().plugin().hasAvatars()) {
setVisible(false);
return; return;
} }

View File

@ -494,7 +494,7 @@ public class MergeOp implements AutoCloseable {
Multimap<Branch.NameKey, ChangeData> cbb = cs.changesByBranch(); Multimap<Branch.NameKey, ChangeData> cbb = cs.changesByBranch();
for (Branch.NameKey branch : cbb.keySet()) { for (Branch.NameKey branch : cbb.keySet()) {
OpenRepo or = openRepo(branch.getParentKey()); OpenRepo or = openRepo(branch.getParentKey());
toSubmit.put(branch, validateChangeList(or, cbb.get(branch))); toSubmit.put(branch, validateChangeList(or, cbb.get(branch), caller));
} }
failFast(cs); // Done checks that don't involve running submit strategies. failFast(cs); // Done checks that don't involve running submit strategies.
@ -616,7 +616,8 @@ public class MergeOp implements AutoCloseable {
} }
private BranchBatch validateChangeList(OpenRepo or, private BranchBatch validateChangeList(OpenRepo or,
Collection<ChangeData> submitted) throws IntegrationException { Collection<ChangeData> submitted, IdentifiedUser caller)
throws IntegrationException {
logDebug("Validating {} changes", submitted.size()); logDebug("Validating {} changes", submitted.size());
List<ChangeData> toSubmit = new ArrayList<>(submitted.size()); List<ChangeData> toSubmit = new ArrayList<>(submitted.size());
Multimap<ObjectId, PatchSet.Id> revisions = getRevisions(or, submitted); Multimap<ObjectId, PatchSet.Id> revisions = getRevisions(or, submitted);
@ -691,7 +692,7 @@ public class MergeOp implements AutoCloseable {
MergeValidators mergeValidators = mergeValidatorsFactory.create(); MergeValidators mergeValidators = mergeValidatorsFactory.create();
try { try {
mergeValidators.validatePreMerge( mergeValidators.validatePreMerge(
or.repo, commit, or.project, destBranch, ps.getId()); or.repo, commit, or.project, destBranch, ps.getId(), caller);
} catch (MergeValidationException mve) { } catch (MergeValidationException mve) {
problems.put(changeId, mve.getMessage()); problems.put(changeId, mve.getMessage());
continue; continue;

View File

@ -37,6 +37,7 @@ import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
@ -53,6 +54,12 @@ public class RebaseIfNecessary extends SubmitStrategy {
this.newCommits = new HashMap<>(); this.newCommits = new HashMap<>();
} }
private PersonIdent getSubmitterIdent() {
return args.caller.newCommitterIdent(
args.serverIdent.getWhen(),
args.serverIdent.getTimeZone());
}
@Override @Override
public MergeTip run(final CodeReviewCommit branchTip, public MergeTip run(final CodeReviewCommit branchTip,
final Collection<CodeReviewCommit> toMerge) throws IntegrationException { final Collection<CodeReviewCommit> toMerge) throws IntegrationException {
@ -156,7 +163,7 @@ public class RebaseIfNecessary extends SubmitStrategy {
// Racy read of patch set is ok; see comments in RebaseChangeOp. // Racy read of patch set is ok; see comments in RebaseChangeOp.
args.db.patchSets().get(toMerge.getPatchsetId()), args.db.patchSets().get(toMerge.getPatchsetId()),
mergeTip.getCurrentTip().name()) mergeTip.getCurrentTip().name())
.setCommitterIdent(args.serverIdent) .setCommitterIdent(getSubmitterIdent())
.setRunHooks(false) .setRunHooks(false)
.setValidatePolicy(CommitValidators.Policy.NONE); .setValidatePolicy(CommitValidators.Policy.NONE);
try { try {

View File

@ -17,6 +17,7 @@ package com.google.gerrit.server.git.validators;
import com.google.gerrit.extensions.annotations.ExtensionPoint; import com.google.gerrit.extensions.annotations.ExtensionPoint;
import com.google.gerrit.reviewdb.client.Branch; import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.CodeReviewCommit; import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.project.ProjectState; import com.google.gerrit.server.project.ProjectState;
@ -37,12 +38,14 @@ public interface MergeValidationListener {
* @param destProject the destination project * @param destProject the destination project
* @param destBranch the destination branch * @param destBranch the destination branch
* @param patchSetId the patch set ID * @param patchSetId the patch set ID
* @param caller the user who initiated the merge request
* @throws MergeValidationException if the commit fails to validate * @throws MergeValidationException if the commit fails to validate
*/ */
void onPreMerge(Repository repo, void onPreMerge(Repository repo,
CodeReviewCommit commit, CodeReviewCommit commit,
ProjectState destProject, ProjectState destProject,
Branch.NameKey destBranch, Branch.NameKey destBranch,
PatchSet.Id patchSetId) PatchSet.Id patchSetId,
IdentifiedUser caller)
throws MergeValidationException; throws MergeValidationException;
} }

View File

@ -60,7 +60,8 @@ public class MergeValidators {
CodeReviewCommit commit, CodeReviewCommit commit,
ProjectState destProject, ProjectState destProject,
Branch.NameKey destBranch, Branch.NameKey destBranch,
PatchSet.Id patchSetId) PatchSet.Id patchSetId,
IdentifiedUser caller)
throws MergeValidationException { throws MergeValidationException {
List<MergeValidationListener> validators = Lists.newLinkedList(); List<MergeValidationListener> validators = Lists.newLinkedList();
@ -68,7 +69,8 @@ public class MergeValidators {
validators.add(projectConfigValidatorFactory.create()); validators.add(projectConfigValidatorFactory.create());
for (MergeValidationListener validator : validators) { for (MergeValidationListener validator : validators) {
validator.onPreMerge(repo, commit, destProject, destBranch, patchSetId); validator.onPreMerge(repo, commit, destProject, destBranch, patchSetId,
caller);
} }
} }
@ -124,7 +126,8 @@ public class MergeValidators {
final CodeReviewCommit commit, final CodeReviewCommit commit,
final ProjectState destProject, final ProjectState destProject,
final Branch.NameKey destBranch, final Branch.NameKey destBranch,
final PatchSet.Id patchSetId) final PatchSet.Id patchSetId,
IdentifiedUser caller)
throws MergeValidationException { throws MergeValidationException {
if (RefNames.REFS_CONFIG.equals(destBranch.get())) { if (RefNames.REFS_CONFIG.equals(destBranch.get())) {
final Project.NameKey newParent; final Project.NameKey newParent;
@ -200,10 +203,12 @@ public class MergeValidators {
CodeReviewCommit commit, CodeReviewCommit commit,
ProjectState destProject, ProjectState destProject,
Branch.NameKey destBranch, Branch.NameKey destBranch,
PatchSet.Id patchSetId) PatchSet.Id patchSetId,
IdentifiedUser caller)
throws MergeValidationException { throws MergeValidationException {
for (MergeValidationListener validator : mergeValidationListeners) { for (MergeValidationListener validator : mergeValidationListeners) {
validator.onPreMerge(repo, commit, destProject, destBranch, patchSetId); validator.onPreMerge(repo, commit, destProject, destBranch, patchSetId,
caller);
} }
} }
} }

View File

@ -45,10 +45,13 @@ import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException; import java.io.IOException;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class Schema_115 extends SchemaVersion { public class Schema_115 extends SchemaVersion {
private final GitRepositoryManager mgr; private final GitRepositoryManager mgr;
@ -72,54 +75,73 @@ public class Schema_115 extends SchemaVersion {
Map<Account.Id, DiffPreferencesInfo> imports = new HashMap<>(); Map<Account.Id, DiffPreferencesInfo> imports = new HashMap<>();
try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement(); try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
ResultSet rs = stmt.executeQuery( ResultSet rs = stmt.executeQuery(
"SELECT " "SELECT * FROM account_diff_preferences")) {
+ "id, " Set<String> availableColumns = getColumns(rs);
+ "context, "
+ "expand_all_comments, "
+ "hide_line_numbers, "
+ "hide_top_menu, "
+ "ignore_whitespace, "
+ "intraline_difference, "
+ "line_length, "
+ "manual_review, "
+ "render_entire_file, "
+ "retain_header, "
+ "show_line_endings, "
+ "show_tabs, "
+ "show_whitespace_errors, "
+ "skip_deleted, "
+ "skip_uncommented, "
+ "syntax_highlighting, "
+ "tab_size, "
+ "theme, "
+ "hide_empty_pane, "
+ "auto_hide_diff_table_header "
+ "FROM account_diff_preferences")) {
while (rs.next()) { while (rs.next()) {
Account.Id accountId = new Account.Id(rs.getInt(1)); Account.Id accountId = new Account.Id(rs.getInt("id"));
DiffPreferencesInfo prefs = new DiffPreferencesInfo(); DiffPreferencesInfo prefs = new DiffPreferencesInfo();
prefs.context = (int)rs.getShort(2); if (availableColumns.contains("context")) {
prefs.expandAllComments = toBoolean(rs.getString(3)); prefs.context = (int)rs.getShort("context");
prefs.hideLineNumbers = toBoolean(rs.getString(4)); }
prefs.hideTopMenu = toBoolean(rs.getString(5)); if (availableColumns.contains("expand_all_comments")) {
// Enum with char as value prefs.expandAllComments = toBoolean(rs.getString("expand_all_comments"));
prefs.ignoreWhitespace = toWhitespace(rs.getString(6)); }
prefs.intralineDifference = toBoolean(rs.getString(7)); if (availableColumns.contains("hide_line_numbers")) {
prefs.lineLength = rs.getInt(8); prefs.hideLineNumbers = toBoolean(rs.getString("hide_line_numbers"));
prefs.manualReview = toBoolean(rs.getString(9)); }
prefs.renderEntireFile = toBoolean(rs.getString(10)); if (availableColumns.contains("hide_top_menu")) {
prefs.retainHeader = toBoolean(rs.getString(11)); prefs.hideTopMenu = toBoolean(rs.getString("hide_top_menu"));
prefs.showLineEndings = toBoolean(rs.getString(12)); }
prefs.showTabs = toBoolean(rs.getString(13)); if (availableColumns.contains("ignore_whitespace")) {
prefs.showWhitespaceErrors = toBoolean(rs.getString(14)); // Enum with char as value
prefs.skipDeleted = toBoolean(rs.getString(15)); prefs.ignoreWhitespace = toWhitespace(rs.getString("ignore_whitespace"));
prefs.skipUncommented = toBoolean(rs.getString(16)); }
prefs.syntaxHighlighting = toBoolean(rs.getString(17)); if (availableColumns.contains("intraline_difference")) {
prefs.tabSize = rs.getInt(18); prefs.intralineDifference = toBoolean(rs.getString("intraline_difference"));
// Enum with name as values; can be null }
prefs.theme = toTheme(rs.getString(19)); if (availableColumns.contains("line_length")) {
prefs.hideEmptyPane = toBoolean(rs.getString(20)); prefs.lineLength = rs.getInt("line_length");
prefs.autoHideDiffTableHeader = toBoolean(rs.getString(21)); }
if (availableColumns.contains("manual_review")) {
prefs.manualReview = toBoolean(rs.getString("manual_review"));
}
if (availableColumns.contains("render_entire_file")) {
prefs.renderEntireFile = toBoolean(rs.getString("render_entire_file"));
}
if (availableColumns.contains("retain_header")) {
prefs.retainHeader = toBoolean(rs.getString("retain_header"));
}
if (availableColumns.contains("show_line_endings")) {
prefs.showLineEndings = toBoolean(rs.getString("show_line_endings"));
}
if (availableColumns.contains("show_tabs")) {
prefs.showTabs = toBoolean(rs.getString("show_tabs"));
}
if (availableColumns.contains("show_whitespace_errors")) {
prefs.showWhitespaceErrors = toBoolean(rs.getString("show_whitespace_errors"));
}
if (availableColumns.contains("skip_deleted")) {
prefs.skipDeleted = toBoolean(rs.getString("skip_deleted"));
}
if (availableColumns.contains("skip_uncommented")) {
prefs.skipUncommented = toBoolean(rs.getString("skip_uncommented"));
}
if (availableColumns.contains("syntax_highlighting")) {
prefs.syntaxHighlighting = toBoolean(rs.getString("syntax_highlighting"));
}
if (availableColumns.contains("tab_size")) {
prefs.tabSize = rs.getInt("tab_size");
}
if (availableColumns.contains("theme")) {
// Enum with name as values; can be null
prefs.theme = toTheme(rs.getString("theme"));
}
if (availableColumns.contains("hide_empty_pane")) {
prefs.hideEmptyPane = toBoolean(rs.getString("hide_empty_pane"));
}
if (availableColumns.contains("auto_hide_diff_table_header")) {
prefs.autoHideDiffTableHeader = toBoolean(rs.getString("auto_hide_diff_table_header"));
}
imports.put(accountId, prefs); imports.put(accountId, prefs);
} }
} }
@ -151,6 +173,16 @@ public class Schema_115 extends SchemaVersion {
} }
} }
private Set<String> getColumns(ResultSet rs) throws SQLException {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
Set<String> columns = new HashSet<>(columnCount);
for (int i = 1; i <= columnCount; i++) {
columns.add(metaData.getColumnLabel(i).toLowerCase());
}
return columns;
}
private static Theme toTheme(String v) { private static Theme toTheme(String v) {
if (v == null) { if (v == null) {
return Theme.DEFAULT; return Theme.DEFAULT;

@ -1 +1 @@
Subproject commit 88b0984638857ac7139de83b18dc7cad23670b4d Subproject commit 29f134c383e8958132887f5275e331472b981faa