1
0
mirror of https://github.com/go-gitea/gitea.git synced 2024-06-29 01:45:30 +00:00

Merge branch 'main' into tsconfig

This commit is contained in:
silverwind 2024-06-04 13:08:24 +02:00 committed by GitHub
commit 576e78fa09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 324 additions and 83 deletions

View File

@ -10,7 +10,8 @@
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12"
}
},
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
},
"customizations": {
"vscode": {
@ -25,7 +26,7 @@
"Vue.volar",
"ms-azuretools.vscode-docker",
"vitest.explorer",
"qwtel.sqlite-viewer",
"cweijan.vscode-database-client2",
"GitHub.vscode-pull-request-github",
"Azurite.azurite"
]

View File

@ -43,7 +43,7 @@ vscode:
- Vue.volar
- ms-azuretools.vscode-docker
- vitest.explorer
- qwtel.sqlite-viewer
- cweijan.vscode-database-client2
- GitHub.vscode-pull-request-github
ports:

View File

@ -25,7 +25,7 @@ COMMA := ,
XGO_VERSION := go-1.22.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1
AIR_PACKAGE ?= github.com/air-verse/air@v1
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0

View File

@ -1687,6 +1687,16 @@ LEVEL = Info
;; convert \r\n to \n for Sendmail
;SENDMAIL_CONVERT_CRLF = true
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[mailer.override_header]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This is empty by default, use it only if you know what you need it for.
;Reply-To = test@example.com, test2@example.com
;Content-Type = text/html; charset=utf-8
;In-Reply-To =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[email.incoming]

View File

@ -724,11 +724,13 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
## Mailer (`mailer`)
⚠️ This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
:::warning
This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
please refer to
[Gitea 1.17 app.ini example](https://github.com/go-gitea/gitea/blob/release/v1.17/custom/conf/app.example.ini)
and
[Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md)
:::
- `ENABLED`: **false**: Enable to use a mail service.
- `PROTOCOL`: **_empty_**: Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._
@ -761,6 +763,21 @@ and
- `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
- `SEND_AS_PLAIN_TEXT`: **false**: Send mails only in plain text, without HTML alternative.
## Override Email Headers (`mailer.override_header`)
:::warning
This is empty by default, use it only if you know what you need it for.
:::
examples would be:
```ini
[mailer.override_header]
Reply-To = test@example.com, test2@example.com
Content-Type = text/html; charset=utf-8
In-Reply-To =
```
## Incoming Email (`email.incoming`)
- `ENABLED`: **false**: Enable handling of incoming emails.

2
go.mod
View File

@ -20,7 +20,7 @@ require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
github.com/ProtonMail/go-crypto v1.0.0
github.com/PuerkitoBio/goquery v1.9.1
github.com/alecthomas/chroma/v2 v2.13.0
github.com/alecthomas/chroma/v2 v2.14.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.3.10
github.com/buildkite/terminal-to-html/v3 v3.11.0

8
go.sum
View File

@ -82,11 +82,11 @@ 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.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE=
github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
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/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
github.com/alecthomas/assert/v2 v2.7.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.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=

View File

@ -18,14 +18,15 @@ import (
// Mailer represents mail service.
type Mailer struct {
// Mailer
Name string `ini:"NAME"`
From string `ini:"FROM"`
EnvelopeFrom string `ini:"ENVELOPE_FROM"`
OverrideEnvelopeFrom bool `ini:"-"`
FromName string `ini:"-"`
FromEmail string `ini:"-"`
SendAsPlainText bool `ini:"SEND_AS_PLAIN_TEXT"`
SubjectPrefix string `ini:"SUBJECT_PREFIX"`
Name string `ini:"NAME"`
From string `ini:"FROM"`
EnvelopeFrom string `ini:"ENVELOPE_FROM"`
OverrideEnvelopeFrom bool `ini:"-"`
FromName string `ini:"-"`
FromEmail string `ini:"-"`
SendAsPlainText bool `ini:"SEND_AS_PLAIN_TEXT"`
SubjectPrefix string `ini:"SUBJECT_PREFIX"`
OverrideHeader map[string][]string `ini:"-"`
// SMTP sender
Protocol string `ini:"PROTOCOL"`
@ -151,6 +152,12 @@ func loadMailerFrom(rootCfg ConfigProvider) {
log.Fatal("Unable to map [mailer] section on to MailService. Error: %v", err)
}
overrideHeader := rootCfg.Section("mailer.override_header").Keys()
MailService.OverrideHeader = make(map[string][]string)
for _, key := range overrideHeader {
MailService.OverrideHeader[key.Name()] = key.Strings(",")
}
// Infer SMTPPort if not set
if MailService.SMTPPort == "" {
switch MailService.Protocol {

View File

@ -6,8 +6,11 @@ package structs
import "time"
type Activity struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"` // Receiver user
ID int64 `json:"id"`
UserID int64 `json:"user_id"` // Receiver user
// the type of action
//
// enum: create_repo,rename_repo,star_repo,watch_repo,commit_repo,create_issue,create_pull_request,transfer_repo,push_tag,comment_issue,merge_pull_request,close_issue,reopen_issue,close_pull_request,reopen_pull_request,delete_tag,delete_branch,mirror_sync_push,mirror_sync_create,mirror_sync_delete,approve_pull_request,reject_pull_request,comment_pull,publish_release,pull_review_dismissed,pull_request_ready_for_review,auto_merge_pull_request
OpType string `json:"op_type"`
ActUserID int64 `json:"act_user_id"`
ActUser *User `json:"act_user"`

8
package-lock.json generated
View File

@ -10,7 +10,7 @@
"@citation-js/plugin-csl": "0.7.11",
"@citation-js/plugin-software-formats": "0.6.1",
"@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.4.0",
"@github/relative-time-element": "4.4.1",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
"@primer/octicons": "19.9.0",
@ -1032,9 +1032,9 @@
"integrity": "sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A=="
},
"node_modules/@github/relative-time-element": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.0.tgz",
"integrity": "sha512-CrI6oAecoahG7PF5dsgjdvlF5kCtusVMjg810EULD81TvnDsP+k/FRi/ClFubWLgBo4EGpr2EfvmumtqQFo7ow=="
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.1.tgz",
"integrity": "sha512-E2vRcIgDj8AHv/iHpQMLJ/RqKOJ704OXkKw6+Zdhk3X+kVQhOf3Wj8KVz4DfCQ1eOJR8XxY6XVv73yd+pjMfXA=="
},
"node_modules/@github/text-expander-element": {
"version": "2.6.1",

View File

@ -9,7 +9,7 @@
"@citation-js/plugin-csl": "0.7.11",
"@citation-js/plugin-software-formats": "0.6.1",
"@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.4.0",
"@github/relative-time-element": "4.4.1",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
"@primer/octicons": "19.9.0",

View File

@ -96,20 +96,34 @@ func FeedCapabilityResource(ctx *context.Context) {
xmlResponse(ctx, http.StatusOK, Metadata)
}
var searchTermExtract = regexp.MustCompile(`'([^']+)'`)
var (
searchTermExtract = regexp.MustCompile(`'([^']+)'`)
searchTermExact = regexp.MustCompile(`\s+eq\s+'`)
)
func getSearchTerm(ctx *context.Context) string {
func getSearchTerm(ctx *context.Context) packages_model.SearchValue {
searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'")
if searchTerm == "" {
// $filter contains a query like:
// (((Id ne null) and substringof('microsoft',tolower(Id)))
// We don't support these queries, just extract the search term.
match := searchTermExtract.FindStringSubmatch(ctx.FormTrim("$filter"))
if len(match) == 2 {
searchTerm = strings.TrimSpace(match[1])
if searchTerm != "" {
return packages_model.SearchValue{
Value: searchTerm,
ExactMatch: false,
}
}
return searchTerm
// $filter contains a query like:
// (((Id ne null) and substringof('microsoft',tolower(Id)))
// https://www.odata.org/documentation/odata-version-2-0/uri-conventions/ section 4.5
// We don't support these queries, just extract the search term.
filter := ctx.FormTrim("$filter")
match := searchTermExtract.FindStringSubmatch(filter)
if len(match) == 2 {
return packages_model.SearchValue{
Value: strings.TrimSpace(match[1]),
ExactMatch: searchTermExact.MatchString(filter),
}
}
return packages_model.SearchValue{}
}
// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs
@ -118,11 +132,9 @@ func SearchServiceV2(ctx *context.Context) {
paginator := db.NewAbsoluteListOptions(skip, take)
pvs, total, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNuGet,
Name: packages_model.SearchValue{
Value: getSearchTerm(ctx),
},
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeNuGet,
Name: getSearchTerm(ctx),
IsInternal: optional.Some(false),
Paginator: paginator,
})
@ -169,10 +181,8 @@ func SearchServiceV2(ctx *context.Context) {
// http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351
func SearchServiceV2Count(ctx *context.Context) {
count, err := nuget_model.CountPackages(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Name: packages_model.SearchValue{
Value: getSearchTerm(ctx),
},
OwnerID: ctx.Package.Owner.ID,
Name: getSearchTerm(ctx),
IsInternal: optional.Some(false),
})
if err != nil {

View File

@ -156,7 +156,7 @@ func GetContentHistoryDetail(ctx *context.Context) {
// use chroma to render the diff html
diffHTMLBuf := bytes.Buffer{}
diffHTMLBuf.WriteString("<pre class='chroma' style='tab-size: 4'>")
diffHTMLBuf.WriteString("<pre class='chroma'>")
for _, it := range diff {
if it.Type == diffmatchpatch.DiffInsert {
diffHTMLBuf.WriteString("<span class='gi'>")

View File

@ -57,7 +57,7 @@ func (m *Message) ToMessage() *gomail.Message {
msg.SetHeader(header, m.Headers[header]...)
}
if len(setting.MailService.SubjectPrefix) > 0 {
if setting.MailService.SubjectPrefix != "" {
msg.SetHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject)
} else {
msg.SetHeader("Subject", m.Subject)
@ -79,6 +79,14 @@ func (m *Message) ToMessage() *gomail.Message {
if len(msg.GetHeader("Message-ID")) == 0 {
msg.SetHeader("Message-ID", m.generateAutoMessageID())
}
for k, v := range setting.MailService.OverrideHeader {
if len(msg.GetHeader(k)) != 0 {
log.Debug("Mailer override header '%s' as per config", k)
}
msg.SetHeader(k, v...)
}
return msg
}

View File

@ -4,6 +4,7 @@
package mailer
import (
"strings"
"testing"
"time"
@ -36,3 +37,78 @@ func TestGenerateMessageID(t *testing.T) {
gm = m.ToMessage()
assert.Equal(t, "<msg-d@domain.com>", gm.GetHeader("Message-ID")[0])
}
func TestToMessage(t *testing.T) {
oldConf := *setting.MailService
defer func() {
setting.MailService = &oldConf
}()
setting.MailService.From = "test@gitea.com"
m1 := Message{
Info: "info",
FromAddress: "test@gitea.com",
FromDisplayName: "Test Gitea",
To: "a@b.com",
Subject: "Issue X Closed",
Body: "Some Issue got closed by Y-Man",
}
buf := &strings.Builder{}
_, err := m1.ToMessage().WriteTo(buf)
assert.NoError(t, err)
header, _ := extractMailHeaderAndContent(t, buf.String())
assert.EqualValues(t, map[string]string{
"Content-Type": "multipart/alternative;",
"Date": "Mon, 01 Jan 0001 00:00:00 +0000",
"From": "\"Test Gitea\" <test@gitea.com>",
"Message-ID": "<autogen--6795364578871-69c000786adc60dc@localhost>",
"Mime-Version": "1.0",
"Subject": "Issue X Closed",
"To": "a@b.com",
"X-Auto-Response-Suppress": "All",
}, header)
setting.MailService.OverrideHeader = map[string][]string{
"Message-ID": {""}, // delete message id
"Auto-Submitted": {"auto-generated"}, // suppress auto replay
}
buf = &strings.Builder{}
_, err = m1.ToMessage().WriteTo(buf)
assert.NoError(t, err)
header, _ = extractMailHeaderAndContent(t, buf.String())
assert.EqualValues(t, map[string]string{
"Content-Type": "multipart/alternative;",
"Date": "Mon, 01 Jan 0001 00:00:00 +0000",
"From": "\"Test Gitea\" <test@gitea.com>",
"Message-ID": "",
"Mime-Version": "1.0",
"Subject": "Issue X Closed",
"To": "a@b.com",
"X-Auto-Response-Suppress": "All",
"Auto-Submitted": "auto-generated",
}, header)
}
func extractMailHeaderAndContent(t *testing.T, mail string) (map[string]string, string) {
header := make(map[string]string)
parts := strings.SplitN(mail, "boundary=", 2)
if !assert.Len(t, parts, 2) {
return nil, ""
}
content := strings.TrimSpace("boundary=" + parts[1])
hParts := strings.Split(parts[0], "\n")
for _, hPart := range hParts {
parts := strings.SplitN(hPart, ":", 2)
hk := strings.TrimSpace(parts[0])
if hk != "" {
header[hk] = strings.TrimSpace(parts[1])
}
}
return header, content
}

View File

@ -1,6 +1,7 @@
import {readFileSync} from 'node:fs';
import {env} from 'node:process';
import {parse} from 'postcss';
import plugin from 'tailwindcss/plugin.js';
const isProduction = env.NODE_ENV !== 'development';
@ -98,4 +99,26 @@ export default {
})),
},
},
plugins: [
plugin(({addUtilities}) => {
addUtilities({
// tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
// do not use:
// * "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
// * ".hidden" class: it has been polluted by Fomantic UI in many cases
// * inline style="display: none": it's difficult to tweak
// * jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
// only use:
// * this ".tw-hidden" class
// * showElem/hideElem/toggleElem functions in "utils/dom.js"
'.hidden.hidden': {
'display': 'none',
},
// proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128
'.break-anywhere': {
'overflow-wrap': 'anywhere',
},
});
}),
],
};

View File

@ -66,7 +66,7 @@
<div id="project-board">
<div class="board {{if .CanWriteProjects}}sortable{{end}}"{{if .CanWriteProjects}} data-url="{{$.Link}}/move"{{end}}>
{{range .Columns}}
<div class="ui segment project-column"{{if .Color}} style="background: {{.Color}} !important; color: {{ContrastColor .Color}} !important"{{end}} data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}">
<div class="project-column"{{if .Color}} style="background: {{.Color}} !important; color: {{ContrastColor .Color}} !important"{{end}} data-id="{{.ID}}" data-sorting="{{.Sorting}}" data-url="{{$.Link}}/{{.ID}}">
<div class="project-column-header{{if $canWriteProject}} tw-cursor-grab{{end}}">
<div class="ui circular label project-column-issue-count">
{{.NumIssues ctx}}

View File

@ -1,6 +1,6 @@
{{range .RecentlyPushedNewBranches}}
<div class="ui positive message tw-flex tw-items-center">
<div class="tw-flex-1">
<div class="ui positive message tw-flex tw-items-center tw-gap-2">
<div class="tw-flex-1 tw-break-anywhere">
{{$timeSince := TimeSince .CommitTime.AsTime ctx.Locale}}
{{$branchLink := HTMLFormat `<a href="%s">%s</a>` .BranchLink .BranchDisplayName}}
{{ctx.Locale.Tr "repo.pulls.recently_pushed_new_branches" $branchLink $timeSince}}

View File

@ -18178,7 +18178,37 @@
"x-go-name": "IsPrivate"
},
"op_type": {
"description": "the type of action",
"type": "string",
"enum": [
"create_repo",
"rename_repo",
"star_repo",
"watch_repo",
"commit_repo",
"create_issue",
"create_pull_request",
"transfer_repo",
"push_tag",
"comment_issue",
"merge_pull_request",
"close_issue",
"reopen_issue",
"close_pull_request",
"reopen_pull_request",
"delete_tag",
"delete_branch",
"mirror_sync_push",
"mirror_sync_create",
"mirror_sync_delete",
"approve_pull_request",
"reject_pull_request",
"comment_pull",
"publish_release",
"pull_review_dismissed",
"pull_request_ready_for_review",
"auto_merge_pull_request"
],
"x-go-name": "OpType"
},
"ref_name": {

View File

@ -44,14 +44,14 @@
{{end}}
</div>
<a class="notifications-link tw-flex tw-flex-1 tw-flex-col silenced" href="{{.Link ctx}}">
<div class="notifications-top-row tw-text-13">
<div class="notifications-top-row tw-text-13 tw-break-anywhere">
{{.Repository.FullName}} {{if .Issue}}<span class="text light-3">#{{.Issue.Index}}</span>{{end}}
{{if eq .Status 3}}
{{svg "octicon-pin" 13 "text blue tw-mt-0.5 tw-ml-1"}}
{{end}}
</div>
<div class="notifications-bottom-row tw-text-16 tw-py-0.5">
<span class="issue-title">
<span class="issue-title tw-break-anywhere">
{{if .Issue}}
{{.Issue.Title | RenderEmoji $.Context | RenderCodeBlock}}
{{else}}

View File

@ -429,22 +429,33 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
t.Run("SearchService", func(t *testing.T) {
cases := []struct {
Query string
Skip int
Take int
ExpectedTotal int64
ExpectedResults int
Query string
Skip int
Take int
ExpectedTotal int64
ExpectedResults int
ExpectedExactMatch bool
}{
{"", 0, 0, 1, 1},
{"", 0, 10, 1, 1},
{"gitea", 0, 10, 0, 0},
{"test", 0, 10, 1, 1},
{"test", 1, 10, 1, 0},
{"", 0, 0, 4, 4, false},
{"", 0, 10, 4, 4, false},
{"gitea", 0, 10, 0, 0, false},
{"test", 0, 10, 1, 1, false},
{"test", 1, 10, 1, 0, false},
{"almost.similar", 0, 0, 3, 3, true},
}
req := NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
fakePackages := []string{
packageName,
"almost.similar.dependency",
"almost.similar",
"almost.similar.dependant",
}
for _, fakePackageName := range fakePackages {
req := NewRequestWithBody(t, "PUT", url, createPackage(fakePackageName, "1.0.99")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusCreated)
}
t.Run("v2", func(t *testing.T) {
t.Run("Search()", func(t *testing.T) {
@ -491,6 +502,63 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
}
})
t.Run("Packages()", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("substringof", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
for i, c := range cases {
req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
var result FeedResponse
decodeXML(t, resp, &result)
assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i)
assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i)
req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
AddBasicAuth(user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i)
}
})
t.Run("IdEq", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
for i, c := range cases {
if c.Query == "" {
// Ignore the `tolower(Id) eq ''` as it's unlikely to happen
continue
}
req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
AddBasicAuth(user.Name)
resp := MakeRequest(t, req, http.StatusOK)
var result FeedResponse
decodeXML(t, resp, &result)
expectedCount := 0
if c.ExpectedExactMatch {
expectedCount = 1
}
assert.Equal(t, int64(expectedCount), result.Count, "case %d: unexpected total hits", i)
assert.Len(t, result.Entries, expectedCount, "case %d: unexpected result count", i)
req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
AddBasicAuth(user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, strconv.FormatInt(int64(expectedCount), 10), resp.Body.String(), "case %d: unexpected total hits", i)
}
})
})
t.Run("Next", func(t *testing.T) {
req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='test'&$skip=0&$top=1", url)).
AddBasicAuth(user.Name)
@ -548,9 +616,11 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
})
})
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusNoContent)
for _, fakePackageName := range fakePackages {
req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, fakePackageName, "1.0.99")).
AddBasicAuth(user.Name)
MakeRequest(t, req, http.StatusNoContent)
}
})
t.Run("RegistrationService", func(t *testing.T) {

View File

@ -9,6 +9,7 @@
.project-column {
background-color: var(--color-project-column-bg) !important;
border: 1px solid var(--color-secondary) !important;
border-radius: var(--border-radius);
margin: 0 0.5rem !important;
padding: 0.5rem !important;
width: 320px;

View File

@ -35,22 +35,6 @@ Gitea's private styles use `g-` prefix.
.interact-bg:hover { background: var(--color-hover) !important; }
.interact-bg:active { background: var(--color-active) !important; }
/*
tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
do not use:
* "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
* ".hidden" class: it has been polluted by Fomantic UI in many cases
* inline style="display: none": it's difficult to tweak
* jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
only use:
* this ".tw-hidden" class
* showElem/hideElem/toggleElem functions in "utils/dom.js"
*/
.tw-hidden.tw-hidden { display: none !important; }
/* proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128 */
.tw-break-anywhere { overflow-wrap: anywhere !important; }
@media (max-width: 767.98px) {
/* double selector so it wins over .tw-flex (old .gt-df) etc */
.not-mobile.not-mobile {

View File

@ -2322,6 +2322,7 @@ tbody.commit-list {
min-height: 12em;
max-height: calc(100vh - 10.5rem);
overflow-y: auto;
tab-size: 4;
}
.comment-diff-data pre {