Merge "Support reading default project.config for All-Projects from etc"
This commit is contained in:
commit
af2d832f85
@ -4959,6 +4959,38 @@ executions are `Wed 10:30`, `Fri 10:30`. etc.
|
|||||||
Assuming that the server is started on `Mon 07:00` then this yields the
|
Assuming that the server is started on `Mon 07:00` then this yields the
|
||||||
first run on Tuesday at 06:00 and a repetition interval of 1 day.
|
first run on Tuesday at 06:00 and a repetition interval of 1 day.
|
||||||
|
|
||||||
|
[[All-Projects-project.config]]
|
||||||
|
== File `etc/All-Projects/project.config`
|
||||||
|
|
||||||
|
The optional file `'$site_path'/etc/All-Projects/project.config` provides
|
||||||
|
defaults for configuration read from
|
||||||
|
link:config-project-config.html[`project.config`] in the
|
||||||
|
`All-Projects` repo. Unlike `gerrit.config`, this file contains project-type
|
||||||
|
configuration rather than server-type configuration.
|
||||||
|
|
||||||
|
Most administrators will not need this file, and should instead make commits to
|
||||||
|
`All-Projects` to modify global config. However, a separate file can be useful
|
||||||
|
when managing multiple Gerrit servers, since pushing changes to defaults using
|
||||||
|
Puppet or a similar tool can be easier than scripting git updates to
|
||||||
|
`All-Projects`.
|
||||||
|
|
||||||
|
The contents of the file are loaded each time the `All-Projects` project is
|
||||||
|
reloaded. Updating the file requires either evicting the project cache or
|
||||||
|
restarting the server.
|
||||||
|
|
||||||
|
Caveats:
|
||||||
|
|
||||||
|
* The path from which the file is read corresponds to the name of the repo,
|
||||||
|
which is link:#gerrit.allProjects[configurable].
|
||||||
|
* Although the file lives in a directory that shares a name with a repository,
|
||||||
|
this directory is not a Git repository.
|
||||||
|
* Only the file `project.config` is read from this directory to provide
|
||||||
|
defaults; any other files in this directory, such as `rules.pl`, are ignored.
|
||||||
|
(This behavior may change in the future.)
|
||||||
|
* Group names listed in the access config in this file are resolved to UUIDs
|
||||||
|
using the `groups` file in the repository, not in the config directory. As a
|
||||||
|
result, setting ACLs in this file is not recommended.
|
||||||
|
|
||||||
[[secure.config]]
|
[[secure.config]]
|
||||||
== File `etc/secure.config`
|
== File `etc/secure.config`
|
||||||
|
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
package com.google.gerrit.pgm.init.api;
|
package com.google.gerrit.pgm.init.api;
|
||||||
|
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
import com.google.gerrit.common.Nullable;
|
||||||
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.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.config.SitePaths;
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.project.GroupList;
|
import com.google.gerrit.server.project.GroupList;
|
||||||
import com.google.gerrit.server.project.ProjectConfig;
|
import com.google.gerrit.server.project.ProjectConfig;
|
||||||
@ -27,16 +29,21 @@ import org.eclipse.jgit.lib.CommitBuilder;
|
|||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.RepositoryCache;
|
import org.eclipse.jgit.lib.RepositoryCache;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
|
|
||||||
public class AllProjectsConfig extends VersionedMetaDataOnInit {
|
public class AllProjectsConfig extends VersionedMetaDataOnInit {
|
||||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
|
@Nullable private final StoredConfig baseConfig;
|
||||||
private Config cfg;
|
private Config cfg;
|
||||||
private GroupList groupList;
|
private GroupList groupList;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AllProjectsConfig(AllProjectsNameOnInitProvider allProjects, SitePaths site, InitFlags flags) {
|
AllProjectsConfig(AllProjectsNameOnInitProvider allProjects, SitePaths site, InitFlags flags) {
|
||||||
super(flags, site, allProjects.get(), RefNames.REFS_CONFIG);
|
super(flags, site, allProjects.get(), RefNames.REFS_CONFIG);
|
||||||
|
this.baseConfig =
|
||||||
|
ProjectConfig.Factory.getBaseConfig(
|
||||||
|
site, new AllProjectsName(allProjects.get()), new Project.NameKey(allProjects.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Config getConfig() {
|
public Config getConfig() {
|
||||||
@ -55,8 +62,11 @@ public class AllProjectsConfig extends VersionedMetaDataOnInit {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLoad() throws IOException, ConfigInvalidException {
|
protected void onLoad() throws IOException, ConfigInvalidException {
|
||||||
|
if (baseConfig != null) {
|
||||||
|
baseConfig.load();
|
||||||
|
}
|
||||||
groupList = readGroupList();
|
groupList = readGroupList();
|
||||||
cfg = readConfig(ProjectConfig.PROJECT_CONFIG);
|
cfg = readConfig(ProjectConfig.PROJECT_CONFIG, baseConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupList readGroupList() throws IOException {
|
private GroupList readGroupList() throws IOException {
|
||||||
|
@ -462,7 +462,12 @@ public abstract class VersionedMetaData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Config readConfig(String fileName) throws IOException, ConfigInvalidException {
|
protected Config readConfig(String fileName) throws IOException, ConfigInvalidException {
|
||||||
Config rc = new Config();
|
return readConfig(fileName, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Config readConfig(String fileName, Config baseConfig)
|
||||||
|
throws IOException, ConfigInvalidException {
|
||||||
|
Config rc = new Config(baseConfig);
|
||||||
String text = readUTF8(fileName);
|
String text = readUTF8(fileName);
|
||||||
if (!text.isEmpty()) {
|
if (!text.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
|
@ -52,13 +52,16 @@ 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.account.GroupBackend;
|
import com.google.gerrit.server.account.GroupBackend;
|
||||||
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
|
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.config.ConfigUtil;
|
import com.google.gerrit.server.config.ConfigUtil;
|
||||||
import com.google.gerrit.server.config.PluginConfig;
|
import com.google.gerrit.server.config.PluginConfig;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.git.BranchOrderSection;
|
import com.google.gerrit.server.git.BranchOrderSection;
|
||||||
import com.google.gerrit.server.git.NotifyConfig;
|
import com.google.gerrit.server.git.NotifyConfig;
|
||||||
import com.google.gerrit.server.git.ValidationError;
|
import com.google.gerrit.server.git.ValidationError;
|
||||||
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
||||||
import com.google.gerrit.server.git.meta.VersionedMetaData;
|
import com.google.gerrit.server.git.meta.VersionedMetaData;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -83,8 +86,11 @@ import org.eclipse.jgit.lib.CommitBuilder;
|
|||||||
import org.eclipse.jgit.lib.Config;
|
import org.eclipse.jgit.lib.Config;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig;
|
||||||
import org.eclipse.jgit.transport.RefSpec;
|
import org.eclipse.jgit.transport.RefSpec;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
|
|
||||||
public class ProjectConfig extends VersionedMetaData implements ValidationError.Sink {
|
public class ProjectConfig extends VersionedMetaData implements ValidationError.Sink {
|
||||||
public static final String COMMENTLINK = "commentlink";
|
public static final String COMMENTLINK = "commentlink";
|
||||||
@ -173,8 +179,28 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
// ProjectCache, so this would retain lots more memory.
|
// ProjectCache, so this would retain lots more memory.
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class Factory {
|
public static class Factory {
|
||||||
|
@Nullable
|
||||||
|
public static StoredConfig getBaseConfig(
|
||||||
|
SitePaths sitePaths, AllProjectsName allProjects, Project.NameKey projectName) {
|
||||||
|
return projectName.equals(allProjects)
|
||||||
|
// Delay loading till onLoad method.
|
||||||
|
? new FileBasedConfig(
|
||||||
|
sitePaths.etc_dir.resolve(allProjects.get()).resolve(PROJECT_CONFIG).toFile(),
|
||||||
|
FS.DETECTED)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SitePaths sitePaths;
|
||||||
|
private final AllProjectsName allProjects;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Factory(SitePaths sitePaths, AllProjectsName allProjects) {
|
||||||
|
this.sitePaths = sitePaths;
|
||||||
|
this.allProjects = allProjects;
|
||||||
|
}
|
||||||
|
|
||||||
public ProjectConfig create(Project.NameKey projectName) {
|
public ProjectConfig create(Project.NameKey projectName) {
|
||||||
return new ProjectConfig(projectName);
|
return new ProjectConfig(projectName, getBaseConfig(sitePaths, allProjects, projectName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProjectConfig read(MetaDataUpdate update) throws IOException, ConfigInvalidException {
|
public ProjectConfig read(MetaDataUpdate update) throws IOException, ConfigInvalidException {
|
||||||
@ -191,6 +217,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final StoredConfig baseConfig;
|
||||||
|
|
||||||
private Project project;
|
private Project project;
|
||||||
private AccountsSection accountsSection;
|
private AccountsSection accountsSection;
|
||||||
private GroupList groupList;
|
private GroupList groupList;
|
||||||
@ -253,8 +281,9 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
commentLinkSections.add(commentLink);
|
commentLinkSections.add(commentLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProjectConfig(Project.NameKey projectName) {
|
private ProjectConfig(Project.NameKey projectName, @Nullable StoredConfig baseConfig) {
|
||||||
this.projectName = projectName;
|
this.projectName = projectName;
|
||||||
|
this.baseConfig = baseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(Repository repo) throws IOException, ConfigInvalidException {
|
public void load(Repository repo) throws IOException, ConfigInvalidException {
|
||||||
@ -516,11 +545,14 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLoad() throws IOException, ConfigInvalidException {
|
protected void onLoad() throws IOException, ConfigInvalidException {
|
||||||
|
if (baseConfig != null) {
|
||||||
|
baseConfig.load();
|
||||||
|
}
|
||||||
readGroupList();
|
readGroupList();
|
||||||
groupsByName = mapGroupReferences();
|
groupsByName = mapGroupReferences();
|
||||||
|
|
||||||
rulesId = getObjectId("rules.pl");
|
rulesId = getObjectId("rules.pl");
|
||||||
Config rc = readConfig(PROJECT_CONFIG);
|
Config rc = readConfig(PROJECT_CONFIG, baseConfig);
|
||||||
project = new Project(projectName);
|
project = new Project(projectName);
|
||||||
|
|
||||||
Project p = project;
|
Project p = project;
|
||||||
|
@ -17,12 +17,17 @@ package com.google.gerrit.server.schema;
|
|||||||
import static com.google.gerrit.server.project.ProjectConfig.ACCESS;
|
import static com.google.gerrit.server.project.ProjectConfig.ACCESS;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.gerrit.common.Nullable;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
||||||
import com.google.gerrit.server.git.meta.VersionedMetaData;
|
import com.google.gerrit.server.git.meta.VersionedMetaData;
|
||||||
import com.google.gerrit.server.project.ProjectConfig;
|
import com.google.gerrit.server.project.ProjectConfig;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -31,22 +36,38 @@ 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;
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
|
|
||||||
public class ProjectConfigSchemaUpdate extends VersionedMetaData {
|
public class ProjectConfigSchemaUpdate extends VersionedMetaData {
|
||||||
|
public static class Factory {
|
||||||
|
private final SitePaths sitePaths;
|
||||||
|
private final AllProjectsName allProjectsName;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Factory(SitePaths sitePaths, AllProjectsName allProjectsName) {
|
||||||
|
this.sitePaths = sitePaths;
|
||||||
|
this.allProjectsName = allProjectsName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectConfigSchemaUpdate read(MetaDataUpdate update)
|
||||||
|
throws IOException, ConfigInvalidException {
|
||||||
|
ProjectConfigSchemaUpdate r =
|
||||||
|
new ProjectConfigSchemaUpdate(
|
||||||
|
update,
|
||||||
|
ProjectConfig.Factory.getBaseConfig(sitePaths, allProjectsName, allProjectsName));
|
||||||
|
r.load(update);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final MetaDataUpdate update;
|
private final MetaDataUpdate update;
|
||||||
|
@Nullable private final StoredConfig baseConfig;
|
||||||
private Config config;
|
private Config config;
|
||||||
private boolean updated;
|
private boolean updated;
|
||||||
|
|
||||||
public static ProjectConfigSchemaUpdate read(MetaDataUpdate update)
|
private ProjectConfigSchemaUpdate(MetaDataUpdate update, @Nullable StoredConfig baseConfig) {
|
||||||
throws IOException, ConfigInvalidException {
|
|
||||||
ProjectConfigSchemaUpdate r = new ProjectConfigSchemaUpdate(update);
|
|
||||||
r.load(update);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ProjectConfigSchemaUpdate(MetaDataUpdate update) {
|
|
||||||
this.update = update;
|
this.update = update;
|
||||||
|
this.baseConfig = baseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -56,7 +77,15 @@ public class ProjectConfigSchemaUpdate extends VersionedMetaData {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLoad() throws IOException, ConfigInvalidException {
|
protected void onLoad() throws IOException, ConfigInvalidException {
|
||||||
config = readConfig(ProjectConfig.PROJECT_CONFIG);
|
if (baseConfig != null) {
|
||||||
|
baseConfig.load();
|
||||||
|
}
|
||||||
|
config = readConfig(ProjectConfig.PROJECT_CONFIG, baseConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
Config getConfig() {
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeForceFromPermission(String name) {
|
public void removeForceFromPermission(String name) {
|
||||||
|
@ -41,15 +41,18 @@ public class Schema_130 extends ReviewDbSchemaVersion {
|
|||||||
|
|
||||||
private final GitRepositoryManager repoManager;
|
private final GitRepositoryManager repoManager;
|
||||||
private final PersonIdent serverUser;
|
private final PersonIdent serverUser;
|
||||||
|
private final ProjectConfigSchemaUpdate.Factory projectConfigSchemaUpdateFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Schema_130(
|
Schema_130(
|
||||||
Provider<Schema_129> prior,
|
Provider<Schema_129> prior,
|
||||||
GitRepositoryManager repoManager,
|
GitRepositoryManager repoManager,
|
||||||
@GerritPersonIdent PersonIdent serverUser) {
|
@GerritPersonIdent PersonIdent serverUser,
|
||||||
|
ProjectConfigSchemaUpdate.Factory projectConfigSchemaUpdateFactory) {
|
||||||
super(prior);
|
super(prior);
|
||||||
this.repoManager = repoManager;
|
this.repoManager = repoManager;
|
||||||
this.serverUser = serverUser;
|
this.serverUser = serverUser;
|
||||||
|
this.projectConfigSchemaUpdateFactory = projectConfigSchemaUpdateFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,7 +63,7 @@ public class Schema_130 extends ReviewDbSchemaVersion {
|
|||||||
for (Project.NameKey projectName : repoList) {
|
for (Project.NameKey projectName : repoList) {
|
||||||
try (Repository git = repoManager.openRepository(projectName);
|
try (Repository git = repoManager.openRepository(projectName);
|
||||||
MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
|
MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
|
||||||
ProjectConfigSchemaUpdate cfg = ProjectConfigSchemaUpdate.read(md);
|
ProjectConfigSchemaUpdate cfg = projectConfigSchemaUpdateFactory.read(md);
|
||||||
cfg.removeForceFromPermission("pushTag");
|
cfg.removeForceFromPermission("pushTag");
|
||||||
if (cfg.isUpdated()) {
|
if (cfg.isUpdated()) {
|
||||||
repoUpgraded.add(projectName);
|
repoUpgraded.add(projectName);
|
||||||
|
@ -12,6 +12,7 @@ junit_tests(
|
|||||||
"//java/com/google/gerrit/pgm/init/api",
|
"//java/com/google/gerrit/pgm/init/api",
|
||||||
"//java/com/google/gerrit/server",
|
"//java/com/google/gerrit/server",
|
||||||
"//java/com/google/gerrit/server/securestore/testing",
|
"//java/com/google/gerrit/server/securestore/testing",
|
||||||
|
"//java/com/google/gerrit/testing:gerrit-test-util",
|
||||||
"//lib:guava",
|
"//lib:guava",
|
||||||
"//lib:junit",
|
"//lib:junit",
|
||||||
"//lib/easymock",
|
"//lib/easymock",
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.pgm.init.api;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.easymock.EasyMock.createStrictMock;
|
||||||
|
import static org.easymock.EasyMock.replay;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.securestore.testing.InMemorySecureStore;
|
||||||
|
import com.google.gerrit.testing.TempFileUtil;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||||
|
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class AllProjectsConfigTest {
|
||||||
|
private static final String ALL_PROJECTS = "All-The-Projects";
|
||||||
|
|
||||||
|
private SitePaths sitePaths;
|
||||||
|
private AllProjectsConfig allProjectsConfig;
|
||||||
|
private File allProjectsRepoFile;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
|
||||||
|
Files.createDirectories(sitePaths.etc_dir);
|
||||||
|
|
||||||
|
Path gitPath = sitePaths.resolve("git");
|
||||||
|
|
||||||
|
StoredConfig gerritConfig =
|
||||||
|
new FileBasedConfig(
|
||||||
|
sitePaths.resolve("etc").resolve("gerrit.config").toFile(), FS.DETECTED);
|
||||||
|
gerritConfig.load();
|
||||||
|
gerritConfig.setString("gerrit", null, "basePath", gitPath.toAbsolutePath().toString());
|
||||||
|
gerritConfig.setString("gerrit", null, "allProjects", ALL_PROJECTS);
|
||||||
|
gerritConfig.save();
|
||||||
|
|
||||||
|
Files.createDirectories(sitePaths.resolve("git"));
|
||||||
|
allProjectsRepoFile = gitPath.resolve("All-The-Projects.git").toFile();
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
repo.create(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
InMemorySecureStore secureStore = new InMemorySecureStore();
|
||||||
|
InitFlags flags = new InitFlags(sitePaths, secureStore, ImmutableList.of(), false);
|
||||||
|
ConsoleUI ui = createStrictMock(ConsoleUI.class);
|
||||||
|
replay(ui);
|
||||||
|
Section.Factory sections =
|
||||||
|
(name, subsection) -> new Section(flags, sitePaths, secureStore, ui, name, subsection);
|
||||||
|
allProjectsConfig =
|
||||||
|
new AllProjectsConfig(new AllProjectsNameOnInitProvider(sections), sitePaths, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
TempFileUtil.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noBaseConfig() throws Exception {
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isNull();
|
||||||
|
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
TestRepository<?> tr = new TestRepository<>(repo);
|
||||||
|
tr.branch("refs/meta/config").commit().add("project.config", "[foo]\nbar = baz").create();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void baseConfig() throws Exception {
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isNull();
|
||||||
|
|
||||||
|
Path baseConfigPath = sitePaths.etc_dir.resolve(ALL_PROJECTS).resolve("project.config");
|
||||||
|
Files.createDirectories(baseConfigPath.getParent());
|
||||||
|
Files.write(baseConfigPath, ImmutableList.of("[foo]", "bar = base"));
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("base");
|
||||||
|
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
TestRepository<?> tr = new TestRepository<>(repo);
|
||||||
|
tr.branch("refs/meta/config").commit().add("project.config", "[foo]\nbar = baz").create();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Config getConfig() throws IOException, ConfigInvalidException {
|
||||||
|
return allProjectsConfig.load().getConfig();
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,9 @@ package com.google.gerrit.server.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.gerrit.reviewdb.client.BooleanProjectConfig.REQUIRE_CHANGE_ID;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.gerrit.common.data.AccessSection;
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
import com.google.gerrit.common.data.ContributorAgreement;
|
import com.google.gerrit.common.data.ContributorAgreement;
|
||||||
@ -24,16 +26,22 @@ import com.google.gerrit.common.data.GroupReference;
|
|||||||
import com.google.gerrit.common.data.LabelType;
|
import com.google.gerrit.common.data.LabelType;
|
||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
|
import com.google.gerrit.extensions.client.InheritableBoolean;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
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.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.config.PluginConfig;
|
import com.google.gerrit.server.config.PluginConfig;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
import com.google.gerrit.server.git.ValidationError;
|
import com.google.gerrit.server.git.ValidationError;
|
||||||
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
||||||
import com.google.gerrit.server.project.testing.Util;
|
import com.google.gerrit.server.project.testing.Util;
|
||||||
import com.google.gerrit.testing.GerritBaseTests;
|
import com.google.gerrit.testing.GerritBaseTests;
|
||||||
|
import com.google.gerrit.testing.TempFileUtil;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -50,6 +58,7 @@ import org.eclipse.jgit.lib.Repository;
|
|||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
import org.eclipse.jgit.revwalk.RevObject;
|
import org.eclipse.jgit.revwalk.RevObject;
|
||||||
import org.eclipse.jgit.util.RawParseUtils;
|
import org.eclipse.jgit.util.RawParseUtils;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -74,21 +83,31 @@ public class ProjectConfigTest extends GerritBaseTests {
|
|||||||
+ !LabelType.DEF_COPY_ALL_SCORES_IF_NO_CHANGE
|
+ !LabelType.DEF_COPY_ALL_SCORES_IF_NO_CHANGE
|
||||||
+ "\n";
|
+ "\n";
|
||||||
|
|
||||||
|
private static final AllProjectsName ALL_PROJECTS = new AllProjectsName("All-The-Projects");
|
||||||
|
|
||||||
private final GroupReference developers =
|
private final GroupReference developers =
|
||||||
new GroupReference(new AccountGroup.UUID("X"), "Developers");
|
new GroupReference(new AccountGroup.UUID("X"), "Developers");
|
||||||
private final GroupReference staff = new GroupReference(new AccountGroup.UUID("Y"), "Staff");
|
private final GroupReference staff = new GroupReference(new AccountGroup.UUID("Y"), "Staff");
|
||||||
|
|
||||||
|
private SitePaths sitePaths;
|
||||||
private ProjectConfig.Factory factory;
|
private ProjectConfig.Factory factory;
|
||||||
private Repository db;
|
private Repository db;
|
||||||
private TestRepository<?> tr;
|
private TestRepository<?> tr;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
factory = new ProjectConfig.Factory();
|
sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
|
||||||
|
Files.createDirectories(sitePaths.etc_dir);
|
||||||
|
factory = new ProjectConfig.Factory(sitePaths, ALL_PROJECTS);
|
||||||
db = new InMemoryRepository(new DfsRepositoryDescription("repo"));
|
db = new InMemoryRepository(new DfsRepositoryDescription("repo"));
|
||||||
tr = new TestRepository<>(db);
|
tr = new TestRepository<>(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
TempFileUtil.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readConfig() throws Exception {
|
public void readConfig() throws Exception {
|
||||||
RevCommit rev =
|
RevCommit rev =
|
||||||
@ -593,6 +612,44 @@ public class ProjectConfigTest extends GerritBaseTests {
|
|||||||
+ "commentlink.bugzilla must have either link or html"));
|
+ "commentlink.bugzilla must have either link or html"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readAllProjectsBaseConfigFromSitePaths() throws Exception {
|
||||||
|
ProjectConfig cfg = factory.create(ALL_PROJECTS);
|
||||||
|
cfg.load(db);
|
||||||
|
assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
|
||||||
|
.isEqualTo(InheritableBoolean.INHERIT);
|
||||||
|
|
||||||
|
writeDefaultAllProjectsConfig("[receive]", "requireChangeId = false");
|
||||||
|
|
||||||
|
cfg.load(db);
|
||||||
|
assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
|
||||||
|
.isEqualTo(InheritableBoolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readOtherProjectIgnoresAllProjectsBaseConfig() throws Exception {
|
||||||
|
ProjectConfig cfg = factory.create(new Project.NameKey("test"));
|
||||||
|
cfg.load(db);
|
||||||
|
assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
|
||||||
|
.isEqualTo(InheritableBoolean.INHERIT);
|
||||||
|
|
||||||
|
writeDefaultAllProjectsConfig("[receive]", "requireChangeId = false");
|
||||||
|
|
||||||
|
cfg.load(db);
|
||||||
|
// If we went through ProjectState, then this would return FALSE, since project.config for
|
||||||
|
// All-Projects would inherit from all_projects.config, and this project would inherit from
|
||||||
|
// All-Projects. But in ProjectConfig itself, there is no inheritance from All-Projects, so this
|
||||||
|
// continues to return the default.
|
||||||
|
assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
|
||||||
|
.isEqualTo(InheritableBoolean.INHERIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path writeDefaultAllProjectsConfig(String... lines) throws IOException {
|
||||||
|
Path dir = sitePaths.etc_dir.resolve(ALL_PROJECTS.get());
|
||||||
|
Files.createDirectories(dir);
|
||||||
|
return Files.write(dir.resolve("project.config"), ImmutableList.copyOf(lines));
|
||||||
|
}
|
||||||
|
|
||||||
private ProjectConfig read(RevCommit rev) throws IOException, ConfigInvalidException {
|
private ProjectConfig read(RevCommit rev) throws IOException, ConfigInvalidException {
|
||||||
ProjectConfig cfg = factory.create(new Project.NameKey("test"));
|
ProjectConfig cfg = factory.create(new Project.NameKey("test"));
|
||||||
cfg.load(db, rev);
|
cfg.load(db, rev);
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.schema;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||||
|
import com.google.gerrit.server.git.meta.MetaDataUpdate;
|
||||||
|
import com.google.gerrit.testing.TempFileUtil;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||||
|
import org.eclipse.jgit.junit.TestRepository;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
|
import org.eclipse.jgit.storage.file.FileBasedConfig;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ProjectConfigSchemaUpdateTest {
|
||||||
|
private static final String ALL_PROJECTS = "All-The-Projects";
|
||||||
|
|
||||||
|
private SitePaths sitePaths;
|
||||||
|
private ProjectConfigSchemaUpdate.Factory factory;
|
||||||
|
private File allProjectsRepoFile;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
sitePaths = new SitePaths(TempFileUtil.createTempDirectory().toPath());
|
||||||
|
Files.createDirectories(sitePaths.etc_dir);
|
||||||
|
|
||||||
|
Path gitPath = sitePaths.resolve("git");
|
||||||
|
|
||||||
|
StoredConfig gerritConfig = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
|
||||||
|
gerritConfig.load();
|
||||||
|
gerritConfig.setString("gerrit", null, "basePath", gitPath.toAbsolutePath().toString());
|
||||||
|
gerritConfig.setString("gerrit", null, "allProjects", ALL_PROJECTS);
|
||||||
|
gerritConfig.save();
|
||||||
|
|
||||||
|
Files.createDirectories(sitePaths.resolve("git"));
|
||||||
|
allProjectsRepoFile = gitPath.resolve("All-The-Projects.git").toFile();
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
repo.create(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory = new ProjectConfigSchemaUpdate.Factory(sitePaths, new AllProjectsName(ALL_PROJECTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
TempFileUtil.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noBaseConfig() throws Exception {
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isNull();
|
||||||
|
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
TestRepository<?> tr = new TestRepository<>(repo);
|
||||||
|
tr.branch("refs/meta/config").commit().add("project.config", "[foo]\nbar = baz").create();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void baseConfig() throws Exception {
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isNull();
|
||||||
|
|
||||||
|
Path baseConfigPath = sitePaths.etc_dir.resolve(ALL_PROJECTS).resolve("project.config");
|
||||||
|
Files.createDirectories(baseConfigPath.getParent());
|
||||||
|
Files.write(baseConfigPath, ImmutableList.of("[foo]", "bar = base"));
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("base");
|
||||||
|
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
TestRepository<?> tr = new TestRepository<>(repo);
|
||||||
|
tr.branch("refs/meta/config").commit().add("project.config", "[foo]\nbar = baz").create();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(getConfig().getString("foo", null, "bar")).isEqualTo("baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Config getConfig() throws Exception {
|
||||||
|
try (Repository repo = new FileRepository(allProjectsRepoFile)) {
|
||||||
|
return factory
|
||||||
|
.read(
|
||||||
|
new MetaDataUpdate(
|
||||||
|
GitReferenceUpdated.DISABLED, new Project.NameKey(ALL_PROJECTS), repo, null))
|
||||||
|
.getConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user