Merge changes I92746327,I9516b07c,I56b0f01c,If3477ba6,I8db9e1ed
* changes: Change default submit type for new projects to INHERIT CreateProjectIT: Assert that API creates refs/meta/config RepositoryConfig: Extract a constant for default submit type RepositoryConfig: Change return types to ImmutableList Streamify RepositoryConfig
This commit is contained in:
@@ -3765,10 +3765,14 @@ are `INHERIT`, `MERGE_IF_NECESSARY`, `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`,
|
|||||||
+
|
+
|
||||||
For more details see link:project-configuration.html#submit_type[Submit Types].
|
For more details see link:project-configuration.html#submit_type[Submit Types].
|
||||||
+
|
+
|
||||||
|
Default is link:project-configuration.html#submit_type_inherit[`INHERIT`].
|
||||||
|
+
|
||||||
This submit type is only applied at project creation time if a submit type is
|
This submit type is only applied at project creation time if a submit type is
|
||||||
omitted from the link:rest-api-projects.html#project-input[ProjectInput]. If the
|
omitted from the link:rest-api-projects.html#project-input[ProjectInput]. If the
|
||||||
submit type is unset in the project config at runtime, it defaults to
|
submit type is unset in the project config at runtime, for backwards
|
||||||
link:project-configuration.html#merge_if_necessary[`MERGE_IF_NECESSARY`].
|
compatibility purposes, it defaults to
|
||||||
|
link:project-configuration.html#merge_if_necessary[`MERGE_IF_NECESSARY`] rather
|
||||||
|
than `INHERIT`.
|
||||||
|
|
||||||
[[repository.name.ownerGroup]]repository.<name>.ownerGroup::
|
[[repository.name.ownerGroup]]repository.<name>.ownerGroup::
|
||||||
+
|
+
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ The following submit types are supported:
|
|||||||
[[submit_type_inherit]]
|
[[submit_type_inherit]]
|
||||||
* Inherit
|
* Inherit
|
||||||
+
|
+
|
||||||
|
This is the default for new projects, unless overridden by a global
|
||||||
|
link:config-gerrit.html#repository.name.defaultSubmitType[`defaultSubmitType` option].
|
||||||
|
+
|
||||||
Inherit the submit type from the parent project. In `All-Projects`, this
|
Inherit the submit type from the parent project. In `All-Projects`, this
|
||||||
is equivalent to link:#merge_if_necessary[Merge If Necessary].
|
is equivalent to link:#merge_if_necessary[Merge If Necessary].
|
||||||
|
|
||||||
@@ -76,9 +79,6 @@ tip of the destination branch at submit time.
|
|||||||
[[merge_if_necessary]]
|
[[merge_if_necessary]]
|
||||||
* Merge If Necessary
|
* Merge If Necessary
|
||||||
+
|
+
|
||||||
This is the default for new projects, unless overridden by a global
|
|
||||||
link:config-gerrit.html#repository.name.defaultSubmitType[`defaultSubmitType` option].
|
|
||||||
+
|
|
||||||
If the change being submitted is a strict superset of the destination
|
If the change being submitted is a strict superset of the destination
|
||||||
branch, then the branch is fast-forwarded to the change. If not,
|
branch, then the branch is fast-forwarded to the change. If not,
|
||||||
then a merge commit is automatically created. This is identical
|
then a merge commit is automatically created. This is identical
|
||||||
|
|||||||
@@ -14,15 +14,18 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.config;
|
package com.google.gerrit.server.config;
|
||||||
|
|
||||||
|
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||||
|
import static java.util.Comparator.comparing;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.extensions.client.SubmitType;
|
import com.google.gerrit.extensions.client.SubmitType;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.Objects;
|
||||||
import java.util.List;
|
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@@ -33,6 +36,8 @@ public class RepositoryConfig {
|
|||||||
static final String DEFAULT_SUBMIT_TYPE_NAME = "defaultSubmitType";
|
static final String DEFAULT_SUBMIT_TYPE_NAME = "defaultSubmitType";
|
||||||
static final String BASE_PATH_NAME = "basePath";
|
static final String BASE_PATH_NAME = "basePath";
|
||||||
|
|
||||||
|
static final SubmitType DEFAULT_SUBMIT_TYPE = SubmitType.INHERIT;
|
||||||
|
|
||||||
private final Config cfg;
|
private final Config cfg;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -42,13 +47,10 @@ public class RepositoryConfig {
|
|||||||
|
|
||||||
public SubmitType getDefaultSubmitType(Project.NameKey project) {
|
public SubmitType getDefaultSubmitType(Project.NameKey project) {
|
||||||
return cfg.getEnum(
|
return cfg.getEnum(
|
||||||
SECTION_NAME,
|
SECTION_NAME, findSubSection(project.get()), DEFAULT_SUBMIT_TYPE_NAME, DEFAULT_SUBMIT_TYPE);
|
||||||
findSubSection(project.get()),
|
|
||||||
DEFAULT_SUBMIT_TYPE_NAME,
|
|
||||||
SubmitType.MERGE_IF_NECESSARY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getOwnerGroups(Project.NameKey project) {
|
public ImmutableList<String> getOwnerGroups(Project.NameKey project) {
|
||||||
return ImmutableList.copyOf(
|
return ImmutableList.copyOf(
|
||||||
cfg.getStringList(SECTION_NAME, findSubSection(project.get()), OWNER_GROUP_NAME));
|
cfg.getStringList(SECTION_NAME, findSubSection(project.get()), OWNER_GROUP_NAME));
|
||||||
}
|
}
|
||||||
@@ -58,22 +60,20 @@ public class RepositoryConfig {
|
|||||||
return basePath != null ? Paths.get(basePath) : null;
|
return basePath != null ? Paths.get(basePath) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Path> getAllBasePaths() {
|
public ImmutableList<Path> getAllBasePaths() {
|
||||||
List<Path> basePaths = new ArrayList<>();
|
return cfg.getSubsections(SECTION_NAME)
|
||||||
for (String subSection : cfg.getSubsections(SECTION_NAME)) {
|
.stream()
|
||||||
String basePath = cfg.getString(SECTION_NAME, subSection, BASE_PATH_NAME);
|
.map(sub -> cfg.getString(SECTION_NAME, sub, BASE_PATH_NAME))
|
||||||
if (basePath != null) {
|
.filter(Objects::nonNull)
|
||||||
basePaths.add(Paths.get(basePath));
|
.map(Paths::get)
|
||||||
}
|
.collect(toImmutableList());
|
||||||
}
|
|
||||||
return basePaths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the subSection to get repository configuration from.
|
* Find the subsection to get repository configuration from.
|
||||||
*
|
*
|
||||||
* <p>SubSection can use the * pattern so if project name matches more than one section, return
|
* <p>Subsection can use the * pattern so if project name matches more than one section, return
|
||||||
* the more precise one. E.g if the following subSections are defined:
|
* the more precise one. E.g if the following subsections are defined:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* [repository "somePath/*"]
|
* [repository "somePath/*"]
|
||||||
@@ -83,20 +83,18 @@ public class RepositoryConfig {
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* and this method is called with "somePath/somePath/someProject" as project name, it will return
|
* and this method is called with "somePath/somePath/someProject" as project name, it will return
|
||||||
* the subSection "somePath/somePath/*"
|
* the subsection "somePath/somePath/*"
|
||||||
*
|
*
|
||||||
* @param project Name of the project
|
* @param project Name of the project
|
||||||
* @return the name of the subSection, null if none is found
|
* @return the name of the subsection, null if none is found
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
private String findSubSection(String project) {
|
private String findSubSection(String project) {
|
||||||
String subSectionFound = null;
|
return cfg.getSubsections(SECTION_NAME)
|
||||||
for (String subSection : cfg.getSubsections(SECTION_NAME)) {
|
.stream()
|
||||||
if (isMatch(subSection, project)
|
.filter(ss -> isMatch(ss, project))
|
||||||
&& (subSectionFound == null || subSectionFound.length() < subSection.length())) {
|
.max(comparing(String::length))
|
||||||
subSectionFound = subSection;
|
.orElse(null);
|
||||||
}
|
|
||||||
}
|
|
||||||
return subSectionFound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMatch(String subSection, String project) {
|
private boolean isMatch(String subSection, String project) {
|
||||||
|
|||||||
@@ -16,8 +16,11 @@ package com.google.gerrit.acceptance.rest.project;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
import static com.google.common.truth.Truth8.assertThat;
|
||||||
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectInfo;
|
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectInfo;
|
||||||
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectOwners;
|
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjectOwners;
|
||||||
|
import static com.google.gerrit.server.git.ProjectConfig.PROJECT_CONFIG;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@@ -46,6 +49,7 @@ import com.google.gerrit.reviewdb.client.RefNames;
|
|||||||
import com.google.gerrit.server.group.SystemGroupBackend;
|
import com.google.gerrit.server.group.SystemGroupBackend;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CyclicBarrier;
|
import java.util.concurrent.CyclicBarrier;
|
||||||
@@ -55,7 +59,10 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.ObjectLoader;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
@@ -155,6 +162,8 @@ public class CreateProjectIT extends AbstractDaemonTest {
|
|||||||
assertThat(projectState).isNotNull();
|
assertThat(projectState).isNotNull();
|
||||||
assertProjectInfo(projectState.getProject(), p);
|
assertProjectInfo(projectState.getProject(), p);
|
||||||
assertHead(newProjectName, "refs/heads/master");
|
assertHead(newProjectName, "refs/heads/master");
|
||||||
|
assertThat(readProjectConfig(newProjectName))
|
||||||
|
.hasValue("[access]\n\tinheritFrom = All-Projects\n[submit]\n\taction = inherit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -343,7 +352,7 @@ public class CreateProjectIT extends AbstractDaemonTest {
|
|||||||
ConfigInfo cfg = gApi.projects().create(pin).config();
|
ConfigInfo cfg = gApi.projects().create(pin).config();
|
||||||
assertThat(cfg.submitType).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
assertThat(cfg.submitType).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
||||||
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
assertThat(cfg.defaultSubmitType.value).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
||||||
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
assertThat(cfg.defaultSubmitType.configuredValue).isEqualTo(SubmitType.INHERIT);
|
||||||
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
assertThat(cfg.defaultSubmitType.inheritedValue).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
||||||
|
|
||||||
ConfigInput cin = new ConfigInput();
|
ConfigInput cin = new ConfigInput();
|
||||||
@@ -438,4 +447,19 @@ public class CreateProjectIT extends AbstractDaemonTest {
|
|||||||
exception.expect(errType);
|
exception.expect(errType);
|
||||||
gApi.projects().create(in);
|
gApi.projects().create(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<String> readProjectConfig(String projectName) throws Exception {
|
||||||
|
try (Repository repo = repoManager.openRepository(new Project.NameKey(projectName))) {
|
||||||
|
TestRepository<?> tr = new TestRepository<>(repo);
|
||||||
|
RevWalk rw = tr.getRevWalk();
|
||||||
|
Ref ref = repo.exactRef(RefNames.REFS_CONFIG);
|
||||||
|
if (ref == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
ObjectLoader obj =
|
||||||
|
rw.getObjectReader()
|
||||||
|
.open(tr.get(rw.parseTree(ref.getObjectId()), PROJECT_CONFIG), Constants.OBJ_BLOB);
|
||||||
|
return Optional.of(new String(obj.getCachedBytes(Integer.MAX_VALUE), UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ public class RepositoryConfigTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultSubmitTypeWhenNotConfigured() {
|
public void defaultSubmitTypeWhenNotConfigured() {
|
||||||
|
// Check expected value explicitly rather than depending on constant.
|
||||||
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
|
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
|
||||||
.isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
.isEqualTo(SubmitType.INHERIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -67,7 +68,7 @@ public class RepositoryConfigTest {
|
|||||||
public void defaultSubmitTypeForSpecificFilter() {
|
public void defaultSubmitTypeForSpecificFilter() {
|
||||||
configureDefaultSubmitType("someProject", SubmitType.CHERRY_PICK);
|
configureDefaultSubmitType("someProject", SubmitType.CHERRY_PICK);
|
||||||
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someOtherProject")))
|
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someOtherProject")))
|
||||||
.isEqualTo(SubmitType.MERGE_IF_NECESSARY);
|
.isEqualTo(RepositoryConfig.DEFAULT_SUBMIT_TYPE);
|
||||||
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
|
assertThat(repoCfg.getDefaultSubmitType(new NameKey("someProject")))
|
||||||
.isEqualTo(SubmitType.CHERRY_PICK);
|
.isEqualTo(SubmitType.CHERRY_PICK);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static org.easymock.EasyMock.expect;
|
|||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.reset;
|
import static org.easymock.EasyMock.reset;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.config.RepositoryConfig;
|
import com.google.gerrit.server.config.RepositoryConfig;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
@@ -28,8 +29,6 @@ import com.google.gerrit.testing.TempFileUtil;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
@@ -55,7 +54,7 @@ public class MultiBaseLocalDiskRepositoryManagerTest extends GerritBaseTests {
|
|||||||
cfg = new Config();
|
cfg = new Config();
|
||||||
cfg.setString("gerrit", null, "basePath", "git");
|
cfg.setString("gerrit", null, "basePath", "git");
|
||||||
configMock = createNiceMock(RepositoryConfig.class);
|
configMock = createNiceMock(RepositoryConfig.class);
|
||||||
expect(configMock.getAllBasePaths()).andReturn(new ArrayList<Path>()).anyTimes();
|
expect(configMock.getAllBasePaths()).andReturn(ImmutableList.of()).anyTimes();
|
||||||
replay(configMock);
|
replay(configMock);
|
||||||
repoManager = new MultiBaseLocalDiskRepositoryManager(site, cfg, configMock);
|
repoManager = new MultiBaseLocalDiskRepositoryManager(site, cfg, configMock);
|
||||||
}
|
}
|
||||||
@@ -96,7 +95,7 @@ public class MultiBaseLocalDiskRepositoryManagerTest extends GerritBaseTests {
|
|||||||
Project.NameKey someProjectKey = new Project.NameKey("someProject");
|
Project.NameKey someProjectKey = new Project.NameKey("someProject");
|
||||||
reset(configMock);
|
reset(configMock);
|
||||||
expect(configMock.getBasePath(someProjectKey)).andReturn(alternateBasePath).anyTimes();
|
expect(configMock.getBasePath(someProjectKey)).andReturn(alternateBasePath).anyTimes();
|
||||||
expect(configMock.getAllBasePaths()).andReturn(Arrays.asList(alternateBasePath)).anyTimes();
|
expect(configMock.getAllBasePaths()).andReturn(ImmutableList.of(alternateBasePath)).anyTimes();
|
||||||
replay(configMock);
|
replay(configMock);
|
||||||
|
|
||||||
Repository repo = repoManager.createRepository(someProjectKey);
|
Repository repo = repoManager.createRepository(someProjectKey);
|
||||||
@@ -130,7 +129,7 @@ public class MultiBaseLocalDiskRepositoryManagerTest extends GerritBaseTests {
|
|||||||
reset(configMock);
|
reset(configMock);
|
||||||
expect(configMock.getBasePath(altPathProject)).andReturn(alternateBasePath).anyTimes();
|
expect(configMock.getBasePath(altPathProject)).andReturn(alternateBasePath).anyTimes();
|
||||||
expect(configMock.getBasePath(misplacedProject2)).andReturn(alternateBasePath).anyTimes();
|
expect(configMock.getBasePath(misplacedProject2)).andReturn(alternateBasePath).anyTimes();
|
||||||
expect(configMock.getAllBasePaths()).andReturn(Arrays.asList(alternateBasePath)).anyTimes();
|
expect(configMock.getAllBasePaths()).andReturn(ImmutableList.of(alternateBasePath)).anyTimes();
|
||||||
replay(configMock);
|
replay(configMock);
|
||||||
|
|
||||||
repoManager.createRepository(basePathProject);
|
repoManager.createRepository(basePathProject);
|
||||||
@@ -157,7 +156,7 @@ public class MultiBaseLocalDiskRepositoryManagerTest extends GerritBaseTests {
|
|||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testRelativeAlternateLocation() {
|
public void testRelativeAlternateLocation() {
|
||||||
configMock = createNiceMock(RepositoryConfig.class);
|
configMock = createNiceMock(RepositoryConfig.class);
|
||||||
expect(configMock.getAllBasePaths()).andReturn(Arrays.asList(Paths.get("repos"))).anyTimes();
|
expect(configMock.getAllBasePaths()).andReturn(ImmutableList.of(Paths.get("repos"))).anyTimes();
|
||||||
replay(configMock);
|
replay(configMock);
|
||||||
repoManager = new MultiBaseLocalDiskRepositoryManager(site, cfg, configMock);
|
repoManager = new MultiBaseLocalDiskRepositoryManager(site, cfg, configMock);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user