Prevent inheriting from multiple projects

Adding more than one project to inherit from manually in project.config
will silently ignore all but the last value, which is likely not what
the user expects. Reject the config instead.

Change-Id: I8139746a31e1ba78a88c54ed486920acf5544c1d
This commit is contained in:
Patrick Hiesel 2016-07-13 11:43:22 +02:00 committed by Dave Borowitz
parent a16f8a3973
commit 69e27a3c5c
2 changed files with 41 additions and 0 deletions

View File

@ -20,6 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.fail;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.common.data.Permission;
@ -28,10 +29,13 @@ import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.project.Util;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.revwalk.RevObject;
@ -143,6 +147,36 @@ public class ConfigChangeIT extends AbstractDaemonTest {
.isEqualTo(parent.name);
}
@Test
public void rejectDoubleInheritance() throws Exception {
setApiUser(admin);
// Create separate projects to test the config
Project.NameKey parent = createProject("projectToInheritFrom");
Project.NameKey child = createProject("projectWithMalformedConfig");
String config = gApi.projects()
.name(child.get())
.branch(RefNames.REFS_CONFIG).file("project.config").asString();
// Append and push malformed project config
String pattern = "[access]\n"
+ "\tinheritFrom = " + allProjects.get() + "\n";
String doubleInherit = pattern + "\tinheritFrom = " + parent.get() + "\n";
config = config.replace(pattern, doubleInherit);
TestRepository<InMemoryRepository> childRepo =
cloneProject(child, admin);
// Fetch meta ref
GitUtil.fetch(childRepo, RefNames.REFS_CONFIG + ":cfg");
childRepo.reset("cfg");
PushOneCommit push = pushFactory.create(
db, admin.getIdent(), childRepo, "Subject", "project.config",
config);
PushOneCommit.Result res = push.to(RefNames.REFS_CONFIG);
res.assertErrorStatus();
res.assertMessage("cannot inherit from multiple projects");
}
private void fetchRefsMetaConfig() throws Exception {
git().fetch().setRefSpecs(new RefSpec("refs/meta/config:refs/meta/config"))
.call();

View File

@ -479,6 +479,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
if (p.getDescription() == null) {
p.setDescription("");
}
if (rc.getStringList(ACCESS, null, KEY_INHERIT_FROM).length > 1) {
// The config must not contain more than one parent to inherit from
// as there is no guarantee which of the parents would be used then.
error(new ValidationError(PROJECT_CONFIG,
"Cannot inherit from multiple projects"));
}
p.setParentName(rc.getString(ACCESS, null, KEY_INHERIT_FROM));
p.setUseContributorAgreements(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, InheritableBoolean.INHERIT));