snapshot of https://github.com/go-gitea/gitea.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped
Some checks failed
cache-seeder / prune (push) Has been skipped
cache-seeder / frontend (push) Failing after 3s
cache-seeder / python (push) Failing after 3s
cache-seeder / gobuild (push) Failing after 4s
cache-seeder / lint (bindata, lint-backend) (push) Failing after 3s
giteabot backport / giteabot (push) Has been skipped
giteabot / giteabot (push) Has been skipped
cache-prune / prune (push) Has been skipped
release-nightly-snapcraft / build-and-publish (ubuntu-24.04) (push) Has been cancelled
release-nightly-snapcraft / build-and-publish (ubuntu-24.04-arm) (push) Has been cancelled
release-nightly / nightly-binary (push) Has been cancelled
release-nightly / nightly-container (push) Has been cancelled
cron-renovate / cron-renovate (push) Has been skipped
This commit is contained in:
222
services/repository/license_test.go
Normal file
222
services/repository/license_test.go
Normal file
@@ -0,0 +1,222 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
repo_module "gitea.dev/modules/repository"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_detectLicense(t *testing.T) {
|
||||
type DetectLicenseTest struct {
|
||||
name string
|
||||
arg string
|
||||
want []string
|
||||
}
|
||||
|
||||
tests := []DetectLicenseTest{
|
||||
{
|
||||
name: "empty",
|
||||
arg: "",
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "no detected license",
|
||||
arg: "Copyright (c) 2023 Gitea",
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, repo_module.LoadRepoConfig())
|
||||
for _, licenseName := range repo_module.Licenses {
|
||||
license, err := repo_module.GetLicense(licenseName, &repo_module.LicenseValues{
|
||||
Owner: "Gitea",
|
||||
Email: "teabot@gitea.io",
|
||||
Repo: "gitea",
|
||||
Year: "2024",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tests = append(tests, DetectLicenseTest{
|
||||
name: "single license test: " + licenseName,
|
||||
arg: string(license),
|
||||
want: []string{licenseName},
|
||||
})
|
||||
}
|
||||
|
||||
require.NoError(t, InitLicenseClassifier())
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
license, err := detectLicense(strings.NewReader(tt.arg))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, license)
|
||||
})
|
||||
}
|
||||
|
||||
// Build multi-license content from the first 3 real license entries.
|
||||
require.GreaterOrEqual(t, len(repo_module.Licenses), 3, "need at least 3 licenses for multi-license test")
|
||||
var multiContent strings.Builder
|
||||
var multiWant []string
|
||||
for _, name := range repo_module.Licenses[:3] {
|
||||
lic, err := repo_module.GetLicense(name, &repo_module.LicenseValues{
|
||||
Owner: "Gitea", Email: "teabot@gitea.io", Repo: "gitea", Year: "2024",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
multiContent.Write(lic)
|
||||
multiWant = append(multiWant, name)
|
||||
}
|
||||
t.Run("multiple licenses", func(t *testing.T) {
|
||||
result, err := detectLicense(strings.NewReader(multiContent.String()))
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, multiWant, result)
|
||||
})
|
||||
}
|
||||
|
||||
func detectedLicenseIDs(licenses []repo_model.DetectedLicense) []string {
|
||||
ids := make([]string, 0, len(licenses))
|
||||
for _, l := range licenses {
|
||||
ids = append(ids, l.SPDXID)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func Test_resolveLicenses(t *testing.T) {
|
||||
require.NoError(t, repo_module.LoadRepoConfig())
|
||||
require.NoError(t, InitLicenseClassifier())
|
||||
|
||||
mitLicense, err := repo_module.GetLicense("MIT", &repo_module.LicenseValues{
|
||||
Owner: "Test",
|
||||
Email: "test@test.com",
|
||||
Repo: "test",
|
||||
Year: "2024",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
repoDir := filepath.Join(t.TempDir(), "repo.git")
|
||||
require.NoError(t, git.InitRepositoryLocal(t.Context(), repoDir, true, "sha1"))
|
||||
gitRepo, err := git.OpenRepositoryLocal(t.Context(), repoDir)
|
||||
require.NoError(t, err)
|
||||
defer gitRepo.Close()
|
||||
|
||||
// 1. repo with no license at all
|
||||
require.NoError(t, git.ForceFastImport(t.Context(), gitRepo, []git.FastImportCommit{{
|
||||
Ref: "refs/heads/master",
|
||||
Message: "empty",
|
||||
}}))
|
||||
commit, err := gitRepo.GetBranchCommit(t.Context(), "master")
|
||||
require.NoError(t, err)
|
||||
|
||||
licenses, err := resolveLicenses(t.Context(), gitRepo, commit)
|
||||
assert.Empty(t, licenses)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 2. repo with a plain LICENSE file — classifier should detect MIT
|
||||
require.NoError(t, git.ForceFastImport(t.Context(), gitRepo, []git.FastImportCommit{{
|
||||
Ref: "refs/heads/master",
|
||||
Message: "add LICENSE",
|
||||
Files: []git.FastImportFile{
|
||||
{Mode: git.EntryModeBlob, Path: "LICENSE", Content: string(mitLicense)},
|
||||
},
|
||||
}}))
|
||||
commit, err = gitRepo.GetBranchCommit(t.Context(), "master")
|
||||
require.NoError(t, err)
|
||||
|
||||
licenses, err = resolveLicenses(t.Context(), gitRepo, commit)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, licenses, 1)
|
||||
assert.Equal(t, "MIT", licenses[0].SPDXID)
|
||||
assert.Equal(t, "LICENSE", licenses[0].LicensePath)
|
||||
|
||||
// 3. repo with REUSE LICENSES/ dir — should take priority over root LICENSE
|
||||
require.NoError(t, git.ForceFastImport(t.Context(), gitRepo, []git.FastImportCommit{{
|
||||
Ref: "refs/heads/master",
|
||||
Message: "add LICENSES dir",
|
||||
Files: []git.FastImportFile{
|
||||
{Mode: git.EntryModeBlob, Path: "LICENSE", Content: string(mitLicense)},
|
||||
{Mode: git.EntryModeBlob, Path: "LICENSES/MIT.txt", Content: "MIT license text"},
|
||||
{Mode: git.EntryModeBlob, Path: "LICENSES/Apache-2.0.txt", Content: "Apache license text"},
|
||||
},
|
||||
}}))
|
||||
commit, err = gitRepo.GetBranchCommit(t.Context(), "master")
|
||||
require.NoError(t, err)
|
||||
|
||||
licenses, err = resolveLicenses(t.Context(), gitRepo, commit)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, licenses, 2)
|
||||
|
||||
ids := detectedLicenseIDs(licenses)
|
||||
assert.ElementsMatch(t, []string{"Apache-2.0", "MIT"}, ids)
|
||||
// REUSE entries carry full path including LICENSES/ prefix
|
||||
for _, l := range licenses {
|
||||
assert.True(t, strings.HasPrefix(l.LicensePath, "LICENSES/"))
|
||||
}
|
||||
|
||||
// 4. remove all licenses — should return not exist
|
||||
require.NoError(t, git.ForceFastImport(t.Context(), gitRepo, []git.FastImportCommit{{
|
||||
Ref: "refs/heads/master",
|
||||
Message: "remove licenses",
|
||||
}}))
|
||||
commit, err = gitRepo.GetBranchCommit(t.Context(), "master")
|
||||
require.NoError(t, err)
|
||||
|
||||
licenses, err = resolveLicenses(t.Context(), gitRepo, commit)
|
||||
assert.Empty(t, licenses)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_isLicenseFile(t *testing.T) {
|
||||
shouldMatch := []string{
|
||||
"LICENSE",
|
||||
"LICENCE",
|
||||
"COPYING",
|
||||
"License",
|
||||
"Licence",
|
||||
"copying",
|
||||
"LICENSE.txt",
|
||||
"LICENSE.md",
|
||||
"LICENCE.txt",
|
||||
"LICENCE.md",
|
||||
"COPYING.txt",
|
||||
"COPYING.md",
|
||||
"LICENSE.TXT",
|
||||
"LICENSE.MD",
|
||||
"license.txt",
|
||||
"licence.md",
|
||||
"copying.TXT",
|
||||
"COPYING.LESSER",
|
||||
}
|
||||
|
||||
shouldNotMatch := []string{
|
||||
"LICENSE.",
|
||||
"README",
|
||||
"README.md",
|
||||
"NOTICE",
|
||||
"AUTHORS",
|
||||
"LICENSING",
|
||||
"COPYLEFT",
|
||||
"LICENSE.a.b",
|
||||
"LICENSE.a.",
|
||||
"LICENSE.a.md",
|
||||
"LICENSE.md.a",
|
||||
}
|
||||
t.Run("match", func(t *testing.T) {
|
||||
for _, name := range shouldMatch {
|
||||
assert.True(t, isLicenseFile(name))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("nomatch", func(t *testing.T) {
|
||||
for _, name := range shouldNotMatch {
|
||||
assert.False(t, isLicenseFile(name))
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user