From 3e2d43ab77cfbbf9d441bef8f0481b31276041e6 Mon Sep 17 00:00:00 2001 From: yystopf Date: Tue, 11 Apr 2023 09:42:44 +0800 Subject: [PATCH 01/18] =?UTF-8?q?=E6=9B=B4=E6=94=B9=EF=BC=9Atestgitea?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devops/testgitea环境.yml | 65 +++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/.devops/testgitea环境.yml b/.devops/testgitea环境.yml index b2001d8..20b989d 100644 --- a/.devops/testgitea环境.yml +++ b/.devops/testgitea环境.yml @@ -16,25 +16,62 @@ workflow: - ref: start name: 开始 task: start - - ref: ssh_cmd_0 - name: ssh执行命令 - task: ssh_cmd@1.1.0 + - ref: git_clone_0 + name: git clone + on-failure: ignore + task: git_clone@1.2.6 input: - ssh_private_key: ((ssh.siyao)) - ssh_ip: '"123.59.135.93"' - ssh_port: '"51123"' - ssh_user: '"pdl"' - ssh_cmd: '"ssh root@10.9.69.134 -p30122 \" - cd /root - && - sh ./update.sh - && - echo done \""' + remote_url: '"https://gitlink.org.cn/Gitlink/gitea_hat.git"' + ref: '"refs/heads/develop"' + commit_id: '""' + depth: 1 needs: - start + - ref: golang_build_node_0 + name: golang_build_node + on-failure: ignore + task: yystopf/golang_build_node@0.0.2 + input: + workspace: git_clone_0.git_path + out_bin_name: '"gitea"' + goos: '"linux"' + goarch: '"amd64"' + needs: + - git_clone_0 + - ref: gitlink_scp_resource_0 + name: scp复制文件(支持跳板机) + on-failure: ignore + task: yystopf/gitlink_scp_resource@0.0.7 + input: + ssh_private_key: ((ssh.siyao)) + remote_host: '"10.9.69.134"' + remote_port: '"30122"' + remote_user: '"root"' + remote_file: '"/root/gitea"' + local_file: golang_build_node_0.bin_dir + gateway_host: '"123.59.135.93"' + gateway_port: '"51123"' + gateway_user: '"pdl"' + temp_file: '"/home/pdl/gitea"' + needs: + - golang_build_node_0 + - ref: gitlink_ssh_cmd_0 + name: ssh执行命令(支持跳板机) + task: yystopf/gitlink_ssh_cmd@0.0.6 + input: + ssh_private_key: ((ssh.siyao)) + remote_host: '"10.9.69.134"' + remote_port: '"22"' + remote_user: '"root"' + gateway_host: '"123.59.135.93"' + gateway_port: '"51123"' + gateway_user: '"pdl"' + ssh_cmd: '"sh update.sh"' + needs: + - gitlink_scp_resource_0 - ref: end name: 结束 task: end needs: - - ssh_cmd_0 + - gitlink_ssh_cmd_0 -- 2.34.1 From 357d28a2c9c818d4e24a86303b78ef91cd5d722f Mon Sep 17 00:00:00 2001 From: yystopf Date: Tue, 11 Apr 2023 09:47:23 +0800 Subject: [PATCH 02/18] =?UTF-8?q?=E6=9B=B4=E6=94=B9=EF=BC=9Atestgitea?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devops/testgitea环境.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devops/testgitea环境.yml b/.devops/testgitea环境.yml index 20b989d..c2d6cea 100644 --- a/.devops/testgitea环境.yml +++ b/.devops/testgitea环境.yml @@ -61,7 +61,7 @@ workflow: input: ssh_private_key: ((ssh.siyao)) remote_host: '"10.9.69.134"' - remote_port: '"22"' + remote_port: '"30122"' remote_user: '"root"' gateway_host: '"123.59.135.93"' gateway_port: '"51123"' -- 2.34.1 From 9614d81c9a9abebaa0c591c589fb32cf50d06303 Mon Sep 17 00:00:00 2001 From: yystopf Date: Tue, 11 Apr 2023 16:58:54 +0800 Subject: [PATCH 03/18] =?UTF-8?q?refactor:=20.devops/testgitea=E7=8E=AF?= =?UTF-8?q?=E5=A2=83.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devops/testgitea环境.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devops/testgitea环境.yml b/.devops/testgitea环境.yml index c2d6cea..1925a51 100644 --- a/.devops/testgitea环境.yml +++ b/.devops/testgitea环境.yml @@ -10,7 +10,7 @@ trigger: ruleset: - param-ref: branch operator: EQ - value: '"develop"' + value: '"feature"' ruleset-operator: AND workflow: - ref: start -- 2.34.1 From c1d4bdbab08cab542dadd29accfe5d0828c08c72 Mon Sep 17 00:00:00 2001 From: yystopf Date: Tue, 11 Apr 2023 18:03:29 +0800 Subject: [PATCH 04/18] =?UTF-8?q?refactor:=20.devops/testgitea=E7=8E=AF?= =?UTF-8?q?=E5=A2=83.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devops/testgitea环境.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devops/testgitea环境.yml b/.devops/testgitea环境.yml index 1925a51..7ba216d 100644 --- a/.devops/testgitea环境.yml +++ b/.devops/testgitea环境.yml @@ -22,7 +22,7 @@ workflow: task: git_clone@1.2.6 input: remote_url: '"https://gitlink.org.cn/Gitlink/gitea_hat.git"' - ref: '"refs/heads/develop"' + ref: '"refs/heads/feature"' commit_id: '""' depth: 1 needs: -- 2.34.1 From f513d462e52cf7ec89d59fdc6b955a0addd42ce9 Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 17 Apr 2023 10:38:18 +0800 Subject: [PATCH 05/18] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E8=B4=A1?= =?UTF-8?q?=E7=8C=AE=E8=80=85=E4=BB=A3=E7=A0=81=E8=A1=8C=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/git/repo_stats.go | 8 +++++--- routers/hat/hat.go | 1 + routers/hat/repo/repo.go | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index d348b26..fa54183 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -8,6 +8,7 @@ import ( "sort" "strconv" "strings" + "time" "code.gitea.io/gitea/modules/container" gitea_git "code.gitea.io/gitea/modules/git" @@ -145,11 +146,12 @@ func GetCodeActivityStatsWithoutSince(repo *gitea_git.Repository, branch string) } // GetCodeActivityStats returns code statistics for activity page -func GetPaginateCodeAuthorsWithoutSince(repo *gitea_git.Repository, branch string, page, pageSize int) (int64, []*CodeActivityAuthor, error) { +func GetPaginateCodeAuthors(repo *gitea_git.Repository, fromTime time.Time, branch string, page, pageSize int) (int64, []*CodeActivityAuthor, error) { var total int64 var authors []*CodeActivityAuthor + since := fromTime.Format(time.RFC3339) - authorCmd := gitea_git.NewCommand(repo.Ctx, "log", "--no-merges", "--format=%aN <%aE>", "--date=iso") + authorCmd := gitea_git.NewCommand(repo.Ctx, "log", "--no-merges", "--format=%aN <%aE>", "--date=iso").AddDynamicArguments("--since='%s'", since) if len(branch) == 0 { authorCmd.AddArguments("--branches=*") } else { @@ -199,7 +201,7 @@ func GetPaginateCodeAuthorsWithoutSince(repo *gitea_git.Repository, branch strin _ = stdoutReader.Close() _ = stdoutWriter.Close() }() - gitCmd := gitea_git.NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", gitea_git.CmdArg(fmt.Sprintf("--author=%s", filterAuthor))) + gitCmd := gitea_git.NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", gitea_git.CmdArg(fmt.Sprintf("--author=%s", filterAuthor))).AddDynamicArguments("--since='%s'", since) if len(branch) == 0 { gitCmd.AddArguments("--branches=*") } else { diff --git a/routers/hat/hat.go b/routers/hat/hat.go index 1e247b4..539d108 100644 --- a/routers/hat/hat.go +++ b/routers/hat/hat.go @@ -119,6 +119,7 @@ func Routers(ctx gocontext.Context) *web.Route { }, reqRepoReader(unit.TypeReleases)) m.Group("/contributors", func() { m.Get("", context.ReferencesGitRepo(), repo.GetContributors) + m.Get("/stat", context.ReferencesGitRepo(), repo.GetContributorStat) }) m.Group("/count", func() { m.Get("", context.ReferencesGitRepo(), repo.GetCommitCount) diff --git a/routers/hat/repo/repo.go b/routers/hat/repo/repo.go index 8e206ba..685fde1 100644 --- a/routers/hat/repo/repo.go +++ b/routers/hat/repo/repo.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "strings" + "time" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" @@ -498,6 +499,31 @@ func GetContributors(ctx *context.APIContext) { ctx.JSON(http.StatusOK, list) } +func GetContributorStat(ctx *context.APIContext) { + listOptions := utils.GetListOptions(ctx) + + ref := ctx.FormString("ref") + year := ctx.FormInt("pass_year") + var timeFrom time.Time = time.Now().AddDate(-1, 0, 0) // 默认近一年 + + if year > 0 { + timeFrom = time.Now().AddDate(-year, 0, 0) // 近几年 + } + + total, list, err := hat_git.GetPaginateCodeAuthors(ctx.Repo.GitRepo, timeFrom, ref, listOptions.Page, listOptions.PageSize) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetPaginateCodeAuthors", err) + return + } + + ctx.SetLinkHeader(int(total), listOptions.PageSize) + ctx.RespHeader().Set("X-Total", fmt.Sprintf("%d", total)) + ctx.RespHeader().Set("X-Total-Count", fmt.Sprintf("%d", total)) + ctx.RespHeader().Set("Access-Control-Expose-Headers", "X-Total-Count, Link, X-Total") + + ctx.JSON(http.StatusOK, list) +} + type CountDTO struct { Branch CountDTOBranch `json:"branch"` ReleaseCount int64 `json:"release_count"` -- 2.34.1 From d70d74a2aed23e0121ddf454034c01f6cc50c66b Mon Sep 17 00:00:00 2001 From: yystopf Date: Mon, 17 Apr 2023 11:11:59 +0800 Subject: [PATCH 06/18] =?UTF-8?q?=E6=9B=B4=E6=94=B9=EF=BC=9A=E4=BD=BF?= =?UTF-8?q?=E7=94=A8gitcmd=E4=BF=9D=E8=AF=81=E4=B8=8D=E4=BC=9Abroken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/git/repo_stats.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index fa54183..dac957f 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -151,7 +151,7 @@ func GetPaginateCodeAuthors(repo *gitea_git.Repository, fromTime time.Time, bran var authors []*CodeActivityAuthor since := fromTime.Format(time.RFC3339) - authorCmd := gitea_git.NewCommand(repo.Ctx, "log", "--no-merges", "--format=%aN <%aE>", "--date=iso").AddDynamicArguments("--since='%s'", since) + authorCmd := gitea_git.NewCommand(repo.Ctx, "log", "--no-merges", "--format=%aN <%aE>", "--date=iso", gitea_git.CmdArg(fmt.Sprintf("--since='%s'", since))) if len(branch) == 0 { authorCmd.AddArguments("--branches=*") } else { @@ -201,7 +201,7 @@ func GetPaginateCodeAuthors(repo *gitea_git.Repository, fromTime time.Time, bran _ = stdoutReader.Close() _ = stdoutWriter.Close() }() - gitCmd := gitea_git.NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", gitea_git.CmdArg(fmt.Sprintf("--author=%s", filterAuthor))).AddDynamicArguments("--since='%s'", since) + gitCmd := gitea_git.NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", gitea_git.CmdArg(fmt.Sprintf("--author=%s", filterAuthor)), gitea_git.CmdArg(fmt.Sprintf("--since='%s'", since))) if len(branch) == 0 { gitCmd.AddArguments("--branches=*") } else { -- 2.34.1 From 3872146a9d3e1e2deaae900069d011d79425d4a1 Mon Sep 17 00:00:00 2001 From: xxq250 Date: Fri, 5 May 2023 14:52:20 +0800 Subject: [PATCH 07/18] =?UTF-8?q?commit=E5=A2=9E=E5=8A=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0stat=E6=8F=90=E9=AB=98=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/convert/git_commit.go | 136 +++++++++++++++++++++++++++++++++- routers/hat/repo/commits.go | 12 ++- 2 files changed, 142 insertions(+), 6 deletions(-) diff --git a/modules/convert/git_commit.go b/modules/convert/git_commit.go index 7c63263..c9ac248 100644 --- a/modules/convert/git_commit.go +++ b/modules/convert/git_commit.go @@ -3,13 +3,16 @@ package convert import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - gitea_convert "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" + api "code.gitea.io/gitea/modules/structs" hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs" + "net/url" + "time" ) func ToCommit(repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit, userCache map[string]*user_model.User, stat bool) (*hat_api.Commit, error) { - giteaApiCommit, err := gitea_convert.ToCommit(repo, gitRepo, commit, userCache, stat) + giteaApiCommit, err := ToCommitNotDiff(repo, gitRepo, commit, userCache, stat) if err != nil { return nil, err } @@ -24,3 +27,132 @@ func ToCommit(repo *repo_model.Repository, gitRepo *git.Repository, commit *git. Branch: commit.Branch, }, nil } + +func ToCommitNotDiff(repo *repo_model.Repository, gitRepo *git.Repository, commit *git.Commit, userCache map[string]*user_model.User, stat bool) (*api.Commit, error) { + var apiAuthor, apiCommitter *api.User + + // Retrieve author and committer information + + var cacheAuthor *user_model.User + var ok bool + if userCache == nil { + cacheAuthor = (*user_model.User)(nil) + ok = false + } else { + cacheAuthor, ok = userCache[commit.Author.Email] + } + + if ok { + apiAuthor = convert.ToUser(cacheAuthor, nil) + } else { + author, err := user_model.GetUserByEmail(commit.Author.Email) + if err != nil && !user_model.IsErrUserNotExist(err) { + return nil, err + } else if err == nil { + apiAuthor = convert.ToUser(author, nil) + if userCache != nil { + userCache[commit.Author.Email] = author + } + } + } + + var cacheCommitter *user_model.User + if userCache == nil { + cacheCommitter = (*user_model.User)(nil) + ok = false + } else { + cacheCommitter, ok = userCache[commit.Committer.Email] + } + + if ok { + apiCommitter = convert.ToUser(cacheCommitter, nil) + } else { + committer, err := user_model.GetUserByEmail(commit.Committer.Email) + if err != nil && !user_model.IsErrUserNotExist(err) { + return nil, err + } else if err == nil { + apiCommitter = convert.ToUser(committer, nil) + if userCache != nil { + userCache[commit.Committer.Email] = committer + } + } + } + + // Retrieve parent(s) of the commit + apiParents := make([]*api.CommitMeta, commit.ParentCount()) + for i := 0; i < commit.ParentCount(); i++ { + sha, _ := commit.ParentID(i) + apiParents[i] = &api.CommitMeta{ + URL: repo.APIURL() + "/git/commits/" + url.PathEscape(sha.String()), + SHA: sha.String(), + } + } + + res := &api.Commit{ + CommitMeta: &api.CommitMeta{ + URL: repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String()), + SHA: commit.ID.String(), + Created: commit.Committer.When, + }, + HTMLURL: repo.HTMLURL() + "/commit/" + url.PathEscape(commit.ID.String()), + RepoCommit: &api.RepoCommit{ + URL: repo.APIURL() + "/git/commits/" + url.PathEscape(commit.ID.String()), + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: commit.Author.Name, + Email: commit.Author.Email, + }, + Date: commit.Author.When.Format(time.RFC3339), + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: commit.Committer.Name, + Email: commit.Committer.Email, + }, + Date: commit.Committer.When.Format(time.RFC3339), + }, + Message: commit.Message(), + Tree: &api.CommitMeta{ + URL: repo.APIURL() + "/git/trees/" + url.PathEscape(commit.ID.String()), + SHA: commit.ID.String(), + Created: commit.Committer.When, + }, + Verification: convert.ToVerification(commit), + }, + Author: apiAuthor, + Committer: apiCommitter, + Parents: apiParents, + } + + // Retrieve files affected by the commit + if stat { + fileStatus, err := git.GetCommitFileStatus(gitRepo.Ctx, repo.RepoPath(), commit.ID.String()) + if err != nil { + return nil, err + } + affectedFileList := make([]*api.CommitAffectedFiles, 0, len(fileStatus.Added)+len(fileStatus.Removed)+len(fileStatus.Modified)) + for _, files := range [][]string{fileStatus.Added, fileStatus.Removed, fileStatus.Modified} { + for _, filename := range files { + affectedFileList = append(affectedFileList, &api.CommitAffectedFiles{ + Filename: filename, + }) + } + } + + //diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + // AfterCommitID: commit.ID.String(), + //}) + //if err != nil { + // return nil, err + //} + + res.Files = affectedFileList + //res.Stats = &api.CommitStats{ + // Total: diff.TotalAddition + diff.TotalDeletion, + // Additions: diff.TotalAddition, + // Deletions: diff.TotalDeletion, + //} + } + + return res, nil +} diff --git a/routers/hat/repo/commits.go b/routers/hat/repo/commits.go index fd3698f..ff93fe5 100644 --- a/routers/hat/repo/commits.go +++ b/routers/hat/repo/commits.go @@ -87,8 +87,10 @@ func GetAllCommitsSliceByTime(ctx *context.APIContext) { apiCommits := make([]*responseCommit, len(commits)) apiCommitsList := []responseCommit{} + stat := ctx.FormString("stat") == "" || ctx.FormBool("stat") + for i, commitPoniter := range commits { - apiCommits[i], err = toResponseCommit(ctx.Repo.Repository, gitRepo, commitPoniter, userCache) + apiCommits[i], err = toResponseCommit(ctx.Repo.Repository, gitRepo, commitPoniter, userCache, stat) if err != nil { ctx.Error(http.StatusInternalServerError, "ToCommit", err) return @@ -114,8 +116,8 @@ type responseCommit struct { CommitDate string `json:"commit_date"` } -func toResponseCommit(repo *repo.Repository, gitRepo *git.Repository, commit *git.Commit, userCache map[string]*user.User) (*responseCommit, error) { - apiCommit, err := convert.ToCommit(repo, gitRepo, commit, userCache, true) +func toResponseCommit(repo *repo.Repository, gitRepo *git.Repository, commit *git.Commit, userCache map[string]*user.User, stat bool) (*responseCommit, error) { + apiCommit, err := convert.ToCommit(repo, gitRepo, commit, userCache, stat) if err != nil { return nil, err } @@ -190,8 +192,10 @@ func GetFileAllCommits(ctx *context.APIContext) { userCache := make(map[string]*user_model.User) apiCommits := make([]*api.Commit, len(commits)) + + stat := ctx.FormString("stat") == "" || ctx.FormBool("stat") for i, commit := range commits { - apiCommits[i], err = convert.ToCommit(ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, true) + apiCommits[i], err = hat_convert.ToCommitNotDiff(ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, stat) if err != nil { ctx.Error(http.StatusInternalServerError, "ToCommit", err) return -- 2.34.1 From b593911114deeebf98197bd6f99d6c8c68c29462 Mon Sep 17 00:00:00 2001 From: xxq250 Date: Fri, 12 May 2023 16:27:25 +0800 Subject: [PATCH 08/18] =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- options/locale/locale_en-US.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a1c250f..7536862 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2533,6 +2533,7 @@ dashboard.delete_old_actions = Delete all old actions from database dashboard.delete_old_actions.started = Delete all old actions from database started. dashboard.update_checker = Update checker dashboard.delete_old_system_notices = Delete all old system notices from database +dashboard.update_mirror = Update mirror users.user_manage_panel = User Account Management users.new_account = Create User Account -- 2.34.1 From a868cce758c44e1e2554d5d2ebe37f3f6a78a7c7 Mon Sep 17 00:00:00 2001 From: xxq250 Date: Fri, 12 May 2023 17:25:36 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- options/locale/locale_en-US.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 7536862..0871ef9 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2484,7 +2484,7 @@ dashboard.delete_repo_archives.started = Delete all repository archives task sta dashboard.delete_missing_repos = Delete all repositories missing their Git files dashboard.delete_missing_repos.started = Delete all repositories missing their Git files task started. dashboard.delete_generated_repository_avatars = Delete generated repository avatars -dashboard.update_mirrors = Update Mirrors +;dashboard.update_mirrors = Update Mirrors dashboard.repo_health_check = Health check all repositories dashboard.check_repo_stats = Check all repository statistics dashboard.archive_cleanup = Delete old repository archives @@ -2533,7 +2533,6 @@ dashboard.delete_old_actions = Delete all old actions from database dashboard.delete_old_actions.started = Delete all old actions from database started. dashboard.update_checker = Update checker dashboard.delete_old_system_notices = Delete all old system notices from database -dashboard.update_mirror = Update mirror users.user_manage_panel = User Account Management users.new_account = Create User Account -- 2.34.1 From 18d236f50f76ebb30dcc5f33c3a9064100f5689c Mon Sep 17 00:00:00 2001 From: xxq250 Date: Fri, 12 May 2023 17:58:01 +0800 Subject: [PATCH 10/18] =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96reset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- options/locale/locale_en-US.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0871ef9..a1c250f 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2484,7 +2484,7 @@ dashboard.delete_repo_archives.started = Delete all repository archives task sta dashboard.delete_missing_repos = Delete all repositories missing their Git files dashboard.delete_missing_repos.started = Delete all repositories missing their Git files task started. dashboard.delete_generated_repository_avatars = Delete generated repository avatars -;dashboard.update_mirrors = Update Mirrors +dashboard.update_mirrors = Update Mirrors dashboard.repo_health_check = Health check all repositories dashboard.check_repo_stats = Check all repository statistics dashboard.archive_cleanup = Delete old repository archives -- 2.34.1 From 49efd7598ac2a1c136556aac6f0b72e54d5dab5a Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Thu, 18 May 2023 17:49:18 +0800 Subject: [PATCH 11/18] =?UTF-8?q?=E8=B4=A1=E7=8C=AE=E8=80=85=E4=BB=85?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E9=82=AE=E7=AE=B1=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/git/repo_contributors.go | 79 ++++++++++++++++++++++++++++++++ routers/hat/repo/repo.go | 2 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/modules/git/repo_contributors.go b/modules/git/repo_contributors.go index 8d2a566..e75b532 100644 --- a/modules/git/repo_contributors.go +++ b/modules/git/repo_contributors.go @@ -82,3 +82,82 @@ func GetRepoContributors(repo *gitea_git.Repository, page, pageSize int) (int, [ return total, contributors, nil } + +func GetRepoContributorsNew(repo *gitea_git.Repository, page, pageSize int) (int, []*RepoContributor, error) { + var total, totalContributions, skip int + var contributors []*RepoContributor + var contributorInfos []*RepoContributor + contributorInfoHash := make(map[string]*RepoContributor) + + skip = (page - 1) * pageSize + + stdoutReader, stdoutWriter, err := os.Pipe() + if err != nil { + return total, nil, err + } + defer func() { + _ = stdoutReader.Close() + _ = stdoutWriter.Close() + }() + cmd := gitea_git.NewCommand(repo.Ctx, "shortlog", "-sne", "--all") + + stderr := new(strings.Builder) + err = cmd.Run(&gitea_git.RunOpts{ + Env: []string{}, + Dir: repo.Path, + Stdout: stdoutWriter, + Stderr: stderr, + PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { + _ = stdoutWriter.Close() + scanner := bufio.NewScanner(stdoutReader) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + l := strings.TrimSpace(scanner.Text()) + commits := l[0:strings.Index(l, "\t")] + commitsInt, err := strconv.Atoi(commits) + if err != nil { + return err + } + name := l[strings.Index(l, "\t")+1 : strings.Index(l, " <")] + email := l[strings.Index(l, "<")+1 : strings.Index(l, ">")] + totalContributions += commitsInt + // committer is not system user + if existedContributorInfo, ok := contributorInfoHash[email]; ok { + // existed: same primary email, different committer name + existedContributorInfo.Commits += commitsInt + } else { + var newContributor = &RepoContributor{ + Commits: commitsInt, + Name: name, + Email: email, + } + total++ + contributorInfos = append(contributorInfos, newContributor) + contributorInfoHash[email] = newContributor + } + } + + _ = stdoutReader.Close() + return nil + }, + }) + + var ca int + for _, cont := range contributorInfos { + if skip > 0 { + skip-- + } else { + if ca < pageSize { + fperc := fmt.Sprintf("%.2f", float64(cont.Commits)*100/float64(totalContributions)) + contributors = append(contributors, &RepoContributor{ + Commits: cont.Commits, + Name: cont.Name, + Email: cont.Email, + ContributionPerc: fperc + "%", + }) + ca++ + } + } + } + return total, contributors, nil +} diff --git a/routers/hat/repo/repo.go b/routers/hat/repo/repo.go index 685fde1..ad05c48 100644 --- a/routers/hat/repo/repo.go +++ b/routers/hat/repo/repo.go @@ -485,7 +485,7 @@ func SetDiffViewStyle(ctx *context.Context) { func GetContributors(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) - total, list, err := hat_git.GetRepoContributors(ctx.Repo.GitRepo, listOptions.Page, listOptions.PageSize) + total, list, err := hat_git.GetRepoContributorsNew(ctx.Repo.GitRepo, listOptions.Page, listOptions.PageSize) if err != nil { ctx.Error(http.StatusInternalServerError, "GetRepoContributors", err) return -- 2.34.1 From bffe0ca1b7d9c775550019f04d49372fbc17a0b7 Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Tue, 23 May 2023 16:26:28 +0800 Subject: [PATCH 12/18] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=A2=B3=E7=90=86?= =?UTF-8?q?=E6=89=93=E5=8C=85=EF=BC=8C=E5=8A=A0=E5=85=A5options,public,tem?= =?UTF-8?q?plates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.go | 14 ++ build.sh | 15 +++ build/generate-bindata.go | 87 +++++++++++++ build/generate-emoji.go | 225 +++++++++++++++++++++++++++++++++ build/generate-gitignores.go | 131 +++++++++++++++++++ build/generate-images.js | 83 ++++++++++++ build/generate-licenses.go | 119 +++++++++++++++++ build/generate-svg.js | 63 +++++++++ build/gocovmerge.go | 120 ++++++++++++++++++ build/update-locales.sh | 23 ++++ go.mod | 2 + go.sum | 4 + modules/schemas/issue.json | 114 +++++++++++++++++ modules/schemas/label.json | 28 ++++ modules/schemas/milestone.json | 67 ++++++++++ modules/schemas/reaction.json | 29 +++++ 16 files changed, 1124 insertions(+) create mode 100644 build.go create mode 100644 build.sh create mode 100644 build/generate-bindata.go create mode 100644 build/generate-emoji.go create mode 100644 build/generate-gitignores.go create mode 100755 build/generate-images.js create mode 100644 build/generate-licenses.go create mode 100755 build/generate-svg.js create mode 100644 build/gocovmerge.go create mode 100755 build/update-locales.sh create mode 100644 modules/schemas/issue.json create mode 100644 modules/schemas/label.json create mode 100644 modules/schemas/milestone.json create mode 100644 modules/schemas/reaction.json diff --git a/build.go b/build.go new file mode 100644 index 0000000..d410e17 --- /dev/null +++ b/build.go @@ -0,0 +1,14 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +//go:build vendor + +package main + +// Libraries that are included to vendor utilities used during build. +// These libraries will not be included in a normal compilation. + +import ( + // for embed + _ "github.com/shurcooL/vfsgen" +) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..573317a --- /dev/null +++ b/build.sh @@ -0,0 +1,15 @@ +#!/bin/bash +echo "go mod tidy..." +go mod tidy + +echo "go mod vendor..." +go mod vendor + +echo "go generate bindata.go for migration,options,public,templates..." +go run build/generate-bindata.go modules/schemas migration vendor/code.gitea.io/gitea/modules/migration/bindata.go +go run build/generate-bindata.go options options vendor/code.gitea.io/gitea/modules/options/bindata.go +go run build/generate-bindata.go public public vendor/code.gitea.io/gitea/modules/public/bindata.go +go run build/generate-bindata.go templates templates vendor/code.gitea.io/gitea/modules/templates/bindata.go + +echo "go build -tags 'bindata' -o gitea_hat main.go..." +go build -tags 'bindata' -o gitea_hat main.go diff --git a/build/generate-bindata.go b/build/generate-bindata.go new file mode 100644 index 0000000..efd172f --- /dev/null +++ b/build/generate-bindata.go @@ -0,0 +1,87 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package main + +import ( + "bytes" + "crypto/sha1" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + "strconv" + + "github.com/shurcooL/vfsgen" +) + +func needsUpdate(dir string, filename string) (bool, []byte) { + needRegen := false + _, err := os.Stat(filename) + if err != nil { + needRegen = true + } + + oldHash, err := ioutil.ReadFile(filename + ".hash") + if err != nil { + oldHash = []byte{} + } + + hasher := sha1.New() + + err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + _, _ = hasher.Write([]byte(info.Name())) + _, _ = hasher.Write([]byte(info.ModTime().String())) + _, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16))) + return nil + }) + if err != nil { + return true, oldHash + } + + newHash := hasher.Sum([]byte{}) + + if bytes.Compare(oldHash, newHash) != 0 { + + return true, newHash + } + + return needRegen, newHash +} + +func main() { + if len(os.Args) != 4 { + log.Fatal("Insufficient number of arguments. Need: directory packageName filename") + } + + dir, packageName, filename := os.Args[1], os.Args[2], os.Args[3] + + update, newHash := needsUpdate(dir, filename) + + if !update { + fmt.Printf("bindata for %s already up-to-date\n", packageName) + return + } + + fmt.Printf("generating bindata for %s\n", packageName) + var fsTemplates http.FileSystem = http.Dir(dir) + err := vfsgen.Generate(fsTemplates, vfsgen.Options{ + PackageName: packageName, + BuildTags: "bindata", + VariableName: "Assets", + Filename: filename, + }) + if err != nil { + log.Fatalf("%v\n", err) + } + _ = ioutil.WriteFile(filename+".hash", newHash, 0666) +} diff --git a/build/generate-emoji.go b/build/generate-emoji.go new file mode 100644 index 0000000..f8e6498 --- /dev/null +++ b/build/generate-emoji.go @@ -0,0 +1,225 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Copyright 2015 Kenneth Shaw +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package main + +import ( + "flag" + "fmt" + "go/format" + "io/ioutil" + "log" + "net/http" + "regexp" + "sort" + "strconv" + "strings" + "unicode/utf8" + + jsoniter "github.com/json-iterator/go" +) + +const ( + gemojiURL = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json" + maxUnicodeVersion = 12 +) + +var ( + flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out") +) + +// Gemoji is a set of emoji data. +type Gemoji []Emoji + +// Emoji represents a single emoji and associated data. +type Emoji struct { + Emoji string `json:"emoji"` + Description string `json:"description,omitempty"` + Aliases []string `json:"aliases"` + UnicodeVersion string `json:"unicode_version,omitempty"` + SkinTones bool `json:"skin_tones,omitempty"` +} + +// Don't include some fields in JSON +func (e Emoji) MarshalJSON() ([]byte, error) { + type emoji Emoji + x := emoji(e) + x.UnicodeVersion = "" + x.Description = "" + x.SkinTones = false + json := jsoniter.ConfigCompatibleWithStandardLibrary + return json.Marshal(x) +} + +func main() { + var err error + + flag.Parse() + + // generate data + buf, err := generate() + if err != nil { + log.Fatal(err) + } + + // write + err = ioutil.WriteFile(*flagOut, buf, 0644) + if err != nil { + log.Fatal(err) + } +} + +var replacer = strings.NewReplacer( + "main.Gemoji", "Gemoji", + "main.Emoji", "\n", + "}}", "},\n}", + ", Description:", ", ", + ", Aliases:", ", ", + ", UnicodeVersion:", ", ", + ", SkinTones:", ", ", +) + +var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`) + +func generate() ([]byte, error) { + var err error + + // load gemoji data + res, err := http.Get(gemojiURL) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // read all + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, err + } + + // unmarshal + var data Gemoji + json := jsoniter.ConfigCompatibleWithStandardLibrary + err = json.Unmarshal(body, &data) + if err != nil { + return nil, err + } + + var skinTones = make(map[string]string) + + skinTones["\U0001f3fb"] = "Light Skin Tone" + skinTones["\U0001f3fc"] = "Medium-Light Skin Tone" + skinTones["\U0001f3fd"] = "Medium Skin Tone" + skinTones["\U0001f3fe"] = "Medium-Dark Skin Tone" + skinTones["\U0001f3ff"] = "Dark Skin Tone" + + var tmp Gemoji + + //filter out emoji that require greater than max unicode version + for i := range data { + val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64) + if int(val) <= maxUnicodeVersion { + tmp = append(tmp, data[i]) + } + } + data = tmp + + sort.Slice(data, func(i, j int) bool { + return data[i].Aliases[0] < data[j].Aliases[0] + }) + + aliasMap := make(map[string]int, len(data)) + + for i, e := range data { + if e.Emoji == "" || len(e.Aliases) == 0 { + continue + } + for _, a := range e.Aliases { + if a == "" { + continue + } + aliasMap[a] = i + } + } + + // gitea customizations + i, ok := aliasMap["tada"] + if ok { + data[i].Aliases = append(data[i].Aliases, "hooray") + } + i, ok = aliasMap["laughing"] + if ok { + data[i].Aliases = append(data[i].Aliases, "laugh") + } + + // write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet) + file, _ := json.Marshal(data) + _ = ioutil.WriteFile("assets/emoji.json", file, 0644) + + // Add skin tones to emoji that support it + var ( + s []string + newEmoji string + newDescription string + newData Emoji + ) + + for i := range data { + if data[i].SkinTones { + for k, v := range skinTones { + s = strings.Split(data[i].Emoji, "") + + if utf8.RuneCountInString(data[i].Emoji) == 1 { + s = append(s, k) + } else { + // insert into slice after first element because all emoji that support skin tones + // have that modifier placed at this spot + s = append(s, "") + copy(s[2:], s[1:]) + s[1] = k + } + + newEmoji = strings.Join(s, "") + newDescription = data[i].Description + ": " + v + newAlias := data[i].Aliases[0] + "_" + strings.ReplaceAll(v, " ", "_") + + newData = Emoji{newEmoji, newDescription, []string{newAlias}, "12.0", false} + data = append(data, newData) + } + } + } + + // add header + str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data)) + + // change the format of the unicode string + str = emojiRE.ReplaceAllStringFunc(str, func(s string) string { + var err error + s, err = strconv.Unquote(s[len("{Emoji:"):]) + if err != nil { + panic(err) + } + return "{" + strconv.QuoteToASCII(s) + }) + + // format + return format.Source([]byte(str)) +} + +const hdr = ` +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package emoji + +// Code generated by gen.go. DO NOT EDIT. +// Sourced from %s +// +var GemojiData = %#v +` diff --git a/build/generate-gitignores.go b/build/generate-gitignores.go new file mode 100644 index 0000000..d0b972e --- /dev/null +++ b/build/generate-gitignores.go @@ -0,0 +1,131 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "archive/tar" + "compress/gzip" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" + + "code.gitea.io/gitea/modules/util" +) + +func main() { + var ( + prefix = "gitea-gitignore" + url = "https://api.github.com/repos/github/gitignore/tarball" + githubApiToken = "" + githubUsername = "" + destination = "" + ) + + flag.StringVar(&destination, "dest", "options/gitignore/", "destination for the gitignores") + flag.StringVar(&githubUsername, "username", "", "github username") + flag.StringVar(&githubApiToken, "token", "", "github api token") + flag.Parse() + + file, err := ioutil.TempFile(os.TempDir(), prefix) + + if err != nil { + log.Fatalf("Failed to create temp file. %s", err) + } + + defer util.Remove(file.Name()) + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Fatalf("Failed to download archive. %s", err) + } + + if len(githubApiToken) > 0 && len(githubUsername) > 0 { + req.SetBasicAuth(githubUsername, githubApiToken) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Fatalf("Failed to download archive. %s", err) + } + defer resp.Body.Close() + + if _, err := io.Copy(file, resp.Body); err != nil { + log.Fatalf("Failed to copy archive to file. %s", err) + } + + if _, err := file.Seek(0, 0); err != nil { + log.Fatalf("Failed to reset seek on archive. %s", err) + } + + gz, err := gzip.NewReader(file) + + if err != nil { + log.Fatalf("Failed to gunzip the archive. %s", err) + } + + tr := tar.NewReader(gz) + + filesToCopy := make(map[string]string, 0) + + for { + hdr, err := tr.Next() + + if err == io.EOF { + break + } + + if err != nil { + log.Fatalf("Failed to iterate archive. %s", err) + } + + if filepath.Ext(hdr.Name) != ".gitignore" { + continue + } + + if hdr.Typeflag == tar.TypeSymlink { + fmt.Printf("Found symlink %s -> %s\n", hdr.Name, hdr.Linkname) + filesToCopy[strings.TrimSuffix(filepath.Base(hdr.Name), ".gitignore")] = strings.TrimSuffix(filepath.Base(hdr.Linkname), ".gitignore") + continue + } + + out, err := os.Create(path.Join(destination, strings.TrimSuffix(filepath.Base(hdr.Name), ".gitignore"))) + + if err != nil { + log.Fatalf("Failed to create new file. %s", err) + } + + defer out.Close() + + if _, err := io.Copy(out, tr); err != nil { + log.Fatalf("Failed to write new file. %s", err) + } else { + fmt.Printf("Written %s\n", out.Name()) + } + } + + for dst, src := range filesToCopy { + // Read all content of src to data + src = path.Join(destination, src) + data, err := ioutil.ReadFile(src) + if err != nil { + log.Fatalf("Failed to read src file. %s", err) + } + // Write data to dst + dst = path.Join(destination, dst) + err = ioutil.WriteFile(dst, data, 0644) + if err != nil { + log.Fatalf("Failed to write new file. %s", err) + } + fmt.Printf("Written (copy of %s) %s\n", src, dst) + } + + fmt.Println("Done") +} diff --git a/build/generate-images.js b/build/generate-images.js new file mode 100755 index 0000000..b661681 --- /dev/null +++ b/build/generate-images.js @@ -0,0 +1,83 @@ +import imageminZopfli from 'imagemin-zopfli'; +import {optimize, extendDefaultPlugins} from 'svgo'; +import {fabric} from 'fabric'; +import fs from 'fs'; +import {resolve, dirname} from 'path'; +import {fileURLToPath} from 'url'; + +const {readFile, writeFile} = fs.promises; +const __dirname = dirname(fileURLToPath(import.meta.url)); +const logoFile = resolve(__dirname, '../assets/logo.svg'); + +function exit(err) { + if (err) console.error(err); + process.exit(err ? 1 : 0); +} + +function loadSvg(svg) { + return new Promise((resolve) => { + fabric.loadSVGFromString(svg, (objects, options) => { + resolve({objects, options}); + }); + }); +} + +async function generate(svg, outputFile, {size, bg}) { + if (outputFile.endsWith('.svg')) { + const {data} = optimize(svg, { + plugins: extendDefaultPlugins([ + 'removeDimensions', + { + name: 'addAttributesToSVGElement', + params: {attributes: [{width: size}, {height: size}]} + }, + ]), + }); + await writeFile(outputFile, data); + return; + } + + const {objects, options} = await loadSvg(svg); + const canvas = new fabric.Canvas(); + canvas.setDimensions({width: size, height: size}); + const ctx = canvas.getContext('2d'); + ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1); + + if (bg) { + canvas.add(new fabric.Rect({ + left: 0, + top: 0, + height: size * (1 / (size / options.height)), + width: size * (1 / (size / options.width)), + fill: 'white', + })); + } + + canvas.add(fabric.util.groupSVGElements(objects, options)); + canvas.renderAll(); + + let png = Buffer.from([]); + for await (const chunk of canvas.createPNGStream()) { + png = Buffer.concat([png, chunk]); + } + + png = await imageminZopfli({more: true})(png); + await writeFile(outputFile, png); +} + +async function main() { + const gitea = process.argv.slice(2).includes('gitea'); + const svg = await readFile(logoFile, 'utf8'); + + await Promise.all([ + generate(svg, resolve(__dirname, '../public/img/logo.svg'), {size: 32}), + generate(svg, resolve(__dirname, '../public/img/logo.png'), {size: 512}), + generate(svg, resolve(__dirname, '../public/img/favicon.png'), {size: 180}), + generate(svg, resolve(__dirname, '../public/img/avatar_default.png'), {size: 200}), + generate(svg, resolve(__dirname, '../public/img/apple-touch-icon.png'), {size: 180, bg: true}), + gitea && generate(svg, resolve(__dirname, '../public/img/gitea.svg'), {size: 32}), + ]); +} + +main().then(exit).catch(exit); + diff --git a/build/generate-licenses.go b/build/generate-licenses.go new file mode 100644 index 0000000..4009a03 --- /dev/null +++ b/build/generate-licenses.go @@ -0,0 +1,119 @@ +//go:build ignore +// +build ignore + +package main + +import ( + "archive/tar" + "compress/gzip" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" + + "code.gitea.io/gitea/modules/util" +) + +func main() { + var ( + prefix = "gitea-licenses" + url = "https://api.github.com/repos/spdx/license-list-data/tarball" + githubApiToken = "" + githubUsername = "" + destination = "" + ) + + flag.StringVar(&destination, "dest", "options/license/", "destination for the licenses") + flag.StringVar(&githubUsername, "username", "", "github username") + flag.StringVar(&githubApiToken, "token", "", "github api token") + flag.Parse() + + file, err := ioutil.TempFile(os.TempDir(), prefix) + + if err != nil { + log.Fatalf("Failed to create temp file. %s", err) + } + + defer util.Remove(file.Name()) + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Fatalf("Failed to download archive. %s", err) + } + + if len(githubApiToken) > 0 && len(githubUsername) > 0 { + req.SetBasicAuth(githubUsername, githubApiToken) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Fatalf("Failed to download archive. %s", err) + } + + defer resp.Body.Close() + + if _, err := io.Copy(file, resp.Body); err != nil { + log.Fatalf("Failed to copy archive to file. %s", err) + } + + if _, err := file.Seek(0, 0); err != nil { + log.Fatalf("Failed to reset seek on archive. %s", err) + } + + gz, err := gzip.NewReader(file) + + if err != nil { + log.Fatalf("Failed to gunzip the archive. %s", err) + } + + tr := tar.NewReader(gz) + + for { + hdr, err := tr.Next() + + if err == io.EOF { + break + } + + if err != nil { + log.Fatalf("Failed to iterate archive. %s", err) + } + + if !strings.Contains(hdr.Name, "/text/") { + continue + } + + if filepath.Ext(hdr.Name) != ".txt" { + continue + } + + if strings.HasPrefix(filepath.Base(hdr.Name), "README") { + continue + } + + if strings.HasPrefix(filepath.Base(hdr.Name), "deprecated_") { + continue + } + out, err := os.Create(path.Join(destination, strings.TrimSuffix(filepath.Base(hdr.Name), ".txt"))) + + if err != nil { + log.Fatalf("Failed to create new file. %s", err) + } + + defer out.Close() + + if _, err := io.Copy(out, tr); err != nil { + log.Fatalf("Failed to write new file. %s", err) + } else { + fmt.Printf("Written %s\n", out.Name()) + } + } + + fmt.Println("Done") +} diff --git a/build/generate-svg.js b/build/generate-svg.js new file mode 100755 index 0000000..cde3f31 --- /dev/null +++ b/build/generate-svg.js @@ -0,0 +1,63 @@ +import fastGlob from 'fast-glob'; +import {optimize, extendDefaultPlugins} from 'svgo'; +import {resolve, parse, dirname} from 'path'; +import fs from 'fs'; +import {fileURLToPath} from 'url'; + +const {readFile, writeFile, mkdir} = fs.promises; +const __dirname = dirname(fileURLToPath(import.meta.url)); +const glob = (pattern) => fastGlob.sync(pattern, {cwd: resolve(__dirname), absolute: true}); +const outputDir = resolve(__dirname, '../public/img/svg'); + +function exit(err) { + if (err) console.error(err); + process.exit(err ? 1 : 0); +} + +async function processFile(file, {prefix, fullName} = {}) { + let name; + + if (fullName) { + name = fullName; + } else { + name = parse(file).name; + if (prefix) name = `${prefix}-${name}`; + if (prefix === 'octicon') name = name.replace(/-[0-9]+$/, ''); // chop of '-16' on octicons + } + + const {data} = optimize(await readFile(file, 'utf8'), { + plugins: extendDefaultPlugins([ + 'removeXMLNS', + 'removeDimensions', + {name: 'prefixIds', params: {prefix: () => name}}, + { + name: 'addClassesToSVGElement', + params: {classNames: ['svg', name]}, + }, + { + name: 'addAttributesToSVGElement', + params: {attributes: [{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'}]}, + }, + ]), + }); + await writeFile(resolve(outputDir, `${name}.svg`), data); +} + +function processFiles(pattern, opts) { + return glob(pattern).map((file) => processFile(file, opts)); +} + +async function main() { + try { + await mkdir(outputDir); + } catch {} + + await Promise.all([ + ...processFiles('../node_modules/@primer/octicons/build/svg/*-16.svg', {prefix: 'octicon'}), + ...processFiles('../web_src/svg/*.svg'), + ...processFiles('../public/img/gitea.svg', {fullName: 'gitea-gitea'}), + ]); +} + +main().then(exit).catch(exit); + diff --git a/build/gocovmerge.go b/build/gocovmerge.go new file mode 100644 index 0000000..b38cf5e --- /dev/null +++ b/build/gocovmerge.go @@ -0,0 +1,120 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Copyright (c) 2015, Wade Simmons +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// gocovmerge takes the results from multiple `go test -coverprofile` runs and +// merges them into one profile + +//go:build ignore +// +build ignore + +package main + +import ( + "flag" + "fmt" + "io" + "log" + "os" + "sort" + + "golang.org/x/tools/cover" +) + +func mergeProfiles(p *cover.Profile, merge *cover.Profile) { + if p.Mode != merge.Mode { + log.Fatalf("cannot merge profiles with different modes") + } + // Since the blocks are sorted, we can keep track of where the last block + // was inserted and only look at the blocks after that as targets for merge + startIndex := 0 + for _, b := range merge.Blocks { + startIndex = mergeProfileBlock(p, b, startIndex) + } +} + +func mergeProfileBlock(p *cover.Profile, pb cover.ProfileBlock, startIndex int) int { + sortFunc := func(i int) bool { + pi := p.Blocks[i+startIndex] + return pi.StartLine >= pb.StartLine && (pi.StartLine != pb.StartLine || pi.StartCol >= pb.StartCol) + } + + i := 0 + if sortFunc(i) != true { + i = sort.Search(len(p.Blocks)-startIndex, sortFunc) + } + i += startIndex + if i < len(p.Blocks) && p.Blocks[i].StartLine == pb.StartLine && p.Blocks[i].StartCol == pb.StartCol { + if p.Blocks[i].EndLine != pb.EndLine || p.Blocks[i].EndCol != pb.EndCol { + log.Fatalf("OVERLAP MERGE: %v %v %v", p.FileName, p.Blocks[i], pb) + } + switch p.Mode { + case "set": + p.Blocks[i].Count |= pb.Count + case "count", "atomic": + p.Blocks[i].Count += pb.Count + default: + log.Fatalf("unsupported covermode: '%s'", p.Mode) + } + } else { + if i > 0 { + pa := p.Blocks[i-1] + if pa.EndLine >= pb.EndLine && (pa.EndLine != pb.EndLine || pa.EndCol > pb.EndCol) { + log.Fatalf("OVERLAP BEFORE: %v %v %v", p.FileName, pa, pb) + } + } + if i < len(p.Blocks)-1 { + pa := p.Blocks[i+1] + if pa.StartLine <= pb.StartLine && (pa.StartLine != pb.StartLine || pa.StartCol < pb.StartCol) { + log.Fatalf("OVERLAP AFTER: %v %v %v", p.FileName, pa, pb) + } + } + p.Blocks = append(p.Blocks, cover.ProfileBlock{}) + copy(p.Blocks[i+1:], p.Blocks[i:]) + p.Blocks[i] = pb + } + return i + 1 +} + +func addProfile(profiles []*cover.Profile, p *cover.Profile) []*cover.Profile { + i := sort.Search(len(profiles), func(i int) bool { return profiles[i].FileName >= p.FileName }) + if i < len(profiles) && profiles[i].FileName == p.FileName { + mergeProfiles(profiles[i], p) + } else { + profiles = append(profiles, nil) + copy(profiles[i+1:], profiles[i:]) + profiles[i] = p + } + return profiles +} + +func dumpProfiles(profiles []*cover.Profile, out io.Writer) { + if len(profiles) == 0 { + return + } + fmt.Fprintf(out, "mode: %s\n", profiles[0].Mode) + for _, p := range profiles { + for _, b := range p.Blocks { + fmt.Fprintf(out, "%s:%d.%d,%d.%d %d %d\n", p.FileName, b.StartLine, b.StartCol, b.EndLine, b.EndCol, b.NumStmt, b.Count) + } + } +} + +func main() { + flag.Parse() + + var merged []*cover.Profile + + for _, file := range flag.Args() { + profiles, err := cover.ParseProfiles(file) + if err != nil { + log.Fatalf("failed to parse profiles: %v", err) + } + for _, p := range profiles { + merged = addProfile(merged, p) + } + } + + dumpProfiles(merged, os.Stdout) +} diff --git a/build/update-locales.sh b/build/update-locales.sh new file mode 100755 index 0000000..046f48e --- /dev/null +++ b/build/update-locales.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +mv ./options/locale/locale_en-US.ini ./options/ + +# Make sure to only change lines that have the translation enclosed between quotes +sed -i -r -e '/^[a-zA-Z0-9_.-]+[ ]*=[ ]*".*"$/ { + s/^([a-zA-Z0-9_.-]+)[ ]*="/\1=/ + s/\\"/"/g + s/"$// + }' ./options/locale/*.ini + +# Remove translation under 25% of en_us +baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1) +baselines=$((baselines / 4)) +for filename in ./options/locale/*.ini; do + lines=$(wc -l "$filename" | cut -d" " -f1) + if [ $lines -lt $baselines ]; then + echo "Removing $filename: $lines/$baselines" + rm "$filename" + fi +done + +mv ./options/locale_en-US.ini ./options/locale/ diff --git a/go.mod b/go.mod index 5c36cf0..51b38b7 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/klauspost/cpuid/v2 v2.2.3 github.com/russross/blackfriday/v2 v2.1.0 + github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 github.com/urfave/cli v1.22.12 golang.org/x/net v0.8.0 golang.org/x/text v0.8.0 @@ -180,6 +181,7 @@ require ( github.com/rs/xid v1.4.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 // indirect github.com/sergi/go-diff v1.3.1 // indirect + github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/skeema/knownhosts v1.1.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect diff --git a/go.sum b/go.sum index 74eaa0a..f6e54ca 100644 --- a/go.sum +++ b/go.sum @@ -1119,7 +1119,11 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY= github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= diff --git a/modules/schemas/issue.json b/modules/schemas/issue.json new file mode 100644 index 0000000..25753c3 --- /dev/null +++ b/modules/schemas/issue.json @@ -0,0 +1,114 @@ +{ + "title": "Issue", + "description": "Issues associated to a repository within a forge (Gitea, GitLab, etc.).", + + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "number": { + "description": "Unique identifier, relative to the repository.", + "type": "number" + }, + "poster_id": { + "description": "Unique identifier of the user who authored the issue.", + "type": "number" + }, + "poster_name": { + "description": "Name of the user who authored the issue.", + "type": "string" + }, + "poster_email": { + "description": "Email of the user who authored the issue.", + "type": "string" + }, + "title": { + "description": "Short description displayed as the title.", + "type": "string" + }, + "content": { + "description": "Long, multiline, description.", + "type": "string" + }, + "ref": { + "description": "Target branch in the repository.", + "type": "string" + }, + "milestone": { + "description": "Name of the milestone.", + "type": "string" + }, + "state": { + "description": "A 'closed' issue will not see any activity in the future, otherwise it is 'open'.", + "enum": [ + "closed", + "open" + ] + }, + "is_locked": { + "description": "A locked issue can only be modified by privileged users.", + "type": "boolean" + }, + "created": { + "description": "Creation time.", + "type": "string", + "format": "date-time" + }, + "updated": { + "description": "Last update time.", + "type": "string", + "format": "date-time" + }, + "closed": { + "description": "The last time 'state' changed to 'closed'.", + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ] + }, + "labels": { + "description": "List of labels.", + "type": "array", + "items": { + "$ref": "label.json" + } + }, + "reactions": { + "description": "List of reactions.", + "type": "array", + "items": { + "$ref": "reaction.json" + } + }, + "assignees": { + "description": "List of assignees.", + "type": "array", + "items": { + "description": "Name of a user assigned to the issue.", + "type": "string" + } + } + }, + "required": [ + "number", + "poster_id", + "poster_name", + "title", + "content", + "state", + "is_locked", + "created", + "updated" + ] + }, + + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "http://example.com/issue.json", + "$$target": "issue.json" +} diff --git a/modules/schemas/label.json b/modules/schemas/label.json new file mode 100644 index 0000000..561a2e3 --- /dev/null +++ b/modules/schemas/label.json @@ -0,0 +1,28 @@ +{ + "title": "Label", + "description": "Label associated to an issue.", + + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "Name of the label, unique within the repository.", + "type": "string" + }, + "color": { + "description": "Color code of the label.", + "type": "string" + }, + "description": { + "description": "Long, multiline, description.", + "type": "string" + } + }, + "required": [ + "name" + ], + + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "label.json", + "$$target": "label.json" +} diff --git a/modules/schemas/milestone.json b/modules/schemas/milestone.json new file mode 100644 index 0000000..7024ef4 --- /dev/null +++ b/modules/schemas/milestone.json @@ -0,0 +1,67 @@ +{ + "title": "Milestone", + "description": "Milestone associated to a repository within a forge.", + + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "title": { + "description": "Short description.", + "type": "string" + }, + "description": { + "description": "Long, multiline, description.", + "type": "string" + }, + "deadline": { + "description": "Deadline after which the milestone is overdue.", + "type": "string", + "format": "date-time" + }, + "created": { + "description": "Creation time.", + "type": "string", + "format": "date-time" + }, + "updated": { + "description": "Last update time.", + "type": "string", + "format": "date-time" + }, + "closed": { + "description": "The last time 'state' changed to 'closed'.", + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ] + }, + "state": { + "description": "A 'closed' issue will not see any activity in the future, otherwise it is 'open'.", + "enum": [ + "closed", + "open" + ] + } + }, + "required": [ + "title", + "description", + "deadline", + "created", + "updated", + "closed", + "state" + ] + }, + + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "http://example.com/milestone.json", + "$$target": "milestone.json" +} diff --git a/modules/schemas/reaction.json b/modules/schemas/reaction.json new file mode 100644 index 0000000..2565251 --- /dev/null +++ b/modules/schemas/reaction.json @@ -0,0 +1,29 @@ +{ + "title": "Reaction", + "description": "Reaction associated to an issue or a comment.", + + "type": "object", + "additionalProperties": false, + "properties": { + "user_id": { + "description": "Unique identifier of the user who authored the reaction.", + "type": "number" + }, + "user_name": { + "description": "Name of the user who authored the reaction.", + "type": "string" + }, + "content": { + "description": "Representation of the reaction", + "type": "string" + } + }, + "required": [ + "user_id", + "content" + ], + + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "http://example.com/reaction.json", + "$$target": "reaction.json" +} -- 2.34.1 From ebf898c2976e83b83aa50d12400022de80ba9d99 Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Tue, 23 May 2023 18:17:57 +0800 Subject: [PATCH 13/18] Dockerfile --- Dockerfile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..96c86f1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM bitnami/git:latest +RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list +RUN apt update +RUN apt install -y vim nano curl wget +RUN wget http://go.dev/dl/go1.20.4.linux-amd64.tar.gz +RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz +ENV PATH=$PATH:/usr/local/go/bin +RUN go version +ADD ./ /gitea_hat/ +RUN cd /gitea_hat/ && ls -lh && sh build.sh -- 2.34.1 From 93e71d78008e4873a90c95febe199c888a9cf615 Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Tue, 23 May 2023 18:26:04 +0800 Subject: [PATCH 14/18] Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 96c86f1..10bd599 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM bitnami/git:latest RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list RUN apt update RUN apt install -y vim nano curl wget -RUN wget http://go.dev/dl/go1.20.4.linux-amd64.tar.gz +RUN wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz ENV PATH=$PATH:/usr/local/go/bin RUN go version -- 2.34.1 From 102cf582f0ddd5250a830f2c09599d6060f22544 Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Tue, 23 May 2023 18:29:59 +0800 Subject: [PATCH 15/18] Dockerfile wget --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 10bd599..90c84cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM bitnami/git:latest RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list RUN apt update RUN apt install -y vim nano curl wget -RUN wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz +RUN wget --no-check-certificate https://go.dev/dl/go1.20.4.linux-amd64.tar.gz RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz ENV PATH=$PATH:/usr/local/go/bin RUN go version -- 2.34.1 From 6ceb249c13bac644b6fb58e485daedbad7cb928f Mon Sep 17 00:00:00 2001 From: xxqfamous Date: Wed, 24 May 2023 09:29:32 +0800 Subject: [PATCH 16/18] Dockerfile GOPROXY --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 90c84cf..b396794 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,5 +6,6 @@ RUN wget --no-check-certificate https://go.dev/dl/go1.20.4.linux-amd64.tar.gz RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz ENV PATH=$PATH:/usr/local/go/bin RUN go version +RUN go env -w GOPROXY=https://goproxy.cn ADD ./ /gitea_hat/ RUN cd /gitea_hat/ && ls -lh && sh build.sh -- 2.34.1 From f6ce389d6c1c4864f9ae973645a05f9623ae1fef Mon Sep 17 00:00:00 2001 From: xxq250 Date: Wed, 14 Jun 2023 09:43:39 +0800 Subject: [PATCH 17/18] gitea admin cmd --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index b396794..6a6fa03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,3 +9,5 @@ RUN go version RUN go env -w GOPROXY=https://goproxy.cn ADD ./ /gitea_hat/ RUN cd /gitea_hat/ && ls -lh && sh build.sh + +#/gitea_hat/gitea_hat admin user create --username root --password 123456 --email root@forge.com --admin -- 2.34.1 From 555994308b540b675cba4898763d4f34b2450b7b Mon Sep 17 00:00:00 2001 From: xxq250 Date: Tue, 18 Jul 2023 16:13:31 +0800 Subject: [PATCH 18/18] Update README.md --- README.md | 157 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 80 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 883dc85..3ca6da3 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,80 @@ -

- - Project logo - -

- -

Gitea GitLink版本

- -
- -[![Status](https://img.shields.io/badge/status-active-success.svg)]() -[![GitLink Issues](https://img.shields.io/github/issues/kylelobo/The-Documentation-Compendium.svg)](https://www.gitlink.org.cn/Gitlink/gitea_hat/issues) -[![GitLink Pull Requests](https://img.shields.io/github/issues-pr/kylelobo/The-Documentation-Compendium.svg)](https://www.gitlink.org.cn/Gitlink/gitea_hat/pulls) -[![License](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE) - -
- ---- - -

此版本为GitLink平台使用的Git服务,该服务基于Gitea进行开发。 -
-

- -- [🧐 关于](#-关于) -- [编译](#编译) -- [运行](#运行) -- [接口文档](#接口文档) -- [⛏️ 使用](#️-使用) - -## 🧐 关于 - -该项目是为了方便平台后续Gitea版本的升级,将个性化接口部分从Gitea中抽离出来的项目,模块定义遵循Gitea规则,目前基于Gitea v1.18.5版本。 - -## 编译 - -类Linux平台,在项目根目录运行: -```shell -# 编译Linux 64位可执行程序 -CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o gitea main.go - -# 编译Windows 64位可执行程序 -CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o gitea main.go - -# 编译mac 64位可执行程序 -CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o gitea main.go -``` - -Win平台,在项目根目录运行: -```shell -# 编译Linux 64位可执行程序 -SET CGO_ENABLED=0 -SET GOOS=linux -SET GOARCH=amd64 -go build -o gitea main.go - -... -``` - -## 运行 - -在项目根目录下运行: - -``` -./gitea -p 10082 -``` - -## 接口文档 -- [ApiDoc](https://www.apifox.cn/apidoc/project-1809666) - 接口文档 - -## ⛏️ 使用 - -- [Gitea](https://gitea.io/zh-cn/) - Gitea +

+ + Project logo + +

+ +

Gitea GitLink版本

+ +
+ +[![Status](https://img.shields.io/badge/status-active-success.svg)]() +[![GitLink Issues](https://img.shields.io/github/issues/kylelobo/The-Documentation-Compendium.svg)](https://www.gitlink.org.cn/Gitlink/gitea_hat/issues) +[![GitLink Pull Requests](https://img.shields.io/github/issues-pr/kylelobo/The-Documentation-Compendium.svg)](https://www.gitlink.org.cn/Gitlink/gitea_hat/pulls) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE) + +
+ +--- + +

此版本为GitLink平台使用的Git服务,该服务基于Gitea进行开发。 +
+

+ +- [🧐 关于](#-关于) +- [编译](#编译) +- [运行](#运行) +- [接口文档](#接口文档) +- [⛏️ 使用](#️-使用) + +## 🧐 关于 + +该项目是为了方便平台后续Gitea版本的升级,将个性化接口部分从Gitea中抽离出来的项目,模块定义遵循Gitea规则,目前基于Gitea v1.18.5版本。 + +## Go环境安装 +推荐1.20.x以上版本,下载https://go.dev/dl/ + +## 编译 + +类Linux平台,在项目根目录运行: +```shell +# 编译Linux 64位可执行程序 +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o gitea main.go + +# 编译Windows 64位可执行程序 +CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o gitea main.go + +# 编译mac 64位可执行程序 +CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o gitea main.go +``` + +Win平台,在项目根目录运行: +```shell +# 编译Linux 64位可执行程序 +SET CGO_ENABLED=0 +SET GOOS=linux +SET GOARCH=amd64 +go build -o gitea main.go + +... +``` + +## 运行 + +在项目根目录下运行: + +``` +./gitea -p 10082 +``` + +## 接口文档 +- [ApiDoc](https://www.apifox.cn/apidoc/project-1809666) - 接口文档 + +## ⛏️ 使用 + +- [Gitea](https://gitea.io/zh-cn/) - Gitea -- 2.34.1