move rename logic to repository manager

This commit is contained in:
Eduard Heimbuch
2020-06-26 09:24:13 +02:00
parent cc9be30065
commit 7fa256bedb
12 changed files with 619 additions and 640 deletions

View File

@@ -24,14 +24,19 @@
package sonia.scm.repository;
import sonia.scm.HandlerEventType;
import sonia.scm.event.AbstractHandlerEvent;
import sonia.scm.event.Event;
import sonia.scm.BadRequestException;
import sonia.scm.ContextEntry;
@Event
public class RepositoryRenamedEvent extends AbstractHandlerEvent<Repository> {
public class ChangeNamespaceNotAllowedException extends BadRequestException {
public RepositoryRenamedEvent(HandlerEventType eventType, Repository item, Repository oldItem) {
super(eventType, item, oldItem);
public ChangeNamespaceNotAllowedException(Repository repository) {
super(ContextEntry.ContextBuilder.entity(repository).build(), "change of namespace is not allowed in current namespace strategy");
}
private static final String CODE = "ERS2vYb7U1";
@Override
public String getCode() {
return CODE;
}
}

View File

@@ -38,18 +38,15 @@ import java.util.Collection;
* This class is a singleton and is available via injection.
*
* @author Sebastian Sdorra
*
* @apiviz.uses sonia.scm.repository.RepositoryHandler
*/
public interface RepositoryManager
extends TypeManager<Repository, RepositoryHandler>
{
extends TypeManager<Repository, RepositoryHandler> {
/**
* Fire {@link RepositoryHookEvent} to the event bus.
*
* @param event hook event
*
* @since 2.0.0
*/
public void fireHookEvent(RepositoryHookEvent event);
@@ -58,9 +55,7 @@ public interface RepositoryManager
* Imports an existing {@link Repository}.
* Note: This method should only be called from a {@link RepositoryHandler}.
*
*
* @param repository {@link Repository} to import
*
* @throws IOException
*/
public void importRepository(Repository repository) throws IOException;
@@ -71,10 +66,7 @@ public interface RepositoryManager
* Returns a {@link Repository} by its namespace and name or
* null if the {@link Repository} could not be found.
*
*
* @param namespaceAndName namespace and name of the {@link Repository}
*
*
* @return {@link Repository} by its namespace and name or null
* if the {@link Repository} could not be found
*/
@@ -83,7 +75,6 @@ public interface RepositoryManager
/**
* Returns all configured repository types.
*
*
* @return all configured repository types
*/
public Collection<RepositoryType> getConfiguredTypes();
@@ -91,11 +82,17 @@ public interface RepositoryManager
/**
* Returns a {@link RepositoryHandler} by the given type (hg, git, svn ...).
*
*
* @param type the type of the {@link RepositoryHandler}
*
* @return {@link RepositoryHandler} by the given type
*/
@Override
public RepositoryHandler getHandler(String type);
/**
* @param repository the repository {@link Repository}
* @param newNameSpace the new repository namespace
* @param newName the new repository name
* @return {@link Repository} the renamed repository
*/
public Repository rename(Repository repository, String newNameSpace, String newName);
}

View File

@@ -42,17 +42,14 @@ import java.util.Collection;
*/
public class RepositoryManagerDecorator
extends ManagerDecorator<Repository>
implements RepositoryManager
{
implements RepositoryManager {
/**
* Constructs ...
*
*
* @param decorated
*/
public RepositoryManagerDecorator(RepositoryManager decorated)
{
public RepositoryManagerDecorator(RepositoryManager decorated) {
super(decorated);
this.decorated = decorated;
}
@@ -63,8 +60,7 @@ public class RepositoryManagerDecorator
* {@inheritDoc}
*/
@Override
public void fireHookEvent(RepositoryHookEvent event)
{
public void fireHookEvent(RepositoryHookEvent event) {
decorated.fireHookEvent(event);
}
@@ -79,65 +75,66 @@ public class RepositoryManagerDecorator
//~--- get methods ----------------------------------------------------------
@Override
public Repository get(NamespaceAndName namespaceAndName)
{
public Repository get(NamespaceAndName namespaceAndName) {
return decorated.get(namespaceAndName);
}
/**
* {@inheritDoc}
*
*
* @return
*/
@Override
public Collection<RepositoryType> getConfiguredTypes()
{
public Collection<RepositoryType> getConfiguredTypes() {
return decorated.getConfiguredTypes();
}
/**
* Returns the decorated {@link RepositoryManager}.
*
*
* @return decorated {@link RepositoryManager}
*
* @since 1.34
*/
public RepositoryManager getDecorated()
{
public RepositoryManager getDecorated() {
return decorated;
}
/**
* {@inheritDoc}
*
*
* @param type
*
* @return
*/
@Override
@SuppressWarnings("unchecked")
public RepositoryHandler getHandler(String type)
{
public RepositoryHandler getHandler(String type) {
return decorated.getHandler(type);
}
/**
* {@inheritDoc}
*
* @return
*/
@Override
public Collection<Type> getTypes() {
return decorated.getTypes();
}
/**
* {@inheritDoc}
*
* @return
*/
@Override
public Collection<Type> getTypes()
{
return decorated.getTypes();
public Repository rename(Repository repository, String newNamespace, String newName) {
return decorated.rename(repository, newNamespace, newName);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
/**
* Field description
*/
private final RepositoryManager decorated;
}

View File

@@ -49,7 +49,7 @@ public final class RepositoryModificationEvent extends RepositoryEvent implement
*/
public RepositoryModificationEvent(HandlerEventType eventType, Repository item, Repository itemBeforeModification)
{
super(eventType, item);
super(eventType, item, itemBeforeModification);
this.itemBeforeModification = itemBeforeModification;
}

View File

@@ -116,4 +116,4 @@ const mapDispatchToProps = (dispatch: any) => {
};
};
export default compose(connect(mapStateToProps, mapDispatchToProps))(withRouter(EditRepo));
export default compose(connect(mapStateToProps, mapDispatchToProps), withRouter)(EditRepo);

View File

@@ -24,19 +24,13 @@
package sonia.scm.api.v2.resources;
import com.google.common.base.Strings;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import sonia.scm.HandlerEventType;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryPermissions;
import sonia.scm.repository.RepositoryRenamedEvent;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
@@ -65,22 +59,17 @@ public class RepositoryResource {
private final RepositoryManager manager;
private final SingleResourceManagerAdapter<Repository, RepositoryDto> adapter;
private final RepositoryBasedResourceProvider resourceProvider;
private final ScmConfiguration scmConfiguration;
private final ScmEventBus scmEventBus;
@Inject
public RepositoryResource(
RepositoryToRepositoryDtoMapper repositoryToDtoMapper,
RepositoryDtoToRepositoryMapper dtoToRepositoryMapper, RepositoryManager manager,
RepositoryBasedResourceProvider resourceProvider,
ScmConfiguration scmConfiguration, ScmEventBus scmEventBus) {
RepositoryBasedResourceProvider resourceProvider) {
this.dtoToRepositoryMapper = dtoToRepositoryMapper;
this.manager = manager;
this.repositoryToDtoMapper = repositoryToDtoMapper;
this.adapter = new SingleResourceManagerAdapter<>(manager, Repository.class);
this.resourceProvider = resourceProvider;
this.scmConfiguration = scmConfiguration;
this.scmEventBus = scmEventBus;
}
/**
@@ -210,48 +199,11 @@ public class RepositoryResource {
))
@ApiResponse(responseCode = "500", description = "internal server error")
public Response rename(@PathParam("namespace") String namespace, @PathParam("name") String name, @Valid RepositoryRenameDto renameDto) {
Supplier<Repository> repoSupplier = loadBy(namespace, name);
Repository unchangedRepo = repoSupplier.get();
Repository changedRepo = unchangedRepo.clone();
if (isRenameForbidden(unchangedRepo, renameDto)) {
return Response.status(403).build();
Repository repository = loadBy(namespace, name).get();
manager.rename(repository, renameDto.getNamespace(), renameDto.getName());
return Response.status(204).build();
}
if (hasNamespaceOrNameNotChanged(unchangedRepo, renameDto)) {
return Response.status(400).build();
}
if (!Strings.isNullOrEmpty(renameDto.getName())) {
changedRepo.setName(renameDto.getName());
}
if (!Strings.isNullOrEmpty(renameDto.getNamespace())) {
changedRepo.setNamespace(renameDto.getNamespace());
}
return adapter.update(
repoSupplier,
existing -> {
scmEventBus.post(new RepositoryRenamedEvent(HandlerEventType.MODIFY, changedRepo, unchangedRepo));
return changedRepo;
},
changed -> true,
r -> r.getNamespaceAndName().logString()
);
}
private boolean hasNamespaceOrNameNotChanged(Repository repo, @Valid RepositoryRenameDto renameDto) {
return repo.getName().equals(renameDto.getName())
&& repo.getNamespace().equals(renameDto.getNamespace());
}
private boolean isRenameForbidden(Repository repo, RepositoryRenameDto renameDto) {
return !scmConfiguration.getNamespaceStrategy().equals("CustomNamespaceStrategy")
&& !repo.getNamespace().equals(renameDto.getNamespace())
|| !RepositoryPermissions.rename(repo).isPermitted();
}
private Repository processUpdate(RepositoryDto repositoryDto, Repository existing) {
Repository changedRepository = dtoToRepositoryMapper.map(repositoryDto, existing.getId());
changedRepository.setPermissions(existing.getPermissions());

View File

@@ -25,6 +25,7 @@
package sonia.scm.repository;
import com.github.sdorra.ssp.PermissionActionCheck;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.Inject;
@@ -35,6 +36,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.ConfigurationException;
import sonia.scm.HandlerEventType;
import sonia.scm.ManagerDaoAdapter;
import sonia.scm.NoChangesMadeException;
import sonia.scm.NotFoundException;
import sonia.scm.SCMContextProvider;
import sonia.scm.Type;
@@ -83,7 +85,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
private final Provider<NamespaceStrategy> namespaceStrategyProvider;
private final ManagerDaoAdapter<Repository> managerDaoAdapter;
@Inject
public DefaultRepositoryManager(ScmConfiguration configuration,
SCMContextProvider contextProvider, KeyGenerator keyGenerator,
@@ -243,6 +244,40 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
return repository;
}
public Repository rename(Repository repository, String newNamespace, String newName) {
if (!configuration.getNamespaceStrategy().equals("CustomNamespaceStrategy")
&& !repository.getNamespace().equals(newNamespace)) {
throw new ChangeNamespaceNotAllowedException(repository);
}
if (hasNamespaceOrNameNotChanged(repository, newNamespace, newName)) {
throw new NoChangesMadeException(repository);
}
Repository changedRepository = repository.clone();
if (!Strings.isNullOrEmpty(newName)) {
changedRepository.setName(newName);
}
if (!Strings.isNullOrEmpty(newNamespace)) {
changedRepository.setNamespace(newNamespace);
}
managerDaoAdapter.modify(
changedRepository,
RepositoryPermissions::rename,
notModified -> {
},
notModified -> fireEvent(HandlerEventType.MODIFY, changedRepository, repository));
return changedRepository;
}
private boolean hasNamespaceOrNameNotChanged(Repository repository, String newNamespace, String newName) {
return repository.getName().equals(newName)
&& repository.getNamespace().equals(newNamespace);
}
@Override
public Collection<Repository> getAll(Predicate<Repository> filter, Comparator<Repository> comparator) {
List<Repository> repositories = Lists.newArrayList();
@@ -345,8 +380,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
types.add(type);
}
private RepositoryHandler getHandler(Repository repository)
{
private RepositoryHandler getHandler(Repository repository) {
String type = repository.getType();
RepositoryHandler handler = handlerMap.get(type);

View File

@@ -191,6 +191,10 @@
"displayName": "Es wurden keine Änderungen durchgeführt",
"description": "Das Repository wurde nicht verändert. Daher konnte kein neuer Commit erzeugt werden. Womöglich werden Änderungen aufgrund einer .ignore-Datei Definition nicht berücksichtigt."
},
"ERS2vYb7U1": {
"displayName": "Änderung des Namespace nicht möglich",
"description": "Namespaces dürfen nur mit der Namespace Strategie \"Benutzerdefiniert\" verändert werden."
},
"4iRct4avG1": {
"displayName": "Die Revisionen haben keinen gemeinsamen Ursprung",
"description": "Die Historie der Revisionen hat keinen gemeinsamen Urspung und kann somit auch nicht gegen einen solchen verglichen werden."

View File

@@ -197,6 +197,10 @@
"displayName": "No changes were made",
"description": "No changes were made to the files of the repository. Therefor no new commit could be created. Possibly changes cannot be applied due to an .ignore-File definition."
},
"ERS2vYb7U1": {
"displayName": "Illegal change of namespace",
"description": "Namespaces can only be changed if namespace strategy is \"custom\"."
},
"4iRct4avG1": {
"displayName": "The revisions have unrelated histories",
"description": "The revisions have unrelated histories. Therefor there is no common commit to compare with."

View File

@@ -27,7 +27,6 @@ package sonia.scm.api.v2.resources;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.io.Resources;
import com.google.inject.util.Providers;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.jboss.resteasy.mock.MockHttpRequest;
@@ -35,19 +34,16 @@ import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.jupiter.api.Nested;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import sonia.scm.PageResult;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryInitializer;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryRenamedEvent;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.user.User;
@@ -66,7 +62,6 @@ import static java.util.Collections.singletonList;
import static java.util.stream.Stream.of;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
@@ -109,9 +104,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
@Mock
private RepositoryInitializer repositoryInitializer;
@Mock
private ScmConfiguration scmConfiguration;
@Mock
private ScmEventBus scmEventBus;
private ScmConfiguration configuration;
@Captor
private ArgumentCaptor<Predicate<Repository>> filterCaptor;
@@ -130,14 +123,11 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
super.repositoryToDtoMapper = repositoryToDtoMapper;
super.dtoToRepositoryMapper = dtoToRepositoryMapper;
super.manager = repositoryManager;
super.scmConfiguration = scmConfiguration;
super.scmEventBus = scmEventBus;
RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks);
super.repositoryCollectionResource = new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks, repositoryInitializer);
dispatcher.addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
when(scmPathInfoStore.get()).thenReturn(uriInfo);
when(scmConfiguration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y"));
SimplePrincipalCollection trillian = new SimplePrincipalCollection("trillian", REALM);
trillian.add(new User("trillian"), REALM);
@@ -164,6 +154,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
@Test
public void shouldFindExistingRepository() throws URISyntaxException, UnsupportedEncodingException {
mockRepository("space", "repo");
when(configuration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo");
MockHttpResponse response = new MockHttpResponse();
@@ -178,6 +169,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
public void shouldGetAll() throws URISyntaxException, UnsupportedEncodingException {
PageResult<Repository> singletonPageResult = createSingletonPageResult(mockRepository("space", "repo"));
when(repositoryManager.getPage(any(), any(), eq(0), eq(10))).thenReturn(singletonPageResult);
when(configuration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2);
MockHttpResponse response = new MockHttpResponse();
@@ -192,6 +184,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
public void shouldCreateFilterForSearch() throws URISyntaxException {
PageResult<Repository> singletonPageResult = createSingletonPageResult(mockRepository("space", "repo"));
when(repositoryManager.getPage(filterCaptor.capture(), any(), eq(0), eq(10))).thenReturn(singletonPageResult);
when(configuration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "?q=Rep");
MockHttpResponse response = new MockHttpResponse();
@@ -374,6 +367,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
public void shouldCreateArrayOfProtocolUrls() throws Exception {
mockRepository("space", "repo");
when(service.getSupportedProtocols()).thenReturn(of(new MockScmProtocol("http", "http://"), new MockScmProtocol("ssh", "ssh://")));
when(configuration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo");
MockHttpResponse response = new MockHttpResponse();
@@ -384,48 +378,12 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
assertTrue(response.getContentAsString().contains("\"protocol\":[{\"href\":\"http://\",\"name\":\"http\"},{\"href\":\"ssh://\",\"name\":\"ssh\"}]"));
}
@Test
public void shouldNotRenameRepositoryNamespaceIfNamespaceStrategyIsNotCustom() throws Exception {
mockRepository("hitchhiker", "heart-of-gold");
when(scmConfiguration.getNamespaceStrategy()).thenReturn("UsernameNamespaceStrategy");
URL url = Resources.getResource("sonia/scm/api/v2/rename-repo.json");
byte[] repository = Resources.toByteArray(url);
MockHttpRequest request = MockHttpRequest
.post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "hitchhiker/heart-of-gold/rename")
.contentType(VndMediaType.REPOSITORY)
.content(repository);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_FORBIDDEN, response.getStatus());
}
@Test
public void shouldNotRenameRepositoryIfNamespaceAndNameDidNotChanged() throws Exception {
mockRepository("space", "x");
when(scmConfiguration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
URL url = Resources.getResource("sonia/scm/api/v2/rename-repo.json");
byte[] repository = Resources.toByteArray(url);
MockHttpRequest request = MockHttpRequest
.post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/x/rename")
.contentType(VndMediaType.REPOSITORY)
.content(repository);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_BAD_REQUEST, response.getStatus());
}
@Test
public void shouldRenameRepository() throws Exception {
mockRepository("space", "repo");
when(scmConfiguration.getNamespaceStrategy()).thenReturn("CustomNamespaceStrategy");
String namespace = "space";
String name = "repo";
Repository repository1 = mockRepository(namespace, name);
when(manager.get(new NamespaceAndName(namespace, name))).thenReturn(repository1);
URL url = Resources.getResource("sonia/scm/api/v2/rename-repo.json");
byte[] repository = Resources.toByteArray(url);
@@ -439,31 +397,9 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
dispatcher.invoke(request, response);
assertEquals(SC_NO_CONTENT, response.getStatus());
verify(repositoryManager).modify(any(Repository.class));
verify(scmEventBus).post(any(RepositoryRenamedEvent.class));
verify(repositoryManager).rename(repository1, "space", "x");
}
@Test
public void shouldRenameRepositoryNameIfNamespaceStrategyNotCustom() throws Exception {
mockRepository("space", "repo");
when(scmConfiguration.getNamespaceStrategy()).thenReturn("UsernameNamespaceStrategy");
URL url = Resources.getResource("sonia/scm/api/v2/rename-repo.json");
byte[] repository = Resources.toByteArray(url);
MockHttpRequest request = MockHttpRequest
.post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/rename")
.contentType(VndMediaType.REPOSITORY)
.content(repository);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_NO_CONTENT, response.getStatus());
verify(repositoryManager).modify(any(Repository.class));
}
private PageResult<Repository> createSingletonPageResult(Repository repository) {
return new PageResult<>(singletonList(repository), 0);
}

View File

@@ -24,12 +24,9 @@
package sonia.scm.api.v2.resources;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.RepositoryManager;
import static com.google.inject.util.Providers.of;
import static org.mockito.Mockito.mock;
abstract class RepositoryTestBase {
@@ -48,9 +45,6 @@ abstract class RepositoryTestBase {
IncomingRootResource incomingRootResource;
RepositoryCollectionResource repositoryCollectionResource;
AnnotateResource annotateResource;
ScmConfiguration scmConfiguration;
ScmEventBus scmEventBus;
RepositoryRootResource getRepositoryRootResource() {
RepositoryBasedResourceProvider repositoryBasedResourceProvider = new RepositoryBasedResourceProvider(
@@ -70,8 +64,7 @@ abstract class RepositoryTestBase {
repositoryToDtoMapper,
dtoToRepositoryMapper,
manager,
repositoryBasedResourceProvider,
scmConfiguration, scmEventBus)),
repositoryBasedResourceProvider)),
of(repositoryCollectionResource));
}
}

View File

@@ -30,7 +30,6 @@ import com.github.legman.Subscribe;
import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.util.Providers;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.util.ThreadContext;
@@ -44,32 +43,46 @@ import sonia.scm.AlreadyExistsException;
import sonia.scm.HandlerEventType;
import sonia.scm.Manager;
import sonia.scm.ManagerTestBase;
import sonia.scm.NoChangesMadeException;
import sonia.scm.NotFoundException;
import sonia.scm.SCMContext;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.event.ScmEventBus;
import sonia.scm.io.DefaultFileSystem;
import sonia.scm.repository.api.HookContext;
import sonia.scm.repository.api.HookContextFactory;
import sonia.scm.repository.api.HookFeature;
import sonia.scm.repository.spi.HookContextProvider;
import sonia.scm.repository.xml.PathBasedRepositoryLocationResolver;
import sonia.scm.repository.xml.XmlRepositoryDAO;
import sonia.scm.security.DefaultKeyGenerator;
import sonia.scm.security.KeyGenerator;
import sonia.scm.store.ConfigurationStoreFactory;
import sonia.scm.store.JAXBConfigurationStoreFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static java.util.Collections.emptySet;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
//~--- JDK imports ------------------------------------------------------------
@@ -83,447 +96,491 @@ import static org.mockito.Mockito.*;
password = "secret",
configuration = "classpath:sonia/scm/repository/shiro.ini"
)
public class DefaultRepositoryManagerTest {//extends ManagerTestBase<Repository> {
public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
{
ThreadContext.unbindSubject();
}
@Rule
public ShiroRule shiro = new ShiroRule();
@Rule
public ExpectedException thrown = ExpectedException.none();
private ScmConfiguration configuration;
private String mockedNamespace = "default_namespace";
@Before
public void initContext() {
((TempSCMContextProvider) SCMContext.getContext()).setBaseDirectory(temp);
}
@Test
public void testCreate() {
Repository heartOfGold = createTestRepository();
Repository dbRepo = manager.get(heartOfGold.getId());
assertNotNull(dbRepo);
assertRepositoriesEquals(dbRepo, heartOfGold);
}
@SubjectAware(
username = "unpriv"
)
@Test(expected = UnauthorizedException.class)
public void testCreateWithoutPrivileges() {
createTestRepository();
}
@Test
public void testCreateExisting() {
createTestRepository();
thrown.expect(AlreadyExistsException.class);
createTestRepository();
}
@Test
public void testDelete() {
delete(manager, createTestRepository());
}
@SubjectAware(
username = "unpriv"
)
@Test(expected = UnauthorizedException.class)
public void testDeleteWithoutPrivileges() {
delete(manager, createTestRepository());
}
@Test(expected = NotFoundException.class)
public void testDeleteNotFound() {
manager.delete(createRepositoryWithId());
}
@Test
public void testGet() {
Repository heartOfGold = createTestRepository();
String id = heartOfGold.getId();
String description = heartOfGold.getDescription();
assertNotNull(description);
// test for reference
heartOfGold.setDescription("prototype ship");
heartOfGold = manager.get(id);
assertNotNull(heartOfGold);
assertEquals(description, heartOfGold.getDescription());
}
@Test
@SubjectAware(
username = "crato"
)
public void testGetWithoutRequiredPrivileges() {
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
manager.create(heartOfGold);
thrown.expect(UnauthorizedException.class);
manager.get(heartOfGold.getId());
}
@Test
public void testGetAll() {
Repository heartOfGold = createTestRepository();
Repository happyVerticalPeopleTransporter = createSecondTestRepository();
boolean foundHeart = false;
boolean foundTransporter = false;
Collection<Repository> repositories = manager.getAll();
assertNotNull(repositories);
assertFalse(repositories.isEmpty());
assertTrue(repositories.size() >= 2);
Repository heartReference = null;
for (Repository repository : repositories) {
if (repository.getId().equals(heartOfGold.getId())) {
assertRepositoriesEquals(heartOfGold, repository);
foundHeart = true;
heartReference = repository;
} else if (repository.getId().equals(happyVerticalPeopleTransporter.getId())) {
assertRepositoriesEquals(happyVerticalPeopleTransporter, repository);
foundTransporter = true;
}
}
assertTrue(foundHeart);
assertTrue(foundTransporter);
// test for reference
assertNotSame(heartOfGold, heartReference);
heartReference.setDescription("prototype ship");
assertFalse(
heartOfGold.getDescription().equals(heartReference.getDescription()));
}
@Test
@SuppressWarnings("unchecked")
@SubjectAware(username = "dent")
public void testGetAllWithPermissionsForTwoOrThreeRepos() {
// mock key generator
KeyGenerator keyGenerator = mock(KeyGenerator.class);
Stack<String> keys = new Stack<>();
keys.push("rateotu");
keys.push("p42");
keys.push("hof");
when(keyGenerator.createKey()).then((InvocationOnMock invocation) -> {
return keys.pop();
});
// create repository manager
RepositoryManager repositoryManager = createRepositoryManager(keyGenerator);
// create first test repository
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
repositoryManager.create(heartOfGold);
assertEquals("hof", heartOfGold.getId());
// create second test repository
Repository puzzle42 = RepositoryTestData.create42Puzzle();
repositoryManager.create(puzzle42);
assertEquals("p42", puzzle42.getId());
// create third test repository
Repository restaurant = RepositoryTestData.createRestaurantAtTheEndOfTheUniverse();
repositoryManager.create(restaurant);
assertEquals("rateotu", restaurant.getId());
// assert returned repositories
Collection<Repository> repositories = repositoryManager.getAll();
assertEquals(2, repositories.size());
assertThat(repositories, containsInAnyOrder(
hasProperty("id", is("p42")),
hasProperty("id", is("hof"))
)
);
}
@Test
public void testEvents() {
RepositoryManager repoManager = createManager();
repoManager.init(contextProvider);
TestListener listener = new TestListener();
ScmEventBus.getInstance().register(listener);
Repository repository = RepositoryTestData.create42Puzzle();
repoManager.create(repository);
assertRepositoriesEquals(repository, listener.preRepository);
assertSame(HandlerEventType.BEFORE_CREATE, listener.preEvent);
assertRepositoriesEquals(repository, listener.postRepository);
assertSame(HandlerEventType.CREATE, listener.postEvent);
repository.setDescription("changed description");
repoManager.modify(repository);
assertRepositoriesEquals(repository, listener.preRepository);
assertSame(HandlerEventType.BEFORE_MODIFY, listener.preEvent);
assertRepositoriesEquals(repository, listener.postRepository);
assertSame(HandlerEventType.MODIFY, listener.postEvent);
repoManager.delete(repository);
assertRepositoriesEquals(repository, listener.preRepository);
assertSame(HandlerEventType.BEFORE_DELETE, listener.preEvent);
assertRepositoriesEquals(repository, listener.postRepository);
assertSame(HandlerEventType.DELETE, listener.postEvent);
}
@Test
public void testModify() {
Repository heartOfGold = createTestRepository();
heartOfGold.setDescription("prototype ship");
manager.modify(heartOfGold);
Repository hearReference = manager.get(heartOfGold.getId());
assertNotNull(hearReference);
assertEquals(hearReference.getDescription(), "prototype ship");
}
@Test
@SubjectAware(username = "crato")
public void testModifyWithoutRequiredPermissions() {
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
manager.create(heartOfGold);
heartOfGold.setDescription("prototype ship");
thrown.expect(UnauthorizedException.class);
manager.modify(heartOfGold);
}
@Test(expected = NotFoundException.class)
public void testModifyNotFound() {
manager.modify(createRepositoryWithId());
}
@Test
public void testRefresh() {
Repository heartOfGold = createTestRepository();
String description = heartOfGold.getDescription();
heartOfGold.setDescription("prototype ship");
manager.refresh(heartOfGold);
assertEquals(description, heartOfGold.getDescription());
}
@Test
@SubjectAware(username = "crato")
public void testRefreshWithoutRequiredPermissions() {
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
manager.create(heartOfGold);
heartOfGold.setDescription("prototype ship");
thrown.expect(UnauthorizedException.class);
manager.refresh(heartOfGold);
}
@Test(expected = NotFoundException.class)
public void testRefreshNotFound() {
manager.refresh(createRepositoryWithId());
}
@Test
public void testRepositoryHook() {
CountingReceiveHook hook = new CountingReceiveHook();
RepositoryManager repoManager = createManager();
ScmEventBus.getInstance().register(hook);
assertEquals(0, hook.eventsReceived);
Repository repository = createTestRepository();
HookContext ctx = createHookContext(repository);
repoManager.fireHookEvent(new RepositoryHookEvent(ctx, repository,
RepositoryHookType.POST_RECEIVE));
assertEquals(1, hook.eventsReceived);
repoManager.fireHookEvent(new RepositoryHookEvent(ctx, repository,
RepositoryHookType.POST_RECEIVE));
assertEquals(2, hook.eventsReceived);
}
@Test
public void testNamespaceSet() {
RepositoryManager repoManager = createManager();
Repository repository = spy(createTestRepository());
repository.setName("Testrepo");
repoManager.create(repository);
assertEquals("default_namespace", repository.getNamespace());
}
@Test
public void shouldSetNamespace() {
Repository repository = new Repository(null, "hg", null, "scm");
manager.create(repository);
assertNotNull(repository.getId());
assertNotNull(repository.getNamespace());
}
@Test
public void shouldThrowChangeNamespaceNotAllowedException() {
Repository repository = new Repository("1", "hg", "space", "x");
RepositoryManager repoManager = createManager();
thrown.expect(ChangeNamespaceNotAllowedException.class);
repoManager.rename(repository, "hitchhiker", "heart-of-gold");
}
@Test
public void shouldThrowNoChangesMadeException() {
configuration.setNamespaceStrategy("CustomNamespaceStrategy");
Repository repository = new Repository("1", "hg", "space", "x");
RepositoryManager repoManager = createManager();
thrown.expect(NoChangesMadeException.class);
repoManager.rename(repository, "space", "x");
}
@Test
public void shouldOnlyChangeRepositoryName() {
Repository repository = createTestRepository();
RepositoryManager repoManager = (RepositoryManager) manager;
configuration.setNamespaceStrategy("UsernameNamespaceStrategy");
Repository changedRepo = repoManager.rename(repository, "default_namespace", "puzzle42");
assertNotEquals(changedRepo.getName(), repository.getName());
}
@Test
public void shouldRenameRepositoryNamespaceAndName() {
Repository repository = createTestRepository();
RepositoryManager repoManager = (RepositoryManager) manager;
configuration.setNamespaceStrategy("CustomNamespaceStrategy");
Repository changedRepo = repoManager.rename(repository, "hitchhiker", "puzzle42");
assertNotEquals(changedRepo.getName(), repository.getName());
assertNotEquals(changedRepo.getNamespace(), repository.getNamespace());
}
//~--- methods --------------------------------------------------------------
@Override
protected DefaultRepositoryManager createManager() {
return createRepositoryManager(new DefaultKeyGenerator());
}
private DefaultRepositoryManager createRepositoryManager(KeyGenerator keyGenerator) {
Set<RepositoryHandler> handlerSet = new HashSet<>();
RepositoryDAO repositoryDAO = createRepositoryDaoMock();
mock(ConfigurationStoreFactory.class);
handlerSet.add(createRepositoryHandler("dummy", "Dummy"));
handlerSet.add(createRepositoryHandler("git", "Git"));
handlerSet.add(createRepositoryHandler("hg", "Mercurial"));
handlerSet.add(createRepositoryHandler("svn", "SVN"));
this.configuration = new ScmConfiguration();
NamespaceStrategy namespaceStrategy = mock(NamespaceStrategy.class);
when(namespaceStrategy.createNamespace(Mockito.any(Repository.class))).thenAnswer(invocation -> mockedNamespace);
return new DefaultRepositoryManager(configuration, contextProvider,
keyGenerator, repositoryDAO, handlerSet, Providers.of(namespaceStrategy));
}
private RepositoryDAO createRepositoryDaoMock() {
Map<String, Repository> repositoriesById = new HashMap<>();
Map<NamespaceAndName, Repository> repositoriesByNamespaceAndName = new HashMap<>();
RepositoryDAO mock = mock(RepositoryDAO.class);
doAnswer(invocation -> {
Repository repo = invocation.getArgument(0, Repository.class);
if (repositoriesById.containsKey(repo.getId()) || repositoriesByNamespaceAndName.containsKey(repo.getNamespaceAndName())) {
throw new AlreadyExistsException(repo);
}
Repository clone = repo.clone();
repositoriesById.put(repo.getId(), clone);
repositoriesByNamespaceAndName.put(repo.getNamespaceAndName(), clone);
return null;
}).when(mock).add(any());
doAnswer(invocation -> {
Repository repo = invocation.getArgument(0, Repository.class);
Repository clone = repo.clone();
repositoriesById.put(repo.getId(), clone);
repositoriesByNamespaceAndName.put(repo.getNamespaceAndName(), clone);
return null;
}).when(mock).modify(any());
when(mock.get(anyString())).thenAnswer(invocation -> repositoriesById.get(invocation.getArgument(0, String.class)));
when(mock.get(any(NamespaceAndName.class))).thenAnswer(invocation -> repositoriesByNamespaceAndName.get(invocation.getArgument(0, NamespaceAndName.class)));
when(mock.getAll()).thenAnswer(invocation -> repositoriesById.values());
when(mock.contains(anyString())).thenAnswer(invocation -> repositoriesById.containsKey(invocation.getArgument(0, String.class)));
when(mock.contains(any(Repository.class))).thenAnswer(invocation -> repositoriesById.containsKey(invocation.getArgument(0, Repository.class).getId()));
doAnswer(invocation -> {
Repository repo = invocation.getArgument(0, Repository.class);
repositoriesById.remove(repo.getId());
repositoriesByNamespaceAndName.remove(repo.getNamespaceAndName());
return null;
}).when(mock).delete(any(Repository.class));
return mock;
}
private RepositoryHandler createRepositoryHandler(String name, String diplayName) {
RepositoryHandler handler = mock(RepositoryHandler.class);
when(handler.getType()).thenReturn(new RepositoryType(name, diplayName, emptySet()));
when(handler.isConfigured()).thenReturn(true);
return handler;
}
private HookContext createHookContext(Repository repository) {
PreProcessorUtil ppu = mock(PreProcessorUtil.class);
HookContextProvider provider = mock(HookContextProvider.class);
Set<HookFeature> features = ImmutableSet.of();
when(provider.getSupportedFeatures()).thenReturn(features);
return new HookContextFactory(ppu).createContext(provider, repository);
}
private void assertRepositoriesEquals(Repository repo, Repository other) {
assertEquals(repo.getId(), other.getId());
assertEquals(repo.getName(), other.getName());
assertEquals(repo.getDescription(), other.getDescription());
assertEquals(repo.getContact(), other.getContact());
assertEquals(repo.getCreationDate(), other.getCreationDate());
assertEquals(repo.getLastModified(), other.getLastModified());
}
private Repository createRepository(Repository repository) {
manager.create(repository);
assertNotNull(repository.getId());
assertNotNull(manager.get(repository.getId()));
assertTrue(repository.getCreationDate() > 0);
return repository;
}
private Repository createRepositoryWithId() {
Repository repository = RepositoryTestData.createHeartOfGold();
repository.setId("abc");
return repository;
}
private Repository createSecondTestRepository() {
return createRepository(
RepositoryTestData.createHappyVerticalPeopleTransporter());
}
private Repository createTestRepository() {
return createRepository(RepositoryTestData.createHeartOfGold());
}
private void delete(Manager<Repository> manager, Repository repository) {
String id = repository.getId();
manager.delete(repository);
assertNull(manager.get(id));
}
private static class CountingReceiveHook {
private int eventsReceived = 0;
@Subscribe(async = false)
public void onEvent(PostReceiveRepositoryHookEvent event) {
eventsReceived++;
}
@Subscribe(async = false)
public void onEvent(PreReceiveRepositoryHookEvent event) {
eventsReceived++;
}
}
private class TestListener {
private HandlerEventType postEvent;
private Repository postRepository;
private HandlerEventType preEvent;
private Repository preRepository;
@Subscribe(async = false)
public void onEvent(RepositoryEvent event) {
if (event.getEventType().isPost()) {
this.postRepository = event.getItem();
this.postEvent = event.getEventType();
} else if (event.getEventType().isPre()) {
this.preRepository = event.getItem();
this.preEvent = event.getEventType();
}
}
}
// {
// ThreadContext.unbindSubject();
// }
//
// @Rule
// public ShiroRule shiro = new ShiroRule();
//
// @Rule
// public ExpectedException thrown = ExpectedException.none();
//
// private ScmConfiguration configuration;
//
// private String mockedNamespace = "default_namespace";
//
// @Before
// public void initContext() {
// ((TempSCMContextProvider)SCMContext.getContext()).setBaseDirectory(temp);
// }
//
// @Test
// public void testCreate() {
// Repository heartOfGold = createTestRepository();
// Repository dbRepo = manager.get(heartOfGold.getId());
//
// assertNotNull(dbRepo);
// assertRepositoriesEquals(dbRepo, heartOfGold);
// }
//
// @SubjectAware(
// username = "unpriv"
// )
// @Test(expected = UnauthorizedException.class)
// public void testCreateWithoutPrivileges() {
// createTestRepository();
// }
//
// @Test
// public void testCreateExisting() {
// Repository testRepository = createTestRepository();
// String expectedNamespaceAndName = testRepository.getNamespaceAndName().logString();
// thrown.expect(AlreadyExistsException.class);
// thrown.expectMessage(expectedNamespaceAndName);
// createTestRepository();
// }
//
// @Test
// public void testDelete() {
// delete(manager, createTestRepository());
// }
//
// @SubjectAware(
// username = "unpriv"
// )
// @Test(expected = UnauthorizedException.class)
// public void testDeleteWithoutPrivileges() {
// delete(manager, createTestRepository());
// }
//
// @Test(expected = RepositoryIsNotArchivedException.class)
// public void testDeleteNonArchived() {
// configuration.setEnableRepositoryArchive(true);
// delete(manager, createTestRepository());
// }
//
// @Test(expected = NotFoundException.class)
// public void testDeleteNotFound(){
// manager.delete(createRepositoryWithId());
// }
//
// @Test
// public void testDeleteWithEnabledArchive() {
// Repository repository = createTestRepository();
//
// repository.setArchived(true);
// RepositoryManager drm = createRepositoryManager(true);
// drm.init(contextProvider);
// delete(drm, repository);
// }
//
// @Test
// public void testGet() {
// Repository heartOfGold = createTestRepository();
// String id = heartOfGold.getId();
// String description = heartOfGold.getDescription();
//
// assertNotNull(description);
//
// // test for reference
// heartOfGold.setDescription("prototype ship");
// heartOfGold = manager.get(id);
// assertNotNull(heartOfGold);
// assertEquals(description, heartOfGold.getDescription());
// }
//
// @Test
// @SubjectAware(
// username = "crato"
// )
// public void testGetWithoutRequiredPrivileges() {
// Repository heartOfGold = RepositoryTestData.createHeartOfGold();
// manager.create(heartOfGold);
//
// thrown.expect(UnauthorizedException.class);
// manager.get(heartOfGold.getId());
// }
//
// @Test
// public void testGetAll() {
// Repository heartOfGold = createTestRepository();
// Repository happyVerticalPeopleTransporter = createSecondTestRepository();
// boolean foundHeart = false;
// boolean foundTransporter = false;
// Collection<Repository> repositories = manager.getAll();
//
// assertNotNull(repositories);
// assertFalse(repositories.isEmpty());
// assertTrue(repositories.size() >= 2);
//
// Repository heartReference = null;
//
// for (Repository repository : repositories) {
// if (repository.getId().equals(heartOfGold.getId())) {
// assertRepositoriesEquals(heartOfGold, repository);
// foundHeart = true;
// heartReference = repository;
// }
// else if (repository.getId().equals(happyVerticalPeopleTransporter.getId())) {
// assertRepositoriesEquals(happyVerticalPeopleTransporter, repository);
// foundTransporter = true;
// }
// }
//
// assertTrue(foundHeart);
// assertTrue(foundTransporter);
//
// // test for reference
// assertNotSame(heartOfGold, heartReference);
// heartReference.setDescription("prototype ship");
// assertFalse(
// heartOfGold.getDescription().equals(heartReference.getDescription()));
// }
//
// @Test
// @SuppressWarnings("unchecked")
// @SubjectAware(username = "dent")
// public void testGetAllWithPermissionsForTwoOrThreeRepos() {
// // mock key generator
// KeyGenerator keyGenerator = mock(KeyGenerator.class);
// Stack<String> keys = new Stack<>();
// keys.push("rateotu");
// keys.push("p42");
// keys.push("hof");
//
// when(keyGenerator.createKey()).then((InvocationOnMock invocation) -> {
// return keys.pop();
// });
//
// // create repository manager
// RepositoryManager repositoryManager = createRepositoryManager(false, keyGenerator);
//
// // create first test repository
// Repository heartOfGold = RepositoryTestData.createHeartOfGold();
// repositoryManager.create(heartOfGold);
// assertEquals("hof", heartOfGold.getId());
//
// // create second test repository
// Repository puzzle42 = RepositoryTestData.create42Puzzle();
// repositoryManager.create(puzzle42);
// assertEquals("p42", puzzle42.getId());
//
// // create third test repository
// Repository restaurant = RepositoryTestData.createRestaurantAtTheEndOfTheUniverse();
// repositoryManager.create(restaurant);
// assertEquals("rateotu", restaurant.getId());
//
// // assert returned repositories
// Collection<Repository> repositories = repositoryManager.getAll();
// assertEquals(2, repositories.size());
// assertThat(repositories, containsInAnyOrder(
// hasProperty("id", is("p42")),
// hasProperty("id", is("hof"))
// )
// );
// }
//
// @Test
// public void testEvents() {
// RepositoryManager repoManager = createRepositoryManager(false);
// repoManager.init(contextProvider);
// TestListener listener = new TestListener();
//
// ScmEventBus.getInstance().register(listener);
//
// Repository repository = RepositoryTestData.create42Puzzle();
//
// repoManager.create(repository);
// assertRepositoriesEquals(repository, listener.preRepository);
// assertSame(HandlerEventType.BEFORE_CREATE, listener.preEvent);
// assertRepositoriesEquals(repository, listener.postRepository);
// assertSame(HandlerEventType.CREATE, listener.postEvent);
//
// repository.setDescription("changed description");
// repoManager.modify(repository);
// assertRepositoriesEquals(repository, listener.preRepository);
// assertSame(HandlerEventType.BEFORE_MODIFY, listener.preEvent);
// assertRepositoriesEquals(repository, listener.postRepository);
// assertSame(HandlerEventType.MODIFY, listener.postEvent);
//
// repoManager.delete(repository);
//
// assertRepositoriesEquals(repository, listener.preRepository);
// assertSame(HandlerEventType.BEFORE_DELETE, listener.preEvent);
// assertRepositoriesEquals(repository, listener.postRepository);
// assertSame(HandlerEventType.DELETE, listener.postEvent);
// }
//
// @Test
// public void testModify() {
// Repository heartOfGold = createTestRepository();
//
// heartOfGold.setDescription("prototype ship");
// manager.modify(heartOfGold);
//
// Repository hearReference = manager.get(heartOfGold.getId());
//
// assertNotNull(hearReference);
// assertEquals(hearReference.getDescription(), "prototype ship");
// }
//
// @Test
// @SubjectAware(username = "crato")
// public void testModifyWithoutRequiredPermissions() {
// Repository heartOfGold = RepositoryTestData.createHeartOfGold();
// manager.create(heartOfGold);
// heartOfGold.setDescription("prototype ship");
//
// thrown.expect(UnauthorizedException.class);
// manager.modify(heartOfGold);
// }
//
// @Test(expected = NotFoundException.class)
// public void testModifyNotFound(){
// manager.modify(createRepositoryWithId());
// }
//
// @Test
// public void testRefresh() {
// Repository heartOfGold = createTestRepository();
// String description = heartOfGold.getDescription();
//
// heartOfGold.setDescription("prototype ship");
// manager.refresh(heartOfGold);
// assertEquals(description, heartOfGold.getDescription());
// }
//
// @Test
// @SubjectAware(username = "crato")
// public void testRefreshWithoutRequiredPermissions() {
// Repository heartOfGold = RepositoryTestData.createHeartOfGold();
// manager.create(heartOfGold);
// heartOfGold.setDescription("prototype ship");
//
// thrown.expect(UnauthorizedException.class);
// manager.refresh(heartOfGold);
// }
//
// @Test(expected = NotFoundException.class)
// public void testRefreshNotFound(){
// manager.refresh(createRepositoryWithId());
// }
//
// @Test
// public void testRepositoryHook() {
// CountingReceiveHook hook = new CountingReceiveHook();
// RepositoryManager repoManager = createRepositoryManager(false);
//
// ScmEventBus.getInstance().register(hook);
//
// assertEquals(0, hook.eventsReceived);
//
// Repository repository = createTestRepository();
// HookContext ctx = createHookContext(repository);
//
// repoManager.fireHookEvent(new RepositoryHookEvent(ctx, repository,
// RepositoryHookType.POST_RECEIVE));
// assertEquals(1, hook.eventsReceived);
// repoManager.fireHookEvent(new RepositoryHookEvent(ctx, repository,
// RepositoryHookType.POST_RECEIVE));
// assertEquals(2, hook.eventsReceived);
// }
//
// @Test
// public void testNamespaceSet() {
// RepositoryManager repoManager = createRepositoryManager(false);
// Repository repository = spy(createTestRepository());
// repository.setName("Testrepo");
// repoManager.create(repository);
// assertEquals("default_namespace", repository.getNamespace());
// }
//
// @Test
// public void shouldSetNamespace() {
// Repository repository = new Repository(null, "hg", null, "scm");
// manager.create(repository);
// assertNotNull(repository.getId());
// assertNotNull(repository.getNamespace());
// }
//
// //~--- methods --------------------------------------------------------------
//
// @Override
// protected DefaultRepositoryManager createManager() {
// return createRepositoryManager(false);
// }
//
// private DefaultRepositoryManager createRepositoryManager(boolean archiveEnabled) {
// return createRepositoryManager(archiveEnabled, new DefaultKeyGenerator());
// }
//
// private DefaultRepositoryManager createRepositoryManager(boolean archiveEnabled, KeyGenerator keyGenerator) {
// DefaultFileSystem fileSystem = new DefaultFileSystem();
// Set<RepositoryHandler> handlerSet = new HashSet<>();
// PathBasedRepositoryLocationResolver repositoryLocationResolver = mock(PathBasedRepositoryLocationResolver.class, RETURNS_DEEP_STUBS);
// when(repositoryLocationResolver.forClass(Path.class).getLocation(anyString())).thenReturn(Paths.get("."));
// XmlRepositoryDAO repositoryDAO = new XmlRepositoryDAO(contextProvider, repositoryLocationResolver, fileSystem);
// ConfigurationStoreFactory factory = new JAXBConfigurationStoreFactory(contextProvider, repositoryLocationResolver);
// handlerSet.add(new DummyRepositoryHandler(factory, repositoryLocationResolver));
// handlerSet.add(new DummyRepositoryHandler(factory, repositoryLocationResolver) {
// @Override
// public RepositoryType getType() {
// return new RepositoryType("hg", "Mercurial", Sets.newHashSet());
// }
// });
// handlerSet.add(new DummyRepositoryHandler(factory, repositoryLocationResolver) {
// @Override
// public RepositoryType getType() {
// return new RepositoryType("git", "Git", Sets.newHashSet());
// }
// });
//
//
// this.configuration = new ScmConfiguration();
//
// configuration.setEnableRepositoryArchive(archiveEnabled);
//
// NamespaceStrategy namespaceStrategy = mock(NamespaceStrategy.class);
// when(namespaceStrategy.createNamespace(Mockito.any(Repository.class))).thenAnswer(invocation -> mockedNamespace);
//
// return new DefaultRepositoryManager(configuration, contextProvider,
// keyGenerator, repositoryDAO, handlerSet, Providers.of(namespaceStrategy));
// }
//
// private HookContext createHookContext(Repository repository) {
// PreProcessorUtil ppu = mock(PreProcessorUtil.class);
// HookContextProvider provider = mock(HookContextProvider.class);
// Set<HookFeature> features = ImmutableSet.of();
//
// when(provider.getSupportedFeatures()).thenReturn(features);
//
// return new HookContextFactory(ppu).createContext(provider, repository);
// }
//
// private void assertRepositoriesEquals(Repository repo, Repository other) {
// assertEquals(repo.getId(), other.getId());
// assertEquals(repo.getName(), other.getName());
// assertEquals(repo.getDescription(), other.getDescription());
// assertEquals(repo.getContact(), other.getContact());
// assertEquals(repo.getCreationDate(), other.getCreationDate());
// assertEquals(repo.getLastModified(), other.getLastModified());
// }
//
// private Repository createRepository(Repository repository) {
// manager.create(repository);
// assertNotNull(repository.getId());
// assertNotNull(manager.get(repository.getId()));
// assertTrue(repository.getCreationDate() > 0);
//
// return repository;
// }
//
// private Repository createRepositoryWithId() {
// Repository repository = RepositoryTestData.createHeartOfGold();
// repository.setId("abc");
// return repository;
// }
//
// private Repository createSecondTestRepository() {
// return createRepository(
// RepositoryTestData.createHappyVerticalPeopleTransporter());
// }
//
// private Repository createTestRepository() {
// return createRepository(RepositoryTestData.createHeartOfGold());
// }
//
// private void delete(Manager<Repository> manager, Repository repository){
//
// String id = repository.getId();
//
// manager.delete(repository);
// assertNull(manager.get(id));
// }
//
// private static class CountingReceiveHook {
//
// private int eventsReceived = 0;
//
// @Subscribe(async = false)
// public void onEvent(PostReceiveRepositoryHookEvent event) {
// eventsReceived++;
// }
//
// @Subscribe(async = false)
// public void onEvent(PreReceiveRepositoryHookEvent event) {
// eventsReceived++;
// }
// }
//
// private class TestListener {
//
// private HandlerEventType postEvent;
//
// private Repository postRepository;
//
// private HandlerEventType preEvent;
//
// private Repository preRepository;
//
// @Subscribe(async = false)
// public void onEvent(RepositoryEvent event) {
// if (event.getEventType().isPost()) {
// this.postRepository = event.getItem();
// this.postEvent = event.getEventType();
// }
// else if (event.getEventType().isPre()) {
// this.preRepository = event.getItem();
// this.preEvent = event.getEventType();
// }
// }
// }
//
}