mirror of
https://github.com/go-gitea/gitea
synced 2025-01-10 01:34:43 +00:00
Merge branch 'main' into lunny/issue_dev
This commit is contained in:
commit
8951291e6c
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Gitea DevContainer",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
|
||||
"features": {
|
||||
// installs nodejs into container
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.2.2": {},
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "3.12"
|
||||
|
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@ -70,10 +70,11 @@ modifies/go:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.go"
|
||||
|
||||
modifies/js:
|
||||
modifies/frontend:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.js"
|
||||
- "**/*.ts"
|
||||
- "**/*.vue"
|
||||
|
||||
docs-update-needed:
|
||||
|
4
.github/workflows/pull-db-tests.yml
vendored
4
.github/workflows/pull-db-tests.yml
vendored
@ -198,7 +198,9 @@ jobs:
|
||||
test-mssql:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
# specifying the version of ubuntu in use as mssql fails on newer kernels
|
||||
# pending resolution from vendor
|
||||
runs-on: ubuntu-20.04
|
||||
services:
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
|
||||
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
|
||||
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
|
6
Makefile
6
Makefile
@ -23,12 +23,12 @@ SHASUM ?= shasum -a 256
|
||||
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
||||
COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.22.x
|
||||
XGO_VERSION := go-1.23.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.60.3
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
|
||||
|
59
assets/go-licenses.json
generated
59
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@ -158,7 +158,7 @@ func runCreateUser(c *cli.Context) error {
|
||||
IsRestricted: restricted,
|
||||
}
|
||||
|
||||
if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil {
|
||||
if err := user_model.CreateUser(ctx, u, &user_model.Meta{}, overwriteDefault); err != nil {
|
||||
return fmt.Errorf("CreateUser: %w", err)
|
||||
}
|
||||
|
||||
|
@ -542,14 +542,14 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
index := bytes.IndexByte(rs.Data, byte(0))
|
||||
if index >= len(rs.Data) {
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
||||
}
|
||||
|
||||
if index < 0 {
|
||||
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
||||
index = 9
|
||||
} else {
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
||||
}
|
||||
}
|
||||
|
||||
|
11
cmd/serv.go
11
cmd/serv.go
@ -143,6 +143,12 @@ func runServ(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
_ = fail(ctx, "Internal Server Error", "Panic: %v\n%s", err, log.Stack(2))
|
||||
}
|
||||
}()
|
||||
|
||||
keys := strings.Split(c.Args().First(), "-")
|
||||
if len(keys) != 2 || keys[0] != "key" {
|
||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
||||
@ -189,10 +195,7 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
verb := words[0]
|
||||
repoPath := words[1]
|
||||
if repoPath[0] == '/' {
|
||||
repoPath = repoPath[1:]
|
||||
}
|
||||
repoPath := strings.TrimPrefix(words[1], "/")
|
||||
|
||||
var lfsVerb string
|
||||
if verb == lfsAuthenticateVerb {
|
||||
|
@ -507,6 +507,9 @@ INTERNAL_TOKEN =
|
||||
;; stemming from cached/logged plain-text API tokens.
|
||||
;; In future releases, this will become the default behavior
|
||||
;DISABLE_QUERY_AUTH_TOKEN = false
|
||||
;;
|
||||
;; On user registration, record the IP address and user agent of the user to help identify potential abuse.
|
||||
;; RECORD_USER_SIGNUP_METADATA = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@ -523,7 +526,8 @@ INTERNAL_TOKEN =
|
||||
;; HMAC to encode urls with, it **is required** if camo is enabled.
|
||||
;HMAC_KEY =
|
||||
;; Set to true to use camo for https too lese only non https urls are proxyed
|
||||
;ALLWAYS = false
|
||||
;; ALLWAYS is deprecated and will be removed in the future
|
||||
;ALWAYS = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@ -2692,7 +2696,7 @@ LEVEL = Info
|
||||
;; It's always recommended to use compression when using local disk as log storage if CPU or memory is not a bottleneck.
|
||||
;; And for object storage services like S3, which is billed for requests, it would cause extra 2 times of get requests for each log view.
|
||||
;; But it will save storage space and network bandwidth, so it's still recommended to use compression.
|
||||
;LOG_COMPRESSION = none
|
||||
;LOG_COMPRESSION = zstd
|
||||
;; Default artifact retention time in days. Artifacts could have their own retention periods by setting the `retention-days` option in `actions/upload-artifact` step.
|
||||
;ARTIFACT_RETENTION_DAYS = 90
|
||||
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
||||
|
30
go.mod
30
go.mod
@ -1,6 +1,11 @@
|
||||
module code.gitea.io/gitea
|
||||
|
||||
go 1.22
|
||||
go 1.23
|
||||
|
||||
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
|
||||
// But some CAs use negative serial number, just relax the check. related:
|
||||
// Default TLS cert uses negative serial number #895 https://github.com/microsoft/mssql-docker/issues/895
|
||||
godebug x509negativeserial=1
|
||||
|
||||
require (
|
||||
code.gitea.io/actions-proto-go v0.4.0
|
||||
@ -23,6 +28,9 @@ require (
|
||||
github.com/PuerkitoBio/goquery v1.9.2
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||
github.com/alecthomas/chroma/v2 v2.14.0
|
||||
github.com/aws/aws-sdk-go v1.43.21
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.4.2
|
||||
github.com/buildkite/terminal-to-html/v3 v3.12.1
|
||||
@ -112,11 +120,11 @@ require (
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.26.0
|
||||
golang.org/x/image v0.18.0
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/net v0.28.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/sys v0.23.0
|
||||
golang.org/x/text v0.17.0
|
||||
golang.org/x/tools v0.22.0
|
||||
golang.org/x/tools v0.24.0
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
@ -146,6 +154,10 @@ require (
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
|
||||
github.com/aws/smithy-go v1.20.4 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
@ -249,18 +261,20 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.33.1 // indirect
|
||||
github.com/paulmach/orb v0.11.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.50.0 // indirect
|
||||
github.com/prometheus/procfs v0.13.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rhysd/actionlint v1.7.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
@ -300,7 +314,7 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
|
53
go.sum
53
go.sum
@ -109,6 +109,20 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go v1.43.21 h1:E4S2eX3d2gKJyI/ISrcIrSwXwqjIvCK85gtBMt4sAPE=
|
||||
github.com/aws/aws-sdk-go v1.43.21/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30 h1:aau/oYFtibVovr2rDt8FHlU17BTicFEMAi29V1U+L5Q=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30/go.mod h1:BPJ/yXV92ZVq6G8uYvbU0gSl8q94UB63nMT5ctNO38g=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1 h1:mOOALIM4JzhYkq3voCBbmZqmyEVEhHsfasMTbVxLkNs=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1/go.mod h1:6zf5j3mIUXKM0s2iz5ttR2Qwq+o47D0jotpAyaKgZRA=
|
||||
github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
|
||||
github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@ -504,6 +518,9 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk=
|
||||
github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@ -611,6 +628,8 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
||||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
|
||||
@ -635,8 +654,8 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
@ -646,8 +665,8 @@ github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
||||
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
@ -666,12 +685,12 @@ github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.50.0 h1:YSZE6aa9+luNa2da6/Tik0q0A5AbR+U003TItK57CPQ=
|
||||
github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ=
|
||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw=
|
||||
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
@ -752,6 +771,7 @@ github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -880,8 +900,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -891,6 +911,7 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
@ -899,8 +920,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -985,8 +1006,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -34,6 +34,7 @@ type ActivityStats struct {
|
||||
OpenedPRAuthorCount int64
|
||||
MergedPRs issues_model.PullRequestList
|
||||
MergedPRAuthorCount int64
|
||||
ActiveIssues issues_model.IssueList
|
||||
OpenedIssues issues_model.IssueList
|
||||
OpenedIssueAuthorCount int64
|
||||
ClosedIssues issues_model.IssueList
|
||||
@ -172,7 +173,7 @@ func (stats *ActivityStats) MergedPRPerc() int {
|
||||
|
||||
// ActiveIssueCount returns total active issue count
|
||||
func (stats *ActivityStats) ActiveIssueCount() int {
|
||||
return stats.OpenedIssueCount() + stats.ClosedIssueCount()
|
||||
return len(stats.ActiveIssues)
|
||||
}
|
||||
|
||||
// OpenedIssueCount returns open issue count
|
||||
@ -285,13 +286,21 @@ func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTi
|
||||
stats.ClosedIssueAuthorCount = count
|
||||
|
||||
// New issues
|
||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||
sess = newlyCreatedIssues(ctx, repoID, fromTime)
|
||||
sess.OrderBy("issue.created_unix ASC")
|
||||
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
||||
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Active issues
|
||||
sess = activeIssues(ctx, repoID, fromTime)
|
||||
sess.OrderBy("issue.created_unix ASC")
|
||||
stats.ActiveIssues = make(issues_model.IssueList, 0)
|
||||
if err = sess.Find(&stats.ActiveIssues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Opened issue authors
|
||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
||||
@ -317,6 +326,23 @@ func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int
|
||||
return sess.Find(&stats.UnresolvedIssues)
|
||||
}
|
||||
|
||||
func newlyCreatedIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||
And("issue.is_pull = ?", false). // Retain the is_pull check to exclude pull requests
|
||||
And("issue.created_unix >= ?", fromTime.Unix()) // Include all issues created after fromTime
|
||||
|
||||
return sess
|
||||
}
|
||||
|
||||
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||
And("issue.is_pull = ?", false).
|
||||
And("issue.created_unix >= ?", fromTime.Unix()).
|
||||
Or("issue.closed_unix >= ?", fromTime.Unix())
|
||||
|
||||
return sess
|
||||
}
|
||||
|
||||
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||
And("issue.is_closed = ?", closed)
|
||||
|
@ -114,7 +114,7 @@ func readArmoredSign(r io.Reader) (body io.Reader, err error) {
|
||||
return nil, err
|
||||
}
|
||||
if block.Type != openpgp.SignatureType {
|
||||
return nil, fmt.Errorf("expected '" + openpgp.SignatureType + "', got: " + block.Type)
|
||||
return nil, fmt.Errorf("expected '%s', got: %s", openpgp.SignatureType, block.Type)
|
||||
}
|
||||
return block.Body, nil
|
||||
}
|
||||
@ -139,7 +139,7 @@ func tryGetKeyIDFromSignature(sig *packet.Signature) string {
|
||||
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
|
||||
return fmt.Sprintf("%016X", *sig.IssuerKeyId)
|
||||
}
|
||||
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
|
||||
if len(sig.IssuerFingerprint) > 0 {
|
||||
return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20])
|
||||
}
|
||||
return ""
|
||||
|
@ -39,7 +39,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
|
||||
|
||||
// golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here
|
||||
// and in any case pq does not implement it
|
||||
if execer, ok := conn.(driver.Execer); ok { //nolint
|
||||
if execer, ok := conn.(driver.Execer); ok { //nolint:staticcheck
|
||||
_, err := execer.Exec(`SELECT set_config(
|
||||
'search_path',
|
||||
$1 || ',' || current_setting('search_path'),
|
||||
@ -64,7 +64,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
|
||||
// driver.String.ConvertValue will never return err for string
|
||||
|
||||
// golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here
|
||||
_, err = stmt.Exec([]driver.Value{schemaValue}) //nolint
|
||||
_, err = stmt.Exec([]driver.Value{schemaValue}) //nolint:staticcheck
|
||||
if err != nil {
|
||||
_ = conn.Close()
|
||||
return nil, err
|
||||
|
@ -48,12 +48,12 @@ func (issue *Issue) ProjectColumnID(ctx context.Context) int64 {
|
||||
}
|
||||
|
||||
// LoadIssuesFromColumn load issues assigned to this column
|
||||
func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column) (IssueList, error) {
|
||||
issueList, err := Issues(ctx, &IssuesOptions{
|
||||
ProjectColumnID: b.ID,
|
||||
ProjectID: b.ProjectID,
|
||||
SortType: "project-column-sorting",
|
||||
})
|
||||
func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column, opts *IssuesOptions) (IssueList, error) {
|
||||
issueList, err := Issues(ctx, opts.Copy(func(o *IssuesOptions) {
|
||||
o.ProjectColumnID = b.ID
|
||||
o.ProjectID = b.ProjectID
|
||||
o.SortType = "project-column-sorting"
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,10 +78,10 @@ func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column) (IssueLi
|
||||
}
|
||||
|
||||
// LoadIssuesFromColumnList load issues assigned to the columns
|
||||
func LoadIssuesFromColumnList(ctx context.Context, bs project_model.ColumnList) (map[int64]IssueList, error) {
|
||||
func LoadIssuesFromColumnList(ctx context.Context, bs project_model.ColumnList, opts *IssuesOptions) (map[int64]IssueList, error) {
|
||||
issuesMap := make(map[int64]IssueList, len(bs))
|
||||
for i := range bs {
|
||||
il, err := LoadIssuesFromColumn(ctx, bs[i])
|
||||
il, err := LoadIssuesFromColumn(ctx, bs[i], opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -54,6 +54,19 @@ type IssuesOptions struct { //nolint
|
||||
User *user_model.User // issues permission scope
|
||||
}
|
||||
|
||||
// Copy returns a copy of the options.
|
||||
// Be careful, it's not a deep copy, so `IssuesOptions.RepoIDs = {...}` is OK while `IssuesOptions.RepoIDs[0] = ...` is not.
|
||||
func (o *IssuesOptions) Copy(edit ...func(options *IssuesOptions)) *IssuesOptions {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
v := *o
|
||||
for _, e := range edit {
|
||||
e(&v)
|
||||
}
|
||||
return &v
|
||||
}
|
||||
|
||||
// applySorts sort an issues-related session based on the provided
|
||||
// sortType string
|
||||
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
|
||||
|
@ -268,6 +268,10 @@ func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pr *PullRequest) IsAgitFlow() bool {
|
||||
return pr.Flow == PullRequestFlowAGit
|
||||
}
|
||||
|
||||
// LoadHeadRepo loads the head repository, pr.HeadRepo will remain nil if it does not exist
|
||||
// and thus ErrRepoNotExist will never be returned
|
||||
func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) {
|
||||
|
@ -247,7 +247,7 @@ func (r *Review) TooltipContent() string {
|
||||
}
|
||||
return "repo.issues.review.official"
|
||||
case ReviewTypeComment:
|
||||
return "repo.issues.review.comment"
|
||||
return "repo.issues.review.commented"
|
||||
case ReviewTypeReject:
|
||||
return "repo.issues.review.rejected"
|
||||
case ReviewTypeRequest:
|
||||
|
@ -83,7 +83,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal %s: %w", source.Cfg, err)
|
||||
}
|
||||
if wrapped.Source != nil && len(wrapped.Source) > 0 {
|
||||
if len(wrapped.Source) > 0 {
|
||||
bs, err := json.Marshal(wrapped.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,7 +9,9 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"xorm.io/builder"
|
||||
@ -112,6 +114,49 @@ func IsUserOrgOwner(ctx context.Context, users user_model.UserList, orgID int64)
|
||||
return results
|
||||
}
|
||||
|
||||
// GetOrgAssignees returns all users that have write access and can be assigned to issues
|
||||
// of the any repository in the organization.
|
||||
func GetOrgAssignees(ctx context.Context, orgID int64) (_ []*user_model.User, err error) {
|
||||
e := db.GetEngine(ctx)
|
||||
userIDs := make([]int64, 0, 10)
|
||||
if err = e.Table("access").
|
||||
Join("INNER", "repository", "`repository`.id = `access`.repo_id").
|
||||
Where("`repository`.owner_id = ? AND `access`.mode >= ?", orgID, perm.AccessModeWrite).
|
||||
Select("user_id").
|
||||
Find(&userIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
additionalUserIDs := make([]int64, 0, 10)
|
||||
if err = e.Table("team_user").
|
||||
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
|
||||
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
|
||||
Join("INNER", "repository", "`repository`.id = `team_repo`.repo_id").
|
||||
Where("`repository`.owner_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
|
||||
orgID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
|
||||
Distinct("`team_user`.uid").
|
||||
Select("`team_user`.uid").
|
||||
Find(&additionalUserIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uniqueUserIDs := make(container.Set[int64])
|
||||
uniqueUserIDs.AddMultiple(userIDs...)
|
||||
uniqueUserIDs.AddMultiple(additionalUserIDs...)
|
||||
|
||||
users := make([]*user_model.User, 0, len(uniqueUserIDs))
|
||||
if len(userIDs) > 0 {
|
||||
if err = e.In("id", uniqueUserIDs.Values()).
|
||||
Where(builder.Eq{"`user`.is_active": true}).
|
||||
OrderBy(user_model.GetOrderByName()).
|
||||
Find(&users); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func loadOrganizationOwners(ctx context.Context, users user_model.UserList, orgID int64) (map[int64]*TeamUser, error) {
|
||||
if len(users) == 0 {
|
||||
return nil, nil
|
||||
|
@ -234,6 +234,7 @@ type FindReleasesOptions struct {
|
||||
IsDraft optional.Option[bool]
|
||||
TagNames []string
|
||||
HasSha1 optional.Option[bool] // useful to find draft releases which are created with existing tags
|
||||
NamePattern optional.Option[string]
|
||||
}
|
||||
|
||||
func (opts FindReleasesOptions) ToConds() builder.Cond {
|
||||
@ -261,6 +262,11 @@ func (opts FindReleasesOptions) ToConds() builder.Cond {
|
||||
cond = cond.And(builder.Eq{"sha1": ""})
|
||||
}
|
||||
}
|
||||
|
||||
if opts.NamePattern.Has() && opts.NamePattern.Value() != "" {
|
||||
cond = cond.And(builder.Like{"lower_tag_name", strings.ToLower(opts.NamePattern.Value())})
|
||||
}
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
|
@ -749,7 +749,7 @@ func GetUserRepositories(ctx context.Context, opts *SearchRepoOptions) (Reposito
|
||||
cond = cond.And(builder.Eq{"is_private": false})
|
||||
}
|
||||
|
||||
if opts.LowerNames != nil && len(opts.LowerNames) > 0 {
|
||||
if len(opts.LowerNames) > 0 {
|
||||
cond = cond.And(builder.In("lower_name", opts.LowerNames))
|
||||
}
|
||||
|
||||
|
@ -14,4 +14,8 @@ const (
|
||||
UserActivityPubPrivPem = "activitypub.priv_pem"
|
||||
// UserActivityPubPubPem is user's public key
|
||||
UserActivityPubPubPem = "activitypub.pub_pem"
|
||||
// SignupIP is the IP address that the user signed up with
|
||||
SignupIP = "signup.ip"
|
||||
// SignupUserAgent is the user agent that the user signed up with
|
||||
SignupUserAgent = "signup.user_agent"
|
||||
)
|
||||
|
@ -150,6 +150,14 @@ type User struct {
|
||||
KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
// Meta defines the meta information of a user, to be stored in the K/V table
|
||||
type Meta struct {
|
||||
// Store the initial registration of the user, to aid in spam prevention
|
||||
// Ensure that one IP isn't creating many accounts (following mediawiki approach)
|
||||
InitialIP string
|
||||
InitialUserAgent string
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(User))
|
||||
}
|
||||
@ -615,17 +623,17 @@ type CreateUserOverwriteOptions struct {
|
||||
}
|
||||
|
||||
// CreateUser creates record of a new user.
|
||||
func CreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
return createUser(ctx, u, false, overwriteDefault...)
|
||||
func CreateUser(ctx context.Context, u *User, meta *Meta, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
return createUser(ctx, u, meta, false, overwriteDefault...)
|
||||
}
|
||||
|
||||
// AdminCreateUser is used by admins to manually create users
|
||||
func AdminCreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
return createUser(ctx, u, true, overwriteDefault...)
|
||||
func AdminCreateUser(ctx context.Context, u *User, meta *Meta, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
return createUser(ctx, u, meta, true, overwriteDefault...)
|
||||
}
|
||||
|
||||
// createUser creates record of a new user.
|
||||
func createUser(ctx context.Context, u *User, createdByAdmin bool, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
|
||||
if err = IsUsableUsername(u.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -745,6 +753,22 @@ func createUser(ctx context.Context, u *User, createdByAdmin bool, overwriteDefa
|
||||
return err
|
||||
}
|
||||
|
||||
if setting.RecordUserSignupMetadata {
|
||||
// insert initial IP and UserAgent
|
||||
if err = SetUserSetting(ctx, u.ID, SignupIP, meta.InitialIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// trim user agent string to a reasonable length, if necessary
|
||||
userAgent := strings.TrimSpace(meta.InitialUserAgent)
|
||||
if len(userAgent) > 255 {
|
||||
userAgent = userAgent[:255]
|
||||
}
|
||||
if err = SetUserSetting(ctx, u.ID, SignupUserAgent, userAgent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// insert email address
|
||||
if err := db.Insert(ctx, &EmailAddress{
|
||||
UID: u.ID,
|
||||
|
@ -227,7 +227,7 @@ func TestCreateUserInvalidEmail(t *testing.T) {
|
||||
MustChangePassword: false,
|
||||
}
|
||||
|
||||
err := user_model.CreateUser(db.DefaultContext, user)
|
||||
err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, user_model.IsErrEmailCharIsNotSupported(err))
|
||||
}
|
||||
@ -241,7 +241,7 @@ func TestCreateUserEmailAlreadyUsed(t *testing.T) {
|
||||
user.Name = "testuser"
|
||||
user.LowerName = strings.ToLower(user.Name)
|
||||
user.ID = 0
|
||||
err := user_model.CreateUser(db.DefaultContext, user)
|
||||
err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, user_model.IsErrEmailAlreadyUsed(err))
|
||||
}
|
||||
@ -258,7 +258,7 @@ func TestCreateUserCustomTimestamps(t *testing.T) {
|
||||
user.ID = 0
|
||||
user.Email = "unique@example.com"
|
||||
user.CreatedUnix = creationTimestamp
|
||||
err := user_model.CreateUser(db.DefaultContext, user)
|
||||
err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
fetched, err := user_model.GetUserByID(context.Background(), user.ID)
|
||||
@ -283,7 +283,7 @@ func TestCreateUserWithoutCustomTimestamps(t *testing.T) {
|
||||
user.Email = "unique@example.com"
|
||||
user.CreatedUnix = 0
|
||||
user.UpdatedUnix = 0
|
||||
err := user_model.CreateUser(db.DefaultContext, user)
|
||||
err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
timestampEnd := time.Now().Unix()
|
||||
|
15
modules/cache/context.go
vendored
15
modules/cache/context.go
vendored
@ -63,9 +63,9 @@ func (cc *cacheContext) isDiscard() bool {
|
||||
}
|
||||
|
||||
// cacheContextLifetime is the max lifetime of cacheContext.
|
||||
// Since cacheContext is used to cache data in a request level context, 10s is enough.
|
||||
// If a cacheContext is used more than 10s, it's probably misuse.
|
||||
const cacheContextLifetime = 10 * time.Second
|
||||
// Since cacheContext is used to cache data in a request level context, 5 minutes is enough.
|
||||
// If a cacheContext is used more than 5 minutes, it's probably misuse.
|
||||
const cacheContextLifetime = 5 * time.Minute
|
||||
|
||||
var timeNow = time.Now
|
||||
|
||||
@ -109,7 +109,8 @@ func WithCacheContext(ctx context.Context) context.Context {
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
return context.WithValue(ctx, cacheContextKey, &cacheContext{
|
||||
// FIXME: review the use of this nolint directive
|
||||
return context.WithValue(ctx, cacheContextKey, &cacheContext{ //nolint:staticcheck
|
||||
data: make(map[any]map[any]any),
|
||||
created: timeNow(),
|
||||
})
|
||||
@ -131,7 +132,7 @@ func GetContextData(ctx context.Context, tp, key any) any {
|
||||
if c.Expired() {
|
||||
// The warning means that the cache context is misused for long-life task,
|
||||
// it can be resolved with WithNoCacheContext(ctx).
|
||||
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
|
||||
log.Warn("cache context is expired, is highly likely to be misused for long-life tasks: %v", c)
|
||||
return nil
|
||||
}
|
||||
return c.Get(tp, key)
|
||||
@ -144,7 +145,7 @@ func SetContextData(ctx context.Context, tp, key, value any) {
|
||||
if c.Expired() {
|
||||
// The warning means that the cache context is misused for long-life task,
|
||||
// it can be resolved with WithNoCacheContext(ctx).
|
||||
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
|
||||
log.Warn("cache context is expired, is highly likely to be misused for long-life tasks: %v", c)
|
||||
return
|
||||
}
|
||||
c.Put(tp, key, value)
|
||||
@ -157,7 +158,7 @@ func RemoveContextData(ctx context.Context, tp, key any) {
|
||||
if c.Expired() {
|
||||
// The warning means that the cache context is misused for long-life task,
|
||||
// it can be resolved with WithNoCacheContext(ctx).
|
||||
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
|
||||
log.Warn("cache context is expired, is highly likely to be misused for long-life tasks: %v", c)
|
||||
return
|
||||
}
|
||||
c.Delete(tp, key)
|
||||
|
2
modules/cache/context_test.go
vendored
2
modules/cache/context_test.go
vendored
@ -45,7 +45,7 @@ func TestWithCacheContext(t *testing.T) {
|
||||
timeNow = now
|
||||
}()
|
||||
timeNow = func() time.Time {
|
||||
return now().Add(10 * time.Second)
|
||||
return now().Add(5 * time.Minute)
|
||||
}
|
||||
v = GetContextData(ctx, field, "my_config1")
|
||||
assert.Nil(t, v)
|
||||
|
@ -114,7 +114,7 @@ type LogNameStatusCommitData struct {
|
||||
// Next returns the next LogStatusCommitData
|
||||
func (g *LogNameStatusRepoParser) Next(treepath string, paths2ids map[string]int, changed []bool, maxpathlen int) (*LogNameStatusCommitData, error) {
|
||||
var err error
|
||||
if g.next == nil || len(g.next) == 0 {
|
||||
if len(g.next) == 0 {
|
||||
g.buffull = false
|
||||
g.next, err = g.rd.ReadSlice('\x00')
|
||||
if err != nil {
|
||||
|
@ -13,11 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// NewDialContext returns a DialContext for Transport, the DialContext will do allow/block list check
|
||||
func NewDialContext(usage string, allowList, blockList *HostMatchList) func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return NewDialContextWithProxy(usage, allowList, blockList, nil)
|
||||
}
|
||||
|
||||
func NewDialContextWithProxy(usage string, allowList, blockList *HostMatchList, proxy *url.URL) func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
func NewDialContext(usage string, allowList, blockList *HostMatchList, proxy *url.URL) func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// How Go HTTP Client works with redirection:
|
||||
// transport.RoundTrip URL=http://domain.com, Host=domain.com
|
||||
// transport.DialContext addrOrHost=domain.com:80
|
||||
|
@ -75,7 +75,8 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
|
||||
w.Header().Set("Etag", etag)
|
||||
}
|
||||
if lastModified != nil && !lastModified.IsZero() {
|
||||
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
|
||||
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||
w.Header().Set("Last-Modified", lastModified.UTC().Format(http.TimeFormat))
|
||||
}
|
||||
|
||||
if len(etag) > 0 {
|
||||
|
@ -79,6 +79,7 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
|
||||
httpcache.SetCacheControlInHeader(header, duration)
|
||||
|
||||
if !opts.LastModified.IsZero() {
|
||||
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +52,6 @@ func getRequestScheme(req *http.Request) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func getForwardedHost(req *http.Request) string {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host
|
||||
return req.Header.Get("X-Forwarded-Host")
|
||||
}
|
||||
|
||||
// GuessCurrentAppURL tries to guess the current full app URL (with sub-path) by http headers. It always has a '/' suffix, exactly the same as setting.AppURL
|
||||
func GuessCurrentAppURL(ctx context.Context) string {
|
||||
return GuessCurrentHostURL(ctx) + setting.AppSubURL + "/"
|
||||
@ -81,11 +76,9 @@ func GuessCurrentHostURL(ctx context.Context) string {
|
||||
if reqScheme == "" {
|
||||
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
|
||||
}
|
||||
reqHost := getForwardedHost(req)
|
||||
if reqHost == "" {
|
||||
reqHost = req.Host
|
||||
}
|
||||
return reqScheme + "://" + reqHost
|
||||
// X-Forwarded-Host has many problems: non-standard, not well-defined (X-Forwarded-Port or not), conflicts with Host header.
|
||||
// So do not use X-Forwarded-Host, just use Host header directly.
|
||||
return reqScheme + "://" + req.Host
|
||||
}
|
||||
|
||||
// MakeAbsoluteURL tries to make a link to an absolute URL:
|
||||
|
@ -70,7 +70,7 @@ func TestMakeAbsoluteURL(t *testing.T) {
|
||||
"X-Forwarded-Proto": {"https"},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, "https://forwarded-host/foo", MakeAbsoluteURL(ctx, "/foo"))
|
||||
assert.Equal(t, "https://user-host/foo", MakeAbsoluteURL(ctx, "/foo"))
|
||||
}
|
||||
|
||||
func TestIsCurrentGiteaSiteURL(t *testing.T) {
|
||||
@ -119,5 +119,6 @@ func TestIsCurrentGiteaSiteURL(t *testing.T) {
|
||||
},
|
||||
})
|
||||
assert.True(t, IsCurrentGiteaSiteURL(ctx, "http://localhost:3000"))
|
||||
assert.True(t, IsCurrentGiteaSiteURL(ctx, "https://forwarded-host"))
|
||||
assert.True(t, IsCurrentGiteaSiteURL(ctx, "https://user-host"))
|
||||
assert.False(t, IsCurrentGiteaSiteURL(ctx, "https://forwarded-host"))
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ func (f *valuedField) Render() string {
|
||||
}
|
||||
|
||||
func (f *valuedField) Value() string {
|
||||
return strings.TrimSpace(f.Get(fmt.Sprintf("form-field-" + f.ID)))
|
||||
return strings.TrimSpace(f.Get(fmt.Sprintf("form-field-%s", f.ID)))
|
||||
}
|
||||
|
||||
func (f *valuedField) Options() []*valuedOption {
|
||||
|
@ -38,7 +38,7 @@ func camoHandleLink(link string) string {
|
||||
if setting.Camo.Enabled {
|
||||
lnkURL, err := url.Parse(link)
|
||||
if err == nil && lnkURL.IsAbs() && !strings.HasPrefix(link, setting.AppURL) &&
|
||||
(setting.Camo.Allways || lnkURL.Scheme != "https") {
|
||||
(setting.Camo.Always || lnkURL.Scheme != "https") {
|
||||
return CamoEncode(link)
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func TestCamoHandleLink(t *testing.T) {
|
||||
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
||||
camoHandleLink("http://testimages.org/img.jpg"))
|
||||
|
||||
setting.Camo.Allways = true
|
||||
setting.Camo.Always = true
|
||||
assert.Equal(t,
|
||||
"https://gitea.com/img.jpg",
|
||||
camoHandleLink("https://gitea.com/img.jpg"))
|
||||
|
@ -38,4 +38,7 @@ type MigrateOptions struct {
|
||||
ReleaseAssets bool
|
||||
MigrateToRepoID int64
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
|
||||
AWSAccessKeyID string
|
||||
AWSSecretAccessKey string
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ type Metadata struct {
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
License Licenses `json:"license,omitempty"`
|
||||
Authors []Author `json:"authors,omitempty"`
|
||||
Bin []string `json:"bin,omitempty"`
|
||||
Autoload map[string]any `json:"autoload,omitempty"`
|
||||
AutoloadDev map[string]any `json:"autoload-dev,omitempty"`
|
||||
Extra map[string]any `json:"extra,omitempty"`
|
||||
|
@ -120,7 +120,7 @@ func (q *baseChannel) RemoveAll(ctx context.Context) error {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
|
||||
for q.c != nil && len(q.c) > 0 {
|
||||
for len(q.c) > 0 {
|
||||
<-q.c
|
||||
}
|
||||
|
||||
|
@ -62,11 +62,11 @@ func (c logCompression) IsValid() bool {
|
||||
}
|
||||
|
||||
func (c logCompression) IsNone() bool {
|
||||
return c == "" || strings.ToLower(string(c)) == "none"
|
||||
return strings.ToLower(string(c)) == "none"
|
||||
}
|
||||
|
||||
func (c logCompression) IsZstd() bool {
|
||||
return strings.ToLower(string(c)) == "zstd"
|
||||
return c == "" || strings.ToLower(string(c)) == "zstd"
|
||||
}
|
||||
|
||||
func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||
|
@ -3,18 +3,28 @@
|
||||
|
||||
package setting
|
||||
|
||||
import "code.gitea.io/gitea/modules/log"
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
var Camo = struct {
|
||||
Enabled bool
|
||||
ServerURL string `ini:"SERVER_URL"`
|
||||
HMACKey string `ini:"HMAC_KEY"`
|
||||
Allways bool
|
||||
Always bool
|
||||
}{}
|
||||
|
||||
func loadCamoFrom(rootCfg ConfigProvider) {
|
||||
mustMapSetting(rootCfg, "camo", &Camo)
|
||||
if Camo.Enabled {
|
||||
oldValue := rootCfg.Section("camo").Key("ALLWAYS").MustString("")
|
||||
if oldValue != "" {
|
||||
log.Warn("camo.ALLWAYS is deprecated, use camo.ALWAYS instead")
|
||||
Camo.Always, _ = strconv.ParseBool(oldValue)
|
||||
}
|
||||
|
||||
if Camo.ServerURL == "" || Camo.HMACKey == "" {
|
||||
log.Fatal(`Camo settings require "SERVER_URL" and HMAC_KEY`)
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ var (
|
||||
DisableQueryAuthToken bool
|
||||
CSRFCookieName = "_csrf"
|
||||
CSRFCookieHTTPOnly = true
|
||||
RecordUserSignupMetadata = false
|
||||
)
|
||||
|
||||
// loadSecret load the secret from ini by uriKey or verbatimKey, only one of them could be set
|
||||
@ -164,6 +165,8 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
|
||||
// TODO: default value should be true in future releases
|
||||
DisableQueryAuthToken = sec.Key("DISABLE_QUERY_AUTH_TOKEN").MustBool(false)
|
||||
|
||||
RecordUserSignupMetadata = sec.Key("RECORD_USER_SIGNUP_METADATA").MustBool(false)
|
||||
|
||||
// warn if the setting is set to false explicitly
|
||||
if sectionHasDisableQueryAuthToken && !DisableQueryAuthToken {
|
||||
log.Warn("Enabling Query API Auth tokens is not recommended. DISABLE_QUERY_AUTH_TOKEN will default to true in gitea 1.23 and will be removed in gitea 1.24.")
|
||||
|
@ -114,7 +114,7 @@ func convertAzureBlobErr(err error) error {
|
||||
if !errors.As(err, &respErr) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf(respErr.ErrorCode)
|
||||
return fmt.Errorf("%s", respErr.ErrorCode)
|
||||
}
|
||||
|
||||
// NewAzureBlobStorage returns a azure blob storage
|
||||
|
@ -291,15 +291,16 @@ type GitServiceType int
|
||||
|
||||
// enumerate all GitServiceType
|
||||
const (
|
||||
NotMigrated GitServiceType = iota // 0 not migrated from external sites
|
||||
PlainGitService // 1 plain git service
|
||||
GithubService // 2 github.com
|
||||
GiteaService // 3 gitea service
|
||||
GitlabService // 4 gitlab service
|
||||
GogsService // 5 gogs service
|
||||
OneDevService // 6 onedev service
|
||||
GitBucketService // 7 gitbucket service
|
||||
CodebaseService // 8 codebase service
|
||||
NotMigrated GitServiceType = iota // 0 not migrated from external sites
|
||||
PlainGitService // 1 plain git service
|
||||
GithubService // 2 github.com
|
||||
GiteaService // 3 gitea service
|
||||
GitlabService // 4 gitlab service
|
||||
GogsService // 5 gogs service
|
||||
OneDevService // 6 onedev service
|
||||
GitBucketService // 7 gitbucket service
|
||||
CodebaseService // 8 codebase service
|
||||
CodeCommitService // 9 codecommit service
|
||||
)
|
||||
|
||||
// Name represents the service type's name
|
||||
@ -325,6 +326,8 @@ func (gt GitServiceType) Title() string {
|
||||
return "GitBucket"
|
||||
case CodebaseService:
|
||||
return "Codebase"
|
||||
case CodeCommitService:
|
||||
return "CodeCommit"
|
||||
case PlainGitService:
|
||||
return "Git"
|
||||
}
|
||||
@ -361,6 +364,9 @@ type MigrateRepoOptions struct {
|
||||
PullRequests bool `json:"pull_requests"`
|
||||
Releases bool `json:"releases"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
|
||||
AWSAccessKeyID string `json:"aws_access_key_id"`
|
||||
AWSSecretAccessKey string `json:"aws_secret_access_key"`
|
||||
}
|
||||
|
||||
// TokenAuth represents whether a service type supports token-based auth
|
||||
@ -382,6 +388,7 @@ var SupportedFullGitService = []GitServiceType{
|
||||
OneDevService,
|
||||
GitBucketService,
|
||||
CodebaseService,
|
||||
CodeCommitService,
|
||||
}
|
||||
|
||||
// RepoTransfer represents a pending repo transfer
|
||||
|
@ -34,7 +34,7 @@ func AvatarHTML(src string, size int, class, name string) template.HTML {
|
||||
name = "avatar"
|
||||
}
|
||||
|
||||
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
return template.HTML(`<img loading="lazy" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||
}
|
||||
|
||||
// Avatar renders user avatars. args: user, size (int), class (string)
|
||||
|
2
options/gitignore/Zig
Normal file
2
options/gitignore/Zig
Normal file
@ -0,0 +1,2 @@
|
||||
.zig-cache/
|
||||
zig-out/
|
14
options/license/Boehm-GC-without-fee
Normal file
14
options/license/Boehm-GC-without-fee
Normal file
@ -0,0 +1,14 @@
|
||||
Copyright (c) 2000
|
||||
SWsoft company
|
||||
|
||||
Modifications copyright (c) 2001, 2013. Oracle and/or its affiliates.
|
||||
All rights reserved.
|
||||
|
||||
This material is provided "as is", with absolutely no warranty expressed
|
||||
or implied. Any use is at your own risk.
|
||||
|
||||
Permission to use or copy this software for any purpose is hereby granted
|
||||
without fee, provided the above notices are retained on all copies.
|
||||
Permission to modify the code and to distribute modified code is granted,
|
||||
provided the above notices are retained, and a notice that the code was
|
||||
modified is included with the above copyright notice.
|
@ -218,8 +218,6 @@ string.desc=Z – A
|
||||
|
||||
[error]
|
||||
occurred=Došlo k chybě
|
||||
missing_csrf=Špatný požadavek: Neexistuje CSRF token
|
||||
invalid_csrf=Špatný požadavek: Neplatný CSRF token
|
||||
not_found=Cíl nebyl nalezen.
|
||||
network_error=Chyba sítě
|
||||
|
||||
@ -1701,7 +1699,6 @@ issues.dependency.add_error_dep_not_same_repo=Oba úkoly musí být ve stejném
|
||||
issues.review.self.approval=Nemůžete schválit svůj pull request.
|
||||
issues.review.self.rejection=Nemůžete požadovat změny ve svém vlastním pull requestu.
|
||||
issues.review.approve=schválil tyto změny %s
|
||||
issues.review.comment=Okomentovat
|
||||
issues.review.dismissed=zamítl/a posouzení od %s %s
|
||||
issues.review.dismissed_label=Zamítnuto
|
||||
issues.review.left_comment=zanechal komentář
|
||||
@ -1726,6 +1723,7 @@ issues.review.hide_resolved=Skrýt vyřešené
|
||||
issues.review.resolve_conversation=Vyřešit konverzaci
|
||||
issues.review.un_resolve_conversation=Nevyřešit konverzaci
|
||||
issues.review.resolved_by=označil tuto konverzaci jako vyřešenou
|
||||
issues.review.commented=Okomentovat
|
||||
issues.assignee.error=Ne všichni zpracovatelé byli přidáni z důvodu neočekávané chyby.
|
||||
issues.reference_issue.body=Tělo zprávy
|
||||
issues.content_history.deleted=vymazáno
|
||||
|
@ -213,8 +213,6 @@ string.desc=Z–A
|
||||
|
||||
[error]
|
||||
occurred=Ein Fehler ist aufgetreten
|
||||
missing_csrf=Fehlerhafte Anfrage: Kein CSRF Token verfügbar
|
||||
invalid_csrf=Fehlerhafte Anfrage: Ungültiger CSRF Token
|
||||
not_found=Das Ziel konnte nicht gefunden werden.
|
||||
network_error=Netzwerkfehler
|
||||
|
||||
@ -1681,7 +1679,6 @@ issues.dependency.add_error_dep_not_same_repo=Beide Issues müssen sich im selbe
|
||||
issues.review.self.approval=Du kannst nicht dein eigenen Pull-Request genehmigen.
|
||||
issues.review.self.rejection=Du kannst keine Änderungen an deinem eigenen Pull-Request anfragen.
|
||||
issues.review.approve=hat die Änderungen %s genehmigt
|
||||
issues.review.comment=Kommentieren
|
||||
issues.review.dismissed=verwarf %ss Review %s
|
||||
issues.review.dismissed_label=Verworfen
|
||||
issues.review.left_comment=hat einen Kommentar hinterlassen
|
||||
@ -1706,6 +1703,7 @@ issues.review.hide_resolved=Gelöste ausblenden
|
||||
issues.review.resolve_conversation=Diskussion als "erledigt" markieren
|
||||
issues.review.un_resolve_conversation=Diskussion als "nicht-erledigt" markieren
|
||||
issues.review.resolved_by=markierte diese Unterhaltung als gelöst
|
||||
issues.review.commented=Kommentieren
|
||||
issues.assignee.error=Aufgrund eines unerwarteten Fehlers konnten nicht alle Beauftragten hinzugefügt werden.
|
||||
issues.reference_issue.body=Beschreibung
|
||||
issues.content_history.deleted=gelöscht
|
||||
|
@ -184,8 +184,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Παρουσιάστηκε ένα σφάλμα
|
||||
missing_csrf=Bad Request: δεν υπάρχει διακριτικό CSRF
|
||||
invalid_csrf=Λάθος Αίτημα: μη έγκυρο διακριτικό CSRF
|
||||
not_found=Ο προορισμός δεν βρέθηκε.
|
||||
network_error=Σφάλμα δικτύου
|
||||
|
||||
@ -1603,7 +1601,6 @@ issues.dependency.add_error_dep_not_same_repo=Και τα δύο ζητήματ
|
||||
issues.review.self.approval=Δεν μπορείτε να εγκρίνετε το δικό σας pull request.
|
||||
issues.review.self.rejection=Δεν μπορείτε να ζητήσετε αλλαγές στο δικό σας pull request.
|
||||
issues.review.approve=ενέκρινε αυτές τις αλλαγές %s
|
||||
issues.review.comment=Σχόλιο
|
||||
issues.review.dismissed=απέρριψε την αξιολόγηση %s %s
|
||||
issues.review.dismissed_label=Απορρίφθηκε
|
||||
issues.review.left_comment=άφησε ένα σχόλιο
|
||||
@ -1628,6 +1625,7 @@ issues.review.hide_resolved=Απόκρυψη επιλυμένων
|
||||
issues.review.resolve_conversation=Επίλυση συνομιλίας
|
||||
issues.review.un_resolve_conversation=Ανεπίλυτη συνομιλία
|
||||
issues.review.resolved_by=σημείωση αυτή την συνομιλία ως επιλυμένη
|
||||
issues.review.commented=Σχόλιο
|
||||
issues.assignee.error=Δεν προστέθηκαν όλοι οι παραλήπτες λόγω απροσδόκητου σφάλματος.
|
||||
issues.reference_issue.body=Σώμα
|
||||
issues.content_history.deleted=διαγράφηκε
|
||||
|
@ -159,6 +159,7 @@ filter.public = Public
|
||||
filter.private = Private
|
||||
|
||||
no_results_found = No results found.
|
||||
internal_error_skipped = Internal error occurred but is skipped: %s
|
||||
|
||||
[search]
|
||||
search = Search...
|
||||
@ -177,6 +178,8 @@ code_search_by_git_grep = Current code search results are provided by "git grep"
|
||||
package_kind = Search packages...
|
||||
project_kind = Search projects...
|
||||
branch_kind = Search branches...
|
||||
tag_kind = Search tags...
|
||||
tag_tooltip = Search for matching tags. Use '%' to match any sequence of numbers.
|
||||
commit_kind = Search commits...
|
||||
runner_kind = Search runners...
|
||||
no_results = No matching results found.
|
||||
@ -219,8 +222,6 @@ string.desc = Z - A
|
||||
[error]
|
||||
occurred = An error occurred
|
||||
report_message = If you believe that this is a Gitea bug, please search for issues on <a href="%s" target="_blank">GitHub</a> or open a new issue if necessary.
|
||||
missing_csrf = Bad Request: no CSRF token present
|
||||
invalid_csrf = Bad Request: invalid CSRF token
|
||||
not_found = The target couldn't be found.
|
||||
network_error = Network error
|
||||
|
||||
@ -1176,6 +1177,11 @@ migrate.gogs.description = Migrate data from notabug.org or other Gogs instances
|
||||
migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
|
||||
migrate.codebase.description = Migrate data from codebasehq.com.
|
||||
migrate.gitbucket.description = Migrate data from GitBucket instances.
|
||||
migrate.codecommit.description = Migrate data from AWS CodeCommit.
|
||||
migrate.codecommit.aws_access_key_id = AWS Access Key ID
|
||||
migrate.codecommit.aws_secret_access_key = AWS Secret Access Key
|
||||
migrate.codecommit.https_git_credentials_username = HTTPS Git Credentials Username
|
||||
migrate.codecommit.https_git_credentials_password = HTTPS Git Credentials Password
|
||||
migrate.migrating_git = Migrating Git Data
|
||||
migrate.migrating_topics = Migrating Topics
|
||||
migrate.migrating_milestones = Migrating Milestones
|
||||
@ -1274,7 +1280,6 @@ commit_graph.color = Color
|
||||
commit.contained_in = This commit is contained in:
|
||||
commit.contained_in_default_branch = This commit is part of the default branch
|
||||
commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit
|
||||
commit.load_tags_failed = Load tags failed because of internal error
|
||||
blame = Blame
|
||||
download_file = Download file
|
||||
normal_view = Normal View
|
||||
@ -1761,7 +1766,7 @@ issues.review.hide_resolved = Hide resolved
|
||||
issues.review.resolve_conversation = Resolve conversation
|
||||
issues.review.un_resolve_conversation = Unresolve conversation
|
||||
issues.review.resolved_by = marked this conversation as resolved
|
||||
issues.review.comment = Comment
|
||||
issues.review.commented = Comment
|
||||
issues.review.official = Approved
|
||||
issues.review.requested = Review pending
|
||||
issues.review.rejected = Changes requested
|
||||
@ -1931,6 +1936,7 @@ pulls.delete.text = Do you really want to delete this pull request? (This will p
|
||||
pulls.recently_pushed_new_branches = You pushed on branch <strong>%[1]s</strong> %[2]s
|
||||
|
||||
pull.deleted_branch = (deleted):%s
|
||||
pull.agit_documentation = Review documentation about AGit
|
||||
|
||||
comments.edit.already_changed = Unable to save changes to the comment. It appears the content has already been changed by another user. Please refresh the page and try editing again to avoid overwriting their changes
|
||||
|
||||
|
@ -182,8 +182,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Ha ocurrido un error
|
||||
missing_csrf=Solicitud incorrecta: sin token CSRF
|
||||
invalid_csrf=Solicitud incorrecta: el token CSRF no es válido
|
||||
not_found=El objetivo no pudo ser encontrado.
|
||||
network_error=Error de red
|
||||
|
||||
@ -1593,7 +1591,6 @@ issues.dependency.add_error_dep_not_same_repo=Ambas incidencias deben estar en e
|
||||
issues.review.self.approval=No puede aprobar su propio pull request.
|
||||
issues.review.self.rejection=No puede sugerir cambios en su propio pull request.
|
||||
issues.review.approve=aprobado estos cambios %s
|
||||
issues.review.comment=Comentario
|
||||
issues.review.dismissed=descartó la revisión de %s %s
|
||||
issues.review.dismissed_label=Descartado
|
||||
issues.review.left_comment=dejó un comentario
|
||||
@ -1618,6 +1615,7 @@ issues.review.hide_resolved=Ocultar resueltos
|
||||
issues.review.resolve_conversation=Resolver conversación
|
||||
issues.review.un_resolve_conversation=Marcar conversación sin resolver
|
||||
issues.review.resolved_by=ha marcado esta conversación como resuelta
|
||||
issues.review.commented=Comentario
|
||||
issues.assignee.error=No todos los asignados fueron añadidos debido a un error inesperado.
|
||||
issues.reference_issue.body=Cuerpo
|
||||
issues.content_history.deleted=borrado
|
||||
|
@ -118,7 +118,6 @@ filter.private=خصوصی
|
||||
[filter]
|
||||
|
||||
[error]
|
||||
missing_csrf=درخواست بد: بلیط CSRF ندارد
|
||||
|
||||
[startpage]
|
||||
app_desc=یک سرویس گیت بیدرد سر و راحت
|
||||
@ -1235,7 +1234,6 @@ issues.dependency.add_error_dep_not_same_repo=هر دو موضوع باید از
|
||||
issues.review.self.approval=شما نمیتوانید تقاضای واکشی خود را تایید کنید.
|
||||
issues.review.self.rejection=شما نمیتوانید تقاضا تغییرات تقاضای واکشی خود را تغییر دهید.
|
||||
issues.review.approve=این تغییرات را تایید شدند %s
|
||||
issues.review.comment=دیدگاه
|
||||
issues.review.dismissed=بررسی %s %s را رد شده
|
||||
issues.review.dismissed_label=رها شده
|
||||
issues.review.left_comment=یک نظر ثبت کرد
|
||||
@ -1256,6 +1254,7 @@ issues.review.hide_resolved=مخفی کردن حل شده ها
|
||||
issues.review.resolve_conversation=مکالمه را بعنوان حل شده علامت گذاری کردن
|
||||
issues.review.un_resolve_conversation=مکالمه را بعنوان حل نشده علامت گذاری کردن
|
||||
issues.review.resolved_by=علامت گذاری این مکالمه بعنوان حل شده
|
||||
issues.review.commented=دیدگاه
|
||||
issues.assignee.error=به دلیل خطای غیرمنتظره همه تکالیف اضافه نشد.
|
||||
issues.reference_issue.body=Body
|
||||
issues.content_history.deleted=حذف شده
|
||||
|
@ -133,8 +133,6 @@ filter.private=Yksityinen
|
||||
|
||||
[error]
|
||||
occurred=Virhe tapahtui
|
||||
missing_csrf=Virheellinen pyyntö: CSRF-tunnusta ei ole olemassa
|
||||
invalid_csrf=Virheellinen pyyntö: Virheellinen CSRF-tunniste
|
||||
not_found=Kohdetta ei löytynyt.
|
||||
network_error=Verkkovirhe
|
||||
|
||||
@ -955,6 +953,7 @@ issues.review.left_comment=jätti kommentin
|
||||
issues.review.pending=Odottaa
|
||||
issues.review.show_resolved=Näytä ratkaisu
|
||||
issues.review.hide_resolved=Piilota ratkaisu
|
||||
issues.review.commented=Kommentoi
|
||||
issues.reference_issue.body=Kuvaus
|
||||
issues.content_history.deleted=poistettu
|
||||
issues.content_history.edited=muokattu
|
||||
|
@ -217,8 +217,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Une erreur s’est produite
|
||||
missing_csrf=Requête incorrecte: aucun jeton CSRF présent
|
||||
invalid_csrf=Requête incorrecte : jeton CSRF invalide
|
||||
not_found=La cible n'a pu être trouvée.
|
||||
network_error=Erreur réseau
|
||||
|
||||
@ -1254,7 +1252,6 @@ commit_graph.color=Couleur
|
||||
commit.contained_in=Cette révision appartient à :
|
||||
commit.contained_in_default_branch=Cette révision appartient à la branche par défaut
|
||||
commit.load_referencing_branches_and_tags=Charger les branches et étiquettes référençant cette révision
|
||||
commit.load_tags_failed=Le chargement des étiquettes a échoué à cause d’une erreur interne
|
||||
blame=Annotations
|
||||
download_file=Télécharger le fichier
|
||||
normal_view=Vue normale
|
||||
@ -1705,7 +1702,6 @@ issues.dependency.add_error_dep_not_same_repo=Les deux tickets doivent être dan
|
||||
issues.review.self.approval=Vous ne pouvez approuver vos propres demandes d'ajout.
|
||||
issues.review.self.rejection=Vous ne pouvez demander de changements sur vos propres demandes de changement.
|
||||
issues.review.approve=a approuvé ces modifications %s.
|
||||
issues.review.comment=Commenter
|
||||
issues.review.dismissed=a révoqué l’évaluation de %s %s.
|
||||
issues.review.dismissed_label=Révoquée
|
||||
issues.review.left_comment=laisser un commentaire
|
||||
@ -1730,6 +1726,7 @@ issues.review.hide_resolved=Réduire
|
||||
issues.review.resolve_conversation=Clore la conversation
|
||||
issues.review.un_resolve_conversation=Rouvrir la conversation
|
||||
issues.review.resolved_by=a marqué cette conversation comme résolue.
|
||||
issues.review.commented=Commenter
|
||||
issues.assignee.error=Tous les assignés n'ont pas été ajoutés en raison d'une erreur inattendue.
|
||||
issues.reference_issue.body=Corps
|
||||
issues.content_history.deleted=a supprimé
|
||||
|
@ -901,13 +901,13 @@ issues.dependency.add_error_dep_issue_not_exist=Függő hibajegy nem létezik.
|
||||
issues.dependency.add_error_dep_not_exist=A függőség nem létezik.
|
||||
issues.dependency.add_error_dep_exists=A függőség már létezik.
|
||||
issues.dependency.add_error_dep_not_same_repo=Mindkét hibajegynek ugyanabban a tárolóban kell lennie.
|
||||
issues.review.comment=Hozzászólás
|
||||
issues.review.reject=%s változtatások kérése
|
||||
issues.review.pending=Függőben
|
||||
issues.review.review=Értékelés
|
||||
issues.review.reviewers=Véleményezők
|
||||
issues.review.show_outdated=Elavultak mutatása
|
||||
issues.review.hide_outdated=Elavultak elrejtése
|
||||
issues.review.commented=Hozzászólás
|
||||
issues.assignee.error=Nem minden megbízott lett hozzáadva egy nem várt hiba miatt.
|
||||
|
||||
|
||||
|
@ -129,8 +129,6 @@ filter.public=Opinbert
|
||||
|
||||
[error]
|
||||
occurred=Villa kom upp
|
||||
missing_csrf=Slæm beiðni: enginn CSRF lykill
|
||||
invalid_csrf=Slæm beiðni: ógildur CSRF lykill
|
||||
not_found=Markmiðið fannst ekki.
|
||||
network_error=Netkerfisvilla
|
||||
|
||||
@ -850,13 +848,13 @@ issues.dependency.remove_header=Fjarlægja Kröfu
|
||||
issues.dependency.add_error_dep_not_exist=Krafa er ekki til.
|
||||
issues.dependency.add_error_dep_exists=Krafa er nú þegar til.
|
||||
issues.review.approve=samþykkti þessar breytingar %s
|
||||
issues.review.comment=Senda Ummæli
|
||||
issues.review.dismissed_label=Hunsað
|
||||
issues.review.left_comment=gerði ummæli
|
||||
issues.review.pending=Í bið
|
||||
issues.review.outdated=Úrelt
|
||||
issues.review.show_outdated=Sýna úrelt
|
||||
issues.review.hide_outdated=Fela úreld
|
||||
issues.review.commented=Senda Ummæli
|
||||
issues.reference_issue.body=Meginmál
|
||||
issues.content_history.deleted=eytt
|
||||
issues.content_history.edited=breytt
|
||||
|
@ -135,8 +135,6 @@ filter.private=Privati
|
||||
|
||||
[error]
|
||||
occurred=Si è verificato un errore
|
||||
missing_csrf=Richiesta errata: nessun token CSRF presente
|
||||
invalid_csrf=Richiesta errata: token CSRF non valido
|
||||
not_found=Il bersaglio non è stato trovato.
|
||||
network_error=Errore di rete
|
||||
|
||||
@ -1331,7 +1329,6 @@ issues.dependency.add_error_dep_not_same_repo=Entrambi i problemi devono essere
|
||||
issues.review.self.approval=Non puoi approvare la tua pull request.
|
||||
issues.review.self.rejection=Non puoi richiedere modifiche sulla tua pull request.
|
||||
issues.review.approve=hanno approvato queste modifiche %s
|
||||
issues.review.comment=Commentare
|
||||
issues.review.dismissed=recensione %s di %s respinta
|
||||
issues.review.dismissed_label=Respinta
|
||||
issues.review.left_comment=lascia un commento
|
||||
@ -1352,6 +1349,7 @@ issues.review.hide_resolved=Nascondi risolte
|
||||
issues.review.resolve_conversation=Risolvi la conversazione
|
||||
issues.review.un_resolve_conversation=Segnala la conversazione come non risolta
|
||||
issues.review.resolved_by=ha contrassegnato questa conversazione come risolta
|
||||
issues.review.commented=Commentare
|
||||
issues.assignee.error=Non tutte le assegnazioni sono state aggiunte a causa di un errore imprevisto.
|
||||
issues.reference_issue.body=Corpo
|
||||
issues.content_history.deleted=eliminato
|
||||
|
@ -159,6 +159,7 @@ filter.public=公開
|
||||
filter.private=プライベート
|
||||
|
||||
no_results_found=見つかりません。
|
||||
internal_error_skipped=内部エラーが発生しましたがスキップされました: %s
|
||||
|
||||
[search]
|
||||
search=検索…
|
||||
@ -177,6 +178,8 @@ code_search_by_git_grep=現在のコード検索は "git grep" によって行
|
||||
package_kind=パッケージを検索...
|
||||
project_kind=プロジェクトを検索...
|
||||
branch_kind=ブランチを検索...
|
||||
tag_kind=タグを検索...
|
||||
tag_tooltip=一致するタグを検索します。任意のシーケンスに一致させるには '%' を使用してください。
|
||||
commit_kind=コミットを検索...
|
||||
runner_kind=ランナーを検索...
|
||||
no_results=一致する結果が見つかりませんでした
|
||||
@ -218,18 +221,20 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=エラーが発生しました
|
||||
missing_csrf=不正なリクエスト: CSRFトークンがありません
|
||||
invalid_csrf=不正なリクエスト: CSRFトークンが無効です
|
||||
report_message=Gitea のバグが疑われる場合は、<a href="%s" target="_blank">GitHub</a>でIssueを検索して、見つからなければ新しいIssueを作成してください。
|
||||
not_found=ターゲットが見つかりませんでした。
|
||||
network_error=ネットワークエラー
|
||||
|
||||
[startpage]
|
||||
app_desc=自分で立てる、超簡単 Git サービス
|
||||
install=簡単インストール
|
||||
install_desc=シンプルに、プラットフォームに応じて<a target="_blank" rel="noopener noreferrer" href="%[1]s">バイナリを実行</a>したり、<a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>で動かしたり、<a target="_blank" rel="noopener noreferrer" href="%[3]s">パッケージ</a>を使うだけ。
|
||||
platform=クロスプラットフォーム
|
||||
platform_desc=Giteaは<a target="_blank" rel="noopener noreferrer" href="%s">Go</a>がコンパイル可能なあらゆる環境で動きます: Windows、macOS、Linux、ARMなど。 あなたの好きなものを選んでください!
|
||||
lightweight=軽量
|
||||
lightweight_desc=Gitea の最小動作要件は小さいため、安価な Raspberry Pi でも動きます。エネルギーを節約しましょう!
|
||||
license=オープンソース
|
||||
license_desc=Go get <a target="_blank" rel="noopener noreferrer" href="%[1]s">%[2]s</a>! このプロジェクトをさらに向上させるため、ぜひ<a target="_blank" rel="noopener noreferrer" href="%[3]s">貢献</a>して参加してください。 貢献者になることを恥ずかしがらないで!
|
||||
|
||||
[install]
|
||||
install=インストール
|
||||
@ -452,6 +457,7 @@ authorize_title=`"%s"にあなたのアカウントへのアクセスを許可
|
||||
authorization_failed=認可失敗
|
||||
authorization_failed_desc=無効なリクエストを検出したため認可が失敗しました。 認可しようとしたアプリの開発者に連絡してください。
|
||||
sspi_auth_failed=SSPI認証に失敗しました
|
||||
password_pwned=あなたが選択したパスワードは、過去の情報漏洩事件で流出した<a target="_blank" rel="noopener noreferrer" href="%s">盗まれたパスワードのリスト</a>に含まれています。 別のパスワードでもう一度試してください。 また他の登録でもこのパスワードからの変更を検討してください。
|
||||
password_pwned_err=HaveIBeenPwnedへのリクエストを完了できませんでした
|
||||
last_admin=最後の管理者は削除できません。少なくとも一人の管理者が必要です。
|
||||
signin_passkey=パスキーでサインイン
|
||||
@ -921,6 +927,7 @@ oauth2_client_secret_hint=このページから移動したりページを更新
|
||||
oauth2_application_edit=編集
|
||||
oauth2_application_create_description=OAuth2アプリケーションで、サードパーティアプリケーションがこのインスタンス上のユーザーアカウントにアクセスできるようになります。
|
||||
oauth2_application_remove_description=OAuth2アプリケーションを削除すると、このインスタンス上の許可されたユーザーアカウントへのアクセスができなくなります。 続行しますか?
|
||||
oauth2_application_locked=設定で有効にされた場合、Giteaは起動時にいくつかのOAuth2アプリケーションを事前登録します。 想定されていない動作を防ぐため、これらは編集も削除もできません。 詳細についてはOAuth2のドキュメントを参照してください。
|
||||
|
||||
authorized_oauth2_applications=許可済みOAuth2アプリケーション
|
||||
authorized_oauth2_applications_description=これらのサードパーティ アプリケーションに、あなたのGiteaアカウントへのアクセスを許可しています。 不要になったアプリケーションはアクセス権を取り消すようにしてください。
|
||||
@ -948,6 +955,7 @@ passcode_invalid=パスコードが間違っています。 再度お試しく
|
||||
twofa_enrolled=あなたのアカウントは正常に登録されました。 一回限りのリカバリキー (%s) は安全な場所に保存してください。 これは二度と表示されません。
|
||||
twofa_failed_get_secret=シークレットが取得できません。
|
||||
|
||||
webauthn_desc=セキュリティキーは暗号化キーを内蔵するハードウェア ・ デバイスです。 2要素認証に使用できます。 セキュリティキーは<a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a>規格をサポートしている必要があります。
|
||||
webauthn_register_key=セキュリティキーを追加
|
||||
webauthn_nickname=ニックネーム
|
||||
webauthn_delete_key=セキュリティキーの登録解除
|
||||
@ -969,7 +977,7 @@ orgs_none=あなたはどの組織のメンバーでもありません。
|
||||
repos_none=あなたはリポジトリを所有していません。
|
||||
|
||||
delete_account=アカウントを削除
|
||||
delete_prompt=この操作により、あなたのユーザーアカウントは恒久的に抹消されます。 取り消すことは<strong>できません</strong>。
|
||||
delete_prompt=この操作により、あなたのユーザーアカウントは恒久的に抹消されます。 元に戻すことは<strong>できません</strong>。
|
||||
delete_with_all_comments=あなたのアカウントは作成からまだ %s 経過していません。 幽霊コメント回避のため、イシューやPRのすべてのコメントは一緒に削除されます。
|
||||
confirm_delete_account=削除の続行
|
||||
delete_account_title=ユーザーアカウントの削除
|
||||
@ -1092,7 +1100,9 @@ tree_path_not_found_branch=パス %[1]s はブランチ %[2]s に存在しませ
|
||||
tree_path_not_found_tag=パス %[1]s はタグ %[2]s に存在しません
|
||||
|
||||
transfer.accept=移転を承認
|
||||
transfer.accept_desc=`"%s" に移転`
|
||||
transfer.reject=移転を拒否
|
||||
transfer.reject_desc=`"%s" への移転をキャンセル`
|
||||
transfer.no_permission_to_accept=この移転を承認する権限がありません。
|
||||
transfer.no_permission_to_reject=この移転を拒否する権限がありません。
|
||||
|
||||
@ -1167,6 +1177,11 @@ migrate.gogs.description=notabug.org やその他の Gogs インスタンスか
|
||||
migrate.onedev.description=code.onedev.io やその他の OneDev インスタンスからデータを移行します。
|
||||
migrate.codebase.description=codebasehq.com からデータを移行します。
|
||||
migrate.gitbucket.description=GitBucket インスタンスからデータを移行します。
|
||||
migrate.codecommit.description=AWS CodeCommitからデータを移行します。
|
||||
migrate.codecommit.aws_access_key_id=AWS アクセスキー ID
|
||||
migrate.codecommit.aws_secret_access_key=AWSシークレットアクセスキー
|
||||
migrate.codecommit.https_git_credentials_username=HTTPS Git 認証情報 ユーザー名
|
||||
migrate.codecommit.https_git_credentials_password=HTTPS Git 認証情報 パスワード
|
||||
migrate.migrating_git=Gitデータ移行中
|
||||
migrate.migrating_topics=トピック移行中
|
||||
migrate.migrating_milestones=マイルストーン移行中
|
||||
@ -1227,6 +1242,7 @@ releases=リリース
|
||||
tag=タグ
|
||||
released_this=がこれをリリース
|
||||
tagged_this=がタグ付け
|
||||
file.title=%s at %s
|
||||
file_raw=Raw
|
||||
file_history=履歴
|
||||
file_view_source=ソースを表示
|
||||
@ -1243,6 +1259,7 @@ ambiguous_runes_header=このファイルには曖昧(ambiguous)なUnicode文字
|
||||
ambiguous_runes_description=このファイルには、他の文字と見間違える可能性があるUnicode文字が含まれています。 それが意図的なものと考えられる場合は、この警告を無視して構いません。 それらの文字を表示するにはエスケープボタンを使用します。
|
||||
invisible_runes_line=`この行には不可視のUnicode文字があります`
|
||||
ambiguous_runes_line=`この行には曖昧(ambiguous)なUnicode文字があります`
|
||||
ambiguous_character=`%[1]c [U+%04[1]X] は %[2]c [U+%04[2]X] と混同するおそれがあります`
|
||||
|
||||
escape_control_characters=エスケープ
|
||||
unescape_control_characters=エスケープ解除
|
||||
@ -1263,7 +1280,6 @@ commit_graph.color=カラー
|
||||
commit.contained_in=このコミットが含まれているのは:
|
||||
commit.contained_in_default_branch=このコミットはデフォルトブランチに含まれています
|
||||
commit.load_referencing_branches_and_tags=このコミットを参照しているブランチやタグを取得
|
||||
commit.load_tags_failed=内部エラーによりタグの読み込みに失敗しました
|
||||
blame=Blame
|
||||
download_file=ファイルをダウンロード
|
||||
normal_view=通常表示
|
||||
@ -1715,7 +1731,7 @@ issues.dependency.add_error_dep_not_same_repo=両方とも同じリポジトリ
|
||||
issues.review.self.approval=自分のプルリクエストを承認することはできません。
|
||||
issues.review.self.rejection=自分のプルリクエストに対して修正を要求することはできません。
|
||||
issues.review.approve=が変更を承認 %s
|
||||
issues.review.comment=コメント
|
||||
issues.review.comment=がレビュー %s
|
||||
issues.review.dismissed=が %s のレビューを棄却 %s
|
||||
issues.review.dismissed_label=棄却
|
||||
issues.review.left_comment=がコメント
|
||||
@ -1740,6 +1756,12 @@ issues.review.hide_resolved=解決済みを隠す
|
||||
issues.review.resolve_conversation=解決済みにする
|
||||
issues.review.un_resolve_conversation=未解決にする
|
||||
issues.review.resolved_by=がこの会話を解決済みにしました
|
||||
issues.review.commented=コメント
|
||||
issues.review.official=承認済み
|
||||
issues.review.requested=レビュー待ち
|
||||
issues.review.rejected=変更要請済み
|
||||
issues.review.stale=承認後に更新されました
|
||||
issues.review.unofficial=カウントされない承認
|
||||
issues.assignee.error=予期しないエラーにより、一部の担当者を追加できませんでした。
|
||||
issues.reference_issue.body=内容
|
||||
issues.content_history.deleted=削除しました
|
||||
@ -1813,6 +1835,8 @@ pulls.is_empty=このブランチの変更は既にターゲットブランチ
|
||||
pulls.required_status_check_failed=いくつかの必要なステータスチェックが成功していません。
|
||||
pulls.required_status_check_missing=必要なチェックがいくつか抜けています。
|
||||
pulls.required_status_check_administrator=管理者であるため、このプルリクエストをマージすることは可能です。
|
||||
pulls.blocked_by_approvals=このプルリクエストはまだ必要な承認数を満たしていません。 公式の承認を %[1]d / %[2]d 得ています。
|
||||
pulls.blocked_by_approvals_whitelisted=このプルリクエストはまだ必要な承認数を満たしていません。 許可リストのユーザーまたはチームからの承認を %[1]d / %[2]d 得ています。
|
||||
pulls.blocked_by_rejection=このプルリクエストは公式レビューアにより変更要請されています。
|
||||
pulls.blocked_by_official_review_requests=このプルリクエストには公式レビュー依頼があります。
|
||||
pulls.blocked_by_outdated_branch=このプルリクエストは遅れのためブロックされています。
|
||||
@ -1854,7 +1878,9 @@ pulls.unrelated_histories=マージ失敗: マージHEADとベースには共通
|
||||
pulls.merge_out_of_date=マージ失敗: マージの生成中にベースが更新されました。 ヒント: もう一度試してみてください
|
||||
pulls.head_out_of_date=マージ失敗: マージの生成中に head が更新されました。 ヒント: もう一度試してみてください
|
||||
pulls.has_merged=失敗: プルリクエストはマージされていました。再度マージしたり、ターゲットブランチを変更することはできません。
|
||||
pulls.push_rejected=プッシュ失敗: プッシュは拒否されました。 このリポジトリのGitフックを見直してください。
|
||||
pulls.push_rejected_summary=拒否メッセージ全体:
|
||||
pulls.push_rejected_no_message=プッシュ失敗: プッシュは拒否されましたが、リモートからのメッセージがありません。このリポジトリのGitフックを見直してください
|
||||
pulls.open_unmerged_pull_exists=`同じ条件のプルリクエスト (#%d) が未処理のため、再オープンはできません。`
|
||||
pulls.status_checking=いくつかのステータスチェックが待機中です
|
||||
pulls.status_checks_success=ステータスチェックはすべて成功しました
|
||||
@ -1910,6 +1936,7 @@ milestones.no_due_date=期日なし
|
||||
milestones.open=オープン
|
||||
milestones.close=クローズ
|
||||
milestones.new_subheader=マイルストーンを使うとイシューの整理や進捗確認がしやすくなります。
|
||||
milestones.completeness=<strong>%d%%</strong>消化
|
||||
milestones.create=マイルストーンを作成
|
||||
milestones.title=タイトル
|
||||
milestones.desc=説明
|
||||
@ -2309,6 +2336,7 @@ settings.event_pull_request_merge=プルリクエストのマージ
|
||||
settings.event_package=パッケージ
|
||||
settings.event_package_desc=リポジトリにパッケージが作成または削除されたとき。
|
||||
settings.branch_filter=ブランチ フィルター
|
||||
settings.branch_filter_desc=プッシュ、ブランチ作成、ブランチ削除のイベントを通知するブランチを、globパターンで指定するホワイトリストです。 空か<code>*</code>のときは、すべてのブランチのイベントを通知します。 文法については <a href="%[1]s">%[2]s</a> を参照してください。 例: <code>master</code> 、 <code>{master,release*}</code>
|
||||
settings.authorization_header=Authorizationヘッダー
|
||||
settings.authorization_header_desc=入力した場合、リクエストにAuthorizationヘッダーとして付加します。 例: %s
|
||||
settings.active=有効
|
||||
@ -2359,6 +2387,7 @@ settings.protected_branch.save_rule=ルールを保存
|
||||
settings.protected_branch.delete_rule=ルールを削除
|
||||
settings.protected_branch_can_push=プッシュを許可する
|
||||
settings.protected_branch_can_push_yes=プッシュできます
|
||||
settings.protected_branch_can_push_no=プッシュできません
|
||||
settings.branch_protection=ブランチ '<b>%s</b>' の保護ルール
|
||||
settings.protect_this_branch=ブランチの保護を有効にする
|
||||
settings.protect_this_branch_desc=ブランチの削除を防ぎ、ブランチへのプッシュやマージを制限します。
|
||||
@ -2395,6 +2424,7 @@ settings.protect_status_check_matched=マッチ
|
||||
settings.protect_invalid_status_check_pattern=`不正なステータスチェックパターン: "%s"`
|
||||
settings.protect_no_valid_status_check_patterns=有効なステータスチェックパターンがありません。
|
||||
settings.protect_required_approvals=必要な承認数:
|
||||
settings.protect_required_approvals_desc=必要な承認数を満たしたプルリクエストしかマージできないようにします。 必要となる承認とは、許可リストにあるユーザーやチーム、もしくは書き込み権限を持つ誰かからのものです。
|
||||
settings.protect_approvals_whitelist_enabled=許可リストに登録したユーザーやチームに承認を制限
|
||||
settings.protect_approvals_whitelist_enabled_desc=許可リストに登録したユーザーまたはチームによるレビューのみを、必要な承認数にカウントします。 承認の許可リストが無い場合は、書き込み権限を持つ人によるレビューを必要な承認数にカウントします。
|
||||
settings.protect_approvals_whitelist_users=許可リストに含めるレビューア:
|
||||
@ -2406,9 +2436,12 @@ settings.ignore_stale_approvals_desc=古いコミットに対して行われた
|
||||
settings.require_signed_commits=コミット署名必須
|
||||
settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。
|
||||
settings.protect_branch_name_pattern=保護ブランチ名のパターン
|
||||
settings.protect_branch_name_pattern_desc=保護ブランチ名のパターン。書き方については <a href="%s">ドキュメント</a> を参照してください。例: main, release/**
|
||||
settings.protect_patterns=パターン
|
||||
settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン';'で区切る):
|
||||
settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン(';')で区切って複数のパターンを指定できます。 パターンの文法については <a href='%[1]s'>%[2]s</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
|
||||
settings.protect_unprotected_file_patterns=保護しないファイルのパターン (セミコロン';'で区切る):
|
||||
settings.protect_unprotected_file_patterns_desc=保護しないファイルは、ユーザーに書き込み権限があればプッシュ制限をバイパスして直接変更できます。 セミコロン(';')で区切って複数のパターンを指定できます。 パターンの文法については <a href='%[1]s'>%[2]s</a> を参照してください。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
|
||||
settings.add_protected_branch=保護を有効にする
|
||||
settings.delete_protected_branch=保護を無効にする
|
||||
settings.update_protect_branch_success=ルール "%s" に対するブランチ保護を更新しました。
|
||||
@ -2440,6 +2473,7 @@ settings.tags.protection.allowed.teams=許可するチーム
|
||||
settings.tags.protection.allowed.noone=なし
|
||||
settings.tags.protection.create=タグを保護
|
||||
settings.tags.protection.none=タグは保護されていません。
|
||||
settings.tags.protection.pattern.description=ひとつのタグ名か、複数のタグにマッチするglobパターンまたは正規表現を使用できます。 詳しくは<a target="_blank" rel="noopener" href="%s">タグの保護ガイド</a> をご覧ください。
|
||||
settings.bot_token=Botトークン
|
||||
settings.chat_id=チャットID
|
||||
settings.thread_id=スレッドID
|
||||
@ -2654,6 +2688,7 @@ tag.create_success=タグ "%s" を作成しました。
|
||||
|
||||
topic.manage_topics=トピックの管理
|
||||
topic.done=完了
|
||||
topic.count_prompt=選択できるのは25トピックまでです。
|
||||
topic.format_prompt=トピック名は英字または数字で始め、ダッシュ('-')やドット('.')を含めることができます。最大35文字までです。文字は小文字でなければなりません。
|
||||
|
||||
find_file.go_to_file=ファイルへ移動
|
||||
@ -2722,7 +2757,7 @@ settings.change_orgname_redirect_prompt=古い名前は、再使用されてい
|
||||
settings.update_avatar_success=組織のアバターを更新しました。
|
||||
settings.delete=組織を削除
|
||||
settings.delete_account=この組織を削除
|
||||
settings.delete_prompt=組織は恒久的に削除され、元に戻すことは<strong>できません</strong>。 続行しますか?
|
||||
settings.delete_prompt=組織は恒久的に削除されます。 元に戻すことは<strong>できません</strong>!
|
||||
settings.confirm_delete_account=削除を確認
|
||||
settings.delete_org_title=組織の削除
|
||||
settings.delete_org_desc=組織を恒久的に削除します。 続行しますか?
|
||||
@ -2751,6 +2786,7 @@ teams.leave.detail=%s から脱退しますか?
|
||||
teams.can_create_org_repo=リポジトリを作成
|
||||
teams.can_create_org_repo_helper=メンバーは組織のリポジトリを新たに作成できます。作成者には新しいリポジトリの管理者権限が与えられます。
|
||||
teams.none_access=アクセスなし
|
||||
teams.none_access_helper=メンバーは、このユニットを表示したり他の操作を行うことはできません。 公開リポジトリには適用されません。
|
||||
teams.general_access=一般的なアクセス
|
||||
teams.general_access_helper=メンバーの権限は下記の権限テーブルで決定されます。
|
||||
teams.read_access=読み取り
|
||||
@ -2819,6 +2855,7 @@ last_page=最後
|
||||
total=合計: %d
|
||||
settings=管理設定
|
||||
|
||||
dashboard.new_version_hint=Gitea %s が入手可能になりました。 現在実行しているのは %s です。 詳細は <a target="_blank" rel="noreferrer" href="%s">ブログ</a> を確認してください。
|
||||
dashboard.statistic=サマリー
|
||||
dashboard.maintenance_operations=メンテナンス操作
|
||||
dashboard.system_status=システム状況
|
||||
@ -3010,10 +3047,12 @@ packages.size=サイズ
|
||||
packages.published=配布
|
||||
|
||||
defaulthooks=デフォルトWebhook
|
||||
defaulthooks.desc=Webhookは、特定のGiteaイベントが発生したときに、サーバーにHTTP POSTリクエストを自動的に送信するものです。 ここで定義したWebhookはデフォルトとなり、全ての新規リポジトリにコピーされます。 詳しくは<a target="_blank" rel="noopener" href="%s">Webhooksガイド</a>をご覧下さい。
|
||||
defaulthooks.add_webhook=デフォルトWebhookの追加
|
||||
defaulthooks.update_webhook=デフォルトWebhookの更新
|
||||
|
||||
systemhooks=システムWebhook
|
||||
systemhooks.desc=Webhookは、特定のGiteaイベントが発生したときに、サーバーにHTTP POSTリクエストを自動的に送信するものです。 ここで定義したWebhookは、システム内のすべてのリポジトリで呼び出されます。 そのため、パフォーマンスに及ぼす影響を考慮したうえで設定してください。 詳しくは<a target="_blank" rel="noopener" href="%s">Webhooksガイド</a>をご覧下さい。
|
||||
systemhooks.add_webhook=システムWebhookを追加
|
||||
systemhooks.update_webhook=システムWebhookを更新
|
||||
|
||||
@ -3108,8 +3147,18 @@ auths.tips=ヒント
|
||||
auths.tips.oauth2.general=OAuth2認証
|
||||
auths.tips.oauth2.general.tip=新しいOAuth2認証を登録するときは、コールバック/リダイレクトURLは以下になります:
|
||||
auths.tip.oauth2_provider=OAuth2プロバイダー
|
||||
auths.tip.bitbucket=新しいOAuthコンシューマーを %s から登録し、"アカウント" に "読み取り" 権限を追加してください。
|
||||
auths.tip.nextcloud=新しいOAuthコンシューマーを、インスタンスのメニュー "Settings -> Security -> OAuth 2.0 client" から登録してください。
|
||||
auths.tip.dropbox=新しいアプリケーションを %s から登録してください。
|
||||
auths.tip.facebook=新しいアプリケーションを %s で登録し、"Facebook Login"を追加してください。
|
||||
auths.tip.github=新しいOAuthアプリケーションを %s から登録してください。
|
||||
auths.tip.gitlab_new=新しいアプリケーションを %s から登録してください。
|
||||
auths.tip.google_plus=OAuth2クライアント資格情報を、Google APIコンソール %s から取得してください。
|
||||
auths.tip.openid_connect=OpenID Connect DiscoveryのURL "https://{server}/.well-known/openid-configuration" をエンドポイントとして指定してください
|
||||
auths.tip.twitter=%s へアクセスしてアプリケーションを作成し、“Allow this application to be used to Sign in with Twitter”オプションを有効にしてください。
|
||||
auths.tip.discord=新しいアプリケーションを %s から登録してください。
|
||||
auths.tip.gitea=新しいOAuthアプリケーションを登録してください。 利用ガイドは %s にあります
|
||||
auths.tip.yandex=`%s で新しいアプリケーションを作成してください。 "Yandex.Passport API" セクションで次の項目を許可します: "Access to email address"、"Access to user avatar"、"Access to username, first name and surname, gender"`
|
||||
auths.tip.mastodon=認証したいMastodonインスタンスのカスタムURLを入力してください (入力しない場合はデフォルトのURLを使用します)
|
||||
auths.edit=認証ソースの編集
|
||||
auths.activated=認証ソースはアクティベート済み
|
||||
@ -3275,6 +3324,7 @@ monitor.next=次回
|
||||
monitor.previous=前回
|
||||
monitor.execute_times=実行回数
|
||||
monitor.process=実行中のプロセス
|
||||
monitor.stacktrace=スタックトレース
|
||||
monitor.processes_count=%d プロセス
|
||||
monitor.download_diagnosis_report=診断レポートをダウンロード
|
||||
monitor.desc=説明
|
||||
@ -3282,6 +3332,8 @@ monitor.start=開始日時
|
||||
monitor.execute_time=実行時間
|
||||
monitor.last_execution_result=結果
|
||||
monitor.process.cancel=処理をキャンセル
|
||||
monitor.process.cancel_desc=処理をキャンセルするとデータが失われる可能性があります
|
||||
monitor.process.cancel_notices=キャンセル: <strong>%s</strong>?
|
||||
monitor.process.children=子プロセス
|
||||
|
||||
monitor.queues=キュー
|
||||
@ -3383,6 +3435,7 @@ raw_minutes=分
|
||||
|
||||
[dropzone]
|
||||
default_message=ファイルをここにドロップ、またはここをクリックしてアップロード
|
||||
invalid_input_type=この種類のファイルはアップロードできません。
|
||||
file_too_big=アップロードされたファイルのサイズ ({{filesize}} MB) は、最大サイズ ({{maxFilesize}} MB) を超えています。
|
||||
remove_file=ファイル削除
|
||||
|
||||
@ -3530,6 +3583,7 @@ settings.link=このパッケージをリポジトリにリンク
|
||||
settings.link.description=パッケージをリポジトリにリンクすると、リポジトリのパッケージリストに表示されるようになります。
|
||||
settings.link.select=リポジトリを選択
|
||||
settings.link.button=リポジトリのリンクを更新
|
||||
settings.link.success=リポジトリのリンクが正常に更新されました。
|
||||
settings.link.error=リポジトリのリンクの更新に失敗しました。
|
||||
settings.delete=パッケージ削除
|
||||
settings.delete.description=パッケージの削除は恒久的で元に戻すことはできません。
|
||||
|
@ -818,12 +818,12 @@ issues.dependency.add_error_dep_not_same_repo=두 이슈는 같은 레포지토
|
||||
issues.review.self.approval=자신의 풀 리퀘스트를 승인할 수 없습니다.
|
||||
issues.review.self.rejection=자신의 풀 리퀘스트에 대한 변경을 요청할 수 없습니다.
|
||||
issues.review.approve="이 변경사항을 승인하였습니다. %s"
|
||||
issues.review.comment=댓글
|
||||
issues.review.pending=보류
|
||||
issues.review.review=검토
|
||||
issues.review.reviewers=리뷰어
|
||||
issues.review.show_outdated=오래된 내역 보기
|
||||
issues.review.hide_outdated=오래된 내역 숨기기
|
||||
issues.review.commented=댓글
|
||||
|
||||
|
||||
pulls.new=새 풀 리퀘스트
|
||||
|
@ -187,8 +187,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Radusies kļūda
|
||||
missing_csrf=Kļūdains pieprasījums: netika iesūtīta drošības pilnvara
|
||||
invalid_csrf=Kļūdains pieprasījums: iesūtīta kļūdaina drošības pilnvara
|
||||
not_found=Pieprasītie dati netika atrasti.
|
||||
network_error=Tīkla kļūda
|
||||
|
||||
@ -1609,7 +1607,6 @@ issues.dependency.add_error_dep_not_same_repo=Abām problēmām ir jābūt no vi
|
||||
issues.review.self.approval=Nevar apstiprināt savu izmaiņu pieprasījumi.
|
||||
issues.review.self.rejection=Nevar pieprasīt izmaiņas savam izmaiņu pieprasījumam.
|
||||
issues.review.approve=apstiprināja izmaiņas %s
|
||||
issues.review.comment=Komentēt
|
||||
issues.review.dismissed=atmeta %s recenziju %s
|
||||
issues.review.dismissed_label=Atmesta
|
||||
issues.review.left_comment=atstāja komentāru
|
||||
@ -1634,6 +1631,7 @@ issues.review.hide_resolved=Paslēpt atrisināto
|
||||
issues.review.resolve_conversation=Atrisināt sarunu
|
||||
issues.review.un_resolve_conversation=Atcelt sarunas atrisinājumu
|
||||
issues.review.resolved_by=atzīmēja sarunu kā atrisinātu
|
||||
issues.review.commented=Komentēt
|
||||
issues.assignee.error=Ne visi atbildīgie tika pievienoti, jo radās neparedzēta kļūda.
|
||||
issues.reference_issue.body=Saturs
|
||||
issues.content_history.deleted=dzēsts
|
||||
|
@ -134,8 +134,6 @@ filter.private=Prive
|
||||
|
||||
[error]
|
||||
occurred=Er is een fout opgetreden
|
||||
missing_csrf=Foutief verzoek: geen CSRF-token aanwezig
|
||||
invalid_csrf=Verkeerd verzoek: ongeldig CSRF-token
|
||||
not_found=Het doel kon niet worden gevonden.
|
||||
network_error=Netwerk fout
|
||||
|
||||
@ -1328,7 +1326,6 @@ issues.dependency.add_error_dep_not_same_repo=Beide kwesties moeten in dezelfde
|
||||
issues.review.self.approval=Je kan je eigen pull-aanvraag niet goedkeuren.
|
||||
issues.review.self.rejection=Je kan geen wijzigingen aanvragen op je eigen pull-aanvraag.
|
||||
issues.review.approve=heeft deze veranderingen %s goedgekeurd
|
||||
issues.review.comment=Opmerking
|
||||
issues.review.dismissed=%s's beoordeling afgewezen %s
|
||||
issues.review.dismissed_label=Afgewezen
|
||||
issues.review.left_comment=heeft een reactie achtergelaten
|
||||
@ -1349,6 +1346,7 @@ issues.review.hide_resolved=Verbergen afgehandeld
|
||||
issues.review.resolve_conversation=Gesprek oplossen
|
||||
issues.review.un_resolve_conversation=Gesprek niet oplossen
|
||||
issues.review.resolved_by=markeerde dit gesprek als opgelost
|
||||
issues.review.commented=Opmerking
|
||||
issues.assignee.error=Niet alle aangewezen personen zijn toegevoegd vanwege een onverwachte fout.
|
||||
issues.reference_issue.body=Inhoud
|
||||
issues.content_history.deleted=verwijderd
|
||||
|
@ -131,8 +131,6 @@ filter.private=Prywatne
|
||||
|
||||
[error]
|
||||
occurred=Wystąpił błąd
|
||||
missing_csrf=Błędne żądanie: brak tokenu CSRF
|
||||
invalid_csrf=Błędne żądanie: nieprawidłowy token CSRF
|
||||
not_found=Nie można odnaleźć celu.
|
||||
network_error=Błąd sieci
|
||||
|
||||
@ -1220,7 +1218,6 @@ issues.dependency.add_error_dep_not_same_repo=Oba zgłoszenia muszą być w tym
|
||||
issues.review.self.approval=Nie możesz zatwierdzić swojego własnego Pull Requesta.
|
||||
issues.review.self.rejection=Nie możesz zażądać zmian w swoim własnym Pull Requeście.
|
||||
issues.review.approve=zatwierdza te zmiany %s
|
||||
issues.review.comment=Skomentuj
|
||||
issues.review.dismissed_label=Odrzucony
|
||||
issues.review.left_comment=zostawił komentarz
|
||||
issues.review.content.empty=Musisz pozostawić komentarz o pożądanej zmianie/zmianach.
|
||||
@ -1240,6 +1237,7 @@ issues.review.hide_resolved=Ukryj rozwiązane
|
||||
issues.review.resolve_conversation=Rozwiąż dyskusję
|
||||
issues.review.un_resolve_conversation=Oznacz dyskusję jako nierozstrzygniętą
|
||||
issues.review.resolved_by=oznaczył(-a) tę rozmowę jako rozwiązaną
|
||||
issues.review.commented=Skomentuj
|
||||
issues.assignee.error=Nie udało się dodać wszystkich wybranych osób do przypisanych przez nieoczekiwany błąd.
|
||||
issues.reference_issue.body=Treść
|
||||
issues.content_history.edited=edytowano
|
||||
|
@ -184,8 +184,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Ocorreu um erro
|
||||
missing_csrf=Pedido inválido: não tem token CSRF presente
|
||||
invalid_csrf=Requisição Inválida: token CSRF inválido
|
||||
not_found=Não foi possível encontrar o destino.
|
||||
network_error=Erro de rede
|
||||
|
||||
@ -1599,7 +1597,6 @@ issues.dependency.add_error_dep_not_same_repo=Ambas as issues devem estar no mes
|
||||
issues.review.self.approval=Você não pode aprovar o seu próprio pull request.
|
||||
issues.review.self.rejection=Você não pode solicitar alterações em seu próprio pull request.
|
||||
issues.review.approve=aprovou estas alterações %s
|
||||
issues.review.comment=Comentar
|
||||
issues.review.dismissed=rejeitou a revisão de %s %s
|
||||
issues.review.dismissed_label=Rejeitada
|
||||
issues.review.left_comment=deixou um comentário
|
||||
@ -1624,6 +1621,7 @@ issues.review.hide_resolved=Ocultar resolvidas
|
||||
issues.review.resolve_conversation=Resolver conversa
|
||||
issues.review.un_resolve_conversation=Conversa não resolvida
|
||||
issues.review.resolved_by=marcou esta conversa como resolvida
|
||||
issues.review.commented=Comentar
|
||||
issues.assignee.error=Nem todos os responsáveis foram adicionados devido a um erro inesperado.
|
||||
issues.reference_issue.body=Conteúdo
|
||||
issues.content_history.deleted=excluído
|
||||
|
@ -159,6 +159,7 @@ filter.public=Público
|
||||
filter.private=Privado
|
||||
|
||||
no_results_found=Não foram encontrados quaisquer resultados.
|
||||
internal_error_skipped=Ocorreu um erro interno mas foi ignorado: %s
|
||||
|
||||
[search]
|
||||
search=Pesquisar...
|
||||
@ -177,6 +178,8 @@ code_search_by_git_grep=Os resultados da pesquisa no código-fonte neste momento
|
||||
package_kind=Pesquisar pacotes...
|
||||
project_kind=Pesquisar planeamentos...
|
||||
branch_kind=Pesquisar ramos...
|
||||
tag_kind=Pesquisar etiquetas...
|
||||
tag_tooltip=Pesquisar etiquetas correspondentes. Use '%' para corresponder a qualquer sequência de números.
|
||||
commit_kind=Pesquisar cometimentos...
|
||||
runner_kind=Pesquisar executores...
|
||||
no_results=Não foram encontrados resultados correspondentes.
|
||||
@ -219,8 +222,6 @@ string.desc=Z - A
|
||||
[error]
|
||||
occurred=Ocorreu um erro
|
||||
report_message=Se acredita tratar-se de um erro do Gitea, procure questões relacionadas no <a href="%s">GitHub</a> ou abra uma nova questão, se necessário.
|
||||
missing_csrf=Pedido inválido: não há código CSRF
|
||||
invalid_csrf=Pedido inválido: código CSRF inválido
|
||||
not_found=Não foi possível encontrar o destino.
|
||||
network_error=Erro de rede
|
||||
|
||||
@ -1176,6 +1177,11 @@ migrate.gogs.description=Migrar dados de notabug.org ou de outras instâncias do
|
||||
migrate.onedev.description=Migrar dados de code.onedev.io ou de outras instâncias do OneDev.
|
||||
migrate.codebase.description=Migrar dados de codebasehq.com.
|
||||
migrate.gitbucket.description=Migrar dados de instâncias do GitBucket.
|
||||
migrate.codecommit.description=Migrar dados de AWS CodeCommit.
|
||||
migrate.codecommit.aws_access_key_id=ID da chave de acesso AWS
|
||||
migrate.codecommit.aws_secret_access_key=Chave de acesso secreto AWS
|
||||
migrate.codecommit.https_git_credentials_username=Nome de utilizador das credenciais Git para HTTPS
|
||||
migrate.codecommit.https_git_credentials_password=Senha das credenciais Git para HTTPS
|
||||
migrate.migrating_git=Migrando dados Git
|
||||
migrate.migrating_topics=Migrando tópicos
|
||||
migrate.migrating_milestones=Migrando etapas
|
||||
@ -1274,7 +1280,6 @@ commit_graph.color=Colorido
|
||||
commit.contained_in=Este cometimento está contido em:
|
||||
commit.contained_in_default_branch=Este cometimento é parte do ramo principal
|
||||
commit.load_referencing_branches_and_tags=Carregar ramos e etiquetas que referenciem este cometimento
|
||||
commit.load_tags_failed=O carregamento das etiquetas falhou por causa de um erro interno
|
||||
blame=Responsabilidade
|
||||
download_file=Descarregar ficheiro
|
||||
normal_view=Vista normal
|
||||
@ -1726,7 +1731,7 @@ issues.dependency.add_error_dep_not_same_repo=Ambas as questões têm que estar
|
||||
issues.review.self.approval=Não pode aprovar o seu próprio pedido de integração.
|
||||
issues.review.self.rejection=Não pode solicitar modificações sobre o seu próprio pedido de integração.
|
||||
issues.review.approve=aprovou estas modificações %s
|
||||
issues.review.comment=Comentar
|
||||
issues.review.comment=reviu %s
|
||||
issues.review.dismissed=descartou a revisão de %s %s
|
||||
issues.review.dismissed_label=Descartada
|
||||
issues.review.left_comment=deixou um comentário
|
||||
@ -1751,6 +1756,7 @@ issues.review.hide_resolved=Ocultar os concluídos
|
||||
issues.review.resolve_conversation=Passar diálogo ao estado de resolvido
|
||||
issues.review.un_resolve_conversation=Passar diálogo ao estado de não resolvido
|
||||
issues.review.resolved_by=marcou este diálogo como estando concluído
|
||||
issues.review.commented=Comentar
|
||||
issues.review.official=Aprovada
|
||||
issues.review.requested=Revisão pendente
|
||||
issues.review.rejected=Modificações solicitadas
|
||||
|
@ -182,8 +182,6 @@ string.desc=Я - А
|
||||
|
||||
[error]
|
||||
occurred=Произошла ошибка
|
||||
missing_csrf=Некорректный запрос: отсутствует токен CSRF
|
||||
invalid_csrf=Некорректный запрос: неверный токен CSRF
|
||||
not_found=Цель не найдена.
|
||||
network_error=Ошибка сети
|
||||
|
||||
@ -1578,7 +1576,6 @@ issues.dependency.add_error_dep_not_same_repo=Обе задачи должны
|
||||
issues.review.self.approval=Вы не можете одобрить собственный запрос на слияние.
|
||||
issues.review.self.rejection=Невозможно запрашивать изменения своего запроса на слияние.
|
||||
issues.review.approve=одобрил(а) эти изменения %s
|
||||
issues.review.comment=Комментировать
|
||||
issues.review.dismissed=отклонен отзыв %s %s
|
||||
issues.review.dismissed_label=Отклонено
|
||||
issues.review.left_comment=оставил комментарий
|
||||
@ -1602,6 +1599,7 @@ issues.review.hide_resolved=Скрыть разрешенные
|
||||
issues.review.resolve_conversation=Покинуть диалог
|
||||
issues.review.un_resolve_conversation=Незавершённый разговор
|
||||
issues.review.resolved_by=пометить этот разговор как разрешённый
|
||||
issues.review.commented=Комментировать
|
||||
issues.assignee.error=Не все назначения были добавлены из-за непредвиденной ошибки.
|
||||
issues.reference_issue.body=Тело
|
||||
issues.content_history.deleted=удалено
|
||||
|
@ -118,7 +118,6 @@ filter.private=පෞද්ගලික
|
||||
[filter]
|
||||
|
||||
[error]
|
||||
missing_csrf=නරක ඉල්ලීම: CSRF ටෝකන් නොමැත
|
||||
|
||||
[startpage]
|
||||
app_desc=වේදනාකාරී, ස්වයං-සත්කාරක Git සේවාවක්
|
||||
@ -1200,7 +1199,6 @@ issues.dependency.add_error_dep_not_same_repo=මෙම ගැටළු දෙ
|
||||
issues.review.self.approval=ඔබ ඔබේ ම අදින්න ඉල්ලීම අනුමත කළ නොහැක.
|
||||
issues.review.self.rejection=ඔබ ඔබේ ම අදින්න ඉල්ලීම මත වෙනස්කම් ඉල්ලා සිටිය නොහැක.
|
||||
issues.review.approve=මෙම වෙනස්කම් අනුමත %s
|
||||
issues.review.comment=අදහස
|
||||
issues.review.dismissed=%sහි සමාලෝචනය %sප්රතික්ෂේප කරන ලද
|
||||
issues.review.dismissed_label=බැහැර
|
||||
issues.review.left_comment=අදහසක් හැරගියා
|
||||
@ -1221,6 +1219,7 @@ issues.review.hide_resolved=විසඳා සඟවන්න
|
||||
issues.review.resolve_conversation=සංවාදය විසඳන්න
|
||||
issues.review.un_resolve_conversation=නොවිසඳිය හැකි සංවාදය
|
||||
issues.review.resolved_by=මෙම සංවාදය විසඳා ඇති පරිදි සලකුණු කර ඇත
|
||||
issues.review.commented=අදහස
|
||||
issues.assignee.error=අනපේක්ෂිත දෝෂයක් හේතුවෙන් සියලුම ඇසිග්නස් එකතු නොකළේය.
|
||||
issues.reference_issue.body=ශරීරය
|
||||
issues.content_history.deleted=මකා දැමූ
|
||||
|
@ -181,8 +181,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Vyskytla sa chyba
|
||||
missing_csrf=Nesprávna žiadosť: neprítomný CSFR token
|
||||
invalid_csrf=Nesprávna žiadosť: nesprávny CSFR token
|
||||
not_found=Nebolo možné nájsť cieľ.
|
||||
network_error=Chyba siete
|
||||
|
||||
|
@ -1039,7 +1039,6 @@ issues.dependency.add_error_dep_not_same_repo=Båda ärendena måste vara i samm
|
||||
issues.review.self.approval=Du kan inte godkänna din egen pull-begäran.
|
||||
issues.review.self.rejection=Du kan inte begära ändringar för din egna pull-förfrågan.
|
||||
issues.review.approve=godkände dessa ändringar %s
|
||||
issues.review.comment=Kommentar
|
||||
issues.review.left_comment=lämnade en kommentar
|
||||
issues.review.content.empty=Du måste skriva en kommentar som anger de önskade ändringarna.
|
||||
issues.review.reject=begärda ändringar %s
|
||||
@ -1056,6 +1055,7 @@ issues.review.show_resolved=Visa löst
|
||||
issues.review.hide_resolved=Dölj löst
|
||||
issues.review.resolve_conversation=Lös konversation
|
||||
issues.review.resolved_by=markerade denna konversation som löst
|
||||
issues.review.commented=Kommentar
|
||||
issues.assignee.error=Inte alla tilldelade har lagts till på grund av ett oväntat fel.
|
||||
issues.content_history.options=Alternativ
|
||||
|
||||
|
@ -218,8 +218,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Bir hata oluştu
|
||||
missing_csrf=Hatalı İstek: CSRF anahtarı yok
|
||||
invalid_csrf=Hatalı İstek: geçersiz CSRF erişim anahtarı
|
||||
not_found=Hedef bulunamadı.
|
||||
network_error=Ağ hatası
|
||||
|
||||
@ -1704,7 +1702,6 @@ issues.dependency.add_error_dep_not_same_repo=Her iki konu da aynı depoda olmal
|
||||
issues.review.self.approval=Kendi değişiklik isteğinizi onaylayamazsınız.
|
||||
issues.review.self.rejection=Kendi değişiklik isteğinizde değişiklik isteyemezsiniz.
|
||||
issues.review.approve=%s bu değişiklikleri onayladı
|
||||
issues.review.comment=Yorum Yap
|
||||
issues.review.dismissed=%s incelemesini %s reddetti
|
||||
issues.review.dismissed_label=Reddedildi
|
||||
issues.review.left_comment=bir yorum yaptı
|
||||
@ -1729,6 +1726,7 @@ issues.review.hide_resolved=Çözülenleri gizle
|
||||
issues.review.resolve_conversation=Konuşmayı çöz
|
||||
issues.review.un_resolve_conversation=Konuşmayı çözme
|
||||
issues.review.resolved_by=bu konuşmayı çözümlenmiş olarak işaretledi
|
||||
issues.review.commented=Yorum Yap
|
||||
issues.assignee.error=Beklenmeyen bir hata nedeniyle tüm atananlar eklenmedi.
|
||||
issues.reference_issue.body=Gövde
|
||||
issues.content_history.deleted=silindi
|
||||
|
@ -120,7 +120,6 @@ filter.private=Приватний
|
||||
|
||||
[error]
|
||||
occurred=Сталася помилка
|
||||
missing_csrf=Некоректний запит: токен CSRF не задано
|
||||
network_error=Помилка мережі
|
||||
|
||||
[startpage]
|
||||
@ -1245,7 +1244,6 @@ issues.dependency.add_error_dep_not_same_repo=Обидві задачі пови
|
||||
issues.review.self.approval=Ви не можете схвалити власний пулл-реквест.
|
||||
issues.review.self.rejection=Ви не можете надіслати запит на зміну на власний пулл-реквест.
|
||||
issues.review.approve=зміни затверджено %s
|
||||
issues.review.comment=Коментар
|
||||
issues.review.dismissed=відхилено відгук %s %s
|
||||
issues.review.dismissed_label=Відхилено
|
||||
issues.review.left_comment=додав коментар
|
||||
@ -1266,6 +1264,7 @@ issues.review.hide_resolved=Приховати вирішене
|
||||
issues.review.resolve_conversation=Завершити обговорення
|
||||
issues.review.un_resolve_conversation=Поновити обговорення
|
||||
issues.review.resolved_by=позначив обговорення завершеним
|
||||
issues.review.commented=Коментар
|
||||
issues.assignee.error=Додано не всіх виконавців через непередбачену помилку.
|
||||
issues.reference_issue.body=Тіло
|
||||
issues.content_history.deleted=видалено
|
||||
|
@ -217,8 +217,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=发生了一个错误
|
||||
missing_csrf=错误的请求:没有 CSRF 令牌
|
||||
invalid_csrf=错误的请求:无效的 CSRF 令牌
|
||||
not_found=找不到目标。
|
||||
network_error=网络错误
|
||||
|
||||
@ -1692,7 +1690,6 @@ issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓
|
||||
issues.review.self.approval=您不能批准您自己的合并请求。
|
||||
issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。
|
||||
issues.review.approve=于 %s 批准此合并请求
|
||||
issues.review.comment=评论
|
||||
issues.review.dismissed=于 %[2]s 取消了 %[1]s 的评审
|
||||
issues.review.dismissed_label=已取消
|
||||
issues.review.left_comment=留下了一条评论
|
||||
@ -1717,6 +1714,7 @@ issues.review.hide_resolved=隐藏已解决的
|
||||
issues.review.resolve_conversation=已解决问题
|
||||
issues.review.un_resolve_conversation=未解决问题
|
||||
issues.review.resolved_by=标记问题为已解决
|
||||
issues.review.commented=评论
|
||||
issues.assignee.error=因为未知原因,并非所有的指派都成功。
|
||||
issues.reference_issue.body=内容
|
||||
issues.content_history.deleted=删除于
|
||||
|
@ -167,8 +167,6 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=發生錯誤
|
||||
missing_csrf=錯誤的請求:未提供 CSRF token
|
||||
invalid_csrf=錯誤的請求:無效的 CSRF token
|
||||
not_found=找不到目標。
|
||||
network_error=網路錯誤
|
||||
|
||||
@ -1467,7 +1465,6 @@ issues.dependency.add_error_dep_not_same_repo=這兩個問題必須在同一個
|
||||
issues.review.self.approval=您不能核可自己的合併請求。
|
||||
issues.review.self.rejection=您不能對自己的合併請求提出請求變更。
|
||||
issues.review.approve=核可了這些變更 %s
|
||||
issues.review.comment=留言
|
||||
issues.review.dismissed=取消 %s 的審核 %s
|
||||
issues.review.dismissed_label=已取消
|
||||
issues.review.left_comment=留下了回應
|
||||
@ -1488,6 +1485,7 @@ issues.review.hide_resolved=隱藏已解決
|
||||
issues.review.resolve_conversation=解決對話
|
||||
issues.review.un_resolve_conversation=取消解決對話
|
||||
issues.review.resolved_by=標記了此對話為已解決
|
||||
issues.review.commented=留言
|
||||
issues.assignee.error=因為未預期的錯誤,未能成功加入所有負責人。
|
||||
issues.reference_issue.body=內容
|
||||
issues.content_history.deleted=刪除
|
||||
|
1
public/assets/img/svg/gitea-codecommit.svg
generated
Normal file
1
public/assets/img/svg/gitea-codecommit.svg
generated
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 100 100" class="svg gitea-codecommit" width="16" height="16" aria-hidden="true"><g fill="none" fill-rule="evenodd"><path fill="#C925D1" d="M0 0h80v80H0z"/><path fill="#FFF" d="M26.628 28.105h-2.017v-6.982c0-.558.36-.99.926-.99l7.144-.007v1.994H27.95l4.862 4.819-1.445 1.434-4.806-4.728zm28.07 10.867 1.869.827-6.541 14.446-1.868-.827zm1.311 10.493 4.003-2.89-3.526-3.535 1.458-1.422 4.36 4.373a1.002 1.002 0 0 1-.126 1.527l-4.963 3.58zm-9.043-8.802 1.205 1.633-4.061 2.932 3.538 3.536-1.454 1.424-4.374-4.373a1 1 0 0 1 .124-1.528zM69 24.13v42.858c0 .56-.458 1.012-1.024 1.012h-31.26c-.272 0-.53-.107-.723-.297a.96.96 0 0 1-.285-.7V55.034h2.018v10.971h29.256V25.113H37.726v-1.995h30.25c.566 0 1.024.453 1.024 1.012M33.182 34.588c0-1.927 1.585-3.495 3.535-3.495s3.535 1.568 3.535 3.495-1.585 3.495-3.535 3.495-3.535-1.568-3.535-3.495M17.549 66.009c-1.95 0-3.535-1.568-3.535-3.495s1.585-3.494 3.535-3.494 3.535 1.567 3.535 3.494-1.585 3.495-3.535 3.495m-3.535-23.442c0-1.927 1.585-3.495 3.535-3.495 1.982 0 3.535 1.535 3.535 3.495 0 1.927-1.585 3.495-3.535 3.495s-3.535-1.568-3.535-3.495m.004-25.081c0-1.925 1.584-3.491 3.53-3.491 1.948 0 3.532 1.566 3.532 3.49s-1.584 3.491-3.531 3.491-3.531-1.566-3.531-3.49m23.708 29.762v-7.276c2.57-.477 4.535-2.708 4.535-5.384 0-3.022-2.487-5.482-5.544-5.482s-5.545 2.46-5.545 5.482c0 2.676 1.966 4.907 4.536 5.384v7.276c0 1.163-.786 2.218-1.98 2.686l-10.451 4.1c-1.673.657-2.903 1.948-3.434 3.496-.433-.195-.801-.336-1.285-.416v-9.146c2.623-.433 4.535-2.687 4.535-5.401 0-2.764-1.878-4.972-4.535-5.393V22.889c2.626-.431 4.54-2.688 4.54-5.403 0-3.025-2.49-5.486-5.55-5.486S12 14.46 12 17.486c0 2.64 2.022 4.85 4.54 5.369v14.347c-2.515.518-4.536 2.727-4.536 5.365s2.02 4.846 4.536 5.365v9.217c-2.515.52-4.536 2.727-4.536 5.365 0 3.022 2.488 5.482 5.545 5.482s5.544-2.46 5.544-5.482a5.43 5.43 0 0 0-1.458-3.693c.167-1.27 1.066-2.384 2.397-2.905l10.45-4.1c1.98-.777 3.244-2.57 3.244-4.568"/></g></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -123,6 +123,54 @@ func listChunksByRunID(st storage.ObjectStorage, runID int64) (map[int64][]*chun
|
||||
return chunksMap, nil
|
||||
}
|
||||
|
||||
func listChunksByRunIDV4(st storage.ObjectStorage, runID, artifactID int64, blist *BlockList) ([]*chunkFileItem, error) {
|
||||
storageDir := fmt.Sprintf("tmpv4%d", runID)
|
||||
var chunks []*chunkFileItem
|
||||
chunkMap := map[string]*chunkFileItem{}
|
||||
dummy := &chunkFileItem{}
|
||||
for _, name := range blist.Latest {
|
||||
chunkMap[name] = dummy
|
||||
}
|
||||
if err := st.IterateObjects(storageDir, func(fpath string, obj storage.Object) error {
|
||||
baseName := filepath.Base(fpath)
|
||||
if !strings.HasPrefix(baseName, "block-") {
|
||||
return nil
|
||||
}
|
||||
// when read chunks from storage, it only contains storage dir and basename,
|
||||
// no matter the subdirectory setting in storage config
|
||||
item := chunkFileItem{Path: storageDir + "/" + baseName, ArtifactID: artifactID}
|
||||
var size int64
|
||||
var b64chunkName string
|
||||
if _, err := fmt.Sscanf(baseName, "block-%d-%d-%s", &item.RunID, &size, &b64chunkName); err != nil {
|
||||
return fmt.Errorf("parse content range error: %v", err)
|
||||
}
|
||||
rchunkName, err := base64.URLEncoding.DecodeString(b64chunkName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse chunkName: %v", err)
|
||||
}
|
||||
chunkName := string(rchunkName)
|
||||
item.End = item.Start + size - 1
|
||||
if _, ok := chunkMap[chunkName]; ok {
|
||||
chunkMap[chunkName] = &item
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, name := range blist.Latest {
|
||||
chunk, ok := chunkMap[name]
|
||||
if !ok || chunk.Path == "" {
|
||||
return nil, fmt.Errorf("missing Chunk (%d/%d): %s", i, len(blist.Latest), name)
|
||||
}
|
||||
chunks = append(chunks, chunk)
|
||||
if i > 0 {
|
||||
chunk.Start = chunkMap[blist.Latest[i-1]].End + 1
|
||||
chunk.End += chunk.Start
|
||||
}
|
||||
}
|
||||
return chunks, nil
|
||||
}
|
||||
|
||||
func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int64, artifactName string) error {
|
||||
// read all db artifacts by name
|
||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||
@ -230,7 +278,7 @@ func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st st
|
||||
rawChecksum := hash.Sum(nil)
|
||||
actualChecksum := hex.EncodeToString(rawChecksum)
|
||||
if !strings.HasSuffix(checksum, actualChecksum) {
|
||||
return fmt.Errorf("update artifact error checksum is invalid")
|
||||
return fmt.Errorf("update artifact error checksum is invalid %v vs %v", checksum, actualChecksum)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,15 @@ package actions
|
||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=block
|
||||
// 1.3. Continue Upload Zip Content to Blobstorage (unauthenticated request), repeat until everything is uploaded
|
||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=appendBlock
|
||||
// 1.4. Unknown xml payload to Blobstorage (unauthenticated request), ignored for now
|
||||
// 1.4. BlockList xml payload to Blobstorage (unauthenticated request)
|
||||
// Files of about 800MB are parallel in parallel and / or out of order, this file is needed to enshure the correct order
|
||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=blockList
|
||||
// Request
|
||||
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
// <BlockList>
|
||||
// <Latest>blockId1</Latest>
|
||||
// <Latest>blockId2</Latest>
|
||||
// </BlockList>
|
||||
// 1.5. FinalizeArtifact
|
||||
// Post: /twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact
|
||||
// Request
|
||||
@ -82,6 +89,7 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -152,31 +160,34 @@ func ArtifactsV4Routes(prefix string) *web.Router {
|
||||
return m
|
||||
}
|
||||
|
||||
func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, taskID int64) []byte {
|
||||
func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, taskID, artifactID int64) []byte {
|
||||
mac := hmac.New(sha256.New, setting.GetGeneralTokenSigningSecret())
|
||||
mac.Write([]byte(endp))
|
||||
mac.Write([]byte(expires))
|
||||
mac.Write([]byte(artifactName))
|
||||
mac.Write([]byte(fmt.Sprint(taskID)))
|
||||
mac.Write([]byte(fmt.Sprint(artifactID)))
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
func (r artifactV4Routes) buildArtifactURL(ctx *ArtifactContext, endp, artifactName string, taskID int64) string {
|
||||
func (r artifactV4Routes) buildArtifactURL(ctx *ArtifactContext, endp, artifactName string, taskID, artifactID int64) string {
|
||||
expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
|
||||
uploadURL := strings.TrimSuffix(httplib.GuessCurrentAppURL(ctx), "/") + strings.TrimSuffix(r.prefix, "/") +
|
||||
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID)
|
||||
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID, artifactID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID) + "&artifactID=" + fmt.Sprint(artifactID)
|
||||
return uploadURL
|
||||
}
|
||||
|
||||
func (r artifactV4Routes) verifySignature(ctx *ArtifactContext, endp string) (*actions.ActionTask, string, bool) {
|
||||
rawTaskID := ctx.Req.URL.Query().Get("taskID")
|
||||
rawArtifactID := ctx.Req.URL.Query().Get("artifactID")
|
||||
sig := ctx.Req.URL.Query().Get("sig")
|
||||
expires := ctx.Req.URL.Query().Get("expires")
|
||||
artifactName := ctx.Req.URL.Query().Get("artifactName")
|
||||
dsig, _ := base64.URLEncoding.DecodeString(sig)
|
||||
taskID, _ := strconv.ParseInt(rawTaskID, 10, 64)
|
||||
artifactID, _ := strconv.ParseInt(rawArtifactID, 10, 64)
|
||||
|
||||
expecedsig := r.buildSignature(endp, expires, artifactName, taskID)
|
||||
expecedsig := r.buildSignature(endp, expires, artifactName, taskID, artifactID)
|
||||
if !hmac.Equal(dsig, expecedsig) {
|
||||
log.Error("Error unauthorized")
|
||||
ctx.Error(http.StatusUnauthorized, "Error unauthorized")
|
||||
@ -271,6 +282,8 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
|
||||
return
|
||||
}
|
||||
artifact.ContentEncoding = ArtifactV4ContentEncoding
|
||||
artifact.FileSize = 0
|
||||
artifact.FileCompressedSize = 0
|
||||
if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
|
||||
log.Error("Error UpdateArtifactByID: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
||||
@ -279,7 +292,7 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
|
||||
|
||||
respData := CreateArtifactResponse{
|
||||
Ok: true,
|
||||
SignedUploadUrl: r.buildArtifactURL(ctx, "UploadArtifact", artifactName, ctx.ActionTask.ID),
|
||||
SignedUploadUrl: r.buildArtifactURL(ctx, "UploadArtifact", artifactName, ctx.ActionTask.ID, artifact.ID),
|
||||
}
|
||||
r.sendProtbufBody(ctx, &respData)
|
||||
}
|
||||
@ -293,38 +306,77 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
|
||||
comp := ctx.Req.URL.Query().Get("comp")
|
||||
switch comp {
|
||||
case "block", "appendBlock":
|
||||
// get artifact by name
|
||||
artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
|
||||
if err != nil {
|
||||
log.Error("Error artifact not found: %v", err)
|
||||
ctx.Error(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
blockid := ctx.Req.URL.Query().Get("blockid")
|
||||
if blockid == "" {
|
||||
// get artifact by name
|
||||
artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
|
||||
if err != nil {
|
||||
log.Error("Error artifact not found: %v", err)
|
||||
ctx.Error(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
|
||||
if comp == "block" {
|
||||
artifact.FileSize = 0
|
||||
artifact.FileCompressedSize = 0
|
||||
_, err = appendUploadChunk(r.fs, ctx, artifact, artifact.FileSize, ctx.Req.ContentLength, artifact.RunID)
|
||||
if err != nil {
|
||||
log.Error("Error runner api getting task: task is not running")
|
||||
ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
|
||||
return
|
||||
}
|
||||
artifact.FileCompressedSize += ctx.Req.ContentLength
|
||||
artifact.FileSize += ctx.Req.ContentLength
|
||||
if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
|
||||
log.Error("Error UpdateArtifactByID: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
_, err := r.fs.Save(fmt.Sprintf("tmpv4%d/block-%d-%d-%s", task.Job.RunID, task.Job.RunID, ctx.Req.ContentLength, base64.URLEncoding.EncodeToString([]byte(blockid))), ctx.Req.Body, -1)
|
||||
if err != nil {
|
||||
log.Error("Error runner api getting task: task is not running")
|
||||
ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err = appendUploadChunk(r.fs, ctx, artifact, artifact.FileSize, ctx.Req.ContentLength, artifact.RunID)
|
||||
ctx.JSON(http.StatusCreated, "appended")
|
||||
case "blocklist":
|
||||
rawArtifactID := ctx.Req.URL.Query().Get("artifactID")
|
||||
artifactID, _ := strconv.ParseInt(rawArtifactID, 10, 64)
|
||||
_, err := r.fs.Save(fmt.Sprintf("tmpv4%d/%d-%d-blocklist", task.Job.RunID, task.Job.RunID, artifactID), ctx.Req.Body, -1)
|
||||
if err != nil {
|
||||
log.Error("Error runner api getting task: task is not running")
|
||||
ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
|
||||
return
|
||||
}
|
||||
artifact.FileCompressedSize += ctx.Req.ContentLength
|
||||
artifact.FileSize += ctx.Req.ContentLength
|
||||
if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
|
||||
log.Error("Error UpdateArtifactByID: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusCreated, "appended")
|
||||
case "blocklist":
|
||||
ctx.JSON(http.StatusCreated, "created")
|
||||
}
|
||||
}
|
||||
|
||||
type BlockList struct {
|
||||
Latest []string `xml:"Latest"`
|
||||
}
|
||||
|
||||
type Latest struct {
|
||||
Value string `xml:",chardata"`
|
||||
}
|
||||
|
||||
func (r *artifactV4Routes) readBlockList(runID, artifactID int64) (*BlockList, error) {
|
||||
blockListName := fmt.Sprintf("tmpv4%d/%d-%d-blocklist", runID, runID, artifactID)
|
||||
s, err := r.fs.Open(blockListName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
xdec := xml.NewDecoder(s)
|
||||
blockList := &BlockList{}
|
||||
err = xdec.Decode(blockList)
|
||||
|
||||
delerr := r.fs.Delete(blockListName)
|
||||
if delerr != nil {
|
||||
log.Warn("Failed to delete blockList %s: %v", blockListName, delerr)
|
||||
}
|
||||
return blockList, err
|
||||
}
|
||||
|
||||
func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
||||
var req FinalizeArtifactRequest
|
||||
|
||||
@ -343,18 +395,34 @@ func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
||||
ctx.Error(http.StatusNotFound, "Error artifact not found")
|
||||
return
|
||||
}
|
||||
chunkMap, err := listChunksByRunID(r.fs, runID)
|
||||
|
||||
var chunks []*chunkFileItem
|
||||
blockList, err := r.readBlockList(runID, artifact.ID)
|
||||
if err != nil {
|
||||
log.Error("Error merge chunks: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
}
|
||||
chunks, ok := chunkMap[artifact.ID]
|
||||
if !ok {
|
||||
log.Error("Error merge chunks")
|
||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
log.Warn("Failed to read BlockList, fallback to old behavior: %v", err)
|
||||
chunkMap, err := listChunksByRunID(r.fs, runID)
|
||||
if err != nil {
|
||||
log.Error("Error merge chunks: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
}
|
||||
chunks, ok = chunkMap[artifact.ID]
|
||||
if !ok {
|
||||
log.Error("Error merge chunks")
|
||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
chunks, err = listChunksByRunIDV4(r.fs, runID, artifact.ID, blockList)
|
||||
if err != nil {
|
||||
log.Error("Error merge chunks: %v", err)
|
||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||
return
|
||||
}
|
||||
artifact.FileSize = chunks[len(chunks)-1].End + 1
|
||||
artifact.FileCompressedSize = chunks[len(chunks)-1].End + 1
|
||||
}
|
||||
|
||||
checksum := ""
|
||||
if req.Hash != nil {
|
||||
checksum = req.Hash.Value
|
||||
@ -455,7 +523,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
|
||||
}
|
||||
}
|
||||
if respData.SignedUrl == "" {
|
||||
respData.SignedUrl = r.buildArtifactURL(ctx, "DownloadArtifact", artifactName, ctx.ActionTask.ID)
|
||||
respData.SignedUrl = r.buildArtifactURL(ctx, "DownloadArtifact", artifactName, ctx.ActionTask.ID, artifact.ID)
|
||||
}
|
||||
r.sendProtbufBody(ctx, &respData)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"strings"
|
||||
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
"code.gitea.io/gitea/modules/globallock"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
@ -114,7 +115,9 @@ func serveMavenMetadata(ctx *context.Context, params parameters) {
|
||||
xmlMetadataWithHeader := append([]byte(xml.Header), xmlMetadata...)
|
||||
|
||||
latest := pds[len(pds)-1]
|
||||
ctx.Resp.Header().Set("Last-Modified", latest.Version.CreatedUnix.Format(http.TimeFormat))
|
||||
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||
lastModifed := latest.Version.CreatedUnix.AsTime().UTC().Format(http.TimeFormat)
|
||||
ctx.Resp.Header().Set("Last-Modified", lastModifed)
|
||||
|
||||
ext := strings.ToLower(filepath.Ext(params.Filename))
|
||||
if isChecksumExtension(ext) {
|
||||
@ -223,6 +226,10 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
|
||||
helper.ServePackageFile(ctx, s, u, pf, opts)
|
||||
}
|
||||
|
||||
func mavenPkgNameKey(packageName string) string {
|
||||
return "pkg_maven_" + packageName
|
||||
}
|
||||
|
||||
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.
|
||||
func UploadPackageFile(ctx *context.Context) {
|
||||
params, err := extractPathParameters(ctx)
|
||||
@ -241,6 +248,14 @@ func UploadPackageFile(ctx *context.Context) {
|
||||
|
||||
packageName := params.GroupID + "-" + params.ArtifactID
|
||||
|
||||
// for the same package, only one upload at a time
|
||||
releaser, err := globallock.Lock(ctx, mavenPkgNameKey(packageName))
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer releaser()
|
||||
|
||||
buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
|
@ -133,7 +133,7 @@ func CreateUser(ctx *context.APIContext) {
|
||||
u.UpdatedUnix = u.CreatedUnix
|
||||
}
|
||||
|
||||
if err := user_model.AdminCreateUser(ctx, u, overwriteDefault); err != nil {
|
||||
if err := user_model.AdminCreateUser(ctx, u, &user_model.Meta{}, overwriteDefault); err != nil {
|
||||
if user_model.IsErrUserAlreadyExist(err) ||
|
||||
user_model.IsErrEmailAlreadyUsed(err) ||
|
||||
db.IsErrNameReserved(err) ||
|
||||
|
@ -1286,6 +1286,8 @@ func Routes() *web.Router {
|
||||
m.Group("/{ref}", func() {
|
||||
m.Get("/status", repo.GetCombinedCommitStatusByRef)
|
||||
m.Get("/statuses", repo.GetCommitStatusesByRef)
|
||||
}, context.ReferencesGitRepo())
|
||||
m.Group("/{sha}", func() {
|
||||
m.Get("/pull", repo.GetCommitPullRequest)
|
||||
}, context.ReferencesGitRepo())
|
||||
}, reqRepoReader(unit.TypeCode))
|
||||
|
@ -325,11 +325,11 @@ func DownloadCommitDiffOrPatch(ctx *context.APIContext) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetCommitPullRequest returns the pull request of the commit
|
||||
// GetCommitPullRequest returns the merged pull request of the commit
|
||||
func GetCommitPullRequest(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/commits/{sha}/pull repository repoGetCommitPullRequest
|
||||
// ---
|
||||
// summary: Get the pull request of the commit
|
||||
// summary: Get the merged pull request of the commit
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
@ -354,7 +354,7 @@ func GetCommitPullRequest(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
pr, err := issues_model.GetPullRequestByMergedCommit(ctx, ctx.Repo.Repository.ID, ctx.PathParam(":sha"))
|
||||
pr, err := issues_model.GetPullRequestByMergedCommit(ctx, ctx.Repo.Repository.ID, ctx.PathParam("sha"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.Error(http.StatusNotFound, "GetPullRequestByMergedCommit", err)
|
||||
|
@ -833,10 +833,16 @@ func EditIssue(ctx *context.APIContext) {
|
||||
if (form.Deadline != nil || form.RemoveDeadline != nil) && canWrite {
|
||||
var deadlineUnix timeutil.TimeStamp
|
||||
|
||||
if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() {
|
||||
deadline := time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
|
||||
23, 59, 59, 0, form.Deadline.Location())
|
||||
deadlineUnix = timeutil.TimeStamp(deadline.Unix())
|
||||
if form.RemoveDeadline == nil || !*form.RemoveDeadline {
|
||||
if form.Deadline == nil {
|
||||
ctx.Error(http.StatusBadRequest, "", "The due_date cannot be empty")
|
||||
return
|
||||
}
|
||||
if !form.Deadline.IsZero() {
|
||||
deadline := time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
|
||||
23, 59, 59, 0, form.Deadline.Location())
|
||||
deadlineUnix = timeutil.TimeStamp(deadline.Unix())
|
||||
}
|
||||
}
|
||||
|
||||
if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil {
|
||||
|
@ -169,6 +169,10 @@ func Migrate(ctx *context.APIContext) {
|
||||
opts.PullRequests = false
|
||||
opts.Releases = false
|
||||
}
|
||||
if gitServiceType == api.CodeCommitService {
|
||||
opts.AWSAccessKeyID = form.AWSAccessKeyID
|
||||
opts.AWSSecretAccessKey = form.AWSSecretAccessKey
|
||||
}
|
||||
|
||||
repo, err := repo_service.CreateRepositoryDirectly(ctx, ctx.Doer, repoOwner, repo_service.CreateRepoOptions{
|
||||
Name: opts.RepoName,
|
||||
|
@ -766,7 +766,7 @@ func EditPullRequest(ctx *context.APIContext) {
|
||||
// update allow edits
|
||||
if form.AllowMaintainerEdit != nil {
|
||||
if err := pull_service.SetAllowEdits(ctx, ctx.Doer, pr, *form.AllowMaintainerEdit); err != nil {
|
||||
if errors.Is(pull_service.ErrUserHasNoPermissionForAction, err) {
|
||||
if errors.Is(err, pull_service.ErrUserHasNoPermissionForAction) {
|
||||
ctx.Error(http.StatusForbidden, "SetAllowEdits", fmt.Sprintf("SetAllowEdits: %s", err))
|
||||
return
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
@ -251,6 +252,8 @@ func CreateRelease(ctx *context.APIContext) {
|
||||
ctx.Error(http.StatusConflict, "ReleaseAlreadyExist", err)
|
||||
} else if models.IsErrProtectedTagName(err) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "ProtectedTagName", err)
|
||||
} else if git.IsErrNotExist(err) {
|
||||
ctx.Error(http.StatusNotFound, "ErrNotExist", fmt.Errorf("target \"%v\" not found: %w", rel.Target, err))
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateRelease", err)
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
ctx.Error(http.StatusBadRequest, "AccessTokenScope.Normalize", fmt.Errorf("invalid access token scope provided: %w", err))
|
||||
return
|
||||
}
|
||||
if scope == "" {
|
||||
ctx.Error(http.StatusBadRequest, "AccessTokenScope", "access token must have a scope")
|
||||
return
|
||||
}
|
||||
t.Scope = scope
|
||||
|
||||
if err := auth_model.NewAccessToken(ctx, t); err != nil {
|
||||
@ -129,6 +133,7 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||
Token: t.Token,
|
||||
ID: t.ID,
|
||||
TokenLastEight: t.TokenLastEight,
|
||||
Scopes: t.Scope.StringSlice(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -554,7 +554,7 @@ func SubmitInstall(ctx *context.Context) {
|
||||
IsActive: optional.Some(true),
|
||||
}
|
||||
|
||||
if err = user_model.CreateUser(ctx, u, overwriteDefault); err != nil {
|
||||
if err = user_model.CreateUser(ctx, u, &user_model.Meta{}, overwriteDefault); err != nil {
|
||||
if !user_model.IsErrUserAlreadyExist(err) {
|
||||
setting.InstallLock = false
|
||||
ctx.Data["Err_AdminName"] = true
|
||||
|
@ -177,7 +177,7 @@ func NewUserPost(ctx *context.Context) {
|
||||
u.MustChangePassword = form.MustChangePassword
|
||||
}
|
||||
|
||||
if err := user_model.AdminCreateUser(ctx, u, overwriteDefault); err != nil {
|
||||
if err := user_model.AdminCreateUser(ctx, u, &user_model.Meta{}, overwriteDefault); err != nil {
|
||||
switch {
|
||||
case user_model.IsErrUserAlreadyExist(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
|
@ -228,12 +228,12 @@ func SignInPost(ctx *context.Context) {
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) || errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
} else if user_model.IsErrEmailAlreadyUsed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
} else if user_model.IsErrUserProhibitLogin(err) {
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
} else if user_model.IsErrUserInactive(err) {
|
||||
@ -241,7 +241,7 @@ func SignInPost(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
|
||||
ctx.HTML(http.StatusOK, TplActivate)
|
||||
} else {
|
||||
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
log.Warn("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
|
||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
|
||||
}
|
||||
@ -541,7 +541,11 @@ func createAndHandleCreatedUser(ctx *context.Context, tpl base.TplName, form any
|
||||
// createUserInContext creates a user and handles errors within a given context.
|
||||
// Optionally a template can be specified.
|
||||
func createUserInContext(ctx *context.Context, tpl base.TplName, form any, u *user_model.User, overwrites *user_model.CreateUserOverwriteOptions, gothUser *goth.User, allowLink bool) (ok bool) {
|
||||
if err := user_model.CreateUser(ctx, u, overwrites); err != nil {
|
||||
meta := &user_model.Meta{
|
||||
InitialIP: ctx.RemoteAddr(),
|
||||
InitialUserAgent: ctx.Req.UserAgent(),
|
||||
}
|
||||
if err := user_model.CreateUser(ctx, u, meta, overwrites); err != nil {
|
||||
if allowLink && (user_model.IsErrUserAlreadyExist(err) || user_model.IsErrEmailAlreadyUsed(err)) {
|
||||
if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingAuto {
|
||||
var user *user_model.User
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
org_model "code.gitea.io/gitea/models/organization"
|
||||
project_model "code.gitea.io/gitea/models/project"
|
||||
attachment_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
@ -333,7 +334,29 @@ func ViewProject(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, columns)
|
||||
var labelIDs []int64
|
||||
// 1,-2 means including label 1 and excluding label 2
|
||||
// 0 means issues with no label
|
||||
// blank means labels will not be filtered for issues
|
||||
selectLabels := ctx.FormString("labels")
|
||||
if selectLabels == "" {
|
||||
ctx.Data["AllLabels"] = true
|
||||
} else if selectLabels == "0" {
|
||||
ctx.Data["NoLabel"] = true
|
||||
}
|
||||
if len(selectLabels) > 0 {
|
||||
labelIDs, err = base.StringsToInt64s(strings.Split(selectLabels, ","))
|
||||
if err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("invalid_data", selectLabels), true)
|
||||
}
|
||||
}
|
||||
|
||||
assigneeID := ctx.FormInt64("assignee")
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, columns, &issues_model.IssuesOptions{
|
||||
LabelIDs: labelIDs,
|
||||
AssigneeID: assigneeID,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfColumns", err)
|
||||
return
|
||||
@ -372,6 +395,46 @@ func ViewProject(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add option to filter also by repository specific labels
|
||||
labels, err := issues_model.GetLabelsByOrgID(ctx, project.OwnerID, "", db.ListOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetLabelsByOrgID", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the exclusive scope for every label ID
|
||||
labelExclusiveScopes := make([]string, 0, len(labelIDs))
|
||||
for _, labelID := range labelIDs {
|
||||
foundExclusiveScope := false
|
||||
for _, label := range labels {
|
||||
if label.ID == labelID || label.ID == -labelID {
|
||||
labelExclusiveScopes = append(labelExclusiveScopes, label.ExclusiveScope())
|
||||
foundExclusiveScope = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundExclusiveScope {
|
||||
labelExclusiveScopes = append(labelExclusiveScopes, "")
|
||||
}
|
||||
}
|
||||
|
||||
for _, l := range labels {
|
||||
l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes)
|
||||
}
|
||||
ctx.Data["Labels"] = labels
|
||||
ctx.Data["NumLabels"] = len(labels)
|
||||
|
||||
// Get assignees.
|
||||
assigneeUsers, err := org_model.GetOrgAssignees(ctx, project.OwnerID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
ctx.Data["SelectLabels"] = selectLabels
|
||||
ctx.Data["AssigneeID"] = assigneeID
|
||||
|
||||
project.RenderedContent = templates.RenderMarkdownToHtml(ctx, project.Description)
|
||||
ctx.Data["LinkedPRs"] = linkedPrsMap
|
||||
ctx.Data["PageIsViewProjects"] = true
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers/web/repo"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
|
||||
@ -252,7 +252,7 @@ func List(ctx *context.Context) {
|
||||
ctx.ServerError("GetActors", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Actors"] = repo.MakeSelfOnTop(ctx.Doer, actors)
|
||||
ctx.Data["Actors"] = shared_user.MakeSelfOnTop(ctx.Doer, actors)
|
||||
|
||||
ctx.Data["StatusInfoList"] = actions_model.GetStatusInfoList(ctx)
|
||||
|
||||
|
@ -90,7 +90,7 @@ func Commits(ctx *context.Context) {
|
||||
commitsTagsMap, err := repo_model.FindTagsByCommitIDs(ctx, ctx.Repo.Repository.ID, commitIDs...)
|
||||
if err != nil {
|
||||
log.Error("FindTagsByCommitIDs: %v", err)
|
||||
ctx.Flash.Error(ctx.Tr("repo.commit.load_tags_failed"))
|
||||
ctx.Flash.Error(ctx.Tr("internal_error_skipped", "FindTagsByCommitIDs"))
|
||||
} else {
|
||||
ctx.Data["CommitsTagsMap"] = commitsTagsMap
|
||||
}
|
||||
|
@ -395,7 +395,8 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
|
||||
|
||||
ctx.Resp.Header().Set("Content-Type", contentType)
|
||||
ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", fi.Size()))
|
||||
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
|
||||
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
|
||||
http.ServeFile(ctx.Resp, ctx.Req, reqFile)
|
||||
}
|
||||
|
||||
|
@ -5,25 +5,11 @@ package repo
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"sort"
|
||||
|
||||
"code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
func MakeSelfOnTop(doer *user.User, users []*user.User) []*user.User {
|
||||
if doer != nil {
|
||||
sort.Slice(users, func(i, j int) bool {
|
||||
if users[i].ID == users[j].ID {
|
||||
return false
|
||||
}
|
||||
return users[i].ID == doer.ID // if users[i] is self, put it before others, so less=true
|
||||
})
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
func HandleGitError(ctx *context.Context, msg string, err error) {
|
||||
if git.IsErrNotExist(err) {
|
||||
refType := ""
|
||||
|
@ -49,6 +49,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/utils"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/context/upload"
|
||||
@ -360,7 +361,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
handleTeamMentions(ctx)
|
||||
if ctx.Written() {
|
||||
@ -466,6 +467,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||
ctx.Data["AssigneeID"] = assigneeID
|
||||
ctx.Data["PosterID"] = posterID
|
||||
ctx.Data["Keyword"] = keyword
|
||||
ctx.Data["IsShowClosed"] = isShowClosed
|
||||
switch {
|
||||
case isShowClosed.Value():
|
||||
ctx.Data["State"] = "closed"
|
||||
@ -580,7 +582,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
handleTeamMentions(ctx)
|
||||
}
|
||||
@ -3796,7 +3798,7 @@ func issuePosters(ctx *context.Context, isPullList bool) {
|
||||
}
|
||||
}
|
||||
|
||||
posters = MakeSelfOnTop(ctx.Doer, posters)
|
||||
posters = shared_user.MakeSelfOnTop(ctx.Doer, posters)
|
||||
|
||||
resp := &userSearchResponse{}
|
||||
resp.Results = make([]*userSearchInfo, len(posters))
|
||||
|
@ -231,6 +231,10 @@ func MigratePost(ctx *context.Context) {
|
||||
opts.PullRequests = false
|
||||
opts.Releases = false
|
||||
}
|
||||
if form.Service == structs.CodeCommitService {
|
||||
opts.AWSAccessKeyID = form.AWSAccessKeyID
|
||||
opts.AWSSecretAccessKey = form.AWSSecretAccessKey
|
||||
}
|
||||
|
||||
err = repo_model.CheckCreateRepository(ctx, ctx.Doer, ctxUser, opts.RepoName, false)
|
||||
if err != nil {
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
project_service "code.gitea.io/gitea/services/projects"
|
||||
@ -313,7 +314,29 @@ func ViewProject(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, columns)
|
||||
var labelIDs []int64
|
||||
// 1,-2 means including label 1 and excluding label 2
|
||||
// 0 means issues with no label
|
||||
// blank means labels will not be filtered for issues
|
||||
selectLabels := ctx.FormString("labels")
|
||||
if selectLabels == "" {
|
||||
ctx.Data["AllLabels"] = true
|
||||
} else if selectLabels == "0" {
|
||||
ctx.Data["NoLabel"] = true
|
||||
}
|
||||
if len(selectLabels) > 0 {
|
||||
labelIDs, err = base.StringsToInt64s(strings.Split(selectLabels, ","))
|
||||
if err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("invalid_data", selectLabels), true)
|
||||
}
|
||||
}
|
||||
|
||||
assigneeID := ctx.FormInt64("assignee")
|
||||
|
||||
issuesMap, err := issues_model.LoadIssuesFromColumnList(ctx, columns, &issues_model.IssuesOptions{
|
||||
LabelIDs: labelIDs,
|
||||
AssigneeID: assigneeID,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("LoadIssuesOfColumns", err)
|
||||
return
|
||||
@ -353,6 +376,55 @@ func ViewProject(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["LinkedPRs"] = linkedPrsMap
|
||||
|
||||
labels, err := issues_model.GetLabelsByRepoID(ctx, project.RepoID, "", db.ListOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetLabelsByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.Owner.IsOrganization() {
|
||||
orgLabels, err := issues_model.GetLabelsByOrgID(ctx, ctx.Repo.Owner.ID, "", db.ListOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetLabelsByOrgID", err)
|
||||
return
|
||||
}
|
||||
|
||||
labels = append(labels, orgLabels...)
|
||||
}
|
||||
|
||||
// Get the exclusive scope for every label ID
|
||||
labelExclusiveScopes := make([]string, 0, len(labelIDs))
|
||||
for _, labelID := range labelIDs {
|
||||
foundExclusiveScope := false
|
||||
for _, label := range labels {
|
||||
if label.ID == labelID || label.ID == -labelID {
|
||||
labelExclusiveScopes = append(labelExclusiveScopes, label.ExclusiveScope())
|
||||
foundExclusiveScope = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundExclusiveScope {
|
||||
labelExclusiveScopes = append(labelExclusiveScopes, "")
|
||||
}
|
||||
}
|
||||
|
||||
for _, l := range labels {
|
||||
l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes)
|
||||
}
|
||||
ctx.Data["Labels"] = labels
|
||||
ctx.Data["NumLabels"] = len(labels)
|
||||
|
||||
// Get assignees.
|
||||
assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
ctx.Data["SelectLabels"] = selectLabels
|
||||
ctx.Data["AssigneeID"] = assigneeID
|
||||
|
||||
project.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
||||
Links: markup.Links{
|
||||
Base: ctx.Repo.RepoLink,
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/utils"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
"code.gitea.io/gitea/services/automerge"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
@ -163,7 +164,19 @@ func setMergeTarget(ctx *context.Context, pull *issues_model.PullRequest) {
|
||||
ctx.Data["HeadTarget"] = pull.MustHeadUserName(ctx) + "/" + pull.HeadRepo.Name + ":" + pull.HeadBranch
|
||||
}
|
||||
ctx.Data["BaseTarget"] = pull.BaseBranch
|
||||
ctx.Data["HeadBranchLink"] = pull.GetHeadBranchLink(ctx)
|
||||
headBranchLink := ""
|
||||
if pull.Flow == issues_model.PullRequestFlowGithub {
|
||||
b, err := git_model.GetBranch(ctx, ctx.Repo.Repository.ID, pull.HeadBranch)
|
||||
switch {
|
||||
case err == nil:
|
||||
if !b.IsDeleted {
|
||||
headBranchLink = pull.GetHeadBranchLink(ctx)
|
||||
}
|
||||
case !git_model.IsErrBranchNotExist(err):
|
||||
log.Error("GetBranch: %v", err)
|
||||
}
|
||||
}
|
||||
ctx.Data["HeadBranchLink"] = headBranchLink
|
||||
ctx.Data["BaseBranchLink"] = pull.GetBaseBranchLink(ctx)
|
||||
}
|
||||
|
||||
@ -825,7 +838,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
handleTeamMentions(ctx)
|
||||
if ctx.Written() {
|
||||
@ -1625,7 +1638,7 @@ func SetAllowEdits(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if err := pull_service.SetAllowEdits(ctx, ctx.Doer, pr, form.AllowMaintainerEdit); err != nil {
|
||||
if errors.Is(pull_service.ErrUserHasNoPermissionForAction, err) {
|
||||
if errors.Is(err, pull_service.ErrUserHasNoPermissionForAction) {
|
||||
ctx.Error(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/web/feed"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/context/upload"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
@ -213,6 +214,8 @@ func TagsList(ctx *context.Context) {
|
||||
ctx.Data["HideBranchesInDropdown"] = true
|
||||
ctx.Data["CanCreateRelease"] = ctx.Repo.CanWrite(unit.TypeReleases) && !ctx.Repo.Repository.IsArchived
|
||||
|
||||
namePattern := ctx.FormTrim("q")
|
||||
|
||||
listOptions := db.ListOptions{
|
||||
Page: ctx.FormInt("page"),
|
||||
PageSize: ctx.FormInt("limit"),
|
||||
@ -232,6 +235,7 @@ func TagsList(ctx *context.Context) {
|
||||
IncludeTags: true,
|
||||
HasSha1: optional.Some(true),
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
NamePattern: optional.Some(namePattern),
|
||||
}
|
||||
|
||||
releases, err := db.Find[repo_model.Release](ctx, opts)
|
||||
@ -240,14 +244,21 @@ func TagsList(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Releases"] = releases
|
||||
count, err := db.Count[repo_model.Release](ctx, opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetReleasesByRepoID", err)
|
||||
return
|
||||
}
|
||||
|
||||
numTags := ctx.Data["NumTags"].(int64)
|
||||
pager := context.NewPagination(int(numTags), opts.PageSize, opts.Page, 5)
|
||||
ctx.Data["Keyword"] = namePattern
|
||||
ctx.Data["Releases"] = releases
|
||||
ctx.Data["TagCount"] = count
|
||||
|
||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
||||
pager.SetDefaultParams(ctx)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
ctx.Data["PageIsViewCode"] = !ctx.Repo.Repository.UnitEnabled(ctx, unit.TypeReleases)
|
||||
|
||||
ctx.HTML(http.StatusOK, tplTagsList)
|
||||
}
|
||||
|
||||
@ -370,7 +381,7 @@ func NewRelease(ctx *context.Context) {
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
upload.AddUploadContext(ctx, "release")
|
||||
|
||||
@ -559,7 +570,7 @@ func EditRelease(ctx *context.Context) {
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
ctx.HTML(http.StatusOK, tplReleaseNew)
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user