Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions models/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit
Type: tp,
Config: cfg,
}
case unit.TypePackages:
cfg := new(PackagesConfig)
return &RepoUnit{
Type: tp,
Config: cfg,
}
}

return &RepoUnit{
Expand Down
24 changes: 23 additions & 1 deletion models/repo/repo_unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,11 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
r.Config = new(IssuesConfig)
case unit.TypeActions:
r.Config = new(ActionsConfig)
case unit.TypePackages:
r.Config = new(PackagesConfig)
case unit.TypeProjects:
r.Config = new(ProjectsConfig)
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypePackages:
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki:
fallthrough
default:
r.Config = new(UnitConfig)
Expand Down Expand Up @@ -319,6 +321,26 @@ func (r *RepoUnit) ProjectsConfig() *ProjectsConfig {
return r.Config.(*ProjectsConfig)
}

// PackagesConfig returns config for unit.PackagesConfig
func (r *RepoUnit) PackagesConfig() *PackagesConfig {
return r.Config.(*PackagesConfig)
}

// PackagesConfig describes package config
type PackagesConfig struct {
GoModuleSubDir string
}

// FromDB fills up a PackagesConfig from serialized format.
func (cfg *PackagesConfig) FromDB(bs []byte) error {
return json.UnmarshalHandleDoubleEncode(bs, &cfg)
}

// ToDB exports a PackagesConfig to a serialized format.
func (cfg *PackagesConfig) ToDB() ([]byte, error) {
return json.Marshal(cfg)
}

func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
var tmpUnits []*RepoUnit
if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions modules/structs/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ type EditRepoOption struct {
MirrorInterval *string `json:"mirror_interval,omitempty"`
// enable prune - remove obsolete remote-tracking references when mirroring
EnablePrune *bool `json:"enable_prune,omitempty"`
// set the subdirectory for Go modules
GoModuleSubDir *string `json:"go_module_sub_dir,omitempty"`
}

// GenerateRepoOption options when creating a repository using a template
Expand Down
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2629,6 +2629,9 @@ settings.rename_branch_from=old branch name
settings.rename_branch_to=new branch name
settings.rename_branch=Rename branch

settings.go_module_sub_dir = Golang module subdirectory
settings.go_module_sub_dir_desc = The subdirectory in repository redirect for go module (which is supported since go 1.25, see <a target="_blank" rel="noopener noreferrer" href="%[1]s">%[2]s</a> for more detail)

diff.browse_source = Browse Source
diff.parent = parent
diff.commit = commit
Expand Down
8 changes: 8 additions & 0 deletions routers/api/v1/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,9 +994,17 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {

if opts.HasPackages != nil && !unit_model.TypePackages.UnitGlobalDisabled() {
if *opts.HasPackages {
unit := repo.MustGetUnit(ctx, unit_model.TypePackages)
cfg := unit.PackagesConfig()

if opts.GoModuleSubDir != nil {
cfg.GoModuleSubDir = *opts.GoModuleSubDir
}

units = append(units, repo_model.RepoUnit{
RepoID: repo.ID,
Type: unit_model.TypePackages,
Config: cfg,
})
} else {
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePackages)
Expand Down
18 changes: 17 additions & 1 deletion routers/web/goget.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,18 @@ func goGet(ctx *context.Context) {
if err == nil && len(repo.DefaultBranch) > 0 {
branchName = repo.DefaultBranch
}
prefix := setting.AppURL + path.Join(url.PathEscape(ownerName), url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName))

subDir := ""
if repo != nil {
subDir = context.GetGoModuleSubDirConfig(ctx, repo)
}

var prefix string
if len(subDir) > 0 {
prefix = setting.AppURL + path.Join(url.PathEscape(ownerName), url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName), subDir)
} else {
prefix = setting.AppURL + path.Join(url.PathEscape(ownerName), url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName))
}

appURL, _ := url.Parse(setting.AppURL)

Expand All @@ -73,6 +84,11 @@ func goGet(ctx *context.Context) {
} else {
cloneURL = repo_model.ComposeHTTPSCloneURL(ctx, ownerName, repoName)
}

if len(subDir) > 0 {
cloneURL += " " + util.PathEscapeSegments(subDir)
}

goImportContent := fmt.Sprintf("%s git %s", goGetImport, cloneURL /*CloneLink*/)
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/)
goGetCli := fmt.Sprintf("go get %s%s", insecure, goGetImport)
Expand Down
4 changes: 3 additions & 1 deletion routers/web/repo/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,9 @@ func handleSettingsPostAdvanced(ctx *context.Context) {
}

if form.EnablePackages && !unit_model.TypePackages.UnitGlobalDisabled() {
units = append(units, newRepoUnit(repo, unit_model.TypePackages, nil))
units = append(units, newRepoUnit(repo, unit_model.TypePackages, &repo_model.PackagesConfig{
GoModuleSubDir: form.GoModuleSubDir,
}))
} else if !unit_model.TypePackages.UnitGlobalDisabled() {
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePackages)
}
Expand Down
7 changes: 7 additions & 0 deletions services/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
ctx.PlainText(http.StatusOK, htmlMeta)
}

// GetGoModuleSubDirConfig retrieves the subdirectory configuration for a Go module.
func GetGoModuleSubDirConfig(ctx *Context, repo *repo_model.Repository) string {
pkgCfg := repo.MustGetUnit(ctx, unit_model.TypePackages).PackagesConfig()

return strings.TrimSpace(pkgCfg.GoModuleSubDir)
}

// RedirectToRepo redirect to a differently-named repository
func RedirectToRepo(ctx *Base, redirectRepoID int64) {
ownerName := ctx.PathParam("username")
Expand Down
2 changes: 2 additions & 0 deletions services/forms/repo_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ type RepoSettingForm struct {

EnableActions bool

GoModuleSubDir string

IsArchived bool

// Signing Settings
Expand Down
14 changes: 13 additions & 1 deletion templates/repo/settings/options.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -499,16 +499,28 @@
</div>
</div>

<div class="divider"></div>
{{$isPackagesEnabled := .Repository.UnitEnabled ctx ctx.Consts.RepoUnitTypePackages}}
{{$isPackagesGlobalDisabled := ctx.Consts.RepoUnitTypePackages.UnitGlobalDisabled}}
{{$pkgUnit := .Repository.MustGetUnit ctx ctx.Consts.RepoUnitTypePackages}}
<div class="inline field">
<label>{{ctx.Locale.Tr "repo.packages"}}</label>
<div class="ui checkbox{{if $isPackagesGlobalDisabled}} disabled{{end}}"{{if $isPackagesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
<input class="enable-system" name="enable_packages" type="checkbox" {{if $isPackagesEnabled}}checked{{end}}>
<input class="enable-system" name="enable_packages" type="checkbox" data-target="#packages_box" {{if $isPackagesEnabled}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.packages_desc"}}</label>
</div>
</div>

<div class="field{{if not $isPackagesEnabled}} disabled{{end}}" id="packages_box">
<div class="field tw-pl-4 {{if $isPackagesGlobalDisabled}}disabled{{end}}">
<label for="go_module_sub_dir">{{ctx.Locale.Tr "repo.settings.go_module_sub_dir"}}</label>
<input id="go_module_sub_dir" name="go_module_sub_dir" value="{{$pkgUnit.PackagesConfig.GoModuleSubDir}}">
<p class="help">{{ctx.Locale.Tr "repo.settings.go_module_sub_dir_desc" "https://github.com/golang/go/commit/835e36fc7f631f74233edfd4ab43b6b56833db86" "github.com/golang/go@835e36fc7f"}}</p>
</div>
</div>

<div class="divider"></div>

{{if .EnableActions}}
{{$isActionsEnabled := .Repository.UnitEnabled ctx ctx.Consts.RepoUnitTypeActions}}
{{$isActionsGlobalDisabled := ctx.Consts.RepoUnitTypeActions.UnitGlobalDisabled}}
Expand Down
5 changes: 5 additions & 0 deletions templates/swagger/v1_json.tmpl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions tests/integration/goget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"net/http"
"testing"

auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/tests"

Expand All @@ -34,6 +38,39 @@ func TestGoGet(t *testing.T) {
assert.Equal(t, expected, resp.Body.String())
}

func TestGoGetSubDir(t *testing.T) {
defer tests.PrepareTestEnv(t)()

user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})

// Get user2's token
session := loginUser(t, user2.Name)
token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
repoEditOption := getRepoEditOptionFromRepo(repo1)
goModuleSubDir := "package"
repoEditOption.GoModuleSubDir = &goModuleSubDir
req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusOK)

req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/plah?go-get=1", user2.Name, repo1.Name))
resp := MakeRequest(t, req, http.StatusOK)

expected := fmt.Sprintf(`<!doctype html>
<html>
<head>
<meta name="go-import" content="%[1]s:%[2]s/%[4]s/%[5]s git %[3]s%[4]s/%[5]s.git package">
<meta name="go-source" content="%[1]s:%[2]s/%[4]s/%[5]s _ %[3]s%[4]s/%[5]s/src/branch/master/package{/dir} %[3]s%[4]s/%[5]s/src/branch/master/package{/dir}/{file}#L{line}">
</head>
<body>
go get --insecure %[1]s:%[2]s/%[4]s/%[5]s
</body>
</html>`, setting.Domain, setting.HTTPPort, setting.AppURL, user2.Name, repo1.Name)

assert.Equal(t, expected, resp.Body.String())
}

func TestGoGetForSSH(t *testing.T) {
defer tests.PrepareTestEnv(t)()

Expand Down