mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-20 16:58:31 +02:00
Merge branch 'main' into lunny/move_wikipath
This commit is contained in:
commit
38a445575e
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Gitea DevContainer",
|
"name": "Gitea DevContainer",
|
||||||
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
|
"image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm",
|
||||||
"features": {
|
"features": {
|
||||||
// installs nodejs into container
|
// installs nodejs into container
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
|
@ -6,10 +6,12 @@ package actions
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
@ -32,26 +34,39 @@ type ActionVariable struct {
|
|||||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"`
|
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"`
|
||||||
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
||||||
Data string `xorm:"LONGTEXT NOT NULL"`
|
Data string `xorm:"LONGTEXT NOT NULL"`
|
||||||
|
Description string `xorm:"TEXT"`
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
VariableDataMaxLength = 65536
|
||||||
|
VariableDescriptionMaxLength = 4096
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
db.RegisterModel(new(ActionVariable))
|
db.RegisterModel(new(ActionVariable))
|
||||||
}
|
}
|
||||||
|
|
||||||
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) {
|
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*ActionVariable, error) {
|
||||||
if ownerID != 0 && repoID != 0 {
|
if ownerID != 0 && repoID != 0 {
|
||||||
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
|
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
ownerID = 0
|
ownerID = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if utf8.RuneCountInString(data) > VariableDataMaxLength {
|
||||||
|
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = util.TruncateRunes(description, VariableDescriptionMaxLength)
|
||||||
|
|
||||||
variable := &ActionVariable{
|
variable := &ActionVariable{
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
Name: strings.ToUpper(name),
|
Name: strings.ToUpper(name),
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Description: description,
|
||||||
}
|
}
|
||||||
return variable, db.Insert(ctx, variable)
|
return variable, db.Insert(ctx, variable)
|
||||||
}
|
}
|
||||||
@ -96,6 +111,12 @@ func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariab
|
|||||||
}
|
}
|
||||||
|
|
||||||
func UpdateVariableCols(ctx context.Context, variable *ActionVariable, cols ...string) (bool, error) {
|
func UpdateVariableCols(ctx context.Context, variable *ActionVariable, cols ...string) (bool, error) {
|
||||||
|
if utf8.RuneCountInString(variable.Data) > VariableDataMaxLength {
|
||||||
|
return false, util.NewInvalidArgumentErrorf("data too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
variable.Description = util.TruncateRunes(variable.Description, VariableDescriptionMaxLength)
|
||||||
|
|
||||||
variable.Name = strings.ToUpper(variable.Name)
|
variable.Name = strings.ToUpper(variable.Name)
|
||||||
count, err := db.GetEngine(ctx).
|
count, err := db.GetEngine(ctx).
|
||||||
ID(variable.ID).
|
ID(variable.ID).
|
||||||
|
@ -376,6 +376,7 @@ func prepareMigrationTasks() []*migration {
|
|||||||
newMigration(313, "Move PinOrder from issue table to a new table issue_pin", v1_24.MovePinOrderToTableIssuePin),
|
newMigration(313, "Move PinOrder from issue table to a new table issue_pin", v1_24.MovePinOrderToTableIssuePin),
|
||||||
newMigration(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
|
newMigration(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
|
||||||
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
|
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
|
||||||
|
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
|
||||||
}
|
}
|
||||||
return preparedMigrations
|
return preparedMigrations
|
||||||
}
|
}
|
||||||
|
20
models/migrations/v1_24/v316.go
Normal file
20
models/migrations/v1_24/v316.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_24 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddDescriptionForSecretsAndVariables(x *xorm.Engine) error {
|
||||||
|
type Secret struct {
|
||||||
|
Description string `xorm:"TEXT"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionVariable struct {
|
||||||
|
Description string `xorm:"TEXT"`
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.Sync(new(Secret), new(ActionVariable))
|
||||||
|
}
|
@ -215,12 +215,24 @@ func init() {
|
|||||||
db.RegisterModel(new(Repository))
|
db.RegisterModel(new(Repository))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) GetName() string {
|
func RelativePath(ownerName, repoName string) string {
|
||||||
return repo.Name
|
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) GetOwnerName() string {
|
// RelativePath should be an unix style path like username/reponame.git
|
||||||
return repo.OwnerName
|
func (repo *Repository) RelativePath() string {
|
||||||
|
return RelativePath(repo.OwnerName, repo.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type StorageRepo string
|
||||||
|
|
||||||
|
// RelativePath should be an unix style path like username/reponame.git
|
||||||
|
func (sr StorageRepo) RelativePath() string {
|
||||||
|
return string(sr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) WikiStorageRepo() StorageRepo {
|
||||||
|
return StorageRepo(strings.ToLower(repo.OwnerName) + "/" + strings.ToLower(repo.Name) + ".wiki.git")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SanitizedOriginalURL returns a sanitized OriginalURL
|
// SanitizedOriginalURL returns a sanitized OriginalURL
|
||||||
|
@ -40,9 +40,15 @@ type Secret struct {
|
|||||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
|
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
|
||||||
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
||||||
Data string `xorm:"LONGTEXT"` // encrypted data
|
Data string `xorm:"LONGTEXT"` // encrypted data
|
||||||
|
Description string `xorm:"TEXT"`
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SecretDataMaxLength = 65536
|
||||||
|
SecretDescriptionMaxLength = 4096
|
||||||
|
)
|
||||||
|
|
||||||
// ErrSecretNotFound represents a "secret not found" error.
|
// ErrSecretNotFound represents a "secret not found" error.
|
||||||
type ErrSecretNotFound struct {
|
type ErrSecretNotFound struct {
|
||||||
Name string
|
Name string
|
||||||
@ -57,7 +63,7 @@ func (err ErrSecretNotFound) Unwrap() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
|
// InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
|
||||||
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*Secret, error) {
|
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*Secret, error) {
|
||||||
if ownerID != 0 && repoID != 0 {
|
if ownerID != 0 && repoID != 0 {
|
||||||
// It's trying to create a secret that belongs to a repository, but OwnerID has been set accidentally.
|
// It's trying to create a secret that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
@ -67,15 +73,23 @@ func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, dat
|
|||||||
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
|
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(data) > SecretDataMaxLength {
|
||||||
|
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
|
||||||
|
|
||||||
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secret := &Secret{
|
secret := &Secret{
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
Name: strings.ToUpper(name),
|
Name: strings.ToUpper(name),
|
||||||
Data: encrypted,
|
Data: encrypted,
|
||||||
|
Description: description,
|
||||||
}
|
}
|
||||||
return secret, db.Insert(ctx, secret)
|
return secret, db.Insert(ctx, secret)
|
||||||
}
|
}
|
||||||
@ -114,7 +128,13 @@ func (opts FindSecretsOptions) ToConds() builder.Cond {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSecret changes org or user reop secret.
|
// UpdateSecret changes org or user reop secret.
|
||||||
func UpdateSecret(ctx context.Context, secretID int64, data string) error {
|
func UpdateSecret(ctx context.Context, secretID int64, data, description string) error {
|
||||||
|
if len(data) > SecretDataMaxLength {
|
||||||
|
return util.NewInvalidArgumentErrorf("data too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
|
||||||
|
|
||||||
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -122,8 +142,9 @@ func UpdateSecret(ctx context.Context, secretID int64, data string) error {
|
|||||||
|
|
||||||
s := &Secret{
|
s := &Secret{
|
||||||
Data: encrypted,
|
Data: encrypted,
|
||||||
|
Description: description,
|
||||||
}
|
}
|
||||||
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data").Update(s)
|
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data", "description").Update(s)
|
||||||
if affected != 1 {
|
if affected != 1 {
|
||||||
return ErrSecretNotFound{}
|
return ErrSecretNotFound{}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ type Command struct {
|
|||||||
args []string
|
args []string
|
||||||
globalArgsLength int
|
globalArgsLength int
|
||||||
brokenArgs []string
|
brokenArgs []string
|
||||||
|
cmd *exec.Cmd // for debug purpose only
|
||||||
}
|
}
|
||||||
|
|
||||||
func logArgSanitize(arg string) string {
|
func logArgSanitize(arg string) string {
|
||||||
@ -314,6 +315,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, c.prog, c.args...)
|
cmd := exec.CommandContext(ctx, c.prog, c.args...)
|
||||||
|
c.cmd = cmd // for debug purpose only
|
||||||
if opts.Env == nil {
|
if opts.Env == nil {
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
@ -102,7 +104,7 @@ type CheckAttributeReader struct {
|
|||||||
|
|
||||||
stdinReader io.ReadCloser
|
stdinReader io.ReadCloser
|
||||||
stdinWriter *os.File
|
stdinWriter *os.File
|
||||||
stdOut attributeWriter
|
stdOut *nulSeparatedAttributeWriter
|
||||||
cmd *Command
|
cmd *Command
|
||||||
env []string
|
env []string
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -152,7 +154,6 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run run cmd
|
|
||||||
func (c *CheckAttributeReader) Run() error {
|
func (c *CheckAttributeReader) Run() error {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = c.stdinReader.Close()
|
_ = c.stdinReader.Close()
|
||||||
@ -176,7 +177,7 @@ func (c *CheckAttributeReader) Run() error {
|
|||||||
func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) {
|
func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && err != c.ctx.Err() {
|
if err != nil && err != c.ctx.Err() {
|
||||||
log.Error("Unexpected error when checking path %s in %s. Error: %v", path, c.Repo.Path, err)
|
log.Error("Unexpected error when checking path %s in %s, error: %v", path, filepath.Base(c.Repo.Path), err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -191,9 +192,31 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reportTimeout := func() error {
|
||||||
|
stdOutClosed := false
|
||||||
|
select {
|
||||||
|
case <-c.stdOut.closed:
|
||||||
|
stdOutClosed = true
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
debugMsg := fmt.Sprintf("check path %q in repo %q", path, filepath.Base(c.Repo.Path))
|
||||||
|
debugMsg += fmt.Sprintf(", stdOut: tmp=%q, pos=%d, closed=%v", string(c.stdOut.tmp), c.stdOut.pos, stdOutClosed)
|
||||||
|
if c.cmd.cmd != nil {
|
||||||
|
debugMsg += fmt.Sprintf(", process state: %q", c.cmd.cmd.ProcessState.String())
|
||||||
|
}
|
||||||
|
_ = c.Close()
|
||||||
|
return fmt.Errorf("CheckPath timeout: %s", debugMsg)
|
||||||
|
}
|
||||||
|
|
||||||
rs = make(map[string]string)
|
rs = make(map[string]string)
|
||||||
for range c.Attributes {
|
for range c.Attributes {
|
||||||
select {
|
select {
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
// There is a strange "hang" problem in gitdiff.GetDiff -> CheckPath
|
||||||
|
// So add a timeout here to mitigate the problem, and output more logs for debug purpose
|
||||||
|
// In real world, if CheckPath runs long than seconds, it blocks the end user's operation,
|
||||||
|
// and at the moment the CheckPath result is not so important, so we can just ignore it.
|
||||||
|
return nil, reportTimeout()
|
||||||
case attr, ok := <-c.stdOut.ReadAttribute():
|
case attr, ok := <-c.stdOut.ReadAttribute():
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, c.ctx.Err()
|
return nil, c.ctx.Err()
|
||||||
@ -206,18 +229,12 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
|
|||||||
return rs, nil
|
return rs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close close pip after use
|
|
||||||
func (c *CheckAttributeReader) Close() error {
|
func (c *CheckAttributeReader) Close() error {
|
||||||
c.cancel()
|
c.cancel()
|
||||||
err := c.stdinWriter.Close()
|
err := c.stdinWriter.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type attributeWriter interface {
|
|
||||||
io.WriteCloser
|
|
||||||
ReadAttribute() <-chan attributeTriple
|
|
||||||
}
|
|
||||||
|
|
||||||
type attributeTriple struct {
|
type attributeTriple struct {
|
||||||
Filename string
|
Filename string
|
||||||
Attribute string
|
Attribute string
|
||||||
@ -281,7 +298,7 @@ func (wr *nulSeparatedAttributeWriter) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a check attribute reader for the current repository and provided commit ID
|
// CheckAttributeReader creates a check attribute reader for the current repository and provided commit ID
|
||||||
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) {
|
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) {
|
||||||
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
|
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -303,21 +320,21 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
|
|||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(repo.Ctx)
|
ctx, cancel := context.WithCancel(repo.Ctx)
|
||||||
if err := checker.Init(ctx); err != nil {
|
if err := checker.Init(ctx); err != nil {
|
||||||
log.Error("Unable to open checker for %s. Error: %v", commitID, err)
|
log.Error("Unable to open attribute checker for commit %s, error: %v", commitID, err)
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
err := checker.Run()
|
err := checker.Run()
|
||||||
if err != nil && err != ctx.Err() {
|
if err != nil && !IsErrCanceledOrKilled(err) {
|
||||||
log.Error("Unable to open checker for %s. Error: %v", commitID, err)
|
log.Error("Attribute checker for commit %s exits with error: %v", commitID, err)
|
||||||
}
|
}
|
||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
deferable := func() {
|
deferrable := func() {
|
||||||
_ = checker.Close()
|
_ = checker.Close()
|
||||||
cancel()
|
cancel()
|
||||||
deleteTemporaryFile()
|
deleteTemporaryFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
return checker, deferable
|
return checker, deferrable
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,16 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
mathRand "math/rand/v2"
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||||
@ -95,3 +101,57 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
|||||||
Value: "unspecified",
|
Value: "unspecified",
|
||||||
}, attr)
|
}, attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAttributeReader(t *testing.T) {
|
||||||
|
t.Skip() // for debug purpose only, do not run in CI
|
||||||
|
|
||||||
|
ctx := t.Context()
|
||||||
|
|
||||||
|
timeout := 1 * time.Second
|
||||||
|
repoPath := filepath.Join(testReposDir, "language_stats_repo")
|
||||||
|
commitRef := "HEAD"
|
||||||
|
|
||||||
|
oneRound := func(t *testing.T, roundIdx int) {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
|
_ = cancel
|
||||||
|
gitRepo, err := OpenRepository(ctx, repoPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer gitRepo.Close()
|
||||||
|
|
||||||
|
commit, err := gitRepo.GetCommit(commitRef)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
files, err := gitRepo.LsFiles()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
randomFiles := slices.Clone(files)
|
||||||
|
randomFiles = append(randomFiles, "any-file-1", "any-file-2")
|
||||||
|
|
||||||
|
t.Logf("Round %v with %d files", roundIdx, len(randomFiles))
|
||||||
|
|
||||||
|
attrReader, deferrable := gitRepo.CheckAttributeReader(commit.ID.String())
|
||||||
|
defer deferrable()
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
file := randomFiles[mathRand.IntN(len(randomFiles))]
|
||||||
|
_, err := attrReader.CheckPath(file)
|
||||||
|
if err != nil {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
_, _ = attrReader.CheckPath(file)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
oneRound(t, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -44,24 +44,12 @@ func GetDefaultBranch(ctx context.Context, repo Repository) (string, error) {
|
|||||||
return git.GetDefaultBranch(ctx, repoPath(repo))
|
return git.GetDefaultBranch(ctx, repoPath(repo))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWikiDefaultBranch(ctx context.Context, repo Repository) (string, error) {
|
|
||||||
return git.GetDefaultBranch(ctx, wikiPath(repo))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsReferenceExist returns true if given reference exists in the repository.
|
// IsReferenceExist returns true if given reference exists in the repository.
|
||||||
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
|
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
|
||||||
return git.IsReferenceExist(ctx, repoPath(repo), name)
|
return git.IsReferenceExist(ctx, repoPath(repo), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsWikiReferenceExist(ctx context.Context, repo Repository, name string) bool {
|
|
||||||
return git.IsReferenceExist(ctx, wikiPath(repo), name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBranchExist returns true if given branch exists in the repository.
|
// IsBranchExist returns true if given branch exists in the repository.
|
||||||
func IsBranchExist(ctx context.Context, repo Repository, name string) bool {
|
func IsBranchExist(ctx context.Context, repo Repository, name string) bool {
|
||||||
return IsReferenceExist(ctx, repo, git.BranchPrefix+name)
|
return IsReferenceExist(ctx, repo, git.BranchPrefix+name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsWikiBranchExist(ctx context.Context, repo Repository, name string) bool {
|
|
||||||
return IsWikiReferenceExist(ctx, repo, git.BranchPrefix+name)
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/reqctx"
|
"code.gitea.io/gitea/modules/reqctx"
|
||||||
@ -16,17 +15,15 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Repository represents a git repository which stored in a disk
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
GetName() string
|
RelativePath() string // We don't assume how the directory structure of the repository is, so we only need the relative path
|
||||||
GetOwnerName() string
|
|
||||||
}
|
|
||||||
|
|
||||||
func absPath(owner, name string) string {
|
|
||||||
return filepath.Join(setting.RepoRootPath, strings.ToLower(owner), strings.ToLower(name)+".git")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RelativePath should be an unix style path like username/reponame.git
|
||||||
|
// This method should change it according to the current OS.
|
||||||
func repoPath(repo Repository) string {
|
func repoPath(repo Repository) string {
|
||||||
return absPath(repo.GetOwnerName(), repo.GetName())
|
return filepath.Join(setting.RepoRootPath, filepath.FromSlash(repo.RelativePath()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenRepository opens the repository at the given relative path with the provided context.
|
// OpenRepository opens the repository at the given relative path with the provided context.
|
||||||
@ -78,9 +75,8 @@ func DeleteRepository(ctx context.Context, repo Repository) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RenameRepository renames a repository's name on disk
|
// RenameRepository renames a repository's name on disk
|
||||||
func RenameRepository(ctx context.Context, repo Repository, newName string) error {
|
func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
|
||||||
newRepoPath := absPath(repo.GetOwnerName(), newName)
|
if err := util.Rename(repoPath(repo), repoPath(newRepo)); err != nil {
|
||||||
if err := util.Rename(repoPath(repo), newRepoPath); err != nil {
|
|
||||||
return fmt.Errorf("rename repository directory: %w", err)
|
return fmt.Errorf("rename repository directory: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -106,16 +106,11 @@ done
|
|||||||
return hookNames, hookTpls, giteaHookTpls
|
return hookNames, hookTpls, giteaHookTpls
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDelegateHooksForRepo creates all the hooks scripts for the repo
|
// CreateDelegateHooks creates all the hooks scripts for the repo
|
||||||
func CreateDelegateHooksForRepo(_ context.Context, repo Repository) (err error) {
|
func CreateDelegateHooks(_ context.Context, repo Repository) (err error) {
|
||||||
return createDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
|
return createDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDelegateHooksForWiki creates all the hooks scripts for the wiki repo
|
|
||||||
func CreateDelegateHooksForWiki(_ context.Context, repo Repository) (err error) {
|
|
||||||
return createDelegateHooks(filepath.Join(wikiPath(repo), "hooks"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDelegateHooks(hookDir string) (err error) {
|
func createDelegateHooks(hookDir string) (err error) {
|
||||||
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
||||||
|
|
||||||
@ -178,16 +173,11 @@ func ensureExecutable(filename string) error {
|
|||||||
return os.Chmod(filename, mode)
|
return os.Chmod(filename, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckDelegateHooksForRepo checks the hooks scripts for the repo
|
// CheckDelegateHooks checks the hooks scripts for the repo
|
||||||
func CheckDelegateHooksForRepo(_ context.Context, repo Repository) ([]string, error) {
|
func CheckDelegateHooks(_ context.Context, repo Repository) ([]string, error) {
|
||||||
return checkDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
|
return checkDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckDelegateHooksForWiki checks the hooks scripts for the repo
|
|
||||||
func CheckDelegateHooksForWiki(_ context.Context, repo Repository) ([]string, error) {
|
|
||||||
return checkDelegateHooks(filepath.Join(wikiPath(repo), "hooks"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkDelegateHooks(hookDir string) ([]string, error) {
|
func checkDelegateHooks(hookDir string) ([]string, error) {
|
||||||
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ func CheckInitRepository(ctx context.Context, repo *repo_model.Repository) (err
|
|||||||
// Init git bare new repository.
|
// Init git bare new repository.
|
||||||
if err = git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil {
|
if err = git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil {
|
||||||
return fmt.Errorf("git.InitRepository: %w", err)
|
return fmt.Errorf("git.InitRepository: %w", err)
|
||||||
} else if err = gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
} else if err = gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -10,6 +10,8 @@ import "time"
|
|||||||
type Secret struct {
|
type Secret struct {
|
||||||
// the secret's name
|
// the secret's name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
// the secret's description
|
||||||
|
Description string `json:"description"`
|
||||||
// swagger:strfmt date-time
|
// swagger:strfmt date-time
|
||||||
Created time.Time `json:"created_at"`
|
Created time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
@ -21,4 +23,9 @@ type CreateOrUpdateSecretOption struct {
|
|||||||
//
|
//
|
||||||
// required: true
|
// required: true
|
||||||
Data string `json:"data" binding:"Required"`
|
Data string `json:"data" binding:"Required"`
|
||||||
|
|
||||||
|
// Description of the secret to update
|
||||||
|
//
|
||||||
|
// required: false
|
||||||
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,11 @@ type CreateVariableOption struct {
|
|||||||
//
|
//
|
||||||
// required: true
|
// required: true
|
||||||
Value string `json:"value" binding:"Required"`
|
Value string `json:"value" binding:"Required"`
|
||||||
|
|
||||||
|
// Description of the variable to create
|
||||||
|
//
|
||||||
|
// required: false
|
||||||
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateVariableOption the option when updating variable
|
// UpdateVariableOption the option when updating variable
|
||||||
@ -21,6 +26,11 @@ type UpdateVariableOption struct {
|
|||||||
//
|
//
|
||||||
// required: true
|
// required: true
|
||||||
Value string `json:"value" binding:"Required"`
|
Value string `json:"value" binding:"Required"`
|
||||||
|
|
||||||
|
// Description of the variable to update
|
||||||
|
//
|
||||||
|
// required: false
|
||||||
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActionVariable return value of the query API
|
// ActionVariable return value of the query API
|
||||||
@ -34,4 +44,6 @@ type ActionVariable struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// the value of the variable
|
// the value of the variable
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
|
// the description of the variable
|
||||||
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
@ -3679,6 +3679,7 @@ secrets=Tajné klíče
|
|||||||
description=Tejné klíče budou předány určitým akcím a nelze je přečíst jinak.
|
description=Tejné klíče budou předány určitým akcím a nelze je přečíst jinak.
|
||||||
none=Zatím zde nejsou žádné tajné klíče.
|
none=Zatím zde nejsou žádné tajné klíče.
|
||||||
creation=Přidat tajný klíč
|
creation=Přidat tajný klíč
|
||||||
|
creation.description=Popis
|
||||||
creation.name_placeholder=nerozlišovat velká a malá písmena, pouze alfanumerické znaky nebo podtržítka, nemohou začínat na GITEA_ nebo GITHUB_
|
creation.name_placeholder=nerozlišovat velká a malá písmena, pouze alfanumerické znaky nebo podtržítka, nemohou začínat na GITEA_ nebo GITHUB_
|
||||||
creation.value_placeholder=Vložte jakýkoliv obsah. Mezery na začátku a konci budou vynechány.
|
creation.value_placeholder=Vložte jakýkoliv obsah. Mezery na začátku a konci budou vynechány.
|
||||||
creation.success=Tajný klíč „%s“ byl přidán.
|
creation.success=Tajný klíč „%s“ byl přidán.
|
||||||
|
@ -3670,6 +3670,7 @@ secrets=Secrets
|
|||||||
description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
|
description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
|
||||||
none=Noch keine Secrets vorhanden.
|
none=Noch keine Secrets vorhanden.
|
||||||
creation=Secret hinzufügen
|
creation=Secret hinzufügen
|
||||||
|
creation.description=Beschreibung
|
||||||
creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen
|
creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen
|
||||||
creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen.
|
creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen.
|
||||||
creation.success=Das Secret "%s" wurde hinzugefügt.
|
creation.success=Das Secret "%s" wurde hinzugefügt.
|
||||||
|
@ -3338,6 +3338,7 @@ secrets=Μυστικά
|
|||||||
description=Τα μυστικά θα περάσουν σε ορισμένες δράσεις και δεν μπορούν να αναγνωστούν αλλού.
|
description=Τα μυστικά θα περάσουν σε ορισμένες δράσεις και δεν μπορούν να αναγνωστούν αλλού.
|
||||||
none=Δεν υπάρχουν ακόμα μυστικά.
|
none=Δεν υπάρχουν ακόμα μυστικά.
|
||||||
creation=Προσθήκη Μυστικού
|
creation=Προσθήκη Μυστικού
|
||||||
|
creation.description=Περιγραφή
|
||||||
creation.name_placeholder=αλφαριθμητικοί χαρακτήρες ή κάτω παύλες μόνο, δεν μπορούν να ξεκινούν με GITEA_ ή GITHUB_
|
creation.name_placeholder=αλφαριθμητικοί χαρακτήρες ή κάτω παύλες μόνο, δεν μπορούν να ξεκινούν με GITEA_ ή GITHUB_
|
||||||
creation.value_placeholder=Εισάγετε οποιοδήποτε περιεχόμενο. Τα κενά στην αρχή παραλείπονται.
|
creation.value_placeholder=Εισάγετε οποιοδήποτε περιεχόμενο. Τα κενά στην αρχή παραλείπονται.
|
||||||
creation.success=Το μυστικό "%s" προστέθηκε.
|
creation.success=Το μυστικό "%s" προστέθηκε.
|
||||||
|
@ -3712,8 +3712,10 @@ secrets = Secrets
|
|||||||
description = Secrets will be passed to certain actions and cannot be read otherwise.
|
description = Secrets will be passed to certain actions and cannot be read otherwise.
|
||||||
none = There are no secrets yet.
|
none = There are no secrets yet.
|
||||||
creation = Add Secret
|
creation = Add Secret
|
||||||
|
creation.description = Description
|
||||||
creation.name_placeholder = case-insensitive, alphanumeric characters or underscores only, cannot start with GITEA_ or GITHUB_
|
creation.name_placeholder = case-insensitive, alphanumeric characters or underscores only, cannot start with GITEA_ or GITHUB_
|
||||||
creation.value_placeholder = Input any content. Whitespace at the start and end will be omitted.
|
creation.value_placeholder = Input any content. Whitespace at the start and end will be omitted.
|
||||||
|
creation.description_placeholder = Enter short description (optional).
|
||||||
creation.success = The secret "%s" has been added.
|
creation.success = The secret "%s" has been added.
|
||||||
creation.failed = Failed to add secret.
|
creation.failed = Failed to add secret.
|
||||||
deletion = Remove secret
|
deletion = Remove secret
|
||||||
|
@ -3318,6 +3318,7 @@ secrets=Secretos
|
|||||||
description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo.
|
description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo.
|
||||||
none=Todavía no hay secretos.
|
none=Todavía no hay secretos.
|
||||||
creation=Añadir secreto
|
creation=Añadir secreto
|
||||||
|
creation.description=Descripción
|
||||||
creation.name_placeholder=sin distinción de mayúsculas, solo carácteres alfanuméricos o guiones bajos, no puede empezar por GITEA_ o GITHUB_
|
creation.name_placeholder=sin distinción de mayúsculas, solo carácteres alfanuméricos o guiones bajos, no puede empezar por GITEA_ o GITHUB_
|
||||||
creation.value_placeholder=Introduce cualquier contenido. Se omitirá el espacio en blanco en el inicio y el final.
|
creation.value_placeholder=Introduce cualquier contenido. Se omitirá el espacio en blanco en el inicio y el final.
|
||||||
creation.success=El secreto "%s" ha sido añadido.
|
creation.success=El secreto "%s" ha sido añadido.
|
||||||
|
@ -2513,6 +2513,7 @@ conan.details.repository=مخزن
|
|||||||
owner.settings.cleanuprules.enabled=فعال شده
|
owner.settings.cleanuprules.enabled=فعال شده
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=شرح
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -1694,6 +1694,7 @@ conan.details.repository=Repo
|
|||||||
owner.settings.cleanuprules.enabled=Käytössä
|
owner.settings.cleanuprules.enabled=Käytössä
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Kuvaus
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -3705,6 +3705,7 @@ secrets=Secrets
|
|||||||
description=Les secrets seront transmis à certaines actions et ne pourront pas être lus autrement.
|
description=Les secrets seront transmis à certaines actions et ne pourront pas être lus autrement.
|
||||||
none=Il n'y a pas encore de secrets.
|
none=Il n'y a pas encore de secrets.
|
||||||
creation=Ajouter un secret
|
creation=Ajouter un secret
|
||||||
|
creation.description=Description
|
||||||
creation.name_placeholder=Caractères alphanumériques ou tirets bas uniquement, insensibles à la casse, ne peut commencer par GITEA_ ou GITHUB_.
|
creation.name_placeholder=Caractères alphanumériques ou tirets bas uniquement, insensibles à la casse, ne peut commencer par GITEA_ ou GITHUB_.
|
||||||
creation.value_placeholder=Entrez n’importe quoi. Les blancs cernant seront taillés.
|
creation.value_placeholder=Entrez n’importe quoi. Les blancs cernant seront taillés.
|
||||||
creation.success=Le secret "%s" a été ajouté.
|
creation.success=Le secret "%s" a été ajouté.
|
||||||
|
@ -3705,6 +3705,7 @@ secrets=Rúin
|
|||||||
description=Cuirfear rúin ar aghaidh chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt.
|
description=Cuirfear rúin ar aghaidh chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt.
|
||||||
none=Níl aon rúin ann fós.
|
none=Níl aon rúin ann fós.
|
||||||
creation=Cuir Rúnda leis
|
creation=Cuir Rúnda leis
|
||||||
|
creation.description=Cur síos
|
||||||
creation.name_placeholder=carachtair alfanumair nó íoslaghda amháin nach féidir a thosú le GITEA_ nó GITHUB_
|
creation.name_placeholder=carachtair alfanumair nó íoslaghda amháin nach féidir a thosú le GITEA_ nó GITHUB_
|
||||||
creation.value_placeholder=Ionchur ábhar ar bith. Fágfar spás bán ag tús agus ag deireadh ar lár.
|
creation.value_placeholder=Ionchur ábhar ar bith. Fágfar spás bán ag tús agus ag deireadh ar lár.
|
||||||
creation.success=Tá an rún "%s" curtha leis.
|
creation.success=Tá an rún "%s" curtha leis.
|
||||||
|
@ -1598,6 +1598,7 @@ conan.details.repository=Tároló
|
|||||||
owner.settings.cleanuprules.enabled=Engedélyezett
|
owner.settings.cleanuprules.enabled=Engedélyezett
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Leírás
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -1398,6 +1398,7 @@ conan.details.repository=Repositori
|
|||||||
owner.settings.cleanuprules.enabled=Aktif
|
owner.settings.cleanuprules.enabled=Aktif
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Deskripsi
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -1326,6 +1326,7 @@ npm.details.tag=Merki
|
|||||||
pypi.requires=Þarfnast Python
|
pypi.requires=Þarfnast Python
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Lýsing
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -2790,6 +2790,7 @@ settings.delete.error=Impossibile eliminare il pacchetto.
|
|||||||
owner.settings.cleanuprules.enabled=Attivo
|
owner.settings.cleanuprules.enabled=Attivo
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Descrizione
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -3699,6 +3699,7 @@ secrets=シークレット
|
|||||||
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
||||||
none=シークレットはまだありません。
|
none=シークレットはまだありません。
|
||||||
creation=シークレットを追加
|
creation=シークレットを追加
|
||||||
|
creation.description=説明
|
||||||
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
||||||
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
||||||
creation.success=シークレット "%s" を追加しました。
|
creation.success=シークレット "%s" を追加しました。
|
||||||
|
@ -1547,6 +1547,7 @@ conan.details.repository=저장소
|
|||||||
owner.settings.cleanuprules.enabled=활성화됨
|
owner.settings.cleanuprules.enabled=활성화됨
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=설명
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -3341,6 +3341,7 @@ secrets=Noslēpumi
|
|||||||
description=Noslēpumi tiks padoti atsevišķām darbībām un citādi nevar tikt nolasīti.
|
description=Noslēpumi tiks padoti atsevišķām darbībām un citādi nevar tikt nolasīti.
|
||||||
none=Pagaidām nav neviena noslēpuma.
|
none=Pagaidām nav neviena noslēpuma.
|
||||||
creation=Pievienot noslēpumu
|
creation=Pievienot noslēpumu
|
||||||
|
creation.description=Apraksts
|
||||||
creation.name_placeholder=reģistr-nejūtīgs, tikai burti, cipari un apakšsvītras, nevar sākties ar GITEA_ vai GITHUB_
|
creation.name_placeholder=reģistr-nejūtīgs, tikai burti, cipari un apakšsvītras, nevar sākties ar GITEA_ vai GITHUB_
|
||||||
creation.value_placeholder=Ievadiet jebkādu saturu. Atstarpes sākumā un beigā tiks noņemtas.
|
creation.value_placeholder=Ievadiet jebkādu saturu. Atstarpes sākumā un beigā tiks noņemtas.
|
||||||
creation.success=Noslēpums "%s" tika pievienots.
|
creation.success=Noslēpums "%s" tika pievienots.
|
||||||
|
@ -2523,6 +2523,7 @@ settings.link.button=Repository link bijwerken
|
|||||||
owner.settings.cleanuprules.enabled=Ingeschakeld
|
owner.settings.cleanuprules.enabled=Ingeschakeld
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Omschrijving
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -2412,6 +2412,7 @@ conan.details.repository=Repozytorium
|
|||||||
owner.settings.cleanuprules.enabled=Włączone
|
owner.settings.cleanuprules.enabled=Włączone
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Opis
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -2194,7 +2194,7 @@ settings.protect_check_status_contexts_list=Verificações de status encontradas
|
|||||||
settings.protect_required_approvals=Aprovações necessárias:
|
settings.protect_required_approvals=Aprovações necessárias:
|
||||||
settings.dismiss_stale_approvals=Descartar aprovações obsoletas
|
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=Exigir 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_branch_name_pattern=Padrão de Nome de Branch Protegida
|
||||||
settings.protect_patterns=Padrões
|
settings.protect_patterns=Padrões
|
||||||
@ -3278,6 +3278,7 @@ secrets=Segredos
|
|||||||
description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma.
|
description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma.
|
||||||
none=Não há segredos ainda.
|
none=Não há segredos ainda.
|
||||||
creation=Adicionar Segredo
|
creation=Adicionar Segredo
|
||||||
|
creation.description=Descrição
|
||||||
creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), não pode começar com GITEA_ ou GITHUB_
|
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.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.
|
||||||
|
@ -113,6 +113,7 @@ copy_type_unsupported=Este tipo de ficheiro não pode ser copiado
|
|||||||
write=Escrever
|
write=Escrever
|
||||||
preview=Pré-visualizar
|
preview=Pré-visualizar
|
||||||
loading=Carregando…
|
loading=Carregando…
|
||||||
|
files=Ficheiros
|
||||||
|
|
||||||
error=Erro
|
error=Erro
|
||||||
error404=A página que pretende aceder <strong>não existe</strong> ou <strong>não tem autorização</strong> para a ver.
|
error404=A página que pretende aceder <strong>não existe</strong> ou <strong>não tem autorização</strong> para a ver.
|
||||||
@ -3710,8 +3711,10 @@ secrets=Segredos
|
|||||||
description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma.
|
description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma.
|
||||||
none=Ainda não há segredos.
|
none=Ainda não há segredos.
|
||||||
creation=Adicionar segredo
|
creation=Adicionar segredo
|
||||||
|
creation.description=Descrição
|
||||||
creation.name_placeholder=Só sublinhados ou alfanuméricos sem distinguir maiúsculas, sem começar com GITEA_ nem GITHUB_
|
creation.name_placeholder=Só sublinhados ou alfanuméricos sem distinguir maiúsculas, sem começar com GITEA_ nem GITHUB_
|
||||||
creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos.
|
creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos.
|
||||||
|
creation.description_placeholder=Escreva uma descrição curta (opcional).
|
||||||
creation.success=O segredo "%s" foi adicionado.
|
creation.success=O segredo "%s" foi adicionado.
|
||||||
creation.failed=Falhou ao adicionar o segredo.
|
creation.failed=Falhou ao adicionar o segredo.
|
||||||
deletion=Remover segredo
|
deletion=Remover segredo
|
||||||
|
@ -3275,6 +3275,7 @@ secrets=Секреты
|
|||||||
description=Секреты будут передаваться определенным действиям и не могут быть прочитаны иначе.
|
description=Секреты будут передаваться определенным действиям и не могут быть прочитаны иначе.
|
||||||
none=Секретов пока нет.
|
none=Секретов пока нет.
|
||||||
creation=Добавить секрет
|
creation=Добавить секрет
|
||||||
|
creation.description=Описание
|
||||||
creation.name_placeholder=регистр не важен, только алфавитно-цифровые символы и подчёркивания, не может начинаться с GITEA_ или GITHUB_
|
creation.name_placeholder=регистр не важен, только алфавитно-цифровые символы и подчёркивания, не может начинаться с GITEA_ или GITHUB_
|
||||||
creation.value_placeholder=Введите любое содержимое. Пробельные символы в начале и конце будут опущены.
|
creation.value_placeholder=Введите любое содержимое. Пробельные символы в начале и конце будут опущены.
|
||||||
creation.success=Секрет «%s» добавлен.
|
creation.success=Секрет «%s» добавлен.
|
||||||
|
@ -2454,6 +2454,7 @@ conan.details.repository=කෝෂ්ඨය
|
|||||||
owner.settings.cleanuprules.enabled=සබල කර ඇත
|
owner.settings.cleanuprules.enabled=සබල කර ඇත
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=සවිස්තරය
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -1989,6 +1989,7 @@ conan.details.repository=Utvecklingskatalog
|
|||||||
owner.settings.cleanuprules.enabled=Aktiv
|
owner.settings.cleanuprules.enabled=Aktiv
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Beskrivning
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -3534,6 +3534,7 @@ secrets=Gizlilikler
|
|||||||
description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
|
description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
|
||||||
none=Henüz gizlilik yok.
|
none=Henüz gizlilik yok.
|
||||||
creation=Gizlilik Ekle
|
creation=Gizlilik Ekle
|
||||||
|
creation.description=Açıklama
|
||||||
creation.name_placeholder=küçük-büyük harfe duyarlı değil, alfanümerik karakterler veya sadece alt tire, GITEA_ veya GITHUB_ ile başlayamaz
|
creation.name_placeholder=küçük-büyük harfe duyarlı değil, alfanümerik karakterler veya sadece alt tire, GITEA_ veya GITHUB_ ile başlayamaz
|
||||||
creation.value_placeholder=Herhangi bir içerik girin. Baştaki ve sondaki boşluklar ihmal edilecektir.
|
creation.value_placeholder=Herhangi bir içerik girin. Baştaki ve sondaki boşluklar ihmal edilecektir.
|
||||||
creation.success=Gizlilik "%s" eklendi.
|
creation.success=Gizlilik "%s" eklendi.
|
||||||
|
@ -2524,6 +2524,7 @@ conan.details.repository=Репозиторій
|
|||||||
owner.settings.cleanuprules.enabled=Увімкнено
|
owner.settings.cleanuprules.enabled=Увімкнено
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=Опис
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ edit=编辑
|
|||||||
view=查看
|
view=查看
|
||||||
test=测试
|
test=测试
|
||||||
|
|
||||||
enabled=启用
|
enabled=已启用
|
||||||
disabled=禁用
|
disabled=已禁用
|
||||||
locked=已锁定
|
locked=已锁定
|
||||||
|
|
||||||
copy=复制
|
copy=复制
|
||||||
@ -148,7 +148,7 @@ name=名称
|
|||||||
value=值
|
value=值
|
||||||
readme=自述文档
|
readme=自述文档
|
||||||
|
|
||||||
filter=过滤
|
filter=筛选
|
||||||
filter.clear=清除筛选器
|
filter.clear=清除筛选器
|
||||||
filter.is_archived=已归档
|
filter.is_archived=已归档
|
||||||
filter.not_archived=非存档
|
filter.not_archived=非存档
|
||||||
@ -159,7 +159,7 @@ filter.not_mirror=非镜像
|
|||||||
filter.is_template=模板
|
filter.is_template=模板
|
||||||
filter.not_template=非模板
|
filter.not_template=非模板
|
||||||
filter.public=公开
|
filter.public=公开
|
||||||
filter.private=私有库
|
filter.private=私有
|
||||||
|
|
||||||
no_results_found=未找到结果
|
no_results_found=未找到结果
|
||||||
internal_error_skipped=发生内部错误,但已被跳过: %s
|
internal_error_skipped=发生内部错误,但已被跳过: %s
|
||||||
@ -245,6 +245,7 @@ license_desc=所有的代码都开源在 <a target="_blank" rel="noopener norefe
|
|||||||
|
|
||||||
[install]
|
[install]
|
||||||
install=安装页面
|
install=安装页面
|
||||||
|
installing_desc=正在安装,请稍候...
|
||||||
title=初始配置
|
title=初始配置
|
||||||
docker_helper=如果您正在使用 Docker 容器运行 Gitea,请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
|
docker_helper=如果您正在使用 Docker 容器运行 Gitea,请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
|
||||||
require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
|
require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
|
||||||
@ -2870,7 +2871,7 @@ authentication=认证源
|
|||||||
emails=用户邮件
|
emails=用户邮件
|
||||||
config=应用配置
|
config=应用配置
|
||||||
config_summary=摘要
|
config_summary=摘要
|
||||||
config_settings=组织设置
|
config_settings=设置
|
||||||
notices=系统提示
|
notices=系统提示
|
||||||
monitor=监控面板
|
monitor=监控面板
|
||||||
first_page=首页
|
first_page=首页
|
||||||
@ -3349,6 +3350,7 @@ monitor.previous=上次执行时间
|
|||||||
monitor.execute_times=执行次数
|
monitor.execute_times=执行次数
|
||||||
monitor.process=运行中进程
|
monitor.process=运行中进程
|
||||||
monitor.stacktrace=调用栈踪迹
|
monitor.stacktrace=调用栈踪迹
|
||||||
|
monitor.performance_logs=性能日志
|
||||||
monitor.processes_count=%d 个进程
|
monitor.processes_count=%d 个进程
|
||||||
monitor.download_diagnosis_report=下载诊断报告
|
monitor.download_diagnosis_report=下载诊断报告
|
||||||
monitor.desc=进程描述
|
monitor.desc=进程描述
|
||||||
@ -3529,12 +3531,12 @@ alpine.registry.info=从下面的列表中选择 $branch 和 $repository。
|
|||||||
alpine.install=要安装包,请运行以下命令:
|
alpine.install=要安装包,请运行以下命令:
|
||||||
alpine.repository=仓库信息
|
alpine.repository=仓库信息
|
||||||
alpine.repository.branches=分支
|
alpine.repository.branches=分支
|
||||||
alpine.repository.repositories=仓库管理
|
alpine.repository.repositories=仓库
|
||||||
alpine.repository.architectures=架构
|
alpine.repository.architectures=架构
|
||||||
arch.registry=添加具有相关仓库和架构的服务器到 <code>/etc/pacman.conf</code> 中:
|
arch.registry=添加具有相关仓库和架构的服务器到 <code>/etc/pacman.conf</code> 中:
|
||||||
arch.install=使用 pacman 同步软件包:
|
arch.install=使用 pacman 同步软件包:
|
||||||
arch.repository=仓库信息
|
arch.repository=仓库信息
|
||||||
arch.repository.repositories=仓库管理
|
arch.repository.repositories=仓库
|
||||||
arch.repository.architectures=架构
|
arch.repository.architectures=架构
|
||||||
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
|
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
|
||||||
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
|
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
|
||||||
@ -3552,6 +3554,7 @@ conda.install=要使用 Conda 安装软件包,请运行以下命令:
|
|||||||
container.details.type=镜像类型
|
container.details.type=镜像类型
|
||||||
container.details.platform=平台
|
container.details.platform=平台
|
||||||
container.pull=从命令行拉取镜像:
|
container.pull=从命令行拉取镜像:
|
||||||
|
container.images=镜像
|
||||||
container.multi_arch=OS / Arch
|
container.multi_arch=OS / Arch
|
||||||
container.layers=镜像层
|
container.layers=镜像层
|
||||||
container.labels=标签
|
container.labels=标签
|
||||||
@ -3655,6 +3658,7 @@ secrets=密钥
|
|||||||
description=Secrets 将被传给特定的 Actions,其它情况将不能读取
|
description=Secrets 将被传给特定的 Actions,其它情况将不能读取
|
||||||
none=还没有密钥。
|
none=还没有密钥。
|
||||||
creation=添加密钥
|
creation=添加密钥
|
||||||
|
creation.description=组织描述
|
||||||
creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
|
creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
|
||||||
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
|
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
|
||||||
creation.success=您的密钥 '%s' 添加成功。
|
creation.success=您的密钥 '%s' 添加成功。
|
||||||
|
@ -963,6 +963,7 @@ conan.details.repository=儲存庫
|
|||||||
owner.settings.cleanuprules.enabled=已啟用
|
owner.settings.cleanuprules.enabled=已啟用
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
creation.description=組織描述
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
|
||||||
|
@ -3646,6 +3646,7 @@ secrets=Secret
|
|||||||
description=Secret 會被傳給特定的 Action,其他情況無法讀取。
|
description=Secret 會被傳給特定的 Action,其他情況無法讀取。
|
||||||
none=還沒有 Secret。
|
none=還沒有 Secret。
|
||||||
creation=加入 Secret
|
creation=加入 Secret
|
||||||
|
creation.description=描述
|
||||||
creation.name_placeholder=不區分大小寫,只能包含英文字母、數字、底線 ('_'),不能以 GITEA_ 或 GITHUB_ 開頭。
|
creation.name_placeholder=不區分大小寫,只能包含英文字母、數字、底線 ('_'),不能以 GITEA_ 或 GITHUB_ 開頭。
|
||||||
creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
|
creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
|
||||||
creation.success=已新增 Secret「%s」。
|
creation.success=已新增 Secret「%s」。
|
||||||
|
@ -62,6 +62,7 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
|
|||||||
for k, v := range secrets {
|
for k, v := range secrets {
|
||||||
apiSecrets[k] = &api.Secret{
|
apiSecrets[k] = &api.Secret{
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
|
Description: v.Description,
|
||||||
Created: v.CreatedUnix.AsTime(),
|
Created: v.CreatedUnix.AsTime(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +107,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
|
|||||||
|
|
||||||
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
||||||
|
|
||||||
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data)
|
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
@ -234,6 +235,7 @@ func (Action) ListVariables(ctx *context.APIContext) {
|
|||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Data: v.Data,
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,6 +287,7 @@ func (Action) GetVariable(ctx *context.APIContext) {
|
|||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Data: v.Data,
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, variable)
|
ctx.JSON(http.StatusOK, variable)
|
||||||
@ -386,7 +389,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value); err != nil {
|
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value, opt.Description); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
} else {
|
} else {
|
||||||
@ -453,6 +456,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
|
|||||||
|
|
||||||
v.Name = opt.Name
|
v.Name = opt.Name
|
||||||
v.Data = opt.Value
|
v.Data = opt.Value
|
||||||
|
v.Description = opt.Description
|
||||||
|
|
||||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
|
@ -85,6 +85,7 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
|
|||||||
for k, v := range secrets {
|
for k, v := range secrets {
|
||||||
apiSecrets[k] = &api.Secret{
|
apiSecrets[k] = &api.Secret{
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
|
Description: v.Description,
|
||||||
Created: v.CreatedUnix.AsTime(),
|
Created: v.CreatedUnix.AsTime(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +137,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
|
|||||||
|
|
||||||
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
||||||
|
|
||||||
_, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data)
|
_, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data, opt.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
@ -253,6 +254,7 @@ func (Action) GetVariable(ctx *context.APIContext) {
|
|||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Data: v.Data,
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, variable)
|
ctx.JSON(http.StatusOK, variable)
|
||||||
@ -362,7 +364,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value); err != nil {
|
if _, err := actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value, opt.Description); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
} else {
|
} else {
|
||||||
@ -432,6 +434,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
|
|||||||
|
|
||||||
v.Name = opt.Name
|
v.Name = opt.Name
|
||||||
v.Data = opt.Value
|
v.Data = opt.Value
|
||||||
|
v.Description = opt.Description
|
||||||
|
|
||||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
@ -494,6 +497,8 @@ func (Action) ListVariables(ctx *context.APIContext) {
|
|||||||
OwnerID: v.OwnerID,
|
OwnerID: v.OwnerID,
|
||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
|
|||||||
// findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error.
|
// findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error.
|
||||||
// The caller is responsible for closing the returned repo again
|
// The caller is responsible for closing the returned repo again
|
||||||
func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) {
|
func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) {
|
||||||
wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
wikiRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if git.IsErrNotExist(err) || err.Error() == "no such file or directory" {
|
if git.IsErrNotExist(err) || err.Error() == "no such file or directory" {
|
||||||
ctx.APIErrorNotFound(err)
|
ctx.APIErrorNotFound(err)
|
||||||
|
@ -49,7 +49,7 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
|
|||||||
|
|
||||||
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
||||||
|
|
||||||
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Doer.ID, 0, ctx.PathParam("secretname"), opt.Data)
|
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Doer.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
@ -153,7 +153,7 @@ func CreateVariable(ctx *context.APIContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value); err != nil {
|
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value, opt.Description); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
ctx.APIError(http.StatusBadRequest, err)
|
ctx.APIError(http.StatusBadRequest, err)
|
||||||
} else {
|
} else {
|
||||||
@ -215,6 +215,7 @@ func UpdateVariable(ctx *context.APIContext) {
|
|||||||
|
|
||||||
v.Name = opt.Name
|
v.Name = opt.Name
|
||||||
v.Data = opt.Value
|
v.Data = opt.Value
|
||||||
|
v.Description = opt.Description
|
||||||
|
|
||||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||||
if errors.Is(err, util.ErrInvalidArgument) {
|
if errors.Is(err, util.ErrInvalidArgument) {
|
||||||
@ -304,6 +305,7 @@ func GetVariable(ctx *context.APIContext) {
|
|||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Data: v.Data,
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, variable)
|
ctx.JSON(http.StatusOK, variable)
|
||||||
@ -349,6 +351,7 @@ func ListVariables(ctx *context.APIContext) {
|
|||||||
RepoID: v.RepoID,
|
RepoID: v.RepoID,
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Data: v.Data,
|
Data: v.Data,
|
||||||
|
Description: v.Description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ func Diff(ctx *context.Context) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if ctx.Data["PageIsWiki"] != nil {
|
if ctx.Data["PageIsWiki"] != nil {
|
||||||
gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("Repo.GitRepo.GetCommit", err)
|
ctx.ServerError("Repo.GitRepo.GetCommit", err)
|
||||||
return
|
return
|
||||||
@ -417,7 +417,7 @@ func Diff(ctx *context.Context) {
|
|||||||
func RawDiff(ctx *context.Context) {
|
func RawDiff(ctx *context.Context) {
|
||||||
var gitRepo *git.Repository
|
var gitRepo *git.Repository
|
||||||
if ctx.Data["PageIsWiki"] != nil {
|
if ctx.Data["PageIsWiki"] != nil {
|
||||||
wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
wikiRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("OpenRepository", err)
|
ctx.ServerError("OpenRepository", err)
|
||||||
return
|
return
|
||||||
|
@ -885,7 +885,7 @@ func ExcerptBlob(ctx *context.Context) {
|
|||||||
gitRepo := ctx.Repo.GitRepo
|
gitRepo := ctx.Repo.GitRepo
|
||||||
if ctx.Data["PageIsWiki"] == true {
|
if ctx.Data["PageIsWiki"] == true {
|
||||||
var err error
|
var err error
|
||||||
gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("OpenRepository", err)
|
ctx.ServerError("OpenRepository", err)
|
||||||
return
|
return
|
||||||
|
@ -96,7 +96,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
|
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
|
||||||
wikiGitRepo, errGitRepo := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
wikiGitRepo, errGitRepo := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if errGitRepo != nil {
|
if errGitRepo != nil {
|
||||||
ctx.ServerError("OpenRepository", errGitRepo)
|
ctx.ServerError("OpenRepository", errGitRepo)
|
||||||
return nil, nil, errGitRepo
|
return nil, nil, errGitRepo
|
||||||
@ -105,7 +105,7 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err
|
|||||||
commit, errCommit := wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
|
commit, errCommit := wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
|
||||||
if git.IsErrNotExist(errCommit) {
|
if git.IsErrNotExist(errCommit) {
|
||||||
// if the default branch recorded in database is out of sync, then re-sync it
|
// if the default branch recorded in database is out of sync, then re-sync it
|
||||||
gitRepoDefaultBranch, errBranch := gitrepo.GetWikiDefaultBranch(ctx, ctx.Repo.Repository)
|
gitRepoDefaultBranch, errBranch := gitrepo.GetDefaultBranch(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||||
if errBranch != nil {
|
if errBranch != nil {
|
||||||
return wikiGitRepo, nil, errBranch
|
return wikiGitRepo, nil, errBranch
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry {
|
func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry {
|
||||||
wikiRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
wikiRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer wikiRepo.Close()
|
defer wikiRepo.Close()
|
||||||
commit, err := wikiRepo.GetBranchCommit("master")
|
commit, err := wikiRepo.GetBranchCommit("master")
|
||||||
|
@ -106,7 +106,8 @@ func Variables(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Variables"] = variables
|
ctx.Data["Variables"] = variables
|
||||||
|
ctx.Data["DataMaxLength"] = actions_model.VariableDataMaxLength
|
||||||
|
ctx.Data["DescriptionMaxLength"] = actions_model.VariableDescriptionMaxLength
|
||||||
ctx.HTML(http.StatusOK, vCtx.VariablesTemplate)
|
ctx.HTML(http.StatusOK, vCtx.VariablesTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ func VariableCreate(ctx *context.Context) {
|
|||||||
|
|
||||||
form := web.GetForm(ctx).(*forms.EditVariableForm)
|
form := web.GetForm(ctx).(*forms.EditVariableForm)
|
||||||
|
|
||||||
v, err := actions_service.CreateVariable(ctx, vCtx.OwnerID, vCtx.RepoID, form.Name, form.Data)
|
v, err := actions_service.CreateVariable(ctx, vCtx.OwnerID, vCtx.RepoID, form.Name, form.Data, form.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("CreateVariable: %v", err)
|
log.Error("CreateVariable: %v", err)
|
||||||
ctx.JSONError(ctx.Tr("actions.variables.creation.failed"))
|
ctx.JSONError(ctx.Tr("actions.variables.creation.failed"))
|
||||||
@ -157,6 +158,7 @@ func VariableUpdate(ctx *context.Context) {
|
|||||||
form := web.GetForm(ctx).(*forms.EditVariableForm)
|
form := web.GetForm(ctx).(*forms.EditVariableForm)
|
||||||
variable.Name = form.Name
|
variable.Name = form.Name
|
||||||
variable.Data = form.Data
|
variable.Data = form.Data
|
||||||
|
variable.Description = form.Description
|
||||||
|
|
||||||
if ok, err := actions_service.UpdateVariableNameData(ctx, variable); err != nil || !ok {
|
if ok, err := actions_service.UpdateVariableNameData(ctx, variable); err != nil || !ok {
|
||||||
log.Error("UpdateVariable: %v", err)
|
log.Error("UpdateVariable: %v", err)
|
||||||
|
@ -22,12 +22,14 @@ func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Secrets"] = secrets
|
ctx.Data["Secrets"] = secrets
|
||||||
|
ctx.Data["DataMaxLength"] = secret_model.SecretDataMaxLength
|
||||||
|
ctx.Data["DescriptionMaxLength"] = secret_model.SecretDescriptionMaxLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
|
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
|
||||||
form := web.GetForm(ctx).(*forms.AddSecretForm)
|
form := web.GetForm(ctx).(*forms.AddSecretForm)
|
||||||
|
|
||||||
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data))
|
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data), form.Description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("CreateOrUpdateSecret failed: %v", err)
|
log.Error("CreateOrUpdateSecret failed: %v", err)
|
||||||
ctx.JSONError(ctx.Tr("secrets.creation.failed"))
|
ctx.JSONError(ctx.Tr("secrets.creation.failed"))
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
secret_service "code.gitea.io/gitea/services/secrets"
|
secret_service "code.gitea.io/gitea/services/secrets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*actions_model.ActionVariable, error) {
|
func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*actions_model.ActionVariable, error) {
|
||||||
if err := secret_service.ValidateName(name); err != nil {
|
if err := secret_service.ValidateName(name); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data strin
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := actions_model.InsertVariable(ctx, ownerID, repoID, name, util.ReserveLineBreakForTextarea(data))
|
v, err := actions_model.InsertVariable(ctx, ownerID, repoID, name, util.ReserveLineBreakForTextarea(data), description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ func UpdateVariableNameData(ctx context.Context, variable *actions_model.ActionV
|
|||||||
|
|
||||||
variable.Data = util.ReserveLineBreakForTextarea(variable.Data)
|
variable.Data = util.ReserveLineBreakForTextarea(variable.Data)
|
||||||
|
|
||||||
return actions_model.UpdateVariableCols(ctx, variable, "name", "data")
|
return actions_model.UpdateVariableCols(ctx, variable, "name", "data", "description")
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteVariableByID(ctx context.Context, variableID int64) error {
|
func DeleteVariableByID(ctx context.Context, variableID int64) error {
|
||||||
|
@ -204,7 +204,7 @@ Loop:
|
|||||||
return false, "", nil, &ErrWontSign{twofa}
|
return false, "", nil, &ErrWontSign{twofa}
|
||||||
}
|
}
|
||||||
case parentSigned:
|
case parentSigned:
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
|
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", nil, err
|
return false, "", nil, err
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,14 @@ func checkScriptType(ctx context.Context, logger log.Logger, autofix bool) error
|
|||||||
|
|
||||||
func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error {
|
func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||||
if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
|
if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
|
||||||
results, err := gitrepo.CheckDelegateHooksForRepo(ctx, repo)
|
results, err := gitrepo.CheckDelegateHooks(ctx, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Critical("Unable to check delegate hooks for repo %-v. ERROR: %v", repo, err)
|
logger.Critical("Unable to check delegate hooks for repo %-v. ERROR: %v", repo, err)
|
||||||
return fmt.Errorf("Unable to check delegate hooks for repo %-v. ERROR: %w", repo, err)
|
return fmt.Errorf("Unable to check delegate hooks for repo %-v. ERROR: %w", repo, err)
|
||||||
}
|
}
|
||||||
if len(results) > 0 && autofix {
|
if len(results) > 0 && autofix {
|
||||||
logger.Warn("Regenerated hooks for %s", repo.FullName())
|
logger.Warn("Regenerated hooks for %s", repo.FullName())
|
||||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
logger.Critical("Unable to recreate delegate hooks for %-v. ERROR: %v", repo, err)
|
logger.Critical("Unable to recreate delegate hooks for %-v. ERROR: %v", repo, err)
|
||||||
return fmt.Errorf("Unable to recreate delegate hooks for %-v. ERROR: %w", repo, err)
|
return fmt.Errorf("Unable to recreate delegate hooks for %-v. ERROR: %w", repo, err)
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,7 @@ func (f *AddKeyForm) Validate(req *http.Request, errs binding.Errors) binding.Er
|
|||||||
type AddSecretForm struct {
|
type AddSecretForm struct {
|
||||||
Name string `binding:"Required;MaxSize(255)"`
|
Name string `binding:"Required;MaxSize(255)"`
|
||||||
Data string `binding:"Required;MaxSize(65535)"`
|
Data string `binding:"Required;MaxSize(65535)"`
|
||||||
|
Description string `binding:"MaxSize(65535)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
@ -336,6 +337,7 @@ func (f *AddSecretForm) Validate(req *http.Request, errs binding.Errors) binding
|
|||||||
type EditVariableForm struct {
|
type EditVariableForm struct {
|
||||||
Name string `binding:"Required;MaxSize(255)"`
|
Name string `binding:"Required;MaxSize(255)"`
|
||||||
Data string `binding:"Required;MaxSize(65535)"`
|
Data string `binding:"Required;MaxSize(65535)"`
|
||||||
|
Description string `binding:"MaxSize(65535)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *EditVariableForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
|
func (f *EditVariableForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
|
||||||
|
@ -1253,6 +1253,8 @@ func GetDiffForRender(ctx context.Context, gitRepo *git.Repository, opts *DiffOp
|
|||||||
if language.Has() {
|
if language.Has() {
|
||||||
diffFile.Language = language.Value()
|
diffFile.Language = language.Value()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
checker = nil // CheckPath fails, it's not impossible to "check" anymore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
|
|||||||
|
|
||||||
var gitRepo *git.Repository
|
var gitRepo *git.Repository
|
||||||
if isWiki {
|
if isWiki {
|
||||||
gitRepo, err = gitrepo.OpenWikiRepository(ctx, repo)
|
gitRepo, err = gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||||
} else {
|
} else {
|
||||||
gitRepo, err = gitrepo.OpenRepository(ctx, repo)
|
gitRepo, err = gitrepo.OpenRepository(ctx, repo)
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBr
|
|||||||
return fmt.Errorf("adoptRepository: path does not already exist: %s", repo.FullName())
|
return fmt.Errorf("adoptRepository: path does not already exist: %s", repo.FullName())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
|
|||||||
return fmt.Errorf("git update-server-info: %w", err)
|
return fmt.Errorf("git update-server-info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
if err = gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,16 +31,16 @@ func SyncRepositoryHooks(ctx context.Context) error {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
return fmt.Errorf("CreateDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
exist, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
|
exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
if err := gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
|
||||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
return fmt.Errorf("CreateDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -265,16 +265,16 @@ func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error {
|
|||||||
|
|
||||||
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
|
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
|
||||||
func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) {
|
func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) {
|
||||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||||
return repo, fmt.Errorf("createDelegateHooks: %w", err)
|
return repo, fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasWiki, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
|
hasWiki, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, fmt.Errorf("IsWikiRepositoryExist: %w", err)
|
return repo, fmt.Errorf("IsWikiRepositoryExist: %w", err)
|
||||||
}
|
}
|
||||||
if hasWiki {
|
if hasWiki {
|
||||||
if err := gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
|
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
|
||||||
return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err)
|
return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,12 +331,13 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
|
|||||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return repo_model.ErrRepoAlreadyExist{
|
return repo_model.ErrRepoAlreadyExist{
|
||||||
Uname: repo.Owner.Name,
|
Uname: repo.OwnerName,
|
||||||
Name: newRepoName,
|
Name: newRepoName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = gitrepo.RenameRepository(ctx, repo, newRepoName); err != nil {
|
if err = gitrepo.RenameRepository(ctx, repo,
|
||||||
|
repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, newRepoName))); err != nil {
|
||||||
return fmt.Errorf("rename repository directory: %w", err)
|
return fmt.Errorf("rename repository directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
secret_model "code.gitea.io/gitea/models/secret"
|
secret_model "code.gitea.io/gitea/models/secret"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*secret_model.Secret, bool, error) {
|
func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*secret_model.Secret, bool, error) {
|
||||||
if err := ValidateName(name); err != nil {
|
if err := ValidateName(name); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -25,14 +25,14 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, name, data)
|
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, name, data, description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
return s, true, nil
|
return s, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := secret_model.UpdateSecret(ctx, s[0].ID, data); err != nil {
|
if err := secret_model.UpdateSecret(ctx, s[0].ID, data, description); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
|
|||||||
|
|
||||||
if err := git.InitRepository(ctx, repo.WikiPath(), true, repo.ObjectFormatName); err != nil {
|
if err := git.InitRepository(ctx, repo.WikiPath(), true, repo.ObjectFormatName); err != nil {
|
||||||
return fmt.Errorf("InitRepository: %w", err)
|
return fmt.Errorf("InitRepository: %w", err)
|
||||||
} else if err = gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
|
} else if err = gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
} else if _, _, err = git.NewCommand("symbolic-ref", "HEAD").AddDynamicArguments(git.BranchPrefix+repo.DefaultWikiBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.WikiPath()}); err != nil {
|
} else if _, _, err = git.NewCommand("symbolic-ref", "HEAD").AddDynamicArguments(git.BranchPrefix+repo.DefaultWikiBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.WikiPath()}); err != nil {
|
||||||
return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err)
|
return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err)
|
||||||
@ -102,7 +102,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||||||
return fmt.Errorf("InitWiki: %w", err)
|
return fmt.Errorf("InitWiki: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasDefaultBranch := gitrepo.IsWikiBranchExist(ctx, repo, repo.DefaultWikiBranch)
|
hasDefaultBranch := gitrepo.IsBranchExist(ctx, repo.WikiStorageRepo(), repo.DefaultWikiBranch)
|
||||||
|
|
||||||
basePath, err := repo_module.CreateTemporaryPath("update-wiki")
|
basePath, err := repo_module.CreateTemporaryPath("update-wiki")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -392,7 +392,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo)
|
oldDefBranch, err := gitrepo.GetDefaultBranch(ctx, repo.WikiStorageRepo())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get default branch: %w", err)
|
return fmt.Errorf("unable to get default branch: %w", err)
|
||||||
}
|
}
|
||||||
@ -400,7 +400,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
|
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||||
if errors.Is(err, util.ErrNotExist) {
|
if errors.Is(err, util.ErrNotExist) {
|
||||||
return nil // no git repo on storage, no need to do anything else
|
return nil // no git repo on storage, no need to do anything else
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -168,7 +168,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
|
|||||||
webPath := UserTitleToWebPath("", userTitle)
|
webPath := UserTitleToWebPath("", userTitle)
|
||||||
assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg))
|
assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg))
|
||||||
// Now need to show that the page has been added:
|
// Now need to show that the page has been added:
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
@ -215,7 +215,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
|
|||||||
assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg))
|
assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg))
|
||||||
|
|
||||||
// Now need to show that the page has been added:
|
// Now need to show that the page has been added:
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -239,7 +239,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
|||||||
assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home"))
|
assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home"))
|
||||||
|
|
||||||
// Now need to show that the page has been added:
|
// Now need to show that the page has been added:
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
@ -253,7 +253,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
|||||||
func TestPrepareWikiFileName(t *testing.T) {
|
func TestPrepareWikiFileName(t *testing.T) {
|
||||||
unittest.PrepareTestEnv(t)
|
unittest.PrepareTestEnv(t)
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
|
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
|
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="top aligned">{{$key}}</td>
|
<td class="tw-align-top">{{$key}}</td>
|
||||||
<td class="tw-break-anywhere">{{$value}}</td>
|
<td class="tw-break-anywhere">{{$value}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -63,14 +63,12 @@
|
|||||||
|
|
||||||
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
|
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
<div class="ui grid middle aligned">
|
<div>{{/* parent is flex, so use block here to keep sentence spaces */}}
|
||||||
<div class="ten wide column">
|
|
||||||
{{ctx.Locale.Tr "repo.org_labels_desc"}}
|
{{ctx.Locale.Tr "repo.org_labels_desc"}}
|
||||||
{{if .IsOrganizationOwner}}
|
{{if .IsOrganizationOwner}}
|
||||||
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
|
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{{range .OrgLabels}}
|
{{range .OrgLabels}}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="ui equal width compact grid">
|
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
|
||||||
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
|
<div class="flex-text-block" data-tooltip-content="{{$issueReferenceLink}}">
|
||||||
<div class="row tw-items-center" data-tooltip-content="{{$issueReferenceLink}}">
|
<span class="tw-flex-1 gt-ellipsis">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
|
||||||
<span class="text column truncate">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
|
<button class="ui compact tiny icon button" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
|
||||||
<button class="ui two wide button column tw-p-2" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="flex-text-block tw-mb-2">
|
<div class="flex-text-block repo-button-row">
|
||||||
<button class="ui compact tiny icon button"
|
<button class="ui compact basic icon button"
|
||||||
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="hide"
|
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="hide"
|
||||||
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.hide_file_tree"}}">
|
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.hide_file_tree"}}">
|
||||||
{{svg "octicon-sidebar-expand"}}
|
{{svg "octicon-sidebar-expand"}}
|
||||||
|
@ -14,19 +14,21 @@
|
|||||||
{{$entry := $item.Entry}}
|
{{$entry := $item.Entry}}
|
||||||
{{$commit := $item.Commit}}
|
{{$commit := $item.Commit}}
|
||||||
{{$submoduleFile := $item.SubmoduleFile}}
|
{{$submoduleFile := $item.SubmoduleFile}}
|
||||||
<div class="repo-file-cell name {{if not $commit}}notready{{end}}">
|
<div class="repo-file-cell name muted-links {{if not $commit}}notready{{end}}">
|
||||||
{{ctx.RenderUtils.RenderFileIcon $entry}}
|
{{ctx.RenderUtils.RenderFileIcon $entry}}
|
||||||
{{if $entry.IsSubModule}}
|
{{if $entry.IsSubModule}}
|
||||||
{{$submoduleLink := $submoduleFile.SubmoduleWebLink ctx}}
|
{{$submoduleLink := $submoduleFile.SubmoduleWebLink ctx}}
|
||||||
{{if $submoduleLink}}
|
{{if $submoduleLink}}
|
||||||
<a class="muted" href="{{$submoduleLink.RepoWebLink}}">{{$entry.Name}}</a> <span class="at">@</span> <a href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
|
<a class="entry-name" href="{{$submoduleLink.RepoWebLink}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
|
||||||
|
@ <a class="text primary" href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{$entry.Name}} <span class="at">@</span> {{ShortSha $submoduleFile.RefID}}
|
<span class="entry-name" title="{{$entry.Name}}">{{$entry.Name}}</span>
|
||||||
|
@ {{ShortSha $submoduleFile.RefID}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if $entry.IsDir}}
|
{{if $entry.IsDir}}
|
||||||
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
|
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
|
||||||
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
|
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
|
||||||
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
|
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
|
||||||
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
|
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
|
||||||
{{if eq $subJumpablePathFieldLast 0}}
|
{{if eq $subJumpablePathFieldLast 0}}
|
||||||
@ -37,7 +39,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
|
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
<div class="flex-item-title">
|
<div class="flex-item-title">
|
||||||
{{.Name}}
|
{{.Name}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
{{if .Description}}{{.Description}}{{else}}-{{end}}
|
||||||
|
</div>
|
||||||
<div class="flex-item-body">
|
<div class="flex-item-body">
|
||||||
******
|
******
|
||||||
</div>
|
</div>
|
||||||
@ -72,9 +75,20 @@
|
|||||||
<textarea required
|
<textarea required
|
||||||
id="secret-data"
|
id="secret-data"
|
||||||
name="data"
|
name="data"
|
||||||
|
maxlength="{{.DataMaxLength}}"
|
||||||
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label for="secret-description">{{ctx.Locale.Tr "secrets.creation.description"}}</label>
|
||||||
|
<textarea
|
||||||
|
id="secret-description"
|
||||||
|
name="description"
|
||||||
|
rows="2"
|
||||||
|
maxlength="{{.DescriptionMaxLength}}"
|
||||||
|
placeholder="{{ctx.Locale.Tr "secrets.creation.description_placeholder"}}"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||||
</form>
|
</form>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
data-modal-header="{{ctx.Locale.Tr "actions.variables.creation"}}"
|
data-modal-header="{{ctx.Locale.Tr "actions.variables.creation"}}"
|
||||||
data-modal-dialog-variable-name=""
|
data-modal-dialog-variable-name=""
|
||||||
data-modal-dialog-variable-data=""
|
data-modal-dialog-variable-data=""
|
||||||
|
data-modal-dialog-variable-description=""
|
||||||
>
|
>
|
||||||
{{ctx.Locale.Tr "actions.variables.creation"}}
|
{{ctx.Locale.Tr "actions.variables.creation"}}
|
||||||
</button>
|
</button>
|
||||||
@ -24,6 +25,9 @@
|
|||||||
<div class="flex-item-title">
|
<div class="flex-item-title">
|
||||||
{{.Name}}
|
{{.Name}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-item-body">
|
||||||
|
{{if .Description}}{{.Description}}{{else}}-{{end}}
|
||||||
|
</div>
|
||||||
<div class="flex-item-body">
|
<div class="flex-item-body">
|
||||||
{{.Data}}
|
{{.Data}}
|
||||||
</div>
|
</div>
|
||||||
@ -39,6 +43,7 @@
|
|||||||
data-modal-header="{{ctx.Locale.Tr "actions.variables.edit"}}"
|
data-modal-header="{{ctx.Locale.Tr "actions.variables.edit"}}"
|
||||||
data-modal-dialog-variable-name="{{.Name}}"
|
data-modal-dialog-variable-name="{{.Name}}"
|
||||||
data-modal-dialog-variable-data="{{.Data}}"
|
data-modal-dialog-variable-data="{{.Data}}"
|
||||||
|
data-modal-dialog-variable-description="{{.Description}}"
|
||||||
>
|
>
|
||||||
{{svg "octicon-pencil"}}
|
{{svg "octicon-pencil"}}
|
||||||
</button>
|
</button>
|
||||||
@ -82,9 +87,20 @@
|
|||||||
<textarea required
|
<textarea required
|
||||||
name="data"
|
name="data"
|
||||||
id="dialog-variable-data"
|
id="dialog-variable-data"
|
||||||
|
maxlength="{{.DataMaxLength}}"
|
||||||
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label for="dialog-variable-description">{{ctx.Locale.Tr "secrets.creation.description"}}</label>
|
||||||
|
<textarea
|
||||||
|
name="description"
|
||||||
|
id="dialog-variable-description"
|
||||||
|
rows="2"
|
||||||
|
maxlength="{{.DescriptionMaxLength}}"
|
||||||
|
placeholder="{{ctx.Locale.Tr "secrets.creation.description_placeholder"}}"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||||
</form>
|
</form>
|
||||||
|
25
templates/swagger/v1_json.tmpl
generated
25
templates/swagger/v1_json.tmpl
generated
@ -19325,6 +19325,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "Data"
|
"x-go-name": "Data"
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"description": "the description of the variable",
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Description"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"description": "the name of the variable",
|
"description": "the name of the variable",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -20988,6 +20993,11 @@
|
|||||||
"description": "Data of the secret to update",
|
"description": "Data of the secret to update",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "Data"
|
"x-go-name": "Data"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"description": "Description of the secret to update",
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Description"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
@ -21498,6 +21508,11 @@
|
|||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"description": "Description of the variable to create",
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Description"
|
||||||
|
},
|
||||||
"value": {
|
"value": {
|
||||||
"description": "Value of the variable to create",
|
"description": "Value of the variable to create",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -25459,6 +25474,11 @@
|
|||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"x-go-name": "Created"
|
"x-go-name": "Created"
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"description": "the secret's description",
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Description"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"description": "the secret's name",
|
"description": "the secret's name",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -26034,6 +26054,11 @@
|
|||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"description": "Description of the variable to update",
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Description"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"description": "New name for the variable. If the field is empty, the variable name won't be updated.",
|
"description": "New name for the variable. If the field is empty, the variable name won't be updated.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
<div class="inline field tw-text-center required">
|
<div class="inline field tw-text-center required">
|
||||||
<div id="captcha" data-captcha-type="g-recaptcha" class="g-recaptcha-style" data-sitekey="{{.RecaptchaSitekey}}"></div>
|
<div id="captcha" data-captcha-type="g-recaptcha" class="g-recaptcha-style" data-sitekey="{{.RecaptchaSitekey}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
|
<script defer src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
|
||||||
{{else if eq .CaptchaType "hcaptcha"}}
|
{{else if eq .CaptchaType "hcaptcha"}}
|
||||||
<div class="inline field tw-text-center required">
|
<div class="inline field tw-text-center required">
|
||||||
<div id="captcha" data-captcha-type="h-captcha" class="h-captcha-style" data-sitekey="{{.HcaptchaSitekey}}"></div>
|
<div id="captcha" data-captcha-type="h-captcha" class="h-captcha-style" data-sitekey="{{.HcaptchaSitekey}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src='https://hcaptcha.com/1/api.js'></script>
|
<script defer src='https://hcaptcha.com/1/api.js'></script>
|
||||||
{{else if eq .CaptchaType "mcaptcha"}}
|
{{else if eq .CaptchaType "mcaptcha"}}
|
||||||
<div class="inline field tw-text-center">
|
<div class="inline field tw-text-center">
|
||||||
<div class="m-captcha-style" id="mcaptcha__widget-container"></div>
|
<div class="m-captcha-style" id="mcaptcha__widget-container"></div>
|
||||||
@ -25,5 +25,5 @@
|
|||||||
<div class="inline field tw-text-center">
|
<div class="inline field tw-text-center">
|
||||||
<div id="captcha" data-captcha-type="cf-turnstile" data-sitekey="{{.CfTurnstileSitekey}}"></div>
|
<div id="captcha" data-captcha-type="cf-turnstile" data-sitekey="{{.CfTurnstileSitekey}}"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src='https://challenges.cloudflare.com/turnstile/v0/api.js'></script>
|
<script defer src='https://challenges.cloudflare.com/turnstile/v0/api.js'></script>
|
||||||
{{end}}{{end}}
|
{{end}}{{end}}
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if .Repos}}
|
{{if .Repos}}
|
||||||
<div class="ui middle aligned divided list">
|
<div class="ui list">
|
||||||
{{range .Repos}}
|
{{range .Repos}}
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="content flex-text-block">
|
<div class="content flex-text-block">
|
||||||
|
@ -27,21 +27,21 @@ func TestActionsVariables(t *testing.T) {
|
|||||||
require.NoError(t, db.DeleteAllRecords("action_variable"))
|
require.NoError(t, db.DeleteAllRecords("action_variable"))
|
||||||
|
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
_, _ = actions_model.InsertVariable(ctx, user2.ID, 0, "VAR", "user2-var")
|
_, _ = actions_model.InsertVariable(ctx, user2.ID, 0, "VAR", "user2-var", "user2-var-description")
|
||||||
user2Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: user2.ID, Name: "VAR"})
|
user2Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: user2.ID, Name: "VAR"})
|
||||||
userWebURL := "/user/settings/actions/variables"
|
userWebURL := "/user/settings/actions/variables"
|
||||||
|
|
||||||
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
|
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
|
||||||
_, _ = actions_model.InsertVariable(ctx, org3.ID, 0, "VAR", "org3-var")
|
_, _ = actions_model.InsertVariable(ctx, org3.ID, 0, "VAR", "org3-var", "org3-var-description")
|
||||||
org3Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: org3.ID, Name: "VAR"})
|
org3Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: org3.ID, Name: "VAR"})
|
||||||
orgWebURL := "/org/org3/settings/actions/variables"
|
orgWebURL := "/org/org3/settings/actions/variables"
|
||||||
|
|
||||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
_, _ = actions_model.InsertVariable(ctx, 0, repo1.ID, "VAR", "repo1-var")
|
_, _ = actions_model.InsertVariable(ctx, 0, repo1.ID, "VAR", "repo1-var", "repo1-var-description")
|
||||||
repo1Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{RepoID: repo1.ID, Name: "VAR"})
|
repo1Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{RepoID: repo1.ID, Name: "VAR"})
|
||||||
repoWebURL := "/user2/repo1/settings/actions/variables"
|
repoWebURL := "/user2/repo1/settings/actions/variables"
|
||||||
|
|
||||||
_, _ = actions_model.InsertVariable(ctx, 0, 0, "VAR", "global-var")
|
_, _ = actions_model.InsertVariable(ctx, 0, 0, "VAR", "global-var", "global-var-description")
|
||||||
globalVar := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{Name: "VAR", Data: "global-var"})
|
globalVar := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{Name: "VAR", Data: "global-var"})
|
||||||
adminWebURL := "/-/admin/actions/variables"
|
adminWebURL := "/-/admin/actions/variables"
|
||||||
|
|
||||||
|
@ -73,6 +73,33 @@ func TestAPIRepoSecrets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("CreateWithDescription", func(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
ExpectedStatus int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "no_description",
|
||||||
|
Description: "",
|
||||||
|
ExpectedStatus: http.StatusCreated,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "description",
|
||||||
|
Description: "some description",
|
||||||
|
ExpectedStatus: http.StatusCreated,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), c.Name), api.CreateOrUpdateSecretOption{
|
||||||
|
Data: "data",
|
||||||
|
Description: c.Description,
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
MakeRequest(t, req, c.ExpectedStatus)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Update", func(t *testing.T) {
|
t.Run("Update", func(t *testing.T) {
|
||||||
name := "update_secret"
|
name := "update_secret"
|
||||||
url := fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), name)
|
url := fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), name)
|
||||||
|
@ -285,7 +285,6 @@
|
|||||||
.markup table {
|
.markup table {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
width: max-content;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
@ -393,28 +393,6 @@
|
|||||||
margin-right: 2.5rem;
|
margin-right: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui[class*="middle aligned"].grid > .column:not(.row),
|
|
||||||
.ui[class*="middle aligned"].grid > .row > .column,
|
|
||||||
.ui.grid > [class*="middle aligned"].row > .column,
|
|
||||||
.ui.grid > [class*="middle aligned"].column:not(.row),
|
|
||||||
.ui.grid > .row > [class*="middle aligned"].column {
|
|
||||||
flex-direction: column;
|
|
||||||
vertical-align: middle;
|
|
||||||
align-self: center !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui[class*="equal width"].grid > .column:not(.row),
|
|
||||||
.ui[class*="equal width"].grid > .row > .column,
|
|
||||||
.ui.grid > [class*="equal width"].row > .column {
|
|
||||||
display: inline-block;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
.ui[class*="equal width"].grid > .wide.column,
|
|
||||||
.ui[class*="equal width"].grid > .row > .wide.column,
|
|
||||||
.ui.grid > [class*="equal width"].row > .wide.column {
|
|
||||||
flex-grow: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 767.98px) {
|
@media only screen and (max-width: 767.98px) {
|
||||||
.ui[class*="mobile reversed"].grid,
|
.ui[class*="mobile reversed"].grid,
|
||||||
.ui[class*="mobile reversed"].grid > .row,
|
.ui[class*="mobile reversed"].grid > .row,
|
||||||
|
@ -152,16 +152,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.table[class*="top aligned"],
|
|
||||||
.ui.table [class*="top aligned"] {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.table[class*="middle aligned"],
|
|
||||||
.ui.table [class*="middle aligned"] {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.table th.collapsing,
|
.ui.table th.collapsing,
|
||||||
.ui.table td.collapsing {
|
.ui.table td.collapsing {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
|
@ -14,10 +14,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#repo-files-table .repo-file-cell.name .svg {
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#repo-files-table .svg.octicon-file-directory-fill,
|
#repo-files-table .svg.octicon-file-directory-fill,
|
||||||
#repo-files-table .svg.octicon-file-submodule {
|
#repo-files-table .svg.octicon-file-submodule {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
@ -70,11 +66,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#repo-files-table .repo-file-cell.name {
|
#repo-files-table .repo-file-cell.name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5em;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#repo-files-table .repo-file-cell.name > a,
|
||||||
|
#repo-files-table .repo-file-cell.name > span {
|
||||||
|
flex-shrink: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#repo-files-table .repo-file-cell.name .entry-name {
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-width: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
#repo-files-table .repo-file-cell.name {
|
#repo-files-table .repo-file-cell.name {
|
||||||
max-width: 35vw;
|
max-width: 35vw;
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.repo-view-container .repo-view-file-tree-container {
|
.repo-view-container .repo-view-file-tree-container {
|
||||||
flex: 0 1 15%;
|
flex: 0 0 15%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
}
|
}
|
||||||
|
@ -1499,16 +1499,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------
|
|
||||||
Equal Width
|
|
||||||
---------------------*/
|
|
||||||
|
|
||||||
.ui[class*="equal width"].form .fields > .field,
|
|
||||||
.ui.form [class*="equal width"].fields > .field {
|
|
||||||
width: 100%;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------
|
/*--------------------
|
||||||
Inline Fields
|
Inline Fields
|
||||||
---------------------*/
|
---------------------*/
|
||||||
|
@ -116,12 +116,7 @@
|
|||||||
align-self: start;
|
align-self: start;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.ui.modal > [class*="top aligned"] {
|
|
||||||
align-self: start;
|
|
||||||
}
|
|
||||||
.ui.modal > [class*="middle aligned"] {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
.ui.modal > [class*="stretched"] {
|
.ui.modal > [class*="stretched"] {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ test('toAbsoluteLocaleDate', () => {
|
|||||||
// test different timezone
|
// test different timezone
|
||||||
const oldTZ = process.env.TZ;
|
const oldTZ = process.env.TZ;
|
||||||
process.env.TZ = 'America/New_York';
|
process.env.TZ = 'America/New_York';
|
||||||
expect(new Date('2024-03-15').toLocaleString()).toEqual('3/14/2024, 8:00:00 PM');
|
expect(new Date('2024-03-15').toLocaleString('en-US')).toEqual('3/14/2024, 8:00:00 PM');
|
||||||
expect(toAbsoluteLocaleDate('2024-03-15')).toEqual('3/15/2024, 12:00:00 AM');
|
expect(toAbsoluteLocaleDate('2024-03-15', 'en-US')).toEqual('3/15/2024, 12:00:00 AM');
|
||||||
process.env.TZ = oldTZ;
|
process.env.TZ = oldTZ;
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user