rename com.imyeyu.server to com.imyeyu.api
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.imyeyu.api.modules.git.bean;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2024-02-21 17:10
|
||||
*/
|
||||
public enum AttachType {
|
||||
|
||||
ISSUE,
|
||||
|
||||
MERGE,
|
||||
|
||||
RELEASE
|
||||
}
|
||||
25
src/main/java/com/imyeyu/api/modules/git/bean/GitCommit.java
Normal file
25
src/main/java/com/imyeyu/api/modules/git/bean/GitCommit.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.imyeyu.api.modules.git.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import com.imyeyu.api.modules.common.vo.user.UserView;
|
||||
|
||||
/**
|
||||
* Git 提交信息
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-14 17:13
|
||||
*/
|
||||
@Data
|
||||
public class GitCommit {
|
||||
|
||||
/** ID */
|
||||
private String id;
|
||||
|
||||
/** 说明 */
|
||||
private String msg;
|
||||
|
||||
/** 时间 */
|
||||
private long time;
|
||||
|
||||
private UserView committer;
|
||||
}
|
||||
59
src/main/java/com/imyeyu/api/modules/git/bean/gitea/API.java
Normal file
59
src/main/java/com/imyeyu/api/modules/git/bean/gitea/API.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.imyeyu.api.modules.git.bean.gitea;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.api.TimiServerAPI;
|
||||
import com.imyeyu.api.modules.common.bean.SettingKey;
|
||||
import com.imyeyu.api.modules.common.service.SettingService;
|
||||
import com.imyeyu.utils.Encoder;
|
||||
import com.imyeyu.utils.StringInterpolator;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-06-26 16:04
|
||||
*/
|
||||
public enum API {
|
||||
|
||||
REPO_LIST("/api/v1/repos/search"),
|
||||
|
||||
REPO_GET("/api/v1/repos/{owner}/{repoName}"),
|
||||
|
||||
REPO_BRANCHES_LIST("/api/v1/repos/{owner}/{repoName}/branches"),
|
||||
|
||||
REPO_FILE_LIST("/api/v1/repos/{owner}/{repoName}/contents/{path}"),
|
||||
|
||||
REPO_FILE_RAW("/api/v1/repos/{owner}/{repoName}/raw/{path}"),
|
||||
|
||||
REPO_ARCHIVE("/api/v1/repos/{owner}/{repoName}/archive/{archiveFormat}"),
|
||||
|
||||
REPO_COMMIT_LIST("/api/v1/repos/{owner}/{repoName}/commits"),
|
||||
|
||||
REPO_LANGUAGES("/api/v1/repos/{owner}/{repoName}/languages")
|
||||
;
|
||||
|
||||
static final StringInterpolator INTERPOLATOR = new StringInterpolator(StringInterpolator.SIMPLE_OBJ);
|
||||
|
||||
final String uri;
|
||||
|
||||
API(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String buildURL(Map<String, Object> argsURI) {
|
||||
return buildURL(argsURI, null);
|
||||
|
||||
}
|
||||
|
||||
public String buildURL(Map<String, Object> argsURI, Map<String, Object> argsURL) {
|
||||
SettingService settingService = TimiServerAPI.applicationContext.getBean(SettingService.class);
|
||||
StringBuilder url = new StringBuilder();
|
||||
url.append(settingService.getAsString(SettingKey.GIT_API));
|
||||
url.append(INTERPOLATOR.inject(uri, argsURI));
|
||||
if (TimiJava.isNotEmpty(argsURL)) {
|
||||
url.append("?");
|
||||
url.append(Encoder.urlArgs(argsURL));
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.imyeyu.api.modules.git.bean.gitea;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-06-28 00:31
|
||||
*/
|
||||
@Data
|
||||
public class Branch {
|
||||
|
||||
private String name;
|
||||
|
||||
@SerializedName("protected")
|
||||
private boolean isProtected;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.imyeyu.api.modules.git.bean.gitea;
|
||||
|
||||
import com.google.gson.annotations.JsonAdapter;
|
||||
import com.imyeyu.api.modules.git.util.GiteaTimestampAdapter;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-06-29 18:43
|
||||
*/
|
||||
@Data
|
||||
public class File {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2025-06-29 19:00
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
file,
|
||||
|
||||
dir
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
private String path;
|
||||
|
||||
private String sha;
|
||||
|
||||
private Long size;
|
||||
|
||||
private Type type;
|
||||
|
||||
private String lastCommitSha;
|
||||
|
||||
@JsonAdapter(GiteaTimestampAdapter.class)
|
||||
private Long lastCommitterDate;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.imyeyu.api.modules.git.bean.gitea;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-07-08 15:05
|
||||
*/
|
||||
@Data
|
||||
public class GiteaResponse<T> {
|
||||
|
||||
private boolean ok;
|
||||
private T data;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.imyeyu.api.modules.git.bean.gitea;
|
||||
|
||||
import com.google.gson.annotations.JsonAdapter;
|
||||
import com.imyeyu.api.modules.git.util.GiteaTimestampAdapter;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-06-26 11:45
|
||||
*/
|
||||
@Data
|
||||
public class Repository {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String fullName;
|
||||
|
||||
private String description;
|
||||
|
||||
private Integer size;
|
||||
|
||||
private String language;
|
||||
|
||||
private String sshUrl;
|
||||
|
||||
private String cloneUrl;
|
||||
|
||||
private String avatarUrl;
|
||||
|
||||
private String defaultBranch;
|
||||
|
||||
private Boolean archived;
|
||||
|
||||
@JsonAdapter(GiteaTimestampAdapter.class)
|
||||
private Long createdAt;
|
||||
|
||||
@JsonAdapter(GiteaTimestampAdapter.class)
|
||||
private Long updatedAt;
|
||||
|
||||
@JsonAdapter(GiteaTimestampAdapter.class)
|
||||
private Long archivedAt;
|
||||
|
||||
private List<String> licenses;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.imyeyu.api.modules.git.bean.hook;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-18 10:13
|
||||
*/
|
||||
@Data
|
||||
public class PostReceive {
|
||||
|
||||
private String pusherName;
|
||||
|
||||
private String repositoryName;
|
||||
|
||||
private String branch;
|
||||
|
||||
private String fromSHA1;
|
||||
|
||||
private String toSHA1;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.imyeyu.api.modules.git.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.imyeyu.api.annotation.EnableSetting;
|
||||
import com.imyeyu.api.modules.common.bean.SettingKey;
|
||||
import com.imyeyu.api.modules.git.entity.Developer;
|
||||
import com.imyeyu.api.modules.git.service.DeveloperService;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.annotation.RequiredToken;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 13:48
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/git/developer")
|
||||
public class DeveloperController {
|
||||
|
||||
private final DeveloperService service;
|
||||
|
||||
@AOPLog
|
||||
@RequiredToken
|
||||
@RequestRateLimit
|
||||
@PostMapping("")
|
||||
public Developer view() {
|
||||
return service.view();
|
||||
}
|
||||
|
||||
@AOPLog
|
||||
@RequiredToken
|
||||
@EnableSetting(value = SettingKey.ENABLE_USER_UPDATE, message = "user.data.off_service")
|
||||
@RequestRateLimit
|
||||
@PostMapping("/update")
|
||||
public void update(@RequestBody Developer developer) {
|
||||
service.update(developer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.imyeyu.api.modules.git.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.api.annotation.CaptchaValid;
|
||||
import com.imyeyu.api.bean.CaptchaFrom;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||
import com.imyeyu.api.modules.common.service.CommentService;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.service.IssueService;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssuePage;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssueRequest;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssueView;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.annotation.RequiredToken;
|
||||
import com.imyeyu.spring.bean.CaptchaData;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Git 反馈接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-15 15:02
|
||||
*/
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/git/issue")
|
||||
public class IssueController {
|
||||
|
||||
private final UserService userService;
|
||||
private final IssueService service;
|
||||
private final CommentService commentService;
|
||||
private final AttachmentService attachmentService;
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*
|
||||
* @param id 反馈 ID
|
||||
* @return 反馈数据
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{id}")
|
||||
public IssueView view(@Min(1) @NotNull @PathVariable Long id) {
|
||||
Issue issue = service.get(id);
|
||||
IssueView view = new IssueView();
|
||||
BeanUtils.copyProperties(issue, view);
|
||||
if (TimiJava.isNotEmpty(issue.getPublisherId())) {
|
||||
view.setPublisher(userService.view(issue.getPublisherId()));
|
||||
}
|
||||
view.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GIT, id));
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取反馈列表
|
||||
*
|
||||
* @param issuePage 反馈页面参数
|
||||
* @return 反馈列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<Issue> page(@Valid @RequestBody IssuePage issuePage) {
|
||||
return service.page(issuePage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建反馈,不需要登录
|
||||
*
|
||||
* @param captchaData 反馈请求
|
||||
*/
|
||||
@AOPLog
|
||||
@CaptchaValid(CaptchaFrom.GIT_ISSUE)
|
||||
@RequestRateLimit
|
||||
@PostMapping("/create")
|
||||
public void create(@Valid @RequestBody CaptchaData<IssueRequest> captchaData) {
|
||||
service.create(captchaData.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改反馈,非讨论类型和未完成的反馈可以修改
|
||||
*
|
||||
* @param issueRequest 修改反馈请求
|
||||
*/
|
||||
@AOPLog
|
||||
@RequiredToken
|
||||
@RequestRateLimit
|
||||
@PostMapping("/update")
|
||||
public void update(@Valid @RequestBody IssueRequest issueRequest) {
|
||||
service.update(issueRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.imyeyu.api.modules.git.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.api.annotation.CaptchaValid;
|
||||
import com.imyeyu.api.bean.CaptchaFrom;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
import com.imyeyu.api.modules.git.service.IssueService;
|
||||
import com.imyeyu.api.modules.git.service.MergeService;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergePage;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergeRequest;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergeView;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.annotation.RequiredToken;
|
||||
import com.imyeyu.spring.bean.CaptchaData;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 和并请求接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-15 15:02
|
||||
*/
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/git/merge")
|
||||
public class MergeController {
|
||||
|
||||
private final UserService userService;
|
||||
private final MergeService service;
|
||||
private final IssueService issueService;
|
||||
private final AttachmentService attachmentService;
|
||||
|
||||
/**
|
||||
* 合并请求详情
|
||||
*
|
||||
* @param id 和并请求 ID
|
||||
* @return 详情数据
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{id}")
|
||||
public MergeView view(@Min(1) @NotNull @PathVariable Long id) {
|
||||
Merge merge = service.get(id);
|
||||
MergeView view = new MergeView();
|
||||
BeanUtils.copyProperties(merge, view);
|
||||
if (TimiJava.isNotEmpty(view.getIssueId())) {
|
||||
view.setIssue(issueService.get(view.getIssueId()));
|
||||
}
|
||||
view.setRequester(userService.view(view.getRequesterId()));
|
||||
view.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.GIT, id));
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合并请求列表
|
||||
*
|
||||
* @param mergePage 页面参数
|
||||
* @return 列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<Merge> page(@Valid @RequestBody MergePage mergePage) {
|
||||
return service.page(mergePage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请合并请求
|
||||
*
|
||||
* @param captchaData 申请数据
|
||||
*/
|
||||
@AOPLog
|
||||
@CaptchaValid(CaptchaFrom.GIT_MERGE)
|
||||
@RequiredToken
|
||||
@RequestRateLimit
|
||||
@PostMapping("/create")
|
||||
public void create(@Valid @RequestBody CaptchaData<MergeRequest> captchaData) {
|
||||
service.create(captchaData.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改合并请求
|
||||
*
|
||||
* @param mergeRequest 修改数据
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@RequiredToken
|
||||
@PostMapping("/update")
|
||||
public void update(@Valid @RequestBody MergeRequest mergeRequest) {
|
||||
service.update(mergeRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.imyeyu.api.modules.git.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.imyeyu.api.modules.git.service.ReleaseService;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleasePage;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleaseView;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Git 项目版本发布接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:25
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/git/release")
|
||||
public class ReleaseController {
|
||||
|
||||
private final ReleaseService service;
|
||||
|
||||
/**
|
||||
* 获取版本发布列表
|
||||
*
|
||||
* @param releasePage 版本发布页面参数
|
||||
* @return 版本发布列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<ReleaseView> page(@Valid @RequestBody ReleasePage releasePage) {
|
||||
return service.pageByRepositoryId(releasePage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.imyeyu.api.modules.git.controller;
|
||||
|
||||
import com.imyeyu.io.IO;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.network.Network;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.File;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Repository;
|
||||
import com.imyeyu.api.modules.git.service.RepositoryService;
|
||||
import com.imyeyu.api.modules.git.vo.repository.RepositoryView;
|
||||
import com.imyeyu.api.modules.gitea.service.GiteaService;
|
||||
import com.imyeyu.api.modules.gitea.vo.ActionLogView;
|
||||
import com.imyeyu.spring.TimiSpring;
|
||||
import com.imyeyu.spring.annotation.AOPLog;
|
||||
import com.imyeyu.spring.annotation.IgnoreGlobalReturn;
|
||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Git 仓库接口
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-06 01:19
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/git/repository")
|
||||
public class RepositoryController {
|
||||
|
||||
private final GiteaService giteaService;
|
||||
private final RepositoryService service;
|
||||
|
||||
|
||||
@RequestRateLimit
|
||||
@PostMapping("/log")
|
||||
public PageResult<ActionLogView> pagePush(@Valid @RequestBody Page page) {
|
||||
return giteaService.pagePush(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看仓库
|
||||
*
|
||||
* @param name 仓库 ID
|
||||
* @return 仓库数据
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{name}")
|
||||
public RepositoryView view(@PathVariable String name) {
|
||||
Repository source = service.get(name);
|
||||
RepositoryView view = new RepositoryView();
|
||||
BeanUtils.copyProperties(source, view);
|
||||
view.setBranchList(service.listBranches(name));
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库列表
|
||||
*
|
||||
* @param page 页面参数
|
||||
* @return 仓库列表
|
||||
*/
|
||||
@RequestRateLimit
|
||||
@PostMapping("/list")
|
||||
public PageResult<Repository> page(@Valid @RequestBody Page page) {
|
||||
return service.page(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库文件结构树
|
||||
*
|
||||
* @param repoName 仓库名称
|
||||
* @param branch 分支名称
|
||||
* @return 文件结构树
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit(20)
|
||||
@RequestMapping("/{repoName}:{branch}/file/list/**")
|
||||
public List<File> listFile(@PathVariable String repoName, @PathVariable String branch) {
|
||||
return service.listFile(repoName, branch, TimiSpring.cutURIStartAt("/file/list/"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载仓库文件,/request/raw/ 后的路径为加载目标文件的绝对仓库路径
|
||||
*
|
||||
* @param repositoryName 仓库名称
|
||||
* @param branch 分支名称
|
||||
* @param resp 返回体
|
||||
*/
|
||||
@RequestRateLimit
|
||||
@IgnoreGlobalReturn
|
||||
@GetMapping("/{repositoryName}:{branch}/file/raw/**")
|
||||
public void raw(@PathVariable String repositoryName, @PathVariable String branch, HttpServletResponse resp) {
|
||||
try {
|
||||
String path = TimiSpring.cutURIStartAt("/file/raw");
|
||||
if (TimiJava.isEmpty(path)) {
|
||||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
resp.setCharacterEncoding(StandardCharsets.UTF_8.toString());
|
||||
} else {
|
||||
resp.setContentType(service.getFileMimeType(repositoryName, branch, path));
|
||||
IO.toOutputStream(service.getFileRaw(repositoryName, branch, path), resp.getOutputStream());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
resp.setCharacterEncoding(StandardCharsets.UTF_8.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件 MimeType
|
||||
*
|
||||
* @param repositoryName 仓库名称
|
||||
* @param branch 分支名称
|
||||
*/
|
||||
@RequestRateLimit
|
||||
@GetMapping("/{repositoryName}:{branch}/file/mime/**")
|
||||
public String mimeType(@PathVariable String repositoryName, @PathVariable String branch) {
|
||||
return service.getFileMimeType(repositoryName, branch, TimiSpring.cutURIStartAt("/file/mime"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取仓库提交消息列表
|
||||
*
|
||||
* @param page 提交消息页面参数
|
||||
* @return 提交消息列表
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@PostMapping("/{repositoryName}:{branch}/log/push")
|
||||
public PageResult<ActionLogView> pagePush(@PathVariable String repositoryName, @PathVariable String branch, @Valid @RequestBody Page page) {
|
||||
if (branch.equals("all")) {
|
||||
branch = null;
|
||||
}
|
||||
return giteaService.pagePush(repositoryName, branch, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包下载仓库源码文件
|
||||
*
|
||||
* @param repositoryName 仓库名称
|
||||
* @param branch 分支名称
|
||||
* @param resp 返回体
|
||||
*/
|
||||
@AOPLog
|
||||
@RequestRateLimit
|
||||
@RequestMapping("/{repositoryName}:{branch}/archive")
|
||||
public void downloadArchive(@PathVariable String repositoryName, @PathVariable String branch, HttpServletResponse resp) {
|
||||
try {
|
||||
resp.setHeader("Content-Disposition", Network.getFileDownloadHeader("%s-%s.tar.gz".formatted(repositoryName.toLowerCase(), branch)));
|
||||
resp.setHeader("Accept-Ranges", "bytes");
|
||||
IO.toOutputStream(service.getArchive(repositoryName, branch), resp.getOutputStream());
|
||||
resp.flushBuffer();
|
||||
} catch (Exception e) {
|
||||
log.error("downloadArchive error", e);
|
||||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
resp.setCharacterEncoding(StandardCharsets.UTF_8.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.Id;
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import com.imyeyu.spring.entity.Creatable;
|
||||
import com.imyeyu.spring.entity.IDEntity;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 提交日志
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:34
|
||||
*/
|
||||
@Data
|
||||
@Table("git_commit_log")
|
||||
public class CommitLog implements IDEntity<Long>, Creatable {
|
||||
|
||||
@Id
|
||||
protected Long id;
|
||||
|
||||
/** 所属推送 ID */
|
||||
protected Long pushId;
|
||||
|
||||
/** SHA1 */
|
||||
protected String sha1;
|
||||
|
||||
/** 说明 */
|
||||
protected String message;
|
||||
|
||||
/** 提交时间 */
|
||||
protected Long createdAt;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.api.modules.common.entity.User;
|
||||
import com.imyeyu.spring.annotation.table.Id;
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import com.imyeyu.spring.entity.Updatable;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 开发者
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:37
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Table("git_developer")
|
||||
public class Developer implements Updatable {
|
||||
|
||||
/** 开发者 ID({@link User#getId()}) */
|
||||
@Id
|
||||
protected Long developerId;
|
||||
|
||||
/** 昵称 */
|
||||
protected String name;
|
||||
|
||||
/** RSA 密钥 */
|
||||
protected String rsa;
|
||||
|
||||
/** 更新时间 */
|
||||
protected Long updatedAt;
|
||||
|
||||
public Developer(Long developerId) {
|
||||
this.developerId = developerId;
|
||||
}
|
||||
}
|
||||
120
src/main/java/com/imyeyu/api/modules/git/entity/Issue.java
Normal file
120
src/main/java/com/imyeyu/api/modules/git/entity/Issue.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.bean.CommentSupport;
|
||||
import com.imyeyu.spring.entity.Entity;
|
||||
|
||||
/**
|
||||
* Git 问题反馈
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 15:18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("git_issue")
|
||||
public class Issue extends Entity implements CommentSupport {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 17:18
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
/** 异常 */
|
||||
BUG,
|
||||
|
||||
/** 功能 */
|
||||
FEATURE,
|
||||
|
||||
/** 安全 */
|
||||
SECURITY,
|
||||
|
||||
/** 提问 */
|
||||
QUESTION,
|
||||
|
||||
/** 讨论 */
|
||||
DISCUSS
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 15:26
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
/** 待确认 */
|
||||
BEFORE_CONFIRM,
|
||||
|
||||
/** 已确认,待开发 */
|
||||
CONFIRMED,
|
||||
|
||||
/** 开发中 */
|
||||
DEVELOPING,
|
||||
|
||||
/** 已完成 */
|
||||
FINISHED,
|
||||
|
||||
/** 已关闭 */
|
||||
CLOSED
|
||||
}
|
||||
|
||||
/** 所属仓库 ID */
|
||||
protected long repositoryId;
|
||||
|
||||
/** 发布者 ID */
|
||||
protected Long publisherId;
|
||||
|
||||
/** 发布者昵称 */
|
||||
protected String publisherNick;
|
||||
|
||||
/** 类型 */
|
||||
protected Type type;
|
||||
|
||||
/** 版本 */
|
||||
protected String version;
|
||||
|
||||
/** 标题 */
|
||||
protected String title;
|
||||
|
||||
/** 描述 */
|
||||
protected String description;
|
||||
|
||||
/** 状态 */
|
||||
protected Status status;
|
||||
|
||||
/** 确认时间 */
|
||||
protected Long confirmedAt;
|
||||
|
||||
/** 开发时间 */
|
||||
protected Long developAt;
|
||||
|
||||
/** 关闭时间 */
|
||||
protected Long closedAt;
|
||||
|
||||
@Override
|
||||
public boolean canComment() {
|
||||
return status != Status.CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNotComment() {
|
||||
return !canComment();
|
||||
}
|
||||
|
||||
/** @return true 为可更新 */
|
||||
public boolean canUpdate() {
|
||||
return type != Type.DISCUSS && !isClosed() && status != Status.FINISHED;
|
||||
}
|
||||
|
||||
/** @return true 为已关闭 */
|
||||
public boolean isClosed() {
|
||||
return closedAt != null;
|
||||
}
|
||||
}
|
||||
133
src/main/java/com/imyeyu/api/modules/git/entity/Merge.java
Normal file
133
src/main/java/com/imyeyu/api/modules/git/entity/Merge.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.bean.CommentSupport;
|
||||
import com.imyeyu.spring.entity.Entity;
|
||||
|
||||
/**
|
||||
* 合并请求
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 14:52
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("git_merge")
|
||||
public class Merge extends Entity implements CommentSupport {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:32
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
/** 异常 */
|
||||
BUG,
|
||||
|
||||
/** 功能 */
|
||||
FEATURE,
|
||||
|
||||
/** 安全 */
|
||||
SECURITY,
|
||||
|
||||
/** 文档改进 */
|
||||
DOCUMENT,
|
||||
|
||||
/** 重构 */
|
||||
REFACTOR
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:33
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
/** 等待代码审查 */
|
||||
BEFORE_CHECK,
|
||||
|
||||
/** 等待合并 */
|
||||
WAITING,
|
||||
|
||||
/** 已合并 */
|
||||
MERGED,
|
||||
|
||||
/** 已拒绝 */
|
||||
REJECTED,
|
||||
|
||||
CLOSED
|
||||
}
|
||||
|
||||
/** 所属仓库 ID */
|
||||
protected long repositoryId;
|
||||
|
||||
/** 申请合并用户 ID */
|
||||
protected long requesterId;
|
||||
|
||||
/** 相关反馈 ID */
|
||||
protected Long issueId;
|
||||
|
||||
/** 类型 */
|
||||
protected Type type;
|
||||
|
||||
/** 来自分支 */
|
||||
protected String fromBranch;
|
||||
|
||||
/** 去向分支(基准分支) */
|
||||
protected String toBranch;
|
||||
|
||||
/** 说明标题 */
|
||||
protected String title;
|
||||
|
||||
/** 合并说明 */
|
||||
protected String description;
|
||||
|
||||
/** 通过审查时间 */
|
||||
protected Long checkedAt;
|
||||
|
||||
/** 合并时间 */
|
||||
protected Long mergedAt;
|
||||
|
||||
/** 拒绝时间 */
|
||||
protected Long rejectedAt;
|
||||
|
||||
/** 拒绝原因 */
|
||||
protected String rejectReason;
|
||||
|
||||
/** 关闭时间 */
|
||||
protected Long closedAt;
|
||||
|
||||
/** 请求状态 */
|
||||
protected Status status;
|
||||
|
||||
@Override
|
||||
public boolean canComment() {
|
||||
return status != Status.CLOSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNotComment() {
|
||||
return !canComment();
|
||||
}
|
||||
|
||||
/** @return true 为可更新 */
|
||||
public boolean canUpdate() {
|
||||
return status == Status.BEFORE_CHECK && !isClosed();
|
||||
}
|
||||
|
||||
/** @return true 为可更新 */
|
||||
public boolean canNotUpdate() {
|
||||
return !canUpdate();
|
||||
}
|
||||
|
||||
/** @return true 为已关闭 */
|
||||
public boolean isClosed() {
|
||||
return closedAt != null;
|
||||
}
|
||||
}
|
||||
39
src/main/java/com/imyeyu/api/modules/git/entity/PushLog.java
Normal file
39
src/main/java/com/imyeyu/api/modules/git/entity/PushLog.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.Id;
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import com.imyeyu.spring.entity.Creatable;
|
||||
import com.imyeyu.spring.entity.IDEntity;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Git 推送日志
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:35
|
||||
*/
|
||||
@Data
|
||||
@Table("git_push_log")
|
||||
public class PushLog implements IDEntity<Long>, Creatable {
|
||||
|
||||
@Id
|
||||
protected Long id;
|
||||
|
||||
/** 所属仓库 ID */
|
||||
protected Long repositoryId;
|
||||
|
||||
/** 推送 ID */
|
||||
protected Long pusherId;
|
||||
|
||||
/** 分支 */
|
||||
protected String branch;
|
||||
|
||||
/** 来源提交 */
|
||||
protected String from;
|
||||
|
||||
/** 去向提交 */
|
||||
protected String to;
|
||||
|
||||
/** 推送时间 */
|
||||
protected Long createdAt;
|
||||
}
|
||||
33
src/main/java/com/imyeyu/api/modules/git/entity/Release.java
Normal file
33
src/main/java/com/imyeyu/api/modules/git/entity/Release.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.imyeyu.api.modules.git.entity;
|
||||
|
||||
import com.imyeyu.spring.annotation.table.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.spring.entity.Entity;
|
||||
|
||||
/**
|
||||
* Git 版本发布
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("git_release")
|
||||
public class Release extends Entity {
|
||||
|
||||
/** 所属仓库 ID */
|
||||
protected long repositoryId;
|
||||
|
||||
/** 版本 */
|
||||
protected String version;
|
||||
|
||||
/** 描述 */
|
||||
protected String description;
|
||||
|
||||
/** SHA1 */
|
||||
protected String sha1;
|
||||
|
||||
/** 发布时提交数量 */
|
||||
protected int commits;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.imyeyu.api.modules.git.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Developer;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:42
|
||||
*/
|
||||
public interface DeveloperMapper extends BaseMapper<Developer, Long> {
|
||||
|
||||
@Select("SELECT * FROM git_developer WHERE BINARY name = #{name} LIMIT 1")
|
||||
Developer queryByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.imyeyu.api.modules.git.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssuePage;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Git 反馈表
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 15:19
|
||||
*/
|
||||
public interface IssueMapper extends BaseMapper<Issue, Long> {
|
||||
|
||||
/**
|
||||
* 根据仓库 ID 统计总反馈数量
|
||||
*
|
||||
* @param issuePage 仓库 ID
|
||||
* @return 仓库反馈总数量
|
||||
*/
|
||||
long countByIssuePage(@Param("issuePage") IssuePage issuePage);
|
||||
|
||||
/**
|
||||
* 根据仓库 ID 查询部分反馈
|
||||
*
|
||||
* @param issuePage 仓库 ID
|
||||
* @param offset 偏移
|
||||
* @param limit 数据量
|
||||
* @return 反馈列表
|
||||
*/
|
||||
List<Issue> listByIssuePage(@Param("issuePage") IssuePage issuePage, long offset, int limit);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.imyeyu.api.modules.git.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergePage;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:42
|
||||
*/
|
||||
public interface MergeMapper extends BaseMapper<Merge, Long> {
|
||||
|
||||
@Select("SELECT * FROM git_merge WHERE id = #{id}" + NOT_DELETE + LIMIT_1)
|
||||
Merge select(Long id);
|
||||
|
||||
long countByMergePage(@Param("mergePage") MergePage mergePage);
|
||||
|
||||
List<Merge> listByMergePage(@Param("mergePage") MergePage mergePage, long offset, int limit);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.imyeyu.api.modules.git.mapper;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Release;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleaseView;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:30
|
||||
*/
|
||||
public interface ReleaseMapper extends BaseMapper<Release, Long> {
|
||||
|
||||
@Select("SELECT COUNT(1) FROM git_release WHERE repository_id = #{repositoryId}" + NOT_DELETE)
|
||||
long countByRepositoryId(long repositoryId);
|
||||
|
||||
List<ReleaseView> listByRepositoryId(long repositoryId, long offset, int limit);
|
||||
|
||||
@Select("SELECT * FROM git_release WHERE repository_id = #{repositoryId}" + NOT_DELETE + "ORDER BY created_at DESC" + LIMIT_1)
|
||||
Release queryLatestByRepositoryId(long repositoryId);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.imyeyu.api.modules.git.service;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Developer;
|
||||
import com.imyeyu.spring.service.CreatableService;
|
||||
import com.imyeyu.spring.service.GettableService;
|
||||
import com.imyeyu.spring.service.UpdatableService;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:40
|
||||
*/
|
||||
public interface DeveloperService extends GettableService<Developer, Long>, CreatableService<Developer>, UpdatableService<Developer> {
|
||||
|
||||
Developer view();
|
||||
|
||||
Developer getByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.imyeyu.api.modules.git.service;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssuePage;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssueRequest;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import com.imyeyu.spring.service.GettableService;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 15:18
|
||||
*/
|
||||
public interface IssueService extends GettableService<Issue, Long> {
|
||||
|
||||
void create(IssueRequest issueRequest);
|
||||
|
||||
void update(IssueRequest issueRequest);
|
||||
|
||||
PageResult<Issue> page(IssuePage issuePage);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.imyeyu.api.modules.git.service;
|
||||
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergePage;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergeRequest;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import com.imyeyu.spring.service.GettableService;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 14:46
|
||||
*/
|
||||
public interface MergeService extends GettableService<Merge, Long> {
|
||||
|
||||
void create(MergeRequest mergeRequest);
|
||||
|
||||
void update(MergeRequest mergeRequest);
|
||||
|
||||
PageResult<Merge> page(MergePage mergePage);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.imyeyu.api.modules.git.service;
|
||||
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleasePage;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleaseView;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:27
|
||||
*/
|
||||
public interface ReleaseService {
|
||||
|
||||
PageResult<ReleaseView> pageByRepositoryId(ReleasePage releasePage);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.imyeyu.api.modules.git.service;
|
||||
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Branch;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.File;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Repository;
|
||||
import com.imyeyu.spring.service.PageableService;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Git 仓库服务
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-06 01:19
|
||||
*/
|
||||
public interface RepositoryService extends PageableService<Repository> {
|
||||
|
||||
/**
|
||||
* 根据名称获取数据库仓库
|
||||
*
|
||||
* @param repoName 仓库名
|
||||
* @return 数据库仓库
|
||||
* @throws TimiException 服务异常
|
||||
*/
|
||||
Repository get(String repoName);
|
||||
/**
|
||||
* 获取仓库所有分支列表
|
||||
*
|
||||
* @param repoName 仓库名
|
||||
* @return 分支列表
|
||||
* @throws TimiException 服务异常
|
||||
*/
|
||||
List<Branch> listBranches(String repoName);
|
||||
|
||||
List<File> listFile(String repoName, String branch, String path);
|
||||
|
||||
InputStream getFileRaw(String repoName, String branch, String path);
|
||||
|
||||
String getFileMimeType(String repoName, String branch, String path);
|
||||
|
||||
InputStream getArchive(String repoName, String branch);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.imyeyu.api.modules.git.service.implement;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiCode;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.entity.Developer;
|
||||
import com.imyeyu.api.modules.git.mapper.DeveloperMapper;
|
||||
import com.imyeyu.api.modules.git.service.DeveloperService;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:41
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor(onConstructor_ = { @Lazy})
|
||||
public class DeveloperServiceImplement extends AbstractEntityService<Developer, Long> implements DeveloperService {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
private final DeveloperMapper mapper;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<Developer, Long> mapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void update(Developer developer) {
|
||||
Developer dbDeveloper = get(userService.getLoginUser().getId());
|
||||
dbDeveloper.setName(developer.getName());
|
||||
dbDeveloper.setRsa(developer.getRsa());
|
||||
|
||||
if (TimiJava.isNotEmpty(dbDeveloper.getName())) {
|
||||
Developer developerByName = getByName(dbDeveloper.getName());
|
||||
if (developerByName != null && !developerByName.getDeveloperId().equals(dbDeveloper.getDeveloperId())) {
|
||||
throw new TimiException(TimiCode.ARG_BAD).msgKey("TODO 开发者冲突,此名称已被使用");
|
||||
}
|
||||
}
|
||||
if (TimiJava.isNotEmpty(dbDeveloper.getRsa())) {
|
||||
if (!dbDeveloper.getRsa().startsWith("ssh-rsa")) {
|
||||
throw new TimiException(TimiCode.ARG_BAD).msgKey("TODO 无效的 RSA 公钥");
|
||||
}
|
||||
}
|
||||
super.update(dbDeveloper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Developer view() {
|
||||
return get(userService.getLoginUser().getId());
|
||||
}
|
||||
|
||||
public Developer getByName(String name) {
|
||||
return mapper.queryByName(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.imyeyu.api.modules.git.service.implement;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||
import com.imyeyu.api.modules.common.entity.User;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.mapper.IssueMapper;
|
||||
import com.imyeyu.api.modules.git.service.IssueService;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssuePage;
|
||||
import com.imyeyu.api.modules.git.vo.issue.IssueRequest;
|
||||
import com.imyeyu.api.modules.gitea.entity.Repository;
|
||||
import com.imyeyu.api.modules.gitea.service.GiteaService;
|
||||
import com.imyeyu.spring.TimiSpring;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Git 反馈服务
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 15:18
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class IssueServiceImplement extends AbstractEntityService<Issue, Long> implements IssueService {
|
||||
|
||||
private final UserService userService;
|
||||
private final GiteaService giteaService;
|
||||
|
||||
private final IssueMapper mapper;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<Issue, Long> mapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void create(IssueRequest issueRequest) {
|
||||
Repository repository = giteaService.getRepository(issueRequest.getRepositoryId());
|
||||
Issue issue = new Issue();
|
||||
// 令牌和账号验证
|
||||
if (TimiJava.isNotEmpty(TimiSpring.getToken())) {
|
||||
User publisher = userService.getLoginUser();
|
||||
TimiException.requiredTrue(!publisher.isBanning() && !publisher.isMuting(), "TODO publisher.banned");
|
||||
issue.setPublisherId(publisher.getId());
|
||||
issue.setPublisherNick(null);
|
||||
} else {
|
||||
// 昵称
|
||||
TimiException.required(issueRequest.getPublisherNick(), "TODO comment.nick.empty");
|
||||
issue.setPublisherNick(issueRequest.getPublisherNick());
|
||||
}
|
||||
TimiException.required(issueRequest.getTitle(), "TODO comment.title.empty");
|
||||
TimiException.required(issueRequest.getDescription(), "TODO comment.data.empty");
|
||||
issue.setRepositoryId(repository.getId());
|
||||
issue.setType(issueRequest.getType());
|
||||
issue.setVersion(issueRequest.getVersion());
|
||||
issue.setTitle(issueRequest.getTitle());
|
||||
issue.setDescription(issueRequest.getDescription());
|
||||
issue.setStatus(Issue.Status.BEFORE_CONFIRM);
|
||||
super.create(issue);
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void update(IssueRequest issueRequest) {
|
||||
Issue issue = get(issueRequest.getId());
|
||||
TimiException.requiredTrue(issue.canUpdate(), "TODO can not update");
|
||||
|
||||
User publisher = userService.getLoginUser();
|
||||
TimiException.required(publisher.getId().equals(issue.getPublisherId()), "TODO not permission edit issue");
|
||||
TimiException.requiredTrue(!publisher.isMuting(), "TODO publisher.banned");
|
||||
|
||||
TimiException.required(issueRequest.getTitle(), "TODO comment.title.empty");
|
||||
TimiException.required(issueRequest.getDescription(), "TODO comment.data.empty");
|
||||
issue.setType(issueRequest.getType());
|
||||
issue.setVersion(issueRequest.getVersion());
|
||||
issue.setTitle(issueRequest.getTitle());
|
||||
issue.setDescription(issueRequest.getDescription());
|
||||
mapper.update(issue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Issue> page(IssuePage issuePage) {
|
||||
PageResult<Issue> result = new PageResult<>();
|
||||
result.setList(mapper.listByIssuePage(issuePage, issuePage.getOffset(), issuePage.getLimit()));
|
||||
result.setTotal(mapper.countByIssuePage(issuePage));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.imyeyu.api.modules.git.service.implement;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||
import com.imyeyu.api.modules.common.entity.User;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
import com.imyeyu.api.modules.git.mapper.MergeMapper;
|
||||
import com.imyeyu.api.modules.git.service.IssueService;
|
||||
import com.imyeyu.api.modules.git.service.MergeService;
|
||||
import com.imyeyu.api.modules.git.service.RepositoryService;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergePage;
|
||||
import com.imyeyu.api.modules.git.vo.merge.MergeRequest;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import com.imyeyu.spring.mapper.BaseMapper;
|
||||
import com.imyeyu.spring.service.AbstractEntityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:38
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MergeServiceImplement extends AbstractEntityService<Merge, Long> implements MergeService {
|
||||
|
||||
private final UserService userService;
|
||||
private final IssueService issueService;
|
||||
private final RepositoryService repositoryService;
|
||||
|
||||
private final MergeMapper mapper;
|
||||
|
||||
@Override
|
||||
protected BaseMapper<Merge, Long> mapper() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void create(MergeRequest mergeRequest) {
|
||||
// Repository repository = repositoryService.get(mergeRequest.getRepositoryId());
|
||||
User requester = userService.getLoginUser();
|
||||
TimiException.required(mergeRequest.getTitle(), "TODO mergeRequest.title.empty");
|
||||
TimiException.required(mergeRequest.getDescription(), "TODO mergeRequest.description.empty");
|
||||
TimiException.required(mergeRequest.getFromBranch(), "TODO mergeRequest.fromBranch.empty");
|
||||
// List<GitBranch> branches = repositoryService.listAllBranches(repository.getId());
|
||||
// if (branches.stream().filter(i -> i.getName().equals(mergeRequest.getFromBranch())).toList().isEmpty()) {
|
||||
// throw new TimiException(TimiCode.ARG_MISS).msgKey("TODO 来源分支不存在");
|
||||
// }
|
||||
// if (branches.stream().filter(i -> i.getName().equals(mergeRequest.getToBranch())).toList().isEmpty()) {
|
||||
// throw new TimiException(TimiCode.ARG_MISS).msgKey("TODO 去向分支不存在");
|
||||
// }
|
||||
Merge merge = new Merge();
|
||||
if (TimiJava.isNotEmpty(mergeRequest.getIssueId())) {
|
||||
Issue issue = issueService.get(mergeRequest.getIssueId());
|
||||
merge.setIssueId(issue.getId());
|
||||
}
|
||||
// merge.setRepositoryId(repository.getId());
|
||||
merge.setRequesterId(requester.getId());
|
||||
merge.setType(mergeRequest.getType());
|
||||
merge.setFromBranch(mergeRequest.getFromBranch());
|
||||
merge.setToBranch(mergeRequest.getToBranch());
|
||||
merge.setTitle(mergeRequest.getTitle());
|
||||
merge.setDescription(mergeRequest.getDescription());
|
||||
merge.setStatus(Merge.Status.BEFORE_CHECK);
|
||||
mapper.insert(merge);
|
||||
}
|
||||
|
||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||
@Override
|
||||
public void update(MergeRequest mergeRequest) {
|
||||
Merge merge = get(mergeRequest.getId());
|
||||
|
||||
TimiException.requiredTrue(merge.canNotUpdate(), "TODO can not update");
|
||||
TimiException.required(mergeRequest.getTitle(), "TODO mergeRequest.title.empty");
|
||||
TimiException.required(mergeRequest.getDescription(), "TODO mergeRequest.data.empty");
|
||||
TimiException.requiredTrue(mergeRequest.getFromBranch().equals(merge.getToBranch()), "TODO 来源分支和去向分支不能相等");
|
||||
|
||||
User requester = userService.getLoginUser();
|
||||
TimiException.requiredTrue(!requester.getId().equals(merge.getRequesterId()), "TODO not permission edit merge");
|
||||
|
||||
// List<GitBranch> branches = repositoryService.listAllBranches(merge.getRepositoryId());
|
||||
// if (branches.stream().filter(i -> i.getName().equals(mergeRequest.getFromBranch())).toList().isEmpty()) {
|
||||
// throw new TimiException(TimiCode.ARG_MISS).msgKey("TODO 来源分支不存在");
|
||||
// }
|
||||
// if (branches.stream().filter(i -> i.getName().equals(mergeRequest.getToBranch())).toList().isEmpty()) {
|
||||
// throw new TimiException(TimiCode.ARG_MISS).msgKey("TODO 去向分支不存在");
|
||||
// }
|
||||
// if (TimiJava.isNotEmpty(mergeRequest.getIssueId())) {
|
||||
// Issue issue = issueService.get(mergeRequest.getIssueId());
|
||||
// merge.setIssueId(issue.getId());
|
||||
// }
|
||||
merge.setType(mergeRequest.getType());
|
||||
merge.setFromBranch(mergeRequest.getFromBranch());
|
||||
merge.setToBranch(mergeRequest.getToBranch());
|
||||
merge.setTitle(mergeRequest.getTitle());
|
||||
merge.setDescription(mergeRequest.getDescription());
|
||||
mapper.update(merge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Merge> page(MergePage mergePage) {
|
||||
PageResult<Merge> result = new PageResult<>();
|
||||
result.setList(mapper.listByMergePage(mergePage, mergePage.getOffset(), mergePage.getLimit()));
|
||||
result.setTotal(mapper.countByMergePage(mergePage));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.imyeyu.api.modules.git.service.implement;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.imyeyu.api.modules.git.mapper.ReleaseMapper;
|
||||
import com.imyeyu.api.modules.git.service.ReleaseService;
|
||||
import com.imyeyu.api.modules.git.service.RepositoryService;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleasePage;
|
||||
import com.imyeyu.api.modules.git.vo.release.ReleaseView;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:27
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ReleaseServiceImplement implements ReleaseService {
|
||||
|
||||
private final RepositoryService repositoryService;
|
||||
|
||||
private final ReleaseMapper mapper;
|
||||
|
||||
@Override
|
||||
public PageResult<ReleaseView> pageByRepositoryId(ReleasePage releasePage) {
|
||||
// Repository repository = repositoryService.get(releasePage.getRepositoryId());
|
||||
PageResult<ReleaseView> result = new PageResult<>();
|
||||
// result.setList(mapper.listByRepositoryId(repository.getId(), releasePage.getOffset(), releasePage.getLimit()));
|
||||
// result.setTotal(mapper.countByRepositoryId(repository.getId()));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package com.imyeyu.api.modules.git.service.implement;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import com.imyeyu.java.bean.timi.TimiCode;
|
||||
import com.imyeyu.java.bean.timi.TimiException;
|
||||
import com.imyeyu.network.Network;
|
||||
import com.imyeyu.api.modules.common.bean.SettingKey;
|
||||
import com.imyeyu.api.modules.common.service.SettingService;
|
||||
import com.imyeyu.api.modules.common.service.UserService;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.API;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Branch;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.File;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.GiteaResponse;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Repository;
|
||||
import com.imyeyu.api.modules.git.service.RepositoryService;
|
||||
import com.imyeyu.api.modules.gitea.entity.User;
|
||||
import com.imyeyu.api.modules.gitea.service.GiteaService;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
import com.imyeyu.spring.bean.PageResult;
|
||||
import jakarta.activation.MimetypesFileTypeMap;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.Cleanup;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hc.client5.http.fluent.Request;
|
||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||
import org.apache.tika.Tika;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTree;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Git 仓库服务
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-06 01:19
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RepositoryServiceImplement implements RepositoryService {
|
||||
|
||||
private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
|
||||
|
||||
private final UserService userService;
|
||||
private final GiteaService giteaService;
|
||||
private final SettingService settingService;
|
||||
|
||||
private User owner;
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
owner = giteaService.getOwner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Repository> page(Page page) {
|
||||
try {
|
||||
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_LIST.buildURL(null, new HashMap<>() {{
|
||||
put("uid", owner.getId());
|
||||
put("sort", "updated");
|
||||
put("order", "desc");
|
||||
put("page", page.getIndex() + 1);
|
||||
put("limit", page.getLimit());
|
||||
}})).execute().returnResponse();
|
||||
String respText = EntityUtils.toString(resp.getEntity());
|
||||
GiteaResponse<List<Repository>> respObj = gson.fromJson(respText, new TypeToken<GiteaResponse<List<Repository>>>() {
|
||||
}.getType());
|
||||
|
||||
PageResult<Repository> result = new PageResult<>();
|
||||
result.setTotal(Long.parseLong(resp.getHeader("X-Total-Count").getValue()));
|
||||
result.setList(respObj.getData());
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("list repository error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "list repository error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repository get(String repoName) {
|
||||
try {
|
||||
String respText = Request.get(API.REPO_GET.buildURL(new HashMap<>() {{
|
||||
put("owner", owner.getName());
|
||||
put("repoName", repoName);
|
||||
}})).execute().returnContent().asString();
|
||||
return gson.fromJson(respText, Repository.class);
|
||||
} catch (Exception e) {
|
||||
log.error("get repository error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "get repository error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Branch> listBranches(String repoName) {
|
||||
try {
|
||||
String respText = Request.get(API.REPO_BRANCHES_LIST.buildURL(new HashMap<>() {{
|
||||
put("owner", owner.getName());
|
||||
put("repoName", repoName);
|
||||
}})).execute().returnContent().asString();
|
||||
return gson.fromJson(respText, new TypeToken<List<Branch>>() {}.getType());
|
||||
} catch (Exception e) {
|
||||
log.error("list repository branches error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "list repository branches error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<File> listFile(String repoName, String branch, String path) {
|
||||
try {
|
||||
String respText = Request.get(API.REPO_FILE_LIST.buildURL(new HashMap<>() {{
|
||||
put("owner", owner.getName());
|
||||
put("repoName", repoName);
|
||||
put("path", path);
|
||||
}}, new HashMap<>() {{
|
||||
put("ref", branch);
|
||||
}})).execute().returnContent().asString();
|
||||
List<File> list = gson.fromJson(respText, new TypeToken<List<File>>() {}.getType());
|
||||
// 排序
|
||||
list.sort((f1, f2) -> {
|
||||
if (f1.getType() == File.Type.dir && f2.getType() == File.Type.file) {
|
||||
return -1;
|
||||
} else {
|
||||
if (f1.getType() == File.Type.file && f2.getType() == File.Type.dir) {
|
||||
return 1;
|
||||
}
|
||||
return f1.getName().compareToIgnoreCase(f2.getName());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
log.error("list repository file error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "list repository file error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getFileRaw(String repoName, String branch, String path) {
|
||||
try {
|
||||
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_FILE_RAW.buildURL(new HashMap<>() {{
|
||||
put("owner", owner.getName());
|
||||
put("repoName", repoName);
|
||||
put("path", path);
|
||||
}}, new HashMap<>() {{
|
||||
put("ref", branch);
|
||||
}})).execute().returnResponse();
|
||||
return resp.getEntity().getContent();
|
||||
} catch (Exception e) {
|
||||
log.error("get repository file raw error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "get repository file raw error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileMimeType(String repoName, String branch, String path) {
|
||||
try {
|
||||
String repoPath = settingService.getAsString(SettingKey.GIT_REPO_PATH);
|
||||
if (TimiJava.isEmpty(repoPath)) {
|
||||
// 根据文件名猜测
|
||||
return new MimetypesFileTypeMap().getContentType(Network.uriFileName(path));
|
||||
} else {
|
||||
repoPath = "%s/%s.git".formatted(repoPath, repoName.toLowerCase());
|
||||
// 仓库
|
||||
@Cleanup
|
||||
org.eclipse.jgit.lib.Repository repo = new FileRepositoryBuilder().setGitDir(Path.of(repoPath).toFile()).build();
|
||||
TimiException.required(repo, "not found repository: %s".formatted(repoPath));
|
||||
|
||||
// 分支
|
||||
ObjectId commitId = repo.resolve("refs/heads/%s".formatted(branch));
|
||||
TimiException.required(commitId, "not found branch: %s".formatted(branch));
|
||||
|
||||
// 提交
|
||||
RevWalk revWalk = new RevWalk(repo);
|
||||
RevCommit commit = revWalk.parseCommit(commitId);
|
||||
RevTree tree = commit.getTree();
|
||||
|
||||
// 文件
|
||||
path = path.substring(1);
|
||||
TreeWalk treeWalk = TreeWalk.forPath(repo, path, tree);
|
||||
TimiException.required(treeWalk, "not found file: %s".formatted(path));
|
||||
ObjectId fileObjectId = treeWalk.getObjectId(0);
|
||||
|
||||
// 读取文件
|
||||
ObjectReader reader = repo.newObjectReader();
|
||||
ObjectLoader loader = reader.open(fileObjectId);
|
||||
InputStream stream = loader.openStream();
|
||||
return new Tika().detect(stream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("get repository file mime error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "get repository file mime error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getArchive(String repoName, String branch) {
|
||||
try {
|
||||
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_ARCHIVE.buildURL(new HashMap<>() {{
|
||||
put("owner", owner.getName());
|
||||
put("repoName", repoName);
|
||||
put("archiveFormat", "%s.tar.gz".formatted(branch));
|
||||
}})).execute().returnResponse();
|
||||
return resp.getEntity().getContent();
|
||||
} catch (Exception e) {
|
||||
log.error("get repository archive error", e);
|
||||
throw new TimiException(TimiCode.ERROR, "get repository archive error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.imyeyu.api.modules.git.util;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2025-06-26 11:40
|
||||
*/
|
||||
public class GiteaTimestampAdapter implements JsonSerializer<Long>, JsonDeserializer<Long> {
|
||||
|
||||
@Override
|
||||
public Long deserialize(JsonElement json, Type type, JsonDeserializationContext context) {
|
||||
return Instant.parse(json.getAsString()).toEpochMilli();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Long src, Type type, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.imyeyu.api.modules.git.vo.developer;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-09-19 11:57
|
||||
*/
|
||||
@Data
|
||||
public class DeveloperRequest {
|
||||
|
||||
private String email;
|
||||
|
||||
private String rsa;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.imyeyu.api.modules.git.vo.issue;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.entity.Comment;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2024-02-28 14:27
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CommentPage extends Page {
|
||||
|
||||
private Comment.BizType bizType;
|
||||
|
||||
private long bizId;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.imyeyu.api.modules.git.vo.issue;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-15 15:04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class IssuePage extends Page {
|
||||
|
||||
private long repositoryId;
|
||||
|
||||
private Issue.Type type;
|
||||
|
||||
private Issue.Status status;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.imyeyu.api.modules.git.vo.issue;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
|
||||
/**
|
||||
* 工单反馈
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-15 15:51
|
||||
*/
|
||||
@Data
|
||||
public class IssueRequest {
|
||||
|
||||
/** 工单 ID,在编辑时携带 */
|
||||
private Long id;
|
||||
|
||||
/** 工单类型 */
|
||||
@NotNull
|
||||
private Issue.Type type;
|
||||
|
||||
/** 所属仓库 ID,创建工单时携带,编辑时不需要 */
|
||||
private Long repositoryId;
|
||||
|
||||
/** 反馈用户昵称 */
|
||||
private String publisherNick;
|
||||
|
||||
/** 版本 */
|
||||
private String version;
|
||||
|
||||
/** 标题 */
|
||||
private String title;
|
||||
|
||||
/** 反馈数据 */
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.imyeyu.api.modules.git.vo.issue;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.vo.user.UserView;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 15:40
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class IssueView extends Issue {
|
||||
|
||||
private UserView publisher;
|
||||
|
||||
private List<Attachment> attachmentList;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.imyeyu.api.modules.git.vo.merge;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:52
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MergePage extends Page {
|
||||
|
||||
private long repositoryId;
|
||||
|
||||
private Merge.Type type;
|
||||
|
||||
private Merge.Status status;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.imyeyu.api.modules.git.vo.merge;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
|
||||
/**
|
||||
* 申请合并请求
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 11:43
|
||||
*/
|
||||
@Data
|
||||
public class MergeRequest {
|
||||
|
||||
/** 和并请求 ID,编辑时携带 */
|
||||
private Long id;
|
||||
|
||||
/** 所属仓库 ID */
|
||||
private long repositoryId;
|
||||
|
||||
private Long issueId;
|
||||
|
||||
/** 类型 */
|
||||
@NotNull(message = "请选择类型")
|
||||
private Merge.Type type;
|
||||
|
||||
/** 来源分支 */
|
||||
@NotBlank(message = "请选择来源分支")
|
||||
private String fromBranch;
|
||||
|
||||
/** 去向分支 */
|
||||
@NotBlank(message = "请选择去向分支")
|
||||
private String toBranch;
|
||||
|
||||
/** 说明标题 */
|
||||
@NotBlank(message = "请填写标题")
|
||||
private String title;
|
||||
|
||||
/** 合并说明 */
|
||||
@NotBlank(message = "请填写合并相关说明")
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.imyeyu.api.modules.git.vo.merge;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.common.vo.user.UserView;
|
||||
import com.imyeyu.api.modules.git.entity.Issue;
|
||||
import com.imyeyu.api.modules.git.entity.Merge;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-17 15:40
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MergeView extends Merge {
|
||||
|
||||
private Issue issue;
|
||||
|
||||
private UserView requester;
|
||||
|
||||
private List<Attachment> attachmentList;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.imyeyu.api.modules.git.vo.release;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.spring.bean.Page;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2023-08-16 11:46
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ReleasePage extends Page {
|
||||
|
||||
private long repositoryId;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.imyeyu.api.modules.git.vo.release;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||
import com.imyeyu.api.modules.git.entity.Release;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2024-03-11 11:29
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ReleaseView extends Release {
|
||||
|
||||
private List<Attachment> attachmentList;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.imyeyu.api.modules.git.vo.repository;
|
||||
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Branch;
|
||||
import com.imyeyu.api.modules.git.bean.gitea.Repository;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2024-01-09 15:21
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RepositoryView extends Repository {
|
||||
|
||||
private List<Branch> branchList;
|
||||
}
|
||||
Reference in New Issue
Block a user