204 lines
8.0 KiB
Java
204 lines
8.0 KiB
Java
// Copyright (C) 2016 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.acceptance.rest.change;
|
|
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
|
|
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;
|
|
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
|
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;
|
|
import org.eclipse.jgit.revwalk.RevTree;
|
|
import org.eclipse.jgit.revwalk.RevWalk;
|
|
import org.eclipse.jgit.transport.RefSpec;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
|
|
public class ConfigChangeIT extends AbstractDaemonTest {
|
|
@Before
|
|
public void setUp() throws Exception {
|
|
ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
|
|
Util.allow(cfg, Permission.OWNER, REGISTERED_USERS, "refs/*");
|
|
Util.allow(cfg, Permission.PUSH, REGISTERED_USERS, "refs/for/refs/meta/config");
|
|
Util.allow(cfg, Permission.SUBMIT, REGISTERED_USERS, RefNames.REFS_CONFIG);
|
|
saveProjectConfig(project, cfg);
|
|
|
|
setApiUser(user);
|
|
fetchRefsMetaConfig();
|
|
}
|
|
|
|
@Test
|
|
@TestProjectInput(cloneAs = "user")
|
|
public void updateProjectConfig() throws Exception {
|
|
String id = testUpdateProjectConfig();
|
|
assertThat(gApi.changes().id(id).get().revisions).hasSize(1);
|
|
}
|
|
|
|
@Test
|
|
@TestProjectInput(cloneAs = "user", submitType = SubmitType.CHERRY_PICK)
|
|
public void updateProjectConfigWithCherryPick() throws Exception {
|
|
String id = testUpdateProjectConfig();
|
|
assertThat(gApi.changes().id(id).get().revisions).hasSize(2);
|
|
}
|
|
|
|
private String testUpdateProjectConfig() throws Exception {
|
|
Config cfg = readProjectConfig();
|
|
assertThat(cfg.getString("project", null, "description")).isNull();
|
|
String desc = "new project description";
|
|
cfg.setString("project", null, "description", desc);
|
|
|
|
PushOneCommit.Result r = createConfigChange(cfg);
|
|
String id = r.getChangeId();
|
|
|
|
gApi.changes().id(id).current().review(ReviewInput.approve());
|
|
gApi.changes().id(id).current().submit();
|
|
|
|
assertThat(gApi.changes().id(id).info().status).isEqualTo(ChangeStatus.MERGED);
|
|
assertThat(gApi.projects().name(project.get()).get().description).isEqualTo(desc);
|
|
fetchRefsMetaConfig();
|
|
assertThat(readProjectConfig().getString("project", null, "description")).isEqualTo(desc);
|
|
String changeRev = gApi.changes().id(id).get().currentRevision;
|
|
String branchRev =
|
|
gApi.projects().name(project.get()).branch(RefNames.REFS_CONFIG).get().revision;
|
|
assertThat(changeRev).isEqualTo(branchRev);
|
|
return id;
|
|
}
|
|
|
|
@Test
|
|
@TestProjectInput(cloneAs = "user")
|
|
public void onlyAdminMayUpdateProjectParent() throws Exception {
|
|
setApiUser(admin);
|
|
ProjectInput parent = new ProjectInput();
|
|
parent.name = name("parent");
|
|
parent.permissionsOnly = true;
|
|
gApi.projects().create(parent);
|
|
|
|
setApiUser(user);
|
|
Config cfg = readProjectConfig();
|
|
assertThat(cfg.getString("access", null, "inheritFrom")).isAnyOf(null, allProjects.get());
|
|
cfg.setString("access", null, "inheritFrom", parent.name);
|
|
|
|
PushOneCommit.Result r = createConfigChange(cfg);
|
|
String id = r.getChangeId();
|
|
|
|
gApi.changes().id(id).current().review(ReviewInput.approve());
|
|
try {
|
|
gApi.changes().id(id).current().submit();
|
|
fail("expected submit to fail");
|
|
} catch (ResourceConflictException e) {
|
|
int n = gApi.changes().id(id).info()._number;
|
|
assertThat(e)
|
|
.hasMessage(
|
|
"Failed to submit 1 change due to the following problems:\n"
|
|
+ "Change "
|
|
+ n
|
|
+ ": Change contains a project configuration that"
|
|
+ " changes the parent project.\n"
|
|
+ "The change must be submitted by a Gerrit administrator.");
|
|
}
|
|
|
|
assertThat(gApi.projects().name(project.get()).get().parent).isEqualTo(allProjects.get());
|
|
fetchRefsMetaConfig();
|
|
assertThat(readProjectConfig().getString("access", null, "inheritFrom"))
|
|
.isAnyOf(null, allProjects.get());
|
|
|
|
setApiUser(admin);
|
|
gApi.changes().id(id).current().submit();
|
|
assertThat(gApi.changes().id(id).info().status).isEqualTo(ChangeStatus.MERGED);
|
|
assertThat(gApi.projects().name(project.get()).get().parent).isEqualTo(parent.name);
|
|
fetchRefsMetaConfig();
|
|
assertThat(readProjectConfig().getString("access", null, "inheritFrom")).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();
|
|
testRepo.reset(RefNames.REFS_CONFIG);
|
|
}
|
|
|
|
private Config readProjectConfig() throws Exception {
|
|
RevWalk rw = testRepo.getRevWalk();
|
|
RevTree tree = rw.parseTree(testRepo.getRepository().resolve("HEAD"));
|
|
RevObject obj = rw.parseAny(testRepo.get(tree, "project.config"));
|
|
ObjectLoader loader = rw.getObjectReader().open(obj);
|
|
String text = new String(loader.getCachedBytes(), UTF_8);
|
|
Config cfg = new Config();
|
|
cfg.fromText(text);
|
|
return cfg;
|
|
}
|
|
|
|
private PushOneCommit.Result createConfigChange(Config cfg) throws Exception {
|
|
PushOneCommit.Result r =
|
|
pushFactory
|
|
.create(
|
|
db,
|
|
user.getIdent(),
|
|
testRepo,
|
|
"Update project config",
|
|
"project.config",
|
|
cfg.toText())
|
|
.to("refs/for/refs/meta/config");
|
|
r.assertOkStatus();
|
|
return r;
|
|
}
|
|
}
|