Compare commits

..
38 Commits
Author SHA1 Message Date
bircniandGitHub b969123b7f chore: don't auto refresh the merge box when user has interacted with it (#38436)
Backport #38435

Otherwise, the user just isn't able to use "auto merge" form
2026-07-13 02:54:47 -07:00
bircniandGitHub c6627af968 docs: update changelog for 1.27.0 (#38427) 2026-07-13 06:31:20 +02:00
de4b8277e9 fix: various security fixes (#38406) (#38426)
Backport #38406 by @bircni

Addresses a batch of privately reported security issues, grouped by
area:

- **SSRF** - migration PR-patch/asset fetches, OAuth2 avatar & OpenID
discovery, pull-mirror URL re-validation, and the outbound proxy path.
- **Access-token scope** - prevent scope escalation on token creation;
keep public-only tokens confined (feeds, packages, Actions listings,
star/watch lists, limited/private owners).
- **Access control / disclosure** - go-get default-branch leak, webhook
authorization-header leak, watch clearing on private transitions,
label/attachment scoping.
- **Denial of service** - input bounds for npm dist-tags, Debian control
files, Arch file lists, and SSH keys.

### 📌 Attention for site admins

Not breaking - existing configs keep working - but two changes are worth
a look:

- **New SSRF protection** Outbound requests (migrations, OAuth2 avatars,
OpenID discovery, pull mirrors, proxy path) are now validated against
the allow/block host lists. If your instance legitimately reaches
internal hosts, you may need to add them to
`[security].ALLOWED_HOST_LIST` (and the relevant `ALLOW_LOCALNETWORKS`
settings).
- **Deprecation** `[webhook].ALLOWED_HOST_LIST` is deprecated and will
be removed in a future release. Use `[security].ALLOWED_HOST_LIST`
instead; the old key still works for now.

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-07-12 17:41:58 +00:00
acbc75e2bd fix(util): reject invalid characters between time-estimate units (#38416) (#38423)
Backport #38416 by @TowyTowy

### What / why

`TimeEstimateParse` (used by the issue time-estimate form) only checked
that the first token starts at the beginning of the string and the last
token ends at its end, but never checked the gaps between consecutive
tokens. Non-whitespace garbage embedded between two valid units was
silently dropped and the string accepted with a wrong value instead of
being reported as invalid.

Examples that were wrongly accepted before this change:

- `1h 2x 3m` → 3780s (parsed as 1h3m)
- `1h_2m`    → 3720s
- `1h,1m`    → 3660s

All three now return an "invalid time string" error, while valid inputs
such as `1h 1m 1s` and `1h1m1s` keep working.

### How

Reject any non-whitespace content between two matched units.

Signed-off-by: TowyTowy <towy@airreps.link>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: TowyTowy <85077986+TowyTowy@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-12 09:59:28 -07:00
c3325be816 fix: represent a deleted assignee team as a Ghost team (#38413) (#38419)
Backport #38413

Fixes #35472.

Co-authored-by: Harsh Satyajit Thakur <f20240223@goa.bits-pilani.ac.in>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-12 13:06:24 +00:00
d4250bafd9 fix(turnstile): route CAPTCHA verification through the configured proxy (#38412) (#38420)
Backport #38412

Fixes #38217

Co-authored-by: Lovepreet Singh <lovepreet.singh61182@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-12 05:39:14 -07:00
6815d1646c fix: refresh pull request merge box when the commit status is pending (#38410) (#38411)
Backport #38410

Before: the merge box is only refreshed when the PR is being
conflict-checked.

After: also refresh the merge box when the commit status is pending
(e.g.: Action task is running)

By the way, slightly increase the refresh interval to 5s

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-12 07:15:25 +08:00
8ba4d4ebec fix: actions task state concurrent update (#38405) (#38409)
Backport #38405

fix #38333

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-11 16:51:32 +02:00
b2794f96b9 fix(actions): keep workflow run trailing on one row with long branch names (#38382) (#38403)
Backport #38382 by @bircni

The flex-list refactor (#37505) raised the shared `.item-trailing`
selector's specificity, so its `flex-wrap: wrap` started overriding the
run list's intended `flex-wrap: nowrap` — a long branch name pushed the
trailing content past its fixed 280px width and wrapped the kebab menu
onto its own line.

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-10 22:08:24 +00:00
b6aa2b61c6 fix(web): use locale-aware date formatting for contribution calendar tooltips (#38398) (#38401)
Backport #38398 by @SudhanshuMatrix

The contribution calendar manually constructed localized date strings
instead of using the browser's locale-aware date formatting. Replace
this with `toLocaleDateString()` to correctly format dates for all
locales and calendar systems, including non-Gregorian calendars.

Fixes https://github.com/go-gitea/gitea/issues/38375
---

### Before and After Comparison (Persian `fa-IR`)

Before (Buggy) 
 
<img width="1246" height="651" alt="image"
src="https://github.com/user-attachments/assets/670698e6-dd4a-4c7e-b7fb-23849090d1b9"
/>
 
After (Fixed) 
<img width="1246" height="651" alt="image"
src="https://github.com/user-attachments/assets/9b65c647-876e-475b-98d1-614ef316fd6f"
/>

Co-authored-by: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
2026-07-10 21:28:54 +00:00
74ad781db9 fix(pull): re-evaluate review official flag on target branch change (#38319) (#38402)
Backport #38319 by @bircni

The `official` flag of a pull request review is computed against the
target branch's protection rules at submit time and stored on the review
record. `ChangeTargetBranch` updated the base branch but never
re-evaluated it, so an `official` approval obtained against an
unprotected branch could be retargeted onto a protected branch and
satisfy its required approvals, bypassing the branch protection.

This re-evaluates the `official` flag of the latest approve/reject
reviews against the new base branch whenever the target branch changes.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-10 19:42:00 +00:00
GiteabotandGitHub ed493f0684 fix(security): harden access checks and migration validation (#38324) (#38400) 2026-07-10 20:14:38 +02:00
af7ba2edef fix: enforce public-only token scope and harden push options / locale parsing (#38323) (#38399)
Backport #38323 by @bircni

Three independent security hardening fixes, each with a regression test:

- **Locale DoS:** the `Locale` middleware passed the raw
`Accept-Language` header to `ParseAcceptLanguage`, whose guard only
counts `-` while the scanner aliases `_` to `-` — a large `_`-separated
header on an unauthenticated request burned CPU. The header is now
length-bounded before parsing.
- **Public-only token scope:** `GET /teams/{id}/repos`,
`.../repos/{org}/{repo}`, `/teams/{id}/activities/feeds`, and
`/users/{username}/orgs/{org}/permissions` still returned private
repo/activity/permission data to a public-only token. They now filter
via `TokenCanAccessRepo` / `ApplyPublicOnly` and reject non-public org
permissions.
- **Push-option visibility:** `repo.private` / `repo.template` push
options were applied to any existing repo, letting an owner/admin
silently flip visibility bypassing audit, webhooks, and notifications.
They are now honored only on push-to-create.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-10 19:07:04 +02:00
8b4252e7f6 fix: co-author detection (#38392) (#38397)
Backport #38392

Fix #38384

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-10 11:15:20 +00:00
500a09e044 fix(api): stop leaking private repo metadata after access revocation (#38321) (#38390)
Backport #38321 by @bircni

The `/user/starred` and `/user/subscriptions` endpoints returned private
repositories a user had starred/watched even after their access to those
repositories was revoked, still exposing the repository name,
description and visibility (including later metadata changes).

Private repositories in the starred/watched queries are now gated on the
actor's current access via `AccessibleRepositoryCondition`, so users who
no longer have access no longer receive the metadata. Public
repositories and public-only tokens are unaffected.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-10 07:40:02 +00:00
bfebc4b0e1 fix: incorrect co-author detection on commit page (#38386) (#38387)
Backport #38386 by @bircni


The commit page built its "co-authored by" list from
`AllParticipantIdentities()[1:]`, which only drops the author and leaves
the committer in the list even though the committer is already shown
separately as "committed by". This caused the committer to be wrongly
rendered as a co-author (issue #38384): a commit authored by
`silverwind`, committed by `bircni`, with a `Co-authored-by: silverwind`
trailer displayed "co-authored by bircni" instead of the actual trailer
identity. This adds a `Commit.CoAuthorIdentities()` method that excludes
both the author and the committer, uses it on the commit page, and
covers the fix with a regression test.

Closes #38384

Co-authored-by: bircni <bircni@icloud.com>
2026-07-09 18:29:28 -07:00
d9534e7bfa fix(lfs): require proof of possession for cross-repo objects (#38322) (#38389)
Backport #38322 by @bircni

The LFS batch and upload handlers linked an object that already existed
in the content store but was not linked to the current repo whenever the
token's user could access it in another repo. Deploy-key tokens carry
the repo owner's identity, so a single-repo write deploy key could link
and then download objects from any repo the owner can see.

This drops the cross-repo access check: the batch handler now makes the
client upload (hash-verified) any object not yet linked to the repo, and
the upload handler skips proof of possession only when the object is
already linked to the current repo.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-09 22:18:07 +00:00
532828cc82 enhance(actions): only create filtered-out workflow commit status for required contexts (#38371) (#38385)
Backport #38371 by @Zettat123

Follow #38237

#38237 posts "skipped" commit statuses for every workflow that is not
triggered due to a filter (e.g. `paths` or `branches`) mismatch.
However, for non-required workflows, creating "skipped" commit statuses
for them would generate a lot of noise.

To address this issue, this PR adds a check before creating commit
status:

- For the context that matches any required status check patterns, a
"skipped" commit status will be created. The `Required` label can inform
users that this status check is required, but has been skipped because
of a filter mismatch.

<img width="800" alt="image"
src="https://github.com/user-attachments/assets/264fd716-413c-457d-a5a6-6717175d3807"
/>

- For a non-required context, nothing will be created.

NOTE: Reducing noise is a best-effort approach and isn't entirely
accurate. When creating commit statuses, it is impossible to predict
which branch protection rule will take effect. Therefore, we have to
compare the commit status context against the required patterns from all
rules. If any rule matches, the context is considered "required".
 
Closes https://github.com/go-gitea/gitea/issues/38351

Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-07-09 15:58:46 +00:00
8cf988f0a6 fix(ui): restore commits table column widths (#38379) (#38383)
Backport #38379 by @silverwind

https://github.com/go-gitea/gitea/pull/37594 widened the author column
from `three wide` to `four wide`, leaving a large empty gap around the
SHA column in the common single-author case. The old author cell was
capped at 180px, so the wider column only adds whitespace: avatar-stack
names ellipsize at 240px each, and wider multi-author rows still expand
naturally in the auto-layout table. Restore the pre-existing
`three`/`eight` widths.

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
2026-07-09 17:07:20 +02:00
04a26f40a0 test(e2e): fix race in pdf file render test (#38380) (#38381)
Backport #38380 by @silverwind

`data-render-name` is set before the plugin's async render runs, so
measuring the container height right after the attribute appears can
observe the pre-render 48px height when the `pdfobject` chunk loads
slowly (flaked in CI). Poll for the height instead, like the asciicast
test in the same file does.

Co-authored-by: silverwind <me@silverwind.io>
2026-07-09 13:57:50 +00:00
fc4eac390a fix: golang html template url escaping (#38363) (#38369)
Backport #38363

fix #38362

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-08 12:10:26 +08:00
64d559a8e6 perf(actions): debounce runner heartbeat writes and throttle task picks (#38281) (#38368)
Backport #38281 by @bircni

3 reductions in the DB load generated by many runners polling `FetchTask`:

**1. Debounce runner heartbeat writes**
Every poll wrote `last_online`, and every `UpdateTask`/`UpdateLog` wrote
`last_active` — while a runner streams logs that is many writes per
second per runner. These are now persisted only when stale enough to
actually affect the active/offline status (`ShouldPersistLastOnline` /
`ShouldPersistLastActive`), using the existing columns.

**2. Throttle concurrent task picks**
A new in-process semaphore (`MAX_CONCURRENT_TASK_PICKS`) bounds how many
runners run the task-assignment transaction at once, so a fleet polling
together cannot stampede the query. Throttled polls retry on their next
poll without advancing the runner's tasks version.

**3. Paginate the task-pick query**
`CreateTaskForRunner` previously loaded every waiting job in the
runner's scope into memory on each poll (no `LIMIT`). Now it pages
through the waiting backlog oldest-first with `LIMIT`, claiming the
first label-matching job.

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-07-07 16:27:00 -07:00
03372836ab fix(mirror): disable HTTP redirects on pull mirror sync (#38320) (#38367)
Backport #38320 by @bircni

Pull mirror sync ran `git fetch` / `remote update` / `remote prune`
without disabling HTTP redirects. A mirror remote that later starts
redirecting to an otherwise-blocked or internal address could be used as
an SSRF/exfiltration vector on scheduled syncs, bypassing the
allow/block validation applied at migration time.

This sets `http.followRedirects=false` on all three remote-contacting
commands in the pull mirror path, matching the existing guard already
present on the clone path.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-07 17:59:33 +00:00
1af1e06ac4 fix: minio init check (#38355) (#38361)
Backport #38355

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-07 14:41:57 +02:00
e07a5de53f fix: org project view assignee list (#38357) (#38360)
Backport #38357

fix #38129

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-07 07:07:30 +00:00
GiteabotandGitHub d4d81af583 fix(actions): release claimed task if context is cancelled during FetchTask (#38343) (#38347) 2026-07-06 07:38:47 +02:00
6cd2c647ec test: compare key file contents instead of FileInfo in TestInitKeys (#38330) (#38331)
Backport #38330 by @Zettat123

`TestInitKeys` verified whether a host key file was regenerated by
comparing `os.FileInfo` before and after a `InitDefaultHostKeys` call.
On systems where the OS clock / filesystem timestamp granularity is
coarse, both writes land in the same tick and get an identical mtime.
The resulting `FileInfo` is then byte-for-byte equal even though the key
was actually regenerated, so `assert.NotEqual` fails.

Since a regenerated key always produces different random bytes,
comparing the content can reliably detect regeneration.

Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-07-04 20:52:52 +00:00
37c8604105 fix(release): validate web attachment renames against allowed types (#38314) (#38328)
Backport #38314 by @lunny

This fixes the web release edit flow so renamed release attachments are
validated against `[repository.release] ALLOWED_TYPES`.

Previously, the API attachment edit endpoint already enforced release
attachment type restrictions, but the web release edit form passed
`attachment-edit-*` values into `release_service.UpdateRelease`, which
updated attachment names directly without validating the new filename
against `setting.Repository.Release.AllowedTypes`.

As a result, a user with repository write access could rename an
existing release attachment to a disallowed extension through the web
UI.

- validate edited release attachment names in
`release_service.UpdateRelease`
- reject forbidden attachment renames using
  `setting.Repository.Release.AllowedTypes`
- re-render the web release edit page with a validation error instead of
  returning an internal server error
- add regression coverage for both the service layer and the web flow

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-04 17:45:11 +02:00
a9814e789c fix(actions): make runner list pagination order deterministic (#38313) (#38327)
Backport #38313 by @bircni

The runner-listing API endpoints (`admin`, `org`, `user`, `repo`, and
`shared`) return runners in a non-deterministic order across pages. When
paging through runners, some runners from page 1 could reappear on page
2 (and others get skipped entirely).

The cause is in `FindRunnerOptions.ToOrders()`. Most sort modes order by
a **non-unique** column only:

- default / `online` / `offline` → `last_online`
- `alphabetically` / `reversealphabetically` → `name`

When multiple runners tie on the sort key (e.g. every offline runner
shares `last_online = 0`, or two runners have the same name), the
database is free to return the tied rows in any order between separate
queries. Combined with `LIMIT`/`OFFSET` pagination, this means the same
runner can land on more than one page.

## Fix

Append the unique primary key `id` as a stable tiebreaker to each
non-unique sort order:

The `newest`/`oldest` modes already sort by the unique `id`, so they are
left unchanged.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-03 20:59:33 +00:00
ab10e37acf fix(release): gate draft release attachments on web download endpoints (#38318) (#38325)
Backport #38318 by @bircni

Draft-release access control was enforced only on the API release
endpoints (`/api/v1/repos/{owner}/{repo}/releases/...`) but not on the
UUID-based web attachment endpoints (`/attachments/{uuid}`,
`/{owner}/{repo}/attachments/{uuid}`,
`/{owner}/{repo}/releases/attachments/{uuid}`).

Anyone who obtained an attachment UUID — including unauthenticated
callers — could download files belonging to a hidden draft release,
since `ServeAttachment` only checked repo-level read permission and
never the release's draft state.

This extends `ServeAttachment` to require write access to releases when
the attachment belongs to a draft release, mirroring the existing
API-side `canAccessReleaseDraft` gate. A regression test is included.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-03 20:34:37 +02:00
f7bc6b89c1 fix: Improve since/until when counting commits for X-Total-Count (#38243) (#38304)
Backport #38243 by @puni9869

Follow up for https://github.com/go-gitea/gitea/pull/38204.

Signed-off-by: puni9869 <80308335+puni9869@users.noreply.github.com>
Co-authored-by: puni9869 <80308335+puni9869@users.noreply.github.com>
2026-07-02 10:07:29 +00:00
fabc5e6fcb fix(actions): prevent chevron overlap with log text when timestamps are enabled (#38227) (#38307)
Backport #38227 by @SudhanshuMatrix

### Description
This PR resolves a UI alignment bug in the Gitea Actions log viewer
where the expand/collapse disclosure chevron overlaps with the log text
(specifically the timestamp) when timestamps are enabled.

### Cause
When log timestamps are enabled, the timestamp element
(`.log-time-stamp`) is rendered as the first element next to the line
number. Because it only had a default `10px` left margin, it positioned
itself exactly where the group's expand/collapse chevron is located,
causing them to overlap.

Fixes #38222.

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Shudhanshu Singh <sudhanshuwriterblc@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-07-02 11:22:26 +02:00
GiteabotandGitHub a016d678db fix(workflows): branch protection status checks fail when workflow uses on: paths filter (#38237) (#38302) 2026-07-01 20:10:11 +00:00
b6e409badd fix(oauth2): persist linkAccountData during auto-link 2FA flow (#38274) (#38295)
Backport #38274 by @afahey03

Fixes HTTP 500 when OIDC auto account linking (`ACCOUNT_LINKING=auto`)
requires local 2FA. `oauth2LinkAccount` set `linkAccount` in the session
before redirecting to 2FA but did not persist `linkAccountData`, so
`TwoFactorPost` failed with `not in LinkAccount session`. The manual
linking flow already stored both, this aligns auto-link with that
behavior.

Created the test, `TestOAuth2AutoLinkWithTwoFactor`, which verifies that
automatic account linking completes after the user passes local 2FA when
an OIDC identity matches an existing account.

DISCLAIMER: I used AI to create the test

Closes #38171

Co-authored-by: Aidan Fahey <afahey2003@yahoo.com>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-01 13:18:37 +02:00
2734504cfc fix(actions): allow Actions bot to push to protected branches (#38284) (#38293)
Backport #38284 by @bircni

Fixes #38278

## Problem

When branch protection matches the branch an Actions workflow pushes to,
the runner's `git push` is rejected — even though the workflow token has
`contents: write` and the same push performed with a PAT (write access)
succeeds. Disabling protection or changing the pattern so it no longer
matches makes the push work.

## Root cause

In `preReceiveBranch` (`routers/private/hook_pre_receive.go`), the "can
the doer push to this protected branch" check resolves the pusher with
`user_model.GetUserByID(ctx, ctx.opts.UserID)`. For an Actions push the
user ID is `-2` (the virtual `ActionsUserID`), which has no database
row, so the lookup fails. Even past that, `CanUserPush` →
`HasAccessUnit`/whitelist membership cannot evaluate a virtual user and
returns `false`. As a result the Actions bot was rejected on every
matching protected branch, despite the earlier `assertCanWriteRef`
already confirming the token's code-write via
`GetActionsUserRepoPermission`.

This was inconsistent: a PAT with identical write access passed the
exact same check.

## Fix

Evaluate the Actions bot against its already-computed token permission
instead of a user lookup, mirroring the existing
`IsUserMergeWhitelisted` pattern:

- Add `CanActionsUserPush` / `CanActionsUserForcePush` on
`ProtectedBranch`, which take the precomputed `access_model.Permission`.
- Allow the push when push is enabled, **no** push whitelist is
enforced, and the token has code-write.
- Keep the bot blocked when a whitelist is enforced — it cannot be added
to one, so it must use a pull request. This preserves the whitelist as a
real security boundary.

Force-push, signed-commit and protected-file-path checks are untouched.

Signed-off-by: bircni <bircni@icloud.com>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-07-01 11:46:17 +02:00
eee7967b81 fix(actions): include all aggregable run statuses in status filter (#38280) (#38287)
Backport #38280 by @bircni

The **Status** filter dropdown on the repository Actions run list does
not let you filter for **Blocked** runs (nor **Cancelled** or
**Skipped**). These statuses are missing from the dropdown even though a
run can legitimately end up in any of them.

A run's status is computed by `aggregateJobStatus`, which can return
`Blocked`, `Cancelled` and `Skipped`. Because the filter dropdown only
offered Success, Failure, Waiting, Running and Cancelling, runs in those
other states existed but were impossible to filter for.

Co-authored-by: bircni <bircni@icloud.com>
2026-07-01 10:12:11 +02:00
1df8f91691 fix(archiver): use serializable repo-archive queue payload (#38273) (#38283)
Backport #38273 by @Vinod-OAI

After upgrading from 1.25.x to 1.26.x, `repo-archive` workers can fail
to unmarshal queued items:

```
Failed to unmarshal item from queue "repo-archive":
json: unable to unmarshal into Go convert.Conversion within "/Repo/Units/0/Config":
cannot derive concrete type for nil interface with finite type set
```

`ArchiveRequest` started embedding `*repo_model.Repository` in 1.26,
which does not round-trip through the JSON queue.

This change stores a minimal `archiveQueueItem` (`RepoID`, `Type`,
`CommitID`, `Paths`) in `repo-archive` and loads the repository in the
worker. `UnmarshalJSON` accepts legacy payloads that used `RepoID` or
embedded `Repo.id`.

Fixes #38272

<!--
Before submitting:
- Target the `main` branch; release branches are for backports only.
- Use a Conventional Commits title, e.g. `fix(repo): handle empty branch
names`.
- Read the contributing guidelines:
https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
- Documentation changes go to https://gitea.com/gitea/docs

Describe your change below and link any issue it fixes.
-->

Co-authored-by: Vinod-OAI <venkat.vinod@observe.ai>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-30 19:17:29 +02:00
4654e7eccd docs: Changelog for 1.27.0-rc0 (#38247)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-06-29 21:06:07 +02:00
243 changed files with 3327 additions and 3630 deletions
+4 -4
View File
@@ -9,10 +9,10 @@ inputs:
runs:
using: composite
steps:
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Build regular image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: ${{ inputs.platform }}
@@ -20,7 +20,7 @@ runs:
file: Dockerfile
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful
- name: Build rootless image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: ${{ inputs.platform }}
+6 -6
View File
@@ -16,34 +16,34 @@ runs:
using: composite
steps:
- if: ${{ github.workflow == 'cache-seeder' }}
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/go/pkg/mod
key: gomod-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
- if: ${{ github.workflow != 'cache-seeder' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/go/pkg/mod
key: gomod-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gomod-${{ runner.os }}-${{ runner.arch }}
- if: ${{ github.workflow == 'cache-seeder' && inputs.lint-cache != 'true' }}
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/go-build
key: gobuild-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
- if: ${{ github.workflow != 'cache-seeder' || inputs.lint-cache == 'true' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/go-build
key: gobuild-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum') }}
restore-keys: gobuild-${{ runner.os }}-${{ runner.arch }}
- if: ${{ inputs.lint-cache == 'true' && github.workflow == 'cache-seeder' }}
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/golangci-lint
key: golint-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum', '.golangci.yml') }}
- if: ${{ inputs.lint-cache == 'true' && github.workflow != 'cache-seeder' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.cache/golangci-lint
key: golint-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('go.sum', '.golangci.yml') }}
+2 -2
View File
@@ -13,10 +13,10 @@ runs:
- if: ${{ inputs.cache == 'true' }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 26
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- if: ${{ inputs.cache != 'true' }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 26
node-version: 24
+2 -2
View File
@@ -21,12 +21,12 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
- uses: renovatebot/github-action@b50d2ba2bd928235abdcc14d06dfafc217f1c565 # v46.1.18
- uses: renovatebot/github-action@6d859fc95779be83a0335ca704879b47e5d79641 # v46.1.16
with:
renovate-version: ${{ env.RENOVATE_VERSION }}
configurationFile: renovate.json5
token: ${{ secrets.RENOVATE_TOKEN }}
env:
RENOVATE_BINARY_SOURCE: install # auto-install go/node toolchains needed by post-upgrade tasks.
RENOVATE_ALLOWED_POST_UPGRADE_COMMANDS: '["^make (tidy|svg|generate-codemirror-languages)$"]'
RENOVATE_ALLOWED_POST_UPGRADE_COMMANDS: '["^make (tidy|svg)$"]'
RENOVATE_REPOSITORIES: '["go-gitea/gitea"]'
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
shell: ${{ steps.changes.outputs.shell }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: changes
with:
filters: |
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
- run: make lint-spell
- if: needs.files-changed.outputs.templates == 'true' || needs.files-changed.outputs.yaml == 'true' || needs.files-changed.outputs.actions == 'true'
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
python-version: 3.14
- if: needs.files-changed.outputs.templates == 'true' || needs.files-changed.outputs.yaml == 'true'
+1 -1
View File
@@ -131,7 +131,7 @@ jobs:
ports:
- "7700:7700"
redis:
image: redis:latest@sha256:5d2c689b4b55fc3fab4b0cc8aaa950f85b508c76c1e0f35a90d8f411d55a8b2b
image: redis:latest@sha256:c904002d182255b6db3cbe3a1e8ce6c187d15390c39500b59fc07181aabff7bf
options: >- # wait until redis has started
--health-cmd "redis-cli ping"
--health-interval 5s
+2 -2
View File
@@ -17,7 +17,7 @@ jobs:
contents: read
pull-requests: write
steps:
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
with:
sync-labels: true
@@ -35,7 +35,7 @@ jobs:
ref: ${{ github.event.pull_request.base.sha }}
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 26
node-version: 24
# Labels are only synced after the title lints, so an invalid title never reaches the label diff.
- run: node ./tools/ci-tools.ts lint-pr-title
env:
+29 -19
View File
@@ -6,30 +6,40 @@ on:
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
build-and-publish:
strategy:
fail-fast: false
matrix:
runner: [ubuntu-24.04, ubuntu-24.04-arm]
runs-on: ${{ matrix.runner }}
runs-on: ubuntu-latest
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
fetch-depth: 0
- uses: snapcore/action-build@3bdaa03e1ba6bf59a65f84a751d943d549a54e79 # v1.3.0
id: build
- uses: snapcore/action-publish@214b86e5ca036ead1668c79afb81e550e6c54d40 # v1.2.0
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
with:
snap: ${{ steps.build.outputs.snap }}
release: latest/edge
- name: Install snapcraft
run: sudo snap install snapcraft --classic
- name: Authenticate snapcraft
shell: bash
run: snapcraft login --with <(printf '%s' "$SNAPCRAFT_STORE_CREDENTIALS")
- name: Remote build
run: |
snapcraft remote-build \
--launchpad-accept-public-upload \
--build-for=amd64,arm64,armhf
- name: List built snaps
run: find . -maxdepth 1 -type f -name '*.snap' -print
- name: Upload and release snapcraft nightly build
run: |
set -euo pipefail
for snap in ./*.snap; do
echo "Uploading $snap to edge"
snapcraft upload --release="latest/edge" "$snap"
done
+15 -10
View File
@@ -23,7 +23,12 @@ jobs:
with:
go-version-file: go.mod
check-latest: true
- uses: ./.github/actions/node-setup
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- run: make deps-frontend deps-backend
# xgo build
- run: make release
@@ -56,7 +61,7 @@ jobs:
echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
@@ -78,8 +83,8 @@ jobs:
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Get cleaned branch name
id: clean_name
env:
@@ -87,7 +92,7 @@ jobs:
run: |
REF_NAME=$(echo "$REF" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta
with:
images: |-
@@ -97,7 +102,7 @@ jobs:
type=raw,value=${{ steps.clean_name.outputs.branch }}
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta_rootless
with:
images: |-
@@ -111,18 +116,18 @@ jobs:
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- name: Login to Docker Hub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR using PAT
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build regular docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
@@ -132,7 +137,7 @@ jobs:
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful
cache-to: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful,mode=max
- name: build rootless docker image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
+15 -10
View File
@@ -24,7 +24,12 @@ jobs:
with:
go-version-file: go.mod
check-latest: true
- uses: ./.github/actions/node-setup
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- run: make deps-frontend deps-backend
# xgo build
- run: make release
@@ -57,7 +62,7 @@ jobs:
echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
@@ -89,9 +94,9 @@ jobs:
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta
with:
images: |-
@@ -104,7 +109,7 @@ jobs:
type=semver,pattern={{version}}
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta_rootless
with:
images: |-
@@ -120,18 +125,18 @@ jobs:
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- name: Login to Docker Hub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR using PAT
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build regular container image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
@@ -139,7 +144,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
annotations: ${{ steps.meta.outputs.annotations }}
- name: build rootless container image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
+15 -10
View File
@@ -27,7 +27,12 @@ jobs:
with:
go-version-file: go.mod
check-latest: true
- uses: ./.github/actions/node-setup
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- run: make deps-frontend deps-backend
# xgo build
- run: make release
@@ -60,7 +65,7 @@ jobs:
echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
@@ -92,9 +97,9 @@ jobs:
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta
with:
images: |-
@@ -111,7 +116,7 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta_rootless
with:
images: |-
@@ -132,18 +137,18 @@ jobs:
annotations: |
org.opencontainers.image.authors="maintainers@gitea.io"
- name: Login to Docker Hub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR using PAT
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build regular container image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
@@ -151,7 +156,7 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
annotations: ${{ steps.meta.outputs.annotations }}
- name: build rootless container image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64,linux/riscv64
+303
View File
@@ -4,6 +4,309 @@ This changelog goes through the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.com).
## [1.27.0](https://github.com/go-gitea/gitea/releases/tag/v1.27.0) - 2026-07-13
* BREAKING
* Feat(actions)!: improve support for reusable workflows (#37478)
* Use Content-Security-Policy: script nonce (#37232)
* SECURITY
* Fix: various security fixes (#38406) (#38426)
* Fix(security): harden access checks and migration validation (#38324) (#38400)
* Fix: enforce public-only token scope and harden push options / locale parsing (#38323) (#38399)
* Fix(pull): re-evaluate review official flag on target branch change (#38319) (#38402)
* Fix(api): stop leaking private repo metadata after access revocation (#38321) (#38390)
* Fix(lfs): require proof of possession for cross-repo objects (#38322) (#38389)
* Fix(mirror): disable HTTP redirects on pull mirror sync (#38320) (#38367)
* Fix: golang html template url escaping (#38363) (#38369)
* Fix(release): validate web attachment renames against allowed types (#38314) (#38328)
* Fix(release): gate draft release attachments on web download endpoints (#38318) (#38325)
* Fix(deps): update module github.com/go-git/go-git/v5 to v5.19.1 [security] (#37786)
* Fix(oauth): restrict introspection to the token's client (#38042)
* Fix(api): don't expose private org membership via public_members (#38145)
* Fix(actions): deny fork-PR cross-repo access via collaborative owner (#38214)
* Fix(migrations): prevent path traversal in repository restore (#38215)
* FEATURES
* Feat(actions): add workflow status badge modal (#38196)
* Feat(actions): support owner-level and global scoped workflows (#38154)
* Feat(api): support ref suffixes in compare (#38148)
* Feat(actions): implement `jobs.<job_id>.continue-on-error` (#38100)
* Feat(actions): show run status on browser tab favicon (#38071)
* Feat(api): add token introspection and self-deletion endpoint (#37995)
* Feat(api): add q parameter to list branches API for server-side filtering (#37982)
* Feat(repo): split repository creation limit into user and org scopes (#37872)
* Feat(actions): bulk delete, disable and enable runners in admin UI (#37869)
* Feat(actions): List workflows that were executed once but got removed from the default branch (#37835)
* Feat(org): add team visibility so org members can discover teams (#37680)
* Feat: add raw diff/patch endpoint for repository comparisons (#37632)
* Feat: Add avatar stacks (#37594)
* Feat(actions): add job summaries (GITHUB_STEP_SUMMARY) (#37500)
* Feat(web): Add Jupyter Notebook (.ipynb) Rendering Support (#37433)
* Support for Custom URI Schemes in OAuth2 Redirect URIs (#37356)
* Feat(orgs): Add search bar for organization members tab page (#37347)
* Feat(api): Add assignees APIs (#37330)
* Feat(api): Add GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs (#37196)
* Serve OpenAPI 3.0 spec at /openapi.v1.json (#37038)
* Add project column picker to issue and pull request sidebar (#37037)
* Allow multiple projects per issue and pull requests (#36784)
* Feat(ui): add "follow rename" to file commit history list (#34994)
* Feat(ssh): auto generate additional ssh keys (#33974)
* ENHANCEMENTS
* Enhance(actions): only create filtered-out workflow commit status for required contexts (#38371) (#38385)
* Enhance: allow builtin default git config options to be overridden (#38172)
* Enhance: allow MathML core elements (#38034)
* Enhance(markup): improve issue title rendering (#37908)
* Enhance(actions): set descriptive browser tab title on run view (#37870)
* Enhance: Migrate remaining gopkg.in/yaml.v3 usages to go.yaml.in/yaml/v4 (#37866)
* Enhance(actions): show workflow name from YAML instead of filename (#37833)
* Feat(actions): add before/after to PR synchronize event payload (#37827)
* Enhance(actions): add branch filters to run list (#37826)
* Enhance(actions): Make Summary UI more beautiful with more infos (#37824)
* Feat: add copy button to action step header, improve other copy buttons (#37744)
* Fix(icon): use repo-forked icon to display forks count (#37731)
* Feat(api): add sort and order query parameters to job list endpoints (#37672)
* Feat(api): add last_sync to repository API (#37566)
* Enhance: Adjust Workflow Graph styling (#37497)
* Improve code editor text selection and clean up lint enablement (#37474)
* Add mirror auth updates to repo edit API and settings (#37468)
* Replace `olivere/elastic` with REST API client, add OpenSearch support (#37411)
* Feat: Add default PR branch update style setting (#37410)
* Fix inconsistent disabled styling on logged-out repo header buttons (#37406)
* Allow fast-forward-only merge when signed commits are required (#37335)
* Enhance styling in actions page (#37323)
* Fix: improve actions status icons and texts (#37206)
* Make Markdown fenced code block work with more syntaxes (#37154)
* Fix: Sort action run jobs by JobID and Name with matrix examples (#37046)
* Add API endpoint to reply to pull request review comments (#36683)
* PERFORMANCE
* Perf(actions): debounce runner heartbeat writes and throttle task picks (#38281) (#38368)
* Perf(web): sort the action_run query by a repo-scoped index when possible (#38155)
* Perf: Various performance regression fixes (#38078)
* Perf: extend action `c_u` index to include `created_unix` for faster dashboard feeds (#38076)
* Batch-load related data in actions run, job, and task API endpoints (#37032)
* BUGFIXES
* Fix(util): reject invalid characters between time-estimate units (#38416) (#38423)
* Fix: represent a deleted assignee team as a Ghost team (#38413) (#38419)
* Fix(turnstile): route CAPTCHA verification through the configured proxy (#38412) (#38420)
* Fix: refresh pull request merge box when the commit status is pending (#38410) (#38411)
* Fix: actions task state concurrent update (#38405) (#38409)
* Fix(actions): keep workflow run trailing on one row with long branch names (#38382) (#38403)
* Fix(web): use locale-aware date formatting for contribution calendar tooltips (#38398) (#38401)
* Fix: co-author detection (#38392) (#38397)
* Fix: incorrect co-author detection on commit page (#38386) (#38387)
* Fix(ui): restore commits table column widths (#38379) (#38383)
* Fix: minio init check (#38355) (#38361)
* Fix: org project view assignee list (#38357) (#38360)
* Fix(actions): release claimed task if context is cancelled during `FetchTask` (#38343) (#38347)
* Fix(actions): make runner list pagination order deterministic (#38313) (#38327)
* Fix: Improve since/until when counting commits for X-Total-Count (#38243) (#38304)
* Fix(actions): prevent chevron overlap with log text when timestamps are enabled (#38227) (#38307)
* Fix(workflows): branch protection status checks fail when workflow uses on: paths filter (#38237) (#38302)
* Fix(oauth2): persist linkAccountData during auto-link 2FA flow (#38274) (#38295)
* Fix(actions): allow Actions bot to push to protected branches (#38284) (#38293)
* Fix(actions): include all aggregable run statuses in status filter (#38280) (#38287)
* Fix(archiver): use serializable repo-archive queue payload (#38273) (#38283)
* Fix: update npm dependencies, fix misc issues (#38257)
* Fix(api): respect since/until when counting commits for X-Total-Count (#38204)
* Fix: codemirror regressions (#38248)
* Fix(api): support HEAD requests on all API GET endpoints (#38245)
* Fix(actions): Cleanup workflow status badge code (#38241)
* Fix(web): Correctly align the "disabled" label on larger workflow names (#38240)
* Fix(actions): don't swallow HTML entities into linkified URLs (#38239)
* Fix(packages): accept npm "repository" and "bin" in string form (#38236)
* Fix(actions): fix 500 error when canceling a canceling task (#38223)
* Fix(deps): update module golang.org/x/image to v0.43.0 [security] (#38219)
* Fix(mssql): convert legacy DATETIME columns to DATETIME2 (#38216)
* Fix(api): deny private org member enumeration via /members (#38213)
* Fix(actions): ensure all waiting jobs get runners in large workflows (#38200)
* Fix(deps): update go dependencies (#38194)
* Fix(deps): update npm dependencies (#38193)
* Fix(cli): default must-change-password to false for bot users (#38175)
* Fix(actions): show run index in run view and fix summary graph height (#38165)
* Fix: csp (#38162)
* Fix(deps): update npm dependencies (#38123)
* Fix(mssql): expand legacy issue and comment long-text columns (#38120)
* Fix(packages): validate debian distribution and component names (#38116)
* Fix(packages): validate module version in goproxy ParsePackage (#38104)
* Fix(deps): update dependency esbuild to v0.28.1 [security] (#38097)
* Fix: git push hook post receive (#38089)
* Fix(ui): prevent commit status popup overflowing its row (#38081)
* Fix: validate gem name in rubygems parseMetadataFile (#38061)
* Fix: commit display name (#38057)
* Fix: csp regressions (#38047)
* Fix: api error message (#38031)
* Fix(deps): update npm dependencies (#38029)
* Fix: pgsql lint (#38022)
* Fix(indexer): fix assignee filters in issue search (#38021)
* Fix: various dropdown problems (#38020)
* Fix: refactor git error handling and make archive streaming handle non-existing commit id (#38007)
* Fix: raise git required version to 2.13 (#37996)
* Fix: remove "no-transfrom" from the cache-control header (#37985)
* Fix(deps): update module github.com/google/go-github/v87 to v88 (#37971)
* Fix: use committer time where ever possible as default (#37969)
* Fix(deps): update npm dependencies, remove nolyfill (#37968)
* Fix(deps): update go dependencies (#37967)
* Fix(pull): preserve squash message trailers and additional commit messages (#37954)
* Fix(deps): update module golang.org/x/image to v0.41.0 [security] (#37904)
* Fix: support ##[command] log prefix in action run UI (#37882)
* Fix(deps): update module github.com/google/go-github/v86 to v87 (#37845)
* Fix(deps): update npm dependencies (#37844)
* Fix(deps): update go dependencies (#37841)
* Fix(frontend): resolve Vite assets by manifest source path (#37836)
* Fix(locales): Replace hardcoded strings (#37788)
* Fix(packages): render markdown links relative to linked repo (#37676)
* Fix: persist mirror repository metadata (#37519)
* Fix cmd tests by mocking builtin paths (#37369)
* Add `form-fetch-action` to some forms, fix "fetch action" resp bug (#37305)
* Feat: execute post run cleanup when workflow is cancelled (#37275)
* Fix `relative-time` error and improve global error handler (#37241)
* Refactor flash message and remove SanitizeHTML template func (#37179)
* TESTING
* Test(e2e): fix race in pdf file render test (#38380) (#38381)
* Test: compare key file contents instead of `FileInfo` in `TestInitKeys` (#38330) (#38331)
* Test: speed up two tests (#37905)
* Test: Fix random failure test (#37887)
* Test: fix flaky `issue-comment` close test (#37880)
* Test: enable WAL for sqlite integration tests (#37861)
* Test: fix flaky `TestResourceIndex` and reduce its runtime (#37847)
* Test: run `TestAPIRepoMigrate` offline via a local clone source (#37817)
* Ci: shard tests and reduce redundant work (#37618)
* Test(e2e): run playwright via container (#37300)
* Remove external service dependencies in migration tests (#36866)
* BUILD
* Fix(actions): authenticate snapcraft before nightly remote build (#38252)
* Ci: cap Elasticsearch heap in db-tests (#37816)
* Build(snap): publish nightly version to snapcraft via actions (#37814)
* Ci: split pgsql shards into plain jobs, dedupe setup actions (#37802)
* Ci: narrow files-changed frontend filter (#37749)
* Ci: add `zizmor` to `lint-actions` (#37720)
* Chore: clean up "contrib" dir (#37690)
* Fix: snap build (main branch) (#37685)
* Ci: Also lint json5 files (#37659)
* Feat(editor): broaden language detection in web code editor (#37619)
* Build: update pnpm to v11 (#37591)
* Refactor(deps): migrate from `nektos/act` fork to `gitea/runner` (#37557)
* Refactor: lint bare `fill`/`stroke` colors, add vars for git graph color series (#37543)
* Update go js py dependencies (#37525)
* Ci: lint PR titles with commitlint (#37498)
* Chore: upgrade Go version in devcontainer image to 1.26 (#37374)
* Update GitHub Actions to latest major versions (#37313)
* Update go js dependencies (#37312)
* Fail vite build on rolldown warnings via NODE_ENV=test (#37270)
* Remove htmx (#37224)
* Replace custom Go formatter with `golangci-lint fmt` (#37194)
* Refactor htmx and fetch-action related code (#37186)
* Integrate renovate bot for all dependency updates (#37050)
* Build(sign): move to sigstore (#38250)
* DOCS
* Docs: update changelog for 1.26.3 & 1.26.4 (#38178)
* Docs: fix duplicated word in foreachref doc comment (#38161)
* Docs: Clarify criteria for becoming a merger (#38113)
* Docs: Publish TOC Election Result 2026 (#38111)
* Docs: mark openapi3 as autogenerated in attributes (#37963)
* Docs: add development setup guide (#37960)
* MISC
* Revert(sign): restore gpg (#38251)
* Refactor: replace legacy `delete-button` with `link-action` (#38143)
* Refactor(actions): read runner capabilities from proto field (#38068)
* Refactor(api): clarify APIError message usage and fix legacy lint error (#38012)
* Refactor: Use db.Get[] instead of db.GetEngine(ctx).Get(bean) to avoid zero value fetching wrong database record (#37977)
* Fix(deps): update go dependencies (#37851)
* Ci: Fix sync PR labels from the conventional-commit title (#37784) (#37825)
* Ci: tweak `files-changed`, add `free-disk-space` (#37819)
* Fix(deps): update module golang.org/x/crypto to v0.52.0 [security] (#37806)
* Test(e2e): add comment, release, star, PR and fork tests (#37800)
* Chore: simplify issue and pull request templates (#37799)
* Chore: Update giteabot to fix failure when backport (#37789)
* Fix(api): handle partial failures in push mirror synchronization gracefully (#37782)
* Fix(deps): update module gitlab.com/gitlab-org/api/client-go/v2 to v2.26.0 (#37771)
* Ci: split giteabot workflow (#37770)
* Fix(deps): update npm dependencies (#37768)
* Refactor(waitgroup): replace Add/Done goroutines with WaitGroup.Go (#37764)
* Fix(deps): update module google.golang.org/grpc to v1.81.1 (#37762)
* Ci: fix cache-related issues (#37761)
* Chore: fix tests (#37760)
* Fix(deps): update module github.com/google/go-github/v85 to v86 (#37754)
* Fix(deps): update npm dependencies (#37753)
* Fix(deps): update go dependencies (#37752)
* Chore(deps): update action dependencies (#37751)
* Fix(markup): wrap indented code blocks for the code-copy button (#37748)
* Chore(db): introduce db.Session and db.EngineMigration interfaces (#37746)
* Feat(web): also display PR counts in repo list (#37739)
* Refactor(glob): use strings.Builder for regexp compilation (#37730)
* Chore(doctor): remove four obsolete doctor check implementations (#37728)
* Refactor(org): simplify owner-team org repo creation logic (#37727)
* Refactor: move `workflowpattern` into `modules/actions` (#37717)
* Chore: clean up tests (#37715)
* Style: misc UI fixes (#37691)
* Ci: add shellcheck linter (#37682)
* Fix: catch and fix more lint problems (#37674)
* Fix(deps): update dependency mermaid to v11.15.0 [security], add e2e test (#37662)
* Fix(deps): update npm dependencies (#37647)
* Ci(renovate): update Go import paths on major bumps (#37641)
* Fix(deps): update go dependencies (major) (#37639)
* Chore(deps): update action dependencies (major) (#37638)
* Fix(deps): update module code.gitea.io/sdk/gitea to v0.25.0 (#37637)
* Fix(deps): update npm dependencies (#37636)
* Refactor(log): replace log.Critical with log.Error (#37624)
* Build(deps): bump fast-uri from 3.1.0 to 3.1.2 (#37616)
* Feat(oauth): Support AWS Cognito OAuth2 provider (#37607)
* Chore(deps): update action dependencies (#37603)
* Ci: allow `chore` type in PR title lint (#37575)
* Refactor: only reset a database table when the table's data was changed (#37573)
* Ci: increase renovate frequency and fix RENOVATE_ALLOWED_POST_UPGRADE_COMMANDS (#37565)
* Refactor: use modernc sqlite driver as default (#37562)
* Docs: fix 4 typos in CHANGELOG.md (#37549)
* Fix(deps): update go dependencies (#37541)
* Chore(deps): update action dependencies (#37540)
* Refactor pull request view (6) (#37522)
* Fix: redirect early CLI console logger to stderr (#37507)
* Refactor "flex-list" to "flex-divided-list" (#37505)
* Refactor compare diff/pull page (1) (#37481)
* Refactor pull request view (4) (#37451)
* Update 1.26.1 changelog in main (#37442)
* Refactor: use named `Permission` field in `Repository` struct instead of anonymous embedding (#37441)
* Refactor: serve site manifest via `/assets/site-manifest.json` endpoint (#37405)
* Remove IsValidExternalURL/IsAPIURL and use IsValidURL at call sites (#37364)
* Update `Block a user` form (#37359)
* Move review request functions to a standalone file (#37358)
* Feat(security): set X-Content-Type-Options: nosniff by default (#37354)
* Enable strict TypeScript, add `errorMessage` helper (#37292)
* Refactor frontend `tw-justify-between` layouts to `flex-left-right` (#37291)
* Update Nix flake (#37284)
* Fix Repository transferring page (#37277)
* Remove `SubmitEvent` polyfill (#37276)
* Remove dead code identified by `deadcode` tool (#37271)
* Upgrade go-git to v5.18.0 (#37268)
* Don't add useless labels which will bother changelog generation (#37267)
* Move heatmap to first-party code (#37262)
* Tests/integration: simplify code (#37249)
* Add pagination and search box to org teams list (#37245)
* Remove error returns from crypto random helpers and callers (#37240)
* Add `ExternalIDClaim` option for OAuth2 OIDC auth source (#37229)
* Refactor: simplify ParseCatFileTreeLine and catBatchParseTreeEntries (#37210)
* Refactor "htmx" to "fetch action" (#37208)
* Update go js py dependencies (#37204)
* Add comment for the design of "user activity time" (#37195)
* Remove outdated RunUser logic (#37180)
* Models/fixtures: add "DO NOT add more test data" comment to all yml fixture files (#37150)
* Update javascript dependencies (#37142)
* Update go dependencies (#37141)
* Frontport changelog of v1.26.0-rc0 (#37138)
* Introduce `ActionRunAttempt` to represent each execution of a run (#37119)
* Workflow Artifact Info Hover (#37100)
* Extend issue context popup beyond markdown content (#36908)
* Add bulk repository deletion for organizations (#36763)
* Feat: Add bypass allowlist for branch protection (#36514)
## [1.26.4](https://github.com/go-gitea/gitea/releases/tag/1.26.4) - 2026-06-21
* SECURITY
+1
View File
@@ -41,6 +41,7 @@ Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
Leon Hofmeister <dev.lh@web.de> (@delvh)
Wim <wim@42.be> (@42wim)
Jason Song <i@wolfogre.com> (@wolfogre)
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
Yu Tian <zettat123@gmail.com> (@Zettat123)
Dong Ge <gedong_1994@163.com> (@sillyguodong)
Xinyi Gong <hestergong@gmail.com> (@HesterG)
+7 -11
View File
@@ -12,13 +12,13 @@ COMMA := ,
XGO_VERSION := go-1.26.x
AIR_PACKAGE ?= github.com/air-verse/air@v1.65.3 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.8.0 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.7.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 # renovate: datasource=go
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15 # renovate: datasource=go
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.8.0 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.35.0 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.34.1 # renovate: datasource=go
XGO_PACKAGE ?= src.techknowlogick.com/xgo@v1.9.0 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.5.0 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.4.0 # renovate: datasource=go
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.7.12 # renovate: datasource=go
SHELLCHECK_IMAGE ?= docker.io/koalaman/shellcheck:v0.11.0@sha256:61862eba1fcf09a484ebcc6feea46f1782532571a34ed51fedf90dd25f925a8d # renovate: datasource=docker
@@ -231,9 +231,7 @@ endif
generate-swagger: $(SWAGGER_SPEC) $(OPENAPI3_SPEC) ## generate the swagger spec from code comments
$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT)
@output="$$($(GO) run $(SWAGGER_PACKAGE) generate spec --enable-allof-compounding --skip-enum-desc --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)' 2>&1)" || { printf '%s\n' "$$output" >&2; exit 1; }; \
warnings="$$(printf '%s\n' "$$output" | grep -v '^go: ')"; \
if [ -n "$$warnings" ]; then printf '%s\n' "$$warnings" >&2; exit 1; fi
$(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)'
.PHONY: swagger-check
swagger-check: generate-swagger
@@ -248,11 +246,9 @@ swagger-check: generate-swagger
swagger-validate: ## check if the swagger spec is valid
@# swagger "validate" requires that the "basePath" must start with a slash, but we are using Golang template "{{...}}"
@$(SED_INPLACE) -E -e 's|"basePath":( *)"(.*)"|"basePath":\1"/\2"|g' './$(SWAGGER_SPEC)' # add a prefix slash to basePath
@output="$$($(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)' 2>&1)"; status=$$?; \
$(SED_INPLACE) -E -e 's|"basePath":( *)"/(.*)"|"basePath":\1"\2"|g' './$(SWAGGER_SPEC)'; \
printf '%s\n' "$$output" | grep -v '^go: '; \
[ $$status -eq 0 ] || exit $$status; \
case "$$output" in *WARNING:*) exit 1;; esac
@# FIXME: there are some warnings
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
@$(SED_INPLACE) -E -e 's|"basePath":( *)"/(.*)"|"basePath":\1"\2"|g' './$(SWAGGER_SPEC)' # remove the prefix slash from basePath
.PHONY: generate-openapi3
generate-openapi3: $(OPENAPI3_SPEC) ## generate the OpenAPI 3.0 spec from the Swagger 2.0 spec
-8
View File
@@ -436,7 +436,6 @@
"jsonl",
"mcmeta",
"sarif",
"slnlaunch",
"tact",
"tfstate",
"topojson",
@@ -692,17 +691,10 @@
"extensions": [
"ini",
"cnf",
"container",
"dof",
"lektorproject",
"mount",
"network",
"prefs",
"properties",
"service",
"socket",
"target",
"timer",
"url",
"conf"
],
+12 -2
View File
File diff suppressed because one or more lines are too long
-1
View File
@@ -18,7 +18,6 @@ func newUserCommand() *cli.Command {
microcmdUserDelete(),
newUserGenerateAccessTokenCommand(),
microcmdUserMustChangePassword(),
microcmdUserDisableTwoFactor(),
},
}
}
-72
View File
@@ -1,72 +0,0 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"errors"
"fmt"
"strings"
auth_model "gitea.dev/models/auth"
user_model "gitea.dev/models/user"
"gitea.dev/modules/setting"
"github.com/urfave/cli/v3"
)
func microcmdUserDisableTwoFactor() *cli.Command {
return &cli.Command{
Name: "disable-2fa",
Usage: "Disable two-factor authentication for a user",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "username",
Aliases: []string{"u"},
Usage: "Username of the user to disable 2FA for",
},
&cli.Int64Flag{
Name: "id",
Usage: "ID of the user to disable 2FA for",
},
},
Action: runDisableTwoFactor,
}
}
func runDisableTwoFactor(ctx context.Context, c *cli.Command) error {
if !c.IsSet("id") && !c.IsSet("username") {
return errors.New("either --id or --username must be provided")
}
if !setting.IsInTesting {
if err := initDB(ctx); err != nil {
return err
}
}
var user *user_model.User
var err error
if c.IsSet("id") {
user, err = user_model.GetUserByID(ctx, c.Int64("id"))
} else {
user, err = user_model.GetUserByName(ctx, c.String("username"))
}
if err != nil {
return err
}
// When both selectors are given, make sure they refer to the same user.
if c.IsSet("id") && c.IsSet("username") && user.LowerName != strings.ToLower(strings.TrimSpace(c.String("username"))) {
return fmt.Errorf("the user with id %d is %q, which does not match the provided username %q", user.ID, user.Name, c.String("username"))
}
totp, webAuthn, err := auth_model.DisableTwoFactor(ctx, user.ID)
if err != nil {
return err
}
fmt.Printf("Disabled 2FA for user %q (removed %d TOTP and %d WebAuthn credential(s))\n", user.Name, totp, webAuthn)
return nil
}
-119
View File
@@ -1,119 +0,0 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"io"
"strconv"
"testing"
auth_model "gitea.dev/models/auth"
"gitea.dev/models/db"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDisableTwoFactorCommand(t *testing.T) {
ctx := t.Context()
defer func() {
require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{}, &auth_model.TwoFactor{}, &auth_model.WebAuthnCredential{}))
}()
t.Run("disable TOTP and WebAuthn", func(t *testing.T) {
require.NoError(t, microcmdUserCreate().Run(ctx, []string{"create", "--username", "tfuser", "--email", "tfuser@gitea.local", "--random-password"}))
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "tfuser"})
// Enroll TOTP.
tf := &auth_model.TwoFactor{UID: user.ID}
require.NoError(t, tf.SetSecret("test-secret"))
_, err := tf.GenerateScratchToken()
require.NoError(t, err)
require.NoError(t, auth_model.NewTwoFactor(ctx, tf))
// Register a WebAuthn credential.
_, err = auth_model.CreateCredential(ctx, user.ID, "test-key", &webauthn.Credential{ID: []byte("test-cred-id")})
require.NoError(t, err)
has, err := auth_model.HasTwoFactorOrWebAuthn(ctx, user.ID)
require.NoError(t, err)
require.True(t, has)
require.NoError(t, microcmdUserDisableTwoFactor().Run(ctx, []string{"disable-2fa", "--username", "tfuser"}))
// Both factors must be gone afterwards.
has, err = auth_model.HasTwoFactorOrWebAuthn(ctx, user.ID)
require.NoError(t, err)
assert.False(t, has)
})
t.Run("disable by id", func(t *testing.T) {
require.NoError(t, microcmdUserCreate().Run(ctx, []string{"create", "--username", "iduser", "--email", "iduser@gitea.local", "--random-password"}))
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "iduser"})
tf := &auth_model.TwoFactor{UID: user.ID}
require.NoError(t, tf.SetSecret("test-secret"))
require.NoError(t, auth_model.NewTwoFactor(ctx, tf))
require.NoError(t, microcmdUserDisableTwoFactor().Run(ctx, []string{"disable-2fa", "--id", strconv.FormatInt(user.ID, 10)}))
has, err := auth_model.HasTwoFactorOrWebAuthn(ctx, user.ID)
require.NoError(t, err)
assert.False(t, has)
})
t.Run("no enrollment is a no-op", func(t *testing.T) {
require.NoError(t, microcmdUserCreate().Run(ctx, []string{"create", "--username", "plainuser", "--email", "plainuser@gitea.local", "--random-password"}))
require.NoError(t, microcmdUserDisableTwoFactor().Run(ctx, []string{"disable-2fa", "--username", "plainuser"}))
})
t.Run("id and username must match when both given", func(t *testing.T) {
require.NoError(t, microcmdUserCreate().Run(ctx, []string{"create", "--username", "matchuser", "--email", "matchuser@gitea.local", "--random-password"}))
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "matchuser"})
id := strconv.FormatInt(user.ID, 10)
// Matching id + username is accepted.
require.NoError(t, microcmdUserDisableTwoFactor().Run(ctx, []string{"disable-2fa", "--id", id, "--username", "matchuser"}))
// Mismatched id + username is rejected.
cmd := microcmdUserDisableTwoFactor()
cmd.Writer, cmd.ErrWriter = io.Discard, io.Discard
err := cmd.Run(ctx, []string{"disable-2fa", "--id", id, "--username", "someotheruser"})
require.Error(t, err)
require.Contains(t, err.Error(), "does not match the provided username")
})
t.Run("failure cases", func(t *testing.T) {
testCases := []struct {
name string
args []string
expectedErr string
}{
{
name: "user does not exist",
args: []string{"disable-2fa", "--username", "nonexistentuser"},
expectedErr: "user does not exist",
},
{
name: "neither id nor username",
args: []string{"disable-2fa"},
expectedErr: "either --id or --username must be provided",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cmd := microcmdUserDisableTwoFactor()
cmd.Writer, cmd.ErrWriter = io.Discard, io.Discard
err := cmd.Run(ctx, tc.args)
require.Error(t, err)
require.Contains(t, err.Error(), tc.expectedErr)
})
}
})
}
-1
View File
@@ -1198,7 +1198,6 @@ LEVEL = Info
;; Default source for the pull request title when opening a new PR.
;; "first-commit" uses the oldest commit's summary.
;; "auto" uses commit's summary if the PR only has one commit, normalizes the branch name if multiple commits.
;; "branch-name" always uses the PR's branch name.
;DEFAULT_TITLE_SOURCE = auto
;;
;; Delay mergeable check until page view or API access, for pull requests that have not been updated in the specified days when their base branches get updated.
+6 -20
View File
@@ -95,15 +95,8 @@ However, if there are no objections from maintainers, the PR can be merged with
### Commit messages
Mergers are required to rewrite the PR title and the first comment (the summary) when necessary so the squash commit message is clear.
Usually the Pull Request description and commit message body should not be empty, unless the title is already clear enough or the description would be a copy of the comments in code.
The final commit message:
- should match the code changes.
- should only keep true co-authors, false-positive co-authors should be removed.
- should not hedge: replace phrases like `hopefully, <x> won't happen anymore` with definite wording.
- should not contain hidden information like `<!-- -->` or extra information after the description's divider `----`.
- should not contain unrelated contents (e.g.: Release Notes, Configuration, etc.) from a Renovate update PR.
The final commit message should not hedge: replace phrases like `hopefully, <x> won't happen anymore` with definite wording.
#### PR Co-authors
@@ -165,16 +158,9 @@ Any account with write access (including bots and TOC members) **must** use [2FA
Mergers are the maintainers who carry out the final merge of approved PRs. Their responsibilities, described throughout this guide, are:
- Merging PRs from the [merge queue](#getting-prs-merged) in order, once a PR has `lgtm/done`, no open discussions, and no merge conflicts.
- Rewriting the PR title and description prior to the merge, making the [commit message](#commit-messages) clear.\
In particular, mergers should edit the PR description.\
Mergers should **not** edit the actual commit message except to remove unnecessary information. Because of that, even if users are looking at the PR, they can understand what changed.
- Rewriting the PR title and summary so the squash [commit message](#commit-messages) is clear, removing false-positive co-authors while keeping every true co-author.
- Assigning the correct labels (including `type/…`) needed for changelog and backport decisions.
- Agreeing, together with the owners, on when a release is ready (see [release management](release-management.md)).
- Merging a PR also means the PR looks good to the merger and is approved by the merger.
If a merger violates these merge guides more than 3 times in the past 365 days
(e.g.: merge with unresolved reviews without TOC decision to ignore the review, merge with garbage commit messages),
they may lose their merging privileges for at least three months.
#### Becoming a merger
@@ -214,20 +200,20 @@ random.seed("Gitea TOC <YEAR> Election")
random.choice([<CANDIDATE_1>, <CANDIDATE_2>, ...])
```
The result of this script needs then to be published in the TOC election issue to ensure transparency of the process.
The result of this script needs then to be published in the TOC election issue to ensure transparency of the process.
### Current TOC members
- 2026-06-14 ~ 2026-12-31
- Company
- [Yu Tian](https://gitea.com/Zettat123) <zettat123@gmail.com>
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com>
- Community
- [bircni](https://gitea.com/bircni) <bircni@icloud.com>
- [delvh](https://gitea.com/delvh) <dev.lh@web.de>
- [TheFox0x7](https://gitea.com/TheFox0x7) <thefox0x7@gmail.com>
### Previous TOC/owners members
@@ -241,7 +227,7 @@ Here's the history of the owners and the time they served:
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [6543](https://gitea.com/6543) - 2023, 2025
- [John Olheiser](https://gitea.com/jolheiser) - 2023, 2024
- [Jason Song](https://gitea.com/wolfogre) - 2023, 2025
- [Jason Song](https://gitea.com/wolfogre) - 2023
## Governance Compensation
+14 -23
View File
@@ -1,4 +1,6 @@
import arrayFunc from 'eslint-plugin-array-func';
import comments from '@eslint-community/eslint-plugin-eslint-comments';
import deMorgan from 'eslint-plugin-de-morgan';
import globals from 'globals';
import importPlugin from 'eslint-plugin-import-x';
import playwright from 'eslint-plugin-playwright';
@@ -13,6 +15,7 @@ import vue from 'eslint-plugin-vue';
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
import wc from 'eslint-plugin-wc';
import {defineConfig, globalIgnores} from 'eslint/config';
import type {ESLint} from 'eslint';
import unescapedHtmlLiteral from './tools/eslint-rules/unescaped-html-literal.ts';
@@ -61,8 +64,10 @@ export default defineConfig([
'@eslint-community/eslint-comments': comments,
'@stylistic': stylistic,
'@typescript-eslint': typescriptPlugin.plugin,
'array-func': arrayFunc,
'de-morgan': deMorgan,
'gitea': {rules: {'unescaped-html-literal': unescapedHtmlLiteral}},
'import-x': importPlugin,
'import-x': importPlugin as unknown as ESLint.Plugin, // https://github.com/un-ts/eslint-plugin-import-x/issues/203
regexp,
sonarjs,
unicorn,
@@ -273,6 +278,12 @@ export default defineConfig([
'@typescript-eslint/unified-signatures': [2],
'accessor-pairs': [2],
'array-callback-return': [2, {checkForEach: true}],
'array-func/avoid-reverse': [2],
'array-func/from-map': [2],
'array-func/no-unnecessary-this-arg': [2],
'array-func/prefer-array-from': [2],
'array-func/prefer-flat-map': [0], // handled by unicorn/prefer-array-flat-map
'array-func/prefer-flat': [0], // handled by unicorn/prefer-array-flat
'arrow-body-style': [0],
'block-scoped-var': [2],
'camelcase': [0],
@@ -283,6 +294,8 @@ export default defineConfig([
'consistent-this': [0],
'constructor-super': [2],
'curly': [0],
'de-morgan/no-negated-conjunction': [2],
'de-morgan/no-negated-disjunction': [2],
'default-case-last': [2],
'default-case': [0],
'default-param-last': [0],
@@ -732,7 +745,6 @@ export default defineConfig([
'unicorn/consistent-json-file-read': [2],
'unicorn/consistent-optional-chaining': [2],
'unicorn/consistent-template-literal-escape': [2],
'unicorn/consistent-tuple-labels': [2],
'unicorn/custom-error-definition': [0],
'unicorn/default-export-style': [2],
'unicorn/dom-node-dataset': [2, {preferAttributes: true}],
@@ -766,7 +778,6 @@ export default defineConfig([
'unicorn/no-array-sort-for-min-max': [2],
'unicorn/no-array-splice': [0],
'unicorn/no-asterisk-prefix-in-documentation-comments': [0],
'unicorn/no-async-promise-finally': [2],
'unicorn/no-await-expression-member': [0],
'unicorn/no-await-in-promise-methods': [2],
'unicorn/no-blob-to-file': [2],
@@ -803,10 +814,8 @@ export default defineConfig([
'unicorn/no-invalid-fetch-options': [2],
'unicorn/no-invalid-file-input-accept': [2],
'unicorn/no-invalid-remove-event-listener': [2],
'unicorn/no-invalid-well-known-symbol-methods': [2],
'unicorn/no-keyword-prefix': [0],
'unicorn/no-late-current-target-access': [2],
'unicorn/no-late-event-control': [2],
'unicorn/no-lonely-if': [2],
'unicorn/no-loop-iterable-mutation': [2],
'unicorn/no-magic-array-flat-depth': [0],
@@ -843,11 +852,9 @@ export default defineConfig([
'unicorn/no-uncalled-method': [2],
'unicorn/no-undeclared-class-members': [2],
'unicorn/no-unnecessary-array-flat-depth': [2],
'unicorn/no-unnecessary-array-flat-map': [2],
'unicorn/no-unnecessary-array-splice-count': [2],
'unicorn/no-unnecessary-await': [2],
'unicorn/no-unnecessary-boolean-comparison': [2],
'unicorn/no-unnecessary-fetch-options': [0],
'unicorn/no-unnecessary-global-this': [0],
'unicorn/no-unnecessary-nested-ternary': [2],
'unicorn/no-unnecessary-polyfills': [2],
@@ -860,7 +867,6 @@ export default defineConfig([
'unicorn/no-unreadable-object-destructuring': [0],
'unicorn/no-unsafe-buffer-conversion': [2],
'unicorn/no-unsafe-dom-html': [0],
'unicorn/no-unsafe-promise-all-settled-values': [2],
'unicorn/no-unsafe-property-key': [0],
'unicorn/no-unsafe-string-replacement': [0],
'unicorn/no-unused-array-method-return': [2],
@@ -890,17 +896,13 @@ export default defineConfig([
'unicorn/number-literal-case': [0],
'unicorn/numeric-separators-style': [0],
'unicorn/operator-assignment': [2],
'unicorn/prefer-abort-signal-any': [2],
'unicorn/prefer-abort-signal-timeout': [2],
'unicorn/prefer-add-event-listener': [2],
'unicorn/prefer-add-event-listener-options': [2],
'unicorn/prefer-aggregate-error': [2],
'unicorn/prefer-array-find': [0], // handled by @typescript-eslint/prefer-find
'unicorn/prefer-array-flat': [2],
'unicorn/prefer-array-flat-map': [2],
'unicorn/prefer-array-from-async': [2],
'unicorn/prefer-array-from-map': [2],
'unicorn/prefer-array-from-range': [2],
'unicorn/prefer-array-index-of': [2],
'unicorn/prefer-array-iterable-methods': [2],
'unicorn/prefer-array-last-methods': [2],
@@ -910,7 +912,6 @@ export default defineConfig([
'unicorn/prefer-await': [2],
'unicorn/prefer-bigint-literals': [2],
'unicorn/prefer-blob-reading-methods': [2],
'unicorn/prefer-block-statement-over-iife': [2],
'unicorn/prefer-boolean-return': [2],
'unicorn/prefer-class-fields': [2],
'unicorn/prefer-classlist-toggle': [2],
@@ -923,18 +924,15 @@ export default defineConfig([
'unicorn/prefer-dom-node-append': [2],
'unicorn/prefer-dom-node-html-methods': [0],
'unicorn/prefer-dom-node-remove': [2],
'unicorn/prefer-dom-node-replace-children': [2],
'unicorn/prefer-dom-node-text-content': [2],
'unicorn/prefer-early-return': [0],
'unicorn/prefer-else-if': [2],
'unicorn/prefer-error-is-error': [0],
'unicorn/prefer-event-target': [2],
'unicorn/prefer-export-from': [0],
'unicorn/prefer-flat-math-min-max': [2],
'unicorn/prefer-get-or-insert-computed': [2],
'unicorn/prefer-global-number-constants': [2],
'unicorn/prefer-global-this': [0],
'unicorn/prefer-group-by': [2],
'unicorn/prefer-has-check': [2],
'unicorn/prefer-hoisting-branch-code': [2],
'unicorn/prefer-https': [0], // false-positives on namespace and schema URIs
@@ -944,7 +942,6 @@ export default defineConfig([
'unicorn/prefer-includes-over-repeated-comparisons': [0], // too opinionated
'unicorn/prefer-iterable-in-constructor': [2],
'unicorn/prefer-iterator-concat': [0], // too opinionated
'unicorn/prefer-iterator-helpers': [2],
'unicorn/prefer-iterator-to-array': [2],
'unicorn/prefer-iterator-to-array-at-end': [2],
'unicorn/prefer-keyboard-event-key': [2],
@@ -969,11 +966,9 @@ export default defineConfig([
'unicorn/prefer-object-destructuring-defaults': [2],
'unicorn/prefer-object-from-entries': [2],
'unicorn/prefer-object-iterable-methods': [2],
'unicorn/prefer-observer-apis': [2],
'unicorn/prefer-optional-catch-binding': [2],
'unicorn/prefer-path2d': [2],
'unicorn/prefer-private-class-fields': [0],
'unicorn/prefer-promise-try': [2],
'unicorn/prefer-promise-with-resolvers': [2],
'unicorn/prefer-prototype-methods': [0],
'unicorn/prefer-query-selector': [2],
@@ -984,12 +979,10 @@ export default defineConfig([
'unicorn/prefer-response-static-json': [2],
'unicorn/prefer-scoped-selector': [0],
'unicorn/prefer-set-has': [0],
'unicorn/prefer-set-methods': [0],
'unicorn/prefer-set-size': [2],
'unicorn/prefer-short-arrow-method': [2],
'unicorn/prefer-simple-condition-first': [0],
'unicorn/prefer-simple-sort-comparator': [2],
'unicorn/prefer-simplified-conditions': [2],
'unicorn/prefer-single-array-predicate': [2],
'unicorn/prefer-single-call': [2],
'unicorn/prefer-single-object-destructuring': [2],
@@ -1009,7 +1002,6 @@ export default defineConfig([
'unicorn/prefer-switch': [0],
'unicorn/prefer-temporal': [0],
'unicorn/prefer-ternary': [0],
'unicorn/prefer-toggle-attribute': [2],
'unicorn/prefer-top-level-await': [0],
'unicorn/prefer-type-error': [0],
'unicorn/prefer-type-literal-last': [0],
@@ -1018,7 +1010,6 @@ export default defineConfig([
'unicorn/prefer-unicode-code-point-escapes': [0],
'unicorn/prefer-url-can-parse': [2],
'unicorn/prefer-url-href': [2],
'unicorn/prefer-url-search-parameters': [2],
'unicorn/prefer-while-loop-condition': [2],
'unicorn/prevent-abbreviations': [0],
'unicorn/relative-url-style': [2],
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1782723713,
"narHash": "sha256-oPXCU/SSUokcGaJREHibG1CBX3+s/W7orDWQOZDsEeQ=",
"lastModified": 1776877367,
"narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b5aa0fbd538984f6e3d201be0005b4463d8b09f8",
"rev": "0726a0ecb6d4e08f6adced58726b95db924cef57",
"type": "github"
},
"original": {
+1 -1
View File
@@ -34,7 +34,7 @@
# only bump toolchain versions here
go = pkgs.go_1_26;
nodejs = pkgs.nodejs_26;
nodejs = pkgs.nodejs_24;
python3 = pkgs.python314;
pnpm = pkgs.pnpm_10;
+31 -29
View File
@@ -1,6 +1,6 @@
module gitea.dev
go 1.26.5
go 1.26.4
require (
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
@@ -9,11 +9,11 @@ require (
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a
gitea.com/go-chi/cache v0.2.1
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
gitea.com/go-chi/session v0.0.0-20260708011333-ebced8a7a2d6
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
gitea.dev/actions-proto-go v0.6.0
gitea.dev/sdk v1.2.0
gitea.dev/sdk v1.1.0
github.com/42wim/httpsig v1.2.4
github.com/42wim/sshsig v0.0.0-20260317195500-b9f38cf0d432
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0
@@ -24,12 +24,12 @@ require (
github.com/PuerkitoBio/goquery v1.12.0
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.10.0
github.com/alecthomas/chroma/v2 v2.27.0
github.com/aws/aws-sdk-go-v2/credentials v1.19.28
github.com/aws/aws-sdk-go-v2/service/codecommit v1.35.0
github.com/aws/aws-sdk-go-v2/credentials v1.19.24
github.com/aws/aws-sdk-go-v2/service/codecommit v1.34.4
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.6.0
github.com/bohde/codel v0.2.0
github.com/buildkite/terminal-to-html/v3 v3.17.1
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.25.4
github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20260309112543-12416315a635
github.com/chi-middleware/proxy v1.1.1
@@ -44,20 +44,20 @@ require (
github.com/fsnotify/fsnotify v1.10.1
github.com/getkin/kin-openapi v0.140.0
github.com/gliderlabs/ssh v0.3.8
github.com/go-chi/chi/v5 v5.3.1
github.com/go-chi/chi/v5 v5.3.0
github.com/go-chi/cors v1.2.2
github.com/go-co-op/gocron/v2 v2.21.2
github.com/go-enry/go-enry/v2 v2.9.6
github.com/go-git/go-billy/v5 v5.9.0
github.com/go-git/go-git/v5 v5.19.1
github.com/go-ldap/ldap/v3 v3.4.13
github.com/go-redsync/redsync/v4 v4.17.0
github.com/go-redsync/redsync/v4 v4.16.0
github.com/go-sql-driver/mysql v1.10.0
github.com/go-webauthn/webauthn v0.17.4
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/google/go-github/v89 v89.0.0
github.com/google/go-github/v88 v88.0.0
github.com/google/licenseclassifier/v2 v2.0.0
github.com/google/pprof v0.0.0-20260604005048-7023385849c0
github.com/google/uuid v1.6.0
@@ -68,8 +68,8 @@ require (
github.com/huandu/xstrings v1.5.0
github.com/jhillyerd/enmime/v2 v2.4.1
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.19.0
github.com/klauspost/cpuid/v2 v2.4.0
github.com/klauspost/compress v1.18.6
github.com/klauspost/cpuid/v2 v2.3.0
github.com/lib/pq v1.12.3
github.com/markbates/goth v1.82.0
github.com/mattn/go-isatty v0.0.22
@@ -78,7 +78,7 @@ require (
github.com/mholt/archives v0.1.5
github.com/microcosm-cc/bluemonday v1.0.27
github.com/microsoft/go-mssqldb v1.10.0
github.com/minio/minio-go/v7 v7.2.1
github.com/minio/minio-go/v7 v7.2.0
github.com/msteinert/pam/v2 v2.1.0
github.com/niklasfasching/go-org v1.9.1
github.com/opencontainers/go-digest v1.0.0
@@ -96,29 +96,29 @@ require (
github.com/tstranex/u2f v1.0.0
github.com/ulikunitz/xz v0.5.15
github.com/urfave/cli-docs/v3 v3.1.0
github.com/urfave/cli/v3 v3.10.1
github.com/wneessen/go-mail v0.8.1
github.com/urfave/cli/v3 v3.10.0
github.com/wneessen/go-mail v0.7.3
github.com/yohcop/openid-go v1.0.1
github.com/yuin/goldmark v1.8.2
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
gitlab.com/gitlab-org/api/client-go/v2 v2.46.0
gitlab.com/gitlab-org/api/client-go/v2 v2.42.0
go.yaml.in/yaml/v4 v4.0.0-rc.5
golang.org/x/crypto v0.54.0
golang.org/x/image v0.44.0
golang.org/x/mod v0.38.0
golang.org/x/net v0.57.0
golang.org/x/crypto v0.53.0
golang.org/x/image v0.43.0
golang.org/x/mod v0.37.0
golang.org/x/net v0.56.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.22.0
golang.org/x/sys v0.47.0
golang.org/x/text v0.40.0
google.golang.org/grpc v1.82.0
golang.org/x/sync v0.21.0
golang.org/x/sys v0.46.0
golang.org/x/text v0.38.0
google.golang.org/grpc v1.81.1
google.golang.org/protobuf v1.36.11
gopkg.in/ini.v1 v1.67.3
modernc.org/sqlite v1.53.0
mvdan.cc/xurls/v2 v2.6.0
strk.kbt.io/projects/go/libravatar v0.0.0-20260301104140-add494e31dab
xorm.io/builder v0.3.13
xorm.io/xorm v1.4.1
xorm.io/xorm v1.3.11
)
require (
@@ -133,10 +133,10 @@ require (
github.com/andybalholm/brotli v1.2.1 // indirect
github.com/andybalholm/cascadia v1.3.4 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/aws/aws-sdk-go-v2 v1.42.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 // indirect
github.com/aws/smithy-go v1.27.3 // indirect
github.com/aws/aws-sdk-go-v2 v1.42.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect
github.com/aws/smithy-go v1.27.2 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.24.5 // indirect
@@ -199,7 +199,9 @@ require (
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/inbucket/html2text v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
@@ -267,7 +269,7 @@ require (
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org v0.0.0-20260112195520-a5071408f32f // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.47.0 // indirect
golang.org/x/tools v0.45.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260610212136-7ab31c22f7ad // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+69 -62
View File
@@ -18,8 +18,8 @@ gitea.com/go-chi/cache v0.2.1 h1:bfAPkvXlbcZxPCpcmDVCWoHgiBSBmZN/QosnZvEC0+g=
gitea.com/go-chi/cache v0.2.1/go.mod h1:Qic0HZ8hOHW62ETGbonpwz8WYypj9NieU9659wFUJ8Q=
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 h1:p2ki+WK0cIeNQuqjR98IP2KZQKRzJJiV7aTeMAFwaWo=
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098/go.mod h1:LjzIOHlRemuUyO7WR12fmm18VZIlCAaOt9L3yKw40pk=
gitea.com/go-chi/session v0.0.0-20260708011333-ebced8a7a2d6 h1:YWzVGeC/8SZThrJS48ZmQYLkzssdeABxHPhbdnxPDIU=
gitea.com/go-chi/session v0.0.0-20260708011333-ebced8a7a2d6/go.mod h1:KDvcfMUoXfATPHs2mbMoXFTXT45/FAFAS39waz9tPk0=
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e h1:4bugwPyGMLvblEm3pZ8fZProSPVxE4l0UXF2Kv6IJoY=
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e/go.mod h1:KDvcfMUoXfATPHs2mbMoXFTXT45/FAFAS39waz9tPk0=
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:+wWBi6Qfruqu7xJgjOIrKVQGiLUZdpKYCZewJ4clqhw=
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:VyMQP6ue6MKHM8UsOXfNfuMKD0oSAWZdXVcpHIN2yaY=
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o=
@@ -28,8 +28,8 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGq
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
gitea.dev/actions-proto-go v0.6.0 h1:gjllYQ5vmwlkqOeofTQu5qKTZpmf7kWsafoHvoPCSzY=
gitea.dev/actions-proto-go v0.6.0/go.mod h1:p4RX+D9oqiEEzzkPMXscw2CmaGuYFPWFc6xIOmDNDqs=
gitea.dev/sdk v1.2.0 h1:avRtJl/nKCGispgSalo9czoZM9Rto1awnE0caNAoXGo=
gitea.dev/sdk v1.2.0/go.mod h1:rfh5oNdIK24cbCREwIn1tqWKQW+IICXFGWJyebuOAOE=
gitea.dev/sdk v1.1.0 h1:wLlz03WkLEiXa2bQpO1JQBTlYf7tQI2neYtZK1kU+TE=
gitea.dev/sdk v1.1.0/go.mod h1:Zfl+EZXdsGGCLkryDfsmvYrQo6GKMl4U3BJA8Beu+cs=
github.com/42wim/httpsig v1.2.4 h1:mI5bH0nm4xn7K18fo1K3okNDRq8CCJ0KbBYWyA6r8lU=
github.com/42wim/httpsig v1.2.4/go.mod h1:yKsYfSyTBEohkPik224QPFylmzEBtda/kjyIAJjh3ps=
github.com/42wim/sshsig v0.0.0-20260317195500-b9f38cf0d432 h1:3Fcz1QzlS7Jv4FT2KI3cHNSZL+KPN3dXxurn9f3YL/Y=
@@ -92,18 +92,18 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go-v2 v1.42.1 h1:9eOTgu1z/dVtYpNZ3/8/XbbaX0x/BqE3HUzAzs6K0ek=
github.com/aws/aws-sdk-go-v2 v1.42.1/go.mod h1:5pKeft2eJj+gElQ38Jqg4ibCqh+/AK33/0X3hip7IjM=
github.com/aws/aws-sdk-go-v2/credentials v1.19.28 h1:zTXJSsNcoO91/mTXsZoYf0AK8dvNPiA58/VtyGXR+wM=
github.com/aws/aws-sdk-go-v2/credentials v1.19.28/go.mod h1:Kd9E0JzDBW/q1xbsHFrev/GnbAf5J0Ng8xoyc7HZ91Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 h1:xM/Is9cKMHa8Jj8zkvWhvrFkZsXJV9E+BB4g0HW0duQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30/go.mod h1:WueJeNDZvK1fMYEWJIkcivBfEzUkTpBhzlrUKKY8EuA=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 h1:jn46zC9LdsVR/ZpMIJqMqb8hHv31BlLx3ulVqNspUOk=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30/go.mod h1:1hTMsAgbdS/AtUi4bw8+gUuh1pceo+eXRLfpSuSQj3M=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.35.0 h1:w/iPWj+VObIbyo1WYN5010Bi61OkkqOiFZpNDAP1Rfc=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.35.0/go.mod h1:uH156Pb0jnMXuCSD9irU0Qz6UNhYUF2qbowFqIwyLQ8=
github.com/aws/smithy-go v1.27.3 h1:F3Zb497UhhskkfpJmfkXswyo+t0sh9OTBnIHjogWbVY=
github.com/aws/smithy-go v1.27.3/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/aws/aws-sdk-go-v2 v1.42.0 h1:XvXMJTkFQtpBKIWZnmr9ZEOc2InWM2yldjXEJ/bymhA=
github.com/aws/aws-sdk-go-v2 v1.42.0/go.mod h1:27+ACypSLljLAEKsCYOmrjKh83vuTRkuAe9Uv/3A4bg=
github.com/aws/aws-sdk-go-v2/credentials v1.19.24 h1:2hQqYCV9yqyePQ9o6dCrZc/zO8U3TwPr9mIKlZnPu/I=
github.com/aws/aws-sdk-go-v2/credentials v1.19.24/go.mod h1:IDwpACtwqHLISdzfwUUNq4P9DsB/h5BLg4FwJPNfqFY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 h1:f3vKqSo13fhTYb+JEcXwXefZQE26I1FB5eTSniU67ko=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29/go.mod h1:MzoLFUArKGpGD+ukmPiTPG1X5x4o6M2kq4v2dr1FiEc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 h1:RdwIf/CuUsvJX3RgJagbOyotl/cxoLY4xviKuE7p2GY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29/go.mod h1:71wt8W2EgswdZy9Mf9KNnzxZ3TiZlv4caKghPktDOkA=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.34.4 h1:Uu+wqrOXozYYvaxcNIqjFsMTjoIJIZDN3R0f70ZIjyQ=
github.com/aws/aws-sdk-go-v2/service/codecommit v1.34.4/go.mod h1:pYrBdL1tMTZO7PaKRsa1cTUB8HtQh3fFM3zJHGhTQcE=
github.com/aws/smithy-go v1.27.2 h1:y9NPmSE6am6LjEFPfqHqG/jJk7AauQvhCJONKh7kpzk=
github.com/aws/smithy-go v1.27.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -185,8 +185,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/buildkite/terminal-to-html/v3 v3.17.1 h1:gs9WhKUwxK27YHf3hijj4tG4wuDLfCANYbRPd5ltMdI=
github.com/buildkite/terminal-to-html/v3 v3.17.1/go.mod h1:0pv+Z75FC+NvIju2o+Cw+YHIDkueeudIoeyfVm8i8GQ=
github.com/buildkite/terminal-to-html/v3 v3.16.8 h1:QN/daUob6cmK8GcdKnwn9+YTlPr1vNj+oeAIiJK6fPc=
github.com/buildkite/terminal-to-html/v3 v3.16.8/go.mod h1:+k1KVKROZocrTLsEQ9PEf9A+8+X8uaVV5iO1ZIOwKYM=
github.com/caddyserver/certmagic v0.25.4 h1:8eIXh0HC3MsGnNo8One+BCxMGTbe5zb/oz+2KsxBFQg=
github.com/caddyserver/certmagic v0.25.4/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA=
github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE=
@@ -285,8 +285,8 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/chi/v5 v5.3.0 h1:halUjDxhshgXHMrao5bB8eNBXo/rnzwr8m5m36glehM=
github.com/go-chi/chi/v5 v5.3.0/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron/v2 v2.21.2 h1:bD8/YwkojYHgXFr3iEulL148KBdTbKVxUZzFKpXcdbY=
@@ -319,8 +319,8 @@ github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOr
github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-redsync/redsync/v4 v4.17.0 h1:FFJ+uxZs44y4Sq10//IFKic9T94AYl+u3Sog98AHzBo=
github.com/go-redsync/redsync/v4 v4.17.0/go.mod h1:CKVA6qwT07S/916i+Yd9h1/8YFQhCCpPYTQhvvYytJo=
github.com/go-redsync/redsync/v4 v4.16.0 h1:bNcOzeHH9d3s6pghU9NJFMPrQa41f5Nx3L4YKr3BdEU=
github.com/go-redsync/redsync/v4 v4.16.0/go.mod h1:V4gagqgyASWBZuwx4xGzu72aZNb/6Mo05byUa3mVmKQ=
github.com/go-sql-driver/mysql v1.10.0 h1:Q+1LV8DkHJvSYAdR83XzuhDaTykuDx0l6fkXxoWCWfw=
github.com/go-sql-driver/mysql v1.10.0/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
@@ -376,8 +376,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v89 v89.0.0 h1:35bEK5XoEcF3PZrlVbl9XN63f5BcJRA/UGkxeC9xPg0=
github.com/google/go-github/v89 v89.0.0/go.mod h1:QLcbU0ipeAqQuR5KSg8c2lql4Qk1EwJ2dWz/0rP4Nho=
github.com/google/go-github/v88 v88.0.0 h1:dZA9IKkPK1eXZj4ypngnpRj5FwdpTv4whix2PrQMP7M=
github.com/google/go-github/v88 v88.0.0/go.mod h1:rufTDgn2N45wjhukLTyxmvc9nilSp3mr3Rgtt6b1MPw=
github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0=
github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU=
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
@@ -413,10 +413,17 @@ github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pw
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/graph-gophers/graphql-go v1.10.2 h1:HXu6Wu5klCH4ALn1fQHVI20cjEIa4wftavHIgbLA4Fo=
github.com/graph-gophers/graphql-go v1.10.2/go.mod h1:AsADheC4CCFwd8n1/QbkduTlHgYYMsRgtPihYVAlEsk=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
@@ -464,12 +471,12 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C
github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY=
github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ=
github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
@@ -527,8 +534,8 @@ github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.2.1 h1:PfBfwvKB/MmqyN8Vb1G9voWisaM9OrLv+WwOvMwS9Dw=
github.com/minio/minio-go/v7 v7.2.1/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0=
github.com/minio/minio-go/v7 v7.2.0 h1:RCJM0R1XOsRs+A3x3UCaf3ZYbByDaLjFeAi+YCQEPhs=
github.com/minio/minio-go/v7 v7.2.0/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0=
github.com/minio/minlz v1.1.1 h1:OGmft1V6AnI/Wme332U6bhG54nxEan+VFgkD7lat4KM=
github.com/minio/minlz v1.1.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -613,10 +620,10 @@ github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKc
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.21.0 h1:FPBE4hhbAke+TLmcY3WkpbDffJEomdqPn3HYiqAtL9E=
github.com/redis/go-redis/v9 v9.21.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
github.com/redis/rueidis v1.0.76 h1:RdDWuvlYBSp+bTrBvaXqJnNEL3VVzsnjo+0psPFgLc4=
github.com/redis/rueidis v1.0.76/go.mod h1:UsfHPSbomB6QAVMk4iiFkzRy0nh9o7scDGa+SitvBY4=
github.com/redis/rueidis/rueidiscompat v1.0.76 h1:7LikbiqCQqCsZXeZ+akgZMnjIV/J0VHih9PIX4gGZC4=
github.com/redis/rueidis/rueidiscompat v1.0.76/go.mod h1:UatQQLVj4QMIsZtpvRWY28qm6r2d72idhcS+C/RM+Zg=
github.com/redis/rueidis v1.0.71 h1:pODtnAR5GAB7j4ekhldZ29HKOxe4Hph0GTDGk1ayEQY=
github.com/redis/rueidis v1.0.71/go.mod h1:lfdcZzJ1oKGKL37vh9fO3ymwt+0TdjkkUCJxbgpmcgQ=
github.com/redis/rueidis/rueidiscompat v1.0.71 h1:wNZ//kEjMZgBM0KCk7ncOX8KmAgROU2kDdDNpwheG4w=
github.com/redis/rueidis/rueidiscompat v1.0.71/go.mod h1:esmCLJvaRzZoKlgB82G1bY7Iky5TnO9Rz+NlhbEccFI=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rhysd/actionlint v1.7.12 h1:vQ4GeJN86C0QH+gTUQcs8McmK62OLT3kmakPMtEWYnY=
@@ -702,11 +709,11 @@ github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/urfave/cli-docs/v3 v3.1.0 h1:Sa5xm19IpE5gpm6tZzXdfjdFxn67PnEsE4dpXF7vsKw=
github.com/urfave/cli-docs/v3 v3.1.0/go.mod h1:59d+5Hz1h6GSGJ10cvcEkbIe3j233t4XDqI72UIx7to=
github.com/urfave/cli/v3 v3.10.1 h1:7Kx9H50hrHbRbyxgO1KP6/BcbiGRz0uYh5YyQ30JEEY=
github.com/urfave/cli/v3 v3.10.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/urfave/cli/v3 v3.10.0 h1:0aU8yOObVDMkM13Cj4G+zb4P0PdeJMec65f81Ak1ioM=
github.com/urfave/cli/v3 v3.10.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/wneessen/go-mail v0.8.1 h1:tVcncj02/QySVFw3zr/kXOzZcuFQqBNT6K+Rbgm/pcM=
github.com/wneessen/go-mail v0.8.1/go.mod h1:dWZ61zadzCIyvB4y1/YzC5O7MrbbzBfPkARmbosdf8w=
github.com/wneessen/go-mail v0.7.3 h1:g3DravXC5SMlVdboFrQA8Jx95A8sOzoBeS5F+vzNRK0=
github.com/wneessen/go-mail v0.7.3/go.mod h1:QGhBX0yNbc1J+Mkjcu7z2rpj4B4l+BmDY8gYznPC9sk=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@@ -733,8 +740,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
gitlab.com/gitlab-org/api/client-go/v2 v2.46.0 h1:t9QSeMck3kuHu9R6C7h8cYk4qBI4ZD4SQ0jspxKYs2E=
gitlab.com/gitlab-org/api/client-go/v2 v2.46.0/go.mod h1:1LK5UOowqo9apkL+zn7sM8t/hCzBV6F1b2RUIHL9+Oo=
gitlab.com/gitlab-org/api/client-go/v2 v2.42.0 h1:Bq5YIYgUJVbt4Hbh7ibBwNR4SNEafsyDVhIXl7dXDdg=
gitlab.com/gitlab-org/api/client-go/v2 v2.42.0/go.mod h1:SKUbKSS59KPt6WeGNJoYF8HDaf/rFMUSITlftj/HkLg=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
@@ -769,12 +776,12 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
golang.org/x/image v0.43.0 h1:FLxcP4ec2350nTfOC8ysKtqYSIFbk/QGjw1ZHNP4tsY=
golang.org/x/image v0.43.0/go.mod h1:rrpelvGFt+kLPAjPM4HeWPgrl0FtafueU//e5N0qk/Q=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -783,8 +790,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -800,8 +807,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -815,8 +822,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -847,8 +854,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -858,8 +865,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -870,8 +877,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -883,16 +890,16 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260610212136-7ab31c22f7ad h1:45WmJvIV6C2+O/jjLkPUH+F3aOj/1miDoU2DD0+NWbg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260610212136-7ab31c22f7ad/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU=
google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -957,5 +964,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20260301104140-add494e31dab h1:3IZDVyI
strk.kbt.io/projects/go/libravatar v0.0.0-20260301104140-add494e31dab/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.4.1 h1:m7QlNd0eBGb31IV4Q/ow0Du83rtdC1CiwlvJZGvYde8=
xorm.io/xorm v1.4.1/go.mod h1:cs0ePc8O4a0jD78cNvD+0VFwhqotTvLQZv372QsDw7Q=
xorm.io/xorm v1.3.11 h1:i4tlVUASogb0ZZFJHA7dZqoRU2pUpUsutnNdaOlFyMI=
xorm.io/xorm v1.3.11/go.mod h1:cs0ePc8O4a0jD78cNvD+0VFwhqotTvLQZv372QsDw7Q=
-6
View File
@@ -277,12 +277,6 @@ func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, er
return &run, nil
}
func GetRunsByRepoAndID(ctx context.Context, repoID int64, runIDs []int64) ([]*ActionRun, error) {
var runs []*ActionRun
err := db.GetEngine(ctx).In("id", runIDs).Where("repo_id=?", repoID).Find(&runs)
return runs, err
}
func GetRunByRepoAndIndex(ctx context.Context, repoID, runIndex int64) (*ActionRun, error) {
run, has, err := db.Get[ActionRun](ctx, builder.Eq{"repo_id": repoID, "`index`": runIndex})
if err != nil {
-15
View File
@@ -195,18 +195,3 @@ func HasTwoFactorOrWebAuthn(ctx context.Context, id int64) (bool, error) {
}
return HasWebAuthnRegistrationsByUID(ctx, id)
}
// DisableTwoFactor removes every two-factor method of the given user atomically,
// returning the number of TOTP records and WebAuthn credentials removed.
// It is a no-op for a user that has no 2FA enrolled.
func DisableTwoFactor(ctx context.Context, uid int64) (totp, webAuthn int64, err error) {
err = db.WithTx(ctx, func(ctx context.Context) error {
var e error
if totp, e = db.GetEngine(ctx).Where("uid = ?", uid).Delete(&TwoFactor{}); e != nil {
return e
}
webAuthn, e = db.GetEngine(ctx).Where("user_id = ?", uid).Delete(&WebAuthnCredential{})
return e
})
return totp, webAuthn, err
}
-35
View File
@@ -10,7 +10,6 @@ import (
auth_model "gitea.dev/models/auth"
"gitea.dev/models/unittest"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/pquerna/otp/totp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -46,37 +45,3 @@ func TestTwoFactorValidateAndConsumeTOTP(t *testing.T) {
require.NoError(t, err)
assert.False(t, ok)
}
func TestDisableTwoFactor(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
ctx := t.Context()
const uid = 1000 // a uid with no user/2FA fixtures
// Enroll TOTP and register a WebAuthn credential.
tfa := &auth_model.TwoFactor{UID: uid}
require.NoError(t, tfa.SetSecret("test-secret"))
require.NoError(t, auth_model.NewTwoFactor(ctx, tfa))
_, err := auth_model.CreateCredential(ctx, uid, "test-key", &webauthn.Credential{ID: []byte("test-cred-id")})
require.NoError(t, err)
has, err := auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
require.NoError(t, err)
require.True(t, has)
// Both records are removed and counted separately.
totp, webAuthn, err := auth_model.DisableTwoFactor(ctx, uid)
require.NoError(t, err)
assert.EqualValues(t, 1, totp)
assert.EqualValues(t, 1, webAuthn)
has, err = auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
require.NoError(t, err)
assert.False(t, has)
// A second call on a user without 2FA is a no-op.
totp, webAuthn, err = auth_model.DisableTwoFactor(ctx, uid)
require.NoError(t, err)
assert.EqualValues(t, 0, totp)
assert.EqualValues(t, 0, webAuthn)
}
+5 -7
View File
@@ -4,8 +4,6 @@
package actions
import (
"context"
"gitea.dev/modules/actions/jobparser"
"gitea.dev/modules/git"
"gitea.dev/modules/log"
@@ -15,8 +13,8 @@ import (
)
// ListScopedWorkflows lists scoped workflow files (under SCOPED_WORKFLOW_DIRS) at the given commit.
func ListScopedWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, git.Entries, error) {
return listWorkflowsInDirs(ctx, gitRepo, commit, setting.Actions.ScopedWorkflowDirs)
func ListScopedWorkflows(commit *git.Commit) (string, git.Entries, error) {
return listWorkflowsInDirs(commit, setting.Actions.ScopedWorkflowDirs)
}
// ParsedScopedWorkflow is one scoped workflow's source-side parse result
@@ -28,15 +26,15 @@ type ParsedScopedWorkflow struct {
}
// ParseScopedWorkflows lists and parses the scoped workflow files at sourceCommit (under SCOPED_WORKFLOW_DIRS).
func ParseScopedWorkflows(ctx context.Context, gitRepo *git.Repository, sourceCommit *git.Commit) ([]*ParsedScopedWorkflow, error) {
_, entries, err := ListScopedWorkflows(ctx, gitRepo, sourceCommit)
func ParseScopedWorkflows(sourceCommit *git.Commit) ([]*ParsedScopedWorkflow, error) {
_, entries, err := ListScopedWorkflows(sourceCommit)
if err != nil {
return nil, err
}
parsed := make([]*ParsedScopedWorkflow, 0, len(entries))
for _, entry := range entries {
content, err := GetContentFromEntry(gitRepo, entry)
content, err := GetContentFromEntry(entry)
if err != nil {
return nil, err
}
+18 -20
View File
@@ -5,7 +5,6 @@ package actions
import (
"bytes"
"context"
"fmt"
"path"
"slices"
@@ -70,16 +69,16 @@ func isWorkflowInDirs(path string, dirs []string) bool {
return false
}
func ListWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, git.Entries, error) {
return listWorkflowsInDirs(ctx, gitRepo, commit, setting.Actions.WorkflowDirs)
func ListWorkflows(commit *git.Commit) (string, git.Entries, error) {
return listWorkflowsInDirs(commit, setting.Actions.WorkflowDirs)
}
func listWorkflowsInDirs(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, dirs []string) (string, git.Entries, error) {
func listWorkflowsInDirs(commit *git.Commit, dirs []string) (string, git.Entries, error) {
var tree *git.Tree
var err error
var workflowDir string
for _, workflowDir = range dirs {
tree, err = commit.SubTree(ctx, gitRepo, workflowDir)
tree, err = commit.SubTree(workflowDir)
if err == nil {
break
}
@@ -91,7 +90,7 @@ func listWorkflowsInDirs(ctx context.Context, gitRepo *git.Repository, commit *g
return "", nil, nil
}
entries, err := tree.ListEntriesRecursiveFast(ctx, gitRepo)
entries, err := tree.ListEntriesRecursiveFast()
if err != nil {
return "", nil, err
}
@@ -105,8 +104,8 @@ func listWorkflowsInDirs(ctx context.Context, gitRepo *git.Repository, commit *g
return workflowDir, ret, nil
}
func GetContentFromEntry(gitRepo *git.Repository, entry *git.TreeEntry) ([]byte, error) {
f, err := entry.Blob(gitRepo).DataAsync()
func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) {
f, err := entry.Blob().DataAsync()
if err != nil {
return nil, err
}
@@ -176,20 +175,19 @@ func ShouldEventCreateCommitStatus(event string) bool {
}
func DetectWorkflows(
ctx context.Context,
gitRepo *git.Repository,
commit *git.Commit,
triggedEvent webhook_module.HookEventType,
payload api.Payloader,
detectSchedule bool,
) (workflows, schedules, filtered []*DetectedWorkflow, err error) {
_, entries, err := ListWorkflows(ctx, gitRepo, commit)
_, entries, err := ListWorkflows(commit)
if err != nil {
return nil, nil, nil, err
}
for _, entry := range entries {
content, err := GetContentFromEntry(gitRepo, entry)
content, err := GetContentFromEntry(entry)
if err != nil {
return nil, nil, nil, err
}
@@ -231,15 +229,15 @@ func DetectWorkflows(
return workflows, schedules, filtered, nil
}
func DetectScheduledWorkflows(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
_, entries, err := ListWorkflows(ctx, gitRepo, commit)
func DetectScheduledWorkflows(gitRepo *git.Repository, commit *git.Commit) ([]*DetectedWorkflow, error) {
_, entries, err := ListWorkflows(commit)
if err != nil {
return nil, err
}
wfs := make([]*DetectedWorkflow, 0, len(entries))
for _, entry := range entries {
content, err := GetContentFromEntry(gitRepo, entry)
content, err := GetContentFromEntry(entry)
if err != nil {
return nil, err
}
@@ -286,7 +284,7 @@ func detectWorkflowMatch(gitRepo *git.Repository, commit *git.Commit, triggedEve
case // push
webhook_module.HookEventPush:
return matchPushEvent(gitRepo, commit, payload.(*api.PushPayload), evt)
return matchPushEvent(commit, payload.(*api.PushPayload), evt)
case // issues
webhook_module.HookEventIssues,
@@ -359,7 +357,7 @@ func detectWorkflowMatch(gitRepo *git.Repository, commit *git.Commit, triggedEve
}
}
func matchPushEvent(gitRepo *git.Repository, commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) detectResult {
func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) detectResult {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return detectMatched
@@ -425,7 +423,7 @@ func matchPushEvent(gitRepo *git.Repository, commit *git.Commit, pushPayload *ap
matchTimes++
break
}
filesChanged, err := commit.GetFilesChangedSinceCommit(gitRepo, pushPayload.Before)
filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
return detectNotApplicable
@@ -442,7 +440,7 @@ func matchPushEvent(gitRepo *git.Repository, commit *git.Commit, pushPayload *ap
matchTimes++
break
}
filesChanged, err := commit.GetFilesChangedSinceCommit(gitRepo, pushPayload.Before)
filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
return detectNotApplicable
@@ -592,7 +590,7 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
matchTimes++
}
case "paths":
filesChanged, err := headCommit.GetFilesChangedSinceCommit(gitRepo, prPayload.PullRequest.MergeBase)
filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase)
if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
return detectNotApplicable
@@ -605,7 +603,7 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
matchTimes++
}
case "paths-ignore":
filesChanged, err := headCommit.GetFilesChangedSinceCommit(gitRepo, prPayload.PullRequest.MergeBase)
filesChanged, err := headCommit.GetFilesChangedSinceCommit(prPayload.PullRequest.MergeBase)
if err != nil {
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", headCommit.ID.String(), err)
return detectNotApplicable
+3 -7
View File
@@ -3,11 +3,7 @@
package fileicon
import (
"context"
"gitea.dev/modules/git"
)
import "gitea.dev/modules/git"
type EntryInfo struct {
BaseName string
@@ -16,10 +12,10 @@ type EntryInfo struct {
IsOpen bool
}
func EntryInfoFromGitTreeEntry(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, fullPath string, gitEntry *git.TreeEntry) *EntryInfo {
func EntryInfoFromGitTreeEntry(commit *git.Commit, fullPath string, gitEntry *git.TreeEntry) *EntryInfo {
ret := &EntryInfo{BaseName: gitEntry.Name(), EntryMode: gitEntry.Mode()}
if gitEntry.IsLink() {
if res, err := git.EntryFollowLink(ctx, gitRepo, commit, fullPath, gitEntry); err == nil && res.TargetEntry.IsDir() {
if res, err := git.EntryFollowLink(commit, fullPath, gitEntry); err == nil && res.TargetEntry.IsDir() {
ret.SymlinkToMode = res.TargetEntry.Mode()
}
}
+43 -52
View File
@@ -17,17 +17,17 @@ import (
// Commit represents a git commit.
type Commit struct {
Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache"
CommitMessage
ID ObjectID
TreeID ObjectID
Parents []ObjectID
Author *Signature // never nil
Committer *Signature // never nil
Signature *CommitSignature
Parents []ObjectID // ID strings
submoduleCache *ObjectCache[*SubModule]
treeCache *Tree
}
// CommitSignature represents a git commit signature part.
@@ -46,12 +46,12 @@ func (c *Commit) ParentID(n int) (ObjectID, error) {
}
// Parent returns n-th parent (0-based index) of the commit.
func (c *Commit) Parent(gitRepo *Repository, n int) (*Commit, error) {
func (c *Commit) Parent(n int) (*Commit, error) {
id, err := c.ParentID(n)
if err != nil {
return nil, err
}
parent, err := gitRepo.getCommit(id)
parent, err := c.repo.getCommit(id)
if err != nil {
return nil, err
}
@@ -65,44 +65,25 @@ func (c *Commit) ParentCount() int {
}
// GetCommitByPath return the commit of relative path object.
func (c *Commit) GetCommitByPath(gitRepo *Repository, relpath string) (*Commit, error) {
if gitRepo.LastCommitCache != nil {
return gitRepo.LastCommitCache.GetCommitByPath(c.ID.String(), relpath)
func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) {
if c.repo.LastCommitCache != nil {
return c.repo.LastCommitCache.GetCommitByPath(c.ID.String(), relpath)
}
return gitRepo.getCommitByPathWithID(c.ID, relpath)
}
func (c *Commit) Tree() *Tree {
if c.treeCache == nil {
c.treeCache = newTree(c.TreeID)
}
return c.treeCache
}
func (c *Commit) GetBlobByPath(ctx context.Context, gitRepo *Repository, relpath string) (*Blob, error) {
return c.Tree().GetBlobByPath(ctx, gitRepo, relpath)
}
func (c *Commit) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (_ *TreeEntry, err error) {
return c.Tree().GetTreeEntryByPath(ctx, gitRepo, relpath)
}
func (c *Commit) SubTree(ctx context.Context, gitRepo *Repository, relpath string) (*Tree, error) {
return c.Tree().SubTree(ctx, gitRepo, relpath)
return c.repo.getCommitByPathWithID(c.ID, relpath)
}
// CommitsByRange returns the specific page commits before current revision, every page's number default by CommitsRangeSize
func (c *Commit) CommitsByRange(gitRepo *Repository, page, pageSize int, not, since, until string) ([]*Commit, error) {
return gitRepo.commitsByRangeWithTime(c.ID, page, pageSize, not, since, until)
func (c *Commit) CommitsByRange(page, pageSize int, not, since, until string) ([]*Commit, error) {
return c.repo.commitsByRangeWithTime(c.ID, page, pageSize, not, since, until)
}
// CommitsBefore returns all the commits before current revision
func (c *Commit) CommitsBefore(gitRepo *Repository) ([]*Commit, error) {
return gitRepo.getCommitsBefore(c.ID)
func (c *Commit) CommitsBefore() ([]*Commit, error) {
return c.repo.getCommitsBefore(c.ID)
}
// HasPreviousCommit returns true if a given commitHash is contained in commit's parents
func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, objectID ObjectID) (bool, error) {
func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) {
this := c.ID.String()
that := objectID.String()
@@ -112,8 +93,8 @@ func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, obj
_, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor").
AddDynamicArguments(that, this).
WithDir(gitRepo.Path).
RunStdString(ctx)
WithDir(c.repo.Path).
RunStdString(c.repo.Ctx)
if err == nil {
return true, nil
}
@@ -127,8 +108,8 @@ func (c *Commit) HasPreviousCommit(ctx context.Context, gitRepo *Repository, obj
}
// IsForcePush returns true if a push from oldCommitHash to this is a force push
func (c *Commit) IsForcePush(ctx context.Context, gitRepo *Repository, oldCommitID string) (bool, error) {
objectFormat, err := gitRepo.GetObjectFormat()
func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
objectFormat, err := c.repo.GetObjectFormat()
if err != nil {
return false, err
}
@@ -136,22 +117,22 @@ func (c *Commit) IsForcePush(ctx context.Context, gitRepo *Repository, oldCommit
return false, nil
}
oldCommit, err := gitRepo.GetCommit(oldCommitID)
oldCommit, err := c.repo.GetCommit(oldCommitID)
if err != nil {
return false, err
}
hasPreviousCommit, err := c.HasPreviousCommit(ctx, gitRepo, oldCommit.ID)
hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID)
return !hasPreviousCommit, err
}
// CommitsBeforeLimit returns num commits before current revision
func (c *Commit) CommitsBeforeLimit(gitRepo *Repository, num int) ([]*Commit, error) {
return gitRepo.getCommitsBeforeLimit(c.ID, num)
func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) {
return c.repo.getCommitsBeforeLimit(c.ID, num)
}
// CommitsBeforeUntil returns the commits in range "[cur, ref)"
func (c *Commit) CommitsBeforeUntil(gitRepo *Repository, ref RefName) ([]*Commit, error) {
return gitRepo.CommitsBetween(c.ID.RefName(), ref, -1)
func (c *Commit) CommitsBeforeUntil(ref RefName) ([]*Commit, error) {
return c.repo.CommitsBetween(c.ID.RefName(), ref, -1)
}
// SearchCommitsOptions specify the parameters for SearchCommits
@@ -194,29 +175,39 @@ func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommits
}
// SearchCommits returns the commits match the keyword before current revision
func (c *Commit) SearchCommits(gitRepo *Repository, opts SearchCommitsOptions) ([]*Commit, error) {
return gitRepo.searchCommits(c.ID, opts)
func (c *Commit) SearchCommits(opts SearchCommitsOptions) ([]*Commit, error) {
return c.repo.searchCommits(c.ID, opts)
}
// GetFilesChangedSinceCommit get all changed file names between pastCommit to current revision
func (c *Commit) GetFilesChangedSinceCommit(gitRepo *Repository, pastCommit string) ([]string, error) {
return gitRepo.GetFilesChangedBetween(pastCommit, c.ID.String())
func (c *Commit) GetFilesChangedSinceCommit(pastCommit string) ([]string, error) {
return c.repo.GetFilesChangedBetween(pastCommit, c.ID.String())
}
// FileChangedSinceCommit Returns true if the file given has changed since the past commit
// YOU MUST ENSURE THAT pastCommit is a valid commit ID.
func (c *Commit) FileChangedSinceCommit(gitRepo *Repository, filename, pastCommit string) (bool, error) {
return gitRepo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String())
func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) {
return c.repo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String())
}
// HasFile returns true if the file given exists on this commit
// This does only mean it's there - it does not mean the file was changed during the commit.
func (c *Commit) HasFile(filename string) (bool, error) {
_, err := c.GetBlobByPath(filename)
if err != nil {
return false, err
}
return true, nil
}
// GetFileContent reads a file content as a string or returns false if this was not possible
func (c *Commit) GetFileContent(ctx context.Context, gitRepo *Repository, filename string, limit int) (string, error) {
entry, err := c.GetTreeEntryByPath(ctx, gitRepo, filename)
func (c *Commit) GetFileContent(filename string, limit int) (string, error) {
entry, err := c.GetTreeEntryByPath(filename)
if err != nil {
return "", err
}
r, err := entry.Blob(gitRepo).DataAsync()
r, err := entry.Blob().DataAsync()
if err != nil {
return "", err
}
+2 -4
View File
@@ -3,8 +3,6 @@
package git
import "context"
// CommitInfo describes the first commit with the provided entry
type CommitInfo struct {
Entry *TreeEntry
@@ -12,8 +10,8 @@ type CommitInfo struct {
SubmoduleFile *CommitSubmoduleFile
}
func GetCommitInfoSubmoduleFile(ctx context.Context, repoLink, fullPath string, gitRepo *Repository, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) {
submodule, err := commit.GetSubModule(ctx, gitRepo, fullPath)
func GetCommitInfoSubmoduleFile(repoLink, fullPath string, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) {
submodule, err := commit.GetSubModule(fullPath)
if err != nil {
return nil, err
}
+22 -25
View File
@@ -17,7 +17,7 @@ import (
)
// GetCommitsInfo gets information of all commits that are corresponding to these entries
func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo *Repository, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) {
func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) {
entryPaths := make([]string, len(tes)+1)
// Get the commit for the treePath itself
entryPaths[0] = ""
@@ -25,16 +25,25 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
entryPaths[i+1] = entry.Name()
}
commitNodeIndex, commitGraphFile := commit.repo.CommitNodeIndex()
if commitGraphFile != nil {
defer commitGraphFile.Close()
}
c, err := commitNodeIndex.Get(plumbing.Hash(commit.ID.RawValue()))
if err != nil {
return nil, nil, err
}
var revs map[string]*Commit
var err error
if gitRepo.LastCommitCache != nil {
if commit.repo.LastCommitCache != nil {
var unHitPaths []string
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, gitRepo.LastCommitCache)
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
revs2, err := GetLastCommitForPaths(ctx, gitRepo, commit, treePath, unHitPaths)
revs2, err := GetLastCommitForPaths(ctx, commit.repo.LastCommitCache, c, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}
@@ -42,13 +51,13 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
maps.Copy(revs, revs2)
}
} else {
revs, err = GetLastCommitForPaths(ctx, gitRepo, commit, treePath, entryPaths)
revs, err = GetLastCommitForPaths(ctx, nil, c, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
}
gitRepo.gogitStorage.Close()
commit.repo.gogitStorage.Close()
commitsInfo := make([]CommitInfo, len(tes))
for i, entry := range tes {
@@ -63,7 +72,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
// If the entry is a submodule, add a submodule file for this
if entry.IsSubModule() {
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(ctx, repoLink, path.Join(treePath, entry.Name()), gitRepo, commit, entry.ID)
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID)
if err != nil {
return nil, nil, err
}
@@ -74,10 +83,11 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
// get it for free during the tree traversal and it's used for listing
// pages to display information about newest commit for a given path.
var treeCommit *Commit
var ok bool
if treePath == "" {
treeCommit = commit
} else {
treeCommit = revs[""]
} else if treeCommit, ok = revs[""]; ok {
treeCommit.repo = commit.repo
}
return commitsInfo, treeCommit, nil
}
@@ -152,20 +162,7 @@ func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cac
}
// GetLastCommitForPaths returns last commit information
func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) {
commitNodeIndex, commitGraphFile := gitRepo.CommitNodeIndex()
if commitGraphFile != nil {
defer commitGraphFile.Close()
}
c, err := commitNodeIndex.Get(plumbing.Hash(commit.ID.RawValue()))
if err != nil {
return nil, err
}
return getLastCommitForPathsByCommitNode(ctx, gitRepo, c, treePath, paths)
}
func getLastCommitForPathsByCommitNode(ctx context.Context, gitRepo *Repository, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) {
func GetLastCommitForPaths(ctx context.Context, cache *LastCommitCache, c cgobject.CommitNode, treePath string, paths []string) (map[string]*Commit, error) {
refSha := c.ID().String()
// We do a tree traversal with nodes sorted by commit time
@@ -246,7 +243,7 @@ heaploop:
// match any of the hashes being merged. This is more common for directories,
// but it can also happen if a file is changed through conflict resolution.
resultNodes[pth] = current.commit
if err := gitRepo.LastCommitCache.Put(refSha, path.Join(treePath, pth), current.commit.ID().String()); err != nil {
if err := cache.Put(refSha, path.Join(treePath, pth), current.commit.ID().String()); err != nil {
return nil, err
}
}
+12 -11
View File
@@ -15,7 +15,7 @@ import (
)
// GetCommitsInfo gets information of all commits that are corresponding to these entries
func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo *Repository, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) {
func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) {
entryPaths := make([]string, len(tes)+1)
// Get the commit for the treePath itself
entryPaths[0] = ""
@@ -26,15 +26,15 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
var err error
var revs map[string]*Commit
if gitRepo.LastCommitCache != nil {
if commit.repo.LastCommitCache != nil {
var unHitPaths []string
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, gitRepo.LastCommitCache)
revs, unHitPaths, err = getLastCommitForPathsByCache(commit.ID.String(), treePath, entryPaths, commit.repo.LastCommitCache)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
sort.Strings(unHitPaths)
commits, err := GetLastCommitForPaths(ctx, gitRepo, commit, treePath, unHitPaths)
commits, err := GetLastCommitForPaths(ctx, commit, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}
@@ -43,7 +43,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
}
} else {
sort.Strings(entryPaths)
revs, err = GetLastCommitForPaths(ctx, gitRepo, commit, treePath, entryPaths)
revs, err = GetLastCommitForPaths(ctx, commit, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
@@ -64,7 +64,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
// If the entry is a submodule, add a submodule file for this
if entry.IsSubModule() {
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(ctx, repoLink, path.Join(treePath, entry.Name()), gitRepo, commit, entry.ID)
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID)
if err != nil {
return nil, nil, err
}
@@ -75,10 +75,11 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo
// get it for free during the tree traversal, and it's used for listing
// pages to display information about the newest commit for a given path.
var treeCommit *Commit
var ok bool
if treePath == "" {
treeCommit = commit
} else {
treeCommit = revs[""]
} else if treeCommit, ok = revs[""]; ok {
treeCommit.repo = commit.repo
}
return commitsInfo, treeCommit, nil
}
@@ -103,9 +104,9 @@ func getLastCommitForPathsByCache(commitID, treePath string, paths []string, cac
}
// GetLastCommitForPaths returns last commit information
func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) {
func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) {
// We read backwards from the commit to obtain all of the commits
revs, err := walkGitLog(ctx, gitRepo, commit, treePath, paths...)
revs, err := walkGitLog(ctx, commit.repo, commit, treePath, paths...)
if err != nil {
return nil, err
}
@@ -125,7 +126,7 @@ func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Com
continue
}
c, err := gitRepo.GetCommit(commitID) // Ensure the commit exists in the repository
c, err := commit.repo.GetCommit(commitID) // Ensure the commit exists in the repository
if err != nil {
return nil, err
}
+3 -3
View File
@@ -24,7 +24,7 @@ func TestEntries_GetCommitsInfo_ContextErr(t *testing.T) {
commit, err := repo.GetCommit("feaf4ba6bc635fec442f46ddd4512416ec43c2c2")
require.NoError(t, err)
entries, err := commit.Tree().ListEntries(t.Context(), repo)
entries, err := commit.Tree.ListEntries()
require.NoError(t, err)
countCommitInfosCommit := func(infos []CommitInfo) (nilCommits, nonNilCommits int) {
@@ -39,14 +39,14 @@ func TestEntries_GetCommitsInfo_ContextErr(t *testing.T) {
defer test.MockVariableValue(&walkGitLogDebugBeforeNext)()
walkGitLogDebugBeforeNext = cancel
commitInfos, _, err := entries.GetCommitsInfo(ctx, "/any/repo-link", repo, commit, "")
commitInfos, _, err := entries.GetCommitsInfo(ctx, "/any/repo-link", commit, "")
assert.NoError(t, err)
nilCommits, nonNilCommits := countCommitInfosCommit(commitInfos)
assert.Equal(t, 0, nonNilCommits) // no commit info due to canceled (or deadline-exceeded) context
assert.Equal(t, 3, nilCommits)
walkGitLogDebugBeforeNext = nil
commitInfos, _, err = entries.GetCommitsInfo(t.Context(), "/any/repo-link", repo, commit, "")
commitInfos, _, err = entries.GetCommitsInfo(t.Context(), "/any/repo-link", commit, "")
assert.NoError(t, err)
nilCommits, nonNilCommits = countCommitInfosCommit(commitInfos)
assert.Equal(t, 3, nonNilCommits)
+58 -7
View File
@@ -91,9 +91,10 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
continue
}
assert.NotNil(t, commit)
assert.NotNil(t, commit.TreeID)
assert.NotNil(t, commit.Tree)
assert.NotNil(t, commit.Tree.repo)
tree, err := commit.SubTree(t.Context(), repo1, testCase.Path)
tree, err := commit.Tree.SubTree(testCase.Path)
if err != nil {
assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
@@ -101,8 +102,9 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
entries, err := tree.ListEntries(t.Context(), repo1)
entries, err := tree.ListEntries()
if err != nil {
assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
@@ -110,7 +112,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
// FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain.
commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", repo1, commit, testCase.Path)
commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", commit, testCase.Path)
assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
if err != nil {
t.FailNow()
@@ -125,7 +127,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
continue
}
assert.Equal(t, expectedInfo.CommitID, commit.ID.String())
assert.Equal(t, expectedInfo.Size, entry.GetSize(t.Context(), repo1), entry.Name())
assert.Equal(t, expectedInfo.Size, entry.Size(), entry.Name())
}
}
}
@@ -153,9 +155,9 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) {
commit, err := bareRepo1.GetCommit("HEAD")
require.NoError(t, err)
treeEntry, err := commit.GetTreeEntryByPath(t.Context(), bareRepo1, "file1.txt")
treeEntry, err := commit.GetTreeEntryByPath("file1.txt")
require.NoError(t, err)
cisf, err := GetCommitInfoSubmoduleFile(t.Context(), "/any/repo-link", "file1.txt", bareRepo1, commit, treeEntry.ID)
cisf, err := GetCommitInfoSubmoduleFile("/any/repo-link", "file1.txt", commit, treeEntry.ID)
require.NoError(t, err)
assert.Equal(t, &CommitSubmoduleFile{
repoLink: "/any/repo-link",
@@ -167,3 +169,52 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
assert.Nil(t, cisf.SubmoduleWebLinkTree(t.Context()))
})
}
func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
type benchmarkType struct {
url string
name string
}
benchmarks := []benchmarkType{
{url: "https://github.com/go-gitea/gitea.git", name: "gitea"},
{url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"},
{url: "https://github.com/moby/moby.git", name: "moby"},
{url: "https://github.com/golang/go.git", name: "go"},
{url: "https://github.com/torvalds/linux.git", name: "linux"},
}
doBenchmark := func(benchmark benchmarkType) {
var commit *Commit
var entries Entries
var repo *Repository
repoPath, err := cloneRepo(b, benchmark.url)
if err != nil {
b.Fatal(err)
}
if repo, err = OpenRepository(b.Context(), repoPath); err != nil {
b.Fatal(err)
}
defer repo.Close()
if commit, err = repo.GetBranchCommit("master"); err != nil {
b.Fatal(err)
} else if entries, err = commit.Tree.ListEntries(); err != nil {
b.Fatal(err)
}
b.ResetTimer()
b.Run(benchmark.name, func(b *testing.B) {
for b.Loop() {
_, _, err := entries.GetCommitsInfo(b.Context(), "/any/repo-link", commit, "")
if err != nil {
b.Fatal(err)
}
}
})
}
for _, benchmark := range benchmarks {
doBenchmark(benchmark)
}
}
+4 -4
View File
@@ -15,7 +15,7 @@ const (
commitHeaderGpgsigSha256 = "gpgsig-sha256"
)
func assignCommitFields(commit *Commit, headerKey string, headerValue []byte) error {
func assignCommitFields(gitRepo *Repository, commit *Commit, headerKey string, headerValue []byte) error {
if len(headerValue) > 0 && headerValue[len(headerValue)-1] == '\n' {
headerValue = headerValue[:len(headerValue)-1] // remove trailing newline
}
@@ -25,7 +25,7 @@ func assignCommitFields(commit *Commit, headerKey string, headerValue []byte) er
if err != nil {
return fmt.Errorf("invalid tree ID %q: %w", string(headerValue), err)
}
commit.TreeID = objID
commit.Tree = *NewTree(gitRepo, objID)
case "parent":
objID, err := NewIDFromString(string(headerValue))
if err != nil {
@@ -48,7 +48,7 @@ func assignCommitFields(commit *Commit, headerKey string, headerValue []byte) er
// We need this to interpret commits from cat-file or cat-file --batch
//
// If used as part of a cat-file --batch stream you need to limit the reader to the correct size
func CommitFromReader(objectID ObjectID, reader io.Reader) (*Commit, error) {
func CommitFromReader(gitRepo *Repository, objectID ObjectID, reader io.Reader) (*Commit, error) {
commit := &Commit{
ID: objectID,
Author: &Signature{},
@@ -74,7 +74,7 @@ func CommitFromReader(objectID ObjectID, reader io.Reader) (*Commit, error) {
k, v, _ := bytes.Cut(line, []byte{' '})
if len(k) != 0 || !inHeader {
if headerKey != "" {
if err = assignCommitFields(commit, headerKey, headerValue); err != nil {
if err = assignCommitFields(gitRepo, commit, headerKey, headerValue); err != nil {
return nil, fmt.Errorf("unable to parse commit %q: %w", objectID.String(), err)
}
}
+5 -5
View File
@@ -65,7 +65,7 @@ signed commit`
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
assert.NoError(t, err)
require.NotNil(t, commitFromReader)
assert.EqualValues(t, sha, commitFromReader.ID)
@@ -93,7 +93,7 @@ committer Adam Majer <amajer@suse.de> 1698676906 +0100
signed commit`, commitFromReader.Signature.Payload)
assert.Equal(t, "Adam Majer <amajer@suse.de>", commitFromReader.Author.String())
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
assert.NoError(t, err)
commitFromReader.CommitMessage.MessageRaw += "\n\n"
commitFromReader.Signature.Payload += "\n\n"
@@ -118,15 +118,15 @@ func TestHasPreviousCommitSha256(t *testing.T) {
assert.Equal(t, objectFormat, parentSHA.Type())
assert.Equal(t, "sha256", objectFormat.Name())
haz, err := commit.HasPreviousCommit(t.Context(), repo, parentSHA)
haz, err := commit.HasPreviousCommit(parentSHA)
assert.NoError(t, err)
assert.True(t, haz)
hazNot, err := commit.HasPreviousCommit(t.Context(), repo, notParentSHA)
hazNot, err := commit.HasPreviousCommit(notParentSHA)
assert.NoError(t, err)
assert.False(t, hazNot)
selfNot, err := commit.HasPreviousCommit(t.Context(), repo, commit.ID)
selfNot, err := commit.HasPreviousCommit(commit.ID)
assert.NoError(t, err)
assert.False(t, selfNot)
}
+5 -7
View File
@@ -3,19 +3,17 @@
package git
import "context"
type SubmoduleWebLink struct {
RepoWebLink, CommitWebLink string
}
// GetSubModules get all the submodules of current revision git tree
func (c *Commit) GetSubModules(ctx context.Context, gitRepo *Repository) (*ObjectCache[*SubModule], error) {
func (c *Commit) GetSubModules() (*ObjectCache[*SubModule], error) {
if c.submoduleCache != nil {
return c.submoduleCache, nil
}
entry, err := c.GetTreeEntryByPath(ctx, gitRepo, ".gitmodules")
entry, err := c.GetTreeEntryByPath(".gitmodules")
if err != nil {
if _, ok := err.(ErrNotExist); ok {
return nil, nil //nolint:nilnil // return nil to indicate that the submodule does not exist
@@ -23,7 +21,7 @@ func (c *Commit) GetSubModules(ctx context.Context, gitRepo *Repository) (*Objec
return nil, err
}
rd, err := entry.Blob(gitRepo).DataAsync()
rd, err := entry.Blob().DataAsync()
if err != nil {
return nil, err
}
@@ -39,8 +37,8 @@ func (c *Commit) GetSubModules(ctx context.Context, gitRepo *Repository) (*Objec
// GetSubModule gets the submodule by the entry name.
// It returns "nil, nil" if the submodule does not exist, caller should always remember to check the "nil"
func (c *Commit) GetSubModule(ctx context.Context, gitRepo *Repository, entryName string) (*SubModule, error) {
modules, err := c.GetSubModules(ctx, gitRepo)
func (c *Commit) GetSubModule(entryName string) (*SubModule, error) {
modules, err := c.GetSubModules()
if err != nil {
return nil, err
}
+7 -7
View File
@@ -61,7 +61,7 @@ empty commit`
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
assert.NoError(t, err)
require.NotNil(t, commitFromReader)
assert.EqualValues(t, sha, commitFromReader.ID)
@@ -89,7 +89,7 @@ committer silverwind <me@silverwind.io> 1563741793 +0200
empty commit`, commitFromReader.Signature.Payload)
assert.Equal(t, "silverwind <me@silverwind.io>", commitFromReader.Author.String())
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
assert.NoError(t, err)
commitFromReader.CommitMessage.MessageRaw += "\n\n"
commitFromReader.Signature.Payload += "\n\n"
@@ -125,7 +125,7 @@ ISO-8859-1`
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
commitFromReader, err := CommitFromReader(sha, strings.NewReader(commitString))
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
assert.NoError(t, err)
require.NotNil(t, commitFromReader)
assert.EqualValues(t, sha, commitFromReader.ID)
@@ -152,7 +152,7 @@ encoding ISO-8859-1
ISO-8859-1`, commitFromReader.Signature.Payload)
assert.Equal(t, "KN4CK3R <admin@oldschoolhack.me>", commitFromReader.Author.String())
commitFromReader2, err := CommitFromReader(sha, strings.NewReader(commitString+"\n\n"))
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
assert.NoError(t, err)
commitFromReader.CommitMessage.MessageRaw += "\n\n"
commitFromReader.Signature.Payload += "\n\n"
@@ -172,15 +172,15 @@ func TestHasPreviousCommit(t *testing.T) {
parentSHA := MustIDFromString("8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2")
notParentSHA := MustIDFromString("2839944139e0de9737a044f78b0e4b40d989a9e3")
haz, err := commit.HasPreviousCommit(t.Context(), repo, parentSHA)
haz, err := commit.HasPreviousCommit(parentSHA)
assert.NoError(t, err)
assert.True(t, haz)
hazNot, err := commit.HasPreviousCommit(t.Context(), repo, notParentSHA)
hazNot, err := commit.HasPreviousCommit(notParentSHA)
assert.NoError(t, err)
assert.False(t, hazNot)
selfNot, err := commit.HasPreviousCommit(t.Context(), repo, commit.ID)
selfNot, err := commit.HasPreviousCommit(commit.ID)
assert.NoError(t, err)
assert.False(t, selfNot)
}
+2 -2
View File
@@ -75,7 +75,7 @@ func getRepoRawDiffForFileCmd(_ context.Context, repo *Repository, startCommit,
} else if commit.ParentCount() == 0 {
cmd.AddArguments("show").AddDynamicArguments(endCommit).AddDashesAndList(files...)
} else {
c, err := commit.Parent(repo, 0)
c, err := commit.Parent(0)
if err != nil {
return nil, err
}
@@ -90,7 +90,7 @@ func getRepoRawDiffForFileCmd(_ context.Context, repo *Repository, startCommit,
} else if commit.ParentCount() == 0 {
cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root").AddDynamicArguments(endCommit).AddDashesAndList(files...)
} else {
c, err := commit.Parent(repo, 0)
c, err := commit.Parent(0)
if err != nil {
return nil, err
}
@@ -7,7 +7,6 @@ package languagestats
import (
"bytes"
"context"
"io"
"gitea.dev/modules/analyze"
@@ -22,7 +21,7 @@ import (
)
// GetLanguageStats calculates language stats for git repository at specified commit
func GetLanguageStats(_ context.Context, repo *git_module.Repository, commitID string) (map[string]int64, error) {
func GetLanguageStats(repo *git_module.Repository, commitID string) (map[string]int64, error) {
r, err := git.PlainOpen(repo.Path)
if err != nil {
return nil, err
@@ -7,7 +7,6 @@ package languagestats
import (
"bytes"
"context"
"io"
"gitea.dev/modules/analyze"
@@ -20,10 +19,10 @@ import (
)
// GetLanguageStats calculates language stats for git repository at specified commit
func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string) (map[string]int64, error) {
func GetLanguageStats(repo *git.Repository, commitID string) (map[string]int64, error) {
// We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary.
// so let's create a batch stdin and stdout
batch, cancel, err := repo.CatFileBatch(ctx)
batch, cancel, err := repo.CatFileBatch(repo.Ctx)
if err != nil {
return nil, err
}
@@ -44,7 +43,7 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
return nil, git.ErrNotExist{ID: commitID}
}
commit, err := git.CommitFromReader(sha, io.LimitReader(batchReader, commitInfo.Size))
commit, err := git.CommitFromReader(repo, sha, io.LimitReader(batchReader, commitInfo.Size))
if err != nil {
log.Debug("Unable to get commit for: %s. Err: %v", commitID, err)
return nil, err
@@ -53,7 +52,9 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
return nil, err
}
entries, err := commit.Tree().ListEntriesRecursiveWithSize(ctx, repo)
tree := commit.Tree
entries, err := tree.ListEntriesRecursiveWithSize()
if err != nil {
return nil, err
}
@@ -80,15 +81,13 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
select {
case <-repo.Ctx.Done():
return sizes, repo.Ctx.Err()
case <-ctx.Done():
return sizes, ctx.Err()
default:
}
contentBuf.Reset()
content = contentBuf.Bytes()
if f.GetSize(ctx, repo) == 0 {
if f.Size() == 0 {
continue
}
@@ -125,7 +124,7 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
}
// this language will always be added to the size
sizes[language] += f.GetSize(ctx, repo)
sizes[language] += f.Size()
continue
}
}
@@ -139,7 +138,7 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
// If content can not be read or file is too big just do detection by filename
if f.GetSize(ctx, repo) <= bigFileSize {
if f.Size() <= bigFileSize {
info, _, err := batch.QueryContent(f.ID.String())
if err != nil {
return nil, err
@@ -193,10 +192,10 @@ func GetLanguageStats(ctx context.Context, repo *git.Repository, commitID string
includedLanguage[language] = included
}
if included || isDetectable.ValueOrDefault(false) {
sizes[language] += f.GetSize(ctx, repo)
sizes[language] += f.Size()
} else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) {
firstExcludedLanguage = language
firstExcludedLanguageSize += f.GetSize(ctx, repo)
firstExcludedLanguageSize += f.Size()
}
}
@@ -22,7 +22,7 @@ func TestRepository_GetLanguageStats(t *testing.T) {
require.NoError(t, err)
defer gitRepo.Close()
stats, err := GetLanguageStats(t.Context(), gitRepo, "8fee858da5796dfb37704761701bb8e800ad9ef3")
stats, err := GetLanguageStats(gitRepo, "8fee858da5796dfb37704761701bb8e800ad9ef3")
require.NoError(t, err)
assert.Equal(t, map[string]int64{
+9 -9
View File
@@ -13,26 +13,26 @@ import (
)
// CacheCommit will cache the commit from the gitRepository
func (c *Commit) CacheCommit(ctx context.Context, gitRepo *Repository) error {
if gitRepo.LastCommitCache == nil {
func (c *Commit) CacheCommit(ctx context.Context) error {
if c.repo.LastCommitCache == nil {
return nil
}
commitNodeIndex, _ := gitRepo.CommitNodeIndex()
commitNodeIndex, _ := c.repo.CommitNodeIndex()
index, err := commitNodeIndex.Get(plumbing.Hash(c.ID.RawValue()))
if err != nil {
return err
}
return c.recursiveCache(ctx, gitRepo, index, c.Tree(), "", 1)
return c.recursiveCache(ctx, index, &c.Tree, "", 1)
}
func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, index cgobject.CommitNode, tree *Tree, treePath string, level int) error {
func (c *Commit) recursiveCache(ctx context.Context, index cgobject.CommitNode, tree *Tree, treePath string, level int) error {
if level == 0 {
return nil
}
entries, err := tree.ListEntries(ctx, gitRepo)
entries, err := tree.ListEntries()
if err != nil {
return err
}
@@ -44,18 +44,18 @@ func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, index
entryMap[entry.Name()] = entry
}
commits, err := getLastCommitForPathsByCommitNode(ctx, gitRepo, index, treePath, entryPaths)
commits, err := GetLastCommitForPaths(ctx, c.repo.LastCommitCache, index, treePath, entryPaths)
if err != nil {
return err
}
for entry := range commits {
if entryMap[entry].IsDir() {
subTree, err := tree.SubTree(ctx, gitRepo, entry)
subTree, err := tree.SubTree(entry)
if err != nil {
return err
}
if err := c.recursiveCache(ctx, gitRepo, index, subTree, entry, level-1); err != nil {
if err := c.recursiveCache(ctx, index, subTree, entry, level-1); err != nil {
return err
}
}
+9 -8
View File
@@ -10,18 +10,19 @@ import (
)
// CacheCommit will cache the commit from the gitRepository
func (c *Commit) CacheCommit(ctx context.Context, gitRepo *Repository) error {
if gitRepo.LastCommitCache == nil {
func (c *Commit) CacheCommit(ctx context.Context) error {
if c.repo.LastCommitCache == nil {
return nil
}
return c.recursiveCache(ctx, gitRepo, c.Tree(), "", 1)
return c.recursiveCache(ctx, &c.Tree, "", 1)
}
func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, tree *Tree, treePath string, level int) error {
func (c *Commit) recursiveCache(ctx context.Context, tree *Tree, treePath string, level int) error {
if level == 0 {
return nil
}
entries, err := tree.ListEntries(ctx, gitRepo)
entries, err := tree.ListEntries()
if err != nil {
return err
}
@@ -31,7 +32,7 @@ func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, tree *
entryPaths[i] = entry.Name()
}
_, err = walkGitLog(ctx, gitRepo, c, treePath, entryPaths...)
_, err = walkGitLog(ctx, c.repo, c, treePath, entryPaths...)
if err != nil {
return err
}
@@ -39,11 +40,11 @@ func (c *Commit) recursiveCache(ctx context.Context, gitRepo *Repository, tree *
for _, treeEntry := range entries {
// entryMap won't contain "" therefore skip this.
if treeEntry.IsDir() {
subTree, err := tree.SubTree(ctx, gitRepo, treeEntry.Name())
subTree, err := tree.SubTree(treeEntry.Name())
if err != nil {
return err
}
if err := c.recursiveCache(ctx, gitRepo, subTree, treeEntry.Name(), level-1); err != nil {
if err := c.recursiveCache(ctx, subTree, treeEntry.Name(), level-1); err != nil {
return err
}
}
+3 -2
View File
@@ -263,12 +263,13 @@ var walkGitLogDebugBeforeNext func() // is used to simulate various edge git pro
// walkGitLog walks the git log --name-status for the head commit in the provided treepath and files
func walkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath string, paths ...string) (map[string]string, error) {
headRef := head.ID.String()
tree, err := head.SubTree(ctx, repo, treepath)
tree, err := head.SubTree(treepath)
if err != nil {
return nil, err
}
entries, err := tree.ListEntries(ctx, repo)
entries, err := tree.ListEntries()
if err != nil {
return nil, err
}
-85
View File
@@ -3,14 +3,6 @@
package git
import (
"context"
"io"
"strings"
"gitea.dev/modules/log"
)
// NotesRef is the git ref where Gitea will look for git-notes data.
// The value ("refs/notes/commits") is the default ref used by git-notes.
const NotesRef = "refs/notes/commits"
@@ -20,80 +12,3 @@ type Note struct {
Message []byte
Commit *Commit
}
// GetNote retrieves the git-notes data for a given commit.
// FIXME: Add LastCommitCache support
func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error {
log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path)
notes, err := repo.GetCommit(NotesRef)
if err != nil {
if IsErrNotExist(err) {
return err
}
log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err)
return err
}
path := ""
tree := notes.Tree()
log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", tree.ID, commitID)
var entry *TreeEntry
originalCommitID := commitID
for len(commitID) > 2 {
entry, err = tree.GetTreeEntryByPath(ctx, repo, commitID)
if err == nil {
path += commitID
break
}
if IsErrNotExist(err) {
tree, err = tree.SubTree(ctx, repo, commitID[0:2])
path += commitID[0:2] + "/"
commitID = commitID[2:]
}
if err != nil {
// Err may have been updated by the SubTree we need to recheck if it's again an ErrNotExist
if !IsErrNotExist(err) {
log.Error("Unable to find git note corresponding to the commit %q. Error: %v", originalCommitID, err)
}
return err
}
}
blob := entry.Blob(repo)
dataRc, err := blob.DataAsync()
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
closed := false
defer func() {
if !closed {
_ = dataRc.Close()
}
}()
d, err := io.ReadAll(dataRc)
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
_ = dataRc.Close()
closed = true
note.Message = d
treePath := ""
if idx := strings.LastIndex(path, "/"); idx > -1 {
treePath = path[:idx]
path = path[idx+1:]
}
lastCommits, err := GetLastCommitForPaths(ctx, repo, notes, treePath, []string{path})
if err != nil {
log.Error("Unable to get the commit for the path %q. Error: %v", treePath, err)
return err
}
note.Commit = lastCommits[path]
return nil
}
+95
View File
@@ -0,0 +1,95 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build gogit
package git
import (
"context"
"fmt"
"io"
"strings"
"gitea.dev/modules/log"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
// GetNote retrieves the git-notes data for a given commit.
// FIXME: Add LastCommitCache support
func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error {
log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path)
notes, err := repo.GetCommit(NotesRef)
if err != nil {
if IsErrNotExist(err) {
return err
}
log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err)
return err
}
remainingCommitID := commitID
var path strings.Builder
currentTree, err := notes.Tree.gogitTreeObject()
if err != nil {
return fmt.Errorf("unable to get tree object for notes commit %q: %w", notes.ID.String(), err)
}
log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", currentTree.Entries[0].Name, commitID)
var file *object.File
for len(remainingCommitID) > 2 {
file, err = currentTree.File(remainingCommitID)
if err == nil {
path.WriteString(remainingCommitID)
break
}
if err == object.ErrFileNotFound {
currentTree, err = currentTree.Tree(remainingCommitID[0:2])
path.WriteString(remainingCommitID[0:2] + "/")
remainingCommitID = remainingCommitID[2:]
}
if err != nil {
if err == object.ErrDirectoryNotFound {
return ErrNotExist{ID: remainingCommitID, RelPath: path.String()}
}
log.Error("Unable to find git note corresponding to the commit %q. Error: %v", commitID, err)
return err
}
}
blob := file.Blob
dataRc, err := blob.Reader()
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
defer dataRc.Close()
d, err := io.ReadAll(dataRc)
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
note.Message = d
commitNodeIndex, commitGraphFile := repo.CommitNodeIndex()
if commitGraphFile != nil {
defer commitGraphFile.Close()
}
commitNode, err := commitNodeIndex.Get(plumbing.Hash(notes.ID.RawValue()))
if err != nil {
return err
}
lastCommits, err := GetLastCommitForPaths(ctx, nil, commitNode, "", []string{path.String()})
if err != nil {
log.Error("Unable to get the commit for the path %q. Error: %v", path.String(), err)
return err
}
note.Commit = lastCommits[path.String()]
return nil
}
+91
View File
@@ -0,0 +1,91 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build !gogit
package git
import (
"context"
"io"
"strings"
"gitea.dev/modules/log"
)
// GetNote retrieves the git-notes data for a given commit.
// FIXME: Add LastCommitCache support
func GetNote(ctx context.Context, repo *Repository, commitID string, note *Note) error {
log.Trace("Searching for git note corresponding to the commit %q in the repository %q", commitID, repo.Path)
notes, err := repo.GetCommit(NotesRef)
if err != nil {
if IsErrNotExist(err) {
return err
}
log.Error("Unable to get commit from ref %q. Error: %v", NotesRef, err)
return err
}
path := ""
tree := &notes.Tree
log.Trace("Found tree with ID %q while searching for git note corresponding to the commit %q", tree.ID, commitID)
var entry *TreeEntry
originalCommitID := commitID
for len(commitID) > 2 {
entry, err = tree.GetTreeEntryByPath(commitID)
if err == nil {
path += commitID
break
}
if IsErrNotExist(err) {
tree, err = tree.SubTree(commitID[0:2])
path += commitID[0:2] + "/"
commitID = commitID[2:]
}
if err != nil {
// Err may have been updated by the SubTree we need to recheck if it's again an ErrNotExist
if !IsErrNotExist(err) {
log.Error("Unable to find git note corresponding to the commit %q. Error: %v", originalCommitID, err)
}
return err
}
}
blob := entry.Blob()
dataRc, err := blob.DataAsync()
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
closed := false
defer func() {
if !closed {
_ = dataRc.Close()
}
}()
d, err := io.ReadAll(dataRc)
if err != nil {
log.Error("Unable to read blob with ID %q. Error: %v", blob.ID, err)
return err
}
_ = dataRc.Close()
closed = true
note.Message = d
treePath := ""
if idx := strings.LastIndex(path, "/"); idx > -1 {
treePath = path[:idx]
path = path[idx+1:]
}
lastCommits, err := GetLastCommitForPaths(ctx, notes, treePath, []string{path})
if err != nil {
log.Error("Unable to get the commit for the path %q. Error: %v", treePath, err)
return err
}
note.Commit = lastCommits[path]
return nil
}
+2 -2
View File
@@ -10,10 +10,10 @@ import (
"strconv"
)
// sha1Pattern can be used to determine if a string is a valid sha
// sha1Pattern can be used to determine if a string is an valid sha
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
// sha256Pattern can be used to determine if a string is a valid sha
// sha256Pattern can be used to determine if a string is an valid sha
var sha256Pattern = regexp.MustCompile(`^[0-9a-f]{4,64}$`)
type ObjectFormat interface {
+2 -2
View File
@@ -72,7 +72,7 @@ func findLFSFileFunc(repo *git.Repository, objectID git.ObjectID, revListReader
continue
case "commit":
// Read in the commit to get its tree and in case this is one of the last used commits
curCommit, err = git.CommitFromReader(git.MustIDFromString(commitID), io.LimitReader(batchReader, info.Size))
curCommit, err = git.CommitFromReader(repo, git.MustIDFromString(commitID), io.LimitReader(batchReader, info.Size))
if err != nil {
return nil, err
}
@@ -80,7 +80,7 @@ func findLFSFileFunc(repo *git.Repository, objectID git.ObjectID, revListReader
return nil, err
}
if info, _, err = batch.QueryContent(curCommit.TreeID.String()); err != nil {
if info, _, err = batch.QueryContent(curCommit.Tree.ID.String()); err != nil {
return nil, err
}
curPath = ""
+3 -2
View File
@@ -92,14 +92,15 @@ func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
}
commit := convertCommit(gogitCommit)
commit.repo = repo
tree, err := gogitCommit.Tree()
if err != nil {
return nil, err
}
commit.TreeID = ParseGogitHash(tree.Hash)
commit.Tree().resolvedGogitTreeObject = tree
commit.Tree.ID = ParseGogitHash(tree.Hash)
commit.Tree.resolvedGogitTreeObject = tree
return commit, nil
}
+1 -1
View File
@@ -88,7 +88,7 @@ func (repo *Repository) getCommitWithBatch(batch CatFileBatch, id ObjectID) (*Co
}
return repo.getCommitWithBatch(batch, tag.Object)
case "commit":
commit, err := CommitFromReader(id, io.LimitReader(rd, info.Size))
commit, err := CommitFromReader(repo, id, io.LimitReader(rd, info.Size))
if err != nil {
return nil, err
}
+1 -1
View File
@@ -149,5 +149,5 @@ func (repo *Repository) WriteTree() (*Tree, error) {
if err != nil {
return nil, err
}
return newTree(id), nil
return NewTree(repo, id), nil
}
+3 -1
View File
@@ -25,7 +25,7 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
return nil, err
}
tree := newTree(id)
tree := NewTree(repo, id)
tree.resolvedGogitTreeObject = gogitTree
return tree, nil
}
@@ -53,6 +53,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
if err != nil {
return nil, err
}
resolvedID := id
commitObject, err := repo.gogitRepo.CommitObject(plumbing.Hash(id.RawValue()))
if err == nil {
id = ParseGogitHash(commitObject.TreeHash)
@@ -61,5 +62,6 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
if err != nil {
return nil, err
}
treeObject.ResolvedID = resolvedID
return treeObject, nil
}
+8 -6
View File
@@ -23,6 +23,7 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
switch info.Type {
case "tag":
resolvedID := id
data, err := io.ReadAll(io.LimitReader(rd, info.Size))
if err != nil {
return nil, err
@@ -36,20 +37,21 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
if err != nil {
return nil, err
}
tree := commit.Tree()
return tree, nil
commit.Tree.ResolvedID = resolvedID
return &commit.Tree, nil
case "commit":
commit, err := CommitFromReader(id, io.LimitReader(rd, info.Size))
commit, err := CommitFromReader(repo, id, io.LimitReader(rd, info.Size))
if err != nil {
return nil, err
}
if _, err := rd.Discard(1); err != nil {
return nil, err
}
tree := commit.Tree()
return tree, nil
commit.Tree.ResolvedID = commit.ID
return &commit.Tree, nil
case "tree":
tree := newTree(id)
tree := NewTree(repo, id)
tree.ResolvedID = id
objectFormat, err := repo.GetObjectFormat()
if err != nil {
return nil, err
+17 -7
View File
@@ -6,22 +6,31 @@ package git
import (
"bytes"
"context"
"strings"
"gitea.dev/modules/git/gitcmd"
)
type TreeCommon struct {
ID ObjectID
ID ObjectID
ResolvedID ObjectID
repo *Repository
ptree *Tree // parent tree
}
func newTree(id ObjectID) *Tree {
return &Tree{TreeCommon: TreeCommon{ID: id}}
// NewTree create a new tree according the repository and tree id
func NewTree(repo *Repository, id ObjectID) *Tree {
return &Tree{
TreeCommon: TreeCommon{
ID: id,
repo: repo,
},
}
}
// SubTree get a subtree by the sub dir path
func (t *Tree) SubTree(ctx context.Context, gitRepo *Repository, rpath string) (*Tree, error) {
func (t *Tree) SubTree(rpath string) (*Tree, error) {
if len(rpath) == 0 {
return t, nil
}
@@ -34,15 +43,16 @@ func (t *Tree) SubTree(ctx context.Context, gitRepo *Repository, rpath string) (
te *TreeEntry
)
for _, name := range paths {
te, err = p.GetTreeEntryByPath(ctx, gitRepo, name)
te, err = p.GetTreeEntryByPath(name)
if err != nil {
return nil, err
}
g, err = gitRepo.getTree(te.ID)
g, err = t.repo.getTree(te.ID)
if err != nil {
return nil, err
}
g.ptree = p
p = g
}
return g, nil
+3 -5
View File
@@ -4,17 +4,15 @@
package git
import "context"
// GetBlobByPath get the blob object according the path
func (t *Tree) GetBlobByPath(ctx context.Context, gitRepo *Repository, relpath string) (*Blob, error) {
entry, err := t.GetTreeEntryByPath(ctx, gitRepo, relpath)
func (t *Tree) GetBlobByPath(relpath string) (*Blob, error) {
entry, err := t.GetTreeEntryByPath(relpath)
if err != nil {
return nil, err
}
if !entry.IsDir() && !entry.IsSubModule() {
return entry.Blob(gitRepo), nil
return entry.Blob(), nil
}
return nil, ErrNotExist{"", relpath}
+3 -4
View File
@@ -7,7 +7,6 @@
package git
import (
"context"
"path"
"strings"
@@ -15,7 +14,7 @@ import (
)
// GetTreeEntryByPath get the tree entries according the sub dir
func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (*TreeEntry, error) {
func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
if len(relpath) == 0 {
return &TreeEntry{
ID: t.ID,
@@ -31,7 +30,7 @@ func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relp
tree := t
for i, name := range parts {
if i == len(parts)-1 {
entries, err := tree.ListEntries(ctx, gitRepo)
entries, err := tree.ListEntries()
if err != nil {
if err == plumbing.ErrObjectNotFound {
return nil, ErrNotExist{
@@ -46,7 +45,7 @@ func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relp
}
}
} else {
tree, err = tree.SubTree(ctx, gitRepo, name)
tree, err = tree.SubTree(name)
if err != nil {
if err == plumbing.ErrObjectNotFound {
return nil, ErrNotExist{
+3 -4
View File
@@ -6,13 +6,12 @@
package git
import (
"context"
"path"
"strings"
)
// GetTreeEntryByPath get the tree entries according the sub dir
func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relpath string) (_ *TreeEntry, err error) {
func (t *Tree) GetTreeEntryByPath(relpath string) (_ *TreeEntry, err error) {
if len(relpath) == 0 {
return &TreeEntry{
ptree: t,
@@ -27,14 +26,14 @@ func (t *Tree) GetTreeEntryByPath(ctx context.Context, gitRepo *Repository, relp
tree := t
for _, name := range parts[:len(parts)-1] {
tree, err = tree.SubTree(ctx, gitRepo, name)
tree, err = tree.SubTree(name)
if err != nil {
return nil, err
}
}
name := parts[len(parts)-1]
entries, err := tree.ListEntries(ctx, gitRepo)
entries, err := tree.ListEntries()
if err != nil {
return nil, err
}
+14 -13
View File
@@ -5,7 +5,6 @@
package git
import (
"context"
"path"
"slices"
"strings"
@@ -79,18 +78,18 @@ type EntryFollowResult struct {
TargetEntry *TreeEntry
}
func EntryFollowLink(ctx context.Context, gitRepo *Repository, commit *Commit, fullPath string, te *TreeEntry) (*EntryFollowResult, error) {
func EntryFollowLink(commit *Commit, fullPath string, te *TreeEntry) (*EntryFollowResult, error) {
if !te.IsLink() {
return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q is not a symlink", fullPath)
}
// git's filename max length is 4096, hopefully a link won't be longer than multiple of that
const maxSymlinkSize = 20 * 4096
if te.Blob(gitRepo).Size() > maxSymlinkSize {
if te.Blob().Size() > maxSymlinkSize {
return nil, util.ErrorWrap(util.ErrUnprocessableContent, "%q content exceeds symlink limit", fullPath)
}
link, err := te.Blob(gitRepo).GetBlobContent(maxSymlinkSize)
link, err := te.Blob().GetBlobContent(maxSymlinkSize)
if err != nil {
return nil, err
}
@@ -100,18 +99,18 @@ func EntryFollowLink(ctx context.Context, gitRepo *Repository, commit *Commit, f
}
targetFullPath := path.Join(path.Dir(fullPath), link)
targetEntry, err := commit.GetTreeEntryByPath(ctx, gitRepo, targetFullPath)
targetEntry, err := commit.GetTreeEntryByPath(targetFullPath)
if err != nil {
return &EntryFollowResult{SymlinkContent: link}, err
}
return &EntryFollowResult{SymlinkContent: link, TargetFullPath: targetFullPath, TargetEntry: targetEntry}, nil
}
func EntryFollowLinks(ctx context.Context, gitRepo *Repository, commit *Commit, firstFullPath string, firstTreeEntry *TreeEntry, optLimit ...int) (res *EntryFollowResult, err error) {
func EntryFollowLinks(commit *Commit, firstFullPath string, firstTreeEntry *TreeEntry, optLimit ...int) (res *EntryFollowResult, err error) {
limit := util.OptionalArg(optLimit, 10)
treeEntry, fullPath := firstTreeEntry, firstFullPath
for range limit {
res, err = EntryFollowLink(ctx, gitRepo, commit, fullPath, treeEntry)
res, err = EntryFollowLink(commit, fullPath, treeEntry)
if err != nil {
return res, err
}
@@ -126,26 +125,28 @@ func EntryFollowLinks(ctx context.Context, gitRepo *Repository, commit *Commit,
return res, nil
}
func (te *TreeEntry) Tree(gitRepo *Repository) *Tree {
t, err := gitRepo.getTree(te.ID)
// returns the Tree pointed to by this TreeEntry, or nil if this is not a tree
func (te *TreeEntry) Tree() *Tree {
t, err := te.ptree.repo.getTree(te.ID)
if err != nil {
return nil
}
t.ptree = te.ptree
return t
}
// GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory )
func (te *TreeEntry) GetSubJumpablePathName(ctx context.Context, gitRepo *Repository) string {
func (te *TreeEntry) GetSubJumpablePathName() string {
if te.IsSubModule() || !te.IsDir() {
return ""
}
tree, err := te.ptree.SubTree(ctx, gitRepo, te.Name())
tree, err := te.ptree.SubTree(te.Name())
if err != nil {
return te.Name()
}
entries, _ := tree.ListEntries(ctx, gitRepo)
entries, _ := tree.ListEntries()
if len(entries) == 1 && entries[0].IsDir() {
name := entries[0].GetSubJumpablePathName(ctx, gitRepo)
name := entries[0].GetSubJumpablePathName()
if name != "" {
return te.Name() + "/" + name
}
+10 -10
View File
@@ -23,12 +23,12 @@ func TestFollowLink(t *testing.T) {
// get the symlink
{
lnkFullPath := "foo/bar/link_to_hello"
lnk, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/bar/link_to_hello")
lnk, err := commit.Tree.GetTreeEntryByPath("foo/bar/link_to_hello")
require.NoError(t, err)
assert.True(t, lnk.IsLink())
// should be able to dereference to target
res, err := EntryFollowLink(t.Context(), r, commit, lnkFullPath, lnk)
res, err := EntryFollowLink(commit, lnkFullPath, lnk)
require.NoError(t, err)
assert.Equal(t, "hello", res.TargetEntry.Name())
assert.Equal(t, "foo/nar/hello", res.TargetFullPath)
@@ -38,38 +38,38 @@ func TestFollowLink(t *testing.T) {
{
// should error when called on a normal file
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "file1.txt")
entry, err := commit.Tree.GetTreeEntryByPath("file1.txt")
require.NoError(t, err)
res, err := EntryFollowLink(t.Context(), r, commit, "file1.txt", entry)
res, err := EntryFollowLink(commit, "file1.txt", entry)
assert.ErrorIs(t, err, util.ErrUnprocessableContent)
assert.Nil(t, res)
}
{
// should error for broken links
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/broken_link")
entry, err := commit.Tree.GetTreeEntryByPath("foo/broken_link")
require.NoError(t, err)
assert.True(t, entry.IsLink())
res, err := EntryFollowLink(t.Context(), r, commit, "foo/broken_link", entry)
res, err := EntryFollowLink(commit, "foo/broken_link", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "nar/broken_link", res.SymlinkContent)
}
{
// should error for external links
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/outside_repo")
entry, err := commit.Tree.GetTreeEntryByPath("foo/outside_repo")
require.NoError(t, err)
assert.True(t, entry.IsLink())
res, err := EntryFollowLink(t.Context(), r, commit, "foo/outside_repo", entry)
res, err := EntryFollowLink(commit, "foo/outside_repo", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "../../outside_repo", res.SymlinkContent)
}
{
// testing fix for short link bug
entry, err := commit.Tree().GetTreeEntryByPath(t.Context(), r, "foo/link_short")
entry, err := commit.Tree.GetTreeEntryByPath("foo/link_short")
require.NoError(t, err)
res, err := EntryFollowLink(t.Context(), r, commit, "foo/link_short", entry)
res, err := EntryFollowLink(commit, "foo/link_short", entry)
assert.ErrorIs(t, err, util.ErrNotExist)
assert.Equal(t, "a", res.SymlinkContent)
}
+5 -7
View File
@@ -7,8 +7,6 @@
package git
import (
"context"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/object"
@@ -31,15 +29,15 @@ func (te *TreeEntry) toGogitTreeEntry() *object.TreeEntry {
}
}
// GetSize returns the size of the entry
func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 {
// Size returns the size of the entry
func (te *TreeEntry) Size() int64 {
if te.IsDir() {
return 0
} else if te.sized {
return te.size
}
ptreeGogitTree, err := te.ptree.gogitTreeObject(gitRepo)
ptreeGogitTree, err := te.ptree.gogitTreeObject()
if err != nil {
return 0
}
@@ -54,10 +52,10 @@ func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 {
}
// Blob returns the blob object the entry
func (te *TreeEntry) Blob(gitRepo *Repository) *Blob {
func (te *TreeEntry) Blob() *Blob {
return &Blob{
ID: te.ID,
repo: gitRepo,
repo: te.ptree.repo,
name: te.Name(),
}
}
+8 -11
View File
@@ -5,28 +5,25 @@
package git
import (
"context"
import "gitea.dev/modules/log"
"gitea.dev/modules/log"
)
func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 {
// Size returns the size of the entry
func (te *TreeEntry) Size() int64 {
if te.IsDir() {
return 0
} else if te.sized {
return te.size
}
batch, cancel, err := gitRepo.CatFileBatch(ctx)
batch, cancel, err := te.ptree.repo.CatFileBatch(te.ptree.repo.Ctx)
if err != nil {
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), gitRepo.Path, err)
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
return 0
}
defer cancel()
info, err := batch.QueryInfo(te.ID.String())
if err != nil {
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), gitRepo.Path, err)
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
return 0
}
@@ -36,12 +33,12 @@ func (te *TreeEntry) GetSize(ctx context.Context, gitRepo *Repository) int64 {
}
// Blob returns the blob object the entry
func (te *TreeEntry) Blob(gitRepo *Repository) *Blob {
func (te *TreeEntry) Blob() *Blob {
return &Blob{
ID: te.ID,
name: te.Name(),
size: te.size,
gotSize: te.sized,
repo: gitRepo,
repo: te.ptree.repo,
}
}
+8 -9
View File
@@ -7,7 +7,6 @@
package git
import (
"context"
"io"
"github.com/go-git/go-git/v5/plumbing"
@@ -21,9 +20,9 @@ type Tree struct {
resolvedGogitTreeObject *object.Tree
}
func (t *Tree) gogitTreeObject(gitRepo *Repository) (_ *object.Tree, err error) {
func (t *Tree) gogitTreeObject() (_ *object.Tree, err error) {
if t.resolvedGogitTreeObject == nil {
t.resolvedGogitTreeObject, err = gitRepo.gogitRepo.TreeObject(plumbing.Hash(t.ID.RawValue()))
t.resolvedGogitTreeObject, err = t.repo.gogitRepo.TreeObject(plumbing.Hash(t.ID.RawValue()))
if err != nil {
return nil, err
}
@@ -32,8 +31,8 @@ func (t *Tree) gogitTreeObject(gitRepo *Repository) (_ *object.Tree, err error)
}
// ListEntries returns all entries of current tree.
func (t *Tree) ListEntries(_ context.Context, gitRepo *Repository) (Entries, error) {
gogitTree, err := t.gogitTreeObject(gitRepo)
func (t *Tree) ListEntries() (Entries, error) {
gogitTree, err := t.gogitTreeObject()
if err != nil {
return nil, err
}
@@ -51,8 +50,8 @@ func (t *Tree) ListEntries(_ context.Context, gitRepo *Repository) (Entries, err
}
// ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees
func (t *Tree) ListEntriesRecursiveWithSize(_ context.Context, gitRepo *Repository) (entries Entries, _ error) {
gogitTree, err := t.gogitTreeObject(gitRepo)
func (t *Tree) ListEntriesRecursiveWithSize() (entries Entries, _ error) {
gogitTree, err := t.gogitTreeObject()
if err != nil {
return nil, err
}
@@ -77,6 +76,6 @@ func (t *Tree) ListEntriesRecursiveWithSize(_ context.Context, gitRepo *Reposito
}
// ListEntriesRecursiveFast is the alias of ListEntriesRecursiveWithSize for the gogit version
func (t *Tree) ListEntriesRecursiveFast(ctx context.Context, gitRepo *Repository) (Entries, error) {
return t.ListEntriesRecursiveWithSize(ctx, gitRepo)
func (t *Tree) ListEntriesRecursiveFast() (Entries, error) {
return t.ListEntriesRecursiveWithSize()
}
+39 -37
View File
@@ -6,7 +6,6 @@
package git
import (
"context"
"io"
"gitea.dev/modules/git/gitcmd"
@@ -21,47 +20,49 @@ type Tree struct {
}
// ListEntries returns all entries of current tree.
func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, error) {
func (t *Tree) ListEntries() (Entries, error) {
if t.entriesParsed {
return t.entries, nil
}
batch, cancel, err := gitRepo.CatFileBatch(ctx)
if err != nil {
return nil, err
}
defer cancel()
info, rd, err := batch.QueryContent(t.ID.String())
if err != nil {
return nil, err
}
if info.Type == "commit" {
treeID, err := ReadTreeID(rd, info.Size)
if err != nil && err != io.EOF {
return nil, err
}
info, rd, err = batch.QueryContent(treeID)
if t.repo != nil {
batch, cancel, err := t.repo.CatFileBatch(t.repo.Ctx)
if err != nil {
return nil, err
}
}
if info.Type == "tree" {
t.entries, err = catBatchParseTreeEntries(t.ID.Type(), t, rd, info.Size)
defer cancel()
info, rd, err := batch.QueryContent(t.ID.String())
if err != nil {
return nil, err
}
t.entriesParsed = true
return t.entries, nil
if info.Type == "commit" {
treeID, err := ReadTreeID(rd, info.Size)
if err != nil && err != io.EOF {
return nil, err
}
info, rd, err = batch.QueryContent(treeID)
if err != nil {
return nil, err
}
}
if info.Type == "tree" {
t.entries, err = catBatchParseTreeEntries(t.ID.Type(), t, rd, info.Size)
if err != nil {
return nil, err
}
t.entriesParsed = true
return t.entries, nil
}
// Not a tree just use ls-tree instead
if err := DiscardFull(rd, info.Size+1); err != nil {
return nil, err
}
}
// Not a tree just use ls-tree instead
if err := DiscardFull(rd, info.Size+1); err != nil {
return nil, err
}
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(gitRepo.Path).RunStdBytes(ctx)
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(t.repo.Path).RunStdBytes(t.repo.Ctx)
if runErr != nil {
if gitcmd.IsStderr(runErr, gitcmd.StderrNotValidObjectName) || gitcmd.IsStderr(runErr, gitcmd.StderrNotTreeObject) {
return nil, ErrNotExist{
@@ -71,6 +72,7 @@ func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, e
return nil, runErr
}
var err error
t.entries, err = parseTreeEntries(stdout, t)
if err == nil {
t.entriesParsed = true
@@ -81,12 +83,12 @@ func (t *Tree) ListEntries(ctx context.Context, gitRepo *Repository) (Entries, e
// listEntriesRecursive returns all entries of current tree recursively including all subtrees
// extraArgs could be "-l" to get the size, which is slower
func (t *Tree) listEntriesRecursive(ctx context.Context, gitRepo *Repository, extraArgs gitcmd.TrustedCmdArgs) (Entries, error) {
func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, error) {
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r").
AddArguments(extraArgs...).
AddDynamicArguments(t.ID.String()).
WithDir(gitRepo.Path).
RunStdBytes(ctx)
WithDir(t.repo.Path).
RunStdBytes(t.repo.Ctx)
if runErr != nil {
return nil, runErr
}
@@ -97,11 +99,11 @@ func (t *Tree) listEntriesRecursive(ctx context.Context, gitRepo *Repository, ex
}
// ListEntriesRecursiveFast returns all entries of current tree recursively including all subtrees, no size
func (t *Tree) ListEntriesRecursiveFast(ctx context.Context, gitRepo *Repository) (Entries, error) {
return t.listEntriesRecursive(ctx, gitRepo, nil)
func (t *Tree) ListEntriesRecursiveFast() (Entries, error) {
return t.listEntriesRecursive(nil)
}
// ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size
func (t *Tree) ListEntriesRecursiveWithSize(ctx context.Context, gitRepo *Repository) (Entries, error) {
return t.listEntriesRecursive(ctx, gitRepo, gitcmd.TrustedCmdArgs{"--long"})
func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) {
return t.listEntriesRecursive(gitcmd.TrustedCmdArgs{"--long"})
}
+1 -1
View File
@@ -20,7 +20,7 @@ func TestSubTree_Issue29101(t *testing.T) {
// old code could produce a different error if called multiple times
for range 10 {
_, err = commit.SubTree(t.Context(), repo, "file1.txt")
_, err = commit.SubTree("file1.txt")
assert.Error(t, err)
assert.True(t, IsErrNotExist(err))
}
+5 -5
View File
@@ -139,7 +139,7 @@ func (r *BlameReader) cleanup() {
}
// CreateBlameReader creates reader for given repository, commit and file
func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo Repository, gitRepo *git.Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) {
func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo Repository, commit *git.Commit, file string, bypassBlameIgnore bool) (rd *BlameReader, retErr error) {
defer func() {
if retErr != nil {
rd.cleanup()
@@ -158,7 +158,7 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo
rd.cleanupFuncs = append(rd.cleanupFuncs, stdoutReaderClose)
if git.DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore {
ignoreRevsFileName, ignoreRevsFileCleanup, err := tryCreateBlameIgnoreRevsFile(ctx, gitRepo, commit)
ignoreRevsFileName, ignoreRevsFileCleanup, err := tryCreateBlameIgnoreRevsFile(commit)
if err != nil && !git.IsErrNotExist(err) {
return nil, err
} else if err == nil {
@@ -180,13 +180,13 @@ func CreateBlameReader(ctx context.Context, objectFormat git.ObjectFormat, repo
return rd, nil
}
func tryCreateBlameIgnoreRevsFile(ctx context.Context, gitRepo *git.Repository, commit *git.Commit) (string, func(), error) {
entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, ".git-blame-ignore-revs")
func tryCreateBlameIgnoreRevsFile(commit *git.Commit) (string, func(), error) {
entry, err := commit.GetTreeEntryByPath(".git-blame-ignore-revs")
if err != nil {
return "", nil, err
}
r, err := entry.Blob(gitRepo).DataAsync()
r, err := entry.Blob().DataAsync()
if err != nil {
return "", nil, err
}
+2 -2
View File
@@ -49,7 +49,7 @@ func TestReadingBlameOutputSha256(t *testing.T) {
}
for _, bypass := range []bool{false, true} {
blameReader, err := CreateBlameReader(ctx, git.Sha256ObjectFormat, storage, repo, commit, "README.md", bypass)
blameReader, err := CreateBlameReader(ctx, git.Sha256ObjectFormat, storage, commit, "README.md", bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()
@@ -134,7 +134,7 @@ func TestReadingBlameOutputSha256(t *testing.T) {
for _, c := range cases {
commit, err := repo.GetCommit(c.CommitID)
assert.NoError(t, err)
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass)
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, commit, "blame.txt", c.Bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()
+2 -2
View File
@@ -43,7 +43,7 @@ func TestReadingBlameOutput(t *testing.T) {
}
for _, bypass := range []bool{false, true} {
blameReader, err := CreateBlameReader(ctx, git.Sha1ObjectFormat, storage, repo, commit, "README.md", bypass)
blameReader, err := CreateBlameReader(ctx, git.Sha1ObjectFormat, storage, commit, "README.md", bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()
@@ -129,7 +129,7 @@ func TestReadingBlameOutput(t *testing.T) {
commit, err := repo.GetCommit(c.CommitID)
assert.NoError(t, err)
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, repo, commit, "blame.txt", c.Bypass)
blameReader, err := CreateBlameReader(ctx, objectFormat, storage, commit, "blame.txt", c.Bypass)
assert.NoError(t, err)
assert.NotNil(t, blameReader)
defer blameReader.Close()
+10 -10
View File
@@ -26,7 +26,7 @@ func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (stri
}
// getRepoChanges returns changes to repo since last indexer update
func getRepoChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) {
func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) {
status, err := repo_model.GetIndexerStatus(ctx, repo, repo_model.RepoIndexerTypeCode)
if err != nil {
return nil, err
@@ -40,9 +40,9 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *g
}
if needGenesis {
return genesisChanges(ctx, repo, gitRepo, revision)
return genesisChanges(ctx, repo, revision)
}
return nonGenesisChanges(ctx, repo, gitRepo, revision)
return nonGenesisChanges(ctx, repo, revision)
}
func isIndexable(entry *git.TreeEntry) bool {
@@ -64,7 +64,7 @@ func isIndexable(entry *git.TreeEntry) bool {
}
// parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command
func parseGitLsTreeOutput(ctx context.Context, gitRepo *git.Repository, stdout []byte) ([]internal.FileUpdate, error) {
func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) {
entries, err := git.ParseTreeEntries(stdout)
if err != nil {
return nil, err
@@ -76,7 +76,7 @@ func parseGitLsTreeOutput(ctx context.Context, gitRepo *git.Repository, stdout [
updates[idxCount] = internal.FileUpdate{
Filename: entry.Name(),
BlobSha: entry.ID.String(),
Size: entry.GetSize(ctx, gitRepo),
Size: entry.Size(),
Sized: true,
}
idxCount++
@@ -86,7 +86,7 @@ func parseGitLsTreeOutput(ctx context.Context, gitRepo *git.Repository, stdout [
}
// genesisChanges get changes to add repo to the indexer for the first time
func genesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) {
func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) {
var changes internal.RepoChanges
stdout, _, runErr := gitrepo.RunCmdBytes(ctx, repo, gitcmd.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision))
if runErr != nil {
@@ -94,12 +94,12 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *g
}
var err error
changes.Updates, err = parseGitLsTreeOutput(ctx, gitRepo, stdout)
changes.Updates, err = parseGitLsTreeOutput(stdout)
return &changes, err
}
// nonGenesisChanges get changes since the previous indexer update
func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, revision string) (*internal.RepoChanges, error) {
func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) {
diffCmd := gitcmd.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision)
stdout, _, runErr := gitrepo.RunCmdString(ctx, repo, diffCmd)
if runErr != nil {
@@ -109,7 +109,7 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo
if err := (*globalIndexer.Load()).Delete(ctx, repo.ID); err != nil {
return nil, err
}
return genesisChanges(ctx, repo, gitRepo, revision)
return genesisChanges(ctx, repo, revision)
}
var changes internal.RepoChanges
@@ -124,7 +124,7 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, gitRepo
return err
}
updates, err1 := parseGitLsTreeOutput(ctx, gitRepo, lsTreeStdout)
updates, err1 := parseGitLsTreeOutput(lsTreeStdout)
if err1 != nil {
return err1
}
+1 -8
View File
@@ -13,7 +13,6 @@ import (
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/graceful"
"gitea.dev/modules/indexer"
"gitea.dev/modules/indexer/code/bleve"
@@ -74,17 +73,11 @@ func index(ctx context.Context, indexer internal.Indexer, repoID int64) error {
return nil
}
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return err
}
defer closer.Close()
sha, err := getDefaultBranchSha(ctx, repo)
if err != nil {
return err
}
changes, err := getRepoChanges(ctx, repo, gitRepo, sha)
changes, err := getRepoChanges(ctx, repo, sha)
if err != nil {
return err
} else if changes == nil {
+1 -1
View File
@@ -63,7 +63,7 @@ func (db *DBIndexer) Index(id int64) error {
}
// Calculate and save language statistics to database
stats, err := languagestats.GetLanguageStats(ctx, gitRepo, commitID)
stats, err := languagestats.GetLanguageStats(gitRepo, commitID)
if err != nil {
if !setting.IsInTesting {
log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.FullName(), err)
+2 -2
View File
@@ -167,7 +167,7 @@ func validateOptions(field *api.IssueFormField, idx int) error {
options, ok := field.Attributes["options"].([]any)
if !ok || len(options) == 0 {
return position.Errorf("'options' is required and should be an array")
return position.Errorf("'options' is required and should be a array")
}
for optIdx, option := range options {
@@ -270,7 +270,7 @@ func validateDropdownDefault(position errorPosition, attributes map[string]any)
options, ok := attributes["options"].([]any)
if !ok {
// should not happen
return position.Errorf("'options' is required and should be an array")
return position.Errorf("'options' is required and should be a array")
}
if defaultValue < 0 || defaultValue >= len(options) {
return position.Errorf("the value of 'default' is out of range")
+1 -1
View File
@@ -268,7 +268,7 @@ body:
attributes:
label: "a"
`,
wantErr: "body[0](dropdown): 'options' is required and should be an array",
wantErr: "body[0](dropdown): 'options' is required and should be a array",
},
{
name: "dropdown invalid options",
+10 -11
View File
@@ -4,7 +4,6 @@
package template
import (
"context"
"fmt"
"path"
"strconv"
@@ -42,35 +41,35 @@ func Unmarshal(filename string, content []byte) (*api.IssueTemplate, error) {
}
// UnmarshalFromEntry parses out a valid template from the blob in entry
func UnmarshalFromEntry(gitRepo *git.Repository, entry *git.TreeEntry, dir string) (*api.IssueTemplate, error) {
return unmarshalFromEntry(gitRepo, entry, path.Join(dir, entry.Name())) // Filepaths in Git are ALWAYS '/' separated do not use filepath here
func UnmarshalFromEntry(entry *git.TreeEntry, dir string) (*api.IssueTemplate, error) {
return unmarshalFromEntry(entry, path.Join(dir, entry.Name())) // Filepaths in Git are ALWAYS '/' separated do not use filepath here
}
// UnmarshalFromCommit parses out a valid template from the commit
func UnmarshalFromCommit(ctx context.Context, gitRepo *git.Repository, commit *git.Commit, filename string) (*api.IssueTemplate, error) {
entry, err := commit.GetTreeEntryByPath(ctx, gitRepo, filename)
func UnmarshalFromCommit(commit *git.Commit, filename string) (*api.IssueTemplate, error) {
entry, err := commit.GetTreeEntryByPath(filename)
if err != nil {
return nil, fmt.Errorf("get entry for %q: %w", filename, err)
}
return unmarshalFromEntry(gitRepo, entry, filename)
return unmarshalFromEntry(entry, filename)
}
// UnmarshalFromRepo parses out a valid template from the head commit of the branch
func UnmarshalFromRepo(ctx context.Context, repo *git.Repository, branch, filename string) (*api.IssueTemplate, error) {
func UnmarshalFromRepo(repo *git.Repository, branch, filename string) (*api.IssueTemplate, error) {
commit, err := repo.GetBranchCommit(branch)
if err != nil {
return nil, fmt.Errorf("get commit on branch %q: %w", branch, err)
}
return UnmarshalFromCommit(ctx, repo, commit, filename)
return UnmarshalFromCommit(commit, filename)
}
func unmarshalFromEntry(gitRepo *git.Repository, entry *git.TreeEntry, filename string) (*api.IssueTemplate, error) {
if size := entry.Blob(gitRepo).Size(); size > setting.UI.MaxDisplayFileSize {
func unmarshalFromEntry(entry *git.TreeEntry, filename string) (*api.IssueTemplate, error) {
if size := entry.Blob().Size(); size > setting.UI.MaxDisplayFileSize {
return nil, fmt.Errorf("too large: %v > MaxDisplayFileSize", size)
}
r, err := entry.Blob(gitRepo).DataAsync()
r, err := entry.Blob().DataAsync()
if err != nil {
return nil, fmt.Errorf("data async: %w", err)
}
+1 -1
View File
@@ -51,7 +51,7 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
v := &globalVarsType{}
// NOTE: All below regex matching do not perform any extra validation.
// Thus a link is produced even if the linked entity does not exist.
// While fast, this is also incorrect and leads to false positives.
// While fast, this is also incorrect and lead to false positives.
// TODO: fix invalid linking issue (update: stale TODO, what issues? maybe no TODO anymore)
// valid chars in encoded path and parameter: [-+~_%.a-zA-Z0-9/]
+1 -1
View File
@@ -54,7 +54,7 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
// Allow 'color' and 'background-color' properties for the style attribute on text elements.
policy.AllowStyles("color", "background-color").OnElements("div", "span", "p", "tr", "th", "td")
policy.AllowAttrs("src", "autoplay", "controls", "muted", "loop", "playsinline").OnElements("video")
policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
// Native support of "<picture><source media=... srcset=...><img src=...></picture>"
// ATTENTION: it only works with "auto" theme, because "media" query doesn't work with the theme chosen by end user manually.
+1 -1
View File
@@ -24,7 +24,7 @@ var (
// NOTE: All below regex matching do not perform any extra validation.
// Thus a link is produced even if the linked entity does not exist.
// While fast, this is also incorrect and leads to false positives.
// While fast, this is also incorrect and lead to false positives.
// TODO: fix invalid linking issue
// mentionPattern matches all mentions in the form of "@user" or "@org/team"
-1
View File
@@ -22,7 +22,6 @@ const (
const (
RepoPRTitleSourceFirstCommit = "first-commit"
RepoPRTitleSourceAuto = "auto"
RepoPRTitleSourceBranchName = "branch-name"
)
// ItemsPerPage maximum items per page in forks, watchers and stars of a repo
+1
View File
@@ -19,6 +19,7 @@ type CreateUserOption struct {
// The full display name of the user
FullName string `json:"full_name" binding:"MaxSize(100)"`
// required: true
// swagger:strfmt email
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
// The plain text password for the user
Password string `json:"password" binding:"MaxSize(255)"`
+1
View File
@@ -133,6 +133,7 @@ type IssueAssigneesOption struct {
// EditDeadlineOption options for creating a deadline
type EditDeadlineOption struct {
// required:true
// swagger:strfmt date-time
Deadline *time.Time `json:"due_date"`
}
+1 -1
View File
@@ -68,7 +68,7 @@ const (
type NotifySubjectType string
const (
// NotifySubjectIssue an issue is subject of a notification
// NotifySubjectIssue a issue is subject of an notification
NotifySubjectIssue NotifySubjectType = "Issue"
// NotifySubjectPull a pull is subject of an notification
NotifySubjectPull NotifySubjectType = "Pull"
+2 -2
View File
@@ -54,10 +54,10 @@ type CreateTeamOption struct {
// Whether the team has access to all repositories in the organization
IncludesAllRepositories bool `json:"includes_all_repositories"`
Permission RepoWritePermission `json:"permission"`
// example: ["repo.actions","repo.packages","repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"]
// example: ["repo.actions","repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.ext_wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"]
// Deprecated: This variable should be replaced by UnitsMap and will be dropped in later versions.
Units []string `json:"units"`
// example: {"repo.actions":"read","repo.packages":"read","repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}
// example: {"repo.actions","repo.packages","repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}
UnitsMap map[string]string `json:"units_map"`
// Whether the team can create repositories in the organization
CanCreateOrgRepo bool `json:"can_create_org_repo"`
+1
View File
@@ -1950,6 +1950,7 @@
"repo.settings.webhook_deletion": "Odstranit webový háček",
"repo.settings.webhook_deletion_desc": "Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat?",
"repo.settings.webhook_deletion_success": "Webový háček byl smazán.",
"repo.settings.webhook.test_delivery_desc_disabled": "Chcete-li tento webový háček otestovat s falešnou událostí, aktivujte ho.",
"repo.settings.webhook.request": "Požadavek",
"repo.settings.webhook.response": "Odpověď",
"repo.settings.webhook.headers": "Hlavičky",
+6 -32
View File
@@ -74,7 +74,7 @@
"forks": "Forks",
"activities": "Aktivitäten",
"pull_requests": "Pull-Requests",
"issues": "Issues",
"issues": "Probleme",
"milestones": "Meilensteine",
"ok": "OK",
"cancel": "Abbrechen",
@@ -1101,7 +1101,7 @@
"repo.migrate_items_wiki": "Wiki",
"repo.migrate_items_milestones": "Meilensteine",
"repo.migrate_items_labels": "Labels",
"repo.migrate_items_issues": "Issues",
"repo.migrate_items_issues": "Probleme",
"repo.migrate_items_pullrequests": "Pull-Requests",
"repo.migrate_items_merge_requests": "Merge-Requests",
"repo.migrate_items_releases": "Veröffentlichungen",
@@ -1178,7 +1178,7 @@
"repo.find_tag": "Tag finden",
"repo.branches": "Branches",
"repo.tags": "Tags",
"repo.issues": "Issues",
"repo.issues": "Probleme",
"repo.pulls": "Pull-Requests",
"repo.projects": "Projekte",
"repo.packages": "Pakete",
@@ -2251,6 +2251,7 @@
"repo.settings.webhook_deletion_success": "Webhook wurde entfernt.",
"repo.settings.webhook.test_delivery": "Test Push Ereignis",
"repo.settings.webhook.test_delivery_desc": "Teste diesen Webhook mit einem Fake-Push-Event.",
"repo.settings.webhook.test_delivery_desc_disabled": "Um diesen Webhook mit einem Fake-Event zu testen, aktiviere ihn.",
"repo.settings.webhook.request": "Anfrage",
"repo.settings.webhook.response": "Antwort",
"repo.settings.webhook.headers": "Kopfzeilen",
@@ -2299,7 +2300,7 @@
"repo.settings.event_repository": "Repository",
"repo.settings.event_repository_desc": "Repository erstellt oder gelöscht.",
"repo.settings.event_header_issue": "Issue Ereignisse",
"repo.settings.event_issues": "Issues",
"repo.settings.event_issues": "Probleme",
"repo.settings.event_issues_desc": "Issue geöffnet, geschlossen, wieder geöffnet, bearbeitet oder gelöscht.",
"repo.settings.event_issue_assign": "Issue zugewiesen",
"repo.settings.event_issue_assign_desc": "Issue zugewiesen oder Zuweisung entfernt.",
@@ -3103,7 +3104,7 @@
"admin.repos.owner": "Besitzer",
"admin.repos.name": "Name",
"admin.repos.private": "Privat",
"admin.repos.issues": "Issues",
"admin.repos.issues": "Probleme",
"admin.repos.size": "Größe",
"admin.repos.lfs_size": "LFS-Größe",
"admin.packages.package_manage_panel": "Paketverwaltung",
@@ -3778,7 +3779,6 @@
"actions.runs.commit": "Commit",
"actions.runs.run_details": "Run Details",
"actions.runs.workflow_file": "Workflow-Datei",
"actions.runs.workflow_file_no_permission": "Keine Berechtigung zum Anzeigen der Workflow-Datei",
"actions.runs.scheduled": "Geplant",
"actions.runs.pushed_by": "gepusht von",
"actions.runs.invalid_workflow_helper": "Die Workflow-Konfigurationsdatei ist ungültig. Bitte überprüfe Deine Konfigurationsdatei: %s",
@@ -3835,33 +3835,7 @@
"actions.workflow.scope_owner": "Besitzer",
"actions.workflow.scope_global": "Global",
"actions.workflow.required": "Erforderlich",
"actions.workflow.scoped_required_cannot_disable": "Dieser Scoped Workflow ist erforderlich und kann nicht deaktiviert werden.",
"actions.scoped_workflows": "Scoped Workflows",
"actions.scoped_workflows.desc_org": "Repositories als Scoped Workflow Quellen registrieren. Workflow-Dateien unter den Workflow-Verzeichnissen eines Quell-Repositorys laufen in jedem Projektarchiv dieser Organisation, im eigenen Kontext des Projektarchivs.",
"actions.scoped_workflows.desc_user": "Repositories als Scoped Workflow Quellen registrieren. Workflow-Dateien unter den Workflow-Verzeichnissen eines Quell-Repositorys laufen in jedem Projektarchiv dieser Organisation, im eigenen Kontext des Projektarchivs.",
"actions.scoped_workflows.desc_global": "Repositories als Scoped Workflow-Quellen registrieren. Workflow-Dateien unter den Workflow-Verzeichnissen eines Quellcode-Repositorys laufen auf jedem Projektarchiv in dieser Instanz im eigenen Kontext des Projektarchivs. Da Quellen auf Instanzenebene auf den Ereignissen jedes Projektarchivs ausgewertet werden, kann die Registrierung bei großen Instanzen Overhead hinzufügen.",
"actions.scoped_workflows.add_help": "Um Scoped Workflows aus einem Repository zu erstellen, übertrage die Workflow-Dateien unter <code>%s</code> in seinem Standard Branch, dann registrieren Sie das Projektarchiv als Quelle unten.",
"actions.scoped_workflows.security_note": "Der Workflow-Inhalt eines Quell-Repositorys wird in jedem Repository ausgeführt, für das er gilt. Die Skripte der einzelnen Schritte sowie deren Ausgabe werden in den Actions-Logs des jeweiligen Repositorys gespeichert und sind für alle sichtbar, die die Actions des konsumierenden Repositorys einsehen können. Das Registrieren eines privaten Repositorys als Quelle legt daher dessen Workflow-Logik über diese Logs offen. Registriere nur Repositorys, deren Workflow-Inhalte mit allen konsumierenden Repositorys geteilt werden dürfen. Wenn ein scoped Workflow einen wiederverwendbaren Workflow aus einem privaten Repository referenziert, stelle sicher, dass jedes konsumierende Repository darauf Lesezugriff hat andernfalls schlägt der Workflow dort fehl.",
"actions.scoped_workflows.source.add": "Quell-Repository hinzufügen",
"actions.scoped_workflows.source.add_success": "Quell-Repository hinzugefügt.",
"actions.scoped_workflows.source.remove_success": "Quell-Repository entfernt.",
"actions.scoped_workflows.source.not_found": "Repository nicht gefunden.",
"actions.scoped_workflows.required.update_success": "Erforderliche Workflows aktualisiert.",
"actions.scoped_workflows.required.label": "Workflows als erforderlich markieren (ein erforderlicher Workflow kann nicht durch Repositories deaktiviert werden):",
"actions.scoped_workflows.required.patterns": "Erforderliche Statusüberprüfungsmuster",
"actions.scoped_workflows.required.patterns_aria": "Erforderliche Statusüberprüfungsmuster für %s",
"actions.scoped_workflows.required.patterns_note": "nur erzwungen während der Workflow benötigt wird",
"actions.scoped_workflows.required.patterns_hint": "Markieren Sie den Workflow als erforderlich, um seine Statusüberprüfungsmuster zu konfigurieren.",
"actions.scoped_workflows.required.patterns_help": "Ein Statusüberprüfungsmuster (glob) pro Zeile. Ein Pull-Request kann erst zusammengeführt werden, wenn ein Status mit jedem Muster übereinstimmt. Dies wird für jeden Zielzweig erzwungen, der eine Schutzregel hat, auch für einen mit einer eigenen Statusüberprüfung; ein Zielzweig ohne Schutzregel ist nicht ausgeschaltet.",
"actions.scoped_workflows.required.patterns_empty": "Jeder benötigte Workflow benötigt mindestens ein Statusüberprüfungsmuster.",
"actions.scoped_workflows.required.missing_file": "nicht mehr im Quelltext",
"actions.scoped_workflows.required.expected_contexts": "Erwartete Statusüberprüfung (eine Prüfung, die zu einem Muster passt)",
"actions.scoped_workflows.required.no_status_contexts": "Dieser Workflow postet keine Status Checks, ihn als Anforderung zu markieren würde jede Pull Request blockieren. Deaktiviere die Anforderung.",
"actions.scoped_workflows.no_files": "Im Standard-Branch wurden keine Scoped Workflow-Dateien gefunden.",
"actions.workflow.run": "Workflow ausführen",
"actions.workflow.create_status_badge": "Status Badge erstellen",
"actions.workflow.status_badge": "Status Badge",
"actions.workflow.status_badge_url": "Badge-URL",
"actions.workflow.not_found": "Workflow '%s' wurde nicht gefunden.",
"actions.workflow.run_success": "Workflow '%s' erfolgreich ausgeführt.",
"actions.workflow.from_ref": "Nutze Workflow von",
+1
View File
@@ -1781,6 +1781,7 @@
"repo.settings.webhook_deletion": "Αφαίρεση Webhook",
"repo.settings.webhook_deletion_desc": "Η αφαίρεση ενός webhook διαγράφει τις ρυθμίσεις και το ιστορικό παραδόσεων. Συνέχεια;",
"repo.settings.webhook_deletion_success": "Το webhook έχει αφαιρεθεί.",
"repo.settings.webhook.test_delivery_desc_disabled": "Για να δοκιμάσετε αυτό το webhook με μια ψεύτικη κλήση, ενεργοποιήστε το.",
"repo.settings.webhook.request": "Αίτημα",
"repo.settings.webhook.response": "Απάντηση",
"repo.settings.webhook.headers": "Κεφαλίδες",
+1
View File
@@ -2251,6 +2251,7 @@
"repo.settings.webhook_deletion_success": "The webhook has been removed.",
"repo.settings.webhook.test_delivery": "Test Push Event",
"repo.settings.webhook.test_delivery_desc": "Test this webhook with a fake push event.",
"repo.settings.webhook.test_delivery_desc_disabled": "To test this webhook with a fake event, activate it.",
"repo.settings.webhook.request": "Request",
"repo.settings.webhook.response": "Response",
"repo.settings.webhook.headers": "Headers",
+1
View File
@@ -1753,6 +1753,7 @@
"repo.settings.webhook_deletion": "Eliminar Webhook",
"repo.settings.webhook_deletion_desc": "Eliminar un webhook borra sus ajustes e historial de entrega. ¿Continuar?",
"repo.settings.webhook_deletion_success": "El webhook ha sido eliminado.",
"repo.settings.webhook.test_delivery_desc_disabled": "Para probar este webhook con un evento falso, actívalo.",
"repo.settings.webhook.request": "Petición",
"repo.settings.webhook.response": "Respuesta",
"repo.settings.webhook.headers": "Encabezado",
+170 -214
View File
@@ -10,7 +10,7 @@
"sign_out": "Déconnexion",
"sign_up": "S'inscrire",
"link_account": "Lier un Compte",
"register": "Sinscrire",
"register": "S'inscrire",
"version": "Version",
"powered_by": "Propulsé par %s",
"page": "Page",
@@ -80,8 +80,8 @@
"cancel": "Annuler",
"retry": "Réessayez",
"rerun": "Relancer",
"rerun_all": "Relancer toutes les missions.",
"rerun_failed": "Relancer les missions échouées.",
"rerun_all": "Relancer toutes les tâches",
"rerun_failed": "Relancer les tâches échouées",
"save": "Enregistrer",
"add": "Ajouter",
"add_all": "Tout Ajouter",
@@ -165,7 +165,7 @@
"search.fuzzy_tooltip": "Inclure également les résultats proches de la recherche",
"search.words": "Mots",
"search.words_tooltip": "Inclure uniquement les résultats qui correspondent exactement aux mots recherchés",
"search.regexp": "Expression régulière",
"search.regexp": "Regexp",
"search.regexp_tooltip": "Inclure uniquement les résultats qui correspondent à lexpression régulière recherchée",
"search.exact": "Exact",
"search.exact_tooltip": "Inclure uniquement les résultats qui correspondent exactement au terme de recherche",
@@ -185,7 +185,7 @@
"search.tag_kind": "Chercher des étiquettes…",
"search.tag_tooltip": "Cherchez des étiquettes correspondantes. Utilisez « % » pour rechercher nimporte quelle suite de nombres.",
"search.commit_kind": "Chercher des révisions…",
"search.runner_kind": "Chercher des opérateurs…",
"search.runner_kind": "Chercher des exécuteurs…",
"search.no_results": "Aucun résultat correspondant trouvé.",
"search.issue_kind": "Recherche de tickets…",
"search.pull_kind": "Recherche de demandes dajouts…",
@@ -289,7 +289,7 @@
"install.smtp_port": "Port SMTP",
"install.smtp_from": "Envoyer les courriels en tant que",
"install.smtp_from_invalid": "Ladresse « Envoyer le courriel sous » est invalide",
"install.smtp_from_helper": "Adresse courriel utilisée par Gitea. Utilisez directement votre adresse ou la forme « Nom <courriel@exemple.com> ».",
"install.smtp_from_helper": "Adresse courriel utilisée par Gitea. Utilisez directement votre adresse ou la forme « Nom <email@example.com> ».",
"install.mailer_user": "Utilisateur SMTP",
"install.mailer_password": "Mot de passe SMTP",
"install.register_confirm": "Exiger la confirmation du courriel lors de linscription",
@@ -308,7 +308,7 @@
"install.require_sign_in_view_popup": "Limiter laccès aux pages aux utilisateurs connectés. Les visiteurs ne verront que les pages de connexion et dinscription.",
"install.admin_setting_desc": "La création d'un compte administrateur est facultative. Le premier utilisateur enregistré deviendra automatiquement un administrateur le cas échéant.",
"install.admin_title": "Paramètres de compte administrateur",
"install.admin_name": "Nom de ladministrateur",
"install.admin_name": "Nom dutilisateur administrateur",
"install.admin_password": "Mot de passe",
"install.confirm_password": "Confirmez le mot de passe",
"install.admin_email": "Courriel",
@@ -505,10 +505,10 @@
"mail.repo.actions.run.failed": "Lexécution a échoué",
"mail.repo.actions.run.succeeded": "Lexécution a réussi",
"mail.repo.actions.run.cancelled": "Lexécution a été annulée",
"mail.repo.actions.jobs.all_succeeded": "Tous les missions ont réussi.",
"mail.repo.actions.jobs.all_failed": "Toutes les missions ont échoué.",
"mail.repo.actions.jobs.some_not_successful": "Certaines missions nont pas réussi.",
"mail.repo.actions.jobs.all_cancelled": "Toutes les missions ont bien été annulées.",
"mail.repo.actions.jobs.all_succeeded": "Tous les tâches ont réussi.",
"mail.repo.actions.jobs.all_failed": "Toutes les tâches ont échoué.",
"mail.repo.actions.jobs.some_not_successful": "Certaines tâches nont pas réussi.",
"mail.repo.actions.jobs.all_cancelled": "Toutes les tâches ont bien été annulés.",
"mail.team_invite.subject": "%[1]s vous a invité à rejoindre lorganisation %[2]s",
"mail.team_invite.text_1": "%[1]s vous a invité à rejoindre l’équipe %[2]s dans lorganisation %[3]s.",
"mail.team_invite.text_2": "Veuillez cliquer sur le lien suivant pour rejoindre l'équipe :",
@@ -916,7 +916,7 @@
"settings.passcode_invalid": "Le mot de passe est invalide. Réessayez.",
"settings.twofa_enrolled": "Lauthentification à deux facteurs a été activée pour votre compte. Gardez votre clé de secours (%s) en lieu sûr, car il ne vous sera montré qu'une seule fois.",
"settings.twofa_failed_get_secret": "Impossible d'obtenir le secret.",
"settings.webauthn_desc": "Les clés de sécurité sont des dispositifs matériels contenant des clés cryptographiques. Elles peuvent être utilisées pour lauthentification à deux facteurs. Gitea requière le support de l<a rel=\"noreferrer\" target=\"_blank\" href=\"%s\">API Web Authentication</a>.",
"settings.webauthn_desc": "Les clés de sécurité sont des dispositifs matériels contenant des clés cryptographiques. Elles peuvent être utilisées pour lauthentification à deux facteurs. La clé de sécurité doit supporter le standard <a rel=\"noreferrer\" target=\"_blank\" href=\"%s\">WebAuthn Authenticator</a>.",
"settings.webauthn_register_key": "Ajouter une clé de sécurité",
"settings.webauthn_nickname": "Pseudonyme",
"settings.webauthn_delete_key": "Retirer la clé de sécurité",
@@ -944,8 +944,8 @@
"settings.email_notifications.disable": "Ne pas notifier",
"settings.email_notifications.submit": "Définir les préférences de courriel",
"settings.email_notifications.andyourown": "Inclure vos propres notifications",
"settings.email_notifications.actions.desc": "Notifier les procédures des dépôts configurés avec les <a target=\"_blank\" href=\"%s\">Actions Gitea</a>.",
"settings.email_notifications.actions.failure_only": "Ne notifier que procédures échouées",
"settings.email_notifications.actions.desc": "Notification pour les executions de workflows sur les dépôts configurés avec les <a target=\"_blank\" href=\"%s\">Actions Gitea</a>.",
"settings.email_notifications.actions.failure_only": "Ne notifier que pour les exécutions échouées",
"settings.visibility": "Visibilité de l'utilisateur",
"settings.visibility.public": "Publique",
"settings.visibility.public_tooltip": "Visible par tout le monde",
@@ -992,7 +992,7 @@
"repo.repo_desc": "Description",
"repo.repo_desc_helper": "Décrire brièvement votre dépôt",
"repo.repo_no_desc": "Aucune description fournie",
"repo.repo_lang": "Langues",
"repo.repo_lang": "Langue",
"repo.repo_gitignore_helper": "Sélectionner quelques .gitignore prédéfinies",
"repo.repo_gitignore_helper_desc": "De nombreux outils et compilateurs génèrent des fichiers résiduels qui n'ont pas besoin d'être supervisés par git. Composez un .gitignore à laide de cette liste des languages de programmation courants.",
"repo.issue_labels": "Jeu de labels pour les tickets",
@@ -1041,7 +1041,7 @@
"repo.stars": "Favoris",
"repo.reactions_more": "et %d de plus",
"repo.reactions": "Réactions",
"repo.unit_disabled": "Ladministrateur du site a désactivé cette section du dépôt.",
"repo.unit_disabled": "L'administrateur du site a désactivé cette section du dépôt.",
"repo.language_other": "Autre",
"repo.adopt_search": "Entrez un nom dutilisateur pour rechercher les dépôts dépossédés… (laissez vide pour tous trouver)",
"repo.adopt_preexisting_label": "Adopter les fichiers",
@@ -1106,9 +1106,9 @@
"repo.migrate_items_merge_requests": "Demandes de fusion",
"repo.migrate_items_releases": "Publications",
"repo.migrate_repo": "Migrer le dépôt",
"repo.migrate.clone_address": "Migrer depuis une URL",
"repo.migrate.clone_address": "Migrer/Cloner depuis une URL",
"repo.migrate.clone_address_desc": "LURL ou le lien « Git clone » dun dépôt existant",
"repo.migrate.github_token_desc": "Vous pouvez mettre un ou plusieurs jetons séparés par des virgules ici pour rendre la migration plus rapide et contourner la limite de débit de lAPI GitHub. Attention : abuser de cette fonctionnalité peut enfreindre la politique du fournisseur de service et entraîner un blocage de votre compte.",
"repo.migrate.github_token_desc": "Vous pouvez mettre un ou plusieurs jetons séparés par des virgules ici pour rendre la migration plus rapide et contourner la limite de débit de lAPI GitHub. ATTENTION : abuser de cette fonctionnalité peut enfreindre la politique du fournisseur de service et entraîner un blocage de votre compte.",
"repo.migrate.clone_local_path": "ou un chemin serveur local",
"repo.migrate.permission_denied": "Vous n'êtes pas autorisé à importer des dépôts locaux.",
"repo.migrate.permission_denied_blocked": "Vous ne pouvez pas importer depuis des domaines bannis, veuillez demander à votre administrateur de vérifier les paramètres ALLOWED_DOMAINS, ALLOW_LOCALNETWORKS ou BLOCKED_DOMAINS.",
@@ -1165,7 +1165,7 @@
"repo.clone_this_repo": "Cloner ce dépôt",
"repo.cite_this_repo": "Citer ce dépôt",
"repo.create_new_repo_command": "Création d'un nouveau dépôt en ligne de commande",
"repo.push_exist_repo": "Soumission dun dépôt existant par ligne de commande",
"repo.push_exist_repo": "Soumission d'un dépôt existant par ligne de commande",
"repo.empty_message": "Ce dépôt na pas de contenu.",
"repo.broken_message": "Les données git de ce dépôt ne peuvent pas être lues. Contactez l'administrateur de cette instance ou supprimez ce dépôt.",
"repo.no_branch": "Ce dépôt na aucune branche.",
@@ -1294,7 +1294,7 @@
"repo.editor.file_changed_while_editing": "Le contenu du fichier a changé depuis que vous avez commencé à éditer. <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">Cliquez ici</a> pour voir les changements ou <strong>soumettez de nouveau</strong> pour les écraser.",
"repo.editor.file_already_exists": "Un fichier nommé \"%s\" existe déjà dans ce dépôt.",
"repo.editor.commit_id_not_matching": "LID de la révision ne correspond pas à lID lorsque vous avez commencé à éditer. Faites une révision dans une branche de correctif puis fusionnez.",
"repo.editor.push_out_of_date": "Cette soumission semble être obsolète.",
"repo.editor.push_out_of_date": "Cet envoi semble être obsolète.",
"repo.editor.commit_empty_file_header": "Réviser un fichier vide",
"repo.editor.commit_empty_file_text": "Le fichier que vous allez réviser est vide. Continuer ?",
"repo.editor.no_changes_to_show": "Il ny a aucune modification à afficher.",
@@ -1307,7 +1307,7 @@
"repo.editor.upload_files_to_dir": "Téléverser les fichiers vers \"%s\"",
"repo.editor.cannot_commit_to_protected_branch": "Impossible de créer une révision sur la branche protégée \"%s\".",
"repo.editor.no_commit_to_branch": "Impossible de réviser cette branche car :",
"repo.editor.user_no_push_to_branch": "Lutilisateur ne peut pas soumettre sur la branche",
"repo.editor.user_no_push_to_branch": "L'utilisateur ne peut pas pousser vers la branche",
"repo.editor.require_signed_commit": "Cette branche nécessite une révision signée",
"repo.editor.cherry_pick": "Picorer %s vers:",
"repo.editor.revert": "Rétablir %s sur:",
@@ -1317,11 +1317,10 @@
"repo.editor.fork_create_description": "Vous ne pouvez pas modifier ce dépôt directement. Cependant, vous pouvez bifurquer ce dépôt, et créer une demande dajout avec vos contributions.",
"repo.editor.fork_edit_description": "Vous ne pouvez pas modifier ce dépôt directement. Les modifications seront écrites sur une bifurcation <b>%s</b>, vous permettant de faire une demande dajout.",
"repo.editor.fork_not_editable": "Vous avez bifurqué ce dépôt mais votre copie nest pas modifiable.",
"repo.editor.fork_failed_to_push_branch": "Impossible de soumettre la branche %s vers votre dépôt.",
"repo.editor.fork_failed_to_push_branch": "Impossible de pousser la branche %s vers votre dépôt.",
"repo.editor.fork_branch_exists": "La branche « %s » existe déjà dans votre bifurcation, veuillez choisir un nouveau nom.",
"repo.commits.desc": "Naviguer dans l'historique des modifications.",
"repo.commits.commits": "Révisions",
"repo.commits.history_enable_follow_renames": "Inclure les renommages",
"repo.commits.no_commits": "Pas de révisions en commun. \"%s\" et \"%s\" ont des historiques entièrement différents.",
"repo.commits.nothing_to_compare": "Ces révisions sont équivalentes.",
"repo.commits.search.tooltip": "Vous pouvez utiliser les mots-clés \"author:\", \"committer:\", \"after:\", ou \"before:\" pour filtrer votre recherche, ex.: \"revert author:Alice before:2019-01-13\".",
@@ -1333,8 +1332,8 @@
"repo.commits.older": "Précédemment",
"repo.commits.newer": "Récemment",
"repo.commits.signed_by": "Signé par",
"repo.commits.signed_by_untrusted_user": "Signé en dilettante par",
"repo.commits.signed_by_untrusted_user_unmatched": "Signé, sans en être lauteur, par",
"repo.commits.signed_by_untrusted_user": "Signature provenant d'un utilisateur dilletant",
"repo.commits.signed_by_untrusted_user_unmatched": "Signature discordante de l'auteur de la révision et provenant d'un utilisateur dilletant",
"repo.commits.gpg_key_id": "ID de la clé GPG",
"repo.commits.ssh_key_fingerprint": "Empreinte numérique de la clé SSH",
"repo.commits.view_path": "Voir à ce point de l'historique",
@@ -1622,7 +1621,7 @@
"repo.issues.lock.notice_2": "- Vous et les autres collaborateurs ayant accès à ce dépôt peuvent toujours laisser des commentaires que dautres peuvent voir.",
"repo.issues.lock.notice_3": "- Vous pouvez toujours déverrouiller ce ticket à l'avenir.",
"repo.issues.unlock.notice_1": "- Tout le monde sera de nouveau en mesure de commenter ce ticket.",
"repo.issues.unlock.notice_2": "- Vous pouvez toujours verrouiller ce ticket à lavenir.",
"repo.issues.unlock.notice_2": "- Vous pouvez toujours verrouiller ce ticket à l'avenir.",
"repo.issues.lock.reason": "Motif de verrouillage",
"repo.issues.lock.title": "Verrouiller la conversation sur ce ticket.",
"repo.issues.unlock.title": "Déverrouiller la conversation sur ce ticket.",
@@ -1818,9 +1817,9 @@
"repo.pulls.is_checking": "Recherche de conflits de fusion…",
"repo.pulls.is_ancestor": "Cette branche est déjà présente dans la branche ciblée. Il n'y a rien à fusionner.",
"repo.pulls.is_empty": "Les changements sur cette branche sont déjà sur la branche cible. Cette révision sera vide.",
"repo.pulls.required_status_check_failed": "Certains signaux requis n'ont pas réussi.",
"repo.pulls.required_status_check_missing": "Certains signaux requis sont manquants.",
"repo.pulls.required_status_check_administrator": "En tant quadministrateur, vous pouvez fusionner cette demande dajout.",
"repo.pulls.required_status_check_failed": "Certains contrôles requis n'ont pas réussi.",
"repo.pulls.required_status_check_missing": "Certains contrôles requis sont manquants.",
"repo.pulls.required_status_check_administrator": "En tant qu'administrateur, vous pouvez toujours fusionner cette requête de pull.",
"repo.pulls.required_status_check_bypass_allowlist": "Vous êtes autorisé à contourner les règles de protection pour cette fusion.",
"repo.pulls.blocked_by_approvals": "Cette demande dajout nest pas suffisamment approuvée. %d approbations obtenues sur %d.",
"repo.pulls.blocked_by_approvals_whitelisted": "Cette demande dajout na pas encore assez dapprobations. %d sur %d approbations de la part des utilisateurs ou équipes sur la liste autorisée.",
@@ -1844,7 +1843,7 @@
"repo.pulls.no_merge_desc": "Cette demande dajout ne peut être fusionnée car toutes les options de fusion du dépôt sont désactivées.",
"repo.pulls.no_merge_helper": "Activez des options de fusion dans les paramètres du dépôt ou fusionnez la demande manuellement.",
"repo.pulls.no_merge_wip": "Cette demande dajout ne peut pas être fusionnée car elle est marquée en chantier.",
"repo.pulls.no_merge_not_ready": "Cette demande dajout nest pas prête à être fusionnée, vérifiez les évaluations et les signaux.",
"repo.pulls.no_merge_not_ready": "Cette demande dajout nest pas prête à être fusionnée, vérifiez les évaluations et le contrôle qualité.",
"repo.pulls.no_merge_access": "Vous n'êtes pas autorisé⋅e à fusionner cette demande d'ajout.",
"repo.pulls.merge_pull_request": "Créer une révision de fusion",
"repo.pulls.rebase_merge_pull_request": "Rebaser puis rattraper",
@@ -1868,19 +1867,19 @@
"repo.pulls.push_rejected_summary": "Message de rejet complet",
"repo.pulls.push_rejected_no_message": "Échec de la fusion : la soumission a été rejetée sans raison. Contrôler les déclencheurs Git pour ce dépôt.",
"repo.pulls.open_unmerged_pull_exists": "Vous ne pouvez pas rouvrir ceci car la demande dajout #%d, en attente, a des propriétés identiques.",
"repo.pulls.status_checking": "Certains signaux sont en attente",
"repo.pulls.status_checks_success": "Tous les signaux ont réussi",
"repo.pulls.status_checks_warning": "Des signaux déclarent des avertissements",
"repo.pulls.status_checks_failure_required": "Des signaux requis ont échoués",
"repo.pulls.status_checks_failure_optional": "Des signaux optionnels ont échoués",
"repo.pulls.status_checks_error": "Des signaux rapportent des erreurs",
"repo.pulls.status_checking": "Certains contrôles sont en attente",
"repo.pulls.status_checks_success": "Tous les contrôles ont réussi",
"repo.pulls.status_checks_warning": "Quelques vérifications ont signalé des avertissements",
"repo.pulls.status_checks_failure_required": "Des vérifications obligatoires ont échoué",
"repo.pulls.status_checks_failure_optional": "Des vérifications optionnelles ont échoué",
"repo.pulls.status_checks_error": "Quelques vérifications ont signalé des erreurs",
"repo.pulls.status_checks_requested": "Requis",
"repo.pulls.status_checks_details": "Détails",
"repo.pulls.status_checks_hide_all": "Masquer les signaux",
"repo.pulls.status_checks_hide_all": "Masquer toutes les vérifications",
"repo.pulls.status_checks_show_all": "Afficher toutes les vérifications",
"repo.pulls.status_checks_approve_all": "Approuver toutes les procédures",
"repo.pulls.status_checks_need_approvals": "%d procédure(s) en attente dapprobation",
"repo.pulls.status_checks_need_approvals_helper": "Cette procédure ne sexecutera quaprès lapprobation par le mainteneur du dépôt.",
"repo.pulls.status_checks_approve_all": "Accepter tous les flux de travail",
"repo.pulls.status_checks_need_approvals": "%d flux de travail en attente dapprobation",
"repo.pulls.status_checks_need_approvals_helper": "Ce flux de travail ne sexécutera quaprès lapprobation par le mainteneur du dépôt.",
"repo.pulls.update_branch": "Actualiser la branche par fusion",
"repo.pulls.update_branch_rebase": "Actualiser la branche par rebasage",
"repo.pulls.update_branch_success": "La mise à jour de la branche a réussi",
@@ -1964,8 +1963,8 @@
"repo.ext_wiki.desc": "Lier un wiki externe.",
"repo.wiki": "Wiki",
"repo.wiki.welcome": "Bienvenue sur le Wiki.",
"repo.wiki.welcome_desc": "Le wiki vous permet de rédiger et partager de la documentation avec des collaborateurs.",
"repo.wiki.desc": "Rédiger et partager de la documentation avec des collaborateurs.",
"repo.wiki.welcome_desc": "Le wiki vous permet d'écrire ou de partager de la documentation avec vos collaborateurs.",
"repo.wiki.desc": "Écrire et partager de la documentation avec vos collaborateurs.",
"repo.wiki.create_first_page": "Créer la première page",
"repo.wiki.page": "Page",
"repo.wiki.filter_page": "Filtrer la page",
@@ -1987,7 +1986,7 @@
"repo.wiki.pages": "Pages",
"repo.wiki.last_updated": "Dernière mise à jour: %s",
"repo.wiki.page_name_desc": "Entrez un nom pour cette page Wiki. Certains noms spéciaux sont « Home », « _Sidebar » et « _Footer ».",
"repo.wiki.original_git_entry_tooltip": "Voir le fichier Git original au lieu dutiliser un lien convivial.",
"repo.wiki.original_git_entry_tooltip": "Voir le fichier Git original au lieu d'utiliser un lien convivial.",
"repo.activity": "Activité",
"repo.activity.navbar.pulse": "Impulsion",
"repo.activity.navbar.code_frequency": "Fréquence du code",
@@ -2067,23 +2066,23 @@
"repo.settings.public_access": "Accès public",
"repo.settings.public_access_desc": "Configurer les permissions des visiteurs publics remplaçant les valeurs par défaut de ce dépôt.",
"repo.settings.public_access.docs.not_set": "Non défini : ne donne aucune permission supplémentaire. Les règles du dépôt et les permissions des utilisateurs font foi.",
"repo.settings.public_access.docs.anonymous_read": "Accès anonyme : les visiteurs non connectés peuvent consulter cette section.",
"repo.settings.public_access.docs.everyone_read": "Consultation collective : tous les utilisateurs connectés peuvent consulter cette section. Pour les Tickets et les Demandes dajouts, cela permet aussi aux utilisateurs connectés den créer.",
"repo.settings.public_access.docs.everyone_write": "Participation collective : tous les utilisateurs connectés peuvent participer à la section. Seul le Wiki supporte cette permission.",
"repo.settings.public_access.docs.anonymous_read": "Lecture anonyme : les utilisateurs qui ne sont pas connectés peuvent consulter la ressource.",
"repo.settings.public_access.docs.everyone_read": "Consultation collective : tous les utilisateurs connectés peuvent consulter la ressource. Mettre les tickets et demandes dajouts en accès public signifie que les utilisateurs connectés peuvent en créer.",
"repo.settings.public_access.docs.everyone_write": "Participation collective : tous les utilisateurs connectés ont la permission d’écrire sur la ressource. Seule le Wiki supporte cette autorisation.",
"repo.settings.collaboration": "Collaborateurs",
"repo.settings.collaboration.admin": "Administrateur",
"repo.settings.collaboration.write": "Écriture",
"repo.settings.collaboration.read": "Lecture",
"repo.settings.collaboration.owner": "Propriétaire",
"repo.settings.collaboration.undefined": "Indéfini",
"repo.settings.collaboration.per_unit": "Permissions de section",
"repo.settings.collaboration.per_unit": "Permissions de ressource",
"repo.settings.hooks": "Déclencheurs web",
"repo.settings.githooks": "Déclencheurs Git",
"repo.settings.basic_settings": "Paramètres de base",
"repo.settings.mirror_settings": "Réglages Miroir",
"repo.settings.mirror_settings.docs": "Configurez votre dépôt pour synchroniser automatiquement les révisions, étiquettes et branches avec un autre dépôt.",
"repo.settings.mirror_settings.docs.disabled_pull_mirror.instructions": "Configurez votre projet pour soumettre automatiquement les révisions, étiquettes et branches vers un autre dépôt. Les miroirs ont été désactivés par ladministrateur de votre site.",
"repo.settings.mirror_settings.docs.disabled_push_mirror.instructions": "Configurez votre projet pour synchroniser automatiquement les révisions, étiquettes et branches dun autre dépôt.",
"repo.settings.mirror_settings.docs.disabled_pull_mirror.instructions": "Configurez votre projet pour soumettre automatiquement les révisions, étiquettes et branches vers un autre dépôt. Les miroirs ont été désactivés par l'administrateur de votre site.",
"repo.settings.mirror_settings.docs.disabled_push_mirror.instructions": "Configurez votre projet pour synchroniser automatiquement les révisions, étiquettes et branches d'un autre dépôt.",
"repo.settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning": "Pour linstant, cela ne peut être fait que dans le menu « Nouvelle migration ». Pour plus dinformations, veuillez consulter :",
"repo.settings.mirror_settings.docs.disabled_push_mirror.info": "Les miroirs push ont été désactivés par ladministrateur de votre site.",
"repo.settings.mirror_settings.docs.no_new_mirrors": "Votre dépôt se synchronise avec un dépôt distant. Vous ne pouvez pas créer de nouveaux miroirs pour le moment.",
@@ -2202,13 +2201,11 @@
"repo.settings.trust_model.default.desc": "Utiliser le niveau de confiance configuré par défaut pour cette instance Gitea.",
"repo.settings.trust_model.collaborator": "Collaborateur",
"repo.settings.trust_model.collaborator.long": "Collaborateur : ne se fier qu'aux signatures des collaborateurs du dépôt",
"repo.settings.trust_model.collaborator.desc": "Une révision est réputée authentifiée si elle est signée par un collaborateur du dépôt. Si elle nest que signée par son auteur, elle sera réputée dilettante, et discordante sinon.",
"repo.settings.trust_model.collaborator.desc": "La signature dune révision est dite « fiable » si elle correspond à un collaborateur du dépôt, indépendamment de son auteur. À défaut, si elle correspond à lauteur de la révision, elle sera « dilettante », et « discordante » sinon.",
"repo.settings.trust_model.committer": "Auteur",
"repo.settings.trust_model.committer.long": "Auteur : ne se fier quaux signatures des auteurs des révisions (mimique GitHub en forçant Gitea à co-signer ses révisions).",
"repo.settings.trust_model.committer.desc": "Une révision est réputée authentifiée si elle est signée par son auteur, et discordante si les signatures diffèrent. Cela force Gitea à signer ses propres révisions en créditant lauteur original en pied de révision \"Co-authored-by:\" et \"Co-committed-by:\". La clé par défaut de Gitea doit correspondre à celle dun utilisateur existant.",
"repo.settings.trust_model.collaboratorcommitter": "Collaborateur et Auteur",
"repo.settings.trust_model.collaboratorcommitter.long": "Collaborateur et Auteur : ne se fier qu'aux signatures des auteurs collaborant au dépôt",
"repo.settings.trust_model.collaboratorcommitter.desc": "Une révision est réputée authentifiée si est elle signée par son auteur étant lui-même collaborateur du dépôt. Si elle nest que signée par son auteur, elle sera réputée dilettante, et discordante sinon. Cela force Gitea à signer ses propres révisions en créditant lauteur original en pied de révision \"Co-authored-by:\". La clé par défaut de Gitea doit correspondre à celle dun utilisateur existant.",
"repo.settings.wiki_delete": "Supprimer les données du Wiki",
"repo.settings.wiki_delete_desc": "Supprimer les données du wiki d'un dépôt est permanent. Cette action est irréversible.",
"repo.settings.wiki_delete_notices_1": "- Ceci supprimera de manière permanente et désactivera le wiki de dépôt pour %s.",
@@ -2221,7 +2218,7 @@
"repo.settings.delete_notices_fork_1": "- Les bifurcations de ce dépôt deviendront indépendants après suppression.",
"repo.settings.deletion_success": "Le dépôt a été supprimé.",
"repo.settings.update_settings_success": "Les options du dépôt ont été mises à jour.",
"repo.settings.update_settings_no_unit": "Si vous désactivez toutes les sections du dépôt, vous ne pourrez gère plus lutiliser.",
"repo.settings.update_settings_no_unit": "Impossible de désactiver toutes les fonctionnalités d'un dépôt. Vous ne pourrez gère l'utiliser.",
"repo.settings.confirm_delete": "Supprimer le dépôt",
"repo.settings.add_collaborator": "Ajouter un collaborateur",
"repo.settings.add_collaborator_success": "Le collaborateur a été ajouté.",
@@ -2251,6 +2248,7 @@
"repo.settings.webhook_deletion_success": "Le webhook a été supprimé.",
"repo.settings.webhook.test_delivery": "Tester lenvoi",
"repo.settings.webhook.test_delivery_desc": "Testez ce webhook avec un faux événement.",
"repo.settings.webhook.test_delivery_desc_disabled": "Pour tester ce webhook avec un faux événement, activez-le.",
"repo.settings.webhook.request": "Requête",
"repo.settings.webhook.response": "Réponse",
"repo.settings.webhook.headers": "Entêtes",
@@ -2294,7 +2292,7 @@
"repo.settings.event_release": "Publication",
"repo.settings.event_release_desc": "Publication publiée, mise à jour ou supprimée.",
"repo.settings.event_push": "Soumission",
"repo.settings.event_force_push": "Soumission forcée",
"repo.settings.event_force_push": "Poussée forcée",
"repo.settings.event_push_desc": "Soumission Git.",
"repo.settings.event_repository": "Dépôt",
"repo.settings.event_repository_desc": "Dépôt créé ou supprimé.",
@@ -2328,11 +2326,11 @@
"repo.settings.event_pull_request_review_request_desc": "Création ou suppresion de demandes d’évaluation.",
"repo.settings.event_pull_request_approvals": "Approbations de demande d'ajout",
"repo.settings.event_pull_request_merge": "Fusion de demande d'ajout",
"repo.settings.event_header_workflow": "Événements de procédure",
"repo.settings.event_workflow_run": "Exécution de procédure",
"repo.settings.event_workflow_run_desc": "Exécution des procédures des Actions Gitea ajoutée, en attente, en cours ou terminées.",
"repo.settings.event_workflow_job": "Missions de la procédure",
"repo.settings.event_workflow_job_desc": "Les missions ajoutées, en attente, en cours ou terminées des Actions Gitea.",
"repo.settings.event_header_workflow": "Événements du flux de travail",
"repo.settings.event_workflow_run": "Exécution du flux de travail",
"repo.settings.event_workflow_run_desc": "Tâche du flux de travail Gitea Actions ajoutée, en attente, en cours ou terminée.",
"repo.settings.event_workflow_job": "Tâches du flux de travail",
"repo.settings.event_workflow_job_desc": "Tâches du flux de travail Gitea Actions en file dattente, en attente, en cours ou terminée.",
"repo.settings.event_package": "Paquet",
"repo.settings.event_package_desc": "Paquet créé ou supprimé.",
"repo.settings.branch_filter": "Filtre de branche",
@@ -2392,44 +2390,44 @@
"repo.settings.protected_branch_can_push_no": "Vous ne pouvez pas soumettre",
"repo.settings.branch_protection": "Paramètres de protection de branches pour la branche <b>%s</b>",
"repo.settings.protect_this_branch": "Activer la protection de branche",
"repo.settings.protect_this_branch_desc": "Empêche la suppression et Git de soumettre et fusionner sur cette branche.",
"repo.settings.protect_this_branch_desc": "Empêche les suppressions et limite les poussées et fusions sur cette branche.",
"repo.settings.protect_disable_push": "Désactiver la soumission",
"repo.settings.protect_disable_push_desc": "Aucune soumission ne sera possible sur cette branche.",
"repo.settings.protect_disable_force_push": "Désactiver la soumission forcée",
"repo.settings.protect_disable_force_push_desc": "Aucune soumission forcée ne sera possible sur cette branche.",
"repo.settings.protect_disable_force_push": "Désactiver les poussés forcées",
"repo.settings.protect_disable_force_push_desc": "Aucune poussée forcée ne sera possible sur cette branche.",
"repo.settings.protect_enable_push": "Activer la soumission",
"repo.settings.protect_enable_push_desc": "Toute personne ayant un accès en écriture sera autorisée à soumettre sur cette branche (sans forcer).",
"repo.settings.protect_enable_force_push_all": "Activer la soumission forcée",
"repo.settings.protect_enable_force_push_all_desc": "Toute personne pouvant soumettre pourra forcer sur cette branche.",
"repo.settings.protect_enable_force_push_all": "Activer les poussées forcées",
"repo.settings.protect_enable_force_push_all_desc": "Toute personne pouvant pousser pourra forcer sur cette branche.",
"repo.settings.protect_enable_force_push_allowlist": "Soumission forcée sur autorisation uniquement",
"repo.settings.protect_enable_force_push_allowlist_desc": "Seuls les utilisateurs ou équipes autorisés ayants un droit de soumission seront autorisés à soumettre en force sur cette branche.",
"repo.settings.protect_enable_force_push_allowlist_desc": "Seuls les utilisateurs ou équipes autorisés ayants un droit de pousser seront autorisés à pousser en force sur cette branche.",
"repo.settings.protect_enable_merge": "Activer la fusion",
"repo.settings.protect_enable_merge_desc": "Toute personne ayant un accès en écriture sera autorisée à fusionner les demandes d'ajout dans cette branche.",
"repo.settings.protect_whitelist_committers": "Soumissions sur autorisation uniquement",
"repo.settings.protect_whitelist_committers_desc": "Seuls les utilisateurs ou les équipes autorisés pourront soumettre sur cette branche (sans forcer).",
"repo.settings.protect_whitelist_committers_desc": "Seuls les utilisateurs ou les équipes autorisés pourront pousser sur cette branche (sans forcer).",
"repo.settings.protect_whitelist_deploy_keys": "Clés de déploiement pouvant écrire autorisées à pousser.",
"repo.settings.protect_whitelist_users": "Utilisateurs autorisés à pousser :",
"repo.settings.protect_whitelist_teams": "Équipes autorisées à pousser :",
"repo.settings.protect_force_push_allowlist_users": "Utilisateurs autorisés à soumettre en force :",
"repo.settings.protect_force_push_allowlist_teams": "Équipes autorisées à soumettre en force :",
"repo.settings.protect_force_push_allowlist_deploy_keys": "Inclure aussi les clés de déploiement autorisées à soumettre.",
"repo.settings.protect_force_push_allowlist_users": "Utilisateurs autorisés à pousser en force :",
"repo.settings.protect_force_push_allowlist_teams": "Équipes autorisées à pousser en force :",
"repo.settings.protect_force_push_allowlist_deploy_keys": "Clés de déploiement pouvant pousser autorisées à pousser en force.",
"repo.settings.protect_merge_whitelist_committers": "Fusion sur autorisation uniquement",
"repo.settings.protect_merge_whitelist_committers_desc": "Nautoriser que les utilisateurs et les équipes listés à appliquer les demandes de fusion sur cette branche.",
"repo.settings.protect_merge_whitelist_users": "Utilisateurs autorisés à fusionner :",
"repo.settings.protect_merge_whitelist_teams": "Équipes autorisées à fusionner :",
"repo.settings.protect_bypass_allowlist": "Contourner la protection de la branche",
"repo.settings.protect_enable_bypass_allowlist": "Autoriser des utilisateurs et des équipes à contourner les restrictions de branche",
"repo.settings.protect_enable_bypass_allowlist_desc": "Les utilisateurs ou équipes autorisés peuvent fusionner ou soumettre des changements nonobstant les règles dapprobations, de vérifications des signaux et les protections de fichiers.",
"repo.settings.protect_enable_bypass_allowlist_desc": "Les utilisateurs ou équipes autorisés peuvent fusionner ou pousser des changements nonobstant les règles dapprobations, de vérifications de statut et les protections fichiers.",
"repo.settings.protect_bypass_allowlist_users": "Liste dutilisateurs autorisés à contourner les protections :",
"repo.settings.protect_bypass_allowlist_teams": "Liste d’équipes autorisées à contourner les protections :",
"repo.settings.protect_check_status_contexts": "Activer les signaux",
"repo.settings.protect_status_check_patterns": "Motifs de signal :",
"repo.settings.protect_status_check_patterns_desc": "Entrez des motifs pour spécifier quelles signaux doivent réussir avant que des branches puissent être fusionnées. Un motif par ligne. Un motif ne peut être vide.",
"repo.settings.protect_check_status_contexts_desc": "Exiger la réussite des signaux avant de fusionner. Quand activé, une branche protégée ne peux accepter que des soumissions ou des fusions ayant le status « succès ». Lorsqu'il ny a pas de contexte, la dernière révision fait foi.",
"repo.settings.protect_check_status_contexts_list": "Signaux trouvés au cours de la semaine passée pour ce dépôt",
"repo.settings.protect_check_status_contexts": "Activer le Contrôle Qualité",
"repo.settings.protect_status_check_patterns": "Motifs de vérification des statuts :",
"repo.settings.protect_status_check_patterns_desc": "Entrez des motifs pour spécifier quelles vérifications doivent réussir avant que des branches puissent être fusionnées. Un motif par ligne. Un motif ne peut être vide.",
"repo.settings.protect_check_status_contexts_desc": "Exiger le status « succès » avant de fusionner. Quand activée, une branche protégée ne peux accepter que des soumissions ou des fusions ayant le status « succès ». Lorsqu'il ny a pas de contexte, la dernière révision fait foi.",
"repo.settings.protect_check_status_contexts_list": "Contrôles qualité trouvés au cours de la semaine dernière pour ce dépôt",
"repo.settings.protect_status_check_matched": "Correspondant",
"repo.settings.protect_invalid_status_check_pattern": "Motif de signal invalide : « %s ».",
"repo.settings.protect_no_valid_status_check_patterns": "Aucun motif de signaux valide.",
"repo.settings.protect_invalid_status_check_pattern": "Motif de vérification des statuts incorrect : « %s ».",
"repo.settings.protect_no_valid_status_check_patterns": "Aucun motif de vérification des statuts valide.",
"repo.settings.protect_required_approvals": "Minimum d'approbations requis :",
"repo.settings.protect_required_approvals_desc": "Permet de fusionner les demandes dajout lorsque suffisamment d’évaluation sont positives.",
"repo.settings.protect_approvals_whitelist_enabled": "Restreindre les approbations sur autorisation uniquement",
@@ -2455,15 +2453,15 @@
"repo.settings.remove_protected_branch_success": "La règle de protection de branche \"%s\" a été retirée.",
"repo.settings.remove_protected_branch_failed": "Impossible de retirer la règle de protection de branche \"%s\".",
"repo.settings.protected_branch_deletion": "Désactiver la protection de branche",
"repo.settings.protected_branch_deletion_desc": "Désactiver la protection de branche permet aux utilisateurs ayant accès en écriture de soumettre des modifications sur la branche. Continuer ?",
"repo.settings.protected_branch_deletion_desc": "Désactiver la protection de branche permet aux utilisateurs ayant accès en écriture de pousser des modifications sur la branche. Continuer ?",
"repo.settings.block_rejected_reviews": "Bloquer la fusion en cas d’évaluations négatives",
"repo.settings.block_rejected_reviews_desc": "La fusion ne sera pas possible lorsque des modifications sont demandées par les évaluateurs officiels, même s'il y a suffisamment dapprobations.",
"repo.settings.block_on_official_review_requests": "Bloquer la fusion en cas de demande d’évaluation officielle",
"repo.settings.block_on_official_review_requests_desc": "La fusion ne sera pas possible tant quelle aura des demandes d’évaluations officielles, même s'il y a suffisamment dapprobations.",
"repo.settings.block_outdated_branch": "Bloquer la fusion si la demande d'ajout est obsolète",
"repo.settings.block_outdated_branch_desc": "La fusion ne sera pas possible lorsque la branche principale est derrière la branche de base.",
"repo.settings.block_admin_merge_override": "Inclure les administrateurs dans lapplication de la règle",
"repo.settings.block_admin_merge_override_desc": "Les administrateurs sont également soumis aux règles de protection des branches. En revanche, les utilisateurs et équipes qui figurent sur la liste dérogatoire y sont exemptés.",
"repo.settings.block_admin_merge_override": "Les administrateurs doivent respecter les règles de protection des branches",
"repo.settings.block_admin_merge_override_desc": "Les administrateurs sont également soumis aux règles de protection des branches. En activant la liste dautorisation de contournement, les utilisateurs et équipes qui y figurent peuvent toujours contourner ces règles.",
"repo.settings.default_branch_desc": "Sélectionnez une branche par défaut pour les révisions.",
"repo.settings.default_target_branch_desc": "Les demandes dajout peuvent utiliser une branche cible différente, telle que définie dans la section Demandes dajouts des Paramètres avancés du dépôt.",
"repo.settings.merge_style_desc": "Styles de fusion",
@@ -2598,9 +2596,7 @@
"repo.diff.review.reject": "Demander des changements",
"repo.diff.review.self_approve": "Les auteurs dune demande dajout ne peuvent pas approuver leur propre demande dajout",
"repo.diff.committed_by": "révisé par",
"repo.diff.coauthored_by": "coécrit par",
"repo.commits.avatar_stack_and": "et",
"repo.commits.avatar_stack_people": "%d personne(s)",
"repo.diff.protected": "Protégé",
"repo.diff.image.side_by_side": "Côte à côte",
"repo.diff.image.swipe": "Glisser",
@@ -2720,7 +2716,7 @@
"repo.error.csv.too_large": "Impossible de visualiser le fichier car il est trop volumineux.",
"repo.error.csv.unexpected": "Impossible de visualiser ce fichier car il contient un caractère inattendu ligne %d, colonne %d.",
"repo.error.csv.invalid_field_count": "Impossible de visualiser ce fichier car il contient un nombre de champs incorrect à la ligne %d.",
"repo.error.broken_git_hook": "Les crochets Git de ce dépôt semblent cassés. Veuillez suivre la <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a> pour les corriger, puis soummettre des révisions pour actualiser le statut.",
"repo.error.broken_git_hook": "Les crochets Git de ce dépôt semblent cassés. Veuillez suivre la <a target=\"_blank\" rel=\"noreferrer\" href=\"%s\">documentation</a> pour les corriger, puis pousser des révisions pour actualiser le statut.",
"graphs.component_loading": "Chargement de %s…",
"graphs.component_loading_failed": "Impossible de charger %s.",
"graphs.component_loading_info": "Ça prend son temps…",
@@ -2728,7 +2724,6 @@
"graphs.code_frequency.what": "fréquence du code",
"graphs.contributors.what": "contributions",
"graphs.recent_commits.what": "révisions récentes",
"graphs.chart_zoom_hint": "Glisser : zoom, Maj + Glisser : pano, Double-clic : recentrer",
"org.org_name_holder": "Nom de l'organisation",
"org.org_full_name_holder": "Nom complet de l'organisation",
"org.org_name_helper": "Le nom de l'organisation doit être court et mémorable.",
@@ -2750,8 +2745,8 @@
"org.team_desc_helper": "Décrire le but ou le rôle de l’équipe.",
"org.team_access_desc": "Accès au dépôt",
"org.team_permission_desc": "Autorisation",
"org.team_unit_desc": "Permettre laccès aux sections du dépôt",
"org.team_unit_disabled": "(Désactivée)",
"org.team_unit_desc": "Permettre laccès aux Sections du dépôt",
"org.team_unit_disabled": "(Désactivé)",
"org.form.name_been_taken": "Le nom dorganisation « %s » a déjà été utilisé.",
"org.form.name_reserved": "Le nom d'organisation \"%s\" est réservé.",
"org.form.name_pattern_not_allowed": "Le motif « %s » n'est pas autorisé dans un nom d'organisation.",
@@ -2819,15 +2814,15 @@
"org.teams.can_create_org_repo": "Créer des dépôts",
"org.teams.can_create_org_repo_helper": "Les membres peuvent créer de nouveaux dépôts dans l'organisation. Le créateur obtiendra l'accès administrateur au nouveau dépôt.",
"org.teams.none_access": "Aucun accès",
"org.teams.none_access_helper": "Les membres ne peuvent ni consulter ni participer à cette section. Ne sapplique pas pour les dépôts publics.",
"org.teams.none_access_helper": "Les membres ne peuvent voir ou faire quoi que ce soit sur cette partie. Sans effet pour les dépôts publics.",
"org.teams.general_access": "Accès général",
"org.teams.general_access_helper": "Les permissions des membres seront déterminées par la table des permissions ci-dessous.",
"org.teams.read_access": "Lecture",
"org.teams.read_access_helper": "Les membres peuvent voir et cloner les dépôts de léquipe.",
"org.teams.read_access_helper": "Les membres peuvent voir et cloner les dépôts de l'équipe.",
"org.teams.write_access": "Écriture",
"org.teams.write_access_helper": "Les membres peuvent consulter et soumettre sur les dépôts de léquipe.",
"org.teams.write_access_helper": "Les membres peuvent voir et pousser dans les dépôts de l'équipe.",
"org.teams.admin_access": "Accès Administrateur",
"org.teams.admin_access_helper": "Les membres peuvent extraire et soumettre les dépôts de léquipe et y ajouter des collaborateurs.",
"org.teams.admin_access_helper": "Les membres peuvent tirer et pousser des modifications vers les dépôts de l'équipe, et y ajouter des collaborateurs.",
"org.teams.no_desc": "Aucune description",
"org.teams.settings": "Paramètres",
"org.teams.owners_permission_desc": "Les propriétaires ont un accès complet à <strong>tous les dépôts</strong> et disposent <strong> d'un accès administrateur</strong> de l'organisation.",
@@ -2844,8 +2839,8 @@
"org.teams.delete_team_desc": "Supprimer une équipe supprime l'accès aux dépôts à ses membres. Continuer ?",
"org.teams.delete_team_success": "L’équipe a été supprimée.",
"org.teams.read_permission_desc": "Cette équipe permet l'accès en <strong>lecture</strong> : les membres peuvent voir et dupliquer ses dépôts.",
"org.teams.write_permission_desc": "Cette équipe accorde un accès en <strong>écriture</strong> : les membres peuvent participer à ses dépôts.",
"org.teams.admin_permission_desc": "Cette équipe accorde un accès <strong>administrateur</strong> : les membres peuvent consulter, participer et ajouter des collaborateurs à ses dépôts.",
"org.teams.write_permission_desc": "Cette équipe permet l'accès en <strong>écriture</strong> : les membres peuvent participer à ses dépôts.",
"org.teams.admin_permission_desc": "Cette équipe permet l'accès <strong>administrateur</strong> : les membres peuvent voir, participer et ajouter des collaborateurs à ses dépôts.",
"org.teams.create_repo_permission_desc": "De plus, cette équipe accorde la permission <strong>Créer un dépôt</strong> : les membres peuvent créer de nouveaux dépôts dans l'organisation.",
"org.teams.repositories": "Dépôts de l'Équipe",
"org.teams.remove_all_repos_title": "Supprimer tous les dépôts de l'équipe",
@@ -2862,8 +2857,8 @@
"org.teams.all_repositories": "Tous les dépôts",
"org.teams.all_repositories_helper": "L'équipe a accès à tous les dépôts. Sélectionner ceci <strong>ajoutera tous les dépôts existants</strong> à l'équipe.",
"org.teams.all_repositories_read_permission_desc": "Cette équipe accorde l'accès <strong>en lecture</strong> à <strong>tous les dépôts</strong> : les membres peuvent voir et cloner les dépôts.",
"org.teams.all_repositories_write_permission_desc": "Cette équipe accorde un accès <strong>en écriture</strong> à <strong>tous les dépôts</strong> : les membres peuvent participer aux dépôts.",
"org.teams.all_repositories_admin_permission_desc": "Cette équipe accorde un accès <strong>administrateur</strong> à <strong>tous les dépôts</strong> : les membres peuvent consulter, participer et ajouter des collaborateurs aux dépôts.",
"org.teams.all_repositories_write_permission_desc": "Cette équipe accorde l'accès <strong>en écriture</strong> à <strong>tous les dépôts</strong> : les membres peuvent lire et écrire dans les dépôts.",
"org.teams.all_repositories_admin_permission_desc": "Cette équipe accorde l'accès <strong>administrateur</strong> à <strong>tous les dépôts</strong> : les membres peuvent lire, écrire dans et ajouter des collaborateurs aux dépôts.",
"org.teams.visibility": "Visibilité",
"org.teams.visibility_private": "Privé",
"org.teams.visibility_private_helper": "Visible uniquement aux membres de l’équipe et aux propriétaires de lorganisation.",
@@ -3013,7 +3008,7 @@
"admin.dashboard.gc_lfs": "Purger les métaobjets LFS",
"admin.dashboard.stop_zombie_tasks": "Arrêter les tâches zombies",
"admin.dashboard.stop_endless_tasks": "Arrêter les tâches interminables",
"admin.dashboard.cancel_abandoned_jobs": "Annuler les actions des missions abandonnées",
"admin.dashboard.cancel_abandoned_jobs": "Annuler les actions des tâches abandonnés",
"admin.dashboard.start_schedule_tasks": "Démarrer les tâches planifiées",
"admin.dashboard.sync_branch.started": "Début de la synchronisation des branches",
"admin.dashboard.sync_tag.started": "Synchronisation des étiquettes",
@@ -3450,7 +3445,7 @@
"action.merge_pull_request": "a fusionné la demande dajout <a href=\"%[1]s\">%[3]s#%[2]s</a>",
"action.auto_merge_pull_request": "a fusionné automatiquement la demande dajout <a href=\"%[1]s\">%[3]s#%[2]s</a>",
"action.transfer_repo": "a transféré le dépôt <code>%s</code> vers <a href=\"%s\">%s</a>",
"action.push_tag": "a soumis l’étiquette <a href=\"%[2]s\">%[3]s</a> de <a href=\"%[1]s\">%[4]s</a>",
"action.push_tag": "a poussé l’étiquette <a href=\"%[2]s\">%[3]s</a> de <a href=\"%[1]s\">%[4]s</a>",
"action.delete_tag": "a supprimé l’étiquette %[2]s de <a href=\"%[1]s\">%[3]s</a>",
"action.delete_branch": "a supprimé la branche %[2]s de <a href=\"%[1]s\">%[3]s</a>",
"action.compare_branch": "Comparer",
@@ -3510,9 +3505,9 @@
"gpg.error.failed_retrieval_gpg_keys": "Impossible de récupérer la clé liée au compte de l'auteur",
"gpg.error.probable_bad_signature": "AVERTISSEMENT ! Bien quil y ait une clé avec cet ID dans la base de données, elle ne vérifie pas cette révision ! Cette révision est SUSPECTE.",
"gpg.error.probable_bad_default_signature": "AVERTISSEMENT ! Bien que la clé par défaut ait cet ID, elle ne vérifie pas cette révision ! Cette révision est SUSPECTE.",
"units.unit": "Section",
"units.error.no_unit_allowed_repo": "Vous nêtes pas autorisé à accéder à quelconque section de ce dépôt.",
"units.error.unit_not_allowed": "Vous nêtes pas autorisé à accéder à cette section du dépôt.",
"units.unit": "Ressource",
"units.error.no_unit_allowed_repo": "Vous n'êtes pas autorisé à accéder à n'importe quelle section de ce dépôt.",
"units.error.unit_not_allowed": "Vous n'êtes pas autorisé à accéder à cette section du dépôt.",
"packages.title": "Paquets",
"packages.desc": "Gérer les paquets du dépôt.",
"packages.empty": "Il n'y pas de paquet pour le moment.",
@@ -3726,66 +3721,64 @@
"actions.status.cancelling": "Annulation",
"actions.status.skipped": "Ignoré",
"actions.status.blocked": "Bloqué",
"actions.runners": "Opérateurs",
"actions.runners.runner_manage_panel": "Gestion des opérateurs",
"actions.runners.new": "Créer un nouvel opérateur",
"actions.runners.new_notice": "Comment démarrer un opérateur",
"actions.runners": "Exécuteurs",
"actions.runners.runner_manage_panel": "Gestion des exécuteurs",
"actions.runners.new": "Créer un nouvel exécuteur",
"actions.runners.new_notice": "Comment démarrer un exécuteur",
"actions.runners.status": "Statut",
"actions.runners.id": "ID",
"actions.runners.name": "Nom",
"actions.runners.owner_type": "Type",
"actions.runners.availability": "Activation",
"actions.runners.availability": "Disponibilité",
"actions.runners.description": "Description",
"actions.runners.labels": "Libels",
"actions.runners.labels": "Labels",
"actions.runners.last_online": "Dernière fois en ligne",
"actions.runners.runner_title": "Opérateur",
"actions.runners.task_list": "Tâches récentes de cet opérateur",
"actions.runners.runner_title": "Exécuteur",
"actions.runners.task_list": "Tâches récentes sur cet exécuteur",
"actions.runners.task_list.no_tasks": "Il n'y a pas de tâche ici.",
"actions.runners.task_list.run": "Exécution",
"actions.runners.task_list.run": "Exécuter",
"actions.runners.task_list.status": "Statut",
"actions.runners.task_list.repository": "Dépôt",
"actions.runners.task_list.commit": "Révision",
"actions.runners.task_list.done_at": "Fait à",
"actions.runners.edit_runner": "Éditer lopérateur",
"actions.runners.edit_runner": "Éditer l'Exécuteur",
"actions.runners.update_runner": "Appliquer les modifications",
"actions.runners.update_runner_success": "Opérateur mis à jour avec succès",
"actions.runners.update_runner_failed": "Impossible d'actualiser lopérateur",
"actions.runners.enable_runner": "Activer cet opérateur",
"actions.runners.enable_runner_success": "Opérateur activé avec succès",
"actions.runners.enable_runner_failed": "Impossible dactiver lopérateur",
"actions.runners.disable_runner": "Désactiver cet opérateur",
"actions.runners.disable_runner_success": "Opérateur désactivé avec succès",
"actions.runners.disable_runner_failed": "Impossible de désactiver lopérateur",
"actions.runners.delete_runner": "Supprimer cet opérateur",
"actions.runners.delete_runner_success": "Opérateur supprimé avec succès",
"actions.runners.delete_runner_failed": "Impossible de supprimer lopérateur",
"actions.runners.delete_runner_header": "Êtes-vous sûr de vouloir supprimer cet opérateur ?",
"actions.runners.delete_runner_notice": "Si des tâches sont en cours de réalisation par cet opérateur, elles seront abandonnées et marquées en échec, pouvant également entrainer l’échec des procédures appelantes.",
"actions.runners.none": "Aucun opérateur disponible",
"actions.runners.update_runner_success": "Exécuteur mis à jour avec succès",
"actions.runners.update_runner_failed": "Impossible d'actualiser l'Exécuteur",
"actions.runners.enable_runner": "Activer cet exécuteur",
"actions.runners.enable_runner_success": "Exécuteur activé avec succès",
"actions.runners.enable_runner_failed": "Impossible dactiver lexécuteur",
"actions.runners.disable_runner": "Désactiver cet exécuteur",
"actions.runners.disable_runner_success": "Exécuteur désactivé avec succès",
"actions.runners.disable_runner_failed": "Impossible de désactiver lexécuteur",
"actions.runners.delete_runner": "Supprimer cet exécuteur",
"actions.runners.delete_runner_success": "Exécuteur supprimé avec succès",
"actions.runners.delete_runner_failed": "Impossible de supprimer l'Exécuteur",
"actions.runners.delete_runner_header": "Êtes-vous sûr de vouloir supprimer cet exécuteur ?",
"actions.runners.delete_runner_notice": "Si une tâche est en cours sur cet exécuteur, elle sera terminée et marquée comme échouée. Cela risque dinterrompre le flux de travail.",
"actions.runners.none": "Aucun exécuteur disponible",
"actions.runners.status.unspecified": "Inconnu",
"actions.runners.status.idle": "Disponible",
"actions.runners.status.active": "Occupé",
"actions.runners.status.idle": "Inactif",
"actions.runners.status.active": "Actif",
"actions.runners.status.offline": "Hors-ligne",
"actions.runners.version": "Version",
"actions.runners.reset_registration_token": "Réinitialiser le jeton denregistrement",
"actions.runners.reset_registration_token": "Réinitialiser le jeton d'enregistrement",
"actions.runners.reset_registration_token_confirm": "Voulez-vous révoquer le jeton actuel et en générer un nouveau ?",
"actions.runners.reset_registration_token_success": "Le jeton dinscription de lopérateur a été réinitialisé avec succès",
"actions.runs.all_workflows": "Toutes les procédures",
"actions.runs.other_workflows": "Autres procédures",
"actions.runs.other_workflows_tooltip": "Les procédures qui ont été exécutées dans ce dépôt mais qui nexistent pas dans la branche par défaut.",
"actions.runs.workflow_run_count_1": "%d exécution de procédure",
"actions.runs.workflow_run_count_n": "%d exécutions de procédure",
"actions.runners.reset_registration_token_success": "Le jeton dinscription de lexécuteur a été réinitialisé avec succès",
"actions.runs.all_workflows": "Tous les flux de travail",
"actions.runs.other_workflows": "Autres flux de travail",
"actions.runs.other_workflows_tooltip": "Les flux de travail qui ont été exécutés dans ce dépôt mais qui nexistent pas dans la branche par défaut.",
"actions.runs.workflow_run_count_1": "%d exécution du workflow",
"actions.runs.workflow_run_count_n": "%d exécutions du workflow",
"actions.runs.commit": "Révision",
"actions.runs.run_details": "Détails de lexécution",
"actions.runs.workflow_file": "Déclaration de la procédure",
"actions.runs.workflow_file_no_permission": "Pas de permission pour voir la procédure",
"actions.runs.workflow_file": "Fichier de flux de travail",
"actions.runs.scheduled": "Planifié",
"actions.runs.pushed_by": "soumis par",
"actions.runs.invalid_workflow_helper": "La déclaration de la procédure est invalide. Veuillez vérifier le fichier « %s ».",
"actions.runs.no_matching_online_runner_helper": "Aucun opérateur disponible correspondant au libellé « %s »",
"actions.runs.no_job_without_needs": "La procédure doit contenir au moins une mission sans dépendance.",
"actions.runs.no_job": "La procédure doit contenir au moins une mission.",
"actions.runs.invalid_reusable_workflow_uses": "Clause \"uses\" invalide dans la procédure : %s",
"actions.runs.invalid_workflow_helper": "La configuration du flux de travail est invalide. Veuillez vérifier votre fichier %s.",
"actions.runs.no_matching_online_runner_helper": "Aucun exécuteur en ligne correspondant au libellé %s",
"actions.runs.no_job_without_needs": "Le flux de travail doit contenir au moins une tâche sans dépendance.",
"actions.runs.no_job": "Le flux de travail doit contenir au moins une tâche",
"actions.runs.actor": "Acteur",
"actions.runs.status": "Statut",
"actions.runs.actors_no_select": "Tous les acteurs",
@@ -3793,82 +3786,45 @@
"actions.runs.branch": "Branche",
"actions.runs.branches_no_select": "Toutes les branches",
"actions.runs.no_results": "Aucun résultat correspondant.",
"actions.runs.no_workflows": "Il ny a pas de procédure ici.",
"actions.runs.no_workflows.quick_start": "Vous découvrez les Actions Gitea ? Consultez <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">le didacticiel</a>.",
"actions.runs.no_workflows.documentation": "Pour plus dinformations sur les Actions Gitea, voir <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">la documentation</a>.",
"actions.runs.no_runs": "Cette procédure na pas encore été exécutée.",
"actions.runs.no_workflows": "Il n'y a pas encore de workflows.",
"actions.runs.no_workflows.quick_start": "Vous découvrez les Actions Gitea ? Consultez <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">le didacticiel</a>.",
"actions.runs.no_workflows.documentation": "Pour plus dinformations sur les actions Gitea, voir <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">la documentation</a>.",
"actions.runs.no_runs": "Le flux de travail n'a pas encore d'exécution.",
"actions.runs.empty_commit_message": "(message de révision vide)",
"actions.runs.expire_log_message": "Les journaux ont été supprimés car ils étaient trop anciens.",
"actions.runs.delete": "Effacer lexecution de cette procédure",
"actions.runs.cancel": "Annuler lexécution de cette procédure",
"actions.runs.delete": "Supprimer cette exécution",
"actions.runs.cancel": "Annuler lexécution du flux",
"actions.runs.delete.description": "Êtes-vous sûr de vouloir supprimer définitivement cette exécution ? Cette action ne peut pas être annulée.",
"actions.runs.not_done": "Cette procédure nest pas terminée.",
"actions.runs.view_workflow_file": "Voir la déclaration de la procédure",
"actions.runs.not_done": "Cette exécution du flux de travail nest pas terminée.",
"actions.runs.view_workflow_file": "Voir le fichier du flux de travail",
"actions.runs.summary": "Résumé",
"actions.runs.all_jobs": "Toutes les missions",
"actions.runs.job_summaries": "Résumé des missions",
"actions.runs.expand_caller_jobs": "Afficher les missions de cette procédure réutilisable",
"actions.runs.collapse_caller_jobs": "Masquer les missions de cette procédure réutilisable",
"actions.runs.all_jobs": "Toutes les tâches",
"actions.runs.attempt": "Tentative",
"actions.runs.latest": "Dernière",
"actions.runs.latest_attempt": "Dernière tentative",
"actions.runs.triggered_via": "Déclenché via %s",
"actions.runs.rerun_triggered": "Relance enclenchée",
"actions.runs.back_to_pull_request": "Retour à la demande dajout",
"actions.runs.back_to_workflow": "Retour à la procédure",
"actions.runs.total_duration": "Durée totale :",
"actions.runs.workflow_dependencies": "Dépendances de la procédure",
"actions.runs.graph_jobs_count_1": "%d mission",
"actions.runs.graph_jobs_count_n": "%d missions",
"actions.runs.graph_dependencies_count_1": "%d dépendance",
"actions.runs.graph_dependencies_count_n": "%d dépendances",
"actions.runs.graph_success_rate": "%s succès",
"actions.runs.graph_zoom_in": "Zoomer (Ctrl/⌘ + défilement)",
"actions.runs.graph_zoom_max": "Déjà à 100%",
"actions.runs.graph_zoom_max": "Déjà zoomé à 100%",
"actions.runs.graph_zoom_out": "Dézoomer (Ctrl/⌘ + défilement)",
"actions.runs.graph_reset_view": "Rétablir",
"actions.workflow.disable": "Désactiver la procédure",
"actions.workflow.disable_success": "La procédure « %s » a bien été désactivée.",
"actions.workflow.enable": "Activer la procédure",
"actions.workflow.enable_success": "La procédure « %s » a bien été activée.",
"actions.workflow.disabled": "La procédure est désactivée.",
"actions.workflow.disable": "Désactiver le flux de travail",
"actions.workflow.disable_success": "Le flux de travail « %s » a bien été désactivé.",
"actions.workflow.enable": "Activer le flux de travail",
"actions.workflow.enable_success": "Le flux de travail « %s » a bien été activé.",
"actions.workflow.disabled": "Le flux de travail est désactivé.",
"actions.workflow.scope_owner": "Propriétaire",
"actions.workflow.scope_global": "Global",
"actions.workflow.required": "Requis",
"actions.workflow.scoped_required_cannot_disable": "Cette procédure transversale est requise.",
"actions.scoped_workflows": "Procédures transversales",
"actions.scoped_workflows.desc_org": "Enrôlez un dépôt afin de rendre ses procédures accessibles à votre organisation. Toutes les procédures de la branche principale de ce dépôt seront ainsi exécutées dans chaque dépôt de cette organisation, comme si elles y avaient été créées.",
"actions.scoped_workflows.desc_user": "Enrôlez un dépôt afin de rendre ses procédures accessibles à votre compte. Toutes les procédures de la branche principale de ce dépôt seront ainsi exécutées dans chaque dépôt que vous possédez, comme si elles y avaient été créées.",
"actions.scoped_workflows.desc_global": "Enrôlez un dépôt afin de rendre ses procédures accessibles à lensemble du serveur. Toutes les procédures de la branche principale de ce dépôt seront ainsi exécutées dans chaque dépôt, comme si elles y avaient été créées. Sur un serveur volumineux, ces procédures peuvent lourdement solliciter les ressources du système.",
"actions.scoped_workflows.add_help": "Pour rendre des procédures transversales, soumettez leurs déclarations dans le dossier <code>%s</code> sur la branche par défaut de ce dépôt, puis enrôlez celui-ci ci-dessous.",
"actions.scoped_workflows.security_note": "Parce quune procédure transversale opère sur dautres dépôts que le sien, ses extrants sont journalisés sur ces dépôts et sont donc consultable par leurs utilisateurs. Ainsi, une procédure issue dun dépôt privé peut-être reconstruit à partir des journaux qu'elle produit. Exposer une procédure transversale peut donc compromètre la confidentialité de son dépôt hôte. Si une procédure transversale référence une autre procédure issue dun dépôt privé, assurez-vous que les dépôts affectés puissent également s'y référer, sans quoi ces procédures échoueront.",
"actions.scoped_workflows.source.add": "Enrôler un dépôt",
"actions.scoped_workflows.source.add_success": "Dépôt enrôlé.",
"actions.scoped_workflows.source.remove_success": "Dépôt retiré.",
"actions.scoped_workflows.source.not_found": "Dépôt introuvable.",
"actions.scoped_workflows.required.update_success": "Procédure requise mise à jour.",
"actions.scoped_workflows.required.label": "Marquer les procédures comme requises (elles ne pourront être désactivés depuis un dépôt) :",
"actions.scoped_workflows.required.patterns": "Motifs de signal requis",
"actions.scoped_workflows.required.patterns_aria": "Motifs de signal requis pour « %s »",
"actions.scoped_workflows.required.patterns_note": "est uniquement appliqué lorsque la procédure est requise",
"actions.scoped_workflows.required.patterns_hint": "Marquez la procédure comme requise pour configurer ses motifs de signal.",
"actions.scoped_workflows.required.patterns_help": "Un motif de signal par ligne. Une demande dajout concernée peut être fusionnée à condition quau moins un signal par motif ait réussi. Cela est imposé pour toutes les branches affectées ayant des règles de protections (même désactivées), mais pas les branches sans protections.",
"actions.scoped_workflows.required.patterns_empty": "Chaque procédure requise nécessite au moins un motif de signal.",
"actions.scoped_workflows.required.missing_file": "Le fichier nest plus dans le dépôt enrôlé.",
"actions.scoped_workflows.required.expected_contexts": "Signaux attendus (un signal qui correspond au motif est marqué)",
"actions.scoped_workflows.required.no_status_contexts": "Comme cette procédure ne publie aucun signal, la rentre obligatoire empêchera toutes demandes dajouts concernées d’être fusionnées. Préférez laisser cette procédure facultative.",
"actions.scoped_workflows.no_files": "Aucune procédure transversale n'a été trouvé dans la branche par défaut.",
"actions.workflow.run": "Réaliser la procédure",
"actions.workflow.create_status_badge": "Créer un badge d’état",
"actions.workflow.status_badge": "Badge d’état",
"actions.workflow.status_badge_url": "URL du badge",
"actions.workflow.not_found": "La procédure « %s » est introuvable.",
"actions.workflow.run_success": "La procédure « %s » est accomplie.",
"actions.workflow.from_ref": "Utiliser la procédure depuis",
"actions.workflow.has_workflow_dispatch": "Cette procédure dispose dun déclencheur workflow_dispatch.",
"actions.workflow.has_no_workflow_dispatch": "La procédure « %s » na pas de déclencheur workflow_dispatch.",
"actions.need_approval_desc": "Une approbation est nécessaire pour exécuter les procédures dune demande dajout de bifurcation.",
"actions.approve_all_success": "Toutes les procédures ont été approuvées.",
"actions.workflow.run": "Exécuter le flux de travail",
"actions.workflow.not_found": "Flux de travail « %s » introuvable.",
"actions.workflow.run_success": "Le flux de travail « %s » sest correctement exécuté.",
"actions.workflow.from_ref": "Utiliser le flux de travail depuis",
"actions.workflow.has_workflow_dispatch": "Ce flux de travail a un déclencheur d’événement workflow_dispatch.",
"actions.workflow.has_no_workflow_dispatch": "Le flux de travail %s na pas de déclencheur d’événement workflow_dispatch.",
"actions.need_approval_desc": "Besoin dapprobation pour exécuter des flux de travail pour une demande dajout de bifurcation.",
"actions.approve_all_success": "Tous les flux de travail ont été acceptés.",
"actions.variables": "Variables",
"actions.variables.management": "Gestion des variables",
"actions.variables.creation": "Ajouter une variable",
@@ -3889,7 +3845,7 @@
"actions.general": "Général",
"actions.general.enable_actions": "Activer les actions",
"actions.general.collaborative_owners_management": "Gestion des collaborateurs",
"actions.general.collaborative_owners_management_help": "Un collaborateur est un utilisateur ou une organisation dont le dépôt privé peut accéder aux actions et procédures de ce dépôt.",
"actions.general.collaborative_owners_management_help": "Un collaborateur est un utilisateur ou une organisation dont le dépôt privé peut accéder aux actions et flux de travail de ce dépôt.",
"actions.general.add_collaborative_owner": "Ajouter un collaborateur",
"actions.general.collaborative_owner_not_exist": "Le collaborateur nexiste pas.",
"actions.general.remove_collaborative_owner": "Supprimer le collaborateur",
@@ -3907,21 +3863,21 @@
"git.filemode.symbolic_link": "Lien symbolique",
"git.filemode.submodule": "Sous-module",
"org.repos.none": "Aucun dépôt.",
"actions.general.permissions": "Permissions intégrées au jeton dActions",
"actions.general.token_permissions.mode": "Régime de restriction par défaut",
"actions.general.token_permissions.mode.desc": "Lorsquune procédure ne contient pas de restriction, elle est alors restreinte au régime par défaut du dépôt.",
"actions.general.token_permissions.mode.permissive": "Régime permissif",
"actions.general.token_permissions.mode.permissive.desc": "Les missions peuvent consulter et modifier ce dépôt.",
"actions.general.token_permissions.mode.restricted": "Régime limitant",
"actions.general.token_permissions.mode.restricted.desc": "Les missions ne peuvent que consulter le contenu (code et publications) de ce dépôt.",
"actions.general.token_permissions.override_owner": "Outrepasser la configuration du propriétaire",
"actions.general.token_permissions.override_owner_desc": "Si actif, ce dépôt donnera ses propres restrictions à la place de celles du propriétaire (utilisateur ou organisation).",
"actions.general.token_permissions.maximum": "Restrictions affinées",
"actions.general.token_permissions.maximum.description": "Pour protéger plus finement le dépôt, les restrictions appliquées aux missions peuvent être définies pour chaque section individuellement.",
"actions.general.token_permissions.fork_pr_note": "Lorsquune mission est initiée par une demande dajout depuis une bifurcation, ses restrictions effectives ne peuvent passer la lecture seule.",
"actions.general.token_permissions.customize_max_permissions": "Affiner les restrictions",
"actions.general.permissions": "Permissions du jeton des actions",
"actions.general.token_permissions.mode": "Permissions par défaut du jeton",
"actions.general.token_permissions.mode.desc": "Une tâche dActions utilisera les permissions par défaut si aucune nest déclarée dans le fichier du flux de travail.",
"actions.general.token_permissions.mode.permissive": "Permissif",
"actions.general.token_permissions.mode.permissive.desc": "Permissions en lecture et écriture sur le dépôt de la tâche.",
"actions.general.token_permissions.mode.restricted": "Restreint",
"actions.general.token_permissions.mode.restricted.desc": "Permissions en lecture seule pour le contenu (code, publications) sur le dépôt de la tâche.",
"actions.general.token_permissions.override_owner": "Écraser la configuration faite par le propriétaire",
"actions.general.token_permissions.override_owner_desc": "Si actif, ce dépôt utilisera sa propre configuration pour les actions au lieu de respecter celle du propriétaire (utilisateur ou organisation).",
"actions.general.token_permissions.maximum": "Permissions maximales du jeton",
"actions.general.token_permissions.maximum.description": "Les permissions effectives de la tâche des actions seront limitées par les permissions maximales.",
"actions.general.token_permissions.fork_pr_note": "Si une tâche est démarrée par une demande de fusion depuis une bifurcation, ses permissions effectives ne dépasseront pas les permissions en lecture-seule.",
"actions.general.token_permissions.customize_max_permissions": "Personnaliser les permissions maximales",
"actions.general.cross_repo": "Accès inter-dépôt",
"actions.general.cross_repo_desc": "Permet aux dépôts de ce propriétaire de consulter (en lecture seule) les dépôts listés ci-dessous pendant lexécution des missions dActions (nécessite un jeton GITEA_TOKEN).",
"actions.general.cross_repo_desc": "Permet aux dépôts sélectionnés d’être visible en lecture-seule par tous les dépôts de ce propriétaire à laide de GITEA_TOKEN lors de lexécution des tâches dactions.",
"actions.general.cross_repo_selected": "Dépôts sélectionnés",
"actions.general.cross_repo_target_repos": "Dépôts cibles",
"actions.general.cross_repo_add": "Ajouter un dépôt cible"
+1 -27
View File
@@ -2251,6 +2251,7 @@
"repo.settings.webhook_deletion_success": "Tá an Crúca Gréasán bainte amach.",
"repo.settings.webhook.test_delivery": "Imeacht Brúigh Tástála",
"repo.settings.webhook.test_delivery_desc": "Déan tástáil ar an webhook seo le teagmhas brú bréige.",
"repo.settings.webhook.test_delivery_desc_disabled": "Chun an Crúca Gréasán seo a thástáil le himeacht bhréige, gníomhachtaigh é.",
"repo.settings.webhook.request": "Iarratas",
"repo.settings.webhook.response": "Freagra",
"repo.settings.webhook.headers": "Ceanntásca",
@@ -3778,7 +3779,6 @@
"actions.runs.commit": "Tiomantas",
"actions.runs.run_details": "Sonraí Rith",
"actions.runs.workflow_file": "Comhad sreabhadh oibre",
"actions.runs.workflow_file_no_permission": "Gan cead chun an comhad sreafa oibre a fheiceáil",
"actions.runs.scheduled": "Sceidealaithe",
"actions.runs.pushed_by": "bhrú ag",
"actions.runs.invalid_workflow_helper": "Tá comhad cumraíochta sreabhadh oibre nebhailí. Seiceáil do chomhad cumraithe le do thoil: %s",
@@ -3835,33 +3835,7 @@
"actions.workflow.scope_owner": "Úinéir",
"actions.workflow.scope_global": "Domhanda",
"actions.workflow.required": "Riachtanach",
"actions.workflow.scoped_required_cannot_disable": "Tá an sreabhadh oibre raonaithe seo riachtanach agus ní féidir é a dhíchumasú.",
"actions.scoped_workflows": "Sreafaí Oibre Raonaithe",
"actions.scoped_workflows.desc_org": "Cláraigh stórtha mar fhoinsí sreabhadh oibre raonta. Ritheann comhaid sreabhadh oibre faoi eolairí sreabhadh oibre raonta brainse réamhshocraithe stórtha foinse ar gach stórtha den eagraíocht seo, i gcomhthéacs an stórtha sin féin.",
"actions.scoped_workflows.desc_user": "Cláraigh stórtha mar fhoinsí sreabhadh oibre raonta. Ritheann comhaid sreabhadh oibre faoi eolairí sreabhadh oibre raonta brainse réamhshocraithe stórtha foinse ar gach stór atá i do sheilbh, i gcomhthéacs an stórtha sin féin.",
"actions.scoped_workflows.desc_global": "Cláraigh stórtha mar fhoinsí sreabhadh oibre raonta. Ritheann comhaid sreabhadh oibre faoi eolairí sreabhadh oibre raonta brainse réamhshocraithe stórtha foinse ar gach stór ar an gcás seo, i gcomhthéacs an stórtha sin féin. Ós rud é go ndéantar foinsí ar leibhéal an chás a mheas ar imeachtaí gach stórtha, is féidir le clárú na gcomhad sin forchostais a chur leis ar chásanna móra.",
"actions.scoped_workflows.add_help": "Chun sreafaí oibre raonta a sholáthar ó stór, cuir na comhaid sreafa oibre faoi <code>%s</code> ar a bhrainse réamhshocraithe, agus ansin cláraigh an stór mar fhoinse thíos.",
"actions.scoped_workflows.security_note": "Déantar ábhar sreafa oibre stórais foinse a fhorghníomhú i ngach stórais lena mbaineann sé, agus scríobhtar a scripteanna céime agus a n-aschur chuig logaí Gníomhartha an stórais sin agus is féidir le duine ar bith ar féidir leo Gníomhartha an stórais ídigh a fheiceáil iad a léamh. Dá bhrí sin, nochtar loighic a sreafa oibre trí na logaí sin nuair a chláraítear stórais phríobháidigh mar fhoinse. Ní chláraítear ach stórais a bhféadfadh a n-ábhar sreafa oibre a bheith roinnte le gach stórais ídigh. Má thagraíonn sreabhadh oibre raonaithe do shreabhadh oibre in-athúsáidte ó stórais phríobháidigh, déan cinnte gur féidir le gach stórais ídigh é a léamh, nó teipfidh ar an sreabhadh oibre ansin.",
"actions.scoped_workflows.source.add": "Cuir stór foinse leis",
"actions.scoped_workflows.source.add_success": "Stór foinse curtha leis.",
"actions.scoped_workflows.source.remove_success": "Baineadh an stór foinse.",
"actions.scoped_workflows.source.not_found": "Níor aimsíodh an stórlann.",
"actions.scoped_workflows.required.update_success": "Sreafaí oibre riachtanacha nuashonraithe.",
"actions.scoped_workflows.required.label": "Marcáil sreafaí oibre mar riachtanacha (ní féidir le stórtha sreabhadh oibre riachtanach a dhíchumasú):",
"actions.scoped_workflows.required.patterns": "Patrúin seiceála stádais riachtanacha",
"actions.scoped_workflows.required.patterns_aria": "Patrúin seiceála stádais riachtanacha do %s",
"actions.scoped_workflows.required.patterns_note": "i bhfeidhm ach amháin nuair a bhíonn an sreabhadh oibre ag teastáil",
"actions.scoped_workflows.required.patterns_hint": "Marcáil an sreabhadh oibre mar is gá chun a phatrúin seiceála stádais a chumrú.",
"actions.scoped_workflows.required.patterns_help": "Patrún seiceála stádais amháin (glob) in aghaidh an líne. Ní féidir iarratas tarraingthe íditheach a chumasc ach amháin nuair a bheidh stádas a mheaitseálann gach patrún rite. Cuirtear é seo i bhfeidhm ar aon bhrainse sprice a bhfuil riail chosanta aige, fiú ceann a bhfuil a sheiceálacha stádais féin díchumasaithe; ní dhéantar geataíocht ar bhrainse sprice gan aon riail chosanta.",
"actions.scoped_workflows.required.patterns_empty": "Teastaíonn patrún seiceála stádais amháin ar a laghad ó gach sreabhadh oibre riachtanach.",
"actions.scoped_workflows.required.missing_file": "níl an comhad sa bhunleagan a thuilleadh",
"actions.scoped_workflows.required.expected_contexts": "Seiceálacha stádais ionchais (marcáiltear seic a mheaitseálann patrún)",
"actions.scoped_workflows.required.no_status_contexts": "Ní phostálann an sreabhadh oibre seo aon seiceálacha stádais, mar sin má mharcálann tú é mar riachtanas, chuirfeadh sé bac ar gach iarratas tarraingthe atá á úsáid ó chumasc. Díthiceáil Riachtanach.",
"actions.scoped_workflows.no_files": "Ní bhfuarthas aon chomhaid sreabha oibre raonaithe ar an mbrainse réamhshocraithe.",
"actions.workflow.run": "Rith Sreabhadh Oibre",
"actions.workflow.create_status_badge": "Cruthaigh suaitheantas stádais",
"actions.workflow.status_badge": "Suaitheantas Stádais",
"actions.workflow.status_badge_url": "URL suaitheantais",
"actions.workflow.not_found": "Níor aimsíodh sreabhadh oibre '%s'.",
"actions.workflow.run_success": "Ritheann sreabhadh oibre '%s' go rathúil.",
"actions.workflow.from_ref": "Úsáid sreabhadh oibre ó",
+1 -28
View File
@@ -2251,6 +2251,7 @@
"repo.settings.webhook_deletion_success": "Webhookを削除しました。",
"repo.settings.webhook.test_delivery": "プッシュ・イベントによるテスト",
"repo.settings.webhook.test_delivery_desc": "ダミーのプッシュ・イベントでこのWebhookをテストします。",
"repo.settings.webhook.test_delivery_desc_disabled": "このWebhookをダミーのイベントでテストするには、有効にしてください。",
"repo.settings.webhook.request": "リクエスト",
"repo.settings.webhook.response": "レスポンス",
"repo.settings.webhook.headers": "ヘッダー",
@@ -2871,7 +2872,6 @@
"org.teams.visibility_limited_helper": "この組織のすべてのメンバーに表示されます。",
"org.teams.visibility_public": "公開",
"org.teams.visibility_public_helper": "サインインしているすべてのユーザーに表示されます。",
"org.teams.owners_visibility_fixed": "Ownersチームの公開範囲は変更できません。",
"org.teams.invite.title": "あなたは組織 <strong>%[2]s</strong> 内のチーム <strong>%[1]s</strong> への参加に招待されました。",
"org.teams.invite.by": "%s からの招待",
"org.teams.invite.description": "下のボタンをクリックしてチームに参加してください。",
@@ -3778,7 +3778,6 @@
"actions.runs.commit": "コミット",
"actions.runs.run_details": "実行の詳細",
"actions.runs.workflow_file": "ワークフローのファイル",
"actions.runs.workflow_file_no_permission": "ワークフローファイルを表示する権限がありません",
"actions.runs.scheduled": "スケジュール済み",
"actions.runs.pushed_by": "pushed by",
"actions.runs.invalid_workflow_helper": "ワークフロー設定ファイルは無効です。あなたの設定ファイルを確認してください: %s",
@@ -3835,33 +3834,7 @@
"actions.workflow.scope_owner": "オーナー",
"actions.workflow.scope_global": "グローバル",
"actions.workflow.required": "必須",
"actions.workflow.scoped_required_cannot_disable": "このスコープ付きワークフローは必須で、無効にできません。",
"actions.scoped_workflows": "スコープ付きワークフロー",
"actions.scoped_workflows.desc_org": "スコープ付きワークフローのソースとなるリポジトリを登録します。 ソースリポジトリのデフォルトブランチ内で、スコープ付きワークフロー用ディレクトリにワークフローファイルを置くと、組織内のすべてのリポジトリで、それぞれのリポジトリ自身のコンテキストで実行されます。",
"actions.scoped_workflows.desc_user": "スコープ付きワークフローのソースとなるリポジトリを登録します。 ソースリポジトリのデフォルトブランチ内で、スコープ付きワークフロー用ディレクトリにワークフローファイルを置くと、あなたが所有するすべてのリポジトリで、それぞれのリポジトリ自身のコンテキストで実行されます。",
"actions.scoped_workflows.desc_global": "スコープ付きワークフローのソースとなるリポジトリを登録します。 ソースリポジトリのデフォルトブランチ内で、スコープ付きワークフロー用ディレクトリにワークフローファイルを置くと、このインスタンスのすべてのリポジトリで、それぞれのリポジトリ自身のコンテキストで実行されます。 インスタンスレベルのソースはあらゆるリポジトリでイベントが発生するたびに評価されるため、大規模インスタンスで登録するとオーバーヘッドが増加する可能性があります。",
"actions.scoped_workflows.add_help": "スコープ付きワークフローをリポジトリから提供するには、デフォルトブランチの <code>%s</code> にワークフローファイルをコミットし、以下でそのリポジトリをソースとして登録します。",
"actions.scoped_workflows.security_note": "ソースリポジトリのワークフローの内容は、適用対象となるすべてのリポジトリ内で実行されます。 ステップごとのスクリプトとその出力は、実行したリポジトリのActionsログに書き込まれ、そのリポジトリのActionsを閲覧できるユーザーであれば誰でも読むことができます。 プライベートリポジトリをソースとして登録しても、そのワークフローのロジックはログを通して開示されることになります。 すべての適用先リポジトリとワークフローの内容を共有しても問題ないリポジトリだけ登録してください。 スコープ付きワークフローが、プライベートリポジトリの再利用可能ワークフローを参照している場合は、すべての適用先リポジトリがそのワークフローを読み取れるようにしてください。 そうでない場合、そこでのワークフローは失敗します。",
"actions.scoped_workflows.source.add": "ソースリポジトリを追加",
"actions.scoped_workflows.source.add_success": "ソースリポジトリを追加しました。",
"actions.scoped_workflows.source.remove_success": "ソースリポジトリを削除しました。",
"actions.scoped_workflows.source.not_found": "リポジトリが見つかりません。",
"actions.scoped_workflows.required.update_success": "必須ワークフローを更新しました。",
"actions.scoped_workflows.required.label": "ワークフローを必須としてマークする (必須ワークフローはリポジトリから無効にすることはできません):",
"actions.scoped_workflows.required.patterns": "必須ステータスチェックパターン",
"actions.scoped_workflows.required.patterns_aria": "%s の必須ステータスチェックパターン",
"actions.scoped_workflows.required.patterns_note": "ワークフローが必須の場合にだけ適用されます",
"actions.scoped_workflows.required.patterns_hint": "ステータスチェックパターンを設定するには、ワークフローを必須とマークします。",
"actions.scoped_workflows.required.patterns_help": "ステータスチェックのパターン(glob)を1行につき1つずつ記入します。 対象となるプルリクエストは、ステータスがすべてのパターンに一致して初めてマージ可能になります。 これは保護ルールを持つターゲットブランチであれば、そのステータスチェックが無効になっていたとしても適用されます。 一方、保護ルールを持たないターゲットブランチは制限されません。",
"actions.scoped_workflows.required.patterns_empty": "必須ワークフローには、少なくともひとつのステータスチェックパターンが必要です。",
"actions.scoped_workflows.required.missing_file": "ファイルがもうソースにありません",
"actions.scoped_workflows.required.expected_contexts": "想定されるステータスチェック (パターンに一致するチェックがマークされています)",
"actions.scoped_workflows.required.no_status_contexts": "このワークフローのステータスチェックが送られてきていないため、必須ワークフローにすると、適用されるプルリクエストのマージをすべてブロックしてしまいます。 必須を解除してください。",
"actions.scoped_workflows.no_files": "デフォルトブランチに、スコープ付きワークフローのファイルが見つかりません。",
"actions.workflow.run": "ワークフローを実行",
"actions.workflow.create_status_badge": "ステータスバッジを作成する",
"actions.workflow.status_badge": "ステータスバッジ",
"actions.workflow.status_badge_url": "バッジURL",
"actions.workflow.not_found": "ワークフロー '%s' が見つかりません。",
"actions.workflow.run_success": "ワークフロー '%s' は正常に実行されました。",
"actions.workflow.from_ref": "使用するワークフローの取得元",
+2 -6
View File
@@ -1584,7 +1584,7 @@
"repo.issues.label_archived_filter": "아카이빙된 레이블 표시",
"repo.issues.label_archive_tooltip": "아카아빙된 레이블은 레이블로 검색할 때 기본적으로 제안 목록에서 제외됩니다.",
"repo.issues.label_exclusive_desc": "레이블명을 <code>스코프/항목</code>으로 지정하여 다른 <code>스코프/</code> 레이블과 상호 배타적으로 만드세요.",
"repo.issues.label_exclusive_warning": "이슈 또는 풀 리퀘스트의 레이블을 편집할 때 충돌하는 범위지정 레이블은 모두 제거됩니다.",
"repo.issues.label_exclusive_warning": "이슈 또는 풀 리퀘스트의 레이블을 편집할 때 충돌하는 스코프 지정 레이블은 모두 제거됩니다.",
"repo.issues.label_exclusive_order": "정렬 순서",
"repo.issues.label_exclusive_order_tooltip": "같은 스코프 내의 독점 레이블은 이 숫자 순서에 따라 정렬됩니다.",
"repo.issues.label_count": "레이블 %d개",
@@ -2248,6 +2248,7 @@
"repo.settings.webhook_deletion_success": "Webhook을 삭제했습니다.",
"repo.settings.webhook.test_delivery": "푸시 이벤트 테스트",
"repo.settings.webhook.test_delivery_desc": "가짜 푸시 이벤트로 웹훅을 테스트합니다.",
"repo.settings.webhook.test_delivery_desc_disabled": "가짜 이벤트로 이 웹훅을 테스트하려면 활성화하십시오.",
"repo.settings.webhook.request": "요청",
"repo.settings.webhook.response": "응답",
"repo.settings.webhook.headers": "제목",
@@ -3819,12 +3820,7 @@
"actions.workflow.scope_owner": "소유자",
"actions.workflow.scope_global": "글로벌",
"actions.workflow.required": "필수 항목",
"actions.workflow.scoped_required_cannot_disable": "범위지정 워크플로우가 요구되며 비활성화할 수 없습니다.",
"actions.scoped_workflows": "범위지정 워크플로우",
"actions.workflow.run": "워크플로 실행",
"actions.workflow.create_status_badge": "상태 배지 생성",
"actions.workflow.status_badge": "상태 배지",
"actions.workflow.status_badge_url": "배지 URL",
"actions.workflow.not_found": "워크플로 '%s'를 찾을 수 없습니다.",
"actions.workflow.run_success": "워크플로 '%s'가 성공적으로 실행되었습니다.",
"actions.workflow.from_ref": "다음에서 워크플로 사용",
+1
View File
@@ -1812,6 +1812,7 @@
"repo.settings.webhook_deletion": "Noņemt tīmekļa āķi",
"repo.settings.webhook_deletion_desc": "Noņemot tīmekļa āķi, tiks dzēsti visi tā iestatījumi un piegādes vēsture. Vai turpināt?",
"repo.settings.webhook_deletion_success": "Tīmekļa āķis tika noņemts.",
"repo.settings.webhook.test_delivery_desc_disabled": "Lai pārbaudītu šo tīmekļa āķi ar neīstu notikumu, tas ir jāiespējo.",
"repo.settings.webhook.request": "Pieprasījums",
"repo.settings.webhook.response": "Atbilde",
"repo.settings.webhook.headers": "Galvenes",
+1
View File
@@ -2019,6 +2019,7 @@
"repo.settings.webhook_deletion_success": "O webhook foi removido.",
"repo.settings.webhook.test_delivery": "Testar Evento de Push",
"repo.settings.webhook.test_delivery_desc": "Teste este webhook com um evento falso.",
"repo.settings.webhook.test_delivery_desc_disabled": "Para testar este webhook com um evento falso, ative-o.",
"repo.settings.webhook.request": "Solicitação",
"repo.settings.webhook.response": "Resposta",
"repo.settings.webhook.headers": "Cabeçalhos",
+1 -27
View File
@@ -165,7 +165,6 @@
"search.fuzzy_tooltip": "Incluir também os resultados que estejam próximos do termo de pesquisa",
"search.words": "Palavras",
"search.words_tooltip": "Incluir apenas os resultados que correspondam às palavras do termo de pesquisa",
"search.regexp": "Expressão regular",
"search.regexp_tooltip": "Incluir apenas os resultados que correspondam ao termo de pesquisa com expressões regulares",
"search.exact": "Fiel",
"search.exact_tooltip": "Incluir somente os resultados que correspondam rigorosamente ao termo de pesquisa",
@@ -1003,7 +1002,6 @@
"repo.multiple_licenses": "Múltiplas licenças",
"repo.object_format": "Formato dos elementos",
"repo.object_format_helper": "Formato dos elementos do repositório. Não poderá ser alterado mais tarde. SHA1 é o mais compatível.",
"repo.readme": "README",
"repo.readme_helper": "Escolha um modelo de ficheiro README.",
"repo.readme_helper_desc": "Este é o sítio onde pode escrever uma descrição completa do seu trabalho.",
"repo.auto_init": "Inicializar repositório (adiciona `.gitignore`, `LICENSE` e `README.md`)",
@@ -1891,7 +1889,6 @@
"repo.pulls.closed_at": "fechou este pedido de integração <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>",
"repo.pulls.reopened_at": "reabriu este pedido de integração <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>",
"repo.pulls.cmd_instruction_hint": "Ver instruções para a linha de comandos",
"repo.pulls.cmd_instruction_checkout_title": "Checkout",
"repo.pulls.cmd_instruction_checkout_desc": "A partir do seu repositório, crie um novo ramo e teste nele as modificações.",
"repo.pulls.cmd_instruction_merge_title": "Integrar",
"repo.pulls.cmd_instruction_merge_desc": "Integrar as modificações e enviar para o Gitea.",
@@ -2251,6 +2248,7 @@
"repo.settings.webhook_deletion_success": "O automatismo web foi removido.",
"repo.settings.webhook.test_delivery": "Testar o envio",
"repo.settings.webhook.test_delivery_desc": "Testar este automatismo web com um evento de envio falso.",
"repo.settings.webhook.test_delivery_desc_disabled": "Para testar este automatismo web com um evento falso, habilite-o.",
"repo.settings.webhook.request": "Pedido",
"repo.settings.webhook.response": "Resposta",
"repo.settings.webhook.headers": "Cabeçalhos",
@@ -3778,7 +3776,6 @@
"actions.runs.commit": "Cometimento",
"actions.runs.run_details": "Detalhes da execução",
"actions.runs.workflow_file": "Ficheiro de sequência de trabalho",
"actions.runs.workflow_file_no_permission": "Sem permissão para ver o ficheiro da sequência de trabalho",
"actions.runs.scheduled": "Agendadas",
"actions.runs.pushed_by": "enviado por",
"actions.runs.invalid_workflow_helper": "O ficheiro de configuração da sequência de trabalho é inválido. Verifique o seu ficheiro de configuração: %s",
@@ -3835,29 +3832,6 @@
"actions.workflow.scope_owner": "Proprietário(a)",
"actions.workflow.scope_global": "Global",
"actions.workflow.required": "Obrigatório",
"actions.workflow.scoped_required_cannot_disable": "Esta sequência de trabalho de âmbito específico é obrigatória e não pode ser desabilitada.",
"actions.scoped_workflows": "Sequências de trabalho de âmbito específico",
"actions.scoped_workflows.desc_org": "Registe repositórios como fontes de sequências de trabalho de âmbito específico. Os ficheiros das sequências de trabalho dentro de pastas das sequências de trabalho de âmbito específico do ramo principal de um repositório fonte são executados em todos os repositórios desta organização, no próprio contexto desse repositório.",
"actions.scoped_workflows.desc_user": "Registe repositórios como fontes de sequências de trabalho de âmbito específico. Os ficheiros das sequências de trabalho dentro de pastas das sequências de trabalho de âmbito específico do ramo principal de um repositório fonte são executados em todos os seus repositórios, no próprio contexto desse repositório.",
"actions.scoped_workflows.desc_global": "Registe repositórios como fontes de sequências de trabalho de âmbito específico. Os ficheiros das sequências de trabalho dentro de pastas das sequências de trabalho de âmbito específico do ramo principal de um repositório fonte são executados em todos os repositórios desta instância, no próprio contexto desse repositório. Uma vez que as fontes ao nível da instância são avaliadas em todos os eventos do repositório, registá-las poderá acrescentar uma sobrecarga em instâncias grandes.",
"actions.scoped_workflows.add_help": "Para fornecer sequências de trabalho de âmbito específico a partir de um repositório, cometa os ficheiros da sequência de trabalho sob <code>%s</code> no seu ramo principal e depois registe o repositório como uma fonte abaixo.",
"actions.scoped_workflows.security_note": "O conteúdo da sequência de trabalho de um repositório de origem é executado em todos os repositórios aos quais se aplica e os seus scripts de etapas, bem como os seus resultados, são escritos nos registos das operações desse repositório e podem ser lidos por qualquer pessoa que tenha permissão para ver as operações do repositório consumidor. Portanto, registar um repositório privado como uma fonte divulga a lógica da sequência de trabalho através desses registos. Registe apenas repositórios cujo conteúdo da sequência de trabalho possa ser partilhado com todos os repositórios consumidores. Se uma sequência de trabalho de âmbito específico fizer referência a uma sequência de trabalho reutilizável de um repositório privado, certifique-se que todos os repositórios consumidores a podem ler, caso contrário a sequência de trabalho irá falhar aí.",
"actions.scoped_workflows.source.add": "Adicionar repositório de origem",
"actions.scoped_workflows.source.add_success": "Repositório de origem adicionado.",
"actions.scoped_workflows.source.remove_success": "Repositório de origem removido.",
"actions.scoped_workflows.source.not_found": "Repositório não encontrado.",
"actions.scoped_workflows.required.update_success": "As sequências de trabalho obrigatórias foram refrescadas.",
"actions.scoped_workflows.required.label": "Marcar sequências de trabalho como sendo obrigatórias (uma sequência de trabalho obrigatória não pode ser desabilitada pelos repositórios):",
"actions.scoped_workflows.required.patterns": "Padrões de verificação de estado obrigatórios",
"actions.scoped_workflows.required.patterns_aria": "Padrões de verificação de estado obrigatórios para %s",
"actions.scoped_workflows.required.patterns_note": "aplicada apenas enquanto a sequência de trabalho for obrigatória",
"actions.scoped_workflows.required.patterns_hint": "Marque a sequência de trabalho como sendo obrigatória para configurar os seus padrões de verificação de estado.",
"actions.scoped_workflows.required.patterns_help": "Um padrão de verificação de estado (glob) por linha. Um pedido de integração consumidor só pode ser executado depois de ter sido aprovado um estado que corresponda a todos os padrões. Esta regra é aplicada a qualquer ramo de destino que tenha uma regra de salvaguarda, mesmo que as suas próprias verificações de estado estejam desabilitadas; um ramo de destino sem regra de salvaguarda não está sujeito a restrições.",
"actions.scoped_workflows.required.patterns_empty": "Cada sequência de trabalho obrigatória precisa de pelo menos um padrão de verificação de estado.",
"actions.scoped_workflows.required.missing_file": "o ficheiro já não está na origem",
"actions.scoped_workflows.required.expected_contexts": "Verificações de estado esperadas (está marcada uma verificação que corresponde a um padrão)",
"actions.scoped_workflows.required.no_status_contexts": "Esta sequência de trabalho não faz verificações de estado; por isso, marcá-la como obrigatória impediria a execução de todos os pedidos de integração que a utilizam. Desmarque a opção «Obrigatória».",
"actions.scoped_workflows.no_files": "Não foram encontrados quaisquer ficheiros de sequência de trabalho de âmbito específico no ramo principal.",
"actions.workflow.run": "Executar sequência de trabalho",
"actions.workflow.create_status_badge": "Criar distintivo de estado",
"actions.workflow.status_badge": "Distintivo de estado",

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