Compare commits

..

72 commits

Author SHA1 Message Date
Matthias Riße
941978ccd6 fix: set committer identity for p2phttp processes (#76)
Some checks failed
/ release (push) Waiting to run
/ build-oci-image (rootful) (push) Failing after 1m30s
/ build-oci-image (rootless) (push) Failing after 1m28s
testing / backend-checks (push) Successful in 30m42s
testing / frontend-checks (push) Successful in 3m25s
testing / test-unit (push) Has been skipped
testing / test-e2e (push) Has been skipped
testing / test-mysql (push) Failing after 46m55s
testing / test-pgsql (push) Failing after 1h1m39s
testing / test-sqlite (push) Failing after 1h21m26s
testing / test-remote-cacher (redis) (push) Has been skipped
testing / security-check (push) Has been skipped
testing / test-remote-cacher (valkey) (push) Has been skipped
testing / test-remote-cacher (garnet) (push) Has been skipped
testing / test-remote-cacher (redict) (push) Has been skipped
Just setting GIT_AUTHOR_{NAME,EMAIL} wasn't enough,
GIT_COMMITTER_{NAME,EMAIL} is also required.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/76
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
matrss
8dfc054035 Forgejo-aneksajo branding (#71)
The original logo was created by Caesar Schinas and is licensed under
the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA
4.0) license.

This implies permission to remix.

Source: https://codeberg.org/forgejo/governance/src/branch/main/branding#logo

The git-annex logo is covered by

```
Copyright: 2007 Henrik Nyh <http://henrik.nyh.se/>
           2010 Joey Hess <id@joeyh.name>
           2013 John Lawrence
           2024 Yann Büchau <nobodyinperson at posteo de>
License: other
  Free to modify and redistribute with due credit, and obviously free to use.
```

Source: https://git-annex.branchable.com/logo/
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/71
2025-06-12 15:16:47 +02:00
Matthias Riße
c38d65118b fix: set git identity for p2phttp processes (#70)
In some situations it could happen that `git annex p2phttp` needs some
kind of maintenance work resulting in a commit, but without a configured
git identity p2phttp would refuse to run. This could break p2phttp
support.

Setting `GIT_AUTHOR_{NAME,EMAIL}` should remedy this issue.

Fixes #69.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/70
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
1eefa7e461 feat: copy annexed files on pull request merge (#62)
This changes the PR merge process such that annexed files contained in the to-be-merged commits are copied from the head repository to the base repository as part of the merge, similar to how it is done for LFS files.

Fixes #11.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/62
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
243aa534b5 fix: improve git-annex UUID cache update times (#65)
Globbing for the config files is marginally faster than walking the
directory and checking for config files. Replacing the expensive calls
to `git config` for each repository with reading the repository's config
as an ini file is two orders of magnitude faster.

All in all this reduces the required time initializing the cache for
approx. 3000 repositories from approx. 5s to 50ms.

The server startup now also logs how long the cache update took and the
cache update is only done if p2phttp support is not disabled, because
p2phttp support is currently the only feature that requires the UUID
cache.

Fixes #63, fixes #64.

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/65
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
2bce84f4e6 Use annexed content for comparison in diffs (#57)
This makes it such that annexed files are treated like plain git files
in comparisons (e.g. the diff of a commit).

It also changes the image diff viewer to show a more reasonable error
message when one of the annexed files under comparison is missing.

Fixes #56.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/57
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
382c22b9fd Invalidate outdated annex UUID cache entries (#60)
The previous implementation could lead to errors e.g. when a repository
was removed and a new one with a new UUID was created under the same
name. This now checks the validity of the retrieved cache entry every
time and invalidates the cache if necessary.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/60
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
9642986bc3 Pre-populate the git-annex UUID cache at startup (#59)
This eliminates the wait time for the first p2phttp connection since
server startup at the cost of adding that time to the startup itself.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/59
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
63bf28d641 Cache git-annex UUID to repository path mappings (#54)
Always walking the filesystem and searching for UUIDs slowed p2phttp
operations down significantly on a production server with more than a
handful of repositories. This caching strategy ensures that only the
first call is rather slow, and subsequent ones should be much faster.

This should better be implemented as a background job, but for now this
is a simple solution to the problem.

Fixes #53.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/54
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
864ff830de Explicitly set http(s) default ports in annex.url (#55)
Otherwise, git-annex tries to use its own default port (9417) and fails.

Fixes #52.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/55
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:47 +02:00
Matthias Riße
8d026ef459 Fix Forgejo version in published OCI images (#51)
The Forgejo version is derived from the git history, so the image build
needs to happen in the context of a full repository clone.

Also, the post-processing of the version string needs to remove the
second occurrence of "-g", as the first one is now part of the added
"-git-annex" part.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/51
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
b3f59b8104 Add an OCI image build and publish workflow (#50)
Fixes #49.

Reviewed-on: https://codeberg.org/forgejo-aneksajo/forgejo-aneksajo/pulls/50
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
9044e035e7 Simplify git blob to annex key lookup (#43)
Fixes #27.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/43
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
a0671027f6 Add git-annex p2phttp support (#42)
This adds a new endpoint under `/git-annex-p2phttp` which acts as an
authenticating proxy to git-annex' p2phttp server. This makes it
possible to set `annex+<server-url>/git-annex-p2phttp` as
`remote.<name>.annexurl` and use git-annex fully over http(s) with the
normal credentials and access tokens provided by Forgejo.

Fixes #25.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/42
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
70db833e76 Add tests for git annex drop (#47)
This adds some rudimentary tests that drop files in a repository's clone
as well as from a repository on Forgejo.

Fixes #4.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/47
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
fd300fd235 Add git-annex' testremote to the test suite (#48)
The `git annex testremote` command runs a built-in set of tests against
a remote. It cannot hurt to check our implementation of a git-annex
remote against it too.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/48
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
e608b7fac4 Only upload to annex in doAnnexUploadTest (#46)
The previous implementation both uploaded to the annex and pushed to the
git repository. This meant that the tests checking that uploads without
permission fail actually could pass when the git push failed but the
git-annex upload didn't. The tests didn't catch the situation where
unauthorized users could modify the annex.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/46
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
69d42f2f81 Use PATH when looking for git commands (#44)
This fixes some issues when using a git-annex that is installed in a
different location than where git is installed, e.g. when using the
git-annex-standalone release or one installed with nix.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/44
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Michael Hanke
ac4b8e579c Elevate external markup renderer interface for annexed file content (#36)
Previously, an external renderer that matched on an annexed file would
only see its content streamed via `STDIN`, or a temporary file with a copy
of its content would be generated and passed-by-filepath (with
`IS_INPUT_FILE=true`). Whether that happens, is also subject to
`MAX_DISPLAY_FILE_SIZE` (which defaults to 8MB).

This was problematic, because annexed files tend to be large. Moreover,
if present, they already exist as write-protected files on the
file-system. Creating a copy is both expensive and serves no particular
purpose.

This commit changes how external renderers are called.

1) With `IS_INPUT_FILE=true`, the renderer is passed the true location
   of an annex key, if present, and an empty path, if not.
2) The original, repository-relative path of the rendering target is
   made available to the renderer via the `GITEA_RELATIVE_PATH`
   environment variable.

To achieve a lean implementation, the `Blob` of the rendering target
is passed on to the `RenderContext` (because the implementation of
the annex-related functionality is centered on this dtype.

This change makes it less costly to increase `MAX_DISPLAY_FILE_SIZE`,
in order to make large, annexed files eligible for markup rendering,
because no content copies will be made any longer.

External renderers can now use the original file path, with the full
original filename, including extensions, for decision making. For
example, to detect particular compression formats based in a file name
extension, or to alter the rendering based on contextual information
encoded in the file path (e.g., a multi-file data structure with a
particular organization pattern).

Apart from the additional environment variable, there is no change to
the handling of renderers that take their input via `STDIN` (i.e.,
`IS_INPUT_FILE=false`).

Fixes #35.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/36
Reviewed-by: matrss <matrss@noreply.codeberg.org>
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Co-committed-by: Michael Hanke <michael.hanke@gmail.com>
2025-06-12 15:16:46 +02:00
Matthias Riße
945d723776 Change the icon for annexed files to file-binary (#29)
Fixes #26.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/29
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
e3cb0ebfd0 Improve views for annexed but missing files (#28)
Previously, trying to view files that were annexed, but missing, just
led to an uninformative error 500. This was rather confusing.

With these changes it now shows the pointer target instead of the
(missing) content of the file, and also indicates this situation in the
"stored with git-annex" message. For semantic correctness views for
missing files return a 404 instead of a 200, as they would with the
content present.

Fixes #7, fixes #13.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/28
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Michael Hanke
8edbc40475 Add git-annex also to the rootless container (#24)
Same as 89f8aa0bf5, but for the rootless container.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/24
Reviewed-by: matrss <matrss@noreply.codeberg.org>
Co-authored-by: Michael Hanke <michael.hanke@gmail.com>
Co-committed-by: Michael Hanke <michael.hanke@gmail.com>
2025-06-12 15:16:46 +02:00
Matthias Riße
36d2cdeab8 Git-annex web uploads (#21)
This implements support for uploading files into the annex using the web
interface.

If a repository is a git-annex-enabled repository all files will be
added to it using git annex add. This means that the repository's
configuration for what to put into the annex (annex.largefiles in
gitattributes) will be respected.

Plain git repositories without git-annex will work as before, directly
uploading to git.

Fixes #5.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/21
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
a57a7df088 Error if git-annex is enabled but missing (#16)
Copied from https://github.com/neuropoly/gitea/pull/47

This adds a check so that if `setting.Annex.Enabled` is true and git-annex is not in the PATH Forgejo will abort on startup with a reasonable error message.

Fixes #15.

Reviewed-on: https://codeberg.org/matrss/forgejo-aneksajo/pulls/16
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
Co-committed-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:46 +02:00
Matthias Riße
4d537d3399 Add git-annex to docker image 2025-06-12 15:16:46 +02:00
Matthias Riße
ae1c051cd0 Adapt patch to upstream changes
Test with different objectFormats.
2025-06-12 15:16:46 +02:00
Nick
227f0c0c7c git-annex: views for annex files
This updates the repo index/file view endpoints so annex files match the way
LFS files are rendered, making annexed files accessible via the web instead of
being black boxes only accessible by git clone.

This mostly just duplicates the existing LFS logic. It doesn't try to combine itself
with the existing logic, to make merging with upstream easier. If upstream ever
decides to accept, I would like to try to merge the redundant logic.

The one bit that doesn't directly copy LFS is my choice to hide annex-symlinks.
LFS files are always _pointer files_ and therefore always render with the "file"
icon and no special label, but annex files come in two flavours: symlinks or
pointer files. I've conflated both kinds to try to give a consistent experience.

The tests in here ensure the correct download link (/media, from the last PR)
renders in both the toolbar and, if a binary file (like most annexed files will be),
in the main pane, but it also adds quite a bit of code to make sure text files
that happen to be annexed are dug out and rendered inline like LFS files are.
2025-06-12 15:16:46 +02:00
Matthias Riße
8f7583454c Adapt patch to upstream changes
Use tests.FileCmp instead of util.FileCmp.
2025-06-12 15:16:46 +02:00
Matthias Riße
5326357578 Adapt patch to upstream changes
Test with different objectFormats.
2025-06-12 15:16:46 +02:00
Nick
3091d08359 git-annex: make /media/ download annexed content
Previously, Gitea's LFS support allowed direct-downloads of LFS content,
via http://$HOSTNAME:$PORT/$USER/$REPO/media/branch/$BRANCH/$FILE
Expand that grace to git-annex too. Now /media should provide the
relevant *content* from the .git/annex/objects/ folder.

This adds tests too. And expands the tests to try symlink-based annexing,
since /media implicitly supports both that and pointer-file-based annexing.
2025-06-12 15:16:45 +02:00
Matthias Riße
f7e27e2c61 Adapt patch to upstream changes
The git repository must be closed after using it. Without this change
some tests started to fail due to the lingering repository running into
a timeout.
2025-06-12 15:16:45 +02:00
Nick
8f5e08da72 git-annex: create modules/annex
This moves the `annexObjectPath()` helper out of the tests and into a
dedicated sub-package as `annex.ContentLocation()`, and expands it with
`.Pointer()` (which validates using `git annex examinekey`),
`.IsAnnexed()` and `.Content()` to make it a more useful module.

The tests retain their own wrapper version of `ContentLocation()`
because I tried to follow close to the API modules/lfs uses, which in
terms of abstract `git.Blob` and `git.TreeEntry` objects, not in terms
of `repoPath string`s which are more convenient for the tests.
2025-06-12 15:16:45 +02:00
Matthias Riße
7cc829b466 Adapt patch to upstream changes
The "context_service" import was changed to use the default name of just
"context". The patch set had to be adapted for that.
2025-06-12 15:16:45 +02:00
Matthias Riße
257dd3a241 Adapt patch to upstream changes
Usage of `path` was replaced by `path/filepath` in upstream forgejo, and
it made sense to use that as well where `path` was previously used. The
`setHeaderCacheForever` function and the `sendFile` method had their
signature changed.
2025-06-12 15:16:45 +02:00
Matthias Riße
d52b0beb04 Fix exit code check for git command
The err.IsExitCode method was changed to a function IsErrorExitCode
taking err as its first argument in
1e7a6483b8.
2025-06-12 15:16:45 +02:00
Matthias Riße
709a2b1032 Replace m.GetOptions with m.Methods
This applies the same changes that were done in
265cd70bdb to the git-annex specific
routes as well.
2025-06-12 15:16:45 +02:00
Nick
96639554a1 git-annex: support downloading over HTTP
This makes HTTP symmetric with SSH clone URLs.

This gives us the fancy feature of _anonymous_ downloads,
so people can access datasets without having to set up an
account or manage ssh keys.

Previously, to access "open access" data shared this way,
users would need to:

  1. Create an account on gitea.example.com
  2. Create ssh keys
  3. Upload ssh keys (and make sure to find and upload the correct file)
  4. `git clone git@gitea.example.com:user/dataset.git`
  5. `cd dataset`
  6. `git annex get`

This cuts that down to just the last three steps:

  1. `git clone https://gitea.example.com/user/dataset.git`
  2. `cd dataset`
  3. `git annex get`

This is significantly simpler for downstream users, especially for those
unfamiliar with the command line.

Unfortunately there's no uploading. While git-annex supports uploading
over HTTP to S3 and some other special remotes, it seems to fail on a
_plain_ HTTP remote. See https://github.com/neuropoly/gitea/issues/7
and https://git-annex.branchable.com/forum/HTTP_uploads/#comment-ce28adc128fdefe4c4c49628174d9b92.

This is not a major loss since no one wants uploading to be anonymous anyway.

To support private repos, I had to hunt down and patch a secret extra security
corner that Gitea only applies to HTTP for some reason (services/auth/basic.go).

This was guided by https://git-annex.branchable.com/tips/setup_a_public_repository_on_a_web_site/

Fixes https://github.com/neuropoly/gitea/issues/3

Co-authored-by: Mathieu Guay-Paquet <mathieu.guaypaquet@polymtl.ca>
2025-06-12 15:16:45 +02:00
Nick
4eef1f0299 git-annex: add configuration setting [annex].ENABLED
Fixes https://github.com/neuropoly/gitea/issues/8

Co-authored-by: Mathieu Guay-Paquet <mathieu.guaypaquet@gmail.com>
2025-06-12 15:16:45 +02:00
Matthias Riße
108ceba1f8 Fix failing tests
Multiple tests that worked fine on v1.20.4-1 started to fail after the
rebase onto v1.20.5-1. These tests are:
- TestGitAnnexPermissions/Private/Owner/HTTP/Init
- TestGitAnnexPermissions/Private/Owner/HTTP/Download
- TestGitAnnexPermissions/Private/Writer/HTTP/Init
- TestGitAnnexPermissions/Private/Writer/HTTP/Download
- TestGitAnnexPermissions/Private/Reader/HTTP/Init
- TestGitAnnexPermissions/Private/Reader/HTTP/Download

What these tests have in common is that they all operate on a private
repository via http with authentication.

They broke at some point between v1.20.4-1 and v1.20.5-1, so I did a
bisect between these two points running the offending tests. This
brought me to the conclusion that
ee48c0d5ea introduced the issue.

The thing is, this commit does not change any code, it only changes the
test environment. Among other things that didn't look as suspicious, it
changes the container image from a bespoke test_env image based on
debian bullseye to a node image based on debian bookworm. Obviously,
this means that there are many version differences between the two.

The first one I looked at was git. The previous bullseye image used a
manually installed git version 2.40.0, while the bookworm image has
2.39.2 installed. Updating git in the new image did not fix the issue,
however.

The next thing I looked at was the git-annex version. Bullseye had
8.20210223 installed and worked, while bookworm used 10.20230126 when
the tests broke. So I tried my luck upgrading to a more recent version
via neurodebian (10.20240227-1~ndall+1). This still worked fine on
bullseye and now also works fine on bookworm.

I have no idea why this specific version of git-annex broke the tests,
but at least there was a commit to pinpoint this to, which isn't always
the case with docker images silently changing beneath you...

Below are the versions as they are reported by git and git-annex:

bullseye (works):

    git version 2.30.2
    git-annex version: 8.20210223
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22 bloomfilter-2.0.1.0 cryptonite-0.26 DAV-1.3.4 feed-1.3.0.1 ghc-8.8.4 http-client-0.6.4.1 persistent-sqlite-2.10.6.2 torrent-10000.1.1 uuid-1.3.13 yesod-1.6.1.0
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7

bullseye + git-annex from neurodebian (works):

    git version 2.30.2
    git-annex version: 10.20240227-1~ndall+1
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10

bookworm (fails):

    git version 2.39.2
    git-annex version: 10.20230126
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10

bookworm + git-annex from neurodebian (works):

    git version 2.39.2
    git-annex version: 10.20240227-1~ndall+1
    build flags: Assistant Webapp Pairing Inotify DBus DesktopNotify TorrentParser MagicMime Benchmark Feeds Testsuite S3 WebDAV
    dependency versions: aws-0.22.1 bloomfilter-2.0.1.0 cryptonite-0.29 DAV-1.3.4 feed-1.3.2.1 ghc-9.0.2 http-client-0.7.13.1 persistent-sqlite-2.13.1.0 torrent-10000.1.1 uuid-1.3.15 yesod-1.6.2.1
    key/value backends: SHA256E SHA256 SHA512E SHA512 SHA224E SHA224 SHA384E SHA384 SHA3_256E SHA3_256 SHA3_512E SHA3_512 SHA3_224E SHA3_224 SHA3_384E SHA3_384 SKEIN256E SKEIN256 SKEIN512E SKEIN512 BLAKE2B256E BLAKE2B256 BLAKE2B512E BLAKE2B512 BLAKE2B160E BLAKE2B160 BLAKE2B224E BLAKE2B224 BLAKE2B384E BLAKE2B384 BLAKE2BP512E BLAKE2BP512 BLAKE2S256E BLAKE2S256 BLAKE2S160E BLAKE2S160 BLAKE2S224E BLAKE2S224 BLAKE2SP256E BLAKE2SP256 BLAKE2SP224E BLAKE2SP224 SHA1E SHA1 MD5E MD5 WORM URL X*
    remote types: git gcrypt p2p S3 bup directory rsync web bittorrent webdav adb tahoe glacier ddar git-lfs httpalso borg hook external
    operating system: linux x86_64
    supported repository versions: 8 9 10
    upgrade supported from repository versions: 0 1 2 3 4 5 6 7 8 9 10
2025-06-12 15:16:45 +02:00
Matthias Riße
fb1ebf705d Install git-annex in the testing workflow 2025-06-12 15:16:45 +02:00
Matthias Riße
d588b9e0d3 Adapt patch to upstream changes 2025-06-12 15:16:45 +02:00
Matthias Riße
2834de417c Adapt patch to upstream changes
A dead code check started to complain because FileCmp was only used in
tests. Moved the function to test_utils.
2025-06-12 15:16:45 +02:00
Matthias Riße
75ae8a96bb Adapt patch to upstream changes
Repository creation now expects an objectFormat to be specified for git.
2025-06-12 15:16:45 +02:00
Nick
f69784d5c1 git-annex tests
Fixes https://github.com/neuropoly/gitea/issues/11

Tests:

* `git annex init`
* `git annex copy --from origin`
* `git annex copy --to origin`

over:

* ssh

for:

* the owner
* a collaborator
* a read-only collaborator
* a stranger

in a

* public repo
* private repo

And then confirms:

* Deletion of the remote repo (to ensure lockdown isn't messing with us: https://git-annex.branchable.com/internals/lockdown/#comment-0cc5225dc5abe8eddeb843bfd2fdc382)

------

To support all this:

* Add util.FileCmp()
* Patch withKeyFile() so it can be nested in other copies of itself

-------

Many thanks to Mathieu for giving style tips and catching several bugs,
including a subtle one in util.filecmp() which neutered it.

Co-authored-by: Mathieu Guay-Paquet <mathieu.guay-paquet@polymtl.ca>
Co-authored-by: Matthias Riße <m.risse@fz-juelich.de>
2025-06-12 15:16:45 +02:00
Nick Guenther
d3dbd61e14 git-annex support
[git-annex](https://git-annex.branchable.com/) is a more complicated cousin to
git-lfs, storing large files in an optional-download side content.  Unlike lfs,
it allows mixing and matching storage remotes, so the content remote(s) doesn't
need to be on the same server as the git remote, making it feasible to scatter
a collection across cloud storage, old harddrives, or anywhere else storage can
be scavenged.  Since this can get complicated, fast, it has a content-tracking
database (`git annex whereis`) to help find everything later.

The use-case we imagine for including it in Gitea is just the simple case, where
we're primarily emulating git-lfs: each repo has its large content at the same URL.

Our motivation is so we can self-host https://www.datalad.org/ datasets, which
currently are only hostable by fragilely scrounging together cloud storage --
and having to manage all the credentials associated with all the pieces -- or at
https://openneuro.org which is fragile in its own ways.

Supporting git-annex also allows multiple Gitea instance to be annex remotes for
each other, mirroring the content or otherwise collaborating the split up the
hosting costs.

Enabling
--------

TODO

HTTP
----

TODO

Permission Checking
-------------------

This tweaks the API in routers/private/serv.go to expose the calling user's
computed permission, instead of just returning HTTP 403.

This doesn't fit in super well. It's the opposite from how the git-lfs support is
done, where there's a complete list of possible subcommands and their matching
permission levels, and then the API compares the requested with the actual level
and returns HTTP 403 if the check fails.

But it's necessary. The main git-annex verbs, 'git-annex-shell configlist' and
'git-annex-shell p2pstdio' are both either read-only or read-write operations,
depending on the state on disk on either end of the connection and what the user
asked it to ask for, with no way to know before git-annex examines the situation.
So tell the level via GIT_ANNEX_READONLY and trust it to handle itself.

In the older Gogs version, the permission was directly read in cmd/serv.go:

```
mode, err = db.UserAccessMode(user.ID, repo)
```
- 966e925cf3/internal/cmd/serv.go (L334)

but in Gitea permission enforcement has been centralized in the API layer.
(perhaps so the cmd layer can avoid making direct DB connections?)

Deletion
--------

git-annex has this "lockdown" feature where it tries
really quite very hard to prevent you deleting its
data, to the point that even an rm -rf won't do it:
each file in annex/objects/ is nested inside a
folder with read-only permissions.

The recommended workaround is to run chmod -R +w when
you're sure you actually want to delete a repo. See
https://git-annex.branchable.com/internals/lockdown

So we edit util.RemoveAll() to do just that, so now
it's `chmod -R +w && rm -rf` instead of just `rm -rf`.
2025-06-12 15:16:45 +02:00
Matthias Riße
d82022e992 Fix name in package-lock.json
The frontend-checks job started failing because the declared name does
not match the repository name.
2025-06-12 15:16:45 +02:00
Matthias Riße
d8168eb42f Run testing workflow unconditionally 2025-06-12 15:16:45 +02:00
Earl Warren
661028623c [v11.0/forgejo] fix(sec): consider webauthn for external login (#7756)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7756
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-02 06:26:31 +00:00
Earl Warren
5a54ce0fbc [v11.0/forgejo] fix(sec): only degrade permission check for git push (#7753)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7753
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-02 06:26:18 +00:00
Gusted
5bb61cf6c2
fix(sec): add tests for OAuth2 signup
Test two scenarios:
1. Account linking is set to `auto` and tries to link against a user who
is enrolled into Webauthn should show 2FA screen.
2. User is already linked and logins via OAuth2 and is enrolled into
WebAuthn should show 2FA screen.

(cherry picked from commit aa4ae81fe0)
2025-05-02 07:33:33 +02:00
Gusted
5d7953def4
fix(sec): consider webauthn for external login
- Currently during external login (such as OAuth2), if the user is
enrolled into Webauthn and not enrolled into TOTP then no 2FA is being
done during external login and when account linking is set to `auto` then
also during automatic linking. This results in bypassing the 2FA of the
user.
- Create a new unified function that checks if the user is enrolled into
2FA and use this when necessary. Rename the old `HasTwoFactorByUID`
function to `HasTOTPByUID` which is a more appropiate naming.

(cherry picked from commit df5d656827)

Conflicts:
  the original commit was trimmed down to be fit for backport
2025-05-02 07:31:20 +02:00
Gusted
5816106de5
fix(sec): only degrade permission check for git push
- A permission check is done when incoming SSH connections are handled (this is
run before git hooks). If this check is for write access and AGit flow
is supported, then this check is degraded to a read check. The
motivation behind this is that for AGit flow the user does not need
write permissions but only read permissions.
- The `if` condition cannot check if this is for AGit flow, as the Git
protocol has not run yet and thus has to delay this permission check.
This `if` condition failed to consider that this also might be run for
LFS which does not care about AGit flow and would not do a delayed
permission check, so ensure that this degradition only happens when the
`git-receive-pack` command is being run (which roughly equals to `git
push`).
- Clarify code comment.
- Added integration test.

(cherry picked from commit 60c1af244a)
2025-05-02 07:05:38 +02:00
0ko
c5601e9399 [v11.0/forgejo] (merge commit) i18n: backport of translation updates (#7743)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7743
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-05-01 11:24:07 +00:00
0ko
1d15e243e4 [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 4a51a1f360

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Dirk <dirk@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: Panagiotis \"Ivory\" Vasilopoulos <git@n0toose.net>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Yushu <yushu@noreply.codeberg.org>
Co-authored-by: aleksi <aleksi@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: docudoc <docudoc@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: hugoalh <hugoalh@noreply.codeberg.org>
Co-authored-by: mimsee <mimsee@noreply.codeberg.org>
Co-authored-by: pixelcode <pixelcode@noreply.codeberg.org>
Co-authored-by: tacaly <frederick@tacaly.com>
Co-authored-by: xtex <xtexchooser@duck.com>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/nds/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hant/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/da/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/el/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ru/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/sv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:39:19 +05:00
0ko
97220d1ce9 [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 8958dee86e

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Caesar Schinas <caesar@caesarschinas.com>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Dirk <dirk@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Juno Takano <jutty@noreply.codeberg.org>
Co-authored-by: Kita Ikuyo <kitakita@disroot.org>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: alperen <alperen@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: mengzhuo <mengzhuo@noreply.codeberg.org>
Co-authored-by: neighborsbear <neighborsbear@noreply.codeberg.org>
Co-authored-by: otf31 <otf31@noreply.codeberg.org>
Co-authored-by: pboguslawski <pboguslawski@noreply.codeberg.org>
Co-authored-by: whytf <whytf@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: yurtpage <yurtpage@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/ko/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/sk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fil/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ko/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nds/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ru/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/sk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/tr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:38:05 +05:00
0ko
44a5cd3b7a [v11.0/forgejo] i18n: update of translations from Codeberg Translate
Translation updates that are applicable to v11 strings were picked from this commit: 4fe172e4b2

Changes to strings that are only present in the v12 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to being v12-only.

Co-authored-by: Caesar Schinas <caesar@caesarschinas.com>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Miguel P.L <miguel_pl@noreply.codeberg.org>
Co-authored-by: PeterDaveHello <peterdavehello@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: antaanimosity <antaanimosity@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: lucasmz.dev <git@lucasmz.dev>
Co-authored-by: oscarotero <oscarotero@noreply.codeberg.org>
Co-authored-by: otf31 <otf31@noreply.codeberg.org>
Co-authored-by: themandalorian <themandalorian@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: zerica <zerica@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/es/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/gl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-05-01 15:36:39 +05:00
Gusted
6a9fb3dbbc [v11.0/forgejo] chore: replace github.com/go-testfixtures/testfixtures (#7729)
**Backport:** #7715

- Replaces `github.com/go-testfixtures/testfixtures` with a homebrew solution that is fully compatible.
- The reason to replace this library is that it pulls in a lot of other libraries which is causing issues: (1) the test binary becomes bigger than necessary which really shows in incremental build times (this patch removes 27.6MiB of the integration test binary) (2) it pulls in libraries (mainly database drivers) that are not used and are not easy to upgrade in case of a security vulnerability, causing CI failures.

(cherry picked from commit 32e64ccd34)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7729
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2025-04-30 13:21:04 +00:00
forgejo-backport-action
fe07c90636 [v11.0/forgejo] chore(release): next-digest moved to invisible.forgejo.org (#7723)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7720

In order to improve the security of the Forgejo infrastructure the next-digest repository was moved to a private instance.

## Testing

- After the merge, trigger a mirror to build a new v12.0-test release
- Verify in experimental that the workflows works as expected
- Verify v12.next.forgejo.org is upgraded with the latest commit
- Once the test completes
    - Tag for backport to v11 & v7
    - Manual backport to v7 because it conflicts

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7723
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-29 18:10:53 +00:00
forgejo-backport-action
4215476cee [v11.0/forgejo] chore: tune down remote user promotion debug message shown as error (#7691)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7687

It is not an error for a remote user to not be promoted: this is the case for all users created via OAuth. Displaying an error is confusing to the admin when seen in the logs.

Refs: https://codeberg.org/forgejo/forgejo/issues/7681

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7691
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-29 13:31:36 +00:00
forgejo-backport-action
e837350319 [v11.0/forgejo] fix: use linguist-generated for language stats (#7694)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7685

- Adds code comment to explain behavior of the `linguist-generated` gitattribute.
- Adjusts the code to ignore the file if `linguist-generated` is true.
- Resolves forgejo/forgejo#7677
- Adds unit testing.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7694): <!--number 7694 --><!--line 0 --><!--description Zml4OiB1c2UgYGxpbmd1aXN0LWdlbmVyYXRlZGAgZm9yIGxhbmd1YWdlIHN0YXRz-->fix: use `linguist-generated` for language stats<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7694
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-28 06:52:28 +00:00
forgejo-backport-action
bc6c0b610b [v11.0/forgejo] fix: set default restricted for OAuth2 user (#7688)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7683

- The OAuthCallback code that is responsible for creating a new user, if one does not exist yet, did not use `[service].ALLOW_ONLY_EXTERNAL_REGISTRATION` as default value for the restricted field of a user.
- Resolves forgejo/forgejo#7681
- Add integration test.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7688
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-27 21:25:42 +00:00
forgejo-backport-action
b067d0df6e [v11.0/forgejo] fix: display the list of tasks in the runner edit page (#7652)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7650

A regression was introduced in Forgejo v11.0 that caused the edit page of a runner (e.g. https://example.org/admin/actions/runners/434) to no longer display the tasks associated with the runner.

Fixes https://codeberg.org/forgejo/forgejo/issues/7643

---

When the fix is absent, the tests fail like so:

```
--- FAIL: TestRunnerDetails (0.03s)
    --- FAIL: TestRunnerDetails/first_page (0.00s)
        runners_test.go:36:
            	Error Trace:	/home/earl-warren/software/forgejo/routers/web/shared/actions/runners_test.go:36
            	Error:      	"[]" should have 30 item(s), but has 0
            	Test:       	TestRunnerDetails/first_page
    --- FAIL: TestRunnerDetails/second_and_last_page (0.00s)
        runners_test.go:43:
            	Error Trace:	/home/earl-warren/software/forgejo/routers/web/shared/actions/runners_test.go:43
            	Error:      	"[]" should have 10 item(s), but has 0
            	Test:       	TestRunnerDetails/second_and_last_page
FAIL
FAIL	forgejo.org/routers/web/shared/actions	0.170s
```

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- User Interface bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): <!--number 7650 --><!--line 0 --><!--description ZGlzcGxheSB0aGUgbGlzdCBvZiB0YXNrcyBpbiB0aGUgcnVubmVyIGVkaXQgcGFnZQ==-->display the list of tasks in the runner edit page<!--description-->
<!--end release-notes-assistant-->

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- User Interface bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): <!--number 7650 --><!--line 0 --><!--description ZGlzcGxheSB0aGUgbGlzdCBvZiB0YXNrcyBpbiB0aGUgcnVubmVyIGVkaXQgcGFnZQ==-->display the list of tasks in the runner edit page<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7652
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-25 12:38:14 +00:00
forgejo-backport-action
c5bfe77873 [v11.0/forgejo] chore: merge tests.AddFixtures and unittest.OverrideFixtures (#7649)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7648

The only parameter that is ever used is a single directory, make it that only instead of a more complex option structure.

Remove tests.AddFixtures that was the simpler form because it is now redundant.

---

Backporting to v11.0 will help with automated backporting of bug fixes in need of custom made fixtures.

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7649
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-25 09:59:30 +00:00
Otto
b2241c3939 [v11.0/forgejo] fix(ui): make pagination labels always visible to screenreader (#7642)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7642
Reviewed-by: Otto <otto@codeberg.org>
2025-04-24 23:13:15 +00:00
Gusted
a4396782b5 fix(ui): make pagination labels always visible to screenreader
- The pagination labels 'First', 'Previous', 'Next' and 'Last' are
hidden away when the screen width becomes smaller. However this also
hides them from the screen reader. Instead of using `display: none`, use
some well-known tricks to still make them visible to the screen reader.
- Add E2E test.
- Resolves Codeberg/Community#1858

(cherry picked from commit b6072496d4)
2025-04-24 22:37:46 +00:00
forgejo-backport-action
55cff9cfb4 [v11.0/forgejo] fix(i18n): prevent incorrect logging on strings missing in JSON locales (#7599)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7594

Fixes https://codeberg.org/forgejo/forgejo/issues/7591
Followup to https://codeberg.org/forgejo/forgejo/pulls/6203

Without the 3rd commit, when this test runs, an error message appears in the logs:
```
[E] Missing translation "incorrect_root_url"
```

With it, it does not. No changes to the actual locale handling are expected and I'm hoping there's enough other testing in place for that.

Reported-by: Paweł Bogusławski <pboguslawski@noreply.codeberg.org>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7599
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-23 13:44:16 +00:00
forgejo-backport-action
5ffe4e54e1 [v11.0/forgejo] fix: delay-write trace.dat for forgejo diagnosis (#7601)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7597

- Delay the writing of `trace.dat` to the forgejo diagnosis zip file. It's not possible to write `cpu-profile.dat` and `trace.dat` at the same time. This caused the implemention to prematurely close `cpu-profile.dat` and leave it as an empty file.
- Regression of forgejo/forgejo#6470

## Testing
1. Go to `/admin/monitor`
2. Click on "Download diagnosis report"
3. Open the zip file and check that all files are non-empty.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7601
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-23 13:40:51 +00:00
forgejo-backport-action
9147665e2c [v11.0/forgejo] fix(ui): use gap in switch items (#7589)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7581

Followup to _many PRs_ where the old switches were converted to this one.

The main change here is to the switch with counter. It was missing a gap.

Additionally, it removes tailwind helpers the other switches retained from before switch refactors, because they are now using gap.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7589
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-21 09:42:23 +00:00
0ko
5395eea338 [v11.0/forgejo] fix(ui): rescope menu height patch to overflow menu (#7583)
Followup to https://codeberg.org/forgejo/forgejo/pulls/7108
v11-specific backport of https://codeberg.org/forgejo/forgejo/pulls/7578, see details here (change 2)

Preview:
https://codeberg.org/attachments/661c50be-7673-4970-a78b-5852b1138417)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7583
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2025-04-21 07:20:28 +00:00
forgejo-backport-action
973bc33a5f [v11.0/forgejo] fix(ui/pr): use eye icon for reviews (#7585)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7584

Followup to #6523
Reverts icon change introduced in #5695

It went unnoticed since v10 and was likely caused by bad copy paste and I don't think it's really worth a test.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7585
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-04-20 21:18:49 +00:00
Beowulf
722ea4179c [v11.0/forgejo] fix(ui): show commit icon in branch dropdown button when viewing a commit (#7576)
Backport: https://codeberg.org/forgejo/forgejo/pulls/7571
Replaces https://codeberg.org/forgejo/forgejo/pulls/7574

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7576
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-committed-by: Beowulf <beowulf@beocode.eu>
2025-04-19 07:03:09 +00:00
Renovate Bot
9ebdc09939 Update module github.com/mattn/go-sqlite3 to v1.14.28 (v11.0/forgejo) (#7563)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) | require | patch | `v1.14.24` -> `v1.14.28` |

---

### Release Notes

<details>
<summary>mattn/go-sqlite3 (github.com/mattn/go-sqlite3)</summary>

### [`v1.14.28`](https://github.com/mattn/go-sqlite3/compare/v1.14.27...v1.14.28)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.27...v1.14.28)

### [`v1.14.27`](https://github.com/mattn/go-sqlite3/compare/v1.14.26...v1.14.27)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.26...v1.14.27)

### [`v1.14.26`](https://github.com/mattn/go-sqlite3/compare/v1.14.25...v1.14.26)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.25...v1.14.26)

### [`v1.14.25`](https://github.com/mattn/go-sqlite3/compare/v1.14.24...v1.14.25)

[Compare Source](https://github.com/mattn/go-sqlite3/compare/v1.14.24...v1.14.25)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - "* 0-3 * * *" (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNDAuMSIsInVwZGF0ZWRJblZlciI6IjM5LjI0MC4xIiwidGFyZ2V0QnJhbmNoIjoidjExLjAvZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7563
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-04-17 06:34:55 +00:00
114 changed files with 1125 additions and 1996 deletions

View file

@ -2,6 +2,8 @@
#
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
#
# TOKEN_NEXT_DIGEST is a token with write repository access to https://invisible.forgejo.org/infrastructure/next-digest issued by https://invisible.forgejo.org/forgejo-next-digest
#
# https://codeberg.org/forgejo-experimental/forgejo
#
# Copies a release from codeberg.org/forgejo-integration to codeberg.org/forgejo-experimental
@ -14,7 +16,7 @@
# vars.DOER: forgejo-experimental-ci
# secrets.TOKEN: <generated from codeberg.org/forgejo-experimental-ci>
#
# http://private.forgejo.org/forgejo/forgejo
# http://invisible.forgejo.org/forgejo/forgejo
#
# Copies & sign a release from codeberg.org/forgejo-integration to codeberg.org/forgejo
#
@ -80,7 +82,7 @@ jobs:
- name: upgrade v*.next.forgejo.org
uses: https://data.forgejo.org/infrastructure/next-digest@v1.1.0
with:
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@invisible.forgejo.org/infrastructure/next-digest
ref_name: '${{ github.ref_name }}'
image: 'codeberg.org/forgejo-experimental/forgejo'
tag_suffix: '-rootless'

47
go.mod
View file

@ -48,7 +48,6 @@ require (
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-openapi/spec v0.20.14
github.com/go-sql-driver/mysql v1.9.1
github.com/go-testfixtures/testfixtures/v3 v3.14.0
github.com/go-webauthn/webauthn v0.12.2
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
@ -72,7 +71,7 @@ require (
github.com/lib/pq v1.10.9
github.com/markbates/goth v1.80.0
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.24
github.com/mattn/go-sqlite3 v1.14.28
github.com/meilisearch/meilisearch-go v0.31.0
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.27
@ -118,21 +117,11 @@ require (
)
require (
cel.dev/expr v0.19.1 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.9.9 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.2.1 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
cloud.google.com/go/monitoring v1.21.1 // indirect
cloud.google.com/go/spanner v1.73.0 // indirect
dario.cat/mergo v1.0.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/RoaringBitmap/roaring v1.9.3 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
@ -164,7 +153,6 @@ require (
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@ -173,11 +161,8 @@ require (
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect
@ -185,12 +170,10 @@ require (
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/swag v0.22.7 // indirect
github.com/go-webauthn/x v0.1.19 // indirect
github.com/go-webauthn/x v0.1.20 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
@ -201,10 +184,6 @@ require (
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.3 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/googleapis/go-sql-spanner v1.7.4 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
@ -235,13 +214,13 @@ require (
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/rhysd/actionlint v1.6.27 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
@ -252,18 +231,9 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/zeebo/assert v1.3.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.etcd.io/bbolt v1.4.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
@ -271,11 +241,6 @@ require (
golang.org/x/mod v0.24.0 // indirect
golang.org/x/time v0.10.0 // indirect
golang.org/x/tools v0.31.0 // indirect
google.golang.org/api v0.203.0 // indirect
google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.71.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

1539
go.sum

File diff suppressed because it is too large Load diff

View file

@ -4,14 +4,12 @@
package auth_test
import (
"path/filepath"
"slices"
"testing"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -275,13 +273,7 @@ func TestBuiltinApplicationsClientIDs(t *testing.T) {
}
func TestOrphanedOAuth2Applications(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/auth/TestOrphanedOAuth2Applications/"},
},
)()
defer unittest.OverrideFixtures("models/auth/TestOrphanedOAuth2Applications")()
require.NoError(t, unittest.PrepareTestDatabase())
count, err := auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)

21
models/auth/two_factor.go Normal file
View file

@ -0,0 +1,21 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"context"
)
// HasTwoFactorByUID returns true if the user has TOTP or WebAuthn enabled for
// their account.
func HasTwoFactorByUID(ctx context.Context, userID int64) (bool, error) {
hasTOTP, err := HasTOTPByUID(ctx, userID)
if err != nil {
return false, err
}
if hasTOTP {
return true, nil
}
return HasWebAuthnRegistrationsByUID(ctx, userID)
}

View file

@ -0,0 +1,34 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"testing"
"forgejo.org/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHasTwoFactorByUID(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
t.Run("No twofactor", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 2)
require.NoError(t, err)
assert.False(t, ok)
})
t.Run("WebAuthn credential", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 32)
require.NoError(t, err)
assert.True(t, ok)
})
t.Run("TOTP", func(t *testing.T) {
ok, err := HasTwoFactorByUID(t.Context(), 24)
require.NoError(t, err)
assert.True(t, ok)
})
}

View file

@ -139,9 +139,9 @@ func GetTwoFactorByUID(ctx context.Context, uid int64) (*TwoFactor, error) {
return twofa, nil
}
// HasTwoFactorByUID returns the two-factor authentication token associated with
// the user, if any.
func HasTwoFactorByUID(ctx context.Context, uid int64) (bool, error) {
// HasTOTPByUID returns the TOTP authentication token associated with
// the user, if the user has TOTP enabled for their account.
func HasTOTPByUID(ctx context.Context, uid int64) (bool, error) {
return db.GetEngine(ctx).Where("uid=?", uid).Exist(&TwoFactor{})
}

View file

@ -5,7 +5,6 @@ package git
import (
"context"
"path/filepath"
"testing"
"forgejo.org/models/db"
@ -18,13 +17,7 @@ import (
)
func TestIterateRepositoryIDsWithLFSMetaObjects(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/git/TestIterateRepositoryIDsWithLFSMetaObjects/"},
},
)()
defer unittest.OverrideFixtures("models/git/TestIterateRepositoryIDsWithLFSMetaObjects")()
require.NoError(t, unittest.PrepareTestDatabase())
type repocount struct {

View file

@ -20,7 +20,7 @@ import (
)
func TestPrivateIssueProjects(t *testing.T) {
defer tests.AddFixtures("models/fixtures/PrivateIssueProjects/")()
defer unittest.OverrideFixtures("models/fixtures/PrivateIssueProjects")()
require.NoError(t, unittest.PrepareTestDatabase())
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -119,7 +119,7 @@ func TestPrivateIssueProjects(t *testing.T) {
}
func TestPrivateRepoProjects(t *testing.T) {
defer tests.AddFixtures("models/fixtures/TestPrivateRepoProjects/")()
defer unittest.OverrideFixtures("models/fixtures/TestPrivateRepoProjects")()
require.NoError(t, unittest.PrepareTestDatabase())
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})

View file

@ -14,7 +14,6 @@ import (
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/setting"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -161,7 +160,7 @@ func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
}
func TestGetUnmergedPullRequestsByHeadInfoMax(t *testing.T) {
defer tests.AddFixtures("models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax/")()
defer unittest.OverrideFixtures("models/fixtures/TestGetUnmergedPullRequestsByHeadInfoMax")()
require.NoError(t, unittest.PrepareTestDatabase())
repoID := int64(1)

View file

@ -4,14 +4,12 @@
package issues_test
import (
"path/filepath"
"testing"
"forgejo.org/models/db"
issues_model "forgejo.org/models/issues"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/setting"
"forgejo.org/modules/timeutil"
"github.com/stretchr/testify/assert"
@ -81,13 +79,7 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
}
func TestGetUIDsAndStopwatch(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/issues/TestGetUIDsAndStopwatch/"},
},
)()
defer unittest.OverrideFixtures("models/issues/TestGetUIDsAndStopwatch")()
require.NoError(t, unittest.PrepareTestDatabase())
uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext)

View file

@ -4,14 +4,12 @@
package organization_test
import (
"path/filepath"
"testing"
"forgejo.org/models/db"
"forgejo.org/models/organization"
"forgejo.org/models/perm"
"forgejo.org/models/unittest"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -189,13 +187,7 @@ func TestHasTeamRepo(t *testing.T) {
}
func TestInconsistentOwnerTeam(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/organization/TestInconsistentOwnerTeam/"},
},
)()
defer unittest.OverrideFixtures("models/organization/TestInconsistentOwnerTeam")()
require.NoError(t, unittest.PrepareTestDatabase())
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, TeamID: 1000, AccessMode: perm.AccessModeNone})

View file

@ -4,11 +4,9 @@
package packages
import (
"path/filepath"
"testing"
"forgejo.org/models/unittest"
"forgejo.org/modules/setting"
_ "forgejo.org/models"
_ "forgejo.org/models/actions"
@ -16,16 +14,6 @@ import (
_ "forgejo.org/models/forgefed"
)
func AddFixtures(dirs ...string) func() {
return unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: dirs,
},
)
}
func TestMain(m *testing.M) {
unittest.MainTest(m)
}

View file

@ -13,7 +13,7 @@ import (
)
func TestPackagesGetOrInsertBlob(t *testing.T) {
defer AddFixtures("models/fixtures/TestPackagesGetOrInsertBlob/")()
defer unittest.OverrideFixtures("models/fixtures/TestPackagesGetOrInsertBlob")()
require.NoError(t, unittest.PrepareTestDatabase())
blake2bIsSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 1})

View file

@ -4,7 +4,6 @@
package repo_test
import (
"path/filepath"
"slices"
"strings"
"testing"
@ -14,7 +13,6 @@ import (
"forgejo.org/models/unittest"
"forgejo.org/models/user"
"forgejo.org/modules/optional"
"forgejo.org/modules/setting"
"forgejo.org/modules/structs"
"github.com/stretchr/testify/assert"
@ -410,13 +408,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
}
func TestSearchRepositoryIDsByCondition(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/repo/TestSearchRepositoryIDsByCondition/"},
},
)()
defer unittest.OverrideFixtures("models/repo/TestSearchRepositoryIDsByCondition")()
require.NoError(t, unittest.PrepareTestDatabase())
// Sanity check of the database
limitedUser := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 33, Visibility: structs.VisibleTypeLimited})

View file

@ -0,0 +1,198 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package unittest
import (
"database/sql"
"encoding/hex"
"encoding/json" //nolint:depguard
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
type insertSQL struct {
statement string
values []any
}
type fixtureFile struct {
name string
insertSQLs []insertSQL
}
type loader struct {
db *sql.DB
dialect string
fixtureFiles []*fixtureFile
}
func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string) (*loader, error) {
l := &loader{
db: db,
dialect: dialect,
fixtureFiles: []*fixtureFile{},
}
// Load fixtures
for _, fixturePath := range fixturePaths {
stat, err := os.Stat(fixturePath)
if err != nil {
return nil, err
}
// If fixture path is a directory, then read read the files of the directory
// and use those as fixture files.
if stat.IsDir() {
files, err := os.ReadDir(fixturePath)
if err != nil {
return nil, err
}
for _, file := range files {
if !file.IsDir() {
fixtureFile, err := l.buildFixtureFile(filepath.Join(fixturePath, file.Name()))
if err != nil {
return nil, err
}
l.fixtureFiles = append(l.fixtureFiles, fixtureFile)
}
}
} else {
fixtureFile, err := l.buildFixtureFile(fixturePath)
if err != nil {
return nil, err
}
l.fixtureFiles = append(l.fixtureFiles, fixtureFile)
}
}
return l, nil
}
// quoteKeyword returns the quoted string of keyword.
func (l *loader) quoteKeyword(keyword string) string {
switch l.dialect {
case "sqlite3":
return `"` + keyword + `"`
case "mysql":
return "`" + keyword + "`"
case "postgres":
parts := strings.Split(keyword, ".")
for i, p := range parts {
parts[i] = `"` + p + `"`
}
return strings.Join(parts, ".")
default:
return "invalid"
}
}
// placeholder returns the placeholder string.
func (l *loader) placeholder(index int) string {
if l.dialect == "postgres" {
return fmt.Sprintf("$%d", index)
}
return "?"
}
func (l *loader) buildFixtureFile(fixturePath string) (*fixtureFile, error) {
f, err := os.Open(fixturePath)
if err != nil {
return nil, err
}
defer f.Close()
var records []map[string]any
if err := yaml.NewDecoder(f).Decode(&records); err != nil {
return nil, err
}
fixture := &fixtureFile{
name: filepath.Base(strings.TrimSuffix(f.Name(), filepath.Ext(f.Name()))),
insertSQLs: []insertSQL{},
}
for _, record := range records {
columns := []string{}
sqlValues := []string{}
values := []any{}
i := 1
for key, value := range record {
columns = append(columns, l.quoteKeyword(key))
switch v := value.(type) {
case string:
// Try to decode hex.
if strings.HasPrefix(v, "0x") {
value, err = hex.DecodeString(strings.TrimPrefix(v, "0x"))
if err != nil {
return nil, err
}
}
case []any:
// Decode array.
var bytes []byte
bytes, err = json.Marshal(v)
if err != nil {
return nil, err
}
value = string(bytes)
}
values = append(values, value)
sqlValues = append(sqlValues, l.placeholder(i))
i++
}
// Construct the insert SQL.
fixture.insertSQLs = append(fixture.insertSQLs, insertSQL{
statement: fmt.Sprintf(
"INSERT INTO %s (%s) VALUES (%s)",
l.quoteKeyword(fixture.name),
strings.Join(columns, ", "),
strings.Join(sqlValues, ", "),
),
values: values,
})
}
return fixture, nil
}
func (l *loader) Load() error {
// Start transaction.
tx, err := l.db.Begin()
if err != nil {
return err
}
defer func() {
_ = tx.Rollback()
}()
// Clean the table and re-insert the fixtures.
tableDeleted := map[string]struct{}{}
for _, fixture := range l.fixtureFiles {
if _, ok := tableDeleted[fixture.name]; !ok {
if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", l.quoteKeyword(fixture.name))); err != nil {
return fmt.Errorf("cannot delete table %s: %w", fixture.name, err)
}
tableDeleted[fixture.name] = struct{}{}
}
for _, insertSQL := range fixture.insertSQLs {
if _, err := tx.Exec(insertSQL.statement, insertSQL.values...); err != nil {
return fmt.Errorf("cannot insert %q with values %q: %w", insertSQL.statement, insertSQL.values, err)
}
}
}
return tx.Commit()
}

View file

@ -6,7 +6,6 @@ package unittest
import (
"fmt"
"os"
"path/filepath"
"time"
@ -14,12 +13,11 @@ import (
"forgejo.org/modules/auth/password/hash"
"forgejo.org/modules/setting"
"github.com/go-testfixtures/testfixtures/v3"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
var fixturesLoader *testfixtures.Loader
var fixturesLoader *loader
// GetXORMEngine gets the XORM engine
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
@ -29,11 +27,18 @@ func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
return db.DefaultContext.(*db.Context).Engine().(*xorm.Engine)
}
func OverrideFixtures(opts FixturesOptions, engine ...*xorm.Engine) func() {
func OverrideFixtures(dir string) func() {
old := fixturesLoader
if err := InitFixtures(opts, engine...); err != nil {
opts := FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{dir},
}
if err := InitFixtures(opts); err != nil {
panic(err)
}
return func() {
fixturesLoader = old
}
@ -42,19 +47,19 @@ func OverrideFixtures(opts FixturesOptions, engine ...*xorm.Engine) func() {
// InitFixtures initialize test fixtures for a test database
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
e := GetXORMEngine(engine...)
var fixtureOptionFiles func(*testfixtures.Loader) error
fixturePaths := []string{}
if opts.Dir != "" {
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
fixturePaths = append(fixturePaths, opts.Dir)
} else {
fixtureOptionFiles = testfixtures.Files(opts.Files...)
fixturePaths = append(fixturePaths, opts.Files...)
}
var fixtureOptionDirs []func(*testfixtures.Loader) error
if opts.Dirs != nil {
for _, dir := range opts.Dirs {
fixtureOptionDirs = append(fixtureOptionDirs, testfixtures.Directory(filepath.Join(opts.Base, dir)))
fixturePaths = append(fixturePaths, filepath.Join(opts.Base, dir))
}
}
dialect := "unknown"
var dialect string
switch e.Dialect().URI().DBType {
case schemas.POSTGRES:
dialect = "postgres"
@ -63,22 +68,10 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
case schemas.SQLITE:
dialect = "sqlite3"
default:
fmt.Println("Unsupported RDBMS for integration tests")
os.Exit(1)
}
loaderOptions := []func(loader *testfixtures.Loader) error{
testfixtures.Database(e.DB().DB),
testfixtures.Dialect(dialect),
testfixtures.DangerousSkipTestDatabaseCheck(),
fixtureOptionFiles,
}
loaderOptions = append(loaderOptions, fixtureOptionDirs...)
if e.Dialect().URI().DBType == schemas.POSTGRES {
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
panic("Unsupported RDBMS for test")
}
fixturesLoader, err = testfixtures.New(loaderOptions...)
fixturesLoader, err = newFixtureLoader(e.DB().DB, dialect, fixturePaths)
if err != nil {
return err
}

View file

@ -11,6 +11,7 @@ import (
_ "forgejo.org/models"
_ "forgejo.org/models/actions"
_ "forgejo.org/models/activities"
_ "forgejo.org/models/forgefed"
_ "forgejo.org/models/user"
)

View file

@ -25,7 +25,6 @@ import (
"forgejo.org/modules/timeutil"
"forgejo.org/modules/util"
"forgejo.org/modules/validation"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -73,7 +72,7 @@ func TestGetUserFromMap(t *testing.T) {
}
func TestGetUserByName(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")()
defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase())
{
@ -120,7 +119,7 @@ func TestCanCreateOrganization(t *testing.T) {
}
func TestGetAllUsers(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")()
defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase())
users, err := user_model.GetAllUsers(db.DefaultContext)
@ -145,7 +144,7 @@ func TestAPActorID(t *testing.T) {
}
func TestSearchUsers(t *testing.T) {
defer tests.AddFixtures("models/user/fixtures/")()
defer unittest.OverrideFixtures("models/user/fixtures")()
require.NoError(t, unittest.PrepareTestDatabase())
testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) {
users, _, err := user_model.SearchUsers(db.DefaultContext, opts)

View file

@ -204,7 +204,13 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil, err
}
}
if !isTrue(isGenerated) && enry.IsGenerated(f.Name(), content) {
// We consider three cases:
// 1. linguist-generated=true, then we ignore the file.
// 2. linguist-generated=false, we don't ignore the file.
// 3. linguist-generated is not set, then `enry.IsGenerated` determines if the file is generated.
if isTrue(isGenerated) || !isFalse(isGenerated) && enry.IsGenerated(f.Name(), content) {
log.Trace("Ignore %q for language stats, because it is generated", f.Name())
continue
}

View file

@ -25,6 +25,15 @@ func TestRepository_GetLanguageStats(t *testing.T) {
"Python": 134,
"Java": 112,
}, stats)
stats, err = gitRepo.GetLanguageStats("95d3505f2db273e40be79f84416051ae85e9ea0d")
require.NoError(t, err)
assert.Equal(t, map[string]int64{
"Cobra": 67,
"Python": 67,
"Java": 112,
}, stats)
}
func TestMergeLanguageStats(t *testing.T) {

View file

@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 8fee858da5796dfb37704761701bb8e800ad9ef3 Andrew Thornton <art27@cantab.net> 1632140318 +0100 commit (initial): Add some test files for GetLanguageStats
8fee858da5796dfb37704761701bb8e800ad9ef3 341fca5b5ea3de596dc483e54c2db28633cd2f97 oliverpool <git@olivier.pfad.fr> 1711278775 +0100 push

View file

@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 8fee858da5796dfb37704761701bb8e800ad9ef3 Andrew Thornton <art27@cantab.net> 1632140318 +0100 commit (initial): Add some test files for GetLanguageStats
8fee858da5796dfb37704761701bb8e800ad9ef3 341fca5b5ea3de596dc483e54c2db28633cd2f97 oliverpool <git@olivier.pfad.fr> 1711278775 +0100 push

View file

@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
95d3505f2db273e40be79f84416051ae85e9ea0d refs/heads/master

View file

@ -1 +0,0 @@
341fca5b5ea3de596dc483e54c2db28633cd2f97

View file

@ -1,4 +1,5 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package i18n
@ -239,6 +240,7 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
if defaultLang, ok := l.store.localeMap[l.store.defaultLang]; ok {
if msg := defaultLang.LookupNewStyleMessage(trKey); msg != "" {
format = msg
found = true
} else if foundIndex {
// Third fallback: old-style default language
if msg, ok := defaultLang.idxToMsgMap[idx]; ok {

View file

@ -939,7 +939,7 @@ access_token_deletion=Odstranit přístupový token
access_token_deletion_cancel_action=Zrušit
access_token_deletion_confirm_action=Smazat
access_token_deletion_desc=Smazání tokenu zruší přístup k vašemu účtu pro aplikace, které jej používají. Tuto akci nelze vrátit. Pokračovat?
delete_token_success=Token byl odstraněn. Aplikace, které jej používají již nemají přístup k vašemu účtu.
delete_token_success=Token byl odstraněn. Aplikace, které jej používají, již nemají přístup k vašemu účtu.
repo_and_org_access=Přístup k repozitářům a organizacím
permissions_public_only=Pouze veřejné
permissions_access_all=Vše (veřejné, soukromé a omezené)

View file

@ -229,7 +229,7 @@ app_desc=Ein einfacher, selbst gehosteter Git-Service
install=Einfach zu installieren
install_desc=Starte einfach <a target="_blank" rel="noopener noreferrer" href="%[1]s">die Anwendung</a> für deine Plattform oder nutze <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>. Es existieren auch <a target="_blank" rel="noopener noreferrer" href="%[3]s">paketierte Versionen</a>.
platform=Plattformübergreifend
platform_desc=Forgejo läuft auf freien Betriebssystemen wie Linux und FreeBSD, sowie auf verschiedenen CPU-Architekturen. Wähle das System, das du magst!
platform_desc=Forgejo läuft auf freien Betriebssystemen wie Linux und FreeBSD sowie auf verschiedenen CPU-Architekturen. Wähle das System, das du magst!
lightweight=Leichtgewichtig
lightweight_desc=Forgejo hat minimale Systemanforderungen und kann selbst auf einem günstigen und stromsparenden Raspberry Pi betrieben werden!
license=Quelloffen
@ -339,7 +339,7 @@ default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
default_enable_timetracking.description=Zeiterfassung standardmäßig für neue Repositorys aktivieren.
no_reply_address=Versteckte E-Mail-Domain
no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist.
password_algorithm=Passwort Hashing Algorithmus
password_algorithm=Passwort-Hashing-Algorithmus
invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus
password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein.
enable_update_checker=Aktualisierungsprüfung aktivieren
@ -347,11 +347,11 @@ env_config_keys=Umgebungskonfiguration
env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet:
allow_dots_in_usernames = Erlaubt Benutzern die Verwendung von Punkten in ihren Benutzernamen. Hat keine Auswirkungen auf bestehende Konten.
enable_update_checker_helper_forgejo = Prüft regelmäßig auf neue Forgejo-Versionen, indem ein DNS-TXT-Eintrag unter release.forgejo.org überprüft wird.
smtp_from_invalid = Die „Sende E-Mail Als“-Adresse ist ungültig
smtp_from_invalid = Die „Sende E-Mail als“-Adresse ist ungültig
config_location_hint = Diese Konfigurationsoptionen werden gespeichert in:
allow_only_external_registration = Registrierung nur mittels externer Dienste zulassen
app_slogan = Instanz-Slogan
app_slogan_helper = Instanz-Slogan hier eingeben. Leer lassen zum deaktivieren.
app_slogan_helper = Instanz-Slogan hier eingeben. Leer lassen zum Deaktivieren.
[home]
uname_holder=Benutzername oder E-Mail-Adresse
@ -418,7 +418,7 @@ forgot_password_title=Passwort vergessen
forgot_password=Passwort vergessen?
sign_up_now=Noch kein Konto? Jetzt registrieren.
sign_up_successful=Konto wurde erfolgreich erstellt. Willkommen!
confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Registrierungsprozess abzuschließen, überprüf bitte deinen Posteingang und folg dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden.
confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Registrierungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden.
must_change_password=Aktualisiere dein Passwort
allow_password_change=Verlange vom Benutzer das Passwort zu ändern (empfohlen)
reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Um den Kontowiederherstellungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von %s.
@ -451,7 +451,7 @@ oauth_signup_tab=Neues Konto registrieren
oauth_signup_title=Neues Konto fertigstellen
oauth_signup_submit=Konto vervollständigen
oauth_signin_tab=Mit einem existierenden Konto verbinden
oauth_signin_title=Anmelden um verbundenes Konto zu autorisieren
oauth_signin_title=Anmelden, um verbundenes Konto zu autorisieren
oauth_signin_submit=Konto verbinden
oauth.signin.error=Beim Verarbeiten der Autorisierungsanfrage ist ein Fehler aufgetreten. Wenn dieser Fehler weiterhin besteht, wende dich bitte an deinen Administrator.
oauth.signin.error.access_denied=Die Autorisierungsanfrage wurde abgelehnt.
@ -562,7 +562,7 @@ password_change.subject = Dein Passwort wurde geändert
password_change.text_1 = Das Passwort für deinen Account wurde soeben geändert.
primary_mail_change.subject = Deine primäre E-Mail-Adresse wurde geändert
totp_disabled.subject = TOTP wurde deaktiviert
totp_disabled.text_1 = TOTP (Time-based one-time password [Zeitbasiertes Einmalpasswort]) wurde auf deinem Account soeben deaktiviert.
totp_disabled.text_1 = TOTP (Time-based one-time password [zeitbasiertes Einmalpasswort]) wurde auf deinem Account soeben deaktiviert.
totp_disabled.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen.
removed_security_key.subject = Ein Sicherheitsschlüssel wurde entfernt
removed_security_key.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen.
@ -572,7 +572,7 @@ reset_password.text_1 = Das Passwort für deinen Account wurde soeben geändert.
primary_mail_change.text_1 = Die primäre E-Mail-Adresse deines Account wurde soeben zu %[1]s geändert. Das bedeutet, dass diese E-Mail-Adresse keine E-Mail-Benachrichtigungen für deinen Account erhalten wird.
account_security_caution.text_2 = Wenn du das nicht warst, wurde dein Account kompromittiert. Bitte kontaktiere die Admins dieser Webseite.
totp_enrolled.subject = Du hast TOTP als 2FA-Methode aktiviert
totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen könntest, oder einen deiner Sicherheitsschlüssel.
totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode oder einen deiner Sicherheitsschlüssel benutzen könntest.
totp_enrolled.text_1.no_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen musst.
[modal]
@ -661,8 +661,8 @@ organization_leave_success=Du hast die Organisation %s erfolgreich verlassen.
invalid_ssh_key=Dein SSH-Key kann nicht überprüft werden: %s
invalid_gpg_key=Dein GPG-Key kann nicht überprüft werden: %s
invalid_ssh_principal=Ungültige Identität: %s
must_use_public_key=Der von dir bereitgestellte Key ist ein privater Key. Bitte lade deinen privaten Key nirgendwo hoch. Verwende stattdessen deinen öffentlichen Key.
unable_verify_ssh_key=Der SSH-Key kann nicht verifiziert werden, überprüfe ihn auf Fehler.
must_use_public_key=Der von dir bereitgestellte Schlüssel ist ein privater. Bitte lade deinen privaten Schlüssel nirgendwo hoch, sondern verwende stattdessen deinen öffentlichen.
unable_verify_ssh_key=Der SSH-Schlüssel kann nicht verifiziert werden, überprüfe ihn auf Fehler.
auth_failed=Authentifizierung fehlgeschlagen: %v
still_own_repo=Dein Konto besitzt ein oder mehrere Repositorys. Diese müssen erst gelöscht oder übertragen werden.
@ -700,7 +700,7 @@ watched=Beobachtete Repositorys
code=Quelltext
projects=Projekte
overview=Übersicht
following_few=%d Folge ich
following_few=%d folge ich
follow=Folgen
unfollow=Nicht mehr folgen
user_bio=Biografie
@ -722,7 +722,7 @@ follow_blocked_user = Du kannst diesen Benutzer nicht folgen, weil du ihn blocki
block_user.detail_3 = Ihr werdet nicht mehr in der Lage sein, euch gegenseitig als Repository-Mitarbeiter hinzuzufügen.
unblock = Nicht mehr blockieren
followers_one = %d Follower
following_one = %d Folge ich
following_one = %d folge ich
followers.title.few = Follower
following.title.one = Folgt
following.title.few = Folgt
@ -774,7 +774,7 @@ cancel=Abbrechen
language=Sprache
ui=Theme
hidden_comment_types=Ausgeblendete Kommentartypen
hidden_comment_types_description=Die hier markierten Kommentartypen werden nicht innerhalb der Issue-Seiten angezeigt. Die Markierung von „Label“ zum Beispiel entfernt alle Kommentare der Form „<Benutzer> hat <Label> hinzugefügt/entfernt“.
hidden_comment_types_description=Die hier markierten Kommentartypen werden innerhalb der Issue-Seiten nicht angezeigt. Beispielsweise entfernt das Ankreuzen von „Label“ alle Kommentare der Form „<Benutzer> hat <Label> hinzugefügt/entfernt“.
hidden_comment_types.ref_tooltip=Kommentare, in denen dieses Issue von einem anderen Issue/Commit/… referenziert wurde
hidden_comment_types.issue_ref_tooltip=Kommentare, bei denen der Benutzer den Branch/Tag des Issues ändert
comment_type_group_reference=Verweis auf Mitglieder
@ -853,9 +853,9 @@ manage_ssh_keys=SSH-Schlüssel verwalten
manage_ssh_principals=SSH-Zertifikats-Principals verwalten
manage_gpg_keys=GPG-Schlüssel verwalten
add_key=Schlüssel hinzufügen
ssh_desc=Diese öffentlichen SSH-Keys sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Keys geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Key können verwendet werden, um SSH-signierte Git-Commits zu signieren.
ssh_desc=Diese öffentlichen SSH-Schlüssel sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Schlüssel geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Schlüssel können verwendet werden, um SSH-signierte Git-Commits zu signieren.
principal_desc=Diese SSH-Zertifikat-Principals sind mit deinem Konto verknüpft und erlauben den vollen Zugriff auf deine Repositorys.
gpg_desc=Diese öffentlichen GPG-Keys sind mit deinem Account verbunden und werden benutzt um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Keys geheim, da diese deine Commits signieren.
gpg_desc=Diese öffentlichen GPG-Schlüssel sind mit deinem Account verbunden und werden benutzt, um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Schlüssel geheim, da diese deine Commits signieren.
ssh_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung zum <a href="%s">Erzeugen deiner eigenen SSH-Schlüssel</a> an oder zum Lösen <a href="%s">häufiger Probleme</a>, denen du bei der Arbeit mit SSH begegnen kannst.
gpg_helper=<strong>Brauchst du Hilfe?</strong> Sieh dir die Anleitung <a href="%s">über GPG</a> an.
add_new_key=SSH-Schlüssel hinzufügen
@ -896,7 +896,7 @@ key_id=Schlüssel-ID
key_name=Schlüsselname
key_content=Inhalt
principal_content=Inhalt
add_key_success=Der SSH-Key „%s“ wurde hinzugefügt.
add_key_success=Der SSH-Schlüssel „%s“ wurde hinzugefügt.
add_gpg_key_success=Der GPG-Schlüssel „%s“ wurde hinzugefügt.
add_principal_success=Die SSH-Zertifikatsidentität „%s“ wurde hinzugefügt.
delete_key=Entfernen
@ -968,8 +968,8 @@ oauth2_confidential_client=Vertraulicher Client. Für Anwendungen aktivieren, di
oauth2_redirect_uris=URIs für die Weiterleitung. Bitte verwende eine neue Zeile für jede URI.
save_application=Speichern
oauth2_client_id=Client-ID
oauth2_client_secret=Client-Secret
oauth2_regenerate_secret=Secret neu generieren
oauth2_client_secret=Client-Geheimnis
oauth2_regenerate_secret=Geheimnis neu generieren
oauth2_regenerate_secret_hint=Secret verloren?
oauth2_client_secret_hint=Das Secret wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast.
oauth2_application_edit=Bearbeiten
@ -984,7 +984,7 @@ revoke_oauth2_grant=Autorisierung widerrufen
revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher?
revoke_oauth2_grant_success=Zugriff erfolgreich widerrufen.
twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du eine Smartphone oder ein anderes Gerät verwenden, um Time-Based One-Time Passwords („TOTP“) zu erhalten.
twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du eine Smartphone oder ein anderes Gerät verwenden, um zeitbasierte Einmalpasswörter („TOTP“) zu erhalten.
twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>.
twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet.
twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren
@ -1028,7 +1028,7 @@ confirm_delete_account=Löschen bestätigen
delete_account_title=Benutzerkonto löschen
delete_account_desc=Bist du sicher, dass du diesen Account dauerhaft löschen möchtest?
email_notifications.enable=E-Mail Benachrichtigungen aktivieren
email_notifications.enable=E-Mail-Benachrichtigungen aktivieren
email_notifications.onmention=Nur E-Mail bei Erwähnung
email_notifications.disable=E-Mail-Benachrichtigungen deaktivieren
email_notifications.submit=E-Mail-Einstellungen festlegen
@ -1045,7 +1045,7 @@ user_block_success = Dieser Benutzer wurde erfolgreich blockiert.
twofa_recovery_tip = Falls du dein Gerät verlierst, wirst du in der Lage sein, einen einmalig verwendbaren Wiederherstellungsschlüssel zu verwenden, um den auf dein Konto wiederherzustellen.
webauthn_alternative_tip = Du möchtest vielleicht eine zusätzliche Authentifizierungsmethode einrichten.
blocked_users_none = Keine Benutzer blockiert.
webauthn_key_loss_warning = Falls du deine Security-Keys verlierst, wirst du Zugang zu deinem Konto verlieren.
webauthn_key_loss_warning = Falls du deine Sicherheitsschlüssel verlierst, wirst du Zugang zu deinem Konto verlieren.
user_unblock_success = Die Blockierung dieses Benutzers wurde erfolgreich zurückgenommen.
blocked_users = Blockierte Benutzer
blocked_since = Blockiert seit %s
@ -1054,7 +1054,7 @@ hints = Hinweise
additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen
update_hints = Hinweise aktualisieren
update_hints_success = Hinweise wurden aktualisiert.
additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis für Repositories, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen.
additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis für Repositorys, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen.
pronouns = Pronomen
pronouns_custom = Eigene
pronouns_unspecified = Nicht spezifiziert
@ -1064,10 +1064,10 @@ language.localization_project = Hilf uns, Forgejo in deine Sprache zu übersetze
language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt.
user_block_yourself = Du kannst dich nicht selbst blockieren.
pronouns_custom_label = Individuelle Pronomen
change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle Verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen.
keep_pronouns_private = Pronomen nur angemeldeten Nutzern anzeigen
keep_pronouns_private.description = Dies verbirgt deine Pronomen von Besuchern die nicht angemeldet sind.
keep_pronouns_private.description = Dies verbirgt deine Pronomen von Besuchern, die nicht angemeldet sind.
quota.sizes.assets.artifacts = Artefakte
quota.applies_to_user = Die folgenden Quota-Regeln greifen für deinen Account
quota.sizes.assets.attachments.issues = Issue-Anhänge
@ -1088,9 +1088,9 @@ quota.sizes.assets.all = Assets
quota.sizes.assets.attachments.all = Anhänge
quota.sizes.assets.packages.all = Pakete
quota.sizes.wiki = Wiki
regenerate_token_success = Der Token wurde regeneriert. Anwendungen die ihn benutzen haben nicht länger Zugriff auf deinen Account und müssen mit dem neuen Token aktualisiert werden.
regenerate_token_success = Der Token wurde regeneriert. Anwendungen, die ihn benutzen, haben nicht länger Zugriff auf deinen Account und müssen mit dem neuen Token aktualisiert werden.
access_token_regeneration = Zugangstoken regenerieren
access_token_regeneration_desc = Einen Token zu regenerieren wird den Zugriff auf deinen Account von Anwendungen die ihn nutzen zurückziehen. Dies kann nicht rückgängig gemacht werden. Fortsetzen?
access_token_regeneration_desc = Einen Token zu regenerieren, wird den Zugriff auf deinen Account von Anwendungen, die ihn nutzen, zurückziehen. Dies kann nicht rückgängig gemacht werden. Fortsetzen?
regenerate_token = Regenerieren
[repo]
@ -1133,7 +1133,7 @@ issue_labels=Labels
issue_labels_helper=Wähle eine Label-Sammlung
license=Lizenz
license_helper=Wähle eine Lizenz
license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) können. Unsicher, welches für dein Projekt die Richtige ist? Siehe <a target="_blank" rel="noopener noreferrer" href="%s">Choose a license</a>.
license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) können. Unsicher, welche für dein Projekt die richtige ist? Siehe <a target="_blank" rel="noopener noreferrer" href="%s">Choose a license</a>.
readme=README
readme_helper=Wähle eine README-Vorlage
readme_helper_desc=Hier kannst du eine komplette Beschreibung für dein Projekt schreiben.
@ -1189,9 +1189,9 @@ tree_path_not_found_commit=Pfad %[1]s existiert nicht in Commit%[2]s
tree_path_not_found_branch=Pfad %[1]s existiert nicht in Branch %[2]s
tree_path_not_found_tag=Pfad %[1]s existiert nicht in Tag %[2]s
transfer.accept=Übertragung Akzeptieren
transfer.accept=Übertragung akzeptieren
transfer.accept_desc=Übertragung nach „%s“
transfer.reject=Übertragung Ablehnen
transfer.reject=Übertragung ablehnen
transfer.reject_desc=Übertragung nach„%s“ abbrechen
transfer.no_permission_to_accept=Du hast keine Berechtigung, diesen Transfer anzunehmen.
transfer.no_permission_to_reject=Du hast keine Berechtigung, diesen Transfer abzulehnen.
@ -1241,7 +1241,7 @@ migrate_items_pullrequests=Pull-Requests
migrate_items_merge_requests=Merge-Requests
migrate_items_releases=Releases
migrate_repo=Repository migrieren
migrate.clone_address=Migrations- / Klon-URL
migrate.clone_address=Migrations-/Klon-URL
migrate.clone_address_desc=Die HTTP(S)- oder „git clone“-URL eines bereits existierenden Repositorys
migrate.github_token_desc=Du kannst hier ein oder mehrere Token durch Komma getrennt eintippen, um die Migration aufgrund der GitHub-API-Ratenlimitierung zu beschleunigen. WARNUNG: Der Missbrauch dieser Funktion kann gegen die Richtlinien des Diensteanbieters verstoßen und zur Kontosperrung führen.
migrate.clone_local_path=oder ein lokaler Serverpfad
@ -1259,7 +1259,7 @@ migrate.migrating_failed=Migrieren von <b>%s</b> fehlgeschlagen.
migrate.migrating_failed.error=Migration fehlgeschlagen: %s
migrate.migrating_failed_no_addr=Migration fehlgeschlagen.
migrate.github.description=Daten von github.com oder GitHub-Enterprise-Server migrieren.
migrate.git.description=Ein Repository von einem beliebigen Git-Service klonen.
migrate.git.description=Ein Repository von einem beliebigen Git-Dienst klonen.
migrate.gitlab.description=Daten von gitlab.com oder anderen GitLab-Instanzen migrieren.
migrate.gitea.description=Daten von gitea.com oder anderen Gitea-Instanzen migrieren.
migrate.gogs.description=Daten von notabug.org oder anderen Gogs-Instanzen migrieren.
@ -1422,8 +1422,8 @@ editor.commit_empty_file_text=Die Datei, die du commiten willst, ist leer. Fortf
editor.no_changes_to_show=Keine Änderungen vorhanden.
editor.fail_to_update_file=Fehler beim Aktualisieren/Erstellen der Datei „%s“.
editor.fail_to_update_file_summary=Fehlermeldung:
editor.push_rejected_no_message=Die Änderung wurde vom Server ohne Nachricht abgelehnt. Bitte überprüfe die Git Hooks.
editor.push_rejected=Die Änderung wurde vom Server abgelehnt. Bitte überprüfe die Git Hooks.
editor.push_rejected_no_message=Die Änderung wurde vom Server ohne Nachricht abgelehnt. Bitte überprüfe die Git-Hooks.
editor.push_rejected=Die Änderung wurde vom Server abgelehnt. Bitte überprüfe die Git-Hooks.
editor.push_rejected_summary=Vollständige Ablehnungsmeldung:
editor.add_subdir=Verzeichnis erstellen …
editor.unable_to_upload_files=Fehler beim Hochladen der Dateien nach „%s“. Fehler: %v
@ -1453,7 +1453,7 @@ commits.signed_by=Signiert von
commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzern
commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt
commits.gpg_key_id=GPG-Schlüssel-ID
commits.ssh_key_fingerprint=SSH-Key-Fingerabdruck
commits.ssh_key_fingerprint=SSH-Schlüssel-Fingerabdruck
commits.view_path=An diesem Punkt im Verlauf anzeigen
commit.operations=Operationen
@ -1500,7 +1500,7 @@ projects.column.new_title=Name
projects.column.new_submit=Spalte erstellen
projects.column.new=Neue Spalte
projects.column.set_default=Als Standard verwenden
projects.column.set_default_desc=Diese Spalte als Standard für nicht kategorisierte Issues und Pull Requests festlegen
projects.column.set_default_desc=Diese Spalte als Standard für nicht kategorisierte Issues und Pull-Requests festlegen
projects.column.unset_default=Standard entfernen
projects.column.unset_default_desc=Diese Spalte nicht als Standard verwenden
projects.column.delete=Spalte löschen
@ -2019,7 +2019,7 @@ milestones.filter_sort.most_complete=Vollständigste
milestones.filter_sort.most_issues=Meiste Issues
milestones.filter_sort.least_issues=Wenigste Issues
signing.will_sign=Dieser Commit wird mit dem Key „%s“ signiert werden.
signing.will_sign=Dieser Commit wird mit dem Schlüssel „%s“ signiert werden.
signing.wont_sign.error=Es gab einen Fehler bei der Prüfung, ob der Commit signiert werden kann.
signing.wont_sign.nokey=Diese Instanz hat keinen Schlüssel, um diesen Commit zu signieren.
signing.wont_sign.never=Commits werden nie signiert.
@ -2216,7 +2216,7 @@ settings.pulls.allow_rebase_update=Update von Pull-Request-Branches per Rebase e
settings.pulls.default_delete_branch_after_merge=Standardmäßig bei Pull-Requests den Branch nach dem Zusammenführen löschen
settings.pulls.default_allow_edits_from_maintainers=Änderungen von Maintainern standardmäßig erlauben
settings.releases_desc=Repository-Releases aktivieren
settings.packages_desc=Repository Packages Registry aktivieren
settings.packages_desc=Repository-Paket-Registry aktivieren
settings.projects_desc=Repository-Projekte aktivieren
settings.actions_desc=Aktiviere integrierte CI/CD-Pipelines mit Forgejo-Actions
settings.admin_settings=Administratoreinstellungen
@ -2791,7 +2791,7 @@ pulls.made_using_agit = AGit
settings.confirmation_string = Bestätigungsstring
pulls.agit_explanation = Mittels AGit-Workflow erstellt. AGit erlaubt Mitwirkenden, Änderungen mittels „git push“ vorzuschlagen, ohne einen Fork oder neuen Branch zu erstellen.
activity.navbar.recent_commits = Neueste Commits
activity.navbar.code_frequency = Code-Frequenz
activity.navbar.code_frequency = Code-Häufigkeit
file_follow = Symlink folgen
error.broken_git_hook = Die Git-Hooks des Repositorys scheinen kaputt zu sein. Bitte folge der <a target="_blank" rel="noreferrer" href="%s">Dokumentation</a> um sie zu reparieren, dann pushe einige Commits um den Status zu aktualisieren.
pulls.merged_title_desc_one = hat %[1]d Commit von <code>%[2]s</code> nach <code>%[3]s</code> %[4]s zusammengeführt
@ -2897,7 +2897,7 @@ pulls.sign_in_require = <a href="%s">Anmelden</a>, um einen neuen Pull-Request z
new_from_template = Eine Vorlage benutzen
new_from_template_description = Du kannst eine existierende Repository-Vorlage auf dieser Instanz benutzen und ihre Einstellungen anwenden.
auto_init_description = Die Git-Historie mit einer README-Datei und optional einer Lizenz- und .gitignore-Datei starten.
issues.context.menu = Kommentar Menü
issues.context.menu = Kommentarmenü
issues.reaction.add = Reaktion hinzufügen
issues.reaction.alt_many = %[1]s und %[2]d mehr reagierten %[3]s.
issues.reaction.alt_few = %[1]s reagierten %[2]s.
@ -2922,7 +2922,7 @@ component_failed_to_load = Ein unerwarteter Fehler ist aufgetreten.
component_loading = Lade %s …
contributors.what = Beiträge
recent_commits.what = neueste Commits
code_frequency.what = Code-Frequenz
code_frequency.what = Code-Häufigkeit
[org]

View file

@ -207,6 +207,10 @@ table_modal.label.rows = Σειρές
table_modal.label.columns = Στήλες
buttons.new_table.tooltip = Προσθήκη πίνακα
link_modal.header = Προσθήκη υπερσυνδέσμου
link_modal.url = URL
link_modal.description = Περιγραφή
[filter]
string.asc=A - Z
string.desc=Z - A

View file

@ -20,7 +20,7 @@ notifications=Notificaciones
active_stopwatch=Rastreador de tiempo activo
create_new=Crear…
user_profile_and_more=Perfil y configuración…
signed_in_as=Identificado como
signed_in_as=Conectado como
enable_javascript=Este sitio web requiere JavaScript.
toc=Tabla de contenidos
licenses=Licencias
@ -38,12 +38,12 @@ passcode=Código de acceso
webauthn_insert_key=Introduzca su clave de seguridad
webauthn_sign_in=Presione el botón en su clave de seguridad. Si su clave de seguridad no tiene ningún botón, vuelva a insertarla.
webauthn_press_button=Por favor, presione el botón de su llave de seguridad…
webauthn_press_button=Por favor, presione el botón en su clave de seguridad…
webauthn_use_twofa=Utilice un código de doble factor desde su teléfono móvil
webauthn_error=No se pudo leer su llave de seguridad.
webauthn_unsupported_browser=Su navegador no soporta actualmente WebAuthn.
webauthn_unsupported_browser=Actualmente su navegador no soporta WebAuthn.
webauthn_error_unknown=Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo.
webauthn_error_insecure=`WebAuthn sólo soporta conexiones seguras. Para probar sobre HTTP, puede utilizar el origen "localhost" o "127.0.0.1"`
webauthn_error_insecure=WebAuthn sólo soporta conexiones seguras. Para probar sobre HTTP, puede utilizar el origen "localhost" o "127.0.0.1"
webauthn_error_unable_to_process=El servidor no pudo procesar su solicitud.
webauthn_error_duplicated=La clave de seguridad no está permitida para esta solicitud. Por favor, asegúrese de que la clave no está ya registrada.
webauthn_error_empty=Debe establecer un nombre para esta clave.
@ -72,7 +72,7 @@ all=Todos
sources=Propios
mirrors=Réplica
collaborative=Colaborativo
forks=Forks
forks=Bifurcaciones
activities=Actividades
pull_requests=Solicitudes de incorporación de cambios
@ -301,7 +301,7 @@ offline_mode.description=Deshabilitar redes de distribución de contenido de ter
disable_gravatar=Desactivar Gravatar
disable_gravatar.description=Desactivar el Gravatar y otros fuentes de avatares de terceros. Se utilizará un avatar por defecto a menos que un usuario suba un avatar localmente.
federated_avatar_lookup=Habilitar avatares federados
federated_avatar_lookup.description=Buscar de avatares con Libravatar.
federated_avatar_lookup.description=Busca avatares con Libravatar.
disable_registration=Deshabilitar auto-registro
disable_registration.description=Sólo los administradores de la instancia podrán crear nuevas cuentas. Es muy recomendable mantener deshabilitado el registro a menos que pretenda alojar una instancia pública para todo el mundo y esté preparado para lidiar con grandes cantidades de cuentas de spam.
allow_only_external_registration.description=Los usuarios sólo podrán crear nuevas cuentas utilizando servicios externos configurados.
@ -669,7 +669,7 @@ still_own_packages=Tu cuenta posee uno o más paquetes, elimínalos primero.
org_still_own_repo=Esta organización todavía posee uno o más repositorios, elimínalos o transfiérelos primero.
org_still_own_packages=Esta organización todavía posee uno o más paquetes, elimínalos primero.
target_branch_not_exist=La rama de destino no existe
target_branch_not_exist=La rama de destino no existe.
admin_cannot_delete_self = No puedes eliminarte a ti mismo cuando eres un admin (administrador). Por favor, elimina primero tus privilegios de administrador.
username_error_no_dots = ` solo puede contener carácteres alfanuméricos ("0-9","a-z","A-Z"), guiones ("-"), y guiones bajos ("_"). No puede empezar o terminar con carácteres no alfanuméricos y también están prohibidos los carácteres no alfanuméricos consecutivos.`
unsupported_login_type = No se admite el tipo de inicio de sesión para eliminar la cuenta.
@ -844,7 +844,7 @@ add_email_success=La nueva dirección de correo electrónico ha sido añadida.
email_preference_set_success=La preferencia de correo electrónico se ha establecido correctamente.
add_openid_success=La nueva dirección OpenID ha sido añadida.
keep_email_private=Ocultar dirección de correo electrónico
keep_email_private_popup=Esto ocultará tu dirección de correo electrónico de tu perfil. Ya no será la dirección predeterminada para los confirmaciones realizadas a través de la interfaz web, como las subidas y ediciones de archivos, y no se utilizará para las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para asociar las confirmaciones a tu cuenta. Ten en cuenta que cambiar esta opción no afectará a las confirmaciones existentes.
keep_email_private_popup=Su dirección de correo electrónico no se mostrará en su perfil y no será la predeterminada para las confirmaciones realizadas a través de la interfaz web, como las subidas de archivos, las ediciones y las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para vincular las confirmaciones a tu cuenta. Esta opción no afectará a las confirmaciones existentes.
openid_desc=OpenID le permite delegar la autenticación a un proveedor externo.
manage_ssh_keys=Gestionar claves SSH
@ -997,7 +997,7 @@ scan_this_image=Escanee esta imagen con su aplicación de autenticación:
or_enter_secret=O introduzca el secreto: %s
then_enter_passcode=E introduzca el código de acceso mostrado en la aplicación:
passcode_invalid=El código de acceso es incorrecto. Vuelva a intentarlo.
twofa_enrolled=Su cuenta ha sido inscrita en la autenticación de doble factor. ¡Guarde su código de respaldo (%s) en un lugar seguro, ya que sólo se muestra una vez!
twofa_enrolled=Su cuenta ha sido inscrita en la autenticación de doble factor. Guarde su código de respaldo (%s) en un lugar seguro, ya que no se mostrará nuevamente.
twofa_failed_get_secret=No se pudo obtener el secreto.
webauthn_desc=Las claves de seguridad son dispositivos hardware que contienen claves criptográficas. Pueden ser usados para la autenticación de doble factor. Las claves de seguridad deben soportar el estándar <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a>.
@ -1084,6 +1084,12 @@ quota.rule.exceeded = Excedido
quota.rule.no_limit = Ilimitado
quota.sizes.assets.all = Activos
access_token_regeneration = Regenerar token de acceso
quota.sizes.git.lfs = Git LFS
quota.sizes.assets.attachments.issues = Archivos adjuntos de incidencia
keep_pronouns_private.description = Esto ocultará sus pronombres a los visitantes que no hayan iniciado sesión.
[repo]
owner=Propietario
owner_helper=Algunas organizaciones pueden no aparecer en el menú desplegable debido a un límite máximo de recuento de repositorios.
@ -1103,8 +1109,8 @@ clone_helper=¿Necesita ayuda para clonar? Visite <a target="_blank" rel="noopen
fork_repo=Hacer una bifurcación del repositorio
fork_from=Crear una bifurcación desde
already_forked=Ya ha forkeado %s
fork_to_different_account=Forkear a una cuenta diferente
fork_visibility_helper=La visibilidad de un repositorio del cual se ha hecho fork no puede ser cambiada.
fork_to_different_account=Bifurcar a una cuenta diferente
fork_visibility_helper=No se puede cambiar la visibilidad de un repositorio bifurcado.
fork_branch=Rama a clonar en la bifurcación
all_branches=Todas las ramas
fork_no_valid_owners=Este repositorio no puede ser bifurcado porque no hay propietarios válidos.
@ -1158,7 +1164,7 @@ mirror_password_help=Cambie el nombre de usario para eliminar una contraseña al
watchers=Seguidores
stargazers=Fans
stars_remove_warning=Esto eliminará todas las estrellas de este repositorio.
forks=Forks
forks=Bifurcaciones
reactions_more=y %d más
unit_disabled=El administrador del sitio ha deshabilitado esta sección del repositorio.
language_other=Otros
@ -1228,8 +1234,8 @@ migrate_items_wiki=Wiki
migrate_items_milestones=Hitos
migrate_items_labels=Etiquetas
migrate_items_issues=Incidencias
migrate_items_pullrequests=Pull requests
migrate_items_merge_requests=Merge requests
migrate_items_pullrequests=Solicitudes de extracción
migrate_items_merge_requests=Solicitudes de fusión
migrate_items_releases=Lanzamientos
migrate_repo=Migrar repositorio
migrate.clone_address=Migrar / Clonar desde URL
@ -1268,17 +1274,17 @@ migrate.cancel_migrating_title=Cancelar la migración
migrate.cancel_migrating_confirm=¿Quiere cancelar esta migración?
mirror_from=réplica de
forked_from=forkeado de
forked_from=bifurcado de
generated_from=generado desde
fork_from_self=No puede hacer fork a un repositorio que ya es suyo.
fork_guest_user=Regístrate para forkear este repositorio.
fork_from_self=No puede bifurcar un repositorio que ya es suyo.
fork_guest_user=Iniciar sesión para bifurcar este repositorio.
watch_guest_user=Iniciar sesión para seguir este repositorio.
star_guest_user=Iniciar sesión para destacar este repositorio.
unwatch=Dejar de seguir
watch=Seguir
unstar=Eliminar de favoritos
star=Destacar
fork=Fork
fork=Bifurcar
download_archive=Descargar repositorio
more_operations=Más operaciones
@ -1520,7 +1526,7 @@ issues.new.no_projects=Ningún proyecto
issues.new.open_projects=Proyectos abiertos
issues.new.closed_projects=Proyectos cerrados
issues.new.no_items=No hay elementos
issues.new.milestone=Milestone
issues.new.milestone=Hito
issues.new.no_milestone=Sin hito
issues.new.clear_milestone=Limpiar Milestone
issues.new.open_milestone=Hitos abiertos
@ -1568,12 +1574,12 @@ issues.change_title_at=`cambió el título de <b><strike>%s</strike></b> a <b>%s
issues.change_ref_at=`cambió referencia de <b><strike>%s</strike></b> a <b>%s</b> %s`
issues.remove_ref_at=`eliminó la referencia <b>%s</b> %s`
issues.add_ref_at=`añadió la referencia <b>%s</b> %s`
issues.delete_branch_at=`rama eliminada <b>%s</b> %s`
issues.delete_branch_at=`eliminó la rama <b>%s</b> %s`
issues.filter_label=Etiqueta
issues.filter_label_exclude=`Usa <code>alt</code> + <code>clic/enter</code> para excluir etiquetas`
issues.filter_label_no_select=Todas las etiquetas
issues.filter_label_select_no_label=Sin etiqueta
issues.filter_milestone=Milestone
issues.filter_milestone=Hito
issues.filter_milestone_all=Todos los hitos
issues.filter_milestone_none=Sin hitos
issues.filter_milestone_open=Abrir hitos
@ -1604,8 +1610,8 @@ issues.filter_sort.nearduedate=Fecha de vencimiento más cercana
issues.filter_sort.farduedate=Fecha de vencimiento más lejana
issues.filter_sort.moststars=Mas estrellas
issues.filter_sort.feweststars=Menor número de estrellas
issues.filter_sort.mostforks=La mayoría de forks
issues.filter_sort.fewestforks=Menor número de forks
issues.filter_sort.mostforks=La mayoría de bifurcaciones
issues.filter_sort.fewestforks=Menor número de bifurcaciones
issues.keyword_search_unavailable=La búsqueda por palabra clave no está disponible actualmente. Por favor, contacte con el administrador de su sitio.
issues.action_open=Abrir
issues.action_close=Cerrar
@ -1629,7 +1635,7 @@ issues.closed_title=Cerrada
issues.draft_title=Borrador
issues.num_comments_1=%d comentario
issues.num_comments=%d comentarios
issues.commented_at=`comentado <a href="#%s">%s</a>`
issues.commented_at=`comentó <a href="#%s">%s</a>`
issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario?
issues.context.copy_link=Copiar enlace
issues.context.quote_reply=Citar respuesta
@ -1639,7 +1645,7 @@ issues.context.delete=Eliminar
issues.no_content=No se ha proporcionado una descripción.
issues.close=Cerrar incidencia
issues.comment_pull_merged_at=commit fusionado %[1]s en %[2]s %[3]s
issues.comment_manually_pull_merged_at=commit manualmente fusionado %[1]s en %[2]s %[3]s
issues.comment_manually_pull_merged_at=commit %[1]s manualmente fusionado en %[2]s %[3]s
issues.close_comment_issue=Cerrar con comentario
issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Reabrir con comentario
@ -1664,7 +1670,7 @@ issues.role.collaborator=Colaborador
issues.role.collaborator_helper=Este usuario ha sido invitado a colaborar en el repositorio.
issues.role.first_time_contributor=Contribuyente por primera vez
issues.role.first_time_contributor_helper=Esta es la primera contribución de este usuario al repositorio.
issues.role.contributor=Colaborador
issues.role.contributor=Contribuidor
issues.role.contributor_helper=Este usuario ha realizado commit previamente en este repositorio.
issues.re_request_review=Solicitar revisión de nuevo
issues.is_stale=Ha habido cambios en este PR desde esta revisión
@ -1755,7 +1761,7 @@ issues.error_modifying_due_date=Fallo al modificar la fecha de vencimiento.
issues.error_removing_due_date=Fallo al eliminar la fecha de vencimiento.
issues.push_commit_1=añadió %d commit %s
issues.push_commits_n=añadió %d commits %s
issues.force_push_codes=`hizo push forzado %[1]s de <a class="%[7]s" href="%[3]s"><code>%[2]s</code></a> a <a class="%[7]s" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_codes=`empujó forzosamente %[1]s de <a class="%[7]s" href="%[3]s"><code>%[2]s</code></a> a <a class="%[7]s" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_compare=Comparar
issues.due_date_form=aaaa-mm-dd
issues.due_date_form_add=Añadir fecha de vencimiento
@ -1874,7 +1880,7 @@ pulls.title_desc_few=quiere fusionar %[1]d commits de <code>%[2]s</code> en <cod
pulls.merged_title_desc_few=fusionó %[1]d commits de <code>%[2]s</code> en <code>%[3]s</code> %[4]s
pulls.change_target_branch_at=`cambió la rama objetivo de <b>%s</b> a <b>%s</b> %s`
pulls.tab_conversation=Conversación
pulls.tab_commits=Commits
pulls.tab_commits=Confirmaciones
pulls.tab_files=Archivos modificados
pulls.reopen_to_merge=Vuelva a abrir este Pull Request para realizar una fusión.
pulls.cant_reopen_deleted_branch=Este pull request no se puede reabrir porque la rama fue eliminada.
@ -1975,7 +1981,7 @@ pulls.auto_merge_canceled_schedule_comment=`canceló la fusión automática de e
pulls.delete.title=¿Borrar este pull request?
pulls.delete.text=¿Realmente quieres eliminar esta pull request? (Esto eliminará permanentemente todo el contenido. Considera cerrarlo si simplemente deseas archivarlo)
pulls.recently_pushed_new_branches=Has realizado push en la rama <strong>%[1]s</strong> %[2]s
pulls.recently_pushed_new_branches=Empujaste en la rama <a href="%[3]s"><strong>%[1]s</strong></a> %[2]s
pull.deleted_branch=(eliminado):%s
@ -1986,7 +1992,7 @@ milestones.no_due_date=Sin fecha límite
milestones.open=Abrir
milestones.close=Cerrar
milestones.new_subheader=Los hitos pueden ayudarle a organizar los problemas y monitorizar su progreso.
milestones.completeness=%d%% Completado
milestones.completeness=<strong>%d%%</strong> Completado
milestones.create=Crear hito
milestones.title=Título
milestones.desc=Descripción
@ -2027,7 +2033,7 @@ ext_wiki=Wiki externa
ext_wiki.desc=Enlace a una wiki externa.
wiki=Wiki
wiki.welcome=¡Bienvenidos a la Wiki!
wiki.welcome=Bienvenido a la Wiki.
wiki.welcome_desc=Esta wiki le permite escribir y compartir documentación con otros colaboradores.
wiki.desc=Escriba y comparta documentación con colaboradores.
wiki.create_first_page=Crear la primera página
@ -2104,7 +2110,7 @@ activity.git_stats_author_n=%d autores
activity.git_stats_pushed_1=ha hecho push
activity.git_stats_pushed_n=han hecho push
activity.git_stats_commit_1=%d commit
activity.git_stats_commit_n=%d commits
activity.git_stats_commit_n=%d confirmaciones
activity.git_stats_push_to_branch=a %s y
activity.git_stats_push_to_all_branches=en todas las ramas.
activity.git_stats_on_default_branch=En %s,
@ -2254,7 +2260,7 @@ settings.trust_model.default.desc=Utilice el modelo de confianza de repositorio
settings.trust_model.collaborator=Colaborador
settings.trust_model.collaborator.long=Colaborador: Confiar en firmas de colaboradores
settings.trust_model.collaborator.desc=Las firmas válidas de los colaboradores de este repositorio serán marcadas como "confiables" - (coincidan o no con el committer). De lo contrario, las firmas válidas serán marcadas como "no confiables" si la firma coincide con el committer y "no coincidente" si no lo es.
settings.trust_model.committer=Committer
settings.trust_model.committer=Confirmador
settings.trust_model.committer.long=Committer: Firmas de confianza que coinciden con los committers (Esto coincide con GitHub y obligará a Forgejo a firmar los commits a tener a Forgejo como el committer)
settings.trust_model.committer.desc=Las firmas válidas sólo se marcarán como "confiables" si coinciden con el committer, de lo contrario se marcarán como "no confiable". Esto obliga a Forgejo a ser el committer en commits firmados con el commit real marcado como Co-autorizado por: y Co-commited por: en el tráiler. La clave de Forgejo por defecto debe coincidir con un usuario en la base de datos.
settings.trust_model.collaboratorcommitter=Colaborador+Comitter
@ -2336,7 +2342,7 @@ settings.event_create=Crear
settings.event_create_desc=Rama o etiqueta creada.
settings.event_delete=Eliminar
settings.event_delete_desc=Rama o etiqueta eliminada.
settings.event_fork=Fork
settings.event_fork=Bifurcación
settings.event_fork_desc=Repositorio forkeado.
settings.event_wiki=Wiki
settings.event_wiki_desc=Página de la Wiki creada, renombrada, editada o eliminada.
@ -2524,7 +2530,7 @@ settings.archive.branchsettings_unavailable=Los ajustes de rama no están dispon
settings.archive.tagsettings_unavailable=Los ajustes de las etiquetas no están disponibles si el repositorio está archivado.
settings.unarchive.button=Desarchivar repositorio
settings.unarchive.header=Desarchivar este repositorio
settings.unarchive.text=La desarchivación del repositorio restablecerá su capacidad de recibir confirmaciones y subidos, así como nuevas incidencias y solicitudes de incorporación de cambios.
settings.unarchive.text=La desarchivación del repositorio restablecerá su capacidad de recibir confirmaciones y empujes, así como nuevas incidencias y solicitudes de incorporación de cambios.
settings.unarchive.success=El repositorio se ha desarchivado correctamente.
settings.unarchive.error=Ocurrió un error mientras se trataba de des-archivar el repositorio. Revisa el registro para más detalles.
settings.update_avatar_success=El avatar del repositorio ha sido actualizado.
@ -2647,7 +2653,7 @@ release.cancel=Cancelar
release.publish=Publicar lanzamiento
release.save_draft=Guardar borrador
release.edit_release=Actualizar Lanzamiento
release.delete_release=Eliminar Lanzamiento
release.delete_release=Eliminar lanzamiento
release.delete_tag=Eliminar tag
release.deletion=Eliminar lanzamiento
release.deletion_desc=Eliminar un lanzamiento sólo lo elimina de Forgejo. No afectará la etiqueta Git, el contenido de su repositorio o su historial. ¿Continuar?
@ -2673,7 +2679,7 @@ branch.delete_html=Eliminar rama
branch.delete_desc=Eliminar una rama es permanente. Aunque la rama eliminada puede continuar existiendo durante un corto tiempo antes de que sea eliminada, en la mayoría de los casos NO PUEDE deshacerse. ¿Continuar?
branch.deletion_success=La rama "%s" ha sido eliminada.
branch.deletion_failed=Error al eliminar la rama "%s".
branch.delete_branch_has_new_commits=La rama "%s" no se puede eliminar porque se han añadido nuevos commits después de la fusión.
branch.delete_branch_has_new_commits=La rama "%s" no se puede eliminar porque se han añadido nuevas confirmaciones después de la fusión.
branch.create_branch=Crear rama %s
branch.create_from=`de "%s"`
branch.create_success=La rama "%s" ha sido creada.
@ -2876,6 +2882,11 @@ issues.filter_no_results = No hay resultados
release.type_attachment = Archivo adjunto
issues.reaction.alt_few = %[1]s reaccionado con %[2]s.
settings.event_pull_request_enforcement = Aplicación
settings.sourcehut_builds.visibility = Visibilidad de trabajo
settings.ignore_stale_approvals = Ignorar las aprobaciones obsoletas
[graphs]
component_loading = Cargando %s…
component_loading_failed = No se pudo cargar %s
@ -2942,11 +2953,11 @@ settings.hooks_desc=Añadir webhooks que serán ejecutados para <strong>todos lo
settings.labels_desc=Añadir etiquetas que pueden ser utilizadas en problemas para <strong>todos los repositorios</strong> bajo esta organización.
members.membership_visibility=Visibilidad de Membresía:
members.membership_visibility=Visibilidad de membresía:
members.public=Público
members.public_helper=hacer oculto
members.public_helper=Hacer oculto
members.private=Oculto
members.private_helper=hacer público
members.private_helper=Hacer público
members.member_role=Rol del miembro:
members.owner=Propietario
members.member=Miembro
@ -2955,7 +2966,7 @@ members.remove.detail=¿Destituir a %[1]s de %[2]s?
members.leave=Abandonar
members.leave.detail=¿Irse de %s?
members.invite_desc=Añadir un miembro nuevo a %s:
members.invite_now=Invitar
members.invite_now=Invitar ahora
teams.join=Unirse
teams.leave=Abandonar
@ -2964,7 +2975,7 @@ teams.can_create_org_repo=Crear repositorios
teams.can_create_org_repo_helper=Los miembros pueden crear nuevos repositorios en la organización. El creador obtendrá acceso al administrador del nuevo repositorio.
teams.none_access=Sin acceso
teams.none_access_helper=Los miembros no pueden ver o hacer ninguna otra acción en esta unidad.
teams.general_access=Acceso general
teams.general_access=Acceso personalizado
teams.general_access_helper=Los permisos de los miembros se decidirán por debajo de la tabla de permisos.
teams.read_access=Leer
teams.read_access_helper=Los miembros pueden ver y clonar los repositorios del equipo.
@ -3554,6 +3565,10 @@ emails.delete_desc = ¿Estás seguro que quieres eliminar esta dirección de cor
monitor.duration = Duración (es)
self_check = Autocomprobación
dashboard.sync_tag.started = Sincronización de etiquetas iniciada
config.app_slogan = Eslogan de la instancia
[action]
create_repo=creó el repositorio <a href="%s">%s</a>
rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
@ -3816,6 +3831,13 @@ alt.repository.multiple_groups = Este paquete está disponible en múltiples gru
arch.version.description = Descripción
arch.version.provides = Proveedores
arch.version.optdepends = Dependencias opcionales
arch.version.makedepends = Construir dependencias
arch.version.checkdepends = Comprobar dependencias
npm.dependencies.bundle = Empaquetar dependencias
arch.pacman.helper.gpg = Añade el certificado de confianza para pacman:
[secrets]
secrets=Secretos
description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo.
@ -3862,7 +3884,7 @@ runners.task_list.no_tasks=Todavía no hay tarea.
runners.task_list.run=Ejecutar
runners.task_list.status=Estado
runners.task_list.repository=Repositorio
runners.task_list.commit=Commit
runners.task_list.commit=Confirmación
runners.task_list.done_at=Hecho en
runners.edit_runner=Editar nodo
runners.update_runner=Actualizar cambios
@ -3922,6 +3944,13 @@ runs.expire_log_message = Los registros han sido eliminados porque eran demasiad
runs.workflow = Flujo de trabajo
workflow.dispatch.use_from = Usar el flujo de trabajo de
workflow.dispatch.run = Correr flujo de trabajo
runs.no_workflows = Aún no hay flujos de trabajo.
workflow.dispatch.success = La ejecución del flujo de trabajo se ha solicitado correctamente.
workflow.dispatch.invalid_input_type = Tipo de entrada inválida "%s".
[projects]
type-1.display_name=Proyecto individual
type-2.display_name=Proyecto de repositorio
@ -3963,7 +3992,7 @@ exact = Exacto
exact_tooltip = Incluir sólo los resultados que corresponden al término de búsqueda exacto
issue_kind = Buscar incidencias…
fuzzy = Difusa
runner_kind = Buscar ejecutores…
runner_kind = Buscar corredores…
regexp_tooltip = Interpretar los términos de búsqueda como una expresión regular
regexp = Expresión Regular

View file

@ -2,7 +2,7 @@
home=Etusivu
dashboard=Kojelauta
explore=Tutki
help=Apua
help=Ohje
logo=Logo
sign_in=Kirjaudu sisään
sign_in_or=tai
@ -41,7 +41,7 @@ webauthn_error=Turva-avainta ei voitu lukea.
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
webauthn_error_insecure=`WebAuthn tukee vain suojattuja yhteyksiä. Testaukseen HTTP:n yli, voit käyttää osoitetta "localhost" tai "127.0.0.1"`
webauthn_error_unable_to_process=Palvelin ei pystynyt toteuttamaan kutsua.
webauthn_error_unable_to_process=Palvelin ei pystynyt käsittelemään pyyntöä.
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity.
webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
webauthn_error_timeout=Aikakatkaisu saavutettu ennenkuin avaintasi on voitu lukea. Lataa tämä sivu uudelleen ja yritä uudelleen.
@ -216,7 +216,7 @@ string.asc = A - Ö
string.desc = Ö - A
[error]
occurred=Virhe tapahtui
occurred=Tapahtui virhe
missing_csrf=Virheellinen pyyntö: CSRF-tunnusta ei ole olemassa
invalid_csrf=Virheellinen pyyntö: Virheellinen CSRF-tunniste
not_found=Kohdetta ei löytynyt.
@ -250,7 +250,7 @@ db_schema=Skeema
ssl_mode=SSL
path=Polku
sqlite_helper=SQLite3-tietokannan tiedostopolku.<br>Syötä absoluuttinen polku, jos ajat Forgejoa palveluna.
reinstall_error=Yrität asentaa olemassa olevaan Forgejo tietokantaan
reinstall_error=Yrität asentaa olemassa olevaan Forgejo-tietokantaan
reinstall_confirm_message=Asentaminen uudelleen olemassa olevalla Forgejo-tietokannalla voi aiheuttaa useita ongelmia. Useimmissa tapauksissa sinun pitäisi käyttää olemassa olevia "app.ini" asetuksia Forgejon käyttöön. Jos tiedät mitä teet, vahvista seuraavat seikat:
reinstall_confirm_check_1=Tiedot, jotka on salattu SECRET_KEY:llä app.ini:ssä saatetaan menettää: käyttäjät eivät ehkä voi kirjautua sisään 2FA/OTP:lla ja peilit eivät välttämättä toimi oikein. Ruksaamalla tämän vahvistat, että nykyinen app.ini -tiedosto sisältää oikean SECRET_KEY:n.
reinstall_confirm_check_2=Repot ja asetukset saattaa olla tarpeen uudelleensynkronoida. Valitsemalla tämän vahvistat, että uudelleensynkronoit repojen koukut ja authorized_keys -tiedoston manuaalisesti. Varmistat, että repon ja peilin asetukset ovat oikeat.
@ -451,7 +451,7 @@ email_domain_blacklisted=Et voi rekisteröityä sähköpostiosoittellasi.
authorize_application=Valtuuta sovellus
authorize_redirect_notice=Sinut uudelleen ohjataan osoitteeseen %s jos valtuutat tämän sovelluksen.
authorize_application_created_by=Tämän sovelluksen on luonnut %s.
authorize_application_description=Jos myönnät valtuuden, sovellus voi käyttää kaikkia tilitietojasi ja kirjoittaa niihin, mukaan lukien yksityiset repot ja organisaatiot.
authorize_application_description=Jos myönnät valtuuden, sovellus voi käyttää kaikkia tilitietojasi ja kirjoittaa niihin, mukaan lukien yksityiset repositoriot ja organisaatiot.
authorize_title=Valtuutatko "%s" pääsemään tilillesi?
authorization_failed=Käyttöoikeuden varmistus epäonnistui
sspi_auth_failed=SSPI todennus epäonnistui
@ -550,6 +550,12 @@ totp_disabled.no_2fa = Muita kaksivaiheisen tunnistautumisen menetelmiä ei ole
totp_enrolled.subject = Olet aktivoinut TOTP:in kaksivaiheisen todennuksen menetelmäksi
removed_security_key.no_2fa = Yhtään kaksivaiheisen tunnistautumisen menetelmää ei ole määritelty, joten tilillesi ei enää tarvitse kirjautua kaksivaiheisella tunnistautumisella.
totp_enrolled.text_1.no_webauthn = Otit TOTP:n käyttöön tilillesi. Tämä tarkoittaa, että kirjauduttaessa sisään tilillesi sinun täytyy käyttää TOTP menetelmää kaksivaiheisena tunnistautumisena.
totp_enrolled.text_1.has_webauthn = Otit TOTP:n käyttöön tilillesi. Tämä tarkoittaa, että kirjauduttaessa sisään tilillesi voit käyttää TOTP menetelmää kaksivaiheisena tunnistautumisena tai mitä tahansa turva-avaimiasi.
repo.collaborator.added.subject = %s lisäsi sinut %s yhteistyökumppaniksi
team_invite.text_3 = Huomaa: Tämä kutsu on tarkoitettu %[1]s:lle. Jos et odottanut tätä kutsua, voit jättää tämän sähköpostin huomiotta.
[modal]
yes=Kyllä
no=Ei
@ -567,7 +573,7 @@ SSHTitle=SSH avain nimi
HttpsUrl=HTTPS-osoite
TeamName=Tiimin nimi
AuthName=Luvan nimi
AdminEmail=Ylläpito sähköposti
AdminEmail=Ylläpitäjän sähköposti
NewBranchName=Uuden haaran nimi
CommitSummary=Commitin yhteenveto
@ -694,7 +700,7 @@ webauthn=Kaksivaiheinen todennus (Turva-avaimet)
public_profile=Julkinen profiili
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjätunnustaan. Ole hyvä ja ota yhteyttä sivuston ylläpitäjään saadaksesi lisätietoa.
full_name=Koko nimi
website=Nettisivut
website=Verkkosivusto
location=Sijainti
update_theme=Vaihda teema
update_profile=Päivitä profiili
@ -830,7 +836,7 @@ access_token_deletion_cancel_action=Peruuta
access_token_deletion_confirm_action=Poista
permission_read=Luettu
edit_oauth2_application=Muokkaa OAuth2 sovellusta
edit_oauth2_application=Muokkaa OAuth2-sovellusta
remove_oauth2_application=Poista OAuth2-sovellus
remove_oauth2_application_success=Sovellus on poistettu.
create_oauth2_application=Luo uusi OAuth2-sovellus
@ -854,7 +860,7 @@ twofa_enrolled=Tiliisi on otettu käyttöön kaksivaiheinen vahvistus. Ota palau
webauthn_nickname=Nimimerkki
manage_account_links=Yhdistetyt tilit
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo tiliisi.
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
link_account=Yhdistä tili
remove_account_link=Poista yhdistetty tili
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tili kautta. Jatketaanko?
@ -1042,7 +1048,7 @@ migrate.github_token_desc=Voit laittaa yhden tai useamman pääsymerkin pilkulla
migrate.permission_denied=Sinun ei sallita tuovan paikallisia repoja.
migrate.failed=Siirto epäonnistui: %v
migrate.migrate_items_options=Pääsymerkki vaaditaan lisäkohteiden siirtämiseen
migrate.migrating=Tuodaan kohteesta <b>%s</b> ...
migrate.migrating=Tuodaan kohteesta <b>%s</b>
migrate.migrating_failed=Tuonti kohteesta <b>%s</b> epäonnistui.
migrate.migrating_git=Tuodaan Git-tietoja
@ -1063,7 +1069,7 @@ code.desc=Pääsy lähdekoodiin, tiedostoihin, committeihin ja haaroihin.
branch=Haara
tree=Puu
filter_branch_and_tag=Suodata haara tai tagi
branches=Branchit
branches=Haarat
tags=Tagit
issues=Ongelmat
pulls=Vetopyynnöt
@ -1088,7 +1094,7 @@ blame=Selitys
download_file=Lataa tiedosto
normal_view=Normaali näkymä
line=rivi
lines=rivejä
lines=riviä
editor.new_file=Uusi tiedosto
editor.upload_file=Lähetä tiedosto
@ -1195,7 +1201,7 @@ 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
issues.filter_type.review_requested=Arvostelua pyydetty
issues.filter_type.review_requested=Katselmointi pyydetty
issues.filter_sort=Lajittele
issues.filter_sort.latest=Uusin
issues.filter_sort.oldest=Vanhin
@ -1576,7 +1582,7 @@ settings.lfs_locks=Lukot
settings.lfs_invalid_locking_path=Virheellinen polku: %s
settings.lfs_invalid_lock_directory=Hakemistoa ei voida lukita: %s
settings.lfs_lock_already_exists=Lukitus on jo olemassa: %s
settings.lfs_lock_path=Lukittavan tiedostopolku...
settings.lfs_lock_path=Lukittavan tiedostopolku
settings.lfs_locks_no_locks=Ei lukkoja
settings.lfs_lock_file_no_exist=Lukittua tiedostoa ei ole olemassa oletushaarassa
settings.lfs_force_unlock=Pakota lukituksen avaus
@ -1610,8 +1616,8 @@ diff.comment.add_single_comment=Lisää yksittäinen kommentti
diff.comment.add_review_comment=Lisää kommentti
diff.comment.start_review=Aloita tarkistus
diff.comment.reply=Vastaa
diff.review.header=Lähetä arvio
diff.review.placeholder=Tarkistuksen kommentti
diff.review.header=Lähetä katselmointi
diff.review.placeholder=Katselmoinnin kommentti
diff.review.comment=Kommentoi
diff.review.approve=Hyväksy
diff.review.reject=Pyydä muutoksia
@ -2204,7 +2210,7 @@ create_org=Luo organisaatio
repo_updated=Päivitetty %s
members=Jäsenet
teams=Tiimit
lower_members=jäsenet
lower_members=jäsentä
lower_repositories=repot
create_new_team=Uusi tiimi
create_team=Luo tiimi
@ -2316,7 +2322,7 @@ config=Asetukset
notices=Järjestelmän ilmoitukset
monitor=Valvonta
first_page=Ensimmäinen
last_page=Viimeisin
last_page=Viimeinen
total=Yhteensä: %d
dashboard.statistic=Yhteenveto
@ -2667,7 +2673,7 @@ auths.enable_ldap_groups = Käytä LDAP-ryhmiä
auths.login_source_exist = Todennuslähde "%s" on jo olemassa.
[action]
create_repo=luotu repo <a href="%s">%s</a>
create_repo=loi repon <a href="%s">%s</a>
rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a>
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
push_tag=työnsi tagin <a href="%[2]s">%[3]s</a> kohteeseen <a href="%[1]s">%[4]s</a>

View file

@ -4082,4 +4082,4 @@ issues.write = <b>Écrire :</b> Fermer des tickets et gérer les métadonnées t
pulls.read = <b>Lire :</b> Lire et créer des demandes de tirage.
[translation_meta]
test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce doux 100 % de complétion :)
test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce doux 100 % de complétion. :-)

View file

@ -128,7 +128,7 @@ copy_success = 복사되었습니다!
copy_error = 복사 실패
copy_type_unsupported = 이 파일 형식은 복사할 수 없습니다
error = 오류
error404 = 도달하려는 페이지가 <strong>존재하지 않거나</strong> 볼 수 있는 <strong>권한이 없습니다</strong>.
error404 = 도달하려는 페이지가 <strong>존재하지 않거나</strong> , <strong>제거 되었거나</strong> 또는 <strong>볼 권한이 없습니다</strong>.
go_back = 돌아가기
invalid_data = 유효하지 않는 데이터: %v
unknown = 알 수 없음
@ -176,10 +176,10 @@ footer.software = 이 소프트웨어에 대하여
[heatmap]
number_of_contributions_in_the_last_12_months = 지난 12달간 %s 명의 기여자
contributions_zero = 기여 없음
contributions_format = {year}년 {month} {day}일에 {contributions}
contributions_one = 기여
contributions_few = 기여
contributions_zero = 기여 없음
contributions_format = {year}년 {month}월 {day}일의 기여자 {contributions}
contributions_one = 기여
contributions_few = 기여
less = 적은
more = 많은
@ -1897,20 +1897,20 @@ branch_kind = 브랜치 검색...
keyword_search_unavailable = 지금은 키워드로 검색이 지원되지 않습니다. 사이트 관리자에게 문의하십시오.
commit_kind = 커밋 검색...
no_results = 일치하는 결과를 찾을 수 없습니다.
search = 검색...
search = 검색
type_tooltip = 검색 타입
fuzzy_tooltip = 검색어와 밀접하게 일치하는 결과도 포함
repo_kind = 저장소 검색...
user_kind = 사용자 검색...
org_kind = 조직 검색...
repo_kind = 저장소 검색
user_kind = 사용자 검색
org_kind = 조직 검색
team_kind = 팀 검색...
code_kind = 코드 검색...
code_search_unavailable = 코드 검색은 현재 허용되지 않았습니다. 사이트 관리자와 연락하세요.
package_kind = 패키지 검색...
project_kind = 프로젝트 검색...
exact_tooltip = 검색어와 정확하게 일치하는 결과만 포함
issue_kind = 이슈 검색...
pull_kind = 풀 검색...
issue_kind = 이슈 검색
pull_kind = 풀 검색
milestone_kind = 마일스톤 검색...
fuzzy = 모호함
union = 통합 검색

View file

@ -228,7 +228,7 @@ server_internal = Iekšēja servera kļūda
app_desc=Pašmitināms Git pakalpojums bez galvassāpēm
install=Viegli uzstādīt
install_desc=Vienkārši <a target="_blank" rel="noopener noreferrer" href="%[1]s">jāpalaiž izpildāmā datne</a> vajadzīgajai sistēmai, jāizmanto <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> vai jāiegūst <a target="_blank" rel="noopener noreferrer" href="%[3]s">pakotne</a>.
platform=Pieejama dažādām platformām
platform=Dažādas platformas
lightweight=Viegla
lightweight_desc=Forgejo ir zemas tehniskās prasības, un to var darbināt nedārgā Raspberry Pi datorā. Taupām savas ierīces patērēto enerģiju!
license=Atvērtā pirmkoda
@ -1557,10 +1557,10 @@ issues.label_templates.helper=Atlasīt priekšiestatītu iezīmju kopu
issues.label_templates.use=Izmantot iezīmju kopu
issues.label_templates.fail_to_load_file=Neizdevās ielādēt iezīmju sagataves datni "%s": %v
issues.add_label=pievienoja %s iezīmi %s
issues.add_labels=pievienoja %s iezīmes %s
issues.add_labels=pievienoja iezīmes %s %s
issues.remove_label=noņēma %s iezīmi %s
issues.remove_labels=noņēma %s iezīmes %s
issues.add_remove_labels=pievienoja %s un noņēma %s iezīmes %s
issues.remove_labels=noņēma iezīmes %s %s
issues.add_remove_labels=pievienoja iezīmes %s un noņēma %s %s
issues.add_milestone_at=`pievienoja atskaites punktu <b>%s</b> %s`
issues.add_project_at=`pievienoja šo projektam <b>%s</b> %s`
issues.change_milestone_at=`nomainīja atskaites punktu no <b>%s</b> uz <b>%s</b> %s`
@ -1581,7 +1581,7 @@ issues.delete_branch_at=`izdzēsa zaru <b>%s</b> %s`
issues.filter_label=Iezīme
issues.filter_label_exclude=`Jāizmanto <code>alt</code> + <code>klikšķis/Enter</code>, lai neiekļautu iezīmes`
issues.filter_label_no_select=Visas iezīmes
issues.filter_label_select_no_label=Nav iezīmes
issues.filter_label_select_no_label=Bez iezīmes
issues.filter_milestone=Atskaites punkts
issues.filter_milestone_all=Visi atskaites punkti
issues.filter_milestone_none=Nav atskaites punkta
@ -2052,7 +2052,7 @@ wiki.filter_page=Meklēt lapu
wiki.new_page=Lapa
wiki.page_title=Lapas virsraksts
wiki.page_content=Lapas saturs
wiki.default_commit_message=Rakstīt piezīmes par šīs lapas izmaiņām (izvēles).
wiki.default_commit_message=Rakstīt piezīmes par šīs lapas izmaiņām (pēc izvēles).
wiki.save_page=Saglabāt lapu
wiki.last_commit_info=%s laboja lapu %s
wiki.edit_page_button=Labot
@ -2739,10 +2739,10 @@ error.csv.invalid_field_count=Nevar atveidot šo datni, jo tā satur nepareizu l
n_release_one = %s laidiens
n_release_few = %s laidieni
issues.new.assign_to_me = Piešķirt man
admin.flags_replaced = Glabātavas iezīmes aizvietotas
admin.failed_to_replace_flags = Neizdevās aizvietot glabātavas iezīmes
admin.manage_flags = Pārvaldīt iezīmes
admin.enabled_flags = Glabātavā iespējotās iezīmes:
admin.flags_replaced = Glabātavas karogi aizvietoti
admin.failed_to_replace_flags = Neizdevās aizvietot glabātavas karogus
admin.manage_flags = Pārvaldīt karogus
admin.enabled_flags = Glabātavā iespējotie karogi:
n_commit_one = %s iesūtījums
editor.push_out_of_date = Aizgādājums izskatās novecojis.
file_follow = Sekot simboliskajai saitei
@ -2764,7 +2764,7 @@ n_branch_one = %s zars
object_format_helper = Glabātavas objektu veidols. Vēlak to nevarēs mainīt. SHA1 ir vissaderīgākais.
commits.renamed_from = Pārdēvēts no %s
rss.must_be_on_branch = Jāatrodas zarā, lai iegūtu RSS barotni.
admin.update_flags = Atjaunināt iezīmes
admin.update_flags = Atjaunināt karogus
open_with_editor = Atvērt ar %s
n_commit_few = %s iesūtījumi
no_eol.text = Nav EOL

View file

@ -3618,7 +3618,7 @@ pin=Przypnij powiadomienie
mark_as_read=Oznacz jako przeczytane
mark_as_unread=Oznacz jak nieprzeczytane
mark_all_as_read=Oznacz wszystkie jako przeczytane
subscriptions = Subskrybcje
subscriptions = Subskrypcje
no_subscriptions = Brak subskrypcji
watching = Obserwowane

View file

@ -1407,7 +1407,7 @@ editor.file_is_a_symlink=`"%s" é um link simbólico. Links simbólicos não pod
editor.filename_is_a_directory=O nome do arquivo "%s" já é usado como um nome de diretório neste repositório.
editor.file_editing_no_longer_exists=O arquivo que está sendo editado, "%s", não existe mais neste repositório.
editor.file_deleting_no_longer_exists=O arquivo a ser excluído, "%s", não existe mais neste repositório.
editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as diferenças ou <strong>clique em Aplicar commit das alterações novamente</strong> para sobrescrever as alterações com sua versão atual.
editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você abriu o arquivo. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as diferenças ou <strong>clique em Aplicar commit das alterações novamente</strong> para sobrescrever as alterações com sua versão atual.
editor.file_already_exists=Um arquivo com nome "%s" já existe neste repositório.
editor.commit_empty_file_header=Fazer commit de um arquivo vazio
editor.commit_empty_file_text=O arquivo que você está prestes fazer commit está vazio. Continuar?

View file

@ -1420,7 +1420,7 @@ editor.file_is_a_symlink=`"%s" é uma ligação simbólica. Ligações simbólic
editor.filename_is_a_directory=O nome de ficheiro "%s" já está a ser usado como um nome de pasta neste repositório.
editor.file_editing_no_longer_exists=O ficheiro que está a ser editado, "%s", já não existe neste repositório.
editor.file_deleting_no_longer_exists=O ficheiro que está a ser eliminado, "%s", já não existe neste repositório.
editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que começou a editar. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou clique em <strong>Cometer modificações novamente</strong> para escrever por cima.
editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que abriu o ficheiro. <a target="_blank" rel="noopener noreferrer" href="%s">Clique aqui</a> para ver as modificações ou <strong>Cometer modificações novamente</strong> para escrever por cima.
editor.file_already_exists=Já existe um ficheiro com o nome "%s" neste repositório.
editor.commit_empty_file_header=Cometer um ficheiro vazio
editor.commit_empty_file_text=O ficheiro que está prestes a cometer está vazio. Quer continuar?

View file

@ -1696,7 +1696,7 @@ issues.num_participants_few=%d участников
issues.attachment.open_tab=`Нажмите, чтобы посмотреть «%s» в новой вкладке`
issues.attachment.download=`Нажмите, чтобы скачать «%s»`
issues.subscribe=Подписаться
issues.unsubscribe=Отказаться от подписки
issues.unsubscribe=Отписаться
issues.unpin_issue=Открепить задачу
issues.max_pinned=Нельзя закрепить больше задач
issues.pin_comment=закрепил(а) эту задачу %s

View file

@ -145,6 +145,9 @@ issues = Problémy
filter.is_archived = Archivované
filter.private = Súkromný
toggle_menu = Prepni menu
more_items = Viac vecí
[aria]
navbar=Navigačná lišta
footer=Päta

View file

@ -2245,15 +2245,15 @@ symbolic_link=Symbolisk länk
milestone_kind = Sök milstolpar...
exact = Exakt
exact_tooltip = Inkludera bara resultat som exakt matchar söktermen
repo_kind = Sök repon...
user_kind = Sök användare...
repo_kind = Sök repon
user_kind = Sök användare
code_kind = Sök kod...
package_kind = Sök paket...
runner_kind = Sök exekutorer...
branch_kind = Sök grenar...
commit_kind = Sök commiter...
project_kind = Sök projekt...
search = Sök...
search = Sök
type_tooltip = Söktyp
team_kind = Sök lag...
org_kind = Sök organisationer...
@ -2265,7 +2265,7 @@ no_results = Inga matchande resultat hittades.
code_search_by_git_grep = Nuvarande kodsökningsresultat gjordes med "git grep". Det kan finnas bättre resultat om webbplatsadministratören möjliggör indexering av kod.
fuzzy = Ungefärlig
union = Nyckelord
union_tooltip = Inkludera resultat som matchar något av de med mellanslag sepererade sökorden
union_tooltip = Inkludera resultat som matchar något av de med mellanslag separerade sökorden
pull_kind = Sök ändringsförslag…
regexp = RegExp
keyword_search_unavailable = Sökning på nyckelord är för närvarande inte tillgängligt. Vänligen kontakta webbplatsadministratören.

View file

@ -167,6 +167,8 @@ new_migrate.title = Yeni geçiş
new_migrate.link = Yeni geçiş
copy_path = Dizini kopyala
confirm_delete_artifact = "%s" adlı öğeyi silmek istediğinizden emin misiniz?
[aria]
navbar=Gezinti çubuğu
footer=Alt Bilgi
@ -3772,13 +3774,13 @@ submodule=Alt modül
[search]
project_kind = Projeleri ara...
org_kind = Organizasyonları ara...
team_kind = Takımları ara...
search = Ara...
code_kind = Kodları ara...
org_kind = Organizasyonları ara
team_kind = Takımları ara
search = Ara
code_kind = Kod ara…
type_tooltip = Arama türü
repo_kind = Depoları ara...
user_kind = Kullanıcıları ara...
user_kind = Kullanıcıları ara
milestone_kind = Kilometre taşlarını ara...
branch_kind = Dalları ara...
package_kind = Paketleri ara...

View file

@ -231,7 +231,7 @@ platform_desc=Forgejo підтверджено працює на вільних
lightweight=Невибагливість
lightweight_desc=Forgejo має низькі вимоги до ресурсів та може працювати на недорогому Raspberry Pi. Заощадьте енергію свого комп'ютера!
license=Відкритий вихідний код
license_desc=Відвідайте <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Приєднайтесь до нас та <a target="_blank" rel="noopener noreferrer" href="%[2]s">зробіть свій внесок</a> до проєкту, щоб зробити його ще краще. Не бійтеся долучитися!
license_desc=Відвідайте <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Приєднуйтеся до нас і <a target="_blank" rel="noopener noreferrer" href="%[2]s">зробіть свій внесок</a>, щоб покращити проєкт ще більше. Не бійтеся долучитися!
install_desc = Просто <a target="_blank" rel="noopener noreferrer" href="%[1]s">запустіть уже зібрану програму</a> для своєї платформи, розгорніть її за допомогою <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> або встановіть <a target="_blank" rel="noopener noreferrer" href="%[3]s">пакунок</a>.
[install]
@ -464,7 +464,7 @@ last_admin = Ви не можете видалити останнього адм
oauth.signin.error.access_denied = Запит на авторизацію було відхилено.
change_unconfirmed_email_error = Не вдалося змінити електронну адресу: %v
manual_activation_only = Зв'яжіться з адміністратором сайту, аби завершити активацію.
prohibit_login_desc = Ваш обліковий запис було відізвано від взаємодії з екземпляром. Звʼяжіться з адміністратором екземпляру, щоб отримати доступ знову.
prohibit_login_desc = Ваш обліковий запис було відізвано від взаємодії з екземпляром. Звʼяжіться з адміністратором екземпляра, щоб отримати доступ знову.
invalid_code_forgot_password = Ваш код підтвердження недійсний. Натисніть <a href="%s">тут</a>, аби почати нову сесію.
reset_password_wrong_user = Ви ввійшли як %s, але посилання на відновлення було передбачене для %s
back_to_sign_in = Назад до входу
@ -2366,8 +2366,8 @@ settings.packages_desc = Увімкнути реєстр пакунків реп
issues.role.contributor_helper = У цьому репозиторії є коміти цього користувача.
contributors.contribution_type.deletions = Видалення
contributors.contribution_type.filter_label = Вид внеску:
issues.role.contributor = Дописувач
activity.navbar.contributors = Дописувачі
issues.role.contributor = Учасник розробки
activity.navbar.contributors = Учасники розробки
settings.protected_branch.save_rule = Зберегти правило
release.tags_for = Теги %s
editor.file_is_a_symlink = `«%s» — символьне посилання. Символьні посилання не можна редагувати у вебредакторі`
@ -2521,7 +2521,7 @@ fork_branch = Гілка, яку буде клоновано у форк
already_forked = Ви вже створили форк %s
fork_to_different_account = Створити форк до іншого облікового запису
fork_no_valid_owners = Неможливо створити форк цього репозиторію, оскільки тут немає дійсних власників.
pulls.agit_explanation = Створено через робочий потік AGit. AGit дозволяє дописувачам пропонувати зміни за допомогою «git push» без створення форку або нової гілки.
pulls.agit_explanation = Створено через робочий потік AGit. AGit дозволяє учасникам пропонувати зміни за допомогою «git push» без створення форку або нової гілки.
diff.review.self_approve = Автори запитів на злиття не можуть схвалювати власні запити на злиття
settings.event_pull_request_approvals = Схвалення запитів на злиття
diff.git-notes.add = Додати примітку
@ -2661,6 +2661,8 @@ release.asset_name = Назва ресурсу
release.add_external_asset = Додати зовнішній ресурс
find_file.no_matching = Не знайдено відповідного файлу
issues.role.first_time_contributor = Новий учасник
[graphs]
contributors.what = внески
component_loading_info = Це може зайняти деякий час…

View file

@ -322,12 +322,12 @@ install_btn_confirm=立即安装
test_git_failed=无法识别 “git” 命令:%v
sqlite3_not_available=当前 Forgejo 版本不支持 SQLite3。请从 %s 下载官方构建版(注:请勿下载标有 “gobuild” 的版本)。
invalid_db_setting=数据库设置无效:%v
invalid_db_table=数据库表 '%s' 无效: %v
invalid_db_table=数据库表 '%s' 无效:%v
invalid_repo_path=仓库根目录设置无效:%v
invalid_app_data_path=应用数据路径无效: %v
invalid_app_data_path=应用数据路径无效:%v
run_user_not_match=运行用户名不是当前的用户名:%s -> %s
internal_token_failed=生成内部令牌失败: %v
secret_key_failed=生成密钥失败: %v
internal_token_failed=生成内部令牌失败:%v
secret_key_failed=生成密钥失败:%v
save_config_failed=应用配置保存失败:%v
invalid_admin_setting=管理员帐户设置无效:%v
invalid_log_root_path=日志路径无效:%v
@ -479,7 +479,7 @@ password_pwned_err=无法完成对 HaveIBeenPwned 的请求
last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。
change_unconfirmed_email = 如果您在注册时提供了错误的邮箱地址,您可以在下方修改,激活邮件会发送到修改后的邮箱地址。
change_unconfirmed_email_summary = 修改用来接收激活邮件的邮箱地址。
change_unconfirmed_email_error = 无法修改邮箱地址: %v
change_unconfirmed_email_error = 无法修改邮箱地址:%v
tab_signin = 登录
tab_signup = 注册
hint_login = 已经有账户了吗?<a href="%s">立即登录!</a>
@ -537,7 +537,7 @@ issue.in_tree_path=在 %s 中:
release.new.subject=%[2]s 中的 %[1]s 发布了
release.new.text=<b>@%[1]s</b> 于 %[3]s 发布了 %[2]s
release.title=标题: %s
release.title=标题:%s
release.note=注释:
release.downloads=下载:
release.download.zip=源代码ZIP
@ -617,7 +617,7 @@ include_error=`必须包含子字符串 "%s"。`
glob_pattern_error=`匹配模式无效:%s.`
regex_pattern_error=`正则表达式无效:%s.`
username_error=` 只允许包含字母数字字符“0-9”、“a-z”、“A-Z”、破折号“-”、下划线“_”和点“.”)。不能以非字母数字字符开头或结尾,并且不允许连续的非字母数字字符。`
invalid_group_team_map_error=`映射无效: %s`
invalid_group_team_map_error=`映射无效:%s`
unknown_error=未知错误:
captcha_incorrect=验证码不正确。
password_not_match=密码不匹配。
@ -659,7 +659,7 @@ organization_leave_success=您已成功离开组织 %s。
invalid_ssh_key=无法验证您的 SSH 密钥:%s
invalid_gpg_key=无法验证您的 GPG 密钥:%s
invalid_ssh_principal=无效的规则: %s
invalid_ssh_principal=无效的规则:%s
must_use_public_key=您提供的密钥是私钥。不要在任何地方上传您的私钥,请改用您的公钥。
unable_verify_ssh_key=无法验证 SSH 密钥,请仔细检查是否有错误。
auth_failed=授权验证失败:%v
@ -683,7 +683,7 @@ To = 分支名
AccessToken = 访问令牌
Description = 描述
Pronouns = 代称
Biography =
Biography =
username_claiming_cooldown = 用户名不能被认领,因为其仍处于保护期。其可以在%[1]s后被认领。
email_domain_is_not_allowed = 用户电子邮件地址的域名<b>%s</b>与EMAIL_DOMAIN_ALLOWLIST或EMAIL_DOMAIN_BLOCKLIST冲突。请确保您正确设置了电子邮件地址。
@ -1461,7 +1461,7 @@ commits.view_path=在历史记录中的此处查看
commit.operations=操作
commit.revert=还原
commit.revert-header=还原: %s
commit.revert-header=还原:%s
commit.revert-content=选择要还原的分支:
commit.cherry-pick=拣选
commit.cherry-pick-header=Cherry-pick%s
@ -2143,7 +2143,7 @@ activity.git_stats_deletion_n=%d 行被删除
contributors.contribution_type.filter_label=贡献类型:
contributors.contribution_type.commits=提交
contributors.contribution_type.additions=更多
contributors.contribution_type.additions=增加
contributors.contribution_type.deletions=删除
search=搜索
@ -2281,7 +2281,7 @@ settings.trust_model.collaborator=协作者
settings.trust_model.collaborator.long=协作者:信任协作者的签名
settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。
settings.trust_model.committer=提交者
settings.trust_model.committer.long=提交者: 信任与提交者相符的签名(此特性类似 GitHub这会强制采用 Forgejo 作为提交者和签名者)
settings.trust_model.committer.long=提交者:信任与提交者相符的签名(此特性类似 GitHub这会强制采用 Forgejo 作为提交者和签名者)
settings.trust_model.committer.desc=有效签名只有和提交者相匹配才会被标记为“受信任”,否则它们将被标记为“不匹配”。这强制 Forgejo 成为签名提交的提交者,而实际提交者被加上 Co-authored-by和 Co-committed-by的标记。 默认的 Forgejo 密钥必须匹配数据库中的一名用户。
settings.trust_model.collaboratorcommitter=协作者+提交者
settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名
@ -2502,9 +2502,9 @@ settings.protect_branch_name_pattern=受保护的分支名称正则
settings.protect_branch_name_pattern_desc=受保护的分支名称正则。语法请参阅<a href="%s">文档</a> 。如main, release/**
settings.protect_patterns=规则
settings.protect_protected_file_patterns=受保护的文件模式(使用半角分号“;”分隔)
settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用半角分号(“;”)分隔多个模式。 见<a href="%[1]s">%[2]s</a>文档了解模式语法。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>。
settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用半角分号(“;”)分隔多个模式。 见<a href="%[1]s">%[2]s</a>文档了解模式语法。例如:<code>.drone.yml</code>, <code>/docs/**/*.txt</code>。
settings.protect_unprotected_file_patterns=不受保护的文件模式(使用半角分号“;”分隔)
settings.protect_unprotected_file_patterns_desc=在用户有写权限的情况下允许绕过限制,直接修改设为不保护的文件。如有多个匹配模式,则可用半角分号(“;”)分隔开。见 <a href="%[1]s">%[2]s</a> 的文档以了解匹配模式的格式。例子: <code>.drone.yml</code>、<code>/docs/**/*.txt</code>。
settings.protect_unprotected_file_patterns_desc=在用户有写权限的情况下允许绕过限制,直接修改设为不保护的文件。如有多个匹配模式,则可用半角分号(“;”)分隔开。见 <a href="%[1]s">%[2]s</a> 的文档以了解匹配模式的格式。例子:<code>.drone.yml</code>、<code>/docs/**/*.txt</code>。
settings.add_protected_branch=启用保护
settings.delete_protected_branch=禁用保护
settings.update_protect_branch_success=分支保护规则 %s 更新成功。
@ -2545,7 +2545,7 @@ settings.matrix.room_id=房间ID
settings.matrix.message_type=消息类型
settings.archive.button=存档仓库
settings.archive.header=存档此仓库
settings.archive.text=存档仓库将使其完全只读。它将在首页隐藏。没有人(甚至你!)能够进行新的提交,或打开工单及合并请求。
settings.archive.text=存档仓库将使其完全只读。它将在首页隐藏。没有人(甚至包括你!)能够进行新的提交,或打开工单及合并请求。
settings.archive.success=仓库已成功存档。
settings.archive.error=仓库在存档时出现异常。请通过日志获取详细信息。
settings.archive.error_ismirror=不能存档镜像仓库。
@ -3083,11 +3083,11 @@ dashboard.task.process=任务:%[1]s
dashboard.task.cancelled=任务:%[1]s 已取消:%[3]s
dashboard.task.error=任务中的错误:%[1]s%[3]s
dashboard.task.finished=任务:%[2]s 启动的 %[1]s 已完成
dashboard.task.unknown=未知任务: %[1]s
dashboard.task.unknown=未知任务:%[1]s
dashboard.cron.started=已开始计划任务:%[1]s
dashboard.cron.process=计划任务:%[1]s
dashboard.cron.cancelled=定时任务:%[1]s 已取消:%[3]s
dashboard.cron.error=任务中的错误: %s%[3]s
dashboard.cron.error=任务中的错误:%s%[3]s
dashboard.cron.finished=任务:%[1]s 已经完成
dashboard.delete_inactive_accounts=删除所有未激活的帐户
dashboard.delete_inactive_accounts.started=删除所有未激活的账户任务已启动。
@ -3221,7 +3221,7 @@ emails.filter_sort.email_reverse=电子邮件(逆序)
emails.filter_sort.name=用户名
emails.filter_sort.name_reverse=用户名(倒序)
emails.updated=电子邮件已更新
emails.not_updated=无法更新请求的电子邮件地址: %v
emails.not_updated=无法更新请求的电子邮件地址:%v
emails.duplicate_active=此电子邮件地址已被另一个用户激活使用。
emails.change_email_header=更新电子邮件属性
emails.change_email_text=您确定要更新该电子邮件地址吗?
@ -3247,7 +3247,7 @@ repos.lfs_size=LFS 大小
packages.package_manage_panel=软件包管理
packages.total_size=总大小:%s
packages.unreferenced_size=未引用大小: %s
packages.unreferenced_size=未引用大小:%s
packages.cleanup=清理过期数据
packages.cleanup.success=清理过期数据成功
packages.owner=所有者
@ -3344,7 +3344,7 @@ auths.oauth2_group_claim_name=用于提供用户组名称的 Claim 声明名称
auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 - 需要上面的声明名称)
auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 - 需要上面的声明名称)
auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - 要求在上面填写声明的名字)
auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,同步团队中移除用户
auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从同步团队中移除用户
auths.enable_auto_register=允许自动注册
auths.sspi_auto_create_users=自动创建用户
auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登录时自动创建新账号
@ -3361,7 +3361,7 @@ auths.tips.oauth2.general=OAuth2 认证
auths.tips.oauth2.general.tip=当注册新的 OAuth2 身份验证时,回调/重定向 URL 应该是:
auths.tip.oauth2_provider=OAuth2 提供程序
auths.tip.bitbucket=`在 %s
auths.tip.nextcloud=使用下面的菜单“设置Settings -> 安全Security -> OAuth 2.0 client”在您的实例上注册一个新的 OAuth 客户端
auths.tip.nextcloud=使用菜单“设置->安全->OAuth 2.0客户端”在您的实例上注册一个新的 OAuth 客户端
auths.tip.dropbox=在 %s 上创建一个新的应用程序
auths.tip.facebook=`在 %s 注册一个新的应用,并添加产品"Facebook 登录"`
auths.tip.github=在 %s 注册一个 OAuth 应用程序
@ -3385,7 +3385,7 @@ auths.still_in_used=认证源仍在使用。请先解除或者删除使用此认
auths.deletion_success=认证源已经更新。
auths.login_source_exist=认证源 '%s' 已经存在。
auths.login_source_of_type_exist=此类型的认证源已存在。
auths.unable_to_initialize_openid=无法初始化 OpenID Connect 提供商: %s
auths.unable_to_initialize_openid=无法初始化 OpenID Connect 提供商:%s
auths.invalid_openIdConnectAutoDiscoveryURL=无效的 Auto Discovery URL这必须是一个以 http:// 或 https://开头的有效的 URL
config.server_config=服务器配置
@ -3546,7 +3546,7 @@ monitor.process.cancel_notices=中止:<strong>%s</strong>
monitor.process.children=子进程
monitor.queues=队列
monitor.queue=队列: %s
monitor.queue=队列:%s
monitor.queue.name=名称
monitor.queue.type=类型
monitor.queue.exemplar=数据类型
@ -3663,7 +3663,7 @@ raw_minutes=分钟
[dropzone]
default_message=拖放文件或点击此处上传。
invalid_input_type=您不能上传该类型的文件。
file_too_big=文件体积({{filesize}} MB超过了最大允许体积{{maxFilesize}} MB
file_too_big=文件体积({{filesize}} MB超过了最大允许体积{{maxFilesize}} MB
remove_file=移除文件
[notification]
@ -3694,7 +3694,7 @@ error.probable_bad_default_signature=警告虽然默认密钥拥有此ID
[units]
unit=单元
error.no_unit_allowed_repo=您没有被允许访问此仓库的任何单元。
error.unit_not_allowed=您没有权限访问此仓库单元
error.unit_not_allowed=您没有权限访问此仓库单元
[packages]
title=软件包
@ -3818,7 +3818,7 @@ settings.delete.error=删除软件包失败。
owner.settings.cargo.title=Cargo 注册中心索引
owner.settings.cargo.initialize=初始化索引
owner.settings.cargo.initialize.description=使用 Cargo 注册中心时需要一个特殊索引的 Git 仓库。使用此选项将(重新)创建仓库并自动配置它。
owner.settings.cargo.initialize.error=初始化Cargo索引失败 %v
owner.settings.cargo.initialize.error=初始化Cargo索引失败%v
owner.settings.cargo.initialize.success=Cargo索引已经成功创建。
owner.settings.cargo.rebuild=重建索引
owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。
@ -3877,11 +3877,11 @@ alt.repository.multiple_groups = 此软件包在多个组中可用。
[secrets]
secrets=密钥
description=Secrets 将被传给特定的 Actions其它情况将不能读取
description=机密将被传给特定的 Action其它情况将不能被读取。
none=还没有密钥。
creation=添加密钥
creation.name_placeholder=不区分大小写,只能包含英文字母、数字或下划线,不能以 GITEA_ 或 GITHUB_ 开头
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
creation.value_placeholder=输入任何内容。开头和结尾的空格都会被省略。
creation.success=您的密钥 '%s' 添加成功。
creation.failed=添加密钥失败。
deletion=删除密钥
@ -3916,7 +3916,7 @@ runners.description=组织描述
runners.labels=标签
runners.last_online=上次在线时间
runners.runner_title=运行器
runners.task_list=最近在此runner上的任务
runners.task_list=最近在此运行器上的任务
runners.task_list.no_tasks=还没有任务。
runners.task_list.run=执行
runners.task_list.status=状态
@ -3932,7 +3932,7 @@ runners.delete_runner_success=运行器删除成功
runners.delete_runner_failed=删除运行器失败
runners.delete_runner_header=确认要删除此运行器
runners.delete_runner_notice=如果一个任务正在运行在此运行器上,它将被终止并标记为失败。它可能会打断正在构建的工作流。
runners.none=无可用的 Runner
runners.none=无可用的运行器
runners.status.unspecified=未知
runners.status.idle=空闲
runners.status.active=激活
@ -3945,8 +3945,8 @@ runs.all_workflows=所有工作流
runs.commit=提交
runs.scheduled=已计划的
runs.pushed_by=推送者
runs.invalid_workflow_helper=工作流配置文件无效。请检查您的配置文件: %s
runs.no_matching_online_runner_helper=没有匹配标签的在线 runner %s
runs.invalid_workflow_helper=工作流配置文件无效。请检查您的配置文件:%s
runs.no_matching_online_runner_helper=没有匹配标签的在线运行器:%s
runs.actor=操作者
runs.status=状态
runs.actors_no_select=所有操作者
@ -3972,7 +3972,7 @@ variables.creation=添加变量
variables.none=目前还没有变量。
variables.deletion=删除变量
variables.deletion.description=删除变量是永久性的,无法撤消。继续吗?
variables.description=变量将被传给特定的 Actions,其它情况将不能读取
variables.description=变量将被传给特定的 Action,其它情况将不能读取
variables.id_not_exist=ID为 %d 的变量不存在。
variables.edit=编辑变量
variables.deletion.failed=删除变量失败。

View file

@ -105,7 +105,7 @@ preview=預覽
loading=載入中…
error=錯誤
error404=您嘗試造訪的頁面 <strong>不存在</strong> 或 <strong>您沒有權限</strong> 檢視該頁面。
error404=您嘗試造訪的頁面<strong>不存在</strong>、<strong>已被移除</strong>,或<strong>您沒有權限</strong>檢視該頁面。
never=從來沒有
unknown=未知
@ -207,6 +207,8 @@ table_modal.header = 新增表格
buttons.indent.tooltip = 使項目縮排一層
buttons.unindent.tooltip = 使項目取消縮排一層
link_modal.header = 新增連結
[filter]
string.asc=A - Z
string.desc=Z - A
@ -1098,7 +1100,7 @@ issue_labels=標籤
issue_labels_helper=選擇標籤集
license=授權條款
license_helper=選擇授權條款檔案
license_helper_desc=授權條款定義了他人使用您原始碼的允許和禁止事項。不確定哪個適用於您的專案?查看<a target="_blank" rel="noopener noreferrer" href="%s">選擇授權條款</a>
license_helper_desc=授權條款定義了他人使用您原始碼的允許和禁止事項。不確定哪個適用於您的專案?查看<a target="_blank" rel="noopener noreferrer" href="%s">選擇授權條款</a>
readme=讀我檔案
readme_helper=選擇讀我檔案範本
readme_helper_desc=這是您能為專案撰寫完整描述的地方。
@ -1204,7 +1206,7 @@ migrate.migrate_items_options=遷移其他項目需要存取符記
migrated_from=已從 <a href="%[1]s">%[2]s</a> 遷移
migrated_from_fake=已從 %[1]s 遷移
migrate.migrate=從 %s 遷移
migrate.migrating=正在從 <b>%s</b> 遷移...
migrate.migrating=正在從 <b>%s</b> 遷移
migrate.migrating_failed=從 <b>%s</b> 遷移失敗。
migrate.migrating_failed_no_addr=遷移失敗。
migrate.github.description=從 github.com 或 GitHub Enterprise 伺服器遷移資料。
@ -2377,7 +2379,7 @@ settings.lfs_invalid_locking_path=無效的路徑: %s
settings.lfs_invalid_lock_directory=無法鎖定目錄: %s
settings.lfs_lock_already_exists=鎖定已存在:%s
settings.lfs_lock=鎖定
settings.lfs_lock_path=要鎖定的檔案路徑...
settings.lfs_lock_path=要鎖定的檔案路徑
settings.lfs_locks_no_locks=沒有鎖定
settings.lfs_lock_file_no_exist=已鎖定的檔案不存在於預設分支
settings.lfs_force_unlock=強制解鎖
@ -3983,7 +3985,7 @@ commit_kind = 搜尋提交…
code_search_by_git_grep = 目前搜尋結果由「git grep」提供。如果網站管理員啟用程式碼索引可能會有更好的結果。
exact = 精確
milestone_kind = 搜尋里程碑...
issue_kind = 搜尋問題...
issue_kind = 搜尋問題
exact_tooltip = 只包含與搜尋詞完全相符的結合
pull_kind = 搜尋拉取…
regexp = 正規表示式

View file

@ -1,12 +1,15 @@
{
"repo.pulls.merged_title_desc": "yhdistetty %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "haluaa yhdistää %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "Etsi merkkipaaluja...",
"search.milestone_kind": "Etsi merkkipaaluja",
"home.welcome.no_activity": "Ei toimintaa",
"incorrect_root_url": "Tämä Forgejo-instanssi on määritetty toimimaan osoitteessa \"%s\". Tarkastelet tällä hetkellä Forgejoa eri URL-osoitteen kautta, mikä saattaa aiheuttaa sovelluksen osien toimimattomuutta. Virallinen URL-osoite on Forgejo-ylläpitäjien hallinnoima ROOT_URL-asetus app.ini -tiedostossa.",
"themes.names.forgejo-auto": "Forgejo (käyttöjärjestelmän määrittelemä teema)",
"home.welcome.activity_hint": "Syötteelläsi ei ole vielä mitään. Toimintasi ja toiminta repositorioissa joita seuraat ilmaantuu tälle sivulle.",
"home.explore_repos": "Tutki repositorioita",
"home.explore_users": "Tutki käyttäjiä",
"home.explore_orgs": "Tutki organisaatioita"
"home.explore_orgs": "Tutki organisaatioita",
"themes.names.forgejo-light": "Forgejo, vaalea",
"themes.names.forgejo-dark": "Forgejo, tumma",
"install.invalid_lfs_path": "LFS juurta ei voitu luoda polkuun: %[1]s"
}

View file

@ -4,5 +4,6 @@
},
"repo.pulls.title_desc": {
"other": "<code>%[2]s</code> 에서 <code id=\"%[4]s\">%[3]s</code> 로 %[1]d개의 커밋들을 병합하려함"
}
},
"home.welcome.no_activity": "활동 없음"
}

View file

@ -1,5 +1,6 @@
{
"repo.pulls.merged_title_desc": "scala %[1]d commity/ów z <code>%[2]s</code> do <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "chce scalić %[1]d commity/ów z <code>%[2]s</code> do <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "Wyszukaj kamienie milowe..."
"search.milestone_kind": "Wyszukaj kamienie milowe...",
"incorrect_root_url": "Ta instancja Forgejo jest skonfigurowana do korzystania z \"%s\". Obecnie oglądasz Forgejo za pomocą innego URL, co może powodować błędne działanie tej aplikacji. URL kanoniczny jest kontrolowany przez administratorów Forgejo za pomocą ROOT_URL w app.ini."
}

View file

@ -18,5 +18,6 @@
"incorrect_root_url": "Esta instância do Forgejo está configurada para o endereço \"%s\". Você está atualmente vendo o Forgejo através de uma URL diferente, o que pode causar erros em algumas partes da aplicação. A URL oficial é controlada pela administração do Forgejo através da configuração ROOT_URL no arquivo app.ini.",
"themes.names.forgejo-auto": "Forgejo (usar o tema do sistema)",
"themes.names.forgejo-light": "Forgejo claro",
"themes.names.forgejo-dark": "Forgejo escuro"
"themes.names.forgejo-dark": "Forgejo escuro",
"install.invalid_lfs_path": "Não foi possível criar um root LFS no caminho especificado: %[1]s"
}

View file

@ -18,5 +18,6 @@
"incorrect_root_url": "Esta instância do Forgejo está configurada para ser servida em “%s”. Atualmente, está a visualizar o Forgejo através de um URL diferente, o que pode causar a quebra de partes da aplicação. O URL official é controlado pelos administradores do Forgejo através da configuração ROOT_URL no ficheiro app.ini.",
"themes.names.forgejo-auto": "Forgejo (segue o tema do sistema)",
"themes.names.forgejo-light": "Forgejo claro",
"themes.names.forgejo-dark": "Forgejo escuro"
"themes.names.forgejo-dark": "Forgejo escuro",
"install.invalid_lfs_path": "Não foi possível criar a raiz LFS no caminho especificado: %[1]s"
}

View file

@ -1 +1,13 @@
{}
{
"home.welcome.no_activity": "Žiadna aktivita",
"home.welcome.activity_hint": "Vo vašom kanáli zatiaľ nič nie je. Tu sa budú zobrazovať vaše akcie a aktivity z repozitárov, ktoré sledujete.",
"home.explore_repos": "Preskúmajte repozitáre",
"home.explore_users": "Preskúmajte používateľov",
"home.explore_orgs": "Preskúmajte organizácie",
"search.milestone_kind": "Hľadať v míľnikoch…",
"incorrect_root_url": "Táto inštancia Forgejo je nakonfigurovaná tak, aby bola obsluhovaná na „%s“. Momentálne zobrazujete Forgejo prostredníctvom inej adresy URL, čo môže spôsobiť poruchu niektorých častí aplikácie. Kanonickú adresu URL kontrolujú správcovia aplikácie Forgejo prostredníctvom nastavenia ROOT_URL v súbore app.ini.",
"themes.names.forgejo-auto": "Forgejo (sleduj systémovú tému)",
"themes.names.forgejo-light": "Forgejo svetlé",
"themes.names.forgejo-dark": "Forgejo tmavé",
"install.invalid_lfs_path": "Nie je možné vytvoriť koreňový systém LFS na zadanej ceste: %[1]s"
}

View file

@ -1,5 +1,5 @@
{
"repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "搜尋里程碑..."
"search.milestone_kind": "搜尋里程碑"
}

View file

@ -300,8 +300,14 @@ func ServCommand(ctx *context.PrivateContext) {
return
}
} else {
// Because of the special ref "refs/for" we will need to delay write permission check
if git.SupportProcReceive && unitType == unit.TypeCode {
// We don't know yet which references the Git client wants to write to,
// but for AGit flow we have to degrade this check to a read permission.
// So if we support proc-receive (needed for AGit flow) and the unit type
// is code and we know the Git client wants to write to us, then degrade
// the permission check to read. The pre-receive hook will do another
// permission check which ensure for non AGit flow references the write
// permission is checked.
if git.SupportProcReceive && unitType == unit.TypeCode && ctx.FormString("verb") == "git-receive-pack" {
mode = perm.AccessModeRead
}

View file

@ -5,7 +5,9 @@ package admin
import (
"archive/zip"
"bytes"
"fmt"
"io"
"runtime"
"runtime/pprof"
"runtime/trace"
@ -45,14 +47,9 @@ func MonitorDiagnosis(ctx *context.Context) {
_, _ = f.Write([]byte(err.Error()))
}
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "trace.dat", Method: zip.Deflate, Modified: time.Now()})
if err != nil {
ctx.ServerError("Failed to create zip file", err)
return
}
if err := trace.Start(f); err != nil {
_, _ = f.Write([]byte(err.Error()))
traceBuf := &bytes.Buffer{}
if err := trace.Start(traceBuf); err != nil {
_, _ = traceBuf.Write([]byte(err.Error()))
}
select {
@ -62,6 +59,17 @@ func MonitorDiagnosis(ctx *context.Context) {
pprof.StopCPUProfile()
trace.Stop()
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "trace.dat", Method: zip.Deflate, Modified: time.Now()})
if err != nil {
ctx.ServerError("Failed to create zip file", err)
return
}
if _, err := io.Copy(f, traceBuf); err != nil {
ctx.ServerError("Failed to create zip file", err)
return
}
f, err = zipWriter.CreateHeader(&zip.FileHeader{Name: "goroutine-after.txt", Method: zip.Deflate, Modified: time.Now()})
if err != nil {
ctx.ServerError("Failed to create zip file", err)

View file

@ -249,7 +249,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
}
ctx.Data["Sources"] = sources
hasTOTP, err := auth.HasTwoFactorByUID(ctx, u.ID)
hasTOTP, err := auth.HasTOTPByUID(ctx, u.ID)
if err != nil {
ctx.ServerError("auth.HasTwoFactorByUID", err)
return nil

View file

@ -242,7 +242,7 @@ func SignInPost(ctx *context.Context) {
// If this user is enrolled in 2FA TOTP, we can't sign the user in just yet.
// Instead, redirect them to the 2FA authentication page.
hasTOTPtwofa, err := auth.HasTwoFactorByUID(ctx, u.ID)
hasTOTPtwofa, err := auth.HasTOTPByUID(ctx, u.ID)
if err != nil {
ctx.ServerError("UserSignIn", err)
return

View file

@ -155,15 +155,14 @@ func linkAccount(ctx *context.Context, u *user_model.User, gothUser goth.User, r
// If this user is enrolled in 2FA, we can't sign the user in just yet.
// Instead, redirect them to the 2FA authentication page.
// We deliberately ignore the skip local 2fa setting here because we are linking to a previous user here
_, err := auth.GetTwoFactorByUID(ctx, u.ID)
hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, u.ID)
if err != nil {
if !auth.IsErrTwoFactorNotEnrolled(err) {
ctx.ServerError("UserLinkAccount", err)
return
}
err = externalaccount.LinkAccountToUser(ctx, u, gothUser)
if err != nil {
if !hasTwoFactor {
if err := externalaccount.LinkAccountToUser(ctx, u, gothUser); err != nil {
ctx.ServerError("UserLinkAccount", err)
return
}

View file

@ -1079,7 +1079,7 @@ func SignInOAuthCallback(ctx *context.Context) {
isAdmin, isRestricted := getUserAdminAndRestrictedFromGroupClaims(source, &gothUser)
u.IsAdmin = isAdmin.ValueOrDefault(false)
u.IsRestricted = isRestricted.ValueOrDefault(false)
u.IsRestricted = isRestricted.ValueOrDefault(setting.Service.DefaultUserIsRestricted)
if !createAndHandleCreatedUser(ctx, base.TplName(""), nil, u, overwriteDefault, &gothUser, setting.OAuth2Client.AccountLinking != setting.OAuth2AccountLinkingDisabled) {
// error already handled
@ -1243,12 +1243,11 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
needs2FA := false
if !source.Cfg.(*oauth2.Source).SkipLocalTwoFA {
_, err := auth.GetTwoFactorByUID(ctx, u.ID)
if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) {
needs2FA, err = auth.HasTwoFactorByUID(ctx, u.ID)
if err != nil {
ctx.ServerError("UserSignIn", err)
return
}
needs2FA = err == nil
}
oauth2Source := source.Cfg.(*oauth2.Source)

View file

@ -36,7 +36,7 @@ func WebAuthn(ctx *context.Context) {
return
}
hasTwoFactor, err := auth.HasTwoFactorByUID(ctx, ctx.Session.Get("twofaUid").(int64))
hasTwoFactor, err := auth.HasTOTPByUID(ctx, ctx.Session.Get("twofaUid").(int64))
if err != nil {
ctx.ServerError("HasTwoFactorByUID", err)
return

View file

@ -0,0 +1,7 @@
-
id: 1004
uuid: "fb857e63-c0ce-4571-a6c9-fde26c128073"
name: "Global runner"
owner_id: 0
repo_id: 0
deleted: 0

View file

@ -0,0 +1,160 @@
-
id: 1
runner_id: 1004
token_hash: a1
-
id: 2
runner_id: 1004
token_hash: a2
-
id: 3
runner_id: 1004
token_hash: a3
-
id: 4
runner_id: 1004
token_hash: a4
-
id: 5
runner_id: 1004
token_hash: a5
-
id: 6
runner_id: 1004
token_hash: a6
-
id: 7
runner_id: 1004
token_hash: a7
-
id: 8
runner_id: 1004
token_hash: a8
-
id: 9
runner_id: 1004
token_hash: a9
-
id: 10
runner_id: 1004
token_hash: a10
-
id: 11
runner_id: 1004
token_hash: a11
-
id: 12
runner_id: 1004
token_hash: a12
-
id: 13
runner_id: 1004
token_hash: a13
-
id: 14
runner_id: 1004
token_hash: a14
-
id: 15
runner_id: 1004
token_hash: a15
-
id: 16
runner_id: 1004
token_hash: a16
-
id: 17
runner_id: 1004
token_hash: a17
-
id: 18
runner_id: 1004
token_hash: a18
-
id: 19
runner_id: 1004
token_hash: a19
-
id: 20
runner_id: 1004
token_hash: a20
-
id: 21
runner_id: 1004
token_hash: a21
-
id: 22
runner_id: 1004
token_hash: a22
-
id: 23
runner_id: 1004
token_hash: a23
-
id: 24
runner_id: 1004
token_hash: a24
-
id: 25
runner_id: 1004
token_hash: a25
-
id: 26
runner_id: 1004
token_hash: a26
-
id: 27
runner_id: 1004
token_hash: a27
-
id: 28
runner_id: 1004
token_hash: a28
-
id: 29
runner_id: 1004
token_hash: a29
-
id: 30
runner_id: 1004
token_hash: a30
-
id: 31
runner_id: 1004
token_hash: a31
-
id: 32
runner_id: 1004
token_hash: a32
-
id: 33
runner_id: 1004
token_hash: a33
-
id: 34
runner_id: 1004
token_hash: a34
-
id: 35
runner_id: 1004
token_hash: a35
-
id: 36
runner_id: 1004
token_hash: a36
-
id: 37
runner_id: 1004
token_hash: a37
-
id: 38
runner_id: 1004
token_hash: a38
-
id: 39
runner_id: 1004
token_hash: a39
-
id: 40
runner_id: 1004
token_hash: a40

View file

@ -0,0 +1,17 @@
// Copyright 2025 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"testing"
"forgejo.org/models/unittest"
_ "forgejo.org/models"
_ "forgejo.org/models/forgefed"
)
func TestMain(m *testing.M) {
unittest.MainTest(m)
}

View file

@ -79,7 +79,6 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
Page: page,
PageSize: 30,
},
Status: []actions_model.Status{actions_model.StatusUnknown}, // Unknown means all
RunnerID: runner.ID,
}

View file

@ -0,0 +1,47 @@
// Copyright 2025 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"net/http"
"testing"
actions_model "forgejo.org/models/actions"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/services/contexttest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRunnerDetails(t *testing.T) {
defer unittest.OverrideFixtures("routers/web/shared/actions/fixtures/TestRunnerDetails")()
require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
runner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1004})
t.Run("permission denied", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
RunnerDetails(ctx, 1, runner.ID, user.ID, 0)
assert.Equal(t, http.StatusNotFound, resp.Code)
})
t.Run("first page", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
page := 1
RunnerDetails(ctx, page, runner.ID, 0, 0)
require.Equal(t, http.StatusOK, resp.Code)
assert.Len(t, ctx.GetData()["Tasks"], 30)
})
t.Run("second and last page", func(t *testing.T) {
ctx, resp := contexttest.MockContext(t, "/admin/actions/runners")
page := 2
RunnerDetails(ctx, page, runner.ID, 0, 0)
require.Equal(t, http.StatusOK, resp.Code)
assert.Len(t, ctx.GetData()["Tasks"], 10)
})
}

View file

@ -55,7 +55,7 @@ func DeleteAccountLink(ctx *context.Context) {
}
func loadSecurityData(ctx *context.Context) {
enrolled, err := auth_model.HasTwoFactorByUID(ctx, ctx.Doer.ID)
enrolled, err := auth_model.HasTOTPByUID(ctx, ctx.Doer.ID)
if err != nil {
ctx.ServerError("SettingsTwoFactor", err)
return

View file

@ -689,7 +689,7 @@ func SendRemovedSecurityKey(ctx context.Context, u *user_model.User, securityKey
if err != nil {
return err
}
hasTOTP, err := auth_model.HasTwoFactorByUID(ctx, u.ID)
hasTOTP, err := auth_model.HasTOTPByUID(ctx, u.ID)
if err != nil {
return err
}

View file

@ -98,7 +98,7 @@ func getRemoteUserToPromote(ctx context.Context, source *auth_model.Source, logi
return nil, NewReason(log.ERROR, ReasonErrorLoginName, "getUserByLoginName('%s') %v", loginName, err), err
}
if len(users) == 0 {
return nil, NewReason(log.ERROR, ReasonLoginNameNotExists, "no user with LoginType UserTypeRemoteUser and LoginName '%s'", loginName), nil
return nil, NewReason(log.DEBUG, ReasonLoginNameNotExists, "no user with LoginType UserTypeRemoteUser and LoginName '%s'", loginName), nil
}
reason := ReasonNoSource

View file

@ -67,13 +67,7 @@ func TestDeleteUser(t *testing.T) {
}
func TestPurgeUser(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/user/TestPurgeUser/"},
},
)()
defer unittest.OverrideFixtures("services/user/TestPurgeUser")()
require.NoError(t, unittest.PrepareTestDatabase())
defer test.MockVariableValue(&setting.SSH.RootPath, t.TempDir())()
defer test.MockVariableValue(&setting.SSH.CreateAuthorizedKeysFile, true)()

View file

@ -4,7 +4,6 @@
package webhook
import (
"path/filepath"
"testing"
"forgejo.org/models/db"
@ -56,13 +55,7 @@ func pushCommits() *repository.PushCommits {
}
func TestSyncPushCommits(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/webhook/TestPushCommits"},
},
)()
defer unittest.OverrideFixtures("services/webhook/TestPushCommits")()
require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -95,13 +88,7 @@ func TestSyncPushCommits(t *testing.T) {
}
func TestPushCommits(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"services/webhook/TestPushCommits"},
},
)()
defer unittest.OverrideFixtures("services/webhook/TestPushCommits")()
require.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -2,11 +2,11 @@
<div class="tw-flex tw-justify-between tw-mb-4">
<div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?state=open&q={{$.Keyword}}">
{{svg "octicon-project-symlink" 16 "tw-mr-2"}}
{{svg "octicon-project-symlink" 16}}
{{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?state=closed&q={{$.Keyword}}">
{{svg "octicon-check" 16 "tw-mr-2"}}
{{svg "octicon-check" 16}}
{{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a>
</div>

View file

@ -77,8 +77,10 @@
{{else}}
{{if eq $type "tag"}}
{{svg "octicon-tag"}}
{{else}}
{{else if eq $type "branch"}}
{{svg "octicon-git-branch"}}
{{else}}
{{svg "octicon-git-commit"}}
{{end}}
<strong ref="dropdownRefName" class="tw-ml-2 tw-inline-block gt-ellipsis">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
{{end}}

View file

@ -48,11 +48,11 @@
</div>
<div class="switch">
<button id="flow-color-monochrome" class="{{if eq .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.monochrome"}}">
{{svg "material-invert-colors" 16 "tw-mr-1"}}
{{svg "material-invert-colors" 16}}
{{ctx.Locale.Tr "repo.commit_graph.monochrome"}}
</button>
<button id="flow-color-colored" class="{{if ne .Mode "monochrome"}}active {{end}}item" title="{{ctx.Locale.Tr "repo.commit_graph.color"}}">
{{svg "material-palette" 16 "tw-mr-1"}}
{{svg "material-palette" 16}}
{{ctx.Locale.Tr "repo.commit_graph.color"}}
</button>
</div>

View file

@ -1,21 +1,21 @@
<div class="switch">
<a class="{{if eq .State "open"}}active {{end}}item" href="{{.OpenLink}}" data-test-name="open-issue-count">
{{if .PageIsMilestones}}
{{svg "octicon-milestone" 16 "tw-mr-2"}}
{{svg "octicon-milestone" 16}}
{{else if .PageIsPullList}}
{{svg "octicon-git-pull-request" 16 "tw-mr-2"}}
{{svg "octicon-git-pull-request" 16}}
{{else}}
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
{{svg "octicon-issue-opened" 16}}
{{end}}
{{ctx.Locale.PrettyNumber .OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a>
<a class="{{if eq .State "closed"}}active {{end}}item" href="{{.ClosedLink}}" data-test-name="closed-issue-count">
{{svg "octicon-issue-closed" 16 "tw-mr-2"}}
{{svg "octicon-issue-closed" 16}}
{{ctx.Locale.PrettyNumber .ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a>
{{if not .PageIsMilestones}}
<a class="{{if eq .State "all"}}active {{end}}item" href="{{.AllStatesLink}}" data-test-name="all-issue-count">
{{svg "octicon-eye" 16 "tw-mr-2"}}
{{svg "octicon-eye" 16}}
{{ctx.Locale.PrettyNumber (.AllCount)}}&nbsp;{{ctx.Locale.Tr "repo.issues.all_title"}}
</a>
{{end}}

View file

@ -526,7 +526,7 @@
{{else if eq .Type 27}}
{{if or .AddedRequestReview .RemovedRequestReview}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge">{{svg "octicon-tag"}}</span>
<span class="badge">{{svg "octicon-eye"}}</span>
{{template "shared/user/avatarlink" dict "user" .Poster}}
<span class="text grey muted-links">
{{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}}
@ -724,7 +724,7 @@
{{if or .AddedRequestReview .RemovedRequestReview}}
<li>
<span class="badge">{{svg "octicon-tag" 20}}</span>
<span class="badge">{{svg "octicon-eye" 20}}</span>
<span class="text grey muted-links">
{{if and (eq (len .RemovedRequestReview) 1) (eq (len .AddedRequestReview) 0) (eq ((index .RemovedRequestReview 0).ID) .PosterID) (eq ((index .RemovedRequestReview 0).Type) "user")}}

View file

@ -6,11 +6,11 @@
<div class="list-header">
<div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&q={{$.Keyword}}">
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
{{svg "octicon-issue-opened" 16}}
{{ctx.Locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?type={{$.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&q={{$.Keyword}}">
{{svg "octicon-issue-closed" 16 "tw-mr-2"}}
{{svg "octicon-issue-closed" 16}}
{{ctx.Locale.PrettyNumber .IssueStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a>
</div>

View file

@ -37,11 +37,11 @@
<div class="list-header">
<div class="switch list-header-toggle">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
{{svg "octicon-milestone" 16 "tw-mr-2"}}
{{svg "octicon-milestone" 16}}
{{ctx.Locale.PrettyNumber .MilestoneStats.OpenCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=closed&q={{$.Keyword}}">
{{svg "octicon-check" 16 "tw-mr-2"}}
{{svg "octicon-check" 16}}
{{ctx.Locale.PrettyNumber .MilestoneStats.ClosedCount}}&nbsp;{{ctx.Locale.Tr "repo.issues.closed_title"}}
</a>
</div>

View file

@ -13,6 +13,7 @@ import (
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/git"
"forgejo.org/modules/indexer/stats"
files_service "forgejo.org/services/repository/files"
"forgejo.org/tests"
@ -36,6 +37,10 @@ func DeclareGitRepos(t *testing.T) func() {
Filename: "testfile",
Versions: []string{"hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"},
}}),
newRepo(t, 2, "language-stats-test", []FileChanges{{
Filename: "main.rs",
Versions: []string{"fn main() {", "println!(\"Hello World!\");", "}"},
}}),
newRepo(t, 2, "mentions-highlighted", []FileChanges{
{
Filename: "history1.md",
@ -105,5 +110,8 @@ func newRepo(t *testing.T, userID int64, repoName string, fileChanges []FileChan
}
}
err := stats.UpdateRepoIndexer(somerepo)
require.NoError(t, err)
return cleanupFunc
}

View file

@ -0,0 +1,15 @@
// @watch start
// template/base/paginate.tmpl
// services/context/pagination.go
// @watch end
import {expect} from '@playwright/test';
import {test} from './utils_e2e.ts';
import {accessibilityCheck} from './shared/accessibility.ts';
test('Pagination a11y', async ({page}) => {
await page.goto('/explore/repos');
await expect(page.locator('.pagination')).toBeVisible();
await accessibilityCheck({page}, ['.pagination'], [], []);
});

View file

@ -1,19 +0,0 @@
// @watch start
// web_src/js/features/common-global.js
// web_src/css/repo.css
// @watch end
import {expect} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
test('Language stats bar', async ({page}) => {
const response = await page.goto('/user2/repo1');
expect(response?.status()).toBe(200);
await expect(page.locator('#language-stats-legend')).toBeVisible();
await save_visual(page);
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeHidden();
await save_visual(page);
});

View file

@ -0,0 +1,35 @@
// @watch start
// web_src/js/components/RepoBranchTagSelector.vue
// web_src/js/features/common-global.js
// web_src/css/repo.css
// @watch end
import {expect} from '@playwright/test';
import {save_visual, test} from './utils_e2e.ts';
test('Language stats bar', async ({page}) => {
const response = await page.goto('/user2/language-stats-test');
expect(response?.status()).toBe(200);
await expect(page.locator('#language-stats-legend')).toBeHidden();
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeVisible();
await save_visual(page);
await page.click('#language-stats-bar');
await expect(page.locator('#language-stats-legend')).toBeHidden();
await save_visual(page);
});
test('Branch selector commit icon', async ({page}) => {
const response = await page.goto('/user2/repo1');
expect(response?.status()).toBe(200);
await expect(page.locator('.branch-dropdown-button svg.octicon-git-branch')).toBeVisible();
await expect(page.locator('.branch-dropdown-button')).toHaveText('master');
await page.goto('/user2/repo1/src/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d');
await expect(page.locator('.branch-dropdown-button svg.octicon-git-commit')).toBeVisible();
await expect(page.locator('.branch-dropdown-button')).toHaveText('65f1bf27bc');
});

View file

@ -19,7 +19,7 @@ import (
)
func TestActionVariablesModification(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestActionVariablesModification")()
defer unittest.OverrideFixtures("tests/integration/fixtures/TestActionVariablesModification")()
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -98,7 +98,7 @@ func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
}
func TestAdminDeleteUser(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestAdminDeleteUser/")()
defer unittest.OverrideFixtures("tests/integration/fixtures/TestAdminDeleteUser")()
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1")

View file

@ -167,7 +167,7 @@ func TestBlockUserFromOrganization(t *testing.T) {
// and as a blocked user and are handled cleanly after the blocking has taken
// place.
func TestBlockActions(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestBlockActions/")()
defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockActions")()
defer tests.PrepareTestEnv(t)()
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
@ -438,7 +438,7 @@ func TestBlockActions(t *testing.T) {
}
func TestBlockedNotification(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestBlockedNotifications")()
defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockedNotifications")()
defer tests.PrepareTestEnv(t)()
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

View file

@ -19,7 +19,7 @@ import (
// As it is not possible to do actions as system users, the tests are done using fixtures.
func TestSystemCommentRoles(t *testing.T) {
defer tests.AddFixtures("tests/integration/fixtures/TestSystemCommentRoles/")()
defer unittest.OverrideFixtures("tests/integration/fixtures/TestSystemCommentRoles")()
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})

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