Merge pull request '[gitea] v1.21 cherry-pick' (#2716) from earl-warren/forgejo:wip-v1.21-gitea-cherry-pick into v1.21/forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2716
This commit is contained in:
Earl Warren 2024-03-22 07:41:50 +00:00
commit 9028d061cc
24 changed files with 256 additions and 45 deletions

12
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
github.com/PuerkitoBio/goquery v1.8.1
github.com/alecthomas/chroma/v2 v2.10.0
github.com/alecthomas/chroma/v2 v2.13.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.3.10
github.com/bufbuild/connect-go v1.10.0
@ -71,7 +71,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.5
github.com/lib/pq v1.10.9
github.com/markbates/goth v1.78.0
github.com/mattn/go-isatty v0.0.19
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.17
github.com/meilisearch/meilisearch-go v0.25.1
github.com/mholt/archiver/v3 v3.5.1
@ -170,10 +170,10 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect

32
go.sum
View file

@ -109,14 +109,14 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
github.com/RoaringBitmap/roaring v1.6.0 h1:dc7kRiroETgJcHhWX6BerXkZz2b3JgLGg9nTURJL/og=
github.com/RoaringBitmap/roaring v1.6.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/chroma/v2 v2.10.0 h1:T2iQOCCt4pRmRMfL55gTodMtc7cU0y7lc1Jb8/mK/64=
github.com/alecthomas/chroma/v2 v2.10.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
@ -267,8 +267,8 @@ github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmW
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
@ -286,8 +286,8 @@ github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjT
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8bnphprS1EoVRe2Q5CKCX8iDlpqjQ/Y=
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
@ -299,13 +299,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4=
github.com/ethantkoenig/rupture v1.0.1/go.mod h1:Sjqo/nbffZp1pVVXNGhpugIjsWmuS9KiIB4GtpEBur4=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
@ -708,8 +708,8 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=

View file

@ -491,7 +491,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
cond = cond.And(builder.Eq{"email_address.is_activated": false})
}
count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.ID = email_address.uid").
count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.id = email_address.uid").
Where(cond).Count(new(EmailAddress))
if err != nil {
return nil, 0, fmt.Errorf("Count: %w", err)
@ -507,7 +507,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
emails := make([]*SearchEmailResult, 0, opts.PageSize)
err = db.GetEngine(ctx).Table("email_address").
Select("email_address.*, `user`.name, `user`.full_name").
Join("INNER", "`user`", "`user`.ID = email_address.uid").
Join("INNER", "`user`", "`user`.id = email_address.uid").
Where(cond).
OrderBy(orderby).
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).

View file

@ -5,6 +5,7 @@ package meilisearch
import (
"context"
"fmt"
"strconv"
"strings"
@ -210,7 +211,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits)
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(options.Keyword, &meilisearch.SearchRequest{
// to make it non fuzzy ("typo tolerance" in meilisearch terms), we have to quote the keyword(s)
// https://www.meilisearch.com/docs/reference/api/search#phrase-search
keyword := doubleQuoteKeyword(options.Keyword)
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
Filter: query.Statement(),
Limit: int64(limit),
Offset: int64(skip),
@ -241,3 +246,16 @@ func parseSortBy(sortBy internal.SortBy) string {
}
return field + ":asc"
}
func doubleQuoteKeyword(k string) string {
kp := strings.Split(k, " ")
parts := 0
for i := range kp {
part := strings.Trim(kp[i], "\"")
if part != "" {
kp[parts] = fmt.Sprintf(`"%s"`, part)
parts++
}
}
return strings.Join(kp[:parts], " ")
}

View file

@ -11,6 +11,8 @@ import (
"time"
"code.gitea.io/gitea/modules/indexer/issues/internal/tests"
"github.com/stretchr/testify/assert"
)
func TestMeilisearchIndexer(t *testing.T) {
@ -49,3 +51,11 @@ func TestMeilisearchIndexer(t *testing.T) {
tests.TestIndexer(t, indexer)
}
func TestDoubleQuoteKeyword(t *testing.T) {
assert.EqualValues(t, "", doubleQuoteKeyword(""))
assert.EqualValues(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c"))
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`))
}

View file

@ -103,7 +103,8 @@ func SpecializedMarkdown() goldmark.Markdown {
}
// include language-x class as part of commonmark spec
_, err = w.WriteString(`<code class="chroma language-` + string(language) + `">`)
// the "display" class is used by "js/markup/math.js" to render the code element as a block
_, err = w.WriteString(`<code class="chroma language-` + string(language) + ` display">`)
if err != nil {
return
}

View file

@ -1269,6 +1269,8 @@ editor.file_editing_no_longer_exists = The file being edited, "%s", no longer ex
editor.file_deleting_no_longer_exists = The file being deleted, "%s", no longer exists in this repository.
editor.file_changed_while_editing = The file contents have changed since you started editing. <a target="_blank" rel="noopener noreferrer" href="%s">Click here</a> to see them or <strong>Commit Changes again</strong> to overwrite them.
editor.file_already_exists = A file named "%s" already exists in this repository.
editor.commit_id_not_matching = The Commit ID does not match the ID when you began editing. Commit into a patch branch and then merge.
editor.push_out_of_date = The push appears to be out of date.
editor.commit_empty_file_header = Commit an empty file
editor.commit_empty_file_text = The file you're about to commit is empty. Proceed?
editor.no_changes_to_show = There are no changes to show.

View file

@ -972,6 +972,8 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
return nil, nil, nil, nil, "", ""
}
headBranch = headInfos[1]
// The head repository can also point to the same repo
isSameRepo = ctx.Repo.Owner.ID == headUser.ID
} else {
ctx.NotFound()

View file

@ -336,9 +336,9 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
ctx.Error(http.StatusInternalServerError, err.Error())
}
} else if models.IsErrCommitIDDoesNotMatch(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplEditFile, &form)
ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplEditFile, &form)
} else if git.IsErrPushOutOfDate(err) {
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(form.NewBranchName)), tplEditFile, &form)
ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(form.NewBranchName)), tplEditFile, &form)
} else if git.IsErrPushRejected(err) {
errPushRej := err.(*git.ErrPushRejected)
if len(errPushRej.Message) == 0 {

View file

@ -1369,7 +1369,7 @@ func registerRoutes(m *web.Route) {
})
m.Post("/cancel", reqRepoActionsWriter, actions.Cancel)
m.Post("/approve", reqRepoActionsWriter, actions.Approve)
m.Post("/artifacts", actions.ArtifactsView)
m.Get("/artifacts", actions.ArtifactsView)
m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView)
m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
})

View file

@ -348,6 +348,12 @@ func (*actionsNotifier) MergePullRequest(ctx context.Context, doer *user_model.U
}
func (n *actionsNotifier) PushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) {
commitID, _ := git.NewIDFromString(opts.NewCommitID)
if commitID.IsZero() {
log.Trace("new commitID is empty")
return
}
ctx = withMethod(ctx, "PushCommits")
apiPusher := convert.ToUser(ctx, pusher, nil)
@ -380,9 +386,9 @@ func (n *actionsNotifier) CreateRef(ctx context.Context, pusher *user_model.User
apiRepo := convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeNone})
newNotifyInput(repo, pusher, webhook_module.HookEventCreate).
WithRef(refFullName.ShortName()). // FIXME: should we use a full ref name
WithRef(refFullName.String()).
WithPayload(&api.CreatePayload{
Ref: refFullName.ShortName(),
Ref: refFullName.String(),
Sha: refID,
RefType: refFullName.RefType(),
Repo: apiRepo,
@ -400,7 +406,7 @@ func (n *actionsNotifier) DeleteRef(ctx context.Context, pusher *user_model.User
newNotifyInput(repo, pusher, webhook_module.HookEventDelete).
WithRef(refFullName.ShortName()). // FIXME: should we use a full ref name
WithPayload(&api.DeletePayload{
Ref: refFullName.ShortName(),
Ref: refFullName.String(),
RefType: refFullName.RefType(),
PusherType: api.PusherTypeUser,
Repo: apiRepo,
@ -457,6 +463,10 @@ func (n *actionsNotifier) UpdateRelease(ctx context.Context, doer *user_model.Us
}
func (n *actionsNotifier) DeleteRelease(ctx context.Context, doer *user_model.User, rel *repo_model.Release) {
if rel.IsTag {
// has sent same action in `PushCommits`, so skip it.
return
}
ctx = withMethod(ctx, "DeleteRelease")
notifyRelease(ctx, doer, rel, api.HookReleaseDeleted)
}

View file

@ -63,7 +63,7 @@
</td>
<td>{{.Package.Type.Name}}</td>
<td class="gt-ellipsis gt-max-width-12rem">{{.Package.Name}}</td>
<td class="gt-ellipsis gt-max-width-12rem"><a href="{{.FullWebLink}}">{{.Version.Version}}</a></td>
<td class="gt-ellipsis gt-max-width-12rem"><a href="{{.VersionWebLink}}">{{.Version.Version}}</a></td>
<td><a href="{{.Creator.HomeLink}}">{{.Creator.Name}}</a></td>
<td>
{{if .Repository}}

View file

@ -4,7 +4,7 @@
<div class="ui container">
{{template "user/overview/header" .}}
{{template "base/alert" .}}
<p><a href="{{.PackageDescriptor.FullWebLink}}">{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</a> / <strong>{{ctx.Locale.Tr "repo.settings"}}</strong></p>
<p><a href="{{.PackageDescriptor.VersionWebLink}}">{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</a> / <strong>{{ctx.Locale.Tr "repo.settings"}}</strong></p>
<h4 class="ui top attached header">
{{ctx.Locale.Tr "packages.settings.link"}}
</h4>

View file

@ -19,7 +19,7 @@
<tr>
<td>{{.Package.Type.Name}}</td>
<td>{{.Package.Name}}</td>
<td><a href="{{.FullWebLink}}">{{.Version.Version}}</a></td>
<td><a href="{{.VersionWebLink}}">{{.Version.Version}}</a></td>
<td><a href="{{.Creator.HomeLink}}">{{.Creator.Name}}</a></td>
<td>{{FileSize .CalculateBlobSize}}</td>
<td>{{DateTime "short" .Version.CreatedUnix}}</td>

View file

@ -20,7 +20,7 @@
<div class="flex-item">
<div class="flex-item-main">
<div class="flex-item-title">
<a href="{{.FullWebLink}}">{{.Package.Name}}</a>
<a href="{{.VersionWebLink}}">{{.Package.Name}}</a>
<span class="ui label">{{svg .Package.Type.SVGName 16}} {{.Package.Type.Name}}</span>
</div>
<div class="flex-item-body">

View file

@ -23,7 +23,7 @@
<div class="flex-list">
<div class="flex-item">
<div class="flex-item-main">
<a class="flex-item-title" href="{{.FullWebLink}}">{{.Version.LowerVersion}}</a>
<a class="flex-item-title" href="{{.VersionWebLink}}">{{.Version.LowerVersion}}</a>
<div class="flex-item-body">
{{ctx.Locale.Tr "packages.published_by" (TimeSinceUnix .Version.CreatedUnix ctx.Locale) .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
</div>

View file

@ -41,7 +41,7 @@
</div>
<div class="field color-field">
<label for="new_project_column_color">{{ctx.Locale.Tr "repo.projects.column.color"}}</label>
<label for="new_project_column_color_picker">{{ctx.Locale.Tr "repo.projects.column.color"}}</label>
<div class="color picker column">
<input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_project_column_color_picker" name="color">
{{template "repo/issue/label_precolors"}}

View file

@ -62,8 +62,8 @@
</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="{{if or (eq .SortType "closestduedate") (not .SortType)}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=closestduedate&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.closest_due_date"}}</a>
<a class="{{if eq .SortType "furthestduedate"}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=furthestduedate&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.furthest_due_date"}}</a>
<a class="{{if or (eq .SortType "closestduedate") (not .SortType)}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=closestduedate&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.earliest_due_data"}}</a>
<a class="{{if eq .SortType "furthestduedate"}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=furthestduedate&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.latest_due_date"}}</a>
<a class="{{if eq .SortType "leastcomplete"}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=leastcomplete&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.least_complete"}}</a>
<a class="{{if eq .SortType "mostcomplete"}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=mostcomplete&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.most_complete"}}</a>
<a class="{{if eq .SortType "mostissues"}}active {{end}}item" href="{{$.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort=mostissues&state={{$.State}}&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.milestones.filter_sort.most_issues"}}</a>

View file

@ -11,6 +11,7 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
@ -21,6 +22,7 @@ import (
webhook_module "code.gitea.io/gitea/modules/webhook"
actions_service "code.gitea.io/gitea/services/actions"
pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files"
@ -198,3 +200,123 @@ func TestPullRequestTargetEvent(t *testing.T) {
assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: baseRepo.ID}))
})
}
func TestCreateDeleteRefEvent(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// create the repo
repo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{
Name: "create-delete-ref-event",
Description: "test create delete ref ci event",
AutoInit: true,
Gitignores: "Go",
License: "MIT",
Readme: "Default",
DefaultBranch: "main",
IsPrivate: false,
})
assert.NoError(t, err)
assert.NotEmpty(t, repo)
// enable actions
err = repo_model.UpdateRepositoryUnits(repo, []repo_model.RepoUnit{{
RepoID: repo.ID,
Type: unit_model.TypeActions,
}}, nil)
assert.NoError(t, err)
// reload units
repo.Units = nil
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
// add workflow file to the repo
addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
Operation: "create",
TreePath: ".gitea/workflows/createdelete.yml",
ContentReader: strings.NewReader("name: test\non:\n [create,delete]\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n"),
},
},
Message: "add workflow",
OldBranch: "main",
NewBranch: "main",
Author: &files_service.IdentityOptions{
Name: user2.Name,
Email: user2.Email,
},
Committer: &files_service.IdentityOptions{
Name: user2.Name,
Email: user2.Email,
},
Dates: &files_service.CommitDateOptions{
Author: time.Now(),
Committer: time.Now(),
},
})
assert.NoError(t, err)
assert.NotEmpty(t, addWorkflowToBaseResp)
// Get the commit ID of the default branch
gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user2.Name, repo.Name))
assert.NoError(t, err)
defer gitRepo.Close()
branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
assert.NoError(t, err)
// create a branch
err = repo_service.CreateNewBranchFromCommit(db.DefaultContext, user2, repo, gitRepo, branch.CommitID, "test-create-branch")
assert.NoError(t, err)
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "add workflow",
RepoID: repo.ID,
Event: "create",
Ref: "refs/heads/test-create-branch",
WorkflowID: "createdelete.yml",
CommitSHA: branch.CommitID,
})
assert.NotNil(t, run)
// create a tag
err = release_service.CreateNewTag(db.DefaultContext, user2, repo, branch.CommitID, "test-create-tag", "test create tag event")
assert.NoError(t, err)
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "add workflow",
RepoID: repo.ID,
Event: "create",
Ref: "refs/tags/test-create-tag",
WorkflowID: "createdelete.yml",
CommitSHA: branch.CommitID,
})
assert.NotNil(t, run)
// delete the branch
err = repo_service.DeleteBranch(db.DefaultContext, user2, repo, gitRepo, "test-create-branch")
assert.NoError(t, err)
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "add workflow",
RepoID: repo.ID,
Event: "delete",
Ref: "main",
WorkflowID: "createdelete.yml",
CommitSHA: branch.CommitID,
})
assert.NotNil(t, run)
// delete the tag
tag, err := repo_model.GetRelease(db.DefaultContext, repo.ID, "test-create-tag")
assert.NoError(t, err)
err = release_service.DeleteReleaseByID(db.DefaultContext, repo, tag, user2, true)
assert.NoError(t, err)
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "add workflow",
RepoID: repo.ID,
Event: "delete",
Ref: "main",
WorkflowID: "createdelete.yml",
CommitSHA: branch.CommitID,
})
assert.NotNil(t, run)
})
}

View file

@ -104,6 +104,23 @@ func TestAPICreatePullSuccess(t *testing.T) {
MakeRequest(t, req, http.StatusUnprocessableEntity) // second request should fail
}
func TestAPICreatePullSameRepoSuccess(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
session := loginUser(t, owner.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner.Name, repo.Name, token), &api.CreatePullRequestOption{
Head: fmt.Sprintf("%s:pr-to-update", owner.Name),
Base: "master",
Title: "successfully create a PR between branches of the same repository",
})
MakeRequest(t, req, http.StatusCreated)
MakeRequest(t, req, http.StatusUnprocessableEntity) // second request should fail
}
func TestAPICreatePullWithFieldsSuccess(t *testing.T) {
defer tests.PrepareTestEnv(t)()
// repo10 have code, pulls units.

View file

@ -20,6 +20,7 @@
left: 50%;
top: 50%;
height: min(4em, 66.6%);
width: fit-content; /* compat: safari - https://bugs.webkit.org/show_bug.cgi?id=267625 */
aspect-ratio: 1;
transform: translate(-50%, -50%);
animation: isloadingspin 1000ms infinite linear;

View file

@ -1432,6 +1432,7 @@
.repository .data-table tr {
border-top: 0;
background: none !important;
}
.repository .data-table td,
@ -1444,6 +1445,21 @@
border: 1px solid var(--color-secondary);
}
/* the border css competes with .markup where all tables have outer border which would add a double
border here, remove only the outer borders from this table */
.repository .data-table tr:first-child :is(td,th) {
border-top: none !important;
}
.repository .data-table tr:last-child :is(td,th) {
border-bottom: none !important;
}
.repository .data-table tr :is(td,th):first-child {
border-left: none !important;
}
.repository .data-table tr :is(td,th):last-child {
border-right: none !important;
}
.repository .data-table td {
white-space: pre-line;
}
@ -1481,7 +1497,7 @@
min-width: 50px;
font-family: monospace;
line-height: 20px;
color: var(--color-secondary-dark-2);
color: var(--color-text-light-1);
white-space: nowrap;
vertical-align: top;
cursor: pointer;

View file

@ -6,10 +6,18 @@
// This file must be imported before any lazy-loading is being attempted.
__webpack_public_path__ = `${window.config?.assetUrlPrefix ?? '/assets'}/`;
const filteredErrors = new Set([
'getModifierState is not a function', // https://github.com/microsoft/monaco-editor/issues/4325
]);
export function showGlobalErrorMessage(msg) {
const pageContent = document.querySelector('.page-content');
if (!pageContent) return;
for (const filteredError of filteredErrors) {
if (msg.includes(filteredError)) return;
}
// compact the message to a data attribute to avoid too many duplicated messages
const msgCompact = msg.replace(/\W/g, '').trim();
let msgDiv = pageContent.querySelector(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);

View file

@ -5,7 +5,7 @@ import {createApp} from 'vue';
import {toggleElem} from '../utils/dom.js';
import {getCurrentLocale} from '../utils.js';
import {renderAnsi} from '../render/ansi.js';
import {POST} from '../modules/fetch.js';
import {GET, POST} from '../modules/fetch.js';
const sfc = {
name: 'RepoActionView',
@ -196,7 +196,7 @@ const sfc = {
},
async fetchArtifacts() {
const resp = await POST(`${this.actionsURL}/runs/${this.runIndex}/artifacts`);
const resp = await GET(`${this.actionsURL}/runs/${this.runIndex}/artifacts`);
return await resp.json();
},
@ -446,7 +446,7 @@ export function initRepositoryActionView() {
</div>
</div>
</div>
<div class="job-step-container" ref="steps">
<div class="job-step-container" ref="steps" v-if="currentJob.steps.length">
<div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i">
<div class="job-step-summary" @click.stop="toggleStepLogs(i)" :class="currentJobStepsStates[i].expanded ? 'selected' : ''">
<!-- If the job is done and the job step log is loaded for the first time, show the loading icon
@ -672,11 +672,15 @@ export function initRepositoryActionView() {
background-color: var(--color-console-bg);
position: sticky;
top: 0;
border-radius: var(--border-radius) var(--border-radius) 0 0;
border-radius: var(--border-radius);
height: 60px;
z-index: 1;
}
.job-info-header:has(+ .job-step-container) {
border-radius: var(--border-radius) var(--border-radius) 0 0;
}
.job-info-header .job-info-header-title {
color: var(--color-console-fg);
font-size: 16px;