/**
* This file is part of git-as-svn. It is subject to the license terms
* in the LICENSE file found in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn,
* including this file, may be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
package svnserver.ext.gitlab.mapping;
import org.gitlab.api.models.GitlabProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import svnserver.StringHelper;
import svnserver.config.ConfigHelper;
import svnserver.context.LocalContext;
import svnserver.context.SharedContext;
import svnserver.repository.RepositoryInfo;
import svnserver.repository.VcsAccess;
import svnserver.repository.VcsRepository;
import svnserver.repository.VcsRepositoryMapping;
import svnserver.repository.mapping.RepositoryListMapping;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Simple repository mapping by predefined list.
*
* @author Artem V. Navrotskiy <bozaro@users.noreply.github.com>
*/
public class GitLabMapping implements VcsRepositoryMapping {
@NotNull
private final NavigableMap<String, GitLabProject> mapping = new ConcurrentSkipListMap<>();
@NotNull
private final SharedContext context;
@NotNull
private final GitLabMappingConfig config;
public GitLabMapping(@NotNull SharedContext context, @NotNull GitLabMappingConfig config) {
this.context = context;
this.config = config;
}
@NotNull
public SharedContext getContext() {
return context;
}
@Nullable
@Override
public RepositoryInfo getRepository(@NotNull SVNURL url) throws SVNException {
final Map.Entry<String, GitLabProject> entry = RepositoryListMapping.getMapped(mapping, url.getPath());
if (entry != null && entry.getValue().isReady()) {
return new RepositoryInfo(
SVNURL.create(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort() == SVNURL.getDefaultPortNumber(url.getProtocol()) ? -1 : url.getPort(), entry.getKey(), true),
entry.getValue().getRepository()
);
}
return null;
}
@Override
public void initRevisions() throws IOException, SVNException {
for (Map.Entry<String, GitLabProject> entry : mapping.entrySet()) {
entry.getValue().initRevisions();
}
}
@Nullable
public GitLabProject addRepository(@NotNull GitlabProject project) throws IOException, SVNException {
final String projectName = project.getPathWithNamespace();
final String projectKey = StringHelper.normalizeDir(projectName);
final GitLabProject oldProject = mapping.get(projectKey);
if (oldProject == null || oldProject.getProjectId() != project.getId()) {
final File basePath = ConfigHelper.joinPath(context.getBasePath(), config.getPath());
final File repoPath = ConfigHelper.joinPath(basePath, project.getPathWithNamespace() + ".git");
final LocalContext local = new LocalContext(context, project.getPathWithNamespace());
local.add(VcsAccess.class, new GitLabAccess(local, config, project.getId()));
final VcsRepository repository = config.getTemplate().create(local, repoPath);
final GitLabProject newProject = new GitLabProject(local, repository, project.getId());
if (mapping.compute(projectKey, (key, value) -> value != null && value.getProjectId() == project.getId() ? value : newProject) == newProject) {
return newProject;
}
}
return null;
}
public void removeRepository(int projectId, @NotNull String projectName) {
final String projectKey = StringHelper.normalizeDir(projectName);
final GitLabProject project = mapping.get(projectKey);
if (project != null && project.getProjectId() == projectId) {
if (mapping.remove(projectKey, project)) {
project.close();
}
}
}
}