feat: update gitea vendor
runner nix smoke / nix label and flake smoke (push) Failing after 1m28s

This commit is contained in:
2026-09-26 21:18:24 +00:00
parent c439c1b948
commit d9b2a4e787
3538 changed files with 116131 additions and 44340 deletions
@@ -8,14 +8,14 @@ import (
"strings"
"testing"
actions_model "code.gitea.io/gitea/models/actions"
db "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git/gitcmd"
"code.gitea.io/gitea/modules/util"
actions_model "gitea.dev/models/actions"
db "gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unit"
"gitea.dev/models/unittest"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -116,12 +116,12 @@ func TestToActionWorkflowRun_UsesTriggerEvent(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 803})
run.Repo = repo
// Scheduled runs keep Event as the registration event (push) and use TriggerEvent as the real trigger.
run.Event = "push"
run.TriggerEvent = "schedule"
apiRun, err := ToActionWorkflowRun(t.Context(), repo, run)
apiRun, err := ToActionWorkflowRun(t.Context(), run, nil, false)
require.NoError(t, err)
assert.Equal(t, "schedule", apiRun.Event)
}
@@ -177,3 +177,13 @@ func TestToActionWorkflowJob_StepStatusIsIndependentOfJobStatus(t *testing.T) {
assert.Equal(t, "completed", apiJob.Steps[1].Status, "step 1 status")
assert.Equal(t, "failure", apiJob.Steps[1].Conclusion, "step 1 conclusion")
}
func TestToActionsStatus_Cancelling(t *testing.T) {
action, conclusion := ToActionsStatus(actions_model.StatusCancelling)
assert.Equal(t, "in_progress", action)
assert.Empty(t, conclusion)
}
func TestToWorkflowRunAction_Cancelling(t *testing.T) {
assert.Equal(t, "in_progress", ToWorkflowRunAction(actions_model.StatusCancelling))
}
@@ -6,12 +6,12 @@ package convert
import (
"context"
activities_model "code.gitea.io/gitea/models/activities"
perm_model "code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
activities_model "gitea.dev/models/activities"
perm_model "gitea.dev/models/perm"
access_model "gitea.dev/models/perm/access"
user_model "gitea.dev/models/user"
"gitea.dev/modules/log"
api "gitea.dev/modules/structs"
)
func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_model.User) *api.Activity {
@@ -4,8 +4,8 @@
package convert
import (
repo_model "code.gitea.io/gitea/models/repo"
api "code.gitea.io/gitea/modules/structs"
repo_model "gitea.dev/models/repo"
api "gitea.dev/modules/structs"
)
func WebAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachment) string {
+259 -66
View File
@@ -5,39 +5,40 @@
package convert
import (
"bytes"
"context"
"errors"
"fmt"
"net/url"
"path"
"strconv"
"strings"
"time"
actions_model "code.gitea.io/gitea/models/actions"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/gitdiff"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"github.com/nektos/act/pkg/model"
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
actions_model "gitea.dev/models/actions"
asymkey_model "gitea.dev/models/asymkey"
"gitea.dev/models/auth"
"gitea.dev/models/db"
git_model "gitea.dev/models/git"
issues_model "gitea.dev/models/issues"
"gitea.dev/models/organization"
"gitea.dev/models/perm"
access_model "gitea.dev/models/perm/access"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unit"
user_model "gitea.dev/models/user"
"gitea.dev/modules/actions"
"gitea.dev/modules/actions/jobparser"
"gitea.dev/modules/container"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/httplib"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
webhook_module "gitea.dev/modules/webhook"
asymkey_service "gitea.dev/services/asymkey"
"gitea.dev/services/gitdiff"
)
// ToEmail convert models.EmailAddress to api.Email
@@ -139,7 +140,7 @@ func getWhitelistEntities[T *user_model.User | *organization.Team](entities []T,
// ToBranchProtection convert a ProtectedBranch to api.BranchProtection
func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo *repo_model.Repository) *api.BranchProtection {
readers, err := access_model.GetUsersWithUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypePullRequests)
readers, err := access_model.GetUsersWithAnyUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
if err != nil {
log.Error("GetRepoReaders: %v", err)
}
@@ -148,6 +149,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
forcePushAllowlistUsernames := getWhitelistEntities(readers, bp.ForcePushAllowlistUserIDs)
mergeWhitelistUsernames := getWhitelistEntities(readers, bp.MergeWhitelistUserIDs)
approvalsWhitelistUsernames := getWhitelistEntities(readers, bp.ApprovalsWhitelistUserIDs)
bypassAllowlistUsernames := getWhitelistEntities(readers, bp.BypassAllowlistUserIDs)
teamReaders, err := organization.GetTeamsWithAccessToAnyRepoUnit(ctx, repo.Owner.ID, repo.ID, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
if err != nil {
@@ -158,6 +160,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
forcePushAllowlistTeams := getWhitelistEntities(teamReaders, bp.ForcePushAllowlistTeamIDs)
mergeWhitelistTeams := getWhitelistEntities(teamReaders, bp.MergeWhitelistTeamIDs)
approvalsWhitelistTeams := getWhitelistEntities(teamReaders, bp.ApprovalsWhitelistTeamIDs)
bypassAllowlistTeams := getWhitelistEntities(teamReaders, bp.BypassAllowlistTeamIDs)
branchName := ""
if !git_model.IsRuleNameSpecial(bp.RuleName) {
@@ -181,6 +184,9 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo
EnableMergeWhitelist: bp.EnableMergeWhitelist,
MergeWhitelistUsernames: mergeWhitelistUsernames,
MergeWhitelistTeams: mergeWhitelistTeams,
EnableBypassAllowlist: bp.EnableBypassAllowlist,
BypassAllowlistUsernames: bypassAllowlistUsernames,
BypassAllowlistTeams: bypassAllowlistTeams,
EnableStatusCheck: bp.EnableStatusCheck,
StatusCheckContexts: bp.StatusCheckContexts,
RequiredApprovals: bp.RequiredApprovals,
@@ -214,7 +220,7 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
return &api.Tag{
Name: t.Name,
Message: strings.ToValidUTF8(strings.TrimSpace(t.Message), "?"), // the trim is not right, 1.27 won't trim
Message: t.MessageUTF8(),
ID: t.ID.String(),
Commit: ToCommitMeta(repo, t),
ZipballURL: zipballURL,
@@ -222,14 +228,18 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
}
}
// ToActionTask convert a actions_model.ActionTask to an api.ActionTask
// ToActionTask convert an actions_model.ActionTask to an api.ActionTask
func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.ActionTask, error) {
if err := t.LoadAttributes(ctx); err != nil {
// don't need Steps here, only need to load job and its run
if err := t.LoadJob(ctx); err != nil {
return nil, err
}
if err := t.Job.LoadRun(ctx); err != nil {
return nil, err
}
if err := t.Job.Run.LoadRepo(ctx); err != nil {
return nil, err
}
url := strings.TrimSuffix(setting.AppURL, "/") + t.GetRunLink()
return &api.ActionTask{
ID: t.ID,
Name: t.Job.Name,
@@ -240,37 +250,161 @@ func ToActionTask(ctx context.Context, t *actions_model.ActionTask) (*api.Action
DisplayTitle: t.Job.Run.Title,
Status: t.Status.String(),
WorkflowID: t.Job.Run.WorkflowID,
URL: url,
URL: httplib.MakeAbsoluteURL(ctx, t.Job.Run.Link()),
CreatedAt: t.Created.AsLocalTime(),
UpdatedAt: t.Updated.AsLocalTime(),
RunStartedAt: t.Started.AsLocalTime(),
}, nil
}
func ToActionWorkflowRun(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun) (*api.ActionWorkflowRun, error) {
err := run.LoadAttributes(ctx)
if err != nil {
func ToActionWorkflowRun(ctx context.Context, run *actions_model.ActionRun, attempt *actions_model.ActionRunAttempt, excludePullRequests bool) (_ *api.ActionWorkflowRun, err error) {
if err := run.LoadAttributes(ctx); err != nil {
return nil, err
}
if attempt == nil {
attempt, _, err = run.GetLatestAttempt(ctx)
if err != nil {
return nil, err
}
}
runAttempt := int64(0)
status, conclusion := ToActionsStatus(run.Status)
startedAt := run.Started.AsLocalTime()
completedAt := run.Stopped.AsLocalTime()
actor := run.TriggerUser // The username of the user that triggered the initial workflow run.
triggerUser := run.TriggerUser // The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from actor.
// previousAttemptURL is the value of ActionWorkflowRun.PreviousAttemptURL, which is declared as *string without `omitempty` on purpose:
// a nil value must still appear in the JSON body as `"previous_attempt_url": null`, matching GitHub's Actions API.
var previousAttemptURL *string
if attempt != nil {
attempt.Run = run
if err := attempt.LoadAttributes(ctx); err != nil {
return nil, err
}
runAttempt = attempt.Attempt
status, conclusion = ToActionsStatus(attempt.Status)
startedAt = attempt.Started.AsLocalTime()
completedAt = attempt.Stopped.AsLocalTime()
triggerUser = attempt.TriggerUser
if attempt.Attempt > 1 {
url := fmt.Sprintf("%s/actions/runs/%d/attempts/%d", run.Repo.APIURL(ctx), run.ID, attempt.Attempt-1)
previousAttemptURL = &url
}
}
pullRequests := []*api.PullRequestMinimal{}
if !excludePullRequests {
pullRequests, err = loadPullRequestsForRun(ctx, run)
if err != nil {
return nil, err
}
}
return &api.ActionWorkflowRun{
ID: run.ID,
URL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(), run.ID),
HTMLURL: run.HTMLURL(),
RunNumber: run.Index,
StartedAt: run.Started.AsLocalTime(),
CompletedAt: run.Stopped.AsLocalTime(),
Event: run.TriggerEvent,
DisplayTitle: run.Title,
HeadBranch: git.RefName(run.Ref).BranchName(),
HeadSha: run.CommitSHA,
Status: status,
Conclusion: conclusion,
Path: fmt.Sprintf("%s@%s", run.WorkflowID, run.Ref),
Repository: ToRepo(ctx, repo, access_model.Permission{AccessMode: perm.AccessModeNone}),
TriggerActor: ToUser(ctx, run.TriggerUser, nil),
// We do not have a way to get a different User for the actor than the trigger user
Actor: ToUser(ctx, run.TriggerUser, nil),
ID: run.ID,
URL: fmt.Sprintf("%s/actions/runs/%d", run.Repo.APIURL(ctx), run.ID),
PreviousAttemptURL: previousAttemptURL,
HTMLURL: run.HTMLURL(ctx),
RunNumber: run.Index,
RunAttempt: runAttempt,
StartedAt: startedAt,
CompletedAt: completedAt,
Event: run.TriggerEvent,
DisplayTitle: run.Title,
HeadBranch: git.RefName(run.Ref).BranchName(),
HeadSha: run.CommitSHA,
Status: status,
Conclusion: conclusion,
Path: fmt.Sprintf("%s@%s", run.WorkflowID, run.Ref),
Repository: ToRepo(ctx, run.Repo, access_model.Permission{AccessMode: perm.AccessModeNone}),
TriggerActor: ToUser(ctx, triggerUser, nil),
Actor: ToUser(ctx, actor, nil),
PullRequests: pullRequests,
}, nil
}
// loadPullRequestsForRun returns the pull requests associated with a run, matching
// GitHub's `pull_requests` field on workflow run responses:
// - For pull_request / pull_request_review events, the PR whose ref triggered the run.
// - For push events, open PRs whose head branch matches the pushed ref in the same repo.
// - For other events, no PRs.
func loadPullRequestsForRun(ctx context.Context, run *actions_model.ActionRun) ([]*api.PullRequestMinimal, error) {
result := []*api.PullRequestMinimal{}
refName := git.RefName(run.Ref)
var prs issues_model.PullRequestList
switch {
case run.Event.IsPullRequest() || run.Event.IsPullRequestReview():
index, err := strconv.ParseInt(refName.PullName(), 10, 64)
if err != nil {
return result, nil
}
pr, err := issues_model.GetPullRequestByIndex(ctx, run.RepoID, index)
if err != nil {
if issues_model.IsErrPullRequestNotExist(err) {
return result, nil
}
return nil, err
}
prs = issues_model.PullRequestList{pr}
case run.Event == webhook_module.HookEventPush:
branch := refName.BranchName()
if branch == "" {
return result, nil
}
var err error
prs, err = issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, run.RepoID, branch)
if err != nil {
return nil, err
}
default:
return result, nil
}
for _, pr := range prs {
minimal, err := toPullRequestMinimal(ctx, run.Repo, pr, run.CommitSHA)
if err != nil {
return nil, err
}
result = append(result, minimal)
}
return result, nil
}
func toPullRequestMinimal(ctx context.Context, repo *repo_model.Repository, pr *issues_model.PullRequest, headSHA string) (*api.PullRequestMinimal, error) {
if err := pr.LoadBaseRepo(ctx); err != nil {
return nil, err
}
if err := pr.LoadHeadRepo(ctx); err != nil {
return nil, err
}
headRepo := pr.HeadRepo
if headRepo == nil {
headRepo = pr.BaseRepo
}
return &api.PullRequestMinimal{
ID: pr.ID,
Number: pr.Index,
URL: fmt.Sprintf("%s/pulls/%d", repo.APIURL(ctx), pr.Index),
Head: api.PullRequestMinimalHead{
Ref: pr.HeadBranch,
SHA: headSHA,
Repo: api.PullRequestMinimalHeadRepo{
ID: headRepo.ID,
URL: headRepo.APIURL(ctx),
Name: headRepo.Name,
},
},
Base: api.PullRequestMinimalHead{
Ref: pr.BaseBranch,
SHA: pr.MergeBase,
Repo: api.PullRequestMinimalHeadRepo{
ID: pr.BaseRepo.ID,
URL: pr.BaseRepo.APIURL(ctx),
Name: pr.BaseRepo.Name,
},
},
}, nil
}
@@ -278,7 +412,7 @@ func ToWorkflowRunAction(status actions_model.Status) (action string) {
switch status {
case actions_model.StatusWaiting, actions_model.StatusBlocked:
action = "requested"
case actions_model.StatusRunning:
case actions_model.StatusRunning, actions_model.StatusCancelling:
action = "in_progress"
default:
if status.IsDone() {
@@ -296,7 +430,7 @@ func ToActionsStatus(status actions_model.Status) (action, conclusion string) {
action = "queued" // "waiting" is a naming conflict of the webhook between Gitea and GitHub Actions
case actions_model.StatusBlocked:
action = "waiting" // naming conflict (as above)
case actions_model.StatusRunning:
case actions_model.StatusRunning, actions_model.StatusCancelling:
action = "in_progress"
default:
action = "completed"
@@ -329,9 +463,9 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task
var runnerName string
var steps []*api.ActionWorkflowStep
if job.TaskID != 0 {
if effectiveTaskID := job.EffectiveTaskID(); effectiveTaskID != 0 {
if task == nil {
task, _, err = db.GetByID[actions_model.ActionTask](ctx, job.TaskID)
task, _, err = db.GetByID[actions_model.ActionTask](ctx, effectiveTaskID)
if err != nil {
return nil, err
}
@@ -366,11 +500,11 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task
return &api.ActionWorkflowJob{
ID: job.ID,
// missing api endpoint for this location
URL: fmt.Sprintf("%s/actions/jobs/%d", repo.APIURL(), job.ID),
HTMLURL: fmt.Sprintf("%s/jobs/%d", job.Run.HTMLURL(), job.ID),
URL: fmt.Sprintf("%s/actions/jobs/%d", repo.APIURL(ctx), job.ID),
HTMLURL: fmt.Sprintf("%s/jobs/%d", job.Run.HTMLURL(ctx), job.ID),
RunID: job.RunID,
// Missing api endpoint for this location, artifacts are available under a nested url
RunURL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(), job.RunID),
RunURL: fmt.Sprintf("%s/actions/runs/%d", repo.APIURL(ctx), job.RunID),
Name: job.Name,
Labels: job.RunsOn,
RunAttempt: job.Attempt,
@@ -421,7 +555,7 @@ func getActionWorkflowEntry(ctx context.Context, repo *repo_model.Repository, co
content, err := actions.GetContentFromEntry(entry)
name := entry.Name()
if err == nil {
workflow, err := model.ReadWorkflow(bytes.NewReader(content))
workflow, err := jobparser.ReadWorkflow(content)
if err == nil {
// Only use the name when specified in the workflow file
if workflow.Name != "" {
@@ -507,6 +641,64 @@ func getActionWorkflowFromCommit(ctx context.Context, repo *repo_model.Repositor
return nil, util.NewNotExistErrorf("workflow %q not found", workflowID)
}
// GetScopedActionWorkflow resolves a scoped workflow definition (under SCOPED_WORKFLOW_DIRS) from the source repo at commitSHA.
func GetScopedActionWorkflow(ctx context.Context, sourceGitRepo *git.Repository, sourceRepo *repo_model.Repository, workflowID, commitSHA string) (*api.ActionWorkflow, error) {
commit, err := sourceGitRepo.GetCommit(commitSHA)
if err != nil {
return nil, err
}
folder, entries, err := actions.ListScopedWorkflows(commit)
if err != nil {
return nil, err
}
for _, entry := range entries {
if entry.Name() == workflowID {
// An empty ref pins HTMLURL to commit (the run's WorkflowCommitSHA) rather than the moving default branch.
wf := getActionWorkflowEntry(ctx, sourceRepo, commit, git.RefName(""), folder, entry)
// TODO: a scoped workflow has no repo-level representation on the source: the workflow API scans WORKFLOW_DIRS (not SCOPED_WORKFLOW_DIRS),
// and the badge only reflects the source's repo-level runs, so neither link resolves a scoped workflow.
// Blank them for now and populate once a scoped-aware workflow/badge endpoint exists.
wf.URL = ""
wf.BadgeURL = ""
return wf, nil
}
}
return nil, util.NewNotExistErrorf("scoped workflow %q not found", workflowID)
}
// ResolveActionWorkflowForRun returns the api.ActionWorkflow describing a run's workflow definition.
// For a scoped run the definition lives in the source repo (run.WorkflowRepoID @ run.WorkflowCommitSHA) under SCOPED_WORKFLOW_DIRS,
// not in the consuming repo, so it is resolved against the source repo.
func ResolveActionWorkflowForRun(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun) (*api.ActionWorkflow, error) {
if run.IsScopedRun {
sourceRepo, err := repo_model.GetRepositoryByID(ctx, run.WorkflowRepoID)
if err != nil {
return nil, err
}
sourceGitRepo, err := gitrepo.OpenRepository(ctx, sourceRepo)
if err != nil {
return nil, err
}
defer sourceGitRepo.Close()
return GetScopedActionWorkflow(ctx, sourceGitRepo, sourceRepo, run.WorkflowID, run.WorkflowCommitSHA)
}
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
if err != nil {
return nil, err
}
defer gitRepo.Close()
convertedWorkflow, err := GetActionWorkflowByRef(ctx, gitRepo, repo, run.WorkflowID, git.RefName(run.Ref))
if err != nil && errors.Is(err, util.ErrNotExist) {
convertedWorkflow, err = GetActionWorkflow(ctx, gitRepo, repo, run.WorkflowID)
}
return convertedWorkflow, err
}
// ToActionArtifact convert a actions_model.ActionArtifact to an api.ActionArtifact
func ToActionArtifact(repo *repo_model.Repository, art *actions_model.ActionArtifact) (*api.ActionArtifact, error) {
url := fmt.Sprintf("%s/actions/artifacts/%d", repo.APIURL(), art.ID)
@@ -670,7 +862,7 @@ func ToOrganization(ctx context.Context, org *organization.Organization) *api.Or
Description: org.Description,
Website: org.Website,
Location: org.Location,
Visibility: org.Visibility.String(),
Visibility: api.UserVisibility(org.Visibility.String()),
RepoAdminChangeTeamAccess: org.RepoAdminChangeTeamAccess,
}
}
@@ -699,9 +891,10 @@ func ToTeams(ctx context.Context, teams []*organization.Team, loadOrgs bool) ([]
Description: t.Description,
IncludesAllRepositories: t.IncludesAllRepositories,
CanCreateOrgRepo: t.CanCreateOrgRepo,
Permission: t.AccessMode.ToString(),
Permission: api.AccessLevelName(t.AccessMode.ToString()),
Units: t.GetUnitNames(),
UnitsMap: t.GetUnitsMap(),
Visibility: api.TeamVisibility(t.Visibility.String()),
}
if loadOrgs {
@@ -728,7 +921,7 @@ func ToAnnotatedTag(ctx context.Context, repo *repo_model.Repository, t *git.Tag
Tag: t.Name,
SHA: t.ID.String(),
Object: ToAnnotatedTagObject(repo, c),
Message: strings.ToValidUTF8(t.Message, "?"),
Message: t.MessageUTF8(),
URL: repo.APIURL() + "/git/tags/" + t.ID.String(),
Tagger: ToCommitUser(t.Tagger),
Verification: ToVerification(ctx, c),
@@ -746,7 +939,7 @@ func ToAnnotatedTagObject(repo *repo_model.Repository, commit *git.Commit) *api.
// ToTagProtection convert a git.ProtectedTag to an api.TagProtection
func ToTagProtection(ctx context.Context, pt *git_model.ProtectedTag, repo *repo_model.Repository) *api.TagProtection {
readers, err := access_model.GetUsersWithUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypePullRequests)
readers, err := access_model.GetUsersWithAnyUnitAccess(ctx, repo, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
if err != nil {
log.Error("GetRepoReaders: %v", err)
}
@@ -8,14 +8,14 @@ import (
"net/url"
"time"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
ctx "code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/gitdiff"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
api "gitea.dev/modules/structs"
ctx "gitea.dev/services/context"
"gitea.dev/services/gitdiff"
)
// ToCommitUser convert a git.Signature to an api.CommitUser
@@ -56,7 +56,7 @@ func ToPayloadCommit(ctx context.Context, repo *repo_model.Repository, c *git.Co
return &api.PayloadCommit{
ID: c.ID.String(),
Message: c.Message(),
Message: c.MessageUTF8(),
URL: repo.HTMLURL() + "/commit/" + c.ID.String(),
Author: &api.PayloadUser{
Name: c.Author.Name,
@@ -171,7 +171,7 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep
},
Date: commit.Committer.When.Format(time.RFC3339),
},
Message: commit.Message(),
Message: commit.MessageUTF8(),
Tree: &api.CommitMeta{
URL: repo.APIURL() + "/git/trees/" + url.PathEscape(commit.ID.String()),
SHA: commit.ID.String(),
@@ -7,10 +7,10 @@ import (
"testing"
"time"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"gitea.dev/modules/git"
api "gitea.dev/modules/structs"
"github.com/stretchr/testify/assert"
)
@@ -21,12 +21,12 @@ func TestToCommitMeta(t *testing.T) {
sha1 := git.Sha1ObjectFormat
signature := &git.Signature{Name: "Test Signature", Email: "test@email.com", When: time.Unix(0, 0)}
tag := &git.Tag{
Name: "Test Tag",
ID: sha1.EmptyObjectID(),
Object: sha1.EmptyObjectID(),
Type: "Test Type",
Tagger: signature,
Message: "Test Message",
Name: "Test Tag",
ID: sha1.EmptyObjectID(),
Object: sha1.EmptyObjectID(),
Type: "Test Type",
Tagger: signature,
CommitMessage: git.CommitMessage{MessageRaw: "Test Message"},
}
commitMeta := ToCommitMeta(headRepo, tag)
+17 -10
View File
@@ -9,16 +9,16 @@ import (
"net/url"
"strings"
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
issues_model "gitea.dev/models/issues"
access_model "gitea.dev/models/perm/access"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/cache"
"gitea.dev/modules/label"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
)
func ToIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
@@ -95,6 +95,13 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss
apiIssue.Milestone = ToAPIMilestone(issue.Milestone)
}
if err := issue.LoadProjects(ctx); err != nil {
return &api.Issue{}
}
if len(issue.Projects) > 0 {
apiIssue.Projects = ToAPIProjectList(issue.Projects)
}
if err := issue.LoadAssignees(ctx); err != nil {
return &api.Issue{}
}
@@ -6,12 +6,12 @@ package convert
import (
"context"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
issues_model "gitea.dev/models/issues"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/log"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
)
// ToAPIComment converts a issues_model.Comment to the api.Comment format for API usage
@@ -8,14 +8,14 @@ import (
"testing"
"time"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
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"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"gitea.dev/models/db"
issues_model "gitea.dev/models/issues"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -6,9 +6,9 @@ package convert
import (
"testing"
"code.gitea.io/gitea/models/unittest"
"gitea.dev/models/unittest"
_ "code.gitea.io/gitea/models/actions"
_ "gitea.dev/models/actions"
)
func TestMain(m *testing.M) {
@@ -6,8 +6,8 @@ package convert
import (
"context"
repo_model "code.gitea.io/gitea/models/repo"
api "code.gitea.io/gitea/modules/structs"
repo_model "gitea.dev/models/repo"
api "gitea.dev/modules/structs"
)
// ToPushMirror convert from repo_model.PushMirror and remoteAddress to api.TopicResponse
@@ -7,10 +7,10 @@ import (
"context"
"net/url"
activities_model "code.gitea.io/gitea/models/activities"
access_model "code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
activities_model "gitea.dev/models/activities"
access_model "gitea.dev/models/perm/access"
"gitea.dev/modules/log"
api "gitea.dev/modules/structs"
)
// ToNotificationThread convert a Notification to api.NotificationThread
@@ -24,19 +24,22 @@ func ToNotificationThread(ctx context.Context, n *activities_model.Notification)
}
// since user only get notifications when he has access to use minimal access mode
if n.Repository != nil {
perm, err := access_model.GetIndividualUserRepoPermission(ctx, n.Repository, n.User)
if err != nil {
log.Error("GetIndividualUserRepoPermission failed: %v", err)
return result
}
if perm.HasAnyUnitAccessOrPublicAccess() { // if user has been revoked access to repo, do not show repo info
result.Repository = ToRepo(ctx, n.Repository, perm)
// This permission is not correct and we should not be reporting it
for repository := result.Repository; repository != nil; repository = repository.Parent {
repository.Permissions = nil
}
}
if n.Repository == nil {
return result
}
perm, err := access_model.GetIndividualUserRepoPermission(ctx, n.Repository, n.User)
if err != nil {
log.Error("GetIndividualUserRepoPermission failed: %v", err)
return result
}
// if the user has been revoked access to the repo, do not leak repo or subject info
if !perm.HasAnyUnitAccessOrPublicAccess() {
return result
}
result.Repository = ToRepo(ctx, n.Repository, perm)
// This permission is not correct and we should not be reporting it
for repository := result.Repository; repository != nil; repository = repository.Parent {
repository.Permissions = nil
}
// handle Subject
@@ -6,13 +6,13 @@ package convert
import (
"testing"
activities_model "code.gitea.io/gitea/models/activities"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
activities_model "gitea.dev/models/activities"
issues_model "gitea.dev/models/issues"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
api "gitea.dev/modules/structs"
"gitea.dev/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -39,6 +39,36 @@ func TestToNotificationThreadOmitsRepoWhenAccessRevoked(t *testing.T) {
assert.Nil(t, thread.Repository)
}
func TestToNotificationThreadOmitsSubjectWhenAccessRevoked(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
ctx := t.Context()
// repo 2 is private; user 4 has no access to it
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.NoError(t, repo.LoadOwner(ctx))
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4, RepoID: repo.ID})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
n := &activities_model.Notification{
ID: 12345,
UserID: user.ID,
RepoID: repo.ID,
Status: activities_model.NotificationStatusUnread,
Source: activities_model.NotificationSourceIssue,
IssueID: issue.ID,
UpdatedUnix: timeutil.TimeStampNow(),
Issue: issue,
Repository: repo,
User: user,
}
thread := ToNotificationThread(ctx, n)
// must not leak private issue metadata once access is revoked
assert.Nil(t, thread.Repository)
assert.Nil(t, thread.Subject)
}
func TestToNotificationThread(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
@@ -6,10 +6,10 @@ package convert
import (
"context"
"code.gitea.io/gitea/models/packages"
access_model "code.gitea.io/gitea/models/perm/access"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"gitea.dev/models/packages"
access_model "gitea.dev/models/perm/access"
user_model "gitea.dev/models/user"
api "gitea.dev/modules/structs"
)
// ToPackage convert a packages.PackageDescriptor to api.Package
@@ -0,0 +1,37 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package convert
import (
project_model "gitea.dev/models/project"
api "gitea.dev/modules/structs"
)
// ToAPIProject converts a Project to API format
func ToAPIProject(p *project_model.Project) *api.Project {
apiProject := &api.Project{
ID: p.ID,
Title: p.Title,
Description: p.Description,
OwnerID: p.OwnerID,
RepoID: p.RepoID,
CreatorID: p.CreatorID,
IsClosed: p.IsClosed,
Created: p.CreatedUnix.AsTime(),
Updated: p.UpdatedUnix.AsTime(),
}
if p.IsClosed && p.ClosedDateUnix > 0 {
apiProject.Closed = p.ClosedDateUnix.AsTimePtr()
}
return apiProject
}
// ToAPIProjectList converts a list of Projects to API format
func ToAPIProjectList(projects []*project_model.Project) []*api.Project {
result := make([]*api.Project, len(projects))
for i := range projects {
result[i] = ToAPIProject(projects[i])
}
return result
}
+15 -15
View File
@@ -7,21 +7,21 @@ import (
"context"
"fmt"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/cachegroup"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/gitdiff"
git_model "gitea.dev/models/git"
issues_model "gitea.dev/models/issues"
"gitea.dev/models/perm"
access_model "gitea.dev/models/perm/access"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/cache"
"gitea.dev/modules/cachegroup"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
"gitea.dev/services/gitdiff"
)
// ToAPIPullRequest assumes following fields have been assigned with valid values:
@@ -7,9 +7,9 @@ import (
"context"
"strings"
issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
issues_model "gitea.dev/models/issues"
user_model "gitea.dev/models/user"
api "gitea.dev/modules/structs"
)
// ToPullReview convert a review to api format
@@ -6,9 +6,9 @@ package convert
import (
"testing"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
issues_model "gitea.dev/models/issues"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/stretchr/testify/assert"
)
@@ -6,12 +6,12 @@ package convert
import (
"testing"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/structs"
issues_model "gitea.dev/models/issues"
"gitea.dev/models/perm"
access_model "gitea.dev/models/perm/access"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"gitea.dev/modules/structs"
"github.com/stretchr/testify/assert"
)
@@ -6,8 +6,8 @@ package convert
import (
"context"
repo_model "code.gitea.io/gitea/models/repo"
api "code.gitea.io/gitea/modules/structs"
repo_model "gitea.dev/models/repo"
api "gitea.dev/modules/structs"
)
// ToAPIRelease convert a repo_model.Release to api.Release
@@ -6,8 +6,8 @@ package convert
import (
"testing"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"github.com/stretchr/testify/assert"
)
@@ -7,15 +7,15 @@ import (
"context"
"time"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"gitea.dev/models/db"
git_model "gitea.dev/models/git"
"gitea.dev/models/perm"
access_model "gitea.dev/models/perm/access"
repo_model "gitea.dev/models/repo"
unit_model "gitea.dev/models/unit"
"gitea.dev/modules/log"
api "gitea.dev/modules/structs"
"gitea.dev/modules/util"
)
// ToRepo converts a Repository to api.Repository
@@ -98,11 +98,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
allowRebaseMerge := false
allowSquash := false
allowFastForwardOnly := false
allowMergeUpdate := false
allowRebaseUpdate := false
allowManualMerge := true
autodetectManualMerge := false
defaultDeleteBranchAfterMerge := false
defaultMergeStyle := repo_model.MergeStyleMerge
defaultUpdateStyle := repo_model.UpdateStyleMerge
defaultAllowMaintainerEdit := false
defaultTargetBranch := ""
if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil {
@@ -114,11 +116,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
allowRebaseMerge = config.AllowRebaseMerge
allowSquash = config.AllowSquash
allowFastForwardOnly = config.AllowFastForwardOnly
allowMergeUpdate = config.AllowMergeUpdate
allowRebaseUpdate = config.AllowRebaseUpdate
allowManualMerge = config.AllowManualMerge
autodetectManualMerge = config.AutodetectManualMerge
defaultDeleteBranchAfterMerge = config.DefaultDeleteBranchAfterMerge
defaultMergeStyle = config.DefaultMergeStyle
defaultUpdateStyle = config.DefaultUpdateStyle
defaultAllowMaintainerEdit = config.DefaultAllowMaintainerEdit
defaultTargetBranch = config.DefaultTargetBranch
}
@@ -152,11 +156,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
mirrorInterval := ""
var mirrorUpdated time.Time
var lastSync time.Time
if repo.IsMirror {
pullMirror, err := repo_model.GetMirrorByRepoID(ctx, repo.ID)
if err == nil {
mirrorInterval = pullMirror.Interval.String()
mirrorUpdated = pullMirror.UpdatedUnix.AsTime()
lastSync = pullMirror.LastSyncUnix.AsTime()
}
}
@@ -238,20 +244,23 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
AllowRebaseMerge: allowRebaseMerge,
AllowSquash: allowSquash,
AllowFastForwardOnly: allowFastForwardOnly,
AllowMergeUpdate: allowMergeUpdate,
AllowRebaseUpdate: allowRebaseUpdate,
AllowManualMerge: allowManualMerge,
AutodetectManualMerge: autodetectManualMerge,
DefaultDeleteBranchAfterMerge: defaultDeleteBranchAfterMerge,
DefaultMergeStyle: string(defaultMergeStyle),
DefaultUpdateStyle: string(defaultUpdateStyle),
DefaultAllowMaintainerEdit: defaultAllowMaintainerEdit,
DefaultTargetBranch: defaultTargetBranch,
AvatarURL: repo.AvatarLink(ctx),
Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
MirrorLastSyncAt: lastSync,
MirrorInterval: mirrorInterval,
MirrorUpdated: mirrorUpdated,
RepoTransfer: transfer,
Topics: util.SliceNilAsEmpty(repo.Topics),
ObjectFormatName: repo.ObjectFormatName,
ObjectFormatName: api.ObjectFormatName(repo.ObjectFormatName),
Licenses: util.SliceNilAsEmpty(repoLicenses.StringList()),
}
}
@@ -1,18 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package convert
import (
secret_model "code.gitea.io/gitea/models/secret"
api "code.gitea.io/gitea/modules/structs"
)
// ToSecret converts Secret to API format
func ToSecret(secret *secret_model.Secret) *api.Secret {
result := &api.Secret{
Name: secret.Name,
}
return result
}
@@ -7,10 +7,10 @@ import (
"context"
"net/url"
git_model "code.gitea.io/gitea/models/git"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/commitstatus"
api "code.gitea.io/gitea/modules/structs"
git_model "gitea.dev/models/git"
user_model "gitea.dev/models/user"
"gitea.dev/modules/commitstatus"
api "gitea.dev/modules/structs"
)
// ToCommitStatus converts git_model.CommitStatus to api.CommitStatus
@@ -6,9 +6,9 @@ package convert
import (
"context"
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"gitea.dev/models/perm"
user_model "gitea.dev/models/user"
api "gitea.dev/modules/structs"
)
// ToUser convert user_model.User to api.User
@@ -65,7 +65,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap
StarredRepos: user.NumStars,
}
result.Visibility = user.Visibility.String()
result.Visibility = api.UserVisibility(user.Visibility.String())
// hide primary email if API caller is anonymous or user keep email private
if signed && (!user.KeepEmailPrivate || authed) {
@@ -109,7 +109,7 @@ func User2UserSettings(ctx context.Context, user *user_model.User) (api.UserSett
func ToUserAndPermission(ctx context.Context, user, doer *user_model.User, accessMode perm.AccessMode) api.RepoCollaboratorPermission {
return api.RepoCollaboratorPermission{
User: ToUser(ctx, user, doer),
Permission: accessMode.ToString(),
Permission: api.AccessLevelName(accessMode.ToString()),
RoleName: accessMode.ToString(),
}
}
@@ -6,9 +6,9 @@ package convert
import (
"testing"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
api "gitea.dev/modules/structs"
"github.com/stretchr/testify/assert"
)
@@ -29,11 +29,11 @@ func TestUser_ToUser(t *testing.T) {
apiUser = toUser(t.Context(), user1, false, false)
assert.False(t, apiUser.IsAdmin)
assert.Equal(t, api.VisibleTypePublic.String(), apiUser.Visibility)
assert.Equal(t, api.UserVisibilityPublic, apiUser.Visibility)
user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31, IsAdmin: false, Visibility: api.VisibleTypePrivate})
apiUser = toUser(t.Context(), user31, true, true)
assert.False(t, apiUser.IsAdmin)
assert.Equal(t, api.VisibleTypePrivate.String(), apiUser.Visibility)
assert.Equal(t, api.UserVisibilityPrivate, apiUser.Visibility)
}
@@ -7,8 +7,8 @@ package convert
import (
"strings"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"gitea.dev/modules/setting"
"gitea.dev/modules/structs"
)
// ToCorrectPageSize makes sure page size is in allowed range.
@@ -6,8 +6,8 @@ package convert
import (
"time"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
"gitea.dev/modules/git"
api "gitea.dev/modules/structs"
)
// ToWikiCommit convert a git commit into a WikiCommit
@@ -28,7 +28,7 @@ func ToWikiCommit(commit *git.Commit) *api.WikiCommit {
},
Date: commit.Committer.When.UTC().Format(time.RFC3339),
},
Message: commit.Message(),
Message: commit.MessageUTF8(),
}
}