Merge branch 'stable-2.15'
* stable-2.15: Fix "Group members can't be added as reviewers" after merging Set version to 2.15-SNAPSHOT ProjectLevelConfig: Import Collectors.toList static Merge parent config values with child values Set version to 2.14.8-SNAPSHOT Fix the missing DB entry in Gerrit DB Fix unit test "addGroupAsReviewersWhenANotPerfectMatchedUserExist" Change-Id: I18e635f55f69892b1c5c9f203030f4181973fa3c
This commit is contained in:
@@ -143,7 +143,21 @@ public class AccountManager {
|
|||||||
try (ReviewDb db = schema.open()) {
|
try (ReviewDb db = schema.open()) {
|
||||||
ExternalId id = externalIds.get(who.getExternalIdKey());
|
ExternalId id = externalIds.get(who.getExternalIdKey());
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
|
if (who.getUserName().isPresent()) {
|
||||||
|
ExternalId.Key key = ExternalId.Key.create(SCHEME_USERNAME, who.getUserName().get());
|
||||||
|
ExternalId existingId = externalIds.get(key);
|
||||||
|
if (existingId != null) {
|
||||||
|
// An inconsistency is detected in the database, having a record for scheme "username:"
|
||||||
|
// but no record for scheme "gerrit:". Try to recover by linking
|
||||||
|
// "gerrit:" identity to the existing account.
|
||||||
|
log.warn(
|
||||||
|
"User {} already has an account; link new identity to the existing account.",
|
||||||
|
who.getUserName());
|
||||||
|
return link(existingId.accountId(), who);
|
||||||
|
}
|
||||||
|
}
|
||||||
// New account, automatically create and return.
|
// New account, automatically create and return.
|
||||||
|
log.info("External ID not found. Attempting to create new account.");
|
||||||
return create(db, who);
|
return create(db, who);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,6 +397,7 @@ public class AccountManager {
|
|||||||
public AuthResult link(Account.Id to, AuthRequest who)
|
public AuthResult link(Account.Id to, AuthRequest who)
|
||||||
throws AccountException, OrmException, IOException, ConfigInvalidException {
|
throws AccountException, OrmException, IOException, ConfigInvalidException {
|
||||||
ExternalId extId = externalIds.get(who.getExternalIdKey());
|
ExternalId extId = externalIds.get(who.getExternalIdKey());
|
||||||
|
log.info("Link another authentication identity to an existing account");
|
||||||
if (extId != null) {
|
if (extId != null) {
|
||||||
if (!extId.accountId().equals(to)) {
|
if (!extId.accountId().equals(to)) {
|
||||||
throw new AccountException(
|
throw new AccountException(
|
||||||
@@ -390,6 +405,7 @@ public class AccountManager {
|
|||||||
}
|
}
|
||||||
update(who, extId);
|
update(who, extId);
|
||||||
} else {
|
} else {
|
||||||
|
log.info("Linking new external ID to the existing account");
|
||||||
accountsUpdateProvider
|
accountsUpdateProvider
|
||||||
.get()
|
.get()
|
||||||
.update(
|
.update(
|
||||||
|
|||||||
@@ -288,7 +288,32 @@ public class PluginConfigFactory implements ReloadPluginListener {
|
|||||||
*/
|
*/
|
||||||
public Config getProjectPluginConfigWithInheritance(
|
public Config getProjectPluginConfigWithInheritance(
|
||||||
Project.NameKey projectName, String pluginName) throws NoSuchProjectException {
|
Project.NameKey projectName, String pluginName) throws NoSuchProjectException {
|
||||||
return getPluginConfig(projectName, pluginName).getWithInheritance();
|
return getPluginConfig(projectName, pluginName).getWithInheritance(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the configuration for the specified plugin that is stored in the '{@code
|
||||||
|
* <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project.
|
||||||
|
* Parameters from the '{@code <plugin-name>.config}' of the parent project are appended to this
|
||||||
|
* project's '{@code <plugin-name>.config}' files.
|
||||||
|
*
|
||||||
|
* <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue
|
||||||
|
*
|
||||||
|
* <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue
|
||||||
|
*
|
||||||
|
* <p>return: [mySection "mySubsection"] myKey = childValue myKey = parentValue anotherKey =
|
||||||
|
* someValue
|
||||||
|
*
|
||||||
|
* @param projectName the name of the project for which the plugin configuration should be
|
||||||
|
* returned
|
||||||
|
* @param pluginName the name of the plugin for which the configuration should be returned
|
||||||
|
* @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified
|
||||||
|
* project with parameters from the parent projects appended to the project values
|
||||||
|
* @throws NoSuchProjectException thrown if the specified project does not exist
|
||||||
|
*/
|
||||||
|
public Config getProjectPluginConfigWithMergedInheritance(
|
||||||
|
Project.NameKey projectName, String pluginName) throws NoSuchProjectException {
|
||||||
|
return getPluginConfig(projectName, pluginName).getWithInheritance(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -310,7 +335,30 @@ public class PluginConfigFactory implements ReloadPluginListener {
|
|||||||
*/
|
*/
|
||||||
public Config getProjectPluginConfigWithInheritance(
|
public Config getProjectPluginConfigWithInheritance(
|
||||||
ProjectState projectState, String pluginName) {
|
ProjectState projectState, String pluginName) {
|
||||||
return projectState.getConfig(pluginName + EXTENSION).getWithInheritance();
|
return projectState.getConfig(pluginName + EXTENSION).getWithInheritance(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the configuration for the specified plugin that is stored in the '{@code
|
||||||
|
* <plugin-name>.config}' file in the 'refs/meta/config' branch of the specified project.
|
||||||
|
* Parameters from the '{@code <plugin-name>.config}' of the parent project are appended to this
|
||||||
|
* project's '{@code <plugin-name>.config}' files.
|
||||||
|
*
|
||||||
|
* <p>E.g.: child project: [mySection "mySubsection"] myKey = childValue
|
||||||
|
*
|
||||||
|
* <p>parent project: [mySection "mySubsection"] myKey = parentValue anotherKey = someValue
|
||||||
|
*
|
||||||
|
* <p>return: [mySection "mySubsection"] myKey = childValue myKey = parentValue anotherKey =
|
||||||
|
* someValue
|
||||||
|
*
|
||||||
|
* @param projectState the project for which the plugin configuration should be returned
|
||||||
|
* @param pluginName the name of the plugin for which the configuration should be returned
|
||||||
|
* @return the plugin configuration from the '{@code <plugin-name>.config}' file of the specified
|
||||||
|
* project with inheriting non-set parameters from the parent projects
|
||||||
|
*/
|
||||||
|
public Config getProjectPluginConfigWithMergedInheritance(
|
||||||
|
ProjectState projectState, String pluginName) {
|
||||||
|
return projectState.getConfig(pluginName + EXTENSION).getWithInheritance(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProjectLevelConfig getPluginConfig(Project.NameKey projectName, String pluginName)
|
private ProjectLevelConfig getPluginConfig(Project.NameKey projectName, String pluginName)
|
||||||
|
|||||||
@@ -14,12 +14,16 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.git;
|
package com.google.gerrit.server.git;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
import org.eclipse.jgit.lib.CommitBuilder;
|
import org.eclipse.jgit.lib.CommitBuilder;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
@@ -53,6 +57,22 @@ public class ProjectLevelConfig extends VersionedMetaData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Config getWithInheritance() {
|
public Config getWithInheritance() {
|
||||||
|
return getWithInheritance(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Config that includes the values from all parent projects.
|
||||||
|
*
|
||||||
|
* <p>Merging means that matching sections/subsection will be merged to include the values from
|
||||||
|
* both parent and child config.
|
||||||
|
*
|
||||||
|
* <p>No merging means that matching sections/subsections in the child project will replace the
|
||||||
|
* corresponding value from the parent.
|
||||||
|
*
|
||||||
|
* @param merge whether to merge parent values with child values or not.
|
||||||
|
* @return a combined config.
|
||||||
|
*/
|
||||||
|
public Config getWithInheritance(boolean merge) {
|
||||||
Config cfgWithInheritance = new Config();
|
Config cfgWithInheritance = new Config();
|
||||||
try {
|
try {
|
||||||
cfgWithInheritance.fromText(get().toText());
|
cfgWithInheritance.fromText(get().toText());
|
||||||
@@ -65,21 +85,41 @@ public class ProjectLevelConfig extends VersionedMetaData {
|
|||||||
for (String section : parentCfg.getSections()) {
|
for (String section : parentCfg.getSections()) {
|
||||||
Set<String> allNames = get().getNames(section);
|
Set<String> allNames = get().getNames(section);
|
||||||
for (String name : parentCfg.getNames(section)) {
|
for (String name : parentCfg.getNames(section)) {
|
||||||
|
String[] parentValues = parentCfg.getStringList(section, null, name);
|
||||||
if (!allNames.contains(name)) {
|
if (!allNames.contains(name)) {
|
||||||
|
cfgWithInheritance.setStringList(section, null, name, Arrays.asList(parentValues));
|
||||||
|
} else if (merge) {
|
||||||
cfgWithInheritance.setStringList(
|
cfgWithInheritance.setStringList(
|
||||||
section, null, name, Arrays.asList(parentCfg.getStringList(section, null, name)));
|
section,
|
||||||
|
null,
|
||||||
|
name,
|
||||||
|
Stream.concat(
|
||||||
|
Arrays.stream(cfg.getStringList(section, null, name)),
|
||||||
|
Arrays.stream(parentValues))
|
||||||
|
.sorted()
|
||||||
|
.distinct()
|
||||||
|
.collect(toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String subsection : parentCfg.getSubsections(section)) {
|
for (String subsection : parentCfg.getSubsections(section)) {
|
||||||
allNames = get().getNames(section, subsection);
|
allNames = get().getNames(section, subsection);
|
||||||
for (String name : parentCfg.getNames(section, subsection)) {
|
for (String name : parentCfg.getNames(section, subsection)) {
|
||||||
|
String[] parentValues = parentCfg.getStringList(section, subsection, name);
|
||||||
if (!allNames.contains(name)) {
|
if (!allNames.contains(name)) {
|
||||||
|
cfgWithInheritance.setStringList(
|
||||||
|
section, subsection, name, Arrays.asList(parentValues));
|
||||||
|
} else if (merge) {
|
||||||
cfgWithInheritance.setStringList(
|
cfgWithInheritance.setStringList(
|
||||||
section,
|
section,
|
||||||
subsection,
|
subsection,
|
||||||
name,
|
name,
|
||||||
Arrays.asList(parentCfg.getStringList(section, subsection, name)));
|
Streams.concat(
|
||||||
|
Arrays.stream(cfg.getStringList(section, subsection, name)),
|
||||||
|
Arrays.stream(parentValues))
|
||||||
|
.sorted()
|
||||||
|
.distinct()
|
||||||
|
.collect(toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,13 +194,20 @@ public class PostReviewers
|
|||||||
|
|
||||||
Addition byAccountId =
|
Addition byAccountId =
|
||||||
addByAccountId(reviewer, rsrc, state, notify, accountsToNotify, allowGroup, allowByEmail);
|
addByAccountId(reviewer, rsrc, state, notify, accountsToNotify, allowGroup, allowByEmail);
|
||||||
|
|
||||||
|
Addition wholeGroup = null;
|
||||||
|
if (byAccountId == null || !byAccountId.exactMatchFound) {
|
||||||
|
wholeGroup =
|
||||||
|
addWholeGroup(
|
||||||
|
reviewer, rsrc, state, notify, accountsToNotify, confirmed, allowGroup, allowByEmail);
|
||||||
|
if (wholeGroup != null && wholeGroup.exactMatchFound) {
|
||||||
|
return wholeGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (byAccountId != null) {
|
if (byAccountId != null) {
|
||||||
return byAccountId;
|
return byAccountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Addition wholeGroup =
|
|
||||||
addWholeGroup(
|
|
||||||
reviewer, rsrc, state, notify, accountsToNotify, confirmed, allowGroup, allowByEmail);
|
|
||||||
if (wholeGroup != null) {
|
if (wholeGroup != null) {
|
||||||
return wholeGroup;
|
return wholeGroup;
|
||||||
}
|
}
|
||||||
@@ -216,7 +223,8 @@ public class PostReviewers
|
|||||||
null,
|
null,
|
||||||
CC,
|
CC,
|
||||||
NotifyHandling.NONE,
|
NotifyHandling.NONE,
|
||||||
ImmutableListMultimap.of());
|
ImmutableListMultimap.of(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -229,9 +237,14 @@ public class PostReviewers
|
|||||||
boolean allowGroup,
|
boolean allowGroup,
|
||||||
boolean allowByEmail)
|
boolean allowByEmail)
|
||||||
throws OrmException, PermissionBackendException, IOException, ConfigInvalidException {
|
throws OrmException, PermissionBackendException, IOException, ConfigInvalidException {
|
||||||
Account.Id accountId = null;
|
IdentifiedUser user = null;
|
||||||
|
boolean exactMatchFound = false;
|
||||||
try {
|
try {
|
||||||
accountId = accounts.parse(reviewer).getAccountId();
|
user = accounts.parse(reviewer);
|
||||||
|
if (reviewer.equalsIgnoreCase(user.getName())
|
||||||
|
|| reviewer.equals(String.valueOf(user.getAccountId()))) {
|
||||||
|
exactMatchFound = true;
|
||||||
|
}
|
||||||
} catch (UnprocessableEntityException | AuthException e) {
|
} catch (UnprocessableEntityException | AuthException e) {
|
||||||
// AuthException won't occur since the user is authenticated at this point.
|
// AuthException won't occur since the user is authenticated at this point.
|
||||||
if (!allowGroup && !allowByEmail) {
|
if (!allowGroup && !allowByEmail) {
|
||||||
@@ -242,13 +255,20 @@ public class PostReviewers
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReviewerResource rrsrc = reviewerFactory.create(rsrc, accountId);
|
ReviewerResource rrsrc = reviewerFactory.create(rsrc, user.getAccountId());
|
||||||
Account member = rrsrc.getReviewerUser().getAccount();
|
Account member = rrsrc.getReviewerUser().getAccount();
|
||||||
PermissionBackend.ForRef perm =
|
PermissionBackend.ForRef perm =
|
||||||
permissionBackend.user(rrsrc.getReviewerUser()).ref(rrsrc.getChange().getDest());
|
permissionBackend.user(rrsrc.getReviewerUser()).ref(rrsrc.getChange().getDest());
|
||||||
if (isValidReviewer(member, perm)) {
|
if (isValidReviewer(member, perm)) {
|
||||||
return new Addition(
|
return new Addition(
|
||||||
reviewer, rsrc, ImmutableSet.of(member.getId()), null, state, notify, accountsToNotify);
|
reviewer,
|
||||||
|
rsrc,
|
||||||
|
ImmutableSet.of(member.getId()),
|
||||||
|
null,
|
||||||
|
state,
|
||||||
|
notify,
|
||||||
|
accountsToNotify,
|
||||||
|
exactMatchFound);
|
||||||
}
|
}
|
||||||
if (!member.isActive()) {
|
if (!member.isActive()) {
|
||||||
if (allowByEmail && state == CC) {
|
if (allowByEmail && state == CC) {
|
||||||
@@ -328,7 +348,7 @@ public class PostReviewers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Addition(reviewer, rsrc, reviewers, null, state, notify, accountsToNotify);
|
return new Addition(reviewer, rsrc, reviewers, null, state, notify, accountsToNotify, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -357,7 +377,7 @@ public class PostReviewers
|
|||||||
return fail(reviewer, MessageFormat.format(ChangeMessages.get().reviewerInvalid, reviewer));
|
return fail(reviewer, MessageFormat.format(ChangeMessages.get().reviewerInvalid, reviewer));
|
||||||
}
|
}
|
||||||
return new Addition(
|
return new Addition(
|
||||||
reviewer, rsrc, null, ImmutableList.of(adr), state, notify, accountsToNotify);
|
reviewer, rsrc, null, ImmutableList.of(adr), state, notify, accountsToNotify, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidReviewer(Account member, PermissionBackend.ForRef perm)
|
private boolean isValidReviewer(Account member, PermissionBackend.ForRef perm)
|
||||||
@@ -395,6 +415,7 @@ public class PostReviewers
|
|||||||
final ReviewerState state;
|
final ReviewerState state;
|
||||||
final ChangeNotes notes;
|
final ChangeNotes notes;
|
||||||
final IdentifiedUser caller;
|
final IdentifiedUser caller;
|
||||||
|
final boolean exactMatchFound;
|
||||||
|
|
||||||
Addition(String reviewer) {
|
Addition(String reviewer) {
|
||||||
result = new AddReviewerResult(reviewer);
|
result = new AddReviewerResult(reviewer);
|
||||||
@@ -404,6 +425,7 @@ public class PostReviewers
|
|||||||
state = REVIEWER;
|
state = REVIEWER;
|
||||||
notes = null;
|
notes = null;
|
||||||
caller = null;
|
caller = null;
|
||||||
|
exactMatchFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Addition(
|
protected Addition(
|
||||||
@@ -413,7 +435,8 @@ public class PostReviewers
|
|||||||
@Nullable Collection<Address> reviewersByEmail,
|
@Nullable Collection<Address> reviewersByEmail,
|
||||||
ReviewerState state,
|
ReviewerState state,
|
||||||
@Nullable NotifyHandling notify,
|
@Nullable NotifyHandling notify,
|
||||||
ListMultimap<RecipientType, Account.Id> accountsToNotify) {
|
ListMultimap<RecipientType, Account.Id> accountsToNotify,
|
||||||
|
boolean exactMatchFound) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
reviewers != null || reviewersByEmail != null,
|
reviewers != null || reviewersByEmail != null,
|
||||||
"must have either reviewers or reviewersByEmail");
|
"must have either reviewers or reviewersByEmail");
|
||||||
@@ -427,6 +450,7 @@ public class PostReviewers
|
|||||||
op =
|
op =
|
||||||
postReviewersOpFactory.create(
|
postReviewersOpFactory.create(
|
||||||
rsrc, this.reviewers, this.reviewersByEmail, state, notify, accountsToNotify);
|
rsrc, this.reviewers, this.reviewersByEmail, state, notify, accountsToNotify);
|
||||||
|
this.exactMatchFound = exactMatchFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gatherResults() throws OrmException, PermissionBackendException {
|
void gatherResults() throws OrmException, PermissionBackendException {
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ import org.eclipse.jgit.revwalk.RevWalk;
|
|||||||
import org.eclipse.jgit.transport.PushResult;
|
import org.eclipse.jgit.transport.PushResult;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@NoHttpd
|
@NoHttpd
|
||||||
@@ -1506,7 +1505,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
assertThat(sender.getMessages()).hasSize(1);
|
assertThat(sender.getMessages()).hasSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void addReviewerThatIsNotPerfectMatch() throws Exception {
|
public void addReviewerThatIsNotPerfectMatch() throws Exception {
|
||||||
TestTimeUtil.resetWithClockStep(1, SECONDS);
|
TestTimeUtil.resetWithClockStep(1, SECONDS);
|
||||||
@@ -1551,7 +1549,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
assertThat(rsrc.getChange().getLastUpdatedOn()).isNotEqualTo(oldTs);
|
assertThat(rsrc.getChange().getLastUpdatedOn()).isNotEqualTo(oldTs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void addGroupAsReviewersWhenANotPerfectMatchedUserExists() throws Exception {
|
public void addGroupAsReviewersWhenANotPerfectMatchedUserExists() throws Exception {
|
||||||
TestTimeUtil.resetWithClockStep(1, SECONDS);
|
TestTimeUtil.resetWithClockStep(1, SECONDS);
|
||||||
@@ -1560,16 +1557,17 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
String oldETag = rsrc.getETag();
|
String oldETag = rsrc.getETag();
|
||||||
Timestamp oldTs = rsrc.getChange().getLastUpdatedOn();
|
Timestamp oldTs = rsrc.getChange().getLastUpdatedOn();
|
||||||
|
|
||||||
//create a group named "us" with one user: testUser
|
//create a group named "kobe" with one user: lee
|
||||||
TestAccount testUser = accountCreator.create("testUser", "testUser@test.com", "testUser");
|
TestAccount testUser = accountCreator.create("kobebryant", "kobebryant@test.com", "kobebryant");
|
||||||
String testGroup =
|
TestAccount myGroupUser = accountCreator.create("lee", "lee@test.com", "lee");
|
||||||
createGroupWithRealName(user.fullName.substring(0, user.fullName.length() / 2));
|
|
||||||
|
String testGroup = createGroupWithRealName("kobe");
|
||||||
GroupApi groupApi = gApi.groups().id(testGroup);
|
GroupApi groupApi = gApi.groups().id(testGroup);
|
||||||
groupApi.description("test group");
|
groupApi.description("test group");
|
||||||
groupApi.addMembers(testUser.fullName);
|
groupApi.addMembers(myGroupUser.fullName);
|
||||||
|
|
||||||
//ensure that user "user" is not in the group
|
//ensure that user "user" is not in the group
|
||||||
groupApi.removeMembers(user.fullName);
|
groupApi.removeMembers(testUser.fullName);
|
||||||
|
|
||||||
AddReviewerInput in = new AddReviewerInput();
|
AddReviewerInput in = new AddReviewerInput();
|
||||||
in.reviewer = testGroup;
|
in.reviewer = testGroup;
|
||||||
@@ -1578,11 +1576,11 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
List<Message> messages = sender.getMessages();
|
List<Message> messages = sender.getMessages();
|
||||||
assertThat(messages).hasSize(1);
|
assertThat(messages).hasSize(1);
|
||||||
Message m = messages.get(0);
|
Message m = messages.get(0);
|
||||||
assertThat(m.rcpt()).containsExactly(testUser.emailAddress);
|
assertThat(m.rcpt()).containsExactly(myGroupUser.emailAddress);
|
||||||
assertThat(m.body()).contains("Hello " + testUser.fullName + ",\n");
|
assertThat(m.body()).contains("Hello " + myGroupUser.fullName + ",\n");
|
||||||
assertThat(m.body()).contains("I'd like you to do a code review.");
|
assertThat(m.body()).contains("I'd like you to do a code review.");
|
||||||
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
|
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
|
||||||
assertMailReplyTo(m, testUser.email);
|
assertMailReplyTo(m, myGroupUser.email);
|
||||||
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
|
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
|
||||||
|
|
||||||
// When NoteDb is enabled adding a reviewer records that user as reviewer
|
// When NoteDb is enabled adding a reviewer records that user as reviewer
|
||||||
@@ -1592,7 +1590,7 @@ public class ChangeIT extends AbstractDaemonTest {
|
|||||||
Collection<AccountInfo> reviewers = c.reviewers.get(REVIEWER);
|
Collection<AccountInfo> reviewers = c.reviewers.get(REVIEWER);
|
||||||
assertThat(reviewers).isNotNull();
|
assertThat(reviewers).isNotNull();
|
||||||
assertThat(reviewers).hasSize(1);
|
assertThat(reviewers).hasSize(1);
|
||||||
assertThat(reviewers.iterator().next()._accountId).isEqualTo(testUser.getId().get());
|
assertThat(reviewers.iterator().next()._accountId).isEqualTo(myGroupUser.getId().get());
|
||||||
|
|
||||||
// Ensure ETag and lastUpdatedOn are updated.
|
// Ensure ETag and lastUpdatedOn are updated.
|
||||||
rsrc = parseResource(r);
|
rsrc = parseResource(r);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.google.gerrit.acceptance.PushOneCommit;
|
|||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
|
import java.util.Arrays;
|
||||||
import org.eclipse.jgit.junit.TestRepository;
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -114,4 +115,67 @@ public class ProjectLevelConfigIT extends AbstractDaemonTest {
|
|||||||
|
|
||||||
assertThat(state.getConfig(configName).get().toText()).isEqualTo(cfg.toText());
|
assertThat(state.getConfig(configName).get().toText()).isEqualTo(cfg.toText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withMergedInheritance() throws Exception {
|
||||||
|
String configName = "test.config";
|
||||||
|
|
||||||
|
Config parentCfg = new Config();
|
||||||
|
parentCfg.setString("s1", null, "k1", "parentValue1");
|
||||||
|
parentCfg.setString("s1", null, "k2", "parentValue2");
|
||||||
|
parentCfg.setString("s2", "ss", "k3", "parentValue3");
|
||||||
|
parentCfg.setString("s2", "ss", "k4", "parentValue4");
|
||||||
|
|
||||||
|
pushFactory
|
||||||
|
.create(
|
||||||
|
db,
|
||||||
|
admin.getIdent(),
|
||||||
|
testRepo,
|
||||||
|
"Create Project Level Config",
|
||||||
|
configName,
|
||||||
|
parentCfg.toText())
|
||||||
|
.to(RefNames.REFS_CONFIG)
|
||||||
|
.assertOkStatus();
|
||||||
|
|
||||||
|
Project.NameKey childProject = createProject("child", project);
|
||||||
|
TestRepository<?> childTestRepo = cloneProject(childProject);
|
||||||
|
fetch(childTestRepo, RefNames.REFS_CONFIG + ":refs/heads/config");
|
||||||
|
childTestRepo.reset("refs/heads/config");
|
||||||
|
|
||||||
|
Config cfg = new Config();
|
||||||
|
cfg.setString("s1", null, "k1", "parentValue1");
|
||||||
|
cfg.setString("s1", null, "k2", "parentValue2");
|
||||||
|
cfg.setString("s2", "ss", "k3", "parentValue3");
|
||||||
|
cfg.setString("s2", "ss", "k4", "parentValue4");
|
||||||
|
cfg.setString("s1", null, "k1", "childValue1");
|
||||||
|
cfg.setString("s2", "ss", "k3", "childValue2");
|
||||||
|
cfg.setString("s3", null, "k5", "childValue3");
|
||||||
|
cfg.setString("s3", "ss", "k6", "childValue4");
|
||||||
|
|
||||||
|
pushFactory
|
||||||
|
.create(
|
||||||
|
db,
|
||||||
|
admin.getIdent(),
|
||||||
|
childTestRepo,
|
||||||
|
"Create Project Level Config",
|
||||||
|
configName,
|
||||||
|
cfg.toText())
|
||||||
|
.to(RefNames.REFS_CONFIG)
|
||||||
|
.assertOkStatus();
|
||||||
|
|
||||||
|
ProjectState state = projectCache.get(childProject);
|
||||||
|
|
||||||
|
Config expectedCfg = new Config();
|
||||||
|
expectedCfg.setStringList("s1", null, "k1", Arrays.asList("childValue1", "parentValue1"));
|
||||||
|
expectedCfg.setString("s1", null, "k2", "parentValue2");
|
||||||
|
expectedCfg.setStringList("s2", "ss", "k3", Arrays.asList("childValue2", "parentValue3"));
|
||||||
|
expectedCfg.setString("s2", "ss", "k4", "parentValue4");
|
||||||
|
expectedCfg.setString("s3", null, "k5", "childValue3");
|
||||||
|
expectedCfg.setString("s3", "ss", "k6", "childValue4");
|
||||||
|
|
||||||
|
assertThat(state.getConfig(configName).getWithInheritance(true).toText())
|
||||||
|
.isEqualTo(expectedCfg.toText());
|
||||||
|
|
||||||
|
assertThat(state.getConfig(configName).get().toText()).isEqualTo(cfg.toText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user