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
	 Edwin Kempin
					Edwin Kempin