Compare commits

..

18 Commits

Author SHA1 Message Date
Joe Chen 593c7b6db6 release: update version to 0.13.2 2024-12-23 10:57:35 -05:00
Joe Chen 01157b2f79 Dockerfile: fix up outdated s6-svscan path (#7880)
## Describe the pull request

Link to the issue: https://github.com/gogs/gogs/issues/7864
2024-12-23 10:54:01 -05:00
Joe Chen 0c40e600a2 ci: fix up unsupported host system version 2024-12-22 17:54:57 -05:00
Joe Chen 080b9a9d03 release: update version to 0.13.1 2024-12-22 17:52:03 -05:00
Joe Chen 300519d1ca ci: fix up lint issues 2024-12-22 17:33:50 -05:00
Joe Chen 88a13fa378 ci: modernize setup 2024-12-22 17:21:26 -05:00
Joe Chen 2b0f129a91 dep: update github.com/gogs/git-module to v1.8.4 (#7872)
Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-m27m-h5gj-wwmg by
including https://github.com/gogs/git-module/pull/110
2024-12-22 17:16:11 -05:00
Joe Chen ce51a8e538 repo: ignore unintended Git options for diff preview (#7871)
## Describe the pull request

Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-9pp6-wq8c-3w2c
2024-12-22 17:15:08 -05:00
Joe Chen 3b527a36c8 repo: prevent preview and delete files in `.git` directories (#7870)
## Describe the pull request

Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-ccqv-43vm-4f3w
2024-12-22 17:14:44 -05:00
Joe Chen f5262441a0 ssh: make `env` command a passthrough (#7868)
Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-vm62-9jw3-c8w3

ssh: make `env` command a passthrough (#7868)

Fixes
https://github.com/gogs/gogs/security/advisories/GHSA-vm62-9jw3-c8w3
2024-12-22 17:04:03 -05:00
Alexandre Jacquin f6862c1f8b Fix s6-svscan path in Dockerfile (#7867)
Related to #7864

## Describe the pull request

Fix the path of the s6-svscan binary path in the Dockerfile. As
mentionned in the issue, it is probably to the alpine base image change
(from `3.17` to `3.21`).

Link to the issue:
https://github.com/gogs/gogs/issues/7864#issuecomment-2558323928

Credit to @cryptovaltt

## Test plan

Build the image and check if the application can be ran. E.g.:

```bash
docker build -t gogs:working-7864 -f Dockerfile .
docker run --name=gogs -p 10022:22 -p 10880:3000 -v gogs:working-7864 --rm
```
2024-12-22 17:01:09 -05:00
Joe Chen bd84b41843 Dockerfile: update base image to alpine3.21 and enable trivy scan (#7863)
Link to the issue: fixes https://github.com/gogs/gogs/issues/6674
2024-12-22 17:00:43 -05:00
Joe Chen c947affcfa api: clean file path for updating repo contents (#7859)
## Describe the pull request

Link to the issue: closes https://github.com/gogs/gogs/issues/7582
2024-12-22 16:55:01 -05:00
Joe Chen 40cb106198 repo/editor: disallow editing symlink while changing file name (#7857)
## Describe the pull request

Link to the issue: https://github.com/gogs/gogs/issues/7582
2024-12-22 16:54:18 -05:00
Mobile Mind b89da2f6eb install: fix SMTP password config name to save (#7807) 2024-12-22 16:54:02 -05:00
Jiaxin Zhu 75969c92ef fix(templates): the green color is supposed to be purple (#7722)
Co-authored-by: jxzhu <zhujiaxin@gmail.com>
2024-12-22 16:53:45 -05:00
bitebyte e993f1dbff Fix issue: synchronize the section name[mailer/email] of app.ini (#7704) 2024-12-22 16:52:23 -05:00
Joe Chen 8c21874c00
release: remove dev version notion 2023-02-25 20:33:19 +08:00
245 changed files with 12642 additions and 9539 deletions

View File

@ -4,6 +4,7 @@ root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

2
.github/CODEOWNERS vendored
View File

@ -1,2 +0,0 @@
# Default
* @unknwon

View File

@ -13,7 +13,7 @@ On the `main` branch:
- [ ] Close stale issues with the label [status: needs feedback](https://github.com/gogs/gogs/issues?q=is%3Aissue+is%3Aopen+label%3A%22status%3A+needs+feedback%22).
- [ ] [Sync locales from Crowdin](https://github.com/gogs/gogs/blob/main/docs/dev/import_locale.md).
- [ ] [Update CHANGELOG](https://github.com/gogs/gogs/commit/540134d4436d8da82247dd2cabe9312ca2f5b1f1) to include entries for the current minor release.
- [ ] [Update CHANGELOG](https://github.com/gogs/gogs/commit/720cb5fcb169b9e026b5b47f57d50888b35fdb4b) to include entries for the current minor release.
- [ ] Cut a new release branch `release/<MAJOR>.<MINOR>`, e.g. `release/0.12`.
## During release
@ -46,7 +46,8 @@ On the `main` branch:
- [ ] Update the repository mirror on [Gitee](https://gitee.com/unknwon/gogs).
- [ ] Create a new release announcement in [Discussions](https://github.com/gogs/gogs/discussions/categories/announcements).
- [ ] Send a tweet on the [official Twitter account](https://twitter.com/GogsHQ) for the minor release.
- [ ] Send out release announcement emails via [Mailchimp](https://mailchimp.com/).
- [ ] Publish a new release article on [OSChina](http://my.oschina.net/Obahua/admin/releases).
- [ ] Close the minor milestone.
- [ ] [Bump the hard-coded version](https://github.com/gogs/gogs/commit/a98968436cd5841cf691bb0b80c54c81470d1676) to the new develop version, e.g. `0.12.0+dev` -> `0.13.0+dev`.
- [ ] [Bump the hard-coded version](https://github.com/gogs/gogs/commit/05477f1d294dc43f36c4a3b3b9575a96aea66a67) to the new develop version, e.g. `0.12.0+dev` -> `0.13.0+dev`.
- [ ] Run `task legacy` to identify deprecated code that is aimed to be removed in current develop version.

View File

@ -12,7 +12,6 @@ _This is generated from the [patch release template](https://github.com/gogs/gog
On the release branch:
- [ ] Make sure all commits are cherry-picked from the `main` branch by checking the patch milestone.
- Run `task build` for every cherry-picked commit to make sure there is no compilation error.
- [ ] [Update CHANGELOG on the `main` branch](https://github.com/gogs/gogs/commit/e6c5633f580399c8f4dfc07166a63a01c6c70346) to include entries for the current patch release.
## During release
@ -21,22 +20,19 @@ On the release branch:
- [ ] [Update the hard-coded version](https://github.com/gogs/gogs/commit/f0e3cd90f8d7695960eeef2e4e54b2e717302f6c) to the current release, e.g. `0.12.0` -> `0.12.1`.
- [ ] Wait for GitHub Actions to complete and no failed jobs.
- [ ] Publish new RC releases (e.g. `v0.12.0-rc.1`, `v0.12.0-rc.2`) to ensure Docker workflow succeeds.
- ⚠️ **Make sure the tag is created on the release branch**.
- [ ] Publish new RC releases (e.g. `v0.12.0-rc.1`, `v0.12.0-rc.2`) to ensure Docker workflow succeeds. **Make sure the tag is created on the release branch**.
- Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current patch release and all previous releases with same minor version.
- ⚠️ **Make sure the tag is created on the release branch**.
- [ ] Publish a new [GitHub release](https://github.com/gogs/gogs/releases) with entries from [CHANGELOG](https://github.com/gogs/gogs/blob/main/CHANGELOG.md) for the current patch release and all previous releases with same minor version. **Make sure the tag is created on the release branch**.
- [ ] Update all previous GitHub releases with same minor version with the warning:
```
** Heads up! There is a new patch release [0.12.1](https://github.com/gogs/gogs/releases/tag/v0.12.1) available, we recommend directly installing or upgrading to that version.**
```
- [ ] [Wait for a new image tag for the current release](https://github.com/gogs/gogs/actions/workflows/docker.yml?query=event%3Arelease) to be created automatically on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
- Pull down the Docker image and [run through application setup](https://github.com/gogs/gogs/blob/main/docker/README.md) to make sure nothing blows up.
- [ ] [Update Docker image tag](https://github.com/gogs/gogs/blob/main/docs/dev/release/release_new_version.md#update-docker-image-tag) for the minor release `<MAJOR>.<MINOR>` on both [Docker Hub](https://hub.docker.com/r/gogs/gogs/tags) and [GitHub Container registry](https://github.com/gogs/gogs/pkgs/container/gogs).
- [ ] [Compile and pack binaries](https://github.com/gogs/gogs/blob/main/docs/dev/release/release_new_version.md#compile-and-pack-binaries) (all prefixed with `gogs_<MAJOR>.<MINOR>.<PATCH>_`, e.g. `gogs_0.12.0_`):
- [ ] macOS: `darwin_arm64.zip`, `darwin_amd64.zip`
- [ ] Linux: `linux_amd64.tar.gz`, `linux_amd64.zip`
- [ ] ARM: `linux_armv8.tar.gz`, `linux_armv8.zip`
- [ ] macOS: `darwin_amd64.zip`, `darwin_arm64.zip`
- [ ] Linux: `linux_386.tar.gz`, `linux_386.zip`, `linux_amd64.tar.gz`, `linux_amd64.zip`
- [ ] ARM: `linux_armv7.tar.gz`, `linux_armv7.zip`, `linux_armv8.tar.gz`, `linux_armv8.zip`
- [ ] Windows: `windows_amd64.zip`, `windows_amd64_mws.zip`
- [ ] [Generate SHA256 checksum](https://github.com/gogs/gogs/blob/main/docs/dev/release/sha256.sh) for all binaries to the file `checksum_sha256.txt`.
- [ ] Upload all binaries and `checksum_sha256.txt` to:

View File

@ -4,7 +4,7 @@ updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "monthly"
interval: "weekly"
reviewers:
- "gogs/core"
commit-message:

35
.github/workflows/codeball.yml vendored Normal file
View File

@ -0,0 +1,35 @@
# Docs: https://github.com/sturdy-dev/codeball-action
name: Codeball
on: [ pull_request ]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
codeball:
runs-on: ubuntu-latest
name: Codeball
steps:
# Start a new Codeball review job
# This step is asynchronous and will return a job id
- name: Trigger Codeball
id: codeball_baller
uses: sturdy-dev/codeball-action/baller@v2
# Wait for Codeball to return the status
- name: Get Status
id: codeball_status
uses: sturdy-dev/codeball-action/status@v2
with:
codeball-job-id: ${{ steps.codeball_baller.outputs.codeball-job-id }}
# If Codeball approved the contribution, approve the PR
- name: Approve PR
uses: sturdy-dev/codeball-action/approver@v2
if: ${{ steps.codeball_status.outputs.approved == 'true' }}
with:
message: "Codeball: LGTM! :+1:"

View File

@ -39,7 +39,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@ -47,7 +47,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -58,7 +58,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -72,4 +72,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1

View File

@ -5,7 +5,6 @@ on:
- main
pull_request:
paths:
- '.trivy.yaml'
- 'Dockerfile'
- 'docker/**'
- '.github/workflows/docker.yml'
@ -15,24 +14,28 @@ on:
jobs:
buildx:
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
runs-on: ubuntu-latest
permissions:
actions: write
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Canel previous runs
uses: styfle/cancel-workflow-action@0.9.1
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
all_but_latest: true
access_token: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v1
with:
config-inline: |
[worker.oci]
max-parallelism = 2
- name: Inspect builder
run: |
echo "Name: ${{ steps.buildx.outputs.name }}"
@ -41,24 +44,18 @@ jobs:
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DigitalOcean Container registry
uses: docker/login-action@v3
with:
registry: registry.digitalocean.com
username: ${{ secrets.DIGITALOCEAN_USERNAME }}
password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Build and push images
uses: docker/build-push-action@v5
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7
@ -96,10 +93,10 @@ jobs:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v1
with:
config-inline: |
[worker.oci]
@ -115,7 +112,7 @@ jobs:
id: short-sha
uses: benjlevesque/short-sha@v2.1
- name: Build and push images
uses: docker/build-push-action@v5
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64
@ -140,14 +137,16 @@ jobs:
- name: Compute image tag name
run: echo "IMAGE_TAG=$(echo $GITHUB_REF_NAME | cut -c 2-)" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v1
with:
config-inline: |
[worker.oci]
max-parallelism = 2
- name: Inspect builder
run: |
echo "Name: ${{ steps.buildx.outputs.name }}"
@ -156,18 +155,18 @@ jobs:
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push images
uses: docker/build-push-action@v5
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64,linux/arm/v7

View File

@ -65,16 +65,16 @@ jobs:
platform: [ ubuntu-latest, macos-latest ]
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./...
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v1.5.0
with:
file: ./coverage
flags: unittests
@ -98,23 +98,23 @@ jobs:
# Running tests with race detection consumes too much memory on Windows,
# see https://github.com/golang/go/issues/46099 for details.
test-windows:
name: Test Windows
name: Test
strategy:
matrix:
go-version: [ 1.23.x ]
platform: [ windows-latest ]
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -shuffle=on -v -coverprofile=coverage -covermode=atomic ./...
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v1.5.0
with:
file: ./coverage
flags: unittests
@ -155,14 +155,14 @@ jobs:
ports:
- 5432:5432
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/database/...
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/db/...
env:
GOGS_DATABASE_TYPE: postgres
PGPORT: 5432
@ -181,14 +181,14 @@ jobs:
steps:
- name: Start MySQL server
run: sudo systemctl start mysql
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/database/...
run: go test -shuffle=on -v -race -coverprofile=coverage -covermode=atomic ./internal/db/...
env:
GOGS_DATABASE_TYPE: mysql
MYSQL_USER: root
@ -204,13 +204,13 @@ jobs:
platform: [ ubuntu-latest ]
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -shuffle=on -v -race -parallel=1 -coverprofile=coverage -covermode=atomic ./internal/database/...
run: go test -shuffle=on -v -race -parallel=1 -coverprofile=coverage -covermode=atomic ./internal/db/...
env:
GOGS_DATABASE_TYPE: sqlite

View File

@ -16,7 +16,7 @@ jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
- uses: dessant/lock-threads@v3
with:
github-token: ${{ github.token }}
issue-inactive-days: '90'

View File

@ -12,6 +12,6 @@ jobs:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master

View File

@ -1,13 +1,13 @@
targets:
debian-10: &debian
debian-9: &debian
build_dependencies:
- libpam0g-dev
dependencies:
- libpam0g
- git
debian-11:
debian-10:
<<: *debian
debian-12:
debian-11:
<<: *debian
ubuntu-18.04:
<<: *debian
@ -15,7 +15,7 @@ targets:
<<: *debian
ubuntu-22.04:
<<: *debian
centos-9:
centos-8:
build_dependencies:
- pam-devel
# required for Go buildpack

View File

@ -4,35 +4,6 @@ All notable changes to Gogs are documented in this file.
## 0.14.0+dev (`main`)
### Added
- Support using TLS for Redis session provider using `[session] PROVIDER_CONFIG = ...,tls=true`. [#7860](https://github.com/gogs/gogs/pull/7860)
### Changed
- The required Go version to compile source code changed to 1.23.4.
- The build tag `cert` has been removed, and the `gogs cert` subcommand is now always available. [#7883](https://github.com/gogs/gogs/pull/7883)
### Fixed
- Submodules using `ssh://` protocol and a port number are not rendered correctly. [#4941](https://github.com/gogs/gogs/issues/4941)
- Missing link to user profile on the first commit in commits history page. [#7404](https://github.com/gogs/gogs/issues/7404)
- Unable to override email templates in custom directory. [#7905](https://github.com/gogs/gogs/pull/7905)
## 0.13.2
### Fixed
- _Security:_ Path Traversal in file editing UI. [GHSA-r7j8-5h9c-f6fx](https://github.com/gogs/gogs/security/advisories/GHSA-r7j8-5h9c-f6fx)
- _Security:_ Path Traversal in file update API. [GHSA-qf5v-rp47-55gg](https://github.com/gogs/gogs/security/advisories/GHSA-qf5v-rp47-55gg)
- _Security:_ Argument Injection in the built-in SSH server. [GHSA-vm62-9jw3-c8w3](https://github.com/gogs/gogs/security/advisories/GHSA-vm62-9jw3-c8w3)
- _Security:_ Deletion of internal files. [GHSA-ccqv-43vm-4f3w](https://github.com/gogs/gogs/security/advisories/GHSA-ccqv-43vm-4f3w)
- _Security:_ Argument Injection during changes preview. [GHSA-9pp6-wq8c-3w2c](https://github.com/gogs/gogs/security/advisories/GHSA-9pp6-wq8c-3w2c)
- _Security:_ Argument Injection when tagging new releases. [GHSA-m27m-h5gj-wwmg](https://github.com/gogs/gogs/security/advisories/GHSA-m27m-h5gj-wwmg)
- Use the non-deprecated section name `[email]` during installation for email settings. [#7704](https://github.com/gogs/gogs/pull/7704)
- Use the non-deprecated section name `[email] PASSWORD` during installation for email password. [#7807](https://github.com/gogs/gogs/pull/7807)
- Make purple template label color to actually use the hexcode of purple. [#7722](https://github.com/gogs/gogs/pull/7722)
## 0.13.0
### Added

View File

@ -31,7 +31,7 @@ The Gogs (`/gɑgz/`) project aims to build a simple, stable and extensible self-
- Jupyter Notebook and PDF rendering.
- Authentication via SMTP, LDAP, reverse proxy, GitHub.com and GitHub Enterprise with 2FA.
- Customize HTML templates, static files and many others.
- Rich database backend support, including PostgreSQL, MySQL, SQLite3 or any database backend that speaks one of those protocols.
- Rich database backend, including PostgreSQL, MySQL, SQLite3 and [TiDB](https://github.com/pingcap/tidb).
- Have localization over [31 languages](https://crowdin.com/project/gogs).
## 💾 Hardware requirements
@ -60,7 +60,11 @@ There are 6 ways to install Gogs:
### Deploy to cloud
- [Cloudron](https://www.cloudron.io/store/io.gogs.cloudronapp.html)
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
- [YunoHost](https://github.com/YunoHost-Apps/gogs_ynh)
- [DPlatform](https://github.com/DFabric/DPlatform-Shell)
- [LunaNode](https://github.com/LunaNode/launchgogs)
- [alwaysdata](https://www.alwaysdata.com/en/marketplace/gogs/)
### Tutorials
@ -77,6 +81,7 @@ There are 6 ways to install Gogs:
## 📦 Software, service and product support
- [Fabric8](http://fabric8.io/) (DevOps)
- [Jenkins](https://plugins.jenkins.io/gogs-webhook/) (CI)
- [Puppet](https://forge.puppet.com/modules/Siteminds/gogs) (IT)
- [Synology](https://www.synology.com) (Docker)
@ -84,18 +89,10 @@ There are 6 ways to install Gogs:
## 🙇‍♂️ Acknowledgments
<p>This project is proudly supported by:</p>
<p>
<a href="https://www.digitalocean.com/">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
</a>
</p>
Other acknowledgments:
- Thanks [Egon Elbre](https://twitter.com/egonelbre) for designing the original version of the logo.
- Thanks [Crowdin](https://crowdin.com/project/gogs) for sponsoring open source translation plan.
- Thanks [MonoVM](https://monovm.com/linux-vps/) for sponsoring VPS services.
- Thanks [DigitalOcean](https://www.digitalocean.com), [VPSServer](https://www.vpsserver.com/), [Hosted.nl](https://www.hosted.nl/), [BitLaunch](https://bitlaunch.io), and [MonoVM](https://monovm.com/linux-vps/) for sponsoring VPS services.
- Thanks [KeyCDN](https://www.keycdn.com/) for sponsoring CDN service.
- Thanks [Buildkite](https://buildkite.com) for sponsoring open source CI/CD plan.
## 👋 Contributors

View File

@ -88,8 +88,9 @@ Gogs`/gɑgz/`)项目旨在打造一个以最简便的方式搭建简单、
## 特别鸣谢
- 感谢 [Egon Elbre](https://twitter.com/egonelbre) 设计的 Logo。
- 感谢 [DigitalOcean](https://www.digitalocean.com) 和 [MonoVM](https://monovm.com) 提供服务器赞助。
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
- 感谢 [DigitalOcean](https://www.digitalocean.com)、[VPSServer](https://www.vpsserver.com/)、[Hosted.nl](https://www.hosted.nl/)、[MonoVM](https://monovm.com) 和 [BitLaunch](https://bitlaunch.io) 提供服务器赞助。
- 感谢 [KeyCDN](https://www.keycdn.com/) 提供 CDN 服务赞助。
- 感谢 [Buildkite](https://buildkite.com) 提供免费的开源项目 CI/CD 支持。
## 贡献成员

View File

@ -2,23 +2,22 @@
## Supported versions
Only the latest minor version releases are supported (>= 0.13) for accepting vulnerability reports and patching fixes.
Only lastest two minor version releases are supported (>= 0.12) for accepting vulnerability reports and patching fixes.
Existing vulnerability reports are being tracked in [GitHub Security Advisories](https://github.com/gogs/gogs/security/advisories).
Existing vulnerability reports are being tracked in [Gogs Vulnerability Reports](https://jcunknwon.notion.site/Gogs-Vulnerability-Reports-81d7df52e45c4f159274e46ba48ed1b9).
## Vulnerability lifecycle
> [!important]
> Starting **Nov 9, 2023 00:00 UTC**, only security vulnerabilities reported through [GitHub Security Advisories](https://github.com/gogs/gogs/security/advisories/new) are accepted.
> Pre-existing vulnerability reported through https://huntr.dev/ or email (`security@gogs.io`) will continue to be worked through.
1. Report an advisory for the vulnerability
1. Project maintainers review the advisory and either:
1. Report a vulnerability:
- We strongly enourage to use https://huntr.dev/ for submitting and managing status of vulnerability reports.
- Alternatively, you may send vulnerability reports through emails to [security@gogs.io](mailto:security@gogs.io).
1. Create a [dummy issue](https://github.com/gogs/gogs/issues/6901) with high-level description of the security vulnerability for credibility and tracking purposes.
1. Project maintainers review the report and either:
- Ask clarifying questions
- Confirm or deny the vulnerability
1. Once the vulnerability is confirmed, the reporter may submit a patch or wait for project maintainers to patch.
- The latter is usually significantly slower.
1. Patch releases will be made for the supported versions.
1. After 14 days of the release, publish the corresponding advisory on [GitHub Security Advisories](https://github.com/gogs/gogs/security/advisories).
1. Publish the original vulnerability report and a new [GitHub security advisory](https://github.com/gogs/gogs/security/advisories).
Thank you!

View File

@ -42,7 +42,7 @@ tasks:
generate-schemadoc:
desc: Generate database schema documentation
cmds:
- go generate ./internal/database/schemadoc
- go generate ./internal/db/schemadoc
generate:
desc: Run all go:generate commands
@ -90,12 +90,3 @@ tasks:
desc: Identify legacy and deprecated lines
cmds:
- grep -rnw "\(LEGACY\|Deprecated\)" internal
drop-test-db:
desc: Drop the test database
cmds:
- |
for dbname in $(psql -Xc "copy (select datname from pg_database where datname like 'gogs-%') to stdout"); do
dropdb "$dbname"
echo "dropped $dbname"
done

View File

@ -247,7 +247,7 @@ PROVIDER = memory
; The configuration for respective provider:
; - memory: does not need any config yet
; - file: session file path, e.g. `data/sessions`
; - redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180,tls=true
; - redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
PROVIDER_CONFIG = data/sessions
; The cookie name to store the session identifier.
COOKIE_NAME = i_like_gogs

View File

@ -44,21 +44,21 @@ issues=Задачи
cancel=Отказ
[status]
page_not_found=Страницата не е намерена
internal_server_error=Вътрешна грешка в сървър
page_not_found=Page Not Found
internal_server_error=Internal Server Error
[install]
install=Инсталация
title=Стъпки за инсталиране при първоначално стартиране
docker_helper=Ако Gogs е стартиран в Docker контейнер, моля прочетете <a target="_blank" href="%s">нашите указания</a> внимателно, преди да правите промени по настройките на тази страница!
requite_db_desc=Gogs изисква MySQL, PostgreSQL, SQLite3 или TiDB (през MySQL протокол).
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Настройки на базата данни
db_type=Тип на база данни
host=Сървър
user=Потребител
password=Парола
db_name=Име на база данни
db_schema=Схема
db_schema=Schema
db_helper=Моля, използвайте INNODB engine с utf8_general_ci кодиране на знаци за MySQL.
ssl_mode=Режим SSL
path=Път
@ -88,7 +88,6 @@ log_root_path=Път към журналите
log_root_path_helper=Директория в която се записват журналите.
enable_console_mode=Включване на конзолен режим
enable_console_mode_popup=Изписване на логовете в конзолата, в допълнение към файловият режим.
default_branch=Клон по подразбиране
optional_title=Опционални настройки
email_title=Настройки на пощенска услуга
@ -127,7 +126,7 @@ run_user_not_match=Потребителският контекст на прил
smtp_host_missing_port=Липсва порт в зададения SMTP адрес.
invalid_smtp_from=Невалидно поле От: %v
save_config_failed=Неуспешно запазване на конфигурация: %v
init_failed=Грешка при инициализация на приложение: %v
init_failed=Failed to initialize application: %v
invalid_admin_setting=Настройките на профил на администратора са невалидни: %v
install_success=Добре дошли! Радваме се, че избрахте Gogs, и Ви пожелаваме приятна работа и сърдечни поздрави!
invalid_log_root_path=Основният път към журналите е невалиден: %v
@ -157,8 +156,8 @@ register_hepler_msg=Вече имате профил? Впишете се сег
social_register_hepler_msg=Вече имате профил? Свържете се сега!
disable_register_prompt=За съжаление създаването на нови регистрации е изключено. Обърнете се към администратора на сайта.
disable_register_mail=За съжаление потвърждението на регистрации е изключено.
auth_source=Източник за удостоверяване
local=Локален
auth_source=Authentication Source
local=Local
remember_me=Запомни ме
forgot_password=Забравена парола
forget_password=Забравена парола?
@ -179,10 +178,10 @@ non_local_account=Нелокални потребители не могат да
login_two_factor=Двуфакторно удостоверяване
login_two_factor_passcode=Парола за удостоверяване
login_two_factor_enter_recovery_code=Въведете двуфакторен код за възстановяване
login_two_factor_recovery=Двуфакторно възстановяване
login_two_factor_enter_recovery_code=Enter a two-factor recovery code
login_two_factor_recovery=Two-factor Recovery
login_two_factor_recovery_code=Код за възстановяване
login_two_factor_enter_passcode=Въведете двуфакторен код
login_two_factor_enter_passcode=Enter a two-factor passcode
login_two_factor_invalid_recovery_code=Този код за възстановяване вече е бил използван или не е валиден.
[mail]
@ -317,7 +316,6 @@ delete_email=Изтрий
email_deletion=Изтрий ел. поща
email_deletion_desc=При изтриване на тази ел. поща ще се премахне свързаната информация от Вашия профил. Желаете ли да продължите?
email_deletion_success=Ел. пощата беше изтрита успешно!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Добавяне на нов адрес на ел. поща
add_email=Добави ел. поща
add_email_confirmation_sent=Ново писмо за потвърждение е изпратено до '%s'. Моля проверете пощенската си кутия в рамките на следващите %d часа, за да завършите процеса на регистрация.
@ -372,7 +370,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=Управление на индивидуални API ключове за достъп
generate_new_token=Генериране на нов API ключ
tokens_desc=Генерирани API ключове, които могат да се използват за достъп до API на Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Всеки API ключ ще има пълен достъп до Вашия профил.
token_name=Име на API ключ
generate_token=Генериране на API ключ
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Конфигурация на хранилище
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Adresář systémových záznamů
log_root_path_helper=Adresář, kam se budou zapisovat soubory se systémovými záznamy.
enable_console_mode=Povolit režim konzole
enable_console_mode_popup=Mimo zápisu do souboru vytisknout systémové záznamy i do konzole.
default_branch=Default Branch
optional_title=Dodatečná nastavení
email_title=Nastavení e-mailové služby
@ -317,7 +316,6 @@ delete_email=Smazat
email_deletion=Smazání e-mailové adresy
email_deletion_desc=Smazání této e-mailové adresy odstraní návazné informace z vašeho účtu. Chcete pokračovat?
email_deletion_success=E-mailová adresa byla smazána!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Přidat novou e-mailovou adresu
add_email=Přidat e-mailovou adresu
add_email_confirmation_sent=Nový potvrzovací e-mail byl odeslán na adresu '%s', prosím zkontrolujte si vaši doručenou poštu během následujících %d hodin pro dokončení procesu potvrzení.
@ -372,7 +370,6 @@ two_factor_disable_success=Dvoufaktorové ověření bylo zakázáno!
manage_access_token=Správa osobních přístupových poukázek
generate_new_token=Vygenerovat novou poukázku
tokens_desc=Poukázky, které jste vygeneroval, mohou být použity pro přístup k Gogs API.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Každá poukázka má úplný přístup k vašemu účtu.
token_name=Název poukázky
generate_token=Vygenerovat poukázku
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Serverové šifry
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Nastavení repositáře
config.repo.root_path=Kořenová cesta

View File

@ -50,8 +50,8 @@ internal_server_error=Interner Serverfehler
[install]
install=Installation
title=Installationsschritte für den ersten Start
docker_helper=Wenn Gogs innerhalb von Docker läuft, lesen Sie sich bitte den <a target="_blank" href="%s">Leitfaden</a> genau durch, bevor Sie etwas auf dieser Seite ändern!
requite_db_desc=Gogs benötigt MySQL, PostgreSQL, SQLite3 oder TiDB (mit MySQL-Protokoll)
docker_helper=Wenn Gogs innerhalb von Docker läuft, lesen Sie sich bitte den <a target="_blank" href="%s">Leitfaden</a> genau durch, bevor Sie irgendwas auf dieser Seite ändern!
requite_db_desc=Gogs benötigt MySQL, PostgreSQL, SQLite3 oder TiDB (per MySQL-Protokoll)
db_title=Datenbankeinstellungen
db_type=Datenbanktyp
host=Host
@ -88,7 +88,6 @@ log_root_path=Logdateipfad
log_root_path_helper=Verzeichnis in das Logdateien geschrieben werden.
enable_console_mode=Konsolen-Modus einschalten
enable_console_mode_popup=Zusätzlich zum Datei-Modus, zeige Logs auch in der Konsole.
default_branch=Standard Branch
optional_title=Optionale Einstellungen
email_title=E-Mail-Service Einstellungen
@ -317,7 +316,6 @@ delete_email=Löschen
email_deletion=E-Mail löschen
email_deletion_desc=Das Löschen dieser E-Mail Adresse wird alle Informationen entfernen, die mit dieser E-Mail Adresse verknüpft sind. Wollen Sie fortfahren?
email_deletion_success=E-Mail-Adresse wurde erfolgreich gelöscht!
email_deletion_primary=Die primäre E-Mail-Adresse kann nicht gelöscht werden.
add_new_email=Neue E-Mail-Adresse hinzufügen
add_email=E-Mail-Adresse hinzufügen
add_email_confirmation_sent=Eine neue Bestätigungsmail wurde an '%s' gesendet, bitte überprüfen Sie Ihren Posteingang innerhalb von %d Stunden um die Bestätigung abzuschließen.
@ -372,7 +370,6 @@ two_factor_disable_success=Die Zwei-Faktor-Authentifizierung wurde erfolgreich d
manage_access_token=Verwaltung persönlicher Zugangs-Token
generate_new_token=Neues Token erzeugen
tokens_desc=Die von Ihnen erzeugten Token können zum Zugriff auf die Gogs-API verwendet werden.
access_token_tips=Der persönliche Zugangs-Token kann entweder als Benutzername oder als Passwort verwendet werden. Es wird empfohlen den "x-access-token" als Benutzernamen und den persönlichen Zugangs-Token als Passwort für Git-Anwendungen zu verwenden.
new_token_desc=Jeder Token erlaubt vollen Zugriff auf ihr Konto.
token_name=Token-Name
generate_token=Token generieren
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen-Host
config.ssh.listen_port=Listen-Port
config.ssh.server_ciphers=Serverchiffren
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server-Algorithmen
config.repo_config=Repository-Konfiguration
config.repo.root_path=Wurzelpfad

View File

@ -88,7 +88,6 @@ log_root_path=Log Path
log_root_path_helper=Directory to write log files to.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
default_branch=Default Branch
optional_title=Optional Settings
email_title=Email Service Settings
@ -319,7 +318,6 @@ delete_email=Delete
email_deletion=Email Deletion
email_deletion_desc=Deleting this email address will remove related information from your account. Do you want to continue?
email_deletion_success=Email has been deleted successfully!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Add new email address
add_email=Add email
add_email_confirmation_sent=A new confirmation email has been sent to '%s', please check your inbox within the next %d hours to complete the confirmation process.
@ -375,7 +373,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=Manage Personal Access Tokens
generate_new_token=Generate New Token
tokens_desc=Tokens you have generated that can be used to access the Gogs APIs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Each token will have full access to your account.
token_name=Token Name
generate_token=Generate Token
@ -1263,7 +1260,6 @@ config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository Configuration
config.repo.root_path=Root path

View File

@ -317,7 +317,6 @@ delete_email = Delete
email_deletion = Email Deletion
email_deletion_desc = Deleting this email address will remove related information from your account. Do you want to continue?
email_deletion_success = Email has been deleted successfully!
email_deletion_primary = Cannot delete primary email address.
add_new_email = Add new email address
add_email = Add Email
add_email_confirmation_sent = A new confirmation email has been sent to '%s', please check your inbox within the next %d hours to complete the confirmation process.

View File

@ -51,14 +51,14 @@ internal_server_error=Error Interno del Servidor
install=Instalación
title=Pasos de la instalación por primera vez
docker_helper=Si está ejecutando Gogs usando Docker, ¡por favor lea <a target="_blank" href="%s"> estas pautas</a> antes de cambiar nada en esta página!
requite_db_desc=Gogs requiere MySQL, PostgreSQL, SQLite3 o TiDB (a través del protocolo MySQL).
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Configuración de base de datos
db_type=Tipo de base de datos
host=Host
user=Usuario
password=Contraseña
db_name=Nombre de la base de datos
db_schema=Esquema
db_schema=Schema
db_helper=Por favor utilice el motor INNODB con la configuración de caracteres utf8_general_ci para MySQL.
ssl_mode=Modo SSL
path=Ruta
@ -88,7 +88,6 @@ log_root_path=Ruta del registro
log_root_path_helper=Directorio donde almacenar los registros.
enable_console_mode=Activar Modo Consola
enable_console_mode_popup=Además del modo archivo, también imprime los registros en consola.
default_branch=Rama por defecto
optional_title=Configuración opcional
email_title=Configuración del servicio de correo
@ -119,7 +118,7 @@ admin_password=Contraseña
confirm_password=Confirmar Contraseña
admin_email=Correo electrónico del administrador
install_gogs=Instalar Gogs
test_git_failed=Error al probar el comando 'git': %v
test_git_failed=Fallo al probar el comando 'git': %v
sqlite3_not_available=Tu versión no soporta SQLite3, por favor descarga el binario oficial desde %s, NO la versión de gobuild.
invalid_db_setting=La configuración de la base de datos no es correcta: %v
invalid_repo_path=La ruta de la raíz del repositorio es inválida: %v
@ -127,7 +126,7 @@ run_user_not_match=El usuario que está ejecutando la aplicación no es el usuar
smtp_host_missing_port=No se ha definido el puerto para el host SMTP.
invalid_smtp_from=El campo SMTP no es válido: %v
save_config_failed=Error al guardar la configuración: %v
init_failed=Error al inicializar la aplicación: %v
init_failed=Failed to initialize application: %v
invalid_admin_setting=La configuración de la cuenta de administración es inválida: %v
install_success=Bienvenido! Estamos encantados de que hayas escogido Gogs, diviértete y cuídate.
invalid_log_root_path=La ruta para los registros es inválida: %v
@ -265,7 +264,7 @@ following=Siguiendo
follow=Seguir
unfollow=Dejar de seguir
form.name_not_allowed=El nombre de usuario o patrón %q no está permitido.
form.name_not_allowed=User name or pattern %q is not allowed.
[settings]
profile=Perfil
@ -317,7 +316,6 @@ delete_email=Eliminar
email_deletion=Eliminar correo electrónico
email_deletion_desc=Al eliminar esta dirección de correo electrónico se eliminará toda la información asociada a esta. ¿Deseas continuar?
email_deletion_success=¡El correo electrónico ha sido eliminado correctamente!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Añadir nueva dirección de correo electrónico
add_email=Añadir correo electrónico
add_email_confirmation_sent=Un nuevo correo de confirmación ha sido enviado a '%s'. Por favor, comprueba tu bandeja de entrada en las próximas %d horas para completar el proceso.
@ -372,7 +370,6 @@ two_factor_disable_success=¡La autenticación en dos pasos ha sido deshabilitad
manage_access_token=Gestionar los Tokens de Acceso personales
generate_new_token=Generar nuevo Token
tokens_desc=Tokens usados para acceder al API de Gogs.
access_token_tips=El token de acceso personal puede utilizarse como nombre de usuario o como contraseña. Se recomienda utilizar el "x-access-token" como nombre de usuario y el token de acceso personal como contraseña para las aplicaciones Git.
new_token_desc=Desde ahora, todos los tokens tendrán acceso completo a tu cuenta.
token_name=Nombre del Token
generate_token=Generar Token
@ -381,7 +378,7 @@ delete_token=Eliminar
access_token_deletion=Borrado de Token de Acceso Personal
access_token_deletion_desc=Si elimina este token de acceso personal la aplicación asociada perderá el permiso de acceso. ¿Desea continuar?
delete_token_success=¡El token de acceso personal ha sido eliminado con éxito! No se olvide de actualizar también las aplicaciones asociadas.
token_name_exists=Ya existe un token con el mismo nombre.
token_name_exists=Token with same name already exists.
orgs.none=No eres un miembro de ninguna organización.
orgs.leave_title=Salir de una organización
@ -403,9 +400,9 @@ owner=Propietario
repo_name=Nombre del repositorio
repo_name_helper=Los grandes nombres de repositorios son cortos, memorables y <strong>únicos</strong>.
visibility=Visibilidad
unlisted=Sin listar
unlisted=Unlisted
visiblity_helper=Este repositorio es <span class="ui red text">privado</span>
unlisted_helper=Este repositorio <span class="ui red text">no está en la lista</span>
unlisted_helper=This repository is <span class="ui red text">Unlisted</span>
visiblity_helper_forced=El administrador web ha obligado a todos los repositorios nuevos a ser <span class="ui red text"> privados</span>
visiblity_fork_helper=(Este cambio afectará a todos los forks)
clone_helper=¿Necesitas ayuda con el clone? ¡Consulta la <a target="_blank" href="%s">Ayuda</a>!
@ -423,7 +420,7 @@ auto_init=Inicializar los archivos seleccionados y plantillas de este repositori
create_repo=Crear repositorio
default_branch=Rama por defecto
mirror_prune=Purgar
mirror_prune_desc=Elimina cualquier referencia de seguimiento remoto que ya no exista en el remoto
mirror_prune_desc=Remover referencias remotas que no existan remotamente
mirror_interval=Intervalo de la réplica (en horas)
mirror_address=Dirección de la réplica
mirror_address_desc=Por favor, incluya las credenciales de usuario necesarias en la dirección.
@ -435,7 +432,7 @@ repo_description_helper=Descripción del repositorio. Longitud máxima de 512 ca
repo_description_length=Caracteres disponibles
form.reach_limit_of_creation=El propietario ha alcanzado el límite máximo de %d repositorios creados.
form.name_not_allowed=El nombre de repositorio o patrón %q no está permitido.
form.name_not_allowed=Repository name or pattern %q is not allowed.
need_auth=Requiere autorización
migrate_type=Tipo de migración
@ -446,7 +443,7 @@ migrate.clone_address_desc=Esto puede ser una dirección URL HTTP/HTTPS/GIT.
migrate.clone_address_desc_import_local=También se le permite migrar un repositorio por la ruta del servidor local.
migrate.permission_denied=No te está permitido importar repositorios locales.
migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio.
migrate.clone_address_resolved_to_blocked_local_address=La dirección de clonado se ha resuelto a una dirección de red local que está implícitamente bloqueada.
migrate.clone_address_resolved_to_blocked_local_address=Clone address resolved to a local network address that is implicitly blocked.
migrate.failed=Migración fallida: %v
mirror_from=espejo de
@ -796,8 +793,8 @@ settings.remove_collaborator_success=El colaborador ha sido eliminado.
settings.search_user_placeholder=Buscar usuario...
settings.org_not_allowed_to_be_collaborator=Las organizaciones no tiene permitido ser añadidas como colaboradores.
settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificaciones cuando sucedan ciertos eventos en Gogs. Cuando sucedan los eventos especificados, enviaremos una petición POST a cada una de las URLs indicadas. Para obtener más información, consulta nuestra <a target="_blank" href="%s">Guía de Webhooks</a>.
settings.webhooks.add_new=Añadir un nuevo webhook:
settings.webhooks.choose_a_type=Elige un tipo...
settings.webhooks.add_new=Add a new webhook:
settings.webhooks.choose_a_type=Choose a type...
settings.add_webhook=Añadir Webhook
settings.webhook_deletion=Eliminar Webhook
settings.webhook_deletion_desc=Al borrar este webhook se eliminará su información y todo su historial. ¿Desea continuar?
@ -812,8 +809,8 @@ settings.webhook.response=Respuesta
settings.webhook.headers=Encabezado
settings.webhook.payload=Payload
settings.webhook.body=Cuerpo del mensaje
settings.webhook.err_cannot_parse_payload_url=No se puede analizar la URL de payload: %v
settings.webhook.url_resolved_to_blocked_local_address=La URL de payload se ha resuelto a una dirección de red local que está implícitamente bloqueada.
settings.webhook.err_cannot_parse_payload_url=Cannot parse payload URL: %v
settings.webhook.url_resolved_to_blocked_local_address=Payload URL resolved to a local network address that is implicitly blocked.
settings.githooks_desc=Los Git Hooks son una funcionalidad del propio Git, puedes editar los ficheros de los hooks soportados en la siguiente lista para aplicar operaciones personalizadas.
settings.githook_edit_desc=Si el hook no está activo, se mostrará contenido de ejemplo. Dejar el contenido vacío deshabilitará este hook.
settings.githook_name=Nombre del Hook
@ -940,8 +937,8 @@ team_name_helper=Utiliza este nombre para mencionar a este equipo en las convers
team_desc_helper=¿En qué consiste este equipo?
team_permission_desc=¿Qué nivel de permisos debería tener este equipo?
form.name_not_allowed=El nombre de la organización o patrón %q no está permitido.
form.team_name_not_allowed=El nombre del equipo o patrón %q no está permitido.
form.name_not_allowed=Organization name or pattern %q is not allowed.
form.team_name_not_allowed=Team name or pattern %q is not allowed.
settings=Configuración
settings.options=Opciones
@ -1014,7 +1011,7 @@ last_page=Última
total=Total: %d
dashboard.build_info=Build Information
dashboard.app_ver=Versión de la aplicación
dashboard.app_ver=Application version
dashboard.git_version=Versión de Git
dashboard.go_version=Versión de Go
dashboard.build_time=Tiempo de compilación
@ -1171,21 +1168,21 @@ auths.delete_auth_desc=Esta autenticación será eliminada. ¿Deseas continuar?
auths.still_in_used=Este método de autentificación aún es utilizado por algunos usuarios, por favor elimine o convierta estos usuarios a otro tipo de autentificación.
auths.deletion_success=¡La autenticación ha sido eliminada con éxito!
auths.login_source_exist=El origen de autenticación '%s' ya existe.
auths.github_api_endpoint=Endpoint de la API
auths.github_api_endpoint=API Endpoint
config.not_set=(sin definir)
config.server_config=Configuración del servidor
config.brand_name=Nombre de la marca
config.brand_name=Brand name
config.run_user=Ejecutada como Usuario
config.run_mode=Modo de ejecución
config.server.external_url=URL externa
config.server.domain=Dominio
config.server.protocol=Protocolo
config.server.external_url=External URL
config.server.domain=Domain
config.server.protocol=Protocol
config.server.http_addr=Dirección HTTP
config.server.http_port=Puerto HTTP
config.server.cert_file=Archivo de certificado
config.server.key_file=Archivo de claves
config.server.tls_min_version=Versión mínima de TLS
config.server.cert_file=Certificate file
config.server.key_file=Key file
config.server.tls_min_version=Minimum TLS version
config.server.unix_socket_permission=Unix socket permission
config.server.local_root_url=Local root URL
config.server.offline_mode=Offline mode
@ -1196,29 +1193,28 @@ config.server.load_assets_from_disk=Load assets from disk
config.server.landing_url=Landing URL
config.ssh_config=Configuración SSH
config.ssh.enabled=Activado
config.ssh.domain=Dominio expuesto
config.ssh.port=Puerto expuesto
config.ssh.enabled=Enabled
config.ssh.domain=Exposed domain
config.ssh.port=Exposed port
config.ssh.root_path=Root path
config.ssh.keygen_path=Ruta del generador de claves
config.ssh.key_test_path=Ruta de la clave de prueba
config.ssh.minimum_key_size_check=Comprobación del tamaño mínimo de la clave
config.ssh.minimum_key_sizes=Tamaño mínimo de las claves
config.ssh.rewrite_authorized_keys_at_start=Reescribir "authorized_keys" al inicio
config.ssh.keygen_path=Keygen path
config.ssh.key_test_path=Key test path
config.ssh.minimum_key_size_check=Minimum key size check
config.ssh.minimum_key_sizes=Minimum key sizes
config.ssh.rewrite_authorized_keys_at_start=Rewrite "authorized_keys" at start
config.ssh.start_builtin_server=Iniciar servidor integrado
config.ssh.listen_host=Host de escucha
config.ssh.listen_port=Puerto de escucha
config.ssh.server_ciphers=Cifrados del servidor
config.ssh.server_macs=MACs del servidor
config.ssh.server_algorithms=Algoritmos del servidor
config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.repo_config=Configuración del repositorio
config.repo.root_path=Ruta raíz
config.repo.root_path=Root path
config.repo.script_type=Script type
config.repo.ansi_chatset=ANSI charset
config.repo.force_private=Force private
config.repo.max_creation_limit=Max creation limit
config.repo.preferred_licenses=Licencias preferidas
config.repo.preferred_licenses=Preferred licenses
config.repo.disable_http_git=Disable HTTP Git
config.repo.enable_local_path_migration=Enable local path migration
config.repo.enable_raw_file_render_mode=Enable raw file render mode
@ -1232,18 +1228,18 @@ config.repo.upload.file_max_size=Upload file size limit
config.repo.upload.max_files=Upload files limit
config.db_config=Configuración de la Base de Datos
config.db.type=Tipo
config.db.type=Type
config.db.host=Host
config.db.name=Nombre
config.db.schema=Esquema
config.db.schema_helper=(sólo para "postgres")
config.db.user=Usuario
config.db.name=Name
config.db.schema=Schema
config.db.schema_helper=(for "postgres" only)
config.db.user=User
config.db.ssl_mode=SSL mode
config.db.ssl_mode_helper=(sólo para "postgres")
config.db.path=Ruta
config.db.path_helper=(sólo para "sqlite3")
config.db.max_open_conns=Número máximo de conexiones abiertas
config.db.max_idle_conns=Número máximo de conexiones inactivas
config.db.ssl_mode_helper=(for "postgres" only)
config.db.path=Path
config.db.path_helper=(for "sqlite3"only)
config.db.max_open_conns=Maximum open connections
config.db.max_idle_conns=Maximum idle connections
config.security_config=Security configuration
config.security.login_remember_days=Login remember days
@ -1266,11 +1262,11 @@ config.email.helo_hostname=HELO hostname
config.email.skip_verify=Skip certificate verify
config.email.use_certificate=Use custom certificate
config.email.cert_file=Certificate file
config.email.key_file=Archivo de claves
config.email.key_file=Key file
config.email.use_plain_text=Use plain text
config.email.add_plain_text_alt=Add plain text alternative
config.email.send_test_mail=Enviar correo de prueba
config.email.test_mail_failed=Error al enviar correo electrónico de prueba a '%s': %v
config.email.send_test_mail=Send test email
config.email.test_mail_failed=Failed to send test email to '%s': %v
config.email.test_mail_sent=Test email has been sent to '%s'.
config.auth_config=Authentication configuration
@ -1325,7 +1321,7 @@ config.picture.disable_gravatar=Disable Gravatar
config.picture.enable_federated_avatar=Enable federated avatars
config.mirror_config=Mirror configuration
config.mirror.default_interval=Intervalo por defecto
config.mirror.default_interval=Default interval
config.webhook_config=Configuración de Webhooks
config.webhook.types=Types

View File

@ -88,7 +88,6 @@ log_root_path=مسیر گزارش‌ها
log_root_path_helper=پوشه‌ای برای نوشتن فایل گزارش.
enable_console_mode=فعال کردن حالت کنسول
enable_console_mode_popup=لاگ‌ها علاوه بر ذخیره در فایل، در کنسول نیز به نمایش در آید.
default_branch=Default Branch
optional_title=تنظیمات اختیاری
email_title=تنظیمات سرویس ایمیل
@ -317,7 +316,6 @@ delete_email=حذف
email_deletion=حذف ایمیل
email_deletion_desc=حذف این آدرس ایمیل دیگر اطلاعات مربوط به آن را هم از حساب شما حذف می‌کند. آیا مایلید ادامه دهید؟
email_deletion_success=ایمیل با موفقیت حذف شد!
email_deletion_primary=Cannot delete primary email address.
add_new_email=اضافه کردن آدرس ایمیل جدید
add_email=اضافه کردن ایمیل
add_email_confirmation_sent=یک ایمیل تایید به آدرس %s ارسال شد, لطفا صندوق خود را حداکثر تا %d ساعت دیگر برای تکمیل فرایند تایید بررسی کنید.
@ -374,7 +372,6 @@ two_factor_disable_success=احراز هویت دوعاملی با موفقیت
manage_access_token=مدیریت توکن دسترسی شخصی
generate_new_token=تولید توکن جدید
tokens_desc=نشانه ایجاد شده که می تواند برای دسترسی به رابط های برنامه کاربردی Gogs مورد استفاده قرار گیرد.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=هر توکن می تواند دسترسی کامل به حساب شما داشته باشد.
token_name=نام توکن
generate_token=تولید توکن
@ -1212,7 +1209,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=پیکربندی مخزن
config.repo.root_path=Root path

View File

@ -22,13 +22,13 @@ password=Salasana
re_type=Kirjoita uudelleen
captcha=Captcha
repository=Tietosäilö
repository=Repository
organization=Organisaatio
mirror=Peili
new_repo=Uusi tietosäilö
new_repo=Uusi repository
new_migrate=Uusi migraatio
new_mirror=Uusi peilaus
new_fork=Uusi tietosäilö haarautuksesta
new_fork=Uusi fork-repository
new_org=Uusi organisaatio
manage_org=Ylläpidä organisaatioita
admin_panel=Ylläpito paneeli
@ -38,8 +38,8 @@ your_profile=Profiilisi
your_settings=Asetuksesi
activities=Toimet
pull_requests=Vetopyynnöt
issues=Esitykset
pull_requests=Pull requestit
issues=Ongelmat
cancel=Peruuta
@ -51,14 +51,14 @@ internal_server_error=Sisäinen palvelinvirhe
install=Asennus
title=Asennusvaiheet ottaessa ensi kertaa käyttöön
docker_helper=Jos käytät Gogsia Dockerin sisällä, ole hyvä ja lue <a target="_blank" href="%s">ohjeet</a> huolellisesti ennen kuin muutat mitään tältä sivulta!
requite_db_desc=Gogs tarvitsee tietokannakseen MySQL, PostgreSQL, SQLite3 tai TiDB (MySQL-protkollan kautta).
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Tietokannan asetukset
db_type=Tietokannan tyyppi
host=Isäntä
user=Käyttäjä
password=Salasana
db_name=Tietokannan nimi
db_schema=Skeema
db_schema=Schema
db_helper=Ole hyvä ja käytä INNODB moottoria ja utf8_general_ci merkistöä MySQLssä.
ssl_mode=SSL-tila
path=Polku
@ -70,8 +70,8 @@ err_empty_admin_password=Ylläpito salasana ei voi olla tyhjä.
general_title=Sovellus yleiset asetukset
app_name=Sovelluksen nimi
app_name_helper=Laita organisaatiosi nimi tähän isolla ja kovaäänisesti!
repo_path=Tietosäilön juurihakemisto
repo_path_helper=Kaikki Git-etätietosäilöt tullaan tallentamaan tähän hakemistoon.
repo_path=Repon juuren polku
repo_path_helper=Kaikki Git-etärepot tullaan tallentamaan tähän hakemistoon.
run_user=Suorita käyttäjänä
run_user_helper=Käyttäjällä täytyy olla oikeus repositoryn juuripolkuun. Käyttäjällä täytyy myös olla oikeus suorittaa Gogs.
domain=Verkkotunnus
@ -88,7 +88,6 @@ log_root_path=Lokin polku
log_root_path_helper=Lokien tallennushakemisto.
enable_console_mode=Ota käyttöön konsoli tila
enable_console_mode_popup=Tiedosto tilan lisäksi tulosta logit konsoliin.
default_branch=Oletus haara
optional_title=Valinnaiset asetukset
email_title=Sähköposti palvelu asetukset
@ -122,7 +121,7 @@ install_gogs=Asenna Gogs
test_git_failed=Epäonnistui testata 'git' komentoa: %v
sqlite3_not_available=Julkaisuversiosi ei tue SQLite3:a, ole hyvä ja lataa virallinen binääriversio osoitteesta %s, EI gobuild-versiota.
invalid_db_setting=Tietokanta asetus ei ole oikea: %v
invalid_repo_path=Tietosäilön juurihakemisto on virheellinen: %v
invalid_repo_path=Repo juuri polku on virheellinen: %v
run_user_not_match=Suoritus käyttäjä ei ole nykyinen käyttäjä: %s -> %s
smtp_host_missing_port=SMTP-isännältä puuttuu portin osoite.
invalid_smtp_from=SMTP From kenttä ei ole kelvollinen: %v
@ -136,17 +135,17 @@ invalid_log_root_path=Loki juurihakemisto ei kelpaa: %v
uname_holder=Käyttäjätunnus tai sähköposti
password_holder=Salasana
switch_dashboard_context=Vaihda kojelaudan kontekstia
my_repos=Minun tietosäilöt
show_more_repos=Näytä lisää tietosäilöjä...
collaborative_repos=Yhteistyötietosäilöt
my_repos=Reponi
show_more_repos=Näytä lisää repoja...
collaborative_repos=Yhteistyörepot
my_orgs=Organisaationi
my_mirrors=Peilaukseni
my_mirrors=Peilini
view_home=Näytä %s
issues.in_your_repos=Sinun tietosäilöissäsi
issues.in_your_repos=Repoissasi
[explore]
repos=Tietosäilöt
repos=Repot
users=Käyttäjät
organizations=Organisaatiot
search=Hae
@ -199,7 +198,7 @@ modify=Muokkaa
[form]
UserName=Käyttäjätunnus
RepoName=Tietosäilön nimi
RepoName=Repon nimi
Email=Sähköpostiosoite
Password=Salasana
Retype=Kirjoita salasana uudelleen
@ -211,8 +210,8 @@ AuthName=Luvan nimi
AdminEmail=Ylläpito sähköposti
NewBranchName=Uuden haaran nimi
CommitSummary=Sitoutuksen yhteenveto
CommitMessage=Sitoutuksen viesti
CommitSummary=Commitin yhteenveto
CommitMessage=Commitin viesti
CommitChoice=Commitin valinta
TreeName=Tiedostopolku
Content=Sisältö
@ -232,13 +231,13 @@ captcha_incorrect=Captcha ei ollut oikein.
password_not_match=Salasana ja salasanan varmistus eivät ole samoja.
username_been_taken=Käyttäjätunnus on jo käytössä.
repo_name_been_taken=Tietosäilön nimi on jo käytössä.
repo_name_been_taken=Repon nimi on jo käytössä.
org_name_been_taken=Organisaation nimi on jo käytössä.
team_name_been_taken=Tiimin nimi on jo käytössä.
email_been_used=Sähköpostiosoite on jo käytössä.
username_password_incorrect=Käyttäjätunnus tai salasana ei ole oikein.
auth_source_mismatch=Valittua todennuslähdettä ei liitetä käyttäjään.
enterred_invalid_repo_name=Ole hyvä ja varmista että kirjoittamasi tietosäilön nimi on oikein.
enterred_invalid_repo_name=Ole hyvä ja varmista että kirjoittamasi repon nimi on oikein.
enterred_invalid_owner_name=Ole hyvä ja varmista että kirjoittamasi omistajan nimi on oikein.
enterred_invalid_password=Ole hyvä ja varmista että kirjoittamasi salasana on oikein.
user_not_exist=Käyttäjää ei ole olemassa.
@ -248,16 +247,16 @@ invalid_ssh_key=Pahoittelut, emme pystyneet varmistamaan SSH-avainta: %s
unable_verify_ssh_key=Gogs ei voi varmistaa SSH-avaintasi, mutta oletamme että se on toimiva, ole hyvä ja tarkista se.
auth_failed=Todennus epäonnistui: %v
still_own_repo=Tililläsi on yhä omistajuus ainakin yhteen tietosäilöön, sinun täytyy poistaa tai siirtää ne ensin.
still_own_repo=Tililläsi on yhä omistajuus ainakin yhteen repoon, sinun täytyy poistaa tai siirtää ne ensin.
still_has_org=Tililläsi on yhä jäsenyys ainakin yhteen organisaatioon, sinun täytyy jäädä pois tai poistaa jäsenyyksiä ensin.
org_still_own_repo=Tällä organisaatiolla on yhä omistajuus tietosäilöön, sinun täytyy poistaa tai siirtää ne ensin.
org_still_own_repo=Tällä organisaatiolla on yhä omistajuus repoon, sinun täytyy poistaa tai siirtää ne ensin.
target_branch_not_exist=Kohde haaraa ei ole olemassa.
target_branch_not_exist=Kohde branchia ei ole olemassa.
[user]
change_avatar=Vaihda profiilikuvasi
join_on=Liitytty
repositories=Tietosäilöt
repositories=Repot
activity=Julkinen toiminta
followers=Seuraajat
starred=Äänestetty
@ -273,7 +272,7 @@ password=Salasana
avatar=Profiilikuva
ssh_keys=SSH avaimet
security=Turvallisuus
repos=Tietosäilö
repos=Repot
orgs=Organisaatiot
applications=Sovellukset
delete=Poista tili
@ -317,7 +316,6 @@ delete_email=Poista
email_deletion=Sähköpostin poistaminen
email_deletion_desc=Tämän sähköpostiosoitteen poistaminen poistaa siihen liittyvät tiedot tililtäsi. Haluatko jatkaa?
email_deletion_success=Sähköposti on poistettu onnistuneesti!
email_deletion_primary=Pääsähköpostin poistaminen ei onnistu.
add_new_email=Lisää uusi sähköpostiosoite
add_email=Lisää sähköposti
add_email_confirmation_sent=Uusi varmistussähköposti on lähetetty osoitteeseen '%s', ole hyvä ja tarkista saapuneet seuraavan %d tunnin sisällä saadaksesi rekisteröintiprosessin valmiiksi.
@ -372,7 +370,6 @@ two_factor_disable_success=Kaksivaiheinen todennus on poistettu käytöstä onni
manage_access_token=Hallitse henkilökohtaisia pääsymerkkejä
generate_new_token=Luo uusi pääsymerkki
tokens_desc=Luomiasi pääsymerkkejä voidaan käyttää Gogs APIn kanssa.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Joka pääsymerkillä on täysi pääsy tiliisi.
token_name=Pääsymerkin nimi
generate_token=Luo pääsymerkki
@ -388,9 +385,9 @@ orgs.leave_title=Poistu organisaatiosta
orgs.leave_desc=Menetät oikeudet kaikkiin niihin repoihin ja tiimeihin joihin organisaatio on sinulle oikeudet antanut. Haluatko varmasti jatkaa?
repos.leave=Poistu
repos.leave_title=Poistu tietosäilöstä
repos.leave_desc=Menetät pääsyn tietosäilöön poistuessasi. Haluatko jatkaa?
repos.leave_success=Olet poistunut tietosäilöstä '%s' onnistuneesti!
repos.leave_title=Poistu reposta
repos.leave_desc=Menetät pääsyn repoon kun poistut. Haluatko jatkaa?
repos.leave_success=Olet poistunut reposta '%s' onnistuneesti!
delete_account=Poista tilisi
delete_prompt=Toiminto poistaa tilisi pysyvästi ja tätä <strong>EI VOI</strong> peruuttaa myöhemmin!
@ -400,18 +397,18 @@ delete_account_desc=Tämä tili poistetaan lopullisesti, haluatko jatkaa?
[repo]
owner=Omistaja
repo_name=Tietosäilön nimi
repo_name_helper=Hyvä tietosäilönimi yleensä koostuu lyhyistä, mieleenpainuvista ja ainutlaatuisista avainsanoista.
repo_name=Repon nimi
repo_name_helper=Hyvä repon nimi yleensä koostuu lyhyistä, mieleenpainuvista ja ainutlaatuisista avainsanoista.
visibility=Näkyvyys
unlisted=Listaamaton
visiblity_helper=Tämä tietosäilö on <span class="ui red text">yksityinen</span>
unlisted_helper=Tämä tietosäilö on <span class="ui red text">listaamaton</span>
visiblity_helper_forced=Sivuston ylläpito on pakottanut kaikkien uusien tietosäilöjen olevan <span class="ui red text">yksityisiä</span>
visiblity_fork_helper=(Arvon vaihtaminen vaikuttaa kaikkiin haarautuksiin)
unlisted=Unlisted
visiblity_helper=Tämä repo on <span class="ui red text">yksityinen</span>
unlisted_helper=This repository is <span class="ui red text">Unlisted</span>
visiblity_helper_forced=Sivuston ylläpito on pakottanut kaikkien uusien repojen olevan <span class="ui red text">yksityisiä</span>
visiblity_fork_helper=(Arvon vaihtaminen vaikuttaa kaikkiin forkkeihin)
clone_helper=Tarvitsetko apua kloonauksessa? Vieraile osoitteessa <a target="_blank" href="%s">Apua</a>!
fork_repo=Haarauta tietosäilö
fork_from=Haarauta lähteestä
fork_visiblity_helper=Et voi muuttaa haarautetun tietosäilön näkyvyyttä.
fork_repo=Forkkaa repo
fork_from=Forkkaa lähteestä
fork_visiblity_helper=Et voi muuttaa forkatun repon näkyvyyttä.
repo_desc=Kuvaus
repo_lang=Kieli
repo_gitignore_helper=Valitse .gitignore malli
@ -419,9 +416,9 @@ license=Lisenssi
license_helper=Valitse lisenssitiedosto
readme=Lueminut-tiedosto
readme_helper=Valitse Lueminut-malli
auto_init=Alusta tämä tietosäilö valituilla tiedostoilla ja mallilla
create_repo=Luo tietosäilö
default_branch=Oletus haara
auto_init=Alusta tämä repo valituilla tiedostoilla ja mallilla
create_repo=Luo repo
default_branch=Oletus branch
mirror_prune=Karsi
mirror_prune_desc=Poista kaikki paikalliset seurantahaarat joiden vastaavia etähaaroja ei ole enää olemassa
mirror_interval=Peili aikaväli (tuntia)
@ -430,7 +427,7 @@ mirror_address_desc=Ole hyvä ja liitä osoitteeseen tarvittavat käyttäjätunn
mirror_last_synced=Synkronoitu viimeksi
watchers=Tarkkailijat
stargazers=Tähtiharrastajat
forks=Haarautukset
forks=Haarat
repo_description_helper=Repon kuvaus. Enintään 512 merkkiä.
repo_description_length=Käytettävissä olevat merkit
@ -441,7 +438,7 @@ need_auth=Tarvitaan lupa
migrate_type=Siirtotyyppi
migrate_type_helper=Tämä repo tulee olemaan <span class="text blue">peili</span>
migrate_repo=Siirrä repo
migrate.clone_address=Monistuksen osoite
migrate.clone_address=Kloonaa osoite
migrate.clone_address_desc=Tämä voi olla HTTP/HTTPS/GIT URL.
migrate.clone_address_desc_import_local=Paikallisen palvelimen kansiopolun käyttö repon migraatiossa on myös salittua.
migrate.permission_denied=Sinun ei sallita tuovan paikallisia repoja.
@ -450,7 +447,7 @@ migrate.clone_address_resolved_to_blocked_local_address=Clone address resolved t
migrate.failed=Siirto epäonnistui: %v
mirror_from=peilaus alkaen
forked_from=haarautettu lähteestä
forked_from=forkattu lähteestä
copy_link=Kopioi
copy_link_success=Kopioitu!
copy_link_error=Paina ⌘-C tai Ctrl-C kopioidaksesi
@ -459,26 +456,26 @@ unwatch=Lopeta tarkkailu
watch=Tarkkaile
unstar=Peru ääni
star=Äänestä
fork=Haarauta
fork=Fork
no_desc=Ei kuvausta
quick_guide=Pikaopas
clone_this_repo=Kloonaa tämä repo
create_new_repo_command=Luo uusi repo komentoriviltä
push_exist_repo=Työnnä olemassa oleva tietosäilö komentoriviltä
push_exist_repo=Työnnä olemassaoleva repo komentoriviltä
bare_message=Tässä repossa ei ole mitään sisältöä vielä.
files=Tiedostot
branch=Haara
tree=Puu
filter_branch_and_tag=Suodata haara tai tunniste
filter_branch_and_tag=Suodata haara tai tagi
branches=Haarat
tags=Tunnisteet
issues=Esitykset
pulls=Vetopyynnöt
labels=Leimat
tags=Tagit
issues=Ongelmat
pulls=Pull-pyynnöt
labels=Tunnisteet
milestones=Merkkipaalut
commits=Sitoutukset
commits=Commitit
git_branches=Haarat
releases=Julkaisut
file_raw=Raaka
@ -486,11 +483,11 @@ file_history=Historia
file_view_raw=Näytä raaka
file_permalink=Pysyvä linkki
file_too_large=Tämä tiedosto on liian suuri näytettäväksi
video_not_supported_in_browser=Selaimesi ei tue HTML5 video-avainsanaa.
video_not_supported_in_browser=Selaimesi ei tue HTML5 video-tagia.
branches.overview=Yleiskatsaus
branches.active_branches=Aktiiviset haarat
branches.stale_branches=Passivoituneet haarat
branches.stale_branches=Vanhentuneet haarat
branches.all=Kaikki haarat
branches.updated_by=Päivitetty %[1]s %[2]s
branches.change_default_branch=Muuta oletushaaraa
@ -502,7 +499,7 @@ editor.preview_changes=Muutosten esikatselu
editor.cannot_edit_non_text_files=Voit editoida vain tekstitiedostoja
editor.edit_this_file=Muokkaa tätä tiedostoa
editor.must_be_on_a_branch=Haara täytyy olla valittuna jotta voit tehdä tai ehdottaa muutoksia tähän tiedostoon
editor.fork_before_edit=Sinun täytyy haarautaa tästä tietosäilöstä ennen tiedoston muokkaamista
editor.fork_before_edit=Sinun täytyy forkata tämä repo ennenkuin voit muokata tiedostoa
editor.delete_this_file=Poista tämä tiedosto
editor.must_have_write_access=Sinulla on kirjoitusoikeus tai ehdottaa muutoksia tiedostoon
editor.file_delete_success=Tiedosto "%s" on poistettu onnistuneesti!
@ -510,14 +507,14 @@ editor.name_your_file=Nimeä tiedostosi...
editor.filename_help=Lisää hakemisto, kirjoita se ja paina /. Poista hakemisto, siirry kentän alkuun ja paina ASKELPALAUTINTA.
editor.or=tai
editor.cancel_lower=peruuta
editor.commit_changes=Sitouta muutokset
editor.commit_changes=Vahvista muutokset
editor.add_tmpl=Lisää '%s/<filename>'
editor.add=Lisää "%s"
editor.update=Päivitä '%s'
editor.delete=Poista "%s"
editor.commit_message_desc=Lisää valinnainen pidennetty kuvaus...
editor.commit_directly_to_this_branch=Sitouta suoraan haaraan <strong class="branch-name">%s</strong>.
editor.create_new_branch=Luo <strong>uusi kehityshaara</strong> tälle sitoutukselle tai tee vetopyyntö.
editor.commit_message_desc=Lisää pidennetty selite (valinnainen)...
editor.commit_directly_to_this_branch=Committaa suoraan haaraan <strong class="branch-name">%s</strong>.
editor.create_new_branch=Luo <strong>uusi haara</strong> tälle commitille tai aloita pull-pyyntö.
editor.new_branch_name_desc=Uuden haaran nimi...
editor.cancel=Peruuta
editor.filename_cannot_be_empty=Tiedostonimi ei voi olla tyhjä.
@ -526,7 +523,7 @@ editor.directory_is_a_file=Annettu nimi '%s' on tiedosto, ei kansio.
editor.file_is_a_symlink=Tiedosto '%s' on symlinkki jota ei voi muokata web-selaimesta.
editor.filename_is_a_directory=Kansio nimeltä '%s' on jo olemassa tässä repossa.
editor.file_editing_no_longer_exists=Tiedostoa '%s' jota olet muokkaamassa ei ole enää olemassa tässä repossa.
editor.file_changed_while_editing=Tiedoston sisältöä on muutettu aloittamisesi jälkeen. <a target="_blank" href="%s">Napsauta tästä</a> nähdäksesi mitä on muutettu tai <strong>paina sitouta uudelleen</strong> kirjoittaaksesi muutosten päälle.
editor.file_changed_while_editing=Tiedoston sisältöä on muutettu aloittamisesi jälkeen. <a target="_blank" href="%s">Napsauta tästä</a> nähdäksesi mitä on muutettu tai <strong>paina commit uudelleen</strong> ylikirjoittaaksesi muutokset.
editor.file_already_exists=Tiedosto '%s' on jo olemassa tässä repossa.
editor.no_changes_to_show=Ei muutoksia näytettäväksi.
editor.fail_to_update_file=Tiedoston '%s' päivitys/luonti epäonnistui virheeseen: %v
@ -535,9 +532,9 @@ editor.add_subdir=Lisää alikansio...
editor.unable_to_upload_files=Tiedostojen lataus epäonnistui kansioon '%s' virheellä: %v
editor.upload_files_to_dir=Lataa tiedostoja kansioon '%s'
commits.commit_history=Sitoutushistoria
commits.commits=Sitoutukset
commits.search=Etsi sitoutuksista
commits.commit_history=Commitin historia
commits.commits=Commitit
commits.search=Etsi commiteista
commits.find=Etsi
commits.author=Tekijä
commits.message=Viesti
@ -545,10 +542,10 @@ commits.date=Päivämäärä
commits.older=Vanhemmat
commits.newer=Uudemmat
issues.new=Uusi esitys
issues.new.labels=Leimat
issues.new.no_label=Ei leimaa
issues.new.clear_labels=Tyhjennä leimavalinta
issues.new=Uusi ongelma
issues.new.labels=Tunnisteet
issues.new.no_label=Ei tunnistetta
issues.new.clear_labels=Tyhjennä tunnisteet
issues.new.milestone=Merkkipaalu
issues.new.no_milestone=Ei merkkipaalua
issues.new.clear_milestone=Tyhjennä merkkipaalu
@ -557,25 +554,25 @@ issues.new.closed_milestone=Suljetut merkkipaalut
issues.new.assignee=Osoitettu
issues.new.clear_assignee=Tyhjennä osoitettu
issues.new.no_assignee=Ei osoitettua
issues.create=Luo esitys
issues.new_label=Uusi leima
issues.new_label_placeholder=Leiman nimi...
issues.create_label=Luo leima
issues.label_templates.title=Lataa ennaltamääritelty leimajoukko
issues.label_templates.info=Täällä ei ole vielä leimoja. Voit luoda uuden napsauttamalla "Uusi leima" tai käyttää ennaltamääriteltyä leimajoukkoa alta.
issues.label_templates.helper=Valitse leimajoukko
issues.label_templates.use=Käytä tätä leimajoukkoa
issues.label_templates.fail_to_load_file=Leimamallin lataus epäonnistui tiedostosta '%s': %v
issues.create=Ilmoita ongelma
issues.new_label=Uusi tunniste
issues.new_label_placeholder=Tunnisteen nimi...
issues.create_label=Luo tunniste
issues.label_templates.title=Lataa ennaltamääritelty tarrajoukko
issues.label_templates.info=Tarroja ei ole. Voit luoda uuden napsauttamalla "Uusi tarra" tai käyttää ennaltamääriteltyä tarrajoukkoa alta.
issues.label_templates.helper=Valitse tarrajoukko
issues.label_templates.use=Käytä tätä tarrajoukkoa
issues.label_templates.fail_to_load_file=Tarramallin lataus epäonnistui tiedostosta '%s': %v
issues.open_tab=%d avoinna
issues.close_tab=%d suljettu
issues.filter_label=Leima
issues.filter_label_no_select=Ei leimaa valittuna
issues.filter_label=Tunniste
issues.filter_label_no_select=Ei valittua tunnistetta
issues.filter_milestone=Merkkipaalu
issues.filter_milestone_no_select=Ei valittua merkkipaalua
issues.filter_assignee=Osoitettu
issues.filter_assginee_no_select=Ei valittua osoitettua
issues.filter_type=Tyyppi
issues.filter_type.all_issues=Kaikki esitykset
issues.filter_type.all_issues=Kaikki ongelmat
issues.filter_type.assigned_to_you=Osoitettu sinulle
issues.filter_type.created_by_you=Ilmoittamasi
issues.filter_type.mentioning_you=Jotka mainitsee sinut
@ -603,7 +600,7 @@ issues.reopen_comment_issue=Kommentoi ja avaa uudelleen
issues.create_comment=Kommentoi
issues.closed_at=`suljettu <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`avattu uudelleen <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`viittasi tähän esitykseen sitoutuksesta <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`viittasi tähän ongelmaan commitissa <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Tekijä
issues.collaborator=Yhteistyökumppani
issues.owner=Omistaja
@ -611,51 +608,51 @@ issues.sign_in_require_desc=<a href="%s">Kirjaudu sisään</a> osallistuaksesi t
issues.edit=Muokkaa
issues.cancel=Peruuta
issues.save=Tallenna
issues.label_title=Leiman nimi
issues.label_color=Leiman väri
issues.label_count=%d leimaa
issues.label_open_issues=%d avointa esitystä
issues.label_title=Tunnisteen nimi
issues.label_color=Tunnisteen väri
issues.label_count=%d tunnistetta
issues.label_open_issues=%d avointa ongelmaa
issues.label_edit=Muokkaa
issues.label_delete=Poista
issues.label_modify=Leiman muokkaus
issues.label_deletion=Leiman poistaminen
issues.label_deletion_desc=Tämän leiman poistaminen kadottaa sen kaikista esityksistä. Haluatko jatkaa?
issues.label_deletion_success=Leima on poistettu onnistuneesti!
issues.label_modify=Tunnisteen muokkaus
issues.label_deletion=Tunnisteen poistaminen
issues.label_deletion_desc=Tämän tunnisteen poistaminen poistaa sen tiedot kaikista siihen liittyvistä ongelmista. Haluatko jatkaa?
issues.label_deletion_success=Tunniste on poistettu onnistuneesti!
issues.num_participants=%d osallistujaa
issues.attachment.open_tab=`Napsauta nähdäksesi "%s" uudessa välilehdessä`
issues.attachment.download=`Napsauta ladataksesi "%s"`
pulls.new=Uusi vetopyyntö
pulls.new=Uusi pull pyyntö
pulls.compare_changes=Vertaa muutoksia
pulls.compare_changes_desc=Vertaa kahta haaraa ja tee vetopyyntö muutoksista.
pulls.compare_base=pohja
pulls.compare_changes_desc=Vertaa kahta branchia ja tee pull-pyyntö muutoksista.
pulls.compare_base=base
pulls.compare_compare=vertaa
pulls.filter_branch=Suodata haara
pulls.no_results=Tuloksia ei löytynyt.
pulls.nothing_to_compare=Ei ole mitään verrattavaa koska base ja head branchit ovat tasoissa.
pulls.nothing_merge_base=Ei ole mitään verrattavaa, koska kahdella haaralla on täysin erilainen historia.
pulls.has_pull_request=`On olemassa jo pull pyyntö näiden kohteiden välillä: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Luo vetopyyntö
pulls.title_desc=haluaa liittää %[1]d sitoutusta lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code>
pulls.merged_title_desc=liitetty %[1]d sitoutusta lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s
pulls.create=Luo Pull-pyyntö
pulls.title_desc=haluaa yhdistää %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code>
pulls.merged_title_desc=yhdistetty %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s
pulls.tab_conversation=Keskustelu
pulls.tab_commits=Sitoutukset
pulls.tab_files=Muutetut tiedostot
pulls.reopen_to_merge=Ole hyvä ja avaa tämä vetopyyntö uudelleen liittääksesi.
pulls.merged=Liitetty
pulls.has_merged=Tämä vetopyyntö on liitetty onnistuneesti!
pulls.data_broken=Tämän vetopyynnön tiedot ovat hajonneet poistettujen haarautustietojen vuoksi.
pulls.tab_commits=Commitit
pulls.tab_files=Muuttuneet tiedostot
pulls.reopen_to_merge=Ole hyvä ja avaa uudelleen tämä pull-pyyntö suorittaaksesi yhdistämisen.
pulls.merged=Yhdistetty
pulls.has_merged=Tämä pull-pyyntö on yhdistetty onnistuneesti!
pulls.data_broken=Tämän pull-pyynnön tiedot ovat rikkoutuneet koska fork tiedot on poistettu.
pulls.is_checking=Konfliktin tarkistus on yhä meneillään, ole hyvä ja päivitä sivu hetken kuluttua.
pulls.can_auto_merge_desc=Tämä vetopyyntö voidaan yhdistää automaattisesti.
pulls.cannot_auto_merge_desc=Tätä vetopyyntöä ei voi liittää automaattisesti konfliktien takia.
pulls.cannot_auto_merge_helper=Ole hyvä ja liitä manuaalisesti konfliktien ratkaisemiseksi.
pulls.create_merge_commit=Luo liitossitoutus
pulls.rebase_before_merging=Sulauta ennen yhdistämistä
pulls.commit_description=Sitoutuksen kuvaus
pulls.merge_pull_request=Liitä vetopyyntö
pulls.can_auto_merge_desc=Tämä pull-pyyntö voidaan yhdistää automaattisesti.
pulls.cannot_auto_merge_desc=Tätä pull-pyyntöä ei voi yhdistää automaattisesti koska on konflikteja.
pulls.cannot_auto_merge_helper=Ole hyvä ja yhdistä manuaalisesti konfliktien ratkaisemiseksi.
pulls.create_merge_commit=Luo yhdistämistoiminto
pulls.rebase_before_merging=Rebase ennen yhdistämistä
pulls.commit_description=Toimituksen kuvaus
pulls.merge_pull_request=Yhdistä Pull-pyyntö
pulls.open_unmerged_pull_exists=`Et voi suorittaa uudelleenavaus toimintoa koska on jo olemassa pull-pyyntö (#%d) samasta reposta samoilla yhdistämistiedoilla ja odottaa yhdistämistä.`
pulls.delete_branch=Poista haara
pulls.delete_branch_has_new_commits=Kehityshaaraa ei voida poistaa, koska siihen on tullut uusia sitoutuksia liitoksen jälkeen.
pulls.delete_branch_has_new_commits=Haaraa ei voida poistaa koska siinä on uusia committeja mergen jälkeen.
milestones.new=Uusi merkkipaalu
milestones.open_tab=%d avoinna
@ -688,7 +685,7 @@ wiki.create_first_page=Luo ensimmäinen sivu
wiki.page=Sivu
wiki.filter_page=Suodatin sivu
wiki.new_page=Luo uusi sivu
wiki.default_commit_message=Kirjoita viesti tästä päivityksestä (valinnainen).
wiki.default_commit_message=Kirjoita huomautus tähän päivitykseen (valinnainen).
wiki.save_page=Tallenna sivu
wiki.last_commit_info=%s muokkasi tätä sivua %s
wiki.edit_page_button=Muokkaa
@ -709,21 +706,21 @@ settings.collaboration.undefined=Määrittelemätön
settings.branches=Haarat
settings.branches_bare=Et voi hallita haaroja tyhjässä repossa. Lisää jotain sisältöä ensin.
settings.default_branch=Oletushaara
settings.default_branch_desc=Oletushaaraa käytetään "pohjahaarana" sitoutuksille, vetopyynnöille ja sivustolla toteutetuille muokkauksille.
settings.default_branch_desc=Oletushaaraa käytetään "pohjahaarana" commiteille, pull-pyynnöille ja sivustolla toteutetuille muokkauksille.
settings.update=Päivitä
settings.update_default_branch_unsupported=Palvelimella oleva Git-versio ei tue oletushaaran vaihtamista.
settings.update_default_branch_success=Repositoryn oletushaara päivitetty!
settings.protected_branches=Suojatut haarat
settings.protected_branches_desc=Suojaa kehityshaaroja pakkotyönnöiltä, vahinkopoistamisilta ja sallituilta sitouttajilta.
settings.protected_branches_desc=Suojaa haaroja pakotetulta push-operaatiolta, vahinkopoistamisilta ja sallitun listan committereilta.
settings.choose_a_branch=Valitse haara...
settings.branch_protection=Haaran suojaus
settings.branch_protection_desc=Valitse suojausasetus haaralle <b>%s</b>.
settings.protect_this_branch=Suojaa tämä haara
settings.protect_this_branch_desc=Kiellä pakoteut push-operaatiot ja estä poistaminen.
settings.protect_require_pull_request=Vaadi pull-pyyntö suoran push-operaation sijaan
settings.protect_require_pull_request_desc=Ota tämä asetus käyttöön estääksesi suorat työnnöt tähän kehityshaaraan. Sitoutukset täytyy työntää ei-suojattuun kehityshaaraan ja liittää tähän kehityshaaraan vetopyynnön kautta.
settings.protect_whitelist_committers=Lista sallituista, jotka voivat työntää tähän kehityshaaraan
settings.protect_whitelist_committers_desc=Lisää käyttäjiä tai tiimejä sallittuihin jotka saavat työntää tähän kehityshaaraan. Sallitut käyttäjät voivat ohittaa vaatimuksen vetopyyntöjen tekemisestä.
settings.protect_require_pull_request_desc=Estä suorat push-operaatiot tähän haaraan. Commitit täytyy pushata ei-suojattuun haaraan ja yhdistää tähän haaraan pull-pyynnön kautta.
settings.protect_whitelist_committers=Lista sallituista, jotka voivat pushata tähän haaraan
settings.protect_whitelist_committers_desc=Lisää käyttäjiä tai tiimejä sallittuihin jotka saavat pushata tähän haaraan. Sallitut käyttäjät voivat ohittaa vaatimuksen pull requestien tekemisestä.
settings.protect_whitelist_users=Käyttäjät jotka voivat pushata tähän haaraan
settings.protect_whitelist_search_users=Etsi käyttäjiä
settings.protect_whitelist_teams=Tiimit joiden jäsenet voivat pushata tähän haaraan
@ -745,22 +742,22 @@ settings.allow_public_wiki_desc=Salli julkinen pääsy wikiin kun repo on yksity
settings.use_external_wiki=Käytä ulkoista wikiä
settings.external_wiki_url=Ulkoisen wikin osoite
settings.external_wiki_url_desc=Vierailijat uudelleenohjataan URL-osoitteeseen kun he napsauttavat välilehteä.
settings.issues_desc=Ota esitystenseuranta käyttöön
settings.use_internal_issue_tracker=Käytä kevyttä, sisäänrakennettua esitystenseurantaa
settings.allow_public_issues_desc=Salli julkinen pääsy esityksiin tietosäilön ollessa yksityinen
settings.use_external_issue_tracker=Käytä ulkoista esitystenseurantaa
settings.issues_desc=Ota virheenseuranta käyttöön
settings.use_internal_issue_tracker=Käytä sisäänrakennettua kevyttä virheenseurantaa
settings.allow_public_issues_desc=Salli julkinen pääsy ongelmiin kun repo on yksityinen
settings.use_external_issue_tracker=Käytä ulkoista vikaseurantaa
settings.external_tracker_url=Ulkoisen virheenseurannan URL
settings.external_tracker_url_desc=Vierailijat ohjataan URL-osoitteeseen kun he napsauttavat välilehteä.
settings.tracker_url_format=Ulkoisen vikaseurannan osoitteen muoto
settings.tracker_issue_style=Ulkoisen esitystenseurannan nimeämistyyli:
settings.tracker_issue_style=Ulkoisen virheenseurannan nimeämistyyli:
settings.tracker_issue_style.numeric=Numeerinen
settings.tracker_issue_style.alphanumeric=Aakkosnumeerinen
settings.tracker_url_format_desc=Voit käyttää paikkamerkkiä <code>{user} {repo} {index}</code> käyttäjänimelle, reponimelle ja vikanumerolle.
settings.pulls_desc=Ota käyttöön pull-pyynnöt hyväksyäksesi vastaanotettua koodia repojen ja haarojen välillä
settings.pulls.ignore_whitespace=Ohita tyhjämerkkien muutokset
settings.pulls.allow_rebase_merge=Salli sitoutusten sulauttaminen
settings.pulls.allow_rebase_merge=Salli rebase yhdistäessä committeja
settings.danger_zone=Vaaravyöhyke
settings.cannot_fork_to_same_owner=Et voi haarauttaa tietosäilöä alkuperäiselle omistajalle.
settings.cannot_fork_to_same_owner=Et voi forkata repoa alkuperäiselle omistajalleen.
settings.new_owner_has_same_repo=Uudella omistajalla on jo samanniminen repo. Ole hyvä ja valitse toinen nimi.
settings.convert=Muunna tavalliseksi repoksi
settings.convert_desc=Voit muuntaa tämän peilin tavalliseksi repoksi. Tätä ei voi peruuttaa.
@ -780,7 +777,7 @@ settings.delete=Poista tämä repo
settings.delete_desc=Huomio, kun kerran poistat repon, niin ei ole paluuta. Varmista että haluat todella tehdä tämän.
settings.delete_notices_1=- Tätä toimintoa <strong>EI VOI</strong> peruuttaa myöhemmin.
settings.delete_notices_2=- Tämä toiminto poistaa pysyvästi kaikki tästä reposta, mukaanlukien Git tiedot, ongelmat, kommentit ja yhteistyökumppanien pääsyoikeudet.
settings.delete_notices_fork_1=- Kaikki haarautukset muuttuvat itsenäisiksi poiston jälkeen.
settings.delete_notices_fork_1=- Kaikki haarat muuttuvat itsenäisiksi poiston jälkeen.
settings.deletion_success=Repo on poistettu onnistuneesti!
settings.update_settings_success=Repon asetukset on päivitetty onnistuneesti.
settings.transfer_owner=Uusi omistaja
@ -828,21 +825,21 @@ settings.slack_username=Käyttäjätunnus
settings.slack_icon_url=Kuvakkeen URL
settings.slack_color=Väri
settings.event_desc=Milloin pitäisi tämän webkoukun laueta?
settings.event_push_only=Vain <code>push</code>-komennolla.
settings.event_push_only=Vain <code>push</code>-tilanteessa.
settings.event_send_everything=Tarvitsen <strong>kaiken</strong>.
settings.event_choose=Haluan valita, mitä tarvitsen.
settings.event_create=Luo
settings.event_create_desc=Kehityshaara tai tunniste luotu
settings.event_create_desc=Branch, tai tagi luotu
settings.event_delete=Poista
settings.event_delete_desc=Kehityshaara tai tunniste poistettu
settings.event_fork=Haarautus
settings.event_fork_desc=Tietosäilö haarautettu
settings.event_push=Työntö
settings.event_push_desc=Git työntö tietosäilöön
settings.event_issues=Esitykset
settings.event_issues_desc=Esitys avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, leima päivitetty, leima poistettu, merkkipaalutettu, tai merkkipaalutus vedottu.
settings.event_delete_desc=Branch, tai tagi luotu
settings.event_fork=Fork
settings.event_fork_desc=Repo forkattu
settings.event_push=Push
settings.event_push_desc=Git push repoon
settings.event_issues=Ongelmat
settings.event_issues_desc=Ongelma avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, tarra päivitetty, tarra poistettu, merkkipaalutettu, tai poistettu merkkipaalu.
settings.event_pull_request=Pull-pyyntö
settings.event_pull_request_desc=Vetopyyntö avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, leima päivitetty, leima poistettu, merkkipaalutettu, merkkipaalutus vedottu, tai synkronoitu.
settings.event_pull_request_desc=Pull-pyyntö avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, tarra päivitetty, tarra poistettu, merkkipaalutettu, poistettu merkkipaalu, tai synkronoitu.
settings.event_issue_comment=Ongelman kommentti
settings.event_issue_comment_desc=Ongelman kommentti luotu, muokattu, tai poistettu.
settings.event_release=Julkaisu
@ -879,7 +876,7 @@ settings.description_length=Käytettävissä olevat merkit
diff.browse_source=Selaa lähdekoodia
diff.parent=vanhempi
diff.commit=sitoutus
diff.commit=commit
diff.data_not_available=Diff tiedot eivät ole saatavilla.
diff.show_diff_stats=Näytä diff tilastot
diff.show_split_view=Jaettu näkymä
@ -895,13 +892,13 @@ release.new_release=Uusi julkaisu
release.draft=Työversio
release.prerelease=Esiversio
release.edit=muokkaa
release.ahead=<strong>%d</strong> sitoutusta kehityshaaraan %s tämän julkaisun jälkeen
release.ahead=<strong>%d</strong> committia kohteeseen %s version jälkeen
release.source_code=Lähdekoodi
release.new_subheader=Julkaise versioita iteroidaksesi tuotetta.
release.edit_subheader=Yksityskohtainen muutosloki auttaa käyttäjiä ymmärtämään mitä on parannettu.
release.tag_name=Tunnisteen nimi
release.tag_name=Taginimi
release.target=Kohde
release.tag_helper=Valitse olemassa oleva tunniste, tai luo uusi tunniste julkaistaessa.
release.tag_helper=Valitse olemassaoleva tagi, tai luo uusi tagi julkaistaessa.
release.title=Otsikko
release.content=Sisältö
release.write=Kirjoita
@ -915,10 +912,10 @@ release.save_draft=Tallenna luonnos
release.edit_release=Muokkaa versiota
release.delete_release=Poista tämä versio
release.deletion=Version poisto
release.deletion_desc=Tämän julkaisun poistaminen poistaa vastaavan Git-tunnisteen. Haluatko jatkaa?
release.deletion_desc=Tämän julkaisun poistaminen poistaa vastaavan Git-tagin. Haluatko jatkaa?
release.deletion_success=Versio on poistettu onnistuneesti!
release.tag_name_already_exist=Julkaisu tällä tunniste nimellä on jo olemassa.
release.tag_name_invalid=Tunnisteen nimi ei kelpaa.
release.tag_name_already_exist=Versio tällä taginimellä on jo olemassa.
release.tag_name_invalid=Tagin nimi ei kelpaa
release.downloads=Lataukset
[org]
@ -1018,7 +1015,7 @@ dashboard.app_ver=Sovellus versio
dashboard.git_version=Git-versio
dashboard.go_version=Go-versio
dashboard.build_time=Rakentamisaika
dashboard.build_commit=Koontisitoutus
dashboard.build_commit=Rakentamis committi
dashboard.statistic=Statistiikka
dashboard.operations=Toiminnot
dashboard.system_status=Järjestelmänvalvonnan tila
@ -1209,8 +1206,7 @@ config.ssh.start_builtin_server=Käynnistä sisäänrakennettu palvelin
config.ssh.listen_host=Kuuntele porttia
config.ssh.listen_port=Kuuntele porttia
config.ssh.server_ciphers=Palvelimen cipherit
config.ssh.server_macs=Serverin MAC-osoite
config.ssh.server_algorithms=Server algorithms
config.ssh.server_macs=Server MACs
config.repo_config=Repositoryn asetukset
config.repo.root_path=Juuripolku
@ -1222,7 +1218,7 @@ config.repo.preferred_licenses=Ensisijaiset lisenssit
config.repo.disable_http_git=Poista käytöstä HTTP Git
config.repo.enable_local_path_migration=Ota käyttöön paikallisen polun migraatio
config.repo.enable_raw_file_render_mode=Ota käyttöön raakatiedoston renderöinti tila
config.repo.commits_fetch_concurrency=Sitoutus noudon samanaikaisuus
config.repo.commits_fetch_concurrency=Committien noudon samanaikaisuus
config.repo.editor.line_wrap_extensions=Muokkaimen rivityksen laajennukset
config.repo.editor.previewable_file_modes=Muokkaimen tiedostomuodot joita voi esikatsella
config.repo.upload.enabled=Tiedoston liittäminen käytössä
@ -1235,8 +1231,8 @@ config.db_config=Tietokannan asetukset
config.db.type=Tyyppi
config.db.host=Isäntä
config.db.name=Nimi
config.db.schema=Skeema
config.db.schema_helper=(koskee vain "postgresia")
config.db.schema=Schema
config.db.schema_helper=(for "postgres" only)
config.db.user=Käyttäjä
config.db.ssl_mode=SSL-tila
config.db.ssl_mode_helper=(vain "postgres")
@ -1381,23 +1377,23 @@ notices.delete_success=Järjestelmän ilmoitukset on poistettu onnistuneesti.
[action]
create_repo=luotu repo <a href="%s">%s</a>
rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a>
commit_repo=työnnetty kehityshaara <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a>
compare_commits=Näytä vertailu näille %d sitoutuksille
commit_repo=pushattu kohteeseen <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a>
compare_commits=Näytä vertailu näille %d commiteille
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
create_issue=`loi esityksen <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`käsitteli esityksen <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`uudelleenavasi esityksen <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`kommentoi esitystä <a href="%s/issues/%s">%s#%[2]s</a>`
create_issue=`avasi ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`sulki ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`avasi uudelleen ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`kommentoi ongelmaa <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`luotu pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`sulki pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`avasi uudelleen pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
merge_pull_request=`yhdistetty vetopyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
merge_pull_request=`yhdistetty pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
create_branch=luotu uusi haara <a href="%[1]s/src/%[2]s">%[3]s</a> kohteeseen <a href="%[1]s">%[4]s</a>
delete_branch=poistettu haara <code>%[2]s</code> kohteesta <a href="%[1]s">%[3]s</a>
push_tag=työnnettiin tunniste <a href="%s/src/%s">%[2]s</a> kohteeseen <a href="%[1]s">%[3]s</a>
delete_tag=poistettiin tunniste <code>%[2]s</code> kohteesta <a href="%[1]s">%[3]s</a>
fork_repo=haarautettiin tietosäilö kohteeseen <a href="%s"> %s</a>
mirror_sync_push=synkronoitiin sitoutukset kohteeseen <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a> peilauksesta
push_tag=pushattu tagi <a href="%s/src/%s">%[2]s</a> kohteeseen <a href="%[1]s">%[3]s</a>
delete_tag=poistettu tagi <code>%[2]s</code> kohteesta <a href="%[1]s">%[3]s</a>
fork_repo=forkattu repo kohteeseen <a href="%s"> %s</a>
mirror_sync_push=synkattu commitit kohteeseen <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a> peilistä
mirror_sync_create=synkattu uusi viite <a href="%s/src/%s">%[2]s</a> kohteeseen <a href="%[1]s">%[3]s</a> peilistä
mirror_sync_delete=synkattu ja poistettu viite <code>%[2]s</code> paikassa <a href="%[1]s">%[3]s</a> peilistä

View File

@ -88,7 +88,6 @@ log_root_path=Chemin des fichiers log
log_root_path_helper=Répertoire d'écriture des fichiers de log.
enable_console_mode=Activer le mode Console
enable_console_mode_popup=En plus du mode fichier, également imprimer des journaux à la console.
default_branch=Default Branch
optional_title=Paramètres facultatifs
email_title=Paramètres du service de messagerie
@ -317,7 +316,6 @@ delete_email=Supprimer
email_deletion=Suppression de l'adresse e-mail
email_deletion_desc=Supprimer cette adresse e-mail supprimera les informations associées à votre compte. Voulez-vous continuer ?
email_deletion_success=L'adresse e-mail a été supprimée avec succès !
email_deletion_primary=Cannot delete primary email address.
add_new_email=Ajouter une nouvelle adresse e-mail
add_email=Ajouter un e-mail
add_email_confirmation_sent=Une nouvelle confirmation d'adresse e-mail a été envoyé à '%s', veuillez vérifier votre boîte de réception dans un délai de %d heures pour terminer le processus de confirmation.
@ -372,7 +370,6 @@ two_factor_disable_success=L'authentification à deux facteurs a été désactiv
manage_access_token=Gérer les jetons d'accès personnels
generate_new_token=Générer le nouveau jeton
tokens_desc=Jetons, que vous avez généré, qui peuvent être utilisés pour accéder à l'API Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Chaque Jeton donnera un accès complet à votre compte.
token_name=Nom du jeton
generate_token=Générer le jeton
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Hôte en écoute
config.ssh.listen_port=Port d'écoute
config.ssh.server_ciphers=Suites de chiffrement
config.ssh.server_macs=Adresses MAC du serveur
config.ssh.server_algorithms=Server algorithms
config.repo_config=Configuration du dépôt
config.repo.root_path=Emplacement racine

View File

@ -88,7 +88,6 @@ log_root_path=Ruta do rexistro
log_root_path_helper=Directorio onde almacenar os rexistros.
enable_console_mode=Habilitar Modo Consola
enable_console_mode_popup=Ademáis do modo de ficheiro, tamén imprime os rexistros para a consola.
default_branch=Default Branch
optional_title=Configuración opcional
email_title=Configuración do servizo de correo
@ -318,7 +317,6 @@ delete_email=Eliminar
email_deletion=Eliminar correo electrónico
email_deletion_desc=Ao eliminar este enderezo de correo electrónico eliminarase toda a información asociada a esta. Desexas continuar?
email_deletion_success=O correo electrónico foi eliminado correctamente!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Engadir novo enderezo de correo electrónico
add_email=Engadir correo electrónico
add_email_confirmation_sent=Un novo correo de confirmación foi enviado a '%s'. Por favor, comproba a túa bandexa de entrada nas próximas %d horas para completar o proceso.
@ -373,7 +371,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=Xestionar os tokens de acceso persoais
generate_new_token=Xerar novo token
tokens_desc=Tokens usados para acceder ao API de Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Dende agora, todos os tokens terán acceso completo á túa conta.
token_name=Nome do token
generate_token=Xerar token
@ -1211,7 +1208,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository configuration
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Naplófájl elérési útja
log_root_path_helper=Naplófájlok könyvtára.
enable_console_mode=Konzol-üzemmód engedélyezése
enable_console_mode_popup=Naplófájl írása mellett a naplóbejegyzések nyomtatása a konzolra.
default_branch=Default Branch
optional_title=További beállítások
email_title=E-mail szolgáltatás beállításai
@ -317,7 +316,6 @@ delete_email=Törlés
email_deletion=E-mail cím törlése
email_deletion_desc=Az e-mail cím törlése kapcsolódó adatokat is eltávolít a fiókjából. Biztosan folytatja?
email_deletion_success=Az e-mail címet töröltük!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Új email cím felvétele
add_email=Email felvétele
add_email_confirmation_sent=Egy új megerősítő e-mailt küldtünk a(z) '%s' címre. Kérlek ellenőrizd a beérkező üzeneteidet %d órán belül, hogy befejezd a megerősítési folyamatot.
@ -372,7 +370,6 @@ two_factor_disable_success=Kétlépcsős hitelesítés sikeresen letiltva a fió
manage_access_token=Személyes hozzáférési jegyek kezelése
generate_new_token=Új jegy generálása
tokens_desc=A generált jegyekkel hozzáférhetsz a Gogs API-hoz.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Minden jegy teljes hozzáférést ad a fiókodhoz.
token_name=Jegy neve
generate_token=Jegy generálása
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Hallgatási cím
config.ssh.listen_port=Hallgatási port
config.ssh.server_ciphers=Kiszolgáló titkosítás módszerei
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Tároló konfiguráció
config.repo.root_path=Gyökér elérési útvonal

View File

@ -44,21 +44,21 @@ issues=Masalah
cancel=Batal
[status]
page_not_found=Halaman tidak ditemukan
internal_server_error=Kesalahan Server Internal
page_not_found=Page Not Found
internal_server_error=Internal Server Error
[install]
install=Instalasi
title=Langkah-langkah untuk Menjalankan Pertama Kali
docker_helper=Jika Anda menjalankan Gogs dalam Docker, silakan baca <a target="_blank" href="%s"> Petunjuk</a> dengan hati-hati sebelum Anda mengubah sesuatu di Halaman ini!
requite_db_desc=Gogs memerlukan MySQL, PostgreSQL, SQLite3 atau TiDB.
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Pengaturan Basisdata
db_type=Tipe Basisdata
host=Host
user=Pengguna
password=Sandi
db_name=Nama Basisdata
db_schema=Skema
db_schema=Schema
db_helper=Harap menggunakan INNODB engine dengan charset utf8_general_ci untuk MySQL.
ssl_mode=Mode SSL
path=Path
@ -88,7 +88,6 @@ log_root_path=Path log
log_root_path_helper=Direktori untuk menulis berkas log.
enable_console_mode=Mengaktifkan Mode Konsol
enable_console_mode_popup=Selain mode file, juga mencetak log ke konsol.
default_branch=Default Branch
optional_title=Pengaturan opsional
email_title=Pengaturan layanan email
@ -127,7 +126,7 @@ run_user_not_match=Pengguna yang sedang menjalankan bukanlah pengguna saat ini:
smtp_host_missing_port=Alamat Host SMTP hilang di alamat.
invalid_smtp_from=SMTP Dari lapangan tidak sesuai: %v
save_config_failed=Gagal untuk menyimpan konfigurasi: %v
init_failed=Gagal melakukan inisialiasi aplikasi: %v
init_failed=Failed to initialize application: %v
invalid_admin_setting=Pengaturan akun admin tidak valid: %v
install_success=Selamat datang! Kami senang bahwa Anda memilih Gogs, bersenang-senang dan berhati-hatilah.
invalid_log_root_path=Path akar log tidak valid: %v
@ -265,7 +264,7 @@ following=Mengikuti
follow=Ikuti
unfollow=Berhenti mengikuti
form.name_not_allowed=Nama pengguna atau pola %q tidak diizinkan.
form.name_not_allowed=User name or pattern %q is not allowed.
[settings]
profile=Profil
@ -317,7 +316,6 @@ delete_email=Hapus
email_deletion=Penghapusan email
email_deletion_desc=Menghapus alamat email ini akan menghapus informasi yang berhubungan dengan akun Anda. Lanjutkan?
email_deletion_success=Email telah berhasil diperbarui!
email_deletion_primary=Tidak bisa menghapus email utama
add_new_email=Menambah alamat email baru
add_email=Tambahkan email
add_email_confirmation_sent=Email konfirmasi baru telah dikirim ke '%s', silakan cek inboxmu dalam waktu %d jam untuk menyelesaikan proses konfirmasi.
@ -372,7 +370,6 @@ two_factor_disable_success=Autentikasi dua faktor telah berhasil dilakukan!
manage_access_token=Kelola Akses Token pribadi
generate_new_token=Buat Token Baru
tokens_desc=Token yang Anda buat dapat digunakan untuk mengakses API-nya Gogs.
access_token_tips=Personal access token mungkin digunakan sebagai username atau password. Sangatn direkomendasikan untuk menggunakan "x-access-token" sebagai username atau personal access token sebagai password untuk aplikasi git.
new_token_desc=Setiap token akan memiliki akses penuh ke akunmu.
token_name=Nama Token
generate_token=Buat Token
@ -381,7 +378,7 @@ delete_token=Hapus
access_token_deletion=Penghapusan Akses Token Pribadi
access_token_deletion_desc=Hapus token akses pribadi ini akan menghapus semua akses aplikasi yang terkait. Apakah Anda ingin melanjutkan?
delete_token_success=Token akses pribadi telah berhasil dihapus! Jangan lupa untuk mengupdate aplikasi anda juga.
token_name_exists=Token dengan nama yang sama telah digunakan.
token_name_exists=Token with same name already exists.
orgs.none=Anda bukan anggota organisasi manapun.
orgs.leave_title=Meninggalkan organisasi
@ -403,7 +400,7 @@ owner=Pemilik
repo_name=Nama Repositori
repo_name_helper=Nama repositori yang baik biasanya terdiri dari kata kunci yang pendek, mudah diingat dan unik.
visibility=Visibilitas
unlisted=Tidak terdaftar
unlisted=Unlisted
visiblity_helper=Repositori ini <span class="ui red text">Pribadi</span>
unlisted_helper=This repository is <span class="ui red text">Unlisted</span>
visiblity_helper_forced=Situs admin telah memaksa semua repositori baru menjadi <span class="ui red text">Pribadi</span>
@ -435,7 +432,7 @@ repo_description_helper=Deskripsi repositori maksimal 512 karakter.
repo_description_length=Karakter tersedia
form.reach_limit_of_creation=Pemiliknya telah mencapai batas pembuatan maksimum %d repositori.
form.name_not_allowed=Nama atau pola repositori %q tidak diizinkan.
form.name_not_allowed=Repository name or pattern %q is not allowed.
need_auth=Butuh Otorisasi
migrate_type=Jenis migrasi
@ -797,7 +794,7 @@ settings.search_user_placeholder=Cari pengguna...
settings.org_not_allowed_to_be_collaborator=Organisasi tidak diperbolehkan untuk ditambahkan sebagai kolaborator.
settings.hooks_desc=Webhooks seperti pemicu peristiwa HTTP POST dasar. Kapan pun terjadi sesuatu di Gog, kami akan menangani pemberitahuan tersebut ke host target yang Anda tentukan. Pelajari lebih lanjut di <a target="_blank" href=" %s "> Panduan Webhooks </a> ini.
settings.webhooks.add_new=Add a new webhook:
settings.webhooks.choose_a_type=Pilih jenis...
settings.webhooks.choose_a_type=Choose a type...
settings.add_webhook=Tambahkan Webhook
settings.webhook_deletion=Hapus Webhook
settings.webhook_deletion_desc=Hapus halaman web ini akan menghapus informasinya dan semua riwayat pengiriman. Apakah Anda ingin melanjutkan?
@ -1013,19 +1010,19 @@ first_page=Pertama
last_page=Terakhir
total=Total: %d
dashboard.build_info=Informasi build
dashboard.app_ver=Versi aplikasi
dashboard.git_version=Versi Git
dashboard.go_version=Versi Go (Golang)
dashboard.build_time=Durasi
dashboard.build_commit=Setuju Membangun
dashboard.build_info=Build Information
dashboard.app_ver=Application version
dashboard.git_version=Git version
dashboard.go_version=Go version
dashboard.build_time=Build time
dashboard.build_commit=Build commit
dashboard.statistic=Statistik
dashboard.operations=Operasi
dashboard.system_status=Status Monitor Sistem
dashboard.statistic_info=GogsDatabase memiliki <b>%d</b> pengguna, <b>%d</b> organisasi, <b>%d</b> kunci publik, <b>%d</b> repositori, <b>%d</b> jamtangan, <b>%d</b> bintang, <b>%d</b>actions, <b>%d</b> akses, <b>%d</b> isu, <b>%d</b> komentar, <b>%d</b> akun sosial, <b>%d</b> berikut, <b>%d<b> mirror, <b>%d</b> rilis, <b>%d</b> sumber masuk, <b>%d</b> webhooks, <b>%d</b> tonggak,<b>%d</b> label, <b>%d</b> tugas hook, <b>%d</b> tim, <b>%d</b> memperbarui tugas, <b>%d</b> lampiran.
dashboard.operation_name=Nama operasi
dashboard.operation_switch=Beralih
dashboard.select_operation_to_run=Harap menentukan operasi yang dijalankan
dashboard.select_operation_to_run=Please select operation to run
dashboard.operation_run=Menjalankan
dashboard.clean_unbind_oauth=Bersihkan OAuth yang tidak terikat
dashboard.clean_unbind_oauth_success=Semua unbind OAuthes telah berhasil dihapus.
@ -1149,7 +1146,7 @@ auths.user_attribute_listed_in_group=Atribut Pengguna Terdaftar di Grup
auths.attributes_in_bind=Ambil atribut dalam konteks Bind DN
auths.filter=Pengguna saringan
auths.admin_filter=Filter Admin
auths.ms_ad_sa=Otentifikasi sistem
auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Autentikasi tipe SMTP
auths.smtphost=Host SMTP
auths.smtpport=Port SMTP
@ -1171,52 +1168,51 @@ auths.delete_auth_desc=Autentikasi ini akan dihapus, apakah Anda ingin melanjutk
auths.still_in_used=Autentikasi ini masih digunakan oleh pengguna lain, silakan hapus atau ubah pengguna tersebut ke tipe masuk lainnya.
auths.deletion_success=Autentikasi berhasil dihapus!
auths.login_source_exist=Sumber masuk %s sudah tersedia.
auths.github_api_endpoint=Titik akhir API
auths.github_api_endpoint=API Endpoint
config.not_set=(tidak diterapkan)
config.server_config=Konfigurasi Server
config.brand_name=Nama Merek/Logo/Perusahaan
config.brand_name=Brand name
config.run_user=Menjalankan penggunaa
config.run_mode=Run mode
config.server.external_url=URL eksternal
config.server.external_url=External URL
config.server.domain=Domain
config.server.protocol=Protokol
config.server.http_addr=Alamat HTTP
config.server.http_port=Port HTTP
config.server.cert_file=Berkas Sertifikat
config.server.key_file=Berkas baru
config.server.tls_min_version=Minimum versi TLS
config.server.unix_socket_permission=Aturan unix socket
config.server.local_root_url=Lokal root url
config.server.offline_mode=mode luring
config.server.disable_router_log=Menonaktifkan router log
config.server.enable_gzip=aktifkan gzip
config.server.app_data_path=target data aplikasi
config.server.load_assets_from_disk=memanggil asset dari disk
config.server.protocol=Protocol
config.server.http_addr=HTTP address
config.server.http_port=HTTP port
config.server.cert_file=Certificate file
config.server.key_file=Key file
config.server.tls_min_version=Minimum TLS version
config.server.unix_socket_permission=Unix socket permission
config.server.local_root_url=Local root URL
config.server.offline_mode=Offline mode
config.server.disable_router_log=Disable router log
config.server.enable_gzip=Enable Gzip
config.server.app_data_path=Application data path
config.server.load_assets_from_disk=Load assets from disk
config.server.landing_url=Landing URL
config.ssh_config=Konfigurasi SSH
config.ssh.enabled=Diaktifkan
config.ssh.enabled=Enabled
config.ssh.domain=Exposed domain
config.ssh.port=Exposed port
config.ssh.root_path=Path akar
config.ssh.keygen_path=Path keygen
config.ssh.root_path=Root path
config.ssh.keygen_path=Keygen path
config.ssh.key_test_path=Key test path
config.ssh.minimum_key_size_check=Minimum key size check
config.ssh.minimum_key_sizes=Ukuran kunci minimum
config.ssh.rewrite_authorized_keys_at_start=Tulis ulang "authorized_keys" saat memulai
config.ssh.minimum_key_sizes=Minimum key sizes
config.ssh.rewrite_authorized_keys_at_start=Rewrite "authorized_keys" at start
config.ssh.start_builtin_server=Start builtin server
config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Cipher server
config.ssh.server_macs=MAC server
config.ssh.server_algorithms=Algoritma server
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.repo_config=Konfigurasi Repositori
config.repo.root_path=Path akar
config.repo.script_type=Jenis skrip
config.repo.ansi_chatset=Set karakter ANSI
config.repo.force_private=Paksa pribadi
config.repo.root_path=Root path
config.repo.script_type=Script type
config.repo.ansi_chatset=ANSI charset
config.repo.force_private=Force private
config.repo.max_creation_limit=Max creation limit
config.repo.preferred_licenses=Preferred licenses
config.repo.disable_http_git=Disable HTTP Git
@ -1225,80 +1221,80 @@ config.repo.enable_raw_file_render_mode=Enable raw file render mode
config.repo.commits_fetch_concurrency=Commits fetch concurrency
config.repo.editor.line_wrap_extensions=Editor line wrap extensions
config.repo.editor.previewable_file_modes=Editor previewable file modes
config.repo.upload.enabled=Pengunggahan diaktifkan
config.repo.upload.temp_path=Path unggah sementara
config.repo.upload.allowed_types=Tipe unggah yang diizinkan
config.repo.upload.file_max_size=Batas ukuran unggah berkas
config.repo.upload.max_files=Batas unggah berkas
config.repo.upload.enabled=Upload enabled
config.repo.upload.temp_path=Upload temporary path
config.repo.upload.allowed_types=Upload allowed types
config.repo.upload.file_max_size=Upload file size limit
config.repo.upload.max_files=Upload files limit
config.db_config=Konfigurasi Basis Data
config.db.type=Tipe
config.db.type=Type
config.db.host=Host
config.db.name=Nama
config.db.schema=Skema
config.db.schema_helper=(hanya untuk "postgres")
config.db.user=Pengguna
config.db.ssl_mode=Modus SSL
config.db.ssl_mode_helper=(hanya untuk "postgres")
config.db.name=Name
config.db.schema=Schema
config.db.schema_helper=(for "postgres" only)
config.db.user=User
config.db.ssl_mode=SSL mode
config.db.ssl_mode_helper=(for "postgres" only)
config.db.path=Path
config.db.path_helper=(hanya untuk "sqlite3")
config.db.max_open_conns=Maksimum koneksi yang terbuka
config.db.max_idle_conns=Maksimum koneksi menganggur
config.db.path_helper=(for "sqlite3"only)
config.db.max_open_conns=Maximum open connections
config.db.max_idle_conns=Maximum idle connections
config.security_config=Konfigurasi keamanan
config.security.login_remember_days=Berapa hari mengingat log masuk
config.security.cookie_remember_name=Ingat cookie
config.security.cookie_username=Cookie pengguna
config.security.cookie_secure=Aktifkan cookie aman
config.security_config=Security configuration
config.security.login_remember_days=Login remember days
config.security.cookie_remember_name=Remember cookie
config.security.cookie_username=Username cookie
config.security.cookie_secure=Enable secure cookie
config.security.reverse_proxy_auth_user=Reverse proxy authentication header
config.security.enable_login_status_cookie=Enable login status cookie
config.security.login_status_cookie_name=Login status cookie
config.security.local_network_allowlist=Local network allowlist
config.email_config=Konfigurasi surel
config.email_config=Email configuration
config.email.enabled=Enabled
config.email.subject_prefix=Subject prefix
config.email.host=Host
config.email.from=Dari
config.email.user=Pengguna
config.email.from=From
config.email.user=User
config.email.disable_helo=Disable HELO
config.email.helo_hostname=HELO hostname
config.email.skip_verify=Lewati verifikasi sertifikat
config.email.use_certificate=Pakai sertifikat ubahan
config.email.cert_file=Berkas sertifikat
config.email.key_file=Berkas kunci
config.email.use_plain_text=Gunakan teks polos
config.email.add_plain_text_alt=Tambahkan alternatif teks polos
config.email.send_test_mail=Kirim surel uji
config.email.test_mail_failed=Gagal mengirim surel uji ke '%s': %v
config.email.test_mail_sent=Surel uji telah dikirim ke '%s'.
config.email.skip_verify=Skip certificate verify
config.email.use_certificate=Use custom certificate
config.email.cert_file=Certificate file
config.email.key_file=Key file
config.email.use_plain_text=Use plain text
config.email.add_plain_text_alt=Add plain text alternative
config.email.send_test_mail=Send test email
config.email.test_mail_failed=Failed to send test email to '%s': %v
config.email.test_mail_sent=Test email has been sent to '%s'.
config.auth_config=Konfigurasi otentikasi
config.auth_config=Authentication configuration
config.auth.activate_code_lives=Activate code lives
config.auth.reset_password_code_lives=Reset password code lives
config.auth.require_email_confirm=Perlu konfirmasi surel
config.auth.require_email_confirm=Require email confirmation
config.auth.require_sign_in_view=Require sign in view
config.auth.disable_registration=Nonaktifkan pendaftaran
config.auth.enable_registration_captcha=Aktifkan captcha pendaftaran
config.auth.enable_reverse_proxy_authentication=Aktifkan otentikasi proksi balik
config.auth.enable_reverse_proxy_auto_registration=Aktifkan pendaftaran otomatis proksi balik
config.auth.disable_registration=Disable registration
config.auth.enable_registration_captcha=Enable registration captcha
config.auth.enable_reverse_proxy_authentication=Enable reverse proxy authentication
config.auth.enable_reverse_proxy_auto_registration=Enable reverse proxy auto registration
config.auth.reverse_proxy_authentication_header=Reverse proxy authentication header
config.user_config=Konfigurasi pengguna
config.user.enable_email_notify=Aktifkan notifikasi surel
config.user_config=User configuration
config.user.enable_email_notify=Enable email notification
config.session_config=Konfigurasi Sesi
config.session.provider=Penyedia
config.session.provider_config=Konfigurasi penyedia
config.session.provider=Provider
config.session.provider_config=Provider config
config.session.cookie_name=Cookie
config.session.https_only=Hanya HTTPS
config.session.gc_interval=Interval GC
config.session.https_only=HTTPS only
config.session.gc_interval=GC interval
config.session.max_life_time=Max life time
config.session.csrf_cookie_name=CSRF cookie
config.cache_config=Konfigurasi Cache
config.cache.adapter=Adaptor
config.cache.interval=Interval GC
config.cache.adapter=Adapter
config.cache.interval=GC interval
config.cache.host=Host
config.http_config=Konfigurasi HTTP
@ -1308,27 +1304,27 @@ config.attachment_config=Attachment configuration
config.attachment.enabled=Enabled
config.attachment.path=Path
config.attachment.allowed_types=Allowed types
config.attachment.max_size=Batas ukuran
config.attachment.max_files=Batas berkas
config.attachment.max_size=Size limit
config.attachment.max_files=Files limit
config.release_config=Release configuration
config.release.attachment.enabled=Lampiran diaktifkan
config.release.attachment.allowed_types=Jens lampiran yang diizinkan
config.release.attachment.max_size=Batas ukuran lampiran
config.release.attachment.max_files=Batas berkas lampiran
config.release.attachment.enabled=Attachment enabled
config.release.attachment.allowed_types=Attachment allowed types
config.release.attachment.max_size=Attachment size limit
config.release.attachment.max_files=Attachment files limit
config.picture_config=Konfigurasi Gambar
config.picture.avatar_upload_path=Path unggah avatar pengguna
config.picture.repo_avatar_upload_path=Path unggah avatar repositori
config.picture.gravatar_source=Sumber gravatar
config.picture.disable_gravatar=Nonaktifkan Gravatar
config.picture.avatar_upload_path=User avatar upload path
config.picture.repo_avatar_upload_path=Repository avatar upload path
config.picture.gravatar_source=Gravatar source
config.picture.disable_gravatar=Disable Gravatar
config.picture.enable_federated_avatar=Enable federated avatars
config.mirror_config=Konfigurasi cermin
config.mirror.default_interval=Interval baku
config.mirror_config=Mirror configuration
config.mirror.default_interval=Default interval
config.webhook_config=Webhook Konfigurasi
config.webhook.types=Tipe
config.webhook.types=Types
config.webhook.deliver_timeout=Deliver timeout
config.webhook.skip_tls_verify=Skip TLS verify
@ -1340,16 +1336,16 @@ config.git.max_diff_files=Diff files limit (for a single diff)
config.git.gc_args=GC arguments
config.git.migrate_timeout=Migration timeout
config.git.mirror_timeout=Mirror fetch timeout
config.git.clone_timeout=Tenggat waktu klon
config.git.pull_timeout=Tenggat waktu pull
config.git.gc_timeout=Tenggat waktu GC
config.git.clone_timeout=Clone timeout
config.git.pull_timeout=Pull timeout
config.git.gc_timeout=GC timeout
config.lfs_config=Konfigurasi LFS
config.lfs.storage=Penyimpanan
config.lfs.objects_path=Path obyek
config.lfs_config=LFS configuration
config.lfs.storage=Storage
config.lfs.objects_path=Objects path
config.log_config=Konfigurasi log
config.log_file_root_path=Path akar berkas log
config.log_config=Log configuration
config.log_file_root_path=Log file root path
config.log_mode=Mode
config.log_options=Pilihan
@ -1421,7 +1417,7 @@ months=%d bulan %s
years=%d tahun %s
raw_seconds=detik
raw_minutes=menit
raw_hours=jam
raw_hours=hours
[dropzone]
default_message=Jatuhkan berkas disini atau klik untuk mengunggah.

View File

@ -88,7 +88,6 @@ log_root_path=Percorso dei log
log_root_path_helper=Directory in cui scrivere i file di log.
enable_console_mode=Abilita modalità Terminale
enable_console_mode_popup=In aggiunta alla modalità file, invia i log anche al terminale.
default_branch=Default Branch
optional_title=Impostazioni Facoltative
email_title=Impostazioni E-mail
@ -317,7 +316,6 @@ delete_email=Elimina
email_deletion=Eliminazione e-mail
email_deletion_desc=La procedura di rimozione indirizzo email eliminerà tutte le informazioni correlate dal tuo account. Si desidera continuare?
email_deletion_success=Indirizzo e-mail eliminato con successo!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Aggiungi un nuovo indirizzo E-mail
add_email=Aggiungi E-mail
add_email_confirmation_sent=Una nuova email di conferma è stata inviata a '%s', per favore controlla la tua posta in arrivo nelle prossime %d ore per completare il processo di registrazione.
@ -372,7 +370,6 @@ two_factor_disable_success=L'autenticazione a due fattori è stata disabilitata!
manage_access_token=Gestisci i Token di Accesso Personale
generate_new_token=Genera Nuovo Token
tokens_desc=I Token che hai generato e che possono essere utilizzati per accedere alle API Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Da questo momento, ogni token avrà pieno accesso al tuo account.
token_name=Nome Token
generate_token=Genera Token
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Configurazione Repository
config.repo.root_path=Root path

View File

@ -51,7 +51,7 @@ internal_server_error=サーバ内部エラー
install=インストール
title=インストールをする前に必要な準備をしましょう
docker_helper=DockerでGogsを稼動する場合は、このページに変更を加える前に、 <a target="_blank" href="%s">ガイドライン</a>をよく読んでください!
requite_db_desc=Gogs は、MySQL、PostgreSQL、SQLite3 または TiDB が必要です。
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=データベース設定
db_type=データベースの種類
host=ホスト
@ -88,7 +88,6 @@ log_root_path=ログのパス
log_root_path_helper=ログファイルを書き込むディレクトリ。
enable_console_mode=コンソールモードの有効化
enable_console_mode_popup=ファイルモードに加えて、コンソールにもログを表示します。
default_branch=Default Branch
optional_title=オプション設定
email_title=メールサービス設定
@ -317,7 +316,6 @@ delete_email=削除
email_deletion=電子メールの削除
email_deletion_desc=このメールアドレスを削除すると、あなたのアカウントの関連情報も削除されます。続行しますか?
email_deletion_success=電子メールが正常に削除されました。
email_deletion_primary=Cannot delete primary email address.
add_new_email=新しいメールアドレスを追加
add_email=メールアドレスの追加
add_email_confirmation_sent='%s' に新しい確認メールを送信しました。%d 時間以内に受信トレイを確認し、確認プロセスを完了してください。
@ -372,7 +370,6 @@ two_factor_disable_success=2段階認証があなたのアカウントで無効
manage_access_token=パーソナルアクセス トークンを管理
generate_new_token=新しいトークンを生成
tokens_desc=生成したトークンを利用して Gogs の API にアクセスすることができます。
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=今のところ、全てのトークンはあなたのアカウントにフルアクセスできます。
token_name=トークン名
generate_token=トークンを生成
@ -918,7 +915,7 @@ release.deletion=リリースの削除
release.deletion_desc=このリリースを削除すると、対応するGitのタグも削除されます。よろしいですか
release.deletion_success=リリースが正常に削除されました。
release.tag_name_already_exist=このタグ名には既にリリースが存在します。
release.tag_name_invalid=タグ名が不正です。
release.tag_name_invalid=使用できないタグ名です。
release.downloads=ダウンロード
[org]
@ -1178,7 +1175,7 @@ config.server_config=サーバーの構成
config.brand_name=ブランド名
config.run_user=実行ユーザー
config.run_mode=実行モード
config.server.external_url=外部 URL
config.server.external_url=外部 URL
config.server.domain=ドメイン
config.server.protocol=プロトコル
config.server.http_addr=HTTPアドレス
@ -1196,7 +1193,7 @@ config.server.load_assets_from_disk=Load assets from disk
config.server.landing_url=Landing URL
config.ssh_config=SSH設定
config.ssh.enabled=有効
config.ssh.enabled=Enabled
config.ssh.domain=Exposed domain
config.ssh.port=Exposed port
config.ssh.root_path=Root path
@ -1210,10 +1207,9 @@ config.ssh.listen_host=待受ホスト
config.ssh.listen_port=待受ポート
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=リポジトリの設定
config.repo.root_path=ルートパス
config.repo.root_path=Root path
config.repo.script_type=Script type
config.repo.ansi_chatset=ANSI 文字コード
config.repo.force_private=非公開にする

View File

@ -51,14 +51,14 @@ internal_server_error=내부 서버 오류
install=설치
title=첫 실행을 위한 설치단계
docker_helper=Gogs를 Docker에서 운영하고 있다면 <a target="_blank" href="%s">안내</a>를 읽고 변경해 주세요!
requite_db_desc=Gogs는 MySQL, PostgreSQL, SQLite3, TiDB (MySQL protocol)을 필요로 합니다.
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=데이터베이스 설정
db_type=데이터베이스 유형
host=호스트
user=사용자
password=비밀번호
db_name=데이터베이스 이름
db_schema=스키마
db_schema=Schema
db_helper=MySQL에서는 utf8_general_ci 캐릭터셋으로 INNODB엔진을 이용해 주세요
ssl_mode=SSL 모드
path=경로
@ -88,7 +88,6 @@ log_root_path=로그 경로
log_root_path_helper=로그 파일을 쓸 디렉터리.
enable_console_mode=콘솔 모드 활성화
enable_console_mode_popup=파일 모드 외에 콘솔에 로그를 인쇄하세요.
default_branch=기본 브랜치
optional_title=추가설정
email_title=이메일 서비스 설정
@ -317,7 +316,6 @@ delete_email=삭제
email_deletion=이메일 삭제
email_deletion_desc=이메일 주소를 삭제하면 당신의 계정과 연관된 정보도 함께 삭제됩니다. 계속 하시겠습니까?
email_deletion_success=이메일 주소를 성공적으로 삭제되하였습니다!
email_deletion_primary=Cannot delete primary email address.
add_new_email=새 이메일 주소 추가
add_email=이메일 추가
add_email_confirmation_sent=새로운 이메일 주소 인증이 '%s'로 발송되었습니다. %d시간 안에 확인 절차를 완료하셔야 합니다.
@ -372,7 +370,6 @@ two_factor_disable_success=2단계 인증이 성공적으로 비활성화되었
manage_access_token=개인 액세스 토큰 관리
generate_new_token=새 토큰을 생성
tokens_desc=Gogs Api에 액세스 하는 데 사용할 수 있는 토큰입니다.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=각 토큰은 당신의 모든 권한을 행사할 수 있습니다.
token_name=토큰 이름
generate_token=토큰 생성
@ -403,9 +400,9 @@ owner=소유자
repo_name=저장소 이름
repo_name_helper=좋은 저장소 이름은 짧고 기억하기 좋은 유니크한 키워드로 이루어 집니다.
visibility=가시성
unlisted=비공개
unlisted=Unlisted
visiblity_helper=이 저장소는 <span class="ui red text">비공개</span> 저장소입니다
unlisted_helper=이 저장소는 <span class="ui red text">비공개</span> 저장소입니다.
unlisted_helper=This repository is <span class="ui red text">Unlisted</span>
visiblity_helper_forced=사이트 관리자가 모든 저장소를 <span class="ui red text">비공개</span>로 변경하였습니다.
visiblity_fork_helper=(이 값의 변경은 모든 포크에 영향을 줍니다)
clone_helper=클론하는데에 도움이 필요하면 <a target="_blank" href="%s">Help</a>에 방문하세요.
@ -1211,7 +1208,6 @@ config.ssh.listen_host=수신 대기 호스트
config.ssh.listen_port=수신 대기 포트
config.ssh.server_ciphers=서버 암호화
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=저장소 설정
config.repo.root_path=최상위 경로
@ -1236,8 +1232,8 @@ config.db_config=데이터베이스 설정
config.db.type=유형
config.db.host=호스트
config.db.name=이름
config.db.schema=스키마
config.db.schema_helper=("postgres" 전용)
config.db.schema=Schema
config.db.schema_helper=(for "postgres" only)
config.db.user=사용자
config.db.ssl_mode=SSL 모드
config.db.ssl_mode_helper=("postgres" 전용)
@ -1277,16 +1273,16 @@ config.email.test_mail_sent='%s'로 테스트 이메일을 보냈습니다.
config.auth_config=Authentication configuration
config.auth.activate_code_lives=Activate code lives
config.auth.reset_password_code_lives=Reset password code lives
config.auth.require_email_confirm=이메일 인증 필요
config.auth.require_email_confirm=Require email confirmation
config.auth.require_sign_in_view=Require sign in view
config.auth.disable_registration=등록 비활성화
config.auth.enable_registration_captcha=등록시 CAPTCHA 사용
config.auth.disable_registration=Disable registration
config.auth.enable_registration_captcha=Enable registration captcha
config.auth.enable_reverse_proxy_authentication=Enable reverse proxy authentication
config.auth.enable_reverse_proxy_auto_registration=Enable reverse proxy auto registration
config.auth.reverse_proxy_authentication_header=Reverse proxy authentication header
config.user_config=User configuration
config.user.enable_email_notify=이메일 알림 활성화
config.user.enable_email_notify=Enable email notification
config.session_config=세션 설정
config.session.provider=공급자
@ -1305,7 +1301,7 @@ config.cache.host=호스트
config.http_config=HTTP 설정
config.http.access_control_allow_origin=Access control allow origin
config.attachment_config=첨부 파일 설정
config.attachment_config=Attachment configuration
config.attachment.enabled=활성화됨
config.attachment.path=경로
config.attachment.allowed_types=허용 유형
@ -1322,10 +1318,10 @@ config.picture_config=이미지 설정
config.picture.avatar_upload_path=사용자 아바타 업로드 경로
config.picture.repo_avatar_upload_path=Repository avatar upload path
config.picture.gravatar_source=Gravatar source
config.picture.disable_gravatar=Gravatar 비활성화
config.picture.disable_gravatar=Disable Gravatar
config.picture.enable_federated_avatar=Enable federated avatars
config.mirror_config=미러 설정
config.mirror_config=Mirror configuration
config.mirror.default_interval=기본 간격
config.webhook_config=웹훅 설정
@ -1345,8 +1341,8 @@ config.git.clone_timeout=클론 제한 시간
config.git.pull_timeout=풀 제한 시간
config.git.gc_timeout=GC 제한 시간
config.lfs_config=LFS 구성
config.lfs.storage=저장소
config.lfs_config=LFS configuration
config.lfs.storage=Storage
config.lfs.objects_path=Objects path
config.log_config=로그 설정

View File

@ -88,7 +88,6 @@ log_root_path=Žurnalizēšanas direktorija
log_root_path_helper=Direktorija, kurā tiks glabāti žurnāla faili.
enable_console_mode=Iespējot konsoles režīmu
enable_console_mode_popup=Papildus faila režīmam, papildus rakstīt žurnāla ierakstus konsolē.
default_branch=Default Branch
optional_title=Neobligātie iestatījumi
email_title=E-pasta pakalpojuma iestatījumi
@ -317,7 +316,6 @@ delete_email=Dzēst
email_deletion=E-pasta dzēšana
email_deletion_desc=Dzēšot šo e-pasta adresi, tiks dzēsta arī visa ar to saistītā informācija no Jūsu konta. Vai vēlaties turpināt?
email_deletion_success=E-pasta adrese ir veiksmīgi izdzēsta!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Pievienot jaunu e-pasta adresi
add_email=Pievienot e-pastu
add_email_confirmation_sent=Jauns apstiprinājuma e-pasts tika nosūtīts uz '%s', pārbaudiet savu e-pastu tuvāko %d stundu laikā, lai pabeigtu apstiprināšanas procesu.
@ -372,7 +370,6 @@ two_factor_disable_success=Divu faktoru autentificēšana ir atspējota!
manage_access_token=Pārvaldīt personīgos piekļuves talonus
generate_new_token=Ģenerēt jaunu talonu
tokens_desc=Taloni, kurus esat uzģenerējuši, kas var tikt izmantoti, lai piekļūtu Gogs API.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Pašlaik visiem taloniem ir pilna piekļuve Jūsu kontam.
token_name=Talona nosaukums
generate_token=Ģenerēt talonu
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repozitorija konfigurācija
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Log Path
log_root_path_helper=Directory to write log files to.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
default_branch=Default Branch
optional_title=Optional Settings
email_title=Email Service Settings
@ -317,7 +316,6 @@ delete_email=Устгах
email_deletion=Имэйл устгах
email_deletion_desc=Энэ имэйл хаягийг устгаснаар холбогдох мэдээллийг таны данснаас устгах болно. Та үргэлжлүүлэхийг хүсч байна уу?
email_deletion_success=Имэйлийг амжилттай устгалаа!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Шинэ имэйл хаяг нэмэх
add_email=Имэйл нэмэх
add_email_confirmation_sent=Шинэ баталгаажуулах имэйлийг '%s' хаяг руу илгээлээ. Баталгаажуулах процессыг дуусгахын тулд имэйл нээж дараагийн %d цагийн дотор баталгаажуулна уу.
@ -372,7 +370,6 @@ two_factor_disable_success=Хоёр давхар баталгаажуулалт
manage_access_token=Хувийн хандалтын токенуудыг удирдах
generate_new_token=Шинэ токен үүсгэх
tokens_desc=Таны үүсгэсэн токенуудыг Gogs API-д нэвтрэхэд ашиглаж болно.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Токен бүр таны дансанд бүрэн нэвтрэх боломжтой болно.
token_name=Токены нэр
generate_token=Токены үүсгэх
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Сонсох хост
config.ssh.listen_port=Сонсох порт
config.ssh.server_ciphers=Серверийн шифр
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Хадгалах сангийн тохиргоо
config.repo.root_path=Root буюу эх зам

View File

@ -45,13 +45,13 @@ cancel=Annuleren
[status]
page_not_found=Pagina niet gevonden
internal_server_error=Interne Server Fout
internal_server_error=Internal Server Error
[install]
install=Installatie
title=Installatiestappen voor de eerste keer opstarten
docker_helper=Als u gebruik maakt Gogs binnen Docker, lees dan de <a target="_blank" href="%s">richtlijnen</a> voordat u iets veranderen op deze pagina!
requite_db_desc=Gogs heeft MySQL, PostgreSQL, SQLite3 of TiDB (via het MySQL protocool) nodig.
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Database-instellingen
db_type=Database-type
host=Host
@ -88,7 +88,6 @@ log_root_path=Log-pad
log_root_path_helper=Directory waar logbestanden opgeslagen worden.
enable_console_mode=Schakel Console modus in
enable_console_mode_popup=Naast de bestand modus print het ook de logs naar de console.
default_branch=Standaard branch
optional_title=Optionele instellingen
email_title=E-mail service instellingen
@ -127,7 +126,7 @@ run_user_not_match=De uitvoerende gebruiker is niet de huidig gebruiker: %s -> %
smtp_host_missing_port=SMTP-Host mist een poort in het adres.
invalid_smtp_from=SMTP-van-veld is niet geldig: %v
save_config_failed=Kan de configuratie niet opslaan: %v
init_failed=Programma initialiseren mislukt: %v
init_failed=Failed to initialize application: %v
invalid_admin_setting=Uw admin-instellingen zijn niet geldig: %v
install_success=Welkom! Wij zijn veheugd dat u voor Gogs heeft gekozen, veel plezier en tot ziens
invalid_log_root_path=Ongeldig log-pad: %v
@ -183,7 +182,7 @@ login_two_factor_enter_recovery_code=Voer de two-factor herstelcode in
login_two_factor_recovery=Two-factor herstel
login_two_factor_recovery_code=Herstel code
login_two_factor_enter_passcode=Voer een two-factor wachtwoord in
login_two_factor_invalid_recovery_code=Herstelcode is al gebruikt of ongeldig.
login_two_factor_invalid_recovery_code=Recovery code already used or invalid.
[mail]
activate_account=Activeer uw account
@ -220,7 +219,7 @@ Content=Inhoud
require_error=kan niet leeg zijn.
alpha_dash_error=moet een valide alfanumeriek of dash(-_) karakter zijn.
alpha_dash_dot_error=moet een valide alfanumeriek, dash(-_) of (.) punt karakter zijn.
alpha_dash_dot_slash_error=` moet een geldige alfanumeriek, (lage) streepje (-_), punt of een schuin karakter zijn.`
alpha_dash_dot_slash_error=` must be alphanumeric, dash (-_), dot or slash characters.`
size_error=moet groter zijn dan %s
min_size_error=moet minimaal %s karakters bevatten.
max_size_error=mag maximaal %s karakters bevatten.
@ -237,7 +236,7 @@ org_name_been_taken=Organisatie naam is al in gebruik.
team_name_been_taken=Team naam is al in gebruik.
email_been_used=e-mailadres is al in gebruik.
username_password_incorrect=Gebruikersnaam of wachtwoord is niet correct.
auth_source_mismatch=De geselecteerde authenticatiebron is niet gekoppeld aan de gebruiker.
auth_source_mismatch=The authentication source selected is not associated with the user.
enterred_invalid_repo_name=U heeft een onjuiste repositorie naam ingevoerd.
enterred_invalid_owner_name=U heeft een onjuiste eigenaar ingevoerd.
enterred_invalid_password=U heeft een onjuiste wachtwoord ingevoerd.
@ -317,7 +316,6 @@ delete_email=Verwijder
email_deletion=E-mail Verwijderen
email_deletion_desc=Dit e-mailadres verwijdert, worden gerelateerde informatie van uw account te verwijderen. Wil je verdergaan?
email_deletion_success=E-mail is succesvol verwijderd!
email_deletion_primary=Kan het primaire e-mailadres niet verwijderen.
add_new_email=Nieuw e-mailadres toevoegen
add_email=E-mailadres toevoegen
add_email_confirmation_sent=Een nieuwe bevestiging e-mail werd verstuurd naar '%s', gelieve uw inbox in de komende %d uren te controleren om het bevestigingsproces te voltooien.
@ -343,7 +341,7 @@ no_activity=Geen recente activiteiten
key_state_desc=Deze sleutel werd gebruikt in de laatste 7 dagen
token_state_desc=Deze token is de laatste 7 dagen gebruikt
two_factor=Twee-factor authenticatie
two_factor=Two-factor Authentication
two_factor_status=Status:
two_factor_on=Aan
two_factor_off=Uit
@ -351,9 +349,9 @@ two_factor_enable=Inschakelen
two_factor_disable=Uitschakelen
two_factor_view_recovery_codes=View and save <a href="%s%s">your recovery codes</a> in a safe place. You can use them as passcode if you lose access to your authentication application.
two_factor_http=For HTTP/HTTPS operations, you are no longer able to use plain username and password. Please create and use <a href="%[1]s%[2]s">Personal Access Token</a> as your credential, e.g. <code>%[3]s</code>.
two_factor_enable_title=Tweestapsverificatie inschakelen
two_factor_enable_title=Enable Two-factor Authentication
two_factor_scan_qr=Please use your authentication application to scan the image:
two_factor_or_enter_secret=Of voer het geheim in:
two_factor_or_enter_secret=Or enter the secret:
two_factor_then_enter_passcode=Then enter passcode:
two_factor_verify=Verifiëren
two_factor_invalid_passcode=The passcode you entered is not valid, please try again!
@ -372,7 +370,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=Persoonlijke toegangstokens beheren
generate_new_token=Nieuwe Token genereren
tokens_desc=Tokens die u hebt gegenereerd om toegang tot de Gogs APIs te verkrijgen.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Zoals voor nu, moet elke token zal hebben volledige toegang tot uw account.
token_name=Symbolische naam
generate_token=Token genereren
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository configuration
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Ścieżka dla logów
log_root_path_helper=Katalog do zapisu logów.
enable_console_mode=Włącz tryb konsolowy
enable_console_mode_popup=Oprócz zapisywania do pliku wyświetlaj logi także w konsoli.
default_branch=Default Branch
optional_title=Ustawienia opcjonalne
email_title=Ustawienia serwera e-mail
@ -317,7 +316,6 @@ delete_email=Usuń
email_deletion=Usunięcie wiadomości e-mail
email_deletion_desc=Usunięcie tego adresu e-mail spowoduje usunięcie innych informacji związanych z Twoim kontem. Czy chcesz kontynuować?
email_deletion_success=E-mail został usunięty pomyślnie!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Dodaj nowy e-mail
add_email=Dodaj e-mail
add_email_confirmation_sent=Nowa wiadomość e-mail z potwierdzeniem została wysłana do '%s', proszę sprawdzić swoją skrzynkę odbiorczą w ciągu %d godzin, aby dokończyć proces potwierdzania.
@ -372,7 +370,6 @@ two_factor_disable_success=Uwierzytelnianie dwuetapowe wyłączono pomyślnie!
manage_access_token=Zarządzaj osobistymi tokenami dostępu
generate_new_token=Wygeneruj nowy token
tokens_desc=Tokeny, które wygenerowałeś, mogą być użyte do dostępu do API Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Jak na razie, każdy token zapewnia pełen dostęp do Twojego konta.
token_name=Nazwa tokena
generate_token=Wygeneruj token
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Port nasłuchu
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Konfiguracja repozytorium
config.repo.root_path=Ścieżka katalogu głównego

View File

@ -88,7 +88,6 @@ log_root_path=Caminho do log
log_root_path_helper=Pasta dos arquivos de log.
enable_console_mode=Ativar o modo de console
enable_console_mode_popup=Além do modo de arquivo, exibir registros (log) no console.
default_branch=Default Branch
optional_title=Configurações opcionais
email_title=Configurações do serviço de e-mail
@ -317,7 +316,6 @@ delete_email=Deletar
email_deletion=Exclusão do email
email_deletion_desc=Ao Excluir este endereço de e-mail será removido informações relacionadas com a sua conta. Você deseja continuar?
email_deletion_success=O E-mail foi excluído com sucesso!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Adicionar novo endereço de e-mail
add_email=Adicionar e-mail
add_email_confirmation_sent=Um novo e-mail de confirmação foi enviado para '%s'. Por favor, verifique sua Caixa de Entrada dentro das próximas %d horas, para concluir o processo de confirmação.
@ -372,7 +370,6 @@ two_factor_disable_success=A autenticação de dois fatores foi desativada com s
manage_access_token=Gerenciar tokens de acesso pessoal
generate_new_token=Gerar novo token
tokens_desc=Tokens gerados por você que podem ser usados para acessar a API do Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Por enquanto, todo token terá acesso completo à sua conta.
token_name=Nome do token
generate_token=Gerar token
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Configuração do Repositório
config.repo.root_path=Root path

View File

@ -51,14 +51,14 @@ internal_server_error=Erro do servidor interno
install=Instalação
title=Procedimentos para a instalação inicial
docker_helper=Se estiver a executar o Gogs dentro de uma instância Docker, por favor leia as<a target="_blank" href="%s">Orientações</a> com atenção, antes de alterar algo nesta página!
requite_db_desc=Gogs requer uma destas base de dados: MySQL, PostgreSQL, SQLite3 ou TiDB (usando o protocolo MySQL).
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Configurações da Base de Dados
db_type=Tipo de Base de Dados
host=Servidor
user=Utilizador
password=Palavra-Chave
db_name=Nome da base de dados
db_schema=Esquema
db_schema=Schema
db_helper=Por favor, utilize o motor INNODB do MySQL, com suporte para o mapa de caracteres utf8_general_ci.
ssl_mode=Modo SSL
path=Directoria
@ -88,7 +88,6 @@ log_root_path=Caminho dos Logs
log_root_path_helper=Directoria para aonde gravar os Logs.
enable_console_mode=Ativar o Modo Consola
enable_console_mode_popup=Para além de guardar logs num ficheiro, mostrá-los na consola.
default_branch=Ramo por omissão
optional_title=Configurações opcionais
email_title=Configurações do serviço de e-mail
@ -265,7 +264,7 @@ following=Seguindo
follow=Seguir
unfollow=Deixar de seguir
form.name_not_allowed=Não é permitido usar o padrão '%s' para o nome do utilizador.
form.name_not_allowed=User name or pattern %q is not allowed.
[settings]
profile=Perfil
@ -317,7 +316,6 @@ delete_email=Eliminar
email_deletion=Eliminação de e-mail
email_deletion_desc=Eliminar este endereço de e-mail irá remover todas as informações relacionadas da sua conta. Pretende continuar?
email_deletion_success=O e-mail foi eliminado com sucesso!
email_deletion_primary=Não é possível remover o endereço de e-mail primário.
add_new_email=Adicionar um novo endereço de e-mail
add_email=Adicionar e-mail
add_email_confirmation_sent=Um novo e-mail de confirmação foi enviado para '%s', por favor verifique a sua caixa de correio dento das próximas %d horas para completar o processo de confirmação.
@ -372,7 +370,6 @@ two_factor_disable_success=A autenticação de dois fatores foi desativada com s
manage_access_token=Gerir Tokens de Acesso Pessoal
generate_new_token=Gerar Novo Token
tokens_desc=Tokens que gerou que podem ser usadas para aceder as APIs do Gogs.
access_token_tips=O token de acesso pessoal pode ser usado tanto como nome do utilizador ou senha de acesso. É recomendado usar o "x-access-token" como o nome do utilizador e o token de acesso pessoal como a senha para aplicações Git.
new_token_desc=Cada token vai ter acesso completo à sua conta.
token_name=Nome do Token
generate_token=Gerar Token
@ -403,9 +400,9 @@ owner=Proprietário
repo_name=Nome do Repositório
repo_name_helper=Um Bom nome de repositório e pequeno, memorável e único.
visibility=Visibilidade
unlisted=Não listado
unlisted=Unlisted
visiblity_helper=Este repositório é <span class="ui red text">Privado</span>
unlisted_helper=Este repositório <span class="ui red text">não está listado</span>
unlisted_helper=This repository is <span class="ui red text">Unlisted</span>
visiblity_helper_forced=Administrador do site forçou todos os novos repositórios para<span class="ui red text">Privado</span>
visiblity_fork_helper=(Alterar desse valor irá afetar todos os forks)
clone_helper=Precisa de ajuda com o clone? Visite a <a target="_blank" href="%s">Ajuda</a>!
@ -435,7 +432,7 @@ repo_description_helper=Descrição do repositório. Máximo de 512 caracteres.
repo_description_length=Caracteres disponíveis
form.reach_limit_of_creation=O criador chegou ao limite de criação de %d repositórios.
form.name_not_allowed=Não é permitido utilizar o padrão '%s' para o nome do repositório.
form.name_not_allowed=Repository name or pattern %q is not allowed.
need_auth=Autorização necessária
migrate_type=Tipo de migração
@ -797,7 +794,7 @@ settings.search_user_placeholder=Procurar utilizador...
settings.org_not_allowed_to_be_collaborator=A organização não tem permissão para ser adicionada como colaboradora.
settings.hooks_desc=Webhooks são muito parecidos com triggers básicos de eventos HTTP POST. Sempre que algo ocorre no Gogs, vamos lidar com a notificação para o host de destino especificado. Saiba mais no nosso <a target="_blank" href="%s"> Guia de Webhooks</a>.
settings.webhooks.add_new=Add a new webhook:
settings.webhooks.choose_a_type=Escolha um tipo...
settings.webhooks.choose_a_type=Choose a type...
settings.add_webhook=Adicionar Webhook
settings.webhook_deletion=Apagar um Webhook
settings.webhook_deletion_desc=Apagar este Webhook vai remover sua informação e todo o histórico de entrega. Deseja continuar?
@ -1025,7 +1022,7 @@ dashboard.system_status=Monitorização de estado do sistema
dashboard.statistic_info=A base de dados do Gogs contém <b>%d</b> utilizadores, <b>%d</b> organizações, <b>%d</b> chaves públicas, <b>%d</b> repositórios, <b>%d</b> observadores, <b>%d</b> estrelas, <b>%d</b> ações, <b>%d</b> acessos, <b>%d</b> questões, <b>%d</b> comentários, <b>%d</b> contas sociais, <b>%d</b> seguidores, <b>%d</b> mirrors, <b>%d</b> versões, <b>%d</b> origens de login, <b>%d</b> Hooks da Web, <b>%d</b> milestones, <b>%d</b> labels, <b>%d</b> tarefas hook, <b>%d</b> equipas, <b>%d</b> tarefas de atualização, <b>%d</b> anexos.
dashboard.operation_name=Nome de operação
dashboard.operation_switch=Mudar
dashboard.select_operation_to_run=Seleccione a operação para executar
dashboard.select_operation_to_run=Please select operation to run
dashboard.operation_run=Executar
dashboard.clean_unbind_oauth=Limpar OAuthes desvinculados
dashboard.clean_unbind_oauth_success=Todos OAuthes desvinculados foram excluídos com sucesso.
@ -1206,15 +1203,14 @@ config.ssh.minimum_key_size_check=Minimum key size check
config.ssh.minimum_key_sizes=Minimum key sizes
config.ssh.rewrite_authorized_keys_at_start=Rewrite "authorized_keys" at start
config.ssh.start_builtin_server=Start builtin server
config.ssh.listen_host=Servidor
config.ssh.listen_port=Porta do servidor
config.ssh.server_ciphers=Cifras do servidor
config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Configuração de repositório
config.repo.root_path=Localização base
config.repo.script_type=Tipo de script
config.repo.root_path=Root path
config.repo.script_type=Script type
config.repo.ansi_chatset=ANSI charset
config.repo.force_private=Force private
config.repo.max_creation_limit=Max creation limit

View File

@ -88,7 +88,6 @@ log_root_path=Calea de jurnal
log_root_path_helper=Director în care să scrie fișiere jurnal.
enable_console_mode=Activați modul consolă
enable_console_mode_popup=În plus față de modul fișier, imprimați și jurnalele pentru consolă.
default_branch=Sucursala implicită
optional_title=Setări opționale
email_title=Setări servicii de e-mail
@ -317,7 +316,6 @@ delete_email=Șterge
email_deletion=Ștergere e-mail
email_deletion_desc=Ștergerea acestei adrese de e-mail va elimina informațiile aferente din contul dumneavoastră. Doriți să continuați?
email_deletion_success=Emailul a fost șters cu succes!
email_deletion_primary=Nu se poate șterge adresa principală de e-mail.
add_new_email=Adăugați o nouă adresă de e-mail
add_email=Adăugați E-mail
add_email_confirmation_sent=Un nou e-mail de confirmare a fost trimis la "%s", vă rugăm să vă verificați căsuța poștală în următoarele %d ore pentru a finaliza procesul de confirmare.
@ -372,7 +370,6 @@ two_factor_disable_success=Autentificarea cu doi factori a fost dezactivată cu
manage_access_token=Gestionează tokenurile de acces personale
generate_new_token=Generarea unui nou token
tokens_desc=Token-urile pe care le-ați generat și care pot fi utilizate pentru a accesa API-urile Gogs.
access_token_tips=Token-ul personal de acces poate fi folosit ca nume de utilizator sau parolă. Este recomandat să utilizaţi "x-access-token" ca nume de utilizator şi token personal de acces ca parolă pentru aplicaţiile Git.
new_token_desc=Fiecare token va avea acces deplin la contul dumneavoastră.
token_name=Nume token
generate_token=Generează Token
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Ascultați gazda
config.ssh.listen_port=Ascultați portul
config.ssh.server_ciphers=Cifre server
config.ssh.server_macs=MAC-uri server
config.ssh.server_algorithms=Algoritmi de server
config.repo_config=Configurarea depozitului
config.repo.root_path=Calea root-ului

View File

@ -88,7 +88,6 @@ log_root_path=Путь к журналу
log_root_path_helper=Каталог для записи файлов журнала.
enable_console_mode=Включите режим консоли
enable_console_mode_popup=В дополнение к файловому режиму, выводить лог в консоль.
default_branch=Ветка по умолчанию
optional_title=Расширенные настройки
email_title=Настройки службы электронной почты
@ -317,7 +316,6 @@ delete_email=Удалить
email_deletion=Удаление адреса электронной почты
email_deletion_desc=Удаление этого адреса электронной почты, приведет к удалению связанной с вашим аккаунтом, информации. Вы точно хотите продолжить?
email_deletion_success=Адрес электронной почты успешно удален.
email_deletion_primary=Cannot delete primary email address.
add_new_email=Добавить новый адрес электронной почты
add_email=Добавить электронную почту
add_email_confirmation_sent=Новое подтверждение по электронной почте было отправлено '%s', пожалуйста, проверьте свой почтовый ящик в течение следующих %d часов, чтобы завершить процесс подтверждения.
@ -372,7 +370,6 @@ two_factor_disable_success=Двухфакторная аутентификаци
manage_access_token=Управление Токенами Персонального Доступа
generate_new_token=Создать новый token
tokens_desc=Созданные вами токены могут использоваться для доступа к Gogs API.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Пока что каждый токен будет иметь полный доступ к вашей учетной записи.
token_name=Имя маркера
generate_token=Генерировать маркер
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Прослушиваемый хост
config.ssh.listen_port=Прослушиваемый порт
config.ssh.server_ciphers=Серверные шифры
config.ssh.server_macs=MAC-серверы
config.ssh.server_algorithms=Серверные алгоритмы
config.repo_config=Настройка репозитория
config.repo.root_path=Корневой путь
@ -1294,7 +1290,7 @@ config.session.cookie_name=Файл cookie
config.session.https_only=Только HTTPS
config.session.gc_interval=GC interval
config.session.max_life_time=Максимальный срок действия
config.session.csrf_cookie_name=CSRF-куки
config.session.csrf_cookie_name=CSRF cookie
config.cache_config=Настройки кеша
config.cache.adapter=Адаптер

View File

@ -88,7 +88,6 @@ log_root_path=Cesta k log súborom
log_root_path_helper=Adresár pre zápis log súborov.
enable_console_mode=Zapnúť režim konzoly
enable_console_mode_popup=Okrem zápisu do súboru, vytlačiť systémové záznamy aj do konzoly.
default_branch=Default Branch
optional_title=Nepovinné nastavenia
email_title=Nastavenie e-mailovej služby
@ -317,7 +316,6 @@ delete_email=Odstrániť
email_deletion=Odstránenie e-mailu
email_deletion_desc=Vymazaním tejto emailovej adresy sa odstránia súvisiace informácie z vášho účtu. Chcete pokračovať?
email_deletion_success=Email bol úspešne odstránený!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Pridať novú e-mailovú adresu
add_email=Pridať email
add_email_confirmation_sent=Nový email s potvrdením bol odoslaný na '%s', v priebehu nasledovných '%d' hodín si prosím skontrolujte vašu schránku pre dokončenie procesu potvrdenia.
@ -372,7 +370,6 @@ two_factor_disable_success=Dvojfaktorové overenie bolo zakázané!
manage_access_token=Spravovať osobné prístupové tokeny
generate_new_token=Vygenerovať nový token
tokens_desc=Tokeny, ktoré ste vygenerovali je možné použiť na prístup ku Gogs API.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Každý token bude mať plný prístup ku vašemu účtu.
token_name=Názov tokenu
generate_token=Vygenerovať token
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Nastavenie repozitára
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Пут до журнала
log_root_path_helper=Директоријум где ће бити снимане датотеке журнала.
enable_console_mode=Омогући конзол начин
enable_console_mode_popup=Поред начин датотеке, пошаљи системске извештаје и конзолу.
default_branch=Default Branch
optional_title=Напредна подешавања
email_title=Подешавања сервиса е-поште
@ -317,7 +316,6 @@ delete_email=Уклони
email_deletion=Брисање адресе е-поште
email_deletion_desc=Брисање ове адресе ће довести до уклањања података. Да ли желите да наставите?
email_deletion_success=Адреса је успешно избрисана!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Додај нови адресу е-поште
add_email=Додај адресу
add_email_confirmation_sent=Послан је нова потврда на '%s', молимо вас проверите ваше поруке унутар %d сата да бисте завршили поступак потврде.
@ -372,7 +370,6 @@ two_factor_disable_success=Двострука аутентификација ј
manage_access_token=Управљање токенима особном приступу
generate_new_token=Генериши нови токен
tokens_desc=Tокени се могу користити за приступ на API за Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Сваки API токен ће имати пун приступ вашем налогу.
token_name=Име токена
generate_token=Генериши токен
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Конфигурација спремишта
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Loggsökväg
log_root_path_helper=Katalog till vilken loggfiler skrivs.
enable_console_mode=Aktivera Konsolläge
enable_console_mode_popup=Utöver fil-läge, skriver även ut loggar till konsol.
default_branch=Default Branch
optional_title=Övriga inställningar
email_title=E-post tjänstens inställningar
@ -317,7 +316,6 @@ delete_email=Radera
email_deletion=Borttagning Av Epostaddress
email_deletion_desc=Borttagning av denna epostaddress kommer att ta bort relaterad information. Vill du fortsätta?
email_deletion_success=Epostaddressen har tagits bort!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Lägg till ny e-postadress
add_email=Lägga till e-post
add_email_confirmation_sent=Ett nytt bekräftelsemail har skickats till '%s', kontrollera vänligen din inbox inom dom närmsta %d timmarna för att slutföra bekräftelsen.
@ -372,7 +370,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=Hantera personliga åtkomst-tokens
generate_new_token=Generera Nya Tokens
tokens_desc=Tokens som du har genererat kan användas för åtkomst av Gogs APIer.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Varje token har full tillgång till ditt konto.
token_name=Tokennamn
generate_token=Generera Token
@ -479,21 +476,21 @@ pulls=Pull-förfrågningar
labels=Etiketter
milestones=Milstenar
commits=Incheckningar
git_branches=Brancher
git_branches=Branches
releases=Släpp
file_raw=
file_history=Historik
file_view_raw=Visa i råformat
file_permalink=Permalänk
file_too_large=Denna fil är för stor för att visas
video_not_supported_in_browser=Din webbläsare stöder inte HTML5 video-tagg.
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Översikt
branches.active_branches=Aktiva brancher
branches.stale_branches=Djärva brancher
branches.all=Alla brancher
branches.updated_by=Uppdaterade %[1]s med %[2]s
branches.change_default_branch=Ändra standard branch
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Ny fil
editor.upload_file=Ladda upp fil
@ -523,19 +520,19 @@ editor.cancel=Avbryt
editor.filename_cannot_be_empty=Filnamnet får inte vara tomt.
editor.branch_already_exists=Grenen '%s' finns redan i förrådet.
editor.directory_is_a_file=Komponenten '%s' i föräldrasökvägen är en fil, inte en katalog i detta förråd.
editor.file_is_a_symlink=Filen '%s' är en symbolisk länk som inte kan editeras i webbläsaren.
editor.file_is_a_symlink=The file '%s' is a symlink that cannot be modified from the web editor.
editor.filename_is_a_directory=Filnmanet '%s' är en existerande katalog i detta förråd.
editor.file_editing_no_longer_exists=Filen '%s' som du redigerar finns inte lägre i förrådet.
editor.file_changed_while_editing=Filinnhållet har ändrats sedan du började redigera. <a target="_blank" href="%s">Klicka här</a> för att se vad som ändrats eller <strong>tryck checka in igen</strong> för att skriva över dessa ändringar.
editor.file_already_exists=En fil med namnet '%s' finns redan i förrådet.
editor.no_changes_to_show=Det finns inga ändringar att visa.
editor.fail_to_update_file=Uppdateringen/skapandet av filen '%s' misslyckades med felet: %v
editor.fail_to_delete_file=Det gick inte att ta bort filen '%s' med fel: %v.
editor.fail_to_delete_file=Failed to delete file '%s' with error: %v
editor.add_subdir=Lägg till underkatalog...
editor.unable_to_upload_files=Uppladdning av filen '%s' misslyckades med felet: %v
editor.upload_files_to_dir=Ladda upp filer till '%s'
commits.commit_history=Commit historia
commits.commit_history=Commit History
commits.commits=Incheckningar
commits.search=Sök bland incheckningar
commits.find=Sök
@ -633,7 +630,7 @@ pulls.compare_compare=jämför
pulls.filter_branch=Filtrera gren
pulls.no_results=Inga resultat hittades.
pulls.nothing_to_compare=Det finns inget att jämföra eftersom bas och huvudgrenar är lika.
pulls.nothing_merge_base=Det finns inget att jämföra eftersom två branch har helt olika historia.
pulls.nothing_merge_base=There is nothing to compare because two branches have completely different history.
pulls.has_pull_request=`Det finns redan en pullförfrågan mellan detta två mål: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]s</a>^
pulls.create=Skapa Pullförfrågan
pulls.title_desc=vill sammanfoga %[1]d incheckningar från <code>s[2]s</code> in i <code>%[3]s</code>
@ -649,13 +646,13 @@ pulls.is_checking=Konfliktkontroll är fortfarande pågågående, vänligen uppd
pulls.can_auto_merge_desc=Denna pull-förfrågan kan sammanfogas automatiskt.
pulls.cannot_auto_merge_desc=Denna pull-förfrågan kan inte sammanfogas automatiskt eftersom det finns konflikter.
pulls.cannot_auto_merge_helper=Vänligen sammanfoga manuellt för att lösa konflikter.
pulls.create_merge_commit=Skapa en merge commit
pulls.rebase_before_merging=Rebase innan merge
pulls.commit_description=Commit beskrivning
pulls.create_merge_commit=Create a merge commit
pulls.rebase_before_merging=Rebase before merging
pulls.commit_description=Commit Description
pulls.merge_pull_request=Sammanfoga Pull-förfrågan
pulls.open_unmerged_pull_exists=`Du kan inte utföra återöppningsoperationen eftersom det finns redan en öppen pull-förfrågan (#%d) från samma repo med samma sammanfogningsinformation som väntar på sammanfogning.`
pulls.delete_branch=Ta bort gren
pulls.delete_branch_has_new_commits=Branch kan inte tas bort eftersom den har nya commits efter merge.
pulls.delete_branch_has_new_commits=Branch cannot be deleted because it has new commits after mergence.
milestones.new=Ny milstolpe
milestones.open_tab=%d Öppna
@ -706,8 +703,8 @@ settings.collaboration.admin=Adminstrera
settings.collaboration.write=Skriva
settings.collaboration.read=Läsa
settings.collaboration.undefined=Odefinierad
settings.branches=Brancher
settings.branches_bare=Du kan inte hantera brancher för kala repository. Vänligen push innehåll först.
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
@ -727,7 +724,7 @@ settings.protect_whitelist_committers_desc=Add people or teams to whitelist of d
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Sök användare
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Sök team
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webbhookar
settings.githooks=Githookar
@ -796,8 +793,8 @@ settings.remove_collaborator_success=Deltagare har tagits bort.
settings.search_user_placeholder=Sök användare...
settings.org_not_allowed_to_be_collaborator=Organisationen kan inte läggas till som en deltagare.
settings.hooks_desc=Webbhookar påminner mycket om vanliga HTTP POST-händelseutlösare. När något inträffar i Gogs, kommer vi att meddela måldatorn som du anger. Läs mera i <a target="_blank" href="%s">Webbhook Guide</a>.
settings.webhooks.add_new=Lägg till en ny webhook:
settings.webhooks.choose_a_type=Välj en typ...
settings.webhooks.add_new=Add a new webhook:
settings.webhooks.choose_a_type=Choose a type...
settings.add_webhook=Lägg Till Webbhook
settings.webhook_deletion=Ta Bort Webbhook
settings.webhook_deletion_desc=Borttagning av denna webbhook kommer att ta bort all dess information och all leveranshistorik. Är du säker på att du vill fortsätta?
@ -805,7 +802,7 @@ settings.webhook_deletion_success=Webbhook har tagits bort!
settings.webhook.test_delivery=Testa Leverans
settings.webhook.test_delivery_desc=Skicka en falsk pushhändelse för att testa dina webbhook-inställningar
settings.webhook.test_delivery_success=Testwebbhook har lagts till leveranskön. Det kan ta några sekunder innan den visas i leveranshistoriken.
settings.webhook.redelivery=Återleverans
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Begäran
settings.webhook.response=Svar
@ -833,10 +830,10 @@ settings.event_send_everything=Jag behöver <strong>allt</strong>.
settings.event_choose=Låt mig välja.
settings.event_create=Skapa
settings.event_create_desc=Branch eller tagg skapad
settings.event_delete=Ta bort
settings.event_delete_desc=Branch eller tagg borttagen
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forkad
settings.event_fork_desc=Repository forked
settings.event_push=Pusha
settings.event_push_desc=Uppladdning till ett förråd
settings.event_issues=Issues
@ -846,7 +843,7 @@ settings.event_pull_request_desc=Pull request opened, closed, reopened, edited,
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_release=Release
settings.event_release_desc=Release publicerat i ett repository.
settings.event_release_desc=Release published in a repository.
settings.active=Aktiv
settings.active_helper=Detaljer kring händelsen som triggade kroken kommer också levereras.
settings.add_hook_success=Ny webbkrok har lagts till.
@ -856,7 +853,7 @@ settings.delete_webhook=Tag bort webbkrok
settings.recent_deliveries=Färska leveranser
settings.hook_type=Kroktyp
settings.add_slack_hook_desc=Lägg till <a href="%s">Slack</a>-integration till ditt förråd.
settings.add_discord_hook_desc=
settings.add_discord_hook_desc=Add <a href="%s">Discord</a> integration to your repository.
settings.add_dingtalk_hook_desc=Add <a href="%s">Dingtalk</a> integration to your repository.
settings.slack_token=Pollett
settings.slack_domain=Domän
@ -875,7 +872,7 @@ settings.deploy_key_deletion=Ta bort distribueringsnyckel
settings.deploy_key_deletion_desc=Borttagning av detta distributionsnyckel kommer att ta bort all relaterad åtkomst till det här repot. Vill du fortsätta?
settings.deploy_key_deletion_success=Distributionsnyckeln har tagits bort!
settings.description_desc=Description of repository. Maximum 512 characters length.
settings.description_length=Tillgängliga tecken
settings.description_length=Available characters
diff.browse_source=Bläddra i källkod
diff.parent=förälder
@ -1015,9 +1012,9 @@ total=Totalt: %d
dashboard.build_info=Build Information
dashboard.app_ver=Application version
dashboard.git_version=Git Version
dashboard.git_version=Git version
dashboard.go_version=Go version
dashboard.build_time=Build tid
dashboard.build_time=Build time
dashboard.build_commit=Build commit
dashboard.statistic=Statistik
dashboard.operations=Operationer
@ -1025,13 +1022,13 @@ dashboard.system_status=Systemstatus
dashboard.statistic_info=Gogs-databasen innehåller <b>%d</b> användare, <b>%d</b> organisationer, <b>%d</b> publika nyckar, <b>%d</b> förråd, <b>%d</b> vakter, <b>%d</b> stjärnor, <b>%d</b> handlingar, <b>%d</b> åtkomster, <b>%d</b> ärenden, <b>%d</b> kommentarer, <b>%d</b> sociala konton, <b>%d</b> följbegäran, <b>%d</b> speglingar, <b>%d</b> släpp, <b>%d</b> inloggningskällor, <b>%d</b> webbkrokar, <b>%d</b> milstolpar, <b>%d</b> etiketter, <b>%d</b> krokuppgifter, <b>%d</b> team, <b>%d</b> uppdateringsuppgifter, <b>%d</b> bilagor.
dashboard.operation_name=Operationsnamn
dashboard.operation_switch=Byt till
dashboard.select_operation_to_run=Välj åtgärd att köra
dashboard.select_operation_to_run=Please select operation to run
dashboard.operation_run=Kör
dashboard.clean_unbind_oauth=Rensa obundna OAuth-begäran
dashboard.clean_unbind_oauth_success=Alla obundna OAuth-begäran har tagit
dashboard.delete_inactivate_accounts=Ta bort alla inaktiva konton
dashboard.delete_inactivate_accounts_success=
dashboard.delete_repo_archives=
dashboard.delete_inactivate_accounts_success=All inactivate accounts have been deleted successfully.
dashboard.delete_repo_archives=Delete all repositories archives
dashboard.delete_repo_archives_success=All repositories archives have been deleted successfully.
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository configuration
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=Günlük Dosyaları Yolu
log_root_path_helper=Günlük dosyalarının yazılacağı dizin.
enable_console_mode=Konsol Modunu Etkinleştir
enable_console_mode_popup=Dosya moduna ek olarak , ayrıca konsolun günlüklerini yazdır.
default_branch=Default Branch
optional_title=İsteğe Bağlı Ayarlar
email_title=E-Posta Servisi Ayarları
@ -317,7 +316,6 @@ delete_email=Sil
email_deletion=E-Posta Silme
email_deletion_desc=Bu e-posta adresini silerseniz hesabınıza ilişkin tüm bilgileriniz de silinecektir. Devam etmek istiyor musunuz?
email_deletion_success=E-posta adresi başarıyla silindi!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Yeni e-posta adresi ekle
add_email=E-posta ekle
add_email_confirmation_sent='%s' adresine yeni bir doğrulama e-postası gönderildi. Doğrulama aşamalarını tamamlamak için lütfen %d saat içinde gelen kutunuzu kontrol edin.
@ -372,7 +370,6 @@ two_factor_disable_success=İki faktörlü kimli doğrulama başarıyla devre d
manage_access_token=Kişisel Erişim Anahtarlarını Yönet
generate_new_token=Yeni Erişim Anahtarı Üret
tokens_desc=Ürettiğiniz erişim anahtarları, Gogs API'lerine erişimde kullanılabilir.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Her bir erişim anahtarının hesabınıza tam erişim yetkisi olacaktır.
token_name=Erişim Anahtarı İsmi
generate_token=Erişim Anahtarı Üret
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Ana makineyi dinle
config.ssh.listen_port=Port'u dinle
config.ssh.server_ciphers=Sunucu şifreleri
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Depo Yapılandırması
config.repo.root_path=Kök yolu

View File

@ -1,14 +1,14 @@
app_desc=Зручний сервіс власного Git хостингу
app_desc=Зручний сервіс власного Git хостінгу
home=Головна сторінка
dashboard=Панель керування
dashboard=Щиток
explore=Огляд
help=Довідка
sign_in=Увійти
sign_out=Вийти
sign_up=Реєстрація
register=Реєстрація
website=Вебсторінка
website=Веб-сторінка
page=Сторінка
template=Шаблон
language=Мова
@ -32,7 +32,7 @@ new_fork=Нове відгалудження
new_org=Нова організація
manage_org=Керування організаціями
admin_panel=Панель адміністратора
account_settings=Налаштування облікового запису
account_settings=Нашалштування облікового запису
settings=Налаштування
your_profile=Ваш профіль
your_settings=Ваші налаштування
@ -51,7 +51,7 @@ internal_server_error=Внутрішня помилка серверу
install=Установка
title=Кроки установки перед першим запуском
docker_helper=Якщо ви запускаєте Gogs всередені Docker, уважно прочитайте <a target="_blank" href="%s">гайдлайни</a> перш ніж змінювати щось!
requite_db_desc=Gogs потребує MySQL, PostgreSQL, SQLite3 або TiDB (за допомогою MySQL протоколу).
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB (via MySQL protocol).
db_title=Налаштування бази даних
db_type=Тип бази данних
host=Хост
@ -83,18 +83,17 @@ use_builtin_ssh_server_popup=Запустити вбудований SSH сер
http_port=Порт HTTP
http_port_helper=Номер порту який программа буде слухати.
app_url=Адреса програми
app_url_helper=Це впливає на клонування URL через HTTP/HTTPS та десь в електронній пошті.
app_url_helper=Це впливає на клонування через HTTP/HTTPS та десь у електроній пошті.
log_root_path=Шлях до лог файлу
log_root_path_helper=Каталог для файлів журналу.
enable_console_mode=Увімкнути консольний режим
enable_console_mode_popup=На додаток до файлового режиму писати логи також і до консолі.
default_branch=Гілка за замовчуванням
optional_title=Додаткові налаштування
email_title=Налаштування електронної пошти
email_title=Параметри електронної пошти
smtp_host=SMTP хост
smtp_from=Від
smtp_from_helper=Поле "Від" адреси, згідно RFC 5322. Це може бути просто адреса електронної пошти або адреса у форматі "Ім'я" <email@example.com>.
smtp_from_helper=Поле "Від" адреси, RFC 5322. Це може бути просто адреса електронної пошти або адреса у форматі «Ім'я» <email@example.com>.
mailer_user=Відправник електронної пошти
mailer_password=Відправник паролю
register_confirm=Увімкнути підтвердження реєстрації
@ -156,7 +155,7 @@ create_new_account=Створити новий обліковий запис
register_hepler_msg=Вже зареєстровані? Увійдіть зараз!
social_register_hepler_msg=Вже зареєстровані? Прив'яжіть зараз!
disable_register_prompt=Вибачте, реєстрація відключена. Будь ласка, зв'яжіться з адміністратором сайту.
disable_register_mail=На жаль, підтвердження реєстрації на електрону пошту вимкнено адміністратором.
disable_register_mail=На жаль, підтвердження реєстрації на електрону пошту було відключено.
auth_source=Джерело автентифікації
local=Локальний
remember_me=Запам'ятати мене
@ -178,7 +177,7 @@ password_too_short=Довжина пароля не може бути меншо
non_local_account=Нелокальні облікові записи не можуть змінити пароль через Gogs.
login_two_factor=Двофакторна автентифікація
login_two_factor_passcode=Код аутентифікації
login_two_factor_passcode=Код автентифікації
login_two_factor_enter_recovery_code=Введіть двофакторний код відновлення
login_two_factor_recovery=Двофакторне відновлення
login_two_factor_recovery_code=Код відновлення
@ -224,7 +223,7 @@ alpha_dash_dot_slash_error=` мусить бути валідною буквою
size_error=` має мати розмір %s.`
min_size_error=' має містити принаймні %s символів.'
max_size_error=' має містити принаймні %s символів.'
email_error=`це не дійсна електронна поштова адреса.`
email_error=це не дійсна електронна поштова адреса.
url_error='не є припустимою URL-Адресою.'
include_error=`повинен містити текст '%s'`
unknown_error=Невідома помилка:
@ -235,7 +234,7 @@ username_been_taken=Ім'я користувача вже зайнято.
repo_name_been_taken=Назва сховища вже використовується.
org_name_been_taken=Назва організаціі вже використовується.
team_name_been_taken=Назва команди вже використовується.
email_been_used=Ця адреса електронної пошти вже використовується.
email_been_used=Адреса електронної пошти вже використовується.
username_password_incorrect=Ім'я користувача або пароль помилкові.
auth_source_mismatch=Обране джерело автентифікації не асоційовано з користувачем.
enterred_invalid_repo_name=Переконайтеся, що ви ввели назву сховища правильно.
@ -317,9 +316,8 @@ delete_email=Видалити
email_deletion=Видалення електронної пошти
email_deletion_desc=Видалення цієї електронної адреси призведе до вилучення інформації, пов'язаної з вашим обліковим записом. Ви бажаєте продовжити?
email_deletion_success=Електронну адресу успішно видалено!
email_deletion_primary=Не вдається видалити основну адресу електронної пошти.
add_new_email=Додати нову адресу електронної пошти
add_email=Додати адресу електронної пошти
add_email=Додати адресу електроної пошти
add_email_confirmation_sent=Новий електронний лист із підтвердженням було направлено на '%s', будь ласка, перевірте вашу поштову скриньку протягом наступних %d годин, щоб завершити процес підтвердження.
add_email_success=Вашу нову адресу електронної пошти було успішно додано.
@ -341,7 +339,7 @@ add_on=Додано
last_used=Останнє використання
no_activity=Жодної діяльності
key_state_desc=Цей ключ використовувався в останні 7 днів
token_state_desc=Цей жетон використовувався в останні 7 днів
token_state_desc=Цей токен використовувався в останні 7 днів
two_factor=Двофакторна автентифікація
two_factor_status=Статус:
@ -350,7 +348,7 @@ two_factor_off=Викл.
two_factor_enable=Увімкнути
two_factor_disable=Вимкнути
two_factor_view_recovery_codes=Перегляньте й збережіть <a href="%s%s">ваші ключі відновлення</a> у безпечному місці. Ви можете використовувати іх як паролі якщо втратите доступ до вашої програми автентифікації.
two_factor_http=Для HTTP/HTTPS операцій, ви більше не можете використовувати звичайні ім'я та пароль. Будь ласка створіть та використовуйте <a href="%[1]s%[2]s">персональний жетон доступу</a> як ваші облікові дані, наприклад <code>%[3]s</code>.
two_factor_http=Для HTTP/HTTPS операцій, ви більше не можете використовувати звичайні ім'я та пароль. Будь ласка створіть та використовуйте <a href="%[1]s%[2]s">персональний токен доступу</a> як ваші облікові дані, наприклад <code>%[3]s</code>.
two_factor_enable_title=Увімкнути двофакторну автентифікацію
two_factor_scan_qr=Будь ласка, використовуйте ваш додаток автентифікації для сканування зображення:
two_factor_or_enter_secret=Або введіть секрет:
@ -369,19 +367,18 @@ two_factor_disable_title=Вимкнути двофакторну автенти
two_factor_disable_desc=Рівень безпеки вашого акаунту знизиться після вимикання двофакторної автентифікаціЇ. Бажаєте продовжити?
two_factor_disable_success=Двофакторну автентифікацію було успішно вимкнено!
manage_access_token=Керувати жетонами особистого доступу
manage_access_token=Керувати токенами особистого доступу
generate_new_token=Генерувати новий жетон
tokens_desc=Створені вами жетони для доступу до Gogs API.
access_token_tips=Персональний жетон доступу може бути використаний як ім'я користувача або пароль. Рекомендується використовувати "x-access-token" як ім'я користувача та персональний жетон доступу, що є паролем для додатків gt.
new_token_desc=На цей час будь-який жетон має повний доступ до вашого облікового запису.
tokens_desc=Створені вами токени для доступу до Gogs API.
new_token_desc=На даний момент будь-який жетон має повний доступ до вашого облікового запису.
token_name=Назва жетону
generate_token=Створити жетон
generate_token_succees=Новий жетон було створено успішно! Переконайтеся, що Ви скопіювали Ваш новий жетон доступу, бо Ви не зможете побачити його знову!
generate_token_succees=Новий жетон було створено успішно! Переконайтеся, що Ви скопіювали Ваш новий жетон доступу. Ви не зможете побачити його знову!
delete_token=Видалити
access_token_deletion=Видалення жетону персонального доступу
access_token_deletion_desc=Видалення цього жетону призведе до неможливості доступу усіх пов’язаних додатків. Продовжити?
delete_token_success=Персональний жетон було видалено. Не забудьте перевірити ваш додаток.
token_name_exists=Жетон з таким ім'ям вже існує.
access_token_deletion=Видалення токену персонального доступу
access_token_deletion_desc=Видалення цього токену призведе до неможливості доступу усіх пов’язаних додатків. Продовжити?
delete_token_success=Персональний токен було видалено. Не забудьте перевірити ваш додаток.
token_name_exists=Токен з таким ім'ям вже існує.
orgs.none=Ви не є членом будь-якої організації.
orgs.leave_title=Залишити організацію
@ -446,7 +443,7 @@ migrate.clone_address_desc=Це може бути URL-адресою HTTP, HTTPS
migrate.clone_address_desc_import_local=Ви також можете змігрувати репозиторій з локального шляху на сервері.
migrate.permission_denied=Вам не дозволено імпортувати локальні репозиторії.
migrate.invalid_local_path=Невірний локальний шлях, він не існує або не є каталогом.
migrate.clone_address_resolved_to_blocked_local_address=Адреса клону розв’язана на адресу локальної мережі, яка неявно заблокована.
migrate.clone_address_resolved_to_blocked_local_address=Clone address resolved to a local network address that is implicitly blocked.
migrate.failed=Перенесення не вдалось: %v
mirror_from=дзеркало
@ -813,7 +810,7 @@ settings.webhook.headers=Заголовки
settings.webhook.payload=Зміст
settings.webhook.body=Тіло
settings.webhook.err_cannot_parse_payload_url=Неможливо розібрати payload URL: %v
settings.webhook.url_resolved_to_blocked_local_address=URL-адреса корисного навантаження розв’язана з адресою у локальної мережі, яка неявно заблокована.
settings.webhook.url_resolved_to_blocked_local_address=Payload URL resolved to a local network address that is implicitly blocked.
settings.githooks_desc=Git хуки керуються самим Git, ви можете редагувати файли хуків, що підтримуються згідно списку нище, щоб виконувати будь-які операції.
settings.githook_edit_desc=Якщо хук неактивний, буде представлено зразок вмісту. Порожнє значення у цьому полі призведе до вимкнення хуку.
settings.githook_name=Ім'я хуку
@ -858,7 +855,7 @@ settings.hook_type=Тип хуку
settings.add_slack_hook_desc=Додати <a href="%s">Slack</a>-інтеграцію до вашого репозиторію.
settings.add_discord_hook_desc=Додати <a href="%s">Discord</a>-інтеграцію до репозиторію.
settings.add_dingtalk_hook_desc=Додати інтеграцію <a href="%s">Dingtalk</a> до вашого репозиторію.
settings.slack_token=Жетон
settings.slack_token=Токен
settings.slack_domain=Домен
settings.slack_channel=Канал
settings.deploy_keys=Ключи для розгортування
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Слухати хост
config.ssh.listen_port=Слухати порт
config.ssh.server_ciphers=Серверні шифри
config.ssh.server_macs=MAC-адреси сервера
config.ssh.server_algorithms=Алгоритми сервера
config.repo_config=Налаштування репозиторія
config.repo.root_path=Кореневий шлях
@ -1222,9 +1218,9 @@ config.repo.preferred_licenses=Бажані ліцензії
config.repo.disable_http_git=Вимкнути HTTP Git
config.repo.enable_local_path_migration=Увімкнути міграцію з локального шляху
config.repo.enable_raw_file_render_mode=Вмикає режим візуалізації неформатованого файлу
config.repo.commits_fetch_concurrency=Запросити коміти конкурентно
config.repo.editor.line_wrap_extensions=Розширення редактора для перенесення рядків
config.repo.editor.previewable_file_modes=Режим редактора попереднього перегляду файлів
config.repo.commits_fetch_concurrency=Commits fetch concurrency
config.repo.editor.line_wrap_extensions=Editor line wrap extensions
config.repo.editor.previewable_file_modes=Editor previewable file modes
config.repo.upload.enabled=Вивантаження увімкнено
config.repo.upload.temp_path=Завантажити тимчасовий шлях
config.repo.upload.allowed_types=Дозволені типи вивантаження
@ -1236,7 +1232,7 @@ config.db.type=Тип
config.db.host=Хост
config.db.name=Ім'я
config.db.schema=Схема
config.db.schema_helper=(тільки для "postgres")
config.db.schema_helper=(for "postgres" only)
config.db.user=Користувач
config.db.ssl_mode=Режим SSL
config.db.ssl_mode_helper=(тільки для "postgres")
@ -1246,72 +1242,72 @@ config.db.max_open_conns=Максимальна кількість відкри
config.db.max_idle_conns=Максимальна кількість бездіяльних з'єднань
config.security_config=Налаштування безпеки
config.security.login_remember_days=Кількість днів запам'ятовування входу
config.security.login_remember_days=Login remember days
config.security.cookie_remember_name=Запам'ятати куки
config.security.cookie_username=Куки імені користувача
config.security.cookie_secure=Увімкнути захищені файли куки
config.security.reverse_proxy_auth_user=Заголовок аутентифікації на зворотному проксі
config.security.enable_login_status_cookie=Увімкнути файли куки стану при вході
config.security.login_status_cookie_name=Куки статусу входу
config.security.local_network_allowlist=Дозволений список у локальної мережі
config.security.cookie_username=Username cookie
config.security.cookie_secure=Enable secure cookie
config.security.reverse_proxy_auth_user=Reverse proxy authentication header
config.security.enable_login_status_cookie=Enable login status cookie
config.security.login_status_cookie_name=Login status cookie
config.security.local_network_allowlist=Local network allowlist
config.email_config=Налаштування електронної пошти
config.email_config=Налаштування пошти
config.email.enabled=Увімкнено
config.email.subject_prefix=Префікс теми
config.email.subject_prefix=Subject prefix
config.email.host=Хост
config.email.from=Від
config.email.from=From
config.email.user=Користувач
config.email.disable_helo=Вимкнути HELO
config.email.helo_hostname=Ім'я хосту HELO
config.email.skip_verify=Пропустити перевірку сертифіката
config.email.use_certificate=Використовувати користувальницький сертифікат
config.email.cert_file=Файл сертифікату
config.email.key_file=Ключовий файл
config.email.use_plain_text=Використовувати звичайний текст
config.email.add_plain_text_alt=Додайте простий текст у якості альтернативи
config.email.send_test_mail=Надіслати пробний лист
config.email.test_mail_failed=Помилка відправлення пробного листа до '%s': %v
config.email.test_mail_sent=Пробного листа було відправлено до '%s'.
config.email.disable_helo=Disable HELO
config.email.helo_hostname=HELO hostname
config.email.skip_verify=Skip certificate verify
config.email.use_certificate=Use custom certificate
config.email.cert_file=Certificate file
config.email.key_file=Key file
config.email.use_plain_text=Use plain text
config.email.add_plain_text_alt=Add plain text alternative
config.email.send_test_mail=Send test email
config.email.test_mail_failed=Failed to send test email to '%s': %v
config.email.test_mail_sent=Test email has been sent to '%s'.
config.auth_config=Налаштування аутентифікації
config.auth.activate_code_lives=Активувати код підтвердження
config.auth.reset_password_code_lives=Термін придатності кода при скиданні пароля
config.auth.require_email_confirm=Вимагає підтвердження електронною поштою
config.auth.require_sign_in_view=Необхідно авторизуватися для перегляду
config.auth.disable_registration=Вимкнути реєстрацію
config.auth.enable_registration_captcha=Включити реєстрацію з капчею
config.auth.enable_reverse_proxy_authentication=Увімкнути аутентифікацію на зворотному проксі
config.auth.enable_reverse_proxy_auto_registration=Увімкнути автоматичну реєстрацію на зворотному проксі
config.auth.reverse_proxy_authentication_header=Заголовок аутентифікації на зворотному проксі
config.auth_config=Authentication configuration
config.auth.activate_code_lives=Activate code lives
config.auth.reset_password_code_lives=Reset password code lives
config.auth.require_email_confirm=Require email confirmation
config.auth.require_sign_in_view=Require sign in view
config.auth.disable_registration=Disable registration
config.auth.enable_registration_captcha=Enable registration captcha
config.auth.enable_reverse_proxy_authentication=Enable reverse proxy authentication
config.auth.enable_reverse_proxy_auto_registration=Enable reverse proxy auto registration
config.auth.reverse_proxy_authentication_header=Reverse proxy authentication header
config.user_config=Налаштування користувача
config.user.enable_email_notify=Увімкнути сповіщення електронною поштою
config.user.enable_email_notify=Enable email notification
config.session_config=Налаштування сесії
config.session.provider=Постачальник
config.session.provider_config=Налаштування постачальника
config.session.cookie_name=Файл куки
config.session.https_only=Виключно по HTTPS
config.session.gc_interval=Інтервал GC
config.session.max_life_time=Максимальний час дії
config.session.csrf_cookie_name=Кука CSRF
config.session.provider=Provider
config.session.provider_config=Provider config
config.session.cookie_name=Cookie
config.session.https_only=HTTPS only
config.session.gc_interval=GC interval
config.session.max_life_time=Max life time
config.session.csrf_cookie_name=CSRF cookie
config.cache_config=Конфігурація кешу
config.cache.adapter=Адаптер
config.cache.interval=GC Інтервал
config.cache.host=Хост
config.cache.adapter=Adapter
config.cache.interval=GC interval
config.cache.host=Host
config.http_config=Налаштування HTTP
config.http.access_control_allow_origin=Контроль доступу дозволяє походження
config.http.access_control_allow_origin=Access control allow origin
config.attachment_config=Налаштування вкладення
config.attachment_config=Attachment configuration
config.attachment.enabled=Увімкнено
config.attachment.path=Шлях
config.attachment.allowed_types=Дозволені типи
config.attachment.max_size=Ліміт розміру
config.attachment.max_files=Ліміт файлів
config.release_config=Налаштування випуску
config.release_config=Release configuration
config.release.attachment.enabled=Вкладення увімкнено
config.release.attachment.allowed_types=Дозволені типи вкладень
config.release.attachment.max_size=Ліміт розміру вкладення
@ -1329,19 +1325,19 @@ config.mirror.default_interval=Інтервал за замовчуванням
config.webhook_config=Налаштування web-хуків
config.webhook.types=Типи
config.webhook.deliver_timeout=Час для доставки вичерпано
config.webhook.skip_tls_verify=Пропустити перевірку TLS
config.webhook.deliver_timeout=Deliver timeout
config.webhook.skip_tls_verify=Skip TLS verify
config.git_config=Налаштування git
config.git.disable_diff_highlight=Вимкнути підсвітку синтаксису порівняння
config.git.max_diff_lines=Обмеження рядків порівнюючи (для одного файлу)
config.git.max_diff_line_characters=Обмеження символів порівнюючи (для одного файлу)
config.git.max_diff_files=Обмеження на порівняння файлів (для одного порівняння)
config.git.disable_diff_highlight=Disable diff syntax highlight
config.git.max_diff_lines=Diff lines limit (for a single file)
config.git.max_diff_line_characters=Diff characters limit (for a single line)
config.git.max_diff_files=Diff files limit (for a single diff)
config.git.gc_args=Аргументи GC
config.git.migrate_timeout=Час для міграції вичерпано
config.git.mirror_timeout=Час для отримання дзеркала вичерпано
config.git.clone_timeout=Час для клонування вичерпано
config.git.pull_timeout=Час для витягання вичерпано
config.git.migrate_timeout=Migration timeout
config.git.mirror_timeout=Mirror fetch timeout
config.git.clone_timeout=Clone timeout
config.git.pull_timeout=Pull timeout
config.git.gc_timeout=Затримка GC
config.lfs_config=Налаштування LFS

View File

@ -88,7 +88,6 @@ log_root_path=Đường dẫn Log
log_root_path_helper=Thư mục để viết vào tập tin Log.
enable_console_mode=Bật chế độ console
enable_console_mode_popup=Ngoài chế độ tập tin, còn có in logs vào console.
default_branch=Default Branch
optional_title=Cài đặt tùy chọn
email_title=Cài đặt dịch vụ email
@ -317,7 +316,6 @@ delete_email=Xóa
email_deletion=Xóa email
email_deletion_desc=Xóa địa chỉ email này sẽ xóa các thông tin liên quan đến tài khoản của bạn. Bạn có muốn tiếp tục?
email_deletion_success=Đã xóa email thành công!
email_deletion_primary=Cannot delete primary email address.
add_new_email=Thêm địa chỉ email mới
add_email=Thêm email
add_email_confirmation_sent=Một email xác nhận mới đã được gửi đến '%s', xin vui lòng kiểm tra hộp thư của bạn trong vòng giờ %d tiếp theo để hoàn tất quá trình xác nhận.
@ -372,7 +370,6 @@ two_factor_disable_success=Xác thực 2 yếu tố đã vô hiệu hoá thành
manage_access_token=Quản lý mã truy cập cá nhân
generate_new_token=Tạo token mới
tokens_desc=Thẻ bạn đã tạo ra mà có thể được sử dụng để truy cập vào các API Gogs.
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=Mỗi token sẽ có thể truy cập vào tài khoản của bạn.
token_name=Token Name
generate_token=Tạo mã
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Máy chủ lắng nghe
config.ssh.listen_port=Cổng lắng nghe
config.ssh.server_ciphers=Mật mã máy chủ
config.ssh.server_macs=Địa chỉ MACs máy chủ
config.ssh.server_algorithms=Server algorithms
config.repo_config=Cấu hình kho
config.repo.root_path=Đường dẫn Root

View File

@ -88,7 +88,6 @@ log_root_path=日志路径
log_root_path_helper=存放日志文件的目录
enable_console_mode=启用控制台模式
enable_console_mode_popup=除了使用文件模式外,还将日志输出到控制台
default_branch=默认分支
optional_title=可选设置
email_title=邮件服务设置
@ -317,7 +316,6 @@ delete_email=删除
email_deletion=邮箱删除操作
email_deletion_desc=删除该邮箱地址将会移除所有相关的信息。是否继续?
email_deletion_success=邮箱删除成功!
email_deletion_primary=无法删除默认邮箱。
add_new_email=添加新的邮箱地址
add_email=添加邮箱
add_email_confirmation_sent=一封待确认的电子邮件已发送到 '%s',请在 %d 小时内检查您的收件箱,并完成确认过程。
@ -372,7 +370,6 @@ two_factor_disable_success=两步验证登录关闭成功!
manage_access_token=管理个人操作令牌
generate_new_token=生成新的令牌
tokens_desc=您可以使用这些已生成的令牌来操作 Gogs API。
access_token_tips=个人访问令牌可以用作用户名或密码。建议使用 "x-access-token" 作为 Git 应用程序的用户名并使用个人访问令牌作为密码。
new_token_desc=目前为止,任何令牌都对您的帐户拥有完整的操作权限。
token_name=令牌名称
generate_token=生成令牌
@ -637,7 +634,7 @@ pulls.nothing_merge_base=由于两个分支各自拥有完全不同的提交历
pulls.has_pull_request=`已经存在目标分支的合并请求:<a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=创建合并请求
pulls.title_desc=请求将 %[1]d 次代码提交从 <code>%[2]s</code> 合并至 <code>%[3]s</code>
pulls.merged_title_desc=于 %[4]s 将 %[1]d 次代码提交从 <code>%[2]s</code>合并至 <code>%[3]s</code>
pulls.merged_title_desc=于 %[4]s 将 %[1]d 次代码提交从 <code>%[2]s</code>合并至 <code>%[3]s</code>
pulls.tab_conversation=对话内容
pulls.tab_commits=代码提交
pulls.tab_files=文件变动
@ -819,7 +816,7 @@ settings.githook_edit_desc=如果钩子未启动,则会显示样例文件中
settings.githook_name=钩子名称
settings.githook_content=钩子文本
settings.update_githook=更新钩子设置
settings.add_webhook_desc=我们会通过 <code>POST</code> 请求将订阅事件信息发送至向指定 URL 地址。您可以设置不同的数据接收方式JSON 或 <code>x-www-form-urlencoded</code>)。 请查阅 <a target="_blank" href="%s">Webhooks 文档</a> 获取更多信息。
settings.add_webhook_desc=我们会通过 <code>POST</code> 请求将订阅事件信息发送至向指定 URL 地址。您可以设置不同的数据接收方式JSON 或 <code>x-www-form-urlencoded</code>)。 请查阅 <a target="_blank" href="%s">Webhooks 文档</a> 获取更多信息。
settings.payload_url=推送地址
settings.content_type=数据格式
settings.secret=密钥文本
@ -1211,7 +1208,6 @@ config.ssh.listen_host=监听主机
config.ssh.listen_port=监听端口
config.ssh.server_ciphers=服务端加密套件
config.ssh.server_macs=服务器 MAC 地址
config.ssh.server_algorithms=服务器算法
config.repo_config=仓库配置
config.repo.root_path=根目录

View File

@ -88,7 +88,6 @@ log_root_path=日誌路徑
log_root_path_helper=寫入日誌檔目錄
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
default_branch=Default Branch
optional_title=可選設置
email_title=電子郵件服務設定
@ -317,7 +316,6 @@ delete_email=刪除
email_deletion=刪除郵箱
email_deletion_desc=刪除該郵箱地址將會移除所有相關的信息。是否繼續?
email_deletion_success=成功刪除郵箱!
email_deletion_primary=Cannot delete primary email address.
add_new_email=添加新的電子郵件地址
add_email=添加電子郵件
add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。
@ -372,7 +370,6 @@ two_factor_disable_success=Two-factor authentication has disabled successfully!
manage_access_token=管理個人操作令牌
generate_new_token=生成新的令牌
tokens_desc=您所產生的token將被用來存取Gogs APIs
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=目前為止,任何令牌都對您的帳戶擁有完整的操作權限。
token_name=令牌名稱
generate_token=生成令牌
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository configuration
config.repo.root_path=Root path

View File

@ -88,7 +88,6 @@ log_root_path=日誌路徑
log_root_path_helper=寫入日誌檔目錄
enable_console_mode=開啟主控台模式
enable_console_mode_popup=除了使用檔案模式之外, 還要將日誌列印到控制台。
default_branch=Default Branch
optional_title=可選設置
email_title=電子郵件服務設定
@ -317,7 +316,6 @@ delete_email=刪除
email_deletion=刪除郵箱
email_deletion_desc=刪除該郵箱地址將會移除所有相關的信息。是否繼續?
email_deletion_success=成功刪除郵箱!
email_deletion_primary=Cannot delete primary email address.
add_new_email=添加新的電子郵件地址
add_email=添加電子郵件
add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。
@ -372,7 +370,6 @@ two_factor_disable_success=您帳戶的兩步驗證已成功停用!
manage_access_token=管理個人操作令牌
generate_new_token=生成新的令牌
tokens_desc=您產生的令牌可以用來存取 Gogs API。
access_token_tips=The personal access token may be used as either username or password. It is recommended to use the "x-access-token" as the username and the personal access token as the password for Git applications.
new_token_desc=目前為止,任何令牌都對您的帳戶擁有完整的操作權限。
token_name=令牌名稱
generate_token=生成令牌
@ -1210,7 +1207,6 @@ config.ssh.listen_host=Listen host
config.ssh.listen_port=Listen port
config.ssh.server_ciphers=Server ciphers
config.ssh.server_macs=Server MACs
config.ssh.server_algorithms=Server algorithms
config.repo_config=Repository 設定
config.repo.root_path=根路徑

View File

@ -55,22 +55,6 @@ Indexes:
"idx_action_user_id" (user_id)
```
# Table "email_address"
```
FIELD | COLUMN | POSTGRESQL | MYSQL | SQLITE3
--------------+--------------+--------------------------------+--------------------------------+---------------------------------
ID | id | BIGSERIAL | BIGINT AUTO_INCREMENT | INTEGER
UserID | uid | BIGINT NOT NULL | BIGINT NOT NULL | INTEGER NOT NULL
Email | email | VARCHAR(254) NOT NULL | VARCHAR(254) NOT NULL | TEXT NOT NULL
IsActivated | is_activated | BOOLEAN NOT NULL DEFAULT FALSE | BOOLEAN NOT NULL DEFAULT FALSE | NUMERIC NOT NULL DEFAULT FALSE
Primary keys: id
Indexes:
"email_address_user_email_unique" UNIQUE (uid, email)
"idx_email_address_user_id" (uid)
```
# Table "follow"
```
@ -116,16 +100,3 @@ Primary keys: repo_id, oid
Primary keys: id
```
# Table "notice"
```
FIELD | COLUMN | POSTGRESQL | MYSQL | SQLITE3
--------------+--------------+------------+-----------------------+----------
ID | id | BIGSERIAL | BIGINT AUTO_INCREMENT | INTEGER
Type | type | BIGINT | BIGINT | INTEGER
Description | description | TEXT | TEXT | TEXT
CreatedUnix | created_unix | BIGINT | BIGINT | INTEGER
Primary keys: id
```

View File

@ -1,7 +1,6 @@
# Import locales from Crowdin
1. Upload the latest version of [`locale_en-US.ini`](https://github.com/gogs/gogs/blob/main/conf/locale/locale_en-US.ini) to the [Crowdin](https://crowdin.gogs.io/project/gogs/sources/files).
1. [Build and download](https://crowdin.gogs.io/project/gogs/translations) the ZIP archive and unzip it.
1. Download the ZIP archive from [Crowdin](https://crowdin.gogs.io/) and unzip it.
1. Go to root directory of the repository.
1. Run the `import` subcommand:

View File

@ -21,7 +21,7 @@ Gogs is built and runs as a single binary and meant to be cross platform. Theref
Gogs has the following dependencies:
- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) (v1.8.3 or higher)
- [Go](https://golang.org/doc/install) (v1.20 or higher)
- [Go](https://golang.org/doc/install) (v1.18 or higher)
- [Less.js](http://lesscss.org/usage/#command-line-usage-installing)
- [Task](https://github.com/go-task/task) (v3)
- [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports)

View File

@ -0,0 +1,80 @@
# Release a new version
- To release a new minor version, use the GitHub issue template [Dev: Release a minor version](https://github.com/gogs/gogs/issues/new?title=Release+<MAJOR>.<MINOR>.0&labels=%F0%9F%93%B8%20release&template=dev_release_minor_version.md).
- To release a new patch version, use the GitHub issue template [Dev: Release a patch version](https://github.com/gogs/gogs/issues/new?title=Release+<MAJOR>.<MINOR>.<PATCH>&labels=%F0%9F%93%B8%20release&template=dev_release_patch_version.md).
## Playbooks
### Update Docker image tag
1. Pull down images and create a manifest:
```sh
$ export VERSION=0.12.4
$ export MINOR_RELEASE=0.12
$ docker pull --platform linux/amd64 gogs/gogs:${VERSION}
$ docker tag gogs/gogs:${VERSION} gogs/gogs:${MINOR_RELEASE}-amd64
$ docker push gogs/gogs:${MINOR_RELEASE}-amd64
$ docker pull --platform linux/arm64 gogs/gogs:${VERSION}
$ docker tag gogs/gogs:${VERSION} gogs/gogs:${MINOR_RELEASE}-arm64
$ docker push gogs/gogs:${MINOR_RELEASE}-arm64
$ docker pull --platform linux/arm/v7 gogs/gogs:${VERSION}
$ docker tag gogs/gogs:${VERSION} gogs/gogs:${MINOR_RELEASE}-armv7
$ docker push gogs/gogs:${MINOR_RELEASE}-armv7
$ docker manifest rm gogs/gogs:${MINOR_RELEASE}
$ docker manifest create \
gogs/gogs:${MINOR_RELEASE} \
gogs/gogs:${MINOR_RELEASE}-amd64 \
gogs/gogs:${MINOR_RELEASE}-arm64 \
gogs/gogs:${MINOR_RELEASE}-armv7
$ docker manifest push gogs/gogs:${MINOR_RELEASE}
# Only push "linux/amd64" for now
$ echo ${GITHUB_CR_PAT} | docker login ghcr.io -u <USERNAME> --password-stdin
$ docker tag gogs/gogs:${MINOR_RELEASE}-amd64 ghcr.io/gogs/gogs:${MINOR_RELEASE}
$ docker push ghcr.io/gogs/gogs:${MINOR_RELEASE}
```
2. Delete ephemeral tags from the [Docker Hub](https://hub.docker.com/repository/docker/gogs/gogs/tags).
### Compile and pack binaries
All commands are starting at the repository root.
- macOS:
```sh
# Produce the ZIP archive
$ TAGS=cert task release
```
- Linux:
```sh
# Produce the ZIP archive
$ TAGS="cert pam" task release
# Produce the Tarball
$ export VERSION=0.12.4
$ cd release && tar czf gogs_${VERSION}_linux_$(go env GOARCH).tar.gz gogs
```
- ARMv7:
```sh
# Produce the ZIP archive
$ TAGS="cert pam" task release
# Produce the Tarball
$ export VERSION=0.12.4
$ cd release && tar czf gogs_${VERSION}_linux_armv7.tar.gz gogs
```
- ARMv8:
```sh
# Produce the ZIP archive
$ TAGS="cert pam" task release
# Produce the Tarball
$ export VERSION=0.12.4
$ cd release && tar czf gogs_${VERSION}_linux_armv8.tar.gz gogs
```
- Windows:
```sh
$ TAGS=cert task release
$ TAGS="cert minwinsvc" task release --force
```

View File

@ -0,0 +1,9 @@
#!/bin/sh
cd gogs || exit # "gogs" is the directory that stores all release archives
for file in *
do
if [ -f "$file" ]; then
shasum -a 256 "$file" >> checksum_sha256.txt
fi
done

98
go.mod
View File

@ -1,19 +1,19 @@
module gogs.io/gogs
go 1.23.4
go 1.18
require (
github.com/Masterminds/semver/v3 v3.3.1
github.com/Masterminds/semver/v3 v3.2.0
github.com/derision-test/go-mockgen v1.3.7
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
github.com/go-ldap/ldap/v3 v3.4.10
github.com/editorconfig/editorconfig-core-go/v2 v2.5.1
github.com/go-ldap/ldap/v3 v3.4.4
github.com/go-macaron/binding v1.2.0
github.com/go-macaron/cache v0.0.0-20190810181446-10f7c57e2196
github.com/go-macaron/captcha v0.2.0
github.com/go-macaron/csrf v0.0.0-20190812063352-946f6d303a4c
github.com/go-macaron/gzip v0.0.0-20160222043647-cad1c6580a07
github.com/go-macaron/i18n v0.6.0
github.com/go-macaron/session v1.0.3
github.com/go-macaron/session v0.0.0-20190805070824-1a3cdc6f5659
github.com/go-macaron/toolbox v0.0.0-20190813233741-94defb8383c6
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
@ -25,14 +25,14 @@ require (
github.com/issue9/identicon v1.2.1
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43
github.com/json-iterator/go v1.1.12
github.com/microcosm-cc/bluemonday v1.0.27
github.com/msteinert/pam v1.2.0
github.com/microcosm-cc/bluemonday v1.0.22
github.com/msteinert/pam v0.0.0-20190215180659-f29b9f28d6f9
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/niklasfasching/go-org v1.7.0
github.com/niklasfasching/go-org v1.6.5
github.com/olekukonko/tablewriter v0.0.5
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0
github.com/prometheus/client_golang v1.21.0
github.com/prometheus/client_golang v1.14.0
github.com/russross/blackfriday v1.6.0
github.com/satori/go.uuid v1.2.0
github.com/sergi/go-diff v1.3.1
@ -43,19 +43,19 @@ require (
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e
github.com/urfave/cli v1.22.16
golang.org/x/crypto v0.35.0
golang.org/x/net v0.36.0
golang.org/x/text v0.22.0
golang.org/x/crypto v0.31.0
golang.org/x/net v0.33.0
golang.org/x/text v0.21.0
gopkg.in/DATA-DOG/go-sqlmock.v2 v2.0.0-20180914054222-c19298f520d0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
gopkg.in/macaron.v1 v1.5.0
gorm.io/driver/mysql v1.5.2
gorm.io/driver/postgres v1.5.11
gopkg.in/macaron.v1 v1.4.0
gorm.io/driver/mysql v1.4.7
gorm.io/driver/postgres v1.4.8
gorm.io/driver/sqlite v1.4.2
gorm.io/driver/sqlserver v1.4.1
gorm.io/gorm v1.25.12
modernc.org/sqlite v1.36.0
gorm.io/gorm v1.24.5
modernc.org/sqlite v1.20.4
unknwon.dev/clog/v2 v2.2.0
xorm.io/builder v0.3.6
xorm.io/core v0.7.2
@ -64,56 +64,58 @@ require (
require (
bitbucket.org/creachadair/shell v0.0.7 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisenkom/go-mssqldb v0.12.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/djherbis/buffer v1.2.0 // indirect
github.com/djherbis/nio/v3 v3.0.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-macaron/inject v0.0.0-20200308113650-138e5925c53b // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/itchyny/gojq v0.12.11 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jackc/pgx/v5 v5.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.8.6 // indirect
github.com/klauspost/cpuid v1.2.1 // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 // indirect
github.com/microsoft/go-mssqldb v0.17.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
@ -121,19 +123,25 @@ require (
go.bobheadxi.dev/streamline v1.2.1 // indirect
go.opentelemetry.io/otel v1.11.0 // indirect
go.opentelemetry.io/otel/trace v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
google.golang.org/protobuf v1.36.1 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
gopkg.in/redis.v2 v2.3.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.61.13 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.8.2 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.22.2 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.4.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
)
// +heroku goVersion go1.23
// +heroku goVersion go1.18
// +heroku install ./

624
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ import (
)
func init() {
conf.App.Version = "0.14.0+dev"
conf.App.Version = "0.13.2"
}
func main() {

View File

@ -23,8 +23,6 @@ const (
PAM // 4
DLDAP // 5
GitHub // 6
Mock Type = 999
)
// Name returns the human-readable name for given authentication type.
@ -47,7 +45,8 @@ type ErrBadCredentials struct {
// IsErrBadCredentials returns true if the underlying error has the type
// ErrBadCredentials.
func IsErrBadCredentials(err error) bool {
return errors.As(err, &ErrBadCredentials{})
_, ok := errors.Cause(err).(ErrBadCredentials)
return ok
}
func (err ErrBadCredentials) Error() string {

View File

@ -14,7 +14,7 @@ import (
"github.com/urfave/cli"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
var (
@ -52,7 +52,7 @@ to make automatic initialization process more smoothly`,
Name: "delete-inactive-users",
Usage: "Delete all inactive accounts",
Action: adminDashboardOperation(
func() error { return database.Handle.Users().DeleteInactivated() },
func() error { return db.Users.DeleteInactivated() },
"All inactivated accounts have been deleted successfully",
),
Flags: []cli.Flag{
@ -64,7 +64,7 @@ to make automatic initialization process more smoothly`,
Name: "delete-repository-archives",
Usage: "Delete all repositories archives",
Action: adminDashboardOperation(
database.DeleteRepositoryArchives,
db.DeleteRepositoryArchives,
"All repositories archives have been deleted successfully",
),
Flags: []cli.Flag{
@ -76,7 +76,7 @@ to make automatic initialization process more smoothly`,
Name: "delete-missing-repositories",
Usage: "Delete all repository records that lost Git files",
Action: adminDashboardOperation(
database.DeleteMissingRepositories,
db.DeleteMissingRepositories,
"All repositories archives have been deleted successfully",
),
Flags: []cli.Flag{
@ -88,7 +88,7 @@ to make automatic initialization process more smoothly`,
Name: "collect-garbage",
Usage: "Do garbage collection on repositories",
Action: adminDashboardOperation(
database.GitGcRepos,
db.GitGcRepos,
"All repositories have done garbage collection successfully",
),
Flags: []cli.Flag{
@ -100,7 +100,7 @@ to make automatic initialization process more smoothly`,
Name: "rewrite-authorized-keys",
Usage: "Rewrite '.ssh/authorized_keys' file (caution: non-Gogs keys will be lost)",
Action: adminDashboardOperation(
database.RewriteAuthorizedKeys,
db.RewriteAuthorizedKeys,
"All public keys have been rewritten successfully",
),
Flags: []cli.Flag{
@ -112,7 +112,7 @@ to make automatic initialization process more smoothly`,
Name: "resync-hooks",
Usage: "Resync pre-receive, update and post-receive hooks",
Action: adminDashboardOperation(
database.SyncRepositoryHooks,
db.SyncRepositoryHooks,
"All repositories' pre-receive, update and post-receive hooks have been resynced successfully",
),
Flags: []cli.Flag{
@ -124,7 +124,7 @@ to make automatic initialization process more smoothly`,
Name: "reinit-missing-repositories",
Usage: "Reinitialize all repository records that lost Git files",
Action: adminDashboardOperation(
database.ReinitMissingRepositories,
db.ReinitMissingRepositories,
"All repository records that lost Git files have been reinitialized successfully",
),
Flags: []cli.Flag{
@ -148,15 +148,15 @@ func runCreateUser(c *cli.Context) error {
}
conf.InitLogging(true)
if _, err = database.SetEngine(); err != nil {
if _, err = db.SetEngine(); err != nil {
return errors.Wrap(err, "set engine")
}
user, err := database.Handle.Users().Create(
user, err := db.Users.Create(
context.Background(),
c.String("name"),
c.String("email"),
database.CreateUserOptions{
db.CreateUserOptions{
Password: c.String("password"),
Activated: true,
Admin: c.Bool("admin"),
@ -178,7 +178,7 @@ func adminDashboardOperation(operation func() error, successMessage string) func
}
conf.InitLogging(true)
if _, err = database.SetEngine(); err != nil {
if _, err = db.SetEngine(); err != nil {
return errors.Wrap(err, "set engine")
}

View File

@ -20,7 +20,7 @@ import (
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/osutil"
)
@ -57,7 +57,7 @@ func runBackup(c *cli.Context) error {
}
conf.InitLogging(true)
conn, err := database.SetEngine()
conn, err := db.SetEngine()
if err != nil {
return errors.Wrap(err, "set engine")
}
@ -95,7 +95,7 @@ func runBackup(c *cli.Context) error {
// Database
dbDir := filepath.Join(rootDir, "db")
if err = database.DumpDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
if err = db.DumpDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
log.Fatal("Failed to dump database: %v", err)
}
if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
@ -127,7 +127,7 @@ func runBackup(c *cli.Context) error {
reposDump := filepath.Join(rootDir, "repositories.zip")
log.Info("Dumping repositories in %q", conf.Repository.Root)
if c.Bool("exclude-mirror-repos") {
repos, err := database.GetNonMirrorRepositories()
repos, err := db.GetNonMirrorRepositories()
if err != nil {
log.Fatal("Failed to get non-mirror repositories: %v", err)
}

View File

@ -1,3 +1,5 @@
//go:build cert
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
@ -145,28 +147,17 @@ func runCert(ctx *cli.Context) error {
if err != nil {
log.Fatalf("Failed to open cert.pem for writing: %s", err)
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
log.Fatalf("Failed to encode data to cert.pem: %s", err)
}
err = certOut.Close()
if err != nil {
log.Fatalf("Failed to close writing to cert.pem: %s", err)
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
log.Println("Written cert.pem")
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("Failed to open key.pem for writing: %v\n", err)
}
err = pem.Encode(keyOut, pemBlockForKey(priv))
if err != nil {
log.Fatalf("Failed to encode data to key.pem: %s", err)
}
err = keyOut.Close()
if err != nil {
log.Fatalf("Failed to close writing to key.pem: %s", err)
}
pem.Encode(keyOut, pemBlockForKey(priv))
keyOut.Close()
log.Println("Written key.pem")
return nil
}

29
internal/cmd/cert_stub.go Normal file
View File

@ -0,0 +1,29 @@
//go:build !cert
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"fmt"
"os"
"github.com/urfave/cli"
)
var Cert = cli.Command{
Name: "cert",
Usage: "Generate self-signed certificate",
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
Action: runCert,
}
func runCert(_ *cli.Context) error {
fmt.Println("Command cert not available, please use build tags 'cert' to rebuild.")
os.Exit(1)
return nil
}

View File

@ -22,7 +22,7 @@ import (
"github.com/gogs/git-module"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/email"
"gogs.io/gogs/internal/httplib"
)
@ -68,7 +68,7 @@ func runHookPreReceive(c *cli.Context) error {
}
setup(c, "pre-receive.log", true)
isWiki := strings.Contains(os.Getenv(database.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
isWiki := strings.Contains(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin)
@ -89,10 +89,10 @@ func runHookPreReceive(c *cli.Context) error {
branchName := git.RefShortName(string(fields[2]))
// Branch protection
repoID := com.StrTo(os.Getenv(database.ENV_REPO_ID)).MustInt64()
protectBranch, err := database.GetProtectBranchOfRepoByName(repoID, branchName)
repoID := com.StrTo(os.Getenv(db.ENV_REPO_ID)).MustInt64()
protectBranch, err := db.GetProtectBranchOfRepoByName(repoID, branchName)
if err != nil {
if database.IsErrBranchNotExist(err) {
if db.IsErrBranchNotExist(err) {
continue
}
fail("Internal error", "GetProtectBranchOfRepoByName [repo_id: %d, branch: %s]: %v", repoID, branchName, err)
@ -105,9 +105,9 @@ func runHookPreReceive(c *cli.Context) error {
bypassRequirePullRequest := false
// Check if user is in whitelist when enabled
userID := com.StrTo(os.Getenv(database.ENV_AUTH_USER_ID)).MustInt64()
userID := com.StrTo(os.Getenv(db.ENV_AUTH_USER_ID)).MustInt64()
if protectBranch.EnableWhitelist {
if !database.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
if !db.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "")
}
@ -126,7 +126,7 @@ func runHookPreReceive(c *cli.Context) error {
// Check force push
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).
RunInDir(database.RepoPath(os.Getenv(database.ENV_REPO_OWNER_NAME), os.Getenv(database.ENV_REPO_NAME)))
RunInDir(db.RepoPath(os.Getenv(db.ENV_REPO_OWNER_NAME), os.Getenv(db.ENV_REPO_NAME)))
if err != nil {
fail("Internal error", "Failed to detect force push: %v", err)
} else if len(output) > 0 {
@ -134,7 +134,7 @@ func runHookPreReceive(c *cli.Context) error {
}
}
customHooksPath := filepath.Join(os.Getenv(database.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive")
customHooksPath := filepath.Join(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), "pre-receive")
if !com.IsFile(customHooksPath) {
return nil
}
@ -145,7 +145,7 @@ func runHookPreReceive(c *cli.Context) error {
} else {
hookCmd = exec.Command(customHooksPath)
}
hookCmd.Dir = database.RepoPath(os.Getenv(database.ENV_REPO_OWNER_NAME), os.Getenv(database.ENV_REPO_NAME))
hookCmd.Dir = db.RepoPath(os.Getenv(db.ENV_REPO_OWNER_NAME), os.Getenv(db.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr
@ -168,7 +168,7 @@ func runHookUpdate(c *cli.Context) error {
fail("First argument 'refName' is empty", "First argument 'refName' is empty")
}
customHooksPath := filepath.Join(os.Getenv(database.ENV_REPO_CUSTOM_HOOKS_PATH), "update")
customHooksPath := filepath.Join(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), "update")
if !com.IsFile(customHooksPath) {
return nil
}
@ -179,7 +179,7 @@ func runHookUpdate(c *cli.Context) error {
} else {
hookCmd = exec.Command(customHooksPath, args...)
}
hookCmd.Dir = database.RepoPath(os.Getenv(database.ENV_REPO_OWNER_NAME), os.Getenv(database.ENV_REPO_NAME))
hookCmd.Dir = db.RepoPath(os.Getenv(db.ENV_REPO_OWNER_NAME), os.Getenv(db.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = os.Stdin
hookCmd.Stderr = os.Stderr
@ -199,7 +199,7 @@ func runHookPostReceive(c *cli.Context) error {
// so we need to setup additional services for email notifications.
email.NewContext()
isWiki := strings.Contains(os.Getenv(database.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
isWiki := strings.Contains(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin)
@ -217,24 +217,24 @@ func runHookPostReceive(c *cli.Context) error {
continue
}
options := database.PushUpdateOptions{
options := db.PushUpdateOptions{
OldCommitID: string(fields[0]),
NewCommitID: string(fields[1]),
FullRefspec: string(fields[2]),
PusherID: com.StrTo(os.Getenv(database.ENV_AUTH_USER_ID)).MustInt64(),
PusherName: os.Getenv(database.ENV_AUTH_USER_NAME),
RepoUserName: os.Getenv(database.ENV_REPO_OWNER_NAME),
RepoName: os.Getenv(database.ENV_REPO_NAME),
PusherID: com.StrTo(os.Getenv(db.ENV_AUTH_USER_ID)).MustInt64(),
PusherName: os.Getenv(db.ENV_AUTH_USER_NAME),
RepoUserName: os.Getenv(db.ENV_REPO_OWNER_NAME),
RepoName: os.Getenv(db.ENV_REPO_NAME),
}
if err := database.PushUpdate(options); err != nil {
if err := db.PushUpdate(options); err != nil {
log.Error("PushUpdate: %v", err)
}
// Ask for running deliver hook and test pull request tasks
q := make(url.Values)
q.Add("branch", git.RefShortName(options.FullRefspec))
q.Add("secret", os.Getenv(database.ENV_REPO_OWNER_SALT_MD5))
q.Add("pusher", os.Getenv(database.ENV_AUTH_USER_ID))
q.Add("secret", os.Getenv(db.ENV_REPO_OWNER_SALT_MD5))
q.Add("pusher", os.Getenv(db.ENV_AUTH_USER_ID))
reqURL := fmt.Sprintf("%s%s/%s/tasks/trigger?%s", conf.Server.LocalRootURL, options.RepoUserName, options.RepoName, q.Encode())
log.Trace("Trigger task: %s", reqURL)
@ -252,7 +252,7 @@ func runHookPostReceive(c *cli.Context) error {
}
}
customHooksPath := filepath.Join(os.Getenv(database.ENV_REPO_CUSTOM_HOOKS_PATH), "post-receive")
customHooksPath := filepath.Join(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), "post-receive")
if !com.IsFile(customHooksPath) {
return nil
}
@ -263,7 +263,7 @@ func runHookPostReceive(c *cli.Context) error {
} else {
hookCmd = exec.Command(customHooksPath)
}
hookCmd.Dir = database.RepoPath(os.Getenv(database.ENV_REPO_OWNER_NAME), os.Getenv(database.ENV_REPO_NAME))
hookCmd.Dir = db.RepoPath(os.Getenv(db.ENV_REPO_OWNER_NAME), os.Getenv(db.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr

View File

@ -83,7 +83,9 @@ func runImportLocale(c *cli.Context) error {
tw, err := os.Create(target)
if err != nil {
return fmt.Errorf("Create: %v", err)
if err != nil {
return fmt.Errorf("Open: %v", err)
}
}
scanner := bufio.NewScanner(sr)

View File

@ -17,7 +17,7 @@ import (
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/osutil"
"gogs.io/gogs/internal/semverutil"
)
@ -108,14 +108,14 @@ func runRestore(c *cli.Context) error {
}
conf.InitLogging(true)
conn, err := database.SetEngine()
conn, err := db.SetEngine()
if err != nil {
return errors.Wrap(err, "set engine")
}
// Database
dbDir := path.Join(archivePath, "db")
if err = database.ImportDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
if err = db.ImportDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
log.Fatal("Failed to import database: %v", err)
}

View File

@ -18,7 +18,7 @@ import (
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
const (
@ -95,7 +95,7 @@ func setup(c *cli.Context, logFile string, connectDB bool) {
_ = os.Chdir(conf.WorkDir())
}
if _, err := database.SetEngine(); err != nil {
if _, err := db.SetEngine(); err != nil {
fail("Internal error", "Failed to set database engine: %v", err)
}
}
@ -108,28 +108,28 @@ func parseSSHCmd(cmd string) (string, string) {
return ss[0], strings.Replace(ss[1], "'/", "'", 1)
}
func checkDeployKey(key *database.PublicKey, repo *database.Repository) {
func checkDeployKey(key *db.PublicKey, repo *db.Repository) {
// Check if this deploy key belongs to current repository.
if !database.HasDeployKey(key.ID, repo.ID) {
if !db.HasDeployKey(key.ID, repo.ID) {
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
}
// Update deploy key activity.
deployKey, err := database.GetDeployKeyByRepo(key.ID, repo.ID)
deployKey, err := db.GetDeployKeyByRepo(key.ID, repo.ID)
if err != nil {
fail("Internal error", "GetDeployKey: %v", err)
}
deployKey.Updated = time.Now()
if err = database.UpdateDeployKey(deployKey); err != nil {
if err = db.UpdateDeployKey(deployKey); err != nil {
fail("Internal error", "UpdateDeployKey: %v", err)
}
}
var allowedCommands = map[string]database.AccessMode{
"git-upload-pack": database.AccessModeRead,
"git-upload-archive": database.AccessModeRead,
"git-receive-pack": database.AccessModeWrite,
var allowedCommands = map[string]db.AccessMode{
"git-upload-pack": db.AccessModeRead,
"git-upload-archive": db.AccessModeRead,
"git-receive-pack": db.AccessModeWrite,
}
func runServ(c *cli.Context) error {
@ -162,17 +162,17 @@ func runServ(c *cli.Context) error {
repoName := strings.TrimSuffix(strings.ToLower(repoFields[1]), ".git")
repoName = strings.TrimSuffix(repoName, ".wiki")
owner, err := database.Handle.Users().GetByUsername(ctx, ownerName)
owner, err := db.Users.GetByUsername(ctx, ownerName)
if err != nil {
if database.IsErrUserNotExist(err) {
if db.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", ownerName)
}
fail("Internal error", "Failed to get repository owner '%s': %v", ownerName, err)
}
repo, err := database.GetRepositoryByName(owner.ID, repoName)
repo, err := db.GetRepositoryByName(owner.ID, repoName)
if err != nil {
if database.IsErrRepoNotExist(err) {
if db.IsErrRepoNotExist(err) {
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", owner.Name, repoName)
}
fail("Internal error", "Failed to get repository: %v", err)
@ -185,19 +185,19 @@ func runServ(c *cli.Context) error {
}
// Prohibit push to mirror repositories.
if requestMode > database.AccessModeRead && repo.IsMirror {
if requestMode > db.AccessModeRead && repo.IsMirror {
fail("Mirror repository is read-only", "")
}
// Allow anonymous (user is nil) clone for public repositories.
var user *database.User
var user *db.User
key, err := database.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64())
key, err := db.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64())
if err != nil {
fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err)
}
if requestMode == database.AccessModeWrite || repo.IsPrivate {
if requestMode == db.AccessModeWrite || repo.IsPrivate {
// Check deploy key or user key.
if key.IsDeployKey() {
if key.Mode < requestMode {
@ -205,20 +205,20 @@ func runServ(c *cli.Context) error {
}
checkDeployKey(key, repo)
} else {
user, err = database.Handle.Users().GetByKeyID(ctx, key.ID)
user, err = db.Users.GetByKeyID(ctx, key.ID)
if err != nil {
fail("Internal error", "Failed to get user by key ID '%d': %v", key.ID, err)
}
mode := database.Handle.Permissions().AccessMode(ctx, user.ID, repo.ID,
database.AccessModeOptions{
mode := db.Perms.AccessMode(ctx, user.ID, repo.ID,
db.AccessModeOptions{
OwnerID: repo.OwnerID,
Private: repo.IsPrivate,
},
)
if mode < requestMode {
clientMessage := _ACCESS_DENIED_MESSAGE
if mode >= database.AccessModeRead {
if mode >= db.AccessModeRead {
clientMessage = "You do not have sufficient authorization for this action"
}
fail(clientMessage,
@ -238,13 +238,13 @@ func runServ(c *cli.Context) error {
// Update user key activity.
if key.ID > 0 {
key, err := database.GetPublicKeyByID(key.ID)
key, err := db.GetPublicKeyByID(key.ID)
if err != nil {
fail("Internal error", "GetPublicKeyByID: %v", err)
}
key.Updated = time.Now()
if err = database.UpdatePublicKey(key); err != nil {
if err = db.UpdatePublicKey(key); err != nil {
fail("Internal error", "UpdatePublicKey: %v", err)
}
}
@ -261,8 +261,8 @@ func runServ(c *cli.Context) error {
} else {
gitCmd = exec.Command(verb, repoFullName)
}
if requestMode == database.AccessModeWrite {
gitCmd.Env = append(os.Environ(), database.ComposeHookEnvs(database.ComposeHookEnvsOptions{
if requestMode == db.AccessModeWrite {
gitCmd.Env = append(os.Environ(), db.ComposeHookEnvs(db.ComposeHookEnvsOptions{
AuthUser: user,
OwnerName: owner.Name,
OwnerSalt: owner.Salt,

View File

@ -33,7 +33,7 @@ import (
"gogs.io/gogs/internal/app"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/context"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/form"
"gogs.io/gogs/internal/osutil"
"gogs.io/gogs/internal/route"
@ -107,20 +107,19 @@ func newMacaron() *macaron.Macaron {
conf.Picture.RepositoryAvatarUploadPath,
macaron.StaticOptions{
ETag: true,
Prefix: database.REPO_AVATAR_URL_PREFIX,
Prefix: db.REPO_AVATAR_URL_PREFIX,
SkipLogging: conf.Server.DisableRouterLog,
},
))
customDir := filepath.Join(conf.CustomDir(), "templates")
renderOpt := macaron.RenderOptions{
Directory: filepath.Join(conf.WorkDir(), "templates"),
AppendDirectories: []string{customDir},
AppendDirectories: []string{filepath.Join(conf.CustomDir(), "templates")},
Funcs: template.FuncMap(),
IndentJSON: macaron.Env != macaron.PROD,
}
if !conf.Server.LoadAssetsFromDisk {
renderOpt.TemplateFileSystem = templates.NewTemplateFileSystem("", customDir)
renderOpt.TemplateFileSystem = templates.NewTemplateFileSystem("", renderOpt.AppendDirectories[0])
}
m.Use(macaron.Renderer(renderOpt))
@ -156,7 +155,7 @@ func newMacaron() *macaron.Macaron {
HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{
{
Desc: "Database connection",
Func: database.Ping,
Func: db.Ping,
},
},
}))
@ -238,11 +237,9 @@ func runWeb(c *cli.Context) error {
m.Get("", user.SettingsOrganizations)
m.Post("/leave", user.SettingsLeaveOrganization)
})
settingsHandler := user.NewSettingsHandler(user.NewSettingsStore())
m.Combo("/applications").Get(settingsHandler.Applications()).
Post(bindIgnErr(form.NewAccessToken{}), settingsHandler.ApplicationsPost())
m.Post("/applications/delete", settingsHandler.DeleteApplication())
m.Combo("/applications").Get(user.SettingsApplications).
Post(bindIgnErr(form.NewAccessToken{}), user.SettingsApplicationsPost)
m.Post("/applications/delete", user.SettingsDeleteApplication)
m.Route("/delete", "GET,POST", user.SettingsDelete)
}, reqSignIn, func(c *context.Context) {
c.Data["PageIsUserSettings"] = true
@ -308,7 +305,7 @@ func runWeb(c *cli.Context) error {
}, context.InjectParamsUser())
m.Get("/attachments/:uuid", func(c *context.Context) {
attach, err := database.GetAttachmentByUUID(c.Params(":uuid"))
attach, err := db.GetAttachmentByUUID(c.Params(":uuid"))
if err != nil {
c.NotFoundOrError(err, "get attachment by UUID")
return
@ -655,7 +652,7 @@ func runWeb(c *cli.Context) error {
SetCookie: true,
Secure: conf.Server.URL.Scheme == "https",
}),
context.Contexter(context.NewStore()),
context.Contexter(),
)
// ***************************
@ -669,7 +666,7 @@ func runWeb(c *cli.Context) error {
lfs.RegisterRoutes(m.Router)
})
m.Route("/*", "GET,POST,OPTIONS", context.ServeGoGet(), repo.HTTPContexter(repo.NewStore()), repo.HTTP)
m.Route("/*", "GET,POST,OPTIONS", context.ServeGoGet(), repo.HTTPContexter(), repo.HTTP)
})
// ***************************

View File

@ -5,10 +5,10 @@
package context
import (
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
type APIOrganization struct {
Organization *database.User
Team *database.Team
Organization *db.User
Team *db.Team
}

View File

@ -19,7 +19,7 @@ import (
"gogs.io/gogs/internal/auth"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/tool"
)
@ -106,45 +106,10 @@ func isAPIPath(url string) bool {
return strings.HasPrefix(url, "/api/")
}
type AuthStore interface {
// GetAccessTokenBySHA1 returns the access token with given SHA1. It returns
// database.ErrAccessTokenNotExist when not found.
GetAccessTokenBySHA1(ctx context.Context, sha1 string) (*database.AccessToken, error)
// TouchAccessTokenByID updates the updated time of the given access token to
// the current time.
TouchAccessTokenByID(ctx context.Context, id int64) error
// GetUserByID returns the user with given ID. It returns
// database.ErrUserNotExist when not found.
GetUserByID(ctx context.Context, id int64) (*database.User, error)
// GetUserByUsername returns the user with given username. It returns
// database.ErrUserNotExist when not found.
GetUserByUsername(ctx context.Context, username string) (*database.User, error)
// CreateUser creates a new user and persists to database. It returns
// database.ErrNameNotAllowed if the given name or pattern of the name is not
// allowed as a username, or database.ErrUserAlreadyExist when a user with same
// name already exists, or database.ErrEmailAlreadyUsed if the email has been
// verified by another user.
CreateUser(ctx context.Context, username, email string, opts database.CreateUserOptions) (*database.User, error)
// AuthenticateUser validates username and password via given login source ID.
// It returns database.ErrUserNotExist when the user was not found.
//
// When the "loginSourceID" is negative, it aborts the process and returns
// database.ErrUserNotExist if the user was not found in the database.
//
// When the "loginSourceID" is non-negative, it returns
// database.ErrLoginSourceMismatch if the user has different login source ID
// than the "loginSourceID".
//
// When the "loginSourceID" is positive, it tries to authenticate via given
// login source and creates a new user when not yet exists in the database.
AuthenticateUser(ctx context.Context, login, password string, loginSourceID int64) (*database.User, error)
}
// authenticatedUserID returns the ID of the authenticated user, along with a bool value
// which indicates whether the user uses token authentication.
func authenticatedUserID(store AuthStore, c *macaron.Context, sess session.Store) (_ int64, isTokenAuth bool) {
if !database.HasEngine {
func authenticatedUserID(c *macaron.Context, sess session.Store) (_ int64, isTokenAuth bool) {
if !db.HasEngine {
return 0, false
}
@ -167,14 +132,14 @@ func authenticatedUserID(store AuthStore, c *macaron.Context, sess session.Store
// Let's see if token is valid.
if len(tokenSHA) > 0 {
t, err := store.GetAccessTokenBySHA1(c.Req.Context(), tokenSHA)
t, err := db.AccessTokens.GetBySHA1(c.Req.Context(), tokenSHA)
if err != nil {
if !database.IsErrAccessTokenNotExist(err) {
if !db.IsErrAccessTokenNotExist(err) {
log.Error("GetAccessTokenBySHA: %v", err)
}
return 0, false
}
if err = store.TouchAccessTokenByID(c.Req.Context(), t.ID); err != nil {
if err = db.AccessTokens.Touch(c.Req.Context(), t.ID); err != nil {
log.Error("Failed to touch access token: %v", err)
}
return t.UserID, true
@ -186,9 +151,9 @@ func authenticatedUserID(store AuthStore, c *macaron.Context, sess session.Store
return 0, false
}
if id, ok := uid.(int64); ok {
_, err := store.GetUserByID(c.Req.Context(), id)
_, err := db.Users.GetByID(c.Req.Context(), id)
if err != nil {
if !database.IsErrUserNotExist(err) {
if !db.IsErrUserNotExist(err) {
log.Error("Failed to get user by ID: %v", err)
}
return 0, false
@ -200,31 +165,31 @@ func authenticatedUserID(store AuthStore, c *macaron.Context, sess session.Store
// authenticatedUser returns the user object of the authenticated user, along with two bool values
// which indicate whether the user uses HTTP Basic Authentication or token authentication respectively.
func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store) (_ *database.User, isBasicAuth, isTokenAuth bool) {
if !database.HasEngine {
func authenticatedUser(ctx *macaron.Context, sess session.Store) (_ *db.User, isBasicAuth, isTokenAuth bool) {
if !db.HasEngine {
return nil, false, false
}
uid, isTokenAuth := authenticatedUserID(store, ctx, sess)
uid, isTokenAuth := authenticatedUserID(ctx, sess)
if uid <= 0 {
if conf.Auth.EnableReverseProxyAuthentication {
webAuthUser := ctx.Req.Header.Get(conf.Auth.ReverseProxyAuthenticationHeader)
if len(webAuthUser) > 0 {
user, err := store.GetUserByUsername(ctx.Req.Context(), webAuthUser)
user, err := db.Users.GetByUsername(ctx.Req.Context(), webAuthUser)
if err != nil {
if !database.IsErrUserNotExist(err) {
if !db.IsErrUserNotExist(err) {
log.Error("Failed to get user by name: %v", err)
return nil, false, false
}
// Check if enabled auto-registration.
if conf.Auth.EnableReverseProxyAutoRegistration {
user, err = store.CreateUser(
user, err = db.Users.Create(
ctx.Req.Context(),
webAuthUser,
gouuid.NewV4().String()+"@localhost",
database.CreateUserOptions{
db.CreateUserOptions{
Activated: true,
},
)
@ -245,7 +210,7 @@ func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store
if len(auths) == 2 && auths[0] == "Basic" {
uname, passwd, _ := tool.BasicAuthDecode(auths[1])
u, err := store.AuthenticateUser(ctx.Req.Context(), uname, passwd, -1)
u, err := db.Users.Authenticate(ctx.Req.Context(), uname, passwd, -1)
if err != nil {
if !auth.IsErrBadCredentials(err) {
log.Error("Failed to authenticate user: %v", err)
@ -259,7 +224,7 @@ func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store
return nil, false, false
}
u, err := store.GetUserByID(ctx.Req.Context(), uid)
u, err := db.Users.GetByID(ctx.Req.Context(), uid)
if err != nil {
log.Error("GetUserByID: %v", err)
return nil, false, false
@ -268,19 +233,19 @@ func authenticatedUser(store AuthStore, ctx *macaron.Context, sess session.Store
}
// AuthenticateByToken attempts to authenticate a user by the given access
// token. It returns database.ErrAccessTokenNotExist when the access token does not
// token. It returns db.ErrAccessTokenNotExist when the access token does not
// exist.
func AuthenticateByToken(store AuthStore, ctx context.Context, token string) (*database.User, error) {
t, err := store.GetAccessTokenBySHA1(ctx, token)
func AuthenticateByToken(ctx context.Context, token string) (*db.User, error) {
t, err := db.AccessTokens.GetBySHA1(ctx, token)
if err != nil {
return nil, errors.Wrap(err, "get access token by SHA1")
}
if err = store.TouchAccessTokenByID(ctx, t.ID); err != nil {
if err = db.AccessTokens.Touch(ctx, t.ID); err != nil {
// NOTE: There is no need to fail the auth flow if we can't touch the token.
log.Error("Failed to touch access token [id: %d]: %v", t.ID, err)
}
user, err := store.GetUserByID(ctx, t.UserID)
user, err := db.Users.GetByID(ctx, t.UserID)
if err != nil {
return nil, errors.Wrapf(err, "get user by ID [user_id: %d]", t.UserID)
}

View File

@ -19,7 +19,7 @@ import (
log "unknwon.dev/clog/v2"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/form"
"gogs.io/gogs/internal/lazyregexp"
@ -35,7 +35,7 @@ type Context struct {
Session session.Store
Link string // Current request URL
User *database.User
User *db.User
IsLogged bool
IsBasicAuth bool
IsTokenAuth bool
@ -235,7 +235,7 @@ func (c *Context) ServeContent(name string, r io.ReadSeeker, params ...any) {
var csrfTokenExcludePattern = lazyregexp.New(`[^a-zA-Z0-9-_].*`)
// Contexter initializes a classic context for a request.
func Contexter(store Store) macaron.Handler {
func Contexter() macaron.Handler {
return func(ctx *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
c := &Context{
Context: ctx,
@ -260,7 +260,7 @@ func Contexter(store Store) macaron.Handler {
}
// Get user from session or header when possible
c.User, c.IsBasicAuth, c.IsTokenAuth = authenticatedUser(store, c.Context, c.Session)
c.User, c.IsBasicAuth, c.IsTokenAuth = authenticatedUser(c.Context, c.Session)
if c.User != nil {
c.IsLogged = true

View File

@ -9,7 +9,7 @@ import (
"gopkg.in/macaron.v1"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/repoutil"
)
@ -27,9 +27,9 @@ func ServeGoGet() macaron.Handler {
repoName := c.Params(":reponame")
branchName := "master"
owner, err := database.Handle.Users().GetByUsername(c.Req.Context(), ownerName)
owner, err := db.Users.GetByUsername(c.Req.Context(), ownerName)
if err == nil {
repo, err := database.Handle.Repositories().GetByName(c.Req.Context(), owner.ID, repoName)
repo, err := db.Repos.GetByName(c.Req.Context(), owner.ID, repoName)
if err == nil && repo.DefaultBranch != "" {
branchName = repo.DefaultBranch
}

View File

@ -10,7 +10,7 @@ import (
"gopkg.in/macaron.v1"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
type Organization struct {
@ -18,10 +18,10 @@ type Organization struct {
IsMember bool
IsTeamMember bool // Is member of team.
IsTeamAdmin bool // In owner team or team that has admin permission level.
Organization *database.User
Organization *db.User
OrgLink string
Team *database.Team
Team *db.Team
}
func HandleOrgAssignment(c *Context, args ...bool) {
@ -47,7 +47,7 @@ func HandleOrgAssignment(c *Context, args ...bool) {
orgName := c.Params(":org")
var err error
c.Org.Organization, err = database.Handle.Users().GetByUsername(c.Req.Context(), orgName)
c.Org.Organization, err = db.Users.GetByUsername(c.Req.Context(), orgName)
if err != nil {
c.NotFoundOrError(err, "get organization by name")
return
@ -78,7 +78,7 @@ func HandleOrgAssignment(c *Context, args ...bool) {
}
} else {
// Fake data.
c.Data["SignedUser"] = &database.User{}
c.Data["SignedUser"] = &db.User{}
}
if (requireMember && !c.Org.IsMember) ||
(requireOwner && !c.Org.IsOwner) {
@ -131,7 +131,7 @@ func HandleOrgAssignment(c *Context, args ...bool) {
return
}
c.Org.IsTeamAdmin = c.Org.Team.IsOwnerTeam() || c.Org.Team.Authorize >= database.AccessModeAdmin
c.Org.IsTeamAdmin = c.Org.Team.IsOwnerTeam() || c.Org.Team.Authorize >= db.AccessModeAdmin
c.Data["IsTeamAdmin"] = c.Org.IsTeamAdmin
if requireTeamAdmin && !c.Org.IsTeamAdmin {
c.NotFound()

View File

@ -17,25 +17,25 @@ import (
"github.com/gogs/git-module"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/repoutil"
)
type PullRequest struct {
BaseRepo *database.Repository
BaseRepo *db.Repository
Allowed bool
SameRepo bool
HeadInfo string // [<user>:]<branch>
}
type Repository struct {
AccessMode database.AccessMode
AccessMode db.AccessMode
IsWatching bool
IsViewBranch bool
IsViewTag bool
IsViewCommit bool
Repository *database.Repository
Owner *database.User
Repository *db.Repository
Owner *db.User
Commit *git.Commit
Tag *git.Tag
GitRepo *git.Repository
@ -46,29 +46,29 @@ type Repository struct {
RepoLink string
CloneLink repoutil.CloneLink
CommitsCount int64
Mirror *database.Mirror
Mirror *db.Mirror
PullRequest *PullRequest
}
// IsOwner returns true if current user is the owner of repository.
func (r *Repository) IsOwner() bool {
return r.AccessMode >= database.AccessModeOwner
return r.AccessMode >= db.AccessModeOwner
}
// IsAdmin returns true if current user has admin or higher access of repository.
func (r *Repository) IsAdmin() bool {
return r.AccessMode >= database.AccessModeAdmin
return r.AccessMode >= db.AccessModeAdmin
}
// IsWriter returns true if current user has write or higher access of repository.
func (r *Repository) IsWriter() bool {
return r.AccessMode >= database.AccessModeWrite
return r.AccessMode >= db.AccessModeWrite
}
// HasAccess returns true if the current user has at least read access for this repository
func (r *Repository) HasAccess() bool {
return r.AccessMode >= database.AccessModeRead
return r.AccessMode >= db.AccessModeRead
}
// CanEnableEditor returns true if repository is editable and user has proper access level.
@ -125,7 +125,7 @@ func (r *Repository) PullRequestURL(baseBranch, headBranch string) string {
func RepoAssignment(pages ...bool) macaron.Handler {
return func(c *Context) {
var (
owner *database.User
owner *db.User
err error
isIssuesPage bool
isWikiPage bool
@ -145,7 +145,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
if c.IsLogged && c.User.LowerName == strings.ToLower(ownerName) {
owner = c.User
} else {
owner, err = database.Handle.Users().GetByUsername(c.Req.Context(), ownerName)
owner, err = db.Users.GetByUsername(c.Req.Context(), ownerName)
if err != nil {
c.NotFoundOrError(err, "get user by name")
return
@ -154,7 +154,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
c.Repo.Owner = owner
c.Data["Username"] = c.Repo.Owner.Name
repo, err := database.GetRepositoryByName(owner.ID, repoName)
repo, err := db.GetRepositoryByName(owner.ID, repoName)
if err != nil {
c.NotFoundOrError(err, "get repository by name")
return
@ -169,10 +169,10 @@ func RepoAssignment(pages ...bool) macaron.Handler {
// Admin has super access
if c.IsLogged && c.User.IsAdmin {
c.Repo.AccessMode = database.AccessModeOwner
c.Repo.AccessMode = db.AccessModeOwner
} else {
c.Repo.AccessMode = database.Handle.Permissions().AccessMode(c.Req.Context(), c.UserID(), repo.ID,
database.AccessModeOptions{
c.Repo.AccessMode = db.Perms.AccessMode(c.Req.Context(), c.UserID(), repo.ID,
db.AccessModeOptions{
OwnerID: repo.OwnerID,
Private: repo.IsPrivate,
},
@ -181,23 +181,23 @@ func RepoAssignment(pages ...bool) macaron.Handler {
// If the authenticated user has no direct access, see if the repository is a fork
// and whether the user has access to the base repository.
if c.Repo.AccessMode == database.AccessModeNone && repo.BaseRepo != nil {
mode := database.Handle.Permissions().AccessMode(c.Req.Context(), c.UserID(), repo.BaseRepo.ID,
database.AccessModeOptions{
if c.Repo.AccessMode == db.AccessModeNone && repo.BaseRepo != nil {
mode := db.Perms.AccessMode(c.Req.Context(), c.UserID(), repo.BaseRepo.ID,
db.AccessModeOptions{
OwnerID: repo.BaseRepo.OwnerID,
Private: repo.BaseRepo.IsPrivate,
},
)
// Users shouldn't have indirect access level higher than write.
if mode > database.AccessModeWrite {
mode = database.AccessModeWrite
if mode > db.AccessModeWrite {
mode = db.AccessModeWrite
}
c.Repo.AccessMode = mode
}
// Check access
if c.Repo.AccessMode == database.AccessModeNone {
if c.Repo.AccessMode == db.AccessModeNone {
// Redirect to any accessible page if not yet on it
if repo.IsPartialPublic() &&
(!(isIssuesPage || isWikiPage) ||
@ -227,7 +227,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
}
if repo.IsMirror {
c.Repo.Mirror, err = database.GetMirrorByRepoID(repo.ID)
c.Repo.Mirror, err = db.GetMirrorByRepoID(repo.ID)
if err != nil {
c.Error(err, "get mirror by repository ID")
return
@ -237,7 +237,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
c.Data["Mirror"] = c.Repo.Mirror
}
gitRepo, err := git.Open(database.RepoPath(ownerName, repoName))
gitRepo, err := git.Open(db.RepoPath(ownerName, repoName))
if err != nil {
c.Error(err, "open repository")
return
@ -265,8 +265,8 @@ func RepoAssignment(pages ...bool) macaron.Handler {
c.Data["WikiCloneLink"] = repo.WikiCloneLink()
if c.IsLogged {
c.Data["IsWatchingRepo"] = database.IsWatching(c.User.ID, repo.ID)
c.Data["IsStaringRepo"] = database.IsStaring(c.User.ID, repo.ID)
c.Data["IsWatchingRepo"] = db.IsWatching(c.User.ID, repo.ID)
c.Data["IsStaringRepo"] = db.IsStaring(c.User.ID, repo.ID)
}
// repo is bare and display enable
@ -314,7 +314,7 @@ func RepoRef() macaron.Handler {
// For API calls.
if c.Repo.GitRepo == nil {
repoPath := database.RepoPath(c.Repo.Owner.Name, c.Repo.Repository.Name)
repoPath := db.RepoPath(c.Repo.Owner.Name, c.Repo.Repository.Name)
c.Repo.GitRepo, err = git.Open(repoPath)
if err != nil {
c.Error(err, "open repository")
@ -403,7 +403,7 @@ func RepoRef() macaron.Handler {
c.Data["IsViewCommit"] = c.Repo.IsViewCommit
// People who have push access or have forked repository can propose a new pull request.
if c.Repo.IsWriter() || (c.IsLogged && database.Handle.Repositories().HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID)) {
if c.Repo.IsWriter() || (c.IsLogged && db.Repos.HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID)) {
// Pull request is allowed if this is a fork repository
// and base repository accepts pull requests.
if c.Repo.Repository.BaseRepo != nil {

View File

@ -1,76 +0,0 @@
package context
import (
"context"
"gogs.io/gogs/internal/database"
)
// Store is the data layer carrier for context middleware. This interface is
// meant to abstract away and limit the exposure of the underlying data layer to
// the handler through a thin-wrapper.
type Store interface {
// GetAccessTokenBySHA1 returns the access token with given SHA1. It returns
// database.ErrAccessTokenNotExist when not found.
GetAccessTokenBySHA1(ctx context.Context, sha1 string) (*database.AccessToken, error)
// TouchAccessTokenByID updates the updated time of the given access token to
// the current time.
TouchAccessTokenByID(ctx context.Context, id int64) error
// GetUserByID returns the user with given ID. It returns
// database.ErrUserNotExist when not found.
GetUserByID(ctx context.Context, id int64) (*database.User, error)
// GetUserByUsername returns the user with given username. It returns
// database.ErrUserNotExist when not found.
GetUserByUsername(ctx context.Context, username string) (*database.User, error)
// CreateUser creates a new user and persists to database. It returns
// database.ErrNameNotAllowed if the given name or pattern of the name is not
// allowed as a username, or database.ErrUserAlreadyExist when a user with same
// name already exists, or database.ErrEmailAlreadyUsed if the email has been
// verified by another user.
CreateUser(ctx context.Context, username, email string, opts database.CreateUserOptions) (*database.User, error)
// AuthenticateUser validates username and password via given login source ID.
// It returns database.ErrUserNotExist when the user was not found.
//
// When the "loginSourceID" is negative, it aborts the process and returns
// database.ErrUserNotExist if the user was not found in the database.
//
// When the "loginSourceID" is non-negative, it returns
// database.ErrLoginSourceMismatch if the user has different login source ID
// than the "loginSourceID".
//
// When the "loginSourceID" is positive, it tries to authenticate via given
// login source and creates a new user when not yet exists in the database.
AuthenticateUser(ctx context.Context, login, password string, loginSourceID int64) (*database.User, error)
}
type store struct{}
// NewStore returns a new Store using the global database handle.
func NewStore() Store {
return &store{}
}
func (*store) GetAccessTokenBySHA1(ctx context.Context, sha1 string) (*database.AccessToken, error) {
return database.Handle.AccessTokens().GetBySHA1(ctx, sha1)
}
func (*store) TouchAccessTokenByID(ctx context.Context, id int64) error {
return database.Handle.AccessTokens().Touch(ctx, id)
}
func (*store) GetUserByID(ctx context.Context, id int64) (*database.User, error) {
return database.Handle.Users().GetByID(ctx, id)
}
func (*store) GetUserByUsername(ctx context.Context, username string) (*database.User, error) {
return database.Handle.Users().GetByUsername(ctx, username)
}
func (*store) CreateUser(ctx context.Context, username, email string, opts database.CreateUserOptions) (*database.User, error) {
return database.Handle.Users().Create(ctx, username, email, opts)
}
func (*store) AuthenticateUser(ctx context.Context, login, password string, loginSourceID int64) (*database.User, error) {
return database.Handle.Users().Authenticate(ctx, login, password, loginSourceID)
}

View File

@ -7,19 +7,19 @@ package context
import (
"gopkg.in/macaron.v1"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
// ParamsUser is the wrapper type of the target user defined by URL parameter, namely ':username'.
type ParamsUser struct {
*database.User
*db.User
}
// InjectParamsUser returns a handler that retrieves target user based on URL parameter ':username',
// and injects it as *ParamsUser.
func InjectParamsUser() macaron.Handler {
return func(c *Context) {
user, err := database.Handle.Users().GetByUsername(c.Req.Context(), c.Params(":username"))
user, err := db.Users.GetByUsername(c.Req.Context(), c.Params(":username"))
if err != nil {
c.NotFoundOrError(err, "get user by name")
return

View File

@ -12,7 +12,7 @@ import (
"github.com/gogs/cron"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/database"
"gogs.io/gogs/internal/db"
)
var c = cron.New()
@ -23,47 +23,47 @@ func NewContext() {
err error
)
if conf.Cron.UpdateMirror.Enabled {
entry, err = c.AddFunc("Update mirrors", conf.Cron.UpdateMirror.Schedule, database.MirrorUpdate)
entry, err = c.AddFunc("Update mirrors", conf.Cron.UpdateMirror.Schedule, db.MirrorUpdate)
if err != nil {
log.Fatal("Cron.(update mirrors): %v", err)
}
if conf.Cron.UpdateMirror.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go database.MirrorUpdate()
go db.MirrorUpdate()
}
}
if conf.Cron.RepoHealthCheck.Enabled {
entry, err = c.AddFunc("Repository health check", conf.Cron.RepoHealthCheck.Schedule, database.GitFsck)
entry, err = c.AddFunc("Repository health check", conf.Cron.RepoHealthCheck.Schedule, db.GitFsck)
if err != nil {
log.Fatal("Cron.(repository health check): %v", err)
}
if conf.Cron.RepoHealthCheck.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go database.GitFsck()
go db.GitFsck()
}
}
if conf.Cron.CheckRepoStats.Enabled {
entry, err = c.AddFunc("Check repository statistics", conf.Cron.CheckRepoStats.Schedule, database.CheckRepoStats)
entry, err = c.AddFunc("Check repository statistics", conf.Cron.CheckRepoStats.Schedule, db.CheckRepoStats)
if err != nil {
log.Fatal("Cron.(check repository statistics): %v", err)
}
if conf.Cron.CheckRepoStats.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go database.CheckRepoStats()
go db.CheckRepoStats()
}
}
if conf.Cron.RepoArchiveCleanup.Enabled {
entry, err = c.AddFunc("Repository archive cleanup", conf.Cron.RepoArchiveCleanup.Schedule, database.DeleteOldRepositoryArchives)
entry, err = c.AddFunc("Repository archive cleanup", conf.Cron.RepoArchiveCleanup.Schedule, db.DeleteOldRepositoryArchives)
if err != nil {
log.Fatal("Cron.(repository archive cleanup): %v", err)
}
if conf.Cron.RepoArchiveCleanup.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go database.DeleteOldRepositoryArchives()
go db.DeleteOldRepositoryArchives()
}
}
c.Start()

View File

@ -1,91 +0,0 @@
// Copyright 2020 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
import (
"context"
"errors"
"fmt"
"time"
"gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/lfsutil"
)
// LFSObject is the relation between an LFS object and a repository.
type LFSObject struct {
RepoID int64 `gorm:"primaryKey;auto_increment:false"`
OID lfsutil.OID `gorm:"primaryKey;column:oid"`
Size int64 `gorm:"not null"`
Storage lfsutil.Storage `gorm:"not null"`
CreatedAt time.Time `gorm:"not null"`
}
// LFSStore is the storage layer for LFS objects.
type LFSStore struct {
db *gorm.DB
}
func newLFSStore(db *gorm.DB) *LFSStore {
return &LFSStore{db: db}
}
// CreateObject creates an LFS object record in database.
func (s *LFSStore) CreateObject(ctx context.Context, repoID int64, oid lfsutil.OID, size int64, storage lfsutil.Storage) error {
object := &LFSObject{
RepoID: repoID,
OID: oid,
Size: size,
Storage: storage,
}
return s.db.WithContext(ctx).Create(object).Error
}
type ErrLFSObjectNotExist struct {
args errutil.Args
}
func IsErrLFSObjectNotExist(err error) bool {
return errors.As(err, &ErrLFSObjectNotExist{})
}
func (err ErrLFSObjectNotExist) Error() string {
return fmt.Sprintf("LFS object does not exist: %v", err.args)
}
func (ErrLFSObjectNotExist) NotFound() bool {
return true
}
// GetObjectByOID returns the LFS object with given OID. It returns
// ErrLFSObjectNotExist when not found.
func (s *LFSStore) GetObjectByOID(ctx context.Context, repoID int64, oid lfsutil.OID) (*LFSObject, error) {
object := new(LFSObject)
err := s.db.WithContext(ctx).Where("repo_id = ? AND oid = ?", repoID, oid).First(object).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrLFSObjectNotExist{args: errutil.Args{"repoID": repoID, "oid": oid}}
}
return nil, err
}
return object, err
}
// GetObjectsByOIDs returns LFS objects found within "oids". The returned list
// could have fewer elements if some oids were not found.
func (s *LFSStore) GetObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfsutil.OID) ([]*LFSObject, error) {
if len(oids) == 0 {
return []*LFSObject{}, nil
}
objects := make([]*LFSObject, 0, len(oids))
err := s.db.WithContext(ctx).Where("repo_id = ? AND oid IN (?)", repoID, oids).Find(&objects).Error
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
return objects, nil
}

View File

@ -1,620 +0,0 @@
// Code generated by go-mockgen 1.3.7; DO NOT EDIT.
//
// This file was generated by running `go-mockgen` at the root of this repository.
// To add additional mocks to this or another package, add a new entry to the
// mockgen.yaml file in the root of this repository.
package database
import (
"sync"
auth "gogs.io/gogs/internal/auth"
)
// MockProvider is a mock implementation of the Provider interface (from the
// package gogs.io/gogs/internal/auth) used for unit testing.
type MockProvider struct {
// AuthenticateFunc is an instance of a mock function object controlling
// the behavior of the method Authenticate.
AuthenticateFunc *ProviderAuthenticateFunc
// ConfigFunc is an instance of a mock function object controlling the
// behavior of the method Config.
ConfigFunc *ProviderConfigFunc
// HasTLSFunc is an instance of a mock function object controlling the
// behavior of the method HasTLS.
HasTLSFunc *ProviderHasTLSFunc
// SkipTLSVerifyFunc is an instance of a mock function object
// controlling the behavior of the method SkipTLSVerify.
SkipTLSVerifyFunc *ProviderSkipTLSVerifyFunc
// UseTLSFunc is an instance of a mock function object controlling the
// behavior of the method UseTLS.
UseTLSFunc *ProviderUseTLSFunc
}
// NewMockProvider creates a new mock of the Provider interface. All methods
// return zero values for all results, unless overwritten.
func NewMockProvider() *MockProvider {
return &MockProvider{
AuthenticateFunc: &ProviderAuthenticateFunc{
defaultHook: func(string, string) (r0 *auth.ExternalAccount, r1 error) {
return
},
},
ConfigFunc: &ProviderConfigFunc{
defaultHook: func() (r0 interface{}) {
return
},
},
HasTLSFunc: &ProviderHasTLSFunc{
defaultHook: func() (r0 bool) {
return
},
},
SkipTLSVerifyFunc: &ProviderSkipTLSVerifyFunc{
defaultHook: func() (r0 bool) {
return
},
},
UseTLSFunc: &ProviderUseTLSFunc{
defaultHook: func() (r0 bool) {
return
},
},
}
}
// NewStrictMockProvider creates a new mock of the Provider interface. All
// methods panic on invocation, unless overwritten.
func NewStrictMockProvider() *MockProvider {
return &MockProvider{
AuthenticateFunc: &ProviderAuthenticateFunc{
defaultHook: func(string, string) (*auth.ExternalAccount, error) {
panic("unexpected invocation of MockProvider.Authenticate")
},
},
ConfigFunc: &ProviderConfigFunc{
defaultHook: func() interface{} {
panic("unexpected invocation of MockProvider.Config")
},
},
HasTLSFunc: &ProviderHasTLSFunc{
defaultHook: func() bool {
panic("unexpected invocation of MockProvider.HasTLS")
},
},
SkipTLSVerifyFunc: &ProviderSkipTLSVerifyFunc{
defaultHook: func() bool {
panic("unexpected invocation of MockProvider.SkipTLSVerify")
},
},
UseTLSFunc: &ProviderUseTLSFunc{
defaultHook: func() bool {
panic("unexpected invocation of MockProvider.UseTLS")
},
},
}
}
// NewMockProviderFrom creates a new mock of the MockProvider interface. All
// methods delegate to the given implementation, unless overwritten.
func NewMockProviderFrom(i auth.Provider) *MockProvider {
return &MockProvider{
AuthenticateFunc: &ProviderAuthenticateFunc{
defaultHook: i.Authenticate,
},
ConfigFunc: &ProviderConfigFunc{
defaultHook: i.Config,
},
HasTLSFunc: &ProviderHasTLSFunc{
defaultHook: i.HasTLS,
},
SkipTLSVerifyFunc: &ProviderSkipTLSVerifyFunc{
defaultHook: i.SkipTLSVerify,
},
UseTLSFunc: &ProviderUseTLSFunc{
defaultHook: i.UseTLS,
},
}
}
// ProviderAuthenticateFunc describes the behavior when the Authenticate
// method of the parent MockProvider instance is invoked.
type ProviderAuthenticateFunc struct {
defaultHook func(string, string) (*auth.ExternalAccount, error)
hooks []func(string, string) (*auth.ExternalAccount, error)
history []ProviderAuthenticateFuncCall
mutex sync.Mutex
}
// Authenticate delegates to the next hook function in the queue and stores
// the parameter and result values of this invocation.
func (m *MockProvider) Authenticate(v0 string, v1 string) (*auth.ExternalAccount, error) {
r0, r1 := m.AuthenticateFunc.nextHook()(v0, v1)
m.AuthenticateFunc.appendCall(ProviderAuthenticateFuncCall{v0, v1, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the Authenticate method
// of the parent MockProvider instance is invoked and the hook queue is
// empty.
func (f *ProviderAuthenticateFunc) SetDefaultHook(hook func(string, string) (*auth.ExternalAccount, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// Authenticate method of the parent MockProvider instance invokes the hook
// at the front of the queue and discards it. After the queue is empty, the
// default hook function is invoked for any future action.
func (f *ProviderAuthenticateFunc) PushHook(hook func(string, string) (*auth.ExternalAccount, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *ProviderAuthenticateFunc) SetDefaultReturn(r0 *auth.ExternalAccount, r1 error) {
f.SetDefaultHook(func(string, string) (*auth.ExternalAccount, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *ProviderAuthenticateFunc) PushReturn(r0 *auth.ExternalAccount, r1 error) {
f.PushHook(func(string, string) (*auth.ExternalAccount, error) {
return r0, r1
})
}
func (f *ProviderAuthenticateFunc) nextHook() func(string, string) (*auth.ExternalAccount, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *ProviderAuthenticateFunc) appendCall(r0 ProviderAuthenticateFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of ProviderAuthenticateFuncCall objects
// describing the invocations of this function.
func (f *ProviderAuthenticateFunc) History() []ProviderAuthenticateFuncCall {
f.mutex.Lock()
history := make([]ProviderAuthenticateFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// ProviderAuthenticateFuncCall is an object that describes an invocation of
// method Authenticate on an instance of MockProvider.
type ProviderAuthenticateFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 string
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 string
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 *auth.ExternalAccount
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c ProviderAuthenticateFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c ProviderAuthenticateFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// ProviderConfigFunc describes the behavior when the Config method of the
// parent MockProvider instance is invoked.
type ProviderConfigFunc struct {
defaultHook func() interface{}
hooks []func() interface{}
history []ProviderConfigFuncCall
mutex sync.Mutex
}
// Config delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockProvider) Config() interface{} {
r0 := m.ConfigFunc.nextHook()()
m.ConfigFunc.appendCall(ProviderConfigFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the Config method of the
// parent MockProvider instance is invoked and the hook queue is empty.
func (f *ProviderConfigFunc) SetDefaultHook(hook func() interface{}) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// Config method of the parent MockProvider instance invokes the hook at the
// front of the queue and discards it. After the queue is empty, the default
// hook function is invoked for any future action.
func (f *ProviderConfigFunc) PushHook(hook func() interface{}) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *ProviderConfigFunc) SetDefaultReturn(r0 interface{}) {
f.SetDefaultHook(func() interface{} {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *ProviderConfigFunc) PushReturn(r0 interface{}) {
f.PushHook(func() interface{} {
return r0
})
}
func (f *ProviderConfigFunc) nextHook() func() interface{} {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *ProviderConfigFunc) appendCall(r0 ProviderConfigFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of ProviderConfigFuncCall objects describing
// the invocations of this function.
func (f *ProviderConfigFunc) History() []ProviderConfigFuncCall {
f.mutex.Lock()
history := make([]ProviderConfigFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// ProviderConfigFuncCall is an object that describes an invocation of
// method Config on an instance of MockProvider.
type ProviderConfigFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 interface{}
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c ProviderConfigFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c ProviderConfigFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// ProviderHasTLSFunc describes the behavior when the HasTLS method of the
// parent MockProvider instance is invoked.
type ProviderHasTLSFunc struct {
defaultHook func() bool
hooks []func() bool
history []ProviderHasTLSFuncCall
mutex sync.Mutex
}
// HasTLS delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockProvider) HasTLS() bool {
r0 := m.HasTLSFunc.nextHook()()
m.HasTLSFunc.appendCall(ProviderHasTLSFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the HasTLS method of the
// parent MockProvider instance is invoked and the hook queue is empty.
func (f *ProviderHasTLSFunc) SetDefaultHook(hook func() bool) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// HasTLS method of the parent MockProvider instance invokes the hook at the
// front of the queue and discards it. After the queue is empty, the default
// hook function is invoked for any future action.
func (f *ProviderHasTLSFunc) PushHook(hook func() bool) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *ProviderHasTLSFunc) SetDefaultReturn(r0 bool) {
f.SetDefaultHook(func() bool {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *ProviderHasTLSFunc) PushReturn(r0 bool) {
f.PushHook(func() bool {
return r0
})
}
func (f *ProviderHasTLSFunc) nextHook() func() bool {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *ProviderHasTLSFunc) appendCall(r0 ProviderHasTLSFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of ProviderHasTLSFuncCall objects describing
// the invocations of this function.
func (f *ProviderHasTLSFunc) History() []ProviderHasTLSFuncCall {
f.mutex.Lock()
history := make([]ProviderHasTLSFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// ProviderHasTLSFuncCall is an object that describes an invocation of
// method HasTLS on an instance of MockProvider.
type ProviderHasTLSFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 bool
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c ProviderHasTLSFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c ProviderHasTLSFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// ProviderSkipTLSVerifyFunc describes the behavior when the SkipTLSVerify
// method of the parent MockProvider instance is invoked.
type ProviderSkipTLSVerifyFunc struct {
defaultHook func() bool
hooks []func() bool
history []ProviderSkipTLSVerifyFuncCall
mutex sync.Mutex
}
// SkipTLSVerify delegates to the next hook function in the queue and stores
// the parameter and result values of this invocation.
func (m *MockProvider) SkipTLSVerify() bool {
r0 := m.SkipTLSVerifyFunc.nextHook()()
m.SkipTLSVerifyFunc.appendCall(ProviderSkipTLSVerifyFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the SkipTLSVerify method
// of the parent MockProvider instance is invoked and the hook queue is
// empty.
func (f *ProviderSkipTLSVerifyFunc) SetDefaultHook(hook func() bool) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// SkipTLSVerify method of the parent MockProvider instance invokes the hook
// at the front of the queue and discards it. After the queue is empty, the
// default hook function is invoked for any future action.
func (f *ProviderSkipTLSVerifyFunc) PushHook(hook func() bool) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *ProviderSkipTLSVerifyFunc) SetDefaultReturn(r0 bool) {
f.SetDefaultHook(func() bool {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *ProviderSkipTLSVerifyFunc) PushReturn(r0 bool) {
f.PushHook(func() bool {
return r0
})
}
func (f *ProviderSkipTLSVerifyFunc) nextHook() func() bool {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *ProviderSkipTLSVerifyFunc) appendCall(r0 ProviderSkipTLSVerifyFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of ProviderSkipTLSVerifyFuncCall objects
// describing the invocations of this function.
func (f *ProviderSkipTLSVerifyFunc) History() []ProviderSkipTLSVerifyFuncCall {
f.mutex.Lock()
history := make([]ProviderSkipTLSVerifyFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// ProviderSkipTLSVerifyFuncCall is an object that describes an invocation
// of method SkipTLSVerify on an instance of MockProvider.
type ProviderSkipTLSVerifyFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 bool
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c ProviderSkipTLSVerifyFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c ProviderSkipTLSVerifyFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// ProviderUseTLSFunc describes the behavior when the UseTLS method of the
// parent MockProvider instance is invoked.
type ProviderUseTLSFunc struct {
defaultHook func() bool
hooks []func() bool
history []ProviderUseTLSFuncCall
mutex sync.Mutex
}
// UseTLS delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockProvider) UseTLS() bool {
r0 := m.UseTLSFunc.nextHook()()
m.UseTLSFunc.appendCall(ProviderUseTLSFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the UseTLS method of the
// parent MockProvider instance is invoked and the hook queue is empty.
func (f *ProviderUseTLSFunc) SetDefaultHook(hook func() bool) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// UseTLS method of the parent MockProvider instance invokes the hook at the
// front of the queue and discards it. After the queue is empty, the default
// hook function is invoked for any future action.
func (f *ProviderUseTLSFunc) PushHook(hook func() bool) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *ProviderUseTLSFunc) SetDefaultReturn(r0 bool) {
f.SetDefaultHook(func() bool {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *ProviderUseTLSFunc) PushReturn(r0 bool) {
f.PushHook(func() bool {
return r0
})
}
func (f *ProviderUseTLSFunc) nextHook() func() bool {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *ProviderUseTLSFunc) appendCall(r0 ProviderUseTLSFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of ProviderUseTLSFuncCall objects describing
// the invocations of this function.
func (f *ProviderUseTLSFunc) History() []ProviderUseTLSFuncCall {
f.mutex.Lock()
history := make([]ProviderUseTLSFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// ProviderUseTLSFuncCall is an object that describes an invocation of
// method UseTLS on an instance of MockProvider.
type ProviderUseTLSFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 bool
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c ProviderUseTLSFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c ProviderUseTLSFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}

View File

@ -1,912 +0,0 @@
// Code generated by go-mockgen 1.3.7; DO NOT EDIT.
//
// This file was generated by running `go-mockgen` at the root of this repository.
// To add additional mocks to this or another package, add a new entry to the
// mockgen.yaml file in the root of this repository.
package database
import "sync"
// MockLoginSourceFileStore is a mock implementation of the
// loginSourceFileStore interface (from the package
// gogs.io/gogs/internal/database) used for unit testing.
type MockLoginSourceFileStore struct {
// SaveFunc is an instance of a mock function object controlling the
// behavior of the method Save.
SaveFunc *LoginSourceFileStoreSaveFunc
// SetConfigFunc is an instance of a mock function object controlling
// the behavior of the method SetConfig.
SetConfigFunc *LoginSourceFileStoreSetConfigFunc
// SetGeneralFunc is an instance of a mock function object controlling
// the behavior of the method SetGeneral.
SetGeneralFunc *LoginSourceFileStoreSetGeneralFunc
}
// NewMockLoginSourceFileStore creates a new mock of the
// loginSourceFileStore interface. All methods return zero values for all
// results, unless overwritten.
func NewMockLoginSourceFileStore() *MockLoginSourceFileStore {
return &MockLoginSourceFileStore{
SaveFunc: &LoginSourceFileStoreSaveFunc{
defaultHook: func() (r0 error) {
return
},
},
SetConfigFunc: &LoginSourceFileStoreSetConfigFunc{
defaultHook: func(interface{}) (r0 error) {
return
},
},
SetGeneralFunc: &LoginSourceFileStoreSetGeneralFunc{
defaultHook: func(string, string) {
return
},
},
}
}
// NewStrictMockLoginSourceFileStore creates a new mock of the
// loginSourceFileStore interface. All methods panic on invocation, unless
// overwritten.
func NewStrictMockLoginSourceFileStore() *MockLoginSourceFileStore {
return &MockLoginSourceFileStore{
SaveFunc: &LoginSourceFileStoreSaveFunc{
defaultHook: func() error {
panic("unexpected invocation of MockLoginSourceFileStore.Save")
},
},
SetConfigFunc: &LoginSourceFileStoreSetConfigFunc{
defaultHook: func(interface{}) error {
panic("unexpected invocation of MockLoginSourceFileStore.SetConfig")
},
},
SetGeneralFunc: &LoginSourceFileStoreSetGeneralFunc{
defaultHook: func(string, string) {
panic("unexpected invocation of MockLoginSourceFileStore.SetGeneral")
},
},
}
}
// surrogateMockLoginSourceFileStore is a copy of the loginSourceFileStore
// interface (from the package gogs.io/gogs/internal/database). It is
// redefined here as it is unexported in the source package.
type surrogateMockLoginSourceFileStore interface {
Save() error
SetConfig(interface{}) error
SetGeneral(string, string)
}
// NewMockLoginSourceFileStoreFrom creates a new mock of the
// MockLoginSourceFileStore interface. All methods delegate to the given
// implementation, unless overwritten.
func NewMockLoginSourceFileStoreFrom(i surrogateMockLoginSourceFileStore) *MockLoginSourceFileStore {
return &MockLoginSourceFileStore{
SaveFunc: &LoginSourceFileStoreSaveFunc{
defaultHook: i.Save,
},
SetConfigFunc: &LoginSourceFileStoreSetConfigFunc{
defaultHook: i.SetConfig,
},
SetGeneralFunc: &LoginSourceFileStoreSetGeneralFunc{
defaultHook: i.SetGeneral,
},
}
}
// LoginSourceFileStoreSaveFunc describes the behavior when the Save method
// of the parent MockLoginSourceFileStore instance is invoked.
type LoginSourceFileStoreSaveFunc struct {
defaultHook func() error
hooks []func() error
history []LoginSourceFileStoreSaveFuncCall
mutex sync.Mutex
}
// Save delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFileStore) Save() error {
r0 := m.SaveFunc.nextHook()()
m.SaveFunc.appendCall(LoginSourceFileStoreSaveFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the Save method of the
// parent MockLoginSourceFileStore instance is invoked and the hook queue is
// empty.
func (f *LoginSourceFileStoreSaveFunc) SetDefaultHook(hook func() error) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// Save method of the parent MockLoginSourceFileStore instance invokes the
// hook at the front of the queue and discards it. After the queue is empty,
// the default hook function is invoked for any future action.
func (f *LoginSourceFileStoreSaveFunc) PushHook(hook func() error) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFileStoreSaveFunc) SetDefaultReturn(r0 error) {
f.SetDefaultHook(func() error {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFileStoreSaveFunc) PushReturn(r0 error) {
f.PushHook(func() error {
return r0
})
}
func (f *LoginSourceFileStoreSaveFunc) nextHook() func() error {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFileStoreSaveFunc) appendCall(r0 LoginSourceFileStoreSaveFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFileStoreSaveFuncCall objects
// describing the invocations of this function.
func (f *LoginSourceFileStoreSaveFunc) History() []LoginSourceFileStoreSaveFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFileStoreSaveFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFileStoreSaveFuncCall is an object that describes an
// invocation of method Save on an instance of MockLoginSourceFileStore.
type LoginSourceFileStoreSaveFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFileStoreSaveFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFileStoreSaveFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// LoginSourceFileStoreSetConfigFunc describes the behavior when the
// SetConfig method of the parent MockLoginSourceFileStore instance is
// invoked.
type LoginSourceFileStoreSetConfigFunc struct {
defaultHook func(interface{}) error
hooks []func(interface{}) error
history []LoginSourceFileStoreSetConfigFuncCall
mutex sync.Mutex
}
// SetConfig delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFileStore) SetConfig(v0 interface{}) error {
r0 := m.SetConfigFunc.nextHook()(v0)
m.SetConfigFunc.appendCall(LoginSourceFileStoreSetConfigFuncCall{v0, r0})
return r0
}
// SetDefaultHook sets function that is called when the SetConfig method of
// the parent MockLoginSourceFileStore instance is invoked and the hook
// queue is empty.
func (f *LoginSourceFileStoreSetConfigFunc) SetDefaultHook(hook func(interface{}) error) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// SetConfig method of the parent MockLoginSourceFileStore instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *LoginSourceFileStoreSetConfigFunc) PushHook(hook func(interface{}) error) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFileStoreSetConfigFunc) SetDefaultReturn(r0 error) {
f.SetDefaultHook(func(interface{}) error {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFileStoreSetConfigFunc) PushReturn(r0 error) {
f.PushHook(func(interface{}) error {
return r0
})
}
func (f *LoginSourceFileStoreSetConfigFunc) nextHook() func(interface{}) error {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFileStoreSetConfigFunc) appendCall(r0 LoginSourceFileStoreSetConfigFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFileStoreSetConfigFuncCall
// objects describing the invocations of this function.
func (f *LoginSourceFileStoreSetConfigFunc) History() []LoginSourceFileStoreSetConfigFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFileStoreSetConfigFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFileStoreSetConfigFuncCall is an object that describes an
// invocation of method SetConfig on an instance of
// MockLoginSourceFileStore.
type LoginSourceFileStoreSetConfigFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 interface{}
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFileStoreSetConfigFuncCall) Args() []interface{} {
return []interface{}{c.Arg0}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFileStoreSetConfigFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// LoginSourceFileStoreSetGeneralFunc describes the behavior when the
// SetGeneral method of the parent MockLoginSourceFileStore instance is
// invoked.
type LoginSourceFileStoreSetGeneralFunc struct {
defaultHook func(string, string)
hooks []func(string, string)
history []LoginSourceFileStoreSetGeneralFuncCall
mutex sync.Mutex
}
// SetGeneral delegates to the next hook function in the queue and stores
// the parameter and result values of this invocation.
func (m *MockLoginSourceFileStore) SetGeneral(v0 string, v1 string) {
m.SetGeneralFunc.nextHook()(v0, v1)
m.SetGeneralFunc.appendCall(LoginSourceFileStoreSetGeneralFuncCall{v0, v1})
return
}
// SetDefaultHook sets function that is called when the SetGeneral method of
// the parent MockLoginSourceFileStore instance is invoked and the hook
// queue is empty.
func (f *LoginSourceFileStoreSetGeneralFunc) SetDefaultHook(hook func(string, string)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// SetGeneral method of the parent MockLoginSourceFileStore instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *LoginSourceFileStoreSetGeneralFunc) PushHook(hook func(string, string)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFileStoreSetGeneralFunc) SetDefaultReturn() {
f.SetDefaultHook(func(string, string) {
return
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFileStoreSetGeneralFunc) PushReturn() {
f.PushHook(func(string, string) {
return
})
}
func (f *LoginSourceFileStoreSetGeneralFunc) nextHook() func(string, string) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFileStoreSetGeneralFunc) appendCall(r0 LoginSourceFileStoreSetGeneralFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFileStoreSetGeneralFuncCall
// objects describing the invocations of this function.
func (f *LoginSourceFileStoreSetGeneralFunc) History() []LoginSourceFileStoreSetGeneralFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFileStoreSetGeneralFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFileStoreSetGeneralFuncCall is an object that describes an
// invocation of method SetGeneral on an instance of
// MockLoginSourceFileStore.
type LoginSourceFileStoreSetGeneralFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 string
// Arg1 is the value of the 2nd argument passed to this method
// invocation.
Arg1 string
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFileStoreSetGeneralFuncCall) Args() []interface{} {
return []interface{}{c.Arg0, c.Arg1}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFileStoreSetGeneralFuncCall) Results() []interface{} {
return []interface{}{}
}
// MockLoginSourceFilesStore is a mock implementation of the
// loginSourceFilesStore interface (from the package
// gogs.io/gogs/internal/database) used for unit testing.
type MockLoginSourceFilesStore struct {
// GetByIDFunc is an instance of a mock function object controlling the
// behavior of the method GetByID.
GetByIDFunc *LoginSourceFilesStoreGetByIDFunc
// LenFunc is an instance of a mock function object controlling the
// behavior of the method Len.
LenFunc *LoginSourceFilesStoreLenFunc
// ListFunc is an instance of a mock function object controlling the
// behavior of the method List.
ListFunc *LoginSourceFilesStoreListFunc
// UpdateFunc is an instance of a mock function object controlling the
// behavior of the method Update.
UpdateFunc *LoginSourceFilesStoreUpdateFunc
}
// NewMockLoginSourceFilesStore creates a new mock of the
// loginSourceFilesStore interface. All methods return zero values for all
// results, unless overwritten.
func NewMockLoginSourceFilesStore() *MockLoginSourceFilesStore {
return &MockLoginSourceFilesStore{
GetByIDFunc: &LoginSourceFilesStoreGetByIDFunc{
defaultHook: func(int64) (r0 *LoginSource, r1 error) {
return
},
},
LenFunc: &LoginSourceFilesStoreLenFunc{
defaultHook: func() (r0 int) {
return
},
},
ListFunc: &LoginSourceFilesStoreListFunc{
defaultHook: func(ListLoginSourceOptions) (r0 []*LoginSource) {
return
},
},
UpdateFunc: &LoginSourceFilesStoreUpdateFunc{
defaultHook: func(*LoginSource) {
return
},
},
}
}
// NewStrictMockLoginSourceFilesStore creates a new mock of the
// loginSourceFilesStore interface. All methods panic on invocation, unless
// overwritten.
func NewStrictMockLoginSourceFilesStore() *MockLoginSourceFilesStore {
return &MockLoginSourceFilesStore{
GetByIDFunc: &LoginSourceFilesStoreGetByIDFunc{
defaultHook: func(int64) (*LoginSource, error) {
panic("unexpected invocation of MockLoginSourceFilesStore.GetByID")
},
},
LenFunc: &LoginSourceFilesStoreLenFunc{
defaultHook: func() int {
panic("unexpected invocation of MockLoginSourceFilesStore.Len")
},
},
ListFunc: &LoginSourceFilesStoreListFunc{
defaultHook: func(ListLoginSourceOptions) []*LoginSource {
panic("unexpected invocation of MockLoginSourceFilesStore.List")
},
},
UpdateFunc: &LoginSourceFilesStoreUpdateFunc{
defaultHook: func(*LoginSource) {
panic("unexpected invocation of MockLoginSourceFilesStore.Update")
},
},
}
}
// surrogateMockLoginSourceFilesStore is a copy of the loginSourceFilesStore
// interface (from the package gogs.io/gogs/internal/database). It is
// redefined here as it is unexported in the source package.
type surrogateMockLoginSourceFilesStore interface {
GetByID(int64) (*LoginSource, error)
Len() int
List(ListLoginSourceOptions) []*LoginSource
Update(*LoginSource)
}
// NewMockLoginSourceFilesStoreFrom creates a new mock of the
// MockLoginSourceFilesStore interface. All methods delegate to the given
// implementation, unless overwritten.
func NewMockLoginSourceFilesStoreFrom(i surrogateMockLoginSourceFilesStore) *MockLoginSourceFilesStore {
return &MockLoginSourceFilesStore{
GetByIDFunc: &LoginSourceFilesStoreGetByIDFunc{
defaultHook: i.GetByID,
},
LenFunc: &LoginSourceFilesStoreLenFunc{
defaultHook: i.Len,
},
ListFunc: &LoginSourceFilesStoreListFunc{
defaultHook: i.List,
},
UpdateFunc: &LoginSourceFilesStoreUpdateFunc{
defaultHook: i.Update,
},
}
}
// LoginSourceFilesStoreGetByIDFunc describes the behavior when the GetByID
// method of the parent MockLoginSourceFilesStore instance is invoked.
type LoginSourceFilesStoreGetByIDFunc struct {
defaultHook func(int64) (*LoginSource, error)
hooks []func(int64) (*LoginSource, error)
history []LoginSourceFilesStoreGetByIDFuncCall
mutex sync.Mutex
}
// GetByID delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFilesStore) GetByID(v0 int64) (*LoginSource, error) {
r0, r1 := m.GetByIDFunc.nextHook()(v0)
m.GetByIDFunc.appendCall(LoginSourceFilesStoreGetByIDFuncCall{v0, r0, r1})
return r0, r1
}
// SetDefaultHook sets function that is called when the GetByID method of
// the parent MockLoginSourceFilesStore instance is invoked and the hook
// queue is empty.
func (f *LoginSourceFilesStoreGetByIDFunc) SetDefaultHook(hook func(int64) (*LoginSource, error)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// GetByID method of the parent MockLoginSourceFilesStore instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *LoginSourceFilesStoreGetByIDFunc) PushHook(hook func(int64) (*LoginSource, error)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFilesStoreGetByIDFunc) SetDefaultReturn(r0 *LoginSource, r1 error) {
f.SetDefaultHook(func(int64) (*LoginSource, error) {
return r0, r1
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFilesStoreGetByIDFunc) PushReturn(r0 *LoginSource, r1 error) {
f.PushHook(func(int64) (*LoginSource, error) {
return r0, r1
})
}
func (f *LoginSourceFilesStoreGetByIDFunc) nextHook() func(int64) (*LoginSource, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFilesStoreGetByIDFunc) appendCall(r0 LoginSourceFilesStoreGetByIDFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFilesStoreGetByIDFuncCall
// objects describing the invocations of this function.
func (f *LoginSourceFilesStoreGetByIDFunc) History() []LoginSourceFilesStoreGetByIDFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFilesStoreGetByIDFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFilesStoreGetByIDFuncCall is an object that describes an
// invocation of method GetByID on an instance of MockLoginSourceFilesStore.
type LoginSourceFilesStoreGetByIDFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 int64
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 *LoginSource
// Result1 is the value of the 2nd result returned from this method
// invocation.
Result1 error
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFilesStoreGetByIDFuncCall) Args() []interface{} {
return []interface{}{c.Arg0}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFilesStoreGetByIDFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
// LoginSourceFilesStoreLenFunc describes the behavior when the Len method
// of the parent MockLoginSourceFilesStore instance is invoked.
type LoginSourceFilesStoreLenFunc struct {
defaultHook func() int
hooks []func() int
history []LoginSourceFilesStoreLenFuncCall
mutex sync.Mutex
}
// Len delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFilesStore) Len() int {
r0 := m.LenFunc.nextHook()()
m.LenFunc.appendCall(LoginSourceFilesStoreLenFuncCall{r0})
return r0
}
// SetDefaultHook sets function that is called when the Len method of the
// parent MockLoginSourceFilesStore instance is invoked and the hook queue
// is empty.
func (f *LoginSourceFilesStoreLenFunc) SetDefaultHook(hook func() int) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// Len method of the parent MockLoginSourceFilesStore instance invokes the
// hook at the front of the queue and discards it. After the queue is empty,
// the default hook function is invoked for any future action.
func (f *LoginSourceFilesStoreLenFunc) PushHook(hook func() int) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFilesStoreLenFunc) SetDefaultReturn(r0 int) {
f.SetDefaultHook(func() int {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFilesStoreLenFunc) PushReturn(r0 int) {
f.PushHook(func() int {
return r0
})
}
func (f *LoginSourceFilesStoreLenFunc) nextHook() func() int {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFilesStoreLenFunc) appendCall(r0 LoginSourceFilesStoreLenFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFilesStoreLenFuncCall objects
// describing the invocations of this function.
func (f *LoginSourceFilesStoreLenFunc) History() []LoginSourceFilesStoreLenFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFilesStoreLenFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFilesStoreLenFuncCall is an object that describes an
// invocation of method Len on an instance of MockLoginSourceFilesStore.
type LoginSourceFilesStoreLenFuncCall struct {
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 int
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFilesStoreLenFuncCall) Args() []interface{} {
return []interface{}{}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFilesStoreLenFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// LoginSourceFilesStoreListFunc describes the behavior when the List method
// of the parent MockLoginSourceFilesStore instance is invoked.
type LoginSourceFilesStoreListFunc struct {
defaultHook func(ListLoginSourceOptions) []*LoginSource
hooks []func(ListLoginSourceOptions) []*LoginSource
history []LoginSourceFilesStoreListFuncCall
mutex sync.Mutex
}
// List delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFilesStore) List(v0 ListLoginSourceOptions) []*LoginSource {
r0 := m.ListFunc.nextHook()(v0)
m.ListFunc.appendCall(LoginSourceFilesStoreListFuncCall{v0, r0})
return r0
}
// SetDefaultHook sets function that is called when the List method of the
// parent MockLoginSourceFilesStore instance is invoked and the hook queue
// is empty.
func (f *LoginSourceFilesStoreListFunc) SetDefaultHook(hook func(ListLoginSourceOptions) []*LoginSource) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// List method of the parent MockLoginSourceFilesStore instance invokes the
// hook at the front of the queue and discards it. After the queue is empty,
// the default hook function is invoked for any future action.
func (f *LoginSourceFilesStoreListFunc) PushHook(hook func(ListLoginSourceOptions) []*LoginSource) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFilesStoreListFunc) SetDefaultReturn(r0 []*LoginSource) {
f.SetDefaultHook(func(ListLoginSourceOptions) []*LoginSource {
return r0
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFilesStoreListFunc) PushReturn(r0 []*LoginSource) {
f.PushHook(func(ListLoginSourceOptions) []*LoginSource {
return r0
})
}
func (f *LoginSourceFilesStoreListFunc) nextHook() func(ListLoginSourceOptions) []*LoginSource {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFilesStoreListFunc) appendCall(r0 LoginSourceFilesStoreListFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFilesStoreListFuncCall objects
// describing the invocations of this function.
func (f *LoginSourceFilesStoreListFunc) History() []LoginSourceFilesStoreListFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFilesStoreListFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFilesStoreListFuncCall is an object that describes an
// invocation of method List on an instance of MockLoginSourceFilesStore.
type LoginSourceFilesStoreListFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 ListLoginSourceOptions
// Result0 is the value of the 1st result returned from this method
// invocation.
Result0 []*LoginSource
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFilesStoreListFuncCall) Args() []interface{} {
return []interface{}{c.Arg0}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFilesStoreListFuncCall) Results() []interface{} {
return []interface{}{c.Result0}
}
// LoginSourceFilesStoreUpdateFunc describes the behavior when the Update
// method of the parent MockLoginSourceFilesStore instance is invoked.
type LoginSourceFilesStoreUpdateFunc struct {
defaultHook func(*LoginSource)
hooks []func(*LoginSource)
history []LoginSourceFilesStoreUpdateFuncCall
mutex sync.Mutex
}
// Update delegates to the next hook function in the queue and stores the
// parameter and result values of this invocation.
func (m *MockLoginSourceFilesStore) Update(v0 *LoginSource) {
m.UpdateFunc.nextHook()(v0)
m.UpdateFunc.appendCall(LoginSourceFilesStoreUpdateFuncCall{v0})
return
}
// SetDefaultHook sets function that is called when the Update method of the
// parent MockLoginSourceFilesStore instance is invoked and the hook queue
// is empty.
func (f *LoginSourceFilesStoreUpdateFunc) SetDefaultHook(hook func(*LoginSource)) {
f.defaultHook = hook
}
// PushHook adds a function to the end of hook queue. Each invocation of the
// Update method of the parent MockLoginSourceFilesStore instance invokes
// the hook at the front of the queue and discards it. After the queue is
// empty, the default hook function is invoked for any future action.
func (f *LoginSourceFilesStoreUpdateFunc) PushHook(hook func(*LoginSource)) {
f.mutex.Lock()
f.hooks = append(f.hooks, hook)
f.mutex.Unlock()
}
// SetDefaultReturn calls SetDefaultHook with a function that returns the
// given values.
func (f *LoginSourceFilesStoreUpdateFunc) SetDefaultReturn() {
f.SetDefaultHook(func(*LoginSource) {
return
})
}
// PushReturn calls PushHook with a function that returns the given values.
func (f *LoginSourceFilesStoreUpdateFunc) PushReturn() {
f.PushHook(func(*LoginSource) {
return
})
}
func (f *LoginSourceFilesStoreUpdateFunc) nextHook() func(*LoginSource) {
f.mutex.Lock()
defer f.mutex.Unlock()
if len(f.hooks) == 0 {
return f.defaultHook
}
hook := f.hooks[0]
f.hooks = f.hooks[1:]
return hook
}
func (f *LoginSourceFilesStoreUpdateFunc) appendCall(r0 LoginSourceFilesStoreUpdateFuncCall) {
f.mutex.Lock()
f.history = append(f.history, r0)
f.mutex.Unlock()
}
// History returns a sequence of LoginSourceFilesStoreUpdateFuncCall objects
// describing the invocations of this function.
func (f *LoginSourceFilesStoreUpdateFunc) History() []LoginSourceFilesStoreUpdateFuncCall {
f.mutex.Lock()
history := make([]LoginSourceFilesStoreUpdateFuncCall, len(f.history))
copy(history, f.history)
f.mutex.Unlock()
return history
}
// LoginSourceFilesStoreUpdateFuncCall is an object that describes an
// invocation of method Update on an instance of MockLoginSourceFilesStore.
type LoginSourceFilesStoreUpdateFuncCall struct {
// Arg0 is the value of the 1st argument passed to this method
// invocation.
Arg0 *LoginSource
}
// Args returns an interface slice containing the arguments of this
// invocation.
func (c LoginSourceFilesStoreUpdateFuncCall) Args() []interface{} {
return []interface{}{c.Arg0}
}
// Results returns an interface slice containing the results of this
// invocation.
func (c LoginSourceFilesStoreUpdateFuncCall) Results() []interface{} {
return []interface{}{}
}

View File

@ -1,108 +0,0 @@
// Copyright 2023 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
import (
"context"
"fmt"
"os"
"strconv"
"time"
"gorm.io/gorm"
log "unknwon.dev/clog/v2"
)
// NoticesStore is the storage layer for system notices.
type NoticesStore struct {
db *gorm.DB
}
func newNoticesStore(db *gorm.DB) *NoticesStore {
return &NoticesStore{db: db}
}
// Create creates a system notice with the given type and description.
func (s *NoticesStore) Create(ctx context.Context, typ NoticeType, desc string) error {
return s.db.WithContext(ctx).Create(
&Notice{
Type: typ,
Description: desc,
},
).Error
}
// DeleteByIDs deletes system notices by given IDs.
func (s *NoticesStore) DeleteByIDs(ctx context.Context, ids ...int64) error {
return s.db.WithContext(ctx).Where("id IN (?)", ids).Delete(&Notice{}).Error
}
// DeleteAll deletes all system notices.
func (s *NoticesStore) DeleteAll(ctx context.Context) error {
return s.db.WithContext(ctx).Where("TRUE").Delete(&Notice{}).Error
}
// List returns a list of system notices. Results are paginated by given page
// and page size, and sorted by primary key (id) in descending order.
func (s *NoticesStore) List(ctx context.Context, page, pageSize int) ([]*Notice, error) {
notices := make([]*Notice, 0, pageSize)
return notices, s.db.WithContext(ctx).
Limit(pageSize).Offset((page - 1) * pageSize).
Order("id DESC").
Find(&notices).
Error
}
// Count returns the total number of system notices.
func (s *NoticesStore) Count(ctx context.Context) int64 {
var count int64
s.db.WithContext(ctx).Model(&Notice{}).Count(&count)
return count
}
type NoticeType int
const (
NoticeTypeRepository NoticeType = iota + 1
)
// TrStr returns a translation format string.
func (t NoticeType) TrStr() string {
return "admin.notices.type_" + strconv.Itoa(int(t))
}
// Notice represents a system notice for admin.
type Notice struct {
ID int64 `gorm:"primaryKey"`
Type NoticeType
Description string `xorm:"TEXT" gorm:"type:TEXT"`
Created time.Time `xorm:"-" gorm:"-" json:"-"`
CreatedUnix int64
}
// BeforeCreate implements the GORM create hook.
func (n *Notice) BeforeCreate(tx *gorm.DB) error {
if n.CreatedUnix == 0 {
n.CreatedUnix = tx.NowFunc().Unix()
}
return nil
}
// AfterFind implements the GORM query hook.
func (n *Notice) AfterFind(*gorm.DB) error {
n.Created = time.Unix(n.CreatedUnix, 0).Local()
return nil
}
// RemoveAllWithNotice is a helper function to remove all directories in given
// path and creates a system notice in case of an error.
func RemoveAllWithNotice(title, path string) {
if err := os.RemoveAll(path); err != nil {
desc := fmt.Sprintf("%s [%s]: %v", title, path, err)
if err = Handle.Notices().Create(context.Background(), NoticeTypeRepository, desc); err != nil {
log.Error("Failed to create repository notice: %v", err)
}
}
}

View File

@ -1,163 +0,0 @@
// Copyright 2023 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
func TestNotice_BeforeCreate(t *testing.T) {
now := time.Now()
db := &gorm.DB{
Config: &gorm.Config{
SkipDefaultTransaction: true,
NowFunc: func() time.Time {
return now
},
},
}
t.Run("CreatedUnix has been set", func(t *testing.T) {
notice := &Notice{
CreatedUnix: 1,
}
_ = notice.BeforeCreate(db)
assert.Equal(t, int64(1), notice.CreatedUnix)
})
t.Run("CreatedUnix has not been set", func(t *testing.T) {
notice := &Notice{}
_ = notice.BeforeCreate(db)
assert.Equal(t, db.NowFunc().Unix(), notice.CreatedUnix)
})
}
func TestNotice_AfterFind(t *testing.T) {
now := time.Now()
db := &gorm.DB{
Config: &gorm.Config{
SkipDefaultTransaction: true,
NowFunc: func() time.Time {
return now
},
},
}
notice := &Notice{
CreatedUnix: now.Unix(),
}
_ = notice.AfterFind(db)
assert.Equal(t, notice.CreatedUnix, notice.Created.Unix())
}
func TestNotices(t *testing.T) {
if testing.Short() {
t.Skip()
}
t.Parallel()
ctx := context.Background()
s := &NoticesStore{
db: newTestDB(t, "NoticesStore"),
}
for _, tc := range []struct {
name string
test func(t *testing.T, ctx context.Context, s *NoticesStore)
}{
{"Create", noticesCreate},
{"DeleteByIDs", noticesDeleteByIDs},
{"DeleteAll", noticesDeleteAll},
{"List", noticesList},
{"Count", noticesCount},
} {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
err := clearTables(t, s.db)
require.NoError(t, err)
})
tc.test(t, ctx, s)
})
if t.Failed() {
break
}
}
}
func noticesCreate(t *testing.T, ctx context.Context, s *NoticesStore) {
err := s.Create(ctx, NoticeTypeRepository, "test")
require.NoError(t, err)
count := s.Count(ctx)
assert.Equal(t, int64(1), count)
}
func noticesDeleteByIDs(t *testing.T, ctx context.Context, s *NoticesStore) {
err := s.Create(ctx, NoticeTypeRepository, "test")
require.NoError(t, err)
notices, err := s.List(ctx, 1, 10)
require.NoError(t, err)
ids := make([]int64, 0, len(notices))
for _, notice := range notices {
ids = append(ids, notice.ID)
}
// Non-existing IDs should be ignored
ids = append(ids, 404)
err = s.DeleteByIDs(ctx, ids...)
require.NoError(t, err)
count := s.Count(ctx)
assert.Equal(t, int64(0), count)
}
func noticesDeleteAll(t *testing.T, ctx context.Context, s *NoticesStore) {
err := s.Create(ctx, NoticeTypeRepository, "test")
require.NoError(t, err)
err = s.DeleteAll(ctx)
require.NoError(t, err)
count := s.Count(ctx)
assert.Equal(t, int64(0), count)
}
func noticesList(t *testing.T, ctx context.Context, s *NoticesStore) {
err := s.Create(ctx, NoticeTypeRepository, "test 1")
require.NoError(t, err)
err = s.Create(ctx, NoticeTypeRepository, "test 2")
require.NoError(t, err)
got1, err := s.List(ctx, 1, 1)
require.NoError(t, err)
require.Len(t, got1, 1)
got2, err := s.List(ctx, 2, 1)
require.NoError(t, err)
require.Len(t, got2, 1)
assert.True(t, got1[0].ID > got2[0].ID)
got, err := s.List(ctx, 1, 3)
require.NoError(t, err)
require.Len(t, got, 2)
}
func noticesCount(t *testing.T, ctx context.Context, s *NoticesStore) {
count := s.Count(ctx)
assert.Equal(t, int64(0), count)
err := s.Create(ctx, NoticeTypeRepository, "test")
require.NoError(t, err)
count = s.Count(ctx)
assert.Equal(t, int64(1), count)
}

View File

@ -1,79 +0,0 @@
// Copyright 2022 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
import (
"context"
"github.com/pkg/errors"
"gorm.io/gorm"
"gogs.io/gogs/internal/dbutil"
)
// OrganizationsStore is the storage layer for organizations.
type OrganizationsStore struct {
db *gorm.DB
}
func newOrganizationsStoreStore(db *gorm.DB) *OrganizationsStore {
return &OrganizationsStore{db: db}
}
type ListOrgsOptions struct {
// Filter by the membership with the given user ID.
MemberID int64
// Whether to include private memberships.
IncludePrivateMembers bool
}
// List returns a list of organizations filtered by options.
func (s *OrganizationsStore) List(ctx context.Context, opts ListOrgsOptions) ([]*Organization, error) {
if opts.MemberID <= 0 {
return nil, errors.New("MemberID must be greater than 0")
}
/*
Equivalent SQL for PostgreSQL:
SELECT * FROM "org"
JOIN org_user ON org_user.org_id = org.id
WHERE
org_user.uid = @memberID
[AND org_user.is_public = @includePrivateMembers]
ORDER BY org.id ASC
*/
tx := s.db.WithContext(ctx).
Joins(dbutil.Quote("JOIN org_user ON org_user.org_id = %s.id", "user")).
Where("org_user.uid = ?", opts.MemberID).
Order(dbutil.Quote("%s.id ASC", "user"))
if !opts.IncludePrivateMembers {
tx = tx.Where("org_user.is_public = ?", true)
}
var orgs []*Organization
return orgs, tx.Find(&orgs).Error
}
// SearchByName returns a list of organizations whose username or full name
// matches the given keyword case-insensitively. Results are paginated by given
// page and page size, and sorted by the given order (e.g. "id DESC"). A total
// count of all results is also returned. If the order is not given, it's up to
// the database to decide.
func (s *OrganizationsStore) SearchByName(ctx context.Context, keyword string, page, pageSize int, orderBy string) ([]*Organization, int64, error) {
return searchUserByName(ctx, s.db, UserTypeOrganization, keyword, page, pageSize, orderBy)
}
// CountByUser returns the number of organizations the user is a member of.
func (s *OrganizationsStore) CountByUser(ctx context.Context, userID int64) (int64, error) {
var count int64
return count, s.db.WithContext(ctx).Model(&OrgUser{}).Where("uid = ?", userID).Count(&count).Error
}
type Organization = User
func (o *Organization) TableName() string {
return "user"
}

View File

@ -1,2 +0,0 @@
{"ID":1,"UserID":1,"Email":"alice@example.com","IsActivated":false}
{"ID":2,"UserID":2,"Email":"bob@example.com","IsActivated":true}

View File

@ -1 +0,0 @@
{"ID":1,"Type":1,"Description":"This is a notice","CreatedUnix":1588568886}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"context"
@ -17,6 +17,28 @@ import (
"gogs.io/gogs/internal/errutil"
)
// AccessTokensStore is the persistent interface for access tokens.
type AccessTokensStore interface {
// Create creates a new access token and persist to database. It returns
// ErrAccessTokenAlreadyExist when an access token with same name already exists
// for the user.
Create(ctx context.Context, userID int64, name string) (*AccessToken, error)
// DeleteByID deletes the access token by given ID.
//
// 🚨 SECURITY: The "userID" is required to prevent attacker deletes arbitrary
// access token that belongs to another user.
DeleteByID(ctx context.Context, userID, id int64) error
// GetBySHA1 returns the access token with given SHA1. It returns
// ErrAccessTokenNotExist when not found.
GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error)
// List returns all access tokens belongs to given user.
List(ctx context.Context, userID int64) ([]*AccessToken, error)
// Touch updates the updated time of the given access token to the current time.
Touch(ctx context.Context, id int64) error
}
var AccessTokens AccessTokensStore
// AccessToken is a personal access token.
type AccessToken struct {
ID int64 `gorm:"primarykey"`
@ -52,13 +74,10 @@ func (t *AccessToken) AfterFind(tx *gorm.DB) error {
return nil
}
// AccessTokensStore is the storage layer for access tokens.
type AccessTokensStore struct {
db *gorm.DB
}
var _ AccessTokensStore = (*accessTokens)(nil)
func newAccessTokensStore(db *gorm.DB) *AccessTokensStore {
return &AccessTokensStore{db: db}
type accessTokens struct {
*gorm.DB
}
type ErrAccessTokenAlreadyExist struct {
@ -66,21 +85,19 @@ type ErrAccessTokenAlreadyExist struct {
}
func IsErrAccessTokenAlreadyExist(err error) bool {
return errors.As(err, &ErrAccessTokenAlreadyExist{})
_, ok := err.(ErrAccessTokenAlreadyExist)
return ok
}
func (err ErrAccessTokenAlreadyExist) Error() string {
return fmt.Sprintf("access token already exists: %v", err.args)
}
// Create creates a new access token and persist to database. It returns
// ErrAccessTokenAlreadyExist when an access token with same name already exists
// for the user.
func (s *AccessTokensStore) Create(ctx context.Context, userID int64, name string) (*AccessToken, error) {
err := s.db.WithContext(ctx).Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
func (db *accessTokens) Create(ctx context.Context, userID int64, name string) (*AccessToken, error) {
err := db.WithContext(ctx).Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
if err == nil {
return nil, ErrAccessTokenAlreadyExist{args: errutil.Args{"userID": userID, "name": name}}
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
} else if err != gorm.ErrRecordNotFound {
return nil, err
}
@ -93,7 +110,7 @@ func (s *AccessTokensStore) Create(ctx context.Context, userID int64, name strin
Sha1: sha256[:40], // To pass the column unique constraint, keep the length of SHA1.
SHA256: sha256,
}
if err = s.db.WithContext(ctx).Create(accessToken).Error; err != nil {
if err = db.WithContext(ctx).Create(accessToken).Error; err != nil {
return nil, err
}
@ -102,12 +119,8 @@ func (s *AccessTokensStore) Create(ctx context.Context, userID int64, name strin
return accessToken, nil
}
// DeleteByID deletes the access token by given ID.
//
// 🚨 SECURITY: The "userID" is required to prevent attacker deletes arbitrary
// access token that belongs to another user.
func (s *AccessTokensStore) DeleteByID(ctx context.Context, userID, id int64) error {
return s.db.WithContext(ctx).Where("id = ? AND uid = ?", id, userID).Delete(new(AccessToken)).Error
func (db *accessTokens) DeleteByID(ctx context.Context, userID, id int64) error {
return db.WithContext(ctx).Where("id = ? AND uid = ?", id, userID).Delete(new(AccessToken)).Error
}
var _ errutil.NotFound = (*ErrAccessTokenNotExist)(nil)
@ -119,7 +132,8 @@ type ErrAccessTokenNotExist struct {
// IsErrAccessTokenNotExist returns true if the underlying error has the type
// ErrAccessTokenNotExist.
func IsErrAccessTokenNotExist(err error) bool {
return errors.As(errors.Cause(err), &ErrAccessTokenNotExist{})
_, ok := errors.Cause(err).(ErrAccessTokenNotExist)
return ok
}
func (err ErrAccessTokenNotExist) Error() string {
@ -130,9 +144,7 @@ func (ErrAccessTokenNotExist) NotFound() bool {
return true
}
// GetBySHA1 returns the access token with given SHA1. It returns
// ErrAccessTokenNotExist when not found.
func (s *AccessTokensStore) GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error) {
func (db *accessTokens) GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error) {
// No need to waste a query for an empty SHA1.
if sha1 == "" {
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha1}}
@ -140,26 +152,25 @@ func (s *AccessTokensStore) GetBySHA1(ctx context.Context, sha1 string) (*Access
sha256 := cryptoutil.SHA256(sha1)
token := new(AccessToken)
err := s.db.WithContext(ctx).Where("sha256 = ?", sha256).First(token).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha1}}
} else if err != nil {
err := db.WithContext(ctx).Where("sha256 = ?", sha256).First(token).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha1}}
}
return nil, err
}
return token, nil
}
// List returns all access tokens belongs to given user.
func (s *AccessTokensStore) List(ctx context.Context, userID int64) ([]*AccessToken, error) {
func (db *accessTokens) List(ctx context.Context, userID int64) ([]*AccessToken, error) {
var tokens []*AccessToken
return tokens, s.db.WithContext(ctx).Where("uid = ?", userID).Order("id ASC").Find(&tokens).Error
return tokens, db.WithContext(ctx).Where("uid = ?", userID).Order("id ASC").Find(&tokens).Error
}
// Touch updates the updated time of the given access token to the current time.
func (s *AccessTokensStore) Touch(ctx context.Context, id int64) error {
return s.db.WithContext(ctx).
func (db *accessTokens) Touch(ctx context.Context, id int64) error {
return db.WithContext(ctx).
Model(new(AccessToken)).
Where("id = ?", id).
UpdateColumn("updated_unix", s.db.NowFunc().Unix()).
UpdateColumn("updated_unix", db.NowFunc().Unix()).
Error
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"context"
@ -13,6 +13,7 @@ import (
"github.com/stretchr/testify/require"
"gorm.io/gorm"
"gogs.io/gogs/internal/dbtest"
"gogs.io/gogs/internal/errutil"
)
@ -97,14 +98,14 @@ func TestAccessTokens(t *testing.T) {
}
t.Parallel()
ctx := context.Background()
s := &AccessTokensStore{
db: newTestDB(t, "AccessTokensStore"),
tables := []any{new(AccessToken)}
db := &accessTokens{
DB: dbtest.NewDB(t, "accessTokens", tables...),
}
for _, tc := range []struct {
name string
test func(t *testing.T, ctx context.Context, s *AccessTokensStore)
test func(t *testing.T, db *accessTokens)
}{
{"Create", accessTokensCreate},
{"DeleteByID", accessTokensDeleteByID},
@ -114,10 +115,10 @@ func TestAccessTokens(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
err := clearTables(t, s.db)
err := clearTables(t, db.DB, tables...)
require.NoError(t, err)
})
tc.test(t, ctx, s)
tc.test(t, db)
})
if t.Failed() {
break
@ -125,9 +126,11 @@ func TestAccessTokens(t *testing.T) {
}
}
func accessTokensCreate(t *testing.T, ctx context.Context, s *AccessTokensStore) {
func accessTokensCreate(t *testing.T, db *accessTokens) {
ctx := context.Background()
// Create first access token with name "Test"
token, err := s.Create(ctx, 1, "Test")
token, err := db.Create(ctx, 1, "Test")
require.NoError(t, err)
assert.Equal(t, int64(1), token.UserID)
@ -135,12 +138,12 @@ func accessTokensCreate(t *testing.T, ctx context.Context, s *AccessTokensStore)
assert.Equal(t, 40, len(token.Sha1), "sha1 length")
// Get it back and check the Created field
token, err = s.GetBySHA1(ctx, token.Sha1)
token, err = db.GetBySHA1(ctx, token.Sha1)
require.NoError(t, err)
assert.Equal(t, s.db.NowFunc().Format(time.RFC3339), token.Created.UTC().Format(time.RFC3339))
assert.Equal(t, db.NowFunc().Format(time.RFC3339), token.Created.UTC().Format(time.RFC3339))
// Try create second access token with same name should fail
_, err = s.Create(ctx, token.UserID, token.Name)
_, err = db.Create(ctx, token.UserID, token.Name)
wantErr := ErrAccessTokenAlreadyExist{
args: errutil.Args{
"userID": token.UserID,
@ -150,25 +153,27 @@ func accessTokensCreate(t *testing.T, ctx context.Context, s *AccessTokensStore)
assert.Equal(t, wantErr, err)
}
func accessTokensDeleteByID(t *testing.T, ctx context.Context, s *AccessTokensStore) {
func accessTokensDeleteByID(t *testing.T, db *accessTokens) {
ctx := context.Background()
// Create an access token with name "Test"
token, err := s.Create(ctx, 1, "Test")
token, err := db.Create(ctx, 1, "Test")
require.NoError(t, err)
// Delete a token with mismatched user ID is noop
err = s.DeleteByID(ctx, 2, token.ID)
err = db.DeleteByID(ctx, 2, token.ID)
require.NoError(t, err)
// We should be able to get it back
_, err = s.GetBySHA1(ctx, token.Sha1)
_, err = db.GetBySHA1(ctx, token.Sha1)
require.NoError(t, err)
// Now delete this token with correct user ID
err = s.DeleteByID(ctx, token.UserID, token.ID)
err = db.DeleteByID(ctx, token.UserID, token.ID)
require.NoError(t, err)
// We should get token not found error
_, err = s.GetBySHA1(ctx, token.Sha1)
_, err = db.GetBySHA1(ctx, token.Sha1)
wantErr := ErrAccessTokenNotExist{
args: errutil.Args{
"sha": token.Sha1,
@ -177,17 +182,19 @@ func accessTokensDeleteByID(t *testing.T, ctx context.Context, s *AccessTokensSt
assert.Equal(t, wantErr, err)
}
func accessTokensGetBySHA(t *testing.T, ctx context.Context, s *AccessTokensStore) {
func accessTokensGetBySHA(t *testing.T, db *accessTokens) {
ctx := context.Background()
// Create an access token with name "Test"
token, err := s.Create(ctx, 1, "Test")
token, err := db.Create(ctx, 1, "Test")
require.NoError(t, err)
// We should be able to get it back
_, err = s.GetBySHA1(ctx, token.Sha1)
_, err = db.GetBySHA1(ctx, token.Sha1)
require.NoError(t, err)
// Try to get a non-existent token
_, err = s.GetBySHA1(ctx, "bad_sha")
_, err = db.GetBySHA1(ctx, "bad_sha")
wantErr := ErrAccessTokenNotExist{
args: errutil.Args{
"sha": "bad_sha",
@ -196,21 +203,23 @@ func accessTokensGetBySHA(t *testing.T, ctx context.Context, s *AccessTokensStor
assert.Equal(t, wantErr, err)
}
func accessTokensList(t *testing.T, ctx context.Context, s *AccessTokensStore) {
func accessTokensList(t *testing.T, db *accessTokens) {
ctx := context.Background()
// Create two access tokens for user 1
_, err := s.Create(ctx, 1, "user1_1")
_, err := db.Create(ctx, 1, "user1_1")
require.NoError(t, err)
_, err = s.Create(ctx, 1, "user1_2")
_, err = db.Create(ctx, 1, "user1_2")
require.NoError(t, err)
// Create one access token for user 2
_, err = s.Create(ctx, 2, "user2_1")
_, err = db.Create(ctx, 2, "user2_1")
require.NoError(t, err)
// List all access tokens for user 1
tokens, err := s.List(ctx, 1)
tokens, err := db.List(ctx, 1)
require.NoError(t, err)
require.Equal(t, 2, len(tokens), "number of tokens")
assert.Equal(t, 2, len(tokens), "number of tokens")
assert.Equal(t, int64(1), tokens[0].UserID)
assert.Equal(t, "user1_1", tokens[0].Name)
@ -219,19 +228,21 @@ func accessTokensList(t *testing.T, ctx context.Context, s *AccessTokensStore) {
assert.Equal(t, "user1_2", tokens[1].Name)
}
func accessTokensTouch(t *testing.T, ctx context.Context, s *AccessTokensStore) {
func accessTokensTouch(t *testing.T, db *accessTokens) {
ctx := context.Background()
// Create an access token with name "Test"
token, err := s.Create(ctx, 1, "Test")
token, err := db.Create(ctx, 1, "Test")
require.NoError(t, err)
// Updated field is zero now
assert.True(t, token.Updated.IsZero())
err = s.Touch(ctx, token.ID)
err = db.Touch(ctx, token.ID)
require.NoError(t, err)
// Get back from DB should have Updated set
token, err = s.GetBySHA1(ctx, token.Sha1)
token, err = db.GetBySHA1(ctx, token.Sha1)
require.NoError(t, err)
assert.Equal(t, s.db.NowFunc().Format(time.RFC3339), token.Updated.UTC().Format(time.RFC3339))
assert.Equal(t, db.NowFunc().Format(time.RFC3339), token.Updated.UTC().Format(time.RFC3339))
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"context"
@ -28,16 +28,61 @@ import (
"gogs.io/gogs/internal/tool"
)
// ActionsStore is the storage layer for actions.
type ActionsStore struct {
db *gorm.DB
// ActionsStore is the persistent interface for actions.
type ActionsStore interface {
// CommitRepo creates actions for pushing commits to the repository. An action
// with the type ActionDeleteBranch is created if the push deletes a branch; an
// action with the type ActionCommitRepo is created for a regular push. If the
// regular push also creates a new branch, then another action with type
// ActionCreateBranch is created.
CommitRepo(ctx context.Context, opts CommitRepoOptions) error
// ListByOrganization returns actions of the organization viewable by the actor.
// Results are paginated if `afterID` is given.
ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error)
// ListByUser returns actions of the user viewable by the actor. Results are
// paginated if `afterID` is given. The `isProfile` indicates whether repository
// permissions should be considered.
ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error)
// MergePullRequest creates an action for merging a pull request.
MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error
// MirrorSyncCreate creates an action for mirror synchronization of a new
// reference.
MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error
// MirrorSyncDelete creates an action for mirror synchronization of a reference
// deletion.
MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error
// MirrorSyncPush creates an action for mirror synchronization of pushed
// commits.
MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error
// NewRepo creates an action for creating a new repository. The action type
// could be ActionCreateRepo or ActionForkRepo based on whether the repository
// is a fork.
NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error
// PushTag creates an action for pushing tags to the repository. An action with
// the type ActionDeleteTag is created if the push deletes a tag. Otherwise, an
// action with the type ActionPushTag is created for a regular push.
PushTag(ctx context.Context, opts PushTagOptions) error
// RenameRepo creates an action for renaming a repository.
RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error
// TransferRepo creates an action for transferring a repository to a new owner.
TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error
}
func newActionsStore(db *gorm.DB) *ActionsStore {
return &ActionsStore{db: db}
var Actions ActionsStore
var _ ActionsStore = (*actions)(nil)
type actions struct {
*gorm.DB
}
func (s *ActionsStore) listByOrganization(ctx context.Context, orgID, actorID, afterID int64) *gorm.DB {
// NewActionsStore returns a persistent interface for actions with given
// database connection.
func NewActionsStore(db *gorm.DB) ActionsStore {
return &actions{DB: db}
}
func (db *actions) listByOrganization(ctx context.Context, orgID, actorID, afterID int64) *gorm.DB {
/*
Equivalent SQL for PostgreSQL:
@ -57,18 +102,18 @@ func (s *ActionsStore) listByOrganization(ctx context.Context, orgID, actorID, a
ORDER BY id DESC
LIMIT @limit
*/
return s.db.WithContext(ctx).
return db.WithContext(ctx).
Where("user_id = ?", orgID).
Where(s.db.
Where(db.
// Not apply when afterID is not given
Where("?", afterID <= 0).
Or("id < ?", afterID),
).
Where("repo_id IN (?)", s.db.
Where("repo_id IN (?)", db.
Select("repository.id").
Table("repository").
Joins("JOIN team_repo ON repository.id = team_repo.repo_id").
Where("team_repo.team_id IN (?)", s.db.
Where("team_repo.team_id IN (?)", db.
Select("team_id").
Table("team_user").
Where("team_user.org_id = ? AND uid = ?", orgID, actorID),
@ -79,14 +124,12 @@ func (s *ActionsStore) listByOrganization(ctx context.Context, orgID, actorID, a
Order("id DESC")
}
// ListByOrganization returns actions of the organization viewable by the actor.
// Results are paginated if `afterID` is given.
func (s *ActionsStore) ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error) {
func (db *actions) ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error) {
actions := make([]*Action, 0, conf.UI.User.NewsFeedPagingNum)
return actions, s.listByOrganization(ctx, orgID, actorID, afterID).Find(&actions).Error
return actions, db.listByOrganization(ctx, orgID, actorID, afterID).Find(&actions).Error
}
func (s *ActionsStore) listByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) *gorm.DB {
func (db *actions) listByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) *gorm.DB {
/*
Equivalent SQL for PostgreSQL:
@ -98,14 +141,14 @@ func (s *ActionsStore) listByUser(ctx context.Context, userID, actorID, afterID
ORDER BY id DESC
LIMIT @limit
*/
return s.db.WithContext(ctx).
return db.WithContext(ctx).
Where("user_id = ?", userID).
Where(s.db.
Where(db.
// Not apply when afterID is not given
Where("?", afterID <= 0).
Or("id < ?", afterID),
).
Where(s.db.
Where(db.
// Not apply when in not profile page or the user is viewing own profile
Where("?", !isProfile || actorID == userID).
Or("is_private = ? AND act_user_id = ?", false, userID),
@ -114,17 +157,14 @@ func (s *ActionsStore) listByUser(ctx context.Context, userID, actorID, afterID
Order("id DESC")
}
// ListByUser returns actions of the user viewable by the actor. Results are
// paginated if `afterID` is given. The `isProfile` indicates whether repository
// permissions should be considered.
func (s *ActionsStore) ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error) {
func (db *actions) ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, conf.UI.User.NewsFeedPagingNum)
return actions, s.listByUser(ctx, userID, actorID, afterID, isProfile).Find(&actions).Error
return actions, db.listByUser(ctx, userID, actorID, afterID, isProfile).Find(&actions).Error
}
// notifyWatchers creates rows in action table for watchers who are able to see the action.
func (s *ActionsStore) notifyWatchers(ctx context.Context, act *Action) error {
watches, err := newReposStore(s.db).ListWatches(ctx, act.RepoID)
func (db *actions) notifyWatchers(ctx context.Context, act *Action) error {
watches, err := NewReposStore(db.DB).ListWatches(ctx, act.RepoID)
if err != nil {
return errors.Wrap(err, "list watches")
}
@ -147,19 +187,16 @@ func (s *ActionsStore) notifyWatchers(ctx context.Context, act *Action) error {
actions = append(actions, clone(watch.UserID))
}
return s.db.Create(actions).Error
return db.Create(actions).Error
}
// NewRepo creates an action for creating a new repository. The action type
// could be ActionCreateRepo or ActionForkRepo based on whether the repository
// is a fork.
func (s *ActionsStore) NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error {
func (db *actions) NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error {
opType := ActionCreateRepo
if repo.IsFork {
opType = ActionForkRepo
}
return s.notifyWatchers(ctx,
return db.notifyWatchers(ctx,
&Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
@ -172,9 +209,8 @@ func (s *ActionsStore) NewRepo(ctx context.Context, doer, owner *User, repo *Rep
)
}
// RenameRepo creates an action for renaming a repository.
func (s *ActionsStore) RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error {
return s.notifyWatchers(ctx,
func (db *actions) RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error {
return db.notifyWatchers(ctx,
&Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
@ -188,8 +224,8 @@ func (s *ActionsStore) RenameRepo(ctx context.Context, doer, owner *User, oldRep
)
}
func (s *ActionsStore) mirrorSyncAction(ctx context.Context, opType ActionType, owner *User, repo *Repository, refName string, content []byte) error {
return s.notifyWatchers(ctx,
func (db *actions) mirrorSyncAction(ctx context.Context, opType ActionType, owner *User, repo *Repository, refName string, content []byte) error {
return db.notifyWatchers(ctx,
&Action{
ActUserID: owner.ID,
ActUserName: owner.Name,
@ -213,15 +249,13 @@ type MirrorSyncPushOptions struct {
Commits *PushCommits
}
// MirrorSyncPush creates an action for mirror synchronization of pushed
// commits.
func (s *ActionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error {
func (db *actions) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error {
if conf.UI.FeedMaxCommitNum > 0 && len(opts.Commits.Commits) > conf.UI.FeedMaxCommitNum {
opts.Commits.Commits = opts.Commits.Commits[:conf.UI.FeedMaxCommitNum]
}
apiCommits, err := opts.Commits.APIFormat(ctx,
newUsersStore(s.db),
NewUsersStore(db.DB),
repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name),
)
@ -254,24 +288,19 @@ func (s *ActionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOp
return errors.Wrap(err, "marshal JSON")
}
return s.mirrorSyncAction(ctx, ActionMirrorSyncPush, opts.Owner, opts.Repo, opts.RefName, data)
return db.mirrorSyncAction(ctx, ActionMirrorSyncPush, opts.Owner, opts.Repo, opts.RefName, data)
}
// MirrorSyncCreate creates an action for mirror synchronization of a new
// reference.
func (s *ActionsStore) MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error {
return s.mirrorSyncAction(ctx, ActionMirrorSyncCreate, owner, repo, refName, nil)
func (db *actions) MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error {
return db.mirrorSyncAction(ctx, ActionMirrorSyncCreate, owner, repo, refName, nil)
}
// MirrorSyncDelete creates an action for mirror synchronization of a reference
// deletion.
func (s *ActionsStore) MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error {
return s.mirrorSyncAction(ctx, ActionMirrorSyncDelete, owner, repo, refName, nil)
func (db *actions) MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error {
return db.mirrorSyncAction(ctx, ActionMirrorSyncDelete, owner, repo, refName, nil)
}
// MergePullRequest creates an action for merging a pull request.
func (s *ActionsStore) MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error {
return s.notifyWatchers(ctx,
func (db *actions) MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error {
return db.notifyWatchers(ctx,
&Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
@ -285,9 +314,8 @@ func (s *ActionsStore) MergePullRequest(ctx context.Context, doer, owner *User,
)
}
// TransferRepo creates an action for transferring a repository to a new owner.
func (s *ActionsStore) TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error {
return s.notifyWatchers(ctx,
func (db *actions) TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error {
return db.notifyWatchers(ctx,
&Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
@ -459,18 +487,13 @@ type CommitRepoOptions struct {
Commits *PushCommits
}
// CommitRepo creates actions for pushing commits to the repository. An action
// with the type ActionDeleteBranch is created if the push deletes a branch; an
// action with the type ActionCommitRepo is created for a regular push. If the
// regular push also creates a new branch, then another action with type
// ActionCreateBranch is created.
func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) error {
err := newReposStore(s.db).Touch(ctx, opts.Repo.ID)
func (db *actions) CommitRepo(ctx context.Context, opts CommitRepoOptions) error {
err := NewReposStore(db.DB).Touch(ctx, opts.Repo.ID)
if err != nil {
return errors.Wrap(err, "touch repository")
}
pusher, err := newUsersStore(s.db).GetByUsername(ctx, opts.PusherName)
pusher, err := NewUsersStore(db.DB).GetByUsername(ctx, opts.PusherName)
if err != nil {
return errors.Wrapf(err, "get pusher [name: %s]", opts.PusherName)
}
@ -513,7 +536,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
}
action.OpType = ActionDeleteBranch
err = s.notifyWatchers(ctx, action)
err = db.notifyWatchers(ctx, action)
if err != nil {
return errors.Wrap(err, "notify watchers")
}
@ -557,7 +580,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
}
action.OpType = ActionCreateBranch
err = s.notifyWatchers(ctx, action)
err = db.notifyWatchers(ctx, action)
if err != nil {
return errors.Wrap(err, "notify watchers")
}
@ -566,7 +589,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
}
commits, err := opts.Commits.APIFormat(ctx,
newUsersStore(s.db),
NewUsersStore(db.DB),
repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name),
)
@ -593,7 +616,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
}
action.OpType = ActionCommitRepo
err = s.notifyWatchers(ctx, action)
err = db.notifyWatchers(ctx, action)
if err != nil {
return errors.Wrap(err, "notify watchers")
}
@ -608,16 +631,13 @@ type PushTagOptions struct {
NewCommitID string
}
// PushTag creates an action for pushing tags to the repository. An action with
// the type ActionDeleteTag is created if the push deletes a tag. Otherwise, an
// action with the type ActionPushTag is created for a regular push.
func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error {
err := newReposStore(s.db).Touch(ctx, opts.Repo.ID)
func (db *actions) PushTag(ctx context.Context, opts PushTagOptions) error {
err := NewReposStore(db.DB).Touch(ctx, opts.Repo.ID)
if err != nil {
return errors.Wrap(err, "touch repository")
}
pusher, err := newUsersStore(s.db).GetByUsername(ctx, opts.PusherName)
pusher, err := NewUsersStore(db.DB).GetByUsername(ctx, opts.PusherName)
if err != nil {
return errors.Wrapf(err, "get pusher [name: %s]", opts.PusherName)
}
@ -652,7 +672,7 @@ func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error {
}
action.OpType = ActionDeleteTag
err = s.notifyWatchers(ctx, action)
err = db.notifyWatchers(ctx, action)
if err != nil {
return errors.Wrap(err, "notify watchers")
}
@ -676,14 +696,14 @@ func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error {
}
action.OpType = ActionPushTag
err = s.notifyWatchers(ctx, action)
err = db.notifyWatchers(ctx, action)
if err != nil {
return errors.Wrap(err, "notify watchers")
}
return nil
}
// ActionType is the type of action.
// ActionType is the type of an action.
type ActionType int
// ⚠️ WARNING: Only append to the end of list to maintain backward compatibility.
@ -852,7 +872,7 @@ func NewPushCommits() *PushCommits {
}
}
func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, repoPath, repoURL string) ([]*api.PayloadCommit, error) {
func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore UsersStore, repoPath, repoURL string) ([]*api.PayloadCommit, error) {
// NOTE: We cache query results in case there are many commits in a single push.
usernameByEmail := make(map[string]string)
getUsernameByEmail := func(email string) (string, error) {
@ -925,7 +945,7 @@ func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, r
func (pcs *PushCommits) AvatarLink(email string) string {
_, ok := pcs.avatars[email]
if !ok {
u, err := Handle.Users().GetByEmail(context.Background(), email)
u, err := Users.GetByEmail(context.Background(), email)
if err != nil {
pcs.avatars[email] = tool.AvatarLink(email)
if !IsErrUserNotExist(err) {

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"context"
@ -16,6 +16,7 @@ import (
"gorm.io/gorm"
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/dbtest"
)
func TestIssueReferencePattern(t *testing.T) {
@ -96,16 +97,16 @@ func TestActions(t *testing.T) {
if testing.Short() {
t.Skip()
}
ctx := context.Background()
t.Parallel()
s := &ActionsStore{
db: newTestDB(t, "ActionsStore"),
tables := []any{new(Action), new(User), new(Repository), new(EmailAddress), new(Watch)}
db := &actions{
DB: dbtest.NewDB(t, "actions", tables...),
}
for _, tc := range []struct {
name string
test func(t *testing.T, ctx context.Context, s *ActionsStore)
test func(t *testing.T, db *actions)
}{
{"CommitRepo", actionsCommitRepo},
{"ListByOrganization", actionsListByOrganization},
@ -121,10 +122,10 @@ func TestActions(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
err := clearTables(t, s.db)
err := clearTables(t, db.DB, tables...)
require.NoError(t, err)
})
tc.test(t, ctx, s)
tc.test(t, db)
})
if t.Failed() {
break
@ -132,10 +133,12 @@ func TestActions(t *testing.T) {
}
}
func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsCommitRepo(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -145,15 +148,13 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
now := time.Unix(1588568886, 0).UTC()
conf.SetMockSSH(t, conf.SSHOpts{})
t.Run("new commit", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.CommitRepo(ctx,
err = db.CommitRepo(ctx,
CommitRepoOptions{
PusherName: alice.Name,
Owner: alice,
@ -183,7 +184,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -200,7 +201,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RefName: "main",
IsPrivate: false,
Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -209,11 +210,11 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("new ref", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.CommitRepo(ctx,
err = db.CommitRepo(ctx,
CommitRepoOptions{
PusherName: alice.Name,
Owner: alice,
@ -243,7 +244,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 2)
got[0].ID = 0
@ -261,7 +262,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RefName: "main",
IsPrivate: false,
Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
{
UserID: alice.ID,
@ -274,7 +275,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RefName: "main",
IsPrivate: false,
Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -284,11 +285,11 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("delete ref", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.CommitRepo(ctx,
err = db.CommitRepo(ctx,
CommitRepoOptions{
PusherName: alice.Name,
Owner: alice,
@ -300,7 +301,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -316,7 +317,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoName: repo.Name,
RefName: "main",
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -324,12 +325,14 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
})
}
func actionsListByOrganization(t *testing.T, ctx context.Context, s *ActionsStore) {
func actionsListByOrganization(t *testing.T, db *actions) {
if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" {
t.Skip("Skipping testing with not using PostgreSQL")
return
}
ctx := context.Background()
conf.SetMockUI(t,
conf.UIOpts{
User: conf.UIUserOpts{
@ -362,20 +365,22 @@ func actionsListByOrganization(t *testing.T, ctx context.Context, s *ActionsStor
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got := s.db.ToSQL(func(tx *gorm.DB) *gorm.DB {
return newActionsStore(tx).listByOrganization(ctx, test.orgID, test.actorID, test.afterID).Find(new(Action))
got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
return NewActionsStore(tx).(*actions).listByOrganization(ctx, test.orgID, test.actorID, test.afterID).Find(new(Action))
})
assert.Equal(t, test.want, got)
})
}
}
func actionsListByUser(t *testing.T, ctx context.Context, s *ActionsStore) {
func actionsListByUser(t *testing.T, db *actions) {
if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" {
t.Skip("Skipping testing with not using PostgreSQL")
return
}
ctx := context.Background()
conf.SetMockUI(t,
conf.UIOpts{
User: conf.UIUserOpts{
@ -427,18 +432,20 @@ func actionsListByUser(t *testing.T, ctx context.Context, s *ActionsStore) {
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got := s.db.ToSQL(func(tx *gorm.DB) *gorm.DB {
return newActionsStore(tx).listByUser(ctx, test.userID, test.actorID, test.afterID, test.isProfile).Find(new(Action))
got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
return NewActionsStore(tx).(*actions).listByUser(ctx, test.userID, test.actorID, test.afterID, test.isProfile).Find(new(Action))
})
assert.Equal(t, test.want, got)
})
}
}
func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsMergePullRequest(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -446,7 +453,7 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore)
)
require.NoError(t, err)
err = s.MergePullRequest(ctx,
err = db.MergePullRequest(ctx,
alice,
alice,
repo,
@ -457,7 +464,7 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore)
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -473,17 +480,19 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore)
RepoName: repo.Name,
IsPrivate: false,
Content: `1|Fix issue 1`,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
assert.Equal(t, want, got)
}
func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsMirrorSyncCreate(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -491,14 +500,14 @@ func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, s *ActionsStore)
)
require.NoError(t, err)
err = s.MirrorSyncCreate(ctx,
err = db.MirrorSyncCreate(ctx,
alice,
repo,
"main",
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -514,17 +523,19 @@ func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, s *ActionsStore)
RepoName: repo.Name,
RefName: "main",
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
assert.Equal(t, want, got)
}
func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsMirrorSyncDelete(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -532,14 +543,14 @@ func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, s *ActionsStore)
)
require.NoError(t, err)
err = s.MirrorSyncDelete(ctx,
err = db.MirrorSyncDelete(ctx,
alice,
repo,
"main",
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -555,17 +566,19 @@ func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, s *ActionsStore)
RepoName: repo.Name,
RefName: "main",
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
assert.Equal(t, want, got)
}
func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsMirrorSyncPush(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -574,7 +587,7 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) {
require.NoError(t, err)
now := time.Unix(1588568886, 0).UTC()
err = s.MirrorSyncPush(ctx,
err = db.MirrorSyncPush(ctx,
MirrorSyncPushOptions{
Owner: alice,
Repo: repo,
@ -603,7 +616,7 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -620,17 +633,19 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) {
RefName: "main",
IsPrivate: false,
Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
assert.Equal(t, want, got)
}
func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsNewRepo(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -640,14 +655,14 @@ func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("new repo", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.NewRepo(ctx, alice, alice, repo)
err = db.NewRepo(ctx, alice, alice, repo)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -662,7 +677,7 @@ func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoUserName: alice.Name,
RepoName: repo.Name,
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -671,15 +686,15 @@ func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("fork repo", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
repo.IsFork = true
err = s.NewRepo(ctx, alice, alice, repo)
err = db.NewRepo(ctx, alice, alice, repo)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -694,7 +709,7 @@ func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoUserName: alice.Name,
RepoName: repo.Name,
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -702,15 +717,16 @@ func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
})
}
func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
func actionsPushTag(t *testing.T, db *actions) {
ctx := context.Background()
// NOTE: We set a noop mock here to avoid data race with other tests that writes
// to the mock server because this function holds a lock.
conf.SetMockServer(t, conf.ServerOpts{})
conf.SetMockSSH(t, conf.SSHOpts{})
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -720,11 +736,11 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("new tag", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.PushTag(ctx,
err = db.PushTag(ctx,
PushTagOptions{
Owner: alice,
Repo: repo,
@ -735,7 +751,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -751,7 +767,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoName: repo.Name,
RefName: "v1.0.0",
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -760,11 +776,11 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
t.Run("delete tag", func(t *testing.T) {
t.Cleanup(func() {
err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error
require.NoError(t, err)
})
err = s.PushTag(ctx,
err = db.PushTag(ctx,
PushTagOptions{
Owner: alice,
Repo: repo,
@ -775,7 +791,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -791,7 +807,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoName: repo.Name,
RefName: "v1.0.0",
IsPrivate: false,
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
@ -799,10 +815,12 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
})
}
func actionsRenameRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsRenameRepo(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -810,10 +828,10 @@ func actionsRenameRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
err = s.RenameRepo(ctx, alice, alice, "oldExample", repo)
err = db.RenameRepo(ctx, alice, alice, "oldExample", repo)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -829,19 +847,21 @@ func actionsRenameRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoName: repo.Name,
IsPrivate: false,
Content: "oldExample",
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)
assert.Equal(t, want, got)
}
func actionsTransferRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
alice, err := newUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
func actionsTransferRepo(t *testing.T, db *actions) {
ctx := context.Background()
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
bob, err := newUsersStore(s.db).Create(ctx, "bob", "bob@example.com", CreateUserOptions{})
bob, err := NewUsersStore(db.DB).Create(ctx, "bob", "bob@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := newReposStore(s.db).Create(ctx,
repo, err := NewReposStore(db.DB).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -849,10 +869,10 @@ func actionsTransferRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
)
require.NoError(t, err)
err = s.TransferRepo(ctx, alice, alice, bob, repo)
err = db.TransferRepo(ctx, alice, alice, bob, repo)
require.NoError(t, err)
got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false)
got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false)
require.NoError(t, err)
require.Len(t, got, 1)
got[0].ID = 0
@ -868,7 +888,7 @@ func actionsTransferRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
RepoName: repo.Name,
IsPrivate: false,
Content: "alice/example",
CreatedUnix: s.db.NowFunc().Unix(),
CreatedUnix: db.NowFunc().Unix(),
},
}
want[0].Created = time.Unix(want[0].CreatedUnix, 0)

118
internal/db/admin.go Normal file
View File

@ -0,0 +1,118 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package db
import (
"fmt"
"os"
"strings"
"time"
"github.com/unknwon/com"
log "unknwon.dev/clog/v2"
"xorm.io/xorm"
"gogs.io/gogs/internal/tool"
)
type NoticeType int
const (
NOTICE_REPOSITORY NoticeType = iota + 1
)
// Notice represents a system notice for admin.
type Notice struct {
ID int64
Type NoticeType
Description string `xorm:"TEXT"`
Created time.Time `xorm:"-" json:"-"`
CreatedUnix int64
}
func (n *Notice) BeforeInsert() {
n.CreatedUnix = time.Now().Unix()
}
func (n *Notice) AfterSet(colName string, _ xorm.Cell) {
switch colName {
case "created_unix":
n.Created = time.Unix(n.CreatedUnix, 0).Local()
}
}
// TrStr returns a translation format string.
func (n *Notice) TrStr() string {
return "admin.notices.type_" + com.ToStr(n.Type)
}
// CreateNotice creates new system notice.
func CreateNotice(tp NoticeType, desc string) error {
// Prevent panic if database connection is not available at this point
if x == nil {
return fmt.Errorf("could not save notice due database connection not being available: %d %s", tp, desc)
}
n := &Notice{
Type: tp,
Description: desc,
}
_, err := x.Insert(n)
return err
}
// CreateRepositoryNotice creates new system notice with type NOTICE_REPOSITORY.
func CreateRepositoryNotice(desc string) error {
return CreateNotice(NOTICE_REPOSITORY, desc)
}
// RemoveAllWithNotice removes all directories in given path and
// creates a system notice when error occurs.
func RemoveAllWithNotice(title, path string) {
if err := os.RemoveAll(path); err != nil {
desc := fmt.Sprintf("%s [%s]: %v", title, path, err)
log.Warn(desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
}
}
// CountNotices returns number of notices.
func CountNotices() int64 {
count, _ := x.Count(new(Notice))
return count
}
// Notices returns number of notices in given page.
func Notices(page, pageSize int) ([]*Notice, error) {
notices := make([]*Notice, 0, pageSize)
return notices, x.Limit(pageSize, (page-1)*pageSize).Desc("id").Find(&notices)
}
// DeleteNotice deletes a system notice by given ID.
func DeleteNotice(id int64) error {
_, err := x.Id(id).Delete(new(Notice))
return err
}
// DeleteNotices deletes all notices with ID from start to end (inclusive).
func DeleteNotices(start, end int64) error {
sess := x.Where("id >= ?", start)
if end > 0 {
sess.And("id <= ?", end)
}
_, err := sess.Delete(new(Notice))
return err
}
// DeleteNoticesByIDs deletes notices by given IDs.
func DeleteNoticesByIDs(ids []int64) error {
if len(ids) == 0 {
return nil
}
_, err := x.Where("id IN (" + strings.Join(tool.Int64sToStrings(ids), ",") + ")").Delete(new(Notice))
return err
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"fmt"
@ -28,7 +28,7 @@ type Attachment struct {
ReleaseID int64 `xorm:"INDEX"`
Name string
Created time.Time `xorm:"-" json:"-" gorm:"-"`
Created time.Time `xorm:"-" json:"-"`
CreatedUnix int64
}

View File

@ -1,4 +1,4 @@
package database
package db
import (
"bufio"
@ -25,9 +25,9 @@ import (
)
// getTableType returns the type name of a table definition without package name,
// e.g. *database.LFSObject -> LFSObject.
// e.g. *db.LFSObject -> LFSObject.
func getTableType(t any) string {
return strings.TrimPrefix(fmt.Sprintf("%T", t), "*database.")
return strings.TrimPrefix(fmt.Sprintf("%T", t), "*db.")
}
// DumpDatabase dumps all data from database to file system in JSON Lines format.
@ -153,7 +153,7 @@ func ImportDatabase(ctx context.Context, db *gorm.DB, dirPath string, verbose bo
default:
}
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*db.")
err := func() error {
tableFile := filepath.Join(dirPath, tableName+".json")
if !osutil.IsFile(tableFile) {
@ -245,7 +245,7 @@ func importLegacyTables(ctx context.Context, dirPath string, verbose bool) error
default:
}
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*db.")
tableFile := filepath.Join(dirPath, tableName+".json")
if !osutil.IsFile(tableFile) {
continue

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"bytes"
@ -31,9 +31,8 @@ func TestDumpAndImport(t *testing.T) {
}
t.Parallel()
const wantTables = 8
if len(Tables) != wantTables {
t.Fatalf("New table has added (want %d got %d), please add new tests for the table and update this check", wantTables, len(Tables))
if len(Tables) != 6 {
t.Fatalf("New table has added (want 6 got %d), please add new tests for the table and update this check", len(Tables))
}
db := dbtest.NewDB(t, "dumpAndImport", Tables...)
@ -132,19 +131,6 @@ func setupDBToDump(t *testing.T, db *gorm.DB) {
CreatedUnix: 1588568886,
},
&EmailAddress{
ID: 1,
UserID: 1,
Email: "alice@example.com",
IsActivated: false,
},
&EmailAddress{
ID: 2,
UserID: 2,
Email: "bob@example.com",
IsActivated: true,
},
&Follow{
ID: 1,
UserID: 1,
@ -190,13 +176,6 @@ func setupDBToDump(t *testing.T, db *gorm.DB) {
}),
CreatedUnix: 1588568886,
},
&Notice{
ID: 1,
Type: NoticeTypeRepository,
Description: "This is a notice",
CreatedUnix: 1588568886,
},
}
for _, val := range vals {
err := db.Create(val).Error

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"context"
@ -53,26 +53,26 @@ type Comment struct {
ID int64
Type CommentType
PosterID int64
Poster *User `xorm:"-" json:"-" gorm:"-"`
Poster *User `xorm:"-" json:"-"`
IssueID int64 `xorm:"INDEX"`
Issue *Issue `xorm:"-" json:"-" gorm:"-"`
Issue *Issue `xorm:"-" json:"-"`
CommitID int64
Line int64
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-" json:"-" gorm:"-"`
RenderedContent string `xorm:"-" json:"-"`
Created time.Time `xorm:"-" json:"-" gorm:"-"`
Created time.Time `xorm:"-" json:"-"`
CreatedUnix int64
Updated time.Time `xorm:"-" json:"-" gorm:"-"`
Updated time.Time `xorm:"-" json:"-"`
UpdatedUnix int64
// Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"`
Attachments []*Attachment `xorm:"-" json:"-" gorm:"-"`
Attachments []*Attachment `xorm:"-" json:"-"`
// For view issue page.
ShowTag CommentTag `xorm:"-" json:"-" gorm:"-"`
ShowTag CommentTag `xorm:"-" json:"-"`
}
func (c *Comment) BeforeInsert() {
@ -95,7 +95,7 @@ func (c *Comment) AfterSet(colName string, _ xorm.Cell) {
func (c *Comment) loadAttributes(e Engine) (err error) {
if c.Poster == nil {
c.Poster, err = Handle.Users().GetByID(context.TODO(), c.PosterID)
c.Poster, err = Users.GetByID(context.TODO(), c.PosterID)
if err != nil {
if IsErrUserNotExist(err) {
c.PosterID = -1

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"fmt"
@ -40,18 +40,14 @@ func newLogWriter() (logger.Writer, error) {
// Tables is the list of struct-to-table mappings.
//
// NOTE: Lines are sorted in alphabetical order, each letter in its own line.
//
// ⚠️ WARNING: This list is meant to be read-only.
var Tables = []any{
new(Access), new(AccessToken), new(Action),
new(EmailAddress),
new(Follow),
new(LFSObject), new(LoginSource),
new(Notice),
}
// NewConnection returns a new database connection with the given logger.
func NewConnection(w logger.Writer) (*gorm.DB, error) {
// Init initializes the database with given logger.
func Init(w logger.Writer) (*gorm.DB, error) {
level := logger.Info
if conf.IsProdMode() {
level = logger.Warn
@ -102,14 +98,14 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
}
// NOTE: GORM has problem detecting existing columns, see
// https://github.com/gogs/gogs/issues/6091. Therefore, only use it to create new
// tables, and do customize migration with future changes.
// https://github.com/gogs/gogs/issues/6091. Therefore only use it to create new
// tables, and do customized migration with future changes.
for _, table := range Tables {
if db.Migrator().HasTable(table) {
continue
}
name := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
name := strings.TrimPrefix(fmt.Sprintf("%T", table), "*db.")
err = db.Migrator().AutoMigrate(table)
if err != nil {
return nil, errors.Wrapf(err, "auto migrate %q", name)
@ -117,77 +113,22 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
log.Trace("Auto migrated %q", name)
}
loadedLoginSourceFilesStore, err = loadLoginSourceFiles(filepath.Join(conf.CustomDir(), "conf", "auth.d"), db.NowFunc)
sourceFiles, err := loadLoginSourceFiles(filepath.Join(conf.CustomDir(), "conf", "auth.d"), db.NowFunc)
if err != nil {
return nil, errors.Wrap(err, "load login source files")
}
// Initialize the database handle.
Handle = &DB{db: db}
// Initialize stores, sorted in alphabetical order.
AccessTokens = &accessTokens{DB: db}
Actions = NewActionsStore(db)
EmailAddresses = NewEmailAddressesStore(db)
LoginSources = &loginSources{DB: db, files: sourceFiles}
LFS = &lfs{DB: db}
Orgs = NewOrgsStore(db)
Perms = NewPermsStore(db)
Repos = NewReposStore(db)
TwoFactors = &twoFactors{DB: db}
Users = NewUsersStore(db)
return db, nil
}
// DB is the database handler for the storage layer.
type DB struct {
db *gorm.DB
}
// Handle is the global database handle. It could be `nil` during the
// installation mode.
//
// NOTE: Because we need to register all the routes even during the installation
// mode (which initially has no database configuration), we have to use a global
// variable since we can't pass a database handler around before it's available.
//
// NOTE: It is not guarded by a mutex because it is only written once either
// during the service start or during the installation process (which is a
// single-thread process).
var Handle *DB
func (db *DB) AccessTokens() *AccessTokensStore {
return newAccessTokensStore(db.db)
}
func (db *DB) Actions() *ActionsStore {
return newActionsStore(db.db)
}
func (db *DB) LFS() *LFSStore {
return newLFSStore(db.db)
}
// NOTE: It is not guarded by a mutex because it only gets written during the
// service start.
var loadedLoginSourceFilesStore loginSourceFilesStore
func (db *DB) LoginSources() *LoginSourcesStore {
return newLoginSourcesStore(db.db, loadedLoginSourceFilesStore)
}
func (db *DB) Notices() *NoticesStore {
return newNoticesStore(db.db)
}
func (db *DB) Organizations() *OrganizationsStore {
return newOrganizationsStoreStore(db.db)
}
func (db *DB) Permissions() *PermissionsStore {
return newPermissionsStore(db.db)
}
func (db *DB) PublicKey() *PublicKeysStore {
return newPublicKeysStore(db.db)
}
func (db *DB) Repositories() *RepositoriesStore {
return newReposStore(db.db)
}
func (db *DB) TwoFactors() *TwoFactorsStore {
return newTwoFactorsStore(db.db)
}
func (db *DB) Users() *UsersStore {
return newUsersStore(db.db)
}

View File

@ -0,0 +1,80 @@
// Copyright 2022 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package db
import (
"context"
"fmt"
"github.com/pkg/errors"
"gorm.io/gorm"
"gogs.io/gogs/internal/errutil"
)
// EmailAddressesStore is the persistent interface for email addresses.
type EmailAddressesStore interface {
// GetByEmail returns the email address with given email. If `needsActivated` is
// true, only activated email will be returned, otherwise, it may return
// inactivated email addresses. It returns ErrEmailNotExist when no qualified
// email is not found.
GetByEmail(ctx context.Context, email string, needsActivated bool) (*EmailAddress, error)
}
var EmailAddresses EmailAddressesStore
var _ EmailAddressesStore = (*emailAddresses)(nil)
type emailAddresses struct {
*gorm.DB
}
// NewEmailAddressesStore returns a persistent interface for email addresses
// with given database connection.
func NewEmailAddressesStore(db *gorm.DB) EmailAddressesStore {
return &emailAddresses{DB: db}
}
var _ errutil.NotFound = (*ErrEmailNotExist)(nil)
type ErrEmailNotExist struct {
args errutil.Args
}
// IsErrEmailAddressNotExist returns true if the underlying error has the type
// ErrEmailNotExist.
func IsErrEmailAddressNotExist(err error) bool {
_, ok := errors.Cause(err).(ErrEmailNotExist)
return ok
}
func (err ErrEmailNotExist) Error() string {
return fmt.Sprintf("email address does not exist: %v", err.args)
}
func (ErrEmailNotExist) NotFound() bool {
return true
}
func (db *emailAddresses) GetByEmail(ctx context.Context, email string, needsActivated bool) (*EmailAddress, error) {
tx := db.WithContext(ctx).Where("email = ?", email)
if needsActivated {
tx = tx.Where("is_activated = ?", true)
}
emailAddress := new(EmailAddress)
err := tx.First(emailAddress).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrEmailNotExist{
args: errutil.Args{
"email": email,
},
}
}
return nil, err
}
return emailAddress, nil
}

View File

@ -0,0 +1,77 @@
// Copyright 2022 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package db
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gogs.io/gogs/internal/dbtest"
"gogs.io/gogs/internal/errutil"
)
func TestEmailAddresses(t *testing.T) {
if testing.Short() {
t.Skip()
}
t.Parallel()
tables := []any{new(EmailAddress)}
db := &emailAddresses{
DB: dbtest.NewDB(t, "emailAddresses", tables...),
}
for _, tc := range []struct {
name string
test func(t *testing.T, db *emailAddresses)
}{
{"GetByEmail", emailAddressesGetByEmail},
} {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(func() {
err := clearTables(t, db.DB, tables...)
require.NoError(t, err)
})
tc.test(t, db)
})
if t.Failed() {
break
}
}
}
func emailAddressesGetByEmail(t *testing.T, db *emailAddresses) {
ctx := context.Background()
const testEmail = "alice@example.com"
_, err := db.GetByEmail(ctx, testEmail, false)
wantErr := ErrEmailNotExist{
args: errutil.Args{
"email": testEmail,
},
}
assert.Equal(t, wantErr, err)
// TODO: Use EmailAddresses.Create to replace SQL hack when the method is available.
err = db.Exec(`INSERT INTO email_address (uid, email, is_activated) VALUES (1, ?, FALSE)`, testEmail).Error
require.NoError(t, err)
got, err := db.GetByEmail(ctx, testEmail, false)
require.NoError(t, err)
assert.Equal(t, testEmail, got.Email)
// Should not return if we only want activated emails
_, err = db.GetByEmail(ctx, testEmail, true)
assert.Equal(t, wantErr, err)
// TODO: Use EmailAddresses.MarkActivated to replace SQL hack when the method is available.
err = db.Exec(`UPDATE email_address SET is_activated = TRUE WHERE email = ?`, testEmail).Error
require.NoError(t, err)
got, err = db.GetByEmail(ctx, testEmail, true)
require.NoError(t, err)
assert.Equal(t, testEmail, got.Email)
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package database
package db
import (
"fmt"

Some files were not shown because too many files have changed in this diff Show More