mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-04-21 07:16:41 +02:00
Merge branch 'forgejo' into TestExampleIntegration
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
This commit is contained in:
commit
c7a2b510cb
132 changed files with 1927 additions and 676 deletions
|
@ -22,11 +22,6 @@ code.gitea.io/gitea/models/actions
|
|||
ScheduleList.LoadTriggerUser
|
||||
ScheduleList.LoadRepos
|
||||
|
||||
code.gitea.io/gitea/models/asymkey
|
||||
ErrGPGKeyAccessDenied.Error
|
||||
ErrGPGKeyAccessDenied.Unwrap
|
||||
HasDeployKey
|
||||
|
||||
code.gitea.io/gitea/models/auth
|
||||
GetSourceByName
|
||||
WebAuthnCredentials
|
||||
|
@ -54,9 +49,7 @@ code.gitea.io/gitea/models/git
|
|||
|
||||
code.gitea.io/gitea/models/issues
|
||||
IsErrUnknownDependencyType
|
||||
ErrNewIssueInsert.Error
|
||||
IsErrIssueWasClosed
|
||||
ChangeMilestoneStatus
|
||||
|
||||
code.gitea.io/gitea/models/organization
|
||||
GetTeamNamesByID
|
||||
|
@ -81,16 +74,12 @@ code.gitea.io/gitea/models/repo
|
|||
WatchRepoMode
|
||||
|
||||
code.gitea.io/gitea/models/user
|
||||
ErrUserInactive.Error
|
||||
ErrUserInactive.Unwrap
|
||||
IsErrExternalLoginUserAlreadyExist
|
||||
IsErrExternalLoginUserNotExist
|
||||
NewFederatedUser
|
||||
IsErrUserSettingIsNotExist
|
||||
GetUserAllSettings
|
||||
DeleteUserSetting
|
||||
GetUserEmailsByNames
|
||||
GetUserNamesByIDs
|
||||
|
||||
code.gitea.io/gitea/modules/activitypub
|
||||
NewContext
|
||||
|
|
|
@ -3,7 +3,7 @@ runs:
|
|||
steps:
|
||||
- run: |
|
||||
su forgejo -c 'make deps-backend'
|
||||
- uses: actions/cache@v4
|
||||
- uses: https://data.forgejo.org/actions/cache@v4
|
||||
id: cache-backend
|
||||
with:
|
||||
path: ${{github.workspace}}/gitea
|
||||
|
|
|
@ -49,7 +49,7 @@ runs:
|
|||
|
||||
- name: "Restore Go dependencies from cache or mark for later caching"
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4
|
||||
uses: https://data.forgejo.org/actions/cache@v4
|
||||
with:
|
||||
key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod') }}
|
||||
restore-keys: |
|
||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
if: vars.ROLE == 'forgejo-coding'
|
||||
runs-on: lxc-bookworm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
|
||||
- id: forgejo
|
||||
uses: https://data.forgejo.org/actions/setup-forgejo@v2.0.4
|
||||
|
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
# root is used for testing, allow it
|
||||
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@ jobs:
|
|||
container:
|
||||
image: data.forgejo.org/oci/node:20-bookworm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
show-progress: 'false'
|
||||
- uses: https://code.forgejo.org/actions/cascading-pr@v2.2.0
|
||||
- uses: https://data.forgejo.org/actions/cascading-pr@v2.2.0
|
||||
with:
|
||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||
origin-repo: ${{ github.repository }}
|
||||
|
|
|
@ -39,7 +39,7 @@ jobs:
|
|||
runs-on: lxc-bookworm
|
||||
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: copy & sign
|
||||
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.3.1
|
||||
|
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:39.106.0
|
||||
image: data.forgejo.org/renovate/renovate:39.136.1
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
apt-get update -qq
|
||||
apt-get -q install -qq -y zstd
|
||||
- name: "Cache frontend build for playwright testing"
|
||||
uses: actions/cache/save@v4
|
||||
uses: https://data.forgejo.org/actions/cache/save@v4
|
||||
with:
|
||||
path: ${{github.workspace}}/public/assets
|
||||
key: frontend-build-${{ github.sha }}
|
||||
|
@ -104,7 +104,7 @@ jobs:
|
|||
fetch-depth: 20
|
||||
- uses: ./.forgejo/workflows-composite/setup-env
|
||||
- name: "Restore frontend build"
|
||||
uses: actions/cache/restore@v4
|
||||
uses: https://data.forgejo.org/actions/cache/restore@v4
|
||||
id: cache-frontend
|
||||
with:
|
||||
path: ${{github.workspace}}/public/assets
|
||||
|
|
|
@ -33,8 +33,9 @@ models/.* @gusted
|
|||
# for code that lives in here.
|
||||
routers/.* @gusted
|
||||
|
||||
# Let new strings be checked by the translation team.
|
||||
options/locale/locale_en-US.ini @0ko
|
||||
# Let locale changes be checked by the translation team.
|
||||
options/locale/.* @0ko
|
||||
options/locale_next/.* @0ko
|
||||
|
||||
# Personal interest
|
||||
.*/webhook.* @oliverpool
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
@ -51,7 +51,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
|||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM code.forgejo.org/oci/alpine:3.21
|
||||
FROM data.forgejo.org/oci/alpine:3.21
|
||||
ARG RELEASE_VERSION
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.23-alpine3.21 as build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
@ -49,7 +49,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
|||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM code.forgejo.org/oci/alpine:3.21
|
||||
FROM data.forgejo.org/oci/alpine:3.21
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
org.opencontainers.image.url="https://forgejo.org" \
|
||||
|
|
4
Makefile
4
Makefile
|
@ -37,7 +37,7 @@ endif
|
|||
XGO_VERSION := go-1.21.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.1.1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.0 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
|||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.29.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.115.4 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.136.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
|
|
@ -195,7 +195,7 @@ func serveInstalled(ctx *cli.Context) error {
|
|||
publicFilesSet.Remove(".well-known")
|
||||
publicFilesSet.Remove("assets")
|
||||
publicFilesSet.Remove("robots.txt")
|
||||
for _, fn := range publicFilesSet.Values() {
|
||||
for fn := range publicFilesSet.Seq() {
|
||||
log.Error("Found legacy public asset %q in CustomPath. Please move it to %s/public/assets/%s", fn, setting.CustomPath, fn)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(setting.CustomPath, "robots.txt")); err == nil {
|
||||
|
|
|
@ -192,28 +192,6 @@ func (err ErrGPGKeyIDAlreadyUsed) Unwrap() error {
|
|||
return util.ErrAlreadyExist
|
||||
}
|
||||
|
||||
// ErrGPGKeyAccessDenied represents a "GPGKeyAccessDenied" kind of Error.
|
||||
type ErrGPGKeyAccessDenied struct {
|
||||
UserID int64
|
||||
KeyID int64
|
||||
}
|
||||
|
||||
// IsErrGPGKeyAccessDenied checks if an error is a ErrGPGKeyAccessDenied.
|
||||
func IsErrGPGKeyAccessDenied(err error) bool {
|
||||
_, ok := err.(ErrGPGKeyAccessDenied)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Error pretty-prints an error of type ErrGPGKeyAccessDenied.
|
||||
func (err ErrGPGKeyAccessDenied) Error() string {
|
||||
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d]",
|
||||
err.UserID, err.KeyID)
|
||||
}
|
||||
|
||||
func (err ErrGPGKeyAccessDenied) Unwrap() error {
|
||||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrKeyAccessDenied represents a "KeyAccessDenied" kind of error.
|
||||
type ErrKeyAccessDenied struct {
|
||||
UserID int64
|
||||
|
|
|
@ -105,14 +105,6 @@ func addDeployKey(ctx context.Context, keyID, repoID int64, name, fingerprint st
|
|||
return key, db.Insert(ctx, key)
|
||||
}
|
||||
|
||||
// HasDeployKey returns true if public key is a deploy key of given repository.
|
||||
func HasDeployKey(ctx context.Context, keyID, repoID int64) bool {
|
||||
has, _ := db.GetEngine(ctx).
|
||||
Where("key_id = ? AND repo_id = ?", keyID, repoID).
|
||||
Get(new(DeployKey))
|
||||
return has
|
||||
}
|
||||
|
||||
// AddDeployKey add new deploy key to database and authorized_keys file.
|
||||
func AddDeployKey(ctx context.Context, repoID int64, name, content string, readOnly bool) (*DeployKey, error) {
|
||||
fingerprint, err := CalcFingerprint(content)
|
||||
|
|
|
@ -63,21 +63,6 @@ func (err ErrIssueIsClosed) Error() string {
|
|||
return fmt.Sprintf("issue is closed [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
|
||||
}
|
||||
|
||||
// ErrNewIssueInsert is used when the INSERT statement in newIssue fails
|
||||
type ErrNewIssueInsert struct {
|
||||
OriginalError error
|
||||
}
|
||||
|
||||
// IsErrNewIssueInsert checks if an error is a ErrNewIssueInsert.
|
||||
func IsErrNewIssueInsert(err error) bool {
|
||||
_, ok := err.(ErrNewIssueInsert)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrNewIssueInsert) Error() string {
|
||||
return err.OriginalError.Error()
|
||||
}
|
||||
|
||||
// ErrIssueWasClosed is used when close a closed issue
|
||||
type ErrIssueWasClosed struct {
|
||||
ID int64
|
||||
|
|
|
@ -433,7 +433,7 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *Issue, la
|
|||
LabelIDs: labelIDs,
|
||||
Attachments: uuids,
|
||||
}); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %w", err)
|
||||
|
|
|
@ -251,21 +251,6 @@ func ChangeMilestoneStatusByRepoIDAndID(ctx context.Context, repoID, milestoneID
|
|||
return committer.Commit()
|
||||
}
|
||||
|
||||
// ChangeMilestoneStatus changes the milestone open/closed status.
|
||||
func ChangeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) (err error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := changeMilestoneStatus(ctx, m, isClosed); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func changeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) error {
|
||||
m.IsClosed = isClosed
|
||||
if isClosed {
|
||||
|
|
|
@ -298,17 +298,16 @@ func TestNewMilestone(t *testing.T) {
|
|||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
}
|
||||
|
||||
func TestChangeMilestoneStatus(t *testing.T) {
|
||||
func TestChangeMilestoneStatusByRepoIDAndID(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1})
|
||||
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, true))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatusByRepoIDAndID(db.DefaultContext, 1, 1, true))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1, IsClosed: true})
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: 1}, &issues_model.Milestone{})
|
||||
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, false))
|
||||
require.NoError(t, issues_model.ChangeMilestoneStatusByRepoIDAndID(db.DefaultContext, 1, 1, false))
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=0")
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{})
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: 1}, &issues_model.Milestone{})
|
||||
}
|
||||
|
||||
func TestDeleteMilestoneByRepoID(t *testing.T) {
|
||||
|
|
|
@ -575,7 +575,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *Iss
|
|||
Attachments: uuids,
|
||||
IsPull: true,
|
||||
}); err != nil {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
|
||||
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %w", err)
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"math"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
@ -67,34 +68,37 @@ func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
|
|||
return langPerc
|
||||
}
|
||||
|
||||
// Rounds to 1 decimal point, target should be the expected sum of percs
|
||||
// Use the quota method to round the percentages to one decimal place while
|
||||
// keeping the sum of the percentages at 100%.
|
||||
func roundByLargestRemainder(percs map[string]float32, target float32) {
|
||||
// Tracks the difference between the sum of percentage and 100%.
|
||||
leftToDistribute := int(target * 10)
|
||||
|
||||
keys := make([]string, 0, len(percs))
|
||||
type key struct {
|
||||
language string
|
||||
remainder float64
|
||||
}
|
||||
keys := make([]key, 0, len(percs))
|
||||
|
||||
for k, v := range percs {
|
||||
percs[k] = v * 10
|
||||
floored := math.Floor(float64(percs[k]))
|
||||
floored, frac := math.Modf(float64(v * 10))
|
||||
percs[k] = float32(floored)
|
||||
leftToDistribute -= int(floored)
|
||||
keys = append(keys, k)
|
||||
keys = append(keys, key{language: k, remainder: frac})
|
||||
}
|
||||
|
||||
// Sort the keys by the largest remainder
|
||||
sort.SliceStable(keys, func(i, j int) bool {
|
||||
_, remainderI := math.Modf(float64(percs[keys[i]]))
|
||||
_, remainderJ := math.Modf(float64(percs[keys[j]]))
|
||||
return remainderI > remainderJ
|
||||
// Sort the fractional part in an ascending order.
|
||||
slices.SortFunc(keys, func(b, a key) int {
|
||||
return cmp.Compare(a.remainder, b.remainder)
|
||||
})
|
||||
|
||||
// Increment the values in order of largest remainder
|
||||
// As long as the sum of 100% is not reached, add 0.1% percentage.
|
||||
for _, k := range keys {
|
||||
percs[k] = float32(math.Floor(float64(percs[k])))
|
||||
if leftToDistribute > 0 {
|
||||
percs[k]++
|
||||
percs[k.language]++
|
||||
leftToDistribute--
|
||||
}
|
||||
percs[k] /= 10
|
||||
percs[k.language] /= 10
|
||||
}
|
||||
}
|
||||
|
||||
|
|
66
models/repo/language_stats_test.go
Normal file
66
models/repo/language_stats_test.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLanguagePercentages(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input LanguageStatList
|
||||
output map[string]float32
|
||||
}{
|
||||
{
|
||||
[]*LanguageStat{{Language: "Go", Size: 500}, {Language: "Rust", Size: 501}},
|
||||
map[string]float32{
|
||||
"Go": 50.0,
|
||||
"Rust": 50.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]*LanguageStat{{Language: "Go", Size: 10}, {Language: "Rust", Size: 91}},
|
||||
map[string]float32{
|
||||
"Go": 9.9,
|
||||
"Rust": 90.1,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]*LanguageStat{{Language: "Go", Size: 1}, {Language: "Rust", Size: 2}},
|
||||
map[string]float32{
|
||||
"Go": 33.3,
|
||||
"Rust": 66.7,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]*LanguageStat{{Language: "Go", Size: 1}, {Language: "Rust", Size: 2}, {Language: "Shell", Size: 3}, {Language: "C#", Size: 4}, {Language: "Zig", Size: 5}, {Language: "Coq", Size: 6}, {Language: "Haskell", Size: 7}},
|
||||
map[string]float32{
|
||||
"Go": 3.6,
|
||||
"Rust": 7.1,
|
||||
"Shell": 10.7,
|
||||
"C#": 14.3,
|
||||
"Zig": 17.9,
|
||||
"Coq": 21.4,
|
||||
"Haskell": 25,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]*LanguageStat{{Language: "Go", Size: 1000}, {Language: "PHP", Size: 1}, {Language: "Java", Size: 1}},
|
||||
map[string]float32{
|
||||
"Go": 99.8,
|
||||
"other": 0.2,
|
||||
},
|
||||
},
|
||||
{
|
||||
[]*LanguageStat{},
|
||||
map[string]float32{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
assert.Equal(t, testCase.output, testCase.input.getLanguagePercentages())
|
||||
}
|
||||
}
|
|
@ -36,18 +36,6 @@ const RepositoryListDefaultPageSize = 64
|
|||
// RepositoryList contains a list of repositories
|
||||
type RepositoryList []*Repository
|
||||
|
||||
func (repos RepositoryList) Len() int {
|
||||
return len(repos)
|
||||
}
|
||||
|
||||
func (repos RepositoryList) Less(i, j int) bool {
|
||||
return repos[i].FullName() < repos[j].FullName()
|
||||
}
|
||||
|
||||
func (repos RepositoryList) Swap(i, j int) {
|
||||
repos[i], repos[j] = repos[j], repos[i]
|
||||
}
|
||||
|
||||
// ValuesRepository converts a repository map to a list
|
||||
// FIXME: Remove in favor of maps.values when MIN_GO_VERSION >= 1.18
|
||||
func ValuesRepository(m map[int64]*Repository) []*Repository {
|
||||
|
|
|
@ -71,27 +71,6 @@ func (err ErrUserProhibitLogin) Unwrap() error {
|
|||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrUserInactive represents a "ErrUserInactive" kind of error.
|
||||
type ErrUserInactive struct {
|
||||
UID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsErrUserInactive checks if an error is a ErrUserInactive
|
||||
func IsErrUserInactive(err error) bool {
|
||||
_, ok := err.(ErrUserInactive)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserInactive) Error() string {
|
||||
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
|
||||
}
|
||||
|
||||
// Unwrap unwraps this error as a ErrPermission error
|
||||
func (err ErrUserInactive) Unwrap() error {
|
||||
return util.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// ErrUserIsNotLocal represents a "ErrUserIsNotLocal" kind of error.
|
||||
type ErrUserIsNotLocal struct {
|
||||
UID int64
|
||||
|
|
|
@ -40,6 +40,7 @@ type SearchUserOptions struct {
|
|||
IsProhibitLogin optional.Option[bool]
|
||||
IncludeReserved bool
|
||||
|
||||
Load2FAStatus bool
|
||||
ExtraParamStrings map[string]string
|
||||
}
|
||||
|
||||
|
@ -126,17 +127,15 @@ func (opts *SearchUserOptions) toSearchQueryBase(ctx context.Context) *xorm.Sess
|
|||
return e.Where(cond)
|
||||
}
|
||||
|
||||
// 2fa filter uses LEFT JOIN to check whether a user has a 2fa record
|
||||
// While using LEFT JOIN, sometimes the performance might not be good, but it won't be a problem now, such SQL is seldom executed.
|
||||
// There are some possible methods to refactor this SQL in future when we really need to optimize the performance (but not now):
|
||||
// (1) add a column in user table (2) add a setting value in user_setting table (3) use search engines (bleve/elasticsearch)
|
||||
// Check if the user has two factor enabled, which is TOTP or Webauthn.
|
||||
if opts.IsTwoFactorEnabled.Value() {
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL"))
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NOT NULL OR webauthn_credential.user_id IS NOT NULL"))
|
||||
} else {
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NULL"))
|
||||
cond = cond.And(builder.Expr("two_factor.uid IS NULL AND webauthn_credential.user_id IS NULL"))
|
||||
}
|
||||
|
||||
return e.Join("LEFT OUTER", "two_factor", "two_factor.uid = `user`.id").
|
||||
Join("LEFT OUTER", "webauthn_credential", "webauthn_credential.user_id = `user`.id").
|
||||
Where(cond)
|
||||
}
|
||||
|
||||
|
|
|
@ -1043,22 +1043,6 @@ func GetUserByName(ctx context.Context, name string) (*User, error) {
|
|||
return u, nil
|
||||
}
|
||||
|
||||
// GetUserEmailsByNames returns a list of e-mails corresponds to names of users
|
||||
// that have their email notifications set to enabled or onmention.
|
||||
func GetUserEmailsByNames(ctx context.Context, names []string) []string {
|
||||
mails := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
u, err := GetUserByName(ctx, name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if u.IsMailable() && u.EmailNotificationsPreference != EmailNotificationsDisabled {
|
||||
mails = append(mails, u.Email)
|
||||
}
|
||||
}
|
||||
return mails
|
||||
}
|
||||
|
||||
// GetMaileableUsersByIDs gets users from ids, but only if they can receive mails
|
||||
func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([]*User, error) {
|
||||
if len(ids) == 0 {
|
||||
|
@ -1085,17 +1069,6 @@ func GetMaileableUsersByIDs(ctx context.Context, ids []int64, isMention bool) ([
|
|||
Find(&ous)
|
||||
}
|
||||
|
||||
// GetUserNamesByIDs returns usernames for all resolved users from a list of Ids.
|
||||
func GetUserNamesByIDs(ctx context.Context, ids []int64) ([]string, error) {
|
||||
unames := make([]string, 0, len(ids))
|
||||
err := db.GetEngine(ctx).In("id", ids).
|
||||
Table("user").
|
||||
Asc("name").
|
||||
Cols("name").
|
||||
Find(&unames)
|
||||
return unames, err
|
||||
}
|
||||
|
||||
// GetUserNameByID returns username for the id
|
||||
func GetUserNameByID(ctx context.Context, id int64) (string, error) {
|
||||
var name string
|
||||
|
|
|
@ -102,16 +102,6 @@ func TestGetUserByName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetUserEmailsByNames(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// ignore none active user email
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
|
||||
assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
|
||||
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"}))
|
||||
}
|
||||
|
||||
func TestCanCreateOrganization(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
|
@ -222,7 +212,7 @@ func TestSearchUsers(t *testing.T) {
|
|||
[]int64{1041, 37})
|
||||
|
||||
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsTwoFactorEnabled: optional.Some(true)},
|
||||
[]int64{24})
|
||||
[]int64{24, 32})
|
||||
}
|
||||
|
||||
func TestEmailNotificationPreferences(t *testing.T) {
|
||||
|
@ -715,7 +705,7 @@ func TestDisabledUserFeatures(t *testing.T) {
|
|||
// no features should be disabled with a plain login type
|
||||
assert.LessOrEqual(t, user.LoginType, auth.Plain)
|
||||
assert.Empty(t, user_model.DisabledFeaturesWithLoginType(user).Values())
|
||||
for _, f := range testValues.Values() {
|
||||
for f := range testValues.Seq() {
|
||||
assert.False(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||
}
|
||||
|
||||
|
@ -724,7 +714,7 @@ func TestDisabledUserFeatures(t *testing.T) {
|
|||
|
||||
// all features should be disabled
|
||||
assert.NotEmpty(t, user_model.DisabledFeaturesWithLoginType(user).Values())
|
||||
for _, f := range testValues.Values() {
|
||||
for f := range testValues.Seq() {
|
||||
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
|
@ -143,8 +143,7 @@ func (l *LayeredFS) ListFiles(name string, fileMode ...bool) ([]string, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
files := fileSet.Values()
|
||||
sort.Strings(files)
|
||||
files := slices.Sorted(fileSet.Seq())
|
||||
return files, nil
|
||||
}
|
||||
|
||||
|
@ -184,8 +183,7 @@ func listAllFiles(layers []*Layer, name string, fileMode ...bool) ([]string, err
|
|||
if err := list(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
files := fileSet.Values()
|
||||
sort.Strings(files)
|
||||
files := slices.Sorted(fileSet.Seq())
|
||||
return files, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
package container
|
||||
|
||||
import (
|
||||
"iter"
|
||||
"maps"
|
||||
)
|
||||
|
||||
type Set[T comparable] map[T]struct{}
|
||||
|
||||
// SetOf creates a set and adds the specified elements to it.
|
||||
|
@ -63,3 +68,9 @@ func (s Set[T]) Values() []T {
|
|||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Seq returns a iterator over the elements in the set.
|
||||
// It returns a single-use iterator.
|
||||
func (s Set[T]) Seq() iter.Seq[T] {
|
||||
return maps.Keys(s)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -29,6 +30,14 @@ func TestSet(t *testing.T) {
|
|||
assert.True(t, s.Contains("key4"))
|
||||
assert.True(t, s.Contains("key5"))
|
||||
|
||||
values := s.Values()
|
||||
called := 0
|
||||
for value := range s.Seq() {
|
||||
called++
|
||||
assert.True(t, slices.Contains(values, value))
|
||||
}
|
||||
assert.EqualValues(t, len(values), called)
|
||||
|
||||
s = SetOf("key6", "key7")
|
||||
assert.False(t, s.Contains("key1"))
|
||||
assert.True(t, s.Contains("key6"))
|
||||
|
|
|
@ -64,7 +64,10 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
|||
} else if commit.ParentCount() == 0 {
|
||||
cmd.AddArguments("show").AddDynamicArguments(endCommit).AddDashesAndList(files...)
|
||||
} else {
|
||||
c, _ := commit.Parent(0)
|
||||
c, err := commit.Parent(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.AddArguments("diff", "-M").AddDynamicArguments(c.ID.String(), endCommit).AddDashesAndList(files...)
|
||||
}
|
||||
case RawDiffPatch:
|
||||
|
@ -74,7 +77,10 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
|||
} else if commit.ParentCount() == 0 {
|
||||
cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root").AddDynamicArguments(endCommit).AddDashesAndList(files...)
|
||||
} else {
|
||||
c, _ := commit.Parent(0)
|
||||
c, err := commit.Parent(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query := fmt.Sprintf("%s...%s", endCommit, c.ID.String())
|
||||
cmd.AddArguments("format-patch", "--no-signature", "--stdout").AddDynamicArguments(query).AddDashesAndList(files...)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ func TestRefName(t *testing.T) {
|
|||
|
||||
// Test pull names
|
||||
assert.Equal(t, "1", RefName("refs/pull/1/head").PullName())
|
||||
assert.True(t, RefName("refs/pull/1/head").IsPull())
|
||||
assert.True(t, RefName("refs/pull/1/merge").IsPull())
|
||||
assert.Equal(t, "my/pull", RefName("refs/pull/my/pull/head").PullName())
|
||||
|
||||
// Test for branch names
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/foreachref"
|
||||
|
@ -153,7 +154,9 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
|
|||
return nil, 0, fmt.Errorf("GetTagInfos: parse output: %w", err)
|
||||
}
|
||||
|
||||
sortTagsByTime(tags)
|
||||
slices.SortFunc(tags, func(b, a *Tag) int {
|
||||
return a.Tagger.When.Compare(b.Tagger.When)
|
||||
})
|
||||
tagsTotal := len(tags)
|
||||
if page != 0 {
|
||||
tags = util.PaginateSlice(tags, page, pageSize).([]*Tag)
|
||||
|
|
|
@ -6,6 +6,7 @@ package git
|
|||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -30,9 +31,11 @@ func TestRepository_GetTags(t *testing.T) {
|
|||
assert.EqualValues(t, "signed-tag", tags[0].Name)
|
||||
assert.EqualValues(t, "36f97d9a96457e2bab511db30fe2db03893ebc64", tags[0].ID.String())
|
||||
assert.EqualValues(t, "tag", tags[0].Type)
|
||||
assert.EqualValues(t, time.Date(2022, time.November, 13, 16, 40, 20, 0, time.FixedZone("", 3600)), tags[0].Tagger.When)
|
||||
assert.EqualValues(t, "test", tags[1].Name)
|
||||
assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[1].ID.String())
|
||||
assert.EqualValues(t, "tag", tags[1].Type)
|
||||
assert.EqualValues(t, time.Date(2018, time.June, 16, 20, 13, 18, 0, time.FixedZone("", -25200)), tags[1].Tagger.When)
|
||||
}
|
||||
|
||||
func TestRepository_GetTag(t *testing.T) {
|
||||
|
|
|
@ -5,7 +5,6 @@ package git
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
@ -107,23 +106,3 @@ l:
|
|||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
type tagSorter []*Tag
|
||||
|
||||
func (ts tagSorter) Len() int {
|
||||
return len([]*Tag(ts))
|
||||
}
|
||||
|
||||
func (ts tagSorter) Less(i, j int) bool {
|
||||
return []*Tag(ts)[i].Tagger.When.After([]*Tag(ts)[j].Tagger.When)
|
||||
}
|
||||
|
||||
func (ts tagSorter) Swap(i, j int) {
|
||||
[]*Tag(ts)[i], []*Tag(ts)[j] = []*Tag(ts)[j], []*Tag(ts)[i]
|
||||
}
|
||||
|
||||
// sortTagsByTime
|
||||
func sortTagsByTime(tags []*Tag) {
|
||||
sorter := tagSorter(tags)
|
||||
sort.Sort(sorter)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
|
@ -77,6 +78,16 @@ func newFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
|
|||
|
||||
commitSha := node.Data[m[4]:m[5]]
|
||||
filePath := node.Data[m[6]:m[7]]
|
||||
urlFullSource := urlFull
|
||||
if strings.HasSuffix(filePath, "?display=source") {
|
||||
filePath = strings.TrimSuffix(filePath, "?display=source")
|
||||
} else if Type(filePath) != "" {
|
||||
urlFullSource = node.Data[m[0]:m[6]] + filePath + "?display=source#" + node.Data[m[8]:m[1]]
|
||||
}
|
||||
filePath, err := url.QueryUnescape(filePath)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
hash := node.Data[m[8]:m[9]]
|
||||
|
||||
preview.start = m[0]
|
||||
|
@ -113,7 +124,7 @@ func newFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
|
|||
titleBuffer.WriteString(" – ")
|
||||
}
|
||||
|
||||
err = html.Render(titleBuffer, createLink(urlFull, filePath, "muted"))
|
||||
err = html.Render(titleBuffer, createLink(urlFullSource, filePath, "muted"))
|
||||
if err != nil {
|
||||
log.Error("failed to render filepathLink: %v", err)
|
||||
}
|
||||
|
|
|
@ -759,9 +759,6 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
|||
title = path.Base(name)
|
||||
}
|
||||
alt := props["alt"]
|
||||
if alt == "" {
|
||||
alt = name
|
||||
}
|
||||
|
||||
// make the childNode an image - if we can, we also place the alt
|
||||
childNode.Type = html.ElementNode
|
||||
|
@ -772,9 +769,6 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
|||
{Key: "title", Val: title},
|
||||
{Key: "alt", Val: alt},
|
||||
}
|
||||
if alt == "" {
|
||||
childNode.Attr = childNode.Attr[:2]
|
||||
}
|
||||
} else {
|
||||
if !absoluteLink {
|
||||
if ctx.IsWiki {
|
||||
|
|
|
@ -416,7 +416,7 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
otherImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+Other.jpg")
|
||||
encodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+%23.jpg")
|
||||
notencodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "some", "path", "Link+#.jpg")
|
||||
favicon := "http://google.com/favicon.ico"
|
||||
favicon := "https://forgejo.org/favicon.ico"
|
||||
|
||||
test(
|
||||
"[[Link]]",
|
||||
|
@ -424,28 +424,28 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a></p>`)
|
||||
test(
|
||||
"[[Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt="Link.jpg"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Link.jpg" alt="Link.jpg"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Link.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Link.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"[["+favicon+"]]",
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt="`+favicon+`"/></a></p>`,
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt="`+favicon+`"/></a></p>`)
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt=""/></a></p>`,
|
||||
`<p><a href="`+favicon+`" rel="nofollow"><img src="`+favicon+`" title="favicon.ico" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link]]",
|
||||
`<p><a href="`+url+`" rel="nofollow">Name</a></p>`,
|
||||
`<p><a href="`+urlWiki+`" rel="nofollow">Name</a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Name" alt="Name"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Name" alt="Name"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Name" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Name" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="AltName" alt="AltName"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="AltName" alt="AltName"/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="Title"/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Title" alt="Title"/></a></p>`)
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt=""/></a></p>`,
|
||||
`<p><a href="`+imgurlWiki+`" rel="nofollow"><img src="`+imgurlWiki+`" title="Title" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link.jpg|alt=AltName|title=Title]]",
|
||||
`<p><a href="`+imgurl+`" rel="nofollow"><img src="`+imgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
|
@ -472,16 +472,16 @@ func TestRender_ShortLinks(t *testing.T) {
|
|||
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a> <a href="`+otherURLWiki+`" rel="nofollow">Other Link</a> <a href="`+encodedURLWiki+`" rel="nofollow">Link?</a></p>`)
|
||||
test(
|
||||
"[[Link #.jpg]]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`)
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Link #.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]",
|
||||
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Title" alt="AltName"/></a></p>`,
|
||||
`<p><a href="`+encodedImgurlWiki+`" rel="nofollow"><img src="`+encodedImgurlWiki+`" title="Title" alt="AltName"/></a></p>`)
|
||||
test(
|
||||
"[[some/path/Link #.jpg]]",
|
||||
`<p><a href="`+notencodedImgurl+`" rel="nofollow"><img src="`+notencodedImgurl+`" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`,
|
||||
`<p><a href="`+notencodedImgurlWiki+`" rel="nofollow"><img src="`+notencodedImgurlWiki+`" title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p>`)
|
||||
`<p><a href="`+notencodedImgurl+`" rel="nofollow"><img src="`+notencodedImgurl+`" title="Link #.jpg" alt=""/></a></p>`,
|
||||
`<p><a href="`+notencodedImgurlWiki+`" rel="nofollow"><img src="`+notencodedImgurlWiki+`" title="Link #.jpg" alt=""/></a></p>`)
|
||||
test(
|
||||
"<p><a href=\"https://example.org\">[[foobar]]</a></p>",
|
||||
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`,
|
||||
|
@ -1026,4 +1026,138 @@ func TestRender_FilePreview(t *testing.T) {
|
|||
localMetas,
|
||||
)
|
||||
})
|
||||
|
||||
commitFileURL := util.URLJoin(markup.TestRepoURL, "src", "commit", "c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be", "path", "to", "file.md")
|
||||
|
||||
t.Run("rendered file with ?display=source", func(t *testing.T) {
|
||||
testRender(
|
||||
commitFileURL+"?display=source"+"#L1-L2",
|
||||
`<p></p>`+
|
||||
`<div class="file-preview-box">`+
|
||||
`<div class="header">`+
|
||||
`<div>`+
|
||||
`<a href="http://localhost:3000/gogits/gogs/src/commit/c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be/path/to/file.md?display=source#L1-L2" class="muted" rel="nofollow">path/to/file.md</a>`+
|
||||
`</div>`+
|
||||
`<span class="text small grey">`+
|
||||
`Lines 1 to 2 in <a href="http://localhost:3000/gogits/gogs/src/commit/c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be" class="text black" rel="nofollow">c991312</a>`+
|
||||
`</span>`+
|
||||
`</div>`+
|
||||
`<div class="ui table">`+
|
||||
`<table class="file-preview">`+
|
||||
`<tbody>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="1"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="gh"># A`+"\n"+`</span></code></td>`+
|
||||
`</tr>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="2"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="gh"></span>B`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`</tbody>`+
|
||||
`</table>`+
|
||||
`</div>`+
|
||||
`</div>`+
|
||||
`<p></p>`,
|
||||
localMetas,
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("rendered file without ?display=source", func(t *testing.T) {
|
||||
testRender(
|
||||
commitFileURL+"#L1-L2",
|
||||
`<p></p>`+
|
||||
`<div class="file-preview-box">`+
|
||||
`<div class="header">`+
|
||||
`<div>`+
|
||||
`<a href="http://localhost:3000/gogits/gogs/src/commit/c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be/path/to/file.md?display=source#L1-L2" class="muted" rel="nofollow">path/to/file.md</a>`+
|
||||
`</div>`+
|
||||
`<span class="text small grey">`+
|
||||
`Lines 1 to 2 in <a href="http://localhost:3000/gogits/gogs/src/commit/c9913120ed2c1e27c1d7752ecdb7a504dc7cf6be" class="text black" rel="nofollow">c991312</a>`+
|
||||
`</span>`+
|
||||
`</div>`+
|
||||
`<div class="ui table">`+
|
||||
`<table class="file-preview">`+
|
||||
`<tbody>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="1"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="gh"># A`+"\n"+`</span></code></td>`+
|
||||
`</tr>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="2"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="gh"></span>B`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`</tbody>`+
|
||||
`</table>`+
|
||||
`</div>`+
|
||||
`</div>`+
|
||||
`<p></p>`,
|
||||
localMetas,
|
||||
)
|
||||
})
|
||||
|
||||
commitFileURL = util.URLJoin(markup.TestRepoURL, "src", "commit", "190d9492934af498c3f669d6a2431dc5459e5b20", "path", "to", "file.go")
|
||||
|
||||
t.Run("normal file with ?display=source", func(t *testing.T) {
|
||||
testRender(
|
||||
commitFileURL+"?display=source"+"#L2-L3",
|
||||
`<p></p>`+
|
||||
`<div class="file-preview-box">`+
|
||||
`<div class="header">`+
|
||||
`<div>`+
|
||||
`<a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20/path/to/file.go?display=source#L2-L3" class="muted" rel="nofollow">path/to/file.go</a>`+
|
||||
`</div>`+
|
||||
`<span class="text small grey">`+
|
||||
`Lines 2 to 3 in <a href="http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" class="text black" rel="nofollow">190d949</a>`+
|
||||
`</span>`+
|
||||
`</div>`+
|
||||
`<div class="ui table">`+
|
||||
`<table class="file-preview">`+
|
||||
`<tbody>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="2"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="nx">B</span>`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="3"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner"><span class="nx">C</span>`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`</tbody>`+
|
||||
`</table>`+
|
||||
`</div>`+
|
||||
`</div>`+
|
||||
`<p></p>`,
|
||||
localMetas,
|
||||
)
|
||||
})
|
||||
|
||||
commitFileURL = util.URLJoin(markup.TestRepoURL, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d", "path", "to", "file%20%23.txt")
|
||||
|
||||
t.Run("file with strange characters in name", func(t *testing.T) {
|
||||
testRender(
|
||||
commitFileURL+"#L1",
|
||||
`<p></p>`+
|
||||
`<div class="file-preview-box">`+
|
||||
`<div class="header">`+
|
||||
`<div>`+
|
||||
`<a href="http://localhost:3000/gogits/gogs/src/commit/eeb243c3395e1921c5d90e73bd739827251fc99d/path/to/file%20%23.txt#L1" class="muted" rel="nofollow">path/to/file #.txt</a>`+
|
||||
`</div>`+
|
||||
`<span class="text small grey">`+
|
||||
`Line 1 in <a href="http://localhost:3000/gogits/gogs/src/commit/eeb243c3395e1921c5d90e73bd739827251fc99d" class="text black" rel="nofollow">eeb243c</a>`+
|
||||
`</span>`+
|
||||
`</div>`+
|
||||
`<div class="ui table">`+
|
||||
`<table class="file-preview">`+
|
||||
`<tbody>`+
|
||||
`<tr>`+
|
||||
`<td class="lines-num"><span data-line-number="1"></span></td>`+
|
||||
`<td class="lines-code chroma"><code class="code-inner">A`+"\n"+`</code></td>`+
|
||||
`</tr>`+
|
||||
`</tbody>`+
|
||||
`</table>`+
|
||||
`</div>`+
|
||||
`</div>`+
|
||||
`<p></p>`,
|
||||
localMetas,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ func TestRender_Images(t *testing.T) {
|
|||
|
||||
test(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt=""/></a></p>`)
|
||||
test(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
@ -119,7 +119,7 @@ func TestRender_Images(t *testing.T) {
|
|||
|
||||
test(
|
||||
"[["+title+"|"+url+"]]",
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt="`+title+`"/></a></p>`)
|
||||
`<p><a href="`+result+`" rel="nofollow"><img src="`+result+`" title="`+title+`" alt=""/></a></p>`)
|
||||
test(
|
||||
"[]("+href+")",
|
||||
`<p><a href="`+href+`" rel="nofollow"><img src="`+result+`" alt="`+title+`"/></a></p>`)
|
||||
|
@ -149,13 +149,13 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
|
|||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><a href="` + baseURLImages + `/images/icon-install.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-install.png" title="icon-install.png" alt="images/icon-install.png"/></a></th>
|
||||
<th><a href="` + baseURLImages + `/images/icon-install.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-install.png" title="icon-install.png" alt=""/></a></th>
|
||||
<th><a href="` + baseURLContent + `/Installation" rel="nofollow">Installation</a></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="` + baseURLImages + `/images/icon-usage.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-usage.png" title="icon-usage.png" alt="images/icon-usage.png"/></a></td>
|
||||
<td><a href="` + baseURLImages + `/images/icon-usage.png" rel="nofollow"><img src="` + baseURLImages + `/images/icon-usage.png" title="icon-usage.png" alt=""/></a></td>
|
||||
<td><a href="` + baseURLContent + `/Usage" rel="nofollow">Usage</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -164,9 +164,9 @@ func testAnswers(baseURLContent, baseURLImages string) []string {
|
|||
`<p><a href="http://www.excelsiorjet.com/" rel="nofollow">Excelsior JET</a> allows you to create native executables for Windows, Linux and Mac OS X.</p>
|
||||
<ol>
|
||||
<li><a href="https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop" rel="nofollow">Package your libGDX application</a><br/>
|
||||
<a href="` + baseURLImages + `/images/1.png" rel="nofollow"><img src="` + baseURLImages + `/images/1.png" title="1.png" alt="images/1.png"/></a></li>
|
||||
<a href="` + baseURLImages + `/images/1.png" rel="nofollow"><img src="` + baseURLImages + `/images/1.png" title="1.png" alt=""/></a></li>
|
||||
<li>Perform a test run by hitting the Run! button.<br/>
|
||||
<a href="` + baseURLImages + `/images/2.png" rel="nofollow"><img src="` + baseURLImages + `/images/2.png" title="2.png" alt="images/2.png"/></a></li>
|
||||
<a href="` + baseURLImages + `/images/2.png" rel="nofollow"><img src="` + baseURLImages + `/images/2.png" title="2.png" alt=""/></a></li>
|
||||
</ol>
|
||||
<h2 id="user-content-custom-id">More tests</h2>
|
||||
<p>(from <a href="https://www.markdownguide.org/extended-syntax/" rel="nofollow">https://www.markdownguide.org/extended-syntax/</a>)</p>
|
||||
|
@ -849,8 +849,8 @@ mail@domain.com
|
|||
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
|
||||
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -876,8 +876,8 @@ space</p>
|
|||
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/wiki/raw/image.jpg" rel="nofollow"><img src="/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/wiki/raw/image.jpg" rel="nofollow"><img src="/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -905,8 +905,8 @@ space</p>
|
|||
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="https://gitea.io/image.jpg" rel="nofollow"><img src="https://gitea.io/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="https://gitea.io/image.jpg" rel="nofollow"><img src="https://gitea.io/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -934,8 +934,8 @@ space</p>
|
|||
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/image.jpg" rel="nofollow"><img src="https://gitea.io/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="https://gitea.io/wiki/raw/image.jpg" rel="nofollow"><img src="https://gitea.io/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -963,8 +963,8 @@ space</p>
|
|||
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/image.jpg" rel="nofollow"><img src="/relative/path/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/image.jpg" rel="nofollow"><img src="/relative/path/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -992,8 +992,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1022,8 +1022,8 @@ space</p>
|
|||
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1052,8 +1052,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1082,8 +1082,8 @@ space</p>
|
|||
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/image.jpg" rel="nofollow"><img src="/user/repo/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/image.jpg" rel="nofollow"><img src="/user/repo/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1112,8 +1112,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1143,8 +1143,8 @@ space</p>
|
|||
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
@ -1174,8 +1174,8 @@ space</p>
|
|||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
|
||||
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt=""/></a><br/>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a><br/>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
x•ŽANÃ0EYû³GB;a U=D9€=þ&–ÚÙÓr} 7èêÞÓÓëåÒŒBœ^¬´¤˜yY8Ï:AІX}<7D>R×XkÎs"î;uìFº®9x” Œ ÊEdÐ’%Í~**Zß3\ºÙvíô9Й>nÿ8Žfxkû=<3D>[9K”%L>®ôêÙ{§<>7Ãs–;aÕvý4ÛhXOûH·Ô“þÕ†ûð`KÑ
|
|
@ -0,0 +1 @@
|
|||
x•ŽKŠ1@]çµ$¿J¥aæz€JRÁ@w+éØsýõ®ÞâñàåÛ²´ÖÛÃè"@VL&J3%f-ÑGDÒq2>FçjBOEݹË:ÀgÃ\1¤œ¦ê¦’kÀêªEM6DÔ,Ÿ\‚âǸÞ:\6é¾OülmÈ©;Ï|ƒ!GäŒE‚£6Z«üzòY¥Î²
¨m¸wÙ›üÂÿi‘.x-o³ò"›úŒLÌ
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
|||
4c1aaf56bcb9f39dcf65f3f250726850aed13cd6
|
||||
eeb243c3395e1921c5d90e73bd739827251fc99d
|
||||
|
|
|
@ -140,6 +140,11 @@ func CompileEmailGlobList(sec ConfigSection, keys ...string) (globs []glob.Glob)
|
|||
return globs
|
||||
}
|
||||
|
||||
// LoadServiceSetting loads the service settings
|
||||
func LoadServiceSetting() {
|
||||
loadServiceFrom(CfgProvider)
|
||||
}
|
||||
|
||||
func loadServiceFrom(rootCfg ConfigProvider) {
|
||||
sec := rootCfg.Section("service")
|
||||
Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
|
||||
|
|
|
@ -34,7 +34,7 @@ func AvatarHTML(src string, size int, class, name string) template.HTML {
|
|||
name = "avatar"
|
||||
}
|
||||
|
||||
return template.HTML(`<img loading="lazy" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
return template.HTML(`<img loading="lazy" alt="" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
}
|
||||
|
||||
// Avatar renders user avatars. args: user, size (int), class (string)
|
||||
|
|
|
@ -194,8 +194,8 @@ func TestRenderMarkdownToHtml(t *testing.T) {
|
|||
<a href="https://example.com" rel="nofollow">remote link</a>
|
||||
<a href="/image.jpg" target="_blank" rel="nofollow noopener"><img src="/image.jpg" alt="local image"/></a>
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt=""/></a>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt=""/></a>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow"><code>88fc37a3c0...12fc37a3c0 (hash)</code></a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow"><code>88fc37a3c0</code></a>
|
||||
|
|
|
@ -158,6 +158,7 @@ commits = fallback value for commits
|
|||
|
||||
found := lang1.HasKey("no-such")
|
||||
assert.False(t, found)
|
||||
assert.EqualValues(t, "no-such", lang1.TrString("no-such"))
|
||||
require.NoError(t, ls.Close())
|
||||
}
|
||||
|
||||
|
|
|
@ -225,9 +225,9 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
|
|||
format = msg
|
||||
} else {
|
||||
// First fallback: old-style translation
|
||||
idx, ok := l.store.trKeyToIdxMap[trKey]
|
||||
idx, foundIndex := l.store.trKeyToIdxMap[trKey]
|
||||
found := false
|
||||
if ok {
|
||||
if foundIndex {
|
||||
if msg, ok := l.idxToMsgMap[idx]; ok {
|
||||
format = msg // use the found translation
|
||||
found = true
|
||||
|
@ -239,7 +239,7 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
|
|||
if defaultLang, ok := l.store.localeMap[l.store.defaultLang]; ok {
|
||||
if msg := defaultLang.LookupNewStyleMessage(trKey); msg != "" {
|
||||
format = msg
|
||||
} else {
|
||||
} else if foundIndex {
|
||||
// Third fallback: old-style default language
|
||||
if msg, ok := defaultLang.idxToMsgMap[idx]; ok {
|
||||
format = msg
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
@ -47,13 +46,6 @@ func SliceRemoveAll[T comparable](slice []T, target T) []T {
|
|||
return slices.DeleteFunc(slice, func(t T) bool { return t == target })
|
||||
}
|
||||
|
||||
// Sorted returns the sorted slice
|
||||
// Note: The parameter is sorted inline.
|
||||
func Sorted[S ~[]E, E cmp.Ordered](values S) S {
|
||||
slices.Sort(values)
|
||||
return values
|
||||
}
|
||||
|
||||
// TODO: Replace with "maps.Values" once available, current it only in golang.org/x/exp/maps but not in standard library
|
||||
func ValuesOfMap[K comparable, V any](m map[K]V) []V {
|
||||
values := make([]V, 0, len(m))
|
||||
|
|
|
@ -680,6 +680,8 @@ Location = Umístění
|
|||
To = Název větve
|
||||
Biography = Životopis
|
||||
AccessToken = Přístupový token
|
||||
username_claiming_cooldown = Uživatelské jméno nelze získat, protože ještě neskončila doba jeho platnosti. Půjde jej získat %[1]s.
|
||||
email_domain_is_not_allowed = Doména uživatelské e-mailové adresy <b>%s</b> je v rozporu se seznamem EMAIL_DOMAIN_ALLOWLIST nebo EMAIL_DOMAIN_BLOCKLIST. Ujistěte se, že je vaše adresa správně nastavena.
|
||||
|
||||
[user]
|
||||
change_avatar=Změnit váš avatar…
|
||||
|
@ -804,7 +806,7 @@ old_password=Stávající heslo
|
|||
new_password=Nové heslo
|
||||
retype_new_password=Potvrzení nového hesla
|
||||
password_incorrect=Zadané heslo není správné.
|
||||
change_password_success=Vaše heslo bylo aktualizováno. Od teď se přihlašujte novým heslem.
|
||||
change_password_success=Vaše heslo bylo aktualizováno. Od nynějška používejte kpřihlášení nové heslo.
|
||||
password_change_disabled=Externě ověřovaní uživatelé nemohou aktualizovat své heslo prostřednictvím webového rozhraní Forgejo.
|
||||
|
||||
emails=E-mailové adresy
|
||||
|
@ -1056,6 +1058,8 @@ language.description = Tento jazyk bude uložen do vašeho účtu a po přihlá
|
|||
language.localization_project = Pomozte nám s překladem Forgejo do vašeho jazyka! <a href="%s">Více informací</a>.
|
||||
user_block_yourself = Nemůžete zablokovat sami sebe.
|
||||
pronouns_custom_label = Vlastní zájmena
|
||||
change_username_redirect_prompt.with_cooldown.few = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnech. Do té doby budete moci své staré uživatelské jméno znovu získat.
|
||||
change_username_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dni. Do té doby budete moci své staré uživatelské jméno znovu získat.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Repozitář obsahuje všechny soubory projektu, včetně historie revizí. Už jej hostujete jinde? <a href="%s">Migrovat repozitář</a>.
|
||||
|
@ -3001,6 +3005,8 @@ teams.invite.by=Pozvání od %s
|
|||
teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže.
|
||||
follow_blocked_user = Tuto organizaci nemůžete sledovat, protože jste v ní zablokováni.
|
||||
open_dashboard = Otevřít nástěnku
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dni. Do té doby budete moci své staré uživatelské jméno znovu získat.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnech. Do té doby budete moci své staré uživatelské jméno znovu získat.
|
||||
|
||||
[admin]
|
||||
dashboard=Přehled
|
||||
|
|
|
@ -629,6 +629,8 @@ password_special_one = Mindst ét specialtegn (tegnsætning, parenteser, anførs
|
|||
unsupported_login_type = Login typen understøttes ikke for at slette kontoen.
|
||||
cannot_add_org_to_team = En organisation kan ikke tilføjes som et holdmedlem.
|
||||
must_use_public_key = Nøglen du har angivet er en privat nøgle. Lad være med at uploade din private nøgle nogen steder. Brug din offentlige nøgle i stedet.
|
||||
username_claiming_cooldown = Brugernavnet kan ikke gøres krav på, fordi dets nedkølingsperiode endnu ikke er forbi. Det kan gøres krav på %[1]s.
|
||||
email_domain_is_not_allowed = Domænet for brugerens e-mailadresse <b>%s</b> er i konflikt med EMAIL_DOMAIN_ALLOWLIST eller EMAIL_DOMAIN_BLOCKLIST. Sørg for, at du har indstillet e-mailadressen korrekt.
|
||||
|
||||
[user]
|
||||
change_avatar = Skift din avatar…
|
||||
|
@ -782,7 +784,7 @@ uploaded_avatar_is_too_big = Den uploadede filstørrelse (%d KiB) overstiger den
|
|||
email_deletion_desc = E-mailadressen og relaterede oplysninger vil blive fjernet fra din konto. Git commits af denne e-mailadresse forbliver uændret. Fortsætte?
|
||||
choose_new_avatar = Vælg ny avatar
|
||||
update_avatar = Opdater avatar
|
||||
change_password_success = Din adgangskode er blevet opdateret. Log ind med din nye adgangskode fra nu af.
|
||||
change_password_success = Din adgangskode er blevet opdateret. Fra nu af skal du bruge din nye adgangskode til at logge ind.
|
||||
add_email = Tilføj e-mailadresse
|
||||
add_openid = Tilføj OpenID URI
|
||||
add_email_confirmation_sent = En bekræftelses-e-mail er blevet sendt til "%s". For at bekræfte din e-mailadresse, tjek venligst din indbakke og følg det medfølgende link inden for de næste %s.
|
||||
|
@ -972,6 +974,8 @@ delete_with_all_comments = Din konto er yngre end %s. For at undgå spøgelsesko
|
|||
delete_account_title = Slet brugerkonto
|
||||
user_block_yourself = Du kan ikke blokere dig selv.
|
||||
pronouns_custom_label = Brugerdefinerede stedord
|
||||
change_username_redirect_prompt.with_cooldown.one = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dag, du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
|
||||
change_username_redirect_prompt.with_cooldown.few = Det gamle brugernavn vil være tilgængeligt for alle efter en nedkølingsperiode på %[1]d dage, du kan stadig kræve det gamle brugernavn tilbage i nedkølingsperioden.
|
||||
|
||||
[repo]
|
||||
rss.must_be_on_branch = Du skal være på en gren for at have et RSS-feed.
|
||||
|
@ -1761,6 +1765,28 @@ pulls.compare_changes = Ny pull-anmodning
|
|||
issues.summary_card_alt = Oversigtskort over et problem med titlen "%s" i depotet %s
|
||||
pulls.edit.already_changed = Kunne ikke gemme ændringer af pull-anmodningen. Det ser ud til, at indholdet allerede er blevet ændret af en anden bruger. Opdater siden, og prøv at redigere igen for at undgå at overskrive deres ændringer
|
||||
pulls.sign_in_require = <a href="%s">Log ind</a> for at oprette en ny pull-anmodning.
|
||||
pulls.allow_edits_from_maintainers = Tillad redigeringer fra vedligeholdere
|
||||
pulls.allow_edits_from_maintainers_desc = Brugere med skriveadgang til basisgrenen kan også trykke til denne gren
|
||||
pulls.allow_edits_from_maintainers_err = Opdatering mislykkedes
|
||||
pulls.compare_base = flet ind i
|
||||
pulls.compare_compare = pull fra
|
||||
pulls.switch_comparison_type = Skift sammenligningstype
|
||||
pulls.switch_head_and_base = Skift hoved og base
|
||||
pulls.filter_branch = Filter gren
|
||||
pulls.compare_changes_desc = Vælg den gren, der skal flettes ind i, og den gren, der skal trækkes fra.
|
||||
pulls.has_viewed_file = Set
|
||||
pulls.has_changed_since_last_review = Ændret siden din sidste gennemgang
|
||||
pulls.no_results = Ingen resultater fundet.
|
||||
pulls.show_all_commits = Vis alle commits
|
||||
pulls.show_changes_since_your_last_review = Vis ændringer siden din sidste gennemgang
|
||||
pulls.showing_only_single_commit = Viser kun ændringer af commit %[1]s
|
||||
pulls.showing_specified_commit_range = Viser kun ændringer mellem %[1]s..%[2]s
|
||||
pulls.select_commit_hold_shift_for_range = Vælg commit. Hold Shift + klik for at vælge et område
|
||||
pulls.review_only_possible_for_full_diff = Gennemgang er kun mulig, når du ser den fulde diff
|
||||
pulls.filter_changes_by_commit = Filtrer efter commit
|
||||
pulls.expand_files = Udvid alle filer
|
||||
pulls.collapse_files = Skjul alle filer
|
||||
pulls.viewed_files_label = %[1]d / %[2]d filer set
|
||||
|
||||
[notification]
|
||||
watching = Overvåger
|
||||
|
|
|
@ -681,6 +681,8 @@ Website = Webseite
|
|||
Location = Ort
|
||||
To = Branchname
|
||||
AccessToken = Zugangstoken
|
||||
username_claiming_cooldown = Der Benutzername kann nicht beansprucht werden, weil seine Schutzzeit noch nicht vorbei ist. Er kann am %[1]s beansprucht werden.
|
||||
email_domain_is_not_allowed = Die Domain der E-Mail-Adresse des Benutzers <b>%s</b> steht in Konflikt mit EMAIL_DOMAIN_ALLOWLIST oder EMAIL_DOMAIN_BLOCKLIST. Bitte stelle sicher, dass du die E-Mail-Adresse richtig gesetzt hast.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -806,7 +808,7 @@ old_password=Aktuelles Passwort
|
|||
new_password=Neues Passwort
|
||||
retype_new_password=Neues Passwort bestätigen
|
||||
password_incorrect=Das aktuelle Passwort ist falsch.
|
||||
change_password_success=Dein Passwort wurde aktualisiert. Bitte verwende dieses beim nächsten Einloggen.
|
||||
change_password_success=Dein Passwort wurde aktualisiert. Verwende ab jetzt dein neues Passwort zum Einloggen.
|
||||
password_change_disabled=Benutzer, die nicht von Forgejo verwaltet werden, können ihr Passwort im Web-Interface nicht ändern.
|
||||
|
||||
emails=E-Mail-Adressen
|
||||
|
@ -1058,6 +1060,8 @@ language.localization_project = Hilf uns, Forgejo in deine Sprache zu übersetze
|
|||
language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt.
|
||||
user_block_yourself = Du kannst dich nicht selbst blockieren.
|
||||
pronouns_custom_label = Individuelle Pronomen
|
||||
change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
|
||||
[repo]
|
||||
owner=Besitzer
|
||||
|
@ -3004,6 +3008,8 @@ teams.invite.by=Von %s eingeladen
|
|||
teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten.
|
||||
follow_blocked_user = Du kannst dieser Organisation nicht folgen, weil diese Organisation dich blockiert hat.
|
||||
open_dashboard = Übersicht öffnen
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
|
||||
|
||||
[admin]
|
||||
dashboard=Übersicht
|
||||
|
@ -3109,7 +3115,7 @@ dashboard.sync_branch.started=Synchronisierung der Branches gestartet
|
|||
dashboard.rebuild_issue_indexer=Issue-Indexer neu bauen
|
||||
|
||||
users.user_manage_panel=Benutzerkonten verwalten
|
||||
users.new_account=Benutzerkonto erstellen
|
||||
users.new_account=Benutzeraccount erstellen
|
||||
users.name=Benutzername
|
||||
users.full_name=Vollständiger Name
|
||||
users.activated=Aktiviert
|
||||
|
@ -3579,7 +3585,7 @@ comment_pull=`hat den Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> kommentiert`
|
|||
merge_pull_request=`führte Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> zusammen`
|
||||
auto_merge_pull_request=`führte Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> automatisch zusammen`
|
||||
transfer_repo=hat Repository <code>%s</code> übertragen zu <a href="%s">%s</a>
|
||||
push_tag=Tag <a href="%[2]s">%[3]s</a> nach <a href="%[1]s">%[4]s</a> wurde gepusht
|
||||
push_tag=hat Tag <a href="%[2]s">%[3]s</a> auf <a href="%[1]s">%[4]s</a> gepusht
|
||||
delete_tag=hat Tag %[2]s in <a href="%[1]s">%[3]s</a> gelöscht
|
||||
delete_branch=hat Branch %[2]s in <a href="%[1]s">%[3]s</a> gelöscht
|
||||
compare_branch=Vergleichen
|
||||
|
|
|
@ -644,6 +644,7 @@ team_name_been_taken = The team name is already taken.
|
|||
team_no_units_error = Allow access to at least one repository section.
|
||||
email_been_used = The email address is already used.
|
||||
email_invalid = The email address is invalid.
|
||||
email_domain_is_not_allowed = The domain of the user's email address <b>%s</b> conflicts with EMAIL_DOMAIN_ALLOWLIST or EMAIL_DOMAIN_BLOCKLIST. Make sure you have set the email address correctly.
|
||||
openid_been_used = The OpenID address "%s" is already used.
|
||||
username_password_incorrect = Username or password is incorrect.
|
||||
password_complexity = Password does not pass complexity requirements:
|
||||
|
@ -819,7 +820,7 @@ old_password = Current password
|
|||
new_password = New password
|
||||
retype_new_password = Confirm new password
|
||||
password_incorrect = The current password is incorrect.
|
||||
change_password_success = Your password has been updated. Sign in using your new password from now on.
|
||||
change_password_success = Your password has been updated. From now on, use your new password to sign in.
|
||||
password_change_disabled = Non-local users cannot update their password through the Forgejo web interface.
|
||||
|
||||
manage_emails = Manage email addresses
|
||||
|
@ -1192,6 +1193,7 @@ archive.title = This repository is archived. You can view files and clone it, bu
|
|||
archive.title_date = This repository has been archived on %s. You can view files and clone it, but cannot push or open issues or pull requests.
|
||||
archive.issue.nocomment = This repository is archived. You cannot comment on issues.
|
||||
archive.pull.nocomment = This repository is archived. You cannot comment on pull requests.
|
||||
archive.pull.noreview = This repository is archived. You cannot review pull requests.
|
||||
|
||||
form.reach_limit_of_creation_1 = The owner has already reached the limit of %d repository.
|
||||
form.reach_limit_of_creation_n = The owner has already reached the limit of %d repositories.
|
||||
|
@ -1430,6 +1432,7 @@ editor.user_no_push_to_branch = User cannot push to branch
|
|||
editor.require_signed_commit = Branch requires a signed commit
|
||||
editor.cherry_pick = Cherry-pick %s onto:
|
||||
editor.revert = Revert %s onto:
|
||||
editor.commit_email = Commit email
|
||||
|
||||
commits.desc = Browse source code change history.
|
||||
commits.commits = Commits
|
||||
|
|
|
@ -56,7 +56,7 @@ mirror=Réplica
|
|||
new_repo=Nuevo repositorio
|
||||
new_migrate=Nueva migración
|
||||
new_mirror=Nueva réplica
|
||||
new_fork=Nuevo fork de repositorio
|
||||
new_fork=Nueva bifurcación del repositorio
|
||||
new_org=Nueva organización
|
||||
new_project=Nuevo proyecto
|
||||
new_project_column=Nueva columna
|
||||
|
@ -75,7 +75,7 @@ collaborative=Colaborativo
|
|||
forks=Forks
|
||||
|
||||
activities=Actividades
|
||||
pull_requests=Pull requests
|
||||
pull_requests=Solicitudes de incorporación de cambios
|
||||
issues=Incidencias
|
||||
milestones=Hitos
|
||||
|
||||
|
@ -156,8 +156,8 @@ invalid_data = Datos inválidos: %v
|
|||
confirm_delete_artifact = ¿Estás seguro de que deseas eliminar el artefacto "%s"?
|
||||
more_items = Mas cosas
|
||||
copy_generic = Copiar al portapapeles
|
||||
filter.not_fork = No forks
|
||||
filter.is_fork = Forks
|
||||
filter.not_fork = No hay bifurcaciones
|
||||
filter.is_fork = Bifurcaciones
|
||||
test = Test
|
||||
error413 = Has agotado tu cuota.
|
||||
new_repo.title = Nuevo repositorio
|
||||
|
@ -397,8 +397,8 @@ code_search_results=Resultados de búsqueda para «%s»
|
|||
code_last_indexed_at=Indexado por última vez %s
|
||||
relevant_repositories_tooltip=Repositorios que son bifurcaciones o que no tienen ningún tema, ningún icono, y ninguna descripción están ocultos.
|
||||
relevant_repositories=Solo se muestran repositorios relevantes, <a href="%s">mostrar resultados sin filtrar</a>.
|
||||
forks_few = %d forks
|
||||
forks_one = %d fork
|
||||
forks_few = %d bifurcaciones
|
||||
forks_one = %d bifurcación
|
||||
stars_few = %d estrellas
|
||||
stars_one = %d estrella
|
||||
|
||||
|
@ -1070,10 +1070,10 @@ visibility=Visibilidad
|
|||
visibility_description=Sólo el propietario o los miembros de la organización -si tienen derechos- podrán verlo.
|
||||
visibility_helper=Hacer el repositorio privado
|
||||
visibility_helper_forced=El administrador de su sitio obliga a nuevos repositorios a ser privados.
|
||||
visibility_fork_helper=(Cambiar esto afectará a la visibilidad de todos los forks.)
|
||||
visibility_fork_helper=(Cambiar esto afectará a la visibilidad de todas las bifurcaciones.)
|
||||
clone_helper=¿Necesita ayuda para clonar? Visite <a target="_blank" rel="noopener noreferrer" href="%s">Ayuda</a>.
|
||||
fork_repo=Hacer fork del repositorio
|
||||
fork_from=Crear un fork desde
|
||||
fork_repo=Hacer una bifurcación del repositorio
|
||||
fork_from=Crear una bifurcación desde
|
||||
already_forked=Ya ha forkeado %s
|
||||
fork_to_different_account=Forkear a una cuenta diferente
|
||||
fork_visibility_helper=La visibilidad de un repositorio del cual se ha hecho fork no puede ser cambiada.
|
||||
|
@ -3852,7 +3852,7 @@ search = Buscar...
|
|||
type_tooltip = Tipo de búsqueda
|
||||
project_kind = Buscar proyectos...
|
||||
branch_kind = Buscar ramas...
|
||||
commit_kind = Buscar commits...
|
||||
commit_kind = Buscar confirmaciones...
|
||||
repo_kind = Buscar repositorios...
|
||||
user_kind = Buscar usuarios...
|
||||
org_kind = Buscar organizaciones...
|
||||
|
|
|
@ -108,7 +108,7 @@ never = Mitte kunagi
|
|||
unknown = Teadmata
|
||||
rss_feed = RSS infovoog
|
||||
confirm_delete_artifact = Kas oled kindel et soovite artefakti "%s" kustutada?
|
||||
pin =
|
||||
pin =
|
||||
artifacts = Artefaktid
|
||||
archived = Arhiveeritud
|
||||
concept_system_global = Ülemaailmne
|
||||
|
|
|
@ -1756,7 +1756,7 @@ issues.close = Sulje ongelma
|
|||
issues.no_content = Ei kuvausta.
|
||||
pulls.reject_count_1 = %d muutospyyntö
|
||||
pulls.update_branch_success = Haarapäivitys onnistui
|
||||
milestones.completeness = <strong>%d%%</strong> valmiina
|
||||
milestones.completeness = <strong>%d% %</strong> valmiina
|
||||
contributors.contribution_type.additions = Lisäykset
|
||||
contributors.contribution_type.deletions = Poistot
|
||||
settings.webhook_deletion_success = Webkoukku on poistettu.
|
||||
|
@ -2088,6 +2088,9 @@ new_from_template_description = Voit valita olemassa olevan repon mallipohjan ja
|
|||
new_advanced = Lisäasetukset
|
||||
new_advanced_expand = Laajenna napsauttamalla
|
||||
template_description = Repojen mallipohjat mahdollistavat uusien repojen luomisen halutulla hakemistorakenteella, tiedostoilla ja valinnaisilla asetuksilla.
|
||||
settings.enter_repo_name = Kirjoita omistajan ja repon nimi täsmälleen kuten esitetty:
|
||||
settings.confirmation_string = Vahvistusteksti
|
||||
settings.delete_notices_2 = - Tämä toiminto poistaa pysyvästi repon <strong>%s</strong> mukaan lukien koodin, ongelmat, kommentit, wikidatan ja avustaja-asetukset.
|
||||
|
||||
|
||||
|
||||
|
@ -2578,6 +2581,12 @@ commit_repo = työnsi haaraan <a href="%[2]s">%[3]s</a> repossa <a href="%[1]s">
|
|||
create_issue = `avasi ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reopen_issue = `avasi uudelleen ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
create_pull_request = `loi vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reopen_pull_request = `avasi uudelleen vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_pull_request = `sulki vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
comment_issue = `kommentoi ongelmaa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_issue = `sulki ongelman <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
merge_pull_request = `yhdisti vetopyynnön <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
comment_pull = `kommentoi vetopyyntöä <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
||||
[tool]
|
||||
now=nyt
|
||||
|
@ -2624,6 +2633,7 @@ error.not_signed_commit=Kommitti ei ole allekirjoitettu
|
|||
error.extract_sign = Allekirjoituksen purkaminen epäonnistui
|
||||
default_key = Allekirjoitettu oletusavaimella
|
||||
error.failed_retrieval_gpg_keys = Ei saatu yhtäkään kommitin tekijän tiliin liitettyä avainta
|
||||
error.generate_hash = Tiivisteen luominen kommitista epäonnistui
|
||||
|
||||
[units]
|
||||
unit = Yksikkö
|
||||
|
@ -2765,6 +2775,11 @@ alpine.registry.info = Valitse $branch ja $repository alla olevasta listasta.
|
|||
container.images.title = Levykuvat
|
||||
owner.settings.cargo.initialize = Alusta indeksi
|
||||
owner.settings.cargo.initialize.description = Erityinen Git-repoindeksi vaaditaan Cargo-rekisterin käyttämiseksi. Tämän valinnan käyttäminen luo (tarvittaessa uudelleen) repon ja määrittää sen asetukset automaattisesti.
|
||||
settings.link.error = Repositorion linkin päivittäminen epäonnistui.
|
||||
alt.repository.multiple_groups = Tämä paketti on saatavilla useissa ryhmissä.
|
||||
alt.repository.architectures = Arkkitehtuurit
|
||||
alt.install = Asenna paketti
|
||||
alt.registry.install = Asenna paketti suorittamalla komento:
|
||||
|
||||
[secrets]
|
||||
creation.failed = Salaisuuden lisääminen epäonnistui.
|
||||
|
|
|
@ -640,6 +640,8 @@ AccessToken = Token ng pag-access
|
|||
Biography = Byograpya
|
||||
Location = Lokasyon
|
||||
visit_rate_limit = Natugunan ang limitasyon sa rate ng malayuang pagbisita.
|
||||
username_claiming_cooldown = Hindi ma-claim ang username na ito, dahil hindi pa tapos ang panahon ng cooldown. Maari itong i-claim sa %[1]s.
|
||||
email_domain_is_not_allowed = Sumasalungat ang domain ng email address ng user <b>%s</b> sa EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Siguraduhing natakda mo ang email address nang tama.
|
||||
|
||||
[user]
|
||||
joined_on = Sumali noong %s
|
||||
|
@ -784,7 +786,7 @@ old_password = Kasalukuyang password
|
|||
new_password = Bagong password
|
||||
retype_new_password = Kumpirmahin ang bagong password
|
||||
password_incorrect = Mali ang kasalukuyang password.
|
||||
change_password_success = Na-update na ang iyong password. Mag-sign in gamit ng bagong password simula ngayon.
|
||||
change_password_success = Na-update na ang iyong password. Simula ngayon, gamitin ang iyong bagong password para mag-sign in.
|
||||
password_change_disabled = Hindi mababago ng mga di-lokal na gumagamit ang kanilang password sa pamamagitan ng Forgejo web interface.
|
||||
emails = Mga email address
|
||||
manage_emails = Ipamahala ang mga email address
|
||||
|
@ -999,6 +1001,8 @@ language.description = Mase-save ang wika sa iyong account at gagamitin bilang d
|
|||
language.localization_project = Tulungan kaming isalin ang Forgejo sa iyong wika! <a href="%s">Matuto pa</a>.
|
||||
pronouns_custom_label = Mga pasadyang pronoun
|
||||
user_block_yourself = Hindi mo maaring harangan ang sarili mo.
|
||||
change_username_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
|
||||
change_username_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
|
||||
|
||||
[repo]
|
||||
template_description = Ang mga template na repositoryo ay pinapayagan ang mga gumagamit na mag-generate ng mga bagong repositoryo na may magkatulad na istraktura ng direktoryo, mga file, at opsyonal na mga setting.
|
||||
|
@ -2911,7 +2915,7 @@ dashboard.delete_old_system_notices = Burahin ang lahat ng mga lumang paunawa ng
|
|||
dashboard.gc_lfs = I-garbage collect ang mga LFS meta object
|
||||
dashboard.stop_zombie_tasks = Itigil ang mga zombie action task
|
||||
users.user_manage_panel = Ipamahala ang mga user account
|
||||
users.new_account = Gumawa ng User Account
|
||||
users.new_account = Gumawa ng user account
|
||||
users.auth_login_name = Pangalan ng sign-in authentication
|
||||
users.password_helper = Iwanang walang laman ang password upang panatilihing hindi nabago.
|
||||
users.max_repo_creation = Pinakamataas na numero ng mga repositoryo
|
||||
|
@ -3394,6 +3398,8 @@ teams.owners_permission_desc = Ang mga owner ay may punong access sa <strong>lah
|
|||
teams.add_nonexistent_repo = Hindi pa umiiral ang repositoryo na sinusubukan mong idagdag. Mangyaring gawin iyan muna.
|
||||
teams.all_repositories = Lahat ng mga repositoryo
|
||||
teams.all_repositories_helper = Ang koponan ay may access sa lahat ng mga repositoryo. Ang pagpili nito ay <strong>idadagdag ang lahat ng mga umiiral</strong> na repositoryo sa koponan.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown.
|
||||
|
||||
|
||||
[packages]
|
||||
|
@ -3571,7 +3577,7 @@ alt.registry = I-setup ang registry na ito mula sa command line:
|
|||
alt.registry.install = Para i-install ang package na ito, patakbuhin ang sumusunod na command:
|
||||
alt.install = I-install ang package
|
||||
alt.setup = Idagdag ang repositoryo sa listahan ng mga nakakonektang repositoryo (piliin ang kinakailangang architechture sa halip ng '_arch_'):
|
||||
alt.repository = Info ng Repositoryo
|
||||
alt.repository = Info ng repositoryo
|
||||
alt.repository.architectures = Mga architechture
|
||||
alt.repository.multiple_groups = Available ang package na ito sa iba't ibang grupo.
|
||||
|
||||
|
@ -3693,7 +3699,7 @@ approve_pull_request = `inaprubahan ang <a href="%[1]s">%[3]s#%[2]s</a>`
|
|||
review_dismissed_reason = Dahilan:
|
||||
compare_branch = Ikumpara
|
||||
reject_pull_request = `nagmungkahi ng mga pagbabago para sa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
rename_repo = pinalitan ang pangalan ng repositoryo mula <code>%[1]s</code> sa <a href="%[2]s">%[3]#</a>
|
||||
rename_repo = pinalitan ang pangalan ng repositoryo mula <code>%[1]s</code> sa <a href="%[2]s">%[3]s</a>
|
||||
close_issue = `sinara ang isyu na <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed = `na-dismiss ang pagsusuri mula <b>%[4]s</b> para sa <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
close_pull_request = `sinara ang hiling sa paghila na <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
|
|
@ -680,6 +680,7 @@ Biography = Biographie
|
|||
Website = Site web
|
||||
Location = Emplacement
|
||||
To = Nom de la branche
|
||||
email_domain_is_not_allowed = Le domaine <b>%s</b> du courriel utilisateur entre en conflit avec EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Veuillez vous assurer le courriel est renseigné.
|
||||
|
||||
[user]
|
||||
change_avatar=Changer votre avatar…
|
||||
|
|
|
@ -75,7 +75,7 @@ mirrors=Spoguļglabātavas
|
|||
collaborative=Līdzdarbošanās
|
||||
forks=Atzarojumi
|
||||
|
||||
activities=Aktivitāte
|
||||
activities=Darbības
|
||||
pull_requests=Izmaiņu pieprasījumi
|
||||
issues=Pieteikumi
|
||||
milestones=Atskaites punkti
|
||||
|
@ -678,6 +678,8 @@ Biography = Dzīves un darbības apraksts
|
|||
Website = Tīmekļvietne
|
||||
AccessToken = Piekļuves pilnvara
|
||||
To = Zara nosaukums
|
||||
username_claiming_cooldown = Šo lietotājvārdu vēl nevar izmantot, jo tā noilgums vēl nav beidzies. To varēs izmantot %[1]s.
|
||||
email_domain_is_not_allowed = Lietotāja e-pasta adreses <b>%s</b> domēna vārds ir pretrunāt ar EMAIL_DOMAIN_ALLOWLIST vai EMAIL_DOMAIN_BLOCKLIST. Jāpārliecinās, ka e-pasta adrese ir norādīta pareizi.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -695,7 +697,7 @@ following_few=%d seko
|
|||
follow=Sekot
|
||||
unfollow=Nesekot
|
||||
user_bio=Biogrāfija
|
||||
disabled_public_activity=Šis lietotājs ir atslēdzies iespēju aplūkot tā aktivitāti.
|
||||
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību visiem.
|
||||
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
|
||||
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
|
||||
show_on_map=Rādīt šo vietu kartē
|
||||
|
@ -803,7 +805,7 @@ old_password=Pašreizējā parole
|
|||
new_password=Jaunā parole
|
||||
retype_new_password=Apstiprināt jauno paroli
|
||||
password_incorrect=Ievadīta nepareiza pašreizējā parole.
|
||||
change_password_success=Parole tika sekmīgi nomainīta. Turpmāk jāpiesakās ar savu jauno paroli.
|
||||
change_password_success=Parole tika atjaunināta. Turpmāk jāizmanto sava jaunā parole, lai pieteiktos.
|
||||
password_change_disabled=Ārējie lietotāji nevar mainīt savu paroli Forgejo tīmekļa saskarnē.
|
||||
|
||||
emails=E-pasta adreses
|
||||
|
@ -904,7 +906,7 @@ added_on=Pievienots %s
|
|||
valid_until_date=Derīgs līdz %s
|
||||
valid_forever=Derīgs mūžīgi
|
||||
last_used=Pēdējo reizi izmantota
|
||||
no_activity=Nav nesenas aktivitātes
|
||||
no_activity=Nav nesenu darbību
|
||||
can_read_info=Lasīt
|
||||
can_write_info=Rakstīt
|
||||
key_state_desc=Šī atslēga ir izmantota pēdējo 7 dienu laikā
|
||||
|
@ -1055,6 +1057,8 @@ additional_repo_units_hint_description = Attēlot norādi "Iespējot vēl" glab
|
|||
language.description = Šī valoda tiks saglabāta kontā un pēc pieteikšanās tiks izmantota kā noklusējuma.
|
||||
user_block_yourself = Nevar liegt sevi.
|
||||
pronouns_custom_label = Pielāgoti vietniekvārdi
|
||||
change_username_redirect_prompt.with_cooldown.one = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d diena. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
change_username_redirect_prompt.with_cooldown.few = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d dienas. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Glabātava satur visas projekta datnes, tajā skaitā izmaiņu vēsturi. Jau tiek izmantota kaut kur citur? <a href="%s">Pārcelt glabātavu</a>.
|
||||
|
@ -1652,7 +1656,7 @@ issues.save=Saglabāt
|
|||
issues.label_title=Nosaukums
|
||||
issues.label_description=Apraksts
|
||||
issues.label_color=Krāsa
|
||||
issues.label_exclusive=Ekskluzīvs
|
||||
issues.label_exclusive=Sevišķa
|
||||
issues.label_archive=Arhivēt iezīmi
|
||||
issues.label_archived_filter=Rādīt arhivētās iezīmes
|
||||
issues.label_archive_tooltip=Arhivētās iezīmes pēc noklusējuma netiek iekļautas ieteikumos, kad meklē pēc iezīmes.
|
||||
|
@ -2033,7 +2037,7 @@ wiki.last_updated=Pēdējo reizi labota %s
|
|||
wiki.page_name_desc=Jāievada šīs vikivietnes lapas nosaukums. Daži īpašie nosaukumi ir: "Home", "_Sidebar" un "_Footer".
|
||||
wiki.original_git_entry_tooltip=Rādīt sākotnējo Git datni, nevis izmantot draudzīgo saiti.
|
||||
|
||||
activity=Aktivitāte
|
||||
activity=Notikumi
|
||||
activity.period.filter_label=Laika periods:
|
||||
activity.period.daily=1 diena
|
||||
activity.period.halfweekly=3 dienas
|
||||
|
@ -2999,6 +3003,8 @@ teams.invite.by=Uzaicināja %s
|
|||
teams.invite.description=Lūgums nospiest zemāk esošo pogu, lai pievienotos komandai.
|
||||
open_dashboard = Atvērt pārskata paneli
|
||||
follow_blocked_user = Tu nevari sekot šai apvienībai, jo tā ir liegusi Tevi.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d diena. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Vecais lietotājvārds būs pieejams visiem pēc noilguma, kas ir %[1]d dienas. Šajā laikā ir iespējams to atkal sākt izmantot.
|
||||
|
||||
[admin]
|
||||
dashboard=Pārskata panelis
|
||||
|
@ -3761,7 +3767,7 @@ settings.link.select=Atlasīt glabātavu
|
|||
settings.link.button=Atjaunināt glabātavas saiti
|
||||
settings.link.success=Glabātavas saite tika sekmīgi atjaunināta.
|
||||
settings.link.error=Neizdevās atjaunināt glabātavas saiti.
|
||||
settings.delete=Dzēst pakotni
|
||||
settings.delete=Izdzēst pakotni
|
||||
settings.delete.description=Pakotne tiks neatgriezeniski izdzēsta.
|
||||
settings.delete.notice=Tiks izdzēsta pakotne %s (%s). Šī darbība ir neatgriezeniska. Tiešām turpināt?
|
||||
settings.delete.success=Pakotne tika izdzēsta.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[common]
|
||||
enable_javascript = Denne nettsiden behøver JavaScript.
|
||||
enable_javascript = Denne nettsiden krever JavaScript.
|
||||
toc = Innholdsfortegnelse
|
||||
licenses = Lisenser
|
||||
return_to_forgejo = Tilbake til Forgejo
|
||||
|
@ -126,6 +126,13 @@ webauthn_sign_in = Trykk på knappen på sikkerhetsnøkkelen din. Dersom nøkkel
|
|||
copy_path = Kopier sti
|
||||
webauthn_error_unable_to_process = Tjeneren kunne ikke behandle forespørselen din.
|
||||
webauthn_error_empty = Du må gi nøkkelen et navn.
|
||||
toggle_menu = Åpne/lukke meny
|
||||
twofa_scratch = To-faktor skrapekode
|
||||
webauthn_press_button = Vennligst trykk på knappen på sikkerhetsnøkkelen…
|
||||
webauthn_error_duplicated = Sikkerhetsnøkkelen er ikke tillatt for denne forespørselen. Vennligst sørg for at nøkkelen ikke allerede er registrert.
|
||||
webauthn_error_timeout = Et tidsavbrudd oppsto før nøkkelen din kunne leses. Vennligst last inn siden på nytt og prøv igjen.
|
||||
new_fork = Ny fork av repository
|
||||
collaborative = Samarbeidende
|
||||
|
||||
[search]
|
||||
search = Søk...
|
||||
|
|
|
@ -681,6 +681,8 @@ To = Branch naam
|
|||
Website = Website
|
||||
AccessToken = Toegangstoken
|
||||
Pronouns = Voornaamwoorden
|
||||
username_claiming_cooldown = De gebruikersnaam kan niet opgeëist worden, omdat de afkoelperiode nog niet voorbij is. Hij kan worden opgeëist op %[1]s.
|
||||
email_domain_is_not_allowed = Het domein van het e-mailadres van de gebruiker <b>%s</b> is in strijd met EMAIL_DOMAIN_ALLOWLIST of EMAIL_DOMAIN_BLOCKLIST. Controleer of u het e-mailadres correct hebt ingesteld.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -1058,6 +1060,8 @@ language.description = Deze taal wordt opgeslagen in uw account en wordt als sta
|
|||
language.localization_project = Help ons Forgejo in uw taal te vertalen! <a href="%s">Leer meer</a>.
|
||||
user_block_yourself = U kunt niet zichzelf blokkeren.
|
||||
pronouns_custom_label = Aangepaste voornaamwoorden
|
||||
change_username_redirect_prompt.with_cooldown.few = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dagen. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
change_username_redirect_prompt.with_cooldown.one = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dag. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
|
||||
[repo]
|
||||
owner=Eigenaar
|
||||
|
@ -2863,6 +2867,7 @@ summary_card_alt = Overzichtskaart van repository %s
|
|||
release.summary_card_alt = Samenvattende kaart van een release met de titel "%s" in repository %s
|
||||
issues.reaction.alt_remove = Verwijder %[1]s reactie van bericht.
|
||||
issues.reaction.alt_many = %[1]s en %[2]d meer gereageerd %[3]s.
|
||||
editor.commit_email = Commit e-mail
|
||||
|
||||
|
||||
|
||||
|
@ -3001,6 +3006,8 @@ settings.visibility.limited = Beperkt (alleen zichtbaar voor ingelogde gebruiker
|
|||
teams.add_nonexistent_repo = De repository die u probeert toe te voegen bestaat niet, maak deze eerst aan alstublieft.
|
||||
teams.all_repositories_write_permission_desc = Dit team verleent <strong>Schrijf</strong> permissies tot <strong>alle repositories</strong>: leden kunnen lezen en pushen naar repositories.
|
||||
open_dashboard = Open dashboard
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dag. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = De oude gebruikersnaam zal voor iedereen beschikbaar zijn na een afkoelperiode van %[1]d dagen. U kunt de oude gebruikersnaam nog steeds opeisen tijdens de afkoelperiode.
|
||||
|
||||
[admin]
|
||||
dashboard=Overzicht
|
||||
|
@ -3083,7 +3090,7 @@ dashboard.gc_times=GC verwerkingen
|
|||
dashboard.delete_old_system_notices=Verwijder alle oude systeemmededelingen uit de database
|
||||
|
||||
users.user_manage_panel=Gebruikersaccounts beheren
|
||||
users.new_account=Nieuw account aanmaken
|
||||
users.new_account=Gebruikersaccount aanmaken
|
||||
users.name=Gebruikersnaam
|
||||
users.full_name=Volledige naam
|
||||
users.activated=Geactiveerd
|
||||
|
|
|
@ -680,6 +680,8 @@ required_prefix = A entrada deve começar com "%s"
|
|||
FullName = Nome completo
|
||||
Description = Descrição
|
||||
unset_password = O usuário de login não definiu a senha.
|
||||
username_claiming_cooldown = Este nome de usuário não pode ser registrado porque o período de espera ainda não acabou. Ele poderá ser registrado em %[1]s.
|
||||
email_domain_is_not_allowed = O domínio do endereço de email da conta <b>%s</b> está em conflito com EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Certifique-se de que você colocou o endereço de email correto.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -805,7 +807,7 @@ old_password=Senha atual
|
|||
new_password=Nova senha
|
||||
retype_new_password=Confirme a nova senha
|
||||
password_incorrect=A senha atual está incorreta.
|
||||
change_password_success=Sua senha foi atualizada. Acesse usando sua nova senha de agora em diante.
|
||||
change_password_success=Sua senha foi atualizada. A partir de agora, use sua nova senha para acessar sua conta.
|
||||
password_change_disabled=Contas não-locais não podem alterar sua senha através da interface web do Forgejo.
|
||||
|
||||
emails=Endereços de e-mail
|
||||
|
@ -1057,6 +1059,8 @@ language.localization_project = Ajude-nos a traduzir Forgejo para o seu idioma!
|
|||
language.description = Essa língua será salva em sua conta e será usada como padrão após você iniciar a sessão.
|
||||
user_block_yourself = Você não pode se bloquear.
|
||||
pronouns_custom_label = Pronomes personalizados
|
||||
change_username_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
|
||||
change_username_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dias, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
|
||||
|
||||
[repo]
|
||||
owner=Proprietário
|
||||
|
@ -2619,7 +2623,7 @@ tag.create_tag_from=`Criar nova tag a partir de "%s"`
|
|||
|
||||
tag.create_success=Tag "%s" criada.
|
||||
|
||||
topic.manage_topics=Gerenciar Tópicos
|
||||
topic.manage_topics=Gerenciar tópicos
|
||||
topic.done=Feito
|
||||
topic.count_prompt=Você não pode selecionar mais de 25 tópicos
|
||||
|
||||
|
@ -3000,6 +3004,8 @@ open_dashboard = Abrir painel
|
|||
settings.change_orgname_prompt = Obs.: Alterar o nome de uma organização resultará na alteração do URL dela e disponibilizará o nome antigo para uso.
|
||||
follow_blocked_user = Não foi possível seguir esta organização porque ela bloqueou-o(a).
|
||||
form.name_pattern_not_allowed = O padrão "%s" não é permitido no nome de uma organização.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dias, você ainda pode recuperar o nome de usuário antigo durante este período de espera.
|
||||
|
||||
[admin]
|
||||
dashboard=Painel
|
||||
|
@ -3820,6 +3826,13 @@ owner.settings.cargo.initialize.description = É necessário um repositório Git
|
|||
owner.settings.chef.keypair.description = É necessário um par de chaves para autenticar no registro Chef. Se você já gerou um par de chaves, gere um novo par e descarte o antigo.
|
||||
container.images.title = Imagens
|
||||
search_in_external_registry = Buscar em %s
|
||||
alt.registry.install = Para instalar o pacote, execute o seguinte comando:
|
||||
alt.registry = Configurar este registro da linha de comando:
|
||||
alt.install = Instalar pacote
|
||||
alt.repository = Informação do repositório
|
||||
alt.repository.architectures = Arquiteturas
|
||||
alt.repository.multiple_groups = Este pacote está disponível em múltiplos grupos.
|
||||
alt.setup = Adicionar um repositório à lista de repositórios conectados (escolha a arquitetura necessária em vez de '_arch_'):
|
||||
|
||||
[secrets]
|
||||
secrets=Segredos
|
||||
|
|
|
@ -681,6 +681,8 @@ AccessToken = Código de acesso
|
|||
FullName = Nome completo
|
||||
Description = Descrição
|
||||
Pronouns = Pronomes
|
||||
username_claiming_cooldown = O nome de utilizador não pode ser reivindicado, porque o período de espera do mesmo ainda não terminou. Pode ser reivindicado em %[1]s.
|
||||
email_domain_is_not_allowed = O domínio do endereço de email <b>%s</b> do utilizador entra em conflito com EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Certifique-se de que definiu corretamente o endereço de email.
|
||||
|
||||
[user]
|
||||
change_avatar=Mude o seu avatar…
|
||||
|
@ -805,7 +807,7 @@ old_password=Senha corrente
|
|||
new_password=Nova senha
|
||||
retype_new_password=Confirme a nova senha
|
||||
password_incorrect=A senha corrente está errada.
|
||||
change_password_success=A sua senha foi substituída. Inicie a sessão com a nova senha a partir de agora.
|
||||
change_password_success=A sua senha foi atualizada. A partir de agora, utilize a sua nova senha para iniciar sessão.
|
||||
password_change_disabled=Os utilizadores não-locais não podem alterar a sua senha através da interface web do Forgejo.
|
||||
|
||||
emails=Endereços de email
|
||||
|
@ -1057,6 +1059,8 @@ language.description = Este idioma vai ser guardado na sua conta e ser usado com
|
|||
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Saiba mais</a>.
|
||||
pronouns_custom_label = Pronomes personalizados
|
||||
user_block_yourself = Não se pode bloquear a si próprio.
|
||||
change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
|
||||
change_username_redirect_prompt.with_cooldown.few = O nome de utilizador antigo ficará disponível para todos após um período de espera de %[1]d dias, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Um repositório contém todos os ficheiros do trabalho, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
|
||||
|
@ -3001,6 +3005,8 @@ teams.invite.by=Convidado(a) por %s
|
|||
teams.invite.description=Clique no botão abaixo para se juntar à equipa.
|
||||
follow_blocked_user = Não pode seguir esta organização porque esta organização bloqueou-o/a.
|
||||
open_dashboard = Abrir painel de controlo
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dias, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
|
||||
|
||||
[admin]
|
||||
dashboard=Painel de controlo
|
||||
|
@ -3821,6 +3827,13 @@ arch.version.backup = Cópia de segurança
|
|||
arch.version.replaces = Substitui
|
||||
container.images.title = Imagens
|
||||
search_in_external_registry = Procurar em %s
|
||||
alt.registry = Configure este registo a partir da linha de comandos:
|
||||
alt.registry.install = Para instalar o pacote, execute o seguinte comando:
|
||||
alt.install = Instalar pacote
|
||||
alt.repository = Informação do repositório
|
||||
alt.repository.architectures = Arquiteturas
|
||||
alt.repository.multiple_groups = Este pacote está disponível em vários grupos.
|
||||
alt.setup = Adicionar um repositório à lista de repositórios ligados (escolha a arquitetura necessária em vez de '_arch_'):
|
||||
|
||||
[secrets]
|
||||
secrets=Segredos
|
||||
|
|
|
@ -680,6 +680,8 @@ Biography = О себе
|
|||
Website = Веб-сайт
|
||||
Location = Местоположение
|
||||
To = Название ветви
|
||||
email_domain_is_not_allowed = Домен адреса эл. почты <b>%s</b> не разрешён к использованию. Убедитесь, что он введён правильно или попробуйте другой адрес.
|
||||
username_claiming_cooldown = Это имя пока не может быть занято, т.к. срок его защиты ещё не вышел. Его получится занять после %[1]s.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -761,7 +763,7 @@ update_language_success=Язык обновлён.
|
|||
update_profile_success=Ваш профиль успешно обновлён.
|
||||
change_username=Ваше имя пользователя было изменено.
|
||||
change_username_prompt=Обратите внимание: изменение имени пользователя также меняет URL вашей учётной записи.
|
||||
change_username_redirect_prompt=Старое имя пользователя будет перенаправлять на новое до тех пор, пока его не займут.
|
||||
change_username_redirect_prompt=Старое имя будет перенаправлять на новое до тех пор, пока оно не будет занято.
|
||||
continue=Далее
|
||||
cancel=Отмена
|
||||
language=Язык
|
||||
|
@ -1057,6 +1059,8 @@ language.description = Выбранный язык будет сохранён
|
|||
language.localization_project = Помогите с переводом Forgejo на свой язык! <a href="%s">Подробнее</a>.
|
||||
user_block_yourself = Нельзя заблокировать себя.
|
||||
pronouns_custom_label = Другие местоимения
|
||||
change_username_redirect_prompt.with_cooldown.one = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d день. Вы сможете вернуть его себе во время срока защиты.
|
||||
change_username_redirect_prompt.with_cooldown.few = Прежнее имя будет доступно для использования другим пользователям после истечения защиты в %[1]d дней. Вы сможете вернуть его себе во время срока защиты.
|
||||
|
||||
[repo]
|
||||
owner=Владелец
|
||||
|
@ -2650,7 +2654,7 @@ tag.create_tag_from=Создать новый тег из «%s»
|
|||
|
||||
tag.create_success=Тег «%s» создан.
|
||||
|
||||
topic.manage_topics=Редактировать тематические метки
|
||||
topic.manage_topics=Изменить темы
|
||||
topic.done=Сохранить
|
||||
topic.count_prompt=Нельзя выбрать более 25 тем
|
||||
topic.format_prompt=Темы должны начинаться с буквы или цифры и могут содержать дефисы («-») и точки («.»). Длина темы не должна превышать 35 символов. Все буквы должны быть строчными.
|
||||
|
@ -3003,6 +3007,8 @@ teams.invite.description=Нажмите на кнопку ниже, чтобы
|
|||
follow_blocked_user = Вы не можете подписаться на эту организацию, т.к. вы в ней заблокированы.
|
||||
teams.general_access = Настраиваемый доступ
|
||||
open_dashboard = Открыть панель
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Прежнее название будет доступно для использования другим пользователям после истечения защиты в %[1]d дней. Вы сможете вернуть его во время срока защиты.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Прежнее название будет доступно для использования другим пользователям после истечения защиты в %[1]d день. Вы сможете вернуть его во время срока защиты.
|
||||
|
||||
[admin]
|
||||
dashboard=Панель управления
|
||||
|
@ -3708,7 +3714,7 @@ composer.install=Чтобы установить пакет с помощью Co
|
|||
composer.dependencies=Зависимости
|
||||
composer.dependencies.development=Зависимости для разработки
|
||||
conan.details.repository=Репозиторий
|
||||
conan.registry=Настроить реестр из командной строки:
|
||||
conan.registry=Добавьте реестр командой:
|
||||
conan.install=Чтобы установить пакет с помощью Conan, выполните следующую команду:
|
||||
conda.registry=Пропишите этот реестр в качестве репозитория Conda в своём файле <code>.condarc</code>:
|
||||
conda.install=Чтобы установить пакет с помощью Conda, выполните следующую команду:
|
||||
|
@ -3723,7 +3729,7 @@ container.labels.key=Ключ
|
|||
container.labels.value=Значение
|
||||
cran.registry=Настройте этот реестр в файле <code>Rprofile.site</code>:
|
||||
cran.install=Чтобы установить пакет, выполните следующую команду:
|
||||
debian.registry=Настроить реестр из командной строки:
|
||||
debian.registry=Добавьте реестр командой:
|
||||
debian.registry.info=Выберите $distribution и $component из списка ниже.
|
||||
debian.install=Чтобы установить пакет, выполните следующую команду:
|
||||
debian.repository=О репозитории
|
||||
|
@ -3732,13 +3738,13 @@ debian.repository.components=Компоненты
|
|||
debian.repository.architectures=Архитектуры
|
||||
generic.download=Скачать пакет из командной строки:
|
||||
go.install=Установите пакет из командной строки:
|
||||
helm.registry=Настроить реестр из командной строки:
|
||||
helm.registry=Добавьте реестр командой:
|
||||
helm.install=Чтобы установить пакет, выполните следующую команду:
|
||||
maven.registry=Настройте реестр в файле <code>pom.xml</code> вашего проекта:
|
||||
maven.install=Чтобы использовать пакет, включите в блок <code>dependencies</code> в файле <code>pom.xml</code> следующее:
|
||||
maven.install2=Выполнить через командную строку:
|
||||
maven.download=Чтобы скачать зависимость, запустите в командной строке:
|
||||
nuget.registry=Настроить реестр из командной строки:
|
||||
nuget.registry=Добавьте реестр командой:
|
||||
nuget.install=Чтобы установить пакет с помощью NuGet, выполните следующую команду:
|
||||
nuget.dependency.framework=Целевой фреймворк
|
||||
npm.registry=Настройте реестр в файле <code>.npmrc</code> вашего проекта:
|
||||
|
@ -3752,7 +3758,7 @@ npm.details.tag=Тег
|
|||
pub.install=Чтобы установить пакет с помощью Dart, выполните следующую команду:
|
||||
pypi.requires=Требуется Python
|
||||
pypi.install=Чтобы установить пакет с помощью pip, выполните следующую команду:
|
||||
rpm.registry=Настроить реестр из командной строки:
|
||||
rpm.registry=Добавьте реестр командой:
|
||||
rpm.distros.redhat=на дистрибутивах семейства RedHat
|
||||
rpm.distros.suse=на дистрибутивах семейства SUSE
|
||||
rpm.install=Чтобы установить пакет, выполните следующую команду:
|
||||
|
@ -3764,7 +3770,7 @@ rubygems.dependencies.runtime=Зависимости времени выполн
|
|||
rubygems.dependencies.development=Зависимости для разработки
|
||||
rubygems.required.ruby=Требуется версия Ruby
|
||||
rubygems.required.rubygems=Требуется версия RubyGem
|
||||
swift.registry=Настроить реестр из командной строки:
|
||||
swift.registry=Добавьте реестр командой:
|
||||
swift.install=Добавьте пакет в свой файл <code>Package.swift</code>:
|
||||
swift.install2=и запустите следующую команду:
|
||||
vagrant.install=Чтобы добавить бокс Vagrant, выполните следующую команду:
|
||||
|
@ -3834,6 +3840,9 @@ container.images.title = Образы
|
|||
search_in_external_registry = Найти в %s
|
||||
alt.repository = О репозитории
|
||||
alt.repository.architectures = Архитектуры
|
||||
alt.registry = Добавьте реестр командой:
|
||||
alt.repository.multiple_groups = Этот пакет доступен в нескольких группах.
|
||||
alt.setup = Добавьте репозиторий в свой список репозиториев (выберите подходящую архитектуру вместо «_arch_»):
|
||||
|
||||
[secrets]
|
||||
secrets=Секреты
|
||||
|
|
|
@ -666,6 +666,8 @@ invalid_group_team_map_error = ` призначення недійсне: %s`
|
|||
unsupported_login_type = Цей тип входу не підтримує видалення облікового запису.
|
||||
admin_cannot_delete_self = Ви не можете видалити себе, якщо ви є адміністратором. Спочатку зніміть із себе права адміністратора.
|
||||
unset_password = Для користувача не встановлено пароль.
|
||||
username_claiming_cooldown = Це ім'я користувача не можна присвоїти, оскільки його період захисту ще не закінчився. Ім'я можна буде присвоїти %[1]s.
|
||||
email_domain_is_not_allowed = Домен адреси електронної пошти <b>%s</b> конфліктує з EMAIL_DOMAIN_ALLOWLIST або EMAIL_DOMAIN_BLOCKLIST. Перевірте, чи ви правильно вказали адресу електронної пошти.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -761,7 +763,7 @@ update_password=Оновити пароль
|
|||
old_password=Поточний пароль
|
||||
new_password=Новий пароль
|
||||
password_incorrect=Поточний пароль неправильний.
|
||||
change_password_success=Ваш пароль був оновлений. Тепер увійдіть в систему, використовуючи новий пароль.
|
||||
change_password_success=Ваш пароль оновлено. Відтепер входьте в систему, використовуючи новий пароль.
|
||||
password_change_disabled=Нелокальні акаунти не можуть змінити пароль через Forgejo.
|
||||
|
||||
emails=Адреса електронної пошти
|
||||
|
@ -1006,6 +1008,9 @@ key_signature_ssh_placeholder = Починається з «-----BEGIN SSH SIGNA
|
|||
user_block_yourself = Ви не можете заблокувати себе.
|
||||
pronouns_custom_label = Інші займенники
|
||||
repo_and_org_access = Доступ до репозиторію та організації
|
||||
change_username_redirect_prompt.with_cooldown.few = Старе ім'я користувача буде доступне всім після періоду захисту, який триватиме %[1]d днів. Протягом періоду захисту ви ще можете повернути собі старе ім'я.
|
||||
change_username_redirect_prompt.with_cooldown.one = Старе ім'я користувача буде доступне всім після періоду захисту, який триватиме %[1]d день. Протягом періоду захисту ви ще можете повернути собі старе ім'я.
|
||||
change_username_redirect_prompt = Старе ім'я користувача буде перенаправленням, поки хтось не присвоїть ім'я собі.
|
||||
|
||||
[repo]
|
||||
owner=Власник
|
||||
|
@ -2595,6 +2600,8 @@ follow_blocked_user = Ви не можете стежити за цією орг
|
|||
teams.invite.description = Щоб приєднатися до команди, натисніть кнопку нижче.
|
||||
teams.invite.title = Вас запрошено приєднатися до команди <strong>%s</strong> в організації <strong>%s</strong>.
|
||||
form.name_reserved = Назву організації «%s» зарезервовано.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = Стара назва буде доступна всім після періоду захисту, який триватиме %[1]d день. Протягом періоду захисту ви ще можете повернути стару назву.
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = Стара назва буде доступна всім після періоду захисту, який триватиме %[1]d днів. Протягом періоду захисту ви ще можете повернути стару назву.
|
||||
|
||||
[admin]
|
||||
dashboard=Панель управління
|
||||
|
|
|
@ -680,6 +680,8 @@ AccessToken = 访问令牌
|
|||
Description = 描述
|
||||
Pronouns = 代称
|
||||
Biography = 简历
|
||||
username_claiming_cooldown = 用户名不能被认领,因为其仍处于冷却期间。其可以在%[1]s后被认领。
|
||||
email_domain_is_not_allowed = 用户电子邮箱的域名<b>%s</b>与EMAIL_DOMAIN_ALLOWLIST或EMAIL_DOMAIN_BLOCKLIST冲突。请确保您正确设置了电子邮件地址。
|
||||
|
||||
[user]
|
||||
change_avatar=修改头像…
|
||||
|
@ -804,7 +806,7 @@ old_password=当前密码
|
|||
new_password=新的密码
|
||||
retype_new_password=确认新密码
|
||||
password_incorrect=当前密码不正确。
|
||||
change_password_success=您的密码已更新。从现在开始使用您的新密码登录。
|
||||
change_password_success=您的密码已更新。从现在开始请使用您的新密码登录。
|
||||
password_change_disabled=非本地帐户不能通过 Forgejo 的 web 界面更改密码。
|
||||
|
||||
emails=邮箱地址
|
||||
|
@ -1056,6 +1058,8 @@ language.description = 此语言将保存到您的账号中,并在您登录后
|
|||
language.localization_project = 帮助我们将 Forgejo 翻译成您的语言!<a href="%s">了解更多</a>。
|
||||
user_block_yourself = 您不能屏蔽自己。
|
||||
pronouns_custom_label = 自定义代词
|
||||
change_username_redirect_prompt.with_cooldown.one = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
change_username_redirect_prompt.with_cooldown.few = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
|
||||
[repo]
|
||||
new_repo_helper=代码仓库包含了所有的项目文件,包括版本历史记录。已经在其他地方托管了?<a href="%s">迁移仓库</a>。
|
||||
|
@ -2866,6 +2870,7 @@ issues.context.menu = 评论菜单
|
|||
issues.reaction.alt_add = 对评论添加 %[1]s 回应。
|
||||
release.summary_card_alt = 仓库 %[2]s 中标题为 %[1]s 的版本发布的摘要卡片
|
||||
summary_card_alt = 仓库 %s 的摘要卡片
|
||||
editor.commit_email = 提交电子邮件
|
||||
|
||||
[graphs]
|
||||
component_loading=正在加载 %s…
|
||||
|
@ -3001,6 +3006,8 @@ teams.invite.by=邀请人 %s
|
|||
teams.invite.description=请点击下面的按钮加入团队。
|
||||
follow_blocked_user = 你无法关注此组织,因为此组织已屏蔽你。
|
||||
open_dashboard = 打开仪表盘
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.one = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
settings.change_orgname_redirect_prompt.with_cooldown.few = 旧的用户名将在%[1]d天的冷却期后对所有人可用,您仍可以在此期间重新认领旧的用户名。
|
||||
|
||||
[admin]
|
||||
dashboard=管理面板
|
||||
|
|
854
package-lock.json
generated
854
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -61,7 +61,7 @@
|
|||
"devDependencies": {
|
||||
"@axe-core/playwright": "4.10.1",
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",
|
||||
"@playwright/test": "1.49.1",
|
||||
"@playwright/test": "1.50.1",
|
||||
"@stoplight/spectral-cli": "6.14.2",
|
||||
"@stylistic/eslint-plugin-js": "2.12.1",
|
||||
"@stylistic/stylelint-plugin": "3.1.1",
|
||||
|
@ -85,9 +85,9 @@
|
|||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
"globals": "15.14.0",
|
||||
"happy-dom": "16.3.0",
|
||||
"happy-dom": "16.8.1",
|
||||
"license-checker-rseidelsohn": "4.4.2",
|
||||
"markdownlint-cli": "0.43.0",
|
||||
"markdownlint-cli": "0.44.0",
|
||||
"postcss-html": "1.8.0",
|
||||
"stylelint": "16.12.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"description": "Group nodejs packages",
|
||||
"matchPackageNames": [
|
||||
"code.forgejo.org/oci/node",
|
||||
"data.forgejo.org/oci/node",
|
||||
"docker.io/library/node",
|
||||
"docker.io/node",
|
||||
"node"
|
||||
|
|
|
@ -8,14 +8,8 @@ import (
|
|||
"fmt"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
actions_module "code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
|
@ -65,82 +59,16 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
|||
}
|
||||
|
||||
func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
||||
event := map[string]any{}
|
||||
_ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event)
|
||||
|
||||
// TriggerEvent is added in https://github.com/go-gitea/gitea/pull/25229
|
||||
// This fallback is for the old ActionRun that doesn't have the TriggerEvent field
|
||||
// and should be removed in 1.22
|
||||
eventName := t.Job.Run.TriggerEvent
|
||||
if eventName == "" {
|
||||
eventName = t.Job.Run.Event.Event()
|
||||
}
|
||||
|
||||
baseRef := ""
|
||||
headRef := ""
|
||||
ref := t.Job.Run.Ref
|
||||
sha := t.Job.Run.CommitSHA
|
||||
if pullPayload, err := t.Job.Run.GetPullRequestEventPayload(); err == nil && pullPayload.PullRequest != nil && pullPayload.PullRequest.Base != nil && pullPayload.PullRequest.Head != nil {
|
||||
baseRef = pullPayload.PullRequest.Base.Ref
|
||||
headRef = pullPayload.PullRequest.Head.Ref
|
||||
|
||||
// if the TriggerEvent is pull_request_target, ref and sha need to be set according to the base of pull request
|
||||
// In GitHub's documentation, ref should be the branch or tag that triggered workflow. But when the TriggerEvent is pull_request_target,
|
||||
// the ref will be the base branch.
|
||||
if t.Job.Run.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
||||
ref = git.BranchPrefix + pullPayload.PullRequest.Base.Name
|
||||
sha = pullPayload.PullRequest.Base.Sha
|
||||
}
|
||||
}
|
||||
|
||||
refName := git.RefName(ref)
|
||||
|
||||
giteaRuntimeToken, err := actions.CreateAuthorizationToken(t.ID, t.Job.RunID, t.JobID)
|
||||
if err != nil {
|
||||
log.Error("actions.CreateAuthorizationToken failed: %v", err)
|
||||
}
|
||||
|
||||
taskContext, err := structpb.NewStruct(map[string]any{
|
||||
// standard contexts, see https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
||||
"action": "", // string, The name of the action currently running, or the id of a step. GitHub removes special characters, and uses the name __run when the current step runs a script without an id. If you use the same action more than once in the same job, the name will include a suffix with the sequence number with underscore before it. For example, the first script you run will have the name __run, and the second script will be named __run_2. Similarly, the second invocation of actions/checkout will be actionscheckout2.
|
||||
"action_path": "", // string, The path where an action is located. This property is only supported in composite actions. You can use this path to access files located in the same repository as the action.
|
||||
"action_ref": "", // string, For a step executing an action, this is the ref of the action being executed. For example, v2.
|
||||
"action_repository": "", // string, For a step executing an action, this is the owner and repository name of the action. For example, actions/checkout.
|
||||
"action_status": "", // string, For a composite action, the current result of the composite action.
|
||||
"actor": t.Job.Run.TriggerUser.Name, // string, The username of the user that triggered the initial workflow run. If the workflow run is a re-run, this value may differ from github.triggering_actor. Any workflow re-runs will use the privileges of github.actor, even if the actor initiating the re-run (github.triggering_actor) has different privileges.
|
||||
"api_url": setting.AppURL + "api/v1", // string, The URL of the GitHub REST API.
|
||||
"base_ref": baseRef, // string, The base_ref or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.
|
||||
"env": "", // string, Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see "Workflow commands for GitHub Actions."
|
||||
"event": event, // object, The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in "Events that trigger workflows." For example, for a workflow run triggered by the push event, this object contains the contents of the push webhook payload.
|
||||
"event_name": eventName, // string, The name of the event that triggered the workflow run.
|
||||
"event_path": "", // string, The path to the file on the runner that contains the full event webhook payload.
|
||||
"graphql_url": "", // string, The URL of the GitHub GraphQL API.
|
||||
"head_ref": headRef, // string, The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.
|
||||
"job": fmt.Sprint(t.JobID), // string, The job_id of the current job.
|
||||
"ref": ref, // string, The fully-formed ref of the branch or tag that triggered the workflow run. For workflows triggered by push, this is the branch or tag ref that was pushed. For workflows triggered by pull_request, this is the pull request merge branch. For workflows triggered by release, this is the release tag created. For other triggers, this is the branch or tag ref that triggered the workflow run. This is only set if a branch or tag is available for the event type. The ref given is fully-formed, meaning that for branches the format is refs/heads/<branch_name>, for pull requests it is refs/pull/<pr_number>/merge, and for tags it is refs/tags/<tag_name>. For example, refs/heads/feature-branch-1.
|
||||
"ref_name": refName.ShortName(), // string, The short ref name of the branch or tag that triggered the workflow run. This value matches the branch or tag name shown on GitHub. For example, feature-branch-1.
|
||||
"ref_protected": false, // boolean, true if branch protections are configured for the ref that triggered the workflow run.
|
||||
"ref_type": refName.RefType(), // string, The type of ref that triggered the workflow run. Valid values are branch or tag.
|
||||
"path": "", // string, Path on the runner to the file that sets system PATH variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see "Workflow commands for GitHub Actions."
|
||||
"repository": t.Job.Run.Repo.OwnerName + "/" + t.Job.Run.Repo.Name, // string, The owner and repository name. For example, Codertocat/Hello-World.
|
||||
"repository_owner": t.Job.Run.Repo.OwnerName, // string, The repository owner's name. For example, Codertocat.
|
||||
"repositoryUrl": t.Job.Run.Repo.HTMLURL(), // string, The Git URL to the repository. For example, git://github.com/codertocat/hello-world.git.
|
||||
"retention_days": "", // string, The number of days that workflow run logs and artifacts are kept.
|
||||
"run_id": fmt.Sprint(t.Job.RunID), // string, A unique number for each workflow run within a repository. This number does not change if you re-run the workflow run.
|
||||
"run_number": fmt.Sprint(t.Job.Run.Index), // string, A unique number for each run of a particular workflow in a repository. This number begins at 1 for the workflow's first run, and increments with each new run. This number does not change if you re-run the workflow run.
|
||||
"run_attempt": fmt.Sprint(t.Job.Attempt), // string, A unique number for each attempt of a particular workflow run in a repository. This number begins at 1 for the workflow run's first attempt, and increments with each re-run.
|
||||
"secret_source": "Actions", // string, The source of a secret used in a workflow. Possible values are None, Actions, Dependabot, or Codespaces.
|
||||
"server_url": setting.AppURL, // string, The URL of the GitHub server. For example: https://github.com.
|
||||
"sha": sha, // string, The commit SHA that triggered the workflow. The value of this commit SHA depends on the event that triggered the workflow. For more information, see "Events that trigger workflows." For example, ffac537e6cbbf934b08745a378932722df287a53.
|
||||
"token": t.Token, // string, A token to authenticate on behalf of the GitHub App installed on your repository. This is functionally equivalent to the GITHUB_TOKEN secret. For more information, see "Automatic token authentication."
|
||||
"triggering_actor": "", // string, The username of the user that initiated the workflow run. If the workflow run is a re-run, this value may differ from github.actor. Any workflow re-runs will use the privileges of github.actor, even if the actor initiating the re-run (github.triggering_actor) has different privileges.
|
||||
"workflow": t.Job.Run.WorkflowID, // string, The name of the workflow. If the workflow file doesn't specify a name, the value of this property is the full path of the workflow file in the repository.
|
||||
"workspace": "", // string, The default working directory on the runner for steps, and the default location of your repository when using the checkout action.
|
||||
gitCtx := actions.GenerateGiteaContext(t.Job.Run, t.Job)
|
||||
gitCtx["token"] = t.Token
|
||||
gitCtx["gitea_runtime_token"] = giteaRuntimeToken
|
||||
|
||||
// additional contexts
|
||||
"gitea_default_actions_url": setting.Actions.DefaultActionsURL.URL(),
|
||||
"gitea_runtime_token": giteaRuntimeToken,
|
||||
})
|
||||
taskContext, err := structpb.NewStruct(gitCtx)
|
||||
if err != nil {
|
||||
log.Error("structpb.NewStruct failed: %v", err)
|
||||
}
|
||||
|
@ -150,68 +78,18 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
|||
|
||||
func findTaskNeeds(ctx context.Context, task *actions_model.ActionTask) (map[string]*runnerv1.TaskNeed, error) {
|
||||
if err := task.LoadAttributes(ctx); err != nil {
|
||||
return nil, fmt.Errorf("LoadAttributes: %w", err)
|
||||
return nil, fmt.Errorf("task LoadAttributes: %w", err)
|
||||
}
|
||||
if len(task.Job.Needs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
needs := container.SetOf(task.Job.Needs...)
|
||||
|
||||
jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: task.Job.RunID})
|
||||
taskNeeds, err := actions.FindTaskNeeds(ctx, task.Job)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FindRunJobs: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jobIDJobs := make(map[string][]*actions_model.ActionRunJob)
|
||||
for _, job := range jobs {
|
||||
jobIDJobs[job.JobID] = append(jobIDJobs[job.JobID], job)
|
||||
}
|
||||
|
||||
ret := make(map[string]*runnerv1.TaskNeed, len(needs))
|
||||
for jobID, jobsWithSameID := range jobIDJobs {
|
||||
if !needs.Contains(jobID) {
|
||||
continue
|
||||
}
|
||||
var jobOutputs map[string]string
|
||||
for _, job := range jobsWithSameID {
|
||||
if job.TaskID == 0 || !job.Status.IsDone() {
|
||||
// it shouldn't happen, or the job has been rerun
|
||||
continue
|
||||
}
|
||||
got, err := actions_model.FindTaskOutputByTaskID(ctx, job.TaskID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FindTaskOutputByTaskID: %w", err)
|
||||
}
|
||||
outputs := make(map[string]string, len(got))
|
||||
for _, v := range got {
|
||||
outputs[v.OutputKey] = v.OutputValue
|
||||
}
|
||||
if len(jobOutputs) == 0 {
|
||||
jobOutputs = outputs
|
||||
} else {
|
||||
jobOutputs = mergeTwoOutputs(outputs, jobOutputs)
|
||||
}
|
||||
}
|
||||
ret := make(map[string]*runnerv1.TaskNeed, len(taskNeeds))
|
||||
for jobID, taskNeed := range taskNeeds {
|
||||
ret[jobID] = &runnerv1.TaskNeed{
|
||||
Outputs: jobOutputs,
|
||||
Result: runnerv1.Result(actions_model.AggregateJobStatus(jobsWithSameID)),
|
||||
Outputs: taskNeed.Outputs,
|
||||
Result: runnerv1.Result(taskNeed.Result),
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// mergeTwoOutputs merges two outputs from two different ActionRunJobs
|
||||
// Values with the same output name may be overridden. The user should ensure the output names are unique.
|
||||
// See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#using-job-outputs-in-a-matrix-job
|
||||
func mergeTwoOutputs(o1, o2 map[string]string) map[string]string {
|
||||
ret := make(map[string]string, len(o1))
|
||||
for k1, v1 := range o1 {
|
||||
if len(v1) > 0 {
|
||||
ret[k1] = v1
|
||||
} else {
|
||||
ret[k1] = o2[k1]
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ Here are some links to the most important topics. You can find the full list of
|
|||
<h2 id="user-content-quick-links">Quick Links</h2>
|
||||
<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>
|
||||
<p><a href="` + FullURL + `wiki/Configuration" rel="nofollow">Configuration</a>
|
||||
<a href="` + FullURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + FullURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt="images/icon-bug.png"/></a></p>
|
||||
<a href="` + FullURL + `wiki/raw/images/icon-bug.png" rel="nofollow"><img src="` + FullURL + `wiki/raw/images/icon-bug.png" title="icon-bug.png" alt=""/></a></p>
|
||||
`,
|
||||
}
|
||||
|
||||
|
|
|
@ -303,11 +303,7 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
if err := asymkey_model.DeleteGPGKey(ctx, ctx.Doer, ctx.ParamsInt64(":id")); err != nil {
|
||||
if asymkey_model.IsErrGPGKeyAccessDenied(err) {
|
||||
ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteGPGKey", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -317,8 +313,6 @@ func DeleteGPGKey(ctx *context.APIContext) {
|
|||
// HandleAddGPGKeyError handle add GPGKey error
|
||||
func HandleAddGPGKeyError(ctx *context.APIContext, err error, token string) {
|
||||
switch {
|
||||
case asymkey_model.IsErrGPGKeyAccessDenied(err):
|
||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key")
|
||||
case asymkey_model.IsErrGPGKeyIDAlreadyUsed(err):
|
||||
ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists")
|
||||
case asymkey_model.IsErrGPGKeyParsing(err):
|
||||
|
|
|
@ -83,6 +83,7 @@ func Users(ctx *context.Context) {
|
|||
IsTwoFactorEnabled: util.OptionalBoolParse(statusFilterMap["is_2fa_enabled"]),
|
||||
IsProhibitLogin: util.OptionalBoolParse(statusFilterMap["is_prohibit_login"]),
|
||||
IncludeReserved: true, // administrator needs to list all accounts include reserved, bot, remote ones
|
||||
Load2FAStatus: true,
|
||||
ExtraParamStrings: extraParamStrings,
|
||||
}, tplUsers)
|
||||
}
|
||||
|
|
|
@ -225,15 +225,6 @@ func SignInPost(ctx *context.Context) {
|
|||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
} else if user_model.IsErrUserInactive(err) {
|
||||
if setting.Service.RegisterEmailConfirm {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(http.StatusOK, TplActivate)
|
||||
} else {
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
}
|
||||
|
|
|
@ -99,16 +99,6 @@ func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl
|
|||
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
} else if user_model.IsErrUserInactive(err) {
|
||||
ctx.Data["user_exists"] = true
|
||||
if setting.Service.RegisterEmailConfirm {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(http.StatusOK, TplActivate)
|
||||
} else {
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError(invoker, err)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,11 @@ func Organizations(ctx *context.Context) {
|
|||
)
|
||||
sortOrder := ctx.FormString("sort")
|
||||
if sortOrder == "" {
|
||||
sortOrder = "newest"
|
||||
if supportedSortOrders.Contains(setting.UI.ExploreDefaultSort) {
|
||||
sortOrder = setting.UI.ExploreDefaultSort
|
||||
} else {
|
||||
sortOrder = "newest"
|
||||
}
|
||||
ctx.SetFormString("sort", sortOrder)
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,9 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
|
|||
ctx.Data["Keyword"] = opts.Keyword
|
||||
ctx.Data["Total"] = count
|
||||
ctx.Data["Users"] = users
|
||||
ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus(ctx)
|
||||
if opts.Load2FAStatus {
|
||||
ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus(ctx)
|
||||
}
|
||||
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
|
||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
|
||||
|
||||
|
@ -149,7 +151,11 @@ func Users(ctx *context.Context) {
|
|||
)
|
||||
sortOrder := ctx.FormString("sort")
|
||||
if sortOrder == "" {
|
||||
sortOrder = "newest"
|
||||
if supportedSortOrders.Contains(setting.UI.ExploreDefaultSort) {
|
||||
sortOrder = setting.UI.ExploreDefaultSort
|
||||
} else {
|
||||
sortOrder = "newest"
|
||||
}
|
||||
ctx.SetFormString("sort", sortOrder)
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,11 @@ func RefBlame(ctx *context.Context) {
|
|||
HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err)
|
||||
return
|
||||
}
|
||||
if entry.IsDir() {
|
||||
ctx.NotFound("Cannot blame directory", nil)
|
||||
return
|
||||
}
|
||||
|
||||
blob := entry.Blob()
|
||||
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"net/http"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -242,7 +241,9 @@ func Milestones(ctx *context.Context) {
|
|||
ctx.ServerError("SearchRepositoryByCondition", err)
|
||||
return
|
||||
}
|
||||
sort.Sort(showRepos)
|
||||
slices.SortFunc(showRepos, func(a, b *repo_model.Repository) int {
|
||||
return strings.Compare(a.FullName(), b.FullName())
|
||||
})
|
||||
|
||||
for i := 0; i < len(milestones); {
|
||||
for _, repo := range showRepos {
|
||||
|
|
|
@ -98,6 +98,8 @@ func TestMilestones(t *testing.T) {
|
|||
assert.EqualValues(t, 1, ctx.Data["Total"])
|
||||
assert.Len(t, ctx.Data["Milestones"], 1)
|
||||
assert.Len(t, ctx.Data["Repos"], 2) // both repo 42 and 1 have milestones and both are owned by user 2
|
||||
assert.EqualValues(t, "user2/glob", ctx.Data["Repos"].(repo_model.RepositoryList)[0].FullName())
|
||||
assert.EqualValues(t, "user2/repo1", ctx.Data["Repos"].(repo_model.RepositoryList)[1].FullName())
|
||||
}
|
||||
|
||||
func TestMilestonesForSpecificRepo(t *testing.T) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue