{ | { | ||||
"name": "Gitea DevContainer", | "name": "Gitea DevContainer", | ||||
"image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye", | |||||
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye", | |||||
"features": { | "features": { | ||||
// installs nodejs into container | // installs nodejs into container | ||||
"ghcr.io/devcontainers/features/node:1": { | "ghcr.io/devcontainers/features/node:1": { |
# Build stage | # Build stage | ||||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env | |||||
FROM docker.io/library/golang:1.22-alpine3.19 AS build-env | |||||
ARG GOPROXY | ARG GOPROXY | ||||
ENV GOPROXY ${GOPROXY:-direct} | ENV GOPROXY ${GOPROXY:-direct} |
# Build stage | # Build stage | ||||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env | |||||
FROM docker.io/library/golang:1.22-alpine3.19 AS build-env | |||||
ARG GOPROXY | ARG GOPROXY | ||||
ENV GOPROXY ${GOPROXY:-direct} | ENV GOPROXY ${GOPROXY:-direct} |
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) | HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) | ||||
COMMA := , | COMMA := , | ||||
XGO_VERSION := go-1.21.x | |||||
XGO_VERSION := go-1.22.x | |||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0 | AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0 | ||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0 | EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0 | ||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 | GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 | ||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 | |||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1 | |||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 | GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 | ||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 | MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 | ||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 | SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 |
for i, c := range active { | for i, c := range active { | ||||
ids[i] = c.ID | ids[i] = c.ID | ||||
} | } | ||||
return neuterCrossReferencesIds(ctx, ids) | |||||
return neuterCrossReferencesIDs(ctx, ids) | |||||
} | } | ||||
func neuterCrossReferencesIds(ctx context.Context, ids []int64) error { | |||||
func neuterCrossReferencesIDs(ctx context.Context, ids []int64) error { | |||||
_, err := db.GetEngine(ctx).In("id", ids).Cols("`ref_action`").Update(&Comment{RefAction: references.XRefActionNeutered}) | _, err := db.GetEngine(ctx).In("id", ids).Cols("`ref_action`").Update(&Comment{RefAction: references.XRefActionNeutered}) | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if len(ids) > 0 { | if len(ids) > 0 { | ||||
if err = neuterCrossReferencesIds(stdCtx, ids); err != nil { | |||||
if err = neuterCrossReferencesIDs(stdCtx, ids); err != nil { | |||||
return err | return err | ||||
} | } | ||||
} | } |
// LoadReviewers loads reviewers | // LoadReviewers loads reviewers | ||||
func (reviews ReviewList) LoadReviewers(ctx context.Context) error { | func (reviews ReviewList) LoadReviewers(ctx context.Context) error { | ||||
reviewerIds := make([]int64, len(reviews)) | |||||
reviewerIDs := make([]int64, len(reviews)) | |||||
for i := 0; i < len(reviews); i++ { | for i := 0; i < len(reviews); i++ { | ||||
reviewerIds[i] = reviews[i].ReviewerID | |||||
reviewerIDs[i] = reviews[i].ReviewerID | |||||
} | } | ||||
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIds) | |||||
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIDs) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
func (reviews ReviewList) LoadIssues(ctx context.Context) error { | func (reviews ReviewList) LoadIssues(ctx context.Context) error { | ||||
issueIds := container.Set[int64]{} | |||||
issueIDs := container.Set[int64]{} | |||||
for i := 0; i < len(reviews); i++ { | for i := 0; i < len(reviews); i++ { | ||||
issueIds.Add(reviews[i].IssueID) | |||||
issueIDs.Add(reviews[i].IssueID) | |||||
} | } | ||||
issues, err := GetIssuesByIDs(ctx, issueIds.Values()) | |||||
issues, err := GetIssuesByIDs(ctx, issueIDs.Values()) | |||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
} | } |
} | } | ||||
// Our "line" must look like: <commitid> SP (<parent> SP) * NUL | // Our "line" must look like: <commitid> SP (<parent> SP) * NUL | ||||
commitIds := string(g.next) | |||||
commitIDs := string(g.next) | |||||
if g.buffull { | if g.buffull { | ||||
more, err := g.rd.ReadString('\x00') | more, err := g.rd.ReadString('\x00') | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
commitIds += more | |||||
commitIDs += more | |||||
} | } | ||||
commitIds = commitIds[:len(commitIds)-1] | |||||
splitIds := strings.Split(commitIds, " ") | |||||
ret.CommitID = splitIds[0] | |||||
if len(splitIds) > 1 { | |||||
ret.ParentIDs = splitIds[1:] | |||||
commitIDs = commitIDs[:len(commitIDs)-1] | |||||
splitIDs := strings.Split(commitIDs, " ") | |||||
ret.CommitID = splitIDs[0] | |||||
if len(splitIDs) > 1 { | |||||
ret.ParentIDs = splitIDs[1:] | |||||
} | } | ||||
// now read the next "line" | // now read the next "line" |
} | } | ||||
// Globs parses the .gitea/template globs or returns them if they were already parsed | // Globs parses the .gitea/template globs or returns them if they were already parsed | ||||
func (gt GiteaTemplate) Globs() []glob.Glob { | |||||
func (gt *GiteaTemplate) Globs() []glob.Glob { | |||||
if gt.globs != nil { | if gt.globs != nil { | ||||
return gt.globs | return gt.globs | ||||
} | } |
linkedPrsMap := make(map[int64][]*issues_model.Issue) | linkedPrsMap := make(map[int64][]*issues_model.Issue) | ||||
for _, issuesList := range issuesMap { | for _, issuesList := range issuesMap { | ||||
for _, issue := range issuesList { | for _, issue := range issuesList { | ||||
var referencedIds []int64 | |||||
var referencedIDs []int64 | |||||
for _, comment := range issue.Comments { | for _, comment := range issue.Comments { | ||||
if comment.RefIssueID != 0 && comment.RefIsPull { | if comment.RefIssueID != 0 && comment.RefIsPull { | ||||
referencedIds = append(referencedIds, comment.RefIssueID) | |||||
referencedIDs = append(referencedIDs, comment.RefIssueID) | |||||
} | } | ||||
} | } | ||||
if len(referencedIds) > 0 { | |||||
if len(referencedIDs) > 0 { | |||||
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ | if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ | ||||
IssueIDs: referencedIds, | |||||
IssueIDs: referencedIDs, | |||||
IsPull: util.OptionalBoolTrue, | IsPull: util.OptionalBoolTrue, | ||||
}); err == nil { | }); err == nil { | ||||
linkedPrsMap[issue.ID] = linkedPrs | linkedPrsMap[issue.ID] = linkedPrs |
linkedPrsMap := make(map[int64][]*issues_model.Issue) | linkedPrsMap := make(map[int64][]*issues_model.Issue) | ||||
for _, issuesList := range issuesMap { | for _, issuesList := range issuesMap { | ||||
for _, issue := range issuesList { | for _, issue := range issuesList { | ||||
var referencedIds []int64 | |||||
var referencedIDs []int64 | |||||
for _, comment := range issue.Comments { | for _, comment := range issue.Comments { | ||||
if comment.RefIssueID != 0 && comment.RefIsPull { | if comment.RefIssueID != 0 && comment.RefIsPull { | ||||
referencedIds = append(referencedIds, comment.RefIssueID) | |||||
referencedIDs = append(referencedIDs, comment.RefIssueID) | |||||
} | } | ||||
} | } | ||||
if len(referencedIds) > 0 { | |||||
if len(referencedIDs) > 0 { | |||||
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ | if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{ | ||||
IssueIDs: referencedIds, | |||||
IssueIDs: referencedIDs, | |||||
IsPull: util.OptionalBoolTrue, | IsPull: util.OptionalBoolTrue, | ||||
}); err == nil { | }); err == nil { | ||||
linkedPrsMap[issue.ID] = linkedPrs | linkedPrsMap[issue.ID] = linkedPrs |
} | } | ||||
} | } | ||||
showRepoIds := make(container.Set[int64], len(showRepos)) | |||||
showRepoIDs := make(container.Set[int64], len(showRepos)) | |||||
for _, repo := range showRepos { | for _, repo := range showRepos { | ||||
if repo.ID > 0 { | if repo.ID > 0 { | ||||
showRepoIds.Add(repo.ID) | |||||
showRepoIDs.Add(repo.ID) | |||||
} | } | ||||
} | } | ||||
if len(repoIDs) == 0 { | if len(repoIDs) == 0 { | ||||
repoIDs = showRepoIds.Values() | |||||
repoIDs = showRepoIDs.Values() | |||||
} | } | ||||
repoIDs = slices.DeleteFunc(repoIDs, func(v int64) bool { | repoIDs = slices.DeleteFunc(repoIDs, func(v int64) bool { | ||||
return !showRepoIds.Contains(v) | |||||
return !showRepoIDs.Contains(v) | |||||
}) | }) | ||||
var pagerCount int | var pagerCount int |
func TestIncludesAllRepositoriesTeams(t *testing.T) { | func TestIncludesAllRepositoriesTeams(t *testing.T) { | ||||
assert.NoError(t, unittest.PrepareTestDatabase()) | assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
testTeamRepositories := func(teamID int64, repoIds []int64) { | |||||
testTeamRepositories := func(teamID int64, repoIDs []int64) { | |||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) | team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) | ||||
assert.NoError(t, team.LoadRepositories(db.DefaultContext), "%s: GetRepositories", team.Name) | assert.NoError(t, team.LoadRepositories(db.DefaultContext), "%s: GetRepositories", team.Name) | ||||
assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name) | assert.Len(t, team.Repos, team.NumRepos, "%s: len repo", team.Name) | ||||
assert.Len(t, team.Repos, len(repoIds), "%s: repo count", team.Name) | |||||
for i, rid := range repoIds { | |||||
assert.Len(t, team.Repos, len(repoIDs), "%s: repo count", team.Name) | |||||
for i, rid := range repoIDs { | |||||
if rid > 0 { | if rid > 0 { | ||||
assert.True(t, HasRepository(db.DefaultContext, team, rid), "%s: HasRepository(%d) %d", rid, i) | assert.True(t, HasRepository(db.DefaultContext, team, rid), "%s: HasRepository(%d) %d", rid, i) | ||||
} | } | ||||
assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories") | assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories") | ||||
// Create repos. | // Create repos. | ||||
repoIds := make([]int64, 0) | |||||
repoIDs := make([]int64, 0) | |||||
for i := 0; i < 3; i++ { | for i := 0; i < 3; i++ { | ||||
r, err := CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)}) | r, err := CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)}) | ||||
assert.NoError(t, err, "CreateRepository %d", i) | assert.NoError(t, err, "CreateRepository %d", i) | ||||
if r != nil { | if r != nil { | ||||
repoIds = append(repoIds, r.ID) | |||||
repoIDs = append(repoIDs, r.ID) | |||||
} | } | ||||
} | } | ||||
// Get fresh copy of Owner team after creating repos. | // Get fresh copy of Owner team after creating repos. | ||||
}, | }, | ||||
} | } | ||||
teamRepos := [][]int64{ | teamRepos := [][]int64{ | ||||
repoIds, | |||||
repoIds, | |||||
repoIDs, | |||||
repoIDs, | |||||
{}, | {}, | ||||
repoIds, | |||||
repoIDs, | |||||
{}, | {}, | ||||
} | } | ||||
for i, team := range teams { | for i, team := range teams { | ||||
// Update teams and check repositories. | // Update teams and check repositories. | ||||
teams[3].IncludesAllRepositories = false | teams[3].IncludesAllRepositories = false | ||||
teams[4].IncludesAllRepositories = true | teams[4].IncludesAllRepositories = true | ||||
teamRepos[4] = repoIds | |||||
teamRepos[4] = repoIDs | |||||
for i, team := range teams { | for i, team := range teams { | ||||
assert.NoError(t, models.UpdateTeam(db.DefaultContext, team, false, true), "%s: UpdateTeam", team.Name) | assert.NoError(t, models.UpdateTeam(db.DefaultContext, team, false, true), "%s: UpdateTeam", team.Name) | ||||
testTeamRepositories(team.ID, teamRepos[i]) | testTeamRepositories(team.ID, teamRepos[i]) | ||||
r, err := CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), CreateRepoOptions{Name: "repo-last"}) | r, err := CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), CreateRepoOptions{Name: "repo-last"}) | ||||
assert.NoError(t, err, "CreateRepository last") | assert.NoError(t, err, "CreateRepository last") | ||||
if r != nil { | if r != nil { | ||||
repoIds = append(repoIds, r.ID) | |||||
repoIDs = append(repoIDs, r.ID) | |||||
} | } | ||||
teamRepos[0] = repoIds | |||||
teamRepos[1] = repoIds | |||||
teamRepos[4] = repoIds | |||||
teamRepos[0] = repoIDs | |||||
teamRepos[1] = repoIDs | |||||
teamRepos[4] = repoIDs | |||||
for i, team := range teams { | for i, team := range teams { | ||||
testTeamRepositories(team.ID, teamRepos[i]) | testTeamRepositories(team.ID, teamRepos[i]) | ||||
} | } | ||||
// Remove repo and check teams repositories. | // Remove repo and check teams repositories. | ||||
assert.NoError(t, DeleteRepositoryDirectly(db.DefaultContext, user, repoIds[0]), "DeleteRepository") | |||||
teamRepos[0] = repoIds[1:] | |||||
teamRepos[1] = repoIds[1:] | |||||
teamRepos[3] = repoIds[1:3] | |||||
teamRepos[4] = repoIds[1:] | |||||
assert.NoError(t, DeleteRepositoryDirectly(db.DefaultContext, user, repoIDs[0]), "DeleteRepository") | |||||
teamRepos[0] = repoIDs[1:] | |||||
teamRepos[1] = repoIDs[1:] | |||||
teamRepos[3] = repoIDs[1:3] | |||||
teamRepos[4] = repoIDs[1:] | |||||
for i, team := range teams { | for i, team := range teams { | ||||
testTeamRepositories(team.ID, teamRepos[i]) | testTeamRepositories(team.ID, teamRepos[i]) | ||||
} | } | ||||
// Wipe created items. | // Wipe created items. | ||||
for i, rid := range repoIds { | |||||
for i, rid := range repoIDs { | |||||
if i > 0 { // first repo already deleted. | if i > 0 { // first repo already deleted. | ||||
assert.NoError(t, DeleteRepositoryDirectly(db.DefaultContext, user, rid), "DeleteRepository %d", i) | assert.NoError(t, DeleteRepositoryDirectly(db.DefaultContext, user, rid), "DeleteRepository %d", i) | ||||
} | } |
source: . | source: . | ||||
stage-packages: [ git, sqlite3, openssh-client ] | stage-packages: [ git, sqlite3, openssh-client ] | ||||
build-packages: [ git, libpam0g-dev, libsqlite3-dev, build-essential] | build-packages: [ git, libpam0g-dev, libsqlite3-dev, build-essential] | ||||
build-snaps: [ go/1.21/stable, node/18/stable ] | |||||
build-snaps: [ go/1.22/stable, node/20/stable ] | |||||
build-environment: | build-environment: | ||||
- LDFLAGS: "" | - LDFLAGS: "" | ||||
override-pull: | | override-pull: | |