Skip to content

Commit

Permalink
Merge branch 'main' into bugfix/issue-23824
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny authored Apr 2, 2023
2 parents 5133af4 + 0ed62db commit e32f9c1
Show file tree
Hide file tree
Showing 38 changed files with 469 additions and 161 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ rules:
jquery/no-parse-html: [2]
jquery/no-prop: [0]
jquery/no-proxy: [2]
jquery/no-ready: [0]
jquery/no-ready: [2]
jquery/no-serialize: [2]
jquery/no-show: [2]
jquery/no-size: [2]
Expand Down
15 changes: 4 additions & 11 deletions build/update-locales.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,10 @@ fi

mv ./options/locale/locale_en-US.ini ./options/

# the "ini" library for locale has many quirks
# * `a="xx"` gets `xx` (no quote)
# * `a=x\"y` gets `x\"y` (no unescaping)
# * `a="x\"y"` gets `"x\"y"` (no unescaping, the quotes are still there)
# * `a='x\"y'` gets `x\"y` (no unescaping, no quote)
# * `a="foo` gets `"foo` (although the quote is not closed)
# * 'a=`foo`' works like single-quote
# crowdin needs the strings to be quoted correctly and doesn't like incomplete quotes
# crowdin always outputs quoted strings if there are quotes in the strings.

# this script helps to unquote the crowdin outputs for the quirky ini library
# the "ini" library for locale has many quirks, its behavior is different from Crowdin.
# see i18n_test.go for more details

# this script helps to unquote the Crowdin outputs for the quirky ini library
# * find all `key="...\"..."` lines
# * remove the leading quote
# * remove the trailing quote
Expand Down
9 changes: 8 additions & 1 deletion models/auth/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,14 @@ func UpdateSource(source *Source) error {
}
}

_, err := db.GetEngine(db.DefaultContext).ID(source.ID).AllCols().Update(source)
has, err := db.GetEngine(db.DefaultContext).Where("name=? AND id!=?", source.Name, source.ID).Exist(new(Source))
if err != nil {
return err
} else if has {
return ErrSourceAlreadyExist{source.Name}
}

_, err = db.GetEngine(db.DefaultContext).ID(source.ID).AllCols().Update(source)
if err != nil {
return err
}
Expand Down
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ var migrations = []Migration{
NewMigration("Add version column to action_runner table", v1_20.AddVersionToActionRunner),
// v249 -> v250
NewMigration("Improve Action table indices v3", v1_20.ImproveActionTableIndices),
// v250 -> v251
NewMigration("Change Container Metadata", v1_20.ChangeContainerMetadataMultiArch),
}

// GetCurrentDBVersion returns the current db version
Expand Down
135 changes: 135 additions & 0 deletions models/migrations/v1_20/v250.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package v1_20 //nolint

import (
"strings"

"code.gitea.io/gitea/modules/json"

"xorm.io/xorm"
)

func ChangeContainerMetadataMultiArch(x *xorm.Engine) error {
sess := x.NewSession()
defer sess.Close()

if err := sess.Begin(); err != nil {
return err
}

type PackageVersion struct {
ID int64 `xorm:"pk"`
MetadataJSON string `xorm:"metadata_json"`
}

type PackageBlob struct{}

// Get all relevant packages (manifest list images have a container.manifest.reference property)

var pvs []*PackageVersion
err := sess.
Table("package_version").
Select("id, metadata_json").
Where("id IN (SELECT DISTINCT ref_id FROM package_property WHERE ref_type = 0 AND name = 'container.manifest.reference')").
Find(&pvs)
if err != nil {
return err
}

type MetadataOld struct {
Type string `json:"type"`
IsTagged bool `json:"is_tagged"`
Platform string `json:"platform,omitempty"`
Description string `json:"description,omitempty"`
Authors []string `json:"authors,omitempty"`
Licenses string `json:"license,omitempty"`
ProjectURL string `json:"project_url,omitempty"`
RepositoryURL string `json:"repository_url,omitempty"`
DocumentationURL string `json:"documentation_url,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
ImageLayers []string `json:"layer_creation,omitempty"`
MultiArch map[string]string `json:"multiarch,omitempty"`
}

type Manifest struct {
Platform string `json:"platform"`
Digest string `json:"digest"`
Size int64 `json:"size"`
}

type MetadataNew struct {
Type string `json:"type"`
IsTagged bool `json:"is_tagged"`
Platform string `json:"platform,omitempty"`
Description string `json:"description,omitempty"`
Authors []string `json:"authors,omitempty"`
Licenses string `json:"license,omitempty"`
ProjectURL string `json:"project_url,omitempty"`
RepositoryURL string `json:"repository_url,omitempty"`
DocumentationURL string `json:"documentation_url,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
ImageLayers []string `json:"layer_creation,omitempty"`
Manifests []*Manifest `json:"manifests,omitempty"`
}

for _, pv := range pvs {
var old *MetadataOld
if err := json.Unmarshal([]byte(pv.MetadataJSON), &old); err != nil {
return err
}

// Calculate the size of every contained manifest

manifests := make([]*Manifest, 0, len(old.MultiArch))
for platform, digest := range old.MultiArch {
size, err := sess.
Table("package_blob").
Join("INNER", "package_file", "package_blob.id = package_file.blob_id").
Join("INNER", "package_version pv", "pv.id = package_file.version_id").
Join("INNER", "package_version pv2", "pv2.package_id = pv.package_id").
Where("pv.lower_version = ? AND pv2.id = ?", strings.ToLower(digest), pv.ID).
SumInt(new(PackageBlob), "size")
if err != nil {
return err
}

manifests = append(manifests, &Manifest{
Platform: platform,
Digest: digest,
Size: size,
})
}

// Convert to new metadata format

new := &MetadataNew{
Type: old.Type,
IsTagged: old.IsTagged,
Platform: old.Platform,
Description: old.Description,
Authors: old.Authors,
Licenses: old.Licenses,
ProjectURL: old.ProjectURL,
RepositoryURL: old.RepositoryURL,
DocumentationURL: old.DocumentationURL,
Labels: old.Labels,
ImageLayers: old.ImageLayers,
Manifests: manifests,
}

metadataJSON, err := json.Marshal(new)
if err != nil {
return err
}

pv.MetadataJSON = string(metadataJSON)

if _, err := sess.ID(pv.ID).Update(pv); err != nil {
return err
}
}

return sess.Commit()
}
8 changes: 7 additions & 1 deletion modules/packages/container/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ type Metadata struct {
DocumentationURL string `json:"documentation_url,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
ImageLayers []string `json:"layer_creation,omitempty"`
MultiArch map[string]string `json:"multiarch,omitempty"`
Manifests []*Manifest `json:"manifests,omitempty"`
}

type Manifest struct {
Platform string `json:"platform"`
Digest string `json:"digest"`
Size int64 `json:"size"`
}

// ParseImageConfig parses the metadata of an image config
Expand Down
2 changes: 1 addition & 1 deletion modules/packages/container/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestParseImageConfig(t *testing.T) {
},
metadata.Labels,
)
assert.Empty(t, metadata.MultiArch)
assert.Empty(t, metadata.Manifests)

configHelm := `{"description":"` + description + `", "home": "` + projectURL + `", "sources": ["` + repositoryURL + `"], "maintainers":[{"name":"` + author + `"}]}`

Expand Down
10 changes: 5 additions & 5 deletions modules/public/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ func AssetsHandlerFunc(opts *Options) http.HandlerFunc {
return
}

var corsSent bool
if opts.CorsHandler != nil {
var corsSent bool
opts.CorsHandler(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
corsSent = true
})).ServeHTTP(resp, req)
}
// If CORS is not sent, the response must have been written by other handlers
if !corsSent {
return
// If CORS is not sent, the response must have been written by other handlers
if !corsSent {
return
}
}

file := req.URL.Path[len(opts.Prefix):]
Expand Down
54 changes: 54 additions & 0 deletions modules/translation/i18n/i18n_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package i18n

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -75,3 +76,56 @@ c=22
assert.Equal(t, "21", ls.Tr("lang1", "b"))
assert.Equal(t, "22", ls.Tr("lang1", "c"))
}

func TestLocaleStoreQuirks(t *testing.T) {
const nl = "\n"
q := func(q1, s string, q2 ...string) string {
return q1 + s + strings.Join(q2, "")
}
testDataList := []struct {
in string
out string
hint string
}{
{` xx`, `xx`, "simple, no quote"},
{`" xx"`, ` xx`, "simple, double-quote"},
{`' xx'`, ` xx`, "simple, single-quote"},
{"` xx`", ` xx`, "simple, back-quote"},

{`x\"y`, `x\"y`, "no unescape, simple"},
{q(`"`, `x\"y`, `"`), `"x\"y"`, "unescape, double-quote"},
{q(`'`, `x\"y`, `'`), `x\"y`, "no unescape, single-quote"},
{q("`", `x\"y`, "`"), `x\"y`, "no unescape, back-quote"},

{q(`"`, `x\"y`) + nl + "b=", `"x\"y`, "half open, double-quote"},
{q(`'`, `x\"y`) + nl + "b=", `'x\"y`, "half open, single-quote"},
{q("`", `x\"y`) + nl + "b=`", `x\"y` + nl + "b=", "half open, back-quote, multi-line"},

{`x ; y`, `x ; y`, "inline comment (;)"},
{`x # y`, `x # y`, "inline comment (#)"},
{`x \; y`, `x ; y`, `inline comment (\;)`},
{`x \# y`, `x # y`, `inline comment (\#)`},
}

for _, testData := range testDataList {
ls := NewLocaleStore()
err := ls.AddLocaleByIni("lang1", "Lang1", []byte("a="+testData.in), nil)
assert.NoError(t, err, testData.hint)
assert.Equal(t, testData.out, ls.Tr("lang1", "a"), testData.hint)
assert.NoError(t, ls.Close())
}

// TODO: Crowdin needs the strings to be quoted correctly and doesn't like incomplete quotes
// and Crowdin always outputs quoted strings if there are quotes in the strings.
// So, Gitea's `key="quoted" unquoted` content shouldn't be used on Crowdin directly,
// it should be converted to `key="\"quoted\" unquoted"` first.
// TODO: We can not use UnescapeValueDoubleQuotes=true, because there are a lot of back-quotes in en-US.ini,
// then Crowdin will output:
// > key = "`x \" y`"
// Then Gitea will read a string with back-quotes, which is incorrect.
// TODO: Crowdin might generate multi-line strings, quoted by double-quote, it's not supported by LocaleStore
// LocaleStore uses back-quote for multi-line strings, it's not supported by Crowdin.
// TODO: Crowdin doesn't support back-quote as string quoter, it mainly uses double-quote
// so, the following line will be parsed as: value="`first", comment="second`" on Crowdin
// > a = `first; second`
}
8 changes: 4 additions & 4 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2140,10 +2140,10 @@ settings.dismiss_stale_approvals_desc = When new commits that change the content
settings.require_signed_commits = Require Signed Commits
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
settings.protect_branch_name_pattern = Protected Branch Name Pattern
settings.protect_protected_file_patterns = `Protected file patterns (separated using semicolon ';'):`
settings.protect_protected_file_patterns_desc = `Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
settings.protect_unprotected_file_patterns = `Unprotected file patterns (separated using semicolon ';'):`
settings.protect_unprotected_file_patterns_desc = `Unprotected files that are allowed to be changed directly if user has write access, bypassing push restriction. Multiple patterns can be separated using semicolon (';'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):"
settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
settings.protect_unprotected_file_patterns = "Unprotected file patterns (separated using semicolon ';'):"
settings.protect_unprotected_file_patterns_desc = "Unprotected files that are allowed to be changed directly if user has write access, bypassing push restriction. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."
settings.add_protected_branch = Enable protection
settings.delete_protected_branch = Disable protection
settings.update_protect_branch_success = Branch protection for rule '%s' has been updated.
Expand Down
12 changes: 8 additions & 4 deletions options/locale/locale_pt-PT.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2140,10 +2140,10 @@ settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o cont
settings.require_signed_commits=Exigir cometimentos assinados
settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis.
settings.protect_branch_name_pattern=Padrão do nome do ramo protegido
settings.protect_protected_file_patterns=`Padrões de ficheiros protegidos (separados com ponto e vírgula ' ;'):`
settings.protect_protected_file_patterns_desc=`Não é permitido alterar imediatamente ficheiros protegidos, mesmo que o utilizador tenha autorização para adicionar, editar ou eliminar ficheiros neste ramo. Podem ser usados múltiplos padrões separados por ponto e vírgula (' ;'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
settings.protect_unprotected_file_patterns=`Padrões de ficheiros desprotegidos (separados com ponto e vírgula ' ;'):`
settings.protect_unprotected_file_patterns_desc=`Ficheiros desprotegidos que é permitido alterar imediatamente se o utilizador tiver permissão de escrita, passando ao lado da restrição no envio. Podem ser usados múltiplos padrões separados por ponto e vírgula (' ;'). See <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.`
settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula ';'):
settings.protect_protected_file_patterns_desc=Ficheiros protegidos não podem ser modificados imediatamente, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula (';'). Veja a documentação em <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Padrões de ficheiros desprotegidos (separados com ponto e vírgula ';'):
settings.protect_unprotected_file_patterns_desc=Ficheiros desprotegidos que podem ser modificados imediatamente se o utilizador tiver direitos de escrita, contornando a restrição no envio. Múltiplos padrões podem ser separados com ponto e vírgula (';'). Veja a documentação em <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.add_protected_branch=Habilitar salvaguarda
settings.delete_protected_branch=Desabilitar salvaguarda
settings.update_protect_branch_success=A salvaguarda do ramo '%s' foi modificada.
Expand Down Expand Up @@ -2280,6 +2280,8 @@ diff.image.side_by_side=Lado a Lado
diff.image.swipe=Deslizar
diff.image.overlay=Sobrepor
diff.has_escaped=Esta linha tem caracteres unicode escondidos
diff.show_file_tree=Mostrar árvore de ficheiros
diff.hide_file_tree=Esconder árvore de ficheiros

releases.desc=Acompanhe as versões e as descargas do repositório.
release.releases=Lançamentos
Expand All @@ -2293,6 +2295,7 @@ release.compare=Comparar
release.edit=editar
release.ahead.commits=<strong>%d</strong> cometimentos
release.ahead.target=para %s desde este lançamento
tag.ahead.target=para o ramo %s desde esta etiqueta
release.source_code=Código fonte
release.new_subheader=Lançamentos organizam as versões do trabalho.
release.edit_subheader=Lançamentos organizam as versões do trabalho.
Expand Down Expand Up @@ -3364,6 +3367,7 @@ runners.status.idle=Parada
runners.status.active=Em funcionamento
runners.status.offline=Desconectada
runners.version=Versão
runners.reset_registration_token_success=O código de incrição do executor foi reposto com sucesso

runs.all_workflows=Todas as sequências de trabalho
runs.open_tab=%d abertas
Expand Down
Loading

0 comments on commit e32f9c1

Please sign in to comment.