mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 06:03:51 +03:00
Merge branch 'forgejo' into forgejo-federated-pr5
This commit is contained in:
commit
5620dd76fa
98 changed files with 1961 additions and 876 deletions
|
@ -1,57 +0,0 @@
|
|||
# The full repository name
|
||||
repo: go-gitea/gitea
|
||||
|
||||
# Service type (gitea or github)
|
||||
service: github
|
||||
|
||||
# Base URL for Gitea instance if using gitea service type (optional)
|
||||
# Default: https://gitea.com
|
||||
base-url:
|
||||
|
||||
# Changelog groups and which labeled PRs to add to each group
|
||||
groups:
|
||||
-
|
||||
name: BREAKING
|
||||
labels:
|
||||
- pr/breaking
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- topic/security
|
||||
-
|
||||
name: FEATURES
|
||||
labels:
|
||||
- type/feature
|
||||
-
|
||||
name: API
|
||||
labels:
|
||||
- modifies/api
|
||||
-
|
||||
name: ENHANCEMENTS
|
||||
labels:
|
||||
- type/enhancement
|
||||
- type/refactoring
|
||||
- topic/ui
|
||||
-
|
||||
name: BUGFIXES
|
||||
labels:
|
||||
- type/bug
|
||||
-
|
||||
name: TESTING
|
||||
labels:
|
||||
- type/testing
|
||||
-
|
||||
name: BUILD
|
||||
labels:
|
||||
- topic/build
|
||||
- topic/code-linting
|
||||
-
|
||||
name: DOCS
|
||||
labels:
|
||||
- type/docs
|
||||
-
|
||||
name: MISC
|
||||
default: true
|
||||
|
||||
# regex indicating which labels to skip for the changelog
|
||||
skip-labels: skip-changelog|backport\/.+
|
2
.forgejo/testdata/build-release/Dockerfile
vendored
2
.forgejo/testdata/build-release/Dockerfile
vendored
|
@ -1,4 +1,4 @@
|
|||
FROM code.forgejo.org/oci/alpine:3.19
|
||||
FROM code.forgejo.org/oci/alpine:3.20
|
||||
ARG RELEASE_VERSION=unkown
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.version="${RELEASE_VERSION}"
|
||||
|
|
|
@ -54,7 +54,7 @@ jobs:
|
|||
MINIO_ROOT_USER: 123456
|
||||
MINIO_ROOT_PASSWORD: 12345678
|
||||
redis:
|
||||
image: redis:7.2.4
|
||||
image: redis:7.2
|
||||
steps:
|
||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.22-alpine3.19 as build-env
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.19 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 docker.io/library/alpine:3.19
|
||||
FROM code.forgejo.org/oci/golang:1.22-alpine3.19
|
||||
ARG RELEASE_VERSION
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.22-alpine3.19 as build-env
|
||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.19 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 docker.io/library/alpine:3.19
|
||||
FROM code.forgejo.org/oci/golang:1.22-alpine3.19
|
||||
LABEL maintainer="contact@forgejo.org" \
|
||||
org.opencontainers.image.authors="Forgejo" \
|
||||
org.opencontainers.image.url="https://forgejo.org" \
|
||||
|
|
2
Makefile
2
Makefile
|
@ -29,7 +29,7 @@ XGO_VERSION := go-1.21.x
|
|||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v2/cmd/editorconfig-checker@2.8.0 # renovate: datasource=go
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.58.1 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.58.2 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1 # renovate: datasource=go
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||
|
|
|
@ -34,7 +34,7 @@ var CmdMigrateStorage = &cli.Command{
|
|||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Value: "",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "storage",
|
||||
|
|
|
@ -2046,6 +2046,17 @@ LEVEL = Info
|
|||
;; or only create new users if UPDATE_EXISTING is set to false
|
||||
;UPDATE_EXISTING = true
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Cleanup expired actions assets
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[cron.cleanup_actions]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;ENABLED = true
|
||||
;RUN_AT_START = true
|
||||
;SCHEDULE = @midnight
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Clean-up deleted branches
|
||||
|
|
61
flake.lock
Normal file
61
flake.lock
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1715534503,
|
||||
"narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2057814051972fa1453ddfb0d98badbea9b83c06",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
37
flake.nix
Normal file
37
flake.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
outputs =
|
||||
{ nixpkgs, flake-utils, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
# generic
|
||||
git
|
||||
git-lfs
|
||||
gnumake
|
||||
gnused
|
||||
gnutar
|
||||
gzip
|
||||
|
||||
# frontend
|
||||
nodejs_20
|
||||
|
||||
# linting
|
||||
python312
|
||||
poetry
|
||||
|
||||
# backend
|
||||
go_1_22
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
|
@ -35,3 +35,9 @@
|
|||
"X-Head": "42"
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
id: 4
|
||||
hook_id: 3
|
||||
uuid: uuid4
|
||||
is_delivered: false
|
||||
|
|
|
@ -155,14 +155,14 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) {
|
|||
if r.CodeComments != nil {
|
||||
return err
|
||||
}
|
||||
if err = r.loadIssue(ctx); err != nil {
|
||||
if err = r.LoadIssue(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Review) loadIssue(ctx context.Context) (err error) {
|
||||
func (r *Review) LoadIssue(ctx context.Context) (err error) {
|
||||
if r.Issue != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) {
|
|||
|
||||
// LoadAttributes loads all attributes except CodeComments
|
||||
func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err = r.loadIssue(ctx); err != nil {
|
||||
if err = r.LoadIssue(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = r.LoadCodeComments(ctx); err != nil {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
|
@ -106,14 +107,27 @@ var (
|
|||
TypeExternalTracker,
|
||||
}
|
||||
|
||||
// DisabledRepoUnits contains the units that have been globally disabled
|
||||
DisabledRepoUnits = []Type{}
|
||||
disabledRepoUnitsAtomic atomic.Pointer[[]Type] // the units that have been globally disabled
|
||||
|
||||
// AllowedRepoUnitGroups contains the units that have been globally enabled,
|
||||
// with mutually exclusive units grouped together.
|
||||
AllowedRepoUnitGroups = [][]Type{}
|
||||
)
|
||||
|
||||
// DisabledRepoUnitsGet returns the globally disabled units, it is a quick patch to fix data-race during testing.
|
||||
// Because the queue worker might read when a test is mocking the value. FIXME: refactor to a clear solution later.
|
||||
func DisabledRepoUnitsGet() []Type {
|
||||
v := disabledRepoUnitsAtomic.Load()
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
func DisabledRepoUnitsSet(v []Type) {
|
||||
disabledRepoUnitsAtomic.Store(&v)
|
||||
}
|
||||
|
||||
// Get valid set of default repository units from settings
|
||||
func validateDefaultRepoUnits(defaultUnits, settingDefaultUnits []Type) []Type {
|
||||
units := defaultUnits
|
||||
|
@ -131,7 +145,7 @@ func validateDefaultRepoUnits(defaultUnits, settingDefaultUnits []Type) []Type {
|
|||
}
|
||||
|
||||
// Remove disabled units
|
||||
for _, disabledUnit := range DisabledRepoUnits {
|
||||
for _, disabledUnit := range DisabledRepoUnitsGet() {
|
||||
for i, unit := range units {
|
||||
if unit == disabledUnit {
|
||||
units = append(units[:i], units[i+1:]...)
|
||||
|
@ -144,11 +158,11 @@ func validateDefaultRepoUnits(defaultUnits, settingDefaultUnits []Type) []Type {
|
|||
|
||||
// LoadUnitConfig load units from settings
|
||||
func LoadUnitConfig() error {
|
||||
var invalidKeys []string
|
||||
DisabledRepoUnits, invalidKeys = FindUnitTypes(setting.Repository.DisabledRepoUnits...)
|
||||
disabledRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DisabledRepoUnits...)
|
||||
if len(invalidKeys) > 0 {
|
||||
log.Warn("Invalid keys in disabled repo units: %s", strings.Join(invalidKeys, ", "))
|
||||
}
|
||||
DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
|
||||
setDefaultRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultRepoUnits...)
|
||||
if len(invalidKeys) > 0 {
|
||||
|
@ -210,7 +224,7 @@ func LoadUnitConfig() error {
|
|||
|
||||
// UnitGlobalDisabled checks if unit type is global disabled
|
||||
func (u Type) UnitGlobalDisabled() bool {
|
||||
for _, ud := range DisabledRepoUnits {
|
||||
for _, ud := range DisabledRepoUnitsGet() {
|
||||
if u == ud {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
func TestLoadUnitConfig(t *testing.T) {
|
||||
t.Run("regular", func(t *testing.T) {
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []Type) {
|
||||
DisabledRepoUnits = disabledRepoUnits
|
||||
DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
DefaultRepoUnits = defaultRepoUnits
|
||||
DefaultForkRepoUnits = defaultForkRepoUnits
|
||||
}(DisabledRepoUnits, DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
}(DisabledRepoUnitsGet(), DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []string) {
|
||||
setting.Repository.DisabledRepoUnits = disabledRepoUnits
|
||||
setting.Repository.DefaultRepoUnits = defaultRepoUnits
|
||||
|
@ -28,16 +28,16 @@ func TestLoadUnitConfig(t *testing.T) {
|
|||
setting.Repository.DefaultRepoUnits = []string{"repo.code", "repo.releases", "repo.issues", "repo.pulls"}
|
||||
setting.Repository.DefaultForkRepoUnits = []string{"repo.releases"}
|
||||
assert.NoError(t, LoadUnitConfig())
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits)
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnitsGet())
|
||||
assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits)
|
||||
assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits)
|
||||
})
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []Type) {
|
||||
DisabledRepoUnits = disabledRepoUnits
|
||||
DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
DefaultRepoUnits = defaultRepoUnits
|
||||
DefaultForkRepoUnits = defaultForkRepoUnits
|
||||
}(DisabledRepoUnits, DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
}(DisabledRepoUnitsGet(), DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []string) {
|
||||
setting.Repository.DisabledRepoUnits = disabledRepoUnits
|
||||
setting.Repository.DefaultRepoUnits = defaultRepoUnits
|
||||
|
@ -48,16 +48,16 @@ func TestLoadUnitConfig(t *testing.T) {
|
|||
setting.Repository.DefaultRepoUnits = []string{"repo.code", "invalid.2", "repo.releases", "repo.issues", "repo.pulls"}
|
||||
setting.Repository.DefaultForkRepoUnits = []string{"invalid.3", "repo.releases"}
|
||||
assert.NoError(t, LoadUnitConfig())
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits)
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnitsGet())
|
||||
assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits)
|
||||
assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits)
|
||||
})
|
||||
t.Run("duplicate", func(t *testing.T) {
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []Type) {
|
||||
DisabledRepoUnits = disabledRepoUnits
|
||||
DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
DefaultRepoUnits = defaultRepoUnits
|
||||
DefaultForkRepoUnits = defaultForkRepoUnits
|
||||
}(DisabledRepoUnits, DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
}(DisabledRepoUnitsGet(), DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []string) {
|
||||
setting.Repository.DisabledRepoUnits = disabledRepoUnits
|
||||
setting.Repository.DefaultRepoUnits = defaultRepoUnits
|
||||
|
@ -68,16 +68,16 @@ func TestLoadUnitConfig(t *testing.T) {
|
|||
setting.Repository.DefaultRepoUnits = []string{"repo.code", "repo.releases", "repo.issues", "repo.pulls", "repo.code"}
|
||||
setting.Repository.DefaultForkRepoUnits = []string{"repo.releases", "repo.releases"}
|
||||
assert.NoError(t, LoadUnitConfig())
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits)
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnitsGet())
|
||||
assert.Equal(t, []Type{TypeCode, TypeReleases, TypePullRequests}, DefaultRepoUnits)
|
||||
assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits)
|
||||
})
|
||||
t.Run("empty_default", func(t *testing.T) {
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []Type) {
|
||||
DisabledRepoUnits = disabledRepoUnits
|
||||
DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
DefaultRepoUnits = defaultRepoUnits
|
||||
DefaultForkRepoUnits = defaultForkRepoUnits
|
||||
}(DisabledRepoUnits, DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
}(DisabledRepoUnitsGet(), DefaultRepoUnits, DefaultForkRepoUnits)
|
||||
defer func(disabledRepoUnits, defaultRepoUnits, defaultForkRepoUnits []string) {
|
||||
setting.Repository.DisabledRepoUnits = disabledRepoUnits
|
||||
setting.Repository.DefaultRepoUnits = defaultRepoUnits
|
||||
|
@ -88,7 +88,7 @@ func TestLoadUnitConfig(t *testing.T) {
|
|||
setting.Repository.DefaultRepoUnits = []string{}
|
||||
setting.Repository.DefaultForkRepoUnits = []string{"repo.releases", "repo.releases"}
|
||||
assert.NoError(t, LoadUnitConfig())
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits)
|
||||
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnitsGet())
|
||||
assert.ElementsMatch(t, []Type{TypeCode, TypePullRequests, TypeReleases, TypeWiki, TypePackages, TypeProjects, TypeActions}, DefaultRepoUnits)
|
||||
assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits)
|
||||
})
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"net/mail"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
|
@ -362,14 +363,12 @@ func MakeEmailPrimary(ctx context.Context, email *EmailAddress) error {
|
|||
|
||||
// VerifyActiveEmailCode verifies active email code when active account
|
||||
func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddress {
|
||||
minutes := setting.Service.ActiveCodeLives
|
||||
|
||||
if user := GetVerifyUser(ctx, code); user != nil {
|
||||
// time limit code
|
||||
prefix := code[:base.TimeLimitCodeLength]
|
||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
||||
|
||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
||||
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
|
||||
return emailAddress
|
||||
|
|
|
@ -321,7 +321,7 @@ func (u *User) OrganisationLink() string {
|
|||
func (u *User) GenerateEmailActivateCode(email string) string {
|
||||
code := base.CreateTimeLimitCode(
|
||||
fmt.Sprintf("%d%s%s%s%s", u.ID, email, u.LowerName, u.Passwd, u.Rands),
|
||||
setting.Service.ActiveCodeLives, nil)
|
||||
setting.Service.ActiveCodeLives, time.Now(), nil)
|
||||
|
||||
// Add tail hex username
|
||||
code += hex.EncodeToString([]byte(u.LowerName))
|
||||
|
@ -818,14 +818,11 @@ func GetVerifyUser(ctx context.Context, code string) (user *User) {
|
|||
|
||||
// VerifyUserActiveCode verifies active code when active account
|
||||
func VerifyUserActiveCode(ctx context.Context, code string) (user *User) {
|
||||
minutes := setting.Service.ActiveCodeLives
|
||||
|
||||
if user = GetVerifyUser(ctx, code); user != nil {
|
||||
// time limit code
|
||||
prefix := code[:base.TimeLimitCodeLength]
|
||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, user.LowerName, user.Passwd, user.Rands)
|
||||
|
||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,15 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
@ -25,13 +28,6 @@ import (
|
|||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
// EncodeSha1 string to sha1 hex value.
|
||||
func EncodeSha1(str string) string {
|
||||
h := sha1.New()
|
||||
_, _ = h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// EncodeSha256 string to sha256 hex value.
|
||||
func EncodeSha256(str string) string {
|
||||
h := sha256.New()
|
||||
|
@ -62,63 +58,62 @@ func BasicAuthDecode(encoded string) (string, string, error) {
|
|||
}
|
||||
|
||||
// VerifyTimeLimitCode verify time limit code
|
||||
func VerifyTimeLimitCode(data string, minutes int, code string) bool {
|
||||
func VerifyTimeLimitCode(now time.Time, data string, minutes int, code string) bool {
|
||||
if len(code) <= 18 {
|
||||
return false
|
||||
}
|
||||
|
||||
// split code
|
||||
start := code[:12]
|
||||
lives := code[12:18]
|
||||
if d, err := strconv.ParseInt(lives, 10, 0); err == nil {
|
||||
minutes = int(d)
|
||||
}
|
||||
startTimeStr := code[:12]
|
||||
aliveTimeStr := code[12:18]
|
||||
aliveTime, _ := strconv.Atoi(aliveTimeStr) // no need to check err, if anything wrong, the following code check will fail soon
|
||||
|
||||
// right active code
|
||||
retCode := CreateTimeLimitCode(data, minutes, start)
|
||||
if retCode == code && minutes > 0 {
|
||||
// check time is expired or not
|
||||
before, _ := time.ParseInLocation("200601021504", start, time.Local)
|
||||
now := time.Now()
|
||||
if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() {
|
||||
return true
|
||||
// check code
|
||||
retCode := CreateTimeLimitCode(data, aliveTime, startTimeStr, nil)
|
||||
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
||||
retCode = CreateTimeLimitCode(data, aliveTime, startTimeStr, sha1.New()) // TODO: this is only for the support of legacy codes, remove this in/after 1.23
|
||||
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
// check time is expired or not: startTime <= now && now < startTime + minutes
|
||||
startTime, _ := time.ParseInLocation("200601021504", startTimeStr, time.Local)
|
||||
return (startTime.Before(now) || startTime.Equal(now)) && now.Before(startTime.Add(time.Minute*time.Duration(minutes)))
|
||||
}
|
||||
|
||||
// TimeLimitCodeLength default value for time limit code
|
||||
const TimeLimitCodeLength = 12 + 6 + 40
|
||||
|
||||
// CreateTimeLimitCode create a time limit code
|
||||
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
|
||||
func CreateTimeLimitCode(data string, minutes int, startInf any) string {
|
||||
format := "200601021504"
|
||||
// CreateTimeLimitCode create a time-limited code.
|
||||
// Format: 12 length date time string + 6 minutes string (not used) + 40 hash string, some other code depends on this fixed length
|
||||
// If h is nil, then use the default hmac hash.
|
||||
func CreateTimeLimitCode[T time.Time | string](data string, minutes int, startTimeGeneric T, h hash.Hash) string {
|
||||
const format = "200601021504"
|
||||
|
||||
var start, end time.Time
|
||||
var startStr, endStr string
|
||||
|
||||
if startInf == nil {
|
||||
// Use now time create code
|
||||
start = time.Now()
|
||||
startStr = start.Format(format)
|
||||
var start time.Time
|
||||
var startTimeAny any = startTimeGeneric
|
||||
if t, ok := startTimeAny.(time.Time); ok {
|
||||
start = t
|
||||
} else {
|
||||
// use start string create code
|
||||
startStr = startInf.(string)
|
||||
start, _ = time.ParseInLocation(format, startStr, time.Local)
|
||||
startStr = start.Format(format)
|
||||
var err error
|
||||
start, err = time.ParseInLocation(format, startTimeAny.(string), time.Local)
|
||||
if err != nil {
|
||||
return "" // return an invalid code because the "parse" failed
|
||||
}
|
||||
}
|
||||
startStr := start.Format(format)
|
||||
end := start.Add(time.Minute * time.Duration(minutes))
|
||||
|
||||
end = start.Add(time.Minute * time.Duration(minutes))
|
||||
endStr = end.Format(format)
|
||||
|
||||
// create sha1 encode string
|
||||
sh := sha1.New()
|
||||
_, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, endStr, minutes)))
|
||||
encoded := hex.EncodeToString(sh.Sum(nil))
|
||||
if h == nil {
|
||||
h = hmac.New(sha1.New, setting.GetGeneralTokenSigningSecret())
|
||||
}
|
||||
_, _ = fmt.Fprintf(h, "%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, end.Format(format), minutes)
|
||||
encoded := hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
|
||||
if len(code) != TimeLimitCodeLength {
|
||||
panic("there is a hard requirement for the length of time-limited code") // it shouldn't happen
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
|
|
|
@ -4,20 +4,18 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncodeSha1(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
"8843d7f92416211de9ebb963ff4ce28125932878",
|
||||
EncodeSha1("foobar"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEncodeSha256(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
"c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2",
|
||||
|
@ -46,43 +44,54 @@ func TestBasicAuthDecode(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVerifyTimeLimitCode(t *testing.T) {
|
||||
tc := []struct {
|
||||
data string
|
||||
minutes int
|
||||
code string
|
||||
valid bool
|
||||
}{{
|
||||
data: "data",
|
||||
minutes: 2,
|
||||
code: testCreateTimeLimitCode(t, "data", 2),
|
||||
valid: true,
|
||||
}, {
|
||||
data: "abc123-ß",
|
||||
minutes: 1,
|
||||
code: testCreateTimeLimitCode(t, "abc123-ß", 1),
|
||||
valid: true,
|
||||
}, {
|
||||
data: "data",
|
||||
minutes: 2,
|
||||
code: "2021012723240000005928251dac409d2c33a6eb82c63410aaad569bed",
|
||||
valid: false,
|
||||
}}
|
||||
for _, test := range tc {
|
||||
actualValid := VerifyTimeLimitCode(test.data, test.minutes, test.code)
|
||||
assert.Equal(t, test.valid, actualValid, "data: '%s' code: '%s' should be valid: %t", test.data, test.code, test.valid)
|
||||
defer test.MockVariableValue(&setting.InstallLock, true)()
|
||||
initGeneralSecret := func(secret string) {
|
||||
setting.InstallLock = true
|
||||
setting.CfgProvider, _ = setting.NewConfigProviderFromData(fmt.Sprintf(`
|
||||
[oauth2]
|
||||
JWT_SECRET = %s
|
||||
`, secret))
|
||||
setting.LoadCommonSettings()
|
||||
}
|
||||
}
|
||||
|
||||
func testCreateTimeLimitCode(t *testing.T, data string, m int) string {
|
||||
result0 := CreateTimeLimitCode(data, m, nil)
|
||||
result1 := CreateTimeLimitCode(data, m, time.Now().Format("200601021504"))
|
||||
result2 := CreateTimeLimitCode(data, m, time.Unix(time.Now().Unix()+int64(time.Minute)*int64(m), 0).Format("200601021504"))
|
||||
initGeneralSecret("KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
||||
now := time.Now()
|
||||
|
||||
assert.Equal(t, result0, result1)
|
||||
assert.NotEqual(t, result0, result2)
|
||||
t.Run("TestGenericParameter", func(t *testing.T) {
|
||||
time2000 := time.Date(2000, 1, 2, 3, 4, 5, 0, time.Local)
|
||||
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, time2000, sha1.New()))
|
||||
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, "200001020304", sha1.New()))
|
||||
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, time2000, nil))
|
||||
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, "200001020304", nil))
|
||||
})
|
||||
|
||||
assert.True(t, len(result0) != 0)
|
||||
return result0
|
||||
t.Run("TestInvalidCode", func(t *testing.T) {
|
||||
assert.False(t, VerifyTimeLimitCode(now, "data", 2, ""))
|
||||
assert.False(t, VerifyTimeLimitCode(now, "data", 2, "invalid code"))
|
||||
})
|
||||
|
||||
t.Run("TestCreateAndVerify", func(t *testing.T) {
|
||||
code := CreateTimeLimitCode("data", 2, now, nil)
|
||||
assert.False(t, VerifyTimeLimitCode(now.Add(-time.Minute), "data", 2, code)) // not started yet
|
||||
assert.True(t, VerifyTimeLimitCode(now, "data", 2, code))
|
||||
assert.True(t, VerifyTimeLimitCode(now.Add(time.Minute), "data", 2, code))
|
||||
assert.False(t, VerifyTimeLimitCode(now.Add(time.Minute), "DATA", 2, code)) // invalid data
|
||||
assert.False(t, VerifyTimeLimitCode(now.Add(2*time.Minute), "data", 2, code)) // expired
|
||||
})
|
||||
|
||||
t.Run("TestDifferentSecret", func(t *testing.T) {
|
||||
// use another secret to ensure the code is invalid for different secret
|
||||
verifyDataCode := func(c string) bool {
|
||||
return VerifyTimeLimitCode(now, "data", 2, c)
|
||||
}
|
||||
code1 := CreateTimeLimitCode("data", 2, now, sha1.New())
|
||||
code2 := CreateTimeLimitCode("data", 2, now, nil)
|
||||
assert.True(t, verifyDataCode(code1))
|
||||
assert.True(t, verifyDataCode(code2))
|
||||
initGeneralSecret("000_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
||||
assert.False(t, verifyDataCode(code1))
|
||||
assert.False(t, verifyDataCode(code2))
|
||||
})
|
||||
}
|
||||
|
||||
func TestFileSize(t *testing.T) {
|
||||
|
|
|
@ -80,7 +80,7 @@ func NewIDFromString(hexHash string) (ObjectID, error) {
|
|||
}
|
||||
|
||||
// IsEmptyCommitID checks if an hexadecimal string represents an empty commit according to git (only '0').
|
||||
// If objectFormat is not nil, the length will be checked as well (otherwise the lenght must match the sha1 or sha256 length).
|
||||
// If objectFormat is not nil, the length will be checked as well (otherwise the length must match the sha1 or sha256 length).
|
||||
func IsEmptyCommitID(commitID string, objectFormat ObjectFormat) bool {
|
||||
if commitID == "" {
|
||||
return true
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -128,3 +130,9 @@ func (l *LimitedReaderCloser) Read(p []byte) (n int, err error) {
|
|||
func (l *LimitedReaderCloser) Close() error {
|
||||
return l.C.Close()
|
||||
}
|
||||
|
||||
func HashFilePathForWebUI(s string) string {
|
||||
h := sha1.New()
|
||||
_, _ = h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
package git
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// This file contains utility functions that are used across multiple tests,
|
||||
// but not in production code.
|
||||
|
@ -13,3 +17,10 @@ func skipIfSHA256NotSupported(t *testing.T) {
|
|||
t.Skip("skipping because installed Git version doesn't support SHA256")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashFilePathForWebUI(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
"8843d7f92416211de9ebb963ff4ce28125932878",
|
||||
HashFilePathForWebUI("foobar"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -91,6 +91,9 @@ func validateYaml(template *api.IssueTemplate) error {
|
|||
if err := validateOptions(field, idx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateDropdownDefault(position, field.Attributes); err != nil {
|
||||
return err
|
||||
}
|
||||
case api.IssueFormFieldTypeCheckboxes:
|
||||
if err := validateStringItem(position, field.Attributes, false, "description"); err != nil {
|
||||
return err
|
||||
|
@ -249,6 +252,28 @@ func validateBoolItem(position errorPosition, m map[string]any, names ...string)
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateDropdownDefault(position errorPosition, attributes map[string]any) error {
|
||||
v, ok := attributes["default"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
defaultValue, ok := v.(int)
|
||||
if !ok {
|
||||
return position.Errorf("'default' should be an int")
|
||||
}
|
||||
|
||||
options, ok := attributes["options"].([]any)
|
||||
if !ok {
|
||||
// should not happen
|
||||
return position.Errorf("'options' is required and should be a array")
|
||||
}
|
||||
if defaultValue < 0 || defaultValue >= len(options) {
|
||||
return position.Errorf("the value of 'default' is out of range")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type errorPosition string
|
||||
|
||||
func (p errorPosition) Errorf(format string, a ...any) error {
|
||||
|
|
|
@ -355,6 +355,96 @@ body:
|
|||
`,
|
||||
wantErr: "body[0](checkboxes), option[1]: can not require a hidden checkbox",
|
||||
},
|
||||
{
|
||||
name: "dropdown default is not an integer",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
description: Description of dropdown
|
||||
multiple: true
|
||||
options:
|
||||
- Option 1 of dropdown
|
||||
- Option 2 of dropdown
|
||||
- Option 3 of dropdown
|
||||
default: "def"
|
||||
validations:
|
||||
required: true
|
||||
`,
|
||||
wantErr: "body[0](dropdown): 'default' should be an int",
|
||||
},
|
||||
{
|
||||
name: "dropdown default is out of range",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
description: Description of dropdown
|
||||
multiple: true
|
||||
options:
|
||||
- Option 1 of dropdown
|
||||
- Option 2 of dropdown
|
||||
- Option 3 of dropdown
|
||||
default: 3
|
||||
validations:
|
||||
required: true
|
||||
`,
|
||||
wantErr: "body[0](dropdown): the value of 'default' is out of range",
|
||||
},
|
||||
{
|
||||
name: "dropdown without default is valid",
|
||||
content: `
|
||||
name: "test"
|
||||
about: "this is about"
|
||||
body:
|
||||
- type: dropdown
|
||||
id: "1"
|
||||
attributes:
|
||||
label: Label of dropdown
|
||||
description: Description of dropdown
|
||||
multiple: true
|
||||
options:
|
||||
- Option 1 of dropdown
|
||||
- Option 2 of dropdown
|
||||
- Option 3 of dropdown
|
||||
validations:
|
||||
required: true
|
||||
`,
|
||||
want: &api.IssueTemplate{
|
||||
Name: "test",
|
||||
About: "this is about",
|
||||
Fields: []*api.IssueFormField{
|
||||
{
|
||||
Type: "dropdown",
|
||||
ID: "1",
|
||||
Attributes: map[string]any{
|
||||
"label": "Label of dropdown",
|
||||
"description": "Description of dropdown",
|
||||
"multiple": true,
|
||||
"options": []any{
|
||||
"Option 1 of dropdown",
|
||||
"Option 2 of dropdown",
|
||||
"Option 3 of dropdown",
|
||||
},
|
||||
},
|
||||
Validations: map[string]any{
|
||||
"required": true,
|
||||
},
|
||||
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
||||
},
|
||||
},
|
||||
FileName: "test.yaml",
|
||||
},
|
||||
wantErr: "",
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
content: `
|
||||
|
@ -399,6 +489,7 @@ body:
|
|||
- Option 1 of dropdown
|
||||
- Option 2 of dropdown
|
||||
- Option 3 of dropdown
|
||||
default: 1
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
|
@ -475,6 +566,7 @@ body:
|
|||
"Option 2 of dropdown",
|
||||
"Option 3 of dropdown",
|
||||
},
|
||||
"default": 1,
|
||||
},
|
||||
Validations: map[string]any{
|
||||
"required": true,
|
||||
|
|
|
@ -20,6 +20,7 @@ func loadAdminFrom(rootCfg ConfigProvider) {
|
|||
sec := rootCfg.Section("admin")
|
||||
Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false)
|
||||
Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled")
|
||||
Admin.SendNotificationEmailOnNewUser = sec.Key("SEND_NOTIFICATION_EMAIL_ON_NEW_USER").MustBool(false)
|
||||
Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...)
|
||||
Admin.ExternalUserDisableFeatures = container.SetOf(sec.Key("EXTERNAL_USER_DISABLE_FEATURES").Strings(",")...)
|
||||
}
|
||||
|
|
32
modules/setting/admin_test.go
Normal file
32
modules/setting/admin_test.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright The Forgejo Authors.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_loadAdminFrom(t *testing.T) {
|
||||
iniStr := `
|
||||
[admin]
|
||||
DISABLE_REGULAR_ORG_CREATION = true
|
||||
DEFAULT_EMAIL_NOTIFICATIONS = z
|
||||
SEND_NOTIFICATION_EMAIL_ON_NEW_USER = true
|
||||
USER_DISABLED_FEATURES = a,b
|
||||
EXTERNAL_USER_DISABLE_FEATURES = x,y
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
loadAdminFrom(cfg)
|
||||
|
||||
assert.EqualValues(t, true, Admin.DisableRegularOrgCreation)
|
||||
assert.EqualValues(t, "z", Admin.DefaultEmailNotification)
|
||||
assert.EqualValues(t, true, Admin.SendNotificationEmailOnNewUser)
|
||||
assert.EqualValues(t, container.SetOf("a", "b"), Admin.UserDisabledFeatures)
|
||||
assert.EqualValues(t, container.SetOf("x", "y"), Admin.ExternalUserDisableFeatures)
|
||||
}
|
190
options/license/3D-Slicer-1.0
Normal file
190
options/license/3D-Slicer-1.0
Normal file
|
@ -0,0 +1,190 @@
|
|||
3D Slicer Contribution and Software License Agreement ("Agreement")
|
||||
Version 1.0 (December 20, 2005)
|
||||
|
||||
This Agreement covers contributions to and downloads from the 3D
|
||||
Slicer project ("Slicer") maintained by The Brigham and Women's
|
||||
Hospital, Inc. ("Brigham"). Part A of this Agreement applies to
|
||||
contributions of software and/or data to Slicer (including making
|
||||
revisions of or additions to code and/or data already in Slicer). Part
|
||||
B of this Agreement applies to downloads of software and/or data from
|
||||
Slicer. Part C of this Agreement applies to all transactions with
|
||||
Slicer. If you distribute Software (as defined below) downloaded from
|
||||
Slicer, all of the paragraphs of Part B of this Agreement must be
|
||||
included with and apply to such Software.
|
||||
|
||||
Your contribution of software and/or data to Slicer (including prior
|
||||
to the date of the first publication of this Agreement, each a
|
||||
"Contribution") and/or downloading, copying, modifying, displaying,
|
||||
distributing or use of any software and/or data from Slicer
|
||||
(collectively, the "Software") constitutes acceptance of all of the
|
||||
terms and conditions of this Agreement. If you do not agree to such
|
||||
terms and conditions, you have no right to contribute your
|
||||
Contribution, or to download, copy, modify, display, distribute or use
|
||||
the Software.
|
||||
|
||||
PART A. CONTRIBUTION AGREEMENT - License to Brigham with Right to
|
||||
Sublicense ("Contribution Agreement").
|
||||
|
||||
1. As used in this Contribution Agreement, "you" means the individual
|
||||
contributing the Contribution to Slicer and the institution or
|
||||
entity which employs or is otherwise affiliated with such
|
||||
individual in connection with such Contribution.
|
||||
|
||||
2. This Contribution Agreement applies to all Contributions made to
|
||||
Slicer, including without limitation Contributions made prior to
|
||||
the date of first publication of this Agreement. If at any time you
|
||||
make a Contribution to Slicer, you represent that (i) you are
|
||||
legally authorized and entitled to make such Contribution and to
|
||||
grant all licenses granted in this Contribution Agreement with
|
||||
respect to such Contribution; (ii) if your Contribution includes
|
||||
any patient data, all such data is de-identified in accordance with
|
||||
U.S. confidentiality and security laws and requirements, including
|
||||
but not limited to the Health Insurance Portability and
|
||||
Accountability Act (HIPAA) and its regulations, and your disclosure
|
||||
of such data for the purposes contemplated by this Agreement is
|
||||
properly authorized and in compliance with all applicable laws and
|
||||
regulations; and (iii) you have preserved in the Contribution all
|
||||
applicable attributions, copyright notices and licenses for any
|
||||
third party software or data included in the Contribution.
|
||||
|
||||
3. Except for the licenses granted in this Agreement, you reserve all
|
||||
right, title and interest in your Contribution.
|
||||
|
||||
4. You hereby grant to Brigham, with the right to sublicense, a
|
||||
perpetual, worldwide, non-exclusive, no charge, royalty-free,
|
||||
irrevocable license to use, reproduce, make derivative works of,
|
||||
display and distribute the Contribution. If your Contribution is
|
||||
protected by patent, you hereby grant to Brigham, with the right to
|
||||
sublicense, a perpetual, worldwide, non-exclusive, no-charge,
|
||||
royalty-free, irrevocable license under your interest in patent
|
||||
rights covering the Contribution, to make, have made, use, sell and
|
||||
otherwise transfer your Contribution, alone or in combination with
|
||||
any other code.
|
||||
|
||||
5. You acknowledge and agree that Brigham may incorporate your
|
||||
Contribution into Slicer and may make Slicer available to members
|
||||
of the public on an open source basis under terms substantially in
|
||||
accordance with the Software License set forth in Part B of this
|
||||
Agreement. You further acknowledge and agree that Brigham shall
|
||||
have no liability arising in connection with claims resulting from
|
||||
your breach of any of the terms of this Agreement.
|
||||
|
||||
6. YOU WARRANT THAT TO THE BEST OF YOUR KNOWLEDGE YOUR CONTRIBUTION
|
||||
DOES NOT CONTAIN ANY CODE THAT REQUIRES OR PRESCRIBES AN "OPEN
|
||||
SOURCE LICENSE" FOR DERIVATIVE WORKS (by way of non-limiting
|
||||
example, the GNU General Public License or other so-called
|
||||
"reciprocal" license that requires any derived work to be licensed
|
||||
under the GNU General Public License or other "open source
|
||||
license").
|
||||
|
||||
PART B. DOWNLOADING AGREEMENT - License from Brigham with Right to
|
||||
Sublicense ("Software License").
|
||||
|
||||
1. As used in this Software License, "you" means the individual
|
||||
downloading and/or using, reproducing, modifying, displaying and/or
|
||||
distributing the Software and the institution or entity which
|
||||
employs or is otherwise affiliated with such individual in
|
||||
connection therewith. The Brigham and Women's Hospital,
|
||||
Inc. ("Brigham") hereby grants you, with right to sublicense, with
|
||||
respect to Brigham's rights in the software, and data, if any,
|
||||
which is the subject of this Software License (collectively, the
|
||||
"Software"), a royalty-free, non-exclusive license to use,
|
||||
reproduce, make derivative works of, display and distribute the
|
||||
Software, provided that:
|
||||
|
||||
(a) you accept and adhere to all of the terms and conditions of this
|
||||
Software License;
|
||||
|
||||
(b) in connection with any copy of or sublicense of all or any portion
|
||||
of the Software, all of the terms and conditions in this Software
|
||||
License shall appear in and shall apply to such copy and such
|
||||
sublicense, including without limitation all source and executable
|
||||
forms and on any user documentation, prefaced with the following
|
||||
words: "All or portions of this licensed product (such portions are
|
||||
the "Software") have been obtained under license from The Brigham and
|
||||
Women's Hospital, Inc. and are subject to the following terms and
|
||||
conditions:"
|
||||
|
||||
(c) you preserve and maintain all applicable attributions, copyright
|
||||
notices and licenses included in or applicable to the Software;
|
||||
|
||||
(d) modified versions of the Software must be clearly identified and
|
||||
marked as such, and must not be misrepresented as being the original
|
||||
Software; and
|
||||
|
||||
(e) you consider making, but are under no obligation to make, the
|
||||
source code of any of your modifications to the Software freely
|
||||
available to others on an open source basis.
|
||||
|
||||
2. The license granted in this Software License includes without
|
||||
limitation the right to (i) incorporate the Software into
|
||||
proprietary programs (subject to any restrictions applicable to
|
||||
such programs), (ii) add your own copyright statement to your
|
||||
modifications of the Software, and (iii) provide additional or
|
||||
different license terms and conditions in your sublicenses of
|
||||
modifications of the Software; provided that in each case your use,
|
||||
reproduction or distribution of such modifications otherwise
|
||||
complies with the conditions stated in this Software License.
|
||||
|
||||
3. This Software License does not grant any rights with respect to
|
||||
third party software, except those rights that Brigham has been
|
||||
authorized by a third party to grant to you, and accordingly you
|
||||
are solely responsible for (i) obtaining any permissions from third
|
||||
parties that you need to use, reproduce, make derivative works of,
|
||||
display and distribute the Software, and (ii) informing your
|
||||
sublicensees, including without limitation your end-users, of their
|
||||
obligations to secure any such required permissions.
|
||||
|
||||
4. The Software has been designed for research purposes only and has
|
||||
not been reviewed or approved by the Food and Drug Administration
|
||||
or by any other agency. YOU ACKNOWLEDGE AND AGREE THAT CLINICAL
|
||||
APPLICATIONS ARE NEITHER RECOMMENDED NOR ADVISED. Any
|
||||
commercialization of the Software is at the sole risk of the party
|
||||
or parties engaged in such commercialization. You further agree to
|
||||
use, reproduce, make derivative works of, display and distribute
|
||||
the Software in compliance with all applicable governmental laws,
|
||||
regulations and orders, including without limitation those relating
|
||||
to export and import control.
|
||||
|
||||
5. The Software is provided "AS IS" and neither Brigham nor any
|
||||
contributor to the software (each a "Contributor") shall have any
|
||||
obligation to provide maintenance, support, updates, enhancements
|
||||
or modifications thereto. BRIGHAM AND ALL CONTRIBUTORS SPECIFICALLY
|
||||
DISCLAIM ALL EXPRESS AND IMPLIED WARRANTIES OF ANY KIND INCLUDING,
|
||||
BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
BRIGHAM OR ANY CONTRIBUTOR BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
INDIRECT, SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY ARISING IN ANY WAY
|
||||
RELATED TO THE SOFTWARE, EVEN IF BRIGHAM OR ANY CONTRIBUTOR HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. TO THE MAXIMUM
|
||||
EXTENT NOT PROHIBITED BY LAW OR REGULATION, YOU FURTHER ASSUME ALL
|
||||
LIABILITY FOR YOUR USE, REPRODUCTION, MAKING OF DERIVATIVE WORKS,
|
||||
DISPLAY, LICENSE OR DISTRIBUTION OF THE SOFTWARE AND AGREE TO
|
||||
INDEMNIFY AND HOLD HARMLESS BRIGHAM AND ALL CONTRIBUTORS FROM AND
|
||||
AGAINST ANY AND ALL CLAIMS, SUITS, ACTIONS, DEMANDS AND JUDGMENTS
|
||||
ARISING THEREFROM.
|
||||
|
||||
6. None of the names, logos or trademarks of Brigham or any of
|
||||
Brigham's affiliates or any of the Contributors, or any funding
|
||||
agency, may be used to endorse or promote products produced in
|
||||
whole or in part by operation of the Software or derived from or
|
||||
based on the Software without specific prior written permission
|
||||
from the applicable party.
|
||||
|
||||
7. Any use, reproduction or distribution of the Software which is not
|
||||
in accordance with this Software License shall automatically revoke
|
||||
all rights granted to you under this Software License and render
|
||||
Paragraphs 1 and 2 of this Software License null and void.
|
||||
|
||||
8. This Software License does not grant any rights in or to any
|
||||
intellectual property owned by Brigham or any Contributor except
|
||||
those rights expressly granted hereunder.
|
||||
|
||||
PART C. MISCELLANEOUS
|
||||
|
||||
This Agreement shall be governed by and construed in accordance with
|
||||
the laws of The Commonwealth of Massachusetts without regard to
|
||||
principles of conflicts of law. This Agreement shall supercede and
|
||||
replace any license terms that you may have agreed to previously with
|
||||
respect to Slicer.
|
13
options/license/Asterisk-linking-protocols-exception
Normal file
13
options/license/Asterisk-linking-protocols-exception
Normal file
|
@ -0,0 +1,13 @@
|
|||
Specific permission is also granted to link Asterisk with OpenSSL, OpenH323
|
||||
UniMRCP, and/or the UW IMAP Toolkit and distribute the resulting binary files.
|
||||
|
||||
In addition, Asterisk implements several management/control protocols.
|
||||
This includes the Asterisk Manager Interface (AMI), the Asterisk Gateway
|
||||
Interface (AGI), and the Asterisk REST Interface (ARI). It is our belief
|
||||
that applications using these protocols to manage or control an Asterisk
|
||||
instance do not have to be licensed under the GPL or a compatible license,
|
||||
as we believe these protocols do not create a 'derivative work' as referred
|
||||
to in the GPL. However, should any court or other judiciary body find that
|
||||
these protocols do fall under the terms of the GPL, then we hereby grant you a
|
||||
license to use these protocols in combination with Asterisk in external
|
||||
applications licensed under any license you wish.
|
25
options/license/HPND-Intel
Normal file
25
options/license/HPND-Intel
Normal file
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 1993 Intel Corporation
|
||||
|
||||
Intel hereby grants you permission to copy, modify, and distribute this
|
||||
software and its documentation. Intel grants this permission provided
|
||||
that the above copyright notice appears in all copies and that both the
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation. In addition, Intel grants this permission provided that
|
||||
you prominently mark as "not part of the original" any modifications
|
||||
made to this software or documentation, and that the name of Intel
|
||||
Corporation not be used in advertising or publicity pertaining to
|
||||
distribution of the software or the documentation without specific,
|
||||
written prior permission.
|
||||
|
||||
Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR
|
||||
IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or
|
||||
representations regarding the use of, or the results of the use of,
|
||||
the software and documentation in terms of correctness, accuracy,
|
||||
reliability, currentness, or otherwise; and you rely on the software,
|
||||
documentation and results solely at your own risk.
|
||||
|
||||
IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS,
|
||||
LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES
|
||||
OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM
|
||||
PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER.
|
22
options/license/HPND-export-US-acknowledgement
Normal file
22
options/license/HPND-export-US-acknowledgement
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (C) 1994 by the University of Southern California
|
||||
|
||||
EXPORT OF THIS SOFTWARE from the United States of America may
|
||||
require a specific license from the United States Government. It
|
||||
is the responsibility of any person or organization
|
||||
contemplating export to obtain such a license before exporting.
|
||||
|
||||
WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute
|
||||
this software and its documentation in source and binary forms is
|
||||
hereby granted, provided that any documentation or other materials
|
||||
related to such distribution or use acknowledge that the software
|
||||
was developed by the University of Southern California.
|
||||
|
||||
DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The
|
||||
University of Southern California MAKES NO REPRESENTATIONS OR
|
||||
WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
|
||||
limitation, the University of Southern California MAKES NO
|
||||
REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
||||
PARTICULAR PURPOSE. The University of Southern California shall not
|
||||
be held liable for any liability nor for any direct, indirect, or
|
||||
consequential damages with respect to any claim by the user or
|
||||
distributor of the ksu software.
|
19
options/license/NCBI-PD
Normal file
19
options/license/NCBI-PD
Normal file
|
@ -0,0 +1,19 @@
|
|||
PUBLIC DOMAIN NOTICE
|
||||
National Center for Biotechnology Information
|
||||
|
||||
This software is a "United States Government Work" under the terms of the
|
||||
United States Copyright Act. It was written as part of the authors'
|
||||
official duties as United States Government employees and thus cannot
|
||||
be copyrighted. This software is freely available to the public for
|
||||
use. The National Library of Medicine and the U.S. Government have not
|
||||
placed any restriction on its use or reproduction.
|
||||
|
||||
Although all reasonable efforts have been taken to ensure the accuracy
|
||||
and reliability of the software and data, the NLM and the U.S.
|
||||
Government do not and cannot warrant the performance or results that
|
||||
may be obtained by using this software or data. The NLM and the U.S.
|
||||
Government disclaim all warranties, express or implied, including
|
||||
warranties of performance, merchantability or fitness for any
|
||||
particular purpose.
|
||||
|
||||
Please cite the author in any work or product based on this material.
|
|
@ -1132,6 +1132,8 @@ pulls.cant_reopen_deleted_branch = Тази заявка за сливане н
|
|||
pulls.status_checks_hide_all = Скриване на всички проверки
|
||||
pulls.status_checks_failure = Някои проверки са неуспешни
|
||||
issues.review.add_review_request = поиска рецензия от %s %s
|
||||
wiki.no_search_results = Няма резултати
|
||||
wiki.search = Търсене в уикито
|
||||
|
||||
[modal]
|
||||
confirm = Потвърждаване
|
||||
|
@ -1474,7 +1476,7 @@ watched_repo = започна да наблюдава <a href="%[1]s">%[2]s</a>
|
|||
delete_tag = изтри маркера %[2]s от <a href="%[1]s">%[3]s</a>
|
||||
delete_branch = изтри клона %[2]s от <a href="%[1]s">%[3]s</a>
|
||||
create_branch = създаде клон <a href="%[2]s">%[3]s</a> на <a href="%[1]s">%[4]s</a>
|
||||
publish_release = `публикува издание <a href="%[2]s"> "%[4]s" </a> на <a href="%[1]s">%[3]s</a>`
|
||||
publish_release = `публикува издание <a href="%[2]s">%[4]s</a> на <a href="%[1]s">%[3]s</a>`
|
||||
push_tag = изтласка маркер <a href="%[2]s">%[3]s</a> към <a href="%[1]s">%[4]s</a>
|
||||
approve_pull_request = `одобри <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reject_pull_request = `предложи промени за <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
|
|
|
@ -2757,6 +2757,8 @@ release.hide_archive_links = Skrýt automaticky generované archivy
|
|||
release.hide_archive_links_helper = Pro toto vydání skrýt automaticky generované archivy zdrojového kódu. Užitečné například pokud nahráváte své vlastní.
|
||||
settings.transfer.button = Převést vlastnictví
|
||||
settings.transfer.modal.title = Převést vlastnictví
|
||||
wiki.search = Hledat na wiki
|
||||
wiki.no_search_results = Žádné výsledky
|
||||
|
||||
[graphs]
|
||||
component_loading_info = Tohle může chvíli trvat…
|
||||
|
@ -3471,7 +3473,7 @@ mirror_sync_create=synchronizoval/a novou referenci <a href="%[2]s">%[3]s</a> do
|
|||
mirror_sync_delete=synchronizoval/a a smazal/a referenci <code>%[2]s</code> v <a href="%[1]s">%[3]s</a> ze zrcadla
|
||||
approve_pull_request=`schválil/a <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reject_pull_request=`navrhl/a změny pro <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
publish_release=`vydal/a <a href="%[2]s"> "%[4]s" </a> v <a href="%[1]s">%[3]s</a>`
|
||||
publish_release=`vydal/a <a href="%[2]s">%[4]s</a> v <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`zamítl/a posouzení z <b>%[4]s</b> pro <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Důvod:
|
||||
create_branch=vytvořil/a větev <a href="%[2]s">%[3]s</a> v <a href="%[1]s">%[4]s</a>
|
||||
|
|
|
@ -2746,6 +2746,8 @@ release.hide_archive_links = Automatisch generierte Archive verstecken
|
|||
release.hide_archive_links_helper = Verstecke automatisch generierte Quellcodearchive für diesen Release. Zum Beispiel, wenn du deine eigenen hochlädst.
|
||||
settings.transfer.button = Besitz übertragen
|
||||
settings.transfer.modal.title = Besitz übertragen
|
||||
wiki.no_search_results = Keine Ergebnisse
|
||||
wiki.search = Wiki durchsuchen
|
||||
|
||||
[graphs]
|
||||
|
||||
|
@ -3444,7 +3446,7 @@ mirror_sync_create=neue Referenz <a href="%[2]s">%[3]s</a> bei <a href="%[1]s">%
|
|||
mirror_sync_delete=hat die Referenz des Spiegels <code>%[2]s</code> in <a href="%[1]s">%[3]s</a> synchronisiert und gelöscht
|
||||
approve_pull_request=`hat <a href="%[1]s">%[3]s#%[2]s</a> genehmigt`
|
||||
reject_pull_request=`schlug Änderungen für <a href="%[1]s">%[3]s#%[2]s</a> vor`
|
||||
publish_release=`veröffentlichte Release <a href="%[2]s"> „%[4]s“ </a> in <a href="%[1]s">%[3]s</a>`
|
||||
publish_release=`veröffentlichte Release <a href="%[2]s">%[4]s</a> in <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`verwarf das Review von <b>%[4]s</b> in <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Grund:
|
||||
create_branch=legte den Branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> an
|
||||
|
|
|
@ -351,15 +351,15 @@ env_config_keys = Environment Configuration
|
|||
env_config_keys_prompt = The following environment variables will also be applied to your configuration file:
|
||||
|
||||
[home]
|
||||
uname_holder = Username or Email address
|
||||
uname_holder = Username or email address
|
||||
password_holder = Password
|
||||
switch_dashboard_context = Switch Dashboard Context
|
||||
switch_dashboard_context = Switch dashboard context
|
||||
my_repos = Repositories
|
||||
my_orgs = Organizations
|
||||
show_more_repos = Show more repositories…
|
||||
collaborative_repos = Collaborative Repositories
|
||||
collaborative_repos = Collaborative repositories
|
||||
view_home = View %s
|
||||
filter = Other Filters
|
||||
filter = Other filters
|
||||
filter_by_team_repositories = Filter by team repositories
|
||||
feed_of = Feed of "%s"
|
||||
|
||||
|
@ -390,7 +390,7 @@ relevant_repositories_tooltip = Repositories that are forks or that have no topi
|
|||
relevant_repositories = Only relevant repositories are being shown, <a href="%s">show unfiltered results</a>.
|
||||
|
||||
[auth]
|
||||
create_new_account = Register Account
|
||||
create_new_account = Register account
|
||||
register_helper_msg = Already have an account? Sign in now!
|
||||
social_register_helper_msg = Already have an account? Link it now!
|
||||
disable_register_prompt = Registration is disabled. Please contact your site administrator.
|
||||
|
@ -398,7 +398,7 @@ disable_register_mail = Email confirmation for registration is disabled.
|
|||
manual_activation_only = Contact your site administrator to complete activation.
|
||||
remember_me = Remember this device
|
||||
remember_me.compromised = The login token is not valid anymore which may indicate a compromised account. Please check your account for unusual activities.
|
||||
forgot_password_title= Forgot Password
|
||||
forgot_password_title= Forgot password
|
||||
forgot_password = Forgot password?
|
||||
sign_up_now = Need an account? Register now.
|
||||
sign_up_successful = Account was successfully created. Welcome!
|
||||
|
@ -406,7 +406,7 @@ confirmation_mail_sent_prompt = A new confirmation email has been sent to <b>%s<
|
|||
must_change_password = Update your password
|
||||
allow_password_change = Require user to change password (recommended)
|
||||
reset_password_mail_sent_prompt = A confirmation email has been sent to <b>%s</b>. Please check your inbox within the next %s to complete the account recovery process.
|
||||
active_your_account = Activate Your Account
|
||||
active_your_account = Activate your account
|
||||
account_activated = Account has been activated
|
||||
prohibit_login = Signing in is prohibited
|
||||
prohibit_login_desc = Your account is prohibited from signing in, please contact your site administrator.
|
||||
|
@ -417,8 +417,8 @@ change_unconfirmed_email = If you have given the wrong email address during regi
|
|||
change_unconfirmed_email_error = Unable to change the email address: %v
|
||||
resend_mail = Click here to resend your activation email
|
||||
email_not_associate = The email address is not associated with any account.
|
||||
send_reset_mail = Send Account Recovery Email
|
||||
reset_password = Account Recovery
|
||||
send_reset_mail = Send recovery email
|
||||
reset_password = Account recovery
|
||||
invalid_code = Your confirmation code is invalid or has expired.
|
||||
invalid_code_forgot_password = Your confirmation code is invalid or has expired. Click <a href="%s">here</a> to start a new session.
|
||||
invalid_password = Your password does not match the password that was used to create the account.
|
||||
|
@ -436,12 +436,12 @@ login_userpass = Sign In
|
|||
tab_signin = Sign In
|
||||
tab_signup = Sign Up
|
||||
tab_openid = OpenID
|
||||
oauth_signup_tab = Register New Account
|
||||
oauth_signup_title = Complete New Account
|
||||
oauth_signup_submit = Complete Account
|
||||
oauth_signup_tab = Register new account
|
||||
oauth_signup_title = Complete new account
|
||||
oauth_signup_submit = Complete account
|
||||
oauth_signin_tab = Link to an existing account
|
||||
oauth_signin_title = Sign in to authorize linked account
|
||||
oauth_signin_submit = Link Account
|
||||
oauth_signin_submit = Link account
|
||||
oauth.signin.error = There was an error processing the authorization request. If this error persists, please contact the site administrator.
|
||||
oauth.signin.error.access_denied = The authorization request was denied.
|
||||
oauth.signin.error.temporarily_unavailable = Authorization failed because the authentication server is temporarily unavailable. Please try again later.
|
||||
|
@ -1607,7 +1607,7 @@ issues.role.collaborator_helper = This user has been invited to collaborate on t
|
|||
issues.role.first_time_contributor = First-time contributor
|
||||
issues.role.first_time_contributor_helper = This is the first contribution of this user to the repository.
|
||||
issues.role.contributor = Contributor
|
||||
issues.role.contributor_helper = This user has previously committed to the repository.
|
||||
issues.role.contributor_helper = This user has previously committed in this repository.
|
||||
issues.re_request_review=Re-request review
|
||||
issues.is_stale = There have been changes to this PR since this review
|
||||
issues.remove_request_review=Remove review request
|
||||
|
@ -1890,9 +1890,9 @@ pulls.unrelated_histories = Merge failed: The merge head and base do not share a
|
|||
pulls.merge_out_of_date = Merge failed: Whilst generating the merge, the base was updated. Hint: Try again.
|
||||
pulls.head_out_of_date = Merge failed: Whilst generating the merge, the head was updated. Hint: Try again.
|
||||
pulls.has_merged = Failed: The pull request has been merged, you cannot merge again or change the target branch.
|
||||
pulls.push_rejected = Push Failed: The push was rejected. Review the Git hooks for this repository.
|
||||
pulls.push_rejected = Push failed: The push was rejected. Review the Git hooks for this repository.
|
||||
pulls.push_rejected_summary = Full rejection message
|
||||
pulls.push_rejected_no_message = Push Failed: The push was rejected but there was no remote message. Review the Git hooks for this repository
|
||||
pulls.push_rejected_no_message = Push failed: The push was rejected but there was no remote message. Review the Git hooks for this repository
|
||||
pulls.open_unmerged_pull_exists = `You cannot perform a reopen operation because there is a pending pull request (#%d) with identical properties.`
|
||||
pulls.status_checking = Some checks are pending
|
||||
pulls.status_checks_success = All checks were successful
|
||||
|
@ -2035,8 +2035,8 @@ activity.period.quarterly = 3 months
|
|||
activity.period.semiyearly = 6 months
|
||||
activity.period.yearly = 1 year
|
||||
activity.overview = Overview
|
||||
activity.active_prs_count_1 = <strong>%d</strong> Active pull request
|
||||
activity.active_prs_count_n = <strong>%d</strong> Active pull requests
|
||||
activity.active_prs_count_1 = <strong>%d</strong> active pull request
|
||||
activity.active_prs_count_n = <strong>%d</strong> active pull requests
|
||||
activity.merged_prs_count_1 = Merged pull request
|
||||
activity.merged_prs_count_n = Merged pull requests
|
||||
activity.opened_prs_count_1 = Proposed pull request
|
||||
|
|
|
@ -463,7 +463,7 @@ reset_password.text = Kung ikaw ito, paki-click ang sumusunod na link para i-rec
|
|||
register_success = Matagumpay ang pag-rehistro
|
||||
issue_assigned.issue = Itinalaga ka ni @%[1]s sa isyu na %[2]s sa repositoryo na %[3]s.
|
||||
issue.x_mentioned_you = Binanggit ka ni <b>%s</b>:
|
||||
issue.action.force_push = Na-force push ni <b>%[1]s</b> ang <b>%[2]s</b> mula %[3]s sa %[4]s.
|
||||
issue.action.force_push = Na-force push ni/ng <b>%[1]s</b> ang <b>%[2]s</b> mula %[3]s sa %[4]s.
|
||||
issue.action.push_n = Nag-push si <b>@%[1]s</b> ng %[3]d (mga) commit sa %[2]s
|
||||
issue.action.close = Sinara ni <b>@%[1]s</b> ang #%[2]d.
|
||||
issue.action.reopen = Binuksan muli ni <b>@%[1]s</b> ang #%[2]d.
|
||||
|
@ -1084,7 +1084,7 @@ file.title = %s sa %s
|
|||
file_view_raw = Tingnan ng raw
|
||||
editor.new_file = Bagong file
|
||||
editor.edit_file = Baguhin ang file
|
||||
commit_graph.hide_pr_refs = Itago ang mga hiling sa paghatak
|
||||
commit_graph.hide_pr_refs = Itago ang mga hiling sa paghila
|
||||
editor.or = o
|
||||
editor.cancel_lower = kanselahin
|
||||
issues.filter_sort.latest = Pinakabago
|
||||
|
@ -1375,7 +1375,7 @@ issues.create = Gumawa ng isyu
|
|||
commits.gpg_key_id = ID ng susi ng GPG
|
||||
editor.no_changes_to_show = Walang maipapakitang pagbabago.
|
||||
editor.name_your_file = Ipangalan ang iyong file…
|
||||
pulls.new = Bagong hiling sa paghatak
|
||||
pulls.new = Bagong hiling sa paghila
|
||||
issues.ref_reopened_from = `<a href="%[3]s">binuksang muli ang isyung %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
settings.event_issues_desc = Binuksan, sinara, muling binuksan, o binago ang isyu.
|
||||
activity.new_issue_label = Nabuksan
|
||||
|
@ -1539,6 +1539,12 @@ projects.column.new_title = Pangalan
|
|||
projects.card_type.desc = Mga preview ng card
|
||||
commits.desc = I-browse ang history ng pagbabago ng source code.
|
||||
commits.search.tooltip = Maari kang mag-prefix ng mga keyword gamit ang "author:", "committer:", "after:", o "before:", hal. "revert author:Nijika before:2022-10-09".
|
||||
issues.force_push_codes = `puwersahang itinulak ang %[1]s mula <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> sa <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
|
||||
issues.push_commit_1 = idinagdag ang %d [commit] %s
|
||||
issues.push_commits_n = idinagdag ang %d mga [commit] %s
|
||||
issues.new.no_reviewers = Walang mga tagasuri
|
||||
pulls.title_desc_one = nais na isama ang %[1]d [commit] mula <code>%[2]s</code> hanggang <code id="branch_target">%[3]s</code>
|
||||
pulls.title_desc_few = nais na isama ang %[1]d mga [commit] mula <code>%[2]s</code> hanggang <code id="branch_target">%[3]s</code>
|
||||
|
||||
[search]
|
||||
commit_kind = Maghanap ng mga commit...
|
||||
|
@ -1915,6 +1921,8 @@ create_branch = ginawa ang branch na <a href="%[2]s">%[3]s</a> sa <a href="%[1]s
|
|||
create_repo = ginawa ang repositoryo na <a href="%s">%s</a>
|
||||
starred_repo = na-star ang <a href="%[1]s">%[2]s</a>
|
||||
watched_repo = ay sinimulang panoorin ang <a href="%[1]s">%[2]s</a>
|
||||
compare_commits_general = Ikumpara ang mga [commit]
|
||||
compare_commits = Ikumpara ang %d mga [commit]
|
||||
|
||||
[tool]
|
||||
1m = 1 minuto
|
||||
|
|
|
@ -770,11 +770,11 @@ primary=Principale
|
|||
activated=Activé
|
||||
requires_activation=Nécessite une activation
|
||||
primary_email=Faire de cette adresse votre adresse principale
|
||||
activate_email=Envoyer l’activation
|
||||
activate_email=Envoyer un courriel d'activation
|
||||
activations_pending=Activations en attente
|
||||
can_not_add_email_activations_pending=Il y a une activation en attente, réessayez dans quelques minutes si vous souhaitez ajouter un nouvel e-mail.
|
||||
delete_email=Exclure
|
||||
email_deletion=Supprimer l'adresse e-mail
|
||||
email_deletion=Supprimer l'adresse email
|
||||
email_deletion_desc=L’adresse e-mail et les informations associées seront retirées de votre compte. Les révisions Git effectuées par cette adresse resteront inchangées. Continuer ?
|
||||
email_deletion_success=L'adresse e-mail a été supprimée.
|
||||
theme_update_success=Votre thème a été mis à jour.
|
||||
|
@ -866,7 +866,7 @@ token_state_desc=Ce jeton a été utilisé au cours des 7 derniers jours
|
|||
principal_state_desc=Ce Principal a été utilisé au cours des 7 derniers jours
|
||||
show_openid=Afficher sur le profil
|
||||
hide_openid=Masquer du profil
|
||||
ssh_disabled=SSH désactivé
|
||||
ssh_disabled=SSH est désactivé
|
||||
ssh_signonly=SSH étant désactivé, ces clés ne servent qu'à vérifier la signature des révisions.
|
||||
ssh_externally_managed=Cette clé SSH est gérée de manière externe pour cet utilisateur
|
||||
manage_social=Gérer les réseaux sociaux associés
|
||||
|
@ -1335,10 +1335,10 @@ editor.commit_empty_file_header=Réviser un fichier vide
|
|||
editor.commit_empty_file_text=Le fichier que vous allez réviser est vide. Continuer ?
|
||||
editor.no_changes_to_show=Il n’y a aucune modification à afficher.
|
||||
editor.fail_to_update_file=Impossible de mettre à jour/créer le fichier "%s".
|
||||
editor.fail_to_update_file_summary=Message d'erreur :
|
||||
editor.fail_to_update_file_summary=Message d'erreur :
|
||||
editor.push_rejected_no_message=La modification a été rejetée par le serveur sans message. Veuillez vérifier les Git hooks.
|
||||
editor.push_rejected=La modification a été rejetée par le serveur. Veuillez vérifier vos Git hooks.
|
||||
editor.push_rejected_summary=Message de rejet complet :
|
||||
editor.push_rejected_summary=Message de rejet complet :
|
||||
editor.add_subdir=Ajouter un dossier…
|
||||
editor.unable_to_upload_files=Impossible d'envoyer le fichier "%s" : %v
|
||||
editor.upload_file_is_locked=Le fichier "%s" est verrouillé par %s.
|
||||
|
@ -1855,13 +1855,13 @@ pulls.merge_commit_id=L'ID de la révision de fusion
|
|||
pulls.require_signed_wont_sign=La branche nécessite des révisions signées mais cette fusion ne sera pas signée
|
||||
|
||||
pulls.invalid_merge_option=Vous ne pouvez pas utiliser cette option de fusion pour cette demande.
|
||||
pulls.merge_conflict=Échec de la fusion : il y a eu un conflit lors de la fusion. Indice : Essayez une autre stratégie
|
||||
pulls.merge_conflict=Fusion échouée : il y a eu un conflit lors de la fusion. Indice : Essayez une stratégie différente
|
||||
pulls.merge_conflict_summary=Message d'erreur
|
||||
pulls.rebase_conflict=Fusion échouée : il y a eu un conflit lors du rebasage de la révision %[1]s. Astuce : Essayez une stratégie différente
|
||||
pulls.rebase_conflict=Fusion échouée : il y a eu un conflit lors du rebasage de la révision %[1]s. Indice : Essayez une stratégie différente
|
||||
pulls.rebase_conflict_summary=Message d'erreur
|
||||
pulls.unrelated_histories=Échec de la fusion : La tête de fusion et la base ne partagent pas d'historique commun. Indice : Essayez une stratégie différente
|
||||
pulls.merge_out_of_date=Échec de la fusion : La base a été mise à jour en cours de fusion. Indice : Réessayez.
|
||||
pulls.head_out_of_date=Échec de la fusion : L’en-tête a été mis à jour pendant la fusion. Conseil : réessayez.
|
||||
pulls.unrelated_histories=Fusion échouée : La tête de fusion et la base ne partagent pas d'historique commun. Indice : Essayez une stratégie différente
|
||||
pulls.merge_out_of_date=Fusion échouée : La base a été mise à jour en cours de fusion. Indice : Réessayez.
|
||||
pulls.head_out_of_date=Fusion échouée : L’en-tête a été mis à jour pendant la fusion. Indice : réessayez.
|
||||
pulls.has_merged=Échec : La demande d’ajout est déjà fusionnée, vous ne pouvez plus la fusionner, ni modifier sa branche cible.
|
||||
pulls.push_rejected=Échec du push : la soumission a été rejetée. Revoyez les Git hook pour ce dépôt.
|
||||
pulls.push_rejected_summary=Message de rejet complet
|
||||
|
@ -2412,9 +2412,9 @@ settings.protect_branch_name_pattern=Motif de nom de branche protégé
|
|||
settings.protect_branch_name_pattern_desc=Motifs de nom de branche protégé. Consultez la <a href="https://github.com/gobwas/glob">documentation</a> pour la syntaxe du motif. Exemples : main, release/**
|
||||
settings.protect_patterns=Motifs
|
||||
settings.protect_protected_file_patterns=Liste des fichiers et motifs protégés (séparés par un point virgule ";") :
|
||||
settings.protect_protected_file_patterns_desc=Les fichiers protégés ne peuvent être modifiés, même si l'utilisateur a le droit d'ajouter, éditer ou supprimer des fichiers dans cette branche. Plusieurs motifs peuvent être séparés par un point-virgule ( ;). Voir la documentation de <a href='https ://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> pour la syntaxe des motifs. Exemples : <code>.forgejo/workflows/test.yml</code>, <code>/docs/**/*.txt</code>.
|
||||
settings.protect_protected_file_patterns_desc=Les fichiers protégés ne peuvent être modifiés, même si l'utilisateur a le droit d'ajouter, éditer ou supprimer des fichiers dans cette branche. Plusieurs motifs peuvent être séparés par un point-virgule (";"). Veuillez voir <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> la documentation pour la syntaxe des motifs. Exemples : <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||
settings.protect_unprotected_file_patterns=Liste des fichiers et motifs exclus (séparés par un point virgule ";") :
|
||||
settings.protect_unprotected_file_patterns_desc=Les fichiers non-protégés qui peuvent être modifiés si l'utilisateur a le droit d'écriture, prenant le pas sur les restrictions de push. Plusieurs motifs peuvent être séparés par un point-virgule ( ;). Voir la documentation de <a href='https ://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> pour la syntaxe des motifs. Exemples : <code>.forgejo/workflows/test.yml</code>, <code>/docs/**/*.txt</code>.
|
||||
settings.protect_unprotected_file_patterns_desc=Les fichiers non-protégés qui peuvent être modifiés si l'utilisateur a le droit d'écriture, prenant le pas sur les restrictions de push. Plusieurs motifs peuvent être séparés par un point-virgule (";"). Veuillez voir <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> la documentation pour la syntaxe des motifs. Exemples : <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||
settings.add_protected_branch=Activer la protection
|
||||
settings.delete_protected_branch=Désactiver la protection
|
||||
settings.update_protect_branch_success=La règle de protection de branche "%s" a été mise à jour.
|
||||
|
@ -2526,8 +2526,8 @@ diff.file_after=Après
|
|||
diff.file_image_width=Largeur
|
||||
diff.file_image_height=Hauteur
|
||||
diff.file_byte_size=Taille
|
||||
diff.file_suppressed=Diff de fichier supprimé car celui-ci est trop grand
|
||||
diff.file_suppressed_line_too_long=Diff de fichier supprimé car une ou plusieurs lignes sont trop longues
|
||||
diff.file_suppressed=Le diff du fichier est caché, car celui-ci est trop grand
|
||||
diff.file_suppressed_line_too_long=Le diff du fichier est caché, car une ou plusieurs lignes sont trop longues
|
||||
diff.too_many_files=Certains fichiers ne sont pas affichés car ce diff contient trop de modifications
|
||||
diff.show_more=Voir plus
|
||||
diff.load=Voir la diff
|
||||
|
@ -2756,6 +2756,8 @@ release.hide_archive_links = Masquer les archives générées automatiquement
|
|||
release.hide_archive_links_helper = Masquer les archives de code source générées automatiquement pour cette publication. Par exemple, si vous téléchargez vos propres archives.
|
||||
settings.transfer.button = Changer de propriétaire
|
||||
settings.transfer.modal.title = Changer de propriétaire
|
||||
wiki.search = Recherche dans le wiki
|
||||
wiki.no_search_results = Pas de résultats
|
||||
|
||||
[graphs]
|
||||
component_loading=Chargement de %s…
|
||||
|
@ -3467,7 +3469,7 @@ mirror_sync_create=a synchronisé la nouvelle référence <a href="%[2]s">%[3]s<
|
|||
mirror_sync_delete=a synchronisé puis supprimé la nouvelle référence <code>%[2]s</code> vers <a href="%[1]s">%[3]s</a> depuis le miroir
|
||||
approve_pull_request=`a approuvé <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reject_pull_request=`a suggérés des changements pour <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
publish_release=`a publié <a href="%[2]s"> "%[4]s" </a> dans <a href="%[1]s">%[3]s</a>`
|
||||
publish_release=`a publié <a href="%[2]s">%[4]s</a> dans <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`a révoqué l’évaluation de <b>%[4]s</b> dans <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Raison :
|
||||
create_branch=a créé la branche <a href="%[2]s">%[3]s</a> dans <a href="%[1]s">%[4]s</a>
|
||||
|
|
|
@ -146,7 +146,7 @@ filter.is_archived = アーカイブ
|
|||
filter.not_archived = アーカイブされていない
|
||||
filter.is_fork = フォーク
|
||||
filter.is_mirror = ミラー
|
||||
filter.not_mirror = ミラーされていない
|
||||
filter.not_mirror = ミラーではない
|
||||
filter.is_template = テンプレート
|
||||
filter = フィルター
|
||||
filter.not_fork = フォークされていない
|
||||
|
@ -171,8 +171,8 @@ contributions_zero=貢献なし
|
|||
less=少
|
||||
more=多
|
||||
contributions_one = 貢献
|
||||
contributions_few = 貢献たち
|
||||
contributions_format = {month} {day}, {year} に {contributions} 件の貢献
|
||||
contributions_few = 貢献
|
||||
contributions_format = {month} {day}, {year} に {contributions}
|
||||
|
||||
[editor]
|
||||
buttons.heading.tooltip=見出し追加
|
||||
|
@ -647,7 +647,7 @@ joined_on=%sに登録
|
|||
repositories=リポジトリ
|
||||
activity=公開アクティビティ
|
||||
followers_few=%d フォロワー
|
||||
starred=スターを付けたリポジトリたち
|
||||
starred=スターを付けたリポジトリ
|
||||
watched=ウォッチ中のリポジトリ
|
||||
code=コード
|
||||
projects=プロジェクト
|
||||
|
@ -2648,7 +2648,7 @@ find_file.no_matching=一致するファイルが見つかりません
|
|||
error.csv.too_large=このファイルは大きすぎるため表示できません。
|
||||
error.csv.unexpected=このファイルは %d 行目の %d 文字目に予期しない文字が含まれているため表示できません。
|
||||
error.csv.invalid_field_count=このファイルは %d 行目のフィールドの数が正しくないため表示できません。
|
||||
admin.enabled_flags = このリポジトリで有効になっているフラグたち:
|
||||
admin.enabled_flags = このリポジトリで有効になっているフラグ:
|
||||
clone_in_vscodium = VSCodiumでcloneする
|
||||
desc.sha256 = SHA256
|
||||
wiki.cancel = キャンセル
|
||||
|
@ -2737,7 +2737,7 @@ component_loading_failed = %s を読み込めませんでした
|
|||
component_loading_info = 少し時間がかかるかもしれません…
|
||||
component_failed_to_load = 予期しないエラーが発生しました。
|
||||
code_frequency.what = コード頻度
|
||||
contributors.what = 貢献たち
|
||||
contributors.what = 貢献
|
||||
recent_commits.what = 最近のコミット
|
||||
|
||||
[org]
|
||||
|
|
|
@ -15,7 +15,7 @@ page=페이지
|
|||
template=템플릿
|
||||
language=언어
|
||||
notifications=알림
|
||||
create_new=생성하기
|
||||
create_new=새로 만들기…
|
||||
user_profile_and_more=프로파일 및 설정…
|
||||
signed_in_as=다음 사용자로 로그인됨
|
||||
|
||||
|
@ -100,8 +100,8 @@ remove_label_str = "%s" 항목 제거
|
|||
disabled = 비활성화됨
|
||||
locked = 잠김
|
||||
filter = 필터
|
||||
filter.not_fork = 포크되지 않음
|
||||
filter.is_mirror = 미러됨
|
||||
filter.not_fork = 포크가 아님
|
||||
filter.is_mirror = 미러
|
||||
webauthn_press_button = 보안 키의 버튼을 누르세요…
|
||||
toggle_menu = 토글 메뉴
|
||||
webauthn_error = 보안 키를 읽을 수 없습니다.
|
||||
|
@ -146,13 +146,16 @@ confirm_delete_selected = 선택된 모든 항목을 삭제하시겠습니까?
|
|||
value = 값
|
||||
filter.is_archived = 보관됨
|
||||
filter.not_archived = 보관되지 않음
|
||||
filter.is_fork = 포크됨
|
||||
filter.not_mirror = 미러되지 않음
|
||||
filter.is_fork = 포크
|
||||
filter.not_mirror = 미러가 아님
|
||||
filter.is_template =템플릿
|
||||
filter.clear = 필터 지우기
|
||||
ok = 확인
|
||||
confirm_delete_artifact = 정말 artifact "%s"를 삭제하실건가요?
|
||||
artifacts = Artifacts
|
||||
filter.public = 공개
|
||||
filter.private = 비공개
|
||||
filter.not_template = 템플릿이 아님
|
||||
|
||||
[aria]
|
||||
navbar = 네비게이션 바
|
||||
|
@ -204,18 +207,18 @@ err_admin_name_is_reserved=관리자 사용자 이름이 올바르지 않습니
|
|||
err_admin_name_is_invalid=관리자 사용자 이름이 올바르지 않습니다
|
||||
|
||||
general_title=기본설정
|
||||
app_name=사이트 제목
|
||||
app_name=인스턴스 제목
|
||||
app_name_helper=회사이름을 넣으세요.
|
||||
repo_path=저장소 최상위 경로
|
||||
repo_path_helper=Git 원격 저장소는 이 디렉터리에 저장 됩니다.
|
||||
lfs_path=Git LFS 루트 경로
|
||||
lfs_path_helper=Git LFS에 저장된 파일들은 이 디렉토리에 저장됩니다. LFS를 사용하지 않는다면 빈칸으로 남겨주세요.
|
||||
run_user=실행 사용자명
|
||||
run_user=다음 사용자로 실행
|
||||
ssh_port=SSH 서버 포트
|
||||
ssh_port_helper=SSH 서버가 실행되고 있는 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
|
||||
http_port=Forgejo HTTP 수신 포트
|
||||
ssh_port_helper=SSH 서버를 실행할 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
|
||||
http_port=HTTP 수신 포트
|
||||
http_port_helper=Forgejo 웹서버가 수신할 포트 번호입니다.
|
||||
app_url=Forgejo 기본 URL
|
||||
app_url=기본 URL
|
||||
app_url_helper=HTTP(S) clone URL 및 이메일 알림 기본 주소입니다.
|
||||
log_root_path=로그 경로
|
||||
log_root_path_helper=로그파일은 이 디렉토리에 저장됩니다.
|
||||
|
@ -235,17 +238,17 @@ offline_mode=로컬 모드 켜기
|
|||
offline_mode_popup=타사 콘텐츠 전송 네트워크를 사용하지 않도록 설정하고 모든 리소스를 로컬로 제공하십시오.
|
||||
disable_gravatar=Gravatar 사용안함
|
||||
disable_gravatar_popup=Gravatar 및 타사 아바타 소스를 사용하지 않도록 설정합니다. 사용자가 로컬로 아바타를 업로드하지 않는 한 기본 아바타가 사용됩니다.
|
||||
federated_avatar_lookup=아바타 연동 사용여부
|
||||
federated_avatar_lookup=탈중앙화 아바타 사용
|
||||
federated_avatar_lookup_popup=libravatar 기반 오픈소스 연합 아바타 조회를 허용합니다.
|
||||
disable_registration=사용자 등록 비활성화
|
||||
disable_registration_popup=사용자가 직접 등록할 수 없게 합니다. 관리자만이 추가할 수 있습니다.
|
||||
allow_only_external_registration_popup=외부 서비스를 통한 등록을 허용여부
|
||||
allow_only_external_registration_popup=외부 서비스를 통한 등록을 허용
|
||||
openid_signin=OpenID 로그인 사용
|
||||
openid_signin_popup=OpenID 를 이용한 로그인을 허용합니다.
|
||||
openid_signup=OpenID 가입 가능여부
|
||||
openid_signup=OpenID 가입 허용
|
||||
openid_signup_popup=OpenID를 통한 가입을 허용합니다.
|
||||
enable_captcha_popup=사용자 등록시 캡차를 요구합니다.
|
||||
require_sign_in_view=페이지를 보기 위해 로그인 하기
|
||||
require_sign_in_view=인스턴스의 콘텐츠를 볼때 로그인 요구
|
||||
admin_setting_desc=관리자 계정을 만드는 것은 선택사항입니다. 첫번째로 등록된 사용자는 자동적으로 관리자로 지정됩니다.
|
||||
admin_title=관리자 계정 설정
|
||||
admin_name=관리자 이름
|
||||
|
@ -257,7 +260,7 @@ test_git_failed='git' 명령 테스트 실패: %v
|
|||
sqlite3_not_available=해당 버전에서는 SQLite3를 지원하지 않습니다. %s에서 공식 버전을 다운로드해주세요. ('gobuild' 버전이 아닙니다).
|
||||
invalid_db_setting=데이터베이스 설정이 올바르지 않습니다: %v
|
||||
invalid_repo_path=저장소(레파지토리) 의 경로가 올바르지 않습니다: %v
|
||||
run_user_not_match=실행 사용자명이 현재 사용자명과 다릅니다.: %s -> %s
|
||||
run_user_not_match=실행 사용자명이 현재 사용자명과 다릅니다: %s -> %s
|
||||
save_config_failed=설정을 저장할 수 없습니다: %v
|
||||
invalid_admin_setting=관리자 계정 설정이 올바르지 않습니다: %v
|
||||
invalid_log_root_path=로그(Log) 의 경로가 올바르지 않습니다: %v
|
||||
|
@ -267,15 +270,15 @@ default_allow_create_organization=조직 생성 허용을 기본값으로 설정
|
|||
default_allow_create_organization_popup=신규 사용자 생성시 조직 생성을 기본값으로 설정합니다.
|
||||
default_enable_timetracking=시간 추적 사용을 기본값으로 설정
|
||||
default_enable_timetracking_popup=신규 레포지토리에 대한 시간 추적 사용을 기본값으로 설정합니다.
|
||||
no_reply_address=숨김처리된 이메일 도메인
|
||||
no_reply_address_helper=숨겨진 이메일을 가진 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자 'joe'의 숨겨진 이메일 도메인이 'noreply.example.org'로 설정되어 있으면 'joe@noreply.example.org'로 로그인 됩니다.
|
||||
no_reply_address=가려진 이메일 도메인
|
||||
no_reply_address_helper=가려진 이메일을 가진 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자 'joe'의 가려잔 이메일 도메인이 'noreply.example.org'로 설정되어 있으면 'joe@noreply.example.org'로 처리 됩니다.
|
||||
|
||||
[home]
|
||||
uname_holder=사용자 이름 또는 이메일 주소
|
||||
password_holder=비밀번호
|
||||
switch_dashboard_context=대시보드 컨텍스트 바꾸기
|
||||
my_repos=저장소
|
||||
show_more_repos=더 많은 저장소 보기
|
||||
show_more_repos=더 많은 저장소 보기…
|
||||
collaborative_repos=협업 저장소
|
||||
my_orgs=내 조직
|
||||
my_mirrors=내 미러 저장소들
|
||||
|
@ -313,7 +316,7 @@ allow_password_change=사용자에게 비밀번호 변경을 요청 (권장됨)
|
|||
reset_password_mail_sent_prompt=확인 메일이 <b>%s</b>로 전송되었습니다. 받은 편지함으로 도착한 메일을 %s 안에 확인해서 비밀번호 찾기 절차를 완료하십시오.
|
||||
active_your_account=계정 활성화
|
||||
account_activated=계정이 활성화 되었습니다
|
||||
prohibit_login=로그인이 금지됨
|
||||
prohibit_login=
|
||||
resent_limit_prompt=활성화를 위한 이메일을 이미 전송했습니다. 3분 내로 이메일을 받지 못한 경우 재시도해주세요.
|
||||
has_unconfirmed_mail=안녕하세요 %s, 이메일 주소(<b>%s</b>)가 확인되지 않았습니다. 확인 메일을 받으시지 못하겼거나 새로운 확인 메일이 필요하다면, 아래 버튼을 클릭해 재발송하실 수 있습니다.
|
||||
resend_mail=여기를 눌러 확인 메일 재전송
|
||||
|
@ -355,11 +358,12 @@ activate_account=계정을 활성화하세요
|
|||
|
||||
activate_email=이메일 주소 확인
|
||||
|
||||
register_notify=Forgejo에 오신것을 환영합니다!
|
||||
register_notify=Forgejo에 오신것을 환영합니다
|
||||
|
||||
reset_password=계정 복구
|
||||
|
||||
register_success=등록 완료
|
||||
issue.action.close = <b>@%[1]s</b>님이 #%[2]d를 닫았습니다.
|
||||
|
||||
|
||||
|
||||
|
@ -432,7 +436,7 @@ target_branch_not_exist=대상 브랜치가 존재하지 않습니다.
|
|||
|
||||
|
||||
[user]
|
||||
change_avatar=아바타 변경
|
||||
change_avatar=아바타 변경…
|
||||
repositories=저장소
|
||||
activity=공개 활동
|
||||
followers_few=%d 팔로워
|
||||
|
@ -443,6 +447,7 @@ follow=추적하기
|
|||
unfollow=추적해제
|
||||
user_bio=소개
|
||||
projects = 프로젝트
|
||||
watched = 주시중인 저장소
|
||||
|
||||
|
||||
[settings]
|
||||
|
@ -497,9 +502,9 @@ manage_emails=이메일 주소 관리
|
|||
manage_themes=기본 테마 선택
|
||||
manage_openid=OpenID 주소 관리
|
||||
theme_desc=이 테마가 사이트 전체 기본 테마가 됩니다.
|
||||
primary=기본
|
||||
primary=대표
|
||||
activated=활성화됨
|
||||
primary_email=프라이머리로 만들기
|
||||
primary_email=대표로 만들기
|
||||
delete_email=삭제
|
||||
email_deletion=이메일 주소 삭제
|
||||
email_deletion_desc=계정의 이메일 주소와 관련된 정보가 삭제됩니다. 이메일 주소로 이미 커밋된 내용들은 바뀌지 않고 남아있게 됩니다. 계속 진행하시겠습니까?
|
||||
|
@ -617,6 +622,8 @@ email_notifications.enable=이메일 알림 켜기
|
|||
email_notifications.disable=이메일 알림 끄기
|
||||
|
||||
visibility.private=비공개
|
||||
change_password = 비밀번호 변경
|
||||
email_desc = 당신의 대표 이메일 주소는 알림, 비밀번호 재설정과 웹에서의 Git 작동에 사용되며 가려지지 않습니다.
|
||||
|
||||
[repo]
|
||||
owner=소유자
|
||||
|
@ -681,8 +688,8 @@ mirror_from=의 미러
|
|||
forked_from=원본 프로젝트
|
||||
fork_from_self=자신의 저장소를 포크 할 수 없습니다.
|
||||
fork_guest_user=로그인하고 Fork 이 창고.
|
||||
unwatch=보지않기
|
||||
watch=보기
|
||||
unwatch=주시 중단
|
||||
watch=주시
|
||||
unstar=좋아요 취소
|
||||
star=좋아요
|
||||
fork=포크
|
||||
|
@ -775,7 +782,7 @@ issues.new.milestone=마일스톤
|
|||
issues.new.no_milestone=마일스톤 없음
|
||||
issues.new.clear_milestone=마일스톤 초기화
|
||||
issues.new.open_milestone=마일스톤 생성
|
||||
issues.new.closed_milestone=마일스톤 닫기
|
||||
issues.new.closed_milestone=닫힌 마일스톤
|
||||
issues.new.assignees=담당자
|
||||
issues.new.clear_assignees=담당자 초기화
|
||||
issues.new.no_assignees=담당자 없음
|
||||
|
@ -982,7 +989,7 @@ wiki.create_first_page=첫 페이지 작성
|
|||
wiki.page=페이지
|
||||
wiki.filter_page=페이지 필터링
|
||||
wiki.new_page=페이지
|
||||
wiki.default_commit_message=이 페이지 수정에 대한 메모를 작성하세요.(선택사항)
|
||||
wiki.default_commit_message=이 페이지 수정에 대한 메모를 작성하세요 (선택).
|
||||
wiki.save_page=페이지 저장하기
|
||||
wiki.last_commit_info=%s이(가) %s에 이 페이지를 수정함
|
||||
wiki.edit_page_button=수정하기
|
||||
|
@ -1166,8 +1173,8 @@ settings.deploy_key_deletion_success=배포키가 삭제되었습니다.
|
|||
settings.branches=브랜치
|
||||
settings.protected_branch=브랜치 보호
|
||||
settings.protected_branch_can_push=푸시를 허용하시겠습니까?
|
||||
settings.protected_branch_can_push_yes=푸시할 수 있습니다.
|
||||
settings.protected_branch_can_push_no=푸시할 수 없습니다.
|
||||
settings.protected_branch_can_push_yes=푸시할 수 있음
|
||||
settings.protected_branch_can_push_no=푸시할 수 없음
|
||||
settings.branch_protection='<b>%s</b>' 브랜치 보호
|
||||
settings.protect_this_branch=브랜치 보호 활성화
|
||||
settings.protect_disable_push=푸시 끄기
|
||||
|
@ -1180,7 +1187,7 @@ settings.protect_approvals_whitelist_users=화이트리스트된 리뷰어:
|
|||
settings.add_protected_branch=보호 활성화
|
||||
settings.delete_protected_branch=보호 비활성화
|
||||
settings.protected_branch_deletion=브랜치 보호 비활성화
|
||||
settings.choose_branch=브랜치 선택...
|
||||
settings.choose_branch=브랜치 선택…
|
||||
settings.no_protected_branch=보호된 브랜치가 없습니다.
|
||||
settings.edit_protected_branch=편집
|
||||
settings.archive.button=아카이브 저장소
|
||||
|
@ -1199,7 +1206,7 @@ diff.stats_desc=<strong>%d개의 변경된 파일</strong>과 <strong>%d개의
|
|||
diff.bin=BIN
|
||||
diff.view_file=파일 보기
|
||||
diff.file_byte_size=크기
|
||||
diff.file_suppressed=파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
|
||||
diff.file_suppressed=파일 크기가 너무 커 변경을 표시할 수 없음
|
||||
diff.comment.placeholder=댓글 남기기
|
||||
diff.comment.add_single_comment=간단한 설명 추가
|
||||
diff.comment.add_review_comment=댓글 추가
|
||||
|
@ -1236,13 +1243,13 @@ branch.name=브랜치명
|
|||
branch.delete_head=삭제
|
||||
branch.delete_html=브랜치 삭제
|
||||
branch.create_branch=<strong>%s</strong> 브랜치 생성
|
||||
branch.deleted_by=%s 에 의해 삭제되었습니다.
|
||||
branch.deleted_by=%s 에 의해 삭제되었음
|
||||
|
||||
|
||||
|
||||
topic.manage_topics=토픽 관리
|
||||
topic.done=완료
|
||||
topic.count_prompt=25개 이상의 토픽을 선택하실 수 없습니다.
|
||||
topic.count_prompt=25개 이상의 토픽을 선택하실 수 없음
|
||||
settings.trust_model.collaboratorcommitter.desc = 이 저장소의 협업자가 작성한 유효한 서명이 커미터와 일치하는 경우 "신뢰할 수 있음"으로 표시됩니다. 협업자가 아니되 유효한 서명이 커미터와 일치하면 "신뢰할 수 없음"으로 표시되고 그렇지 않으면 "일치하지 않음"으로 표시됩니다. 커밋에 Co-Authored-By: 또는 Co-Committed-By: 트레일러로 표시된 실제 커미터와 함께 서명된 커밋이 있다면 Forgejo가 커미터로 표시됩니다. 기본 Forgejo 키는 데이터베이스의 사용자와 일치해야 합니다.
|
||||
settings.matrix.access_token_helper = 이 작업을 위한 개별적인 Matrix 계정을 만드는것이 권장됩니다. 엑세스 토큰은 Element 웹 클라이언트(개인정보 보호 브라우징 권장) > 유저 메뉴(좌상단) > All settings > Help & About > Advanced > Access Token (홈서버 주소 바로 아래) 에서 찾을 수 있습니다. 로그아웃시 토큰이 만료됨을 주의하시고, 창을 닫아주세요.
|
||||
settings.trust_model.collaboratorcommitter = 협업자+커미터
|
||||
|
@ -1274,6 +1281,14 @@ pulls.approve_count_1 = %d명의 승인
|
|||
pulls.blocked_by_approvals = 이 풀 리퀘스트는 충분히 승인되지 않았습니다. %d/%d 승인됨.
|
||||
settings.event_pull_request_approvals = 풀 리퀘스트 승인
|
||||
pulls.blocked_by_official_review_requests = 이 풀 리퀘스트는 공식 검토자에 의한 승인이 부족하여 차단되었습니다.
|
||||
watch_guest_user = 이 저장소를 주시하려면 로그인 해야합니다.
|
||||
issues.closed_by_fake = %[2]s님이 %[1]s에 닫음
|
||||
issues.new.closed_projects = 닫힌 프로젝트
|
||||
pulls.merged_by_fake = %[2]s님이 %[1]s에 머지함
|
||||
issues.closed_by = <a href="%[2]s">%[3]s</a>님이 %[1]s에 닫음
|
||||
issues.closed_at = `<a id="%[1]s" href="#%[1]s">%[2]s</a>`에 이 이슈를 닫음
|
||||
issues.filter_milestone_closed = 닫힌 마일스톤
|
||||
issues.opened_by_fake = %[2]s님이 %[1]s에 열음
|
||||
|
||||
|
||||
|
||||
|
@ -1307,7 +1322,7 @@ settings.update_settings=설정 업데이트
|
|||
settings.update_setting_success=조직 설정이 변경되었습니다.
|
||||
settings.update_avatar_success=조직의 아바타가 갱신되었습니다.
|
||||
settings.delete=조직 삭제
|
||||
settings.delete_account=이 조직을 삭제합니다.
|
||||
settings.delete_account=이 조직을 삭제하기
|
||||
settings.confirm_delete_account=삭제 승인
|
||||
settings.delete_org_title=조직 삭제
|
||||
settings.delete_org_desc=이 조직이 영구히 삭제됩니다. 계속 하시겠습니까?
|
||||
|
@ -1330,7 +1345,7 @@ teams.join=가입
|
|||
teams.leave=탈퇴
|
||||
teams.read_access=읽음
|
||||
teams.admin_access=관리자 액세스
|
||||
teams.no_desc=이 팀은 설명이 없습니다.
|
||||
teams.no_desc=이 팀은 설명이 없음
|
||||
teams.settings=설정
|
||||
teams.members=팀 구성원
|
||||
teams.update_settings=설정 업데이트
|
||||
|
@ -1402,7 +1417,7 @@ users.admin=관리자
|
|||
users.repos=저장소
|
||||
users.created=작성일
|
||||
users.last_login=마지막 로그인
|
||||
users.never_login=로그인 한 적이 없습니다.
|
||||
users.never_login=로그인 한 적이 없음
|
||||
users.send_register_notify=사용자 등록 알림 전송
|
||||
users.edit=수정하기
|
||||
users.auth_source=인증 소스
|
||||
|
@ -1412,7 +1427,7 @@ users.password_helper=비밀번호를 비워두시면 변경하지 않고 유지
|
|||
users.update_profile_success=사용자 계정이 갱신되었습니다.
|
||||
users.edit_account=사용자 계정 편집
|
||||
users.max_repo_creation_desc=(-1을 입력하면 전역 설정된 기본 제한을 따릅니다.)
|
||||
users.is_activated=사용자 계정이 활성화 되었습니다.
|
||||
users.is_activated=사용자 계정이 활성화 되었음
|
||||
users.prohibit_login=로그인 비활성화
|
||||
users.is_admin=관리자
|
||||
users.allow_git_hook=Git 훅 생성 허용
|
||||
|
@ -1496,7 +1511,7 @@ auths.tips=도움말
|
|||
auths.tips.oauth2.general=OAuth2 인증
|
||||
auths.tip.oauth2_provider=OAuth2 프로바이더
|
||||
auths.edit=인증 소스 편집
|
||||
auths.activated=인증 소스가 활성화 되었습니다.
|
||||
auths.activated=인증 소스가 활성화 되었음
|
||||
auths.update_success=인증 소스가 갱신되었습니다.
|
||||
auths.update=인증 소스 갱신
|
||||
auths.delete=인증 소스 삭제
|
||||
|
@ -1556,7 +1571,7 @@ config.default_allow_create_organization=기본적으로 조직 생성을 허용
|
|||
config.enable_timetracking=타임 트래킹 활성화
|
||||
config.default_enable_timetracking=기본 타임 트래킹 활성화
|
||||
config.default_allow_only_contributors_to_track_time=기여자 트랙 타임만
|
||||
config.no_reply_address=답변 받지 않을 이메일 주소
|
||||
config.no_reply_address=가려진 이메일 도메인
|
||||
config.default_enable_dependencies=기본적으로 이슈 종속성을 활성화
|
||||
|
||||
config.webhook_config=웹훅 설정
|
||||
|
@ -1639,14 +1654,15 @@ notices.desc=설명
|
|||
notices.op=일.
|
||||
notices.delete_success=시스템 알림이 삭제되었습니다.
|
||||
users.allow_git_hook_tooltip = Git 훅은 Forgejo가 실행중인 OS 유저로 실행되며 같은 수준의 권한을 갖습니다. 결과적으로, Git 훅 사용권한이 있는 사용자는 Forgejo에서 사용하는 데이터베이스를 포함한 모든 저장소에 접근하거나 수정할 수 있습니다. 궁극적으로 이러한 사용자들은 Forgejo의 관리자 권한을 획득할 수 있습니다.
|
||||
emails.primary = 대표
|
||||
|
||||
|
||||
[action]
|
||||
create_repo=저장소를 만들었습니다. <a href="%s">%s</a>
|
||||
rename_repo=<code>%[1]s에서</code>에서 <a href="%[2]s"> %[3]s</a>으로 저장소 이름을 바꾸었습니다.
|
||||
transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송되었습니다.
|
||||
rename_repo=저장소 이름을 <code>%[1]s에서</code>에서 <a href="%[2]s"> %[3]s</a>으로 변경함
|
||||
transfer_repo=저장소가 <code>%s</code>에서 <a href="%s">%s</a>로 이동됨
|
||||
compare_commits=%d 커밋들 비교
|
||||
watched_repo = <a href="%[1]s">%[2]s</a>에대한 감시를 시작합니다
|
||||
watched_repo = <a href="%[1]s">%[2]s</a>에대한 주시를 시작함
|
||||
|
||||
[tool]
|
||||
now=현재
|
||||
|
@ -1685,12 +1701,12 @@ mark_as_unread=읽지 않음으로 표시
|
|||
mark_all_as_read=모두 읽음으로 표시
|
||||
subscriptions = 구독된 알림
|
||||
no_subscriptions = 알림이 없음
|
||||
watching = 감시
|
||||
watching = 주시중
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=서명 추출에 실패
|
||||
error.generate_hash=커밋의 해시 생성에 실패
|
||||
error.not_signed_commit=서명되지 않은 커밋입니다.
|
||||
error.not_signed_commit=서명되지 않은 커밋
|
||||
|
||||
[units]
|
||||
error.no_unit_allowed_repo=이 저장소의 어떤 섹션에도 접근할 수 없습니다.
|
||||
|
|
|
@ -146,10 +146,18 @@ filter = Filtro
|
|||
filter.clear = Limpar filtros
|
||||
filter.is_archived = Arquivado
|
||||
filter.public = Público
|
||||
filter.is_template = Modelo
|
||||
filter.is_template = Modelos
|
||||
filter.private = Privado
|
||||
invalid_data = Dados inválidos: %v
|
||||
more_items = Mais itens
|
||||
filter.is_fork = Forks
|
||||
filter.is_mirror = Espelhos
|
||||
toggle_menu = Alternar menu
|
||||
filter.not_archived = Não arquivado
|
||||
filter.not_fork = Sem forks
|
||||
filter.not_mirror = Sem espelhos
|
||||
filter.not_template = Sem modelos
|
||||
copy_generic = Copiar para área de transferência
|
||||
|
||||
[aria]
|
||||
navbar=Barra de navegação
|
||||
|
@ -296,7 +304,7 @@ invalid_db_setting=Configuração de banco de dados está inválida: %v
|
|||
invalid_db_table=A tabela "%s" do banco de dados é inválida: %v
|
||||
invalid_repo_path=A raiz do repositório está inválida: %v
|
||||
invalid_app_data_path=O caminho dos dados do aplicativo é inválido: %v
|
||||
run_user_not_match=O nome de usuário 'Executar como' não é o nome de usuário atual: %s -> %s
|
||||
run_user_not_match=
|
||||
internal_token_failed=Falha ao gerar o token interno: %v
|
||||
secret_key_failed=Falha ao gerar a chave secreta: %v
|
||||
save_config_failed=Falha ao salvar a configuração: %v
|
||||
|
@ -306,10 +314,10 @@ default_keep_email_private=Ocultar endereços de e-mail por padrão
|
|||
default_keep_email_private_popup=Ocultar endereços de e-mail de novas contas de usuário por padrão.
|
||||
default_allow_create_organization=Permitir a criação de organizações
|
||||
default_allow_create_organization_popup=Permitir que novas contas de usuários criem organizações por padrão.
|
||||
default_enable_timetracking=Habilitar o Cronômetro por Padrão
|
||||
default_enable_timetracking=Habilitar o cronômetro por padrão
|
||||
default_enable_timetracking_popup=Habilitar o cronômetro para novos repositórios por padrão.
|
||||
no_reply_address=Domínio de e-mail oculto
|
||||
no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'.
|
||||
no_reply_address_helper=Nome de domínio para usuários com endereço de e-mail oculto. Por exemplo, o nome de usuário "joe" será registrado no Git como "joe@noreply.example.org" se o domínio de e-mail oculto estiver definido como "noreply.example.org".
|
||||
password_algorithm=Algoritmo de hash de senhas
|
||||
invalid_password_algorithm=Algoritmo de hash de senha inválido
|
||||
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O algoritmo argon2 é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas com menos recursos.
|
||||
|
@ -318,6 +326,8 @@ env_config_keys=Configuração do ambiente
|
|||
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu arquivo de configuração:
|
||||
allow_dots_in_usernames = Permitir pontos em nomes de usuário. Esta opção não afeta contas já existentes.
|
||||
enable_update_checker_helper_forgejo = Confere periodicamente um registro TXT de DNS em release.forgejo.org para verificar se há uma nova versão do Forgejo disponível.
|
||||
smtp_from_invalid = O endereço "Enviar e-mail como" é inválido
|
||||
config_location_hint = Essas opções de configuração serão salvas em:
|
||||
|
||||
[home]
|
||||
uname_holder=Usuário ou e-mail
|
||||
|
@ -369,6 +379,8 @@ relevant_repositories_tooltip=Repositórios que são forks ou que não possuem t
|
|||
relevant_repositories=Apenas repositórios relevantes estão sendo mostrados, <a href="%s">mostrar resultados não filtrados</a>.
|
||||
stars_one = %d estrela
|
||||
stars_few = %d estrelas
|
||||
forks_one = %d fork
|
||||
forks_few = %d forks
|
||||
|
||||
[auth]
|
||||
create_new_account=Cadastrar conta
|
||||
|
@ -388,7 +400,7 @@ allow_password_change=Exigir que o usuário redefina a senha (recomendado)
|
|||
reset_password_mail_sent_prompt=Um e-mail de confirmação foi enviado para <b>%s</b>. Por favor, verifique sua caixa de entrada dentro do(s) próximo(s) %s para concluir o processo de recuperação de conta.
|
||||
active_your_account=Ativar sua conta
|
||||
account_activated=Conta foi ativada
|
||||
prohibit_login=Acesso proibido
|
||||
prohibit_login=É proibido fazer login
|
||||
prohibit_login_desc=Sua conta está proibida de fazer login, entre em contato com o administrador do site.
|
||||
resent_limit_prompt=Você já solicitou recentemente um e-mail de ativação. Por favor, aguarde 3 minutos e tente novamente.
|
||||
has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (<b>%s</b>). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo.
|
||||
|
@ -414,8 +426,8 @@ tab_openid=OpenID
|
|||
oauth_signup_tab=Cadastrar nova conta
|
||||
oauth_signup_title=Completar Nova Conta
|
||||
oauth_signup_submit=Completar conta
|
||||
oauth_signin_tab=Vincular à uma conta existente
|
||||
oauth_signin_title=Acesse com uma conta vinculada
|
||||
oauth_signin_tab=Vincular a uma conta existente
|
||||
oauth_signin_title=Faça login para autorizar a conta vinculada
|
||||
oauth_signin_submit=Vincular conta
|
||||
oauth.signin.error=Ocorreu um erro durante o processamento do pedido de autorização. Se este erro persistir, contate o administrador.
|
||||
oauth.signin.error.access_denied=O pedido de autorização foi negado.
|
||||
|
@ -445,6 +457,7 @@ last_admin = Não é possível remover o último administrador. Deve haver ao me
|
|||
change_unconfirmed_email = Se você colocou o endereço de e-mail errado durante o cadastro, você pode alterá-lo abaixo, e uma confirmação será enviada para o novo endereço.
|
||||
remember_me.compromised = O token de login foi invalidado, o que pode indicar que a sua conta foi comprometida. Verifique se não há atividades suspeitas em sua conta.
|
||||
tab_signin = Iniciar sessão
|
||||
tab_signup = Inscrever-se
|
||||
|
||||
[mail]
|
||||
view_it_on=Veja em %s
|
||||
|
@ -546,8 +559,8 @@ SSPISeparatorReplacement=Separador
|
|||
SSPIDefaultLanguage=Idioma padrão
|
||||
|
||||
require_error=` não pode estar em branco.`
|
||||
alpha_dash_error=` deve conter somente alfanumérico, caracteres de traço ('-') e sublinhado ('_').`
|
||||
alpha_dash_dot_error=` deve conter somente alfanumérico, caracteres de traço ('-'), sublinhado ('_') e ponto ('. ') .`
|
||||
alpha_dash_error=`deve conter apenas caracteres alfanuméricos, traço ("-") e sublinhado ("_").`
|
||||
alpha_dash_dot_error=`deve conter apenas caracteres alfanuméricos, traço ("-"), sublinhado ("_") e ponto (".").`
|
||||
git_ref_name_error=` deve ser um nome de referência Git válido.`
|
||||
size_error=`deve ser do tamanho %s.`
|
||||
min_size_error=` deve conter pelo menos %s caracteres.`
|
||||
|
@ -593,7 +606,7 @@ enterred_invalid_owner_name=O nome do novo proprietário não é válido.
|
|||
enterred_invalid_password=A senha que você digitou está incorreta.
|
||||
user_not_exist=O usuário não existe.
|
||||
team_not_exist=A equipe não existe.
|
||||
last_org_owner=Você não pode remover o último usuário do time 'proprietários'. Deve haver pelo menos um proprietário em uma organização.
|
||||
last_org_owner=Você não pode remover o último usuário da equipe de “proprietários”. Deve haver pelo menos um proprietário para uma organização.
|
||||
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipe.
|
||||
duplicate_invite_to_team=O usuário já foi convidado para se juntar da equipe.
|
||||
organization_leave_success=Você saiu da organização %s com sucesso.
|
||||
|
@ -606,15 +619,25 @@ unable_verify_ssh_key=Não foi possível validar a chave SSH. Certifique-se de q
|
|||
auth_failed=Autenticação falhou: %v
|
||||
|
||||
still_own_repo=A sua conta possui um ou mais repositórios. Exclua ou transfira-os antes de excluir a conta.
|
||||
still_has_org=Sua conta é um membro de uma ou mais organizações, deixe-as primeiro.
|
||||
still_has_org=Sua conta é membro de uma ou mais organizações, saia delas primeiro.
|
||||
still_own_packages=Sua conta possui um ou mais pacotes, exclua-os primeiro.
|
||||
org_still_own_repo=Esta organização ainda possui repositórios, exclua ou transfira-os primeiro.
|
||||
org_still_own_packages=Esta organização ainda possui pacotes, exclua-os primeiro.
|
||||
org_still_own_repo=Esta organização ainda possui um ou mais repositórios. Exclua-os ou transfira-os primeiro.
|
||||
org_still_own_packages=Esta organização ainda possui um ou mais pacotes. Exclua-os primeiro.
|
||||
|
||||
target_branch_not_exist=O branch de destino não existe.
|
||||
username_error_no_dots = ` pode conter apenas caracteres alfanuméricos ("0-9, "a-z", "A-Z"), hífens ("-") e traços inferiores ("_"). Não é permitido conter caracteres não alfanuméricos no início ou fim. Caracteres não alfanuméricos consecutivos também não são permitidos.`
|
||||
admin_cannot_delete_self = Você não pode excluir a si mesmo quando você é um administrador. Por favor, remova suas permissões de administrador primeiro.
|
||||
AccessToken = Token de acesso
|
||||
To = Nome do Branch
|
||||
Website = Site
|
||||
Pronouns = Pronomes
|
||||
Biography = Biografia
|
||||
Location = Localização
|
||||
unsupported_login_type = O tipo de login não é compatível para excluir conta.
|
||||
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.
|
||||
|
||||
|
||||
[user]
|
||||
|
@ -649,6 +672,7 @@ follow_blocked_user = Você não pode seguir este usuário, pois você o bloqueo
|
|||
block_user.detail_3 = Este usuário não poderá adicionar-lhe como colaborador e você também não poderá adicioná-lo como colaborador.
|
||||
block_user.detail = Por favor, entenda que se você bloquear este usuário, outras ações serão tomadas. Tais como:
|
||||
followers_one = %d seguidor
|
||||
following_one = %d seguindo
|
||||
|
||||
[settings]
|
||||
profile=Perfil
|
||||
|
@ -660,7 +684,7 @@ avatar=Avatar
|
|||
ssh_gpg_keys=Chaves SSH / GPG
|
||||
social=Contas sociais
|
||||
applications=Aplicativos
|
||||
orgs=Gerenciar organizações
|
||||
orgs=Organizações
|
||||
repos=Repositórios
|
||||
delete=Excluir conta
|
||||
twofa=Autenticação de dois fatores
|
||||
|
@ -703,7 +727,7 @@ comment_type_group_branch=Branch
|
|||
comment_type_group_time_tracking=Contagem de tempo
|
||||
comment_type_group_deadline=Prazo final
|
||||
comment_type_group_dependency=Dependência
|
||||
comment_type_group_lock=Status de Bloqueio
|
||||
comment_type_group_lock=Status de bloqueio
|
||||
comment_type_group_review_request=Revisar solicitação
|
||||
comment_type_group_pull_request_push=Commits adicionados
|
||||
comment_type_group_project=Projeto
|
||||
|
@ -713,11 +737,11 @@ privacy=Privacidade
|
|||
keep_activity_private=Ocultar atividade da página de perfil
|
||||
keep_activity_private_popup=A sua atividade estará visível apenas para você e os admnistradores
|
||||
|
||||
lookup_avatar_by_mail=Procurar o avatar do endereço de e-mail
|
||||
federated_avatar_lookup=Busca de avatar federativo
|
||||
lookup_avatar_by_mail=Pesquisar avatar por endereço de e-mail
|
||||
federated_avatar_lookup=Pesquisa de avatar federado
|
||||
enable_custom_avatar=Usar avatar personalizado
|
||||
choose_new_avatar=Escolha um novo avatar
|
||||
update_avatar=Atualizar o avatar
|
||||
update_avatar=Atualizar avatar
|
||||
delete_current_avatar=Excluir avatar atual
|
||||
uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem.
|
||||
uploaded_avatar_is_too_big=O tamanho do arquivo enviado (%d KiB) excede o tamanho máximo permitido (%d KiB).
|
||||
|
@ -734,15 +758,15 @@ password_change_disabled=Contas não-locais não podem alterar sua senha atravé
|
|||
|
||||
emails=Endereços de e-mail
|
||||
manage_emails=Gerenciar endereços de e-mail
|
||||
manage_themes=Selecione o tema padrão
|
||||
manage_openid=Gerenciar endereços OpenID
|
||||
manage_themes=Tema Padrão
|
||||
manage_openid=Endereços OpenID
|
||||
email_desc=Seu endereço de e-mail principal será usado para notificações, recuperação de senha e, desde que não esteja oculto, para operações do Git baseadas na Web.
|
||||
theme_desc=Este será o seu tema padrão em todo o site.
|
||||
primary=Principal
|
||||
activated=Ativado
|
||||
requires_activation=Requer ativação
|
||||
primary_email=Tornar Principal
|
||||
activate_email=Enviar Ativação
|
||||
primary_email=Tornar primário
|
||||
activate_email=Enviar ativação
|
||||
activations_pending=Ativações pendentes
|
||||
can_not_add_email_activations_pending=Há uma ativação pendente, tente novamente em alguns minutos se quiser adicionar um novo e-mail.
|
||||
delete_email=Remover
|
||||
|
@ -770,16 +794,16 @@ manage_ssh_keys=Gerenciar chaves SSH
|
|||
manage_ssh_principals=Gerenciar Nomes Principais do certificado SSH
|
||||
manage_gpg_keys=Gerenciar chaves GPG
|
||||
add_key=Adicionar chave
|
||||
ssh_desc=Estas chaves SSH públicas estão associados a sua conta. Chaves privadas correspondentes permitam acesso completo a seus repositórios.
|
||||
ssh_desc=Essas chaves SSH públicas estão associadas à sua conta. As chaves privadas correspondentes permitem acesso total aos seus repositórios. As chaves SSH que foram verificadas podem ser usadas para verificar commits do Git assinados por SSH.
|
||||
principal_desc=Estes nomes principais do certificado SSH estão associados à sua conta e permitem acesso total aos seus repositórios.
|
||||
gpg_desc=Essas chaves GPG públicas estão associadas à sua conta. Mantenha suas chaves privadas seguras, pois elas permitem que os commits sejam verificados.
|
||||
gpg_desc=Essas chaves GPG públicas são associadas à sua conta e usadas para verificar seus commits. Mantenha suas chaves privadas seguras, pois elas permitem assinar commits com sua identidade.
|
||||
ssh_helper=<strong>Precisa de ajuda?</strong> Dê uma olhada no guia do GitHub para <a href="%s">criar suas próprias chaves SSH</a> ou resolver <a href="%s">problemas comuns</a> que você pode ter usando SSH.
|
||||
gpg_helper=<strong>Precisa de ajuda?</strong> Dê uma olhada no guia do GitHub <a href="%s">sobre GPG</a>.
|
||||
add_new_key=Adicionar chave SSH
|
||||
add_new_gpg_key=Adicionar chave GPG
|
||||
key_content_ssh_placeholder=Começa com "ssh-ed25519", "ssh-rsa", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521", "sk-ecdsa-sha2-nistp256@openssh.com" ou "sk-ssh-ed25519@openssh.com"
|
||||
key_content_gpg_placeholder=Começa com "-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
add_new_principal=Adicionar Nome Principal
|
||||
add_new_principal=Adicionar principal
|
||||
ssh_key_been_used=Esta chave SSH já foi adicionada ao servidor.
|
||||
ssh_key_name_used=Uma chave SSH com o mesmo nome já existe em sua conta.
|
||||
ssh_principal_been_used=Este nome principal já foi adicionada ao servidor.
|
||||
|
@ -838,7 +862,7 @@ token_state_desc=Este token tem sido utilizado nos últimos 7 dias
|
|||
principal_state_desc=Este nome principal foi utilizado nos últimos 7 dias
|
||||
show_openid=Mostrar no perfil
|
||||
hide_openid=Ocultar no perfil
|
||||
ssh_disabled=SSH desabilitado
|
||||
ssh_disabled=SSH está desativado
|
||||
ssh_signonly=O SSH está desativado no momento, portanto, essas chaves são usadas apenas para verificação de assinatura de confirmação.
|
||||
ssh_externally_managed=Esta chave SSH para este usuário é gerenciada externamente
|
||||
manage_social=Gerenciar contas sociais associadas
|
||||
|
@ -846,7 +870,7 @@ social_desc=Essas contas sociais podem ser usadas para fazer login em sua conta.
|
|||
unbind=Desvincular
|
||||
unbind_success=A conta social foi removida com sucesso.
|
||||
|
||||
manage_access_token=Gerenciar tokens de acesso
|
||||
manage_access_token=Tokens de acesso
|
||||
generate_new_token=Gerar novo token
|
||||
tokens_desc=Esses tokens concedem acesso à sua conta usando a API do Forgejo.
|
||||
token_name=Nome do token
|
||||
|
@ -880,12 +904,12 @@ create_oauth2_application_button=Criar aplicativo
|
|||
create_oauth2_application_success=Você criou um aplicativo OAuth2 com sucesso.
|
||||
update_oauth2_application_success=Você atualizou o aplicativo OAuth2 com sucesso.
|
||||
oauth2_application_name=Nome do aplicativo
|
||||
oauth2_confidential_client=Cliente Confidencial. Selecione para aplicativos que mantêm a confidencialidade do segredo, como aplicativos web. Não selecione para aplicativos nativos, incluindo aplicativos desktop e celulares.
|
||||
oauth2_confidential_client=Cliente confidencial. Selecione para aplicativos que mantêm o segredo confidencial, como aplicativos da web. Não selecione aplicativos nativos, incluindo aplicativos de desktop e móveis.
|
||||
oauth2_redirect_uris=URIs de redirecionamento. Por favor use uma nova linha para cada URI.
|
||||
save_application=Salvar
|
||||
oauth2_client_id=Client ID
|
||||
oauth2_client_secret=Client Secret
|
||||
oauth2_regenerate_secret=Gerar novamente o Client Secret
|
||||
oauth2_client_secret=Segredo do cliente
|
||||
oauth2_regenerate_secret=Regenerar segredo
|
||||
oauth2_regenerate_secret_hint=Perdeu seu Client Secret?
|
||||
oauth2_client_secret_hint=O segredo não será exibido novamente depois que você sair ou atualizar esta página. Certifique-se de que você o salvou.
|
||||
oauth2_application_edit=Editar
|
||||
|
@ -967,6 +991,15 @@ blocked_users_none = Nenhum usuário bloqueado.
|
|||
access_token_desc = As permissões selecionadas para o token limitam o acesso apenas às <a %s>rotas da API</a> correspondentes. Veja a <a %s>documentação</a> para mais informações.
|
||||
webauthn_alternative_tip = Você talvez queira configurar um método adicional de autenticação.
|
||||
change_password = Alterar senha
|
||||
hints = Dicas
|
||||
pronouns = Pronomes
|
||||
pronouns_custom = Personalizado
|
||||
pronouns_unspecified = Não especificado
|
||||
language.title = Idioma padrão
|
||||
additional_repo_units_hint = Sugira habilitar unidades de repositório adicionais
|
||||
additional_repo_units_hint_description = Exiba um botão "Adicionar mais unidades..." para repositórios que não possuem todas as unidades disponíveis habilitadas.
|
||||
update_hints = Dicas de atualização
|
||||
update_hints_success = As dicas foram atualizadas.
|
||||
|
||||
[repo]
|
||||
owner=Proprietário
|
||||
|
@ -1126,7 +1159,7 @@ migrate.migrating=Migrando a partir de <b>%s</b> ...
|
|||
migrate.migrating_failed=Migração a partir de <b>%s</b> falhou.
|
||||
migrate.migrating_failed.error=Falha ao migrar: %s
|
||||
migrate.migrating_failed_no_addr=A migração falhou.
|
||||
migrate.github.description=Migrar dados de github.com ou de outras instâncias do GitHub.
|
||||
migrate.github.description=Migre dados do servidor github.com ou GitHub Enterprise.
|
||||
migrate.git.description=Migrar um repositório somente de qualquer serviço Git.
|
||||
migrate.gitlab.description=Migrar dados de gitlab.com ou de outras instâncias do GitLab.
|
||||
migrate.gitea.description=Migrar dados de gitea.com ou de outras instâncias do Gitea/Forgejo.
|
||||
|
@ -2602,6 +2635,8 @@ settings.units.units = Funcionalidades
|
|||
vendored = Externo
|
||||
issues.num_participants_one = %d participante
|
||||
issues.archived_label_description = (arquivada) %s
|
||||
n_branch_few = %s branches
|
||||
stars = Favoritos
|
||||
|
||||
[graphs]
|
||||
|
||||
|
@ -3615,4 +3650,9 @@ fuzzy_tooltip = Inclui resultados que se aproximam dos termos de busca
|
|||
match = Correspondente
|
||||
match_tooltip = Inclui apenas os resultados que correspondem exatamente aos termos de busca
|
||||
repo_kind = Buscar repositórios...
|
||||
type_tooltip = Tipo de busca
|
||||
type_tooltip = Tipo de busca
|
||||
code_search_by_git_grep = Os resultados atuais da pesquisa de código são fornecidos por "git grep". Pode haver melhores resultados se o administrador do site ativar o indexador de código.
|
||||
branch_kind = Pesquisar branches…
|
||||
commit_kind = Pesquisar commits…
|
||||
runner_kind = Pesquisar runners...
|
||||
code_search_unavailable = A pesquisa de código não está disponível no momento. Entre em contato com o administrador do site.
|
|
@ -142,19 +142,19 @@ confirm_delete_selected=Confirma a exclusão de todos os itens marcados?
|
|||
|
||||
name=Nome
|
||||
value=Valor
|
||||
filter.is_fork = Derivado
|
||||
filter.is_mirror = Replicado
|
||||
filter.is_template = Modelo
|
||||
filter.is_fork = Derivações
|
||||
filter.is_mirror = Réplicas
|
||||
filter.is_template = Modelos
|
||||
filter.public = Público
|
||||
filter.not_archived = Não arquivado
|
||||
filter.private = Privado
|
||||
filter.not_fork = Não derivado
|
||||
filter.not_mirror = Não replicado
|
||||
filter.not_fork = Não derivações
|
||||
filter.not_mirror = Não réplicas
|
||||
more_items = Mais itens
|
||||
invalid_data = Dados inválidos: %v
|
||||
filter.clear = Retirar filtros
|
||||
filter.is_archived = Arquivado
|
||||
filter.not_template = Não modelo
|
||||
filter.not_template = Não modelos
|
||||
toggle_menu = Comutar menu
|
||||
filter = Filtro
|
||||
copy_generic = Copiar para a área de transferência
|
||||
|
@ -556,7 +556,7 @@ TreeName=Localização do ficheiro
|
|||
Content=Conteúdo
|
||||
|
||||
SSPISeparatorReplacement=Separador
|
||||
SSPIDefaultLanguage=Idioma predefinido
|
||||
SSPIDefaultLanguage=Idioma padrão
|
||||
|
||||
require_error=` não pode estar em branco.`
|
||||
alpha_dash_error=` deve conter apenas caracteres alfanuméricos, hífen ("-") e sublinhado ("_").`
|
||||
|
@ -685,7 +685,7 @@ avatar=Avatar
|
|||
ssh_gpg_keys=Chaves SSH / GPG
|
||||
social=Contas sociais
|
||||
applications=Aplicações
|
||||
orgs=Gerir organizações
|
||||
orgs=Organizações
|
||||
repos=Repositórios
|
||||
delete=Eliminar a conta
|
||||
twofa=Autenticação em dois passos (TOTP)
|
||||
|
@ -759,8 +759,8 @@ password_change_disabled=Os utilizadores não-locais não podem alterar a sua se
|
|||
|
||||
emails=Endereços de email
|
||||
manage_emails=Gerir endereços de email
|
||||
manage_themes=Escolher o tema padrão
|
||||
manage_openid=Gerir endereços OpenID
|
||||
manage_themes=Tema padrão
|
||||
manage_openid=Endereços OpenID
|
||||
email_desc=O seu endereço de email principal irá ser usado para notificações, recuperação de senha e, desde que não esteja oculto, operações Git baseados na web.
|
||||
theme_desc=Este será o seu tema padrão em todo o sítio.
|
||||
primary=Principal
|
||||
|
@ -804,7 +804,7 @@ add_new_key=Adicionar chave SSH
|
|||
add_new_gpg_key=Adicionar chave GPG
|
||||
key_content_ssh_placeholder=Começa com "ssh-ed25519", "ssh-rsa", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521", "sk-ecdsa-sha2-nistp256@openssh.com", ou "sk-ssh-ed25519@openssh.com"
|
||||
key_content_gpg_placeholder=Começa com "-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
add_new_principal=Adicional Protagonista
|
||||
add_new_principal=Adicionar protagonista
|
||||
ssh_key_been_used=Esta chave SSH já tinha sido adicionada ao servidor.
|
||||
ssh_key_name_used=Já existe uma chave SSH com o mesmo nome na sua conta.
|
||||
ssh_principal_been_used=Este protagonista já tinha sido adicionado ao servidor.
|
||||
|
@ -871,7 +871,7 @@ social_desc=Estas contas sociais podem ser usadas para iniciar sessão na sua co
|
|||
unbind=Desvincular
|
||||
unbind_success=A conta social foi removida com sucesso.
|
||||
|
||||
manage_access_token=Gerir códigos de acesso
|
||||
manage_access_token=Códigos de acesso
|
||||
generate_new_token=Gerar um novo código
|
||||
tokens_desc=Esses códigos concedem acesso à sua conta usando a API do Forgejo.
|
||||
token_name=Nome do código
|
||||
|
@ -953,7 +953,7 @@ webauthn_delete_key_desc=Se remover uma chave de segurança, deixará de poder u
|
|||
webauthn_key_loss_warning=Se perder as suas chaves de segurança, perderá acesso à sua conta.
|
||||
webauthn_alternative_tip=Poderá querer configurar um método de autenticação adicional.
|
||||
|
||||
manage_account_links=Gerir contas vinculadas
|
||||
manage_account_links=Contas vinculadas
|
||||
manage_account_links_desc=Estas contas externas estão vinculadas à sua conta do Forgejo.
|
||||
account_links_not_available=Neste momento não existem contas externas vinculadas à sua conta do Forgejo.
|
||||
link_account=Vincular conta
|
||||
|
@ -986,7 +986,7 @@ visibility.limited=Limitada
|
|||
visibility.limited_tooltip=Visível apenas para utilizadores autenticados
|
||||
visibility.private=Privada
|
||||
visibility.private_tooltip=Visível apenas para membros das organizações a que se associou
|
||||
additional_repo_units_hint = Encorajar a habilitação de unidades do repositório adicionais
|
||||
additional_repo_units_hint = Sugere a habilitação de unidades do repositório adicionais
|
||||
update_hints = Modificar sugestões
|
||||
change_password = Modificar a senha
|
||||
pronouns = Pronomes
|
||||
|
@ -1000,6 +1000,7 @@ additional_repo_units_hint_description = Mostrar um botão "Adicionar mais unida
|
|||
update_hints_success = As sugestões foram modificadas.
|
||||
blocked_users_none = Não há utilizadores bloqueados.
|
||||
user_unblock_success = O utilizador foi desbloqueado com sucesso.
|
||||
language.title = Idioma predefinido
|
||||
|
||||
[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>.
|
||||
|
@ -1171,7 +1172,7 @@ migrate.migrating=Migrando a partir de <b>%s</b> ...
|
|||
migrate.migrating_failed=A migração de <b>%s</b> falhou.
|
||||
migrate.migrating_failed.error=Falhou a migração: %s
|
||||
migrate.migrating_failed_no_addr=A migração falhou.
|
||||
migrate.github.description=Migrar dados de github.com ou de outras instâncias do GitHub.
|
||||
migrate.github.description=Migrar dados do github.com ou do GitHub Enterprise server.
|
||||
migrate.git.description=Migrar um repositório somente de qualquer serviço Git.
|
||||
migrate.gitlab.description=Migrar dados de gitlab.com ou de outras instâncias do GitLab.
|
||||
migrate.gitea.description=Migrar dados de gitea.com ou de outras instâncias do Gitea/Forgejo.
|
||||
|
@ -1258,9 +1259,9 @@ ambiguous_character=`%[1]c [U+%04[1]X] pode confundir-se com %[2]c [U+%04[2]X]`
|
|||
escape_control_characters=Revelar
|
||||
unescape_control_characters=Esconder
|
||||
file_copy_permalink=Copiar ligação permanente
|
||||
view_git_blame=Ver Git Blame
|
||||
video_not_supported_in_browser=O seu navegador não suporta a etiqueta 'video' do HTML5.
|
||||
audio_not_supported_in_browser=O seu navegador não suporta a etiqueta 'audio' do HTML5.
|
||||
view_git_blame=Ver git blame
|
||||
video_not_supported_in_browser=O seu navegador não suporta a etiqueta "video" do HTML5.
|
||||
audio_not_supported_in_browser=O seu navegador não suporta a etiqueta "audio" do HTML5.
|
||||
stored_lfs=Armazenado com Git LFS
|
||||
symbolic_link=Ligação simbólica
|
||||
executable_file=Ficheiro executável
|
||||
|
@ -1296,12 +1297,12 @@ editor.delete_this_file=Eliminar ficheiro
|
|||
editor.must_have_write_access=Tem que ter permissões de escrita para fazer ou propor modificações neste ficheiro.
|
||||
editor.file_delete_success=O ficheiro "%s" foi eliminado.
|
||||
editor.name_your_file=Nomeie o seu ficheiro…
|
||||
editor.filename_help=Adicione uma pasta escrevendo o nome dessa pasta seguido de uma barra('/'). Remova uma pasta carregando na tecla de apagar ('←') no início do campo.
|
||||
editor.filename_help=Adicione uma pasta escrevendo o nome dessa pasta seguido de uma barra("/"). Remova uma pasta carregando na tecla de apagar ("←") no início do campo.
|
||||
editor.or=ou
|
||||
editor.cancel_lower=Cancelar
|
||||
editor.commit_signed_changes=Cometer modificações assinadas
|
||||
editor.commit_changes=Cometer modificações
|
||||
editor.add_tmpl=Adicionar '<filename>'
|
||||
editor.add_tmpl=Adicionar "<filename>"
|
||||
editor.add=Adicionar %s
|
||||
editor.update=Modificar %s
|
||||
editor.delete=Eliminar %s
|
||||
|
@ -1327,7 +1328,7 @@ editor.file_is_a_symlink=`"%s" é uma ligação simbólica. Ligações simbólic
|
|||
editor.filename_is_a_directory=O nome de ficheiro "%s" já está a ser usado como um nome de pasta neste repositório.
|
||||
editor.file_editing_no_longer_exists=O ficheiro que está a ser editado, "%s", já não existe neste repositório.
|
||||
editor.file_deleting_no_longer_exists=O ficheiro que está a ser eliminado, "%s", já não existe neste repositório.
|
||||
editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou clique em <strong>Cometer novamente</strong> para escrever por cima.
|
||||
editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou clique em <strong>Cometer modificações novamente</strong> para escrever por cima.
|
||||
editor.file_already_exists=Já existe um ficheiro com o nome "%s" neste repositório.
|
||||
editor.commit_empty_file_header=Cometer um ficheiro vazio
|
||||
editor.commit_empty_file_text=O ficheiro que está prestes a cometer está vazio. Quer continuar?
|
||||
|
@ -1398,12 +1399,12 @@ projects.deletion_desc=Eliminar um planeamento remove-o de todas as questões re
|
|||
projects.deletion_success=O planeamento foi eliminado.
|
||||
projects.edit=Editar planeamentos
|
||||
projects.edit_subheader=Planeamentos organizam questões e acompanham o progresso.
|
||||
projects.modify=Modificar planeamento
|
||||
projects.modify=Editar planeamento
|
||||
projects.edit_success=O planeamento "%s" foi modificado.
|
||||
projects.type.none=Nenhum
|
||||
projects.type.basic_kanban=Kanban básico
|
||||
projects.type.bug_triage=Triagem de erros
|
||||
projects.template.desc=Modelo de planeamento
|
||||
projects.template.desc=Modelo
|
||||
projects.template.desc_helper=Escolha um modelo de planeamento para começar
|
||||
projects.type.uncategorized=Sem categoria
|
||||
projects.column.edit=Editar coluna
|
||||
|
@ -1416,7 +1417,7 @@ projects.column.set_default_desc=Definir esta coluna como a predefinida para que
|
|||
projects.column.unset_default=Deixar de ser a predefinida
|
||||
projects.column.unset_default_desc=Faz com que esta coluna deixe de ser a predefinida
|
||||
projects.column.delete=Eliminar coluna
|
||||
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna 'Sem categoria'. Continuar?
|
||||
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
|
||||
projects.column.color=Colorido
|
||||
projects.open=Abrir
|
||||
projects.close=Fechar
|
||||
|
@ -1434,7 +1435,7 @@ issues.filter_reviewers=Filtrar revisor
|
|||
issues.new=Questão nova
|
||||
issues.new.title_empty=O título não pode estar vazio
|
||||
issues.new.labels=Rótulos
|
||||
issues.new.no_label=Sem rótulo
|
||||
issues.new.no_label=Sem rótulos
|
||||
issues.new.clear_labels=Retirar rótulos
|
||||
issues.new.projects=Planeamentos
|
||||
issues.new.clear_projects=Limpar planeamentos
|
||||
|
@ -1464,10 +1465,10 @@ issues.new_label=Novo rótulo
|
|||
issues.new_label_placeholder=Nome do rótulo
|
||||
issues.new_label_desc_placeholder=Descrição
|
||||
issues.create_label=Criar rótulo
|
||||
issues.label_templates.title=Carregar um conjunto predefinido de rótulos
|
||||
issues.label_templates.info=Ainda não existem rótulos. Crie um rótulo com 'Novo rótulo' ou use um conjunto de rótulos predefinido:
|
||||
issues.label_templates.helper=Escolha um conjunto de rótulos
|
||||
issues.label_templates.use=Usar conjunto de rótulos
|
||||
issues.label_templates.title=Carregar uma predefinição de rótulos
|
||||
issues.label_templates.info=Ainda não existem rótulos. Crie um rótulo com "Novo rótulo" ou use uma predefinição de rótulos:
|
||||
issues.label_templates.helper=Escolha uma predefinição de rótulos
|
||||
issues.label_templates.use=Usar predefinição de rótulos
|
||||
issues.label_templates.fail_to_load_file=Falhou ao carregar o ficheiro modelo de rótulos "%s": %v
|
||||
issues.add_label=adicionou o rótulo %s %s
|
||||
issues.add_labels=adicionou os rótulos %s %s
|
||||
|
@ -1602,7 +1603,7 @@ issues.label_title=Nome do rótulo
|
|||
issues.label_description=Descrição do rótulo
|
||||
issues.label_color=Cor do rótulo
|
||||
issues.label_exclusive=Exclusivo
|
||||
issues.label_archive=Rótulo de arquivo
|
||||
issues.label_archive=Arquivar rótulo
|
||||
issues.label_archived_filter=Mostrar rótulos arquivados
|
||||
issues.label_archive_tooltip=Os rótulos arquivados são, por norma, excluídos das sugestões ao pesquisar por rótulo.
|
||||
issues.label_exclusive_desc=Nomeie o rótulo <code>âmbito/item</code> para torná-lo mutuamente exclusivo com outros rótulos do <code>âmbito/</code>.
|
||||
|
@ -1672,7 +1673,7 @@ issues.add_time_sum_to_small=Não foi inserido qualquer tempo.
|
|||
issues.time_spent_total=Total de tempo gasto
|
||||
issues.time_spent_from_all_authors=`Total de tempo gasto: %s`
|
||||
issues.due_date=Data de vencimento
|
||||
issues.invalid_due_date_format=O formato da data de vencimento tem que ser 'aaaa-mm-dd'.
|
||||
issues.invalid_due_date_format=O formato da data de vencimento tem que ser "aaaa-mm-dd".
|
||||
issues.error_modifying_due_date=Falhou a modificação da data de vencimento.
|
||||
issues.error_removing_due_date=Falhou a remoção da data de vencimento.
|
||||
issues.push_commit_1=adicionou %d cometimento %s
|
||||
|
@ -1689,7 +1690,7 @@ issues.due_date_added=adicionou a data de vencimento %s %s
|
|||
issues.due_date_modified=modificou a data de vencimento de %[2]s para %[1]s %[3]s
|
||||
issues.due_date_remove=removeu a data de vencimento %s %s
|
||||
issues.due_date_overdue=Em atraso
|
||||
issues.due_date_invalid=A data de vencimento é inválida ou está fora do intervalo permitido. Por favor, use o formato 'aaaa-mm-dd'.
|
||||
issues.due_date_invalid=A data de vencimento é inválida ou está fora do intervalo permitido. Por favor, use o formato "aaaa-mm-dd".
|
||||
issues.dependency.title=Dependências
|
||||
issues.dependency.issue_no_dependencies=Não estão definidas dependências.
|
||||
issues.dependency.pr_no_dependencies=Não estão definidas dependências.
|
||||
|
@ -1862,9 +1863,9 @@ pulls.unrelated_histories=A integração falhou: O topo da integração e a base
|
|||
pulls.merge_out_of_date=Falhou a integração: Enquanto estava a gerar a integração, a base foi modificada. Dica: Tente de novo.
|
||||
pulls.head_out_of_date=Falhou a integração: Enquanto estava a gerar a integração, o topo foi modificado. Dica: Tente de novo.
|
||||
pulls.has_merged=Falhou: A integração constante do pedido foi executada, não pode integrar novamente nem modificar o ramo alvo.
|
||||
pulls.push_rejected=A integração falhou: O envio foi rejeitado. Reveja os Automatismos do Git neste repositório.
|
||||
pulls.push_rejected=A integração falhou: O envio foi rejeitado. Reveja os automatismos do Git neste repositório.
|
||||
pulls.push_rejected_summary=Mensagem completa de rejeição
|
||||
pulls.push_rejected_no_message=A integração falhou: O envio foi rejeitado mas não houve qualquer mensagem remota.<br>Reveja os Automatismos do Git para este repositório
|
||||
pulls.push_rejected_no_message=A integração falhou: O envio foi rejeitado mas não houve qualquer mensagem remota.<br>Reveja os automatismos do Git para este repositório
|
||||
pulls.open_unmerged_pull_exists=`Não pode executar uma operação de reabertura porque há um pedido de integração pendente (#%d) com propriedades idênticas.`
|
||||
pulls.status_checking=Algumas verificações estão pendentes
|
||||
pulls.status_checks_success=Todas as verificações foram bem sucedidas
|
||||
|
@ -1923,7 +1924,7 @@ milestones.title=Título
|
|||
milestones.desc=Descrição
|
||||
milestones.due_date=Data de vencimento (opcional)
|
||||
milestones.clear=Limpar
|
||||
milestones.invalid_due_date_format=O formato da data de vencimento tem que ser 'aaaa-mm-dd'.
|
||||
milestones.invalid_due_date_format=O formato da data de vencimento tem que ser "aaaa-mm-dd".
|
||||
milestones.create_success=A etapa "%s" foi criada.
|
||||
milestones.edit=Editar etapa
|
||||
milestones.edit_subheader=As etapas organizam as questões e acompanham o progresso.
|
||||
|
@ -1942,7 +1943,7 @@ milestones.filter_sort.least_issues=Menos questões
|
|||
|
||||
signing.will_sign=Este cometimento irá ser assinado com a chave "%s".
|
||||
signing.wont_sign.error=Ocorreu um erro enquanto estava a ser verificado se o cometimento poderia ser assinado.
|
||||
signing.wont_sign.nokey=Não existe qualquer chave disponível para assinar este cometimento.
|
||||
signing.wont_sign.nokey=Esta instância não tem qualquer chave com que se possa assinar este cometimento.
|
||||
signing.wont_sign.never=Os cometimentos nunca são assinados.
|
||||
signing.wont_sign.always=Os cometimentos são sempre assinados.
|
||||
signing.wont_sign.pubkey=O cometimento não será assinado porque não tem uma chave pública associada à sua conta.
|
||||
|
@ -1973,7 +1974,7 @@ wiki.last_commit_info=%s editou esta página %s
|
|||
wiki.edit_page_button=Editar
|
||||
wiki.new_page_button=Nova página
|
||||
wiki.file_revision=Revisão da página
|
||||
wiki.wiki_page_revisions=Revisões da página wiki
|
||||
wiki.wiki_page_revisions=Revisões da página
|
||||
wiki.back_to_wiki=Voltar à página wiki
|
||||
wiki.delete_page_button=Eliminar página
|
||||
wiki.delete_page_notice_1=Eliminar a página wiki "%s" é uma operação irreversível. Quer continuar?
|
||||
|
@ -1981,7 +1982,7 @@ wiki.page_already_exists=Já existe uma página wiki com o mesmo nome.
|
|||
wiki.reserved_page=O nome de página wiki "%s" está reservado.
|
||||
wiki.pages=Páginas
|
||||
wiki.last_updated=Última modificação em %s
|
||||
wiki.page_name_desc=Insira um nome para esta página Wiki. Alguns dos nomes especiais são: 'Home', '_Sidebar' e '_Footer'.
|
||||
wiki.page_name_desc=Insira um nome para esta página Wiki. Alguns dos nomes especiais são: "Home", "_Sidebar" e "_Footer".
|
||||
wiki.original_git_entry_tooltip=Ver o ficheiro Git original, ao invés de usar uma ligação amigável.
|
||||
|
||||
activity=Trabalho
|
||||
|
@ -1998,22 +1999,22 @@ activity.period.yearly=1 ano
|
|||
activity.overview=Panorama geral
|
||||
activity.active_prs_count_1=<strong>%d</strong> pedido de integração vigente
|
||||
activity.active_prs_count_n=<strong>%d</strong> pedidos de integração vigentes
|
||||
activity.merged_prs_count_1=pedido de integração executado
|
||||
activity.merged_prs_count_n=pedidos de integração executados
|
||||
activity.opened_prs_count_1=pedido de integração proposto
|
||||
activity.opened_prs_count_n=pedidos de integração propostos
|
||||
activity.merged_prs_count_1=Pedido de integração executado
|
||||
activity.merged_prs_count_n=Pedidos de integração executados
|
||||
activity.opened_prs_count_1=Pedido de integração proposto
|
||||
activity.opened_prs_count_n=Pedidos de integração propostos
|
||||
activity.title.user_1=%d utilizador
|
||||
activity.title.user_n=%d utilizadores
|
||||
activity.title.prs_1=%d pedido de integração
|
||||
activity.title.prs_n=%d Pedidos de integração
|
||||
activity.title.prs_n=%d pedidos de integração
|
||||
activity.title.prs_merged_by=%s executado(s) por %s
|
||||
activity.title.prs_opened_by=%s proposto por %s
|
||||
activity.merged_prs_label=Integrado
|
||||
activity.opened_prs_label=Proposto
|
||||
activity.active_issues_count_1=<strong>%d</strong> questão vigente
|
||||
activity.active_issues_count_n=<strong>%d</strong> questões vigentes
|
||||
activity.closed_issues_count_1=questão encerrada
|
||||
activity.closed_issues_count_n=questões encerradas
|
||||
activity.closed_issues_count_1=Questão encerrada
|
||||
activity.closed_issues_count_n=Questões encerradas
|
||||
activity.title.issues_1=%d questão
|
||||
activity.title.issues_n=%d questões
|
||||
activity.title.issues_closed_from=%s resolvida(s) de %s
|
||||
|
@ -2146,12 +2147,12 @@ settings.pulls.default_allow_edits_from_maintainers=Permitir, por norma, que os
|
|||
settings.releases_desc=Habilitar lançamentos no repositório
|
||||
settings.packages_desc=Habilitar o registo de pacotes do repositório
|
||||
settings.projects_desc=Habilitar planeamentos no repositório
|
||||
settings.actions_desc=Habilitar operações no repositório (Forgejo Actions)
|
||||
settings.actions_desc=Habilitar sequências CI/CD integradas com Forgejo Actions
|
||||
settings.admin_settings=Configurações do administrador
|
||||
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
|
||||
settings.admin_code_indexer=Indexador de código-fonte
|
||||
settings.admin_stats_indexer=Indexador de estatísticas de código-fonte
|
||||
settings.admin_indexer_commit_sha=Último SHA indexado
|
||||
settings.admin_indexer_commit_sha=Último cometimento indexado
|
||||
settings.admin_indexer_unindexed=Não indexado
|
||||
settings.reindex_button=Adicionar à fila de reindexação
|
||||
settings.reindex_requested=Reindexação solicitada
|
||||
|
@ -2551,7 +2552,7 @@ diff.review.reject=Solicitar modificações
|
|||
diff.review.self_approve=Autores de pedidos de integração não podem aprovar o seu próprio pedido de integração
|
||||
diff.committed_by=cometido por
|
||||
diff.protected=Protegido
|
||||
diff.image.side_by_side=Lado a Lado
|
||||
diff.image.side_by_side=Lado a lado
|
||||
diff.image.swipe=Deslizar
|
||||
diff.image.overlay=Sobrepor
|
||||
diff.has_escaped=Esta linha tem caracteres unicode escondidos
|
||||
|
@ -2602,7 +2603,7 @@ release.tag_already_exist=Este nome de etiqueta já existe.
|
|||
release.downloads=Descargas
|
||||
release.download_count=Descargas: %s
|
||||
release.add_tag_msg=Usar o título e o conteúdo do lançamento como mensagem da etiqueta.
|
||||
release.add_tag=Criar apenas a etiqueta
|
||||
release.add_tag=Criar etiqueta
|
||||
release.releases_for=Lançamentos para %s
|
||||
release.tags_for=Etiquetas para %s
|
||||
|
||||
|
@ -2684,7 +2685,7 @@ n_tag_one = %s etiqueta
|
|||
n_tag_few = %s etiquetas
|
||||
migrate.forgejo.description = Migrar dados de codeberg.org ou de outras instâncias Forgejo.
|
||||
n_commit_one = %s cometimento
|
||||
editor.commit_id_not_matching = O ID de cometimento não corresponde ao que estava a editar. Cometa para um ramo novo e depois integre.
|
||||
editor.commit_id_not_matching = O ficheiro foi modificado enquanto o estava a editar. Cometa para um ramo novo e depois integre.
|
||||
commits.search_branch = Este ramo
|
||||
pulls.title_desc_one = quer integrar %[1]d cometimento do ramo <code>%[2]s</code> no ramo <code id="branch_target">%[3]s</code>
|
||||
pulls.reopen_failed.base_branch = O pedido de integração não pode ser reaberto porque o ramo base já não existe.
|
||||
|
@ -2735,6 +2736,10 @@ settings.sourcehut_builds.secrets_helper = Dar, ao trabalho, acesso aos segredos
|
|||
settings.sourcehut_builds.access_token_helper = Código de acesso que tem a permissão JOBS:RW. Gera um <a target="_blank" rel="noopener noreferrer" href="%s">código builds.sr.ht</a> ou um <a target="_blank" rel="noopener noreferrer" href="%s">código builds.sr.ht com acesso aos segredos</a> em meta.sr.ht.
|
||||
release.hide_archive_links = Esconder arquivos gerados automaticamente
|
||||
release.hide_archive_links_helper = Esconder arquivos de código-fonte gerados automaticamente para este lançamento. Por exemplo, se estiver a carregar o seu próprio.
|
||||
wiki.no_search_results = Sem resultados
|
||||
settings.transfer.button = Transferir propriedade
|
||||
settings.transfer.modal.title = Transferir propriedade
|
||||
wiki.search = Pesquisar wiki
|
||||
|
||||
[graphs]
|
||||
component_loading=A carregar %s...
|
||||
|
@ -2804,9 +2809,9 @@ settings.labels_desc=Adicionar rótulos que possam ser usados em questões para
|
|||
|
||||
members.membership_visibility=Visibilidade da filiação:
|
||||
members.public=Visível
|
||||
members.public_helper=tornar oculto
|
||||
members.public_helper=Tornar oculto
|
||||
members.private=Oculto
|
||||
members.private_helper=tornar visível
|
||||
members.private_helper=Tornar visível
|
||||
members.member_role=Função do membro:
|
||||
members.owner=Proprietário(a)
|
||||
members.member=Membro
|
||||
|
@ -2964,8 +2969,8 @@ dashboard.total_gc_time=Pausa total da recolha de lixo
|
|||
dashboard.total_gc_pause=Pausa total da recolha de lixo
|
||||
dashboard.last_gc_pause=Última pausa da recolha de lixo
|
||||
dashboard.gc_times=N.º de recolhas de lixo
|
||||
dashboard.delete_old_actions=Eliminar todas as operações antigas da base de dados
|
||||
dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todas as operações antigas da base de dados.
|
||||
dashboard.delete_old_actions=Eliminar todos os trabalhos antigos da base de dados
|
||||
dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todos os trabalhos antigos da base de dados.
|
||||
dashboard.update_checker=Verificador de novas versões
|
||||
dashboard.delete_old_system_notices=Eliminar todas as notificações do sistema antigas da base de dados
|
||||
dashboard.gc_lfs=Recolher lixo dos meta-elementos LFS
|
||||
|
@ -2992,7 +2997,7 @@ users.repos=Repos.
|
|||
users.created=Criada
|
||||
users.last_login=Último acesso
|
||||
users.never_login=Nunca acedeu
|
||||
users.send_register_notify=Enviar notificação de registo de utilizador
|
||||
users.send_register_notify=Notificar sobre o registo via email
|
||||
users.new_success=A conta de utilizador "%s" foi criada.
|
||||
users.edit=Editar
|
||||
users.auth_source=Fonte de autenticação
|
||||
|
@ -3440,7 +3445,7 @@ mirror_sync_create=sincronizou a nova referência <a href="%[2]s">%[3]s</a> para
|
|||
mirror_sync_delete=sincronizou e eliminou a referência <code>%[2]s</code> em <a href="%[1]s">%[3]s</a> da réplica
|
||||
approve_pull_request=`aprovou <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reject_pull_request=`sugeriu modificações para <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
publish_release=`lançou <a href="%[2]s"> "%[4]s" </a> em <a href="%[1]s">%[3]s</a>`
|
||||
publish_release=`lançou <a href="%[2]s"> %[4]s </a> em <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`descartou a revisão de <b>%[4]s</b> para <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Motivo:
|
||||
create_branch=criou o ramo <a href="%[2]s">%[3]s</a> em <a href="%[1]s">%[4]s</a>
|
||||
|
@ -3631,7 +3636,7 @@ owner.settings.cargo.rebuild=Reconstruir índice
|
|||
owner.settings.cargo.rebuild.description=Reconstruir pode ser útil se o índice não estiver sincronizado com os pacotes de Cargo armazenados.
|
||||
owner.settings.cargo.rebuild.error=Falhou ao reconstruir o índice do Cargo: %v
|
||||
owner.settings.cargo.rebuild.success=O índice do Cargo foi reconstruído com sucesso.
|
||||
owner.settings.cleanuprules.title=Gerir regras de limpeza
|
||||
owner.settings.cleanuprules.title=Regras de limpeza
|
||||
owner.settings.cleanuprules.add=Adicionar regra de limpeza
|
||||
owner.settings.cleanuprules.edit=Editar regra de limpeza
|
||||
owner.settings.cleanuprules.none=Ainda não há quaisquer regras de limpeza.
|
||||
|
@ -3675,7 +3680,7 @@ management=Gerir segredos
|
|||
[actions]
|
||||
actions=Operações
|
||||
|
||||
unit.desc=Gerir operações
|
||||
unit.desc=Gerir sequências CI/CD integradas com Forgejo Actions
|
||||
|
||||
status.unknown=Desconhecido
|
||||
status.waiting=Aguardando
|
||||
|
|
|
@ -1881,7 +1881,7 @@ pull.deleted_branch=(удалена):%s
|
|||
|
||||
milestones.new=Новый этап
|
||||
milestones.closed=Закрыт %s
|
||||
milestones.update_ago=Обновлено %s
|
||||
milestones.update_ago=Обновлён %s
|
||||
milestones.no_due_date=Срок не указан
|
||||
milestones.open=Открыть
|
||||
milestones.close=Закрыть
|
||||
|
@ -2741,6 +2741,8 @@ release.hide_archive_links = Скрыть автоматически генер
|
|||
release.hide_archive_links_helper = Скрыть автоматически добавляемые архивы исходного кода для этого релиза. Например, если вы загружаете свои архивы.
|
||||
settings.transfer.button = Передать репозиторий
|
||||
settings.transfer.modal.title = Передача репозитория
|
||||
wiki.search = Искать в вики
|
||||
wiki.no_search_results = Нет результатов
|
||||
|
||||
[graphs]
|
||||
|
||||
|
@ -2749,7 +2751,7 @@ org_name_holder=Название организации
|
|||
org_full_name_holder=Полное название
|
||||
org_name_helper=Лучшие названия организаций коротки и запоминаемы.
|
||||
create_org=Создать организацию
|
||||
repo_updated=Обновлено %s
|
||||
repo_updated=Обновлён %s
|
||||
members=Участники
|
||||
teams=Команды
|
||||
code=Код
|
||||
|
@ -3439,7 +3441,7 @@ mirror_sync_create=синхронизировал(а) новую ссылку <a
|
|||
mirror_sync_delete=синхронизированные и удалённые ссылки <code>%[2]s</code> на <a href="%[1]s">%[3]s</a> из зеркала
|
||||
approve_pull_request=`одобрен <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
reject_pull_request=`предложил(а) изменения для <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
publish_release=`выпустил(а) <a href="%[2]s"> "%[4]s" </a> в <a href="%[1]s">%[3]s</a>`
|
||||
publish_release=`выпустил(а) <a href="%[2]s"> %[4]s </a> в <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`отклонён отзыв от <b>%[4]s</b> для <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Причина:
|
||||
create_branch=создана ветка <a href="%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
|
||||
|
|
|
@ -656,7 +656,7 @@ following_few=%d 关注中
|
|||
follow=关注
|
||||
unfollow=取消关注
|
||||
user_bio=简历
|
||||
disabled_public_activity=该用户已隐藏活动记录。
|
||||
disabled_public_activity=该用户已隐藏公开活动记录。
|
||||
email_visibility.limited=所有已认证用户均可看到您的电子邮件地址
|
||||
email_visibility.private=只有你本人和管理员可以看到你的电子邮件地址
|
||||
show_on_map=在地图上显示这个位置
|
||||
|
@ -2752,6 +2752,8 @@ release.hide_archive_links_helper = 为此版本发布隐藏自动生成的源
|
|||
release.hide_archive_links = 隐藏自动生成的存档
|
||||
settings.transfer.modal.title = 转移所有权
|
||||
settings.transfer.button = 转移所有权
|
||||
wiki.search = 搜索百科
|
||||
wiki.no_search_results = 无结果
|
||||
|
||||
[graphs]
|
||||
component_loading=正在加载 %s...
|
||||
|
|
File diff suppressed because it is too large
Load diff
151
package-lock.json
generated
151
package-lock.json
generated
|
@ -11,7 +11,7 @@
|
|||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@github/text-expander-element": "2.7.0",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@primer/octicons": "19.9.0",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"pdfobject": "2.3.0",
|
||||
"postcss": "8.4.38",
|
||||
"postcss-loader": "8.1.1",
|
||||
"postcss-nesting": "12.1.4",
|
||||
"postcss-nesting": "12.1.5",
|
||||
"pretty-ms": "9.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"swagger-ui-dist": "5.17.12",
|
||||
|
@ -86,15 +86,15 @@
|
|||
"eslint-plugin-vue": "9.26.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.8.0",
|
||||
"eslint-plugin-wc": "2.1.0",
|
||||
"happy-dom": "14.11.0",
|
||||
"markdownlint-cli": "0.40.0",
|
||||
"happy-dom": "14.11.2",
|
||||
"markdownlint-cli": "0.41.0",
|
||||
"postcss-html": "1.7.0",
|
||||
"stylelint": "16.5.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
"stylelint-declaration-strict-value": "1.10.4",
|
||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||
"svgo": "3.2.0",
|
||||
"updates": "16.0.1",
|
||||
"updates": "16.1.1",
|
||||
"vite-string-plugin": "1.3.1",
|
||||
"vitest": "1.6.0"
|
||||
},
|
||||
|
@ -1003,11 +1003,13 @@
|
|||
"integrity": "sha512-CrI6oAecoahG7PF5dsgjdvlF5kCtusVMjg810EULD81TvnDsP+k/FRi/ClFubWLgBo4EGpr2EfvmumtqQFo7ow=="
|
||||
},
|
||||
"node_modules/@github/text-expander-element": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.6.1.tgz",
|
||||
"integrity": "sha512-i6krPGXJRABfKXut0WArFd365Je4PT0MljtDoXUoCOEp+lGrmdosDMxmO0EfOYc97jBn+Hd2XO1mMsuI5+fwmQ==",
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.7.0.tgz",
|
||||
"integrity": "sha512-zeo7l2L91o6yuGHJfA1Xtpg6UgDuZGq0WCgplDwd+54pVIsNzwsynIo6oTjE03cCtqLQpdYRe1wSQxyKYZOoGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/combobox-nav": "^2.0.2"
|
||||
"@github/combobox-nav": "^2.0.2",
|
||||
"dom-input-range": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
|
@ -4810,6 +4812,15 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-input-range": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/dom-input-range/-/dom-input-range-1.1.5.tgz",
|
||||
"integrity": "sha512-ITURvugfDoy8Wk8JC6NoI4dKyLPR4qbFnXJ+V+qVpQtTmDgT8HZjH2iNUIMiEU1kkdWEMLgDxYTSXJnPz9aeiA==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"demos"
|
||||
]
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
|
@ -6776,10 +6787,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/happy-dom": {
|
||||
"version": "14.11.0",
|
||||
"resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.11.0.tgz",
|
||||
"integrity": "sha512-vu25dY7YJqLuTG/3ADC0FZRRF0yNBp3q2K0YTN08opXdZi8V/YzIJDNJWFiCnDIuyc+RrCIE093+H5fa9Trlxg==",
|
||||
"version": "14.11.2",
|
||||
"resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.11.2.tgz",
|
||||
"integrity": "sha512-KUrwcT2GAVIGkFev287ude3n0BGGK3BWGltlVEPE8osMbDRU4zwKfcg6jUO7HkX1tAUU+kKt2g+LycmCH0Zwsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^4.5.0",
|
||||
"webidl-conversions": "^7.0.0",
|
||||
|
@ -8246,14 +8258,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/markdownlint-cli": {
|
||||
"version": "0.40.0",
|
||||
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.40.0.tgz",
|
||||
"integrity": "sha512-JXhI3dRQcaqwiFYpPz6VJ7aKYheD53GmTz9y4D/d0F1MbZDGOp9pqKlbOfUX/pHP/iAoeiE4wYRmk8/kjLakxA==",
|
||||
"version": "0.41.0",
|
||||
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.41.0.tgz",
|
||||
"integrity": "sha512-kp29tKrMKdn+xonfefjp3a/MsNzAd9c5ke0ydMEI9PR98bOjzglYN4nfMSaIs69msUf1DNkgevAIAPtK2SeX0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "~12.0.0",
|
||||
"commander": "~12.1.0",
|
||||
"get-stdin": "~9.0.0",
|
||||
"glob": "~10.3.12",
|
||||
"glob": "~10.4.1",
|
||||
"ignore": "~5.3.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonc-parser": "~3.2.1",
|
||||
|
@ -8261,7 +8274,7 @@
|
|||
"markdownlint": "~0.34.0",
|
||||
"minimatch": "~9.0.4",
|
||||
"run-con": "~1.3.2",
|
||||
"toml": "~3.0.0"
|
||||
"smol-toml": "~1.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"markdownlint": "markdownlint.js"
|
||||
|
@ -8271,41 +8284,63 @@
|
|||
}
|
||||
},
|
||||
"node_modules/markdownlint-cli/node_modules/commander": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
|
||||
"integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/markdownlint-cli/node_modules/glob": {
|
||||
"version": "10.3.12",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
|
||||
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz",
|
||||
"integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.6",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^7.0.4",
|
||||
"path-scurry": "^1.10.2"
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/markdownlint-cli/node_modules/jackspeak": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz",
|
||||
"integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/markdownlint-cli/node_modules/jsonc-parser": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
|
||||
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/markdownlint-micromark": {
|
||||
"version": "0.1.9",
|
||||
|
@ -8955,9 +8990,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
|
||||
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
|
@ -9472,15 +9508,16 @@
|
|||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
|
||||
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
|
@ -9870,9 +9907,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-nesting": {
|
||||
"version": "12.1.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.4.tgz",
|
||||
"integrity": "sha512-CcHOq94K137E+U4Ommu7pexcpp0Tjm24zl4UcqWs1oSLAr5cLI+jLrqQ5h/bdjhMX6cMbzunyustVNnvrzF8Zg==",
|
||||
"version": "12.1.5",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.5.tgz",
|
||||
"integrity": "sha512-N1NgI1PDCiAGWPTYrwqm8wpjv0bgDmkYHH72pNsqTCv9CObxjxftdYu6AKtGN+pnJa7FQjMm3v4sp8QJbFsYdQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
@ -9883,10 +9920,11 @@
|
|||
"url": "https://opencollective.com/csstools"
|
||||
}
|
||||
],
|
||||
"license": "MIT-0",
|
||||
"dependencies": {
|
||||
"@csstools/selector-resolve-nested": "^1.1.0",
|
||||
"@csstools/selector-specificity": "^3.1.1",
|
||||
"postcss-selector-parser": "^6.0.13"
|
||||
"postcss-selector-parser": "^6.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
|
@ -9944,9 +9982,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-selector-parser": {
|
||||
"version": "6.0.16",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
|
||||
"integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
|
||||
"integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
|
@ -10810,6 +10849,17 @@
|
|||
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/smol-toml": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.2.0.tgz",
|
||||
"integrity": "sha512-KObxdQANC/xje3OoatMbSwQf2XAvJ0RbK+4nmQRszFNZptbNRnMWqbLF/zb4sMi9xJ6HNyhWXeuZ9zC/I/XY7w==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"pnpm": ">= 9"
|
||||
}
|
||||
},
|
||||
"node_modules/solid-js": {
|
||||
"version": "1.8.16",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.16.tgz",
|
||||
|
@ -11831,12 +11881,6 @@
|
|||
"resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz",
|
||||
"integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ=="
|
||||
},
|
||||
"node_modules/toml": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
|
@ -12115,10 +12159,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/updates": {
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/updates/-/updates-16.0.1.tgz",
|
||||
"integrity": "sha512-If3NQKzGcA3aVgz2VyOXqQ+4uqYjPUPqh2PeZPtD+OKT4CTmxRYqoyFO+T3nwfccy4SiWy5AabWrBXXhVQ89Aw==",
|
||||
"version": "16.1.1",
|
||||
"resolved": "https://registry.npmjs.org/updates/-/updates-16.1.1.tgz",
|
||||
"integrity": "sha512-h0Qtbmd9RCi6+99D5o7ACq4h7GxdYjeHFlxd4s0iO3lUOUDo1VnOsbNNIyjHpieVEctaEm/zoEjVggCgAcO/vg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"bin": {
|
||||
"updates": "dist/updates.js"
|
||||
},
|
||||
|
|
10
package.json
10
package.json
|
@ -10,7 +10,7 @@
|
|||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@github/text-expander-element": "2.7.0",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@primer/octicons": "19.9.0",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"pdfobject": "2.3.0",
|
||||
"postcss": "8.4.38",
|
||||
"postcss-loader": "8.1.1",
|
||||
"postcss-nesting": "12.1.4",
|
||||
"postcss-nesting": "12.1.5",
|
||||
"pretty-ms": "9.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"swagger-ui-dist": "5.17.12",
|
||||
|
@ -85,15 +85,15 @@
|
|||
"eslint-plugin-vue": "9.26.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.8.0",
|
||||
"eslint-plugin-wc": "2.1.0",
|
||||
"happy-dom": "14.11.0",
|
||||
"markdownlint-cli": "0.40.0",
|
||||
"happy-dom": "14.11.2",
|
||||
"markdownlint-cli": "0.41.0",
|
||||
"postcss-html": "1.7.0",
|
||||
"stylelint": "16.5.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
"stylelint-declaration-strict-value": "1.10.4",
|
||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||
"svgo": "3.2.0",
|
||||
"updates": "16.0.1",
|
||||
"updates": "16.1.1",
|
||||
"vite-string-plugin": "1.3.1",
|
||||
"vitest": "1.6.0"
|
||||
},
|
||||
|
|
6
poetry.lock
generated
6
poetry.lock
generated
|
@ -16,13 +16,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|||
|
||||
[[package]]
|
||||
name = "codespell"
|
||||
version = "2.2.6"
|
||||
version = "2.3.0"
|
||||
description = "Codespell"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "codespell-2.2.6-py3-none-any.whl", hash = "sha256:9ee9a3e5df0990604013ac2a9f22fa8e57669c827124a2e961fe8a1da4cacc07"},
|
||||
{file = "codespell-2.2.6.tar.gz", hash = "sha256:a8c65d8eb3faa03deabab6b3bbe798bea72e1799c7e9e955d57eca4096abcff9"},
|
||||
{file = "codespell-2.3.0-py3-none-any.whl", hash = "sha256:a9c7cef2501c9cfede2110fd6d4e5e62296920efe9abfb84648df866e47f58d1"},
|
||||
{file = "codespell-2.3.0.tar.gz", hash = "sha256:360c7d10f75e65f67bad720af7007e1060a5d395670ec11a7ed1fed9dd17471f"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
|
1
release-notes/8.0.0/feat/3870.md
Normal file
1
release-notes/8.0.0/feat/3870.md
Normal file
|
@ -0,0 +1 @@
|
|||
Use CSS-native pattern for image diff background, add dark theme support
|
1
release-notes/8.0.0/fix/3904.md
Normal file
1
release-notes/8.0.0/fix/3904.md
Normal file
|
@ -0,0 +1 @@
|
|||
- a v7.0.0 regression causing `[admin].SEND_NOTIFICATION_EMAIL_ON_NEW_USER=true` to always be ignored.
|
1
release-notes/8.0.0/fix/3935.md
Normal file
1
release-notes/8.0.0/fix/3935.md
Normal file
|
@ -0,0 +1 @@
|
|||
- Fixed an issue where migrated activities (such as reviews) were mapped to the user who initiated the migration rather than the Ghost user, if the external user could not be mapped to a local one. This mapping mismatch led to internal server errors in some cases (forgejo/forgejo#3860).
|
1
release-notes/8.0.0/perf/3865.md
Normal file
1
release-notes/8.0.0/perf/3865.md
Normal file
|
@ -0,0 +1 @@
|
|||
Attempt to speed up user deletion when using mariadb 10 (the subquery took advantage of the available index starting with mariadb 11).
|
|
@ -175,7 +175,7 @@ func Migrate(ctx *context.APIContext) {
|
|||
Description: opts.Description,
|
||||
OriginalURL: form.CloneAddr,
|
||||
GitServiceType: gitServiceType,
|
||||
IsPrivate: opts.Private,
|
||||
IsPrivate: opts.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: opts.Mirror,
|
||||
Status: repo_model.RepositoryBeingMigrated,
|
||||
})
|
||||
|
|
|
@ -252,7 +252,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
|
|||
Gitignores: opt.Gitignores,
|
||||
License: opt.License,
|
||||
Readme: opt.Readme,
|
||||
IsPrivate: opt.Private,
|
||||
IsPrivate: opt.Private || setting.Repository.ForcePrivate,
|
||||
AutoInit: opt.AutoInit,
|
||||
DefaultBranch: opt.DefaultBranch,
|
||||
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
||||
|
@ -364,7 +364,7 @@ func Generate(ctx *context.APIContext) {
|
|||
Name: form.Name,
|
||||
DefaultBranch: form.DefaultBranch,
|
||||
Description: form.Description,
|
||||
Private: form.Private,
|
||||
Private: form.Private || setting.Repository.ForcePrivate,
|
||||
GitContent: form.GitContent,
|
||||
Topics: form.Topics,
|
||||
GitHooks: form.GitHooks,
|
||||
|
|
|
@ -542,20 +542,45 @@ func GrantApplicationOAuth(ctx *context.Context) {
|
|||
ctx.Error(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if !form.Granted {
|
||||
handleAuthorizeError(ctx, AuthorizeError{
|
||||
State: form.State,
|
||||
ErrorDescription: "the request is denied",
|
||||
ErrorCode: ErrorCodeAccessDenied,
|
||||
}, form.RedirectURI)
|
||||
return
|
||||
}
|
||||
|
||||
app, err := auth.GetOAuth2ApplicationByClientID(ctx, form.ClientID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOAuth2ApplicationByClientID", err)
|
||||
return
|
||||
}
|
||||
grant, err := app.CreateGrant(ctx, ctx.Doer.ID, form.Scope)
|
||||
grant, err := app.GetGrantByUserID(ctx, ctx.Doer.ID)
|
||||
if err != nil {
|
||||
handleServerError(ctx, form.State, form.RedirectURI)
|
||||
return
|
||||
}
|
||||
if grant == nil {
|
||||
grant, err = app.CreateGrant(ctx, ctx.Doer.ID, form.Scope)
|
||||
if err != nil {
|
||||
handleAuthorizeError(ctx, AuthorizeError{
|
||||
State: form.State,
|
||||
ErrorDescription: "cannot create grant for user",
|
||||
ErrorCode: ErrorCodeServerError,
|
||||
}, form.RedirectURI)
|
||||
return
|
||||
}
|
||||
} else if grant.Scope != form.Scope {
|
||||
handleAuthorizeError(ctx, AuthorizeError{
|
||||
State: form.State,
|
||||
ErrorDescription: "cannot create grant for user",
|
||||
ErrorDescription: "a grant exists with different scope",
|
||||
ErrorCode: ErrorCodeServerError,
|
||||
}, form.RedirectURI)
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Nonce) > 0 {
|
||||
err := grant.SetNonce(ctx, form.Nonce)
|
||||
if err != nil {
|
||||
|
|
|
@ -931,7 +931,7 @@ func ExcerptBlob(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
ctx.Data["section"] = section
|
||||
ctx.Data["FileNameHash"] = base.EncodeSha1(filePath)
|
||||
ctx.Data["FileNameHash"] = git.HashFilePathForWebUI(filePath)
|
||||
ctx.Data["AfterCommitID"] = commitID
|
||||
ctx.Data["Anchor"] = anchor
|
||||
ctx.HTML(http.StatusOK, tplBlobExcerpt)
|
||||
|
|
|
@ -248,7 +248,7 @@ func CreatePost(ctx *context.Context) {
|
|||
opts := repo_service.GenerateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
Private: form.Private,
|
||||
Private: form.Private || setting.Repository.ForcePrivate,
|
||||
GitContent: form.GitContent,
|
||||
Topics: form.Topics,
|
||||
GitHooks: form.GitHooks,
|
||||
|
|
|
@ -57,6 +57,8 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var GzipMinSize = gzhttp.DefaultMinSize
|
||||
|
||||
// optionsCorsHandler return a http handler which sets CORS options if enabled by config, it blocks non-CORS OPTIONS requests.
|
||||
func optionsCorsHandler() func(next http.Handler) http.Handler {
|
||||
var corsHandler func(next http.Handler) http.Handler
|
||||
|
@ -242,7 +244,7 @@ func Routes() *web.Route {
|
|||
var mid []any
|
||||
|
||||
if setting.EnableGzip {
|
||||
wrapper, err := gzhttp.NewWrapper(gzhttp.RandomJitter(32, 0, false))
|
||||
wrapper, err := gzhttp.NewWrapper(gzhttp.RandomJitter(32, 0, false), gzhttp.MinSize(GzipMinSize))
|
||||
if err != nil {
|
||||
log.Fatal("gzhttp.NewWrapper failed: %v", err)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/queue"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
)
|
||||
|
||||
|
@ -30,6 +31,8 @@ var prAutoMergeQueue *queue.WorkerPoolQueue[string]
|
|||
|
||||
// Init runs the task queue to that handles auto merges
|
||||
func Init() error {
|
||||
notify_service.RegisterNotifier(NewNotifier())
|
||||
|
||||
prAutoMergeQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_auto_merge", handler)
|
||||
if prAutoMergeQueue == nil {
|
||||
return fmt.Errorf("unable to create pr_auto_merge queue")
|
||||
|
@ -47,7 +50,7 @@ func handler(items ...string) []string {
|
|||
log.Error("could not parse data from pr_auto_merge queue (%v): %v", s, err)
|
||||
continue
|
||||
}
|
||||
handlePull(id, sha)
|
||||
handlePullRequestAutoMerge(id, sha)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -62,16 +65,6 @@ func addToQueue(pr *issues_model.PullRequest, sha string) {
|
|||
// ScheduleAutoMerge if schedule is false and no error, pull can be merged directly
|
||||
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest, style repo_model.MergeStyle, message string) (scheduled bool, err error) {
|
||||
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||
lastCommitStatus, err := pull_service.GetPullRequestCommitStatusState(ctx, pull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// we don't need to schedule
|
||||
if lastCommitStatus.IsSuccess() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := pull_model.ScheduleAutoMerge(ctx, doer, pull.ID, style, message); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,8 +88,8 @@ func RemoveScheduledAutoMerge(ctx context.Context, doer *user_model.User, pull *
|
|||
})
|
||||
}
|
||||
|
||||
// MergeScheduledPullRequest merges a previously scheduled pull request when all checks succeeded
|
||||
func MergeScheduledPullRequest(ctx context.Context, sha string, repo *repo_model.Repository) error {
|
||||
// StartPRCheckAndAutoMergeBySHA start an automerge check and auto merge task for all pull requests of repository and SHA
|
||||
func StartPRCheckAndAutoMergeBySHA(ctx context.Context, sha string, repo *repo_model.Repository) error {
|
||||
pulls, err := getPullRequestsByHeadSHA(ctx, sha, repo, func(pr *issues_model.PullRequest) bool {
|
||||
return !pr.HasMerged && pr.CanAutoMerge()
|
||||
})
|
||||
|
@ -111,6 +104,32 @@ func MergeScheduledPullRequest(ctx context.Context, sha string, repo *repo_model
|
|||
return nil
|
||||
}
|
||||
|
||||
// StartPRCheckAndAutoMerge start an automerge check and auto merge task for a pull request
|
||||
func StartPRCheckAndAutoMerge(ctx context.Context, pull *issues_model.PullRequest) {
|
||||
if pull == nil || pull.HasMerged || !pull.CanAutoMerge() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := pull.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("LoadBaseRepo: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, pull.BaseRepo)
|
||||
if err != nil {
|
||||
log.Error("OpenRepository: %v", err)
|
||||
return
|
||||
}
|
||||
defer gitRepo.Close()
|
||||
commitID, err := gitRepo.GetRefCommitID(pull.GetGitRefName())
|
||||
if err != nil {
|
||||
log.Error("GetRefCommitID: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
addToQueue(pull, commitID)
|
||||
}
|
||||
|
||||
func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.Repository, filter func(*issues_model.PullRequest) bool) (map[int64]*issues_model.PullRequest, error) {
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
|
||||
if err != nil {
|
||||
|
@ -161,7 +180,8 @@ func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.
|
|||
return pulls, nil
|
||||
}
|
||||
|
||||
func handlePull(pullID int64, sha string) {
|
||||
// handlePullRequestAutoMerge merge the pull request if all checks are successful
|
||||
func handlePullRequestAutoMerge(pullID int64, sha string) {
|
||||
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(),
|
||||
fmt.Sprintf("Handle AutoMerge of PR[%d] with sha[%s]", pullID, sha))
|
||||
defer finished()
|
||||
|
@ -182,24 +202,50 @@ func handlePull(pullID int64, sha string) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = pr.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("%-v LoadBaseRepo: %v", pr, err)
|
||||
return
|
||||
}
|
||||
|
||||
// check the sha is the same as pull request head commit id
|
||||
baseGitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo)
|
||||
if err != nil {
|
||||
log.Error("OpenRepository: %v", err)
|
||||
return
|
||||
}
|
||||
defer baseGitRepo.Close()
|
||||
|
||||
headCommitID, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
log.Error("GetRefCommitID: %v", err)
|
||||
return
|
||||
}
|
||||
if headCommitID != sha {
|
||||
log.Warn("Head commit id of auto merge %-v does not match sha [%s], it may means the head branch has been updated. Just ignore this request because a new request expected in the queue", pr, sha)
|
||||
return
|
||||
}
|
||||
|
||||
// Get all checks for this pr
|
||||
// We get the latest sha commit hash again to handle the case where the check of a previous push
|
||||
// did not succeed or was not finished yet.
|
||||
|
||||
if err = pr.LoadHeadRepo(ctx); err != nil {
|
||||
log.Error("%-v LoadHeadRepo: %v", pr, err)
|
||||
return
|
||||
}
|
||||
|
||||
headGitRepo, err := gitrepo.OpenRepository(ctx, pr.HeadRepo)
|
||||
if err != nil {
|
||||
log.Error("OpenRepository %-v: %v", pr.HeadRepo, err)
|
||||
return
|
||||
var headGitRepo *git.Repository
|
||||
if pr.BaseRepoID == pr.HeadRepoID {
|
||||
headGitRepo = baseGitRepo
|
||||
} else {
|
||||
headGitRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo)
|
||||
if err != nil {
|
||||
log.Error("OpenRepository %-v: %v", pr.HeadRepo, err)
|
||||
return
|
||||
}
|
||||
defer headGitRepo.Close()
|
||||
}
|
||||
defer headGitRepo.Close()
|
||||
|
||||
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
|
||||
|
||||
if pr.HeadRepo == nil || !headBranchExist {
|
||||
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
|
||||
return
|
||||
|
@ -238,25 +284,11 @@ func handlePull(pullID int64, sha string) {
|
|||
return
|
||||
}
|
||||
|
||||
var baseGitRepo *git.Repository
|
||||
if pr.BaseRepoID == pr.HeadRepoID {
|
||||
baseGitRepo = headGitRepo
|
||||
} else {
|
||||
if err = pr.LoadBaseRepo(ctx); err != nil {
|
||||
log.Error("%-v LoadBaseRepo: %v", pr, err)
|
||||
return
|
||||
}
|
||||
|
||||
baseGitRepo, err = gitrepo.OpenRepository(ctx, pr.BaseRepo)
|
||||
if err != nil {
|
||||
log.Error("OpenRepository %-v: %v", pr.BaseRepo, err)
|
||||
return
|
||||
}
|
||||
defer baseGitRepo.Close()
|
||||
}
|
||||
|
||||
if err := pull_service.Merge(ctx, pr, doer, baseGitRepo, scheduledPRM.MergeStyle, "", scheduledPRM.Message, true); err != nil {
|
||||
log.Error("pull_service.Merge: %v", err)
|
||||
// FIXME: if merge failed, we should display some error message to the pull request page.
|
||||
// The resolution is add a new column on automerge table named `error_message` to store the error message and displayed
|
||||
// on the pull request page. But this should not be finished in a bug fix PR which will be backport to release branch.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
46
services/automerge/notify.go
Normal file
46
services/automerge/notify.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package automerge
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
)
|
||||
|
||||
type automergeNotifier struct {
|
||||
notify_service.NullNotifier
|
||||
}
|
||||
|
||||
var _ notify_service.Notifier = &automergeNotifier{}
|
||||
|
||||
// NewNotifier create a new automergeNotifier notifier
|
||||
func NewNotifier() notify_service.Notifier {
|
||||
return &automergeNotifier{}
|
||||
}
|
||||
|
||||
func (n *automergeNotifier) PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User) {
|
||||
// as a missing / blocking reviews could have blocked a pending automerge let's recheck
|
||||
if review.Type == issues_model.ReviewTypeApprove {
|
||||
if err := StartPRCheckAndAutoMergeBySHA(ctx, review.CommitID, pr.BaseRepo); err != nil {
|
||||
log.Error("StartPullRequestAutoMergeCheckBySHA: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *automergeNotifier) PullReviewDismiss(ctx context.Context, doer *user_model.User, review *issues_model.Review, comment *issues_model.Comment) {
|
||||
if err := review.LoadIssue(ctx); err != nil {
|
||||
log.Error("LoadIssue: %v", err)
|
||||
return
|
||||
}
|
||||
if err := review.Issue.LoadPullRequest(ctx); err != nil {
|
||||
log.Error("LoadPullRequest: %v", err)
|
||||
return
|
||||
}
|
||||
// as reviews could have blocked a pending automerge let's recheck
|
||||
StartPRCheckAndAutoMerge(ctx, review.Issue.PullRequest)
|
||||
}
|
|
@ -162,6 +162,7 @@ func (f *AuthorizationForm) Validate(req *http.Request, errs binding.Errors) bin
|
|||
// GrantApplicationForm form for authorizing oauth2 clients
|
||||
type GrantApplicationForm struct {
|
||||
ClientID string `binding:"Required"`
|
||||
Granted bool
|
||||
RedirectURI string
|
||||
State string
|
||||
Scope string
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
pull_model "code.gitea.io/gitea/models/pull"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/highlight"
|
||||
|
@ -742,7 +741,7 @@ parsingLoop:
|
|||
diffLineTypeBuffers[DiffLineAdd] = new(bytes.Buffer)
|
||||
diffLineTypeBuffers[DiffLineDel] = new(bytes.Buffer)
|
||||
for _, f := range diff.Files {
|
||||
f.NameHash = base.EncodeSha1(f.Name)
|
||||
f.NameHash = git.HashFilePathForWebUI(f.Name)
|
||||
|
||||
for _, buffer := range diffLineTypeBuffers {
|
||||
buffer.Reset()
|
||||
|
|
|
@ -403,7 +403,7 @@ func generateAdditionalHeaders(ctx *mailCommentContext, reason string, recipient
|
|||
// https://datatracker.ietf.org/doc/html/rfc2369
|
||||
"List-Archive": fmt.Sprintf("<%s>", repo.HTMLURL()),
|
||||
|
||||
"X-Mailer": "Gitea",
|
||||
"X-Mailer": "Forgejo",
|
||||
"X-Gitea-Reason": reason,
|
||||
"X-Gitea-Sender": ctx.Doer.Name,
|
||||
"X-Gitea-Recipient": recipient.Name,
|
||||
|
@ -415,8 +415,8 @@ func generateAdditionalHeaders(ctx *mailCommentContext, reason string, recipient
|
|||
"X-Gitea-Issue-Link": ctx.Issue.HTMLURL(),
|
||||
|
||||
"X-Forgejo-Reason": reason,
|
||||
"X-Forgejo-Sender": ctx.Doer.DisplayName(),
|
||||
"X-Forgejo-Recipient": recipient.DisplayName(),
|
||||
"X-Forgejo-Sender": ctx.Doer.Name,
|
||||
"X-Forgejo-Recipient": recipient.Name,
|
||||
"X-Forgejo-Recipient-Address": recipient.Email,
|
||||
"X-Forgejo-Repository": repo.Name,
|
||||
"X-Forgejo-Repository-Path": repo.FullName(),
|
||||
|
|
|
@ -360,6 +360,7 @@ func TestGenerateAdditionalHeaders(t *testing.T) {
|
|||
expected := map[string]string{
|
||||
"List-ID": "user2/repo1 <repo1.user2.localhost>",
|
||||
"List-Archive": "<https://try.gitea.io/user2/repo1>",
|
||||
"X-Mailer": "Forgejo",
|
||||
"X-Gitea-Reason": "dummy-reason",
|
||||
"X-Gitea-Sender": "user2",
|
||||
"X-Gitea-Recipient": "test",
|
||||
|
@ -369,6 +370,8 @@ func TestGenerateAdditionalHeaders(t *testing.T) {
|
|||
"X-Gitea-Repository-Link": "https://try.gitea.io/user2/repo1",
|
||||
"X-Gitea-Issue-ID": "1",
|
||||
"X-Gitea-Issue-Link": "https://try.gitea.io/user2/repo1/issues/1",
|
||||
"X-Forgejo-Sender": "user2",
|
||||
"X-Forgejo-Recipient": "test",
|
||||
}
|
||||
|
||||
for key, value := range expected {
|
||||
|
|
|
@ -107,7 +107,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
|
|||
Description: repo.Description,
|
||||
OriginalURL: repo.OriginalURL,
|
||||
GitServiceType: opts.GitServiceType,
|
||||
IsPrivate: opts.Private,
|
||||
IsPrivate: opts.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: opts.Mirror,
|
||||
Status: repo_model.RepositoryBeingMigrated,
|
||||
})
|
||||
|
@ -996,7 +996,7 @@ func (g *GiteaLocalUploader) remapUser(source user_model.ExternalUserMigrated, t
|
|||
if userID > 0 {
|
||||
return target.RemapExternalUser("", 0, userID)
|
||||
}
|
||||
return target.RemapExternalUser(source.GetExternalName(), source.GetExternalID(), g.doer.ID)
|
||||
return target.RemapExternalUser(source.GetExternalName(), source.GetExternalID(), user_model.GhostUserID)
|
||||
}
|
||||
|
||||
func (g *GiteaLocalUploader) remapLocalUser(source user_model.ExternalUserMigrated) (int64, error) {
|
||||
|
|
|
@ -145,24 +145,24 @@ func TestGiteaUploadRemapLocalUser(t *testing.T) {
|
|||
|
||||
//
|
||||
// The externalID does not match any existing user, everything
|
||||
// belongs to the doer
|
||||
// belongs to the Ghost user
|
||||
//
|
||||
target := repo_model.Release{}
|
||||
uploader.userMap = make(map[int64]int64)
|
||||
err := uploader.remapUser(&source, &target)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, doer.ID, target.GetUserID())
|
||||
assert.EqualValues(t, user_model.GhostUserID, target.GetUserID())
|
||||
|
||||
//
|
||||
// The externalID matches a known user but the name does not match,
|
||||
// everything belongs to the doer
|
||||
// everything belongs to the Ghost user
|
||||
//
|
||||
source.PublisherID = user.ID
|
||||
target = repo_model.Release{}
|
||||
uploader.userMap = make(map[int64]int64)
|
||||
err = uploader.remapUser(&source, &target)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, doer.ID, target.GetUserID())
|
||||
assert.EqualValues(t, user_model.GhostUserID, target.GetUserID())
|
||||
|
||||
//
|
||||
// The externalID and externalName match an existing user, everything
|
||||
|
@ -195,13 +195,13 @@ func TestGiteaUploadRemapExternalUser(t *testing.T) {
|
|||
|
||||
//
|
||||
// When there is no user linked to the external ID, the migrated data is authored
|
||||
// by the doer
|
||||
// by the Ghost user
|
||||
//
|
||||
uploader.userMap = make(map[int64]int64)
|
||||
target := repo_model.Release{}
|
||||
err := uploader.remapUser(&source, &target)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, doer.ID, target.GetUserID())
|
||||
assert.EqualValues(t, user_model.GhostUserID, target.GetUserID())
|
||||
|
||||
//
|
||||
// Link the external ID to an existing user
|
||||
|
|
|
@ -117,7 +117,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato
|
|||
}
|
||||
|
||||
if status.State.IsSuccess() {
|
||||
if err := automerge.MergeScheduledPullRequest(ctx, sha, repo); err != nil {
|
||||
if err := automerge.StartPRCheckAndAutoMergeBySHA(ctx, sha, repo); err != nil {
|
||||
return fmt.Errorf("MergeScheduledPullRequest[repo_id: %d, user_id: %d, sha: %s]: %w", repo.ID, creator.ID, sha, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
actions_module "code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
|
||||
"xorm.io/builder"
|
||||
|
@ -125,9 +126,25 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID
|
|||
return err
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"webhook.repo_id": repo.ID})).
|
||||
Delete(&webhook.HookTask{}); err != nil {
|
||||
return err
|
||||
if setting.Database.Type.IsMySQL() {
|
||||
// mariadb:10 does not use the hook_task KEY when using IN.
|
||||
// https://codeberg.org/forgejo/forgejo/issues/3678
|
||||
//
|
||||
// Version 11 does support it, but is not available in debian yet.
|
||||
// Version 11.4 LTS is not available yet (stable should be released mid 2024 https://mariadb.org/mariadb/all-releases/)
|
||||
|
||||
// Sqlite does not support the DELETE *** FROM *** syntax
|
||||
// https://stackoverflow.com/q/24511153/3207406
|
||||
|
||||
// in the meantime, use a dedicated query for mysql...
|
||||
if _, err := db.Exec(ctx, "DELETE `hook_task` FROM `hook_task` INNER JOIN `webhook` ON `webhook`.id = `hook_task`.hook_id WHERE `webhook`.repo_id = ?", repo.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := db.GetEngine(ctx).In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"webhook.repo_id": repo.ID})).
|
||||
Delete(&webhook.HookTask{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.DeleteBeans(ctx,
|
||||
|
|
|
@ -91,7 +91,7 @@ func PushCreateRepo(ctx context.Context, authUser, owner *user_model.User, repoN
|
|||
|
||||
repo, err := CreateRepository(ctx, authUser, owner, CreateRepoOptions{
|
||||
Name: repoName,
|
||||
IsPrivate: setting.Repository.DefaultPushCreatePrivate,
|
||||
IsPrivate: setting.Repository.DefaultPushCreatePrivate || setting.Repository.ForcePrivate,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -107,7 +107,7 @@ func CreateMigrateTask(ctx context.Context, doer, u *user_model.User, opts base.
|
|||
Description: opts.Description,
|
||||
OriginalURL: opts.OriginalURL,
|
||||
GitServiceType: opts.GitServiceType,
|
||||
IsPrivate: opts.Private,
|
||||
IsPrivate: opts.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: opts.Mirror,
|
||||
Status: repo_model.RepositoryBeingMigrated,
|
||||
})
|
||||
|
|
|
@ -77,7 +77,7 @@ func (defaultHandler) NewRequest(ctx context.Context, w *webhook_model.Webhook,
|
|||
// see https://codeberg.org/codeberg/community/issues/1556
|
||||
payloadContent, err = substituteRefShortName(payloadContent)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not substiture ref: %w", err)
|
||||
return nil, nil, fmt.Errorf("could not substitute ref: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ export default {
|
|||
'xl': '12px',
|
||||
'2xl': '16px',
|
||||
'3xl': '24px',
|
||||
'full': 'var(--border-radius-circle)', // 50%
|
||||
'full': 'var(--border-radius-full)',
|
||||
},
|
||||
fontFamily: {
|
||||
sans: 'var(--fonts-regular)',
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<td class="eight wide">
|
||||
{{if .DBBranch.IsDeleted}}
|
||||
<div class="flex-text-block">
|
||||
<a class="gt-ellipsis" href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .DBBranch.Name}}">{{.DBBranch.Name}}</a>
|
||||
<span class="gt-ellipsis">{{.DBBranch.Name}}</span>
|
||||
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
||||
</div>
|
||||
<p class="info">{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{TimeSinceUnix .DBBranch.DeletedUnix ctx.Locale}}</p>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
{{/* show dummy elements before Vue componment is mounted, this code must match the code in BranchTagSelector.vue */}}
|
||||
<div class="ui dropdown custom">
|
||||
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button tw-flex tw-m-0">
|
||||
<span class="text tw-flex tw-items-center tw-mr-1">
|
||||
<span class="text tw-flex tw-items-center tw-mr-1 gt-ellipsis">
|
||||
{{if .release}}
|
||||
{{ctx.Locale.Tr "repo.release.compare"}}
|
||||
{{else}}
|
||||
|
@ -80,7 +80,7 @@
|
|||
{{else}}
|
||||
{{svg "octicon-git-branch"}}
|
||||
{{end}}
|
||||
<strong ref="dropdownRefName" class="tw-ml-2">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
|
||||
<strong ref="dropdownRefName" class="tw-ml-2 tw-inline-block gt-ellipsis">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
|
||||
{{end}}
|
||||
</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{{$file := .file}}
|
||||
{{$blobExcerptRepoLink := or $.root.CommitRepoLink $.root.RepoLink}}
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col width="10">
|
||||
|
@ -18,17 +19,17 @@
|
|||
<td class="lines-num lines-num-old">
|
||||
<div class="tw-flex">
|
||||
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5)}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=down&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=down&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold-down"}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4)}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=up&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=up&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold-up"}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if eq $line.GetExpandDirection 2}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=split&direction=&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold"}}
|
||||
</button>
|
||||
{{end}}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{{$file := .file}}
|
||||
{{$blobExcerptRepoLink := or $.root.CommitRepoLink $.root.RepoLink}}
|
||||
<colgroup>
|
||||
<col width="50">
|
||||
<col width="50">
|
||||
|
@ -14,17 +15,17 @@
|
|||
<td colspan="2" class="lines-num">
|
||||
<div class="tw-flex">
|
||||
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5)}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold-down"}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4)}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=up&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=up&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold-up"}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if eq $line.GetExpandDirection 2}}
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$.root.CommitRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
<button class="code-expander-button" hx-target="closest tr" hx-get="{{$blobExcerptRepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}?{{$line.GetBlobExcerptQuery}}&style=unified&direction=&wiki={{$.root.PageIsWiki}}&anchor=diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
|
||||
{{svg "octicon-fold"}}
|
||||
</button>
|
||||
{{end}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{{template "repo/issue/fields/header" .}}
|
||||
{{/* FIXME: required validation */}}
|
||||
<div class="ui fluid selection dropdown {{if .item.Attributes.multiple}}multiple clearable{{end}}">
|
||||
<input type="hidden" name="form-field-{{.item.ID}}" value="0">
|
||||
<input type="hidden" name="form-field-{{.item.ID}}" value="{{.item.Attributes.default}}">
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
{{if not .item.Validations.required}}
|
||||
{{svg "octicon-x" 14 "remove icon"}}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
{{$.CsrfTokenHtml}}
|
||||
</form>
|
||||
{{/* TODO: share this branch selector dropdown with the same in repo page */}}
|
||||
<div class="ui {{if not .HasIssuesOrPullsWritePermission}}disabled{{end}} floating filter select-branch dropdown" data-no-results="{{ctx.Locale.Tr "repo.pulls.no_results"}}">
|
||||
<div class="ui {{if not .HasIssuesOrPullsWritePermission}}disabled{{end}} floating filter select-branch dropdown tw-max-w-full" data-no-results="{{ctx.Locale.Tr "repo.pulls.no_results"}}">
|
||||
<div class="ui basic small button">
|
||||
<span class="text branch-name">{{if .Reference}}{{$.RefEndName}}{{else}}{{ctx.Locale.Tr "repo.issues.no_ref"}}{{end}}</span>
|
||||
<span class="text branch-name gt-ellipsis">{{if .Reference}}{{$.RefEndName}}{{else}}{{ctx.Locale.Tr "repo.issues.no_ref"}}{{end}}</span>
|
||||
{{if .HasIssuesOrPullsWritePermission}}{{svg "octicon-triangle-down" 14 "dropdown icon"}}{{end}}
|
||||
</div>
|
||||
<div class="menu">
|
||||
|
@ -37,7 +37,7 @@
|
|||
<div class="item text small" data-id="" data-id-selector="#ref_selector"><strong><a href="#">{{ctx.Locale.Tr "repo.clear_ref"}}</a></strong></div>
|
||||
{{end}}
|
||||
{{range .Branches}}
|
||||
<div class="item" data-id="refs/heads/{{.}}" data-name="{{.}}" data-id-selector="#ref_selector">{{.}}</div>
|
||||
<div class="item" data-id="refs/heads/{{.}}" data-name="{{.}}" data-id-selector="#ref_selector" title="{{.}}">{{.}}</div>
|
||||
{{else}}
|
||||
<div class="item">{{ctx.Locale.Tr "repo.pulls.no_results"}}</div>
|
||||
{{end}}
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
{{else}}
|
||||
<div class="ui green label issue-state-label">{{svg "octicon-issue-opened"}} {{ctx.Locale.Tr "repo.issues.open_title"}}</div>
|
||||
{{end}}
|
||||
<div class="tw-ml-2">
|
||||
<div class="tw-ml-2 tw-flex-1 tw-break-anywhere">
|
||||
{{if .Issue.IsPull}}
|
||||
{{$headHref := .HeadTarget}}
|
||||
{{if .HeadBranchLink}}
|
||||
|
|
|
@ -28,9 +28,10 @@
|
|||
<label>{{ctx.Locale.Tr "repo.visibility"}}</label>
|
||||
<div class="ui checkbox" {{if and (not .Repository.IsPrivate) (gt .Repository.NumStars 0)}}data-tooltip-content="{{ctx.Locale.Tr "repo.stars_remove_warning"}}"{{end}}>
|
||||
{{if .IsAdmin}}
|
||||
<input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}>
|
||||
<input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}>
|
||||
{{else}}
|
||||
<input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}{{if and $.ForcePrivate .Repository.IsPrivate}} readonly{{end}}>
|
||||
<input name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}}{{if and $.ForcePrivate .Repository.IsPrivate}} disabled{{end}}>
|
||||
{{if and .Repository.IsPrivate $.ForcePrivate}}<input type="hidden" name="private" value="{{.Repository.IsPrivate}}">{{end}}
|
||||
{{end}}
|
||||
<label>{{ctx.Locale.Tr "repo.visibility_helper"}} {{if .Repository.NumForks}}<span class="text red">{{ctx.Locale.Tr "repo.visibility_fork_helper"}}</span>{{end}}</label>
|
||||
</div>
|
||||
|
|
|
@ -88,18 +88,21 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{if and .Milestone (ne $.listType "milestone")}}
|
||||
<a class="milestone flex-text-inline" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{.Repo.Link}}/milestone/{{.Milestone.ID}}"{{end}}>
|
||||
{{svg "octicon-milestone" 14}}{{.Milestone.Name}}
|
||||
<a class="milestone flex-text-inline tw-max-w-[300px]" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{.Repo.Link}}/milestone/{{.Milestone.ID}}"{{end}}>
|
||||
{{svg "octicon-milestone" 14}}
|
||||
<span class="gt-ellipsis">{{.Milestone.Name}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .Project}}
|
||||
<a class="project flex-text-inline" href="{{.Project.Link ctx}}">
|
||||
{{svg .Project.IconName 14}}{{.Project.Title}}
|
||||
<a class="project flex-text-inline tw-max-w-[300px]" href="{{.Project.Link ctx}}">
|
||||
{{svg .Project.IconName 14}}
|
||||
<span class="gt-ellipsis">{{.Project.Title}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .Ref}}
|
||||
<a class="ref flex-text-inline" {{if $.RepoLink}}href="{{index $.IssueRefURLs .ID}}"{{else}}href="{{.Repo.Link}}{{index $.IssueRefURLs .ID}}"{{end}}>
|
||||
{{svg "octicon-git-branch" 14}}{{index $.IssueRefEndNames .ID}}
|
||||
<a class="ref flex-text-inline tw-max-w-[300px]" {{if $.RepoLink}}href="{{index $.IssueRefURLs .ID}}"{{else}}href="{{.Repo.Link}}{{index $.IssueRefURLs .ID}}"{{end}}>
|
||||
{{svg "octicon-git-branch" 14}}
|
||||
<span class="gt-ellipsis">{{index $.IssueRefEndNames .ID}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
{{$tasks := .GetTasks}}
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
<input type="hidden" name="scope" value="{{.Scope}}">
|
||||
<input type="hidden" name="nonce" value="{{.Nonce}}">
|
||||
<input type="hidden" name="redirect_uri" value="{{.RedirectURI}}">
|
||||
<button type="submit" id="authorize-app" value="{{ctx.Locale.Tr "auth.authorize_application"}}" class="ui red inline button">{{ctx.Locale.Tr "auth.authorize_application"}}</button>
|
||||
<a href="{{.RedirectURI}}" class="ui basic primary inline button">Cancel</a>
|
||||
<button type="submit" id="authorize-app" name="granted" value="true" class="ui red inline button">{{ctx.Locale.Tr "auth.authorize_application"}}</button>
|
||||
<button type="submit" name="granted" value="false" class="ui basic primary inline button">{{ctx.Locale.Tr "cancel"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
@ -251,8 +252,41 @@ func TestCompareCodeExpand(t *testing.T) {
|
|||
owner.Name, repo.Name, forker.Name, repo.Name+"-copy")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
htmlDoc.AssertElement(t, fmt.Sprintf("button.code-expander-button[hx-get^='/%s/%s/blob_excerpt/'] svg.octicon-fold-up", forker.Name, repo.Name+"-copy"), true)
|
||||
htmlDoc.AssertElement(t, fmt.Sprintf("button.code-expander-button[hx-get^='/%s/%s/blob_excerpt/'] svg.octicon-fold-down", forker.Name, repo.Name+"-copy"), true)
|
||||
|
||||
els := htmlDoc.Find(`button.code-expander-button[hx-get]`)
|
||||
|
||||
// all the links in the comparison should be to the forked repo&branch
|
||||
assert.NotZero(t, els.Length())
|
||||
expectedPrefix := fmt.Sprintf("/%s/%s/blob_excerpt/", forker.Name, repo.Name+"-copy")
|
||||
for i := 0; i < els.Length(); i++ {
|
||||
link := els.Eq(i).AttrOr("hx-get", "")
|
||||
assert.True(t, strings.HasPrefix(link, expectedPrefix))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("code expander targets the repo in a PR", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create a pullrequest
|
||||
resp := testPullCreate(t, session, forker.Name, repo.Name+"-copy", false, "main", "code-expand", "This is a pull title")
|
||||
|
||||
// Grab the URL for the PR
|
||||
url := test.RedirectURL(resp) + "/files"
|
||||
|
||||
// Visit the PR's diff
|
||||
req := NewRequest(t, "GET", url)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
els := htmlDoc.Find(`button.code-expander-button[hx-get]`)
|
||||
|
||||
// all the links in the comparison should be to the original repo&branch
|
||||
assert.NotZero(t, els.Length())
|
||||
expectedPrefix := fmt.Sprintf("/%s/%s/blob_excerpt/", owner.Name, repo.Name)
|
||||
for i := 0; i < els.Length(); i++ {
|
||||
link := els.Eq(i).AttrOr("hx-get", "")
|
||||
assert.True(t, strings.HasPrefix(link, expectedPrefix))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -30,28 +30,32 @@ import (
|
|||
func TestCreateFile(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Request editor page
|
||||
req := NewRequest(t, "GET", "/user2/repo1/_new/master/")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
lastCommit := doc.GetInputValueByName("last_commit")
|
||||
assert.NotEmpty(t, lastCommit)
|
||||
|
||||
// Save new file to master branch
|
||||
req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"last_commit": lastCommit,
|
||||
"tree_path": "test.txt",
|
||||
"content": "Content",
|
||||
"commit_choice": "direct",
|
||||
"commit_mail_id": "3",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
testCreateFile(t, session, "user2", "repo1", "master", "test.txt", "Content")
|
||||
})
|
||||
}
|
||||
|
||||
func testCreateFile(t *testing.T, session *TestSession, user, repo, branch, filePath, content string) *httptest.ResponseRecorder {
|
||||
// Request editor page
|
||||
newURL := fmt.Sprintf("/%s/%s/_new/%s/", user, repo, branch)
|
||||
req := NewRequest(t, "GET", newURL)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
lastCommit := doc.GetInputValueByName("last_commit")
|
||||
assert.NotEmpty(t, lastCommit)
|
||||
|
||||
// Save new file to master branch
|
||||
req = NewRequestWithValues(t, "POST", newURL, map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"last_commit": lastCommit,
|
||||
"tree_path": filePath,
|
||||
"content": content,
|
||||
"commit_choice": "direct",
|
||||
"commit_mail_id": "3",
|
||||
})
|
||||
return session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func TestCreateFileOnProtectedBranch(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
session := loginUser(t, "user2")
|
||||
|
|
|
@ -9,13 +9,15 @@ import (
|
|||
"testing"
|
||||
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/tests"
|
||||
)
|
||||
|
||||
func TestOrgProjectAccess(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
defer test.MockVariableValue(&unit_model.DisabledRepoUnits, append(slices.Clone(unit_model.DisabledRepoUnits), unit_model.TypeProjects))()
|
||||
|
||||
disabledRepoUnits := unit_model.DisabledRepoUnitsGet()
|
||||
unit_model.DisabledRepoUnitsSet(append(slices.Clone(disabledRepoUnits), unit_model.TypeProjects))
|
||||
defer unit_model.DisabledRepoUnitsSet(disabledRepoUnits)
|
||||
|
||||
// repo project, 404
|
||||
req := NewRequest(t, "GET", "/user2/repo1/projects")
|
||||
|
|
|
@ -12,6 +12,8 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -19,7 +21,9 @@ import (
|
|||
"code.gitea.io/gitea/models"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
pull_model "code.gitea.io/gitea/models/pull"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
@ -32,7 +36,9 @@ import (
|
|||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
"code.gitea.io/gitea/services/automerge"
|
||||
"code.gitea.io/gitea/services/pull"
|
||||
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
webhook_service "code.gitea.io/gitea/services/webhook"
|
||||
|
||||
|
@ -661,3 +667,195 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func testResetRepo(t *testing.T, repoPath, branch, commitID string) {
|
||||
f, err := os.OpenFile(filepath.Join(repoPath, "refs", "heads", branch), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
assert.NoError(t, err)
|
||||
_, err = f.WriteString(commitID + "\n")
|
||||
assert.NoError(t, err)
|
||||
f.Close()
|
||||
|
||||
repo, err := git.OpenRepository(context.Background(), repoPath)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
id, err := repo.GetBranchCommitID(branch)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, commitID, id)
|
||||
}
|
||||
|
||||
func TestPullAutoMergeAfterCommitStatusSucceed(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
// create a pull request
|
||||
session := loginUser(t, "user1")
|
||||
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
forkedName := "repo1-1"
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", forkedName)
|
||||
defer func() {
|
||||
testDeleteRepository(t, session, "user1", forkedName)
|
||||
}()
|
||||
testEditFile(t, session, "user1", forkedName, "master", "README.md", "Hello, World (Edited)\n")
|
||||
testPullCreate(t, session, "user1", forkedName, false, "master", "master", "Indexer notifier test pull")
|
||||
|
||||
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
|
||||
forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: forkedName})
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
|
||||
BaseRepoID: baseRepo.ID,
|
||||
BaseBranch: "master",
|
||||
HeadRepoID: forkedRepo.ID,
|
||||
HeadBranch: "master",
|
||||
})
|
||||
|
||||
// add protected branch for commit status
|
||||
csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
|
||||
// Change master branch to protected
|
||||
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"rule_name": "master",
|
||||
"enable_push": "true",
|
||||
"enable_status_check": "true",
|
||||
"status_check_contexts": "gitea/actions",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// first time insert automerge record, return true
|
||||
scheduled, err := automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, scheduled)
|
||||
|
||||
// second time insert automerge record, return false because it does exist
|
||||
scheduled, err = automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||
assert.Error(t, err)
|
||||
assert.False(t, scheduled)
|
||||
|
||||
// reload pr again
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.False(t, pr.HasMerged)
|
||||
assert.Empty(t, pr.MergedCommitID)
|
||||
|
||||
// update commit status to success, then it should be merged automatically
|
||||
baseGitRepo, err := gitrepo.OpenRepository(db.DefaultContext, baseRepo)
|
||||
assert.NoError(t, err)
|
||||
sha, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
assert.NoError(t, err)
|
||||
masterCommitID, err := baseGitRepo.GetBranchCommitID("master")
|
||||
assert.NoError(t, err)
|
||||
|
||||
branches, _, err := baseGitRepo.GetBranchNames(0, 100)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{"sub-home-md-img-check", "home-md-img-check", "pr-to-update", "branch2", "DefaultBranch", "develop", "feature/1", "master"}, branches)
|
||||
baseGitRepo.Close()
|
||||
defer func() {
|
||||
testResetRepo(t, baseRepo.RepoPath(), "master", masterCommitID)
|
||||
}()
|
||||
|
||||
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
|
||||
State: api.CommitStatusSuccess,
|
||||
TargetURL: "https://gitea.com",
|
||||
Context: "gitea/actions",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// realod pr again
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.True(t, pr.HasMerged)
|
||||
assert.NotEmpty(t, pr.MergedCommitID)
|
||||
|
||||
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
// create a pull request
|
||||
session := loginUser(t, "user1")
|
||||
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
forkedName := "repo1-2"
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", forkedName)
|
||||
defer func() {
|
||||
testDeleteRepository(t, session, "user1", forkedName)
|
||||
}()
|
||||
testEditFile(t, session, "user1", forkedName, "master", "README.md", "Hello, World (Edited)\n")
|
||||
testPullCreate(t, session, "user1", forkedName, false, "master", "master", "Indexer notifier test pull")
|
||||
|
||||
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
|
||||
forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: forkedName})
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
|
||||
BaseRepoID: baseRepo.ID,
|
||||
BaseBranch: "master",
|
||||
HeadRepoID: forkedRepo.ID,
|
||||
HeadBranch: "master",
|
||||
})
|
||||
|
||||
// add protected branch for commit status
|
||||
csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
|
||||
// Change master branch to protected
|
||||
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"rule_name": "master",
|
||||
"enable_push": "true",
|
||||
"enable_status_check": "true",
|
||||
"status_check_contexts": "gitea/actions",
|
||||
"required_approvals": "1",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// first time insert automerge record, return true
|
||||
scheduled, err := automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, scheduled)
|
||||
|
||||
// second time insert automerge record, return false because it does exist
|
||||
scheduled, err = automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||
assert.Error(t, err)
|
||||
assert.False(t, scheduled)
|
||||
|
||||
// reload pr again
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.False(t, pr.HasMerged)
|
||||
assert.Empty(t, pr.MergedCommitID)
|
||||
|
||||
// update commit status to success, then it should be merged automatically
|
||||
baseGitRepo, err := gitrepo.OpenRepository(db.DefaultContext, baseRepo)
|
||||
assert.NoError(t, err)
|
||||
sha, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
assert.NoError(t, err)
|
||||
masterCommitID, err := baseGitRepo.GetBranchCommitID("master")
|
||||
assert.NoError(t, err)
|
||||
baseGitRepo.Close()
|
||||
defer func() {
|
||||
testResetRepo(t, baseRepo.RepoPath(), "master", masterCommitID)
|
||||
}()
|
||||
|
||||
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
|
||||
State: api.CommitStatusSuccess,
|
||||
TargetURL: "https://gitea.com",
|
||||
Context: "gitea/actions",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// reload pr again
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.False(t, pr.HasMerged)
|
||||
assert.Empty(t, pr.MergedCommitID)
|
||||
|
||||
// approve the PR from non-author
|
||||
approveSession := loginUser(t, "user2")
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("/user2/repo1/pulls/%d", pr.Index))
|
||||
resp := approveSession.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
testSubmitReview(t, approveSession, htmlDoc.GetCSRF(), "user2", "repo1", strconv.Itoa(int(pr.Index)), sha, "approve", http.StatusOK)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// realod pr again
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||
assert.True(t, pr.HasMerged)
|
||||
assert.NotEmpty(t, pr.MergedCommitID)
|
||||
|
||||
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -425,10 +425,10 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
|||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Submit an approve review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "approve", http.StatusUnprocessableEntity)
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "", "approve", http.StatusUnprocessableEntity)
|
||||
|
||||
// Submit a reject review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "reject", http.StatusUnprocessableEntity)
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "", "reject", http.StatusUnprocessableEntity)
|
||||
})
|
||||
|
||||
t.Run("Submit approve/reject review on closed PR", func(t *testing.T) {
|
||||
|
@ -445,18 +445,18 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
|
|||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Submit an approve review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "approve", http.StatusUnprocessableEntity)
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "", "approve", http.StatusUnprocessableEntity)
|
||||
|
||||
// Submit a reject review on the PR.
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "reject", http.StatusUnprocessableEntity)
|
||||
testSubmitReview(t, user2Session, htmlDoc.GetCSRF(), "user2", "repo1", elem[4], "", "reject", http.StatusUnprocessableEntity)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testSubmitReview(t *testing.T, session *TestSession, csrf, owner, repo, pullNumber, reviewType string, expectedSubmitStatus int) *httptest.ResponseRecorder {
|
||||
func testSubmitReview(t *testing.T, session *TestSession, csrf, owner, repo, pullNumber, commitID, reviewType string, expectedSubmitStatus int) *httptest.ResponseRecorder {
|
||||
options := map[string]string{
|
||||
"_csrf": csrf,
|
||||
"commit_id": "",
|
||||
"commit_id": commitID,
|
||||
"content": "test",
|
||||
"type": reviewType,
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/web"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
func TestRepoDownloadArchive(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
defer test.MockVariableValue(&setting.EnableGzip, true)()
|
||||
defer test.MockVariableValue(&web.GzipMinSize, 10)()
|
||||
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
||||
|
||||
req := NewRequest(t, "GET", "/user2/repo1/archive/master.zip")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository_test
|
||||
package integration
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -11,6 +11,7 @@ import (
|
|||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
webhook_model "code.gitea.io/gitea/models/webhook"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -51,5 +52,22 @@ func TestDeleteOwnerRepositoriesDirectly(t *testing.T) {
|
|||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
deletedHookID := unittest.AssertExistsAndLoadBean(t, &webhook_model.Webhook{RepoID: 1}).ID
|
||||
unittest.AssertExistsAndLoadBean(t, &webhook_model.HookTask{
|
||||
HookID: deletedHookID,
|
||||
})
|
||||
|
||||
preservedHookID := unittest.AssertExistsAndLoadBean(t, &webhook_model.Webhook{RepoID: 3}).ID
|
||||
unittest.AssertExistsAndLoadBean(t, &webhook_model.HookTask{
|
||||
HookID: preservedHookID,
|
||||
})
|
||||
|
||||
assert.NoError(t, repo_service.DeleteOwnerRepositoriesDirectly(db.DefaultContext, user))
|
||||
|
||||
unittest.AssertNotExistsBean(t, &webhook_model.HookTask{
|
||||
HookID: deletedHookID,
|
||||
})
|
||||
unittest.AssertExistsAndLoadBean(t, &webhook_model.HookTask{
|
||||
HookID: preservedHookID,
|
||||
})
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
/* other variables */
|
||||
--border-radius: 4px;
|
||||
--border-radius-medium: 6px;
|
||||
--border-radius-circle: 50%;
|
||||
--border-radius-full: 99999px; /* TODO: use calc(infinity * 1px) */
|
||||
--opacity-disabled: 0.55;
|
||||
--height-loading: 16rem;
|
||||
--repo-header-issue-min-height: 41px;
|
||||
|
@ -423,6 +423,8 @@ a.label,
|
|||
|
||||
.ui.dropdown .menu > .item {
|
||||
color: var(--color-text);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ui.dropdown .menu > .item:hover {
|
||||
|
@ -1359,7 +1361,7 @@ svg.text.purple,
|
|||
|
||||
.color-icon {
|
||||
display: inline-block;
|
||||
border-radius: var(--border-radius-circle);
|
||||
border-radius: var(--border-radius-full);
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
|
||||
.image-diff-container img {
|
||||
border: 1px solid var(--color-primary-light-7);
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAG0lEQVQYlWN4+vTpf3SMDTAMBYXYBLFpHgoKAeiOf0SGE9kbAAAAAElFTkSuQmCC") right bottom var(--color-primary-light-7);
|
||||
--gradient: conic-gradient(var(--checkerboard-color-1) 90deg, var(--checkerboard-color-2) 90deg 180deg, var(--checkerboard-color-1) 180deg 270deg, var(--checkerboard-color-2) 270deg);
|
||||
background: var(--gradient);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
.image-diff-container .before-container {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
border-width: 4px;
|
||||
border-style: solid;
|
||||
border-color: var(--color-secondary) var(--color-secondary) var(--color-secondary-dark-8) var(--color-secondary-dark-8);
|
||||
border-radius: var(--border-radius-circle);
|
||||
border-radius: var(--border-radius-full);
|
||||
}
|
||||
|
||||
.is-loading.loading-icon-2px::after {
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
width: 300px;
|
||||
}
|
||||
|
||||
.issue-content-right .dropdown > .menu {
|
||||
max-width: 270px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.issue-content-left,
|
||||
.issue-content-right {
|
||||
|
@ -57,11 +62,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.repository .issue-content-right .menu {
|
||||
overflow-x: auto;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
.repository .issue-content-right .ui.list .dependency {
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
|
@ -113,11 +113,6 @@
|
|||
left: 0;
|
||||
}
|
||||
|
||||
.repository .filter.menu .ui.dropdown .menu .item {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.repository .select-label .desc {
|
||||
padding-left: 23px;
|
||||
}
|
||||
|
@ -666,6 +661,7 @@ td .commit-summary {
|
|||
font-size: 14px !important;
|
||||
padding: 7px 10px !important;
|
||||
border-radius: var(--border-radius-medium) !important;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.issue-state-label .svg {
|
||||
|
@ -791,7 +787,7 @@ td .commit-summary {
|
|||
width: 34px;
|
||||
height: 34px;
|
||||
background-color: var(--color-timeline);
|
||||
border-radius: var(--border-radius-circle);
|
||||
border-radius: var(--border-radius-full);
|
||||
display: flex;
|
||||
float: left;
|
||||
margin-left: -33px;
|
||||
|
@ -1186,10 +1182,6 @@ td .commit-summary {
|
|||
color: var(--color-text-light-2);
|
||||
}
|
||||
|
||||
.repository .ui.dropdown.filter > .menu {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.repository.branches .commit-divergence .bar-group {
|
||||
position: relative;
|
||||
float: left;
|
||||
|
@ -2108,13 +2100,14 @@ td .commit-summary {
|
|||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-cards .list .item {
|
||||
list-style: none;
|
||||
width: 32%;
|
||||
margin: 10px 10px 10px 0;
|
||||
padding-bottom: 14px;
|
||||
width: 31%;
|
||||
margin: 15px 15px 0 0;
|
||||
padding: 14px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
}
|
||||
|
||||
#issue-list .flex-item-body .branches .branch {
|
||||
background-color: var(--color-secondary-alpha-40);
|
||||
background-color: var(--color-secondary-alpha-50);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
@ -83,7 +83,9 @@
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 10em;
|
||||
max-width: 200px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#issue-list .flex-item-body .checklist progress {
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
position: absolute;
|
||||
left: -5.5px;
|
||||
top: 30px;
|
||||
border-radius: var(--border-radius-circle);
|
||||
border-radius: var(--border-radius-full);
|
||||
border: 2.5px solid var(--color-body);
|
||||
}
|
||||
|
||||
|
|
|
@ -242,6 +242,9 @@
|
|||
--color-highlight-fg: var(--color-primary-light-4);
|
||||
--color-highlight-bg: var(--color-primary-alpha-20);
|
||||
--color-overlay-backdrop: #080808c0;
|
||||
/* pattern colors for image diff */
|
||||
--checkerboard-color-1: #474747;
|
||||
--checkerboard-color-2: #313131;
|
||||
accent-color: var(--color-accent);
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,9 @@
|
|||
--color-highlight-fg: var(--color-primary-light-4);
|
||||
--color-highlight-bg: var(--color-primary-light-6);
|
||||
--color-overlay-backdrop: #080808c0;
|
||||
/* pattern colors for gradient */
|
||||
--checkerboard-color-1: #ffffff;
|
||||
--checkerboard-color-2: #e5e5e5;
|
||||
accent-color: var(--color-accent);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
|
|
@ -238,6 +238,9 @@
|
|||
--color-highlight-fg: #87651e;
|
||||
--color-highlight-bg: #352c1c;
|
||||
--color-overlay-backdrop: #080808c0;
|
||||
/* pattern colors for image diff */
|
||||
--checkerboard-color-1: #313131;
|
||||
--checkerboard-color-2: #212121;
|
||||
accent-color: var(--color-accent);
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
|
|
@ -238,6 +238,9 @@
|
|||
--color-highlight-fg: #eed200;
|
||||
--color-highlight-bg: #fffbdd;
|
||||
--color-overlay-backdrop: #080808c0;
|
||||
/* pattern colors for gradient */
|
||||
--checkerboard-color-1: #ffffff;
|
||||
--checkerboard-color-2: #e5e5e5;
|
||||
accent-color: var(--color-accent);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
|
|
@ -248,12 +248,12 @@ export default sfc; // activate IDE's Vue plugin
|
|||
<template>
|
||||
<div class="ui dropdown custom">
|
||||
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button tw-flex tw-m-0" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
|
||||
<span class="text tw-flex tw-items-center tw-mr-1">
|
||||
<span class="text tw-flex tw-items-center tw-mr-1 gt-ellipsis">
|
||||
<template v-if="release">{{ textReleaseCompare }}</template>
|
||||
<template v-else>
|
||||
<svg-icon v-if="isViewTag" name="octicon-tag"/>
|
||||
<svg-icon v-else name="octicon-git-branch"/>
|
||||
<strong ref="dropdownRefName" class="tw-ml-2">{{ refNameText }}</strong>
|
||||
<strong ref="dropdownRefName" class="tw-ml-2 tw-inline-block gt-ellipsis">{{ refNameText }}</strong>
|
||||
</template>
|
||||
</span>
|
||||
<svg-icon name="octicon-triangle-down" :size="14" class-name="dropdown icon"/>
|
||||
|
|
Loading…
Reference in a new issue