Compare commits

..

No commits in common. "b942838bd486f5d3919a14a128efe22fc55c6112" and "a8e13e64da7f9dc6176365e6b9295981af5d81ea" have entirely different histories.

108 changed files with 347 additions and 1913 deletions

View File

@ -250,7 +250,7 @@ func runDump(ctx *cli.Context) error {
if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") { if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") {
log.Info("Skip dumping LFS data") log.Info("Skip dumping LFS data")
} else if err := storage.LFS.IterateObjects("", func(objPath string, object storage.Object) error { } else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
info, err := object.Stat() info, err := object.Stat()
if err != nil { if err != nil {
return err return err
@ -351,7 +351,7 @@ func runDump(ctx *cli.Context) error {
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") { if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
log.Info("Skip dumping attachment data") log.Info("Skip dumping attachment data")
} else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error { } else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
info, err := object.Stat() info, err := object.Stat()
if err != nil { if err != nil {
return err return err
@ -364,7 +364,7 @@ func runDump(ctx *cli.Context) error {
if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") { if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") {
log.Info("Skip dumping package data") log.Info("Skip dumping package data")
} else if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error { } else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error {
info, err := object.Stat() info, err := object.Stat()
if err != nil { if err != nil {
return err return err

View File

@ -2272,17 +2272,6 @@ ROUTER = console
;PULL = 300 ;PULL = 300
;GC = 60 ;GC = 60
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Git Reflog timeout in days
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[git.reflog]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ENABLED = true
;EXPIRATION = 90
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[mirror] ;[mirror]
@ -2516,8 +2505,6 @@ ROUTER = console
;LIMIT_SIZE_PYPI = -1 ;LIMIT_SIZE_PYPI = -1
;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) ;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_RUBYGEMS = -1 ;LIMIT_SIZE_RUBYGEMS = -1
;; Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_SWIFT = -1
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) ;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
;LIMIT_SIZE_VAGRANT = -1 ;LIMIT_SIZE_VAGRANT = -1

View File

@ -1093,11 +1093,6 @@ Default templates for project boards:
- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false. - `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git. - `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
## Git - Reflog settings (`git.reflog`)
- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo.
- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git.
## Git - Timeout settings (`git.timeout`) ## Git - Timeout settings (`git.timeout`)
- `DEFAULT`: **360**: Git operations default timeout seconds. - `DEFAULT`: **360**: Git operations default timeout seconds.
@ -1254,7 +1249,6 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
- `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_SWIFT`: **-1**: Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
- `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
## Mirror (`mirror`) ## Mirror (`mirror`)

View File

@ -14,17 +14,5 @@ menu:
--- ---
# 本地化 # 本地化
Gitea的本地化是通过我们的[Crowdin项目](https://crowdin.com/project/gitea)进行的。
对于对**英语翻译**的更改可以发出pull-request来更改[英语语言环境](https://github.com/go-gitea/gitea/blob/master/options/locale/locale_en-US.ini)中合适的关键字。 ## TBD
有关对**非英语**翻译的更改,请参阅上面的 Crowdin 项目。
## 支持的语言
上述 Crowdin 项目中列出的任何语言一旦翻译了 25% 或更多都将得到支持。
翻译被接受后,它将在下一次 Crowdin 同步后反映在主存储库中,这通常是在任何 PR 合并之后。
在撰写本文时,这意味着更改后的翻译可能要到 Gitea 的下一个版本才会出现。
如果使用开发版本,则在同步更改内容后,它应该会在更新后立即显示。

View File

@ -40,7 +40,6 @@ The following package managers are currently supported:
| [Pub]({{< relref "doc/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` | | [Pub]({{< relref "doc/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` |
| [PyPI]({{< relref "doc/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` | | [PyPI]({{< relref "doc/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` |
| [RubyGems]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` | | [RubyGems]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` |
| [Swift]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Swift | `swift` |
| [Vagrant]({{< relref "doc/packages/vagrant.en-us.md" >}}) | - | `vagrant` | | [Vagrant]({{< relref "doc/packages/vagrant.en-us.md" >}}) | - | `vagrant` |
**The following paragraphs only apply if Packages are not globally disabled!** **The following paragraphs only apply if Packages are not globally disabled!**

View File

@ -1,93 +0,0 @@
---
date: "2023-01-10T00:00:00+00:00"
title: "Swift Packages Repository"
slug: "packages/swift"
draft: false
toc: false
menu:
sidebar:
parent: "packages"
name: "Swift"
weight: 95
identifier: "swift"
---
# Swift Packages Repository
Publish [Swift](hhttps://www.swift.org/) packages for your user or organization.
**Table of Contents**
{{< toc >}}
## Requirements
To work with the Swift package registry, you need to use [swift](https://www.swift.org/getting-started/) to consume and a HTTP client (like `curl`) to publish packages.
## Configuring the package registry
To register the package registry and provide credentials, execute:
```shell
swift package-registry set https://gitea.example.com/api/packages/{owner}/swift -login {username} -password {password}
```
| Placeholder | Description |
| ------------ | ----------- |
| `owner` | The owner of the package. |
| `username` | Your Gitea username. |
| `password` | Your Gitea password. If you are using 2FA or OAuth use a [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}) instead of the password. |
The login is optional and only needed if the package registry is private.
## Publish a package
First you have to pack the contents of your package:
```shell
swift package archive-source
```
To publish the package perform a HTTP PUT request with the package content in the request body.
```shell --user your_username:your_password_or_token \
curl -X PUT --user {username}:{password} \
-H "Accept: application/vnd.swift.registry.v1+json" \
-F source-archive=@/path/to/package.zip \
-F metadata={metadata} \
https://gitea.example.com/api/packages/{owner}/swift/{scope}/{name}/{version}
```
| Placeholder | Description |
| ----------- | ----------- |
| `username` | Your Gitea username. |
| `password` | Your Gitea password. If you are using 2FA or OAuth use a [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}) instead of the password. |
| `owner` | The owner of the package. |
| `scope` | The package scope. |
| `name` | The package name. |
| `version` | The package version. |
| `metadata` | (Optional) The metadata of the package. JSON encoded subset of https://schema.org/SoftwareSourceCode |
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
## Install a package
To install a Swift package from the package registry, add it in the `Package.swift` file dependencies list:
```
dependencies: [
.package(id: "{scope}.{name}", from:"{version}")
]
```
| Parameter | Description |
| ----------- | ----------- |
| `scope` | The package scope. |
| `name` | The package name. |
| `version` | The package version. |
Afterwards execute the following command to install it:
```shell
swift package resolve
```

View File

@ -128,17 +128,6 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
return nil, fmt.Errorf("event %s is not a push event", run.Event) return nil, fmt.Errorf("event %s is not a push event", run.Event)
} }
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
if run.Event == webhook_module.HookEventPullRequest {
var payload api.PullRequestPayload
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
return nil, err
}
return &payload, nil
}
return nil, fmt.Errorf("event %s is not a pull request event", run.Event)
}
func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error {
_, err := db.GetEngine(ctx).ID(repo.ID). _, err := db.GetEngine(ctx).ID(repo.ID).
SetExpr("num_action_runs", SetExpr("num_action_runs",

View File

@ -24,7 +24,6 @@ import (
"code.gitea.io/gitea/modules/packages/pub" "code.gitea.io/gitea/modules/packages/pub"
"code.gitea.io/gitea/modules/packages/pypi" "code.gitea.io/gitea/modules/packages/pypi"
"code.gitea.io/gitea/modules/packages/rubygems" "code.gitea.io/gitea/modules/packages/rubygems"
"code.gitea.io/gitea/modules/packages/swift"
"code.gitea.io/gitea/modules/packages/vagrant" "code.gitea.io/gitea/modules/packages/vagrant"
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
@ -160,8 +159,6 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
metadata = &pypi.Metadata{} metadata = &pypi.Metadata{}
case TypeRubyGems: case TypeRubyGems:
metadata = &rubygems.Metadata{} metadata = &rubygems.Metadata{}
case TypeSwift:
metadata = &swift.Metadata{}
case TypeVagrant: case TypeVagrant:
metadata = &vagrant.Metadata{} metadata = &vagrant.Metadata{}
default: default:

View File

@ -44,7 +44,6 @@ const (
TypePub Type = "pub" TypePub Type = "pub"
TypePyPI Type = "pypi" TypePyPI Type = "pypi"
TypeRubyGems Type = "rubygems" TypeRubyGems Type = "rubygems"
TypeSwift Type = "swift"
TypeVagrant Type = "vagrant" TypeVagrant Type = "vagrant"
) )
@ -63,7 +62,6 @@ var TypeList = []Type{
TypePub, TypePub,
TypePyPI, TypePyPI,
TypeRubyGems, TypeRubyGems,
TypeSwift,
TypeVagrant, TypeVagrant,
} }
@ -98,8 +96,6 @@ func (pt Type) Name() string {
return "PyPI" return "PyPI"
case TypeRubyGems: case TypeRubyGems:
return "RubyGems" return "RubyGems"
case TypeSwift:
return "Swift"
case TypeVagrant: case TypeVagrant:
return "Vagrant" return "Vagrant"
} }
@ -137,8 +133,6 @@ func (pt Type) SVGName() string {
return "gitea-python" return "gitea-python"
case TypeRubyGems: case TypeRubyGems:
return "gitea-rubygems" return "gitea-rubygems"
case TypeSwift:
return "gitea-swift"
case TypeVagrant: case TypeVagrant:
return "gitea-vagrant" return "gitea-vagrant"
} }

View File

@ -62,8 +62,7 @@ func RepositoryListOfMap(repoMap map[int64]*Repository) RepositoryList {
return RepositoryList(ValuesRepository(repoMap)) return RepositoryList(ValuesRepository(repoMap))
} }
// LoadAttributes loads the attributes for the given RepositoryList func (repos RepositoryList) loadAttributes(ctx context.Context) error {
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
if len(repos) == 0 { if len(repos) == 0 {
return nil return nil
} }
@ -108,6 +107,11 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
return nil return nil
} }
// LoadAttributes loads the attributes for the given RepositoryList
func (repos RepositoryList) LoadAttributes() error {
return repos.loadAttributes(db.DefaultContext)
}
// SearchRepoOptions holds the search options // SearchRepoOptions holds the search options
type SearchRepoOptions struct { type SearchRepoOptions struct {
db.ListOptions db.ListOptions
@ -543,7 +547,7 @@ func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
} }
if loadAttributes { if loadAttributes {
if err := repos.LoadAttributes(ctx); err != nil { if err := repos.loadAttributes(ctx); err != nil {
return nil, 0, fmt.Errorf("LoadAttributes: %w", err) return nil, 0, fmt.Errorf("LoadAttributes: %w", err)
} }
} }

View File

@ -31,7 +31,7 @@ func commonCheckStorage(ctx context.Context, logger log.Logger, autofix bool, op
totalSize, orphanedSize := int64(0), int64(0) totalSize, orphanedSize := int64(0), int64(0)
var pathsToDelete []string var pathsToDelete []string
if err := opts.storer.IterateObjects("", func(p string, obj storage.Object) error { if err := opts.storer.IterateObjects(func(p string, obj storage.Object) error {
defer obj.Close() defer obj.Close()
totalCount++ totalCount++

View File

@ -201,23 +201,6 @@ func InitFull(ctx context.Context) (err error) {
return syncGitConfig() return syncGitConfig()
} }
func enableReflogs() error {
if err := configSet("core.logAllRefUpdates", "true"); err != nil {
return err
}
err := configSet("gc.reflogExpire", fmt.Sprintf("%d", setting.Git.Reflog.Expiration))
return err
}
func disableReflogs() error {
if err := configUnsetAll("core.logAllRefUpdates", "true"); err != nil {
return err
} else if err := configUnsetAll("gc.reflogExpire", ""); err != nil {
return err
}
return nil
}
// syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem) // syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem)
func syncGitConfig() (err error) { func syncGitConfig() (err error) {
if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil { if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil {
@ -241,16 +224,6 @@ func syncGitConfig() (err error) {
return err return err
} }
if setting.Git.Reflog.Enabled {
if err := enableReflogs(); err != nil {
return err
}
} else {
if err := disableReflogs(); err != nil {
return err
}
}
if CheckGitVersionAtLeast("2.10") == nil { if CheckGitVersionAtLeast("2.10") == nil {
if err := configSet("receive.advertisePushOptions", "true"); err != nil { if err := configSet("receive.advertisePushOptions", "true"); err != nil {
return err return err

View File

@ -1,214 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package swift
import (
"archive/zip"
"fmt"
"io"
"path"
"regexp"
"strings"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
"github.com/hashicorp/go-version"
)
var (
ErrMissingManifestFile = util.NewInvalidArgumentErrorf("Package.swift file is missing")
ErrManifestFileTooLarge = util.NewInvalidArgumentErrorf("Package.swift file is too large")
ErrInvalidManifestVersion = util.NewInvalidArgumentErrorf("manifest version is invalid")
manifestPattern = regexp.MustCompile(`\APackage(?:@swift-(\d+(?:\.\d+)?(?:\.\d+)?))?\.swift\z`)
toolsVersionPattern = regexp.MustCompile(`\A// swift-tools-version:(\d+(?:\.\d+)?(?:\.\d+)?)`)
)
const (
maxManifestFileSize = 128 * 1024
PropertyScope = "swift.scope"
PropertyName = "swift.name"
PropertyRepositoryURL = "swift.repository_url"
)
// Package represents a Swift package
type Package struct {
RepositoryURLs []string
Metadata *Metadata
}
// Metadata represents the metadata of a Swift package
type Metadata struct {
Description string `json:"description,omitempty"`
Keywords []string `json:"keywords,omitempty"`
RepositoryURL string `json:"repository_url,omitempty"`
License string `json:"license,omitempty"`
Author Person `json:"author,omitempty"`
Manifests map[string]*Manifest `json:"manifests,omitempty"`
}
// Manifest represents a Package.swift file
type Manifest struct {
Content string `json:"content"`
ToolsVersion string `json:"tools_version,omitempty"`
}
// https://schema.org/SoftwareSourceCode
type SoftwareSourceCode struct {
Context []string `json:"@context"`
Type string `json:"@type"`
Name string `json:"name"`
Version string `json:"version"`
Description string `json:"description,omitempty"`
Keywords []string `json:"keywords,omitempty"`
CodeRepository string `json:"codeRepository,omitempty"`
License string `json:"license,omitempty"`
Author Person `json:"author"`
ProgrammingLanguage ProgrammingLanguage `json:"programmingLanguage"`
RepositoryURLs []string `json:"repositoryURLs,omitempty"`
}
// https://schema.org/ProgrammingLanguage
type ProgrammingLanguage struct {
Type string `json:"@type"`
Name string `json:"name"`
URL string `json:"url"`
}
// https://schema.org/Person
type Person struct {
Type string `json:"@type,omitempty"`
GivenName string `json:"givenName,omitempty"`
MiddleName string `json:"middleName,omitempty"`
FamilyName string `json:"familyName,omitempty"`
}
func (p Person) String() string {
var sb strings.Builder
if p.GivenName != "" {
sb.WriteString(p.GivenName)
}
if p.MiddleName != "" {
if sb.Len() > 0 {
sb.WriteRune(' ')
}
sb.WriteString(p.MiddleName)
}
if p.FamilyName != "" {
if sb.Len() > 0 {
sb.WriteRune(' ')
}
sb.WriteString(p.FamilyName)
}
return sb.String()
}
// ParsePackage parses the Swift package upload
func ParsePackage(sr io.ReaderAt, size int64, mr io.Reader) (*Package, error) {
zr, err := zip.NewReader(sr, size)
if err != nil {
return nil, err
}
p := &Package{
Metadata: &Metadata{
Manifests: make(map[string]*Manifest),
},
}
for _, file := range zr.File {
manifestMatch := manifestPattern.FindStringSubmatch(path.Base(file.Name))
if len(manifestMatch) == 0 {
continue
}
if file.UncompressedSize64 > maxManifestFileSize {
return nil, ErrManifestFileTooLarge
}
f, err := zr.Open(file.Name)
if err != nil {
return nil, err
}
content, err := io.ReadAll(f)
if err := f.Close(); err != nil {
return nil, err
}
if err != nil {
return nil, err
}
swiftVersion := ""
if len(manifestMatch) == 2 && manifestMatch[1] != "" {
v, err := version.NewSemver(manifestMatch[1])
if err != nil {
return nil, ErrInvalidManifestVersion
}
swiftVersion = TrimmedVersionString(v)
}
manifest := &Manifest{
Content: string(content),
}
toolsMatch := toolsVersionPattern.FindStringSubmatch(manifest.Content)
if len(toolsMatch) == 2 {
v, err := version.NewSemver(toolsMatch[1])
if err != nil {
return nil, ErrInvalidManifestVersion
}
manifest.ToolsVersion = TrimmedVersionString(v)
}
p.Metadata.Manifests[swiftVersion] = manifest
}
if _, found := p.Metadata.Manifests[""]; !found {
return nil, ErrMissingManifestFile
}
if mr != nil {
var ssc *SoftwareSourceCode
if err := json.NewDecoder(mr).Decode(&ssc); err != nil {
return nil, err
}
p.Metadata.Description = ssc.Description
p.Metadata.Keywords = ssc.Keywords
p.Metadata.License = ssc.License
p.Metadata.Author = Person{
GivenName: ssc.Author.GivenName,
MiddleName: ssc.Author.MiddleName,
FamilyName: ssc.Author.FamilyName,
}
p.Metadata.RepositoryURL = ssc.CodeRepository
if !validation.IsValidURL(p.Metadata.RepositoryURL) {
p.Metadata.RepositoryURL = ""
}
p.RepositoryURLs = ssc.RepositoryURLs
}
return p, nil
}
// TrimmedVersionString returns the version string without the patch segment if it is zero
func TrimmedVersionString(v *version.Version) string {
segments := v.Segments64()
var b strings.Builder
fmt.Fprintf(&b, "%d.%d", segments[0], segments[1])
if segments[2] != 0 {
fmt.Fprintf(&b, ".%d", segments[2])
}
return b.String()
}

View File

@ -1,144 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package swift
import (
"archive/zip"
"bytes"
"strings"
"testing"
"github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
)
const (
packageName = "gitea"
packageVersion = "1.0.1"
packageDescription = "Package Description"
packageRepositoryURL = "https://gitea.io/gitea/gitea"
packageAuthor = "KN4CK3R"
packageLicense = "MIT"
)
func TestParsePackage(t *testing.T) {
createArchive := func(files map[string][]byte) *bytes.Reader {
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
for filename, content := range files {
w, _ := zw.Create(filename)
w.Write(content)
}
zw.Close()
return bytes.NewReader(buf.Bytes())
}
t.Run("MissingManifestFile", func(t *testing.T) {
data := createArchive(map[string][]byte{"dummy.txt": {}})
p, err := ParsePackage(data, data.Size(), nil)
assert.Nil(t, p)
assert.ErrorIs(t, err, ErrMissingManifestFile)
})
t.Run("ManifestFileTooLarge", func(t *testing.T) {
data := createArchive(map[string][]byte{
"Package.swift": make([]byte, maxManifestFileSize+1),
})
p, err := ParsePackage(data, data.Size(), nil)
assert.Nil(t, p)
assert.ErrorIs(t, err, ErrManifestFileTooLarge)
})
t.Run("WithoutMetadata", func(t *testing.T) {
content1 := "// swift-tools-version:5.7\n//\n// Package.swift"
content2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift"
data := createArchive(map[string][]byte{
"Package.swift": []byte(content1),
"Package@swift-5.5.swift": []byte(content2),
})
p, err := ParsePackage(data, data.Size(), nil)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.NotNil(t, p.Metadata)
assert.Empty(t, p.RepositoryURLs)
assert.Len(t, p.Metadata.Manifests, 2)
m := p.Metadata.Manifests[""]
assert.Equal(t, "5.7", m.ToolsVersion)
assert.Equal(t, content1, m.Content)
m = p.Metadata.Manifests["5.5"]
assert.Equal(t, "5.6", m.ToolsVersion)
assert.Equal(t, content2, m.Content)
})
t.Run("WithMetadata", func(t *testing.T) {
data := createArchive(map[string][]byte{
"Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"),
})
p, err := ParsePackage(
data,
data.Size(),
strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","keywords":["swift","package"],"license":"`+packageLicense+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`),
)
assert.NotNil(t, p)
assert.NoError(t, err)
assert.NotNil(t, p.Metadata)
assert.Len(t, p.Metadata.Manifests, 1)
m := p.Metadata.Manifests[""]
assert.Equal(t, "5.7", m.ToolsVersion)
assert.Equal(t, packageDescription, p.Metadata.Description)
assert.ElementsMatch(t, []string{"swift", "package"}, p.Metadata.Keywords)
assert.Equal(t, packageLicense, p.Metadata.License)
assert.Equal(t, packageAuthor, p.Metadata.Author.GivenName)
assert.Equal(t, packageRepositoryURL, p.Metadata.RepositoryURL)
assert.ElementsMatch(t, []string{packageRepositoryURL}, p.RepositoryURLs)
})
}
func TestTrimmedVersionString(t *testing.T) {
cases := []struct {
Version *version.Version
Expected string
}{
{
Version: version.Must(version.NewVersion("1")),
Expected: "1.0",
},
{
Version: version.Must(version.NewVersion("1.0")),
Expected: "1.0",
},
{
Version: version.Must(version.NewVersion("1.0.0")),
Expected: "1.0",
},
{
Version: version.Must(version.NewVersion("1.0.1")),
Expected: "1.0.1",
},
{
Version: version.Must(version.NewVersion("1.0+meta")),
Expected: "1.0",
},
{
Version: version.Must(version.NewVersion("1.0.0+meta")),
Expected: "1.0",
},
{
Version: version.Must(version.NewVersion("1.0.1+meta")),
Expected: "1.0.1",
},
}
for _, c := range cases {
assert.Equal(t, c.Expected, TrimmedVersionString(c.Version))
}
}

View File

@ -12,13 +12,9 @@ import (
// Git settings // Git settings
var Git = struct { var Git = struct {
Path string Path string
HomePath string HomePath string
DisableDiffHighlight bool DisableDiffHighlight bool
Reflog struct {
Enabled bool
Expiration int
} `ini:"git.reflog"`
MaxGitDiffLines int MaxGitDiffLines int
MaxGitDiffLineCharacters int MaxGitDiffLineCharacters int
MaxGitDiffFiles int MaxGitDiffFiles int
@ -41,13 +37,6 @@ var Git = struct {
GC int `ini:"GC"` GC int `ini:"GC"`
} `ini:"git.timeout"` } `ini:"git.timeout"`
}{ }{
Reflog: struct {
Enabled bool
Expiration int
}{
Enabled: true,
Expiration: 90,
},
DisableDiffHighlight: false, DisableDiffHighlight: false,
MaxGitDiffLines: 1000, MaxGitDiffLines: 1000,
MaxGitDiffLineCharacters: 5000, MaxGitDiffLineCharacters: 5000,

View File

@ -39,7 +39,6 @@ var (
LimitSizePub int64 LimitSizePub int64
LimitSizePyPI int64 LimitSizePyPI int64
LimitSizeRubyGems int64 LimitSizeRubyGems int64
LimitSizeSwift int64
LimitSizeVagrant int64 LimitSizeVagrant int64
}{ }{
Enabled: true, Enabled: true,
@ -82,7 +81,6 @@ func loadPackagesFrom(rootCfg ConfigProvider) {
Packages.LimitSizePub = mustBytes(sec, "LIMIT_SIZE_PUB") Packages.LimitSizePub = mustBytes(sec, "LIMIT_SIZE_PUB")
Packages.LimitSizePyPI = mustBytes(sec, "LIMIT_SIZE_PYPI") Packages.LimitSizePyPI = mustBytes(sec, "LIMIT_SIZE_PYPI")
Packages.LimitSizeRubyGems = mustBytes(sec, "LIMIT_SIZE_RUBYGEMS") Packages.LimitSizeRubyGems = mustBytes(sec, "LIMIT_SIZE_RUBYGEMS")
Packages.LimitSizeSwift = mustBytes(sec, "LIMIT_SIZE_SWIFT")
Packages.LimitSizeVagrant = mustBytes(sec, "LIMIT_SIZE_VAGRANT") Packages.LimitSizeVagrant = mustBytes(sec, "LIMIT_SIZE_VAGRANT")
} }

View File

@ -90,6 +90,6 @@ func (s discardStorage) URL(_, _ string) (*url.URL, error) {
return nil, fmt.Errorf("%s", s) return nil, fmt.Errorf("%s", s)
} }
func (s discardStorage) IterateObjects(_ string, _ func(string, Object) error) error { func (s discardStorage) IterateObjects(_ func(string, Object) error) error {
return fmt.Errorf("%s", s) return fmt.Errorf("%s", s)
} }

View File

@ -42,7 +42,7 @@ func Test_discardStorage(t *testing.T) {
assert.Errorf(t, err, string(tt)) assert.Errorf(t, err, string(tt))
} }
{ {
err := tt.IterateObjects("", func(_ string, _ Object) error { return nil }) err := tt.IterateObjects(func(_ string, _ Object) error { return nil })
assert.Error(t, err, string(tt)) assert.Error(t, err, string(tt))
} }
}) })

View File

@ -127,12 +127,8 @@ func (l *LocalStorage) URL(path, name string) (*url.URL, error) {
} }
// IterateObjects iterates across the objects in the local storage // IterateObjects iterates across the objects in the local storage
func (l *LocalStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error { func (l *LocalStorage) IterateObjects(fn func(path string, obj Object) error) error {
dir := l.dir return filepath.WalkDir(l.dir, func(path string, d os.DirEntry, err error) error {
if prefix != "" {
dir = filepath.Join(l.dir, util.CleanPath(prefix))
}
return filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if err != nil { if err != nil {
return err return err
} }

View File

@ -4,10 +4,6 @@
package storage package storage
import ( import (
"bytes"
"context"
"os"
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -54,41 +50,3 @@ func TestBuildLocalPath(t *testing.T) {
}) })
} }
} }
func TestLocalStorageIterator(t *testing.T) {
dir := filepath.Join(os.TempDir(), "TestLocalStorageIteratorTestDir")
l, err := NewLocalStorage(context.Background(), LocalStorageConfig{Path: dir})
assert.NoError(t, err)
testFiles := [][]string{
{"a/1.txt", "a1"},
{"/a/1.txt", "aa1"}, // same as above, but with leading slash that will be trim
{"b/1.txt", "b1"},
{"b/2.txt", "b2"},
{"b/3.txt", "b3"},
{"b/x 4.txt", "bx4"},
}
for _, f := range testFiles {
_, err = l.Save(f[0], bytes.NewBufferString(f[1]), -1)
assert.NoError(t, err)
}
expectedList := map[string][]string{
"a": {"a/1.txt"},
"b": {"b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"/": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"a/b/../../a": {"a/1.txt"},
}
for dir, expected := range expectedList {
count := 0
err = l.IterateObjects(dir, func(path string, f Object) error {
defer f.Close()
assert.Contains(t, expected, path)
count++
return nil
})
assert.NoError(t, err)
assert.Equal(t, count, len(expected))
}
}

View File

@ -209,18 +209,12 @@ func (m *MinioStorage) URL(path, name string) (*url.URL, error) {
} }
// IterateObjects iterates across the objects in the miniostorage // IterateObjects iterates across the objects in the miniostorage
func (m *MinioStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error { func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) error {
opts := minio.GetObjectOptions{} opts := minio.GetObjectOptions{}
lobjectCtx, cancel := context.WithCancel(m.ctx) lobjectCtx, cancel := context.WithCancel(m.ctx)
defer cancel() defer cancel()
basePath := m.basePath
if prefix != "" {
basePath = m.buildMinioPath(prefix)
}
for mObjInfo := range m.client.ListObjects(lobjectCtx, m.bucket, minio.ListObjectsOptions{ for mObjInfo := range m.client.ListObjects(lobjectCtx, m.bucket, minio.ListObjectsOptions{
Prefix: basePath, Prefix: m.basePath,
Recursive: true, Recursive: true,
}) { }) {
object, err := m.client.GetObject(lobjectCtx, m.bucket, mObjInfo.Key, opts) object, err := m.client.GetObject(lobjectCtx, m.bucket, mObjInfo.Key, opts)
@ -229,7 +223,7 @@ func (m *MinioStorage) IterateObjects(prefix string, fn func(path string, obj Ob
} }
if err := func(object *minio.Object, fn func(path string, obj Object) error) error { if err := func(object *minio.Object, fn func(path string, obj Object) error) error {
defer object.Close() defer object.Close()
return fn(strings.TrimPrefix(mObjInfo.Key, basePath), &minioObject{object}) return fn(strings.TrimPrefix(mObjInfo.Key, m.basePath), &minioObject{object})
}(object, fn); err != nil { }(object, fn); err != nil {
return convertMinioErr(err) return convertMinioErr(err)
} }

View File

@ -65,7 +65,7 @@ type ObjectStorage interface {
Stat(path string) (os.FileInfo, error) Stat(path string) (os.FileInfo, error)
Delete(path string) error Delete(path string) error
URL(path, name string) (*url.URL, error) URL(path, name string) (*url.URL, error)
IterateObjects(path string, iterator func(path string, obj Object) error) error IterateObjects(func(path string, obj Object) error) error
} }
// Copy copies a file from source ObjectStorage to dest ObjectStorage // Copy copies a file from source ObjectStorage to dest ObjectStorage
@ -87,7 +87,7 @@ func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, sr
// Clean delete all the objects in this storage // Clean delete all the objects in this storage
func Clean(storage ObjectStorage) error { func Clean(storage ObjectStorage) error {
return storage.IterateObjects("", func(path string, obj Object) error { return storage.IterateObjects(func(path string, obj Object) error {
_ = obj.Close() _ = obj.Close()
return storage.Delete(path) return storage.Delete(path)
}) })

View File

@ -2934,8 +2934,6 @@ config.git_disable_diff_highlight = Disable Diff Syntax Highlight
config.git_max_diff_lines = Max Diff Lines (for a single file) config.git_max_diff_lines = Max Diff Lines (for a single file)
config.git_max_diff_line_characters = Max Diff Characters (for a single line) config.git_max_diff_line_characters = Max Diff Characters (for a single line)
config.git_max_diff_files = Max Diff Files (to be shown) config.git_max_diff_files = Max Diff Files (to be shown)
config.git_enable_reflogs = Enable Reflogs
config.git_reflog_expiry_time = Expiry Time
config.git_gc_args = GC Arguments config.git_gc_args = GC Arguments
config.git_migrate_timeout = Migration Timeout config.git_migrate_timeout = Migration Timeout
config.git_mirror_timeout = Mirror Update Timeout config.git_mirror_timeout = Mirror Update Timeout
@ -3239,10 +3237,6 @@ rubygems.dependencies.development = Development Dependencies
rubygems.required.ruby = Requires Ruby version rubygems.required.ruby = Requires Ruby version
rubygems.required.rubygems = Requires RubyGem version rubygems.required.rubygems = Requires RubyGem version
rubygems.documentation = For more information on the RubyGems registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">the documentation</a>. rubygems.documentation = For more information on the RubyGems registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">the documentation</a>.
swift.registry = Setup this registry from the command line:
swift.install = Add the package in your <code>Package.swift</code> file:
swift.install2 = and run the following command:
swift.documentation = For more information on the Swift registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/swift/">the documentation</a>.
vagrant.install = To add a Vagrant box, run the following command: vagrant.install = To add a Vagrant box, run the following command:
vagrant.documentation = For more information on the Vagrant registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/vagrant/">the documentation</a>. vagrant.documentation = For more information on the Vagrant registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/vagrant/">the documentation</a>.
settings.link = Link this package to a repository settings.link = Link this package to a repository

View File

@ -247,7 +247,6 @@ default_enable_timetracking_popup=Habilitar o cronômetro para novos repositóri
no_reply_address=Domínio de e-mail oculto no_reply_address=Domínio de e-mail oculto
no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'. no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'.
password_algorithm=Algoritmo Hash de Senha password_algorithm=Algoritmo Hash de Senha
invalid_password_algorithm=Algoritmo de hash de senha inválido
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos. password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos.
enable_update_checker=Habilitar Verificador de Atualizações enable_update_checker=Habilitar Verificador de Atualizações
enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io. enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io.
@ -285,7 +284,6 @@ users=Usuários
organizations=Organizações organizations=Organizações
search=Pesquisar search=Pesquisar
code=Código code=Código
search.type.tooltip=Tipo de pesquisa
search.fuzzy=Similar search.fuzzy=Similar
search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Correspondência search.match=Correspondência
@ -821,7 +819,6 @@ remove_account_link=Remover conta vinculada
remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar? remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar?
remove_account_link_success=A conta vinculada foi removida. remove_account_link_success=A conta vinculada foi removida.
hooks.desc=Adicionar webhooks que serão acionados para <strong>todos os repositórios</strong> pertencentes a este usuário.
orgs_none=Você não é membro de nenhuma organização. orgs_none=Você não é membro de nenhuma organização.
repos_none=Você não possui nenhum repositório repos_none=Você não possui nenhum repositório
@ -1234,7 +1231,6 @@ projects.column.color=Colorido
projects.open=Abrir projects.open=Abrir
projects.close=Fechar projects.close=Fechar
projects.column.assigned_to=Atribuído a projects.column.assigned_to=Atribuído a
projects.card_type.desc=Pré-visualizações de Cards
projects.card_type.images_and_text=Imagens e Texto projects.card_type.images_and_text=Imagens e Texto
projects.card_type.text_only=Somente texto projects.card_type.text_only=Somente texto
@ -1403,7 +1399,6 @@ issues.label_title=Nome da etiqueta
issues.label_description=Descrição da etiqueta issues.label_description=Descrição da etiqueta
issues.label_color=Cor da etiqueta issues.label_color=Cor da etiqueta
issues.label_exclusive=Exclusivo issues.label_exclusive=Exclusivo
issues.label_exclusive_desc=Nomeie o rótulo <code>escopo/item</code> para torná-lo mutuamente exclusivo com outros rótulos do <code>escopo/</code>.
issues.label_exclusive_warning=Quaisquer rótulos com escopo conflitantes serão removidos ao editar os rótulos de uma issue ou pull request. issues.label_exclusive_warning=Quaisquer rótulos com escopo conflitantes serão removidos ao editar os rótulos de uma issue ou pull request.
issues.label_count=%d etiquetas issues.label_count=%d etiquetas
issues.label_open_issues=%d issues abertas issues.label_open_issues=%d issues abertas
@ -1660,7 +1655,6 @@ pulls.merge_instruction_hint=`Você também pode ver as <a class="show-instructi
pulls.merge_instruction_step1_desc=No repositório do seu projeto, crie um novo branch e teste as alterações. pulls.merge_instruction_step1_desc=No repositório do seu projeto, crie um novo branch e teste as alterações.
pulls.merge_instruction_step2_desc=Faça merge das alterações e atualize no Gitea. pulls.merge_instruction_step2_desc=Faça merge das alterações e atualize no Gitea.
pulls.clear_merge_message=Limpar mensagem do merge pulls.clear_merge_message=Limpar mensagem do merge
pulls.clear_merge_message_hint=Limpar a mensagem de merge só irá remover o conteúdo da mensagem de commit e manter trailers git gerados, como "Co-Authored-By …".
pulls.auto_merge_button_when_succeed=(Quando a verificação for bem-sucedida) pulls.auto_merge_button_when_succeed=(Quando a verificação for bem-sucedida)
pulls.auto_merge_when_succeed=Mesclar automaticamente quando todas as verificações forem bem sucedidas pulls.auto_merge_when_succeed=Mesclar automaticamente quando todas as verificações forem bem sucedidas
@ -1816,7 +1810,6 @@ activity.git_stats_deletion_n=%d exclusões
search=Pesquisar search=Pesquisar
search.search_repo=Pesquisar no repositório... search.search_repo=Pesquisar no repositório...
search.type.tooltip=Tipo de pesquisa
search.fuzzy=Aproximada search.fuzzy=Aproximada
search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Corresponde search.match=Corresponde
@ -2051,7 +2044,6 @@ settings.event_package_desc=Pacote criado ou excluído em um repositório.
settings.branch_filter=Filtro de branch settings.branch_filter=Filtro de branch
settings.branch_filter_desc=Lista dos branches a serem considerados nos eventos push, criação de branch e exclusão de branch, especificados como padrão glob. Se estiver vazio ou for <code>*</code>, eventos para todos os branches serão relatados. Veja <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentação da sintaxe. Exemplos: <code>master</code>, <code>{master,release*}</code>. settings.branch_filter_desc=Lista dos branches a serem considerados nos eventos push, criação de branch e exclusão de branch, especificados como padrão glob. Se estiver vazio ou for <code>*</code>, eventos para todos os branches serão relatados. Veja <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentação da sintaxe. Exemplos: <code>master</code>, <code>{master,release*}</code>.
settings.authorization_header=Header de Autorização settings.authorization_header=Header de Autorização
settings.authorization_header_desc=Será incluído como header de autorização para solicitações quando estiver presente. Exemplos: %s.
settings.active=Ativo settings.active=Ativo
settings.active_helper=Informações sobre eventos disparados serão enviadas para esta URL do webhook. settings.active_helper=Informações sobre eventos disparados serão enviadas para esta URL do webhook.
settings.add_hook_success=O webhook foi adicionado. settings.add_hook_success=O webhook foi adicionado.
@ -2132,7 +2124,6 @@ settings.dismiss_stale_approvals=Descartar aprovações obsoletas
settings.dismiss_stale_approvals_desc=Quando novos commits que mudam o conteúdo do pull request são enviados para o branch, as antigas aprovações serão descartadas. settings.dismiss_stale_approvals_desc=Quando novos commits que mudam o conteúdo do pull request são enviados para o branch, as antigas aprovações serão descartadas.
settings.require_signed_commits=Exibir commits assinados settings.require_signed_commits=Exibir commits assinados
settings.require_signed_commits_desc=Rejeitar pushes para este branch se não estiverem assinados ou não forem validáveis. settings.require_signed_commits_desc=Rejeitar pushes para este branch se não estiverem assinados ou não forem validáveis.
settings.protect_branch_name_pattern=Padrão de Nome de Branch Protegida
settings.protect_protected_file_patterns=Padrões de arquivos protegidos (separados usando ponto e vírgula '\;'): settings.protect_protected_file_patterns=Padrões de arquivos protegidos (separados usando ponto e vírgula '\;'):
settings.protect_protected_file_patterns_desc=Arquivos protegidos que não têm permissão para serem alterados diretamente, mesmo se o usuário tiver permissão para adicionar, editar ou apagar arquivos neste branch. Vários padrões podem ser separados usando ponto e vírgula ('\;'). Veja <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentação para sintaxe de padrões. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>. settings.protect_protected_file_patterns_desc=Arquivos protegidos que não têm permissão para serem alterados diretamente, mesmo se o usuário tiver permissão para adicionar, editar ou apagar arquivos neste branch. Vários padrões podem ser separados usando ponto e vírgula ('\;'). Veja <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentação para sintaxe de padrões. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Padrões de arquivos desprotegidos (separados usando ponto e vírgula '\;'): settings.protect_unprotected_file_patterns=Padrões de arquivos desprotegidos (separados usando ponto e vírgula '\;'):
@ -2141,7 +2132,6 @@ settings.add_protected_branch=Habilitar proteção
settings.delete_protected_branch=Desabilitar proteção settings.delete_protected_branch=Desabilitar proteção
settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada. settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada.
settings.remove_protected_branch_success=Proteção do branch '%s' foi desabilitada. settings.remove_protected_branch_success=Proteção do branch '%s' foi desabilitada.
settings.remove_protected_branch_failed=Removendo regra de proteção de branch '%s' falhou.
settings.protected_branch_deletion=Desabilitar proteção de branch settings.protected_branch_deletion=Desabilitar proteção de branch
settings.protected_branch_deletion_desc=Desabilitar a proteção de branch permite que os usuários com permissão de escrita realizem push. Continuar? settings.protected_branch_deletion_desc=Desabilitar a proteção de branch permite que os usuários com permissão de escrita realizem push. Continuar?
settings.block_rejected_reviews=Bloquear merge em revisões rejeitadas settings.block_rejected_reviews=Bloquear merge em revisões rejeitadas
@ -2156,8 +2146,6 @@ settings.default_merge_style_desc=Estilo de merge padrão para pull requests:
settings.choose_branch=Escolha um branch... settings.choose_branch=Escolha um branch...
settings.no_protected_branch=Não há branches protegidos. settings.no_protected_branch=Não há branches protegidos.
settings.edit_protected_branch=Editar settings.edit_protected_branch=Editar
settings.protected_branch_required_rule_name=Nome da regra é obrigatório
settings.protected_branch_duplicate_rule_name=Regra com nome duplicado
settings.protected_branch_required_approvals_min=Aprovações necessárias não podem ser negativas. settings.protected_branch_required_approvals_min=Aprovações necessárias não podem ser negativas.
settings.tags=Tags settings.tags=Tags
settings.tags.protection=Proteção das Tags settings.tags.protection=Proteção das Tags
@ -2290,8 +2278,6 @@ release.edit_subheader=Lançamentos organizam versões do projeto.
release.tag_name=Nome da tag release.tag_name=Nome da tag
release.target=Destino release.target=Destino
release.tag_helper=Escolha uma tag existente, ou crie uma nova tag. release.tag_helper=Escolha uma tag existente, ou crie uma nova tag.
release.tag_helper_new=Nova tag. Esta tag será criada a partir do alvo.
release.tag_helper_existing=Tag existente.
release.title=Título release.title=Título
release.content=Conteúdo release.content=Conteúdo
release.prerelease_desc=Marcar como pré-lançamento release.prerelease_desc=Marcar como pré-lançamento
@ -2584,10 +2570,6 @@ dashboard.delete_old_actions=Excluir todas as ações antigas do banco de dados
dashboard.delete_old_actions.started=A exclusão de todas as ações antigas do banco de dados foi iniciada. dashboard.delete_old_actions.started=A exclusão de todas as ações antigas do banco de dados foi iniciada.
dashboard.update_checker=Verificador de atualização dashboard.update_checker=Verificador de atualização
dashboard.delete_old_system_notices=Excluir todos os avisos de sistema antigos do banco de dados dashboard.delete_old_system_notices=Excluir todos os avisos de sistema antigos do banco de dados
dashboard.gc_lfs=Coletar lixos dos meta-objetos LFS
dashboard.stop_zombie_tasks=Parar tarefas zumbi
dashboard.stop_endless_tasks=Parar tarefas infinitas
dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados
users.user_manage_panel=Gerenciamento de conta de usuário users.user_manage_panel=Gerenciamento de conta de usuário
users.new_account=Criar conta de usuário users.new_account=Criar conta de usuário
@ -2676,7 +2658,6 @@ repos.size=Tamanho
packages.package_manage_panel=Gerenciamento de Pacotes packages.package_manage_panel=Gerenciamento de Pacotes
packages.total_size=Tamanho Total: %s packages.total_size=Tamanho Total: %s
packages.unreferenced_size=Tamanho Não Referenciado: %s
packages.owner=Proprietário packages.owner=Proprietário
packages.creator=Criador packages.creator=Criador
packages.name=Nome packages.name=Nome
@ -2770,8 +2751,6 @@ auths.oauth2_required_claim_value_helper=Defina este valor para permitir o login
auths.oauth2_group_claim_name=Nome do claim que fornece os nomes dos grupos para esta fonte. (Opcional) auths.oauth2_group_claim_name=Nome do claim que fornece os nomes dos grupos para esta fonte. (Opcional)
auths.oauth2_admin_group=Valor do Claim de Grupo para os usuários administradores. (Opcional - requer nome do claim acima) auths.oauth2_admin_group=Valor do Claim de Grupo para os usuários administradores. (Opcional - requer nome do claim acima)
auths.oauth2_restricted_group=Valor do Claim de Grupo para os usuários restritos. (Opcional - requer nome do claim acima) auths.oauth2_restricted_group=Valor do Claim de Grupo para os usuários restritos. (Opcional - requer nome do claim acima)
auths.oauth2_map_group_to_team=Mapear grupos para Organizações. (Opcional - requer nome do claim acima)
auths.oauth2_map_group_to_team_removal=Remover usuários de equipes sincronizadas se o usuário não pertence ao grupo correspondente.
auths.enable_auto_register=Habilitar cadastro automático auths.enable_auto_register=Habilitar cadastro automático
auths.sspi_auto_create_users=Criar usuários automaticamente auths.sspi_auto_create_users=Criar usuários automaticamente
auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie automaticamente novas contas para usuários que fazem o login pela primeira vez auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie automaticamente novas contas para usuários que fazem o login pela primeira vez
@ -2812,8 +2791,6 @@ auths.still_in_used=A fonte de autenticação ainda está em uso. Converta ou ex
auths.deletion_success=A fonte de autenticação foi excluída. auths.deletion_success=A fonte de autenticação foi excluída.
auths.login_source_exist=A fonte de autenticação '%s' já existe. auths.login_source_exist=A fonte de autenticação '%s' já existe.
auths.login_source_of_type_exist=Uma fonte de autenticação deste tipo já existe. auths.login_source_of_type_exist=Uma fonte de autenticação deste tipo já existe.
auths.unable_to_initialize_openid=Não é possível inicializar o Provedor OpenID Connect: %s
auths.invalid_openIdConnectAutoDiscoveryURL=URL do Auto Discovery inválida (deve ser uma URL válida, começando com http:// ou https://)
config.server_config=Configuração do servidor config.server_config=Configuração do servidor
config.app_name=Nome do servidor config.app_name=Nome do servidor
@ -3062,7 +3039,6 @@ reopen_pull_request=`reabriu o pull request <a href="%[1]s">%[3]s#%[2]s</a>`
comment_issue=`comentou na issue <a href="%[1]s">%[3]s#%[2]s</a>` comment_issue=`comentou na issue <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`comentou no pull request <a href="%[1]s">%[3]s#%[2]s</a>` comment_pull=`comentou no pull request <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`fez merge do pull request <a href="%[1]s">%[3]s#%[2]s</a>` merge_pull_request=`fez merge do pull request <a href="%[1]s">%[3]s#%[2]s</a>`
auto_merge_pull_request=`fez merge automático do pull request <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=transferiu repositório de <code>%s</code> para <a href="%s">%s</a> transfer_repo=transferiu repositório de <code>%s</code> para <a href="%s">%s</a>
push_tag=fez push da tag <a href="%[2]s">%[3]s</a> to <a href="%[1]s">%[4]s</a> push_tag=fez push da tag <a href="%[2]s">%[3]s</a> to <a href="%[1]s">%[4]s</a>
delete_tag=excluiu tag %[2]s de <a href="%[1]s"> %[3]s</a> delete_tag=excluiu tag %[2]s de <a href="%[1]s"> %[3]s</a>
@ -3172,12 +3148,10 @@ dependency.id=ID
dependency.version=Versão dependency.version=Versão
cargo.registry=Configurar este registro no arquivo de configuração de Cargo (por exemplo <code>~/.cargo/config.toml</code>): cargo.registry=Configurar este registro no arquivo de configuração de Cargo (por exemplo <code>~/.cargo/config.toml</code>):
cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando: cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando:
cargo.documentation=Para obter mais informações sobre o registro Cargo, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">a documentação</a>.
cargo.details.repository_site=Site do Repositório cargo.details.repository_site=Site do Repositório
cargo.details.documentation_site=Site da Documentação cargo.details.documentation_site=Site da Documentação
chef.registry=Configure este registro em seu arquivo <code>~/.chef/config.rb</code>: chef.registry=Configure este registro em seu arquivo <code>~/.chef/config.rb</code>:
chef.install=Para instalar o pacote, execute o seguinte comando: chef.install=Para instalar o pacote, execute o seguinte comando:
chef.documentation=Para obter mais informações sobre o registro Chef, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">a documentação</a>.
composer.registry=Configure este registro em seu arquivo <code>~/.composer/config.json</code>: composer.registry=Configure este registro em seu arquivo <code>~/.composer/config.json</code>:
composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando:
composer.documentation=Para obter mais informações sobre o registro do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>. composer.documentation=Para obter mais informações sobre o registro do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>.
@ -3250,15 +3224,6 @@ settings.delete.description=A exclusão de um pacote é permanente e não pode s
settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza? settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza?
settings.delete.success=O pacote foi excluído. settings.delete.success=O pacote foi excluído.
settings.delete.error=Falha ao excluir o pacote. settings.delete.error=Falha ao excluir o pacote.
owner.settings.cargo.title=Índice do Registro Cargo
owner.settings.cargo.initialize=Iniciar Índice
owner.settings.cargo.initialize.description=Para usar o registro Cargo é necessário um repositório git especial. Aqui você pode (re)criá-lo com a configuração necessária.
owner.settings.cargo.initialize.error=Falha ao inicializar índice Cargo: %v
owner.settings.cargo.initialize.success=O índice Cargo foi criado com sucesso.
owner.settings.cargo.rebuild=Reconstruir Índice
owner.settings.cargo.rebuild.description=Se o índice está fora de sincronia com os pacotes Cargo, você pode reconstruí-lo aqui.
owner.settings.cargo.rebuild.error=Falha ao reconstruir índice Cargo: %v
owner.settings.cargo.rebuild.success=O índice Cargo foi reconstruído com sucesso.
owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza
owner.settings.cleanuprules.add=Adicionar Regra de Limpeza owner.settings.cleanuprules.add=Adicionar Regra de Limpeza
owner.settings.cleanuprules.edit=Editar Regra de Limpeza owner.settings.cleanuprules.edit=Editar Regra de Limpeza
@ -3267,7 +3232,6 @@ owner.settings.cleanuprules.preview=Pré-visualizar Regra de Limpeza
owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos. owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos.
owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote. owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote.
owner.settings.cleanuprules.enabled=Habilitado owner.settings.cleanuprules.enabled=Habilitado
owner.settings.cleanuprules.pattern_full_match=Aplicar padrão ao nome completo do pacote
owner.settings.cleanuprules.keep.title=Versões que correspondem a estas regras são mantidas, mesmo se corresponderem a uma regra de remoção abaixo. owner.settings.cleanuprules.keep.title=Versões que correspondem a estas regras são mantidas, mesmo se corresponderem a uma regra de remoção abaixo.
owner.settings.cleanuprules.keep.count=Manter o mais recente owner.settings.cleanuprules.keep.count=Manter o mais recente
owner.settings.cleanuprules.keep.count.1=1 versão por pacote owner.settings.cleanuprules.keep.count.1=1 versão por pacote
@ -3281,7 +3245,6 @@ owner.settings.cleanuprules.success.update=Regra de limpeza foi atualizada.
owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída. owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída.
owner.settings.chef.title=Registro Chef owner.settings.chef.title=Registro Chef
owner.settings.chef.keypair=Gerar par de chaves owner.settings.chef.keypair=Gerar par de chaves
owner.settings.chef.keypair.description=Gerar um par de chaves usado para autenticar no registro Chef. A chave anterior não pode ser usada depois.
[secrets] [secrets]
secrets=Segredos secrets=Segredos
@ -3290,8 +3253,6 @@ none=Não há segredos ainda.
value=Valor value=Valor
name=Nome name=Nome
creation=Adicionar Segredo creation=Adicionar Segredo
creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), não pode começar com GITEA_ ou GITHUB_
creation.value_placeholder=Insira qualquer conteúdo. Espaços em branco no início e no fim serão omitidos.
creation.success=O segredo '%s' foi adicionado. creation.success=O segredo '%s' foi adicionado.
creation.failed=Falha ao adicionar segredo. creation.failed=Falha ao adicionar segredo.
deletion=Excluir segredo deletion=Excluir segredo
@ -3313,10 +3274,6 @@ status.cancelled=Cancelado
status.skipped=Ignorado status.skipped=Ignorado
status.blocked=Bloqueado status.blocked=Bloqueado
runners=Runners
runners.runner_manage_panel=Gerenciamento de Runners
runners.new=Criar novo Runner
runners.new_notice=Como iniciar um runner
runners.status=Status runners.status=Status
runners.id=ID runners.id=ID
runners.name=Nome runners.name=Nome
@ -3324,36 +3281,21 @@ runners.owner_type=Tipo
runners.description=Descrição runners.description=Descrição
runners.labels=Rótulos runners.labels=Rótulos
runners.last_online=Última Vez Online runners.last_online=Última Vez Online
runners.agent_labels=Etiquetas do Agente
runners.custom_labels=Etiquetas Personalizadas runners.custom_labels=Etiquetas Personalizadas
runners.custom_labels_helper=Etiquetas personalizadas são etiquetas que são adicionadas manualmente por um administrador. Separe as etiquetas com vírgula. Espaço em branco no começo ou no final de cada etiqueta é ignorado. runners.custom_labels_helper=Etiquetas personalizadas são etiquetas que são adicionadas manualmente por um administrador. Separe as etiquetas com vírgula. Espaço em branco no começo ou no final de cada etiqueta é ignorado.
runners.runner_title=Runner
runners.task_list=Tarefas recentes neste runner
runners.task_list.run=Executar runners.task_list.run=Executar
runners.task_list.status=Status runners.task_list.status=Status
runners.task_list.repository=Repositório runners.task_list.repository=Repositório
runners.task_list.commit=Commit runners.task_list.commit=Commit
runners.task_list.done_at=Feito em
runners.edit_runner=Editar Runner
runners.update_runner=Atualizar as Alterações runners.update_runner=Atualizar as Alterações
runners.update_runner_success=Runner atualizado com sucesso
runners.update_runner_failed=Falha ao atualizar runner
runners.delete_runner=Deletar esse runner
runners.delete_runner_success=Runner excluído com sucesso
runners.delete_runner_failed=Falha ao excluir runner
runners.delete_runner_header=Confirme para excluir este runner
runners.delete_runner_notice=Se uma tarefa estiver sendo executada neste runner, ela será encerrada e marcada como falha. Pode quebrar o workflow de construção.
runners.none=Nenhum runner disponível
runners.status.unspecified=Desconhecido runners.status.unspecified=Desconhecido
runners.status.idle=Inativo runners.status.idle=Inativo
runners.status.active=Ativo runners.status.active=Ativo
runners.status.offline=Offiline runners.status.offline=Offiline
runs.all_workflows=Todos os Workflows
runs.open_tab=%d Aberto runs.open_tab=%d Aberto
runs.closed_tab=%d Fechado runs.closed_tab=%d Fechado
runs.commit=Commit runs.commit=Commit
runs.pushed_by=Push realizado por runs.pushed_by=Push realizado por
need_approval_desc=Precisa de aprovação para executar workflowa para pull request do fork.

View File

@ -1 +0,0 @@
<svg viewBox="0 0 448 512" class="svg fontawesome-save" width="16" height="16" aria-hidden="true"><path d="m434 130-84-84a48 48 0 0 0-33.9-14H48A48 48 0 0 0 0 80v352a48 48 0 0 0 48 48h352a48 48 0 0 0 48-48V163.9a48 48 0 0 0-14-34zM224 416a64 64 0 1 1 0-128 64 64 0 0 1 0 128zm96-304.5V212a12 12 0 0 1-12 12H76a12 12 0 0 1-12-12V108a12 12 0 0 1 12-12h228.5a12 12 0 0 1 8.5 3.5l3.5 3.5a12 12 0 0 1 3.5 8.5z"/></svg>

Before

Width:  |  Height:  |  Size: 413 B

View File

@ -1 +0,0 @@
<svg xml:space="preserve" viewBox="0 0 59.5 59.5" class="svg gitea-swift" width="16" height="16" aria-hidden="true"><path fill="#F05138" d="M59.387 16.45a82.463 82.463 0 0 0-.027-1.792c-.034-1.301-.111-2.614-.343-3.9-.234-1.308-.618-2.523-1.222-3.71a12.464 12.464 0 0 0-5.452-5.452C51.156.992 49.94.609 48.635.374c-1.287-.232-2.6-.308-3.902-.343a85.714 85.714 0 0 0-1.792-.027C42.231 0 41.522 0 40.813 0H18.578c-.71 0-1.418 0-2.127.004-.598.004-1.196.01-1.793.027-.325.008-.651.02-.978.036-.978.047-1.959.133-2.924.307-.98.176-1.908.436-2.811.81A12.503 12.503 0 0 0 3.89 3.89a12.46 12.46 0 0 0-2.294 3.158C.992 8.235.61 9.45.374 10.758c-.231 1.286-.308 2.599-.343 3.9a85.767 85.767 0 0 0-.027 1.792C-.001 17.16 0 17.869 0 18.578v22.234c0 .71 0 1.419.004 2.129.004.597.01 1.194.027 1.79.035 1.302.112 2.615.343 3.902.235 1.306.618 2.522 1.222 3.71a12.457 12.457 0 0 0 5.453 5.453c1.186.603 2.401.986 3.707 1.22 1.287.232 2.6.309 3.902.344.597.016 1.195.023 1.793.026.709.005 1.418.004 2.127.004h22.235c.71 0 1.419.001 2.128-.004.598-.003 1.195-.01 1.792-.026 1.302-.035 2.615-.112 3.902-.344 1.306-.234 2.521-.617 3.708-1.221a12.461 12.461 0 0 0 5.452-5.453c.604-1.187.988-2.403 1.222-3.71.232-1.286.309-2.599.343-3.9.017-.597.023-1.194.027-1.791.005-.71.004-1.42.004-2.129V18.578c0-.71 0-1.419-.004-2.128z"/><path fill="#fff" d="m47.061 36.661-.004-.005c.066-.223.133-.446.19-.675 2.466-9.82-3.55-21.432-13.731-27.545 4.461 6.048 6.434 13.373 4.681 19.78-.156.572-.344 1.12-.552 1.653-.225-.148-.51-.316-.89-.526 0 0-10.128-6.253-21.104-17.313-.288-.29 5.853 8.777 12.822 16.14-3.283-1.842-12.434-8.5-18.227-13.802.712 1.187 1.559 2.33 2.49 3.43 4.837 6.136 11.145 13.705 18.703 19.518-5.31 3.25-12.814 3.502-20.285.003a30.646 30.646 0 0 1-5.193-3.098c3.162 5.058 8.033 9.423 13.96 11.97 7.07 3.039 14.1 2.833 19.337.05l-.004.007.079-.047c.215-.116.428-.233.637-.358 2.516-1.306 7.485-2.63 10.152 2.559.653 1.27 2.041-5.46-3.062-11.739z"/></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,50 +0,0 @@
# Gitea Package Registry
This document gives a brief overview how the package registry is organized in code.
## Structure
The package registry code is divided into multiple modules to split the functionality and make code reuse possible.
| Module | Description |
| - | - |
| `models/packages` | Common methods and models used by all registry types |
| `models/packages/<type>` | Methods used by specific registry type. There should be no need to use type specific models. |
| `modules/packages` | Common methods and types used by multiple registry types |
| `modules/packages/<type>` | Registry type specific methods and types (e.g. metadata extraction of package files) |
| `routers/api/packages` | Route definitions for all registry types |
| `routers/api/packages/<type>` | Route implementation for a specific registry type |
| `services/packages` | Helper methods used by registry types to handle common tasks like package creation and deletion in `routers` |
| `services/packages/<type>` | Registry type specific methods used by `routers` and `services` |
## Models
Every package registry implementation uses the same underlaying models:
| Model | Description |
| - | - |
| `Package` | The root of a package providing values fixed for every version (e.g. the package name) |
| `PackageVersion` | A version of a package containing metadata (e.g. the package description) |
| `PackageFile` | A file of a package describing its content (e.g. file name) |
| `PackageBlob` | The content of a file (may be shared by multiple files) |
| `PackageProperty` | Additional properties attached to `Package`, `PackageVersion` or `PackageFile` (e.g. used if metadata is needed for routing) |
The following diagram shows the relationship between the models:
```
Package <1---*> PackageVersion <1---*> PackageFile <*---1> PackageBlob
```
## Adding a new package registry type
Before adding a new package registry type have a look at the existing implementation to get an impression of how it could work.
Most registry types offer endpoints to retrieve the metadata, upload and download package files.
The upload endpoint is often the heavy part because it must validate the uploaded blob, extract metadata and create the models.
The methods to validate and extract the metadata should be added in the `modules/packages/<type>` package.
If the upload is valid the methods in `services/packages` allow to store the upload and create the corresponding models.
It depends if the registry type allows multiple files per package version which method should be called:
- `CreatePackageAndAddFile`: error if package version already exists
- `CreatePackageOrAddFileToExisting`: error if file already exists
- `AddFileToExistingPackage`: error if package version does not exist or file already exists
`services/packages` also contains helper methods to download a file or to remove a package version.
There are no helper methods for metadata endpoints because they are very type specific.

View File

@ -28,7 +28,6 @@ import (
"code.gitea.io/gitea/routers/api/packages/pub" "code.gitea.io/gitea/routers/api/packages/pub"
"code.gitea.io/gitea/routers/api/packages/pypi" "code.gitea.io/gitea/routers/api/packages/pypi"
"code.gitea.io/gitea/routers/api/packages/rubygems" "code.gitea.io/gitea/routers/api/packages/rubygems"
"code.gitea.io/gitea/routers/api/packages/swift"
"code.gitea.io/gitea/routers/api/packages/vagrant" "code.gitea.io/gitea/routers/api/packages/vagrant"
"code.gitea.io/gitea/services/auth" "code.gitea.io/gitea/services/auth"
context_service "code.gitea.io/gitea/services/context" context_service "code.gitea.io/gitea/services/context"
@ -376,41 +375,6 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
r.Delete("/yank", rubygems.DeletePackage) r.Delete("/yank", rubygems.DeletePackage)
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
}, reqPackageAccess(perm.AccessModeRead)) }, reqPackageAccess(perm.AccessModeRead))
r.Group("/swift", func() {
r.Group("/{scope}/{name}", func() {
r.Group("", func() {
r.Get("", swift.EnumeratePackageVersions)
r.Get(".json", swift.EnumeratePackageVersions)
}, swift.CheckAcceptMediaType(swift.AcceptJSON))
r.Group("/{version}", func() {
r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), swift.UploadPackageFile)
r.Get("", func(ctx *context.Context) {
// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
version := ctx.Params("version")
if strings.HasSuffix(version, ".zip") {
swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
if ctx.Written() {
return
}
ctx.SetParams("version", version[:len(version)-4])
swift.DownloadPackageFile(ctx)
} else {
swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
if ctx.Written() {
return
}
if strings.HasSuffix(version, ".json") {
ctx.SetParams("version", version[:len(version)-5])
}
swift.PackageVersionMetadata(ctx)
}
})
})
})
r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/vagrant", func() { r.Group("/vagrant", func() {
r.Group("/authenticate", func() { r.Group("/authenticate", func() {
r.Get("", vagrant.CheckAuthenticate) r.Get("", vagrant.CheckAuthenticate)

View File

@ -1,464 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package swift
import (
"errors"
"fmt"
"io"
"net/http"
"regexp"
"sort"
"strings"
packages_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
swift_module "code.gitea.io/gitea/modules/packages/swift"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/api/packages/helper"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/hashicorp/go-version"
)
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
const (
AcceptJSON = "application/vnd.swift.registry.v1+json"
AcceptSwift = "application/vnd.swift.registry.v1+swift"
AcceptZip = "application/vnd.swift.registry.v1+zip"
)
var (
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#361-package-scope
scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#362-package-name
namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
)
type headers struct {
Status int
ContentType string
Digest string
Location string
Link string
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
func setResponseHeaders(resp http.ResponseWriter, h *headers) {
if h.ContentType != "" {
resp.Header().Set("Content-Type", h.ContentType)
}
if h.Digest != "" {
resp.Header().Set("Digest", "sha256="+h.Digest)
}
if h.Location != "" {
resp.Header().Set("Location", h.Location)
}
if h.Link != "" {
resp.Header().Set("Link", h.Link)
}
resp.Header().Set("Content-Version", "1")
if h.Status != 0 {
resp.WriteHeader(h.Status)
}
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#33-error-handling
func apiError(ctx *context.Context, status int, obj interface{}) {
// https://www.rfc-editor.org/rfc/rfc7807
type Problem struct {
Status int `json:"status"`
Detail string `json:"detail"`
}
helper.LogAndProcessError(ctx, status, obj, func(message string) {
setResponseHeaders(ctx.Resp, &headers{
Status: status,
ContentType: "application/problem+json",
})
if err := json.NewEncoder(ctx.Resp).Encode(Problem{
Status: status,
Detail: message,
}); err != nil {
log.Error("JSON encode: %v", err)
}
})
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
return func(ctx *context.Context) {
accept := ctx.Req.Header.Get("Accept")
if accept != "" && accept != requiredAcceptHeader {
apiError(ctx, http.StatusBadRequest, fmt.Sprintf("Unexpected accept header. Should be '%s'.", requiredAcceptHeader))
}
}
}
func buildPackageID(scope, name string) string {
return scope + "." + name
}
type Release struct {
URL string `json:"url"`
}
type EnumeratePackageVersionsResponse struct {
Releases map[string]Release `json:"releases"`
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#41-list-package-releases
func EnumeratePackageVersions(ctx *context.Context) {
packageScope := ctx.Params("scope")
packageName := ctx.Params("name")
pvs, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(packageScope, packageName))
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
if len(pvs) == 0 {
apiError(ctx, http.StatusNotFound, nil)
return
}
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
sort.Slice(pds, func(i, j int) bool {
return pds[i].SemVer.LessThan(pds[j].SemVer)
})
baseURL := fmt.Sprintf("%sapi/packages/%s/swift/%s/%s/", setting.AppURL, ctx.Package.Owner.LowerName, packageScope, packageName)
releases := make(map[string]Release)
for _, pd := range pds {
version := pd.SemVer.String()
releases[version] = Release{
URL: baseURL + version,
}
}
setResponseHeaders(ctx.Resp, &headers{
Link: fmt.Sprintf(`<%s%s>; rel="latest-version"`, baseURL, pds[len(pds)-1].Version.Version),
})
ctx.JSON(http.StatusOK, EnumeratePackageVersionsResponse{
Releases: releases,
})
}
type Resource struct {
Name string `json:"id"`
Type string `json:"type"`
Checksum string `json:"checksum"`
}
type PackageVersionMetadataResponse struct {
ID string `json:"id"`
Version string `json:"version"`
Resources []Resource `json:"resources"`
Metadata *swift_module.SoftwareSourceCode `json:"metadata"`
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-2
func PackageVersionMetadata(ctx *context.Context) {
id := buildPackageID(ctx.Params("scope"), ctx.Params("name"))
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, id, ctx.Params("version"))
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
pd, err := packages_model.GetPackageDescriptor(ctx, pv)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
metadata := pd.Metadata.(*swift_module.Metadata)
setResponseHeaders(ctx.Resp, &headers{})
ctx.JSON(http.StatusOK, PackageVersionMetadataResponse{
ID: id,
Version: pd.Version.Version,
Resources: []Resource{
{
Name: "source-archive",
Type: "application/zip",
Checksum: pd.Files[0].Blob.HashSHA256,
},
},
Metadata: &swift_module.SoftwareSourceCode{
Context: []string{"http://schema.org/"},
Type: "SoftwareSourceCode",
Name: pd.PackageProperties.GetByName(swift_module.PropertyName),
Version: pd.Version.Version,
Description: metadata.Description,
Keywords: metadata.Keywords,
CodeRepository: metadata.RepositoryURL,
License: metadata.License,
ProgrammingLanguage: swift_module.ProgrammingLanguage{
Type: "ComputerLanguage",
Name: "Swift",
URL: "https://swift.org",
},
Author: swift_module.Person{
Type: "Person",
GivenName: metadata.Author.GivenName,
MiddleName: metadata.Author.MiddleName,
FamilyName: metadata.Author.FamilyName,
},
},
})
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#43-fetch-manifest-for-a-package-release
func DownloadManifest(ctx *context.Context) {
packageScope := ctx.Params("scope")
packageName := ctx.Params("name")
packageVersion := ctx.Params("version")
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(packageScope, packageName), packageVersion)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
pd, err := packages_model.GetPackageDescriptor(ctx, pv)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
swiftVersion := ctx.FormTrim("swift-version")
if swiftVersion != "" {
v, err := version.NewVersion(swiftVersion)
if err == nil {
swiftVersion = swift_module.TrimmedVersionString(v)
}
}
m, ok := pd.Metadata.(*swift_module.Metadata).Manifests[swiftVersion]
if !ok {
setResponseHeaders(ctx.Resp, &headers{
Status: http.StatusSeeOther,
Location: fmt.Sprintf("%sapi/packages/%s/swift/%s/%s/%s/Package.swift", setting.AppURL, ctx.Package.Owner.LowerName, packageScope, packageName, packageVersion),
})
return
}
setResponseHeaders(ctx.Resp, &headers{})
filename := "Package.swift"
if swiftVersion != "" {
filename = fmt.Sprintf("Package@swift-%s.swift", swiftVersion)
}
ctx.ServeContent(strings.NewReader(m.Content), &context.ServeHeaderOptions{
ContentType: "text/x-swift",
Filename: filename,
LastModified: pv.CreatedUnix.AsLocalTime(),
})
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-6
func UploadPackageFile(ctx *context.Context) {
packageScope := ctx.Params("scope")
packageName := ctx.Params("name")
v, err := version.NewVersion(ctx.Params("version"))
if !scopePattern.MatchString(packageScope) || !namePattern.MatchString(packageName) || err != nil {
apiError(ctx, http.StatusBadRequest, err)
return
}
packageVersion := v.Core().String()
file, _, err := ctx.Req.FormFile("source-archive")
if err != nil {
apiError(ctx, http.StatusBadRequest, err)
return
}
defer file.Close()
buf, err := packages_module.CreateHashedBufferFromReader(file, 32*1024*1024)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer buf.Close()
var mr io.Reader
metadata := ctx.Req.FormValue("metadata")
if metadata != "" {
mr = strings.NewReader(metadata)
}
pck, err := swift_module.ParsePackage(buf, buf.Size(), mr)
if err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
apiError(ctx, http.StatusBadRequest, err)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
if _, err := buf.Seek(0, io.SeekStart); err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
pv, _, err := packages_service.CreatePackageAndAddFile(
&packages_service.PackageCreationInfo{
PackageInfo: packages_service.PackageInfo{
Owner: ctx.Package.Owner,
PackageType: packages_model.TypeSwift,
Name: buildPackageID(packageScope, packageName),
Version: packageVersion,
},
SemverCompatible: true,
Creator: ctx.Doer,
Metadata: pck.Metadata,
PackageProperties: map[string]string{
swift_module.PropertyScope: packageScope,
swift_module.PropertyName: packageName,
},
},
&packages_service.PackageFileCreationInfo{
PackageFileInfo: packages_service.PackageFileInfo{
Filename: fmt.Sprintf("%s-%s.zip", packageName, packageVersion),
},
Creator: ctx.Doer,
Data: buf,
IsLead: true,
},
)
if err != nil {
switch err {
case packages_model.ErrDuplicatePackageVersion:
apiError(ctx, http.StatusConflict, err)
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
apiError(ctx, http.StatusForbidden, err)
default:
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
for _, url := range pck.RepositoryURLs {
_, err = packages_model.InsertProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, swift_module.PropertyRepositoryURL, url)
if err != nil {
log.Error("InsertProperty failed: %v", err)
}
}
setResponseHeaders(ctx.Resp, &headers{})
ctx.Status(http.StatusCreated)
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-4
func DownloadPackageFile(ctx *context.Context) {
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version"))
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
pd, err := packages_model.GetPackageDescriptor(ctx, pv)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
pf := pd.Files[0].File
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
setResponseHeaders(ctx.Resp, &headers{
Digest: pd.Files[0].Blob.HashSHA256,
})
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
ContentType: "application/zip",
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
type LookupPackageIdentifiersResponse struct {
Identifiers []string `json:"identifiers"`
}
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-5
func LookupPackageIdentifiers(ctx *context.Context) {
url := ctx.FormTrim("url")
if url == "" {
apiError(ctx, http.StatusBadRequest, nil)
return
}
pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeSwift,
Properties: map[string]string{
swift_module.PropertyRepositoryURL: url,
},
IsInternal: util.OptionalBoolFalse,
})
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
if len(pvs) == 0 {
apiError(ctx, http.StatusNotFound, nil)
return
}
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
identifiers := make([]string, 0, len(pds))
for _, pd := range pds {
identifiers = append(identifiers, pd.Package.Name)
}
setResponseHeaders(ctx.Resp, &headers{})
ctx.JSON(http.StatusOK, LookupPackageIdentifiersResponse{
Identifiers: identifiers,
})
}

View File

@ -32,8 +32,6 @@ func CreateRepo(ctx *context.APIContext) {
// responses: // responses:
// "201": // "201":
// "$ref": "#/responses/Repository" // "$ref": "#/responses/Repository"
// "400":
// "$ref": "#/responses/error"
// "403": // "403":
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
// "404": // "404":

View File

@ -305,10 +305,6 @@ func DeleteUser(ctx *context.APIContext) {
// description: username of user to delete // description: username of user to delete
// type: string // type: string
// required: true // required: true
// - name: purge
// in: query
// description: purge the user from the system completely
// type: boolean
// responses: // responses:
// "204": // "204":
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"

View File

@ -40,7 +40,7 @@ func ListPackages(ctx *context.APIContext) {
// in: query // in: query
// description: package type filter // description: package type filter
// type: string // type: string
// enum: [cargo, chef, composer, conan, conda, container, generic, helm, maven, npm, nuget, pub, pypi, rubygems, swift, vagrant] // enum: [cargo, chef, composer, conan, conda, container, generic, helm, maven, npm, nuget, pub, pypi, rubygems, vagrant]
// - name: q // - name: q
// in: query // in: query
// description: name filter // description: name filter

View File

@ -231,13 +231,6 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
if opt.AutoInit && opt.Readme == "" { if opt.AutoInit && opt.Readme == "" {
opt.Readme = "Default" opt.Readme = "Default"
} }
// If the readme template does not exist, a 400 will be returned.
if opt.AutoInit && len(opt.Readme) > 0 && !util.SliceContains(repo_module.Readmes, opt.Readme) {
ctx.Error(http.StatusBadRequest, "", fmt.Errorf("readme template does not exist, available templates: %v", repo_module.Readmes))
return
}
repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_module.CreateRepoOptions{ repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_module.CreateRepoOptions{
Name: opt.Name, Name: opt.Name,
Description: opt.Description, Description: opt.Description,
@ -290,8 +283,6 @@ func Create(ctx *context.APIContext) {
// responses: // responses:
// "201": // "201":
// "$ref": "#/responses/Repository" // "$ref": "#/responses/Repository"
// "400":
// "$ref": "#/responses/error"
// "409": // "409":
// description: The repository with the same name already exists. // description: The repository with the same name already exists.
// "422": // "422":
@ -473,8 +464,6 @@ func CreateOrgRepo(ctx *context.APIContext) {
// responses: // responses:
// "201": // "201":
// "$ref": "#/responses/Repository" // "$ref": "#/responses/Repository"
// "400":
// "$ref": "#/responses/error"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
// "403": // "403":

View File

@ -31,7 +31,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) {
return return
} }
if err := repos.LoadAttributes(ctx); err != nil { if err := repos.LoadAttributes(); err != nil {
ctx.Error(http.StatusInternalServerError, "RepositoryList.LoadAttributes", err) ctx.Error(http.StatusInternalServerError, "RepositoryList.LoadAttributes", err)
return return
} }

View File

@ -133,8 +133,6 @@ func List(ctx *context.Context) {
pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5) pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
pager.SetDefaultParams(ctx) pager.SetDefaultParams(ctx)
pager.AddParamString("workflow", workflow)
pager.AddParamString("state", ctx.FormString("state"))
ctx.Data["Page"] = pager ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, tplListActions) ctx.HTML(http.StatusOK, tplListActions)

View File

@ -117,7 +117,7 @@ func getNotifications(ctx *context.Context) {
return return
} }
notifications = notifications.Without(failures) notifications = notifications.Without(failures)
if err := repos.LoadAttributes(ctx); err != nil { if err := repos.LoadAttributes(); err != nil { // TODO
ctx.ServerError("LoadAttributes", err) ctx.ServerError("LoadAttributes", err)
return return
} }

View File

@ -21,60 +21,35 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
} }
run := job.Run run := job.Run
var ( if run.Event != webhook_module.HookEventPush {
sha string
creatorID int64
)
switch run.Event {
case webhook_module.HookEventPush:
payload, err := run.GetPushEventPayload()
if err != nil {
return fmt.Errorf("GetPushEventPayload: %w", err)
}
// Since the payload comes from json data, we should check if it's broken, or it will cause panic
switch {
case payload.Repo == nil:
return fmt.Errorf("repo is missing in event payload")
case payload.Pusher == nil:
return fmt.Errorf("pusher is missing in event payload")
case payload.HeadCommit == nil:
return fmt.Errorf("head commit is missing in event payload")
}
sha = payload.HeadCommit.ID
creatorID = payload.Pusher.ID
case webhook_module.HookEventPullRequest:
payload, err := run.GetPullRequestEventPayload()
if err != nil {
return fmt.Errorf("GetPullRequestEventPayload: %w", err)
}
switch {
case payload.PullRequest == nil:
return fmt.Errorf("pull request is missing in event payload")
case payload.PullRequest.Head == nil:
return fmt.Errorf("head of pull request is missing in event payload")
case payload.PullRequest.Head.Repository == nil:
return fmt.Errorf("head repository of pull request is missing in event payload")
case payload.PullRequest.Head.Repository.Owner == nil:
return fmt.Errorf("owner of head repository of pull request is missing in evnt payload")
}
sha = payload.PullRequest.Head.Sha
creatorID = payload.PullRequest.Head.Repository.Owner.ID
default:
return nil return nil
} }
repo := run.Repo payload, err := run.GetPushEventPayload()
ctxname := job.Name if err != nil {
state := toCommitStatus(job.Status) return fmt.Errorf("GetPushEventPayload: %w", err)
creator, err := user_model.GetUserByID(ctx, creatorID) }
// Since the payload comes from json data, we should check if it's broken, or it will cause panic
switch {
case payload.Repo == nil:
return fmt.Errorf("repo is missing in event payload")
case payload.Pusher == nil:
return fmt.Errorf("pusher is missing in event payload")
case payload.HeadCommit == nil:
return fmt.Errorf("head commit is missing in event payload")
}
creator, err := user_model.GetUserByID(ctx, payload.Pusher.ID)
if err != nil { if err != nil {
return fmt.Errorf("GetUserByID: %w", err) return fmt.Errorf("GetUserByID: %w", err)
} }
repo := run.Repo
sha := payload.HeadCommit.ID
ctxname := job.Name
state := toCommitStatus(job.Status)
if statuses, _, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptions{}); err == nil { if statuses, _, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptions{}); err == nil {
for _, v := range statuses { for _, v := range statuses {
if v.Context == ctxname { if v.Context == ctxname {
@ -90,14 +65,14 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{ if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{
Repo: repo, Repo: repo,
SHA: sha, SHA: payload.HeadCommit.ID,
Creator: creator, Creator: creator,
CommitStatus: &git_model.CommitStatus{ CommitStatus: &git_model.CommitStatus{
SHA: sha, SHA: sha,
TargetURL: run.Link(), TargetURL: run.Link(),
Description: "", Description: "",
Context: ctxname, Context: ctxname,
CreatorID: creatorID, CreatorID: payload.Pusher.ID,
State: state, State: state,
}, },
}); err != nil { }); err != nil {

View File

@ -15,7 +15,7 @@ import (
type PackageCleanupRuleForm struct { type PackageCleanupRuleForm struct {
ID int64 ID int64
Enabled bool Enabled bool
Type string `binding:"Required;In(cargo,chef,composer,conan,conda,container,generic,helm,maven,npm,nuget,pub,pypi,rubygems,swift,vagrant)"` Type string `binding:"Required;In(cargo,chef,composer,conan,conda,container,generic,helm,maven,npm,nuget,pub,pypi,rubygems,vagrant)"`
KeepCount int `binding:"In(0,1,5,10,25,50,100)"` KeepCount int `binding:"In(0,1,5,10,25,50,100)"`
KeepPattern string `binding:"RegexPattern"` KeepPattern string `binding:"RegexPattern"`
RemoveDays int `binding:"In(0,7,14,30,60,90,180)"` RemoveDays int `binding:"In(0,7,14,30,60,90,180)"`

View File

@ -361,8 +361,6 @@ func CheckSizeQuotaExceeded(ctx context.Context, doer, owner *user_model.User, p
typeSpecificSize = setting.Packages.LimitSizePyPI typeSpecificSize = setting.Packages.LimitSizePyPI
case packages_model.TypeRubyGems: case packages_model.TypeRubyGems:
typeSpecificSize = setting.Packages.LimitSizeRubyGems typeSpecificSize = setting.Packages.LimitSizeRubyGems
case packages_model.TypeSwift:
typeSpecificSize = setting.Packages.LimitSizeSwift
case packages_model.TypeVagrant: case packages_model.TypeVagrant:
typeSpecificSize = setting.Packages.LimitSizeVagrant typeSpecificSize = setting.Packages.LimitSizeVagrant
} }

View File

@ -433,7 +433,7 @@
<div class="field"> <div class="field">
<button class="ui green button">{{.locale.Tr "admin.auths.update"}}</button> <button class="ui green button">{{.locale.Tr "admin.auths.update"}}</button>
<button class="ui red button delete-button" data-url="{{$.Link}}/delete" data-id="{{.Source.ID}}">{{.locale.Tr "admin.auths.delete"}}</button> <div class="ui red button delete-button" data-url="{{$.Link}}/delete" data-id="{{.Source.ID}}">{{.locale.Tr "admin.auths.delete"}}</div>
</div> </div>
</form> </form>
</div> </div>

View File

@ -331,19 +331,7 @@
<dd>{{.Git.MaxGitDiffFiles}}</dd> <dd>{{.Git.MaxGitDiffFiles}}</dd>
<dt>{{.locale.Tr "admin.config.git_gc_args"}}</dt> <dt>{{.locale.Tr "admin.config.git_gc_args"}}</dt>
<dd><code>{{.Git.GCArgs}}</code></dd> <dd><code>{{.Git.GCArgs}}</code></dd>
<div class="ui divider"></div> <div class="ui divider"></div>
<dt>{{.locale.Tr "admin.config.git_enable_reflogs"}}</dt>
<dd>{{if .Git.Reflog.Enabled}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd>
{{if .Git.Reflog.Enabled}}
<dt>{{.locale.Tr "admin.config.git_reflog_expiry_time"}}</dt>
<dd>{{.locale.Tr "tool.days" .Git.Reflog.Expiration}}</dd>
{{end}}
<div class="ui divider"></div>
<dt>{{.locale.Tr "admin.config.git_migrate_timeout"}}</dt> <dt>{{.locale.Tr "admin.config.git_migrate_timeout"}}</dt>
<dd>{{.Git.Timeout.Migrate}} {{.locale.Tr "tool.raw_seconds"}}</dd> <dd>{{.Git.Timeout.Migrate}} {{.locale.Tr "tool.raw_seconds"}}</dd>
<dt>{{.locale.Tr "admin.config.git_mirror_timeout"}}</dt> <dt>{{.locale.Tr "admin.config.git_mirror_timeout"}}</dt>

View File

@ -78,7 +78,7 @@
{{.locale.Tr "admin.emails.change_email_header"}} {{.locale.Tr "admin.emails.change_email_header"}}
</div> </div>
<div class="content center"> <div class="content center">
<p class="center">{{.locale.Tr "admin.emails.change_email_text"}}</p> <p>{{.locale.Tr "admin.emails.change_email_text"}}</p>
<form class="ui form" id="email-action-form" action="{{AppSubUrl}}/admin/emails/activate" method="post"> <form class="ui form" id="email-action-form" action="{{AppSubUrl}}/admin/emails/activate" method="post">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
@ -93,9 +93,11 @@
<input type="hidden" id="form-primary" name="primary" value="" required> <input type="hidden" id="form-primary" name="primary" value="" required>
<input type="hidden" id="form-activate" name="activate" value="" required> <input type="hidden" id="form-activate" name="activate" value="" required>
<div class="center"> <div class="center actions">
{{template "base/delete_modal_actions" .}} <div class="ui basic cancel inverted button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui basic inverted yellow button">{{$.locale.Tr "modal.yes"}}</button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -23,7 +23,7 @@
<tr> <tr>
<td class="collapsing"> <td class="collapsing">
<div class="ui fitted checkbox" data-id="{{.ID}}"> <div class="ui fitted checkbox" data-id="{{.ID}}">
<input type="checkbox"> <input type="checkbox"> <label></label>
</div> </div>
</td> </td>
<td>{{.ID}}</td> <td>{{.ID}}</td>
@ -39,11 +39,13 @@
<tr> <tr>
<th></th> <th></th>
<th colspan="5"> <th colspan="5">
<form class="ui right" method="post" action="{{AppSubUrl}}/admin/notices/empty"> <div class="ui right">
{{.CsrfTokenHtml}} <form method="post" action="{{AppSubUrl}}/admin/notices/empty">
<button type="submit" class="ui red small button">{{.locale.Tr "admin.notices.delete_all"}}</button> {{.CsrfTokenHtml}}
</form> <button type="submit" class="ui red small button">{{.locale.Tr "admin.notices.delete_all"}}</button>
<div class="ui floating upward dropdown small button">{{/* TODO: Make this dropdown accessible */}} </form>
</div>
<div class="ui floating upward dropdown small button">
<span class="text">{{.locale.Tr "admin.notices.operations"}}</span> <span class="text">{{.locale.Tr "admin.notices.operations"}}</span>
<div class="menu"> <div class="menu">
<div class="item select action" data-action="select-all"> <div class="item select action" data-action="select-all">
@ -57,9 +59,9 @@
</div> </div>
</div> </div>
</div> </div>
<button class="ui small teal button" id="delete-selection" data-link="{{.Link}}/delete" data-redirect="{{.Link}}?page={{.Page.Paginater.Current}}"> <div class="ui small teal button" id="delete-selection" data-link="{{.Link}}/delete" data-redirect="{{.Link}}?page={{.Page.Paginater.Current}}">
{{.locale.Tr "admin.notices.delete_selected"}} {{.locale.Tr "admin.notices.delete_selected"}}
</button> </div>
</th> </th>
</tr> </tr>
</tfoot> </tfoot>

View File

@ -43,7 +43,16 @@
<input type="hidden" name="action" value="adopt"> <input type="hidden" name="action" value="adopt">
<input type="hidden" name="q" value="{{$.Keyword}}"> <input type="hidden" name="q" value="{{$.Keyword}}">
<input type="hidden" name="page" value="{{$.CurrentPage}}"> <input type="hidden" name="page" value="{{$.CurrentPage}}">
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
{{svg "octicon-trash" 16 "gt-mr-2"}}
{{$.locale.Tr "modal.no"}}
</div>
<button class="ui green basic inverted ok button">
{{svg "octicon-check" 16 "gt-mr-2"}}
{{$.locale.Tr "modal.yes"}}
</button>
</div>
</form> </form>
</div> </div>
<button class="ui button submit tiny red delete show-modal" data-modal="#delete-unadopted-modal-{{$dirI}}"><span class="icon">{{svg "octicon-x"}}</span><span class="label">{{$.locale.Tr "repo.delete_preexisting_label"}}</span></button> <button class="ui button submit tiny red delete show-modal" data-modal="#delete-unadopted-modal-{{$dirI}}"><span class="icon">{{svg "octicon-x"}}</span><span class="label">{{$.locale.Tr "repo.delete_preexisting_label"}}</span></button>
@ -61,7 +70,16 @@
<input type="hidden" name="action" value="delete"> <input type="hidden" name="action" value="delete">
<input type="hidden" name="q" value="{{$.Keyword}}"> <input type="hidden" name="q" value="{{$.Keyword}}">
<input type="hidden" name="page" value="{{$.CurrentPage}}"> <input type="hidden" name="page" value="{{$.CurrentPage}}">
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
{{svg "octicon-trash" 16 "gt-mr-2"}}
{{$.locale.Tr "modal.no"}}
</div>
<button class="ui green basic inverted ok button">
{{svg "octicon-check" 16 "gt-mr-2"}}
{{$.locale.Tr "modal.yes"}}
</button>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -151,7 +151,7 @@
<div class="field"> <div class="field">
<button class="ui green button">{{.locale.Tr "admin.users.update_profile"}}</button> <button class="ui green button">{{.locale.Tr "admin.users.update_profile"}}</button>
<button class="ui red button show-modal" data-modal="#delete-user-modal">{{.locale.Tr "admin.users.delete_account"}}</button> <div class="ui red button show-modal" data-modal="#delete-user-modal">{{.locale.Tr "admin.users.delete_account"}}</div>
</div> </div>
</form> </form>
</div> </div>
@ -189,7 +189,7 @@
<div class="field"> <div class="field">
<button class="ui green button">{{$.locale.Tr "settings.update_avatar"}}</button> <button class="ui green button">{{$.locale.Tr "settings.update_avatar"}}</button>
<a class="ui red button delete-post" data-request-url="{{.Link}}/avatar/delete" data-done-url="{{.Link}}">{{$.locale.Tr "settings.delete_current_avatar"}}</a>{{/* TODO: Convert links without href to buttons for a11y */}} <a class="ui red button delete-post" data-request-url="{{.Link}}/avatar/delete" data-done-url="{{.Link}}">{{$.locale.Tr "settings.delete_current_avatar"}}</a>
</div> </div>
</form> </form>
</div> </div>
@ -213,7 +213,16 @@
</div> </div>
<p class="help">{{.locale.Tr "admin.users.purge_help"}}</p> <p class="help">{{.locale.Tr "admin.users.purge_help"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
{{svg "octicon-x"}}
{{.locale.Tr "modal.no"}}
</div>
<button class="ui green basic inverted ok button">
{{svg "octicon-check"}}
{{.locale.Tr "modal.yes"}}
</button>
</div>
</form> </form>
</div> </div>
{{template "base/footer" .}} {{template "base/footer" .}}

View File

@ -1,10 +1,10 @@
<div class="actions"> <div class="actions">
<button class="ui red basic inverted cancel button"> <div class="ui red basic inverted cancel button">
{{svg "octicon-x"}} {{svg "octicon-x"}}
{{.locale.Tr "modal.no"}} {{.locale.Tr "modal.no"}}
</button> </div>
<button class="ui green basic inverted ok button"> <div class="ui green basic inverted ok button">
{{svg "octicon-check"}} {{svg "octicon-check"}}
{{.locale.Tr "modal.yes"}} {{.locale.Tr "modal.yes"}}
</button> </div>
</div> </div>

View File

@ -19,9 +19,9 @@
<label for="org_name">{{.locale.Tr "org.org_name_holder"}}</label> <label for="org_name">{{.locale.Tr "org.org_name_holder"}}</label>
<input id="org_name" name="org_name" value="" autocomplete="off" autofocus required> <input id="org_name" name="org_name" value="" autocomplete="off" autofocus required>
</div> </div>
<button class="ui red button delete-button" data-type="form" data-form="#delete-form"> <div class="ui red button delete-button" data-type="form" data-form="#delete-form">
{{.locale.Tr "org.settings.confirm_delete_account"}} {{.locale.Tr "org.settings.confirm_delete_account"}}
</button> </div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -11,7 +11,7 @@
</div> </div>
<div class="right floated three wide column"> <div class="right floated three wide column">
<div class="ui right"> <div class="ui right">
<button class="ui green new-label button">{{.locale.Tr "repo.issues.new_label"}}</button> <div class="ui green new-label button">{{.locale.Tr "repo.issues.new_label"}}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,40 +0,0 @@
{{if eq .PackageDescriptor.Package.Type "swift"}}
<h4 class="ui top attached header">{{.locale.Tr "packages.installation"}}</h4>
<div class="ui attached segment">
<div class="ui form">
<div class="field">
<label>{{svg "octicon-terminal"}} {{.locale.Tr "packages.swift.registry"}}</label>
<div class="markup"><pre class="code-block"><code>swift package-registry set <gitea-origin-url data-url="{{AppSubUrl}}/api/packages/{{.PackageDescriptor.Owner.Name}}/swift"></gitea-origin-url></code></pre></div>
</div>
<div class="field">
<label>{{svg "octicon-code"}} {{.locale.Tr "packages.swift.install" | Safe}}</label>
<div class="markup"><pre class="code-block"><code>dependencies: [
.package(id: "{{.PackageDescriptor.Package.Name}}", from:"{{.PackageDescriptor.Version.Version}}")
]</code></pre></div>
</div>
<div class="field">
<label>{{svg "octicon-terminal"}} {{.locale.Tr "packages.swift.install2"}}</label>
<div class="markup"><pre class="code-block"><code>swift package resolve</code></pre></div>
</div>
<div class="field">
<label>{{.locale.Tr "packages.swift.documentation" | Safe}}</label>
</div>
</div>
</div>
{{if .PackageDescriptor.Metadata.Description}}
<h4 class="ui top attached header">{{.locale.Tr "packages.about"}}</h4>
<div class="ui attached segment">
{{if .PackageDescriptor.Metadata.Description}}{{.PackageDescriptor.Metadata.Description}}{{end}}
</div>
{{end}}
{{if .PackageDescriptor.Metadata.Keywords}}
<h4 class="ui top attached header">{{.locale.Tr "packages.keywords"}}</h4>
<div class="ui attached segment">
{{range .PackageDescriptor.Metadata.Keywords}}
{{.}}
{{end}}
</div>
{{end}}
{{end}}

View File

@ -1,4 +0,0 @@
{{if eq .PackageDescriptor.Package.Type "swift"}}
{{if .PackageDescriptor.Metadata.Author.String}}<div class="item" title="{{.locale.Tr "packages.details.author"}}">{{svg "octicon-person" 16 "mr-3"}} {{.PackageDescriptor.Metadata.Author}}</div>{{end}}
{{if .PackageDescriptor.Metadata.RepositoryURL}}<div class="item">{{svg "octicon-link-external" 16 "mr-3"}} <a href="{{.PackageDescriptor.Metadata.RepositoryURL}}" target="_blank" rel="noopener noreferrer me">{{.locale.Tr "packages.details.project_site"}}</a></div>{{end}}
{{end}}

View File

@ -57,7 +57,10 @@
<form class="ui form" action="{{.Link}}" method="post"> <form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" name="action" value="delete"> <input type="hidden" name="action" value="delete">
{{template "base/delete_modal_actions" .}} <div class="text right actions">
<div class="ui cancel button">{{.locale.Tr "cancel"}}</div>
<button class="ui red button">{{.locale.Tr "ok"}}</button>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -33,7 +33,6 @@
{{template "package/content/pub" .}} {{template "package/content/pub" .}}
{{template "package/content/pypi" .}} {{template "package/content/pypi" .}}
{{template "package/content/rubygems" .}} {{template "package/content/rubygems" .}}
{{template "package/content/swift" .}}
{{template "package/content/vagrant" .}} {{template "package/content/vagrant" .}}
</div> </div>
<div class="four wide column"> <div class="four wide column">
@ -60,7 +59,6 @@
{{template "package/metadata/pub" .}} {{template "package/metadata/pub" .}}
{{template "package/metadata/pypi" .}} {{template "package/metadata/pypi" .}}
{{template "package/metadata/rubygems" .}} {{template "package/metadata/rubygems" .}}
{{template "package/metadata/swift" .}}
{{template "package/metadata/vagrant" .}} {{template "package/metadata/vagrant" .}}
<div class="item">{{svg "octicon-database" 16 "gt-mr-3"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div> <div class="item">{{svg "octicon-database" 16 "gt-mr-3"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}</div>
</div> </div>

View File

@ -84,6 +84,15 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.projects.deletion_desc"}}</p> <p>{{.locale.Tr "repo.projects.deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{end}} {{end}}

View File

@ -29,7 +29,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button data-url="{{$.Link}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button> <button data-url="{{$.Link}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button>
</div> </div>
</form> </form>
@ -127,7 +127,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button> <button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
</div> </div>
</form> </form>
@ -144,7 +144,7 @@
</label> </label>
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui primary button set-default-project-board" data-url="{{$.Link}}/{{.ID}}/default">{{$.locale.Tr "repo.projects.column.set_default"}}</button> <button class="ui primary button set-default-project-board" data-url="{{$.Link}}/{{.ID}}/default">{{$.locale.Tr "repo.projects.column.set_default"}}</button>
</div> </div>
</div> </div>
@ -158,8 +158,8 @@
{{$.locale.Tr "repo.projects.column.deletion_desc"}} {{$.locale.Tr "repo.projects.column.deletion_desc"}}
</label> </label>
</div> </div>
<div class="text right actions">{{/* TODO: convert to base/delete_modal_actions.tmpl */}} <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui red button delete-project-board" data-url="{{$.Link}}/{{.ID}}">{{$.locale.Tr "repo.projects.column.delete"}}</button> <button class="ui red button delete-project-board" data-url="{{$.Link}}/{{.ID}}">{{$.locale.Tr "repo.projects.column.delete"}}</button>
</div> </div>
</div> </div>
@ -265,6 +265,15 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.projects.deletion_desc"}}</p> <p>{{.locale.Tr "repo.projects.deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{end}} {{end}}

View File

@ -1,18 +1,14 @@
<div class="issue list"> <div class="issue list">
{{range .Runs}} {{range .Runs}}
<li class="item gt-df gt-py-3 gt-ab"> <li class="item gt-df gt-py-3">
<div class="issue-item-left gt-df"> <div class="issue-item-left gt-df">
{{template "repo/actions/status" .Status}} {{template "repo/actions/status" .Status}}
</div> </div>
<div class="issue-item-main action-item-main gt-f1 gt-fc gt-df gt-mr-3"> <div class="issue-item-main gt-f1 gt-fc gt-df">
<div class="issue-item-top-row"> <div class="issue-item-top-row">
<a class="index gt-ml-0 gt-mr-2" title="{{.Title}}" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}"> <a class="index gt-ml-0 gt-mr-2" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">
{{- .Title -}} {{- .Title -}}
</a> </a>
</div>
<div class="desc issue-item-bottom-row gt-df gt-ac gt-fw gt-my-1">
<b>{{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}</b>: {{$.locale.Tr "actions.runs.commit"}}
<a href="{{$.RepoLink}}/commit/{{.CommitSHA}}">{{ShortSha .CommitSHA}}</a>{{$.locale.Tr "actions.runs.pushed_by"}} {{.TriggerUser.GetDisplayName}}
<span class="ui label"> <span class="ui label">
{{if .RefLink}} {{if .RefLink}}
<a href="{{.RefLink}}">{{.PrettyRef}}</a> <a href="{{.RefLink}}">{{.PrettyRef}}</a>
@ -21,6 +17,10 @@
{{end}} {{end}}
</span> </span>
</div> </div>
<div class="desc issue-item-bottom-row gt-df gt-ac gt-fw gt-my-1">
<b>{{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}</b>: {{$.locale.Tr "actions.runs.commit"}}
<a href="{{$.RepoLink}}/commit/{{.CommitSHA}}">{{ShortSha .CommitSHA}}</a>&nbsp; {{$.locale.Tr "actions.runs.pushed_by"}} {{.TriggerUser.GetDisplayName | Escape}}
</div>
</div> </div>
<div class="issue-item-right"> <div class="issue-item-right">
<div>{{TimeSinceUnix .Updated $.locale}}</div> <div>{{TimeSinceUnix .Updated $.locale}}</div>

View File

@ -176,7 +176,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui green button">{{.locale.Tr "repo.branch.confirm_create_branch"}}</button> <button class="ui green button">{{.locale.Tr "repo.branch.confirm_create_branch"}}</button>
</div> </div>
</form> </form>

View File

@ -15,8 +15,8 @@
</div> </div>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui black cancel button"> <div class="ui black deny button">
{{.locale.Tr "cancel"}} {{.locale.Tr "cancel"}}
</button> </div>
</div> </div>
</div> </div>

View File

@ -96,7 +96,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui green button">{{.locale.Tr "repo.branch.confirm_create_branch"}}</button> <button class="ui green button">{{.locale.Tr "repo.branch.confirm_create_branch"}}</button>
</div> </div>
</form> </form>
@ -121,7 +121,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui green button">{{.locale.Tr "repo.tag.confirm_create_tag"}}</button> <button class="ui green button">{{.locale.Tr "repo.tag.confirm_create_tag"}}</button>
</div> </div>
</form> </form>

View File

@ -1,9 +1,6 @@
{{if eq .State "pending"}} {{if eq .State "pending"}}
{{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}} {{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}}
{{end}} {{end}}
{{if eq .State "running"}}
{{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}}
{{end}}
{{if eq .State "success"}} {{if eq .State "success"}}
{{svg "octicon-check" 18 "commit-status icon text green"}} {{svg "octicon-check" 18 "commit-status icon text green"}}
{{end}} {{end}}

View File

@ -107,8 +107,8 @@
<div class="diff-file-header-actions gt-df gt-ac"> <div class="diff-file-header-actions gt-df gt-ac">
{{if $showFileViewToggle}} {{if $showFileViewToggle}}
<div class="ui compact icon buttons"> <div class="ui compact icon buttons">
<button class="ui tiny basic button tooltip file-view-toggle" data-toggle-selector="#diff-source-{{$file.NameHash}}" data-content="{{$.locale.Tr "repo.file_view_source"}}" data-position="bottom center">{{svg "octicon-code"}}</button> <span class="ui tiny basic button tooltip file-view-toggle" data-toggle-selector="#diff-source-{{$file.NameHash}}" data-content="{{$.locale.Tr "repo.file_view_source"}}" data-position="bottom center">{{svg "octicon-code"}}</span>
<button class="ui tiny basic button tooltip file-view-toggle active" data-toggle-selector="#diff-rendered-{{$file.NameHash}}" data-content="{{$.locale.Tr "repo.file_view_rendered"}}" data-position="bottom center">{{svg "octicon-file"}}</button> <span class="ui tiny basic button tooltip file-view-toggle active" data-toggle-selector="#diff-rendered-{{$file.NameHash}}" data-content="{{$.locale.Tr "repo.file_view_rendered"}}" data-position="bottom center">{{svg "octicon-file"}}</span>
</div> </div>
{{end}} {{end}}
{{if $file.IsProtected}} {{if $file.IsProtected}}
@ -200,8 +200,8 @@
{{$.locale.Tr "loading"}} {{$.locale.Tr "loading"}}
</div> </div>
<div class="text right edit buttons"> <div class="text right edit buttons">
<button class="ui basic primary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</button> <div class="ui basic primary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</div>
<button class="ui green save button" tabindex="2">{{.locale.Tr "repo.issues.save"}}</button> <div class="ui green save button" tabindex="2">{{.locale.Tr "repo.issues.save"}}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -65,14 +65,14 @@
<p>{{.locale.Tr "repo.editor.commit_empty_file_text"}}</p> <p>{{.locale.Tr "repo.editor.commit_empty_file_text"}}</p>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui red basic cancel inverted button"> <div class="ui red basic cancel inverted button">
<i class="remove icon"></i> <i class="remove icon"></i>
{{.locale.Tr "repo.editor.cancel"}} {{.locale.Tr "repo.editor.cancel"}}
</button> </div>
<button class="ui green basic ok inverted button"> <div class="ui green basic ok inverted button">
<i class="save icon"></i> <i class="save icon"></i>
{{.locale.Tr "repo.editor.commit_changes"}} {{.locale.Tr "repo.editor.commit_changes"}}
</button> </div>
</div> </div>
</div> </div>

View File

@ -45,14 +45,14 @@
<p>{{.locale.Tr "repo.editor.commit_empty_file_text"}}</p> <p>{{.locale.Tr "repo.editor.commit_empty_file_text"}}</p>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui red basic inverted cancel button"> <div class="ui red basic cancel inverted button">
{{svg "octicon-x"}} <i class="remove icon"></i>
{{.locale.Tr "repo.editor.cancel"}} {{.locale.Tr "repo.editor.cancel"}}
</button> </div>
<button class="ui green basic inverted ok button"> <div class="ui green basic ok inverted button">
{{svg "fontawesome-save"}} <i class="save icon"></i>
{{.locale.Tr "repo.editor.commit_changes"}} {{.locale.Tr "repo.editor.commit_changes"}}
</button> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,7 +6,7 @@
{{template "repo/issue/navbar" .}} {{template "repo/issue/navbar" .}}
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} {{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
<div class="ui right"> <div class="ui right">
<button class="ui green new-label button">{{.locale.Tr "repo.issues.new_label"}}</button> <div class="ui green new-label button">{{.locale.Tr "repo.issues.new_label"}}</div>
</div> </div>
{{end}} {{end}}
</div> </div>

View File

@ -6,7 +6,16 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.issues.label_deletion_desc"}}</p> <p>{{.locale.Tr "repo.issues.label_deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
<div class="ui small edit-label modal"> <div class="ui small edit-label modal">
@ -52,13 +61,11 @@
</form> </form>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui secondary small basic cancel button"> <div class="ui secondary small basic cancel button">
{{svg "octicon-x"}}
{{.locale.Tr "cancel"}} {{.locale.Tr "cancel"}}
</button> </div>
<button class="ui primary small approve button"> <div class="ui primary small approve button">
<i class="save icon"></i>
{{.locale.Tr "save"}} {{.locale.Tr "save"}}
</button> </div>
</div> </div>
</div> </div>

View File

@ -36,15 +36,12 @@
</div> </div>
</form> </form>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui red basic inverted cancel button"> <div class="ui secondary small basic cancel button">
{{svg "octicon-x"}}
{{.locale.Tr "cancel"}} {{.locale.Tr "cancel"}}
</button> </div>
<button class="ui green basic inverted ok button"> <div class="ui primary small approve button">
{{svg "octicon-check"}}
{{.locale.Tr "repo.issues.create_label"}} {{.locale.Tr "repo.issues.create_label"}}
</button> </div>
</div> </div>
</div> </div>

View File

@ -213,9 +213,9 @@
{{if not .Repository.IsArchived}} {{if not .Repository.IsArchived}}
<!-- Action Button --> <!-- Action Button -->
{{if .IsShowClosed}} {{if .IsShowClosed}}
<button class="ui green active basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_open"}}</button> <div class="ui green active basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_open"}}</div>
{{else}} {{else}}
<button class="ui red active basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_close"}}</button> <div class="ui red active basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_close"}}</div>
{{end}} {{end}}
<!-- Labels --> <!-- Labels -->
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item"> <div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item">

View File

@ -149,9 +149,9 @@
<div class="ui secondary filter stackable menu"> <div class="ui secondary filter stackable menu">
<!-- Action Button --> <!-- Action Button -->
{{if .IsShowClosed}} {{if .IsShowClosed}}
<button class="ui green active basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_open"}}</button> <div class="ui green active basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_open"}}</div>
{{else}} {{else}}
<button class="ui red active basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_close"}}</button> <div class="ui red active basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status" style="margin-left: auto">{{.locale.Tr "repo.issues.action_close"}}</div>
{{end}} {{end}}
<!-- Labels --> <!-- Labels -->
<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item"> <div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item">

View File

@ -124,7 +124,16 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.milestones.deletion_desc"}}</p> <p>{{.locale.Tr "repo.milestones.deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{end}} {{end}}
{{template "base/footer" .}} {{template "base/footer" .}}

View File

@ -112,13 +112,13 @@
<div class="text right"> <div class="text right">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .DisableStatusChange)}} {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .DisableStatusChange)}}
{{if .Issue.IsClosed}} {{if .Issue.IsClosed}}
<button id="status-button" class="ui green basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.reopen_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.reopen_comment_issue"}}" data-status-val="reopen"> <div id="status-button" class="ui green basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.reopen_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.reopen_comment_issue"}}" data-status-val="reopen">
{{.locale.Tr "repo.issues.reopen_issue"}} {{.locale.Tr "repo.issues.reopen_issue"}}
</button> </div>
{{else}} {{else}}
<button id="status-button" class="ui red basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.close_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.close_comment_issue"}}" data-status-val="close"> <div id="status-button" class="ui red basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.close_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.close_comment_issue"}}" data-status-val="close">
{{.locale.Tr "repo.issues.close_issue"}} {{.locale.Tr "repo.issues.close_issue"}}
</button> </div>
{{end}} {{end}}
{{end}} {{end}}
<button class="ui green button loading-button" tabindex="5"> <button class="ui green button loading-button" tabindex="5">
@ -163,13 +163,13 @@
<div class="text right"> <div class="text right">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .DisableStatusChange)}} {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .DisableStatusChange)}}
{{if .Issue.IsClosed}} {{if .Issue.IsClosed}}
<button id="status-button" class="ui green basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.reopen_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.reopen_comment_issue"}}" data-status-val="reopen"> <div id="status-button" class="ui green basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.reopen_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.reopen_comment_issue"}}" data-status-val="reopen">
{{.locale.Tr "repo.issues.reopen_issue"}} {{.locale.Tr "repo.issues.reopen_issue"}}
</button> </div>
{{else}} {{else}}
<button id="status-button" class="ui red basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.close_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.close_comment_issue"}}" data-status-val="close"> <div id="status-button" class="ui red basic button" tabindex="6" data-status="{{.locale.Tr "repo.issues.close_issue"}}" data-status-and-comment="{{.locale.Tr "repo.issues.close_comment_issue"}}" data-status-val="close">
{{.locale.Tr "repo.issues.close_issue"}} {{.locale.Tr "repo.issues.close_issue"}}
</button> </div>
{{end}} {{end}}
{{end}} {{end}}
<button class="ui green button loading-button" tabindex="5"> <button class="ui green button loading-button" tabindex="5">
@ -215,8 +215,8 @@
{{end}} {{end}}
<div class="field footer"> <div class="field footer">
<div class="text right edit"> <div class="text right edit">
<button class="ui basic secondary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</button> <div class="ui basic secondary cancel button" tabindex="3">{{.locale.Tr "repo.issues.cancel"}}</div>
<button class="ui primary save button" tabindex="2">{{.locale.Tr "repo.issues.save"}}</button> <div class="ui primary save button" tabindex="2">{{.locale.Tr "repo.issues.save"}}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,7 +7,10 @@
{{.ctxData.CsrfTokenHtml}} {{.ctxData.CsrfTokenHtml}}
</form> </form>
<div class="header">{{.ctxData.locale.Tr "repo.issues.del_time"}}</div> <div class="header">{{.ctxData.locale.Tr "repo.issues.del_time"}}</div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red approve button">{{.ctxData.locale.Tr "repo.issues.context.delete"}}</div>
<div class="ui cancel button">{{.ctxData.locale.Tr "repo.issues.add_time_cancel"}}</div>
</div>
</div> </div>
<button class="ui icon button compact mini issue-delete-time tooltip" data-id="{{.comment.Time.ID}}" data-content="{{.ctxData.locale.Tr "repo.issues.del_time"}}" data-position="top right"> <button class="ui icon button compact mini issue-delete-time tooltip" data-id="{{.comment.Time.ID}}" data-content="{{.ctxData.locale.Tr "repo.issues.del_time"}}" data-position="top right">
{{svg "octicon-trash"}} {{svg "octicon-trash"}}

View File

@ -58,7 +58,7 @@
<input id="message" name="message"> <input id="message" name="message">
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui red button" type="submit">{{$.locale.Tr "ok"}}</button> <button class="ui red button" type="submit">{{$.locale.Tr "ok"}}</button>
</div> </div>
</form> </form>

View File

@ -346,8 +346,8 @@
</form> </form>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui green approve button">{{.locale.Tr "repo.issues.add_time_short"}}</button> <div class="ui green approve button">{{.locale.Tr "repo.issues.add_time_short"}}</div>
<button class="ui red cancel button">{{.locale.Tr "repo.issues.add_time_cancel"}}</button> <div class="ui red cancel button">{{.locale.Tr "repo.issues.add_time_cancel"}}</div>
</div> </div>
</div> </div>
<button class="ui fluid button green tooltip issue-add-time gt-mt-3" data-content='{{.locale.Tr "repo.issues.add_time"}}' data-position="top center">{{.locale.Tr "repo.issues.add_time_short"}}</button> <button class="ui fluid button green tooltip issue-add-time gt-mt-3" data-content='{{.locale.Tr "repo.issues.add_time"}}' data-position="top center">{{.locale.Tr "repo.issues.add_time_short"}}</button>
@ -532,14 +532,14 @@
{{end}}</p> {{end}}</p>
</div> </div>
<div class="actions"> <div class="actions">
<button class="ui red cancel inverted button"> <div class="ui red cancel inverted button">
{{svg "octicon-x"}} {{svg "octicon-x"}}
{{.locale.Tr "repo.issues.dependency.cancel"}} {{.locale.Tr "repo.issues.dependency.cancel"}}
</button> </div>
<button class="ui green ok inverted button"> <div class="ui green ok inverted button">
{{svg "octicon-check"}} {{svg "octicon-check"}}
{{.locale.Tr "repo.issues.dependency.remove"}} {{.locale.Tr "repo.issues.dependency.remove"}}
</button> </div>
</div> </div>
</div> </div>
{{end}} {{end}}
@ -619,7 +619,7 @@
{{end}} {{end}}
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button"> <button class="ui red button">
{{if .Issue.IsLocked}} {{if .Issue.IsLocked}}
{{.locale.Tr "repo.issues.unlock_confirm"}} {{.locale.Tr "repo.issues.unlock_confirm"}}
@ -655,7 +655,7 @@
<form action="{{.Issue.Link}}/delete" method="post"> <form action="{{.Issue.Link}}/delete" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="center actions"> <div class="center actions">
<button class="ui basic cancel inverted button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui basic cancel inverted button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui basic red inverted button">{{.locale.Tr "modal.yes"}}</button> <button class="ui basic red inverted button">{{.locale.Tr "modal.yes"}}</button>
</div> </div>
</form> </form>

View File

@ -19,8 +19,8 @@
<div class="ui dropdown icon button no-text"> <div class="ui dropdown icon button no-text">
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu"> <div class="menu">
<a class="item active selected" data-do="{{.Link}}/update">{{$.locale.Tr "repo.pulls.update_branch"}}</a> <div class="item active selected" data-do="{{.Link}}/update">{{$.locale.Tr "repo.pulls.update_branch"}}</div>
<a class="item" data-do="{{.Link}}/update?style=rebase">{{$.locale.Tr "repo.pulls.update_branch_rebase"}}</a> <div class="item" data-do="{{.Link}}/update?style=rebase">{{$.locale.Tr "repo.pulls.update_branch_rebase"}}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,9 @@
<div class="sixteen wide column title"> <div class="sixteen wide column title">
<div class="issue-title" id="issue-title-wrapper"> <div class="issue-title" id="issue-title-wrapper">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}} {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}}
<button id="edit-title" class="ui basic button secondary edit-button not-in-edit">{{.locale.Tr "repo.issues.edit"}}</button> <div class="edit-button">
<button id="edit-title" class="ui basic button secondary not-in-edit">{{.locale.Tr "repo.issues.edit"}}</button>
</div>
{{end}} {{end}}
<h1> <h1>
<span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}}</span> <span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}}</span>

View File

@ -72,7 +72,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.confirm_delete"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.confirm_delete"}}</button>
</div> </div>
</form> </form>

View File

@ -86,7 +86,16 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.projects.deletion_desc"}}</p> <p>{{.locale.Tr "repo.projects.deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{end}} {{end}}
{{template "base/footer" .}} {{template "base/footer" .}}

View File

@ -33,7 +33,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button> <button data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}" class="ui primary button" id="new_board_submit">{{$.locale.Tr "repo.projects.column.new_submit"}}</button>
</div> </div>
</form> </form>
@ -131,7 +131,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}" class="ui primary button">{{$.locale.Tr "repo.projects.column.edit"}}</button> <button data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}" class="ui primary button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
</div> </div>
</form> </form>
@ -148,7 +148,7 @@
</label> </label>
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui primary button set-default-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}/default">{{$.locale.Tr "repo.projects.column.set_default"}}</button> <button class="ui primary button set-default-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}/default">{{$.locale.Tr "repo.projects.column.set_default"}}</button>
</div> </div>
</div> </div>
@ -162,8 +162,8 @@
{{$.locale.Tr "repo.projects.column.deletion_desc"}} {{$.locale.Tr "repo.projects.column.deletion_desc"}}
</label> </label>
</div> </div>
<div class="text right actions">{{/* TODO: Convert to base/delete_modal_actions.tmpl? */}} <div class="text right actions">
<button class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui red button delete-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}">{{$.locale.Tr "repo.projects.column.delete"}}</button> <button class="ui red button delete-project-board" data-url="{{$.RepoLink}}/projects/{{$.Project.ID}}/{{.ID}}">{{$.locale.Tr "repo.projects.column.delete"}}</button>
</div> </div>
</div> </div>
@ -276,7 +276,16 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.projects.deletion_desc"}}</p> <p>{{.locale.Tr "repo.projects.deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{end}} {{end}}

View File

@ -114,7 +114,7 @@
{{$.locale.Tr "repo.release.delete_release"}} {{$.locale.Tr "repo.release.delete_release"}}
</a> </a>
{{if .IsDraft}} {{if .IsDraft}}
<button class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}">{{.locale.Tr "repo.release.save_draft"}}</button> <input class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}"/>
<button class="ui primary button"> <button class="ui primary button">
{{.locale.Tr "repo.release.publish"}} {{.locale.Tr "repo.release.publish"}}
</button> </button>
@ -125,9 +125,9 @@
{{end}} {{end}}
{{else}} {{else}}
{{if not .tag_name}} {{if not .tag_name}}
<button class="ui grey button" type="submit" name="tag_only" value="{{.locale.Tr "repo.release.add_tag"}}">{{.locale.Tr "repo.release.add_tag"}}</button> <input class="ui grey button" type="submit" name="tag_only" value="{{.locale.Tr "repo.release.add_tag"}}"/>
{{end}} {{end}}
<button class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}">{{.locale.Tr "repo.release.save_draft"}}</button> <input class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}"/>
<button class="ui primary button"> <button class="ui primary button">
{{.locale.Tr "repo.release.publish"}} {{.locale.Tr "repo.release.publish"}}
</button> </button>

View File

@ -8,9 +8,9 @@
{{.locale.Tr "repo.settings.deploy_keys"}} {{.locale.Tr "repo.settings.deploy_keys"}}
<div class="ui right"> <div class="ui right">
{{if not .DisableSSH}} {{if not .DisableSSH}}
<button class="ui primary tiny show-panel button" data-panel="#add-deploy-key-panel">{{.locale.Tr "repo.settings.add_deploy_key"}}</button> <div class="ui primary tiny show-panel button" data-panel="#add-deploy-key-panel">{{.locale.Tr "repo.settings.add_deploy_key"}}</div>
{{else}} {{else}}
<button class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</button> <div class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</div>
{{end}} {{end}}
</div> </div>
</h4> </h4>
@ -85,6 +85,15 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.settings.deploy_key_deletion_desc"}}</p> <p>{{.locale.Tr "repo.settings.deploy_key_deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>
{{template "base/footer" .}} {{template "base/footer" .}}

View File

@ -50,8 +50,8 @@
</p> </p>
<form class="ui form" action="{{$.Link}}/delete/{{.Oid}}" method="post"> <form class="ui form" action="{{$.Link}}/delete/{{.Oid}}" method="post">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<div class="center actions">{{/* TODO: Convert to base/delete_modal_actions */}} <div class="center actions">
<button class="ui basic cancel inverted button">{{$.locale.Tr "settings.cancel"}}</button> <div class="ui basic cancel inverted button">{{$.locale.Tr "settings.cancel"}}</div>
<button class="ui basic inverted yellow button">{{$.locale.Tr "modal.yes"}}</button> <button class="ui basic inverted yellow button">{{$.locale.Tr "modal.yes"}}</button>
</div> </div>
</form> </form>

View File

@ -49,9 +49,9 @@
{{ShortSha .Oid}} {{ShortSha .Oid}}
</a> </a>
{{else}} {{else}}
<button class="ui detail icon button brown disabled truncate"> <span class="ui detail icon button brown disabled truncate">
{{ShortSha .Oid}} {{ShortSha .Oid}}
</button> </span>
{{end}} {{end}}
</span> </span>
</td> </td>

View File

@ -825,7 +825,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.convert_confirm"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.convert_confirm"}}</button>
</div> </div>
</form> </form>
@ -856,7 +856,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.convert_fork_confirm"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.convert_fork_confirm"}}</button>
</div> </div>
</form> </form>
@ -892,7 +892,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.transfer_perform"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.transfer_perform"}}</button>
</div> </div>
</form> </form>
@ -926,7 +926,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.confirm_delete"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.confirm_delete"}}</button>
</div> </div>
</form> </form>
@ -958,7 +958,7 @@
</div> </div>
<div class="text right actions"> <div class="text right actions">
<button class="ui cancel button">{{.locale.Tr "settings.cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "repo.settings.confirm_wiki_delete"}}</button> <button class="ui red button">{{.locale.Tr "repo.settings.confirm_wiki_delete"}}</button>
</div> </div>
</form> </form>
@ -988,7 +988,10 @@
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" name="action" value="{{if .Repository.IsArchived}}unarchive{{else}}archive{{end}}"> <input type="hidden" name="action" value="{{if .Repository.IsArchived}}unarchive{{else}}archive{{end}}">
<input type="hidden" name="repo_id" value="{{.Repository.ID}}"> <input type="hidden" name="repo_id" value="{{.Repository.ID}}">
{{template "base/delete_modal_actions" .}} <div class="center actions">
<div class="ui basic cancel inverted button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui basic inverted yellow button">{{.locale.Tr "modal.yes"}}</button>
</div>
</form> </form>
</div> </div>
{{end}} {{end}}

View File

@ -6,5 +6,14 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "repo.settings.webhook_deletion_desc"}}</p> <p>{{.locale.Tr "repo.settings.webhook_deletion_desc"}}</p>
</div> </div>
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{.locale.Tr "modal.no"}}
</div>
<div class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "modal.yes"}}
</div>
</div>
</div> </div>

View File

@ -1,7 +1,7 @@
{{if .EscapeStatus}} {{if .EscapeStatus}}
{{if .EscapeStatus.HasInvisible}} {{if .EscapeStatus.HasInvisible}}
<div class="ui error message unicode-escape-prompt gt-tl"> <div class="ui error message unicode-escape-prompt gt-tl">
<button class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button> <span class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</span>
<div class="header"> <div class="header">
{{$.root.locale.Tr "repo.invisible_runes_header"}} {{$.root.locale.Tr "repo.invisible_runes_header"}}
</div> </div>
@ -12,7 +12,7 @@
</div> </div>
{{else if .EscapeStatus.HasAmbiguous}} {{else if .EscapeStatus.HasAmbiguous}}
<div class="ui warning message unicode-escape-prompt gt-tl"> <div class="ui warning message unicode-escape-prompt gt-tl">
<button class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</button> <span class="close icon hide-panel button" data-panel-closest=".message">{{svg "octicon-x" 16 "close inside"}}</span>
<div class="header"> <div class="header">
{{$.root.locale.Tr "repo.ambiguous_runes_header"}} {{$.root.locale.Tr "repo.ambiguous_runes_header"}}
</div> </div>

View File

@ -20,9 +20,9 @@
</div> </div>
<div class="ui input"> <div class="ui input">
<input type="text" value="{{.RegistrationToken}}"> <input type="text" value="{{.RegistrationToken}}">
<button class="ui basic label button" aria-label="{{.locale.Tr "copy"}}" data-clipboard-text="{{.RegistrationToken}}"> <div class="ui basic label button" data-clipboard-text="{{.RegistrationToken}}">
{{svg "octicon-copy" 14}} {{svg "octicon-copy" 14}}
</button> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div class="item"> <div class="item">

View File

@ -1,7 +1,7 @@
<h4 class="ui top attached header"> <h4 class="ui top attached header">
{{.locale.Tr "secrets.secrets"}} {{.locale.Tr "secrets.secrets"}}
<div class="ui right"> <div class="ui right">
<button class="ui primary tiny show-panel button" data-panel="#add-secret-panel">{{.locale.Tr "secrets.creation"}}</button> <div class="ui primary tiny show-panel button" data-panel="#add-secret-panel">{{.locale.Tr "secrets.creation"}}</div>
</div> </div>
</h4> </h4>
<div class="ui attached segment"> <div class="ui attached segment">

View File

@ -493,12 +493,6 @@
"name": "username", "name": "username",
"in": "path", "in": "path",
"required": true "required": true
},
{
"type": "boolean",
"description": "purge the user from the system completely",
"name": "purge",
"in": "query"
} }
], ],
"responses": { "responses": {
@ -713,9 +707,6 @@
"201": { "201": {
"$ref": "#/responses/Repository" "$ref": "#/responses/Repository"
}, },
"400": {
"$ref": "#/responses/error"
},
"403": { "403": {
"$ref": "#/responses/forbidden" "$ref": "#/responses/forbidden"
}, },
@ -1929,9 +1920,6 @@
"201": { "201": {
"$ref": "#/responses/Repository" "$ref": "#/responses/Repository"
}, },
"400": {
"$ref": "#/responses/error"
},
"403": { "403": {
"$ref": "#/responses/forbidden" "$ref": "#/responses/forbidden"
}, },
@ -2126,7 +2114,6 @@
"pub", "pub",
"pypi", "pypi",
"rubygems", "rubygems",
"swift",
"vagrant" "vagrant"
], ],
"type": "string", "type": "string",
@ -13388,9 +13375,6 @@
"201": { "201": {
"$ref": "#/responses/Repository" "$ref": "#/responses/Repository"
}, },
"400": {
"$ref": "#/responses/error"
},
"409": { "409": {
"description": "The repository with the same name already exists." "description": "The repository with the same name already exists."
}, },

View File

@ -23,7 +23,7 @@
<input type="hidden" name="scope" value="{{.Scope}}"> <input type="hidden" name="scope" value="{{.Scope}}">
<input type="hidden" name="nonce" value="{{.Nonce}}"> <input type="hidden" name="nonce" value="{{.Nonce}}">
<input type="hidden" name="redirect_uri" value="{{.RedirectURI}}"> <input type="hidden" name="redirect_uri" value="{{.RedirectURI}}">
<button type="submit" id="authorize-app" value="{{.locale.Tr "auth.authorize_application"}}" class="ui red inline button">{{.locale.Tr "auth.authorize_application"}}</button> <input type="submit" id="authorize-app" value="{{.locale.Tr "auth.authorize_application"}}" class="ui red inline button"/>
<a href="{{.RedirectURI}}" class="ui basic primary inline button">Cancel</a> <a href="{{.RedirectURI}}" class="ui basic primary inline button">Cancel</a>
</form> </form>
</div> </div>

View File

@ -17,6 +17,6 @@
</div> </div>
<div class="actions"> <div class="actions">
<button onclick="window.location.reload()" class="success ui button gt-hidden webauthn_error_timeout">{{.locale.Tr "webauthn_reload"}}</button> <button onclick="window.location.reload()" class="success ui button gt-hidden webauthn_error_timeout">{{.locale.Tr "webauthn_reload"}}</button>
<button class="ui cancel button">{{.locale.Tr "cancel"}}</button> <div class="ui cancel button">{{.locale.Tr "cancel"}}</div>
</div> </div>
</div> </div>

View File

@ -151,9 +151,9 @@
<input id="password-confirmation" name="password" type="password" autocomplete="off" required> <input id="password-confirmation" name="password" type="password" autocomplete="off" required>
</div> </div>
<div class="field"> <div class="field">
<button class="ui red button delete-button" data-modal-id="delete-account" data-type="form" data-form="#delete-form"> <div class="ui red button delete-button" data-modal-id="delete-account" data-type="form" data-form="#delete-form">
{{.locale.Tr "settings.confirm_delete_account"}} {{.locale.Tr "settings.confirm_delete_account"}}
</button> </div>
<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.locale.Tr "auth.forgot_password"}}</a> <a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.locale.Tr "auth.forgot_password"}}</a>
</div> </div>
</form> </form>

View File

@ -276,16 +276,15 @@
<div class="content"> <div class="content">
<p>{{.locale.Tr "settings.access_token_deletion_desc"}}</p> <p>{{.locale.Tr "settings.access_token_deletion_desc"}}</p>
</div> </div>
<div class="actions">
<div class="actions">{{/* TODO: Convert to base/delete_modal_actions.tmpl */}} <div class="ui cancel button">
<button class="ui green basic inverted cancel button"> <i class="remove icon"></i>
{{svg "octicon-x"}}
{{.locale.Tr "settings.access_token_deletion_cancel_action"}} {{.locale.Tr "settings.access_token_deletion_cancel_action"}}
</button> </div>
<button class="ui red basic inverted ok button"> <div class="ui red basic inverted ok button">
{{svg "octicon-check"}} <i class="checkmark icon"></i>
{{.locale.Tr "settings.access_token_deletion_confirm_action"}} {{.locale.Tr "settings.access_token_deletion_confirm_action"}}
</button> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
<h4 class="ui top attached header"> <h4 class="ui top attached header">
{{.locale.Tr "settings.manage_gpg_keys"}} {{.locale.Tr "settings.manage_gpg_keys"}}
<div class="ui right"> <div class="ui right">
<button class="ui primary tiny show-panel button" data-panel="#add-gpg-key-panel">{{.locale.Tr "settings.add_key"}}</button> <div class="ui primary tiny show-panel button" data-panel="#add-gpg-key-panel">{{.locale.Tr "settings.add_key"}}</div>
</div> </div>
</h4> </h4>
<div class="ui attached segment"> <div class="ui attached segment">

View File

@ -3,9 +3,9 @@
{{.locale.Tr "settings.manage_ssh_principals"}} {{.locale.Tr "settings.manage_ssh_principals"}}
<div class="ui right"> <div class="ui right">
{{if not .DisableSSH}} {{if not .DisableSSH}}
<button class="ui primary tiny show-panel button" data-panel="#add-ssh-principal-panel">{{.locale.Tr "settings.add_new_principal"}}</button> <div class="ui primary tiny show-panel button" data-panel="#add-ssh-principal-panel">{{.locale.Tr "settings.add_new_principal"}}</div>
{{else}} {{else}}
<button class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</button> <div class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</div>
{{end}} {{end}}
</div> </div>
</h4> </h4>

View File

@ -2,11 +2,11 @@
{{.locale.Tr "settings.manage_ssh_keys"}} {{.locale.Tr "settings.manage_ssh_keys"}}
<div class="ui right"> <div class="ui right">
{{if not .DisableSSH}} {{if not .DisableSSH}}
<button id="add-ssh-button" class="ui primary tiny show-panel button" data-panel="#add-ssh-key-panel"> <div id="add-ssh-button" class="ui primary tiny show-panel button" data-panel="#add-ssh-key-panel">
{{.locale.Tr "settings.add_key"}} {{.locale.Tr "settings.add_key"}}
</button> </div>
{{else}} {{else}}
<button class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</button> <div class="ui primary tiny button disabled">{{.locale.Tr "settings.ssh_disabled"}}</div>
{{end}} {{end}}
</div> </div>
</h4> </h4>

View File

@ -50,7 +50,16 @@
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<input type="hidden" name="id" value="{{$dir}}"> <input type="hidden" name="id" value="{{$dir}}">
<input type="hidden" name="action" value="adopt"> <input type="hidden" name="action" value="adopt">
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{$.locale.Tr "modal.no"}}
</div>
<button class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{$.locale.Tr "modal.yes"}}
</button>
</div>
</form> </form>
</div> </div>
{{end}} {{end}}
@ -68,7 +77,16 @@
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<input type="hidden" name="id" value="{{$dir}}"> <input type="hidden" name="id" value="{{$dir}}">
<input type="hidden" name="action" value="delete"> <input type="hidden" name="action" value="delete">
{{template "base/delete_modal_actions" .}} <div class="actions">
<div class="ui red basic inverted cancel button">
<i class="remove icon"></i>
{{$.locale.Tr "modal.no"}}
</div>
<button class="ui green basic inverted ok button">
<i class="checkmark icon"></i>
{{$.locale.Tr "modal.yes"}}
</button>
</div>
</form> </form>
</div> </div>
{{end}} {{end}}

View File

@ -13,7 +13,7 @@
<form class="ui form" action="{{AppSubUrl}}/user/settings/security/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form"> <form class="ui form" action="{{AppSubUrl}}/user/settings/security/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<p>{{.locale.Tr "settings.twofa_disable_note"}}</p> <p>{{.locale.Tr "settings.twofa_disable_note"}}</p>
<button class="ui red button delete-button" data-modal-id="disable-twofa" data-type="form" data-form="#disable-form">{{$.locale.Tr "settings.twofa_disable"}}</button> <div class="ui red button delete-button" data-modal-id="disable-twofa" data-type="form" data-form="#disable-form">{{$.locale.Tr "settings.twofa_disable"}}</div>
</form> </form>
{{else}} {{else}}
<p>{{.locale.Tr "settings.twofa_not_enrolled"}}</p> <p>{{.locale.Tr "settings.twofa_not_enrolled"}}</p>

View File

@ -1,326 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"archive/zip"
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"strings"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
swift_module "code.gitea.io/gitea/modules/packages/swift"
"code.gitea.io/gitea/modules/setting"
swift_router "code.gitea.io/gitea/routers/api/packages/swift"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestPackageSwift(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
packageScope := "test-scope"
packageName := "test_package"
packageID := packageScope + "." + packageName
packageVersion := "1.0.3"
packageAuthor := "KN4CK3R"
packageDescription := "Gitea Test Package"
packageRepositoryURL := "https://gitea.io/gitea/gitea"
contentManifest1 := "// swift-tools-version:5.7\n//\n// Package.swift"
contentManifest2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift"
url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
t.Run("CheckAcceptMediaType", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
for _, sub := range []string{
"/scope/package",
"/scope/package.json",
"/scope/package/1.0.0",
"/scope/package/1.0.0.json",
"/scope/package/1.0.0.zip",
"/scope/package/1.0.0/Package.swift",
"/identifiers",
} {
req := NewRequest(t, "GET", url+sub)
req.Header.Add("Accept", "application/unknown")
resp := MakeRequest(t, req, http.StatusBadRequest)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
}
req := NewRequestWithBody(t, "PUT", url+"/scope/package/1.0.0", strings.NewReader(""))
req = AddBasicAuthHeader(req, user.Name)
req.Header.Add("Accept", "application/unknown")
resp := MakeRequest(t, req, http.StatusBadRequest)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
})
t.Run("Upload", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
uploadPackage := func(t *testing.T, url string, expectedStatus int, sr io.Reader, metadata string) {
var body bytes.Buffer
mpw := multipart.NewWriter(&body)
part, _ := mpw.CreateFormFile("source-archive", "source-archive.zip")
io.Copy(part, sr)
if metadata != "" {
mpw.WriteField("metadata", metadata)
}
mpw.Close()
req := NewRequestWithBody(t, "PUT", url, &body)
req.Header.Add("Content-Type", mpw.FormDataContentType())
req.Header.Add("Accept", swift_router.AcceptJSON)
req = AddBasicAuthHeader(req, user.Name)
MakeRequest(t, req, expectedStatus)
}
createArchive := func(files map[string]string) *bytes.Buffer {
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
for filename, content := range files {
w, _ := zw.Create(filename)
w.Write([]byte(content))
}
zw.Close()
return &buf
}
for _, triple := range []string{"/sc_ope/package/1.0.0", "/scope/pack~age/1.0.0", "/scope/package/1_0.0"} {
req := NewRequestWithBody(t, "PUT", url+triple, bytes.NewReader([]byte{}))
req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusBadRequest)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
}
uploadURL := fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion)
req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{}))
MakeRequest(t, req, http.StatusUnauthorized)
uploadPackage(
t,
uploadURL,
http.StatusCreated,
createArchive(map[string]string{
"Package.swift": contentManifest1,
"Package@swift-5.6.swift": contentManifest2,
}),
`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`,
)
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeSwift)
assert.NoError(t, err)
assert.Len(t, pvs, 1)
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err)
assert.NotNil(t, pd.SemVer)
assert.Equal(t, packageID, pd.Package.Name)
assert.Equal(t, packageVersion, pd.Version.Version)
assert.IsType(t, &swift_module.Metadata{}, pd.Metadata)
metadata := pd.Metadata.(*swift_module.Metadata)
assert.Equal(t, packageDescription, metadata.Description)
assert.Len(t, metadata.Manifests, 2)
assert.Equal(t, contentManifest1, metadata.Manifests[""].Content)
assert.Equal(t, contentManifest2, metadata.Manifests["5.6"].Content)
assert.Len(t, pd.VersionProperties, 1)
assert.Equal(t, packageRepositoryURL, pd.VersionProperties.GetByName(swift_module.PropertyRepositoryURL))
pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
assert.NoError(t, err)
assert.Len(t, pfs, 1)
assert.Equal(t, fmt.Sprintf("%s-%s.zip", packageName, packageVersion), pfs[0].Name)
assert.True(t, pfs[0].IsLead)
uploadPackage(
t,
uploadURL,
http.StatusConflict,
createArchive(map[string]string{
"Package.swift": contentManifest1,
}),
"",
)
})
t.Run("Download", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.zip", url, packageScope, packageName, packageVersion))
req = AddBasicAuthHeader(req, user.Name)
req.Header.Add("Accept", swift_router.AcceptZip)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "application/zip", resp.Header().Get("Content-Type"))
pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion)
assert.NotNil(t, pv)
assert.NoError(t, err)
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)
assert.NoError(t, err)
assert.Equal(t, "sha256="+pd.Files[0].Blob.HashSHA256, resp.Header().Get("Digest"))
})
t.Run("EnumeratePackageVersions", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", url, packageScope, packageName))
req = AddBasicAuthHeader(req, user.Name)
req.Header.Add("Accept", swift_router.AcceptJSON)
resp := MakeRequest(t, req, http.StatusOK)
versionURL := setting.AppURL + url[1:] + fmt.Sprintf("/%s/%s/%s", packageScope, packageName, packageVersion)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, fmt.Sprintf(`<%s>; rel="latest-version"`, versionURL), resp.Header().Get("Link"))
body := resp.Body.String()
var result *swift_router.EnumeratePackageVersionsResponse
DecodeJSON(t, resp, &result)
assert.Len(t, result.Releases, 1)
assert.Contains(t, result.Releases, packageVersion)
assert.Equal(t, versionURL, result.Releases[packageVersion].URL)
req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s.json", url, packageScope, packageName))
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, body, resp.Body.String())
})
t.Run("PackageVersionMetadata", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion))
req = AddBasicAuthHeader(req, user.Name)
req.Header.Add("Accept", swift_router.AcceptJSON)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
body := resp.Body.String()
var result *swift_router.PackageVersionMetadataResponse
DecodeJSON(t, resp, &result)
pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion)
assert.NotNil(t, pv)
assert.NoError(t, err)
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv)
assert.NoError(t, err)
assert.Equal(t, packageID, result.ID)
assert.Equal(t, packageVersion, result.Version)
assert.Len(t, result.Resources, 1)
assert.Equal(t, "source-archive", result.Resources[0].Name)
assert.Equal(t, "application/zip", result.Resources[0].Type)
assert.Equal(t, pd.Files[0].Blob.HashSHA256, result.Resources[0].Checksum)
assert.Equal(t, "SoftwareSourceCode", result.Metadata.Type)
assert.Equal(t, packageName, result.Metadata.Name)
assert.Equal(t, packageVersion, result.Metadata.Version)
assert.Equal(t, packageDescription, result.Metadata.Description)
assert.Equal(t, "Swift", result.Metadata.ProgrammingLanguage.Name)
assert.Equal(t, packageAuthor, result.Metadata.Author.GivenName)
req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.json", url, packageScope, packageName, packageVersion))
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, body, resp.Body.String())
})
t.Run("DownloadManifest", func(t *testing.T) {
manifestURL := fmt.Sprintf("%s/%s/%s/%s/Package.swift", url, packageScope, packageName, packageVersion)
t.Run("Default", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", manifestURL)
req = AddBasicAuthHeader(req, user.Name)
req.Header.Add("Accept", swift_router.AcceptSwift)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type"))
assert.Equal(t, contentManifest1, resp.Body.String())
})
t.Run("DifferentVersion", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", manifestURL+"?swift-version=5.6")
req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type"))
assert.Equal(t, contentManifest2, resp.Body.String())
req = NewRequest(t, "GET", manifestURL+"?swift-version=5.6.0")
req = AddBasicAuthHeader(req, user.Name)
MakeRequest(t, req, http.StatusOK)
})
t.Run("Redirect", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", manifestURL+"?swift-version=1.0")
req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusSeeOther)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, setting.AppURL+url[1:]+fmt.Sprintf("/%s/%s/%s/Package.swift", packageScope, packageName, packageVersion), resp.Header().Get("Location"))
})
})
t.Run("LookupPackageIdentifiers", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", url+"/identifiers")
req.Header.Add("Accept", swift_router.AcceptJSON)
resp := MakeRequest(t, req, http.StatusBadRequest)
assert.Equal(t, "1", resp.Header().Get("Content-Version"))
assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type"))
req = NewRequest(t, "GET", url+"/identifiers?url=https://unknown.host/")
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", url+"/identifiers?url="+packageRepositoryURL)
req.Header.Add("Accept", swift_router.AcceptJSON)
resp = MakeRequest(t, req, http.StatusOK)
var result *swift_router.LookupPackageIdentifiersResponse
DecodeJSON(t, resp, &result)
assert.Len(t, result.Identifiers, 1)
assert.Equal(t, packageID, result.Identifiers[0])
})
}

View File

@ -201,7 +201,7 @@ func PrepareTestEnv(t testing.TB, skip ...int) func() {
lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")}) lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
assert.NoError(t, err) assert.NoError(t, err)
assert.NoError(t, storage.Clean(storage.LFS)) assert.NoError(t, storage.Clean(storage.LFS))
assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error { assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
_, err := storage.Copy(storage.LFS, path, lfsFixtures, path) _, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
return err return err
})) }))
@ -258,7 +258,7 @@ func ResetFixtures(t *testing.T) {
lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")}) lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
assert.NoError(t, err) assert.NoError(t, err)
assert.NoError(t, storage.Clean(storage.LFS)) assert.NoError(t, storage.Clean(storage.LFS))
assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error { assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
_, err := storage.Copy(storage.LFS, path, lfsFixtures, path) _, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
return err return err
})) }))

View File

@ -43,7 +43,8 @@
<div class="job-step-container"> <div class="job-step-container">
<div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i"> <div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i">
<div class="job-step-summary" @click.stop="toggleStepLogs(i)"> <div class="job-step-summary" @click.stop="toggleStepLogs(i)">
<SvgIcon :name="currentJobStepsStates[i].expanded ? 'octicon-chevron-down': 'octicon-chevron-right'" class="gt-mr-3"/> <SvgIcon name="octicon-chevron-down" class="gt-mr-3" v-show="currentJobStepsStates[i].expanded"/>
<SvgIcon name="octicon-chevron-right" class="gt-mr-3" v-show="!currentJobStepsStates[i].expanded"/>
<ActionRunStatus :status="jobStep.status" class="gt-mr-3"/> <ActionRunStatus :status="jobStep.status" class="gt-mr-3"/>

View File

@ -198,8 +198,7 @@ export function initAdminCommon() {
break; break;
} }
}); });
$('#delete-selection').on('click', function (e) { $('#delete-selection').on('click', function () {
e.preventDefault();
const $this = $(this); const $this = $(this);
$this.addClass('loading disabled'); $this.addClass('loading disabled');
const ids = []; const ids = [];

Some files were not shown because too many files have changed in this diff Show More