mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-18 10:52:56 +02:00
Merge branch 'main' into lunny/move_wikipath
This commit is contained in:
commit
38a445575e
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Gitea DevContainer",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm",
|
||||
"features": {
|
||||
// installs nodejs into container
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
|
@ -6,10 +6,12 @@ package actions
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
@ -32,26 +34,39 @@ type ActionVariable struct {
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"`
|
||||
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
||||
Data string `xorm:"LONGTEXT NOT NULL"`
|
||||
Description string `xorm:"TEXT"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
const (
|
||||
VariableDataMaxLength = 65536
|
||||
VariableDescriptionMaxLength = 4096
|
||||
)
|
||||
|
||||
func init() {
|
||||
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 {
|
||||
// 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.
|
||||
ownerID = 0
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(data) > VariableDataMaxLength {
|
||||
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||
}
|
||||
|
||||
description = util.TruncateRunes(description, VariableDescriptionMaxLength)
|
||||
|
||||
variable := &ActionVariable{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: strings.ToUpper(name),
|
||||
Data: data,
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: strings.ToUpper(name),
|
||||
Data: data,
|
||||
Description: description,
|
||||
}
|
||||
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) {
|
||||
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)
|
||||
count, err := db.GetEngine(ctx).
|
||||
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(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
|
||||
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
|
||||
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
func (repo *Repository) GetName() string {
|
||||
return repo.Name
|
||||
func RelativePath(ownerName, repoName string) string {
|
||||
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
|
||||
}
|
||||
|
||||
func (repo *Repository) GetOwnerName() string {
|
||||
return repo.OwnerName
|
||||
// RelativePath should be an unix style path like username/reponame.git
|
||||
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
|
||||
|
@ -40,9 +40,15 @@ type Secret struct {
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
|
||||
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
|
||||
Data string `xorm:"LONGTEXT"` // encrypted data
|
||||
Description string `xorm:"TEXT"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||
}
|
||||
|
||||
const (
|
||||
SecretDataMaxLength = 65536
|
||||
SecretDescriptionMaxLength = 4096
|
||||
)
|
||||
|
||||
// ErrSecretNotFound represents a "secret not found" error.
|
||||
type ErrSecretNotFound struct {
|
||||
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
|
||||
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 {
|
||||
// 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.
|
||||
@ -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)
|
||||
}
|
||||
|
||||
if len(data) > SecretDataMaxLength {
|
||||
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||
}
|
||||
|
||||
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
|
||||
|
||||
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
secret := &Secret{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: strings.ToUpper(name),
|
||||
Data: encrypted,
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: strings.ToUpper(name),
|
||||
Data: encrypted,
|
||||
Description: description,
|
||||
}
|
||||
return secret, db.Insert(ctx, secret)
|
||||
}
|
||||
@ -114,16 +128,23 @@ func (opts FindSecretsOptions) ToConds() builder.Cond {
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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 {
|
||||
return ErrSecretNotFound{}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ type Command struct {
|
||||
args []string
|
||||
globalArgsLength int
|
||||
brokenArgs []string
|
||||
cmd *exec.Cmd // for debug purpose only
|
||||
}
|
||||
|
||||
func logArgSanitize(arg string) string {
|
||||
@ -314,6 +315,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
|
||||
startTime := time.Now()
|
||||
|
||||
cmd := exec.CommandContext(ctx, c.prog, c.args...)
|
||||
c.cmd = cmd // for debug purpose only
|
||||
if opts.Env == nil {
|
||||
cmd.Env = os.Environ()
|
||||
} else {
|
||||
|
@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
@ -102,7 +104,7 @@ type CheckAttributeReader struct {
|
||||
|
||||
stdinReader io.ReadCloser
|
||||
stdinWriter *os.File
|
||||
stdOut attributeWriter
|
||||
stdOut *nulSeparatedAttributeWriter
|
||||
cmd *Command
|
||||
env []string
|
||||
ctx context.Context
|
||||
@ -152,7 +154,6 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run run cmd
|
||||
func (c *CheckAttributeReader) Run() error {
|
||||
defer func() {
|
||||
_ = c.stdinReader.Close()
|
||||
@ -176,7 +177,7 @@ func (c *CheckAttributeReader) Run() error {
|
||||
func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) {
|
||||
defer func() {
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
for range c.Attributes {
|
||||
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():
|
||||
if !ok {
|
||||
return nil, c.ctx.Err()
|
||||
@ -206,18 +229,12 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
// Close close pip after use
|
||||
func (c *CheckAttributeReader) Close() error {
|
||||
c.cancel()
|
||||
err := c.stdinWriter.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
type attributeWriter interface {
|
||||
io.WriteCloser
|
||||
ReadAttribute() <-chan attributeTriple
|
||||
}
|
||||
|
||||
type attributeTriple struct {
|
||||
Filename string
|
||||
Attribute string
|
||||
@ -281,7 +298,7 @@ func (wr *nulSeparatedAttributeWriter) Close() error {
|
||||
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) {
|
||||
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
|
||||
if err != nil {
|
||||
@ -303,21 +320,21 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
|
||||
}
|
||||
ctx, cancel := context.WithCancel(repo.Ctx)
|
||||
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 {
|
||||
go func() {
|
||||
err := checker.Run()
|
||||
if err != nil && err != ctx.Err() {
|
||||
log.Error("Unable to open checker for %s. Error: %v", commitID, err)
|
||||
if err != nil && !IsErrCanceledOrKilled(err) {
|
||||
log.Error("Attribute checker for commit %s exits with error: %v", commitID, err)
|
||||
}
|
||||
cancel()
|
||||
}()
|
||||
}
|
||||
deferable := func() {
|
||||
deferrable := func() {
|
||||
_ = checker.Close()
|
||||
cancel()
|
||||
deleteTemporaryFile()
|
||||
}
|
||||
|
||||
return checker, deferable
|
||||
return checker, deferrable
|
||||
}
|
||||
|
@ -4,10 +4,16 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
mathRand "math/rand/v2"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||
@ -95,3 +101,57 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||
Value: "unspecified",
|
||||
}, 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))
|
||||
}
|
||||
|
||||
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.
|
||||
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
|
||||
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.
|
||||
func IsBranchExist(ctx context.Context, repo Repository, name string) bool {
|
||||
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"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/reqctx"
|
||||
@ -16,17 +15,15 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// Repository represents a git repository which stored in a disk
|
||||
type Repository interface {
|
||||
GetName() string
|
||||
GetOwnerName() string
|
||||
}
|
||||
|
||||
func absPath(owner, name string) string {
|
||||
return filepath.Join(setting.RepoRootPath, strings.ToLower(owner), strings.ToLower(name)+".git")
|
||||
RelativePath() string // We don't assume how the directory structure of the repository is, so we only need the relative path
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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.
|
||||
@ -78,9 +75,8 @@ func DeleteRepository(ctx context.Context, repo Repository) error {
|
||||
}
|
||||
|
||||
// RenameRepository renames a repository's name on disk
|
||||
func RenameRepository(ctx context.Context, repo Repository, newName string) error {
|
||||
newRepoPath := absPath(repo.GetOwnerName(), newName)
|
||||
if err := util.Rename(repoPath(repo), newRepoPath); err != nil {
|
||||
func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
|
||||
if err := util.Rename(repoPath(repo), repoPath(newRepo)); err != nil {
|
||||
return fmt.Errorf("rename repository directory: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
@ -106,16 +106,11 @@ done
|
||||
return hookNames, hookTpls, giteaHookTpls
|
||||
}
|
||||
|
||||
// CreateDelegateHooksForRepo creates all the hooks scripts for the repo
|
||||
func CreateDelegateHooksForRepo(_ context.Context, repo Repository) (err error) {
|
||||
// CreateDelegateHooks creates all the hooks scripts for the repo
|
||||
func CreateDelegateHooks(_ context.Context, repo Repository) (err error) {
|
||||
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) {
|
||||
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
||||
|
||||
@ -178,16 +173,11 @@ func ensureExecutable(filename string) error {
|
||||
return os.Chmod(filename, mode)
|
||||
}
|
||||
|
||||
// CheckDelegateHooksForRepo checks the hooks scripts for the repo
|
||||
func CheckDelegateHooksForRepo(_ context.Context, repo Repository) ([]string, error) {
|
||||
// CheckDelegateHooks checks the hooks scripts for the repo
|
||||
func CheckDelegateHooks(_ context.Context, repo Repository) ([]string, error) {
|
||||
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) {
|
||||
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
|
||||
|
||||
|
@ -138,7 +138,7 @@ func CheckInitRepository(ctx context.Context, repo *repo_model.Repository) (err
|
||||
// Init git bare new repository.
|
||||
if err = git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil {
|
||||
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 nil
|
||||
|
@ -10,6 +10,8 @@ import "time"
|
||||
type Secret struct {
|
||||
// the secret's name
|
||||
Name string `json:"name"`
|
||||
// the secret's description
|
||||
Description string `json:"description"`
|
||||
// swagger:strfmt date-time
|
||||
Created time.Time `json:"created_at"`
|
||||
}
|
||||
@ -21,4 +23,9 @@ type CreateOrUpdateSecretOption struct {
|
||||
//
|
||||
// required: true
|
||||
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
|
||||
Value string `json:"value" binding:"Required"`
|
||||
|
||||
// Description of the variable to create
|
||||
//
|
||||
// required: false
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// UpdateVariableOption the option when updating variable
|
||||
@ -21,6 +26,11 @@ type UpdateVariableOption struct {
|
||||
//
|
||||
// required: true
|
||||
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
|
||||
@ -34,4 +44,6 @@ type ActionVariable struct {
|
||||
Name string `json:"name"`
|
||||
// the value of the variable
|
||||
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.
|
||||
none=Zatím zde nejsou žádné tajné klíče.
|
||||
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.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.
|
||||
|
@ -3670,6 +3670,7 @@ secrets=Secrets
|
||||
description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
|
||||
none=Noch keine Secrets vorhanden.
|
||||
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.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen.
|
||||
creation.success=Das Secret "%s" wurde hinzugefügt.
|
||||
|
@ -3338,6 +3338,7 @@ secrets=Μυστικά
|
||||
description=Τα μυστικά θα περάσουν σε ορισμένες δράσεις και δεν μπορούν να αναγνωστούν αλλού.
|
||||
none=Δεν υπάρχουν ακόμα μυστικά.
|
||||
creation=Προσθήκη Μυστικού
|
||||
creation.description=Περιγραφή
|
||||
creation.name_placeholder=αλφαριθμητικοί χαρακτήρες ή κάτω παύλες μόνο, δεν μπορούν να ξεκινούν με GITEA_ ή GITHUB_
|
||||
creation.value_placeholder=Εισάγετε οποιοδήποτε περιεχόμενο. Τα κενά στην αρχή παραλείπονται.
|
||||
creation.success=Το μυστικό "%s" προστέθηκε.
|
||||
|
@ -3712,8 +3712,10 @@ secrets = Secrets
|
||||
description = Secrets will be passed to certain actions and cannot be read otherwise.
|
||||
none = There are no secrets yet.
|
||||
creation = Add Secret
|
||||
creation.description = Description
|
||||
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.description_placeholder = Enter short description (optional).
|
||||
creation.success = The secret "%s" has been added.
|
||||
creation.failed = Failed to add 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.
|
||||
none=Todavía no hay secretos.
|
||||
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.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.
|
||||
|
@ -2513,6 +2513,7 @@ conan.details.repository=مخزن
|
||||
owner.settings.cleanuprules.enabled=فعال شده
|
||||
|
||||
[secrets]
|
||||
creation.description=شرح
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -1694,6 +1694,7 @@ conan.details.repository=Repo
|
||||
owner.settings.cleanuprules.enabled=Käytössä
|
||||
|
||||
[secrets]
|
||||
creation.description=Kuvaus
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -3705,6 +3705,7 @@ secrets=Secrets
|
||||
description=Les secrets seront transmis à certaines actions et ne pourront pas être lus autrement.
|
||||
none=Il n'y a pas encore de secrets.
|
||||
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.value_placeholder=Entrez n’importe quoi. Les blancs cernant seront taillés.
|
||||
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.
|
||||
none=Níl aon rúin ann fós.
|
||||
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.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.
|
||||
|
@ -1598,6 +1598,7 @@ conan.details.repository=Tároló
|
||||
owner.settings.cleanuprules.enabled=Engedélyezett
|
||||
|
||||
[secrets]
|
||||
creation.description=Leírás
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -1398,6 +1398,7 @@ conan.details.repository=Repositori
|
||||
owner.settings.cleanuprules.enabled=Aktif
|
||||
|
||||
[secrets]
|
||||
creation.description=Deskripsi
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -1326,6 +1326,7 @@ npm.details.tag=Merki
|
||||
pypi.requires=Þarfnast Python
|
||||
|
||||
[secrets]
|
||||
creation.description=Lýsing
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -2790,6 +2790,7 @@ settings.delete.error=Impossibile eliminare il pacchetto.
|
||||
owner.settings.cleanuprules.enabled=Attivo
|
||||
|
||||
[secrets]
|
||||
creation.description=Descrizione
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -3699,6 +3699,7 @@ secrets=シークレット
|
||||
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
||||
none=シークレットはまだありません。
|
||||
creation=シークレットを追加
|
||||
creation.description=説明
|
||||
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
||||
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
||||
creation.success=シークレット "%s" を追加しました。
|
||||
|
@ -1547,6 +1547,7 @@ conan.details.repository=저장소
|
||||
owner.settings.cleanuprules.enabled=활성화됨
|
||||
|
||||
[secrets]
|
||||
creation.description=설명
|
||||
|
||||
[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.
|
||||
none=Pagaidām nav neviena noslēpuma.
|
||||
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.value_placeholder=Ievadiet jebkādu saturu. Atstarpes sākumā un beigā tiks noņemtas.
|
||||
creation.success=Noslēpums "%s" tika pievienots.
|
||||
|
@ -2523,6 +2523,7 @@ settings.link.button=Repository link bijwerken
|
||||
owner.settings.cleanuprules.enabled=Ingeschakeld
|
||||
|
||||
[secrets]
|
||||
creation.description=Omschrijving
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -2412,6 +2412,7 @@ conan.details.repository=Repozytorium
|
||||
owner.settings.cleanuprules.enabled=Włączone
|
||||
|
||||
[secrets]
|
||||
creation.description=Opis
|
||||
|
||||
[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.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.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.protect_branch_name_pattern=Padrão de Nome de Branch Protegida
|
||||
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.
|
||||
none=Não há segredos ainda.
|
||||
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.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.
|
||||
|
@ -113,6 +113,7 @@ copy_type_unsupported=Este tipo de ficheiro não pode ser copiado
|
||||
write=Escrever
|
||||
preview=Pré-visualizar
|
||||
loading=Carregando…
|
||||
files=Ficheiros
|
||||
|
||||
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.
|
||||
@ -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.
|
||||
none=Ainda não há segredos.
|
||||
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.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.failed=Falhou ao adicionar o segredo.
|
||||
deletion=Remover segredo
|
||||
|
@ -3275,6 +3275,7 @@ secrets=Секреты
|
||||
description=Секреты будут передаваться определенным действиям и не могут быть прочитаны иначе.
|
||||
none=Секретов пока нет.
|
||||
creation=Добавить секрет
|
||||
creation.description=Описание
|
||||
creation.name_placeholder=регистр не важен, только алфавитно-цифровые символы и подчёркивания, не может начинаться с GITEA_ или GITHUB_
|
||||
creation.value_placeholder=Введите любое содержимое. Пробельные символы в начале и конце будут опущены.
|
||||
creation.success=Секрет «%s» добавлен.
|
||||
|
@ -2454,6 +2454,7 @@ conan.details.repository=කෝෂ්ඨය
|
||||
owner.settings.cleanuprules.enabled=සබල කර ඇත
|
||||
|
||||
[secrets]
|
||||
creation.description=සවිස්තරය
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -1989,6 +1989,7 @@ conan.details.repository=Utvecklingskatalog
|
||||
owner.settings.cleanuprules.enabled=Aktiv
|
||||
|
||||
[secrets]
|
||||
creation.description=Beskrivning
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -3534,6 +3534,7 @@ secrets=Gizlilikler
|
||||
description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
|
||||
none=Henüz gizlilik yok.
|
||||
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.value_placeholder=Herhangi bir içerik girin. Baştaki ve sondaki boşluklar ihmal edilecektir.
|
||||
creation.success=Gizlilik "%s" eklendi.
|
||||
|
@ -2524,6 +2524,7 @@ conan.details.repository=Репозиторій
|
||||
owner.settings.cleanuprules.enabled=Увімкнено
|
||||
|
||||
[secrets]
|
||||
creation.description=Опис
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -96,8 +96,8 @@ edit=编辑
|
||||
view=查看
|
||||
test=测试
|
||||
|
||||
enabled=启用
|
||||
disabled=禁用
|
||||
enabled=已启用
|
||||
disabled=已禁用
|
||||
locked=已锁定
|
||||
|
||||
copy=复制
|
||||
@ -148,7 +148,7 @@ name=名称
|
||||
value=值
|
||||
readme=自述文档
|
||||
|
||||
filter=过滤
|
||||
filter=筛选
|
||||
filter.clear=清除筛选器
|
||||
filter.is_archived=已归档
|
||||
filter.not_archived=非存档
|
||||
@ -159,7 +159,7 @@ filter.not_mirror=非镜像
|
||||
filter.is_template=模板
|
||||
filter.not_template=非模板
|
||||
filter.public=公开
|
||||
filter.private=私有库
|
||||
filter.private=私有
|
||||
|
||||
no_results_found=未找到结果
|
||||
internal_error_skipped=发生内部错误,但已被跳过: %s
|
||||
@ -245,6 +245,7 @@ license_desc=所有的代码都开源在 <a target="_blank" rel="noopener norefe
|
||||
|
||||
[install]
|
||||
install=安装页面
|
||||
installing_desc=正在安装,请稍候...
|
||||
title=初始配置
|
||||
docker_helper=如果您正在使用 Docker 容器运行 Gitea,请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
|
||||
require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
|
||||
@ -2870,7 +2871,7 @@ authentication=认证源
|
||||
emails=用户邮件
|
||||
config=应用配置
|
||||
config_summary=摘要
|
||||
config_settings=组织设置
|
||||
config_settings=设置
|
||||
notices=系统提示
|
||||
monitor=监控面板
|
||||
first_page=首页
|
||||
@ -3349,6 +3350,7 @@ monitor.previous=上次执行时间
|
||||
monitor.execute_times=执行次数
|
||||
monitor.process=运行中进程
|
||||
monitor.stacktrace=调用栈踪迹
|
||||
monitor.performance_logs=性能日志
|
||||
monitor.processes_count=%d 个进程
|
||||
monitor.download_diagnosis_report=下载诊断报告
|
||||
monitor.desc=进程描述
|
||||
@ -3529,12 +3531,12 @@ alpine.registry.info=从下面的列表中选择 $branch 和 $repository。
|
||||
alpine.install=要安装包,请运行以下命令:
|
||||
alpine.repository=仓库信息
|
||||
alpine.repository.branches=分支
|
||||
alpine.repository.repositories=仓库管理
|
||||
alpine.repository.repositories=仓库
|
||||
alpine.repository.architectures=架构
|
||||
arch.registry=添加具有相关仓库和架构的服务器到 <code>/etc/pacman.conf</code> 中:
|
||||
arch.install=使用 pacman 同步软件包:
|
||||
arch.repository=仓库信息
|
||||
arch.repository.repositories=仓库管理
|
||||
arch.repository.repositories=仓库
|
||||
arch.repository.architectures=架构
|
||||
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
|
||||
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
|
||||
@ -3552,6 +3554,7 @@ conda.install=要使用 Conda 安装软件包,请运行以下命令:
|
||||
container.details.type=镜像类型
|
||||
container.details.platform=平台
|
||||
container.pull=从命令行拉取镜像:
|
||||
container.images=镜像
|
||||
container.multi_arch=OS / Arch
|
||||
container.layers=镜像层
|
||||
container.labels=标签
|
||||
@ -3655,6 +3658,7 @@ secrets=密钥
|
||||
description=Secrets 将被传给特定的 Actions,其它情况将不能读取
|
||||
none=还没有密钥。
|
||||
creation=添加密钥
|
||||
creation.description=组织描述
|
||||
creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
|
||||
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
|
||||
creation.success=您的密钥 '%s' 添加成功。
|
||||
|
@ -963,6 +963,7 @@ conan.details.repository=儲存庫
|
||||
owner.settings.cleanuprules.enabled=已啟用
|
||||
|
||||
[secrets]
|
||||
creation.description=組織描述
|
||||
|
||||
[actions]
|
||||
|
||||
|
@ -3646,6 +3646,7 @@ secrets=Secret
|
||||
description=Secret 會被傳給特定的 Action,其他情況無法讀取。
|
||||
none=還沒有 Secret。
|
||||
creation=加入 Secret
|
||||
creation.description=描述
|
||||
creation.name_placeholder=不區分大小寫,只能包含英文字母、數字、底線 ('_'),不能以 GITEA_ 或 GITHUB_ 開頭。
|
||||
creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
|
||||
creation.success=已新增 Secret「%s」。
|
||||
|
@ -61,8 +61,9 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
|
||||
apiSecrets := make([]*api.Secret, len(secrets))
|
||||
for k, v := range secrets {
|
||||
apiSecrets[k] = &api.Secret{
|
||||
Name: v.Name,
|
||||
Created: v.CreatedUnix.AsTime(),
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Created: v.CreatedUnix.AsTime(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +107,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
|
||||
|
||||
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 errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
@ -230,10 +231,11 @@ func (Action) ListVariables(ctx *context.APIContext) {
|
||||
variables := make([]*api.ActionVariable, len(vars))
|
||||
for i, v := range vars {
|
||||
variables[i] = &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
Description: v.Description,
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,10 +283,11 @@ func (Action) GetVariable(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
variable := &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
Description: v.Description,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, variable)
|
||||
@ -386,7 +389,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
|
||||
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) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
} else {
|
||||
@ -453,6 +456,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
|
||||
|
||||
v.Name = opt.Name
|
||||
v.Data = opt.Value
|
||||
v.Description = opt.Description
|
||||
|
||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
|
@ -84,8 +84,9 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
|
||||
apiSecrets := make([]*api.Secret, len(secrets))
|
||||
for k, v := range secrets {
|
||||
apiSecrets[k] = &api.Secret{
|
||||
Name: v.Name,
|
||||
Created: v.CreatedUnix.AsTime(),
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
Created: v.CreatedUnix.AsTime(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +137,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
|
||||
|
||||
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 errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
@ -249,10 +250,11 @@ func (Action) GetVariable(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
variable := &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
Description: v.Description,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, variable)
|
||||
@ -362,7 +364,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
|
||||
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) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
} else {
|
||||
@ -432,6 +434,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
|
||||
|
||||
v.Name = opt.Name
|
||||
v.Data = opt.Value
|
||||
v.Description = opt.Description
|
||||
|
||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
@ -491,9 +494,11 @@ func (Action) ListVariables(ctx *context.APIContext) {
|
||||
variables := make([]*api.ActionVariable, len(vars))
|
||||
for i, v := range vars {
|
||||
variables[i] = &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
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.
|
||||
// The caller is responsible for closing the returned repo again
|
||||
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 git.IsErrNotExist(err) || err.Error() == "no such file or directory" {
|
||||
ctx.APIErrorNotFound(err)
|
||||
|
@ -49,7 +49,7 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
|
||||
|
||||
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 errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
@ -153,7 +153,7 @@ func CreateVariable(ctx *context.APIContext) {
|
||||
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) {
|
||||
ctx.APIError(http.StatusBadRequest, err)
|
||||
} else {
|
||||
@ -215,6 +215,7 @@ func UpdateVariable(ctx *context.APIContext) {
|
||||
|
||||
v.Name = opt.Name
|
||||
v.Data = opt.Value
|
||||
v.Description = opt.Description
|
||||
|
||||
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
@ -300,10 +301,11 @@ func GetVariable(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
variable := &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
Description: v.Description,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, variable)
|
||||
@ -345,10 +347,11 @@ func ListVariables(ctx *context.APIContext) {
|
||||
variables := make([]*api.ActionVariable, len(vars))
|
||||
for i, v := range vars {
|
||||
variables[i] = &api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
Description: v.Description,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ func Diff(ctx *context.Context) {
|
||||
)
|
||||
|
||||
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 {
|
||||
ctx.ServerError("Repo.GitRepo.GetCommit", err)
|
||||
return
|
||||
@ -417,7 +417,7 @@ func Diff(ctx *context.Context) {
|
||||
func RawDiff(ctx *context.Context) {
|
||||
var gitRepo *git.Repository
|
||||
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 {
|
||||
ctx.ServerError("OpenRepository", err)
|
||||
return
|
||||
|
@ -885,7 +885,7 @@ func ExcerptBlob(ctx *context.Context) {
|
||||
gitRepo := ctx.Repo.GitRepo
|
||||
if ctx.Data["PageIsWiki"] == true {
|
||||
var err error
|
||||
gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
||||
gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if err != nil {
|
||||
ctx.ServerError("OpenRepository", err)
|
||||
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) {
|
||||
wikiGitRepo, errGitRepo := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
|
||||
wikiGitRepo, errGitRepo := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
|
||||
if errGitRepo != nil {
|
||||
ctx.ServerError("OpenRepository", 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)
|
||||
if git.IsErrNotExist(errCommit) {
|
||||
// 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 {
|
||||
return wikiGitRepo, nil, errBranch
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ const (
|
||||
)
|
||||
|
||||
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)
|
||||
defer wikiRepo.Close()
|
||||
commit, err := wikiRepo.GetBranchCommit("master")
|
||||
|
@ -106,7 +106,8 @@ func Variables(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
ctx.Data["Variables"] = variables
|
||||
|
||||
ctx.Data["DataMaxLength"] = actions_model.VariableDataMaxLength
|
||||
ctx.Data["DescriptionMaxLength"] = actions_model.VariableDescriptionMaxLength
|
||||
ctx.HTML(http.StatusOK, vCtx.VariablesTemplate)
|
||||
}
|
||||
|
||||
@ -124,7 +125,7 @@ func VariableCreate(ctx *context.Context) {
|
||||
|
||||
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 {
|
||||
log.Error("CreateVariable: %v", err)
|
||||
ctx.JSONError(ctx.Tr("actions.variables.creation.failed"))
|
||||
@ -157,6 +158,7 @@ func VariableUpdate(ctx *context.Context) {
|
||||
form := web.GetForm(ctx).(*forms.EditVariableForm)
|
||||
variable.Name = form.Name
|
||||
variable.Data = form.Data
|
||||
variable.Description = form.Description
|
||||
|
||||
if ok, err := actions_service.UpdateVariableNameData(ctx, variable); err != nil || !ok {
|
||||
log.Error("UpdateVariable: %v", err)
|
||||
|
@ -22,12 +22,14 @@ func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
log.Error("CreateOrUpdateSecret failed: %v", err)
|
||||
ctx.JSONError(ctx.Tr("secrets.creation.failed"))
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -22,7 +22,7 @@ func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data strin
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -41,7 +41,7 @@ func UpdateVariableNameData(ctx context.Context, variable *actions_model.ActionV
|
||||
|
||||
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 {
|
||||
|
@ -204,7 +204,7 @@ Loop:
|
||||
return false, "", nil, &ErrWontSign{twofa}
|
||||
}
|
||||
case parentSigned:
|
||||
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||
if err != nil {
|
||||
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 {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
if len(results) > 0 && autofix {
|
||||
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)
|
||||
return fmt.Errorf("Unable to recreate delegate hooks for %-v. ERROR: %w", repo, err)
|
||||
}
|
||||
|
@ -323,8 +323,9 @@ func (f *AddKeyForm) Validate(req *http.Request, errs binding.Errors) binding.Er
|
||||
|
||||
// AddSecretForm for adding secrets
|
||||
type AddSecretForm struct {
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Data string `binding:"Required;MaxSize(65535)"`
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Data string `binding:"Required;MaxSize(65535)"`
|
||||
Description string `binding:"MaxSize(65535)"`
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
@ -334,8 +335,9 @@ func (f *AddSecretForm) Validate(req *http.Request, errs binding.Errors) binding
|
||||
}
|
||||
|
||||
type EditVariableForm struct {
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Data string `binding:"Required;MaxSize(65535)"`
|
||||
Name string `binding:"Required;MaxSize(255)"`
|
||||
Data string `binding:"Required;MaxSize(65535)"`
|
||||
Description string `binding:"MaxSize(65535)"`
|
||||
}
|
||||
|
||||
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() {
|
||||
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
|
||||
if isWiki {
|
||||
gitRepo, err = gitrepo.OpenWikiRepository(ctx, repo)
|
||||
gitRepo, err = gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||
} else {
|
||||
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())
|
||||
}
|
||||
|
||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
||||
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
if err = gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
||||
if err = gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||
}
|
||||
|
||||
|
@ -31,16 +31,16 @@ func SyncRepositoryHooks(ctx context.Context) error {
|
||||
default:
|
||||
}
|
||||
|
||||
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
|
||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
||||
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
|
||||
return fmt.Errorf("CreateDelegateHooks: %w", err)
|
||||
}
|
||||
exist, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
|
||||
exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
|
||||
if err != nil {
|
||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||
}
|
||||
if exist {
|
||||
if err := gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
|
||||
return fmt.Errorf("SyncRepositoryHook: %w", err)
|
||||
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
|
||||
return fmt.Errorf("CreateDelegateHooks: %w", err)
|
||||
}
|
||||
}
|
||||
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.
|
||||
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)
|
||||
}
|
||||
|
||||
hasWiki, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
|
||||
hasWiki, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
|
||||
if err != nil {
|
||||
return repo, fmt.Errorf("IsWikiRepositoryExist: %w", err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -331,12 +331,13 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
|
||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||
} else if has {
|
||||
return repo_model.ErrRepoAlreadyExist{
|
||||
Uname: repo.Owner.Name,
|
||||
Uname: repo.OwnerName,
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
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 {
|
||||
return nil, false, err
|
||||
}
|
||||
@ -25,14 +25,14 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, false, err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
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)
|
||||
} 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)
|
||||
@ -102,7 +102,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
||||
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")
|
||||
if err != nil {
|
||||
@ -392,7 +392,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
|
||||
return nil
|
||||
}
|
||||
|
||||
oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo)
|
||||
oldDefBranch, err := gitrepo.GetDefaultBranch(ctx, repo.WikiStorageRepo())
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
return nil // no git repo on storage, no need to do anything else
|
||||
} else if err != nil {
|
||||
|
@ -168,7 +168,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
|
||||
webPath := UserTitleToWebPath("", userTitle)
|
||||
assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg))
|
||||
// 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)
|
||||
|
||||
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))
|
||||
|
||||
// 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)
|
||||
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
|
||||
assert.NoError(t, err)
|
||||
@ -239,7 +239,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
||||
assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home"))
|
||||
|
||||
// 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)
|
||||
|
||||
defer gitRepo.Close()
|
||||
@ -253,7 +253,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
|
||||
func TestPrepareWikiFileName(t *testing.T) {
|
||||
unittest.PrepareTestEnv(t)
|
||||
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)
|
||||
|
||||
defer gitRepo.Close()
|
||||
|
@ -82,7 +82,7 @@
|
||||
<tbody>
|
||||
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
|
||||
<tr>
|
||||
<td class="top aligned">{{$key}}</td>
|
||||
<td class="tw-align-top">{{$key}}</td>
|
||||
<td class="tw-break-anywhere">{{$value}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
@ -63,13 +63,11 @@
|
||||
|
||||
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
|
||||
<li class="item">
|
||||
<div class="ui grid middle aligned">
|
||||
<div class="ten wide column">
|
||||
{{ctx.Locale.Tr "repo.org_labels_desc"}}
|
||||
{{if .IsOrganizationOwner}}
|
||||
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
|
||||
{{end}}
|
||||
</div>
|
||||
<div>{{/* parent is flex, so use block here to keep sentence spaces */}}
|
||||
{{ctx.Locale.Tr "repo.org_labels_desc"}}
|
||||
{{if .IsOrganizationOwner}}
|
||||
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
|
||||
{{end}}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
<div class="divider"></div>
|
||||
<div class="ui equal width compact grid">
|
||||
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
|
||||
<div class="row tw-items-center" data-tooltip-content="{{$issueReferenceLink}}">
|
||||
<span class="text column truncate">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
|
||||
<button class="ui two wide button column tw-p-2" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
|
||||
</div>
|
||||
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
|
||||
<div class="flex-text-block" data-tooltip-content="{{$issueReferenceLink}}">
|
||||
<span class="tw-flex-1 gt-ellipsis">{{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>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="flex-text-block tw-mb-2">
|
||||
<button class="ui compact tiny icon button"
|
||||
<div class="flex-text-block repo-button-row">
|
||||
<button class="ui compact basic icon button"
|
||||
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="hide"
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.hide_file_tree"}}">
|
||||
{{svg "octicon-sidebar-expand"}}
|
||||
|
@ -14,19 +14,21 @@
|
||||
{{$entry := $item.Entry}}
|
||||
{{$commit := $item.Commit}}
|
||||
{{$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}}
|
||||
{{if $entry.IsSubModule}}
|
||||
{{$submoduleLink := $submoduleFile.SubmoduleWebLink ctx}}
|
||||
{{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}}
|
||||
{{$entry.Name}} <span class="at">@</span> {{ShortSha $submoduleFile.RefID}}
|
||||
<span class="entry-name" title="{{$entry.Name}}">{{$entry.Name}}</span>
|
||||
@ {{ShortSha $submoduleFile.RefID}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if $entry.IsDir}}
|
||||
{{$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 "/"}}
|
||||
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
|
||||
{{if eq $subJumpablePathFieldLast 0}}
|
||||
@ -37,7 +39,7 @@
|
||||
{{end}}
|
||||
</a>
|
||||
{{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}}
|
||||
</div>
|
||||
|
@ -22,6 +22,9 @@
|
||||
<div class="flex-item-title">
|
||||
{{.Name}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
{{if .Description}}{{.Description}}{{else}}-{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
******
|
||||
</div>
|
||||
@ -72,9 +75,20 @@
|
||||
<textarea required
|
||||
id="secret-data"
|
||||
name="data"
|
||||
maxlength="{{.DataMaxLength}}"
|
||||
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
||||
></textarea>
|
||||
</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>
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
</form>
|
||||
|
@ -7,6 +7,7 @@
|
||||
data-modal-header="{{ctx.Locale.Tr "actions.variables.creation"}}"
|
||||
data-modal-dialog-variable-name=""
|
||||
data-modal-dialog-variable-data=""
|
||||
data-modal-dialog-variable-description=""
|
||||
>
|
||||
{{ctx.Locale.Tr "actions.variables.creation"}}
|
||||
</button>
|
||||
@ -24,6 +25,9 @@
|
||||
<div class="flex-item-title">
|
||||
{{.Name}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
{{if .Description}}{{.Description}}{{else}}-{{end}}
|
||||
</div>
|
||||
<div class="flex-item-body">
|
||||
{{.Data}}
|
||||
</div>
|
||||
@ -39,6 +43,7 @@
|
||||
data-modal-header="{{ctx.Locale.Tr "actions.variables.edit"}}"
|
||||
data-modal-dialog-variable-name="{{.Name}}"
|
||||
data-modal-dialog-variable-data="{{.Data}}"
|
||||
data-modal-dialog-variable-description="{{.Description}}"
|
||||
>
|
||||
{{svg "octicon-pencil"}}
|
||||
</button>
|
||||
@ -82,9 +87,20 @@
|
||||
<textarea required
|
||||
name="data"
|
||||
id="dialog-variable-data"
|
||||
maxlength="{{.DataMaxLength}}"
|
||||
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
|
||||
></textarea>
|
||||
</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>
|
||||
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
|
||||
</form>
|
||||
|
25
templates/swagger/v1_json.tmpl
generated
25
templates/swagger/v1_json.tmpl
generated
@ -19325,6 +19325,11 @@
|
||||
"type": "string",
|
||||
"x-go-name": "Data"
|
||||
},
|
||||
"description": {
|
||||
"description": "the description of the variable",
|
||||
"type": "string",
|
||||
"x-go-name": "Description"
|
||||
},
|
||||
"name": {
|
||||
"description": "the name of the variable",
|
||||
"type": "string",
|
||||
@ -20988,6 +20993,11 @@
|
||||
"description": "Data of the secret to update",
|
||||
"type": "string",
|
||||
"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"
|
||||
@ -21498,6 +21508,11 @@
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of the variable to create",
|
||||
"type": "string",
|
||||
"x-go-name": "Description"
|
||||
},
|
||||
"value": {
|
||||
"description": "Value of the variable to create",
|
||||
"type": "string",
|
||||
@ -25459,6 +25474,11 @@
|
||||
"format": "date-time",
|
||||
"x-go-name": "Created"
|
||||
},
|
||||
"description": {
|
||||
"description": "the secret's description",
|
||||
"type": "string",
|
||||
"x-go-name": "Description"
|
||||
},
|
||||
"name": {
|
||||
"description": "the secret's name",
|
||||
"type": "string",
|
||||
@ -26034,6 +26054,11 @@
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of the variable to update",
|
||||
"type": "string",
|
||||
"x-go-name": "Description"
|
||||
},
|
||||
"name": {
|
||||
"description": "New name for the variable. If the field is empty, the variable name won't be updated.",
|
||||
"type": "string",
|
||||
|
@ -10,12 +10,12 @@
|
||||
<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>
|
||||
<script src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
|
||||
<script defer src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
|
||||
{{else if eq .CaptchaType "hcaptcha"}}
|
||||
<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>
|
||||
<script src='https://hcaptcha.com/1/api.js'></script>
|
||||
<script defer src='https://hcaptcha.com/1/api.js'></script>
|
||||
{{else if eq .CaptchaType "mcaptcha"}}
|
||||
<div class="inline field tw-text-center">
|
||||
<div class="m-captcha-style" id="mcaptcha__widget-container"></div>
|
||||
@ -25,5 +25,5 @@
|
||||
<div class="inline field tw-text-center">
|
||||
<div id="captcha" data-captcha-type="cf-turnstile" data-sitekey="{{.CfTurnstileSitekey}}"></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}}
|
||||
|
@ -81,7 +81,7 @@
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .Repos}}
|
||||
<div class="ui middle aligned divided list">
|
||||
<div class="ui list">
|
||||
{{range .Repos}}
|
||||
<div class="item">
|
||||
<div class="content flex-text-block">
|
||||
|
@ -27,21 +27,21 @@ func TestActionsVariables(t *testing.T) {
|
||||
require.NoError(t, db.DeleteAllRecords("action_variable"))
|
||||
|
||||
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"})
|
||||
userWebURL := "/user/settings/actions/variables"
|
||||
|
||||
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"})
|
||||
orgWebURL := "/org/org3/settings/actions/variables"
|
||||
|
||||
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"})
|
||||
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"})
|
||||
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) {
|
||||
name := "update_secret"
|
||||
url := fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), name)
|
||||
|
@ -285,7 +285,6 @@
|
||||
.markup table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
width: max-content;
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
@ -393,28 +393,6 @@
|
||||
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) {
|
||||
.ui[class*="mobile reversed"].grid,
|
||||
.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 td.collapsing {
|
||||
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-submodule {
|
||||
color: var(--color-primary);
|
||||
@ -70,11 +66,25 @@
|
||||
}
|
||||
|
||||
#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;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#repo-files-table .repo-file-cell.name .entry-name {
|
||||
flex-shrink: 1;
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
#repo-files-table .repo-file-cell.name {
|
||||
max-width: 35vw;
|
||||
|
@ -55,7 +55,7 @@
|
||||
}
|
||||
|
||||
.repo-view-container .repo-view-file-tree-container {
|
||||
flex: 0 1 15%;
|
||||
flex: 0 0 15%;
|
||||
min-width: 0;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
@ -1499,16 +1499,6 @@
|
||||
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
|
||||
---------------------*/
|
||||
|
@ -116,12 +116,7 @@
|
||||
align-self: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
.ui.modal > [class*="top aligned"] {
|
||||
align-self: start;
|
||||
}
|
||||
.ui.modal > [class*="middle aligned"] {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.ui.modal > [class*="stretched"] {
|
||||
align-self: stretch;
|
||||
}
|
||||
@ -258,7 +253,7 @@
|
||||
padding: 1rem 0 !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* Let Buttons Stack */
|
||||
.ui.modal > .actions {
|
||||
padding: 1rem 1rem 0rem !important;
|
||||
|
@ -20,7 +20,7 @@ test('toAbsoluteLocaleDate', () => {
|
||||
// test different timezone
|
||||
const oldTZ = process.env.TZ;
|
||||
process.env.TZ = 'America/New_York';
|
||||
expect(new Date('2024-03-15').toLocaleString()).toEqual('3/14/2024, 8:00:00 PM');
|
||||
expect(toAbsoluteLocaleDate('2024-03-15')).toEqual('3/15/2024, 12:00:00 AM');
|
||||
expect(new Date('2024-03-15').toLocaleString('en-US')).toEqual('3/14/2024, 8:00:00 PM');
|
||||
expect(toAbsoluteLocaleDate('2024-03-15', 'en-US')).toEqual('3/15/2024, 12:00:00 AM');
|
||||
process.env.TZ = oldTZ;
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user