diff options
author | yp05327 <576951401@qq.com> | 2024-10-02 04:25:08 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-01 15:25:08 -0400 |
commit | 70b7df0e5e5cce5a3561fa5a6a8abd4ebc902e68 (patch) | |
tree | 6532a12e349fe59e4c9eb66161246360aa6350d2 /routers | |
parent | f4b8f6fc40ce2869135372a5c6ec6418d27ebfba (diff) | |
download | gitea-70b7df0e5e5cce5a3561fa5a6a8abd4ebc902e68.tar.gz gitea-70b7df0e5e5cce5a3561fa5a6a8abd4ebc902e68.zip |
Support repo license (#24872)
Close #278
Close #24076
## Solutions:
- Use
[google/licenseclassifier](https://github.com/google/licenseclassifier/)
Test result between
[google/licensecheck](https://github.com/google/licensecheck) and
[go-license-detector](https://github.com/go-enry/go-license-detector):
https://github.com/go-gitea/gitea/pull/24872#issuecomment-1560361167
Test result between
[google/licensecheck](https://github.com/google/licensecheck) and
[google/licenseclassifier](https://github.com/google/licenseclassifier/):
https://github.com/go-gitea/gitea/pull/24872#issuecomment-1576092178
- Generate License Convert Name List to avoid import license templates
with same contents
Gitea automatically get latest license data from[
spdx/license-list-data](https://github.com/spdx/license-list-data).
But unfortunately, some license templates have same contents. #20915
[click here to see the
list](https://github.com/go-gitea/gitea/pull/24872#issuecomment-1584141684)
So we will generate a list of these license templates with same contents
and create a new file to save the result when using `make
generate-license`. (Need to decide the save path)
- Save License info into a new table `repo_license`
Can easily support searching repo by license in the future.
## Screen shot
Single License:
![image](https://github.com/go-gitea/gitea/assets/18380374/41260bd7-0b4c-4038-8592-508706cffa9f)
Multiple Licenses:
![image](https://github.com/go-gitea/gitea/assets/18380374/34ce2f73-7e18-446b-9b96-ecc4fb61bd70)
Triggers:
- [x] Push commit to default branch
- [x] Create repo
- [x] Mirror repo
- [x] When Default Branch is changed, licenses should be updated
Todo:
- [x] Save Licenses info in to DB when there's a change to license file
in the commit
- [x] DB Migration
- [x] A nominal test?
- [x] Select which library to
use(https://github.com/go-gitea/gitea/pull/24872#issuecomment-1560361167)
- [x] API Support
- [x] Add repo license table
- ~Select license in settings if there are several licenses(Not
recommended)~
- License board(later, not in this PR)
![image](https://github.com/go-gitea/gitea/assets/18380374/2c3c3bf8-bcc2-4c6d-8ce0-81d1a9733878)
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Denys Konovalov <kontakt@denyskon.de>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <m.huber@kithara.com>
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/api.go | 1 | ||||
-rw-r--r-- | routers/api/v1/repo/license.go | 51 | ||||
-rw-r--r-- | routers/api/v1/repo/repo.go | 11 | ||||
-rw-r--r-- | routers/api/v1/swagger/repo.go | 7 | ||||
-rw-r--r-- | routers/init.go | 2 | ||||
-rw-r--r-- | routers/private/default_branch.go | 11 | ||||
-rw-r--r-- | routers/private/hook_post_receive.go | 17 | ||||
-rw-r--r-- | routers/web/repo/branch.go | 2 | ||||
-rw-r--r-- | routers/web/repo/commit.go | 10 | ||||
-rw-r--r-- | routers/web/repo/release.go | 1 | ||||
-rw-r--r-- | routers/web/repo/view.go | 2 |
11 files changed, 105 insertions, 10 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 1244676508..5aa8ad44e5 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1327,6 +1327,7 @@ func Routes() *web.Router { m.Get("/issue_config", context.ReferencesGitRepo(), repo.GetIssueConfig) m.Get("/issue_config/validate", context.ReferencesGitRepo(), repo.ValidateIssueConfig) m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages) + m.Get("/licenses", reqRepoReader(unit.TypeCode), repo.GetLicenses) m.Get("/activities/feeds", repo.ListRepoActivityFeeds) m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed) m.Group("/avatar", func() { diff --git a/routers/api/v1/repo/license.go b/routers/api/v1/repo/license.go new file mode 100644 index 0000000000..8a6bdfd42f --- /dev/null +++ b/routers/api/v1/repo/license.go @@ -0,0 +1,51 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repo + +import ( + "net/http" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/context" +) + +// GetLicenses returns licenses +func GetLicenses(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/licenses repository repoGetLicenses + // --- + // summary: Get repo licenses + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // responses: + // "404": + // "$ref": "#/responses/notFound" + // "200": + // "$ref": "#/responses/LicensesList" + + licenses, err := repo_model.GetRepoLicenses(ctx, ctx.Repo.Repository) + if err != nil { + log.Error("GetRepoLicenses failed: %v", err) + ctx.InternalServerError(err) + return + } + + resp := make([]string, len(licenses)) + for i := range licenses { + resp[i] = licenses[i].License + } + + ctx.JSON(http.StatusOK, resp) +} diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 1bcec8fcf7..6c1a94ee16 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -731,6 +731,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err } // Default branch only updated if changed and exist or the repository is empty + updateRepoLicense := false if opts.DefaultBranch != nil && repo.DefaultBranch != *opts.DefaultBranch && (repo.IsEmpty || ctx.Repo.GitRepo.IsBranchExist(*opts.DefaultBranch)) { if !repo.IsEmpty { if err := gitrepo.SetDefaultBranch(ctx, ctx.Repo.Repository, *opts.DefaultBranch); err != nil { @@ -739,6 +740,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err return err } } + updateRepoLicense = true } repo.DefaultBranch = *opts.DefaultBranch } @@ -748,6 +750,15 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err return err } + if updateRepoLicense { + if err := repo_service.AddRepoToLicenseUpdaterQueue(&repo_service.LicenseUpdaterOptions{ + RepoID: ctx.Repo.Repository.ID, + }); err != nil { + ctx.Error(http.StatusInternalServerError, "AddRepoToLicenseUpdaterQueue", err) + return err + } + } + log.Trace("Repository basic settings updated: %s/%s", owner.Name, repo.Name) return nil } diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index 345835f9a5..b9d2a0217c 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -359,6 +359,13 @@ type swaggerLanguageStatistics struct { Body map[string]int64 `json:"body"` } +// LicensesList +// swagger:response LicensesList +type swaggerLicensesList struct { + // in: body + Body []string `json:"body"` +} + // CombinedStatus // swagger:response CombinedStatus type swaggerCombinedStatus struct { diff --git a/routers/init.go b/routers/init.go index e21f763c1e..fe80dfd2cd 100644 --- a/routers/init.go +++ b/routers/init.go @@ -172,6 +172,8 @@ func InitWebInstalled(ctx context.Context) { actions_service.Init() + mustInit(repo_service.InitLicenseClassifier) + // Finally start up the cron cron.NewContext(ctx) } diff --git a/routers/private/default_branch.go b/routers/private/default_branch.go index 7be909f955..03c19c8ff4 100644 --- a/routers/private/default_branch.go +++ b/routers/private/default_branch.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/private" gitea_context "code.gitea.io/gitea/services/context" + repo_service "code.gitea.io/gitea/services/repository" ) // SetDefaultBranch updates the default branch @@ -36,5 +37,15 @@ func SetDefaultBranch(ctx *gitea_context.PrivateContext) { }) return } + + if err := repo_service.AddRepoToLicenseUpdaterQueue(&repo_service.LicenseUpdaterOptions{ + RepoID: ctx.Repo.Repository.ID, + }); err != nil { + ctx.JSON(http.StatusInternalServerError, private.Response{ + Err: fmt.Sprintf("Unable to set default branch on repository: %s/%s Error: %v", ownerName, repoName, err), + }) + return + } + ctx.PlainText(http.StatusOK, "success") } diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 2d1688523c..5c01216356 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -278,10 +278,19 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { branch := refFullName.BranchName() - // If our branch is the default branch of an unforked repo - there's no PR to create or refer to - if !repo.IsFork && branch == baseRepo.DefaultBranch { - results = append(results, private.HookPostReceiveBranchResult{}) - continue + if branch == baseRepo.DefaultBranch { + if err := repo_service.AddRepoToLicenseUpdaterQueue(&repo_service.LicenseUpdaterOptions{ + RepoID: repo.ID, + }); err != nil { + ctx.JSON(http.StatusInternalServerError, private.Response{Err: err.Error()}) + return + } + + // If our branch is the default branch of an unforked repo - there's no PR to create or refer to + if !repo.IsFork { + results = append(results, private.HookPostReceiveBranchResult{}) + continue + } } pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch, issues_model.PullRequestFlowGithub) diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index 4897a5f4fc..4a62237838 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -89,7 +89,7 @@ func Branches(ctx *context.Context) { pager := context.NewPagination(int(branchesCount), pageSize, page, 5) pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager - + ctx.Data["LicenseFileName"] = repo_service.LicenseFileName ctx.HTML(http.StatusOK, tplBranch) } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index a433dd228e..0e4e10bf50 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -29,7 +29,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/gitdiff" - git_service "code.gitea.io/gitea/services/repository" + repo_service "code.gitea.io/gitea/services/repository" ) const ( @@ -101,7 +101,7 @@ func Commits(ctx *context.Context) { pager := context.NewPagination(int(commitsCount), pageSize, page, 5) pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager - + ctx.Data["LicenseFileName"] = repo_service.LicenseFileName ctx.HTML(http.StatusOK, tplCommits) } @@ -218,6 +218,8 @@ func SearchCommits(ctx *context.Context) { } ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name + ctx.Data["RefName"] = ctx.Repo.RefName + ctx.Data["LicenseFileName"] = repo_service.LicenseFileName ctx.HTML(http.StatusOK, tplCommits) } @@ -263,12 +265,12 @@ func FileHistory(ctx *context.Context) { pager := context.NewPagination(int(commitsCount), setting.Git.CommitsRangeSize, page, 5) pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager - + ctx.Data["LicenseFileName"] = repo_service.LicenseFileName ctx.HTML(http.StatusOK, tplCommits) } func LoadBranchesAndTags(ctx *context.Context) { - response, err := git_service.LoadBranchesAndTags(ctx, ctx.Repo, ctx.PathParam("sha")) + response, err := repo_service.LoadBranchesAndTags(ctx, ctx.Repo, ctx.PathParam("sha")) if err == nil { ctx.JSON(http.StatusOK, response) return diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index f551fffe95..566a82316f 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -289,7 +289,6 @@ func releasesOrTagsFeed(ctx *context.Context, isReleasesOnly bool, formatType st // SingleRelease renders a single release's page func SingleRelease(ctx *context.Context) { ctx.Data["PageIsReleaseList"] = true - ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch writeAccess := ctx.Repo.CanWrite(unit.TypeReleases) ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 12d202e4a0..9769117609 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -51,6 +51,7 @@ import ( "code.gitea.io/gitea/routers/web/feed" "code.gitea.io/gitea/services/context" issue_service "code.gitea.io/gitea/services/issue" + repo_service "code.gitea.io/gitea/services/repository" files_service "code.gitea.io/gitea/services/repository/files" "github.com/nektos/act/pkg/model" @@ -1077,6 +1078,7 @@ func renderHomeCode(ctx *context.Context) { ctx.Data["TreeLink"] = treeLink ctx.Data["TreeNames"] = treeNames ctx.Data["BranchLink"] = branchLink + ctx.Data["LicenseFileName"] = repo_service.LicenseFileName ctx.HTML(http.StatusOK, tplRepoHome) } |