diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java index 1fb9bb53a7..bbf7484eeb 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java @@ -80,8 +80,18 @@ public class GitUtil { public static void createProject(SshSession s, String name, Project.NameKey parent) throws JSchException, IOException { + createProject(s, name, parent, true); + } + + public static void createProject(SshSession s, String name, + Project.NameKey parent, boolean emptyCommit) + throws JSchException, IOException { StringBuilder b = new StringBuilder(); - b.append("gerrit create-project --empty-commit --name \""); + b.append("gerrit create-project"); + if (emptyCommit) { + b.append(" --empty-commit"); + } + b.append(" --name \""); b.append(name); b.append("\""); if (parent != null) { diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchAssert.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchAssert.java new file mode 100644 index 0000000000..654ef65974 --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchAssert.java @@ -0,0 +1,62 @@ +// Copyright (C) 2013 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.project; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +import java.util.List; + +public class BranchAssert { + + public static void assertBranches(List expectedBranches, + List actualBranches) { + List missingBranches = Lists.newArrayList(actualBranches); + for (final BranchInfo b : expectedBranches) { + BranchInfo info = + Iterables.find(actualBranches, new Predicate() { + @Override + public boolean apply(BranchInfo info) { + return info.ref.equals(b.ref); + } + }, null); + assertNotNull("missing branch: " + b.ref, info); + assertBranchInfo(b, info); + missingBranches.remove(info); + } + assertTrue("unexpected branches: " + missingBranches, + missingBranches.isEmpty()); + } + + public static void assertBranchInfo(BranchInfo expected, BranchInfo actual) { + assertEquals(expected.ref, actual.ref); + if (expected.revision != null) { + assertEquals(expected.revision, actual.revision); + } + assertEquals(expected.can_delete, toBoolean(actual.can_delete)); + } + + private static boolean toBoolean(Boolean b) { + if (b == null) { + return false; + } + return b.booleanValue(); + } +} diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchInfo.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchInfo.java new file mode 100644 index 0000000000..2b7933e23f --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/BranchInfo.java @@ -0,0 +1,35 @@ +// Copyright (C) 2013 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.project; + +public class BranchInfo { + public String ref; + public String revision; + public Boolean can_delete; + + public BranchInfo() { + } + + public BranchInfo(String ref, String revision, boolean canDelete) { + this.ref = ref; + this.revision = revision; + this.can_delete = canDelete; + } + + @Override + public String toString() { + return ref; + } +} diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java new file mode 100644 index 0000000000..3fee3d3ada --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java @@ -0,0 +1,227 @@ +// Copyright (C) 2013 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.project; + +import static com.google.gerrit.acceptance.git.GitUtil.cloneProject; +import static com.google.gerrit.acceptance.git.GitUtil.createProject; +import static com.google.gerrit.acceptance.git.GitUtil.initSsh; +import static com.google.gerrit.acceptance.rest.project.BranchAssert.assertBranches; +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.Lists; +import com.google.gerrit.acceptance.AbstractDaemonTest; +import com.google.gerrit.acceptance.AccountCreator; +import com.google.gerrit.acceptance.RestResponse; +import com.google.gerrit.acceptance.RestSession; +import com.google.gerrit.acceptance.SshSession; +import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.acceptance.git.PushOneCommit; +import com.google.gerrit.common.data.AccessSection; +import com.google.gerrit.common.data.Permission; +import com.google.gerrit.common.data.PermissionRule; +import com.google.gerrit.reviewdb.client.AccountGroup; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.account.GroupCache; +import com.google.gerrit.server.git.MetaDataUpdate; +import com.google.gerrit.server.git.ProjectConfig; +import com.google.gerrit.server.project.ProjectCache; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.gwtorm.server.OrmException; +import com.google.gwtorm.server.SchemaFactory; +import com.google.inject.Inject; + +import com.jcraft.jsch.JSchException; + +import org.apache.http.HttpStatus; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class ListBranchesIT extends AbstractDaemonTest { + + @Inject + private AccountCreator accounts; + + @Inject + private MetaDataUpdate.Server metaDataUpdateFactory; + + @Inject + private ProjectCache projectCache; + + @Inject + private GroupCache groupCache; + + @Inject + private SchemaFactory reviewDbProvider; + + private TestAccount admin; + private RestSession session; + private SshSession sshSession; + private Project.NameKey project; + private Git git; + private ReviewDb db; + + @Before + public void setUp() throws Exception { + admin = accounts.create("admin", "admin@example.com", "Administrator", + "Administrators"); + session = new RestSession(admin); + + project = new Project.NameKey("p"); + initSsh(admin); + sshSession = new SshSession(admin); + createProject(sshSession, project.get()); + git = cloneProject(sshSession.getUrl() + "/" + project.get()); + db = reviewDbProvider.open(); + } + + @After + public void cleanup() { + db.close(); + } + + @Test + public void listBranchesOfNonExistingProject_NotFound() throws IOException { + assertEquals(HttpStatus.SC_NOT_FOUND, + GET("/projects/non-existing/branches").getStatusCode()); + } + + @Test + public void listBranchesOfNonVisibleProject_NotFound() throws IOException, + OrmException, JSchException, ConfigInvalidException { + blockRead(project, "refs/*"); + RestSession session = + new RestSession(accounts.create("user", "user@example.com", "User")); + assertEquals(HttpStatus.SC_NOT_FOUND, + session.get("/projects/" + project.get() + "/branches").getStatusCode()); + } + + @Test + public void listBranchesOfEmptyProject() throws IOException, JSchException { + Project.NameKey emptyProject = new Project.NameKey("empty"); + createProject(sshSession, emptyProject.get(), null, false); + RestResponse r = session.get("/projects/" + emptyProject.get() + "/branches"); + List result = + (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + List expected = Lists.asList( + new BranchInfo("refs/meta/config", null, false), + new BranchInfo[] { + new BranchInfo("HEAD", null, false) + }); + assertBranches(expected, result); + } + + @Test + public void listBranches() throws IOException, GitAPIException { + pushTo("refs/heads/master"); + String masterCommit = git.getRepository().getRef("master").getTarget().getObjectId().getName(); + pushTo("refs/heads/dev"); + String devCommit = git.getRepository().getRef("master").getTarget().getObjectId().getName(); + RestResponse r = session.get("/projects/" + project.get() + "/branches"); + List result = + (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + List expected = Lists.asList( + new BranchInfo("refs/meta/config", null, false), + new BranchInfo[] { + new BranchInfo("HEAD", "master", false), + new BranchInfo("refs/heads/master", masterCommit, false), + new BranchInfo("refs/heads/dev", devCommit, true) + }); + assertBranches(expected, result); + + // verify correct sorting + assertEquals("HEAD", result.get(0).ref); + assertEquals("refs/meta/config", result.get(1).ref); + assertEquals("refs/heads/dev", result.get(2).ref); + assertEquals("refs/heads/master", result.get(3).ref); + } + + @Test + public void listBranchesSomeHidden() throws IOException, GitAPIException, + ConfigInvalidException, OrmException, JSchException { + blockRead(project, "refs/heads/dev"); + RestSession session = + new RestSession(accounts.create("user", "user@example.com", "User")); + pushTo("refs/heads/master"); + String masterCommit = git.getRepository().getRef("master").getTarget().getObjectId().getName(); + pushTo("refs/heads/dev"); + RestResponse r = session.get("/projects/" + project.get() + "/branches"); + List result = + (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + // refs/meta/config is hidden since user is no project owner + List expected = Lists.asList( + new BranchInfo("HEAD", "master", false), + new BranchInfo[] { + new BranchInfo("refs/heads/master", masterCommit, false), + }); + assertBranches(expected, result); + } + + @Test + public void listBranchesHeadHidden() throws IOException, GitAPIException, + ConfigInvalidException, OrmException, JSchException { + blockRead(project, "refs/heads/master"); + RestSession session = + new RestSession(accounts.create("user", "user@example.com", "User")); + pushTo("refs/heads/master"); + pushTo("refs/heads/dev"); + String devCommit = git.getRepository().getRef("master").getTarget().getObjectId().getName(); + RestResponse r = session.get("/projects/" + project.get() + "/branches"); + List result = + (new Gson()).fromJson(r.getReader(), + new TypeToken>() {}.getType()); + // refs/meta/config is hidden since user is no project owner + assertBranches(Collections.singletonList(new BranchInfo("refs/heads/dev", + devCommit, false)), result); + } + + private RestResponse GET(String endpoint) throws IOException { + return session.get(endpoint); + } + + private void blockRead(Project.NameKey project, String ref) + throws RepositoryNotFoundException, IOException, ConfigInvalidException { + MetaDataUpdate md = metaDataUpdateFactory.create(project); + md.setMessage("Grant submit on " + ref); + ProjectConfig config = ProjectConfig.read(md); + AccessSection s = config.getAccessSection(ref, true); + Permission p = s.getPermission(Permission.READ, true); + AccountGroup adminGroup = groupCache.get(AccountGroup.REGISTERED_USERS); + PermissionRule rule = new PermissionRule(config.resolve(adminGroup)); + rule.setBlock(); + p.add(rule); + config.commit(md); + projectCache.evict(config.getProject()); + } + + private PushOneCommit.Result pushTo(String ref) throws GitAPIException, + IOException { + PushOneCommit push = new PushOneCommit(db, admin.getIdent()); + return push.to(git, ref); + } +} diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AddBranchResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AddBranchResult.java deleted file mode 100644 index 24e527dce8..0000000000 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AddBranchResult.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2012 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.common.data; - -public class AddBranchResult { - protected ListBranchesResult listBranchesResult; - protected Error error; - - protected AddBranchResult() { - } - - public AddBranchResult(final Error error) { - this.error = error; - } - - public AddBranchResult(final ListBranchesResult listBranchesResult) { - this.listBranchesResult = listBranchesResult; - } - - public ListBranchesResult getListBranchesResult() { - return listBranchesResult; - } - - public boolean hasError() { - return error != null; - } - - public Error getError() { - return error; - } - - public static class Error { - public static enum Type { - /** The branch cannot be created because the given branch name is invalid. */ - INVALID_NAME, - - /** The branch cannot be created because the given revision is invalid. */ - INVALID_REVISION, - - /** - * The branch cannot be created under the given refname prefix (e.g - * branches cannot be created under magic refname prefixes). - */ - BRANCH_CREATION_NOT_ALLOWED_UNDER_REFNAME_PREFIX, - - /** The branch that should be created exists already. */ - BRANCH_ALREADY_EXISTS, - - /** - * The branch cannot be created because it conflicts with an existing - * branch (branches cannot be nested). - */ - BRANCH_CREATION_CONFLICT - } - - protected Type type; - protected String refname; - - protected Error() { - } - - public Error(final Type type) { - this(type, null); - } - - public Error(final Type type, final String refname) { - this.type = type; - this.refname = refname; - } - - public Type getType() { - return type; - } - - public String getRefname() { - return refname; - } - - @Override - public String toString() { - return type + " " + refname; - } - } -} diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java deleted file mode 100644 index 1c830e9a87..0000000000 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2010 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.common.data; - -import com.google.gerrit.reviewdb.client.Branch; - -import java.util.List; - -/** - * It holds list of branches and boolean to indicate if it is allowed to add new - * branches. - */ -public final class ListBranchesResult { - protected boolean noRepository; - protected boolean canAdd; - protected List branches; - - protected ListBranchesResult() { - } - - public ListBranchesResult(List branches, boolean canAdd, - boolean noRepository) { - this.branches = branches; - this.canAdd = canAdd; - this.noRepository = noRepository; - } - - public boolean getNoRepository() { - return noRepository; - } - - public boolean getCanAdd() { - return canAdd; - } - - public List getBranches() { - return branches; - } -} diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java deleted file mode 100644 index 7330337a08..0000000000 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2009 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.httpd.rpc.project; - -import com.google.common.base.Objects; -import com.google.common.collect.Lists; -import com.google.gerrit.common.data.ListBranchesResult; -import com.google.gerrit.extensions.restapi.ResourceNotFoundException; -import com.google.gerrit.httpd.rpc.Handler; -import com.google.gerrit.reviewdb.client.Branch; -import com.google.gerrit.reviewdb.client.Project; -import com.google.gerrit.reviewdb.client.RevId; -import com.google.gerrit.server.project.ListBranches.BranchInfo; -import com.google.gerrit.server.project.NoSuchProjectException; -import com.google.gerrit.server.project.ProjectControl; -import com.google.gerrit.server.project.ProjectResource; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.assistedinject.Assisted; - -import java.io.IOException; -import java.util.List; - -class ListBranches extends Handler { - interface Factory { - ListBranches create(@Assisted Project.NameKey name); - } - - private final ProjectControl.Factory projectControlFactory; - private final Provider listBranchesProvider; - - private final Project.NameKey projectName; - - @Inject - ListBranches(final ProjectControl.Factory projectControlFactory, - final Provider listBranchesProvider, - @Assisted final Project.NameKey name) { - this.projectControlFactory = projectControlFactory; - this.listBranchesProvider = listBranchesProvider; - - this.projectName = name; - } - - @Override - public ListBranchesResult call() throws NoSuchProjectException, IOException { - ProjectControl pctl = - projectControlFactory.validateFor(projectName, ProjectControl.OWNER - | ProjectControl.VISIBLE); - try { - List branches = Lists.newArrayList(); - List branchInfos = listBranchesProvider.get().apply(new ProjectResource(pctl)); - for (BranchInfo info : branchInfos) { - Branch b = new Branch(new Branch.NameKey(projectName, info.ref)); - b.setRevision(new RevId(info.revision)); - b.setCanDelete(Objects.firstNonNull(info.canDelete, false)); - branches.add(b); - } - return new ListBranchesResult(branches, pctl.canAddRefs(), false); - } catch (ResourceNotFoundException e) { - throw new NoSuchProjectException(projectName); - } - } -} diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java index f063e1e6cb..abea6f4f80 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java @@ -31,7 +31,6 @@ public class ProjectModule extends RpcServletModule { factory(ChangeProjectAccess.Factory.class); factory(ReviewProjectAccess.Factory.class); factory(ChangeProjectSettings.Factory.class); - factory(ListBranches.Factory.class); factory(VisibleProjectDetails.Factory.class); factory(ProjectAccessFactory.Factory.class); factory(ProjectDetailFactory.Factory.class); diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java deleted file mode 100644 index 7265470dfb..0000000000 --- a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (C) 2009 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.httpd.rpc.project; - -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.eclipse.jgit.lib.Constants.HEAD; -import static org.eclipse.jgit.lib.Constants.R_HEADS; -import static org.eclipse.jgit.lib.Ref.Storage.LOOSE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.google.gerrit.common.data.ListBranchesResult; -import com.google.gerrit.reviewdb.client.Branch; -import com.google.gerrit.reviewdb.client.Project; -import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.project.NoSuchProjectException; -import com.google.gerrit.server.project.ProjectControl; -import com.google.gerrit.server.project.RefControl; -import com.google.gwtorm.client.KeyUtil; -import com.google.gwtorm.server.StandardKeyEncoder; -import com.google.inject.Provider; - -import org.easymock.IExpectationSetters; -import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; -import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.ObjectIdRef; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.RefUpdate; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.SymbolicRef; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class ListBranchesTest extends LocalDiskRepositoryTestCase { - static { - KeyUtil.setEncoderImpl(new StandardKeyEncoder()); - } - - private ObjectId idA; - private Project.NameKey name; - private Repository realDb; - private Repository mockDb; - private ProjectControl.Factory pcf; - private ProjectControl pc; - private GitRepositoryManager grm; - private List refMocks; - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - - idA = ObjectId.fromString("df84c2f4f7ce7e0b25cdeac84b8870bcff319885"); - name = new Project.NameKey("test"); - realDb = createBareRepository(); - - mockDb = createStrictMock(Repository.class); - pc = createStrictMock(ProjectControl.class); - expect(pc.getProject()).andReturn(new Project(name)).anyTimes(); - pcf = createStrictMock(ProjectControl.Factory.class); - grm = createStrictMock(GitRepositoryManager.class); - refMocks = new ArrayList(); - } - - private IExpectationSetters validate() - throws NoSuchProjectException { - return expect(pcf.validateFor(eq(name), // - eq(ProjectControl.OWNER | ProjectControl.VISIBLE))); - } - - private void doReplay() { - replay(mockDb, pc, pcf, grm); - replay(refMocks.toArray()); - } - - private void doVerify() { - verify(mockDb, pc, pcf, grm); - verify(refMocks.toArray()); - } - - private void set(String branch, ObjectId id) throws IOException { - final RefUpdate u = realDb.updateRef(R_HEADS + branch); - u.setForceUpdate(true); - u.setNewObjectId(id); - switch (u.update()) { - case NEW: - case FAST_FORWARD: - case FORCED: - break; - default: - fail("unexpected update failure " + branch + " " + u.getResult()); - } - } - - @Test - public void testProjectNotVisible() throws Exception { - final NoSuchProjectException err = new NoSuchProjectException(name); - validate().andThrow(err); - doReplay(); - try { - new ListBranches(pcf, createListBranchesProvider(grm), name).call(); - fail("did not throw when expected not authorized"); - } catch (NoSuchProjectException e2) { - assertSame(err, e2); - } - doVerify(); - } - - - private ListBranchesResult permitted(boolean getHead) - throws NoSuchProjectException, IOException { - Map refs = realDb.getAllRefs(); - - validate().andReturn(pc); - - expect(grm.openRepository(eq(name))).andReturn(mockDb); - expect(mockDb.getAllRefs()).andDelegateTo(realDb); - if (getHead) { - expect(mockDb.getRef(HEAD)).andDelegateTo(realDb); - if (!refs.containsKey(HEAD) && realDb.getRef(HEAD) != null) { - refs.put(HEAD, realDb.getRef(HEAD)); - } - } - - Set targets = targets(refs); - for (Ref ref : refs.values()) { - assumeVisible(ref, true, targets); - } - - mockDb.close(); - - expect(pc.canAddRefs()).andReturn(true); - - expectLastCall(); - - doReplay(); - final ListBranchesResult r = - new ListBranches(pcf, createListBranchesProvider(grm), name).call(); - doVerify(); - assertNotNull(r); - assertNotNull(r.getBranches()); - return r; - } - - private Set targets(Map refs) { - Set targets = new HashSet(); - for (Ref ref : refs.values()) { - if (ref.isSymbolic()) { - targets.add(ref.getLeaf().getName()); - } - } - return targets; - } - - private void assumeVisible(Ref ref, boolean visible, Set targets) { - RefControl rc = createStrictMock(RefControl.class); - refMocks.add(rc); - expect(rc.isVisible()).andReturn(visible); - if (visible && !ref.isSymbolic() && !targets.contains(ref.getName())) { - expect(rc.canDelete()).andReturn(true); - } - - if (ref.isSymbolic()) { - expect(pc.controlForRef(ref.getTarget().getName())).andReturn(rc); - } else { - expect(pc.controlForRef(ref.getName())).andReturn(rc); - } - } - - @Test - public void testEmptyProject() throws Exception { - ListBranchesResult r = permitted(true); - - assertEquals(1, r.getBranches().size()); - - Branch b = r.getBranches().get(0); - assertNotNull(b); - - assertNotNull(b.getNameKey()); - assertSame(name, b.getNameKey().getParentKey()); - assertEquals(HEAD, b.getNameKey().get()); - - assertEquals(HEAD, b.getName()); - assertEquals(HEAD, b.getShortName()); - - assertNotNull(b.getRevision()); - assertEquals("master", b.getRevision().get()); - } - - @Test - public void testMasterBranch() throws Exception { - set("master", idA); - - ListBranchesResult r = permitted(false); - assertEquals(2, r.getBranches().size()); - - Branch b = r.getBranches().get(0); - assertNotNull(b); - - assertNotNull(b.getNameKey()); - assertSame(name, b.getNameKey().getParentKey()); - assertEquals(HEAD, b.getNameKey().get()); - - assertEquals(HEAD, b.getName()); - assertEquals(HEAD, b.getShortName()); - - assertNotNull(b.getRevision()); - assertEquals("master", b.getRevision().get()); - - b = r.getBranches().get(1); - assertNotNull(b); - - assertNotNull(b.getNameKey()); - assertSame(name, b.getNameKey().getParentKey()); - assertEquals(R_HEADS + "master", b.getNameKey().get()); - - assertEquals(R_HEADS + "master", b.getName()); - assertEquals("master", b.getShortName()); - - assertNotNull(b.getRevision()); - assertEquals(idA.name(), b.getRevision().get()); - } - - @Test - public void testBranchNotHead() throws Exception { - set("foo", idA); - - ListBranchesResult r = permitted(true); - assertEquals(2, r.getBranches().size()); - - Branch b = r.getBranches().get(0); - assertNotNull(b); - - assertNotNull(b.getNameKey()); - assertSame(name, b.getNameKey().getParentKey()); - assertEquals(HEAD, b.getNameKey().get()); - - assertEquals(HEAD, b.getName()); - assertEquals(HEAD, b.getShortName()); - - assertNotNull(b.getRevision()); - assertEquals("master", b.getRevision().get()); - assertFalse(b.getCanDelete()); - - b = r.getBranches().get(1); - assertNotNull(b); - - assertNotNull(b.getNameKey()); - assertSame(name, b.getNameKey().getParentKey()); - assertEquals(R_HEADS + "foo", b.getNameKey().get()); - - assertEquals(R_HEADS + "foo", b.getName()); - assertEquals("foo", b.getShortName()); - - assertNotNull(b.getRevision()); - assertEquals(idA.name(), b.getRevision().get()); - assertTrue(b.getCanDelete()); - } - - @Test - public void testSortByName() throws Exception { - Map u = new LinkedHashMap(); - u.put("foo", new ObjectIdRef.Unpeeled(LOOSE, R_HEADS + "foo", idA)); - u.put("bar", new ObjectIdRef.Unpeeled(LOOSE, R_HEADS + "bar", idA)); - u.put(HEAD, new SymbolicRef(HEAD, new ObjectIdRef.Unpeeled(LOOSE, R_HEADS - + "master", null))); - - validate().andReturn(pc); - expect(grm.openRepository(eq(name))).andReturn(mockDb); - expect(mockDb.getAllRefs()).andReturn(u); - for (Ref ref : u.values()) { - assumeVisible(ref, true, targets(u)); - } - expect(pc.canAddRefs()).andReturn(true); - mockDb.close(); - expectLastCall(); - - doReplay(); - final ListBranchesResult r = - new ListBranches(pcf, createListBranchesProvider(grm), name).call(); - doVerify(); - assertNotNull(r); - - assertEquals(3, r.getBranches().size()); - assertEquals(HEAD, r.getBranches().get(0).getShortName()); - assertEquals("bar", r.getBranches().get(1).getShortName()); - assertEquals("foo", r.getBranches().get(2).getShortName()); - } - - @Test - public void testHeadNotVisible() throws Exception { - ObjectIdRef.Unpeeled bar = - new ObjectIdRef.Unpeeled(LOOSE, R_HEADS + "bar", idA); - Map u = new LinkedHashMap(); - u.put(bar.getName(), bar); - u.put(HEAD, new SymbolicRef(HEAD, bar)); - - validate().andReturn(pc); - expect(grm.openRepository(eq(name))).andReturn(mockDb); - expect(mockDb.getAllRefs()).andReturn(u); - assumeVisible(bar, false, targets(u)); - assumeVisible(bar, false, targets(u)); - expect(pc.canAddRefs()).andReturn(true); - mockDb.close(); - expectLastCall(); - - doReplay(); - final ListBranchesResult r = - new ListBranches(pcf, createListBranchesProvider(grm), name).call(); - doVerify(); - assertNotNull(r); - assertTrue(r.getBranches().isEmpty()); - } - - @Test - public void testHeadVisibleButBranchHidden() throws Exception { - ObjectIdRef.Unpeeled bar = - new ObjectIdRef.Unpeeled(LOOSE, R_HEADS + "bar", idA); - ObjectIdRef.Unpeeled foo = - new ObjectIdRef.Unpeeled(LOOSE, R_HEADS + "foo", idA); - - Map u = new LinkedHashMap(); - u.put(bar.getName(), bar); - u.put(HEAD, new SymbolicRef(HEAD, bar)); - u.put(foo.getName(), foo); - - validate().andReturn(pc); - expect(grm.openRepository(eq(name))).andReturn(mockDb); - expect(mockDb.getAllRefs()).andReturn(u); - assumeVisible(bar, true, targets(u)); - assumeVisible(bar, true, targets(u)); - assumeVisible(foo, false, targets(u)); - expect(pc.canAddRefs()).andReturn(true); - mockDb.close(); - expectLastCall(); - - doReplay(); - final ListBranchesResult r = - new ListBranches(pcf, createListBranchesProvider(grm), name).call(); - doVerify(); - assertNotNull(r); - - assertEquals(2, r.getBranches().size()); - - assertEquals(HEAD, r.getBranches().get(0).getShortName()); - assertFalse(r.getBranches().get(0).getCanDelete()); - - assertEquals("bar", r.getBranches().get(1).getShortName()); - assertFalse(r.getBranches().get(1).getCanDelete()); - } - - private static Provider createListBranchesProvider( - final GitRepositoryManager grm) { - return new Provider() { - @Override - public com.google.gerrit.server.project.ListBranches get() { - return new com.google.gerrit.server.project.ListBranches(grm); - } - }; - } -}