|
|
@@ -0,0 +1,374 @@
|
|
|
+package seecoder.devcloud.api.gitlab.impl;
|
|
|
+
|
|
|
+
|
|
|
+import seecoder.devcloud.api.ApplicationProperties;
|
|
|
+import seecoder.devcloud.api.gitlab.GitlabApi;
|
|
|
+import seecoder.devcloud.api.gitlab.model.CommitDetails;
|
|
|
+import seecoder.devcloud.api.gitlab.model.GitlabGroup;
|
|
|
+import seecoder.devcloud.api.gitlab.model.GitlabUser;
|
|
|
+import org.gitlab4j.api.*;
|
|
|
+import org.gitlab4j.api.models.*;
|
|
|
+import org.gitlab4j.api.models.ImpersonationToken.Scope;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import seecoder.devcloud.common.util.ToolKit;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Component
|
|
|
+public class GitlabApiImpl implements GitlabApi {
|
|
|
+ private final ApplicationProperties.Gitlab gitlab;
|
|
|
+
|
|
|
+ private final GitLabApi server;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public GitlabApiImpl(ApplicationProperties properties) {
|
|
|
+ gitlab = properties.getGitlab();
|
|
|
+ this.server = new GitLabApi(gitlab.getHost(), gitlab.getToken());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized GitlabUser createUser(String username, String email,
|
|
|
+ String password) throws GitLabApiException {
|
|
|
+ User user = new User();
|
|
|
+ user.setUsername(username);
|
|
|
+ user.setEmail(email);
|
|
|
+ user.setName(username);
|
|
|
+ user.setSkipConfirmation(true);
|
|
|
+ user = server.getUserApi().createUser(user, password, 1000);
|
|
|
+ GitlabUser gitlabUser = new GitlabUser();
|
|
|
+ gitlabUser.setId(user.getId());
|
|
|
+ gitlabUser.setNamespace(fetchNamespace(username));
|
|
|
+ gitlabUser.setToken(createToken(user.getId()));
|
|
|
+ return gitlabUser;
|
|
|
+ }
|
|
|
+
|
|
|
+ //10 => Guest access
|
|
|
+ //20 => Reporter access
|
|
|
+ //30 => Developer access
|
|
|
+ //40 => Maintainer access
|
|
|
+ //50 => Owner access # Only valid for groups
|
|
|
+ @Override
|
|
|
+ public synchronized GitlabGroup createGroup(String groupName) throws GitLabApiException {
|
|
|
+
|
|
|
+ final Group group = server.getGroupApi().addGroup(groupName, groupName);//todo:Group默认private
|
|
|
+ GitlabGroup gitlabGroup = new GitlabGroup();
|
|
|
+ gitlabGroup.setId(group.getId());
|
|
|
+ final Integer ns1 = fetchNamespace("group", groupName);
|
|
|
+ gitlabGroup.setNamespace(ns1);//todo:Namespace
|
|
|
+
|
|
|
+// server.getGroupApi().addMember(group.getId(), userId, 50);
|
|
|
+
|
|
|
+ return gitlabGroup;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void addMemberToGroup(Integer groupId, Integer userId) throws GitLabApiException {
|
|
|
+ server.getGroupApi().addMember(groupId, userId, AccessLevel.MASTER);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer addProjectToGroup(Integer groupId, String projectName) throws GitLabApiException {
|
|
|
+ final Project project = server.getProjectApi().createProject(groupId, projectName);
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer fetchNamespace(String username) throws GitLabApiException {
|
|
|
+ Namespace namespace;
|
|
|
+ namespace = server.getNamespaceApi().findNamespaces(username)
|
|
|
+ .stream()
|
|
|
+ .filter(ns -> "user".equals(ns.getKind()))
|
|
|
+ .reduce((ns1, ns2) -> ns1.getId() > ns2.getId() ? ns1 : ns2)
|
|
|
+ .orElse(null);
|
|
|
+ return namespace != null ? namespace.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer fetchNamespace(String type, String name) throws GitLabApiException {
|
|
|
+ Namespace namespace;
|
|
|
+ namespace = server.getNamespaceApi().findNamespaces(name)
|
|
|
+ .stream()
|
|
|
+ .filter(ns -> type.equals(ns.getKind()))
|
|
|
+ .reduce((ns1, ns2) -> ns1.getId() > ns2.getId() ? ns1 : ns2)
|
|
|
+ .orElse(null);
|
|
|
+ return namespace != null ? namespace.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String createToken(int userId) throws GitLabApiException {
|
|
|
+ Scope[] scopes = new Scope[]{Scope.API};
|
|
|
+ ImpersonationToken token;
|
|
|
+ token = server.getUserApi().createImpersonationToken(userId, "AES-" + ToolKit.randomUUID(), null, scopes);
|
|
|
+ return token.getToken();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer createProject(String name) throws GitLabApiException {
|
|
|
+ Project project = new Project();
|
|
|
+ project.setName(name);
|
|
|
+ project.setVisibility(Visibility.INTERNAL);
|
|
|
+ project = server.getProjectApi().createProject(project);
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer createPrivateProject(String name) throws GitLabApiException {
|
|
|
+ Project project = new Project();
|
|
|
+ project.setName(name);
|
|
|
+ project.setVisibility(Visibility.PRIVATE);
|
|
|
+ project = server.getProjectApi().createProject(project);
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer createProjectForGroup(String name, int groupId) throws GitLabApiException {
|
|
|
+ Project project = server.getProjectApi().createProject(groupId, name);
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer forkProject(int userId, int projectId, int namespaceId) throws GitLabApiException {
|
|
|
+ Project project;
|
|
|
+ try {
|
|
|
+ server.setSudoAsId(userId);
|
|
|
+ project = server.getProjectApi().forkProject(projectId, namespaceId);
|
|
|
+ project.setVisibility(Visibility.PRIVATE);
|
|
|
+ project = server.getProjectApi().updateProject(project);
|
|
|
+ } finally {
|
|
|
+ server.unsudo();
|
|
|
+ }
|
|
|
+ if (project != null) {
|
|
|
+ createWebHook(project.getId());
|
|
|
+ }
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Set<String> compare(int projectId, String from, String to) throws GitLabApiException {
|
|
|
+ CompareResults compareResults = server.getRepositoryApi().compare(projectId, from, to);
|
|
|
+ return compareResults.getDiffs().stream()
|
|
|
+ .map(Diff::getNewPath)
|
|
|
+ .map(p -> {
|
|
|
+ int end = p.indexOf('/');
|
|
|
+ if (end == -1) {
|
|
|
+ end = p.length();
|
|
|
+ }
|
|
|
+ return p.substring(0, end);
|
|
|
+ })
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void createWebHook(int id) throws GitLabApiException {
|
|
|
+ String url = gitlab.getWebHookProxy() + "/internal/notify/webhook/" + id;
|
|
|
+ server.getProjectApi().addHook(id, url, true, false, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized void archiveProject(int projectId) throws GitLabApiException {
|
|
|
+ server.getProjectApi().archiveProject(projectId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized void changePassword(int userId, String password) throws GitLabApiException {
|
|
|
+ User user = server.getUserApi().getUser(userId);
|
|
|
+ server.getUserApi().modifyUser(user, password, user.getProjectsLimit());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized void deleteUser(int userId) throws GitLabApiException {
|
|
|
+ server.getUserApi().deleteUser(userId, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteProject(int projectId) throws GitLabApiException {
|
|
|
+ server.getProjectApi().deleteProject(projectId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得项目下的文件
|
|
|
+ *
|
|
|
+ * @param path 文件的相对路径
|
|
|
+ * @return 文件内容
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String getRepositoryFile(int projectId, String branch,
|
|
|
+ String path) throws GitLabApiException, UnsupportedEncodingException {
|
|
|
+ RepositoryFileApi repositoryFileApi = server.getRepositoryFileApi();
|
|
|
+ RepositoryFile repositoryFile = repositoryFileApi.getFile(path, projectId, branch);
|
|
|
+ if (repositoryFile != null) {
|
|
|
+ return new String(Base64.getDecoder().decode(repositoryFile.getContent()), StandardCharsets.UTF_8);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getRawRepositoryFile(int projectId, String commit,
|
|
|
+ String path) throws GitLabApiException, IOException {
|
|
|
+ RepositoryFileApi repositoryFileApi = server.getRepositoryFileApi();
|
|
|
+ InputStream repositoryFile = repositoryFileApi.getRawFile(projectId, commit, path);
|
|
|
+ InputStreamReader reader = new InputStreamReader(repositoryFile);
|
|
|
+ StringBuilder stringBuilder = new StringBuilder();
|
|
|
+ char[] content = new char[1024];
|
|
|
+ int readCount = 0;
|
|
|
+ while ((readCount = reader.read(content)) > 0) {
|
|
|
+ stringBuilder.append(Arrays.copyOfRange(content, 0, readCount));
|
|
|
+ }
|
|
|
+ return stringBuilder.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void createCommit(int projectId, String branch, String commitMessage, String email, String username,
|
|
|
+ List<CommitAction> actions) throws GitLabApiException {
|
|
|
+ CommitsApi commitsApi = server.getCommitsApi();
|
|
|
+ commitsApi.createCommit(projectId, branch, commitMessage, null, email, username, actions);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer getRootUserId() {
|
|
|
+ return gitlab.getUserId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Integer forkProjectForDocumentWork(int userId, int projectId,
|
|
|
+ int namespaceId) throws GitLabApiException {
|
|
|
+ Project project;
|
|
|
+ try {
|
|
|
+ server.setSudoAsId(userId);
|
|
|
+ project = server.getProjectApi().forkProject(projectId, namespaceId);
|
|
|
+ project.setVisibility(Visibility.PRIVATE);
|
|
|
+ project = server.getProjectApi().updateProject(project);
|
|
|
+ } finally {
|
|
|
+ server.unsudo();
|
|
|
+ }
|
|
|
+ if (project != null) {
|
|
|
+ String url = gitlab.getWebHookProxy() + "/internal/notify/webhook/document/" + project.getId();
|
|
|
+ server.getProjectApi().addHook(project, url, true, false, false);
|
|
|
+ }
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer forkProjectForCodeWork(int userId, int projectId, int namespaceId) throws GitLabApiException {
|
|
|
+ Project project;
|
|
|
+ try {
|
|
|
+ server.setSudoAsId(userId);
|
|
|
+ project = server.getProjectApi().forkProject(projectId, namespaceId);
|
|
|
+ project.setVisibility(Visibility.PRIVATE);
|
|
|
+ project = server.getProjectApi().updateProject(project);
|
|
|
+ } finally {
|
|
|
+ server.unsudo();
|
|
|
+ }
|
|
|
+ if (project != null) {
|
|
|
+ // TODO
|
|
|
+ String url_build = gitlab.getWebHookProxy() + "/internal/notify/webhook/code/build/" + project.getId();
|
|
|
+ server.getProjectApi().addHook(project, url_build, true, false, false);
|
|
|
+ // TODO
|
|
|
+ String url_test = gitlab.getWebHookProxy() + "/internal/notify/webhook/code/unit/" + project.getId();
|
|
|
+ server.getProjectApi().addHook(project, url_test, true, false, false);
|
|
|
+ }
|
|
|
+ return project != null ? project.getId() : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer forkProjectForDLWork(int baseRepoId, int namespaceId) throws GitLabApiException {
|
|
|
+ Project project;
|
|
|
+ ProjectApi projectApi = server.getProjectApi();
|
|
|
+ try {
|
|
|
+ server.setSudoAsId(getRootUserId());
|
|
|
+ project = projectApi.forkProject(baseRepoId, namespaceId);
|
|
|
+ project.setVisibility(Visibility.PRIVATE);
|
|
|
+ project = projectApi.updateProject(project);
|
|
|
+ } finally {
|
|
|
+ server.unsudo();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (project != null) {
|
|
|
+ Integer newProjectId = project.getId();
|
|
|
+ final String webHookUrl = gitlab.getWebHookProxy() + "/internal/notify/webhook/dlwork/" + newProjectId;
|
|
|
+ projectApi.addHook(project, webHookUrl, true, false, false);
|
|
|
+ return newProjectId;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CommitDetails getCommitMessage(int projectId, String commitHash) throws GitLabApiException {
|
|
|
+ CommitsApi commitsApi = server.getCommitsApi();
|
|
|
+ CommitDetails commitDetails = new CommitDetails();
|
|
|
+
|
|
|
+ commitDetails.setProjectId(projectId);
|
|
|
+ commitDetails.setCommitHash(commitHash);
|
|
|
+
|
|
|
+ Commit currentCommit = commitsApi.getCommit(projectId, commitHash);
|
|
|
+
|
|
|
+ RepositoryApi repositoryApi = server.getRepositoryApi();
|
|
|
+ List<Branch> branches = repositoryApi.getBranches(projectId);
|
|
|
+
|
|
|
+ branches.forEach(branch -> {
|
|
|
+ try {
|
|
|
+ List<Commit> commitList = commitsApi.getCommits(projectId, branch.getName(), null);
|
|
|
+ Commit theCommit = commitList.stream().filter(commit -> commit.getId().equals(currentCommit.getId()))
|
|
|
+ .findFirst().orElse(null);
|
|
|
+
|
|
|
+ if(theCommit!=null){
|
|
|
+ commitDetails.setBranch(branch.getName());
|
|
|
+ commitDetails.setCommitMessage(theCommit.getMessage());
|
|
|
+ commitDetails.setUrl(theCommit.getUrl());
|
|
|
+ Instant instant = theCommit.getCommittedDate().toInstant();
|
|
|
+ ZoneId zoneId = ZoneId.systemDefault();
|
|
|
+ LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
|
|
|
+ commitDetails.setTime(localDateTime);
|
|
|
+ commitDetails.setAuthor(theCommit.getAuthorName());
|
|
|
+ }
|
|
|
+ } catch (GitLabApiException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return commitDetails;
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public List<CommitDetails> getAllCommits(int projectId, String commitHash) throws GitLabApiException {
|
|
|
+ CommitsApi commitsApi = server.getCommitsApi();
|
|
|
+ List<CommitDetails> list = new ArrayList<>();
|
|
|
+
|
|
|
+ Commit currentCommit = commitsApi.getCommit(projectId, commitHash);
|
|
|
+
|
|
|
+ RepositoryApi repositoryApi = server.getRepositoryApi();
|
|
|
+ List<Branch> branches = repositoryApi.getBranches(projectId);
|
|
|
+
|
|
|
+ branches.forEach(branch -> {
|
|
|
+ try {
|
|
|
+ List<Commit> commitList = commitsApi.getCommits(projectId, branch.getName(), null);
|
|
|
+ Commit theCommit = commitList.stream().filter(commit -> commit.getId().equals(currentCommit.getId()))
|
|
|
+ .findFirst().orElse(null);
|
|
|
+
|
|
|
+ if(theCommit != null){
|
|
|
+ CommitDetails commitDetails = new CommitDetails();
|
|
|
+ commitDetails.setProjectId(projectId);
|
|
|
+ commitDetails.setCommitHash(commitHash);
|
|
|
+ commitDetails.setBranch(branch.getName());
|
|
|
+ commitDetails.setCommitMessage(theCommit.getMessage());
|
|
|
+
|
|
|
+ Instant instant = theCommit.getCommittedDate().toInstant();
|
|
|
+ ZoneId zoneId = ZoneId.systemDefault();
|
|
|
+ LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
|
|
|
+ commitDetails.setTime(localDateTime);
|
|
|
+ commitDetails.setAuthor(theCommit.getAuthorName());
|
|
|
+ list.add(commitDetails);
|
|
|
+ }
|
|
|
+ } catch (GitLabApiException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+}
|