diff --git a/modules/convert/pull_version.go b/modules/convert/pull_version.go new file mode 100644 index 0000000..d3f02d3 --- /dev/null +++ b/modules/convert/pull_version.go @@ -0,0 +1,23 @@ +package convert + +import ( + hat_pull_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/pull" + hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs" +) + +func ToAPIPullRequestVersion(prv *hat_pull_model.PullRequestVersion) *hat_api.PullRequestVersion { + apiPullRequestVersion := &hat_api.PullRequestVersion{ + ID: prv.ID, + AddLineNum: prv.AddLineNum, + DelLineNum: prv.DelLineNum, + CommitsCount: prv.CommitsCount, + FilesCount: prv.FilesCount, + HeadCommitSha: prv.HeadCommitID, + BaseCommitSha: prv.BaseCommitID, + StartCommitSha: prv.StartCommitID, + CreatedAt: prv.CreatedUnix.AsTimePtr(), + UpdatedAt: prv.UpdatedUnix.AsTimePtr(), + } + + return apiPullRequestVersion +} diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index a224ef8..c7c7d5f 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -6,3 +6,8 @@ func GetDiffFileOnlyName(repo *gitea_git.Repository, base, head string) (string, stdout, _, err := gitea_git.NewCommand(repo.Ctx, "diff", "--name-only", gitea_git.CmdArg(base), gitea_git.CmdArg(head)).RunStdString(&gitea_git.RunOpts{Dir: repo.Path}) return stdout, err } + +func GetDiffStringByFilePath(repo *gitea_git.Repository, base, head, filepath string) (string, error) { + stdout, _, err := gitea_git.NewCommand(repo.Ctx, "diff", "-p", gitea_git.CmdArg(base), gitea_git.CmdArg(head), "--", gitea_git.CmdArg(filepath)).RunStdString(&gitea_git.RunOpts{Dir: repo.Path}) + return stdout, err +} diff --git a/modules/structs/pull_version.go b/modules/structs/pull_version.go new file mode 100644 index 0000000..50ba002 --- /dev/null +++ b/modules/structs/pull_version.go @@ -0,0 +1,16 @@ +package structs + +import "time" + +type PullRequestVersion struct { + ID int64 `json:"id"` + AddLineNum int `json:"add_line_num"` + DelLineNum int `json:"del_line_num"` + CommitsCount int `json:"commits_count"` + FilesCount int `json:"files_count"` + BaseCommitSha string `json:"base_commit_sha"` + HeadCommitSha string `json:"head_commit_sha"` + StartCommitSha string `json:"start_commit_sha"` + CreatedAt *time.Time `json:"created_at"` + UpdatedAt *time.Time `json:"updated_at"` +} diff --git a/routers/hat/hat.go b/routers/hat/hat.go index 837de5b..4a63e45 100644 --- a/routers/hat/hat.go +++ b/routers/hat/hat.go @@ -99,6 +99,9 @@ func Routers(ctx gocontext.Context) *web.Route { m.Combo("").Get(repo.GetPullRequest) m.Get("/commits", context.RepoRef(), repo.GetPullCommits) m.Get("/files", context.RepoRef(), repo.GetPullFiles) + m.Group("/versions", func() { + m.Get("", repo.ListPullRequestVersions) + }) }) }, mustAllowPulls, reqRepoReader(unit_model.TypeCode), context.ReferencesGitRepo()) m.Group("/releases", func() { diff --git a/routers/hat/repo/pull_version.go b/routers/hat/repo/pull_version.go new file mode 100644 index 0000000..d4eaea9 --- /dev/null +++ b/routers/hat/repo/pull_version.go @@ -0,0 +1,132 @@ +package repo + +import ( + "fmt" + "net/http" + "strings" + + issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/gitdiff" + hat_pull_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/pull" + hat_convert "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/convert" + hat_git "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git" + hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs" + hat_gitdiff "code.gitlink.org.cn/Gitlink/gitea_hat.git/services/gitdiff" +) + +func ListPullRequestVersions(ctx *context.APIContext) { + pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.RepoID, ctx.ParamsInt64(":index")) + if err != nil { + if issues_model.IsErrPullRequestNotExist(err) { + ctx.NotFound() + } else { + ctx.InternalServerError(err) + } + return + } + + listOptions := utils.GetListOptions(ctx) + prvs, maxResults, err := hat_pull_model.PullRequestVersions(ctx, pr.ID, &listOptions) + if err != nil { + ctx.Error(http.StatusInternalServerError, "PullRequestVersions", err) + return + } + + apiPrvs := make([]*hat_api.PullRequestVersion, len(prvs)) + for i := range prvs { + apiPrvs[i] = hat_convert.ToAPIPullRequestVersion(prvs[i]) + } + + ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) + ctx.RespHeader().Set("X-Total", fmt.Sprintf("%d", maxResults)) + ctx.RespHeader().Set("X-Total-Count", fmt.Sprintf("%d", maxResults)) + ctx.RespHeader().Set("Access-Control-Expose-Headers", "X-Total-Count, Link, X-Total") + + ctx.JSON(http.StatusOK, &apiPrvs) +} + +func GetPullRequestVersionDiff(ctx *context.APIContext) { + if ctx.Repo.Repository.IsEmpty { + ctx.NotFound() + return + } + + pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) + if err != nil { + if issues_model.IsErrPullRequestNotExist(err) { + ctx.NotFound() + } else { + ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err) + } + return + } + + prv, err := hat_pull_model.GetPullRequestVersionByID(ctx, pr.ID, ctx.ParamsInt64(":versionId")) + if err != nil { + if issues_model.IsErrPullRequestNotExist(err) { + ctx.NotFound() + } else { + ctx.Error(http.StatusInternalServerError, "GetPullRequestVersionByID", err) + } + return + } + + diffs, err := gitdiff.GetDiff(ctx.Repo.GitRepo, &gitdiff.DiffOptions{ + BeforeCommitID: prv.BaseCommitID, + AfterCommitID: prv.HeadCommitID, + MaxLines: setting.Git.MaxGitDiffLines, + MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, + MaxFiles: setting.Git.MaxGitDiffFiles, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetDiff", err) + } + + filepath := ctx.FormString("filepath") + if filepath == "" { + ctx.JSON(http.StatusOK, diffs) + } else { + var targetDiffFile *hat_gitdiff.DiffFile + for _, file := range diffs.Files { + if file.Name == filepath { + if diffString, err := hat_git.GetDiffStringByFilePath(ctx.Repo.GitRepo, prv.BaseCommitID, prv.HeadCommitID, file.Name); err == nil { + stringArray := strings.Split(diffString, "\n") + var afterStrings []string + for _, item := range stringArray { + switch { + case strings.HasPrefix(item, "diff --git"): + continue + case strings.HasPrefix(item, "index"): + continue + case strings.HasPrefix(item, "---"): + continue + case strings.HasPrefix(item, "+++"): + continue + case strings.HasPrefix(item, "new file mode"): + continue + case strings.HasPrefix(item, "deleted file mode"): + continue + case strings.HasSuffix(item, "No newline at end of file"): + continue + default: + afterStrings = append(afterStrings, item) + } + } + targetDiffFile.Diff = strings.Join(afterStrings, "\n") + } + targetDiffFile = &hat_gitdiff.DiffFile{ + DiffFile: *file, + } + break + } + } + if targetDiffFile == nil { + ctx.NotFound() + } else { + ctx.JSON(http.StatusOK, targetDiffFile) + } + } +} diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go new file mode 100644 index 0000000..d2ec6b7 --- /dev/null +++ b/services/gitdiff/gitdiff.go @@ -0,0 +1,10 @@ +package gitdiff + +import ( + gitea_gitdiff "code.gitea.io/gitea/services/gitdiff" +) + +type DiffFile struct { + gitea_gitdiff.DiffFile + Diff string +}