diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 9e290fb6a5..1051b0f2a2 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,6 +1,6 @@
{
"name": "Gitea DevContainer",
- "image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye",
+ "image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye",
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {
diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index 78042a7598..e9991c02ba 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -12,6 +12,7 @@ plugins:
- "@eslint-community/eslint-plugin-eslint-comments"
- "@stylistic/eslint-plugin-js"
- eslint-plugin-array-func
+ - eslint-plugin-github
- eslint-plugin-i
- eslint-plugin-jquery
- eslint-plugin-no-jquery
@@ -209,6 +210,29 @@ rules:
func-names: [0]
func-style: [0]
getter-return: [2]
+ github/a11y-aria-label-is-well-formatted: [0]
+ github/a11y-no-title-attribute: [0]
+ github/a11y-no-visually-hidden-interactive-element: [0]
+ github/a11y-role-supports-aria-props: [0]
+ github/a11y-svg-has-accessible-name: [0]
+ github/array-foreach: [0]
+ github/async-currenttarget: [2]
+ github/async-preventdefault: [2]
+ github/authenticity-token: [0]
+ github/get-attribute: [0]
+ github/js-class-name: [0]
+ github/no-blur: [0]
+ github/no-d-none: [0]
+ github/no-dataset: [2]
+ github/no-dynamic-script-tag: [2]
+ github/no-implicit-buggy-globals: [2]
+ github/no-inner-html: [0]
+ github/no-innerText: [2]
+ github/no-then: [2]
+ github/no-useless-passive: [2]
+ github/prefer-observers: [2]
+ github/require-passive-events: [2]
+ github/unescaped-html-literal: [0]
grouped-accessor-pairs: [2]
guard-for-in: [0]
id-blacklist: [0]
@@ -272,7 +296,7 @@ rules:
jquery/no-delegate: [2]
jquery/no-each: [0]
jquery/no-extend: [2]
- jquery/no-fade: [0]
+ jquery/no-fade: [2]
jquery/no-filter: [0]
jquery/no-find: [0]
jquery/no-global-eval: [2]
@@ -285,7 +309,7 @@ rules:
jquery/no-is-function: [2]
jquery/no-is: [0]
jquery/no-load: [2]
- jquery/no-map: [0]
+ jquery/no-map: [2]
jquery/no-merge: [2]
jquery/no-param: [2]
jquery/no-parent: [0]
@@ -427,7 +451,7 @@ rules:
no-jquery/no-load: [2]
no-jquery/no-map-collection: [0]
no-jquery/no-map-util: [2]
- no-jquery/no-map: [0]
+ no-jquery/no-map: [2]
no-jquery/no-merge: [2]
no-jquery/no-node-name: [2]
no-jquery/no-noop: [2]
@@ -558,7 +582,6 @@ rules:
prefer-rest-params: [2]
prefer-spread: [2]
prefer-template: [2]
- quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
radix: [2, as-needed]
regexp/confusing-quantifier: [2]
regexp/control-character-escape: [2]
@@ -811,7 +834,7 @@ rules:
wc/no-constructor-params: [2]
wc/no-constructor: [2]
wc/no-customized-built-in-elements: [2]
- wc/no-exports-with-element: [2]
+ wc/no-exports-with-element: [0]
wc/no-invalid-element-name: [2]
wc/no-invalid-extends: [2]
wc/no-method-prefixed-with-on: [2]
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 624a2d97db..1447a6ea32 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,2 +1 @@
open_collective: gitea
-custom: https://www.bountysource.com/teams/gitea
diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml
index 0472d9a9f0..391137f015 100644
--- a/.github/workflows/pull-compliance.yml
+++ b/.github/workflows/pull-compliance.yml
@@ -64,6 +64,18 @@ jobs:
- run: make deps-frontend
- run: make lint-swagger
+ lint-spell:
+ if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.templates == 'true'
+ needs: files-changed
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+ check-latest: true
+ - run: make lint-spell
+
lint-go-windows:
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
needs: files-changed
diff --git a/.gitpod.yml b/.gitpod.yml
index 35b22c45ae..ed2f57f4bf 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -10,10 +10,19 @@ tasks:
- name: Run backend
command: |
gp sync-await setup
- if [ ! -f custom/conf/app.ini ]
- then
+
+ # Get the URL and extract the domain
+ url=$(gp url 3000)
+ domain=$(echo $url | awk -F[/:] '{print $4}')
+
+ if [ -f custom/conf/app.ini ]; then
+ sed -i "s|^ROOT_URL =.*|ROOT_URL = ${url}/|" custom/conf/app.ini
+ sed -i "s|^DOMAIN =.*|DOMAIN = ${domain}|" custom/conf/app.ini
+ sed -i "s|^SSH_DOMAIN =.*|SSH_DOMAIN = ${domain}|" custom/conf/app.ini
+ sed -i "s|^NO_REPLY_ADDRESS =.*|SSH_DOMAIN = noreply.${domain}|" custom/conf/app.ini
+ else
mkdir -p custom/conf/
- echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
+ echo -e "[server]\nROOT_URL = ${url}/" > custom/conf/app.ini
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
fi
export TAGS="sqlite sqlite_unlock_notify"
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
index f740d1a4d6..b251ff796c 100644
--- a/.markdownlint.yaml
+++ b/.markdownlint.yaml
@@ -5,13 +5,11 @@ heading-increment: false
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1}
no-alt-text: false
no-bare-urls: false
-no-blanks-blockquote: false
no-emphasis-as-heading: false
no-empty-links: false
no-hard-tabs: {code_blocks: false}
no-inline-html: false
no-space-in-code: false
no-space-in-emphasis: false
-no-trailing-punctuation: false
no-trailing-spaces: {br_spaces: 0}
single-h1: false
diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml
index a44294ee76..7dd0a566f2 100644
--- a/.stylelintrc.yaml
+++ b/.stylelintrc.yaml
@@ -98,7 +98,7 @@ rules:
at-rule-allowed-list: null
at-rule-disallowed-list: null
at-rule-empty-line-before: null
- at-rule-no-unknown: true
+ at-rule-no-unknown: [true, {ignoreAtRules: [tailwind]}]
at-rule-no-vendor-prefix: true
at-rule-property-required-list: null
block-no-empty: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae87638f1c..e119d0bec0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,240 @@ This changelog goes through all 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.21.6](https://github.com/go-gitea/gitea/releases/tag/v1.21.6) - 2024-02-22
+
+* SECURITY
+ * Fix XSS vulnerabilities (#29336)
+ * Use general token signing secret (#29205) (#29325)
+* ENHANCEMENTS
+ * Refactor git version functions and check compatibility (#29155) (#29157)
+ * Improve user experience for outdated comments (#29050) (#29086)
+ * Hide code links on release page if user cannot read code (#29064) (#29066)
+ * Wrap contained tags and branches again (#29021) (#29026)
+ * Fix incorrect button CSS usages (#29015) (#29023)
+ * Strip trailing newline in markdown code copy (#29019) (#29022)
+ * Implement some action notifier functions (#29173) (#29308)
+ * Load outdated comments when (un)resolving conversation on PR timeline (#29203) (#29221)
+* BUGFIXES
+ * Refactor issue template parsing and fix API endpoint (#29069) (#29140)
+ * Fix swift packages not resolving (#29095) (#29102)
+ * Remove SSH workaround (#27893) (#29332)
+ * Only log error when tag sync fails (#29295) (#29327)
+ * Fix SSPI user creation (#28948) (#29323)
+ * Improve the `issue_comment` workflow trigger event (#29277) (#29322)
+ * Discard unread data of `git cat-file` (#29297) (#29310)
+ * Fix error display when merging PRs (#29288) (#29309)
+ * Prevent double use of `git cat-file` session. (#29298) (#29301)
+ * Fix missing link on outgoing new release notifications (#29079) (#29300)
+ * Fix debian InRelease Acquire-By-Hash newline (#29204) (#29299)
+ * Always write proc-receive hook for all git versions (#29287) (#29291)
+ * Do not show delete button when time tracker is disabled (#29257) (#29279)
+ * Workaround to clean up old reviews on creating a new one (#28554) (#29264)
+ * Fix bug when the linked account was disactived and list the linked accounts (#29263)
+ * Do not use lower tag names to find releases/tags (#29261) (#29262)
+ * Fix missed edit issues event for actions (#29237) (#29251)
+ * Only delete scheduled workflows when needed (#29091) (#29235)
+ * Make submit event code work with both jQuery event and native event (#29223) (#29234)
+ * Fix push to create with capitalize repo name (#29090) (#29206)
+ * Use ghost user if user was not found (#29161) (#29169)
+ * Dont load Review if Comment is CommentTypeReviewRequest (#28551) (#29160)
+ * Refactor parseSignatureFromCommitLine (#29054) (#29108)
+ * Avoid showing unnecessary JS errors when there are elements with different origin on the page (#29081) (#29089)
+ * Fix gitea-origin-url with default ports (#29085) (#29088)
+ * Fix orgmode link resolving (#29024) (#29076)
+ * Fix Elasticsearh Request Entity Too Large #28117 (#29062) (#29075)
+ * Do not render empty comments (#29039) (#29049)
+ * Avoid sending update/delete release notice when it is draft (#29008) (#29025)
+ * Fix gitea-action user avatar broken on edited menu (#29190) (#29307)
+ * Disallow merge when required checked are missing (#29143) (#29268)
+ * Fix incorrect link to swift doc and swift package-registry login command (#29096) (#29103)
+ * Convert visibility to number (#29226) (#29244)
+* DOCS
+ * Remove outdated docs from some languages (#27530) (#29208)
+ * Fix typos in the documentation (#29048) (#29056)
+ * Explained where create issue/PR template (#29035)
+
+## [1.21.5](https://github.com/go-gitea/gitea/releases/tag/v1.21.5) - 2024-01-31
+
+* SECURITY
+ * Prevent anonymous container access if `RequireSignInView` is enabled (#28877) (#28882)
+ * Update go dependencies and fix go-git (#28893) (#28934)
+* BUGFIXES
+ * Revert "Speed up loading the dashboard on mysql/mariadb (#28546)" (#29006) (#29007)
+ * Fix an actions schedule bug (#28942) (#28999)
+ * Fix update enable_prune even if mirror_interval is not provided (#28905) (#28929)
+ * Fix uploaded artifacts should be overwritten (#28726) backport v1.21 (#28832)
+ * Preserve BOM in web editor (#28935) (#28959)
+ * Strip `/` from relative links (#28932) (#28952)
+ * Don't remove all mirror repository's releases when mirroring (#28817) (#28939)
+ * Implement `MigrateRepository` for the actions notifier (#28920) (#28923)
+ * Respect branch info for relative links (#28909) (#28922)
+ * Don't reload timeline page when (un)resolving or replying conversation (#28654) (#28917)
+ * Only migrate the first 255 chars of a Github issue title (#28902) (#28912)
+ * Fix sort bug on repository issues list (#28897) (#28901)
+ * Fix `DeleteCollaboration` transaction behaviour (#28886) (#28889)
+ * Fix schedule not trigger bug because matching full ref name with short ref name (#28874) (#28888)
+ * Fix migrate storage bug (#28830) (#28867)
+ * Fix archive creating LFS hooks and breaking pull requests (#28848) (#28851)
+ * Fix reverting a merge commit failing (#28794) (#28825)
+ * Upgrade xorm to v1.3.7 to fix a resource leak problem caused by Iterate (#28891) (#28895)
+ * Fix incorrect PostgreSQL connection string for Unix sockets (#28865) (#28870)
+* ENHANCEMENTS
+ * Make loading animation less aggressive (#28955) (#28956)
+ * Avoid duplicate JS error messages on UI (#28873) (#28881)
+ * Bump `@github/relative-time-element` to 4.3.1 (#28819) (#28826)
+* MISC
+ * Warn that `DISABLE_QUERY_AUTH_TOKEN` is false only if it's explicitly defined (#28783) (#28868)
+ * Remove duplicated checkinit on git module (#28824) (#28831)
+
+## [1.21.4](https://github.com/go-gitea/gitea/releases/tag/v1.21.4) - 2024-01-16
+
+* SECURITY
+ * Update github.com/cloudflare/circl (#28789) (#28790)
+ * Require token for GET subscription endpoint (#28765) (#28768)
+* BUGFIXES
+ * Use refname:strip-2 instead of refname:short when syncing tags (#28797) (#28811)
+ * Fix links in issue card (#28806) (#28807)
+ * Fix nil pointer panic when exec some gitea cli command (#28791) (#28795)
+ * Require token for GET subscription endpoint (#28765) (#28778)
+ * Fix button size in "attached header right" (#28770) (#28774)
+ * Fix `convert.ToTeams` on empty input (#28426) (#28767)
+ * Hide code related setting options in repository when code unit is disabled (#28631) (#28749)
+ * Fix incorrect URL for "Reference in New Issue" (#28716) (#28723)
+ * Fix panic when parsing empty pgsql host (#28708) (#28709)
+ * Upgrade xorm to new version which supported update join for all supported databases (#28590) (#28668)
+ * Fix alpine package files are not rebuilt (#28638) (#28665)
+ * Avoid cycle-redirecting user/login page (#28636) (#28658)
+ * Fix empty ref for cron workflow runs (#28640) (#28647)
+ * Remove unnecessary syncbranchToDB with tests (#28624) (#28629)
+ * Use known issue IID to generate new PR index number when migrating from GitLab (#28616) (#28618)
+ * Fix flex container width (#28603) (#28605)
+ * Fix the scroll behavior for emoji/mention list (#28597) (#28601)
+ * Fix wrong due date rendering in issue list page (#28588) (#28591)
+ * Fix `status_check_contexts` matching bug (#28582) (#28589)
+ * Fix 500 error of searching commits (#28576) (#28579)
+ * Use information from previous blame parts (#28572) (#28577)
+ * Update mermaid for 1.21 (#28571)
+ * Fix 405 method not allowed CORS / OIDC (#28583) (#28586) (#28587) (#28611)
+ * Fix `GetCommitStatuses` (#28787) (#28804)
+ * Forbid removing the last admin user (#28337) (#28793)
+ * Fix schedule tasks bugs (#28691) (#28780)
+ * Fix issue dependencies (#27736) (#28776)
+ * Fix system webhooks API bug (#28531) (#28666)
+ * Fix when private user following user, private user will not be counted in his own view (#28037) (#28792)
+ * Render code block in activity tab (#28816) (#28818)
+* ENHANCEMENTS
+ * Rework markup link rendering (#26745) (#28803)
+ * Modernize merge button (#28140) (#28786)
+ * Speed up loading the dashboard on mysql/mariadb (#28546) (#28784)
+ * Assign pull request to project during creation (#28227) (#28775)
+ * Show description as tooltip instead of title for labels (#28754) (#28766)
+ * Make template `DateTime` show proper tooltip (#28677) (#28683)
+ * Switch destination directory for apt signing keys (#28639) (#28642)
+ * Include heap pprof in diagnosis report to help debugging memory leaks (#28596) (#28599)
+* DOCS
+ * Suggest to use Type=simple for systemd service (#28717) (#28722)
+ * Extend description for ARTIFACT_RETENTION_DAYS (#28626) (#28630)
+* MISC
+ * Add -F to commit search to treat keywords as strings (#28744) (#28748)
+ * Add download attribute to release attachments (#28739) (#28740)
+ * Concatenate error in `checkIfPRContentChanged` (#28731) (#28737)
+ * Improve 1.21 document for Database Preparation (#28643) (#28644)
+
+## [1.21.3](https://github.com/go-gitea/gitea/releases/tag/v1.21.3) - 2023-12-21
+
+* SECURITY
+ * Update golang.org/x/crypto (#28519)
+* API
+ * chore(api): support ignore password if login source type is LDAP for creating user API (#28491) (#28525)
+ * Add endpoint for not implemented Docker auth (#28457) (#28462)
+* ENHANCEMENTS
+ * Add option to disable ambiguous unicode characters detection (#28454) (#28499)
+ * Refactor SSH clone URL generation code (#28421) (#28480)
+ * Polyfill SubmitEvent for PaleMoon (#28441) (#28478)
+* BUGFIXES
+ * Fix the issue ref rendering for wiki (#28556) (#28559)
+ * Fix duplicate ID when deleting repo (#28520) (#28528)
+ * Only check online runner when detecting matching runners in workflows (#28286) (#28512)
+ * Initalize stroage for orphaned repository doctor (#28487) (#28490)
+ * Fix possible nil pointer access (#28428) (#28440)
+ * Don't show unnecessary citation JS error on UI (#28433) (#28437)
+* DOCS
+ * Update actions document about comparsion as Github Actions (#28560) (#28564)
+ * Fix documents for "custom/public/assets/" (#28465) (#28467)
+* MISC
+ * Fix inperformant query on retrifing review from database. (#28552) (#28562)
+ * Improve the prompt for "ssh-keygen sign" (#28509) (#28510)
+ * Update docs for DISABLE_QUERY_AUTH_TOKEN (#28485) (#28488)
+ * Fix Chinese translation of config cheat sheet[API] (#28472) (#28473)
+ * Retry SSH key verification with additional CRLF if it failed (#28392) (#28464)
+
+## [1.21.2](https://github.com/go-gitea/gitea/releases/tag/v1.21.2) - 2023-12-12
+
+* SECURITY
+ * Rebuild with recently released golang version
+ * Fix missing check (#28406) (#28411)
+ * Do some missing checks (#28423) (#28432)
+* BUGFIXES
+ * Fix margin in server signed signature verification view (#28379) (#28381)
+ * Fix object does not exist error when checking citation file (#28314) (#28369)
+ * Use `filepath` instead of `path` to create SQLite3 database file (#28374) (#28378)
+ * Fix the runs will not be displayed bug when the main branch have no workflows but other branches have (#28359) (#28365)
+ * Handle repository.size column being NULL in migration v263 (#28336) (#28363)
+ * Convert git commit summary to valid UTF8. (#28356) (#28358)
+ * Fix migration panic due to an empty review comment diff (#28334) (#28362)
+ * Add `HEAD` support for rpm repo files (#28309) (#28360)
+ * Fix RPM/Debian signature key creation (#28352) (#28353)
+ * Keep profile tab when clicking on Language (#28320) (#28331)
+ * Fix missing issue search index update when changing status (#28325) (#28330)
+ * Fix wrong link in `protect_branch_name_pattern_desc` (#28313) (#28315)
+ * Read `previous` info from git blame (#28306) (#28310)
+ * Ignore "non-existing" errors when getDirectorySize calculates the size (#28276) (#28285)
+ * Use appSubUrl for OAuth2 callback URL tip (#28266) (#28275)
+ * Meilisearch: require all query terms to be matched (#28293) (#28296)
+ * Fix required error for token name (#28267) (#28284)
+ * Fix issue will be detected as pull request when checking `First-time contributor` (#28237) (#28271)
+ * Use full width for project boards (#28225) (#28245)
+ * Increase "version" when update the setting value to a same value as before (#28243) (#28244)
+ * Also sync DB branches on push if necessary (#28361) (#28403)
+ * Make gogit Repository.GetBranchNames consistent (#28348) (#28386)
+ * Recover from panic in cron task (#28409) (#28425)
+ * Deprecate query string auth tokens (#28390) (#28430)
+* ENHANCEMENTS
+ * Improve doctor cli behavior (#28422) (#28424)
+ * Fix margin in server signed signature verification view (#28379) (#28381)
+ * Refactor template empty checks (#28351) (#28354)
+ * Read `previous` info from git blame (#28306) (#28310)
+ * Use full width for project boards (#28225) (#28245)
+ * Enable system users search via the API (#28013) (#28018)
+
+## [1.21.1](https://github.com/go-gitea/gitea/releases/tag/v1.21.1) - 2023-11-26
+
+* SECURITY
+ * Fix comment permissions (#28213) (#28216)
+* BUGFIXES
+ * Fix delete-orphaned-repos (#28200) (#28202)
+ * Make CORS work for oauth2 handlers (#28184) (#28185)
+ * Fix missing buttons (#28179) (#28181)
+ * Fix no ActionTaskOutput table waring (#28149) (#28152)
+ * Fix empty action run title (#28113) (#28148)
+ * Use "is-loading" to avoid duplicate form submit for code comment (#28143) (#28147)
+ * Fix Matrix and MSTeams nil dereference (#28089) (#28105)
+ * Fix incorrect pgsql conn builder behavior (#28085) (#28098)
+ * Fix system config cache expiration timing (#28072) (#28090)
+ * Restricted users only see repos in orgs which their team was assigned to (#28025) (#28051)
+* API
+ * Fix permissions for Token DELETE endpoint to match GET and POST (#27610) (#28099)
+* ENHANCEMENTS
+ * Do not display search box when there's no packages yet (#28146) (#28159)
+ * Add missing `packages.cleanup.success` (#28129) (#28132)
+* DOCS
+ * Docs: Replace deprecated IS_TLS_ENABLED mailer setting in email setup (#28205) (#28208)
+ * Fix the description about the default setting for action in quick start document (#28160) (#28168)
+ * Add guide page to actions when there's no workflows (#28145) (#28153)
+* MISC
+ * Use full width for PR comparison (#28182) (#28186)
+
## [1.21.0](https://github.com/go-gitea/gitea/releases/tag/v1.21.0) - 2023-11-14
* BREAKING
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 96b02edd5b..f9b9a421a3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -47,6 +47,7 @@
- [Release Cycle](#release-cycle)
- [Maintainers](#maintainers)
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc)
+ - [TOC election process](#toc-election-process)
- [Current TOC members](#current-toc-members)
- [Previous TOC/owners members](#previous-tocowners-members)
- [Governance Compensation](#governance-compensation)
@@ -486,36 +487,53 @@ if possible provide GPG signed commits.
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
https://help.github.com/articles/signing-commits-with-gpg/
+Furthermore, any account with write access (like bots and TOC members) **must** use 2FA.
+https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
+
## Technical Oversight Committee (TOC)
-At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions would be elected as it has been over the past years, and the other three would consist of appointed members from the Gitea company.
+At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions are elected as it has been over the past years, and the other three consist of appointed members from the Gitea company.
https://blog.gitea.com/quarterly-23q1/
-When the new community members have been elected, the old members will give up ownership to the newly elected members. For security reasons, TOC members or any account with write access (like a bot) must use 2FA.
-https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
+### TOC election process
+
+Any maintainer is eligible to be part of the community TOC if they are not associated with the Gitea company.
+A maintainer can either nominate themselves, or can be nominated by other maintainers to be a candidate for the TOC election.
+If you are nominated by someone else, you must first accept your nomination before the vote starts to be a candidate.
+
+The TOC is elected for one year, the TOC election happens yearly.
+After the announcement of the results of the TOC election, elected members have two weeks time to confirm or refuse the seat.
+If an elected member does not answer within this timeframe, they are automatically assumed to refuse the seat.
+Refusals result in the person with the next highest vote getting the same choice.
+As long as seats are empty in the TOC, members of the previous TOC can fill them until an elected member accepts the seat.
+
+If an elected member that accepts the seat does not have 2FA configured yet, they will be temporarily counted as `answer pending` until they manage to configure 2FA, thus leaving their seat empty for this duration.
### Current TOC members
-- 2023-01-01 ~ 2023-12-31 - https://blog.gitea.com/quarterly-23q1/
+- 2024-01-01 ~ 2024-12-31
- Company
- [Jason Song](https://gitea.com/wolfogre)
- [Lunny Xiao](https://gitea.com/lunny)
- - [Matti Ranta](https://gitea.com/techknowlogick)
+ - [Matti Ranta](https://gitea.com/techknowlogick)
- Community
- [6543](https://gitea.com/6543) <6543@obermui.de>
- - [Andrew Thornton](https://gitea.com/zeripath)
+ - [delvh](https://gitea.com/delvh)
- [John Olheiser](https://gitea.com/jolheiser)
### Previous TOC/owners members
Here's the history of the owners and the time they served:
-- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [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)
+- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [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
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
-- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [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)
-- [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)
+- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [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
+- [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
+- [John Olheiser](https://gitea.com/jolheiser) - 2023
+- [Jason Song](https://gitea.com/wolfogre) - 2023
## Governance Compensation
diff --git a/Dockerfile b/Dockerfile
index 325b0255df..b647c0cd59 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# Build stage
-FROM docker.io/library/golang:1.21-alpine3.19 AS build-env
+FROM docker.io/library/golang:1.22-alpine3.19 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
diff --git a/Dockerfile.rootless b/Dockerfile.rootless
index 6f27c698ac..dd7da97278 100644
--- a/Dockerfile.rootless
+++ b/Dockerfile.rootless
@@ -1,5 +1,5 @@
# Build stage
-FROM docker.io/library/golang:1.21-alpine3.19 AS build-env
+FROM docker.io/library/golang:1.22-alpine3.19 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
diff --git a/MAINTAINERS b/MAINTAINERS
index 72171f80ed..2f95fdca50 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -59,3 +59,4 @@ Rui Chen (@chenrui333)
Nanguan Lin (@lng2020)
kerwin612 (@kerwin612)
Gary Wang (@BLumia)
+Tim-Niclas Oelschläger (@zokkis)
diff --git a/Makefile b/Makefile
index 273ae1fa68..0e9e792053 100644
--- a/Makefile
+++ b/Makefile
@@ -23,14 +23,14 @@ SHASUM ?= shasum -a 256
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
COMMA := ,
-XGO_VERSION := go-1.21.x
+XGO_VERSION := go-1.22.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
-GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2
+GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
-MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
+MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
@@ -119,7 +119,7 @@ GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/m
FOMANTIC_WORK_DIR := web_src/fomantic
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
-WEBPACK_CONFIGS := webpack.config.js
+WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack
@@ -146,6 +146,8 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
GO_DIRS := build cmd models modules routers services tests
WEB_DIRS := web_src/js web_src/css
+SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github
+
GO_SOURCES := $(wildcard *.go)
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
GO_SOURCES += $(GENERATED_GO_DEST)
@@ -162,8 +164,8 @@ ifdef DEPS_PLAYWRIGHT
endif
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
-SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
-SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
+SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g
+SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g
SWAGGER_EXCLUDE := code.gitea.io/sdk
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
@@ -219,6 +221,8 @@ help:
@echo " - lint-swagger lint swagger files"
@echo " - lint-templates lint template files"
@echo " - lint-yaml lint yaml files"
+ @echo " - lint-spell lint spelling"
+ @echo " - lint-spell-fix lint spelling and fix issues"
@echo " - checks run various consistency checks"
@echo " - checks-frontend check frontend files"
@echo " - checks-backend check backend files"
@@ -308,10 +312,6 @@ fmt-check: fmt
exit 1; \
fi
-.PHONY: misspell-check
-misspell-check:
- go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
-
.PHONY: $(TAGS_EVIDENCE)
$(TAGS_EVIDENCE):
@mkdir -p $(MAKE_EVIDENCE_DIR)
@@ -351,13 +351,13 @@ checks: checks-frontend checks-backend
checks-frontend: lockfile-check svg-check
.PHONY: checks-backend
-checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check
+checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check
.PHONY: lint
-lint: lint-frontend lint-backend
+lint: lint-frontend lint-backend lint-spell
.PHONY: lint-fix
-lint-fix: lint-frontend-fix lint-backend-fix
+lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix
.PHONY: lint-frontend
lint-frontend: lint-js lint-css
@@ -395,6 +395,14 @@ lint-swagger: node_modules
lint-md: node_modules
npx markdownlint docs *.md
+.PHONY: lint-spell
+lint-spell:
+ @go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES)
+
+.PHONY: lint-spell-fix
+lint-spell-fix:
+ @go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES)
+
.PHONY: lint-go
lint-go:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
@@ -594,8 +602,7 @@ test-mssql\#%: integrations.mssql.test generate-ini-mssql
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
.PHONY: playwright
-playwright: $(PLAYWRIGHT_DIR)
- npm install --no-save @playwright/test
+playwright: deps-frontend
npx playwright install $(PLAYWRIGHT_FLAGS)
.PHONY: test-e2e%
@@ -962,7 +969,7 @@ generate-gitignore:
.PHONY: generate-images
generate-images: | node_modules
- npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7
+ npm install --no-save fabric@6.0.0-beta19 imagemin-zopfli@7
node build/generate-images.js $(TAGS)
.PHONY: generate-manpage
@@ -980,3 +987,8 @@ docker:
# This endif closes the if at the top of the file
endif
+
+# Disable parallel execution because it would break some targets that don't
+# specify exact dependencies like 'backend' which does currently not depend
+# on 'frontend' to enable Node.js-less builds from source tarballs.
+.NOTPARALLEL:
diff --git a/README.md b/README.md
index 5356fcfacd..94d7284c7c 100644
--- a/README.md
+++ b/README.md
@@ -45,9 +45,6 @@
-
-
-
@@ -89,25 +86,23 @@ The `build` target is split into two sub-targets:
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js.
-Parallelism (`make -j `) is not supported.
-
More info: https://docs.gitea.com/installation/install-from-source
## Using
./gitea web
-NOTE: If you're interested in using our APIs, we have experimental
-support with [documentation](https://try.gitea.io/api/swagger).
+> [!NOTE]
+> If you're interested in using our APIs, we have experimental support with [documentation](https://try.gitea.io/api/swagger).
## Contributing
Expected workflow is: Fork -> Patch -> Push -> Pull Request
-NOTES:
-
-1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
-2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
+> [!NOTE]
+>
+> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
+> 2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
## Translating
diff --git a/README_ZH.md b/README_ZH.md
index 0d9092a0fd..adfeb9a8df 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -45,9 +45,6 @@
-
-
-
diff --git a/build/generate-images.js b/build/generate-images.js
index a3a0f8d8f3..db31d19e2a 100755
--- a/build/generate-images.js
+++ b/build/generate-images.js
@@ -1,20 +1,13 @@
#!/usr/bin/env node
import imageminZopfli from 'imagemin-zopfli';
import {optimize} from 'svgo';
-import {fabric} from 'fabric';
+import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node';
import {readFile, writeFile} from 'node:fs/promises';
+import {argv, exit} from 'node:process';
-function exit(err) {
+function doExit(err) {
if (err) console.error(err);
- process.exit(err ? 1 : 0);
-}
-
-function loadSvg(svg) {
- return new Promise((resolve) => {
- fabric.loadSVGFromString(svg, (objects, options) => {
- resolve({objects, options});
- });
- });
+ exit(err ? 1 : 0);
}
async function generate(svg, path, {size, bg}) {
@@ -35,14 +28,14 @@ async function generate(svg, path, {size, bg}) {
return;
}
- const {objects, options} = await loadSvg(svg);
- const canvas = new fabric.Canvas();
+ const {objects, options} = await loadSVGFromString(svg);
+ const canvas = new Canvas();
canvas.setDimensions({width: size, height: size});
const ctx = canvas.getContext('2d');
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
if (bg) {
- canvas.add(new fabric.Rect({
+ canvas.add(new Rect({
left: 0,
top: 0,
height: size * (1 / (size / options.height)),
@@ -51,7 +44,7 @@ async function generate(svg, path, {size, bg}) {
}));
}
- canvas.add(fabric.util.groupSVGElements(objects, options));
+ canvas.add(util.groupSVGElements(objects, options));
canvas.renderAll();
let png = Buffer.from([]);
@@ -64,7 +57,7 @@ async function generate(svg, path, {size, bg}) {
}
async function main() {
- const gitea = process.argv.slice(2).includes('gitea');
+ const gitea = argv.slice(2).includes('gitea');
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
@@ -79,4 +72,8 @@ async function main() {
]);
}
-main().then(exit).catch(exit);
+try {
+ doExit(await main());
+} catch (err) {
+ doExit(err);
+}
diff --git a/build/generate-svg.js b/build/generate-svg.js
index b845da9367..f26b60d960 100755
--- a/build/generate-svg.js
+++ b/build/generate-svg.js
@@ -4,15 +4,16 @@ import {optimize} from 'svgo';
import {parse} from 'node:path';
import {readFile, writeFile, mkdir} from 'node:fs/promises';
import {fileURLToPath} from 'node:url';
+import {exit} from 'node:process';
const glob = (pattern) => fastGlob.sync(pattern, {
cwd: fileURLToPath(new URL('..', import.meta.url)),
absolute: true,
});
-function exit(err) {
+function doExit(err) {
if (err) console.error(err);
- process.exit(err ? 1 : 0);
+ exit(err ? 1 : 0);
}
async function processFile(file, {prefix, fullName} = {}) {
@@ -63,4 +64,8 @@ async function main() {
]);
}
-main().then(exit).catch(exit);
+try {
+ doExit(await main());
+} catch (err) {
+ doExit(err);
+}
diff --git a/cmd/admin_user_create.go b/cmd/admin_user_create.go
index fefe18d39c..a257ce21c8 100644
--- a/cmd/admin_user_create.go
+++ b/cmd/admin_user_create.go
@@ -10,8 +10,8 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
pwd "code.gitea.io/gitea/modules/auth/password"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"github.com/urfave/cli/v2"
)
@@ -123,10 +123,10 @@ func runCreateUser(c *cli.Context) error {
changePassword = c.Bool("must-change-password")
}
- restricted := util.OptionalBoolNone
+ restricted := optional.None[bool]()
if c.IsSet("restricted") {
- restricted = util.OptionalBoolOf(c.Bool("restricted"))
+ restricted = optional.Some(c.Bool("restricted"))
}
// default user visibility in app.ini
@@ -142,7 +142,7 @@ func runCreateUser(c *cli.Context) error {
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
IsRestricted: restricted,
}
diff --git a/cmd/generate.go b/cmd/generate.go
index 4ab10da22a..90b32ecaf0 100644
--- a/cmd/generate.go
+++ b/cmd/generate.go
@@ -70,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
}
func runGenerateLfsJwtSecret(c *cli.Context) error {
- _, jwtSecretBase64, err := generate.NewJwtSecretBase64()
+ _, jwtSecretBase64, err := generate.NewJwtSecretWithBase64()
if err != nil {
return err
}
diff --git a/cmd/keys.go b/cmd/keys.go
index ceeec48486..7fdbe16119 100644
--- a/cmd/keys.go
+++ b/cmd/keys.go
@@ -71,7 +71,7 @@ func runKeys(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
- setup(ctx, false)
+ setup(ctx, c.Bool("debug"))
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
diff --git a/cmd/serv.go b/cmd/serv.go
index 726663660b..90190a19db 100644
--- a/cmd/serv.go
+++ b/cmd/serv.go
@@ -63,21 +63,10 @@ func setup(ctx context.Context, debug bool) {
setupConsoleLogger(log.FATAL, false, os.Stderr)
}
setting.MustInstalled()
- if debug {
- setting.RunMode = "dev"
- }
-
- // Check if setting.RepoRootPath exists. It could be the case that it doesn't exist, this can happen when
- // `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
if _, err := os.Stat(setting.RepoRootPath); err != nil {
- if os.IsNotExist(err) {
- _ = fail(ctx, "Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
- } else {
- _ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
- }
+ _ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, err: %v", setting.RepoRootPath, err)
return
}
-
if err := git.InitSimple(context.Background()); err != nil {
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
}
@@ -216,16 +205,18 @@ func runServ(c *cli.Context) error {
}
}
- // LowerCase and trim the repoPath as that's how they are stored.
- repoPath = strings.ToLower(strings.TrimSpace(repoPath))
-
rr := strings.SplitN(repoPath, "/", 2)
if len(rr) != 2 {
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
}
- username := strings.ToLower(rr[0])
- reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
+ username := rr[0]
+ reponame := strings.TrimSuffix(rr[1], ".git")
+
+ // LowerCase and trim the repoPath as that's how they are stored.
+ // This should be done after splitting the repoPath into username and reponame
+ // so that username and reponame are not affected.
+ repoPath = strings.ToLower(strings.TrimSpace(repoPath))
if alphaDashDotPattern.MatchString(reponame) {
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 363bbcb151..5451537d02 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -412,6 +412,10 @@ USER = root
;;
;; Whether execute database models migrations automatically
;AUTO_MIGRATION = true
+;;
+;; Threshold value (in seconds) beyond which query execution time is logged as a warning in the xorm logger
+;;
+;SLOW_QUERY_THRESHOLD = 5s
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1044,7 +1048,7 @@ LEVEL = Info
;; List of keywords used in Pull Request comments to automatically reopen a related issue
;REOPEN_KEYWORDS = reopen,reopens,reopened
;;
-;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash
+;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash, fast-forward-only
;DEFAULT_MERGE_STYLE = merge
;;
;; In the default merge message for squash commits include at most this many commits
@@ -1470,6 +1474,9 @@ LEVEL = Info
;;
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
;DEFAULT_EMAIL_NOTIFICATIONS = enabled
+;; Disabled features for users, could be "deletion", more features can be disabled in future
+;; - deletion: a user cannot delete their own account
+;USER_DISABLED_FEATURES =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docs/content/administration/backup-and-restore.en-us.md b/docs/content/administration/backup-and-restore.en-us.md
index d46efecf99..451ef5c944 100644
--- a/docs/content/administration/backup-and-restore.en-us.md
+++ b/docs/content/administration/backup-and-restore.en-us.md
@@ -92,7 +92,7 @@ cd gitea-dump-1610949662
mv app.ini /etc/gitea/conf/app.ini
mv data/* /var/lib/gitea/data/
mv log/* /var/lib/gitea/log/
-mv repos/* /var/lib/gitea/gitea-repositories/
+mv repos/* /var/lib/gitea/data/gitea-repositories/
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
# mysql
@@ -111,6 +111,8 @@ With Gitea running, and from the directory Gitea's binary is located, execute: `
This ensures that application and configuration file paths in repository Git Hooks are consistent and applicable to the current installation. If these paths are not updated, repository `push` actions will fail.
+If you still have issues, consider running `./gitea doctor check` to inspect possible errors (or run with `--fix`).
+
### Using Docker (`restore`)
There is also no support for a recovery command in a Docker-based gitea instance. The restore process contains the same steps as described in the previous section but with different paths.
diff --git a/docs/content/administration/backup-and-restore.zh-cn.md b/docs/content/administration/backup-and-restore.zh-cn.md
index 98d378d5dc..db7eba84f7 100644
--- a/docs/content/administration/backup-and-restore.zh-cn.md
+++ b/docs/content/administration/backup-and-restore.zh-cn.md
@@ -19,6 +19,12 @@ menu:
Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一个zip压缩文件。该压缩文件可以被用来进行数据恢复。
+## 备份一致性
+
+为了确保 Gitea 实例的一致性,在备份期间必须关闭它。
+
+Gitea 包括数据库、文件和 Git 仓库,当它被使用时所有这些都会发生变化。例如,当迁移正在进行时,在数据库中创建一个事务,而 Git 仓库正在被复制。如果备份发生在迁移的中间,Git 仓库可能是不完整的,尽管数据库声称它是完整的,因为它是在之后被转储的。避免这种竞争条件的唯一方法是在备份期间停止 Gitea 实例。
+
## 备份命令 (`dump`)
先转到git用户的权限: `su git`. 再Gitea目录运行 `./gitea dump`。一般会显示类似如下的输出:
@@ -34,15 +40,43 @@ Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一
最后生成的 `gitea-dump-1482906742.zip` 文件将会包含如下内容:
-* `custom` - 所有保存在 `custom/` 目录下的配置和自定义的文件。
-* `data` - 数据目录下的所有内容不包含使用文件session的文件。该目录包含 `attachments`, `avatars`, `lfs`, `indexers`, 如果使用sqlite 还会包含 sqlite 数据库文件。
+* `app.ini` - 如果原先存储在默认的 custom/ 目录之外,则是配置文件的可选副本
+* `custom/` - 所有保存在 `custom/` 目录下的配置和自定义的文件。
+* `data/` - 数据目录(APP_DATA_PATH),如果使用文件会话,则不包括会话。该目录包括 `attachments`、`avatars`、`lfs`、`indexers`、如果使用 SQLite 则包括 SQLite 文件。
+* `repos/` - 仓库目录的完整副本。
* `gitea-db.sql` - 数据库dump出来的 SQL。
-* `gitea-repo.zip` - Git仓库压缩文件。
* `log/` - Logs文件,如果用作迁移不是必须的。
中间备份文件将会在临时目录进行创建,如果您要重新指定临时目录,可以用 `--tempdir` 参数,或者用 `TMPDIR` 环境变量。
-## Restore Command (`restore`)
+## 备份数据库
+
+`gitea dump` 创建的 SQL 转储使用 XORM,Gitea 管理员可能更喜欢使用本地的 MySQL 和 PostgreSQL 转储工具。使用 XORM 转储数据库时仍然存在一些问题,可能会导致在尝试恢复时出现问题。
+
+```sh
+# mysql
+mysqldump -u$USER -p$PASS --database $DATABASE > gitea-db.sql
+# postgres
+pg_dump -U $USER $DATABASE > gitea-db.sql
+```
+
+### 使用Docker (`dump`)
+
+在使用 Docker 时,使用 `dump` 命令有一些注意事项。
+
+必须以 `gitea/conf/app.ini` 中指定的 `RUN_USER = ` 执行该命令;并且,为了让备份文件夹的压缩过程能够顺利执行,`docker exec` 命令必须在 `--tempdir` 内部执行。
+
+示例:
+
+```none
+docker exec -u -it -w <--tempdir> $(docker ps -qf 'name=^$') bash -c '/usr/local/bin/gitea dump -c '
+```
+
+\*注意:`--tempdir` 指的是 Gitea 使用的 Docker 环境的临时目录;如果您没有指定自定义的 `--tempdir`,那么 Gitea 将使用 `/tmp` 或 Docker 容器的 `TMPDIR` 环境变量。对于 `--tempdir`,请相应调整您的 `docker exec` 命令选项。
+
+结果应该是一个文件,存储在指定的 `--tempdir` 中,类似于:`gitea-dump-1482906742.zip`
+
+## 恢复命令 (`restore`)
当前还没有恢复命令,恢复需要人工进行。主要是把文件和数据库进行恢复。
@@ -51,10 +85,10 @@ Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一
```sh
unzip gitea-dump-1610949662.zip
cd gitea-dump-1610949662
-mv data/conf/app.ini /etc/gitea/conf/app.ini
+mv app.ini /etc/gitea/conf/app.ini
mv data/* /var/lib/gitea/data/
mv log/* /var/lib/gitea/log/
-mv repos/* /var/lib/gitea/repositories/
+mv repos/* /var/lib/gitea/gitea-repositories/
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
# mysql
@@ -66,3 +100,55 @@ psql -U $USER -d $DATABASE < gitea-db.sql
service gitea restart
```
+
+如果安装方式发生了变化(例如 二进制 -> Docker),或者 Gitea 安装到了与之前安装不同的目录,则需要重新生成仓库 Git 钩子。
+
+在 Gitea 运行时,并从 Gitea 二进制文件所在的目录执行:`./gitea admin regenerate hooks`
+
+这样可以确保仓库 Git 钩子中的应用程序和配置文件路径与当前安装一致。如果这些路径没有更新,仓库的 `push` 操作将失败。
+
+### 使用 Docker (`restore`)
+
+在基于 Docker 的 Gitea 实例中,也没有恢复命令的支持。恢复过程与前面描述的步骤相同,但路径不同。
+
+示例:
+
+```sh
+# 在容器中打开 bash 会话
+docker exec --user git -it 2a83b293548e bash
+# 在容器内解压您的备份文件
+unzip gitea-dump-1610949662.zip
+cd gitea-dump-1610949662
+# 恢复 Gitea 数据
+mv data/* /data/gitea
+# 恢复仓库本身
+mv repos/* /data/git/gitea-repositories/
+# 调整文件权限
+chown -R git:git /data
+# 重新生成 Git 钩子
+/usr/local/bin/gitea -c '/data/gitea/conf/app.ini' admin regenerate hooks
+```
+
+Gitea 容器中的默认用户是 `git`(1000:1000)。请用您的 Gitea 容器 ID 或名称替换 `2a83b293548e`。
+
+### 使用 Docker-rootless (`restore`)
+
+在 Docker-rootless 容器中的恢复工作流程只是要使用的目录不同:
+
+```sh
+# 在容器中打开 bash 会话
+docker exec --user git -it 2a83b293548e bash
+# 在容器内解压您的备份文件
+unzip gitea-dump-1610949662.zip
+cd gitea-dump-1610949662
+# 恢复 app.ini
+mv data/conf/app.ini /etc/gitea/app.ini
+# 恢复 Gitea 数据
+mv data/* /var/lib/gitea
+# 恢复仓库本身
+mv repos/* /var/lib/gitea/git/gitea-repositories
+# 调整文件权限
+chown -R git:git /etc/gitea/app.ini /var/lib/gitea
+# 重新生成 Git 钩子
+/usr/local/bin/gitea -c '/etc/gitea/app.ini' admin regenerate hooks
+```
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index 33732d080b..643932de6c 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -126,7 +126,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
keywords used in Pull Request comments to automatically close a related issue
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: List of keywords used in Pull Request comments to automatically reopen
a related issue
-- `DEFAULT_MERGE_STYLE`: **merge**: Set default merge style for repository creating, valid options: `merge`, `rebase`, `rebase-merge`, `squash`
+- `DEFAULT_MERGE_STYLE`: **merge**: Set default merge style for repository creating, valid options: `merge`, `rebase`, `rebase-merge`, `squash`, `fast-forward-only`
- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: In the default merge message for squash commits include at most this many commits. Set to `-1` to include all commits
- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: In the default merge message for squash commits limit the size of the commit messages. Set to `-1` to have no limit. Only used if `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES` is `true`.
- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: In the default merge message for squash commits walk all commits to include all authors in the Co-authored-by otherwise just use those in the limited list
@@ -458,6 +458,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `MAX_IDLE_CONNS` **2**: Max idle database connections on connection pool, default is 2 - this will be capped to `MAX_OPEN_CONNS`.
- `CONN_MAX_LIFETIME` **0 or 3s**: Sets the maximum amount of time a DB connection may be reused - default is 0, meaning there is no limit (except on MySQL where it is 3s - see #6804 & #7071).
- `AUTO_MIGRATION` **true**: Whether execute database models migrations automatically.
+- `SLOW_QUERY_THRESHOLD` **5s**: Threshold value in seconds beyond which query execution time is logged as a warning in the xorm logger.
[^1]: It may be necessary to specify a hostport even when listening on a unix socket, as the port is part of the socket name. see [#24552](https://github.com/go-gitea/gitea/issues/24552#issuecomment-1681649367) for additional details.
@@ -517,6 +518,8 @@ And the following unique queues:
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
- `DISABLE_REGULAR_ORG_CREATION`: **false**: Disallow regular (non-admin) users from creating organizations.
+- `USER_DISABLED_FEATURES`: **_empty_** Disabled features for users, could be `deletion` and more features can be added in future.
+ - `deletion`: User cannot delete their own account.
## Security (`security`)
diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md
index 2cee70daab..5fe0a62215 100644
--- a/docs/content/administration/config-cheat-sheet.zh-cn.md
+++ b/docs/content/administration/config-cheat-sheet.zh-cn.md
@@ -29,7 +29,7 @@ menu:
[ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。
标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。
-在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`enviroment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。
+在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`environment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。
包含`#`或者`;`的变量必须使用引号(`` ` ``或者`""""`)包裹,否则会被解析为注释。
@@ -125,7 +125,7 @@ menu:
- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: 在拉取请求评论中用于自动关闭相关问题的关键词列表。
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: 在拉取请求评论中用于自动重新打开相关问题的
关键词列表。
-- `DEFAULT_MERGE_STYLE`: **merge**: 设置创建仓库的默认合并方式,可选: `merge`, `rebase`, `rebase-merge`, `squash`
+- `DEFAULT_MERGE_STYLE`: **merge**: 设置创建仓库的默认合并方式,可选: `merge`, `rebase`, `rebase-merge`, `squash`, `fast-forward-only`
- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: 在默认合并消息中,对于`squash`提交,最多包括此数量的提交。设置为 -1 以包括所有提交。
- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: 在默认的合并消息中,对于`squash`提交,限制提交消息的大小。设置为 `-1`以取消限制。仅在`POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`为`true`时使用。
- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: 在默认合并消息中,对于`squash`提交,遍历所有提交以包括所有作者的`Co-authored-by`,否则仅使用限定列表中的作者。
@@ -497,6 +497,8 @@ Gitea 创建以下非唯一队列:
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**:用户电子邮件通知的默认配置(用户可配置)。选项:enabled、onmention、disabled
- `DISABLE_REGULAR_ORG_CREATION`: **false**:禁止普通(非管理员)用户创建组织。
+- `USER_DISABLED_FEATURES`:**_empty_** 禁用的用户特性,当前允许为空或者 `deletion`, 未来可以增加更多设置。
+ - `deletion`: 用户不能通过界面或者API删除他自己。
## 安全性 (`security`)
diff --git a/docs/content/administration/customizing-gitea.en-us.md b/docs/content/administration/customizing-gitea.en-us.md
index d122fb4bfa..7efddb2824 100644
--- a/docs/content/administration/customizing-gitea.en-us.md
+++ b/docs/content/administration/customizing-gitea.en-us.md
@@ -284,7 +284,7 @@ syntax and shouldn't be touched without fully understanding these components.
Google Analytics, Matomo (previously Piwik), and other analytics services can be added to Gitea. To add the tracking code, refer to the `Other additions to the page` section of this document, and add the JavaScript to the `$GITEA_CUSTOM/templates/custom/header.tmpl` file.
-## Customizing gitignores, labels, licenses, locales, and readmes.
+## Customizing gitignores, labels, licenses, locales, and readmes
Place custom files in corresponding sub-folder under `custom/options`.
diff --git a/docs/content/administration/https-support.en-us.md b/docs/content/administration/https-support.en-us.md
index 4e18722ddf..981a29bd85 100644
--- a/docs/content/administration/https-support.en-us.md
+++ b/docs/content/administration/https-support.en-us.md
@@ -35,7 +35,7 @@ CERT_FILE = cert.pem
KEY_FILE = key.pem
```
-Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to estalbish the trust relationship.
+Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to establish the trust relationship.
To learn more about the config values, please checkout the [Config Cheat Sheet](administration/config-cheat-sheet.md#server-server).
For the `CERT_FILE` or `KEY_FILE` field, the file path is relative to the `GITEA_CUSTOM` environment variable when it is a relative path. It can be an absolute path as well.
diff --git a/docs/content/administration/mail-templates.en-us.md b/docs/content/administration/mail-templates.en-us.md
index 32b352da4b..b642ff4aa7 100644
--- a/docs/content/administration/mail-templates.en-us.md
+++ b/docs/content/administration/mail-templates.en-us.md
@@ -222,7 +222,7 @@ Please check [Gitea's logs](administration/logging-config.md) for error messages
{{.Repo}}#{{.Issue.Index}} .
{{if not (eq .Body "")}}
- Message content:
+ Message content
{{.Body | Str2html}}
{{end}}
@@ -245,7 +245,7 @@ This template produces something along these lines:
> [@rhonda](#) (Rhonda Myers) updated [mike/stuff#38](#).
>
-> #### Message content:
+> #### Message content
>
> \_********************************\_********************************
>
@@ -266,7 +266,7 @@ the messages. Here's a list of some of them:
| `AppDomain` | - | Any | Gitea's host name |
| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed |
| `Str2html` | string | Body only | Sanitizes text by removing any HTML tags from it. |
-| `Safe` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. |
+| `SafeHTML` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. |
These are _functions_, not metadata, so they have to be used:
diff --git a/docs/content/administration/mail-templates.zh-cn.md b/docs/content/administration/mail-templates.zh-cn.md
index 588f0b2ccb..fd455ef3a8 100644
--- a/docs/content/administration/mail-templates.zh-cn.md
+++ b/docs/content/administration/mail-templates.zh-cn.md
@@ -228,7 +228,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
> [@rhonda](#)(Rhonda Myers)更新了 [mike/stuff#38](#)。
>
-> #### 消息内容:
+> #### 消息内容
>
> \_********************************\_********************************
>
@@ -242,14 +242,14 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
模板系统包含一些函数,可用于进一步处理和格式化消息。以下是其中一些函数的列表:
-| 函数名 | 参数 | 可用于 | 用法 |
-| ----------------- | ----------- | ------------ | --------------------------------------------------------------------------------- |
-| `AppUrl` | - | 任何地方 | Gitea 的 URL |
-| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" |
-| `AppDomain` | - | 任何地方 | Gitea 的主机名 |
-| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 |
-| `Str2html` | string | 仅正文部分 | 通过删除其中的 HTML 标签对文本进行清理 |
-| `Safe` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于 `.ReviewComments.RenderedContent` 等字段 |
+| 函数名 | 参数 | 可用于 | 用法 |
+|------------------| ----------- | ------------ | --------------------------------------------------------------------------------- |
+| `AppUrl` | - | 任何地方 | Gitea 的 URL |
+| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" |
+| `AppDomain` | - | 任何地方 | Gitea 的主机名 |
+| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 |
+| `Str2html` | string | 仅正文部分 | 通过删除其中的 HTML 标签对文本进行清理 |
+| `SafeHTML` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于 `.ReviewComments.RenderedContent` 等字段 |
这些都是 _函数_,而不是元数据,因此必须按以下方式使用:
diff --git a/docs/content/contributing/guidelines-backend.en-us.md b/docs/content/contributing/guidelines-backend.en-us.md
index 084b3886e8..3159a5ff7d 100644
--- a/docs/content/contributing/guidelines-backend.en-us.md
+++ b/docs/content/contributing/guidelines-backend.en-us.md
@@ -101,6 +101,10 @@ i.e. `services/user`, `models/repository`.
Since there are some packages which use the same package name, it is possible that you find packages like `modules/user`, `models/user`, and `services/user`. When these packages are imported in one Go file, it's difficult to know which package we are using and if it's a variable name or an import name. So, we always recommend to use import aliases. To differ from package variables which are commonly in camelCase, just use **snake_case** for import aliases.
i.e. `import user_service "code.gitea.io/gitea/services/user"`
+### Implementing `io.Closer`
+
+If a type implements `io.Closer`, calling `Close` multiple times must not fail or `panic` but return an error or `nil`.
+
### Important Gotchas
- Never write `x.Update(exemplar)` without an explicit `WHERE` clause:
diff --git a/docs/content/contributing/guidelines-frontend.en-us.md b/docs/content/contributing/guidelines-frontend.en-us.md
index edd89e1231..a33a38a6f9 100644
--- a/docs/content/contributing/guidelines-frontend.en-us.md
+++ b/docs/content/contributing/guidelines-frontend.en-us.md
@@ -34,7 +34,7 @@ The source files can be found in the following directories:
We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html) and [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)
-### Gitea specific guidelines:
+### Gitea specific guidelines
1. Every feature (Fomantic-UI/jQuery module) should be put in separate files/directories.
2. HTML ids and classes should use kebab-case, it's preferred to contain 2-3 feature related keywords.
diff --git a/docs/content/contributing/guidelines-frontend.zh-cn.md b/docs/content/contributing/guidelines-frontend.zh-cn.md
index 66a4d4b4d6..43f72b4808 100644
--- a/docs/content/contributing/guidelines-frontend.zh-cn.md
+++ b/docs/content/contributing/guidelines-frontend.zh-cn.md
@@ -34,7 +34,7 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。
我们推荐使用[Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html)和[Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)。
-## Gitea 特定准则:
+## Gitea 特定准则
1. 每个功能(Fomantic-UI/jQuery 模块)应放在单独的文件/目录中。
2. HTML 的 id 和 class 应使用 kebab-case,最好包含2-3个与功能相关的关键词。
@@ -48,6 +48,7 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。
10. 避免在一个事件监听器中混合不同的事件,优先为每个事件使用独立的事件监听器。
11. 推荐使用自定义事件名称前缀`ce-`。
12. Gitea 的 tailwind-style CSS 类使用`gt-`前缀(`gt-relative`),而 Gitea 自身的私有框架级 CSS 类使用`g-`前缀(`g-modal-confirm`)。
+13. 尽量避免内联脚本和样式,建议将JS代码放入JS文件中并使用CSS类。如果内联脚本和样式不可避免,请解释无法避免的原因。
### 可访问性 / ARIA
@@ -64,18 +65,21 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari
* Vue + Vanilla JS
* Fomantic-UI(jQuery)
+* htmx (部分页面重新加载其他静态组件)
* Vanilla JS
不推荐的实现方式:
* Vue + Fomantic-UI(jQuery)
* jQuery + Vanilla JS
+* htmx + 任何其他需要大量 JavaScript 代码或不必要的功能,如 htmx 脚本 (`hx-on`)
为了保持界面一致,Vue 组件可以使用 Fomantic-UI 的 CSS 类。
尽管不建议混合使用不同的框架,
+我们使用 htmx 进行简单的交互。您可以在此 [PR](https://github.com/go-gitea/gitea/pull/28908) 中查看一个简单交互的示例,其中应使用 htmx。如果您需要更高级的反应性,请不要使用 htmx,请使用其他框架(Vue/Vanilla JS)。
但如果混合使用是必要的,并且代码设计良好且易于维护,也可以工作。
-### async 函数
+### `async` 函数
只有当函数内部存在`await`调用或返回`Promise`时,才将函数标记为`async`。
@@ -91,6 +95,12 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari
这是有意为之的,我们想调用异步函数并忽略Promise。
一些 lint 规则和 IDE 也会在未处理返回的 Promise 时发出警告。
+### 获取数据
+
+要获取数据,请使用`modules/fetch.js`中的包装函数`GET`、`POST`等。他们
+接受内容的`data`选项,将自动设置 CSRF 令牌并返回
+[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)。
+
### HTML 属性和 dataset
禁止使用`dataset`,它的驼峰命名行为使得搜索属性变得困难。
@@ -132,3 +142,7 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari
### Vue3 和 JSX
Gitea 现在正在使用 Vue3。我们决定不引入 JSX,以保持 HTML 代码和 JavaScript 代码分离。
+
+### UI示例
+
+Gitea 使用一些自制的 UI 元素并自定义其他元素,以将它们更好地集成到通用 UI 方法中。当在开发模式(`RUN_MODE=dev`)下运行 Gitea 时,在 `http(s)://your-gitea-url:port/devtest` 下会提供一个包含一些标准化 UI 示例的页面。
diff --git a/docs/content/development/api-usage.zh-cn.md b/docs/content/development/api-usage.zh-cn.md
index 96c1997294..d7aca16f7f 100644
--- a/docs/content/development/api-usage.zh-cn.md
+++ b/docs/content/development/api-usage.zh-cn.md
@@ -60,7 +60,7 @@ curl "http://localhost:4000/api/v1/repos/test1/test1/issues" \
`/users/:name/tokens` 是一个特殊的接口,需要您使用 basic authentication 进行认证,具体原因在 issue 中
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346) 有所提及,使用方法如下所示:
-### 使用 Basic authentication 认证:
+### 使用 Basic authentication 认证
```
$ curl --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md
index 4b132c49d9..df8a9047d6 100644
--- a/docs/content/development/hacking-on-gitea.en-us.md
+++ b/docs/content/development/hacking-on-gitea.en-us.md
@@ -243,10 +243,10 @@ documentation using:
make generate-swagger
```
-You should validate your generated Swagger file and spell-check it with:
+You should validate your generated Swagger file:
```bash
-make swagger-validate misspell-check
+make swagger-validate
```
You should commit the changed swagger JSON file. The continuous integration
diff --git a/docs/content/development/hacking-on-gitea.zh-cn.md b/docs/content/development/hacking-on-gitea.zh-cn.md
index 364bbf1ffe..2dba3c92b6 100644
--- a/docs/content/development/hacking-on-gitea.zh-cn.md
+++ b/docs/content/development/hacking-on-gitea.zh-cn.md
@@ -228,10 +228,10 @@ Gitea Logo的 PNG 和 SVG 版本是使用 `TAGS="gitea" make generate-images`
make generate-swagger
```
-您应该验证生成的 Swagger 文件并使用以下命令对其进行拼写检查:
+您应该验证生成的 Swagger 文件:
```bash
-make swagger-validate misspell-check
+make swagger-validate
```
您应该提交更改后的 swagger JSON 文件。持续集成服务器将使用以下方法检查是否已完成:
diff --git a/docs/content/help/support.zh-cn.md b/docs/content/help/support.zh-cn.md
index de56d8abe0..91b37c586c 100644
--- a/docs/content/help/support.zh-cn.md
+++ b/docs/content/help/support.zh-cn.md
@@ -15,11 +15,64 @@ menu:
identifier: "support"
---
-## 需要帮助?
+# 支持选项
-如果您在使用或者开发过程中遇到问题,请到以下渠道咨询:
+- [付费商业支持](https://about.gitea.com/)
+- [Discord](https://discord.gg/Gitea)
+- [Discourse 论坛](https://discourse.gitea.io/)
+- [Matrix](https://matrix.to/#/#gitea-space:matrix.org)
+ - 注意:大多数 Matrix 频道都与 Discord 中的对应频道桥接,可能在桥接过程中会出现一定程度的不稳定性。
+- 中文支持
+ - [Discourse 中文分类](https://discourse.gitea.io/c/5-category/5)
+ - QQ 群 328432459
-- 到 [GitHub Issue](https://github.com/go-gitea/gitea/issues) 提问(因为项目维护人员来自世界各地,为保证沟通顺畅,请使用英文提问)
-- 中文问题到 [Gitea 论坛](https://discourse.gitea.io/c/5-category/5) 提问
-- 访问 [Discord Gitea 聊天室 - 英文](https://discord.gg/Gitea)
-- 加入 QQ群 328432459 获得进一步的支持
+# Bug 报告
+
+如果您发现了 Bug,请在 GitHub 上 [创建一个问题](https://github.com/go-gitea/gitea/issues)。
+
+**注意:** 在请求支持时,可能需要准备以下信息,以便帮助者获得所需的所有信息:
+
+1. 您的 `app.ini`(将任何敏感数据进行必要的清除)。
+2. 您看到的任何错误消息。
+3. Gitea 日志以及与情况相关的所有其他日志。
+ - 收集 `trace` / `debug` 级别的日志更有用(参见下一节)。
+ - 在使用 systemd 时,使用 `journalctl --lines 1000 --unit gitea` 收集日志。
+ - 在使用 Docker 时,使用 `docker logs --tail 1000 ` 收集日志。
+4. 可重现的步骤,以便他人能够更快速、更容易地重现和理解问题。
+ - [try.gitea.io](https://try.gitea.io) 可用于重现问题。
+5. 如果遇到慢速/挂起/死锁等问题,请在出现问题时报告堆栈跟踪。
+ 转到 "Site Admin" -> "Monitoring" -> "Stacktrace" -> "Download diagnosis report"。
+
+# 高级 Bug 报告提示
+
+## 更多日志的配置选项
+
+默认情况下,日志以 `info` 级别输出到控制台。
+如果您需要设置日志级别和/或从文件中收集日志,
+您只需将以下配置复制到您的 `app.ini` 中(删除所有其他 `[log]` 部分),
+然后您将在 Gitea 的日志目录中找到 `*.log` 文件(默认为 `%(GITEA_WORK_DIR)/log`)。
+
+```ini
+; 要显示所有 SQL 日志,您还可以在 [database] 部分中设置 LOG_SQL=true
+[log]
+LEVEL=debug
+MODE=console,file
+```
+
+## 使用命令行收集堆栈跟踪
+
+Gitea 可以使用 Golang 的 pprof 处理程序和工具链来收集堆栈跟踪和其他运行时信息。
+
+如果 Web UI 停止工作,您可以尝试通过命令行收集堆栈跟踪:
+
+1. 设置 app.ini:
+
+ ```
+ [server]
+ ENABLE_PPROF = true
+ ```
+
+2. 重新启动 Gitea
+
+3. 尝试触发bug,当请求卡住一段时间,使用或浏览器访问:获取堆栈跟踪。
+`curl http://127.0.0.1:6060/debug/pprof/goroutine?debug=1`
diff --git a/docs/content/installation/database-preparation.zh-cn.md b/docs/content/installation/database-preparation.zh-cn.md
index d651088395..3fde004a8c 100644
--- a/docs/content/installation/database-preparation.zh-cn.md
+++ b/docs/content/installation/database-preparation.zh-cn.md
@@ -17,7 +17,9 @@ menu:
# 数据库准备
-在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>= 12)、MySQL(>= 8.0)、SQLite 和 MSSQL(>= 2012 SP4)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。
+在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>= 12)、MySQL(>= 8.0)、MariaDB(>= 10.4)、SQLite(内置) 和 MSSQL(>= 2012 SP4)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。
+
+如果您使用不受支持的数据库版本,请通过 [联系我们](/help/support) 以获取有关我们的扩展支持的信息。我们可以为旧数据库提供测试和支持,并将这些修复集成到 Gitea 代码库中。
数据库实例可以与 Gitea 实例在相同机器上(本地数据库),也可以与 Gitea 实例在不同机器上(远程数据库)。
@@ -61,7 +63,9 @@ menu:
4. 使用 UTF-8 字符集和大小写敏感的排序规则创建数据库。
- Gitea 启动后会尝试把数据库修改为更合适的字符集,如果你想指定自己的字符集规则,可以在 app.ini 中设置 `[database].CHARSET_COLLATION`。
+ `utf8mb4_bin` 是 MySQL/MariaDB 的通用排序规则。
+ Gitea 启动后会尝试把数据库修改为更合适的字符集 (`utf8mb4_0900_as_cs` 或者 `uca1400_as_cs`) 并在可能的情况下更改数据库。
+ 如果你想指定自己的字符集规则,可以在 `app.ini` 中设置 `[database].CHARSET_COLLATION`。
```sql
CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_bin';
@@ -85,7 +89,7 @@ menu:
FLUSH PRIVILEGES;
```
-6. 通过 exit 退出数据库控制台。
+6. 通过 `exit` 退出数据库控制台。
7. 在您的 Gitea 服务器上,测试与数据库的连接:
@@ -93,13 +97,13 @@ menu:
mysql -u gitea -h 203.0.113.3 -p giteadb
```
- 其中 `gitea` 是数据库用户名,`giteadb` 是数据库名称,`203.0.113.3` 是数据库实例的 IP 地址。对于本地数据库,省略 -h 选项。
+ 其中 `gitea` 是数据库用户名,`giteadb` 是数据库名称,`203.0.113.3` 是数据库实例的 IP 地址。对于本地数据库,省略 `-h` 选项。
到此您应该能够连接到数据库了。
## PostgreSQL
-1. 对于远程数据库设置,通过编辑数据库实例上的 postgresql.conf 文件中的 listen_addresses 将 PostgreSQL 配置为监听您的 IP 地址:
+1. 对于远程数据库设置,通过编辑数据库实例上的 postgresql.conf 文件中的 `listen_addresses` 将 `PostgreSQL` 配置为监听您的 IP 地址:
```ini
listen_addresses = 'localhost, 203.0.113.3'
diff --git a/docs/content/installation/from-source.en-us.md b/docs/content/installation/from-source.en-us.md
index 601e074745..cd9fd56511 100644
--- a/docs/content/installation/from-source.en-us.md
+++ b/docs/content/installation/from-source.en-us.md
@@ -27,13 +27,7 @@ Next, [install Node.js with npm](https://nodejs.org/en/download/) which is
required to build the JavaScript and CSS files. The minimum supported Node.js
version is @minNodeVersion@ and the latest LTS version is recommended.
-**Note**: When executing make tasks that require external tools, like
-`make misspell-check`, Gitea will automatically download and build these as
-necessary. To be able to use these, you must have the `"$GOPATH/bin"` directory
-on the executable path. If you don't add the go bin directory to the
-executable path, you will have to manage this yourself.
-
-**Note 2**: Go version @minGoVersion@ or higher is required. However, it is recommended to
+**Note**: Go version @minGoVersion@ or higher is required. However, it is recommended to
obtain the same version as our continuous integration, see the advice given in
[Hacking on Gitea](development/hacking-on-gitea.md)
diff --git a/docs/content/installation/from-source.zh-cn.md b/docs/content/installation/from-source.zh-cn.md
index c2bd5785b2..3ff7efb4ed 100644
--- a/docs/content/installation/from-source.zh-cn.md
+++ b/docs/content/installation/from-source.zh-cn.md
@@ -21,9 +21,7 @@ menu:
接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-cn/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。
-**注意**:当执行需要外部工具的 make 任务(如`make misspell-check`)时,Gitea 将根据需要自动下载和构建这些工具。为了能够实现这个目的,你必须将`"$GOPATH/bin"`目录添加到可执行路径中。如果没有将 Go 的二进制目录添加到可执行路径中,你需要自行解决产生的问题。
-
-**注意2**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。
+**注意**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。
## 下载
diff --git a/docs/content/installation/windows-service.zh-cn.md b/docs/content/installation/windows-service.zh-cn.md
index 985492b7e8..d5761d2c19 100644
--- a/docs/content/installation/windows-service.zh-cn.md
+++ b/docs/content/installation/windows-service.zh-cn.md
@@ -15,7 +15,7 @@ menu:
identifier: "windows-service"
---
-# 准备工作
+## 准备工作
在 C:\gitea\custom\conf\app.ini 中进行了以下更改:
@@ -27,7 +27,7 @@ RUN_USER = COMPUTERNAME$
COMPUTERNAME 是从命令行中运行 `echo %COMPUTERNAME%` 后得到的响应。如果响应是 `USER-PC`,那么 `RUN_USER = USER-PC$`。
-## 使用绝对路径
+### 使用绝对路径
如果您使用 SQLite3,请将 `PATH` 更改为包含完整路径:
@@ -36,7 +36,7 @@ COMPUTERNAME 是从命令行中运行 `echo %COMPUTERNAME%` 后得到的响应
PATH = c:/gitea/data/gitea.db
```
-# 注册为Windows服务
+## 注册为Windows服务
要注册为Windows服务,首先以Administrator身份运行 `cmd`,然后执行以下命令:
@@ -48,7 +48,16 @@ sc.exe create gitea start= auto binPath= "\"C:\gitea\gitea.exe\" web --config \"
之后在控制面板打开 "Windows Services",搜索 "gitea",右键选择 "Run"。在浏览器打开 `http://localhost:3000` 就可以访问了。(如果你修改了端口,请访问对应的端口,3000是默认端口)。
-## 添加启动依赖项
+### 服务启动类型
+
+据观察,在启动期间加载的系统上,Gitea 服务可能无法启动,并在 Windows 事件日志中记录超时。
+在这种情况下,将启动类型更改为`Automatic-Delayed`。这可以在服务创建期间完成,或者通过运行配置命令来完成。
+
+```
+sc.exe config gitea start= delayed-auto
+```
+
+### 添加启动依赖项
要将启动依赖项添加到 Gitea Windows 服务(例如 Mysql、Mariadb),作为管理员,然后运行以下命令:
diff --git a/docs/content/usage/actions/act-runner.en-us.md b/docs/content/usage/actions/act-runner.en-us.md
index 3fad9cbfe8..b2806bf5dd 100644
--- a/docs/content/usage/actions/act-runner.en-us.md
+++ b/docs/content/usage/actions/act-runner.en-us.md
@@ -120,6 +120,8 @@ A registration token can also be obtained from the gitea [command-line interface
gitea --config /etc/gitea/app.ini actions generate-runner-token
```
+Tokens are valid for registering multiple runners, until they are revoked and replaced by a new token using the token reset link in the web interface.
+
### Register the runner
The act runner can be registered by running the following command:
diff --git a/docs/content/usage/actions/comparison.zh-cn.md b/docs/content/usage/actions/comparison.zh-cn.md
index dbe9ca007d..16b2181ba2 100644
--- a/docs/content/usage/actions/comparison.zh-cn.md
+++ b/docs/content/usage/actions/comparison.zh-cn.md
@@ -95,12 +95,6 @@ Gitea Actions目前不支持此功能,如果使用它,结果将始终为空
## 缺失的功能
-### 变量
-
-请参阅[变量](https://docs.github.com/zh/actions/learn-github-actions/variables)。
-
-目前变量功能正在开发中。
-
### 问题匹配器
问题匹配器是一种扫描Actions输出以查找指定正则表达式模式并在用户界面中突出显示该信息的方法。
diff --git a/docs/content/usage/actions/quickstart.en-us.md b/docs/content/usage/actions/quickstart.en-us.md
index 2a2cf72584..0514b6ddf2 100644
--- a/docs/content/usage/actions/quickstart.en-us.md
+++ b/docs/content/usage/actions/quickstart.en-us.md
@@ -61,8 +61,8 @@ It is always a bad idea to use a loopback address such as `127.0.0.1` or `localh
If you are unsure which address to use, the LAN address is usually the right choice.
`token` is used for authentication and identification, such as `P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23`.
-It is one-time use only and cannot be used to register multiple runners.
-You can obtain different levels of 'tokens' from the following places to create the corresponding level of' runners':
+Each token can be used to create multiple runners, until it is replaced with a new token using the reset link.
+You can obtain different levels of 'tokens' from the following places to create the corresponding level of 'runners':
- Instance level: The admin settings page, like `/admin/actions/runners`.
- Organization level: The organization settings page, like `//settings/actions/runners`.
diff --git a/docs/content/usage/issue-pull-request-templates.en-us.md b/docs/content/usage/issue-pull-request-templates.en-us.md
index 34475e3465..b031b262fb 100644
--- a/docs/content/usage/issue-pull-request-templates.en-us.md
+++ b/docs/content/usage/issue-pull-request-templates.en-us.md
@@ -19,9 +19,10 @@ menu:
Some projects have a standard list of questions that users need to answer
when creating an issue or pull request. Gitea supports adding templates to the
-main branch of the repository so that they can autopopulate the form when users are
+**default branch of the repository** so that they can autopopulate the form when users are
creating issues and pull requests. This will cut down on the initial back and forth
of getting some clarifying details.
+It is currently not possible to provide generic issue/pull-request templates globally.
Additionally, the New Issue page URL can be suffixed with `?title=Issue+Title&body=Issue+Text` and the form will be populated with those strings. Those strings will be used instead of the template if there is one.
diff --git a/docs/content/usage/packages/container.en-us.md b/docs/content/usage/packages/container.en-us.md
index 6be21c2b27..5676aa36fb 100644
--- a/docs/content/usage/packages/container.en-us.md
+++ b/docs/content/usage/packages/container.en-us.md
@@ -39,6 +39,16 @@ Images must follow this naming convention:
`{registry}/{owner}/{image}`
+When building your docker image, using the naming convention above, this looks like:
+
+```shell
+# build an image with tag
+docker build -t {registry}/{owner}/{image}:{tag} .
+# name an existing image with tag
+docker tag {some-existing-image}:{tag} {registry}/{owner}/{image}:{tag}
+```
+
+where your registry is the domain of your gitea instance (e.g. gitea.example.com).
For example, these are all valid image names for the owner `testuser`:
`gitea.example.com/testuser/myimage`
diff --git a/docs/content/usage/packages/overview.en-us.md b/docs/content/usage/packages/overview.en-us.md
index 44d18ff482..89fc6f286e 100644
--- a/docs/content/usage/packages/overview.en-us.md
+++ b/docs/content/usage/packages/overview.en-us.md
@@ -42,7 +42,7 @@ The following package managers are currently supported:
| [PyPI](usage/packages/pypi.md) | Python | `pip`, `twine` |
| [RPM](usage/packages/rpm.md) | - | `yum`, `dnf`, `zypper` |
| [RubyGems](usage/packages/rubygems.md) | Ruby | `gem`, `Bundler` |
-| [Swift](usage/packages/rubygems.md) | Swift | `swift` |
+| [Swift](usage/packages/swift.md) | Swift | `swift` |
| [Vagrant](usage/packages/vagrant.md) | - | `vagrant` |
**The following paragraphs only apply if Packages are not globally disabled!**
diff --git a/docs/content/usage/packages/swift.en-us.md b/docs/content/usage/packages/swift.en-us.md
index 606fa20b36..38eb155641 100644
--- a/docs/content/usage/packages/swift.en-us.md
+++ b/docs/content/usage/packages/swift.en-us.md
@@ -26,7 +26,8 @@ To work with the Swift package registry, you need to use [swift](https://www.swi
To register the package registry and provide credentials, execute:
```shell
-swift package-registry set https://gitea.example.com/api/packages/{owner}/swift -login {username} -password {password}
+swift package-registry set https://gitea.example.com/api/packages/{owner}/swift
+swift package-registry login https://gitea.example.com/api/packages/{owner}/swift --username {username} --password {password}
```
| Placeholder | Description |
diff --git a/docs/content/usage/profile-readme.zh-cn.md b/docs/content/usage/profile-readme.zh-cn.md
index 804f69d2e6..b69d4aa921 100644
--- a/docs/content/usage/profile-readme.zh-cn.md
+++ b/docs/content/usage/profile-readme.zh-cn.md
@@ -15,6 +15,10 @@ menu:
# 个人资料 README
-要在您的 Gitea 个人资料页面显示一个 Markdown 文件,只需创建一个名为 ".profile" 的仓库,并编辑其中的 README.md 文件。Gitea 将自动获取该文件并在您的仓库上方显示。
+要在您的 Gitea 个人资料页面显示一个 Markdown 文件,只需创建一个名为 `.profile` 的仓库,并编辑其中的 `README.md` 文件。Gitea 将自动获取该文件并在您的仓库上方显示。
注意:您可以将此仓库设为私有。这样可以隐藏您的源文件,使其对公众不可见,并允许您将某些文件设为私有。但是,README.md 文件将是您个人资料上唯一存在的文件。如果您希望完全私有化 .profile 仓库,则需删除或重命名 README.md 文件。
+
+用户示例 `.profile/README.md`:
+
+![个人资料自述文件截图](/images/usage/profile-readme.png)
diff --git a/go.mod b/go.mod
index 7a752ec874..03f6ad1215 100644
--- a/go.mod
+++ b/go.mod
@@ -78,7 +78,6 @@ require (
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.26
github.com/minio/minio-go/v7 v7.0.66
- github.com/minio/sha256-simd v1.0.1
github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52
github.com/niklasfasching/go-org v1.7.0
@@ -230,6 +229,7 @@ require (
github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
+ github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
diff --git a/models/actions/artifact.go b/models/actions/artifact.go
index 5390f6288f..3d0a288e62 100644
--- a/models/actions/artifact.go
+++ b/models/actions/artifact.go
@@ -26,6 +26,8 @@ const (
ArtifactStatusUploadConfirmed // 2, ArtifactStatusUploadConfirmed is the status of an artifact upload that is confirmed
ArtifactStatusUploadError // 3, ArtifactStatusUploadError is the status of an artifact upload that is errored
ArtifactStatusExpired // 4, ArtifactStatusExpired is the status of an artifact that is expired
+ ArtifactStatusPendingDeletion // 5, ArtifactStatusPendingDeletion is the status of an artifact that is pending deletion
+ ArtifactStatusDeleted // 6, ArtifactStatusDeleted is the status of an artifact that is deleted
)
func init() {
@@ -147,8 +149,28 @@ func ListNeedExpiredArtifacts(ctx context.Context) ([]*ActionArtifact, error) {
Where("expired_unix < ? AND status = ?", timeutil.TimeStamp(time.Now().Unix()), ArtifactStatusUploadConfirmed).Find(&arts)
}
+// ListPendingDeleteArtifacts returns all artifacts in pending-delete status.
+// limit is the max number of artifacts to return.
+func ListPendingDeleteArtifacts(ctx context.Context, limit int) ([]*ActionArtifact, error) {
+ arts := make([]*ActionArtifact, 0, limit)
+ return arts, db.GetEngine(ctx).
+ Where("status = ?", ArtifactStatusPendingDeletion).Limit(limit).Find(&arts)
+}
+
// SetArtifactExpired sets an artifact to expired
func SetArtifactExpired(ctx context.Context, artifactID int64) error {
_, err := db.GetEngine(ctx).Where("id=? AND status = ?", artifactID, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusExpired)})
return err
}
+
+// SetArtifactNeedDelete sets an artifact to need-delete, cron job will delete it
+func SetArtifactNeedDelete(ctx context.Context, runID int64, name string) error {
+ _, err := db.GetEngine(ctx).Where("run_id=? AND artifact_name=? AND status = ?", runID, name, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusPendingDeletion)})
+ return err
+}
+
+// SetArtifactDeleted sets an artifact to deleted
+func SetArtifactDeleted(ctx context.Context, artifactID int64) error {
+ _, err := db.GetEngine(ctx).ID(artifactID).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusDeleted)})
+ return err
+}
diff --git a/models/actions/runner.go b/models/actions/runner.go
index 4103ba4477..b646146ee6 100644
--- a/models/actions/runner.go
+++ b/models/actions/runner.go
@@ -97,7 +97,7 @@ func (r *ActionRunner) StatusName() string {
}
func (r *ActionRunner) StatusLocaleName(lang translation.Locale) string {
- return lang.Tr("actions.runners.status." + r.StatusName())
+ return lang.TrString("actions.runners.status." + r.StatusName())
}
func (r *ActionRunner) IsOnline() bool {
diff --git a/models/actions/status.go b/models/actions/status.go
index c97578f2ac..eda2234137 100644
--- a/models/actions/status.go
+++ b/models/actions/status.go
@@ -41,7 +41,7 @@ func (s Status) String() string {
// LocaleString returns the locale string name of the Status
func (s Status) LocaleString(lang translation.Locale) string {
- return lang.Tr("actions.status." + s.String())
+ return lang.TrString("actions.status." + s.String())
}
// IsDone returns whether the Status is final
diff --git a/models/auth/twofactor.go b/models/auth/twofactor.go
index 51061e5205..d0c341a192 100644
--- a/models/auth/twofactor.go
+++ b/models/auth/twofactor.go
@@ -6,6 +6,7 @@ package auth
import (
"context"
"crypto/md5"
+ "crypto/sha256"
"crypto/subtle"
"encoding/base32"
"encoding/base64"
@@ -18,7 +19,6 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
- "github.com/minio/sha256-simd"
"github.com/pquerna/otp/totp"
"golang.org/x/crypto/pbkdf2"
)
diff --git a/models/db/engine.go b/models/db/engine.go
index 2cd1c36c58..2a2743e927 100755
--- a/models/db/engine.go
+++ b/models/db/engine.go
@@ -11,10 +11,13 @@ import (
"io"
"reflect"
"strings"
+ "time"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
+ "xorm.io/xorm/contexts"
"xorm.io/xorm/names"
"xorm.io/xorm/schemas"
@@ -143,6 +146,13 @@ func InitEngine(ctx context.Context) error {
xormEngine.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
xormEngine.SetDefaultContext(ctx)
+ if setting.Database.SlowQueryThreshold > 0 {
+ xormEngine.AddHook(&SlowQueryHook{
+ Threshold: setting.Database.SlowQueryThreshold,
+ Logger: log.GetLogger("xorm"),
+ })
+ }
+
SetDefaultEngine(ctx, xormEngine)
return nil
}
@@ -298,3 +308,24 @@ func SetLogSQL(ctx context.Context, on bool) {
sess.Engine().ShowSQL(on)
}
}
+
+type SlowQueryHook struct {
+ Threshold time.Duration
+ Logger log.Logger
+}
+
+var _ contexts.Hook = &SlowQueryHook{}
+
+func (SlowQueryHook) BeforeProcess(c *contexts.ContextHook) (context.Context, error) {
+ return c.Ctx, nil
+}
+
+func (h *SlowQueryHook) AfterProcess(c *contexts.ContextHook) error {
+ if c.ExecuteTime >= h.Threshold {
+ // 8 is the amount of skips passed to runtime.Caller, so that in the log the correct function
+ // is being displayed (the function that ultimately wants to execute the query in the code)
+ // instead of the function of the slow query hook being called.
+ h.Logger.Log(8, log.WARN, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
+ }
+ return nil
+}
diff --git a/models/error.go b/models/error.go
index 83dfe29805..75c53245de 100644
--- a/models/error.go
+++ b/models/error.go
@@ -493,6 +493,23 @@ func (err ErrMergeUnrelatedHistories) Error() string {
return fmt.Sprintf("Merge UnrelatedHistories Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
}
+// ErrMergeDivergingFastForwardOnly represents an error if a fast-forward-only merge fails because the branches diverge
+type ErrMergeDivergingFastForwardOnly struct {
+ StdOut string
+ StdErr string
+ Err error
+}
+
+// IsErrMergeDivergingFastForwardOnly checks if an error is a ErrMergeDivergingFastForwardOnly.
+func IsErrMergeDivergingFastForwardOnly(err error) bool {
+ _, ok := err.(ErrMergeDivergingFastForwardOnly)
+ return ok
+}
+
+func (err ErrMergeDivergingFastForwardOnly) Error() string {
+ return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
+}
+
// ErrRebaseConflicts represents an error if rebase fails with a conflict
type ErrRebaseConflicts struct {
Style repo_model.MergeStyle
diff --git a/models/fixtures/access.yml b/models/fixtures/access.yml
index 1bb6a9a8ac..641c453eb7 100644
--- a/models/fixtures/access.yml
+++ b/models/fixtures/access.yml
@@ -135,3 +135,27 @@
user_id: 31
repo_id: 28
mode: 4
+
+-
+ id: 24
+ user_id: 38
+ repo_id: 60
+ mode: 2
+
+-
+ id: 25
+ user_id: 38
+ repo_id: 61
+ mode: 1
+
+-
+ id: 26
+ user_id: 39
+ repo_id: 61
+ mode: 1
+
+-
+ id: 27
+ user_id: 40
+ repo_id: 61
+ mode: 4
diff --git a/models/fixtures/collaboration.yml b/models/fixtures/collaboration.yml
index ef77d22b24..7603bdad32 100644
--- a/models/fixtures/collaboration.yml
+++ b/models/fixtures/collaboration.yml
@@ -45,3 +45,9 @@
repo_id: 22
user_id: 18
mode: 2 # write
+
+-
+ id: 9
+ repo_id: 60
+ user_id: 38
+ mode: 2 # write
diff --git a/models/fixtures/email_address.yml b/models/fixtures/email_address.yml
index 67a99f43e2..b2a0432635 100644
--- a/models/fixtures/email_address.yml
+++ b/models/fixtures/email_address.yml
@@ -293,3 +293,27 @@
lower_email: user37@example.com
is_activated: true
is_primary: true
+
+-
+ id: 38
+ uid: 38
+ email: user38@example.com
+ lower_email: user38@example.com
+ is_activated: true
+ is_primary: true
+
+-
+ id: 39
+ uid: 39
+ email: user39@example.com
+ lower_email: user39@example.com
+ is_activated: true
+ is_primary: true
+
+-
+ id: 40
+ uid: 40
+ email: user40@example.com
+ lower_email: user40@example.com
+ is_activated: true
+ is_primary: true
diff --git a/models/fixtures/issue.yml b/models/fixtures/issue.yml
index 0c9b6ff406..ca5b1c6cd1 100644
--- a/models/fixtures/issue.yml
+++ b/models/fixtures/issue.yml
@@ -338,3 +338,37 @@
created_unix: 978307210
updated_unix: 978307210
is_locked: false
+
+-
+ id: 21
+ repo_id: 60
+ index: 1
+ poster_id: 39
+ original_author_id: 0
+ name: repo60 pull1
+ content: content for the 1st issue
+ milestone_id: 0
+ priority: 0
+ is_closed: false
+ is_pull: true
+ num_comments: 0
+ created_unix: 1707270422
+ updated_unix: 1707270422
+ is_locked: false
+
+-
+ id: 22
+ repo_id: 61
+ index: 1
+ poster_id: 40
+ original_author_id: 0
+ name: repo61 pull1
+ content: content for the 1st issue
+ milestone_id: 0
+ priority: 0
+ is_closed: false
+ is_pull: true
+ num_comments: 0
+ created_unix: 1707270422
+ updated_unix: 1707270422
+ is_locked: false
diff --git a/models/fixtures/org_user.yml b/models/fixtures/org_user.yml
index 8d58169a32..a7fbcb2c5a 100644
--- a/models/fixtures/org_user.yml
+++ b/models/fixtures/org_user.yml
@@ -99,3 +99,21 @@
uid: 5
org_id: 36
is_public: true
+
+-
+ id: 18
+ uid: 38
+ org_id: 41
+ is_public: true
+
+-
+ id: 19
+ uid: 39
+ org_id: 41
+ is_public: true
+
+-
+ id: 20
+ uid: 40
+ org_id: 41
+ is_public: true
diff --git a/models/fixtures/pull_request.yml b/models/fixtures/pull_request.yml
index 560674c370..3fc8ce630d 100644
--- a/models/fixtures/pull_request.yml
+++ b/models/fixtures/pull_request.yml
@@ -9,6 +9,7 @@
head_branch: branch1
base_branch: master
merge_base: 4a357436d925b5c974181ff12a994538ddc5a269
+ merged_commit_id: 1a8823cd1a9549fde083f992f6b9b87a7ab74fb3
has_merged: true
merger_id: 2
@@ -98,3 +99,21 @@
index: 1
head_repo_id: 23
base_repo_id: 23
+
+-
+ id: 9
+ type: 0 # gitea pull request
+ status: 2 # mergable
+ issue_id: 21
+ index: 1
+ head_repo_id: 60
+ base_repo_id: 60
+
+-
+ id: 10
+ type: 0 # gitea pull request
+ status: 2 # mergable
+ issue_id: 22
+ index: 1
+ head_repo_id: 61
+ base_repo_id: 61
diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml
index e6c59f527a..4b26674990 100644
--- a/models/fixtures/repo_unit.yml
+++ b/models/fixtures/repo_unit.yml
@@ -676,3 +676,45 @@
type: 1
config: "{}"
created_unix: 946684810
+
+-
+ id: 102
+ repo_id: 60
+ type: 1
+ config: "{}"
+ created_unix: 946684810
+
+-
+ id: 103
+ repo_id: 60
+ type: 2
+ config: "{\"EnableTimetracker\":true,\"AllowOnlyContributorsToTrackTime\":true}"
+ created_unix: 946684810
+
+-
+ id: 104
+ repo_id: 60
+ type: 3
+ config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
+ created_unix: 946684810
+
+-
+ id: 105
+ repo_id: 61
+ type: 1
+ config: "{}"
+ created_unix: 946684810
+
+-
+ id: 106
+ repo_id: 61
+ type: 2
+ config: "{\"EnableTimetracker\":true,\"AllowOnlyContributorsToTrackTime\":true}"
+ created_unix: 946684810
+
+-
+ id: 107
+ repo_id: 61
+ type: 3
+ config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
+ created_unix: 946684810
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index f4e8376735..d094fe82d8 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -1706,3 +1706,65 @@
is_private: true
status: 0
num_issues: 0
+
+-
+ id: 60
+ owner_id: 40
+ owner_name: user40
+ lower_name: repo60
+ name: repo60
+ default_branch: main
+ num_watches: 0
+ num_stars: 0
+ num_forks: 0
+ num_issues: 0
+ num_closed_issues: 0
+ num_pulls: 1
+ num_closed_pulls: 0
+ num_milestones: 0
+ num_closed_milestones: 0
+ num_projects: 0
+ num_closed_projects: 0
+ is_private: false
+ is_empty: false
+ is_archived: false
+ is_mirror: false
+ status: 0
+ is_fork: false
+ fork_id: 0
+ is_template: false
+ template_id: 0
+ size: 0
+ is_fsck_enabled: true
+ close_issues_via_commit_in_any_branch: false
+
+-
+ id: 61
+ owner_id: 41
+ owner_name: org41
+ lower_name: repo61
+ name: repo61
+ default_branch: main
+ num_watches: 0
+ num_stars: 0
+ num_forks: 0
+ num_issues: 0
+ num_closed_issues: 0
+ num_pulls: 1
+ num_closed_pulls: 0
+ num_milestones: 0
+ num_closed_milestones: 0
+ num_projects: 0
+ num_closed_projects: 0
+ is_private: false
+ is_empty: false
+ is_archived: false
+ is_mirror: false
+ status: 0
+ is_fork: false
+ fork_id: 0
+ is_template: false
+ template_id: 0
+ size: 0
+ is_fsck_enabled: true
+ close_issues_via_commit_in_any_branch: false
diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml
index 295e51e39c..149fe90888 100644
--- a/models/fixtures/team.yml
+++ b/models/fixtures/team.yml
@@ -217,3 +217,25 @@
num_members: 1
includes_all_repositories: false
can_create_org_repo: true
+
+-
+ id: 21
+ org_id: 41
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 1
+ num_members: 1
+ includes_all_repositories: true
+ can_create_org_repo: true
+
+-
+ id: 22
+ org_id: 41
+ lower_name: team1
+ name: Team1
+ authorize: 1 # read
+ num_repos: 1
+ num_members: 2
+ includes_all_repositories: false
+ can_create_org_repo: false
diff --git a/models/fixtures/team_repo.yml b/models/fixtures/team_repo.yml
index 8497720892..a29078107e 100644
--- a/models/fixtures/team_repo.yml
+++ b/models/fixtures/team_repo.yml
@@ -63,3 +63,15 @@
org_id: 17
team_id: 9
repo_id: 24
+
+-
+ id: 12
+ org_id: 41
+ team_id: 21
+ repo_id: 61
+
+-
+ id: 13
+ org_id: 41
+ team_id: 22
+ repo_id: 61
diff --git a/models/fixtures/team_unit.yml b/models/fixtures/team_unit.yml
index c5531aa57a..de0e8d738b 100644
--- a/models/fixtures/team_unit.yml
+++ b/models/fixtures/team_unit.yml
@@ -286,3 +286,39 @@
team_id: 2
type: 8
access_mode: 2
+
+-
+ id: 49
+ team_id: 21
+ type: 1
+ access_mode: 4
+
+-
+ id: 50
+ team_id: 21
+ type: 2
+ access_mode: 4
+
+-
+ id: 51
+ team_id: 21
+ type: 3
+ access_mode: 4
+
+-
+ id: 52
+ team_id: 22
+ type: 1
+ access_mode: 1
+
+-
+ id: 53
+ team_id: 22
+ type: 2
+ access_mode: 1
+
+-
+ id: 54
+ team_id: 22
+ type: 3
+ access_mode: 1
diff --git a/models/fixtures/team_user.yml b/models/fixtures/team_user.yml
index 9142fe609a..02d57ae644 100644
--- a/models/fixtures/team_user.yml
+++ b/models/fixtures/team_user.yml
@@ -129,3 +129,21 @@
org_id: 17
team_id: 9
uid: 15
+
+-
+ id: 23
+ org_id: 41
+ team_id: 21
+ uid: 40
+
+-
+ id: 24
+ org_id: 41
+ team_id: 22
+ uid: 38
+
+-
+ id: 25
+ org_id: 41
+ team_id: 22
+ uid: 39
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index aa0daedd85..16b687ae04 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -1369,3 +1369,151 @@
repo_admin_change_team_access: false
theme: ""
keep_activity_private: false
+
+-
+ id: 38
+ lower_name: user38
+ name: user38
+ full_name: User38
+ email: user38@example.com
+ keep_email_private: false
+ email_notifications_preference: enabled
+ passwd: ZogKvWdyEx:password
+ passwd_hash_algo: dummy
+ must_change_password: false
+ login_source: 0
+ login_name: user38
+ type: 0
+ salt: ZogKvWdyEx
+ max_repo_creation: -1
+ is_active: true
+ is_admin: false
+ is_restricted: false
+ allow_git_hook: false
+ allow_import_local: false
+ allow_create_organization: true
+ prohibit_login: false
+ avatar: avatar38
+ avatar_email: user38@example.com
+ use_custom_avatar: false
+ num_followers: 0
+ num_following: 0
+ num_stars: 0
+ num_repos: 0
+ num_teams: 0
+ num_members: 0
+ visibility: 0
+ repo_admin_change_team_access: false
+ theme: ""
+ keep_activity_private: false
+
+-
+ id: 39
+ lower_name: user39
+ name: user39
+ full_name: User39
+ email: user39@example.com
+ keep_email_private: false
+ email_notifications_preference: enabled
+ passwd: ZogKvWdyEx:password
+ passwd_hash_algo: dummy
+ must_change_password: false
+ login_source: 0
+ login_name: user39
+ type: 0
+ salt: ZogKvWdyEx
+ max_repo_creation: -1
+ is_active: true
+ is_admin: false
+ is_restricted: false
+ allow_git_hook: false
+ allow_import_local: false
+ allow_create_organization: true
+ prohibit_login: false
+ avatar: avatar39
+ avatar_email: user39@example.com
+ use_custom_avatar: false
+ num_followers: 0
+ num_following: 0
+ num_stars: 0
+ num_repos: 0
+ num_teams: 0
+ num_members: 0
+ visibility: 0
+ repo_admin_change_team_access: false
+ theme: ""
+ keep_activity_private: false
+
+-
+ id: 40
+ lower_name: user40
+ name: user40
+ full_name: User40
+ email: user40@example.com
+ keep_email_private: false
+ email_notifications_preference: onmention
+ passwd: ZogKvWdyEx:password
+ passwd_hash_algo: dummy
+ must_change_password: false
+ login_source: 0
+ login_name: user40
+ type: 0
+ salt: ZogKvWdyEx
+ max_repo_creation: -1
+ is_active: true
+ is_admin: false
+ is_restricted: false
+ allow_git_hook: false
+ allow_import_local: false
+ allow_create_organization: true
+ prohibit_login: false
+ avatar: avatar40
+ avatar_email: user40@example.com
+ use_custom_avatar: false
+ num_followers: 0
+ num_following: 0
+ num_stars: 0
+ num_repos: 1
+ num_teams: 0
+ num_members: 0
+ visibility: 0
+ repo_admin_change_team_access: false
+ theme: ""
+ keep_activity_private: false
+
+-
+ id: 41
+ lower_name: org41
+ name: org41
+ full_name: Org41
+ email: org41@example.com
+ keep_email_private: false
+ email_notifications_preference: onmention
+ passwd: ZogKvWdyEx:password
+ passwd_hash_algo: dummy
+ must_change_password: false
+ login_source: 0
+ login_name: org41
+ type: 1
+ salt: ZogKvWdyEx
+ max_repo_creation: -1
+ is_active: false
+ is_admin: false
+ is_restricted: false
+ allow_git_hook: false
+ allow_import_local: false
+ allow_create_organization: true
+ prohibit_login: false
+ avatar: avatar41
+ avatar_email: org41@example.com
+ use_custom_avatar: false
+ num_followers: 0
+ num_following: 0
+ num_stars: 0
+ num_repos: 1
+ num_teams: 2
+ num_members: 3
+ visibility: 0
+ repo_admin_change_team_access: false
+ theme: ""
+ keep_activity_private: false
diff --git a/models/git/branch_list.go b/models/git/branch_list.go
index 0e8d28038a..8319e5ecd0 100644
--- a/models/git/branch_list.go
+++ b/models/git/branch_list.go
@@ -9,7 +9,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"xorm.io/builder"
)
@@ -67,7 +67,7 @@ type FindBranchOptions struct {
db.ListOptions
RepoID int64
ExcludeBranchNames []string
- IsDeletedBranch util.OptionalBool
+ IsDeletedBranch optional.Option[bool]
OrderBy string
Keyword string
}
@@ -81,8 +81,8 @@ func (opts FindBranchOptions) ToConds() builder.Cond {
if len(opts.ExcludeBranchNames) > 0 {
cond = cond.And(builder.NotIn("name", opts.ExcludeBranchNames))
}
- if !opts.IsDeletedBranch.IsNone() {
- cond = cond.And(builder.Eq{"is_deleted": opts.IsDeletedBranch.IsTrue()})
+ if opts.IsDeletedBranch.Has() {
+ cond = cond.And(builder.Eq{"is_deleted": opts.IsDeletedBranch.Value()})
}
if opts.Keyword != "" {
cond = cond.And(builder.Like{"name", opts.Keyword})
@@ -92,7 +92,7 @@ func (opts FindBranchOptions) ToConds() builder.Cond {
func (opts FindBranchOptions) ToOrders() string {
orderBy := opts.OrderBy
- if !opts.IsDeletedBranch.IsFalse() { // if deleted branch included, put them at the end
+ if opts.IsDeletedBranch.ValueOrDefault(true) { // if deleted branch included, put them at the end
if orderBy != "" {
orderBy += ", "
}
diff --git a/models/git/branch_test.go b/models/git/branch_test.go
index fd5d6519e9..b8ea663e81 100644
--- a/models/git/branch_test.go
+++ b/models/git/branch_test.go
@@ -13,7 +13,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/stretchr/testify/assert"
)
@@ -50,7 +50,7 @@ func TestGetDeletedBranches(t *testing.T) {
branches, err := db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{
ListOptions: db.ListOptionsAll,
RepoID: repo.ID,
- IsDeletedBranch: util.OptionalBoolTrue,
+ IsDeletedBranch: optional.Some(true),
})
assert.NoError(t, err)
assert.Len(t, branches, 2)
diff --git a/models/git/commit_status.go b/models/git/commit_status.go
index 1118b6cc8c..2d1d1bcb06 100644
--- a/models/git/commit_status.go
+++ b/models/git/commit_status.go
@@ -194,7 +194,7 @@ func (status *CommitStatus) APIURL(ctx context.Context) string {
// LocaleString returns the locale string name of the Status
func (status *CommitStatus) LocaleString(lang translation.Locale) string {
- return lang.Tr("repo.commitstatus." + status.State.String())
+ return lang.TrString("repo.commitstatus." + status.State.String())
}
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go
index eeb307e245..613333a5a2 100644
--- a/models/git/protected_branch_list.go
+++ b/models/git/protected_branch_list.go
@@ -8,7 +8,7 @@ import (
"sort"
"code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/gobwas/glob"
)
@@ -56,7 +56,7 @@ func FindAllMatchedBranches(ctx context.Context, repoID int64, ruleName string)
Page: page,
},
RepoID: repoID,
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
})
if err != nil {
return nil, err
diff --git a/models/issues/comment.go b/models/issues/comment.go
index b00637383a..8f9e340d87 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -210,12 +210,12 @@ const (
// LocaleString returns the locale string name of the role
func (r RoleInRepo) LocaleString(lang translation.Locale) string {
- return lang.Tr("repo.issues.role." + string(r))
+ return lang.TrString("repo.issues.role." + string(r))
}
// LocaleHelper returns the locale tooltip of the role
func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
- return lang.Tr("repo.issues.role." + string(r) + "_helper")
+ return lang.TrString("repo.issues.role." + string(r) + "_helper")
}
// Comment represents a comment in commit and issue page.
@@ -696,8 +696,15 @@ func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository
}
func (c *Comment) loadReview(ctx context.Context) (err error) {
+ if c.ReviewID == 0 {
+ return nil
+ }
if c.Review == nil {
if c.Review, err = GetReviewByID(ctx, c.ReviewID); err != nil {
+ // review request which has been replaced by actual reviews doesn't exist in database anymore, so ignorem them.
+ if c.Type == CommentTypeReviewRequest {
+ return nil
+ }
return err
}
}
@@ -849,6 +856,9 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
// Check comment type.
switch opts.Type {
case CommentTypeCode:
+ if err = updateAttachments(ctx, opts, comment); err != nil {
+ return err
+ }
if comment.ReviewID != 0 {
if comment.Review == nil {
if err := comment.loadReview(ctx); err != nil {
@@ -866,22 +876,9 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
}
fallthrough
case CommentTypeReview:
- // Check attachments
- attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments)
- if err != nil {
- return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", opts.Attachments, err)
+ if err = updateAttachments(ctx, opts, comment); err != nil {
+ return err
}
-
- for i := range attachments {
- attachments[i].IssueID = opts.Issue.ID
- attachments[i].CommentID = comment.ID
- // No assign value could be 0, so ignore AllCols().
- if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil {
- return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
- }
- }
-
- comment.Attachments = attachments
case CommentTypeReopen, CommentTypeClose:
if err = repo_model.UpdateRepoIssueNumbers(ctx, opts.Issue.RepoID, opts.Issue.IsPull, true); err != nil {
return err
@@ -891,6 +888,23 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
return UpdateIssueCols(ctx, opts.Issue, "updated_unix")
}
+func updateAttachments(ctx context.Context, opts *CreateCommentOptions, comment *Comment) error {
+ attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments)
+ if err != nil {
+ return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", opts.Attachments, err)
+ }
+ for i := range attachments {
+ attachments[i].IssueID = opts.Issue.ID
+ attachments[i].CommentID = comment.ID
+ // No assign value could be 0, so ignore AllCols().
+ if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil {
+ return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
+ }
+ }
+ comment.Attachments = attachments
+ return nil
+}
+
func createDeadlineComment(ctx context.Context, doer *user_model.User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) {
var content string
var commentType CommentType
diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go
index 93af45870e..30a437ea50 100644
--- a/models/issues/comment_list.go
+++ b/models/issues/comment_list.go
@@ -225,6 +225,10 @@ func (comments CommentList) loadAssignees(ctx context.Context) error {
for _, comment := range comments {
comment.Assignee = assignees[comment.AssigneeID]
+ if comment.Assignee == nil {
+ comment.AssigneeID = user_model.GhostUserID
+ comment.Assignee = user_model.NewGhostUser()
+ }
}
return nil
}
@@ -430,7 +434,8 @@ func (comments CommentList) loadReviews(ctx context.Context) error {
for _, comment := range comments {
comment.Review = reviews[comment.ReviewID]
if comment.Review == nil {
- if comment.ReviewID > 0 {
+ // review request which has been replaced by actual reviews doesn't exist in database anymore, so don't log errors for them.
+ if comment.ReviewID > 0 && comment.Type != CommentTypeReviewRequest {
log.Error("comment with review id [%d] but has no review record", comment.ReviewID)
}
continue
diff --git a/models/issues/content_history.go b/models/issues/content_history.go
index 8c333bc6dd..8b00adda99 100644
--- a/models/issues/content_history.go
+++ b/models/issues/content_history.go
@@ -161,7 +161,11 @@ func FetchIssueContentHistoryList(dbCtx context.Context, issueID, commentID int6
}
for _, item := range res {
- item.UserAvatarLink = avatars.GenerateUserAvatarFastLink(item.UserName, 0)
+ if item.UserID > 0 {
+ item.UserAvatarLink = avatars.GenerateUserAvatarFastLink(item.UserName, 0)
+ } else {
+ item.UserAvatarLink = avatars.DefaultAvatarLink()
+ }
}
return res, nil
}
diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go
index cc363d2fae..1bbc0eee56 100644
--- a/models/issues/issue_test.go
+++ b/models/issues/issue_test.go
@@ -379,7 +379,7 @@ func TestCountIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{})
assert.NoError(t, err)
- assert.EqualValues(t, 20, count)
+ assert.EqualValues(t, 22, count)
}
func TestIssueLoadAttributes(t *testing.T) {
diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go
index 77ef53a013..cfc3c1683c 100644
--- a/models/issues/issue_xref.go
+++ b/models/issues/issue_xref.go
@@ -46,10 +46,10 @@ func neuterCrossReferences(ctx context.Context, issueID, commentID int64) error
for i, c := range active {
ids[i] = c.ID
}
- return neuterCrossReferencesIds(ctx, ids)
+ return neuterCrossReferencesIDs(ctx, ids)
}
-func neuterCrossReferencesIds(ctx context.Context, ids []int64) error {
+func neuterCrossReferencesIDs(ctx context.Context, ids []int64) error {
_, err := db.GetEngine(ctx).In("id", ids).Cols("`ref_action`").Update(&Comment{RefAction: references.XRefActionNeutered})
return err
}
@@ -100,7 +100,7 @@ func (issue *Issue) createCrossReferences(stdCtx context.Context, ctx *crossRefe
}
}
if len(ids) > 0 {
- if err = neuterCrossReferencesIds(stdCtx, ids); err != nil {
+ if err = neuterCrossReferencesIDs(stdCtx, ids); err != nil {
return err
}
}
diff --git a/models/issues/pull.go b/models/issues/pull.go
index bfec18c923..f032f4b456 100644
--- a/models/issues/pull.go
+++ b/models/issues/pull.go
@@ -1122,3 +1122,23 @@ func UpsertPullRequests(ctx context.Context, prs ...*PullRequest) error {
return nil
})
}
+
+// GetPullRequestByMergedCommit returns a merged pull request by the given commit
+func GetPullRequestByMergedCommit(ctx context.Context, repoID int64, sha string) (*PullRequest, error) {
+ pr := new(PullRequest)
+ has, err := db.GetEngine(ctx).Where("base_repo_id = ? AND merged_commit_id = ?", repoID, sha).Get(pr)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""}
+ }
+
+ if err = pr.LoadAttributes(ctx); err != nil {
+ return nil, err
+ }
+ if err = pr.LoadIssue(ctx); err != nil {
+ return nil, err
+ }
+
+ return pr, nil
+}
diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go
index 173417136c..3a30b2f3de 100644
--- a/models/issues/pull_test.go
+++ b/models/issues/pull_test.go
@@ -339,6 +339,18 @@ func TestGetApprovers(t *testing.T) {
assert.EqualValues(t, expected, approvers)
}
+func TestGetPullRequestByMergedCommit(t *testing.T) {
+ assert.NoError(t, unittest.PrepareTestDatabase())
+ pr, err := issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 1, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3")
+ assert.NoError(t, err)
+ assert.EqualValues(t, 1, pr.ID)
+
+ _, err = issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 0, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3")
+ assert.ErrorAs(t, err, &issues_model.ErrPullRequestNotExist{})
+ _, err = issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 1, "")
+ assert.ErrorAs(t, err, &issues_model.ErrPullRequestNotExist{})
+}
+
func TestMigrate_InsertPullRequests(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
diff --git a/models/issues/review.go b/models/issues/review.go
index d3325992f3..049cbf0062 100644
--- a/models/issues/review.go
+++ b/models/issues/review.go
@@ -160,6 +160,14 @@ func (r *Review) LoadReviewer(ctx context.Context) (err error) {
return err
}
r.Reviewer, err = user_model.GetPossibleUserByID(ctx, r.ReviewerID)
+ if err != nil {
+ if !user_model.IsErrUserNotExist(err) {
+ return fmt.Errorf("GetPossibleUserByID [%d]: %w", r.ReviewerID, err)
+ }
+ r.ReviewerID = user_model.GhostUserID
+ r.Reviewer = user_model.NewGhostUser()
+ return nil
+ }
return err
}
@@ -285,8 +293,14 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio
// CreateReview creates a new review based on opts
func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error) {
+ ctx, committer, err := db.TxContext(ctx)
+ if err != nil {
+ return nil, err
+ }
+ defer committer.Close()
+ sess := db.GetEngine(ctx)
+
review := &Review{
- Type: opts.Type,
Issue: opts.Issue,
IssueID: opts.Issue.ID,
Reviewer: opts.Reviewer,
@@ -296,15 +310,39 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error
CommitID: opts.CommitID,
Stale: opts.Stale,
}
+
if opts.Reviewer != nil {
+ review.Type = opts.Type
review.ReviewerID = opts.Reviewer.ID
- } else {
- if review.Type != ReviewTypeRequest {
- review.Type = ReviewTypeRequest
+
+ reviewCond := builder.Eq{"reviewer_id": opts.Reviewer.ID, "issue_id": opts.Issue.ID}
+ // make sure user review requests are cleared
+ if opts.Type != ReviewTypePending {
+ if _, err := sess.Where(reviewCond.And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)); err != nil {
+ return nil, err
+ }
}
+ // make sure if the created review gets dismissed no old review surface
+ // other types can be ignored, as they don't affect branch protection
+ if opts.Type == ReviewTypeApprove || opts.Type == ReviewTypeReject {
+ if _, err := sess.Where(reviewCond.And(builder.In("type", ReviewTypeApprove, ReviewTypeReject))).
+ Cols("dismissed").Update(&Review{Dismissed: true}); err != nil {
+ return nil, err
+ }
+ }
+
+ } else if opts.ReviewerTeam != nil {
+ review.Type = ReviewTypeRequest
review.ReviewerTeamID = opts.ReviewerTeam.ID
+
+ } else {
+ return nil, fmt.Errorf("provide either reviewer or reviewer team")
}
- return review, db.Insert(ctx, review)
+
+ if _, err := sess.Insert(review); err != nil {
+ return nil, err
+ }
+ return review, committer.Commit()
}
// GetCurrentReview returns the current pending review of reviewer for given issue
@@ -715,6 +753,9 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo
return nil, err
}
+ // func caller use the created comment to retrieve created review too.
+ comment.Review = review
+
return comment, committer.Commit()
}
diff --git a/models/issues/review_list.go b/models/issues/review_list.go
index ed3d0bd028..282f18b4f7 100644
--- a/models/issues/review_list.go
+++ b/models/issues/review_list.go
@@ -18,11 +18,11 @@ type ReviewList []*Review
// LoadReviewers loads reviewers
func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
- reviewerIds := make([]int64, len(reviews))
+ reviewerIDs := make([]int64, len(reviews))
for i := 0; i < len(reviews); i++ {
- reviewerIds[i] = reviews[i].ReviewerID
+ reviewerIDs[i] = reviews[i].ReviewerID
}
- reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIds)
+ reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIDs)
if err != nil {
return err
}
@@ -38,12 +38,12 @@ func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
}
func (reviews ReviewList) LoadIssues(ctx context.Context) error {
- issueIds := container.Set[int64]{}
+ issueIDs := container.Set[int64]{}
for i := 0; i < len(reviews); i++ {
- issueIds.Add(reviews[i].IssueID)
+ issueIDs.Add(reviews[i].IssueID)
}
- issues, err := GetIssuesByIDs(ctx, issueIds.Values())
+ issues, err := GetIssuesByIDs(ctx, issueIDs.Values())
if err != nil {
return err
}
diff --git a/models/migrations/base/hash.go b/models/migrations/base/hash.go
index 0debec272b..00fd1efd4a 100644
--- a/models/migrations/base/hash.go
+++ b/models/migrations/base/hash.go
@@ -4,9 +4,9 @@
package base
import (
+ "crypto/sha256"
"encoding/hex"
- "github.com/minio/sha256-simd"
"golang.org/x/crypto/pbkdf2"
)
diff --git a/models/migrations/v1_14/v166.go b/models/migrations/v1_14/v166.go
index 78f33e8f9b..e5731582fd 100644
--- a/models/migrations/v1_14/v166.go
+++ b/models/migrations/v1_14/v166.go
@@ -4,9 +4,9 @@
package v1_14 //nolint
import (
+ "crypto/sha256"
"encoding/hex"
- "github.com/minio/sha256-simd"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/pbkdf2"
diff --git a/models/organization/org.go b/models/organization/org.go
index 23a4e2f96a..b4919defb4 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -594,9 +594,7 @@ func GetOrgByID(ctx context.Context, id int64) (*Organization, error) {
return nil, err
} else if !has {
return nil, user_model.ErrUserNotExist{
- UID: id,
- Name: "",
- KeyID: 0,
+ UID: id,
}
}
return u, nil
diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go
index 395ecdf1a5..4175cb9b92 100644
--- a/models/perm/access/repo_permission.go
+++ b/models/perm/access/repo_permission.go
@@ -332,7 +332,6 @@ func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.
// CanBeAssigned return true if user can be assigned to issue or pull requests in repo
// Currently any write access (code, issues or pr's) is assignable, to match assignee list in user interface.
-// FIXME: user could send PullRequest also could be assigned???
func CanBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model.Repository, _ bool) (bool, error) {
if user.IsOrganization() {
return false, fmt.Errorf("Organization can't be added as assignee [user_id: %d, repo_id: %d]", user.ID, repo.ID)
@@ -341,7 +340,8 @@ func CanBeAssigned(ctx context.Context, user *user_model.User, repo *repo_model.
if err != nil {
return false, err
}
- return perm.CanAccessAny(perm_model.AccessModeWrite, unit.TypeCode, unit.TypeIssues, unit.TypePullRequests), nil
+ return perm.CanAccessAny(perm_model.AccessModeWrite, unit.AllRepoUnitTypes...) ||
+ perm.CanAccessAny(perm_model.AccessModeRead, unit.TypePullRequests), nil
}
// HasAccess returns true if user has access to repo
diff --git a/models/repo/git.go b/models/repo/git.go
index 610c554296..388bf86522 100644
--- a/models/repo/git.go
+++ b/models/repo/git.go
@@ -21,6 +21,8 @@ const (
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
// MergeStyleSquash squash commits into single commit before merging
MergeStyleSquash MergeStyle = "squash"
+ // MergeStyleFastForwardOnly fast-forward merge if possible, otherwise fail
+ MergeStyleFastForwardOnly MergeStyle = "fast-forward-only"
// MergeStyleManuallyMerged pr has been merged manually, just mark it as merged directly
MergeStyleManuallyMerged MergeStyle = "manually-merged"
// MergeStyleRebaseUpdate not a merge style, used to update pull head by rebase
diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go
index 8a1799aac0..83e37a27fd 100644
--- a/models/repo/repo_list_test.go
+++ b/models/repo/repo_list_test.go
@@ -138,12 +138,12 @@ func getTestCases() []struct {
{
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
- count: 31,
+ count: 33,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
- count: 36,
+ count: 38,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
@@ -158,7 +158,7 @@ func getTestCases() []struct {
{
name: "AllPublic/PublicRepositoriesOfOrganization",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
- count: 31,
+ count: 33,
},
{
name: "AllTemplates",
diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go
index 8a3ba1ee89..31a2a2e248 100644
--- a/models/repo/repo_unit.go
+++ b/models/repo/repo_unit.go
@@ -122,6 +122,7 @@ type PullRequestsConfig struct {
AllowRebase bool
AllowRebaseMerge bool
AllowSquash bool
+ AllowFastForwardOnly bool
AllowManualMerge bool
AutodetectManualMerge bool
AllowRebaseUpdate bool
@@ -148,6 +149,7 @@ func (cfg *PullRequestsConfig) IsMergeStyleAllowed(mergeStyle MergeStyle) bool {
mergeStyle == MergeStyleRebase && cfg.AllowRebase ||
mergeStyle == MergeStyleRebaseMerge && cfg.AllowRebaseMerge ||
mergeStyle == MergeStyleSquash && cfg.AllowSquash ||
+ mergeStyle == MergeStyleFastForwardOnly && cfg.AllowFastForwardOnly ||
mergeStyle == MergeStyleManuallyMerged && cfg.AllowManualMerge
}
diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go
index dd2ef62201..30c9db7474 100644
--- a/models/repo/user_repo.go
+++ b/models/repo/user_repo.go
@@ -8,6 +8,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
+ "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
api "code.gitea.io/gitea/modules/structs"
@@ -78,7 +79,8 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
if err = e.Table("team_user").
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
- Where("`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?", repo.ID, perm.AccessModeWrite).
+ Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
+ repo.ID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
Distinct("`team_user`.uid").
Select("`team_user`.uid").
Find(&additionalUserIDs); err != nil {
diff --git a/models/shared/types/ownertype.go b/models/shared/types/ownertype.go
index e6fe4e4cfd..a1d46c986f 100644
--- a/models/shared/types/ownertype.go
+++ b/models/shared/types/ownertype.go
@@ -17,13 +17,13 @@ const (
func (o OwnerType) LocaleString(locale translation.Locale) string {
switch o {
case OwnerTypeSystemGlobal:
- return locale.Tr("concept_system_global")
+ return locale.TrString("concept_system_global")
case OwnerTypeIndividual:
- return locale.Tr("concept_user_individual")
+ return locale.TrString("concept_user_individual")
case OwnerTypeRepository:
- return locale.Tr("concept_code_repository")
+ return locale.TrString("concept_code_repository")
case OwnerTypeOrganization:
- return locale.Tr("concept_user_organization")
+ return locale.TrString("concept_user_organization")
}
- return locale.Tr("unknown")
+ return locale.TrString("unknown")
}
diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go
index 4c668ad04b..cb90c12f2b 100644
--- a/models/unittest/testdb.go
+++ b/models/unittest/testdb.go
@@ -44,12 +44,12 @@ func fatalTestError(fmtStr string, args ...any) {
}
// InitSettings initializes config provider and load common settings for tests
-func InitSettings(extraConfigs ...string) {
+func InitSettings() {
if setting.CustomConf == "" {
setting.CustomConf = filepath.Join(setting.CustomPath, "conf/app-unittest-tmp.ini")
_ = os.Remove(setting.CustomConf)
}
- setting.InitCfgProvider(setting.CustomConf, strings.Join(extraConfigs, "\n"))
+ setting.InitCfgProvider(setting.CustomConf)
setting.LoadCommonSettings()
if err := setting.PrepareAppDataPath(); err != nil {
diff --git a/models/unittest/unit_tests.go b/models/unittest/unit_tests.go
index d47bceea1e..75898436fc 100644
--- a/models/unittest/unit_tests.go
+++ b/models/unittest/unit_tests.go
@@ -131,8 +131,8 @@ func AssertSuccessfulInsert(t assert.TestingT, beans ...any) {
}
// AssertCount assert the count of a bean
-func AssertCount(t assert.TestingT, bean, expected any) {
- assert.EqualValues(t, expected, GetCount(t, bean))
+func AssertCount(t assert.TestingT, bean, expected any) bool {
+ return assert.EqualValues(t, expected, GetCount(t, bean))
}
// AssertInt64InRange assert value is in range [low, high]
@@ -150,7 +150,7 @@ func GetCountByCond(t assert.TestingT, tableName string, cond builder.Cond) int6
}
// AssertCountByCond test the count of database entries matching bean
-func AssertCountByCond(t assert.TestingT, tableName string, cond builder.Cond, expected int) {
- assert.EqualValues(t, expected, GetCountByCond(t, tableName, cond),
+func AssertCountByCond(t assert.TestingT, tableName string, cond builder.Cond, expected int) bool {
+ return assert.EqualValues(t, expected, GetCountByCond(t, tableName, cond),
"Failed consistency test, the counted bean (of table %s) was %+v", tableName, cond)
}
diff --git a/models/user/email_address.go b/models/user/email_address.go
index 957e72fe89..216840916d 100644
--- a/models/user/email_address.go
+++ b/models/user/email_address.go
@@ -332,9 +332,7 @@ func MakeEmailPrimary(ctx context.Context, email *EmailAddress) error {
return err
} else if !has {
return ErrUserNotExist{
- UID: email.UID,
- Name: "",
- KeyID: 0,
+ UID: email.UID,
}
}
diff --git a/models/user/error.go b/models/user/error.go
index ef572c178a..cbf19998d1 100644
--- a/models/user/error.go
+++ b/models/user/error.go
@@ -31,9 +31,8 @@ func (err ErrUserAlreadyExist) Unwrap() error {
// ErrUserNotExist represents a "UserNotExist" kind of error.
type ErrUserNotExist struct {
- UID int64
- Name string
- KeyID int64
+ UID int64
+ Name string
}
// IsErrUserNotExist checks if an error is a ErrUserNotExist.
@@ -43,7 +42,7 @@ func IsErrUserNotExist(err error) bool {
}
func (err ErrUserNotExist) Error() string {
- return fmt.Sprintf("user does not exist [uid: %d, name: %s, keyid: %d]", err.UID, err.Name, err.KeyID)
+ return fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name)
}
// Unwrap unwraps this error as a ErrNotExist error
diff --git a/models/user/user.go b/models/user/user.go
index e5245dfbb0..e92bbd4d0b 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -25,6 +25,7 @@ import (
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
@@ -425,14 +426,14 @@ func (u *User) GetDisplayName() string {
}
// GetCompleteName returns the the full name and username in the form of
-// "Full Name (@username)" if full name is not empty, otherwise it returns
-// "@username".
+// "Full Name (username)" if full name is not empty, otherwise it returns
+// "username".
func (u *User) GetCompleteName() string {
trimmedFullName := strings.TrimSpace(u.FullName)
if len(trimmedFullName) > 0 {
- return fmt.Sprintf("%s (@%s)", trimmedFullName, u.Name)
+ return fmt.Sprintf("%s (%s)", trimmedFullName, u.Name)
}
- return fmt.Sprintf("@%s", u.Name)
+ return u.Name
}
func gitSafeName(name string) string {
@@ -573,14 +574,14 @@ func IsUsableUsername(name string) error {
// CreateUserOverwriteOptions are an optional options who overwrite system defaults on user creation
type CreateUserOverwriteOptions struct {
- KeepEmailPrivate util.OptionalBool
+ KeepEmailPrivate optional.Option[bool]
Visibility *structs.VisibleType
- AllowCreateOrganization util.OptionalBool
+ AllowCreateOrganization optional.Option[bool]
EmailNotificationsPreference *string
MaxRepoCreation *int
Theme *string
- IsRestricted util.OptionalBool
- IsActive util.OptionalBool
+ IsRestricted optional.Option[bool]
+ IsActive optional.Option[bool]
}
// CreateUser creates record of a new user.
@@ -607,14 +608,14 @@ func CreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOve
// overwrite defaults if set
if len(overwriteDefault) != 0 && overwriteDefault[0] != nil {
overwrite := overwriteDefault[0]
- if !overwrite.KeepEmailPrivate.IsNone() {
- u.KeepEmailPrivate = overwrite.KeepEmailPrivate.IsTrue()
+ if overwrite.KeepEmailPrivate.Has() {
+ u.KeepEmailPrivate = overwrite.KeepEmailPrivate.Value()
}
if overwrite.Visibility != nil {
u.Visibility = *overwrite.Visibility
}
- if !overwrite.AllowCreateOrganization.IsNone() {
- u.AllowCreateOrganization = overwrite.AllowCreateOrganization.IsTrue()
+ if overwrite.AllowCreateOrganization.Has() {
+ u.AllowCreateOrganization = overwrite.AllowCreateOrganization.Value()
}
if overwrite.EmailNotificationsPreference != nil {
u.EmailNotificationsPreference = *overwrite.EmailNotificationsPreference
@@ -625,11 +626,11 @@ func CreateUser(ctx context.Context, u *User, overwriteDefault ...*CreateUserOve
if overwrite.Theme != nil {
u.Theme = *overwrite.Theme
}
- if !overwrite.IsRestricted.IsNone() {
- u.IsRestricted = overwrite.IsRestricted.IsTrue()
+ if overwrite.IsRestricted.Has() {
+ u.IsRestricted = overwrite.IsRestricted.Value()
}
- if !overwrite.IsActive.IsNone() {
- u.IsActive = overwrite.IsActive.IsTrue()
+ if overwrite.IsActive.Has() {
+ u.IsActive = overwrite.IsActive.Value()
}
}
@@ -835,7 +836,7 @@ func GetUserByID(ctx context.Context, id int64) (*User, error) {
if err != nil {
return nil, err
} else if !has {
- return nil, ErrUserNotExist{id, "", 0}
+ return nil, ErrUserNotExist{UID: id}
}
return u, nil
}
@@ -885,14 +886,14 @@ func GetPossibleUserByIDs(ctx context.Context, ids []int64) ([]*User, error) {
// GetUserByNameCtx returns user by given name.
func GetUserByName(ctx context.Context, name string) (*User, error) {
if len(name) == 0 {
- return nil, ErrUserNotExist{0, name, 0}
+ return nil, ErrUserNotExist{Name: name}
}
u := &User{LowerName: strings.ToLower(name), Type: UserTypeIndividual}
has, err := db.GetEngine(ctx).Get(u)
if err != nil {
return nil, err
} else if !has {
- return nil, ErrUserNotExist{0, name, 0}
+ return nil, ErrUserNotExist{Name: name}
}
return u, nil
}
@@ -1033,7 +1034,7 @@ func ValidateCommitsWithEmails(ctx context.Context, oldCommits []*git.Commit) []
// GetUserByEmail returns the user object by given e-mail if exists.
func GetUserByEmail(ctx context.Context, email string) (*User, error) {
if len(email) == 0 {
- return nil, ErrUserNotExist{0, email, 0}
+ return nil, ErrUserNotExist{Name: email}
}
email = strings.ToLower(email)
@@ -1060,7 +1061,7 @@ func GetUserByEmail(ctx context.Context, email string) (*User, error) {
}
}
- return nil, ErrUserNotExist{0, email, 0}
+ return nil, ErrUserNotExist{Name: email}
}
// GetUser checks if a user already exists
@@ -1071,7 +1072,7 @@ func GetUser(ctx context.Context, user *User) (bool, error) {
// GetUserByOpenID returns the user object by given OpenID if exists.
func GetUserByOpenID(ctx context.Context, uri string) (*User, error) {
if len(uri) == 0 {
- return nil, ErrUserNotExist{0, uri, 0}
+ return nil, ErrUserNotExist{Name: uri}
}
uri, err := openid.Normalize(uri)
@@ -1091,7 +1092,7 @@ func GetUserByOpenID(ctx context.Context, uri string) (*User, error) {
return GetUserByID(ctx, oid.UID)
}
- return nil, ErrUserNotExist{0, uri, 0}
+ return nil, ErrUserNotExist{Name: uri}
}
// GetAdminUser returns the first administrator
diff --git a/models/user/user_test.go b/models/user/user_test.go
index f3e5a95b1e..68cee9cdbd 100644
--- a/models/user/user_test.go
+++ b/models/user/user_test.go
@@ -89,7 +89,7 @@ func TestSearchUsers(t *testing.T) {
[]int64{19, 25})
testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 4, PageSize: 2}},
- []int64{26})
+ []int64{26, 41})
testOrgSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 5, PageSize: 2}},
[]int64{})
@@ -101,13 +101,13 @@ func TestSearchUsers(t *testing.T) {
}
testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}},
- []int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37})
+ []int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolFalse},
[]int64{9})
testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
- []int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37})
+ []int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: util.OptionalBoolTrue},
[]int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
diff --git a/modules/actions/github.go b/modules/actions/github.go
index fafea4e11a..68116ec83a 100644
--- a/modules/actions/github.go
+++ b/modules/actions/github.go
@@ -25,6 +25,45 @@ const (
GithubEventSchedule = "schedule"
)
+// IsDefaultBranchWorkflow returns true if the event only triggers workflows on the default branch
+func IsDefaultBranchWorkflow(triggedEvent webhook_module.HookEventType) bool {
+ switch triggedEvent {
+ case webhook_module.HookEventDelete:
+ // GitHub "delete" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#delete
+ return true
+ case webhook_module.HookEventFork:
+ // GitHub "fork" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#fork
+ return true
+ case webhook_module.HookEventIssueComment:
+ // GitHub "issue_comment" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
+ return true
+ case webhook_module.HookEventPullRequestComment:
+ // GitHub "pull_request_comment" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
+ return true
+ case webhook_module.HookEventWiki:
+ // GitHub "gollum" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum
+ return true
+ case webhook_module.HookEventSchedule:
+ // GitHub "schedule" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
+ return true
+ case webhook_module.HookEventIssues,
+ webhook_module.HookEventIssueAssign,
+ webhook_module.HookEventIssueLabel,
+ webhook_module.HookEventIssueMilestone:
+ // Github "issues" event
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
+ return true
+ }
+
+ return false
+}
+
// canGithubEventMatch check if the input Github event can match any Gitea event.
func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEventType) bool {
switch eventName {
@@ -52,7 +91,9 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
case webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
webhook_module.HookEventPullRequestAssign,
- webhook_module.HookEventPullRequestLabel:
+ webhook_module.HookEventPullRequestLabel,
+ webhook_module.HookEventPullRequestReviewRequest,
+ webhook_module.HookEventPullRequestMilestone:
return true
default:
@@ -73,6 +114,11 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
case GithubEventSchedule:
return triggedEvent == webhook_module.HookEventSchedule
+ case GithubEventIssueComment:
+ // https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
+ return triggedEvent == webhook_module.HookEventIssueComment ||
+ triggedEvent == webhook_module.HookEventPullRequestComment
+
default:
return eventName == string(triggedEvent)
}
diff --git a/modules/actions/github_test.go b/modules/actions/github_test.go
index 4bf55ae03f..6652ff6eac 100644
--- a/modules/actions/github_test.go
+++ b/modules/actions/github_test.go
@@ -103,6 +103,12 @@ func TestCanGithubEventMatch(t *testing.T) {
webhook_module.HookEventCreate,
true,
},
+ {
+ "create pull request comment",
+ GithubEventIssueComment,
+ webhook_module.HookEventPullRequestComment,
+ true,
+ },
}
for _, tc := range testCases {
diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go
index a883f4181b..2db4a9296f 100644
--- a/modules/actions/workflows.go
+++ b/modules/actions/workflows.go
@@ -221,7 +221,9 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
webhook_module.HookEventPullRequestAssign,
- webhook_module.HookEventPullRequestLabel:
+ webhook_module.HookEventPullRequestLabel,
+ webhook_module.HookEventPullRequestReviewRequest,
+ webhook_module.HookEventPullRequestMilestone:
return matchPullRequestEvent(gitRepo, commit, payload.(*api.PullRequestPayload), evt)
case // pull_request_review
@@ -397,13 +399,13 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
} else {
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
// Actions with the same name:
- // opened, edited, closed, reopened, assigned, unassigned
+ // opened, edited, closed, reopened, assigned, unassigned, review_requested, review_request_removed, milestoned, demilestoned
// Actions need to be converted:
// synchronized -> synchronize
// label_updated -> labeled
// label_cleared -> unlabeled
// Unsupported activity types:
- // converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
+ // converted_to_draft, ready_for_review, locked, unlocked, auto_merge_enabled, auto_merge_disabled, enqueued, dequeued
action := prPayload.Action
switch action {
diff --git a/modules/auth/password/hash/pbkdf2.go b/modules/auth/password/hash/pbkdf2.go
index 9ff6d162fc..27382fedb8 100644
--- a/modules/auth/password/hash/pbkdf2.go
+++ b/modules/auth/password/hash/pbkdf2.go
@@ -4,12 +4,12 @@
package hash
import (
+ "crypto/sha256"
"encoding/hex"
"strings"
"code.gitea.io/gitea/modules/log"
- "github.com/minio/sha256-simd"
"golang.org/x/crypto/pbkdf2"
)
diff --git a/modules/auth/password/password.go b/modules/auth/password/password.go
index 2c7205b708..27074358a9 100644
--- a/modules/auth/password/password.go
+++ b/modules/auth/password/password.go
@@ -8,6 +8,7 @@ import (
"context"
"crypto/rand"
"errors"
+ "html/template"
"math/big"
"strings"
"sync"
@@ -121,15 +122,15 @@ func Generate(n int) (string, error) {
}
// BuildComplexityError builds the error message when password complexity checks fail
-func BuildComplexityError(locale translation.Locale) string {
+func BuildComplexityError(locale translation.Locale) template.HTML {
var buffer bytes.Buffer
- buffer.WriteString(locale.Tr("form.password_complexity"))
+ buffer.WriteString(locale.TrString("form.password_complexity"))
buffer.WriteString("")
for _, c := range requiredList {
buffer.WriteString("")
- buffer.WriteString(locale.Tr(c.TrNameOne))
+ buffer.WriteString(locale.TrString(c.TrNameOne))
buffer.WriteString(" ")
}
buffer.WriteString(" ")
- return buffer.String()
+ return template.HTML(buffer.String())
}
diff --git a/modules/avatar/hash.go b/modules/avatar/hash.go
index 4fc28a7739..50db9c1943 100644
--- a/modules/avatar/hash.go
+++ b/modules/avatar/hash.go
@@ -4,10 +4,9 @@
package avatar
import (
+ "crypto/sha256"
"encoding/hex"
"strconv"
-
- "github.com/minio/sha256-simd"
)
// HashAvatar will generate a unique string, which ensures that when there's a
diff --git a/modules/avatar/identicon/identicon.go b/modules/avatar/identicon/identicon.go
index 9b7a2faf05..63926d5f19 100644
--- a/modules/avatar/identicon/identicon.go
+++ b/modules/avatar/identicon/identicon.go
@@ -7,11 +7,10 @@
package identicon
import (
+ "crypto/sha256"
"fmt"
"image"
"image/color"
-
- "github.com/minio/sha256-simd"
)
const minImageSize = 16
diff --git a/modules/base/tool.go b/modules/base/tool.go
index e9f4dfa279..168a2220b2 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -5,6 +5,7 @@ package base
import (
"crypto/sha1"
+ "crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
@@ -22,7 +23,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"github.com/dustin/go-humanize"
- "github.com/minio/sha256-simd"
)
// EncodeSha1 string to sha1 hex value.
@@ -115,7 +115,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf any) string {
// create sha1 encode string
sh := sha1.New()
- _, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, setting.SecretKey, startStr, endStr, minutes)))
+ _, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, endStr, minutes)))
encoded := hex.EncodeToString(sh.Sum(nil))
code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
diff --git a/modules/charset/escape_stream.go b/modules/charset/escape_stream.go
index 3f08fd94a4..29943eb858 100644
--- a/modules/charset/escape_stream.go
+++ b/modules/charset/escape_stream.go
@@ -173,7 +173,7 @@ func (e *escapeStreamer) ambiguousRune(r, c rune) error {
Val: "ambiguous-code-point",
}, html.Attribute{
Key: "data-tooltip-content",
- Val: e.locale.Tr("repo.ambiguous_character", r, c),
+ Val: e.locale.TrString("repo.ambiguous_character", r, c),
}); err != nil {
return err
}
diff --git a/modules/context/api.go b/modules/context/api.go
index e226264a87..b18a206b5e 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -245,7 +245,7 @@ func APIContexter() func(http.Handler) http.Handler {
// NotFound handles 404s for APIContext
// String will replace message, errors will be added to a slice
func (ctx *APIContext) NotFound(objs ...any) {
- message := ctx.Tr("error.not_found")
+ message := ctx.Locale.TrString("error.not_found")
var errors []string
for _, obj := range objs {
// Ignore nil
@@ -307,12 +307,6 @@ func RepoRefForAPI(next http.Handler) http.Handler {
return
}
- objectFormat, err := ctx.Repo.GitRepo.GetObjectFormat()
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetCommit", err)
- return
- }
-
if ref := ctx.FormTrim("ref"); len(ref) > 0 {
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil {
@@ -331,6 +325,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
}
refName := getRefName(ctx.Base, ctx.Repo, RepoRefAny)
+ var err error
if ctx.Repo.GitRepo.IsBranchExist(refName) {
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
@@ -346,7 +341,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
- } else if len(refName) == objectFormat.FullLength() {
+ } else if len(refName) == ctx.Repo.GetObjectFormat().FullLength() {
ctx.Repo.CommitID = refName
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
if err != nil {
diff --git a/modules/context/base.go b/modules/context/base.go
index 8df1dde866..fa05850a16 100644
--- a/modules/context/base.go
+++ b/modules/context/base.go
@@ -6,6 +6,7 @@ package context
import (
"context"
"fmt"
+ "html/template"
"io"
"net/http"
"net/url"
@@ -286,11 +287,11 @@ func (b *Base) cleanUp() {
}
}
-func (b *Base) Tr(msg string, args ...any) string {
+func (b *Base) Tr(msg string, args ...any) template.HTML {
return b.Locale.Tr(msg, args...)
}
-func (b *Base) TrN(cnt any, key1, keyN string, args ...any) string {
+func (b *Base) TrN(cnt any, key1, keyN string, args ...any) template.HTML {
return b.Locale.TrN(cnt, key1, keyN, args...)
}
diff --git a/modules/context/context.go b/modules/context/context.go
index d19c5d1198..4b318f7e33 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -6,7 +6,8 @@ package context
import (
"context"
- "html"
+ "encoding/hex"
+ "fmt"
"html/template"
"io"
"net/http"
@@ -71,16 +72,6 @@ func init() {
})
}
-// TrHTMLEscapeArgs runs ".Locale.Tr()" but pre-escapes all arguments with html.EscapeString.
-// This is useful if the locale message is intended to only produce HTML content.
-func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {
- trArgs := make([]any, len(args))
- for i, arg := range args {
- trArgs[i] = html.EscapeString(arg)
- }
- return ctx.Locale.Tr(msg, trArgs...)
-}
-
type webContextKeyType struct{}
var WebContextKey = webContextKeyType{}
@@ -134,7 +125,7 @@ func NewWebContext(base *Base, render Render, session session.Store) *Context {
func Contexter() func(next http.Handler) http.Handler {
rnd := templates.HTMLRenderer()
csrfOpts := CsrfOptions{
- Secret: setting.SecretKey,
+ Secret: hex.EncodeToString(setting.GetGeneralTokenSigningSecret()),
Cookie: setting.CSRFCookieName,
SetCookie: true,
Secure: setting.SessionConfig.Secure,
@@ -201,6 +192,7 @@ func Contexter() func(next http.Handler) http.Handler {
httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform")
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
+ ctx.Data["SystemConfig"] = setting.Config()
ctx.Data["CsrfToken"] = ctx.Csrf.GetToken()
ctx.Data["CsrfTokenHtml"] = template.HTML(` `)
@@ -253,6 +245,13 @@ func (ctx *Context) JSONOK() {
ctx.JSON(http.StatusOK, map[string]any{"ok": true}) // this is only a dummy response, frontend seldom uses it
}
-func (ctx *Context) JSONError(msg string) {
- ctx.JSON(http.StatusBadRequest, map[string]any{"errorMessage": msg})
+func (ctx *Context) JSONError(msg any) {
+ switch v := msg.(type) {
+ case string:
+ ctx.JSON(http.StatusBadRequest, map[string]any{"errorMessage": v, "renderFormat": "text"})
+ case template.HTML:
+ ctx.JSON(http.StatusBadRequest, map[string]any{"errorMessage": v, "renderFormat": "html"})
+ default:
+ panic(fmt.Sprintf("unsupported type: %T", msg))
+ }
}
diff --git a/modules/context/context_response.go b/modules/context/context_response.go
index 5729865561..829bca1f59 100644
--- a/modules/context/context_response.go
+++ b/modules/context/context_response.go
@@ -90,6 +90,20 @@ func (ctx *Context) HTML(status int, name base.TplName) {
}
}
+// JSONTemplate renders the template as JSON response
+// keep in mind that the template is processed in HTML context, so JSON-things should be handled carefully, eg: by JSEscape
+func (ctx *Context) JSONTemplate(tmpl base.TplName) {
+ t, err := ctx.Render.TemplateLookup(string(tmpl), nil)
+ if err != nil {
+ ctx.ServerError("unable to find template", err)
+ return
+ }
+ ctx.Resp.Header().Set("Content-Type", "application/json")
+ if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
+ ctx.ServerError("unable to execute template", err)
+ }
+}
+
// RenderToString renders the template content to a string
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
var buf strings.Builder
@@ -98,12 +112,11 @@ func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (stri
}
// RenderWithErr used for page has form validation but need to prompt error to users.
-func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form any) {
+func (ctx *Context) RenderWithErr(msg any, tpl base.TplName, form any) {
if form != nil {
middleware.AssignForm(form, ctx.Data)
}
- ctx.Flash.ErrorMsg = msg
- ctx.Data["Flash"] = ctx.Flash
+ ctx.Flash.Error(msg, true)
ctx.HTML(http.StatusOK, tpl)
}
diff --git a/modules/context/context_template.go b/modules/context/context_template.go
index ba90fc170a..7878d409ca 100644
--- a/modules/context/context_template.go
+++ b/modules/context/context_template.go
@@ -5,10 +5,7 @@ package context
import (
"context"
- "errors"
"time"
-
- "code.gitea.io/gitea/modules/log"
)
var _ context.Context = TemplateContext(nil)
@@ -36,14 +33,3 @@ func (c TemplateContext) Err() error {
func (c TemplateContext) Value(key any) any {
return c.parentContext().Value(key)
}
-
-// DataRaceCheck checks whether the template context function "ctx()" returns the consistent context
-// as the current template's rendering context (request context), to help to find data race issues as early as possible.
-// When the code is proven to be correct and stable, this function should be removed.
-func (c TemplateContext) DataRaceCheck(dataCtx context.Context) (string, error) {
- if c.parentContext() != dataCtx {
- log.Error("TemplateContext.DataRaceCheck: parent context mismatch\n%s", log.Stack(2))
- return "", errors.New("parent context mismatch")
- }
- return "", nil
-}
diff --git a/modules/context/org.go b/modules/context/org.go
index d068646577..018b76de43 100644
--- a/modules/context/org.go
+++ b/modules/context/org.go
@@ -11,6 +11,8 @@ import (
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
)
@@ -255,6 +257,19 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects)
ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages)
ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode)
+
+ ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
+ if len(ctx.ContextUser.Description) != 0 {
+ content, err := markdown.RenderString(&markup.RenderContext{
+ Metas: map[string]string{"mode": "document"},
+ Ctx: ctx,
+ }, ctx.ContextUser.Description)
+ if err != nil {
+ ctx.ServerError("RenderString", err)
+ return
+ }
+ ctx.Data["RenderedDescription"] = content
+ }
}
// OrgAssignment returns a middleware to handle organization assignment
diff --git a/modules/context/repo.go b/modules/context/repo.go
index 34a72cb164..067ef051eb 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -6,6 +6,7 @@ package context
import (
"context"
+ "errors"
"fmt"
"html"
"net/http"
@@ -26,6 +27,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
code_indexer "code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -81,11 +83,15 @@ func (r *Repository) CanCreateBranch() bool {
return r.Permission.CanWrite(unit_model.TypeCode) && r.Repository.CanCreateBranch()
}
+func (r *Repository) GetObjectFormat() git.ObjectFormat {
+ return git.ObjectFormatFromName(r.Repository.ObjectFormatName)
+}
+
// RepoMustNotBeArchived checks if a repo is archived
func RepoMustNotBeArchived() func(ctx *Context) {
return func(ctx *Context) {
if ctx.Repo.Repository.IsArchived {
- ctx.NotFound("IsArchived", fmt.Errorf(ctx.Tr("repo.archive.title")))
+ ctx.NotFound("IsArchived", errors.New(ctx.Locale.TrString("repo.archive.title")))
}
}
}
@@ -670,7 +676,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
branchOpts := git_model.FindBranchOptions{
RepoID: ctx.Repo.Repository.ID,
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
ListOptions: db.ListOptionsAll,
}
branchesTotal, err := db.Count[git_model.Branch](ctx, branchOpts)
@@ -829,9 +835,8 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
}
// For legacy and API support only full commit sha
parts := strings.Split(path, "/")
- objectFormat, _ := repo.GitRepo.GetObjectFormat()
- if len(parts) > 0 && len(parts[0]) == objectFormat.FullLength() {
+ if len(parts) > 0 && len(parts[0]) == git.ObjectFormatFromName(repo.Repository.ObjectFormatName).FullLength() {
repo.TreePath = strings.Join(parts[1:], "/")
return parts[0]
}
@@ -875,9 +880,8 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
return getRefNameFromPath(ctx, repo, path, repo.GitRepo.IsTagExist)
case RepoRefCommit:
parts := strings.Split(path, "/")
- objectFormat, _ := repo.GitRepo.GetObjectFormat()
- if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= objectFormat.FullLength() {
+ if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= repo.GetObjectFormat().FullLength() {
repo.TreePath = strings.Join(parts[1:], "/")
return parts[0]
}
@@ -936,12 +940,6 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
}
}
- objectFormat, err := ctx.Repo.GitRepo.GetObjectFormat()
- if err != nil {
- log.Error("Cannot determine objectFormat for repository: %w", err)
- ctx.Repo.Repository.MarkAsBrokenEmpty()
- }
-
// Get default branch.
if len(ctx.Params("*")) == 0 {
refName = ctx.Repo.Repository.DefaultBranch
@@ -1008,7 +1006,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
return cancel
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
- } else if len(refName) >= 7 && len(refName) <= objectFormat.FullLength() {
+ } else if len(refName) >= 7 && len(refName) <= ctx.Repo.GetObjectFormat().FullLength() {
ctx.Repo.IsViewCommit = true
ctx.Repo.CommitID = refName
@@ -1018,7 +1016,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
return cancel
}
// If short commit ID add canonical link header
- if len(refName) < objectFormat.FullLength() {
+ if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
ctx.RespHeader().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"",
util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))))
}
diff --git a/modules/contexttest/context_tests.go b/modules/contexttest/context_tests.go
index 9ca028bb6e..c9bacf259f 100644
--- a/modules/contexttest/context_tests.go
+++ b/modules/contexttest/context_tests.go
@@ -40,8 +40,19 @@ func mockRequest(t *testing.T, reqPath string) *http.Request {
return req
}
+type MockContextOption struct {
+ Render context.Render
+}
+
// MockContext mock context for unit tests
-func MockContext(t *testing.T, reqPath string) (*context.Context, *httptest.ResponseRecorder) {
+func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*context.Context, *httptest.ResponseRecorder) {
+ var opt MockContextOption
+ if len(opts) > 0 {
+ opt = opts[0]
+ }
+ if opt.Render == nil {
+ opt.Render = &MockRender{}
+ }
resp := httptest.NewRecorder()
req := mockRequest(t, reqPath)
base, baseCleanUp := context.NewBaseContext(resp, req)
@@ -49,7 +60,7 @@ func MockContext(t *testing.T, reqPath string) (*context.Context, *httptest.Resp
base.Data = middleware.GetContextData(req.Context())
base.Locale = &translation.MockLocale{}
- ctx := context.NewWebContext(base, &MockRender{}, nil)
+ ctx := context.NewWebContext(base, opt.Render, nil)
chiCtx := chi.NewRouteContext()
ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
diff --git a/modules/csv/csv.go b/modules/csv/csv.go
index c5497befe7..35c5d6ab67 100644
--- a/modules/csv/csv.go
+++ b/modules/csv/csv.go
@@ -123,9 +123,9 @@ func guessDelimiter(data []byte) rune {
func FormatError(err error, locale translation.Locale) (string, error) {
if perr, ok := err.(*stdcsv.ParseError); ok {
if perr.Err == stdcsv.ErrFieldCount {
- return locale.Tr("repo.error.csv.invalid_field_count", perr.Line), nil
+ return locale.TrString("repo.error.csv.invalid_field_count", perr.Line), nil
}
- return locale.Tr("repo.error.csv.unexpected", perr.Line, perr.Column), nil
+ return locale.TrString("repo.error.csv.unexpected", perr.Line, perr.Column), nil
}
return "", err
diff --git a/modules/generate/generate.go b/modules/generate/generate.go
index ee3c76059b..2d9a3dd902 100644
--- a/modules/generate/generate.go
+++ b/modules/generate/generate.go
@@ -7,6 +7,7 @@ package generate
import (
"crypto/rand"
"encoding/base64"
+ "fmt"
"io"
"time"
@@ -38,19 +39,24 @@ func NewInternalToken() (string, error) {
return internalToken, nil
}
-// NewJwtSecret generates a new value intended to be used for JWT secrets.
-func NewJwtSecret() ([]byte, error) {
- bytes := make([]byte, 32)
- _, err := io.ReadFull(rand.Reader, bytes)
- if err != nil {
+const defaultJwtSecretLen = 32
+
+// DecodeJwtSecretBase64 decodes a base64 encoded jwt secret into bytes, and check its length
+func DecodeJwtSecretBase64(src string) ([]byte, error) {
+ encoding := base64.RawURLEncoding
+ decoded := make([]byte, encoding.DecodedLen(len(src))+3)
+ if n, err := encoding.Decode(decoded, []byte(src)); err != nil {
return nil, err
+ } else if n != defaultJwtSecretLen {
+ return nil, fmt.Errorf("invalid base64 decoded length: %d, expects: %d", n, defaultJwtSecretLen)
}
- return bytes, nil
+ return decoded[:defaultJwtSecretLen], nil
}
-// NewJwtSecretBase64 generates a new base64 encoded value intended to be used for JWT secrets.
-func NewJwtSecretBase64() ([]byte, string, error) {
- bytes, err := NewJwtSecret()
+// NewJwtSecretWithBase64 generates a jwt secret with its base64 encoded value intended to be used for saving into config file
+func NewJwtSecretWithBase64() ([]byte, string, error) {
+ bytes := make([]byte, defaultJwtSecretLen)
+ _, err := io.ReadFull(rand.Reader, bytes)
if err != nil {
return nil, "", err
}
diff --git a/modules/generate/generate_test.go b/modules/generate/generate_test.go
new file mode 100644
index 0000000000..af640a60c1
--- /dev/null
+++ b/modules/generate/generate_test.go
@@ -0,0 +1,34 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package generate
+
+import (
+ "encoding/base64"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestDecodeJwtSecretBase64(t *testing.T) {
+ _, err := DecodeJwtSecretBase64("abcd")
+ assert.ErrorContains(t, err, "invalid base64 decoded length")
+ _, err = DecodeJwtSecretBase64(strings.Repeat("a", 64))
+ assert.ErrorContains(t, err, "invalid base64 decoded length")
+
+ str32 := strings.Repeat("x", 32)
+ encoded32 := base64.RawURLEncoding.EncodeToString([]byte(str32))
+ decoded32, err := DecodeJwtSecretBase64(encoded32)
+ assert.NoError(t, err)
+ assert.Equal(t, str32, string(decoded32))
+}
+
+func TestNewJwtSecretWithBase64(t *testing.T) {
+ secret, encoded, err := NewJwtSecretWithBase64()
+ assert.NoError(t, err)
+ assert.Len(t, secret, 32)
+ decoded, err := DecodeJwtSecretBase64(encoded)
+ assert.NoError(t, err)
+ assert.Equal(t, secret, decoded)
+}
diff --git a/modules/git/attribute.go b/modules/git/attribute.go
new file mode 100644
index 0000000000..4dfa510369
--- /dev/null
+++ b/modules/git/attribute.go
@@ -0,0 +1,35 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package git
+
+import (
+ "code.gitea.io/gitea/modules/optional"
+)
+
+const (
+ AttributeLinguistVendored = "linguist-vendored"
+ AttributeLinguistGenerated = "linguist-generated"
+ AttributeLinguistDocumentation = "linguist-documentation"
+ AttributeLinguistDetectable = "linguist-detectable"
+ AttributeLinguistLanguage = "linguist-language"
+ AttributeGitlabLanguage = "gitlab-language"
+)
+
+// true if "set"/"true", false if "unset"/"false", none otherwise
+func AttributeToBool(attr map[string]string, name string) optional.Option[bool] {
+ switch attr[name] {
+ case "set", "true":
+ return optional.Some(true)
+ case "unset", "false":
+ return optional.Some(false)
+ }
+ return optional.None[bool]()
+}
+
+func AttributeToString(attr map[string]string, name string) optional.Option[string] {
+ if value, has := attr[name]; has && value != "unspecified" {
+ return optional.Some(value)
+ }
+ return optional.None[string]()
+}
diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go
index 53a9393d5f..043dbb44bd 100644
--- a/modules/git/batch_reader.go
+++ b/modules/git/batch_reader.go
@@ -203,16 +203,7 @@ headerLoop:
}
// Discard the rest of the tag
- discard := size - n + 1
- for discard > math.MaxInt32 {
- _, err := rd.Discard(math.MaxInt32)
- if err != nil {
- return id, err
- }
- discard -= math.MaxInt32
- }
- _, err := rd.Discard(int(discard))
- return id, err
+ return id, DiscardFull(rd, size-n+1)
}
// ReadTreeID reads a tree ID from a cat-file --batch stream, throwing away the rest of the stream.
@@ -238,16 +229,7 @@ headerLoop:
}
// Discard the rest of the commit
- discard := size - n + 1
- for discard > math.MaxInt32 {
- _, err := rd.Discard(math.MaxInt32)
- if err != nil {
- return id, err
- }
- discard -= math.MaxInt32
- }
- _, err := rd.Discard(int(discard))
- return id, err
+ return id, DiscardFull(rd, size-n+1)
}
// git tree files are a list:
@@ -345,3 +327,21 @@ func init() {
_, filename, _, _ := runtime.Caller(0)
callerPrefix = strings.TrimSuffix(filename, "modules/git/batch_reader.go")
}
+
+func DiscardFull(rd *bufio.Reader, discard int64) error {
+ if discard > math.MaxInt32 {
+ n, err := rd.Discard(math.MaxInt32)
+ discard -= int64(n)
+ if err != nil {
+ return err
+ }
+ }
+ for discard > 0 {
+ n, err := rd.Discard(int(discard))
+ discard -= int64(n)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/modules/git/blame.go b/modules/git/blame.go
index 64095a218a..69e1b08f93 100644
--- a/modules/git/blame.go
+++ b/modules/git/blame.go
@@ -115,6 +115,10 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
// Close BlameReader - don't run NextPart after invoking that
func (r *BlameReader) Close() error {
+ if r.bufferedReader == nil {
+ return nil
+ }
+
err := <-r.done
r.bufferedReader = nil
_ = r.reader.Close()
diff --git a/modules/git/blob_nogogit.go b/modules/git/blob_nogogit.go
index 6e8a48b1db..945a6bc432 100644
--- a/modules/git/blob_nogogit.go
+++ b/modules/git/blob_nogogit.go
@@ -9,7 +9,6 @@ import (
"bufio"
"bytes"
"io"
- "math"
"code.gitea.io/gitea/modules/log"
)
@@ -103,26 +102,17 @@ func (b *blobReader) Read(p []byte) (n int, err error) {
// Close implements io.Closer
func (b *blobReader) Close() error {
- defer b.cancel()
- if b.n > 0 {
- for b.n > math.MaxInt32 {
- n, err := b.rd.Discard(math.MaxInt32)
- b.n -= int64(n)
- if err != nil {
- return err
- }
- b.n -= math.MaxInt32
- }
- n, err := b.rd.Discard(int(b.n))
- b.n -= int64(n)
- if err != nil {
- return err
- }
+ if b.rd == nil {
+ return nil
}
- if b.n == 0 {
- _, err := b.rd.Discard(1)
- b.n--
+
+ defer b.cancel()
+
+ if err := DiscardFull(b.rd, b.n+1); err != nil {
return err
}
+
+ b.rd = nil
+
return nil
}
diff --git a/modules/git/commit_info_nogogit.go b/modules/git/commit_info_nogogit.go
index e469d2cab6..a5d18694f7 100644
--- a/modules/git/commit_info_nogogit.go
+++ b/modules/git/commit_info_nogogit.go
@@ -151,6 +151,9 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
return nil, err
}
if typ != "commit" {
+ if err := DiscardFull(batchReader, size+1); err != nil {
+ return nil, err
+ }
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
}
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))
diff --git a/modules/git/error.go b/modules/git/error.go
index dc10d451b3..91d25eca69 100644
--- a/modules/git/error.go
+++ b/modules/git/error.go
@@ -96,7 +96,7 @@ func (err ErrBranchNotExist) Unwrap() error {
return util.ErrNotExist
}
-// ErrPushOutOfDate represents an error if merging fails due to unrelated histories
+// ErrPushOutOfDate represents an error if merging fails due to the base branch being updated
type ErrPushOutOfDate struct {
StdOut string
StdErr string
diff --git a/modules/git/git.go b/modules/git/git.go
index 89c23ff230..f688ea7488 100644
--- a/modules/git/git.go
+++ b/modules/git/git.go
@@ -33,42 +33,45 @@ var (
// DefaultContext is the default context to run git commands in, must be initialized by git.InitXxx
DefaultContext context.Context
- SupportProcReceive bool // >= 2.29
- SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’
+ DefaultFeatures struct {
+ GitVersion *version.Version
- gitVersion *version.Version
+ SupportProcReceive bool // >= 2.29
+ SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’
+ }
)
-// loadGitVersion returns current Git version from shell. Internal usage only.
-func loadGitVersion() (*version.Version, error) {
+// loadGitVersion tries to get the current git version and stores it into a global variable
+func loadGitVersion() error {
// doesn't need RWMutex because it's executed by Init()
- if gitVersion != nil {
- return gitVersion, nil
+ if DefaultFeatures.GitVersion != nil {
+ return nil
}
stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil)
if runErr != nil {
- return nil, runErr
+ return runErr
}
- fields := strings.Fields(stdout)
+ ver, err := parseGitVersionLine(strings.TrimSpace(stdout))
+ if err == nil {
+ DefaultFeatures.GitVersion = ver
+ }
+ return err
+}
+
+func parseGitVersionLine(s string) (*version.Version, error) {
+ fields := strings.Fields(s)
if len(fields) < 3 {
- return nil, fmt.Errorf("invalid git version output: %s", stdout)
+ return nil, fmt.Errorf("invalid git version: %q", s)
}
- var versionString string
-
- // Handle special case on Windows.
- i := strings.Index(fields[2], "windows")
- if i >= 1 {
- versionString = fields[2][:i-1]
- } else {
- versionString = fields[2]
+ // version string is like: "git version 2.29.3" or "git version 2.29.3.windows.1"
+ versionString := fields[2]
+ if pos := strings.Index(versionString, "windows"); pos >= 1 {
+ versionString = versionString[:pos-1]
}
-
- var err error
- gitVersion, err = version.NewVersion(versionString)
- return gitVersion, err
+ return version.NewVersion(versionString)
}
// SetExecutablePath changes the path of git executable and checks the file permission and version.
@@ -83,8 +86,7 @@ func SetExecutablePath(path string) error {
}
GitExecutable = absPath
- _, err = loadGitVersion()
- if err != nil {
+ if err = loadGitVersion(); err != nil {
return fmt.Errorf("unable to load git version: %w", err)
}
@@ -93,7 +95,7 @@ func SetExecutablePath(path string) error {
return err
}
- if gitVersion.LessThan(versionRequired) {
+ if DefaultFeatures.GitVersion.LessThan(versionRequired) {
moreHint := "get git: https://git-scm.com/download/"
if runtime.GOOS == "linux" {
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
@@ -102,19 +104,22 @@ func SetExecutablePath(path string) error {
moreHint = "get git: https://git-scm.com/download/linux and https://ius.io"
}
}
- return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", gitVersion.Original(), RequiredVersion, moreHint)
+ return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures.GitVersion.Original(), RequiredVersion, moreHint)
}
+ if err = checkGitVersionCompatibility(DefaultFeatures.GitVersion); err != nil {
+ return fmt.Errorf("installed git version %s has a known compatibility issue with Gitea: %w, please upgrade (or downgrade) git", DefaultFeatures.GitVersion.String(), err)
+ }
return nil
}
// VersionInfo returns git version information
func VersionInfo() string {
- if gitVersion == nil {
+ if DefaultFeatures.GitVersion == nil {
return "(git not found)"
}
format := "%s"
- args := []any{gitVersion.Original()}
+ args := []any{DefaultFeatures.GitVersion.Original()}
// Since git wire protocol has been released from git v2.18
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
format += ", Wire Protocol %s Enabled"
@@ -184,9 +189,9 @@ func InitFull(ctx context.Context) (err error) {
if CheckGitVersionAtLeast("2.9") == nil {
globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=")
}
- SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil
- SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil && !isGogit
- if SupportHashSha256 {
+ DefaultFeatures.SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil
+ DefaultFeatures.SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil && !isGogit
+ if DefaultFeatures.SupportHashSha256 {
SupportedObjectFormats = append(SupportedObjectFormats, Sha256ObjectFormat)
} else {
log.Warn("sha256 hash support is disabled - requires Git >= 2.42. Gogit is currently unsupported")
@@ -251,7 +256,7 @@ func syncGitConfig() (err error) {
}
}
- if SupportProcReceive {
+ if DefaultFeatures.SupportProcReceive {
// set support for AGit flow
if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil {
return err
@@ -262,19 +267,18 @@ func syncGitConfig() (err error) {
}
}
- // Due to CVE-2022-24765, git now denies access to git directories which are not owned by current user
- // however, some docker users and samba users find it difficult to configure their systems so that Gitea's git repositories are owned by the Gitea user. (Possibly Windows Service users - but ownership in this case should really be set correctly on the filesystem.)
- // see issue: https://github.com/go-gitea/gitea/issues/19455
- // Fundamentally the problem lies with the uid-gid-mapping mechanism for filesystems in docker on windows (and to a lesser extent samba).
- // Docker's configuration mechanism for local filesystems provides no way of setting this mapping and although there is a mechanism for setting this uid through using cifs mounting it is complicated and essentially undocumented
- // Thus the owner uid/gid for files on these filesystems will be marked as root.
+ // Due to CVE-2022-24765, git now denies access to git directories which are not owned by current user.
+ // However, some docker users and samba users find it difficult to configure their systems correctly,
+ // so that Gitea's git repositories are owned by the Gitea user.
+ // (Possibly Windows Service users - but ownership in this case should really be set correctly on the filesystem.)
+ // See issue: https://github.com/go-gitea/gitea/issues/19455
// As Gitea now always use its internal git config file, and access to the git repositories is managed through Gitea,
// it is now safe to set "safe.directory=*" for internal usage only.
- // Please note: the wildcard "*" is only supported by Git 2.30.4/2.31.3/2.32.2/2.33.3/2.34.3/2.35.3/2.36 and later
- // Although only supported by Git 2.30.4/2.31.3/2.32.2/2.33.3/2.34.3/2.35.3/2.36 and later - this setting is tolerated by earlier versions
+ // Although this setting is only supported by some new git versions, it is also tolerated by earlier versions
if err := configAddNonExist("safe.directory", "*"); err != nil {
return err
}
+
if runtime.GOOS == "windows" {
if err := configSet("core.longpaths", "true"); err != nil {
return err
@@ -307,15 +311,30 @@ func syncGitConfig() (err error) {
// CheckGitVersionAtLeast check git version is at least the constraint version
func CheckGitVersionAtLeast(atLeast string) error {
- if _, err := loadGitVersion(); err != nil {
- return err
+ if DefaultFeatures.GitVersion == nil {
+ panic("git module is not initialized") // it shouldn't happen
}
atLeastVersion, err := version.NewVersion(atLeast)
if err != nil {
return err
}
- if gitVersion.Compare(atLeastVersion) < 0 {
- return fmt.Errorf("installed git binary version %s is not at least %s", gitVersion.Original(), atLeast)
+ if DefaultFeatures.GitVersion.Compare(atLeastVersion) < 0 {
+ return fmt.Errorf("installed git binary version %s is not at least %s", DefaultFeatures.GitVersion.Original(), atLeast)
+ }
+ return nil
+}
+
+func checkGitVersionCompatibility(gitVer *version.Version) error {
+ badVersions := []struct {
+ Version *version.Version
+ Reason string
+ }{
+ {version.Must(version.NewVersion("2.43.1")), "regression bug of GIT_FLUSH"},
+ }
+ for _, bad := range badVersions {
+ if gitVer.Equal(bad.Version) {
+ return errors.New(bad.Reason)
+ }
}
return nil
}
diff --git a/modules/git/git_test.go b/modules/git/git_test.go
index 37ab669ea4..fc92bebe04 100644
--- a/modules/git/git_test.go
+++ b/modules/git/git_test.go
@@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
+ "github.com/hashicorp/go-version"
"github.com/stretchr/testify/assert"
)
@@ -93,3 +94,25 @@ func TestSyncConfig(t *testing.T) {
assert.True(t, gitConfigContains("[sync-test]"))
assert.True(t, gitConfigContains("cfg-key-a = CfgValA"))
}
+
+func TestParseGitVersion(t *testing.T) {
+ v, err := parseGitVersionLine("git version 2.29.3")
+ assert.NoError(t, err)
+ assert.Equal(t, "2.29.3", v.String())
+
+ v, err = parseGitVersionLine("git version 2.29.3.windows.1")
+ assert.NoError(t, err)
+ assert.Equal(t, "2.29.3", v.String())
+
+ _, err = parseGitVersionLine("git version")
+ assert.Error(t, err)
+
+ _, err = parseGitVersionLine("git version windows")
+ assert.Error(t, err)
+}
+
+func TestCheckGitVersionCompatibility(t *testing.T) {
+ assert.NoError(t, checkGitVersionCompatibility(version.Must(version.NewVersion("2.43.0"))))
+ assert.ErrorContains(t, checkGitVersionCompatibility(version.Must(version.NewVersion("2.43.1"))), "regression bug of GIT_FLUSH")
+ assert.NoError(t, checkGitVersionCompatibility(version.Must(version.NewVersion("2.43.2"))))
+}
diff --git a/modules/git/last_commit_cache.go b/modules/git/last_commit_cache.go
index 7c7baedd2f..5b62b90b27 100644
--- a/modules/git/last_commit_cache.go
+++ b/modules/git/last_commit_cache.go
@@ -4,12 +4,11 @@
package git
import (
+ "crypto/sha256"
"fmt"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
-
- "github.com/minio/sha256-simd"
)
// Cache represents a caching interface
diff --git a/modules/git/log_name_status.go b/modules/git/log_name_status.go
index 26a0d28098..9e345f3ee0 100644
--- a/modules/git/log_name_status.go
+++ b/modules/git/log_name_status.go
@@ -143,19 +143,19 @@ func (g *LogNameStatusRepoParser) Next(treepath string, paths2ids map[string]int
}
// Our "line" must look like: SP ( SP) * NUL
- commitIds := string(g.next)
+ commitIDs := string(g.next)
if g.buffull {
more, err := g.rd.ReadString('\x00')
if err != nil {
return nil, err
}
- commitIds += more
+ commitIDs += more
}
- commitIds = commitIds[:len(commitIds)-1]
- splitIds := strings.Split(commitIds, " ")
- ret.CommitID = splitIds[0]
- if len(splitIds) > 1 {
- ret.ParentIDs = splitIds[1:]
+ commitIDs = commitIDs[:len(commitIDs)-1]
+ splitIDs := strings.Split(commitIDs, " ")
+ ret.CommitID = splitIDs[0]
+ if len(splitIDs) > 1 {
+ ret.ParentIDs = splitIDs[1:]
}
// now read the next "line"
diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go
index a725f4799d..4c65249089 100644
--- a/modules/git/pipeline/lfs_nogogit.go
+++ b/modules/git/pipeline/lfs_nogogit.go
@@ -169,6 +169,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
} else {
break commitReadingLoop
}
+ default:
+ if err := git.DiscardFull(batchReader, size+1); err != nil {
+ return nil, err
+ }
}
}
}
diff --git a/modules/git/repo.go b/modules/git/repo.go
index db99d285a8..cef45c6af0 100644
--- a/modules/git/repo.go
+++ b/modules/git/repo.go
@@ -101,7 +101,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
if !IsValidObjectFormat(objectFormatName) {
return fmt.Errorf("invalid object format: %s", objectFormatName)
}
- if SupportHashSha256 {
+ if DefaultFeatures.SupportHashSha256 {
cmd.AddOptionValues("--object-format", objectFormatName)
}
@@ -271,7 +271,7 @@ func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error
return time.Time{}, err
}
commitTime := strings.TrimSpace(stdout)
- return time.Parse(GitTimeLayout, commitTime)
+ return time.Parse("Mon Jan _2 15:04:05 2006 -0700", commitTime)
}
// DivergeObject represents commit count diverging commits
diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go
index 2b34f117f7..84f85d1b1a 100644
--- a/modules/git/repo_attribute.go
+++ b/modules/git/repo_attribute.go
@@ -291,10 +291,17 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
}
checker := &CheckAttributeReader{
- Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"},
- Repo: repo,
- IndexFile: indexFilename,
- WorkTree: worktree,
+ Attributes: []string{
+ AttributeLinguistVendored,
+ AttributeLinguistGenerated,
+ AttributeLinguistDocumentation,
+ AttributeLinguistDetectable,
+ AttributeLinguistLanguage,
+ AttributeGitlabLanguage,
+ },
+ Repo: repo,
+ IndexFile: indexFilename,
+ WorkTree: worktree,
}
ctx, cancel := context.WithCancel(repo.Ctx)
if err := checker.Init(ctx); err != nil {
diff --git a/modules/git/repo_attribute_test.go b/modules/git/repo_attribute_test.go
index ed16dccbe4..0fcd94b4c7 100644
--- a/modules/git/repo_attribute_test.go
+++ b/modules/git/repo_attribute_test.go
@@ -24,7 +24,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
select {
case attr := <-wr.ReadAttribute():
assert.Equal(t, ".gitignore\"\n", attr.Filename)
- assert.Equal(t, "linguist-vendored", attr.Attribute)
+ assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
assert.Equal(t, "unspecified", attr.Value)
case <-time.After(100 * time.Millisecond):
assert.FailNow(t, "took too long to read an attribute from the list")
@@ -38,7 +38,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
select {
case attr := <-wr.ReadAttribute():
assert.Equal(t, ".gitignore\"\n", attr.Filename)
- assert.Equal(t, "linguist-vendored", attr.Attribute)
+ assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
assert.Equal(t, "unspecified", attr.Value)
case <-time.After(100 * time.Millisecond):
assert.FailNow(t, "took too long to read an attribute from the list")
@@ -77,21 +77,21 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
assert.NoError(t, err)
assert.EqualValues(t, attributeTriple{
Filename: "shouldbe.vendor",
- Attribute: "linguist-vendored",
+ Attribute: AttributeLinguistVendored,
Value: "set",
}, attr)
attr = <-wr.ReadAttribute()
assert.NoError(t, err)
assert.EqualValues(t, attributeTriple{
Filename: "shouldbe.vendor",
- Attribute: "linguist-generated",
+ Attribute: AttributeLinguistGenerated,
Value: "unspecified",
}, attr)
attr = <-wr.ReadAttribute()
assert.NoError(t, err)
assert.EqualValues(t, attributeTriple{
Filename: "shouldbe.vendor",
- Attribute: "linguist-language",
+ Attribute: AttributeLinguistLanguage,
Value: "unspecified",
}, attr)
}
diff --git a/modules/git/repo_base_gogit.go b/modules/git/repo_base_gogit.go
index 9270bb70f0..3ca5eb36c6 100644
--- a/modules/git/repo_base_gogit.go
+++ b/modules/git/repo_base_gogit.go
@@ -88,16 +88,17 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
}
// Close this repository, in particular close the underlying gogitStorage if this is not nil
-func (repo *Repository) Close() (err error) {
+func (repo *Repository) Close() error {
if repo == nil || repo.gogitStorage == nil {
- return
+ return nil
}
if err := repo.gogitStorage.Close(); err != nil {
gitealog.Error("Error closing storage: %v", err)
}
+ repo.gogitStorage = nil
repo.LastCommitCache = nil
repo.tagCache = nil
- return
+ return nil
}
// GoGitRepo gets the go-git repo representation
diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go
index d5a350a926..86b6a93567 100644
--- a/modules/git/repo_base_nogogit.go
+++ b/modules/git/repo_base_nogogit.go
@@ -27,10 +27,12 @@ type Repository struct {
gpgSettings *GPGSettings
+ batchInUse bool
batchCancel context.CancelFunc
batchReader *bufio.Reader
batchWriter WriteCloserError
+ checkInUse bool
checkCancel context.CancelFunc
checkReader *bufio.Reader
checkWriter WriteCloserError
@@ -79,24 +81,29 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
// CatFileBatch obtains a CatFileBatch for this repository
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
- if repo.batchCancel == nil || repo.batchReader.Buffered() > 0 {
+ if repo.batchCancel == nil || repo.batchInUse {
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
return CatFileBatch(ctx, repo.Path)
}
- return repo.batchWriter, repo.batchReader, func() {}
+ repo.batchInUse = true
+ return repo.batchWriter, repo.batchReader, func() {
+ repo.batchInUse = false
+ }
}
// CatFileBatchCheck obtains a CatFileBatchCheck for this repository
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
- if repo.checkCancel == nil || repo.checkReader.Buffered() > 0 {
- log.Debug("Opening temporary cat file batch-check: %s", repo.Path)
+ if repo.checkCancel == nil || repo.checkInUse {
+ log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
return CatFileBatchCheck(ctx, repo.Path)
}
- return repo.checkWriter, repo.checkReader, func() {}
+ repo.checkInUse = true
+ return repo.checkWriter, repo.checkReader, func() {
+ repo.checkInUse = false
+ }
}
-// Close this repository, in particular close the underlying gogitStorage if this is not nil
-func (repo *Repository) Close() (err error) {
+func (repo *Repository) Close() error {
if repo == nil {
return nil
}
@@ -105,14 +112,16 @@ func (repo *Repository) Close() (err error) {
repo.batchReader = nil
repo.batchWriter = nil
repo.batchCancel = nil
+ repo.batchInUse = false
}
if repo.checkCancel != nil {
repo.checkCancel()
repo.checkCancel = nil
repo.checkReader = nil
repo.checkWriter = nil
+ repo.checkInUse = false
}
repo.LastCommitCache = nil
repo.tagCache = nil
- return err
+ return nil
}
diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go
index f0214e1ff8..a7031184e2 100644
--- a/modules/git/repo_commit_nogogit.go
+++ b/modules/git/repo_commit_nogogit.go
@@ -121,8 +121,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
return commit, nil
default:
log.Debug("Unknown typ: %s", typ)
- _, err = rd.Discard(int(size) + 1)
- if err != nil {
+ if err := DiscardFull(rd, size+1); err != nil {
return nil, err
}
return nil, ErrNotExist{
diff --git a/modules/git/repo_language_stats.go b/modules/git/repo_language_stats.go
index c40d6937b5..8551ea9d24 100644
--- a/modules/git/repo_language_stats.go
+++ b/modules/git/repo_language_stats.go
@@ -6,6 +6,8 @@ package git
import (
"strings"
"unicode"
+
+ "code.gitea.io/gitea/modules/optional"
)
const (
@@ -46,3 +48,20 @@ func mergeLanguageStats(stats map[string]int64) map[string]int64 {
}
return res
}
+
+func TryReadLanguageAttribute(attrs map[string]string) optional.Option[string] {
+ language := AttributeToString(attrs, AttributeLinguistLanguage)
+ if language.Value() == "" {
+ language = AttributeToString(attrs, AttributeGitlabLanguage)
+ if language.Has() {
+ raw := language.Value()
+ // gitlab-language may have additional parameters after the language
+ // ignore them and just use the main language
+ // https://docs.gitlab.com/ee/user/project/highlighting.html#override-syntax-highlighting-for-a-file-type
+ if idx := strings.IndexByte(raw, '?'); idx >= 0 {
+ language = optional.Some(raw[:idx])
+ }
+ }
+ }
+ return language
+}
diff --git a/modules/git/repo_language_stats_gogit.go b/modules/git/repo_language_stats_gogit.go
index 4c6fbd6c7e..a34c03c781 100644
--- a/modules/git/repo_language_stats_gogit.go
+++ b/modules/git/repo_language_stats_gogit.go
@@ -8,9 +8,9 @@ package git
import (
"bytes"
"io"
- "strings"
"code.gitea.io/gitea/modules/analyze"
+ "code.gitea.io/gitea/modules/optional"
"github.com/go-enry/go-enry/v2"
"github.com/go-git/go-git/v5"
@@ -57,25 +57,38 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil
}
- notVendored := false
- notGenerated := false
+ isVendored := optional.None[bool]()
+ isGenerated := optional.None[bool]()
+ isDocumentation := optional.None[bool]()
+ isDetectable := optional.None[bool]()
if checker != nil {
attrs, err := checker.CheckPath(f.Name)
if err == nil {
- if vendored, has := attrs["linguist-vendored"]; has {
- if vendored == "set" || vendored == "true" {
- return nil
- }
- notVendored = vendored == "false"
+ isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
+ if isVendored.ValueOrDefault(false) {
+ return nil
}
- if generated, has := attrs["linguist-generated"]; has {
- if generated == "set" || generated == "true" {
- return nil
- }
- notGenerated = generated == "false"
+
+ isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
+ if isGenerated.ValueOrDefault(false) {
+ return nil
}
- if language, has := attrs["linguist-language"]; has && language != "unspecified" && language != "" {
+
+ isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
+ if isDocumentation.ValueOrDefault(false) {
+ return nil
+ }
+
+ isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
+ if !isDetectable.ValueOrDefault(true) {
+ return nil
+ }
+
+ hasLanguage := TryReadLanguageAttribute(attrs)
+ if hasLanguage.Value() != "" {
+ language := hasLanguage.Value()
+
// group languages, such as Pug -> HTML; SCSS -> CSS
group := enry.GetLanguageGroup(language)
if len(group) != 0 {
@@ -85,28 +98,14 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
// this language will always be added to the size
sizes[language] += f.Size
return nil
- } else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
- // strip off a ? if present
- if idx := strings.IndexByte(language, '?'); idx >= 0 {
- language = language[:idx]
- }
- if len(language) != 0 {
- // group languages, such as Pug -> HTML; SCSS -> CSS
- group := enry.GetLanguageGroup(language)
- if len(group) != 0 {
- language = group
- }
-
- // this language will always be added to the size
- sizes[language] += f.Size
- return nil
- }
}
}
}
- if (!notVendored && analyze.IsVendor(f.Name)) || enry.IsDotFile(f.Name) ||
- enry.IsDocumentation(f.Name) || enry.IsConfiguration(f.Name) {
+ if (!isVendored.Has() && analyze.IsVendor(f.Name)) ||
+ enry.IsDotFile(f.Name) ||
+ (!isDocumentation.Has() && enry.IsDocumentation(f.Name)) ||
+ enry.IsConfiguration(f.Name) {
return nil
}
@@ -115,12 +114,10 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
if f.Size <= bigFileSize {
content, _ = readFile(f, fileSizeLimit)
}
- if !notGenerated && enry.IsGenerated(f.Name, content) {
+ if !isGenerated.Has() && enry.IsGenerated(f.Name, content) {
return nil
}
- // TODO: Use .gitattributes file for linguist overrides
-
language := analyze.GetCodeLanguage(f.Name, content)
if language == enry.OtherLanguage || language == "" {
return nil
@@ -138,7 +135,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
included = langtype == enry.Programming || langtype == enry.Markup
includedLanguage[language] = included
}
- if included {
+ if included || isDetectable.ValueOrDefault(false) {
sizes[language] += f.Size
} else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) {
firstExcludedLanguage = language
diff --git a/modules/git/repo_language_stats_nogogit.go b/modules/git/repo_language_stats_nogogit.go
index 1d94ad6c00..318fc091ce 100644
--- a/modules/git/repo_language_stats_nogogit.go
+++ b/modules/git/repo_language_stats_nogogit.go
@@ -6,14 +6,12 @@
package git
import (
- "bufio"
"bytes"
"io"
- "math"
- "strings"
"code.gitea.io/gitea/modules/analyze"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"github.com/go-enry/go-enry/v2"
)
@@ -90,25 +88,38 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
continue
}
- notVendored := false
- notGenerated := false
+ isVendored := optional.None[bool]()
+ isGenerated := optional.None[bool]()
+ isDocumentation := optional.None[bool]()
+ isDetectable := optional.None[bool]()
if checker != nil {
attrs, err := checker.CheckPath(f.Name())
if err == nil {
- if vendored, has := attrs["linguist-vendored"]; has {
- if vendored == "set" || vendored == "true" {
- continue
- }
- notVendored = vendored == "false"
+ isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
+ if isVendored.ValueOrDefault(false) {
+ continue
}
- if generated, has := attrs["linguist-generated"]; has {
- if generated == "set" || generated == "true" {
- continue
- }
- notGenerated = generated == "false"
+
+ isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
+ if isGenerated.ValueOrDefault(false) {
+ continue
}
- if language, has := attrs["linguist-language"]; has && language != "unspecified" && language != "" {
+
+ isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
+ if isDocumentation.ValueOrDefault(false) {
+ continue
+ }
+
+ isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
+ if !isDetectable.ValueOrDefault(true) {
+ continue
+ }
+
+ hasLanguage := TryReadLanguageAttribute(attrs)
+ if hasLanguage.Value() != "" {
+ language := hasLanguage.Value()
+
// group languages, such as Pug -> HTML; SCSS -> CSS
group := enry.GetLanguageGroup(language)
if len(group) != 0 {
@@ -118,29 +129,14 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
// this language will always be added to the size
sizes[language] += f.Size()
continue
- } else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
- // strip off a ? if present
- if idx := strings.IndexByte(language, '?'); idx >= 0 {
- language = language[:idx]
- }
- if len(language) != 0 {
- // group languages, such as Pug -> HTML; SCSS -> CSS
- group := enry.GetLanguageGroup(language)
- if len(group) != 0 {
- language = group
- }
-
- // this language will always be added to the size
- sizes[language] += f.Size()
- continue
- }
}
-
}
}
- if (!notVendored && analyze.IsVendor(f.Name())) || enry.IsDotFile(f.Name()) ||
- enry.IsDocumentation(f.Name()) || enry.IsConfiguration(f.Name()) {
+ if (!isVendored.Has() && analyze.IsVendor(f.Name())) ||
+ enry.IsDotFile(f.Name()) ||
+ (!isDocumentation.Has() && enry.IsDocumentation(f.Name())) ||
+ enry.IsConfiguration(f.Name()) {
continue
}
@@ -168,12 +164,11 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil, err
}
content = contentBuf.Bytes()
- err = discardFull(batchReader, discard)
- if err != nil {
+ if err := DiscardFull(batchReader, discard); err != nil {
return nil, err
}
}
- if !notGenerated && enry.IsGenerated(f.Name(), content) {
+ if !isGenerated.Has() && enry.IsGenerated(f.Name(), content) {
continue
}
@@ -196,13 +191,12 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
included = langType == enry.Programming || langType == enry.Markup
includedLanguage[language] = included
}
- if included {
+ if included || isDetectable.ValueOrDefault(false) {
sizes[language] += f.Size()
} else if len(sizes) == 0 && (firstExcludedLanguage == "" || firstExcludedLanguage == language) {
firstExcludedLanguage = language
firstExcludedLanguageSize += f.Size()
}
- continue
}
// If there are no included languages add the first excluded language
@@ -212,21 +206,3 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return mergeLanguageStats(sizes), nil
}
-
-func discardFull(rd *bufio.Reader, discard int64) error {
- if discard > math.MaxInt32 {
- n, err := rd.Discard(math.MaxInt32)
- discard -= int64(n)
- if err != nil {
- return err
- }
- }
- for discard > 0 {
- n, err := rd.Discard(int(discard))
- discard -= int64(n)
- if err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go
index af9a75b29c..ae5dbd171f 100644
--- a/modules/git/repo_tag.go
+++ b/modules/git/repo_tag.go
@@ -183,11 +183,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
}
}
- tag.Tagger, err = newSignatureFromCommitline([]byte(ref["creator"]))
- if err != nil {
- return nil, fmt.Errorf("parse tagger: %w", err)
- }
-
+ tag.Tagger = parseSignatureFromCommitLine(ref["creator"])
tag.Message = ref["contents"]
// strip PGP signature if present in contents field
pgpStart := strings.Index(tag.Message, beginpgp)
diff --git a/modules/git/repo_tag_nogogit.go b/modules/git/repo_tag_nogogit.go
index 5d98fadd54..cbab39f8c5 100644
--- a/modules/git/repo_tag_nogogit.go
+++ b/modules/git/repo_tag_nogogit.go
@@ -103,6 +103,9 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
return nil, err
}
if typ != "tag" {
+ if err := DiscardFull(rd, size+1); err != nil {
+ return nil, err
+ }
return nil, ErrNotExist{ID: tagID.String()}
}
diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go
index da7b1455a8..9816e311a8 100644
--- a/modules/git/repo_tag_test.go
+++ b/modules/git/repo_tag_test.go
@@ -227,7 +227,7 @@ func TestRepository_parseTagRef(t *testing.T) {
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
Type: "commit",
- Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"),
+ Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"),
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
Signature: nil,
},
@@ -256,7 +256,7 @@ func TestRepository_parseTagRef(t *testing.T) {
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
Type: "tag",
- Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"),
+ Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"),
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
Signature: nil,
},
@@ -314,7 +314,7 @@ qbHDASXl
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
Type: "tag",
- Tagger: parseAuthorLine(t, "Foo Bar 1565789218 +0300"),
+ Tagger: parseSignatureFromCommitLine("Foo Bar 1565789218 +0300"),
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md",
Signature: &CommitGPGSignature{
Signature: `-----BEGIN PGP SIGNATURE-----
@@ -363,14 +363,3 @@ Add changelog of v1.9.1 (#7859)
})
}
}
-
-func parseAuthorLine(t *testing.T, committer string) *Signature {
- t.Helper()
-
- sig, err := newSignatureFromCommitline([]byte(committer))
- if err != nil {
- t.Fatalf("parse author line '%s': %v", committer, err)
- }
-
- return sig
-}
diff --git a/modules/git/repo_tree_nogogit.go b/modules/git/repo_tree_nogogit.go
index 20c92a79ed..582247b4a4 100644
--- a/modules/git/repo_tree_nogogit.go
+++ b/modules/git/repo_tree_nogogit.go
@@ -58,6 +58,9 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
tree.entriesParsed = true
return tree, nil
default:
+ if err := DiscardFull(rd, size+1); err != nil {
+ return nil, err
+ }
return nil, ErrNotExist{
ID: id.String(),
}
diff --git a/modules/git/signature.go b/modules/git/signature.go
index b5b17f23b0..f50a097758 100644
--- a/modules/git/signature.go
+++ b/modules/git/signature.go
@@ -4,7 +4,46 @@
package git
-const (
- // GitTimeLayout is the (default) time layout used by git.
- GitTimeLayout = "Mon Jan _2 15:04:05 2006 -0700"
+import (
+ "strconv"
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
)
+
+// Helper to get a signature from the commit line, which looks like:
+//
+// full name 1378823654 +0200
+//
+// Haven't found the official reference for the standard format yet.
+// This function never fails, if the "line" can't be parsed, it returns a default Signature with "zero" time.
+func parseSignatureFromCommitLine(line string) *Signature {
+ sig := &Signature{}
+ s1, sx, ok1 := strings.Cut(line, " <")
+ s2, s3, ok2 := strings.Cut(sx, "> ")
+ if !ok1 || !ok2 {
+ sig.Name = line
+ return sig
+ }
+ sig.Name, sig.Email = s1, s2
+
+ if strings.Count(s3, " ") == 1 {
+ ts, tz, _ := strings.Cut(s3, " ")
+ seconds, _ := strconv.ParseInt(ts, 10, 64)
+ if tzTime, err := time.Parse("-0700", tz); err == nil {
+ sig.When = time.Unix(seconds, 0).In(tzTime.Location())
+ }
+ } else {
+ // the old gitea code tried to parse the date in a few different formats, but it's not clear why.
+ // according to public document, only the standard format "timestamp timezone" could be found, so drop other formats.
+ log.Error("suspicious commit line format: %q", line)
+ for _, fmt := range []string{ /*"Mon Jan _2 15:04:05 2006 -0700"*/ } {
+ if t, err := time.Parse(fmt, s3); err == nil {
+ sig.When = t
+ break
+ }
+ }
+ }
+ return sig
+}
diff --git a/modules/git/signature_gogit.go b/modules/git/signature_gogit.go
index c984ad6e20..1fc6aabceb 100644
--- a/modules/git/signature_gogit.go
+++ b/modules/git/signature_gogit.go
@@ -7,52 +7,8 @@
package git
import (
- "bytes"
- "strconv"
- "strings"
- "time"
-
"github.com/go-git/go-git/v5/plumbing/object"
)
// Signature represents the Author or Committer information.
type Signature = object.Signature
-
-// Helper to get a signature from the commit line, which looks like these:
-//
-// author Patrick Gundlach 1378823654 +0200
-// author Patrick Gundlach Thu, 07 Apr 2005 22:13:13 +0200
-//
-// but without the "author " at the beginning (this method should)
-// be used for author and committer.
-//
-// FIXME: include timezone for timestamp!
-func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
- sig := new(Signature)
- emailStart := bytes.IndexByte(line, '<')
- if emailStart > 0 { // Empty name has already occurred, even if it shouldn't
- sig.Name = strings.TrimSpace(string(line[:emailStart-1]))
- }
- emailEnd := bytes.IndexByte(line, '>')
- sig.Email = string(line[emailStart+1 : emailEnd])
-
- // Check date format.
- if len(line) > emailEnd+2 {
- firstChar := line[emailEnd+2]
- if firstChar >= 48 && firstChar <= 57 {
- timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
- timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
- seconds, _ := strconv.ParseInt(timestring, 10, 64)
- sig.When = time.Unix(seconds, 0)
- } else {
- sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
- if err != nil {
- return nil, err
- }
- }
- } else {
- // Fall back to unix 0 time
- sig.When = time.Unix(0, 0)
- }
- return sig, nil
-}
diff --git a/modules/git/signature_nogogit.go b/modules/git/signature_nogogit.go
index 25277f99d5..0d19c0abdc 100644
--- a/modules/git/signature_nogogit.go
+++ b/modules/git/signature_nogogit.go
@@ -7,21 +7,17 @@
package git
import (
- "bytes"
"fmt"
- "strconv"
- "strings"
"time"
+
+ "code.gitea.io/gitea/modules/util"
)
-// Signature represents the Author or Committer information.
+// Signature represents the Author, Committer or Tagger information.
type Signature struct {
- // Name represents a person name. It is an arbitrary string.
- Name string
- // Email is an email, but it cannot be assumed to be well-formed.
- Email string
- // When is the timestamp of the signature.
- When time.Time
+ Name string // the committer name, it can be anything
+ Email string // the committer email, it can be anything
+ When time.Time // the timestamp of the signature
}
func (s *Signature) String() string {
@@ -30,71 +26,5 @@ func (s *Signature) String() string {
// Decode decodes a byte array representing a signature to signature
func (s *Signature) Decode(b []byte) {
- sig, _ := newSignatureFromCommitline(b)
- s.Email = sig.Email
- s.Name = sig.Name
- s.When = sig.When
-}
-
-// Helper to get a signature from the commit line, which looks like these:
-//
-// author Patrick Gundlach 1378823654 +0200
-// author Patrick Gundlach Thu, 07 Apr 2005 22:13:13 +0200
-//
-// but without the "author " at the beginning (this method should)
-// be used for author and committer.
-// FIXME: there are a lot of "return sig, err" (but the err is also nil), that's the old behavior, to avoid breaking
-func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
- sig = new(Signature)
- emailStart := bytes.LastIndexByte(line, '<')
- emailEnd := bytes.LastIndexByte(line, '>')
- if emailStart == -1 || emailEnd == -1 || emailEnd < emailStart {
- return sig, err
- }
-
- if emailStart > 0 { // Empty name has already occurred, even if it shouldn't
- sig.Name = strings.TrimSpace(string(line[:emailStart-1]))
- }
- sig.Email = string(line[emailStart+1 : emailEnd])
-
- hasTime := emailEnd+2 < len(line)
- if !hasTime {
- return sig, err
- }
-
- // Check date format.
- firstChar := line[emailEnd+2]
- if firstChar >= 48 && firstChar <= 57 {
- idx := bytes.IndexByte(line[emailEnd+2:], ' ')
- if idx < 0 {
- return sig, err
- }
-
- timestring := string(line[emailEnd+2 : emailEnd+2+idx])
- seconds, _ := strconv.ParseInt(timestring, 10, 64)
- sig.When = time.Unix(seconds, 0)
-
- idx += emailEnd + 3
- if idx >= len(line) || idx+5 > len(line) {
- return sig, err
- }
-
- timezone := string(line[idx : idx+5])
- tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64)
- tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64)
- if err1 != nil || err2 != nil {
- return sig, err
- }
- if tzhours < 0 {
- tzmins *= -1
- }
- tz := time.FixedZone("", int(tzhours*60*60+tzmins*60))
- sig.When = sig.When.In(tz)
- } else {
- sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
- if err != nil {
- return sig, err
- }
- }
- return sig, err
+ *s = *parseSignatureFromCommitLine(util.UnsafeBytesToString(b))
}
diff --git a/modules/git/signature_test.go b/modules/git/signature_test.go
new file mode 100644
index 0000000000..92681feea9
--- /dev/null
+++ b/modules/git/signature_test.go
@@ -0,0 +1,47 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package git
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestParseSignatureFromCommitLine(t *testing.T) {
+ tests := []struct {
+ line string
+ want *Signature
+ }{
+ {
+ line: "a b 12345 +0100",
+ want: &Signature{
+ Name: "a b",
+ Email: "c@d.com",
+ When: time.Unix(12345, 0).In(time.FixedZone("", 3600)),
+ },
+ },
+ {
+ line: "bad line",
+ want: &Signature{Name: "bad line"},
+ },
+ {
+ line: "bad < line",
+ want: &Signature{Name: "bad < line"},
+ },
+ {
+ line: "bad > line",
+ want: &Signature{Name: "bad > line"},
+ },
+ {
+ line: "bad-line ",
+ want: &Signature{Name: "bad-line "},
+ },
+ }
+ for _, test := range tests {
+ got := parseSignatureFromCommitLine(test.line)
+ assert.EqualValues(t, test.want, got)
+ }
+}
diff --git a/modules/git/tag.go b/modules/git/tag.go
index 01a8d6f6a5..94e5cd7c63 100644
--- a/modules/git/tag.go
+++ b/modules/git/tag.go
@@ -7,6 +7,8 @@ import (
"bytes"
"sort"
"strings"
+
+ "code.gitea.io/gitea/modules/util"
)
const (
@@ -59,11 +61,7 @@ l:
// A commit can have one or more parents
tag.Type = string(line[spacepos+1:])
case "tagger":
- sig, err := newSignatureFromCommitline(line[spacepos+1:])
- if err != nil {
- return nil, err
- }
- tag.Tagger = sig
+ tag.Tagger = parseSignatureFromCommitLine(util.UnsafeBytesToString(line[spacepos+1:]))
}
nextline += eol + 1
case eol == 0:
diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go
index 89d3aebbc0..28d02c7e81 100644
--- a/modules/git/tree_nogogit.go
+++ b/modules/git/tree_nogogit.go
@@ -7,7 +7,6 @@ package git
import (
"io"
- "math"
"strings"
)
@@ -63,19 +62,8 @@ func (t *Tree) ListEntries() (Entries, error) {
}
// Not a tree just use ls-tree instead
- for sz > math.MaxInt32 {
- discarded, err := rd.Discard(math.MaxInt32)
- sz -= int64(discarded)
- if err != nil {
- return nil, err
- }
- }
- for sz > 0 {
- discarded, err := rd.Discard(int(sz))
- sz -= int64(discarded)
- if err != nil {
- return nil, err
- }
+ if err := DiscardFull(rd, sz+1); err != nil {
+ return nil, err
}
}
diff --git a/modules/git/tree_test.go b/modules/git/tree_test.go
new file mode 100644
index 0000000000..6d2b5c84d5
--- /dev/null
+++ b/modules/git/tree_test.go
@@ -0,0 +1,27 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package git
+
+import (
+ "path/filepath"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSubTree_Issue29101(t *testing.T) {
+ repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
+ assert.NoError(t, err)
+ defer repo.Close()
+
+ commit, err := repo.GetCommit("ce064814f4a0d337b333e646ece456cd39fab612")
+ assert.NoError(t, err)
+
+ // old code could produce a different error if called multiple times
+ for i := 0; i < 10; i++ {
+ _, err = commit.SubTree("file1.txt")
+ assert.Error(t, err)
+ assert.True(t, IsErrNotExist(err))
+ }
+}
diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go
index 2fadbfeb06..0f70f13485 100644
--- a/modules/indexer/code/elasticsearch/elasticsearch.go
+++ b/modules/indexer/code/elasticsearch/elasticsearch.go
@@ -180,11 +180,17 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
}
if len(reqs) > 0 {
- _, err := b.inner.Client.Bulk().
- Index(b.inner.VersionedIndexName()).
- Add(reqs...).
- Do(ctx)
- return err
+ esBatchSize := 50
+
+ for i := 0; i < len(reqs); i += esBatchSize {
+ _, err := b.inner.Client.Bulk().
+ Index(b.inner.VersionedIndexName()).
+ Add(reqs[i:min(i+esBatchSize, len(reqs))]...).
+ Do(ctx)
+ if err != nil {
+ return err
+ }
+ }
}
return nil
}
diff --git a/modules/indexer/internal/bleve/indexer.go b/modules/indexer/internal/bleve/indexer.go
index ce06b5afcb..01e53ca636 100644
--- a/modules/indexer/internal/bleve/indexer.go
+++ b/modules/indexer/internal/bleve/indexer.go
@@ -92,7 +92,7 @@ func (i *Indexer) Ping(_ context.Context) error {
}
func (i *Indexer) Close() {
- if i == nil {
+ if i == nil || i.Indexer == nil {
return
}
diff --git a/modules/indexer/internal/meilisearch/indexer.go b/modules/indexer/internal/meilisearch/indexer.go
index b037249d43..f4004849c1 100644
--- a/modules/indexer/internal/meilisearch/indexer.go
+++ b/modules/indexer/internal/meilisearch/indexer.go
@@ -87,8 +87,5 @@ func (i *Indexer) Close() {
if i == nil {
return
}
- if i.Client == nil {
- return
- }
i.Client = nil
}
diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go
index da4fc9b878..3b96686d98 100644
--- a/modules/indexer/issues/indexer_test.go
+++ b/modules/indexer/issues/indexer_test.go
@@ -218,7 +218,7 @@ func searchIssueIsPull(t *testing.T) {
SearchOptions{
IsPull: util.OptionalBoolTrue,
},
- []int64{12, 11, 20, 19, 9, 8, 3, 2},
+ []int64{22, 21, 12, 11, 20, 19, 9, 8, 3, 2},
},
}
for _, test := range tests {
@@ -239,7 +239,7 @@ func searchIssueIsClosed(t *testing.T) {
SearchOptions{
IsClosed: util.OptionalBoolFalse,
},
- []int64{17, 16, 15, 14, 13, 12, 11, 20, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1},
+ []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1},
},
{
SearchOptions{
@@ -305,7 +305,7 @@ func searchIssueByLabelID(t *testing.T) {
SearchOptions{
ExcludedLabelIDs: []int64{1},
},
- []int64{17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3},
+ []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3},
},
}
for _, test := range tests {
@@ -329,7 +329,7 @@ func searchIssueByTime(t *testing.T) {
SearchOptions{
UpdatedAfterUnix: int64Pointer(0),
},
- []int64{17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
+ []int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
},
}
for _, test := range tests {
@@ -350,7 +350,7 @@ func searchIssueWithOrder(t *testing.T) {
SearchOptions{
SortBy: internal.SortByCreatedAsc,
},
- []int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 5, 6, 20, 11, 12, 13, 14, 15, 16, 17},
+ []int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 5, 6, 20, 11, 12, 13, 14, 15, 16, 17, 21, 22},
},
}
for _, test := range tests {
@@ -410,8 +410,8 @@ func searchIssueWithPaginator(t *testing.T) {
PageSize: 5,
},
},
- []int64{17, 16, 15, 14, 13},
- 20,
+ []int64{22, 21, 17, 16, 15},
+ 22,
},
}
for _, test := range tests {
diff --git a/modules/lfs/content_store.go b/modules/lfs/content_store.go
index daf8c6cfdd..0d9c0c98ac 100644
--- a/modules/lfs/content_store.go
+++ b/modules/lfs/content_store.go
@@ -4,6 +4,7 @@
package lfs
import (
+ "crypto/sha256"
"encoding/hex"
"errors"
"hash"
@@ -12,8 +13,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
-
- "github.com/minio/sha256-simd"
)
var (
diff --git a/modules/lfs/pointer.go b/modules/lfs/pointer.go
index 3e5bb8f91d..ebde20f826 100644
--- a/modules/lfs/pointer.go
+++ b/modules/lfs/pointer.go
@@ -4,6 +4,7 @@
package lfs
import (
+ "crypto/sha256"
"encoding/hex"
"errors"
"fmt"
@@ -12,8 +13,6 @@ import (
"regexp"
"strconv"
"strings"
-
- "github.com/minio/sha256-simd"
)
const (
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 33dc1e9086..56e1a1c54e 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -53,38 +53,38 @@ var (
// shortLinkPattern matches short but difficult to parse [[name|link|arg=test]] syntax
shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
- // anySHA1Pattern splits url containing SHA into parts
+ // anyHashPattern splits url containing SHA into parts
anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
- validLinksPattern = regexp.MustCompile(`^[a-z][\w-]+://`)
+ // fullURLPattern matches full URL like "mailto:...", "https://..." and "ssh+git://..."
+ fullURLPattern = regexp.MustCompile(`^[a-z][-+\w]+:`)
- // While this email regex is definitely not perfect and I'm sure you can come up
- // with edge cases, it is still accepted by the CommonMark specification, as
- // well as the HTML5 spec:
+ // emailRegex is definitely not perfect with edge cases,
+ // it is still accepted by the CommonMark specification, as well as the HTML5 spec:
// http://spec.commonmark.org/0.28/#email-address
// https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type%3Demail)
emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))")
- // blackfriday extensions create IDs like fn:user-content-footnote
+ // blackfridayExtRegex is for blackfriday extensions create IDs like fn:user-content-footnote
blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`)
- // EmojiShortCodeRegex find emoji by alias like :smile:
- EmojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
+ // emojiShortCodeRegex find emoji by alias like :smile:
+ emojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
)
// CSS class for action keywords (e.g. "closes: #1")
const keywordClass = "issue-keyword"
-// IsLink reports whether link fits valid format.
-func IsLink(link []byte) bool {
- return validLinksPattern.Match(link)
+// IsFullURLBytes reports whether link fits valid format.
+func IsFullURLBytes(link []byte) bool {
+ return fullURLPattern.Match(link)
}
-func IsLinkStr(link string) bool {
- return validLinksPattern.MatchString(link)
+func IsFullURLString(link string) bool {
+ return fullURLPattern.MatchString(link)
}
// regexp for full links to issues/pulls
@@ -399,7 +399,7 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) {
if attr.Key != "src" {
continue
}
- if len(attr.Val) > 0 && !IsLinkStr(attr.Val) && !strings.HasPrefix(attr.Val, "data:image/") {
+ if len(attr.Val) > 0 && !IsFullURLString(attr.Val) && !strings.HasPrefix(attr.Val, "data:image/") {
attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsWiki), attr.Val)
}
attr.Val = camoHandleLink(attr.Val)
@@ -650,7 +650,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
if equalPos := strings.IndexByte(v, '='); equalPos == -1 {
// There is no equal in this argument; this is a mandatory arg
if props["name"] == "" {
- if IsLinkStr(v) {
+ if IsFullURLString(v) {
// If we clearly see it is a link, we save it so
// But first we need to ensure, that if both mandatory args provided
@@ -725,7 +725,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
DataAtom: atom.A,
}
childNode.Parent = linkNode
- absoluteLink := IsLinkStr(link)
+ absoluteLink := IsFullURLString(link)
if !absoluteLink {
if image {
link = strings.ReplaceAll(link, " ", "+")
@@ -804,7 +804,7 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
// indicate that in the text by appending (comment)
if m[4] != -1 && m[5] != -1 {
if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok {
- text += " " + locale.Tr("repo.from_comment")
+ text += " " + locale.TrString("repo.from_comment")
} else {
text += " (comment)"
}
@@ -1059,7 +1059,7 @@ func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
start := 0
next := node.NextSibling
for node != nil && node != next && start < len(node.Data) {
- m := EmojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
+ m := emojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
if m == nil {
return
}
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 89ecfc036b..cb29431d4b 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -204,6 +204,15 @@ func TestRender_links(t *testing.T) {
test(
"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download",
`magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download
`)
+ test(
+ `[link](https://example.com)`,
+ `link
`)
+ test(
+ `[link](mailto:test@example.com)`,
+ `link
`)
+ test(
+ `[link](javascript:xss)`,
+ `link
`)
// Test that should *not* be turned into URL
test(
@@ -673,3 +682,9 @@ func TestIssue18471(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "783b039...da951ce
", res.String())
}
+
+func TestIsFullURL(t *testing.T) {
+ assert.True(t, markup.IsFullURLString("https://example.com"))
+ assert.True(t, markup.IsFullURLString("mailto:test@example.com"))
+ assert.False(t, markup.IsFullURLString("/foo:bar"))
+}
diff --git a/modules/markup/markdown/ast.go b/modules/markup/markdown/ast.go
index 3e6e291ab2..77ce5cb359 100644
--- a/modules/markup/markdown/ast.go
+++ b/modules/markup/markdown/ast.go
@@ -182,12 +182,7 @@ func IsColorPreview(node ast.Node) bool {
return ok
}
-const (
- AttentionNote string = "Note"
- AttentionWarning string = "Warning"
-)
-
-// Attention is an inline for a color preview
+// Attention is an inline for an attention
type Attention struct {
ast.BaseInline
AttentionType string
diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 178e3d2fdd..c4b23e66fc 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -26,8 +26,6 @@ import (
"github.com/yuin/goldmark/util"
)
-var byteMailto = []byte("mailto:")
-
// ASTTransformer is a default transformer of the goldmark tree.
type ASTTransformer struct{}
@@ -53,7 +51,6 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
}
}
- attentionMarkedBlockquotes := make(container.Set[*ast.Blockquote])
_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
@@ -85,7 +82,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
// 2. If they're not wrapped with a link they need a link wrapper
// Check if the destination is a real link
- if len(v.Destination) > 0 && !markup.IsLink(v.Destination) {
+ if len(v.Destination) > 0 && !markup.IsFullURLBytes(v.Destination) {
v.Destination = []byte(giteautil.URLJoin(
ctx.Links.ResolveMediaLink(ctx.IsWiki),
strings.TrimLeft(string(v.Destination), "/"),
@@ -131,23 +128,17 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
case *ast.Link:
// Links need their href to munged to be a real value
link := v.Destination
- if len(link) > 0 && !markup.IsLink(link) &&
- link[0] != '#' && !bytes.HasPrefix(link, byteMailto) {
- // special case: this is not a link, a hash link or a mailto:, so it's a
- // relative URL
-
- var base string
+ isAnchorFragment := len(link) > 0 && link[0] == '#'
+ if !isAnchorFragment && !markup.IsFullURLBytes(link) {
+ base := ctx.Links.Base
if ctx.IsWiki {
base = ctx.Links.WikiLink()
} else if ctx.Links.HasBranchInfo() {
base = ctx.Links.SrcLink()
- } else {
- base = ctx.Links.Base
}
-
link = []byte(giteautil.URLJoin(base, string(link)))
}
- if len(link) > 0 && link[0] == '#' {
+ if isAnchorFragment {
link = []byte("#user-content-" + string(link)[1:])
}
v.Destination = link
@@ -197,18 +188,55 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
if css.ColorHandler(strings.ToLower(string(colorContent))) {
v.AppendChild(v, NewColorPreview(colorContent))
}
- case *ast.Emphasis:
- // check if inside blockquote for attention, expected hierarchy is
- // Emphasis < Paragraph < Blockquote
- blockquote, isInBlockquote := n.Parent().Parent().(*ast.Blockquote)
- if isInBlockquote && !attentionMarkedBlockquotes.Contains(blockquote) {
- fullText := string(n.Text(reader.Source()))
- if fullText == AttentionNote || fullText == AttentionWarning {
- v.SetAttributeString("class", []byte("attention-"+strings.ToLower(fullText)))
- v.Parent().InsertBefore(v.Parent(), v, NewAttention(fullText))
- attentionMarkedBlockquotes.Add(blockquote)
- }
+ case *ast.Blockquote:
+ // We only want attention blockquotes when the AST looks like:
+ // Text: "["
+ // Text: "!TYPE"
+ // Text(SoftLineBreak): "]"
+
+ // grab these nodes and make sure we adhere to the attention blockquote structure
+ firstParagraph := v.FirstChild()
+ if firstParagraph.ChildCount() < 3 {
+ return ast.WalkContinue, nil
}
+ firstTextNode, ok := firstParagraph.FirstChild().(*ast.Text)
+ if !ok || string(firstTextNode.Segment.Value(reader.Source())) != "[" {
+ return ast.WalkContinue, nil
+ }
+ secondTextNode, ok := firstTextNode.NextSibling().(*ast.Text)
+ if !ok || !attentionTypeRE.MatchString(string(secondTextNode.Segment.Value(reader.Source()))) {
+ return ast.WalkContinue, nil
+ }
+ thirdTextNode, ok := secondTextNode.NextSibling().(*ast.Text)
+ if !ok || string(thirdTextNode.Segment.Value(reader.Source())) != "]" {
+ return ast.WalkContinue, nil
+ }
+
+ // grab attention type from markdown source
+ attentionType := strings.ToLower(strings.TrimPrefix(string(secondTextNode.Segment.Value(reader.Source())), "!"))
+
+ // color the blockquote
+ v.SetAttributeString("class", []byte("gt-py-3 attention attention-"+attentionType))
+
+ // create an emphasis to make it bold
+ emphasis := ast.NewEmphasis(2)
+ emphasis.SetAttributeString("class", []byte("attention-"+attentionType))
+ firstParagraph.InsertBefore(firstParagraph, firstTextNode, emphasis)
+
+ // capitalize first letter
+ attentionText := ast.NewString([]byte(strings.ToUpper(string(attentionType[0])) + attentionType[1:]))
+
+ // replace the ![TYPE] with icon+Type
+ emphasis.AppendChild(emphasis, attentionText)
+ for i := 0; i < 2; i++ {
+ lineBreak := ast.NewText()
+ lineBreak.SetSoftLineBreak(true)
+ firstParagraph.InsertAfter(firstParagraph, emphasis, lineBreak)
+ }
+ firstParagraph.InsertBefore(firstParagraph, emphasis, NewAttention(attentionType))
+ firstParagraph.RemoveChild(firstParagraph, firstTextNode)
+ firstParagraph.RemoveChild(firstParagraph, secondTextNode)
+ firstParagraph.RemoveChild(firstParagraph, thirdTextNode)
}
return ast.WalkContinue, nil
})
@@ -339,17 +367,23 @@ func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Nod
// renderAttention renders a quote marked with i.e. "> **Note**" or "> **Warning**" with a corresponding svg
func (r *HTMLRenderer) renderAttention(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if entering {
- _, _ = w.WriteString(``)
var octiconType string
switch n.AttentionType {
- case AttentionNote:
+ case "note":
octiconType = "info"
- case AttentionWarning:
+ case "tip":
+ octiconType = "light-bulb"
+ case "important":
+ octiconType = "report"
+ case "warning":
octiconType = "alert"
+ case "caution":
+ octiconType = "stop"
}
_, _ = w.WriteString(string(svg.RenderHTML("octicon-" + octiconType)))
} else {
@@ -417,7 +451,10 @@ func (r *HTMLRenderer) renderSummary(w util.BufWriter, source []byte, node ast.N
return ast.WalkContinue, nil
}
-var validNameRE = regexp.MustCompile("^[a-z ]+$")
+var (
+ validNameRE = regexp.MustCompile("^[a-z ]+$")
+ attentionTypeRE = regexp.MustCompile("^!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)$")
+)
func (r *HTMLRenderer) renderIcon(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
diff --git a/modules/markup/markdown/toc.go b/modules/markup/markdown/toc.go
index 9602040931..38f744a25f 100644
--- a/modules/markup/markdown/toc.go
+++ b/modules/markup/markdown/toc.go
@@ -21,7 +21,7 @@ func createTOCNode(toc []markup.Header, lang string, detailsAttrs map[string]str
details.SetAttributeString(k, []byte(v))
}
- summary.AppendChild(summary, ast.NewString([]byte(translation.NewLocale(lang).Tr("toc"))))
+ summary.AppendChild(summary, ast.NewString([]byte(translation.NewLocale(lang).TrString("toc"))))
details.AppendChild(details, summary)
ul := ast.NewList('-')
details.AppendChild(details, ul)
diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go
index abc641fbe2..7f253ae5f1 100644
--- a/modules/markup/orgmode/orgmode.go
+++ b/modules/markup/orgmode/orgmode.go
@@ -133,18 +133,17 @@ type Writer struct {
Ctx *markup.RenderContext
}
-const mailto = "mailto:"
-
-func (r *Writer) resolveLink(l org.RegularLink) string {
- link := html.EscapeString(l.URL)
- if l.Protocol == "file" {
- link = link[len("file:"):]
- }
- if len(link) > 0 && !markup.IsLinkStr(link) &&
- link[0] != '#' && !strings.HasPrefix(link, mailto) {
+func (r *Writer) resolveLink(kind, link string) string {
+ link = strings.TrimPrefix(link, "file:")
+ if !strings.HasPrefix(link, "#") && // not a URL fragment
+ !markup.IsFullURLString(link) {
+ if kind == "regular" {
+ // orgmode reports the link kind as "regular" for "[[ImageLink.svg][The Image Desc]]"
+ // so we need to try to guess the link kind again here
+ kind = org.RegularLink{URL: link}.Kind()
+ }
base := r.Ctx.Links.Base
- switch l.Kind() {
- case "image", "video":
+ if kind == "image" || kind == "video" {
base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsWiki)
}
link = util.URLJoin(base, link)
@@ -154,29 +153,29 @@ func (r *Writer) resolveLink(l org.RegularLink) string {
// WriteRegularLink renders images, links or videos
func (r *Writer) WriteRegularLink(l org.RegularLink) {
- link := r.resolveLink(l)
+ link := r.resolveLink(l.Kind(), l.URL)
// Inspired by https://github.com/niklasfasching/go-org/blob/6eb20dbda93cb88c3503f7508dc78cbbc639378f/org/html_writer.go#L406-L427
switch l.Kind() {
case "image":
if l.Description == nil {
- fmt.Fprintf(r, ` `, link, link)
+ _, _ = fmt.Fprintf(r, ` `, link, link)
} else {
- imageSrc := r.resolveLink(l.Description[0].(org.RegularLink))
- fmt.Fprintf(r, ` `, link, imageSrc, imageSrc)
+ imageSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
+ _, _ = fmt.Fprintf(r, ` `, link, imageSrc, imageSrc)
}
case "video":
if l.Description == nil {
- fmt.Fprintf(r, `%s `, link, link)
+ _, _ = fmt.Fprintf(r, `%s `, link, link)
} else {
- videoSrc := r.resolveLink(l.Description[0].(org.RegularLink))
- fmt.Fprintf(r, `%s `, link, videoSrc, videoSrc)
+ videoSrc := r.resolveLink(l.Kind(), org.String(l.Description...))
+ _, _ = fmt.Fprintf(r, `%s `, link, videoSrc, videoSrc)
}
default:
description := link
if l.Description != nil {
description = r.WriteNodesAsString(l.Description...)
}
- fmt.Fprintf(r, `%s `, link, description)
+ _, _ = fmt.Fprintf(r, `%s `, link, description)
}
}
diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go
index abf5ca8fcf..95f53c9cc9 100644
--- a/modules/markup/orgmode/orgmode_test.go
+++ b/modules/markup/orgmode/orgmode_test.go
@@ -10,26 +10,21 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
)
-const (
- AppURL = "http://localhost:3000/"
- Repo = "gogits/gogs"
- AppSubURL = AppURL + Repo + "/"
-)
+const AppURL = "http://localhost:3000/"
func TestRender_StandardLinks(t *testing.T) {
setting.AppURL = AppURL
- setting.AppSubURL = AppSubURL
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
Links: markup.Links{
- Base: setting.AppSubURL,
+ Base: "/relative-path",
+ BranchPath: "branch/main",
},
}, input)
assert.NoError(t, err)
@@ -38,32 +33,30 @@ func TestRender_StandardLinks(t *testing.T) {
test("[[https://google.com/]]",
`https://google.com/
`)
-
- lnk := util.URLJoin(AppSubURL, "WikiPage")
- test("[[WikiPage][WikiPage]]",
- `WikiPage
`)
+ test("[[WikiPage][The WikiPage Desc]]",
+ `The WikiPage Desc
`)
+ test("[[ImageLink.svg][The Image Desc]]",
+ `The Image Desc
`)
}
func TestRender_Media(t *testing.T) {
setting.AppURL = AppURL
- setting.AppSubURL = AppSubURL
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
Links: markup.Links{
- Base: setting.AppSubURL,
+ Base: "./relative-path",
},
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
- url := "../../.images/src/02/train.jpg"
- result := util.URLJoin(AppSubURL, url)
-
- test("[[file:"+url+"]]",
- `
`)
+ test("[[file:../../.images/src/02/train.jpg]]",
+ `
`)
+ test("[[file:train.jpg]]",
+ `
`)
// With description.
test("[[https://example.com][https://example.com/example.svg]]",
@@ -80,11 +73,20 @@ func TestRender_Media(t *testing.T) {
`
`)
test("[[https://example.com/example.mp4]]",
`https://example.com/example.mp4
`)
+
+ // test [[LINK][DESCRIPTION]] syntax with "file:" prefix
+ test(`[[https://example.com/][file:https://example.com/foo%20bar.svg]]`,
+ `
`)
+ test(`[[file:https://example.com/foo%20bar.svg][Goto Image]]`,
+ `Goto Image
`)
+ test(`[[file:https://example.com/link][https://example.com/image.jpg]]`,
+ `
`)
+ test(`[[file:https://example.com/link][file:https://example.com/image.jpg]]`,
+ `
`)
}
func TestRender_Source(t *testing.T) {
setting.AppURL = AppURL
- setting.AppSubURL = AppSubURL
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go
index 992e85b989..ffc33c3b8e 100644
--- a/modules/markup/sanitizer.go
+++ b/modules/markup/sanitizer.go
@@ -64,9 +64,10 @@ func createDefaultPolicy() *bluemonday.Policy {
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^color-preview$`)).OnElements("span")
// For attention
+ policy.AllowAttrs("class").Matching(regexp.MustCompile(`^gt-py-3 attention attention-\w+$`)).OnElements("blockquote")
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-\w+$`)).OnElements("strong")
- policy.AllowAttrs("class").Matching(regexp.MustCompile(`^attention-icon attention-\w+$`)).OnElements("span", "strong")
- policy.AllowAttrs("class").Matching(regexp.MustCompile(`^svg octicon-\w+$`)).OnElements("svg")
+ policy.AllowAttrs("class").Matching(regexp.MustCompile(`^gt-mr-2 gt-vm attention-\w+$`)).OnElements("span", "strong")
+ policy.AllowAttrs("class").Matching(regexp.MustCompile(`^svg octicon-(\w|-)+$`)).OnElements("svg")
policy.AllowAttrs("viewBox", "width", "height", "aria-hidden").OnElements("svg")
policy.AllowAttrs("fill-rule", "d").OnElements("path")
diff --git a/modules/migration/messenger.go b/modules/migration/messenger.go
index 924aac9769..6f9cad3f10 100644
--- a/modules/migration/messenger.go
+++ b/modules/migration/messenger.go
@@ -3,7 +3,7 @@
package migration
-// Messenger is a formatting function similar to i18n.Tr
+// Messenger is a formatting function similar to i18n.TrString
type Messenger func(key string, args ...any)
// NilMessenger represents an empty formatting function
diff --git a/modules/optional/option_test.go b/modules/optional/option_test.go
index 7ec345b6ba..410fd73577 100644
--- a/modules/optional/option_test.go
+++ b/modules/optional/option_test.go
@@ -1,48 +1,49 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
-package optional
+package optional_test
import (
"testing"
- "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/optional"
"github.com/stretchr/testify/assert"
)
func TestOption(t *testing.T) {
- var uninitialized Option[int]
+ var uninitialized optional.Option[int]
assert.False(t, uninitialized.Has())
assert.Equal(t, int(0), uninitialized.Value())
assert.Equal(t, int(1), uninitialized.ValueOrDefault(1))
- none := None[int]()
+ none := optional.None[int]()
assert.False(t, none.Has())
assert.Equal(t, int(0), none.Value())
assert.Equal(t, int(1), none.ValueOrDefault(1))
- some := Some[int](1)
+ some := optional.Some[int](1)
assert.True(t, some.Has())
assert.Equal(t, int(1), some.Value())
assert.Equal(t, int(1), some.ValueOrDefault(2))
var ptr *int
- assert.False(t, FromPtr(ptr).Has())
+ assert.False(t, optional.FromPtr(ptr).Has())
- opt1 := FromPtr(util.ToPointer(1))
+ int1 := 1
+ opt1 := optional.FromPtr(&int1)
assert.True(t, opt1.Has())
assert.Equal(t, int(1), opt1.Value())
- assert.False(t, FromNonDefault("").Has())
+ assert.False(t, optional.FromNonDefault("").Has())
- opt2 := FromNonDefault("test")
+ opt2 := optional.FromNonDefault("test")
assert.True(t, opt2.Has())
assert.Equal(t, "test", opt2.Value())
- assert.False(t, FromNonDefault(0).Has())
+ assert.False(t, optional.FromNonDefault(0).Has())
- opt3 := FromNonDefault(1)
+ opt3 := optional.FromNonDefault(1)
assert.True(t, opt3.Has())
assert.Equal(t, int(1), opt3.Value())
}
diff --git a/modules/optional/serialization.go b/modules/optional/serialization.go
new file mode 100644
index 0000000000..6688e78cd1
--- /dev/null
+++ b/modules/optional/serialization.go
@@ -0,0 +1,46 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package optional
+
+import (
+ "code.gitea.io/gitea/modules/json"
+
+ "gopkg.in/yaml.v3"
+)
+
+func (o *Option[T]) UnmarshalJSON(data []byte) error {
+ var v *T
+ if err := json.Unmarshal(data, &v); err != nil {
+ return err
+ }
+ *o = FromPtr(v)
+ return nil
+}
+
+func (o Option[T]) MarshalJSON() ([]byte, error) {
+ if !o.Has() {
+ return []byte("null"), nil
+ }
+
+ return json.Marshal(o.Value())
+}
+
+func (o *Option[T]) UnmarshalYAML(value *yaml.Node) error {
+ var v *T
+ if err := value.Decode(&v); err != nil {
+ return err
+ }
+ *o = FromPtr(v)
+ return nil
+}
+
+func (o Option[T]) MarshalYAML() (interface{}, error) {
+ if !o.Has() {
+ return nil, nil
+ }
+
+ value := new(yaml.Node)
+ err := value.Encode(o.Value())
+ return value, err
+}
diff --git a/modules/optional/serialization_test.go b/modules/optional/serialization_test.go
new file mode 100644
index 0000000000..09a4bddea0
--- /dev/null
+++ b/modules/optional/serialization_test.go
@@ -0,0 +1,190 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package optional_test
+
+import (
+ std_json "encoding/json" //nolint:depguard
+ "testing"
+
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/optional"
+
+ "github.com/stretchr/testify/assert"
+ "gopkg.in/yaml.v3"
+)
+
+type testSerializationStruct struct {
+ NormalString string `json:"normal_string" yaml:"normal_string"`
+ NormalBool bool `json:"normal_bool" yaml:"normal_bool"`
+ OptBool optional.Option[bool] `json:"optional_bool,omitempty" yaml:"optional_bool,omitempty"`
+ OptString optional.Option[string] `json:"optional_string,omitempty" yaml:"optional_string,omitempty"`
+ OptTwoBool optional.Option[bool] `json:"optional_two_bool" yaml:"optional_two_bool"`
+ OptTwoString optional.Option[string] `json:"optional_twostring" yaml:"optional_two_string"`
+}
+
+func TestOptionalToJson(t *testing.T) {
+ tests := []struct {
+ name string
+ obj *testSerializationStruct
+ want string
+ }{
+ {
+ name: "empty",
+ obj: new(testSerializationStruct),
+ want: `{"normal_string":"","normal_bool":false,"optional_two_bool":null,"optional_twostring":null}`,
+ },
+ {
+ name: "some",
+ obj: &testSerializationStruct{
+ NormalString: "a string",
+ NormalBool: true,
+ OptBool: optional.Some(false),
+ OptString: optional.Some(""),
+ OptTwoBool: optional.None[bool](),
+ OptTwoString: optional.None[string](),
+ },
+ want: `{"normal_string":"a string","normal_bool":true,"optional_bool":false,"optional_string":"","optional_two_bool":null,"optional_twostring":null}`,
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ b, err := json.Marshal(tc.obj)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, string(b), "gitea json module returned unexpected")
+
+ b, err = std_json.Marshal(tc.obj)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, string(b), "std json module returned unexpected")
+ })
+ }
+}
+
+func TestOptionalFromJson(t *testing.T) {
+ tests := []struct {
+ name string
+ data string
+ want testSerializationStruct
+ }{
+ {
+ name: "empty",
+ data: `{}`,
+ want: testSerializationStruct{
+ NormalString: "",
+ },
+ },
+ {
+ name: "some",
+ data: `{"normal_string":"a string","normal_bool":true,"optional_bool":false,"optional_string":"","optional_two_bool":null,"optional_twostring":null}`,
+ want: testSerializationStruct{
+ NormalString: "a string",
+ NormalBool: true,
+ OptBool: optional.Some(false),
+ OptString: optional.Some(""),
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ var obj1 testSerializationStruct
+ err := json.Unmarshal([]byte(tc.data), &obj1)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, obj1, "gitea json module returned unexpected")
+
+ var obj2 testSerializationStruct
+ err = std_json.Unmarshal([]byte(tc.data), &obj2)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, obj2, "std json module returned unexpected")
+ })
+ }
+}
+
+func TestOptionalToYaml(t *testing.T) {
+ tests := []struct {
+ name string
+ obj *testSerializationStruct
+ want string
+ }{
+ {
+ name: "empty",
+ obj: new(testSerializationStruct),
+ want: `normal_string: ""
+normal_bool: false
+optional_two_bool: null
+optional_two_string: null
+`,
+ },
+ {
+ name: "some",
+ obj: &testSerializationStruct{
+ NormalString: "a string",
+ NormalBool: true,
+ OptBool: optional.Some(false),
+ OptString: optional.Some(""),
+ },
+ want: `normal_string: a string
+normal_bool: true
+optional_bool: false
+optional_string: ""
+optional_two_bool: null
+optional_two_string: null
+`,
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ b, err := yaml.Marshal(tc.obj)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, string(b), "yaml module returned unexpected")
+ })
+ }
+}
+
+func TestOptionalFromYaml(t *testing.T) {
+ tests := []struct {
+ name string
+ data string
+ want testSerializationStruct
+ }{
+ {
+ name: "empty",
+ data: ``,
+ want: testSerializationStruct{},
+ },
+ {
+ name: "empty but init",
+ data: `normal_string: ""
+normal_bool: false
+optional_bool:
+optional_two_bool:
+optional_two_string:
+`,
+ want: testSerializationStruct{},
+ },
+ {
+ name: "some",
+ data: `
+normal_string: a string
+normal_bool: true
+optional_bool: false
+optional_string: ""
+optional_two_bool: null
+optional_twostring: null
+`,
+ want: testSerializationStruct{
+ NormalString: "a string",
+ NormalBool: true,
+ OptBool: optional.Some(false),
+ OptString: optional.Some(""),
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ var obj testSerializationStruct
+ err := yaml.Unmarshal([]byte(tc.data), &obj)
+ assert.NoError(t, err)
+ assert.EqualValues(t, tc.want, obj, "yaml module returned unexpected")
+ })
+ }
+}
diff --git a/modules/packages/alpine/metadata.go b/modules/packages/alpine/metadata.go
index 582c42610d..c492811744 100644
--- a/modules/packages/alpine/metadata.go
+++ b/modules/packages/alpine/metadata.go
@@ -34,6 +34,8 @@ const (
RepositoryPackage = "_alpine"
RepositoryVersion = "_repository"
+
+ NoArch = "noarch"
)
// https://wiki.alpinelinux.org/wiki/Apk_spec
diff --git a/modules/repository/create.go b/modules/repository/create.go
index 7c954a1412..ca2150b972 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -87,7 +87,11 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
units = append(units, repo_model.RepoUnit{
RepoID: repo.ID,
Type: tp,
- Config: &repo_model.PullRequestsConfig{AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle), AllowRebaseUpdate: true},
+ Config: &repo_model.PullRequestsConfig{
+ AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, AllowFastForwardOnly: true,
+ DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle),
+ AllowRebaseUpdate: true,
+ },
})
} else {
units = append(units, repo_model.RepoUnit{
diff --git a/modules/repository/generate.go b/modules/repository/generate.go
index 013dd8f76f..f622383bb5 100644
--- a/modules/repository/generate.go
+++ b/modules/repository/generate.go
@@ -94,7 +94,7 @@ type GiteaTemplate struct {
}
// Globs parses the .gitea/template globs or returns them if they were already parsed
-func (gt GiteaTemplate) Globs() []glob.Glob {
+func (gt *GiteaTemplate) Globs() []glob.Glob {
if gt.globs != nil {
return gt.globs
}
diff --git a/modules/repository/hooks.go b/modules/repository/hooks.go
index daab7c3091..95849789ab 100644
--- a/modules/repository/hooks.go
+++ b/modules/repository/hooks.go
@@ -9,7 +9,6 @@ import (
"path/filepath"
"runtime"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
@@ -94,15 +93,14 @@ done
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
}
- if git.SupportProcReceive {
- hookNames = append(hookNames, "proc-receive")
- hookTpls = append(hookTpls,
- fmt.Sprintf(`#!/usr/bin/env %s
+ // although only new git (>=2.29) supports proc-receive, it's still good to create its hook, in case the user upgrades git
+ hookNames = append(hookNames, "proc-receive")
+ hookTpls = append(hookTpls,
+ fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
%s hook --config=%s proc-receive
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)))
- giteaHookTpls = append(giteaHookTpls, "")
- }
+ giteaHookTpls = append(giteaHookTpls, "")
return hookNames, hookTpls, giteaHookTpls
}
diff --git a/modules/repository/repo.go b/modules/repository/repo.go
index db3bdda0db..858d829717 100644
--- a/modules/repository/repo.go
+++ b/modules/repository/repo.go
@@ -361,7 +361,9 @@ func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitR
}
if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil {
- return fmt.Errorf("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %w", tagName, repo.ID, repo.OwnerName, repo.Name, err)
+ // sometimes, some tags will be sync failed. i.e. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tag/?h=v2.6.11
+ // this is a tree object, not a tag object which created before git
+ log.Error("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %v", tagName, repo.ID, repo.OwnerName, repo.Name, err)
}
return nil
diff --git a/modules/secret/secret.go b/modules/secret/secret.go
index 9c2ecd181d..e70ae1839c 100644
--- a/modules/secret/secret.go
+++ b/modules/secret/secret.go
@@ -7,13 +7,12 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
+ "crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io"
-
- "github.com/minio/sha256-simd"
)
// AesEncrypt encrypts text and given key with AES.
diff --git a/modules/setting/admin.go b/modules/setting/admin.go
index 2d2dd26de9..48a2ea9744 100644
--- a/modules/setting/admin.go
+++ b/modules/setting/admin.go
@@ -3,14 +3,22 @@
package setting
+import "code.gitea.io/gitea/modules/container"
+
// Admin settings
var Admin struct {
DisableRegularOrgCreation bool
DefaultEmailNotification string
+ UserDisabledFeatures container.Set[string]
}
func loadAdminFrom(rootCfg ConfigProvider) {
- mustMapSetting(rootCfg, "admin", &Admin)
sec := rootCfg.Section("admin")
+ Admin.DisableRegularOrgCreation = sec.Key("DISABLE_REGULAR_ORG_CREATION").MustBool(false)
Admin.DefaultEmailNotification = sec.Key("DEFAULT_EMAIL_NOTIFICATIONS").MustString("enabled")
+ Admin.UserDisabledFeatures = container.SetOf(sec.Key("USER_DISABLED_FEATURES").Strings(",")...)
}
+
+const (
+ UserFeatureDeletion = "deletion"
+)
diff --git a/modules/setting/config.go b/modules/setting/config.go
index db189f44ac..03558574c2 100644
--- a/modules/setting/config.go
+++ b/modules/setting/config.go
@@ -15,8 +15,45 @@ type PictureStruct struct {
EnableFederatedAvatar *config.Value[bool]
}
+type OpenWithEditorApp struct {
+ DisplayName string
+ OpenURL string
+}
+
+type OpenWithEditorAppsType []OpenWithEditorApp
+
+func (t OpenWithEditorAppsType) ToTextareaString() string {
+ ret := ""
+ for _, app := range t {
+ ret += app.DisplayName + " = " + app.OpenURL + "\n"
+ }
+ return ret
+}
+
+func DefaultOpenWithEditorApps() OpenWithEditorAppsType {
+ return OpenWithEditorAppsType{
+ {
+ DisplayName: "VS Code",
+ OpenURL: "vscode://vscode.git/clone?url={url}",
+ },
+ {
+ DisplayName: "VSCodium",
+ OpenURL: "vscodium://vscode.git/clone?url={url}",
+ },
+ {
+ DisplayName: "Intellij IDEA",
+ OpenURL: "jetbrains://idea/checkout/git?idea.required.plugins.id=Git4Idea&checkout.repo={url}",
+ },
+ }
+}
+
+type RepositoryStruct struct {
+ OpenWithEditorApps *config.Value[OpenWithEditorAppsType]
+}
+
type ConfigStruct struct {
- Picture *PictureStruct
+ Picture *PictureStruct
+ Repository *RepositoryStruct
}
var (
@@ -28,8 +65,11 @@ func initDefaultConfig() {
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
defaultConfig = &ConfigStruct{
Picture: &PictureStruct{
- DisableGravatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}, "picture.disable_gravatar"),
- EnableFederatedAvatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}, "picture.enable_federated_avatar"),
+ DisableGravatar: config.ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
+ EnableFederatedAvatar: config.ValueJSON[bool]("picture.enable_federated_avatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}),
+ },
+ Repository: &RepositoryStruct{
+ OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"),
},
}
}
@@ -42,6 +82,9 @@ func Config() *ConfigStruct {
type cfgSecKeyGetter struct{}
func (c cfgSecKeyGetter) GetValue(sec, key string) (v string, has bool) {
+ if key == "" {
+ return "", false
+ }
cfgSec, err := CfgProvider.GetSection(sec)
if err != nil {
log.Error("Unable to get config section: %q", sec)
diff --git a/modules/setting/config/value.go b/modules/setting/config/value.go
index 817fcdb786..f0ec120544 100644
--- a/modules/setting/config/value.go
+++ b/modules/setting/config/value.go
@@ -5,8 +5,11 @@ package config
import (
"context"
- "strconv"
"sync"
+
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/util"
)
type CfgSecKey struct {
@@ -23,14 +26,14 @@ type Value[T any] struct {
revision int
}
-func (value *Value[T]) parse(s string) (v T) {
- switch any(v).(type) {
- case bool:
- b, _ := strconv.ParseBool(s)
- return any(b).(T)
- default:
- panic("unsupported config type, please complete the code")
+func (value *Value[T]) parse(key, valStr string) (v T) {
+ v = value.def
+ if valStr != "" {
+ if err := json.Unmarshal(util.UnsafeStringToBytes(valStr), &v); err != nil {
+ log.Error("Unable to unmarshal json config for key %q, err: %v", key, err)
+ }
}
+ return v
}
func (value *Value[T]) Value(ctx context.Context) (v T) {
@@ -62,7 +65,7 @@ func (value *Value[T]) Value(ctx context.Context) (v T) {
if valStr == nil {
v = value.def
} else {
- v = value.parse(*valStr)
+ v = value.parse(value.dynKey, *valStr)
}
value.mu.Lock()
@@ -76,6 +79,16 @@ func (value *Value[T]) DynKey() string {
return value.dynKey
}
-func Bool(def bool, cfgSecKey CfgSecKey, dynKey string) *Value[bool] {
- return &Value[bool]{def: def, cfgSecKey: cfgSecKey, dynKey: dynKey}
+func (value *Value[T]) WithDefault(def T) *Value[T] {
+ value.def = def
+ return value
+}
+
+func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
+ value.cfgSecKey = cfgSecKey
+ return value
+}
+
+func ValueJSON[T any](dynKey string) *Value[T] {
+ return &Value[T]{dynKey: dynKey}
}
diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go
index 132f4acea1..3fa3f3b50b 100644
--- a/modules/setting/config_provider.go
+++ b/modules/setting/config_provider.go
@@ -196,7 +196,7 @@ func NewConfigProviderFromData(configContent string) (ConfigProvider, error) {
// NewConfigProviderFromFile load configuration from file.
// NOTE: do not print any log except error.
-func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvider, error) {
+func NewConfigProviderFromFile(file string) (ConfigProvider, error) {
cfg := ini.Empty(configProviderLoadOptions())
loadedFromEmpty := true
@@ -213,12 +213,6 @@ func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvi
}
}
- for _, s := range extraConfigs {
- if err := cfg.Append([]byte(s)); err != nil {
- return nil, fmt.Errorf("unable to append more config: %v", err)
- }
- }
-
cfg.NameMapper = ini.SnackCase
return &iniConfigProvider{
file: file,
diff --git a/modules/setting/database.go b/modules/setting/database.go
index e200b15b2e..1a4bf64805 100644
--- a/modules/setting/database.go
+++ b/modules/setting/database.go
@@ -25,26 +25,27 @@ var (
// Database holds the database settings
Database = struct {
- Type DatabaseType
- Host string
- Name string
- User string
- Passwd string
- Schema string
- SSLMode string
- Path string
- LogSQL bool
- MysqlCharset string
- CharsetCollation string
- Timeout int // seconds
- SQLiteJournalMode string
- DBConnectRetries int
- DBConnectBackoff time.Duration
- MaxIdleConns int
- MaxOpenConns int
- ConnMaxLifetime time.Duration
- IterateBufferSize int
- AutoMigration bool
+ Type DatabaseType
+ Host string
+ Name string
+ User string
+ Passwd string
+ Schema string
+ SSLMode string
+ Path string
+ LogSQL bool
+ MysqlCharset string
+ CharsetCollation string
+ Timeout int // seconds
+ SQLiteJournalMode string
+ DBConnectRetries int
+ DBConnectBackoff time.Duration
+ MaxIdleConns int
+ MaxOpenConns int
+ ConnMaxLifetime time.Duration
+ IterateBufferSize int
+ AutoMigration bool
+ SlowQueryThreshold time.Duration
}{
Timeout: 500,
IterateBufferSize: 50,
@@ -87,6 +88,7 @@ func loadDBSetting(rootCfg ConfigProvider) {
Database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10)
Database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second)
Database.AutoMigration = sec.Key("AUTO_MIGRATION").MustBool(true)
+ Database.SlowQueryThreshold = sec.Key("SLOW_QUERY_THRESHOLD").MustDuration(5 * time.Second)
}
// DBConnStr returns database connection string
diff --git a/modules/setting/indexer.go b/modules/setting/indexer.go
index 16f3d80168..15f6150242 100644
--- a/modules/setting/indexer.go
+++ b/modules/setting/indexer.go
@@ -53,21 +53,24 @@ var Indexer = struct {
func loadIndexerFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("indexer")
Indexer.IssueType = sec.Key("ISSUE_INDEXER_TYPE").MustString("bleve")
- Indexer.IssuePath = filepath.ToSlash(sec.Key("ISSUE_INDEXER_PATH").MustString(filepath.ToSlash(filepath.Join(AppDataPath, "indexers/issues.bleve"))))
- if !filepath.IsAbs(Indexer.IssuePath) {
- Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath))
- }
- Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr)
-
- if Indexer.IssueType == "meilisearch" {
- u, err := url.Parse(Indexer.IssueConnStr)
- if err != nil {
- log.Warn("Failed to parse ISSUE_INDEXER_CONN_STR: %v", err)
- u = &url.URL{}
+ if Indexer.IssueType == "bleve" {
+ Indexer.IssuePath = filepath.ToSlash(sec.Key("ISSUE_INDEXER_PATH").MustString(filepath.ToSlash(filepath.Join(AppDataPath, "indexers/issues.bleve"))))
+ if !filepath.IsAbs(Indexer.IssuePath) {
+ Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath))
+ }
+ fatalDuplicatedPath("issue_indexer", Indexer.IssuePath)
+ } else {
+ Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr)
+ if Indexer.IssueType == "meilisearch" {
+ u, err := url.Parse(Indexer.IssueConnStr)
+ if err != nil {
+ log.Warn("Failed to parse ISSUE_INDEXER_CONN_STR: %v", err)
+ u = &url.URL{}
+ }
+ Indexer.IssueConnAuth, _ = u.User.Password()
+ u.User = nil
+ Indexer.IssueConnStr = u.String()
}
- Indexer.IssueConnAuth, _ = u.User.Password()
- u.User = nil
- Indexer.IssueConnStr = u.String()
}
Indexer.IssueIndexerName = sec.Key("ISSUE_INDEXER_NAME").MustString(Indexer.IssueIndexerName)
diff --git a/modules/setting/lfs.go b/modules/setting/lfs.go
index a5ea537cef..2034ef782c 100644
--- a/modules/setting/lfs.go
+++ b/modules/setting/lfs.go
@@ -4,22 +4,19 @@
package setting
import (
- "encoding/base64"
"fmt"
"time"
"code.gitea.io/gitea/modules/generate"
- "code.gitea.io/gitea/modules/util"
)
// LFS represents the configuration for Git LFS
var LFS = struct {
- StartServer bool `ini:"LFS_START_SERVER"`
- JWTSecretBase64 string `ini:"LFS_JWT_SECRET"`
- JWTSecretBytes []byte `ini:"-"`
- HTTPAuthExpiry time.Duration `ini:"LFS_HTTP_AUTH_EXPIRY"`
- MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
- LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
+ StartServer bool `ini:"LFS_START_SERVER"`
+ JWTSecretBytes []byte `ini:"-"`
+ HTTPAuthExpiry time.Duration `ini:"LFS_HTTP_AUTH_EXPIRY"`
+ MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
+ LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
Storage *Storage
}{}
@@ -61,10 +58,10 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
return nil
}
- LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
- LFS.JWTSecretBytes, err = util.Base64FixedDecode(base64.RawURLEncoding, []byte(LFS.JWTSecretBase64), 32)
+ jwtSecretBase64 := loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
+ LFS.JWTSecretBytes, err = generate.DecodeJwtSecretBase64(jwtSecretBase64)
if err != nil {
- LFS.JWTSecretBytes, LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
+ LFS.JWTSecretBytes, jwtSecretBase64, err = generate.NewJwtSecretWithBase64()
if err != nil {
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)
}
@@ -74,8 +71,8 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
if err != nil {
return fmt.Errorf("error saving JWT Secret for custom config: %v", err)
}
- rootCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
- saveCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(LFS.JWTSecretBase64)
+ rootCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(jwtSecretBase64)
+ saveCfg.Section("server").Key("LFS_JWT_SECRET").SetValue(jwtSecretBase64)
if err := saveCfg.Save(); err != nil {
return fmt.Errorf("error saving JWT Secret for custom config: %v", err)
}
diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go
index 0d15e91ef0..4d3bfd3eb6 100644
--- a/modules/setting/oauth2.go
+++ b/modules/setting/oauth2.go
@@ -4,13 +4,12 @@
package setting
import (
- "encoding/base64"
"math"
"path/filepath"
+ "sync/atomic"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/util"
)
// OAuth2UsernameType is enum describing the way gitea 'name' should be generated from oauth2 data
@@ -98,7 +97,6 @@ var OAuth2 = struct {
RefreshTokenExpirationTime int64
InvalidateRefreshTokens bool
JWTSigningAlgorithm string `ini:"JWT_SIGNING_ALGORITHM"`
- JWTSecretBase64 string `ini:"JWT_SECRET"`
JWTSigningPrivateKeyFile string `ini:"JWT_SIGNING_PRIVATE_KEY_FILE"`
MaxTokenLength int
DefaultApplications []string
@@ -130,29 +128,50 @@ func loadOAuth2From(rootCfg ConfigProvider) {
return
}
- OAuth2.JWTSecretBase64 = loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
+ jwtSecretBase64 := loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) {
OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile)
}
if InstallLock {
- if _, err := util.Base64FixedDecode(base64.RawURLEncoding, []byte(OAuth2.JWTSecretBase64), 32); err != nil {
- key, err := generate.NewJwtSecret()
+ jwtSecretBytes, err := generate.DecodeJwtSecretBase64(jwtSecretBase64)
+ if err != nil {
+ jwtSecretBytes, jwtSecretBase64, err = generate.NewJwtSecretWithBase64()
if err != nil {
log.Fatal("error generating JWT secret: %v", err)
}
-
- OAuth2.JWTSecretBase64 = base64.RawURLEncoding.EncodeToString(key)
saveCfg, err := rootCfg.PrepareSaving()
if err != nil {
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
}
- rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
- saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
+ rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64)
+ saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(jwtSecretBase64)
if err := saveCfg.Save(); err != nil {
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
}
}
+ generalSigningSecret.Store(&jwtSecretBytes)
}
}
+
+// generalSigningSecret is used as container for a []byte value
+// instead of an additional mutex, we use CompareAndSwap func to change the value thread save
+var generalSigningSecret atomic.Pointer[[]byte]
+
+func GetGeneralTokenSigningSecret() []byte {
+ old := generalSigningSecret.Load()
+ if old == nil || len(*old) == 0 {
+ jwtSecret, _, err := generate.NewJwtSecretWithBase64()
+ if err != nil {
+ log.Fatal("Unable to generate general JWT secret: %s", err.Error())
+ }
+ if generalSigningSecret.CompareAndSwap(old, &jwtSecret) {
+ // FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...)
+ log.Warn("OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes")
+ return jwtSecret
+ }
+ return *generalSigningSecret.Load()
+ }
+ return *old
+}
diff --git a/modules/setting/oauth2_test.go b/modules/setting/oauth2_test.go
new file mode 100644
index 0000000000..d822198619
--- /dev/null
+++ b/modules/setting/oauth2_test.go
@@ -0,0 +1,34 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package setting
+
+import (
+ "testing"
+
+ "code.gitea.io/gitea/modules/generate"
+ "code.gitea.io/gitea/modules/test"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetGeneralSigningSecret(t *testing.T) {
+ // when there is no general signing secret, it should be generated, and keep the same value
+ assert.Nil(t, generalSigningSecret.Load())
+ s1 := GetGeneralTokenSigningSecret()
+ assert.NotNil(t, s1)
+ s2 := GetGeneralTokenSigningSecret()
+ assert.Equal(t, s1, s2)
+
+ // the config value should always override any pre-generated value
+ cfg, _ := NewConfigProviderFromData(`
+[oauth2]
+JWT_SECRET = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+`)
+ defer test.MockVariableValue(&InstallLock, true)()
+ loadOAuth2From(cfg)
+ actual := GetGeneralTokenSigningSecret()
+ expected, _ := generate.DecodeJwtSecretBase64("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB")
+ assert.Len(t, actual, 32)
+ assert.EqualValues(t, expected, actual)
+}
diff --git a/modules/setting/path.go b/modules/setting/path.go
index 0fdc305aa1..b2cca0acbf 100644
--- a/modules/setting/path.go
+++ b/modules/setting/path.go
@@ -66,8 +66,12 @@ func init() {
AppWorkPath = filepath.Dir(AppPath)
}
+ fatalDuplicatedPath("app_work_path", AppWorkPath)
+
appWorkPathBuiltin = AppWorkPath
customPathBuiltin = CustomPath
+
+ fatalDuplicatedPath("custom_path", CustomPath)
customConfBuiltin = CustomConf
}
diff --git a/modules/setting/repository.go b/modules/setting/repository.go
index a6f0ed8833..7990021aaa 100644
--- a/modules/setting/repository.go
+++ b/modules/setting/repository.go
@@ -285,6 +285,9 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
} else {
RepoRootPath = filepath.Clean(RepoRootPath)
}
+
+ fatalDuplicatedPath("repository.ROOT", RepoRootPath)
+
defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder))
for _, charset := range Repository.DetectedCharsetsOrder {
defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder, strings.ToLower(strings.TrimSpace(charset)))
diff --git a/modules/setting/server.go b/modules/setting/server.go
index c09b91612a..0dea4e1ac7 100644
--- a/modules/setting/server.go
+++ b/modules/setting/server.go
@@ -7,7 +7,6 @@ import (
"encoding/base64"
"net"
"net/url"
- "path"
"path/filepath"
"strconv"
"strings"
@@ -321,17 +320,19 @@ func loadServerFrom(rootCfg ConfigProvider) {
}
StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(StaticRootPath)
StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour)
- AppDataPath = sec.Key("APP_DATA_PATH").MustString(path.Join(AppWorkPath, "data"))
+ AppDataPath = sec.Key("APP_DATA_PATH").MustString(filepath.Join(AppWorkPath, "data"))
if !filepath.IsAbs(AppDataPath) {
AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath))
}
+ fatalDuplicatedPath("app_data_path", AppDataPath)
EnableGzip = sec.Key("ENABLE_GZIP").MustBool()
EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false)
- PprofDataPath = sec.Key("PPROF_DATA_PATH").MustString(path.Join(AppWorkPath, "data/tmp/pprof"))
+ PprofDataPath = sec.Key("PPROF_DATA_PATH").MustString(filepath.Join(AppWorkPath, "data/tmp/pprof"))
if !filepath.IsAbs(PprofDataPath) {
PprofDataPath = filepath.Join(AppWorkPath, PprofDataPath)
}
+ fatalDuplicatedPath("pprof_data_path", PprofDataPath)
landingPage := sec.Key("LANDING_PAGE").MustString("home")
switch landingPage {
diff --git a/modules/setting/session.go b/modules/setting/session.go
index 664c66f869..8b9b754b38 100644
--- a/modules/setting/session.go
+++ b/modules/setting/session.go
@@ -5,7 +5,6 @@ package setting
import (
"net/http"
- "path"
"path/filepath"
"strings"
@@ -44,9 +43,10 @@ func loadSessionFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("session")
SessionConfig.Provider = sec.Key("PROVIDER").In("memory",
[]string{"memory", "file", "redis", "mysql", "postgres", "couchbase", "memcache", "db"})
- SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(path.Join(AppDataPath, "sessions")), "\" ")
+ SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(filepath.Join(AppDataPath, "sessions")), "\" ")
if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) {
- SessionConfig.ProviderConfig = path.Join(AppWorkPath, SessionConfig.ProviderConfig)
+ SessionConfig.ProviderConfig = filepath.Join(AppWorkPath, SessionConfig.ProviderConfig)
+ fatalDuplicatedPath("session", SessionConfig.ProviderConfig)
}
SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea")
SessionConfig.CookiePath = AppSubURL + "/" // there was a bug, old code only set CookePath=AppSubURL, no trailing slash
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index d444d9a017..6e7ce7e67f 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -90,9 +90,9 @@ func PrepareAppDataPath() error {
return nil
}
-func InitCfgProvider(file string, extraConfigs ...string) {
+func InitCfgProvider(file string) {
var err error
- if CfgProvider, err = NewConfigProviderFromFile(file, extraConfigs...); err != nil {
+ if CfgProvider, err = NewConfigProviderFromFile(file); err != nil {
log.Fatal("Unable to init config provider from %q: %v", file, err)
}
CfgProvider.DisableSaving() // do not allow saving the CfgProvider into file, it will be polluted by the "MustXxx" calls
@@ -226,3 +226,12 @@ func LoadSettingsForInstall() {
loadServiceFrom(CfgProvider)
loadMailerFrom(CfgProvider)
}
+
+var uniquePaths = make(map[string]string)
+
+func fatalDuplicatedPath(name, p string) {
+ if targetName, ok := uniquePaths[p]; ok && targetName != name {
+ log.Fatal("storage path %q is being used by %q and %q and all storage paths must be unique to prevent data loss.", p, targetName, name)
+ }
+ uniquePaths[p] = name
+}
diff --git a/modules/setting/storage.go b/modules/setting/storage.go
index f937c7cff3..23b08df101 100644
--- a/modules/setting/storage.go
+++ b/modules/setting/storage.go
@@ -240,6 +240,8 @@ func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType,
}
}
+ fatalDuplicatedPath("storage."+name, storage.Path)
+
return &storage, nil
}
diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index 51e175fba8..56d6158bd8 100644
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -98,6 +98,7 @@ type Repository struct {
AllowRebase bool `json:"allow_rebase"`
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
AllowSquash bool `json:"allow_squash_merge"`
+ AllowFastForwardOnly bool `json:"allow_fast_forward_only_merge"`
AllowRebaseUpdate bool `json:"allow_rebase_update"`
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
DefaultMergeStyle string `json:"default_merge_style"`
@@ -195,6 +196,8 @@ type EditRepoOption struct {
AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"`
// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
+ // either `true` to allow fast-forward-only merging pull requests, or `false` to prevent fast-forward-only merging.
+ AllowFastForwardOnly *bool `json:"allow_fast_forward_only_merge,omitempty"`
// either `true` to allow mark pr as merged manually, or `false` to prevent it.
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. Note: In some special cases, misjudgments can occur.
@@ -203,7 +206,7 @@ type EditRepoOption struct {
AllowRebaseUpdate *bool `json:"allow_rebase_update,omitempty"`
// set to `true` to delete pr branch after merge by default
DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"`
- // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash".
+ // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", "squash", or "fast-forward-only".
DefaultMergeStyle *string `json:"default_merge_style,omitempty"`
// set to `true` to allow edits from maintainers by default
DefaultAllowMaintainerEdit *bool `json:"default_allow_maintainer_edit,omitempty"`
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 96cdd9ca46..0f39767586 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -9,12 +9,12 @@ import (
"html"
"html/template"
"net/url"
+ "slices"
"strings"
"time"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/svg"
@@ -35,10 +35,11 @@ func NewFuncMap() template.FuncMap {
// html/template related functions
"dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names.
"Eval": Eval,
- "Safe": Safe,
- "Escape": html.EscapeString,
+ "SafeHTML": SafeHTML,
+ "HTMLFormat": HTMLFormat,
+ "HTMLEscape": HTMLEscape,
"QueryEscape": url.QueryEscape,
- "JSEscape": template.JSEscapeString,
+ "JSEscape": JSEscapeSafe,
"Str2html": Str2html, // TODO: rename it to SanitizeHTML
"URLJoin": util.URLJoin,
"DotEscape": DotEscape,
@@ -159,7 +160,6 @@ func NewFuncMap() template.FuncMap {
"RenderCodeBlock": RenderCodeBlock,
"RenderIssueTitle": RenderIssueTitle,
"RenderEmoji": RenderEmoji,
- "RenderEmojiPlain": emoji.ReplaceAliases,
"ReactionToEmoji": ReactionToEmoji,
"RenderMarkdownToHtml": RenderMarkdownToHtml,
@@ -179,14 +179,57 @@ func NewFuncMap() template.FuncMap {
}
}
-// Safe render raw as HTML
-func Safe(raw string) template.HTML {
- return template.HTML(raw)
+func HTMLFormat(s string, rawArgs ...any) template.HTML {
+ args := slices.Clone(rawArgs)
+ for i, v := range args {
+ switch v := v.(type) {
+ case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
+ // for most basic types (including template.HTML which is safe), just do nothing and use it
+ case string:
+ args[i] = template.HTMLEscapeString(v)
+ case fmt.Stringer:
+ args[i] = template.HTMLEscapeString(v.String())
+ default:
+ args[i] = template.HTMLEscapeString(fmt.Sprint(v))
+ }
+ }
+ return template.HTML(fmt.Sprintf(s, args...))
}
-// Str2html render Markdown text to HTML
-func Str2html(raw string) template.HTML {
- return template.HTML(markup.Sanitize(raw))
+// SafeHTML render raw as HTML
+func SafeHTML(s any) template.HTML {
+ switch v := s.(type) {
+ case string:
+ return template.HTML(v)
+ case template.HTML:
+ return v
+ }
+ panic(fmt.Sprintf("unexpected type %T", s))
+}
+
+// Str2html sanitizes the input by pre-defined markdown rules
+func Str2html(s any) template.HTML {
+ switch v := s.(type) {
+ case string:
+ return template.HTML(markup.Sanitize(v))
+ case template.HTML:
+ return template.HTML(markup.Sanitize(string(v)))
+ }
+ panic(fmt.Sprintf("unexpected type %T", s))
+}
+
+func HTMLEscape(s any) template.HTML {
+ switch v := s.(type) {
+ case string:
+ return template.HTML(html.EscapeString(v))
+ case template.HTML:
+ return v
+ }
+ panic(fmt.Sprintf("unexpected type %T", s))
+}
+
+func JSEscapeSafe(s string) template.HTML {
+ return template.HTML(template.JSEscapeString(s))
}
// DotEscape wraps a dots in names with ZWJ [U+200D] in order to prevent autolinkers from detecting these as urls
diff --git a/modules/templates/helper_test.go b/modules/templates/helper_test.go
index ec83e9ac33..8f5d633d4f 100644
--- a/modules/templates/helper_test.go
+++ b/modules/templates/helper_test.go
@@ -4,6 +4,7 @@
package templates
import (
+ "html/template"
"testing"
"github.com/stretchr/testify/assert"
@@ -52,3 +53,11 @@ func TestSubjectBodySeparator(t *testing.T) {
"",
"Insuficient\n--\nSeparators")
}
+
+func TestJSEscapeSafe(t *testing.T) {
+ assert.EqualValues(t, `\u0026\u003C\u003E\'\"`, JSEscapeSafe(`&<>'"`))
+}
+
+func TestHTMLFormat(t *testing.T) {
+ assert.Equal(t, template.HTML("< < 1 "), HTMLFormat("%s %s %d ", "<", template.HTML("<"), 1))
+}
diff --git a/modules/timeutil/since.go b/modules/timeutil/since.go
index 1cb3c4f288..dfaa0e3e3a 100644
--- a/modules/timeutil/since.go
+++ b/modules/timeutil/since.go
@@ -28,54 +28,54 @@ func computeTimeDiffFloor(diff int64, lang translation.Locale) (int64, string) {
switch {
case diff <= 0:
diff = 0
- diffStr = lang.Tr("tool.now")
+ diffStr = lang.TrString("tool.now")
case diff < 2:
diff = 0
- diffStr = lang.Tr("tool.1s")
+ diffStr = lang.TrString("tool.1s")
case diff < 1*Minute:
- diffStr = lang.Tr("tool.seconds", diff)
+ diffStr = lang.TrString("tool.seconds", diff)
diff = 0
case diff < 2*Minute:
diff -= 1 * Minute
- diffStr = lang.Tr("tool.1m")
+ diffStr = lang.TrString("tool.1m")
case diff < 1*Hour:
- diffStr = lang.Tr("tool.minutes", diff/Minute)
+ diffStr = lang.TrString("tool.minutes", diff/Minute)
diff -= diff / Minute * Minute
case diff < 2*Hour:
diff -= 1 * Hour
- diffStr = lang.Tr("tool.1h")
+ diffStr = lang.TrString("tool.1h")
case diff < 1*Day:
- diffStr = lang.Tr("tool.hours", diff/Hour)
+ diffStr = lang.TrString("tool.hours", diff/Hour)
diff -= diff / Hour * Hour
case diff < 2*Day:
diff -= 1 * Day
- diffStr = lang.Tr("tool.1d")
+ diffStr = lang.TrString("tool.1d")
case diff < 1*Week:
- diffStr = lang.Tr("tool.days", diff/Day)
+ diffStr = lang.TrString("tool.days", diff/Day)
diff -= diff / Day * Day
case diff < 2*Week:
diff -= 1 * Week
- diffStr = lang.Tr("tool.1w")
+ diffStr = lang.TrString("tool.1w")
case diff < 1*Month:
- diffStr = lang.Tr("tool.weeks", diff/Week)
+ diffStr = lang.TrString("tool.weeks", diff/Week)
diff -= diff / Week * Week
case diff < 2*Month:
diff -= 1 * Month
- diffStr = lang.Tr("tool.1mon")
+ diffStr = lang.TrString("tool.1mon")
case diff < 1*Year:
- diffStr = lang.Tr("tool.months", diff/Month)
+ diffStr = lang.TrString("tool.months", diff/Month)
diff -= diff / Month * Month
case diff < 2*Year:
diff -= 1 * Year
- diffStr = lang.Tr("tool.1y")
+ diffStr = lang.TrString("tool.1y")
default:
- diffStr = lang.Tr("tool.years", diff/Year)
+ diffStr = lang.TrString("tool.years", diff/Year)
diff -= (diff / Year) * Year
}
return diff, diffStr
@@ -97,10 +97,10 @@ func timeSincePro(then, now time.Time, lang translation.Locale) string {
diff := now.Unix() - then.Unix()
if then.After(now) {
- return lang.Tr("tool.future")
+ return lang.TrString("tool.future")
}
if diff == 0 {
- return lang.Tr("tool.now")
+ return lang.TrString("tool.now")
}
var timeStr, diffStr string
@@ -115,7 +115,7 @@ func timeSincePro(then, now time.Time, lang translation.Locale) string {
return strings.TrimPrefix(timeStr, ", ")
}
-func timeSinceUnix(then, now time.Time, lang translation.Locale) template.HTML {
+func timeSinceUnix(then, now time.Time, _ translation.Locale) template.HTML {
friendlyText := then.Format("2006-01-02 15:04:05 -07:00")
// document: https://github.com/github/relative-time-element
diff --git a/modules/translation/i18n/i18n.go b/modules/translation/i18n/i18n.go
index 42475545b3..1555cd961e 100644
--- a/modules/translation/i18n/i18n.go
+++ b/modules/translation/i18n/i18n.go
@@ -4,26 +4,25 @@
package i18n
import (
+ "html/template"
"io"
)
var DefaultLocales = NewLocaleStore()
type Locale interface {
- // Tr translates a given key and arguments for a language
- Tr(trKey string, trArgs ...any) string
- // Has reports if a locale has a translation for a given key
- Has(trKey string) bool
+ // TrString translates a given key and arguments for a language
+ TrString(trKey string, trArgs ...any) string
+ // TrHTML translates a given key and arguments for a language, string arguments are escaped to HTML
+ TrHTML(trKey string, trArgs ...any) template.HTML
+ // HasKey reports if a locale has a translation for a given key
+ HasKey(trKey string) bool
}
// LocaleStore provides the functions common to all locale stores
type LocaleStore interface {
io.Closer
- // Tr translates a given key and arguments for a language
- Tr(lang, trKey string, trArgs ...any) string
- // Has reports if a locale has a translation for a given key
- Has(lang, trKey string) bool
// SetDefaultLang sets the default language to fall back to
SetDefaultLang(lang string)
// ListLangNameDesc provides paired slices of language names to descriptors
@@ -45,7 +44,7 @@ func ResetDefaultLocales() {
DefaultLocales = NewLocaleStore()
}
-// GetLocales returns the locale from the default locales
+// GetLocale returns the locale from the default locales
func GetLocale(lang string) (Locale, bool) {
return DefaultLocales.Locale(lang)
}
diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go
index 1d1be43318..b364992dfe 100644
--- a/modules/translation/i18n/i18n_test.go
+++ b/modules/translation/i18n/i18n_test.go
@@ -4,6 +4,7 @@
package i18n
import (
+ "html/template"
"strings"
"testing"
@@ -17,7 +18,7 @@ fmt = %[1]s %[2]s
[section]
sub = Sub String
-mixed = test value; more text
+mixed = test value; %s
`)
testData2 := []byte(`
@@ -32,29 +33,33 @@ sub = Changed Sub String
assert.NoError(t, ls.AddLocaleByIni("lang2", "Lang2", testData2, nil))
ls.SetDefaultLang("lang1")
- result := ls.Tr("lang1", "fmt", "a", "b")
+ lang1, _ := ls.Locale("lang1")
+ lang2, _ := ls.Locale("lang2")
+
+ result := lang1.TrString("fmt", "a", "b")
assert.Equal(t, "a b", result)
- result = ls.Tr("lang2", "fmt", "a", "b")
+ result = lang2.TrString("fmt", "a", "b")
assert.Equal(t, "b a", result)
- result = ls.Tr("lang1", "section.sub")
+ result = lang1.TrString("section.sub")
assert.Equal(t, "Sub String", result)
- result = ls.Tr("lang2", "section.sub")
+ result = lang2.TrString("section.sub")
assert.Equal(t, "Changed Sub String", result)
- result = ls.Tr("", ".dot.name")
+ langNone, _ := ls.Locale("none")
+ result = langNone.TrString(".dot.name")
assert.Equal(t, "Dot Name", result)
- result = ls.Tr("lang2", "section.mixed")
- assert.Equal(t, `test value; more text `, result)
+ result2 := lang2.TrHTML("section.mixed", "a&b")
+ assert.EqualValues(t, `test value; a&b `, result2)
langs, descs := ls.ListLangNameDesc()
assert.ElementsMatch(t, []string{"lang1", "lang2"}, langs)
assert.ElementsMatch(t, []string{"Lang1", "Lang2"}, descs)
- found := ls.Has("lang1", "no-such")
+ found := lang1.HasKey("no-such")
assert.False(t, found)
assert.NoError(t, ls.Close())
}
@@ -72,9 +77,75 @@ c=22
ls := NewLocaleStore()
assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1, testData2))
- assert.Equal(t, "11", ls.Tr("lang1", "a"))
- assert.Equal(t, "21", ls.Tr("lang1", "b"))
- assert.Equal(t, "22", ls.Tr("lang1", "c"))
+ lang1, _ := ls.Locale("lang1")
+ assert.Equal(t, "11", lang1.TrString("a"))
+ assert.Equal(t, "21", lang1.TrString("b"))
+ assert.Equal(t, "22", lang1.TrString("c"))
+}
+
+type stringerPointerReceiver struct {
+ s string
+}
+
+func (s *stringerPointerReceiver) String() string {
+ return s.s
+}
+
+type stringerStructReceiver struct {
+ s string
+}
+
+func (s stringerStructReceiver) String() string {
+ return s.s
+}
+
+type errorStructReceiver struct {
+ s string
+}
+
+func (e errorStructReceiver) Error() string {
+ return e.s
+}
+
+type errorPointerReceiver struct {
+ s string
+}
+
+func (e *errorPointerReceiver) Error() string {
+ return e.s
+}
+
+func TestLocaleWithTemplate(t *testing.T) {
+ ls := NewLocaleStore()
+ assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", []byte(`key=%s `), nil))
+ lang1, _ := ls.Locale("lang1")
+
+ tmpl := template.New("test").Funcs(template.FuncMap{"tr": lang1.TrHTML})
+ tmpl = template.Must(tmpl.Parse(`{{tr "key" .var}}`))
+
+ cases := []struct {
+ in any
+ want string
+ }{
+ {"", "<str> "},
+ {[]byte(""), "[60 98 121 116 101 115 62] "},
+ {template.HTML(""), " "},
+ {stringerPointerReceiver{""}, "{<stringerPointerReceiver>} "},
+ {&stringerPointerReceiver{""}, "<stringerPointerReceiver ptr> "},
+ {stringerStructReceiver{""}, "<stringerStructReceiver> "},
+ {&stringerStructReceiver{""}, "<stringerStructReceiver ptr> "},
+ {errorStructReceiver{""}, "<errorStructReceiver> "},
+ {&errorStructReceiver{""}, "<errorStructReceiver ptr> "},
+ {errorPointerReceiver{""}, "{<errorPointerReceiver>} "},
+ {&errorPointerReceiver{""}, "<errorPointerReceiver ptr> "},
+ }
+
+ buf := &strings.Builder{}
+ for _, c := range cases {
+ buf.Reset()
+ assert.NoError(t, tmpl.Execute(buf, map[string]any{"var": c.in}))
+ assert.Equal(t, c.want, buf.String())
+ }
}
func TestLocaleStoreQuirks(t *testing.T) {
@@ -110,8 +181,9 @@ func TestLocaleStoreQuirks(t *testing.T) {
for _, testData := range testDataList {
ls := NewLocaleStore()
err := ls.AddLocaleByIni("lang1", "Lang1", []byte("a="+testData.in), nil)
+ lang1, _ := ls.Locale("lang1")
assert.NoError(t, err, testData.hint)
- assert.Equal(t, testData.out, ls.Tr("lang1", "a"), testData.hint)
+ assert.Equal(t, testData.out, lang1.TrString("a"), testData.hint)
assert.NoError(t, ls.Close())
}
diff --git a/modules/translation/i18n/localestore.go b/modules/translation/i18n/localestore.go
index f5a951a79f..b422996984 100644
--- a/modules/translation/i18n/localestore.go
+++ b/modules/translation/i18n/localestore.go
@@ -5,6 +5,8 @@ package i18n
import (
"fmt"
+ "html/template"
+ "slices"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -18,6 +20,8 @@ type locale struct {
idxToMsgMap map[int]string // the map idx is generated by store's trKeyToIdxMap
}
+var _ Locale = (*locale)(nil)
+
type localeStore struct {
// After initializing has finished, these fields are read-only.
langNames []string
@@ -85,20 +89,6 @@ func (store *localeStore) SetDefaultLang(lang string) {
store.defaultLang = lang
}
-// Tr translates content to target language. fall back to default language.
-func (store *localeStore) Tr(lang, trKey string, trArgs ...any) string {
- l, _ := store.Locale(lang)
-
- return l.Tr(trKey, trArgs...)
-}
-
-// Has returns whether the given language has a translation for the provided key
-func (store *localeStore) Has(lang, trKey string) bool {
- l, _ := store.Locale(lang)
-
- return l.Has(trKey)
-}
-
// Locale returns the locale for the lang or the default language
func (store *localeStore) Locale(lang string) (Locale, bool) {
l, found := store.localeMap[lang]
@@ -113,13 +103,11 @@ func (store *localeStore) Locale(lang string) (Locale, bool) {
return l, found
}
-// Close implements io.Closer
func (store *localeStore) Close() error {
return nil
}
-// Tr translates content to locale language. fall back to default language.
-func (l *locale) Tr(trKey string, trArgs ...any) string {
+func (l *locale) TrString(trKey string, trArgs ...any) string {
format := trKey
idx, ok := l.store.trKeyToIdxMap[trKey]
@@ -141,8 +129,25 @@ func (l *locale) Tr(trKey string, trArgs ...any) string {
return msg
}
-// Has returns whether a key is present in this locale or not
-func (l *locale) Has(trKey string) bool {
+func (l *locale) TrHTML(trKey string, trArgs ...any) template.HTML {
+ args := slices.Clone(trArgs)
+ for i, v := range args {
+ switch v := v.(type) {
+ case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
+ // for most basic types (including template.HTML which is safe), just do nothing and use it
+ case string:
+ args[i] = template.HTMLEscapeString(v)
+ case fmt.Stringer:
+ args[i] = template.HTMLEscapeString(v.String())
+ default:
+ args[i] = template.HTMLEscapeString(fmt.Sprint(v))
+ }
+ }
+ return template.HTML(l.TrString(trKey, args...))
+}
+
+// HasKey returns whether a key is present in this locale or not
+func (l *locale) HasKey(trKey string) bool {
idx, ok := l.store.trKeyToIdxMap[trKey]
if !ok {
return false
diff --git a/modules/translation/mock.go b/modules/translation/mock.go
index 2d0cb17324..1f0559f38d 100644
--- a/modules/translation/mock.go
+++ b/modules/translation/mock.go
@@ -3,7 +3,10 @@
package translation
-import "fmt"
+import (
+ "fmt"
+ "html/template"
+)
// MockLocale provides a mocked locale without any translations
type MockLocale struct{}
@@ -14,12 +17,16 @@ func (l MockLocale) Language() string {
return "en"
}
-func (l MockLocale) Tr(s string, _ ...any) string {
+func (l MockLocale) TrString(s string, _ ...any) string {
return s
}
-func (l MockLocale) TrN(_cnt any, key1, _keyN string, _args ...any) string {
- return key1
+func (l MockLocale) Tr(s string, a ...any) template.HTML {
+ return template.HTML(s)
+}
+
+func (l MockLocale) TrN(cnt any, key1, keyN string, args ...any) template.HTML {
+ return template.HTML(key1)
}
func (l MockLocale) PrettyNumber(v any) string {
diff --git a/modules/translation/translation.go b/modules/translation/translation.go
index dba4de6607..b7c18f610a 100644
--- a/modules/translation/translation.go
+++ b/modules/translation/translation.go
@@ -5,6 +5,7 @@ package translation
import (
"context"
+ "html/template"
"sort"
"strings"
"sync"
@@ -27,8 +28,11 @@ var ContextKey any = &contextKey{}
// Locale represents an interface to translation
type Locale interface {
Language() string
- Tr(string, ...any) string
- TrN(cnt any, key1, keyN string, args ...any) string
+ TrString(string, ...any) string
+
+ Tr(key string, args ...any) template.HTML
+ TrN(cnt any, key1, keyN string, args ...any) template.HTML
+
PrettyNumber(v any) string
}
@@ -144,6 +148,8 @@ type locale struct {
msgPrinter *message.Printer
}
+var _ Locale = (*locale)(nil)
+
// NewLocale return a locale
func NewLocale(lang string) Locale {
if lock != nil {
@@ -216,8 +222,12 @@ var trNLangRules = map[string]func(int64) int{
},
}
+func (l *locale) Tr(s string, args ...any) template.HTML {
+ return l.TrHTML(s, args...)
+}
+
// TrN returns translated message for plural text translation
-func (l *locale) TrN(cnt any, key1, keyN string, args ...any) string {
+func (l *locale) TrN(cnt any, key1, keyN string, args ...any) template.HTML {
var c int64
if t, ok := cnt.(int); ok {
c = int64(t)
diff --git a/modules/util/filebuffer/file_backed_buffer.go b/modules/util/filebuffer/file_backed_buffer.go
index 6b07bd0413..739543e297 100644
--- a/modules/util/filebuffer/file_backed_buffer.go
+++ b/modules/util/filebuffer/file_backed_buffer.go
@@ -149,6 +149,7 @@ func (b *FileBackedBuffer) Close() error {
if b.file != nil {
err := b.file.Close()
os.Remove(b.file.Name())
+ b.file = nil
return err
}
return nil
diff --git a/modules/util/keypair.go b/modules/util/keypair.go
index 97f2d9ebca..8b86c142af 100644
--- a/modules/util/keypair.go
+++ b/modules/util/keypair.go
@@ -7,10 +7,9 @@ import (
"crypto"
"crypto/rand"
"crypto/rsa"
+ "crypto/sha256"
"crypto/x509"
"encoding/pem"
-
- "github.com/minio/sha256-simd"
)
// GenerateKeyPair generates a public and private keypair
diff --git a/modules/util/keypair_test.go b/modules/util/keypair_test.go
index c9925f7988..c6f68c845a 100644
--- a/modules/util/keypair_test.go
+++ b/modules/util/keypair_test.go
@@ -7,12 +7,12 @@ import (
"crypto"
"crypto/rand"
"crypto/rsa"
+ "crypto/sha256"
"crypto/x509"
"encoding/pem"
"regexp"
"testing"
- "github.com/minio/sha256-simd"
"github.com/stretchr/testify/assert"
)
diff --git a/modules/util/util.go b/modules/util/util.go
index c47931f6c9..28b549f405 100644
--- a/modules/util/util.go
+++ b/modules/util/util.go
@@ -6,12 +6,13 @@ package util
import (
"bytes"
"crypto/rand"
- "encoding/base64"
"fmt"
"math/big"
"strconv"
"strings"
+ "code.gitea.io/gitea/modules/optional"
+
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
@@ -43,6 +44,22 @@ func (o OptionalBool) IsNone() bool {
return o == OptionalBoolNone
}
+// ToGeneric converts OptionalBool to optional.Option[bool]
+func (o OptionalBool) ToGeneric() optional.Option[bool] {
+ if o.IsNone() {
+ return optional.None[bool]()
+ }
+ return optional.Some[bool](o.IsTrue())
+}
+
+// OptionalBoolFromGeneric converts optional.Option[bool] to OptionalBool
+func OptionalBoolFromGeneric(o optional.Option[bool]) OptionalBool {
+ if o.Has() {
+ return OptionalBoolOf(o.Value())
+ }
+ return OptionalBoolNone
+}
+
// OptionalBoolOf get the corresponding OptionalBool of a bool
func OptionalBoolOf(b bool) OptionalBool {
if b {
@@ -246,13 +263,3 @@ func ToFloat64(number any) (float64, error) {
func ToPointer[T any](val T) *T {
return &val
}
-
-func Base64FixedDecode(encoding *base64.Encoding, src []byte, length int) ([]byte, error) {
- decoded := make([]byte, encoding.DecodedLen(len(src))+3)
- if n, err := encoding.Decode(decoded, src); err != nil {
- return nil, err
- } else if n != length {
- return nil, fmt.Errorf("invalid base64 decoded length: %d, expects: %d", n, length)
- }
- return decoded[:length], nil
-}
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index 8509d8aced..c5830ce01c 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -4,7 +4,6 @@
package util
import (
- "encoding/base64"
"regexp"
"strings"
"testing"
@@ -234,16 +233,3 @@ func TestToPointer(t *testing.T) {
val123 := 123
assert.False(t, &val123 == ToPointer(val123))
}
-
-func TestBase64FixedDecode(t *testing.T) {
- _, err := Base64FixedDecode(base64.RawURLEncoding, []byte("abcd"), 32)
- assert.ErrorContains(t, err, "invalid base64 decoded length")
- _, err = Base64FixedDecode(base64.RawURLEncoding, []byte(strings.Repeat("a", 64)), 32)
- assert.ErrorContains(t, err, "invalid base64 decoded length")
-
- str32 := strings.Repeat("x", 32)
- encoded32 := base64.RawURLEncoding.EncodeToString([]byte(str32))
- decoded32, err := Base64FixedDecode(base64.RawURLEncoding, []byte(encoded32), 32)
- assert.NoError(t, err)
- assert.Equal(t, str32, string(decoded32))
-}
diff --git a/modules/web/middleware/binding.go b/modules/web/middleware/binding.go
index d9bcdf3b2a..43e1bbc70e 100644
--- a/modules/web/middleware/binding.go
+++ b/modules/web/middleware/binding.go
@@ -104,40 +104,40 @@ func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Lo
trName := field.Tag.Get("locale")
if len(trName) == 0 {
- trName = l.Tr("form." + field.Name)
+ trName = l.TrString("form." + field.Name)
} else {
- trName = l.Tr(trName)
+ trName = l.TrString(trName)
}
switch errs[0].Classification {
case binding.ERR_REQUIRED:
- data["ErrorMsg"] = trName + l.Tr("form.require_error")
+ data["ErrorMsg"] = trName + l.TrString("form.require_error")
case binding.ERR_ALPHA_DASH:
- data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
+ data["ErrorMsg"] = trName + l.TrString("form.alpha_dash_error")
case binding.ERR_ALPHA_DASH_DOT:
- data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
+ data["ErrorMsg"] = trName + l.TrString("form.alpha_dash_dot_error")
case validation.ErrGitRefName:
- data["ErrorMsg"] = trName + l.Tr("form.git_ref_name_error")
+ data["ErrorMsg"] = trName + l.TrString("form.git_ref_name_error")
case binding.ERR_SIZE:
- data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
+ data["ErrorMsg"] = trName + l.TrString("form.size_error", GetSize(field))
case binding.ERR_MIN_SIZE:
- data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
+ data["ErrorMsg"] = trName + l.TrString("form.min_size_error", GetMinSize(field))
case binding.ERR_MAX_SIZE:
- data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
+ data["ErrorMsg"] = trName + l.TrString("form.max_size_error", GetMaxSize(field))
case binding.ERR_EMAIL:
- data["ErrorMsg"] = trName + l.Tr("form.email_error")
+ data["ErrorMsg"] = trName + l.TrString("form.email_error")
case binding.ERR_URL:
- data["ErrorMsg"] = trName + l.Tr("form.url_error", errs[0].Message)
+ data["ErrorMsg"] = trName + l.TrString("form.url_error", errs[0].Message)
case binding.ERR_INCLUDE:
- data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
+ data["ErrorMsg"] = trName + l.TrString("form.include_error", GetInclude(field))
case validation.ErrGlobPattern:
- data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message)
+ data["ErrorMsg"] = trName + l.TrString("form.glob_pattern_error", errs[0].Message)
case validation.ErrRegexPattern:
- data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
+ data["ErrorMsg"] = trName + l.TrString("form.regex_pattern_error", errs[0].Message)
case validation.ErrUsername:
- data["ErrorMsg"] = trName + l.Tr("form.username_error")
+ data["ErrorMsg"] = trName + l.TrString("form.username_error")
case validation.ErrInvalidGroupTeamMap:
- data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
+ data["ErrorMsg"] = trName + l.TrString("form.invalid_group_team_map_error", errs[0].Message)
default:
msg := errs[0].Classification
if msg != "" && errs[0].Message != "" {
@@ -146,7 +146,7 @@ func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Lo
msg += errs[0].Message
if msg == "" {
- msg = l.Tr("form.unknown_error")
+ msg = l.TrString("form.unknown_error")
}
data["ErrorMsg"] = trName + ": " + msg
}
diff --git a/modules/web/middleware/flash.go b/modules/web/middleware/flash.go
index 41f3aac27c..88da2049a4 100644
--- a/modules/web/middleware/flash.go
+++ b/modules/web/middleware/flash.go
@@ -3,7 +3,11 @@
package middleware
-import "net/url"
+import (
+ "fmt"
+ "html/template"
+ "net/url"
+)
// Flash represents a one time data transfer between two requests.
type Flash struct {
@@ -26,26 +30,36 @@ func (f *Flash) set(name, msg string, current ...bool) {
}
}
+func flashMsgStringOrHTML(msg any) string {
+ switch v := msg.(type) {
+ case string:
+ return v
+ case template.HTML:
+ return string(v)
+ }
+ panic(fmt.Sprintf("unknown type: %T", msg))
+}
+
// Error sets error message
-func (f *Flash) Error(msg string, current ...bool) {
- f.ErrorMsg = msg
- f.set("error", msg, current...)
+func (f *Flash) Error(msg any, current ...bool) {
+ f.ErrorMsg = flashMsgStringOrHTML(msg)
+ f.set("error", f.ErrorMsg, current...)
}
// Warning sets warning message
-func (f *Flash) Warning(msg string, current ...bool) {
- f.WarningMsg = msg
- f.set("warning", msg, current...)
+func (f *Flash) Warning(msg any, current ...bool) {
+ f.WarningMsg = flashMsgStringOrHTML(msg)
+ f.set("warning", f.WarningMsg, current...)
}
// Info sets info message
-func (f *Flash) Info(msg string, current ...bool) {
- f.InfoMsg = msg
- f.set("info", msg, current...)
+func (f *Flash) Info(msg any, current ...bool) {
+ f.InfoMsg = flashMsgStringOrHTML(msg)
+ f.set("info", f.InfoMsg, current...)
}
// Success sets success message
-func (f *Flash) Success(msg string, current ...bool) {
- f.SuccessMsg = msg
- f.set("success", msg, current...)
+func (f *Flash) Success(msg any, current ...bool) {
+ f.SuccessMsg = flashMsgStringOrHTML(msg)
+ f.set("success", f.SuccessMsg, current...)
}
diff --git a/options/license/Brian-Gladman-2-Clause b/options/license/Brian-Gladman-2-Clause
new file mode 100644
index 0000000000..7276f63e9e
--- /dev/null
+++ b/options/license/Brian-Gladman-2-Clause
@@ -0,0 +1,17 @@
+Copyright (C) 1998-2013, Brian Gladman, Worcester, UK. All
+ rights reserved.
+
+The redistribution and use of this software (with or without
+changes) is allowed without the payment of fees or royalties
+provided that:
+
+ source code distributions include the above copyright notice,
+ this list of conditions and the following disclaimer;
+
+ binary distributions include the above copyright notice, this
+ list of conditions and the following disclaimer in their
+ documentation.
+
+This software is provided 'as is' with no explicit or implied
+warranties in respect of its operation, including, but not limited
+to, correctness and fitness for purpose.
diff --git a/options/license/CMU-Mach-nodoc b/options/license/CMU-Mach-nodoc
new file mode 100644
index 0000000000..c81d74fee7
--- /dev/null
+++ b/options/license/CMU-Mach-nodoc
@@ -0,0 +1,11 @@
+Copyright (C) 2002 Naval Research Laboratory (NRL/CCS)
+
+Permission to use, copy, modify and distribute this software and
+its documentation is hereby granted, provided that both the
+copyright notice and this permission notice appear in all copies of
+the software, derivative works or modified versions, and any
+portions thereof.
+
+NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+RESULTING FROM THE USE OF THIS SOFTWARE.
diff --git a/options/license/GNOME-examples-exception b/options/license/GNOME-examples-exception
new file mode 100644
index 0000000000..0f0cd53b50
--- /dev/null
+++ b/options/license/GNOME-examples-exception
@@ -0,0 +1 @@
+As a special exception, the copyright holders give you permission to copy, modify, and distribute the example code contained in this document under the terms of your choosing, without restriction.
diff --git a/options/license/Gmsh-exception b/options/license/Gmsh-exception
new file mode 100644
index 0000000000..6d28f704e4
--- /dev/null
+++ b/options/license/Gmsh-exception
@@ -0,0 +1,16 @@
+The copyright holders of Gmsh give you permission to combine Gmsh
+ with code included in the standard release of Netgen (from Joachim
+ Sch"oberl), METIS (from George Karypis at the University of
+ Minnesota), OpenCASCADE (from Open CASCADE S.A.S) and ParaView
+ (from Kitware, Inc.) under their respective licenses. You may copy
+ and distribute such a system following the terms of the GNU GPL for
+ Gmsh and the licenses of the other code concerned, provided that
+ you include the source code of that other code when and as the GNU
+ GPL requires distribution of source code.
+
+ Note that people who make modified versions of Gmsh are not
+ obligated to grant this special exception for their modified
+ versions; it is their choice whether to do so. The GNU General
+ Public License gives permission to release a modified version
+ without this exception; this exception also makes it possible to
+ release a modified version which carries forward this exception.
diff --git a/options/license/HPND-Fenneberg-Livingston b/options/license/HPND-Fenneberg-Livingston
new file mode 100644
index 0000000000..aaf524f3aa
--- /dev/null
+++ b/options/license/HPND-Fenneberg-Livingston
@@ -0,0 +1,13 @@
+Copyright (C) 1995,1996,1997,1998 Lars Fenneberg
+
+Permission to use, copy, modify, and distribute this software for any
+purpose and without fee is hereby granted, provided that this copyright and
+permission notice appear on all copies and supporting documentation, the
+name of Lars Fenneberg not be used in advertising or publicity pertaining to
+distribution of the program without specific prior permission, and notice be
+given in supporting documentation that copying and distribution is by
+permission of Lars Fenneberg.
+
+Lars Fenneberg makes no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or implied
+warranty.
diff --git a/options/license/HPND-INRIA-IMAG b/options/license/HPND-INRIA-IMAG
new file mode 100644
index 0000000000..87d09d92cb
--- /dev/null
+++ b/options/license/HPND-INRIA-IMAG
@@ -0,0 +1,9 @@
+This software is available with usual "research" terms with
+the aim of retain credits of the software. Permission to use,
+copy, modify and distribute this software for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies, and
+the name of INRIA, IMAG, or any contributor not be used in
+advertising or publicity pertaining to this material without
+the prior explicit permission. The software is provided "as
+is" without any warranties, support or liabilities of any kind.
diff --git a/options/license/Mackerras-3-Clause b/options/license/Mackerras-3-Clause
new file mode 100644
index 0000000000..6467f0c98e
--- /dev/null
+++ b/options/license/Mackerras-3-Clause
@@ -0,0 +1,25 @@
+Copyright (c) 1995 Eric Rosenquist. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name(s) of the authors of this software must not be used to
+ endorse or promote products derived from this software without
+ prior written permission.
+
+ THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/options/license/Mackerras-3-Clause-acknowledgment b/options/license/Mackerras-3-Clause-acknowledgment
new file mode 100644
index 0000000000..5f0187add7
--- /dev/null
+++ b/options/license/Mackerras-3-Clause-acknowledgment
@@ -0,0 +1,25 @@
+Copyright (c) 1993-2002 Paul Mackerras. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. The name(s) of the authors of this software must not be used to
+ endorse or promote products derived from this software without
+ prior written permission.
+
+3. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by Paul Mackerras
+ ".
+
+THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/options/license/OpenVision b/options/license/OpenVision
new file mode 100644
index 0000000000..983505389e
--- /dev/null
+++ b/options/license/OpenVision
@@ -0,0 +1,33 @@
+Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights
+Reserved
+
+WARNING: Retrieving the OpenVision Kerberos Administration system
+source code, as described below, indicates your acceptance of the
+following terms. If you do not agree to the following terms, do
+not retrieve the OpenVision Kerberos administration system.
+
+You may freely use and distribute the Source Code and Object Code
+compiled from it, with or without modification, but this Source
+Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY,
+INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR
+FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER
+EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY
+FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING,
+WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE
+CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY
+OTHER REASON.
+
+OpenVision retains all copyrights in the donated Source Code.
+OpenVision also retains copyright to derivative works of the Source
+Code, whether created by OpenVision or by a third party. The
+OpenVision copyright notice must be preserved if derivative works
+are made based on the donated Source Code.
+
+OpenVision Technologies, Inc. has donated this Kerberos
+Administration system to MIT for inclusion in the standard Kerberos
+5 distribution. This donation underscores our commitment to
+continuing Kerberos technology development and our gratitude for
+the valuable work which has been performed by MIT and the Kerberos
+community.
diff --git a/options/license/Sun-PPP b/options/license/Sun-PPP
new file mode 100644
index 0000000000..5f94a13437
--- /dev/null
+++ b/options/license/Sun-PPP
@@ -0,0 +1,13 @@
+Copyright (c) 2001 by Sun Microsystems, Inc.
+All rights reserved.
+
+Non-exclusive rights to redistribute, modify, translate, and use
+this software in source and binary forms, in whole or in part, is
+hereby granted, provided that the above copyright notice is
+duplicated in any source form, and that neither the name of the
+copyright holder nor the author is used to endorse or promote
+products derived from this software.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/options/license/UMich-Merit b/options/license/UMich-Merit
new file mode 100644
index 0000000000..93e304b90e
--- /dev/null
+++ b/options/license/UMich-Merit
@@ -0,0 +1,19 @@
+[C] The Regents of the University of Michigan and Merit Network, Inc. 1992,
+1993, 1994, 1995 All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice and this permission notice appear in all
+copies of the software and derivative works or modified versions thereof,
+and that both the copyright notice and this permission and disclaimer
+notice appear in supporting documentation.
+
+THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
+UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE
+FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
+THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the
+University of Michigan and Merit Network, Inc. shall not be liable for any
+special, indirect, incidental or consequential damages with respect to any
+claim by Licensee or any third party arising from use of the software.
diff --git a/options/license/bcrypt-Solar-Designer b/options/license/bcrypt-Solar-Designer
new file mode 100644
index 0000000000..8cb05017fc
--- /dev/null
+++ b/options/license/bcrypt-Solar-Designer
@@ -0,0 +1,11 @@
+Written by Solar Designer in 1998-2014.
+No copyright is claimed, and the software is hereby placed in the public
+domain. In case this attempt to disclaim copyright and place the software
+in the public domain is deemed null and void, then the software is
+Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
+general public under the following terms:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted.
+
+There's ABSOLUTELY NO WARRANTY, express or implied.
diff --git a/options/license/gtkbook b/options/license/gtkbook
new file mode 100644
index 0000000000..91215e80d6
--- /dev/null
+++ b/options/license/gtkbook
@@ -0,0 +1,6 @@
+Copyright 2005 Syd Logan, All Rights Reserved
+
+This code is distributed without warranty. You are free to use
+this code for any purpose, however, if this code is republished or
+redistributed in its original form, as hardcopy or electronically,
+then you must include this copyright notice along with the code.
diff --git a/options/license/softSurfer b/options/license/softSurfer
new file mode 100644
index 0000000000..1bbc88c34c
--- /dev/null
+++ b/options/license/softSurfer
@@ -0,0 +1,6 @@
+Copyright 2001, softSurfer (www.softsurfer.com)
+This code may be freely used and modified for any purpose
+providing that this copyright notice is included with it.
+SoftSurfer makes no warranty for this code, and cannot be held
+liable for any real or imagined damage resulting from its use.
+Users of this code must verify correctness for their application.
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index e9428ebcd4..d30103a8eb 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -4,6 +4,7 @@ explore=Procházet
help=Nápověda
logo=Logo
sign_in=Přihlásit se
+sign_in_with_provider=Přihlásit se pomocí %s
sign_in_or=nebo
sign_out=Odhlásit se
sign_up=Registrovat se
@@ -16,6 +17,7 @@ template=Šablona
language=Jazyk
notifications=Oznámení
active_stopwatch=Aktivní sledování času
+tracked_time_summary=Shrnutí sledovaného času na základě filtrů v seznamu úkolů
create_new=Vytvořit…
user_profile_and_more=Profily a nastavení…
signed_in_as=Přihlášen jako
@@ -79,6 +81,7 @@ milestones=Milníky
ok=OK
cancel=Zrušit
+retry=Znovu
rerun=Znovu spustit
rerun_all=Znovu spustit všechny úlohy
save=Uložit
@@ -86,14 +89,17 @@ add=Přidat
add_all=Přidat vše
remove=Odstranit
remove_all=Odstranit vše
-remove_label_str=`Odstranit položku "%s"`
+remove_label_str=Odstranit položku „%s“
edit=Upravit
+view=Zobrazit
enabled=Povolený
disabled=Zakázané
+locked=Uzamčeno
copy=Kopírovat
copy_url=Kopírovat URL
+copy_hash=Kopírovat hash
copy_content=Kopírovat obsah
copy_branch=Kopírovat jméno větve
copy_success=Zkopírováno!
@@ -106,6 +112,7 @@ loading=Načítá se…
error=Chyba
error404=Stránka, kterou se snažíte zobrazit, buď neexistuje , nebo nemáte oprávnění ji zobrazit.
+go_back=Zpět
never=Nikdy
unknown=Neznámý
@@ -127,7 +134,9 @@ concept_user_organization=Organizace
show_timestamps=Zobrazit časové značky
show_log_seconds=Zobrazit sekundy
show_full_screen=Zobrazit celou obrazovku
+download_logs=Stáhnout logy
+confirm_delete_selected=Potvrdit odstranění všech vybraných položek?
name=Název
value=Hodnota
@@ -153,7 +162,7 @@ buttons.code.tooltip=Přidat kód
buttons.link.tooltip=Přidat odkaz
buttons.list.unordered.tooltip=Přidat seznam odrážek
buttons.list.ordered.tooltip=Přidat číslovaný seznam
-buttons.list.task.tooltip=Přidat seznam úkolů
+buttons.list.task.tooltip=Přidat seznam úloh
buttons.mention.tooltip=Uveďte uživatele nebo tým
buttons.ref.tooltip=Odkaz na issue nebo pull request
buttons.switch_to_legacy.tooltip=Místo toho použít starší editor
@@ -166,6 +175,7 @@ string.desc=Z – A
[error]
occurred=Došlo k chybě
+report_message=Pokud jste si jisti, že se jedná o chybu Gitea, prosím vyhledejte problém na GitHub a v případě potřeby založte nový problém.
missing_csrf=Špatný požadavek: Neexistuje CSRF token
invalid_csrf=Špatný požadavek: Neplatný CSRF token
not_found=Cíl nebyl nalezen.
@@ -174,6 +184,7 @@ network_error=Chyba sítě
[startpage]
app_desc=Snadno přístupný vlastní Git
install=Jednoduchá na instalaci
+install_desc=Jednoduše spusťte jako binární program pro vaši platformu, nasaďte jej pomocí Docker , nebo jej stáhněte jako balíček .
platform=Multiplatformní
platform_desc=Gitea běží všude, kde Go může kompilovat: Windows, macOS, Linux, ARM, atd. Vyberte si ten, který milujete!
lightweight=Lehká
@@ -218,6 +229,7 @@ repo_path_helper=Všechny vzdálené repozitáře Gitu budou uloženy do tohoto
lfs_path=Kořenový adresář Git LFS
lfs_path_helper=V tomto adresáři budou uloženy soubory, které jsou sledovány Git LFS. Pokud ponecháte prázdné, LFS zakážete.
run_user=Spustit jako uživatel
+run_user_helper=Zadejte uživatelské jméno, pod kterým Gitea běží v operačním systému. Pozor: tento uživatel musí mít přístup ke kořenovému adresáři repozitářů.
domain=Doména serveru
domain_helper=Adresa domény, nebo hostitele serveru.
ssh_port=Port SSH serveru
@@ -267,7 +279,7 @@ install_btn_confirm=Nainstalovat Gitea
test_git_failed=Chyba při testu příkazu 'git': %v
sqlite3_not_available=Tato verze Gitea nepodporuje SQLite3. Stáhněte si oficiální binární verzi od %s (nikoli verzi „gobuild“).
invalid_db_setting=Nastavení databáze je neplatné: %v
-invalid_db_table=Databázová tabulka "%s" je neplatná: %v
+invalid_db_table=Databázová tabulka „%s“ je neplatná: %v
invalid_repo_path=Kořenový adresář repozitářů není správný: %v
invalid_app_data_path=Cesta k datům aplikace je neplatná: %v
run_user_not_match=`"Run as" uživatelské jméno není aktuální uživatelské jméno: %s -> %s`
@@ -289,6 +301,8 @@ invalid_password_algorithm=Neplatný algoritmus hash hesla
password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. Algoritmus argon2 je poměrně bezpečný, ale používá spoustu paměti a může být nevhodný pro malé systémy.
enable_update_checker=Povolit kontrolu aktualizací
enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke gitea.io.
+env_config_keys=Konfigurace prostředí
+env_config_keys_prompt=Následující proměnné prostředí budou také použity pro váš konfigurační soubor:
[home]
uname_holder=Uživatelské jméno nebo e-mailová adresa
@@ -334,7 +348,7 @@ repo_no_results=Nebyly nalezeny žádné odpovídající repozitáře.
user_no_results=Nebyly nalezeni žádní odpovídající uživatelé.
org_no_results=Nebyly nalezeny žádné odpovídající organizace.
code_no_results=Nebyl nalezen žádný zdrojový kód odpovídající hledanému výrazu.
-code_search_results=`Výsledky hledání pro "%s"`
+code_search_results=Výsledky hledání pro „%s“
code_last_indexed_at=Naposledy indexováno %s
relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty.
relevant_repositories=Zobrazují se pouze relevantní repositáře, zobrazit nefiltrované výsledky .
@@ -347,9 +361,11 @@ disable_register_prompt=Registrace jsou vypnuty. Prosíme, kontaktujte správce
disable_register_mail=E-mailové potvrzení o registraci je zakázané.
manual_activation_only=Pro dokončení aktivace kontaktujte správce webu.
remember_me=Pamatovat si toto zařízení
+remember_me.compromised=Přihlašovací token již není platný, což může znamenat napadení účtu. Zkontrolujte prosím svůj účet pro neobvyklé aktivity.
forgot_password_title=Zapomenuté heslo
forgot_password=Zapomenuté heslo?
sign_up_now=Potřebujete účet? Zaregistrujte se.
+sign_up_successful=Účet byl úspěšně vytvořen. Vítejte!
confirmation_mail_sent_prompt=Na adresu %s byl zaslán nový potvrzovací e-mail. Zkontrolujte prosím vaši doručenou poštu během následujících %s, abyste dokončili proces registrace.
must_change_password=Aktualizujte své heslo
allow_password_change=Vyžádat od uživatele změnu hesla (doporučeno)
@@ -357,6 +373,7 @@ reset_password_mail_sent_prompt=Na adresu %s byl zaslán potvrzovací e-m
active_your_account=Aktivujte si váš účet
account_activated=Účet byl aktivován
prohibit_login=Přihlášení zakázáno
+prohibit_login_desc=Vašemu účtu je zakázáno se přihlásit, kontaktujte prosím správce webu.
resent_limit_prompt=Omlouváme se, ale před chvílí jste požádal o zaslání aktivačního e-mailu. Počkejte prosím 3 minuty a pak to zkuste znovu.
has_unconfirmed_mail=Zdravím, %s, máte nepotvrzenou e-mailovou adresu (%s ). Pokud jste nedostali e-mail pro potvrzení nebo potřebujete zaslat nový, klikněte prosím na tlačítku níže.
resend_mail=Klikněte zde pro odeslání aktivačního e-mailu
@@ -364,8 +381,10 @@ email_not_associate=Tato e-mailová adresa není spojena s žádným účtem.
send_reset_mail=Zaslat e-mail pro obnovení účtu
reset_password=Obnovení účtu
invalid_code=Tento potvrzující kód je neplatný nebo mu vypršela platnost.
+invalid_code_forgot_password=Váš potvrzovací kód je neplatný nebo mu vypršela platnost. Klikněte zde pro vytvoření nového kódu.
invalid_password=Vaše heslo se neshoduje s heslem, které bylo použito k vytvoření účtu.
reset_password_helper=Obnovit účet
+reset_password_wrong_user=Jste přihlášen/a jako %s, ale odkaz pro obnovení účtu je pro %s
password_too_short=Délka hesla musí být minimálně %d znaků.
non_local_account=Externě ověřovaní uživatelé nemohou aktualizovat své heslo prostřednictvím webového rozhraní Gitea.
verify=Ověřit
@@ -390,6 +409,7 @@ openid_connect_title=Připojení k existujícímu účtu
openid_connect_desc=Zvolené OpenID URI není známé. Přidružte nový účet zde.
openid_register_title=Vytvořit nový účet
openid_register_desc=Zvolené OpenID URI není známé. Přidružte nový účet zde.
+openid_signin_desc=Zadejte vaši OpenID URI. Například: alice.openid.example.org nebo https://openid.example.org/alice.
disable_forgot_password_mail=Obnovení účtu je zakázáno, protože není nastaven žádný e-mail. Obraťte se na správce webu.
disable_forgot_password_mail_admin=Obnovení účtu je dostupné pouze po nastavení e-mailu. Pro povolení obnovy účtu nastavte prosím e-mail.
email_domain_blacklisted=Nemůžete se registrovat s vaší e-mailovou adresou.
@@ -399,7 +419,9 @@ authorize_application_created_by=Tuto aplikaci vytvořil %s.
authorize_application_description=Pokud povolíte přístup, bude moci přistupovat a zapisovat do všech vašich informací o účtu včetně soukromých repozitářů a organizací.
authorize_title=Autorizovat „%s“ pro přístup k vašemu účtu?
authorization_failed=Autorizace selhala
+authorization_failed_desc=Autorizace selhala, protože jsme detekovali neplatný požadavek. Kontaktujte prosím správce aplikace, kterou jste se pokoušeli autorizovat.
sspi_auth_failed=SSPI autentizace selhala
+password_pwned=Heslo, které jste zvolili, je na seznamu odcizených hesel , která byla dříve odhalena při narušení veřejných dat. Zkuste to prosím znovu s jiným heslem.
password_pwned_err=Nelze dokončit požadavek na HaveIBeenPwned
[mail]
@@ -414,6 +436,7 @@ activate_account.text_1=Ahoj %[1]s , děkujeme za registraci na %[2]s!
activate_account.text_2=Pro aktivaci vašeho účtu do %s klikněte na následující odkaz:
activate_email=Ověřte vaši e-mailovou adresu
+activate_email.title=%s, prosím ověřte vaši e-mailovou adresu
activate_email.text=Pro aktivaci vašeho účtu do %s klikněte na následující odkaz:
register_notify=Vítejte v Gitea
@@ -509,6 +532,7 @@ url_error=`„%s“ není platná adresa URL.`
include_error=` musí obsahovat substring „%s“.`
glob_pattern_error=`zástupný vzor je neplatný: %s.`
regex_pattern_error=` regex vzor je neplatný: %s.`
+username_error=` může obsahovat pouze alfanumerické znaky („0-9“, „a-z“, „A-Z“), pomlčku („-“), podtržítka („_“) a tečka („.“). Nemůže začínat nebo končit nealfanumerickými znaky a po sobě jdoucí nealfanumerické znaky jsou také zakázány.`
invalid_group_team_map_error=` mapování je neplatné: %s`
unknown_error=Neznámá chyba:
captcha_incorrect=CAPTCHA kód není správný.
@@ -553,13 +577,21 @@ invalid_ssh_key=Nelze ověřit váš SSH klíč: %s
invalid_gpg_key=Nelze ověřit váš GPG klíč: %s
invalid_ssh_principal=Neplatný SSH Principal certifikát: %s
must_use_public_key=Zadaný klíč je soukromý klíč. Nenahrávejte svůj soukromý klíč nikde. Místo toho použijte váš veřejný klíč.
+unable_verify_ssh_key=Nelze ověřit váš SSH klíč.
auth_failed=Ověření selhalo: %v
+still_own_repo=Váš účet vlastní jeden nebo více repozitářů. Nejprve je smažte nebo převeďte.
+still_has_org=Váš účet je členem jedné nebo více organizací. Nejdříve je musíte opustit.
+still_own_packages=Váš účet vlastní jeden nebo více balíčků. Nejprve je musíte odstranit.
+org_still_own_repo=Organizace stále vlastní jeden nebo více repozitářů. Nejdříve je smažte nebo převeďte.
+org_still_own_packages=Organizace stále vlastní jeden nebo více balíčků. Nejdříve je smažte.
target_branch_not_exist=Cílová větev neexistuje.
+
[user]
change_avatar=Změnit váš avatar…
+joined_on=Přidal/a se %s
repositories=Repozitáře
activity=Veřejná aktivita
followers=Sledující
@@ -575,10 +607,12 @@ user_bio=Životopis
disabled_public_activity=Tento uživatel zakázal veřejnou viditelnost aktivity.
email_visibility.limited=Vaše e-mailová adresa je viditelná pro všechny ověřené uživatele
email_visibility.private=Vaše e-mailová adresa je viditelná pouze pro vás a administrátory
+show_on_map=Zobrazit toto místo na mapě
+settings=Uživatelská nastavení
-form.name_reserved=Uživatelské jméno "%s" je rezervováno.
-form.name_pattern_not_allowed=Vzor "%s" není povolen v uživatelském jméně.
-form.name_chars_not_allowed=Uživatelské jméno "%s" obsahuje neplatné znaky.
+form.name_reserved=Uživatelské jméno „%s“ je rezervováno.
+form.name_pattern_not_allowed=Vzor „%s“ není povolen v uživatelském jméně.
+form.name_chars_not_allowed=Uživatelské jméno „%s“ obsahuje neplatné znaky.
[settings]
profile=Profil
@@ -596,9 +630,13 @@ delete=Smazat účet
twofa=Dvoufaktorové ověřování
account_link=Propojené účty
organization=Organizace
+uid=UID
webauthn=Bezpečnostní klíče
public_profile=Veřejný profil
+biography_placeholder=Řekněte nám něco o sobě! (Můžete použít Markdown)
+location_placeholder=Sdílejte svou přibližnou polohu s ostatními
+profile_desc=Nastavte, jak bude váš profil zobrazen ostatním uživatelům. Vaše hlavní e-mailová adresa bude použita pro oznámení, obnovení hesla a operace Git.
password_username_disabled=Externí uživatelé nemohou měnit svoje uživatelské jméno. Kontaktujte prosím svého administrátora pro více detailů.
full_name=Celé jméno
website=Web
@@ -606,15 +644,20 @@ location=Místo
update_theme=Aktualizovat motiv vzhledu
update_profile=Aktualizovat profil
update_language=Aktualizovat jazyk
-update_language_not_found=Jazyk "%s" není k dispozici.
+update_language_not_found=Jazyk „%s“ není k dispozici.
update_language_success=Jazyk byl aktualizován.
update_profile_success=Váš profil byl aktualizován.
change_username=Vaše uživatelské jméno bylo změněno.
+change_username_prompt=Poznámka: Změna uživatelského jména také změní URL vašeho účtu.
+change_username_redirect_prompt=Staré uživatelské jméno bude přesměrováváno, dokud nebude znovu obsazeno.
continue=Pokračovat
cancel=Zrušit
language=Jazyk
ui=Motiv vzhledu
hidden_comment_types=Skryté typy komentářů
+hidden_comment_types_description=Zde zkontrolované typy komentářů nebudou zobrazeny na stránkách problémů. Zaškrtnutí „Štítek“ například odstraní všechny komentáře „ přidal/odstranil “.
+hidden_comment_types.ref_tooltip=Komentáře, na které se odkazovalo z jiného úkolu/commitu/…
+hidden_comment_types.issue_ref_tooltip=Komentáře, kde uživatel změní větev/značku spojenou s problémem
comment_type_group_reference=Reference
comment_type_group_label=Štítek
comment_type_group_milestone=Milník
@@ -631,6 +674,7 @@ comment_type_group_project=Projekt
comment_type_group_issue_ref=Referenční číslo úkolu
saved_successfully=Vaše nastavení bylo úspěšně uloženo.
privacy=Soukromí
+keep_activity_private=Skrýt aktivitu z profilové stránky
keep_activity_private_popup=Učinit aktivitu viditelnou pouze pro vás a administrátory
lookup_avatar_by_mail=Vyhledat avatar pomocí e-mailové adresy
@@ -640,12 +684,14 @@ choose_new_avatar=Vybrat nový avatar
update_avatar=Aktualizovat avatar
delete_current_avatar=Smazat aktuální avatar
uploaded_avatar_not_a_image=Nahraný soubor není obrázek.
+uploaded_avatar_is_too_big=Nahraný soubor (%d KiB) přesahuje maximální velikost (%d KiB).
update_avatar_success=Vaše avatar byl aktualizován.
update_user_avatar_success=Uživatelův avatar byl aktualizován.
change_password=Aktualizovat heslo
old_password=Stávající heslo
new_password=Nové heslo
+retype_new_password=Potvrdit nové heslo
password_incorrect=Zadané heslo není správné.
change_password_success=Vaše heslo bylo aktualizováno. Od teď se přihlašujte novým heslem.
password_change_disabled=Externě ověřovaní uživatelé nemohou aktualizovat své heslo prostřednictvím webového rozhraní Gitea.
@@ -654,6 +700,7 @@ emails=E-mailová adresa
manage_emails=Správa e-mailových adres
manage_themes=Vyberte výchozí motiv vzhledu
manage_openid=Správa OpenID adres
+email_desc=Vaše hlavní e-mailová adresa bude použita pro oznámení, obnovení hesla, a pokud není skrytá, pro operace Gitu.
theme_desc=Toto bude váš výchozí motiv vzhledu napříč stránkou.
primary=Hlavní
activated=Aktivován
@@ -661,6 +708,7 @@ requires_activation=Vyžaduje aktivaci
primary_email=Nastavit jako hlavní
activate_email=Odeslat aktivaci
activations_pending=Čekající aktivace
+can_not_add_email_activations_pending=Existuje čekající aktivace, zkuste to znovu za pár minut, pokud chcete přidat nový e-mail.
delete_email=Smazat
email_deletion=Odstranit e-mailovou adresu
email_deletion_desc=E-mailová adresa a přidružené informace budou z vašeho účtu odstraněny. Commity Gitu s touto e-mailovou adresou zůstanou nezměněny. Pokračovat?
@@ -674,10 +722,12 @@ add_new_email=Přidat novou e-mailovou adresu
add_new_openid=Přidat novou OpenID URI
add_email=Přidat e-mailovou adresu
add_openid=Přidat OpenID URI
+add_email_confirmation_sent=Potvrzovací e-mail byl odeslán na „%s“. Prosím zkontrolujte příchozí poštu během následujících %s pro potvrzení vaší e-mailové adresy.
add_email_success=Nová e-mailová adresa byla přidána.
email_preference_set_success=Nastavení e-mailu bylo úspěšně nastaveno.
add_openid_success=Nová OpenID adresa byla přidána.
keep_email_private=Schovat e-mailovou adresu
+keep_email_private_popup=Toto skryje vaši e-mailovou adresu z vašeho profilu, stejně jako při vytvoření pull requestu nebo úpravě souboru pomocí webového rozhraní. Odeslané commity nebudou změněny. Použijte %s v commitech pro jejich přiřazení k vašemu účtu.
openid_desc=OpenID vám umožní delegovat ověřování na externího poskytovatele.
manage_ssh_keys=Správa klíčů SSH
@@ -711,7 +761,7 @@ gpg_token_help=Podpis můžete vygenerovat pomocí:
gpg_token_code=echo "%s" | gpg -a --default-key %s --detach-sig
gpg_token_signature=Zakódovaný podpis GPG
key_signature_gpg_placeholder=Začíná s „-----BEGIN PGP SIGNATURE-----“
-verify_gpg_key_success=GPG klíč "%s" byl ověřen.
+verify_gpg_key_success=GPG klíč „%s“ byl ověřen.
ssh_key_verified=Ověřený klíč
ssh_key_verified_long=Klíč byl ověřen pomocí tokenu a může být použit k ověření commitů shodujících se s libovolnou vaší aktivovanou e-mailovou adresou pro tohoto uživatele.
ssh_key_verify=Ověřit
@@ -721,14 +771,15 @@ ssh_token=Token
ssh_token_help=Podpis můžete vygenerovat pomocí:
ssh_token_signature=Zakódovaný podpis SSH
key_signature_ssh_placeholder=Začíná s „-----BEGIN SSH SIGNATURE-----“
-verify_ssh_key_success=SSH klíč "%s" byl ověřen.
+verify_ssh_key_success=SSH klíč „%s“ byl ověřen.
subkeys=Podklíče
key_id=ID klíče
key_name=Název klíče
key_content=Obsah
principal_content=Obsah
-add_key_success=SSH klíč "%s" byl přidán.
-add_gpg_key_success=GPG klíč "%s" byl přidán.
+add_key_success=SSH klíč „%s“ byl přidán.
+add_gpg_key_success=GPG klíč „%s“ byl přidán.
+add_principal_success=Byl přidán SSH Principal certifikát „%s“.
delete_key=Odstranit
ssh_key_deletion=Odstraňte SSH klíč
gpg_key_deletion=Odstraňte GPG klíč
@@ -755,7 +806,9 @@ ssh_disabled=SSH zakázáno
ssh_signonly=SSH je v současné době zakázáno, proto jsou tyto klíče použity pouze pro ověření podpisu.
ssh_externally_managed=Tento SSH klíč je spravován externě pro tohoto uživatele
manage_social=Správa propojených účtů sociálních sítí
+social_desc=Tyto účty sociálních sítí lze použít k přihlášení k vašemu účtu. Ujistěte se, že jsou všechny vaše.
unbind=Odpojit
+unbind_success=Účet sociální sítě byl úspěšně odstraněn.
manage_access_token=Spravovat přístupové tokeny
generate_new_token=Vygenerovat nový token
@@ -776,6 +829,7 @@ permissions_access_all=Vše (veřejné, soukromé a omezené)
select_permissions=Vyberte oprávnění
permission_no_access=Bez přístupu
permission_read=Přečtené
+permission_write=čtení i zápis
at_least_one_permission=Musíte vybrat alespoň jedno oprávnění pro vytvoření tokenu
permissions_list=Oprávnění:
@@ -787,6 +841,8 @@ remove_oauth2_application_desc=Odstraněním OAuth2 aplikace odeberete přístup
remove_oauth2_application_success=Aplikace byla odstraněna.
create_oauth2_application=Vytvořit novou OAuth2 aplikaci
create_oauth2_application_button=Vytvořit aplikaci
+create_oauth2_application_success=Úspěšně jste vytvořili novou OAuth2 aplikaci.
+update_oauth2_application_success=Úspěšně jste aktualizovali OAuth2 aplikaci.
oauth2_application_name=Název aplikace
oauth2_confidential_client=Důvěrný klient. Vyberte aplikace, které zachovávají důvěrnosti v utajení, jako jsou webové aplikace. Nevybírejte pro nativní aplikace včetně stolních a mobilních aplikací.
oauth2_redirect_uris=Přesměrování URI. Použijte nový řádek pro každou URI.
@@ -795,19 +851,26 @@ oauth2_client_id=ID klienta
oauth2_client_secret=Tajný klíč klienta
oauth2_regenerate_secret=Obnovit tajný klíč
oauth2_regenerate_secret_hint=Ztratili jste svůj tajný klíč?
+oauth2_client_secret_hint=Tajný klíč se znovu nezobrazí po opuštění nebo obnovení této stránky. Ujistěte se, že jste si jej uložili.
oauth2_application_edit=Upravit
oauth2_application_create_description=OAuth2 aplikace poskytuje přístup aplikacím třetích stran k uživatelským účtům na této instanci.
+oauth2_application_remove_description=Odebráním OAuth2 aplikace zabrání přístupu ověřeným uživatelům na této instanci. Pokračovat?
+oauth2_application_locked=Gitea předregistruje některé OAuth2 aplikace při spuštění, pokud je to povoleno v konfiguraci. Aby se zabránilo neočekávanému chování, nelze je upravovat ani odstranit. Více informací naleznete v dokumentaci OAuth2.
authorized_oauth2_applications=Autorizovat OAuth2 aplikaci
+authorized_oauth2_applications_description=Úspěšně jste povolili přístup k vašemu osobnímu účtu této aplikaci třetí strany. Zrušte prosím přístup aplikacím, které již nadále nepotřebujete.
revoke_key=Zrušit
revoke_oauth2_grant=Zrušit přístup
revoke_oauth2_grant_description=Zrušením přístupu této aplikaci třetí strany ji zabráníte v přístupu k vašim datům. Jste si jisti?
+revoke_oauth2_grant_success=Přístup byl úspěšně zrušen.
twofa_desc=Dvoufaktorový způsob ověřování zvýší zabezpečení vašeho účtu.
+twofa_recovery_tip=Pokud ztratíte své zařízení, budete moci použít jednorázový obnovovací klíč k získání přístupu k vašemu účtu.
twofa_is_enrolled=Váš účet aktuálně používá dvoufaktorové ověřování.
twofa_not_enrolled=Váš účet aktuálně nepoužívá dvoufaktorové ověřování.
twofa_disable=Zakázat dvoufaktorové ověřování
twofa_scratch_token_regenerate=Obnovit pomocný token
+twofa_scratch_token_regenerated=Váš jednorázový obnovovací klíč je nyní %s. Uložte jej na bezpečném místě, protože se znovu nezobrazí.
twofa_enroll=Povolit dvoufaktorové ověřování
twofa_disable_note=Dvoufaktorové ověřování můžete zakázat, když bude potřeba.
twofa_disable_desc=Zakážete-li dvoufaktorové ověřování, bude váš účet méně zabezpečený. Pokračovat?
@@ -825,6 +888,8 @@ webauthn_register_key=Přidat bezpečnostní klíč
webauthn_nickname=Přezdívka
webauthn_delete_key=Odstranit bezpečnostní klíč
webauthn_delete_key_desc=Pokud odstraníte bezpečnostní klíč, již se s ním nebudete moci přihlásit. Pokračovat?
+webauthn_key_loss_warning=Pokud ztratíte své bezpečnostní klíče, ztratíte přístup k vašemu účtu.
+webauthn_alternative_tip=Možná budete chtít nakonfigurovat další metodu ověřování.
manage_account_links=Správa propojených účtů
manage_account_links_desc=Tyto externí účty jsou propojeny s vaším Gitea účtem.
@@ -834,8 +899,10 @@ remove_account_link=Odstranit propojený účet
remove_account_link_desc=Odstraněním propojeného účtu zrušíte jeho přístup k vašemu Gitea účtu. Pokračovat?
remove_account_link_success=Propojený účet byl odstraněn.
+hooks.desc=Přidat webhooky, které budou spouštěny pro všechny repozitáře vve vašem vlastnictví.
orgs_none=Nejste členem žádné organizace.
+repos_none=Nevlastníte žádné repozitáře.
delete_account=Smazat váš účet
delete_prompt=Tato operace natrvalo odstraní váš uživatelský účet. NELZE ji vrátit zpět.
@@ -854,9 +921,12 @@ visibility=Viditelnost uživatele
visibility.public=Veřejný
visibility.public_tooltip=Viditelné pro všechny
visibility.limited=Omezený
+visibility.limited_tooltip=Viditelné pouze pro ověřené uživatele
visibility.private=Soukromý
+visibility.private_tooltip=Viditelné pouze pro členy organizací, ke kterým jste se připojili
[repo]
+new_repo_helper=Repozitář obsahuje všechny projektové soubory, včetně historie revizí. Už jej hostujete jinde? Migrovat repozitář.
owner=Vlastník
owner_helper=Některé organizace se nemusejí v seznamu zobrazit kvůli maximálnímu dosaženému počtu repozitářů.
repo_name=Název repozitáře
@@ -868,6 +938,7 @@ template_helper=Z repozitáře vytvořit šablonu
template_description=Šablony repozitářů umožňují uživatelům generovat nové repositáře se stejnou strukturou, soubory a volitelnými nastaveními.
visibility=Viditelnost
visibility_description=Pouze majitelé nebo členové organizace to budou moci vidět, pokud mají práva.
+visibility_helper=Nastavit repozitář jako soukromý
visibility_helper_forced=Váš administrátor vynutil, že nové repozitáře budou soukromé.
visibility_fork_helper=(Změna tohoto ovlivní všechny rozštěpení repozitáře.)
clone_helper=Potřebujete pomoci s klonováním? Navštivte nápovědu .
@@ -876,6 +947,9 @@ fork_from=Rozštěpit z
already_forked=Již jsi rozštěpil %s
fork_to_different_account=Rozštěpit na jiný účet
fork_visibility_helper=Viditelnost rozštěpeného repozitáře nemůže být změněna.
+fork_branch=Větev, která má být klonována pro fork
+all_branches=Všechny větve
+fork_no_valid_owners=Tento repozitář nemůže být rozštěpen, protože neexistují žádní platní vlastníci.
use_template=Použít tuto šablonu
clone_in_vsc=Klonovat ve VS Code
download_zip=Stáhnout ZIP
@@ -904,6 +978,7 @@ trust_model_helper_collaborator_committer=Spolupracovník+Přispěvatel: Důvě
trust_model_helper_default=Výchozí: Použít výchozí model důvěry pro tuto instalaci
create_repo=Vytvořit repozitář
default_branch=Výchozí větev
+default_branch_label=výchozí
default_branch_helper=Výchozí větev je základní větev pro požadavky na natažení a commity kódu.
mirror_prune=Vyčistit
mirror_prune_desc=Odstranit zastaralé reference na vzdálené sledování
@@ -912,6 +987,8 @@ mirror_interval_invalid=Interval zrcadlení není platný.
mirror_sync_on_commit=Synchronizovat při nahrávání revizí
mirror_address=Klonovat z URL
mirror_address_desc=Zadejte požadované přístupové údaje do sekce Ověření.
+mirror_address_url_invalid=Poskytnutá URL je neplatná. Všechny části musíte správně nahradit escape sekvencí.
+mirror_address_protocol_invalid=Zadaná URL je neplatná. Mohou být zrcadleny pouze umístění http(s):// nebo git://.
mirror_lfs=Úložiště velkých souborů (LFS)
mirror_lfs_desc=Aktivovat zrcadlení dat LFS.
mirror_lfs_endpoint=Koncový bod LFS
@@ -937,13 +1014,19 @@ delete_preexisting=Odstranit již existující soubory
delete_preexisting_content=Odstranit soubory v %s
delete_preexisting_success=Smazány nepřijaté soubory v %s
blame_prior=Zobrazit blame před touto změnou
+blame.ignore_revs.failed=Nepodařilo se ignorovat revize v .git-blame-ignore-revs .
author_search_tooltip=Zobrazí maximálně 30 uživatelů
+tree_path_not_found_commit=Cesta %[1]s v commitu %[2]s neexistuje
+tree_path_not_found_branch=Cesta %[1]s ve větvi %[2]s neexistuje
+tree_path_not_found_tag=Cesta %[1]s ve značce %[2]s neexistuje
transfer.accept=Přijmout převod
transfer.accept_desc=Převést do „%s“
transfer.reject=Odmítnout převod
transfer.reject_desc=Zrušit převod do „%s“
+transfer.no_permission_to_accept=Nemáte oprávnění k přijetí tohoto převodu.
+transfer.no_permission_to_reject=Nemáte oprávnění k odmítnutí tohoto převodu.
desc.private=Soukromý
desc.public=Veřejný
@@ -962,12 +1045,15 @@ template.issue_labels=Štítky úkolů
template.one_item=Musíte vybrat alespoň jednu položku šablony
template.invalid=Musíte vybrat repositář šablony
+archive.title=Tento repozitář je archivovaný. Můžete prohlížet soubory, klonovat, ale nemůžete nahrávat a vytvářet nové úkoly nebo požadavky na natažení.
+archive.title_date=Tento repositář byl archivován %s. Můžete zobrazit soubory a klonovat je, ale nemůžete nahrávat ani otevírat problémy nebo požadavky na natažení.
archive.issue.nocomment=Tento repozitář je archivovaný. Nemůžete komentovat úkoly.
archive.pull.nocomment=Tento repozitář je archivovaný. Nemůžete komentovat požadavky na natažení.
form.reach_limit_of_creation_1=Již jste dosáhli svůj limit %d repozitář.
form.reach_limit_of_creation_n=Již jste dosáhli svůj limit %d repozitářů.
form.name_reserved=Název repozitáře „%s“ je rezervován.
+form.name_pattern_not_allowed=Vzor „%s“ není povolený v názvu repozitáře.
need_auth=Ověření
migrate_options=Možnosti migrace
@@ -977,6 +1063,7 @@ migrate_options_lfs=Migrovat LFS soubory
migrate_options_lfs_endpoint.label=Koncový bod LFS
migrate_options_lfs_endpoint.description=Migrace se pokusí použít váš vzdálený Git pro určení LFS serveru . Můžete také zadat vlastní koncový bod, pokud jsou data LFS repozitáře uložena někde jinde.
migrate_options_lfs_endpoint.description.local=Podporována je také cesta k lokálnímu serveru.
+migrate_options_lfs_endpoint.placeholder=Ponecháte-li prázdné, koncový bod bude odvozen z adresy URL klonu
migrate_items=Položky pro migrování
migrate_items_wiki=Wiki
migrate_items_milestones=Milníky
@@ -992,6 +1079,7 @@ migrate.github_token_desc=Můžete sem vložit jeden nebo více tokenů oddělen
migrate.clone_local_path=nebo místní cesta serveru
migrate.permission_denied=Není dovoleno importovat místní repozitáře.
migrate.permission_denied_blocked=Nelze importovat z nepovolených hostitelů, prosím požádejte správce, aby zkontroloval nastavení ALLOWED_DOMAINS/ALLOW_LOCALETWORKS/BLOCKED_DOMAINS.
+migrate.invalid_local_path=Místní cesta je neplatná, buď neexistuje nebo není adresářem.
migrate.invalid_lfs_endpoint=Koncový bod LFS není platný.
migrate.failed=Přenesení selhalo: %v
migrate.migrate_items_options=Pro migraci dalších položek je vyžadován přístupový token
@@ -1069,6 +1157,7 @@ release=Vydání
releases=Vydání
tag=Značka
released_this=vydal/a toto
+tagged_this=označil/a
file.title=%s v %s
file_raw=Surový
file_history=Historie
@@ -1077,6 +1166,10 @@ file_view_rendered=Zobrazit vykreslené
file_view_raw=Zobrazit v surovém stavu
file_permalink=Trvalý odkaz
file_too_large=Soubor je příliš velký pro zobrazení.
+invisible_runes_header=`Tento soubor obsahuje neviditelné znaky Unicode`
+invisible_runes_description=`Tento soubor obsahuje neviditelné Unicode znaky, které jsou pro člověka nerozeznatelné, ale mohou být zpracovány jiným způsobem. Pokud si myslíte, že je to záměrné, můžete toto varování bezpečně ignorovat. Použijte tlačítko Escape sekvence k jejich zobrazení.`
+ambiguous_runes_header=`Tento soubor obsahuje nejednoznačné znaky Unicode`
+ambiguous_runes_description=`Tento soubor obsahuje znaky Unicode, které mohou být zaměněny s jinými znaky. Pokud si myslíte, že je to záměrné, můžete toto varování bezpečně ignorovat. Použijte tlačítko Escape sekvence k jejich zobrazení.`
invisible_runes_line=`Tento řádek má neviditelné znaky Unicode`
ambiguous_runes_line=`Tento řádek má nejednoznačné znaky Unicode`
ambiguous_character=`%[1]c [U+%04[1]X] je zaměnitelný s %[2]c [U+%04[2]X]`
@@ -1089,11 +1182,15 @@ video_not_supported_in_browser=Váš prohlížeč nepodporuje značku pro HTML5
audio_not_supported_in_browser=Váš prohlížeč nepodporuje značku pro HTML5 audio.
stored_lfs=Uloženo pomocí Git LFS
symbolic_link=Symbolický odkaz
+executable_file=Spustitelný soubor
commit_graph=Graf commitů
commit_graph.select=Vybrat větve
commit_graph.hide_pr_refs=Skrýt požadavky na natažení
commit_graph.monochrome=Černobílé
commit_graph.color=Barva
+commit.contained_in=Tento commit je obsažen v:
+commit.contained_in_default_branch=Tento commit je součástí výchozí větve
+commit.load_referencing_branches_and_tags=Načíst větve a značky odkazující na tento commit
blame=Blame
download_file=Stáhnout soubor
normal_view=Normální zobrazení
@@ -1127,6 +1224,7 @@ editor.update=Aktualizovat %s
editor.delete=Odstranit %s
editor.patch=Použít záplatu
editor.patching=Záplatování:
+editor.fail_to_apply_patch=Nelze použít záplatu „%s“
editor.new_patch=Nová záplata
editor.commit_message_desc=Přidat volitelný rozšířený popis…
editor.signoff_desc=Přidat Signed-off-by podpis přispěvatele na konec zprávy o commitu.
@@ -1141,7 +1239,13 @@ editor.filename_cannot_be_empty=Jméno nemůže být prázdné.
editor.filename_is_invalid=Název souboru je neplatný: „%s“.
editor.branch_does_not_exist=Větev „%s“ v tomto repozitáři neexistuje.
editor.branch_already_exists=Větev „%s“ již existuje v tomto repozitáři.
+editor.directory_is_a_file=Jméno adresáře „%s“ je již použito jako jméno souboru v tomto repozitáři.
+editor.file_is_a_symlink=`„%s“ je symbolický odkaz. Symbolické odkazy nemohou být upravovány ve webovém editoru`
+editor.filename_is_a_directory=Jméno souboru „%s“ je již použito jako jméno adresáře v tomto repozitáři.
+editor.file_editing_no_longer_exists=Upravovaný soubor „%s“ již není součástí tohoto repozitáře.
+editor.file_deleting_no_longer_exists=Odstraňovaný soubor „%s“ již není součástí tohoto repozitáře.
editor.file_changed_while_editing=Obsah souboru byl změněn od doby, kdy jste začaly s úpravou. Klikněte zde , abyste je zobrazili, nebo potvrďte změny ještě jednou pro jejich přepsání.
+editor.file_already_exists=Soubor „%s“ již existuje v tomto repozitáři.
editor.commit_empty_file_header=Odevzdat prázdný soubor
editor.commit_empty_file_text=Soubor, který se chystáte odevzdat, je prázdný. Pokračovat?
editor.no_changes_to_show=Žádné změny k zobrazení.
@@ -1163,8 +1267,10 @@ editor.revert=Vrátit %s na:
commits.desc=Procházet historii změn zdrojového kódu.
commits.commits=Commity
+commits.no_commits=Žádné společné commity. „%s“ a „%s“ mají zcela odlišnou historii.
commits.nothing_to_compare=Tyto větve jsou stejné.
commits.search=Hledání commitů…
+commits.search.tooltip=Můžete předřadit klíčová slova s „author:“, „committer:“, „after:“ nebo „before:“, např. „revert author:Alice before:2019-01-03“.
commits.find=Vyhledat
commits.search_all=Všechny větve
commits.author=Autor
@@ -1177,6 +1283,7 @@ commits.signed_by_untrusted_user=Podepsáno nedůvěryhodným uživatelem
commits.signed_by_untrusted_user_unmatched=Podepsáno nedůvěryhodným uživatelem, který nesouhlasí s přispěvatelem
commits.gpg_key_id=ID GPG klíče
commits.ssh_key_fingerprint=Otisk klíče SSH
+commits.view_path=Zobrazit v tomto bodě v historii
commit.operations=Operace
commit.revert=Vrátit
@@ -1202,12 +1309,14 @@ projects.create=Vytvořit projekt
projects.title=Název
projects.new=Nový projekt
projects.new_subheader=Koordinujte, sledujte a aktualizujte svou práci na jednom místě, aby projekty zůstaly transparentní a v plánu.
+projects.create_success=Projekt „%s“ byl vytvořen.
projects.deletion=Odstranit projekt
projects.deletion_desc=Odstranění projektu jej odstraní ze všech souvisejících úkolů. Pokračovat?
projects.deletion_success=Projekt byl odstraněn.
projects.edit=Upravit projekty
projects.edit_subheader=Projekty organizují úkoly a sledují pokrok.
projects.modify=Aktualizovat projekt
+projects.edit_success=Projekt „%s“ byl aktualizován.
projects.type.none=Žádný
projects.type.basic_kanban=Základní Kanban
projects.type.bug_triage=Třídění chyb
@@ -1233,7 +1342,7 @@ projects.card_type.desc=Náhledy karet
projects.card_type.images_and_text=Obrázky a text
projects.card_type.text_only=Pouze text
-issues.desc=Organizování hlášení chyb, úkolů a milníků.
+issues.desc=Organizování hlášení chyb, úloh a milníků.
issues.filter_assignees=Filtrovat zpracovatele
issues.filter_milestones=Filtrovat milník
issues.filter_projects=Filtrovat projekt
@@ -1265,6 +1374,7 @@ issues.choose.blank=Výchozí
issues.choose.blank_about=Vytvořit úkol z výchozí šablony.
issues.choose.ignore_invalid_templates=Neplatné šablony byly ignorovány
issues.choose.invalid_templates=%v nalezených neplatných šablon
+issues.choose.invalid_config=Nastavení problému obsahuje chyby:
issues.no_ref=Není určena žádná větev/značka
issues.create=Vytvořit úkol
issues.new_label=Nový štítek
@@ -1301,6 +1411,7 @@ issues.delete_branch_at=`odstranil/a větev %s %s`
issues.filter_label=Štítek
issues.filter_label_exclude=`Chcete-li vyloučit štítky, použijte alt
+ click/enter
`
issues.filter_label_no_select=Všechny štítky
+issues.filter_label_select_no_label=Bez štítku
issues.filter_milestone=Milník
issues.filter_milestone_all=Všechny milníky
issues.filter_milestone_none=Žádné milníky
@@ -1334,6 +1445,7 @@ issues.filter_sort.moststars=Nejvíce hvězdiček
issues.filter_sort.feweststars=Nejméně hvězdiček
issues.filter_sort.mostforks=Nejvíce rozštěpení
issues.filter_sort.fewestforks=Nejméně rozštěpení
+issues.keyword_search_unavailable=Hledání podle klíčového slova není momentálně dostupné. Obraťte se na správce webu.
issues.action_open=Otevřít
issues.action_close=Zavřít
issues.action_label=Štítek
@@ -1354,6 +1466,7 @@ issues.next=Další
issues.open_title=otevřený
issues.closed_title=zavřený
issues.draft_title=Koncept
+issues.num_comments_1=%d komentář
issues.num_comments=%d komentářů
issues.commented_at=`okomentoval %s `
issues.delete_comment_confirm=Jste si jist, že chcete smazat tento komentář?
@@ -1362,7 +1475,9 @@ issues.context.quote_reply=Citovat odpověď
issues.context.reference_issue=Odkázat v novém úkolu
issues.context.edit=Upravit
issues.context.delete=Smazat
+issues.no_content=K dispozici není žádný popis.
issues.close=Zavřít problém
+issues.comment_pull_merged_at=sloučený commit %[1]s do %[2]s %[3]s
issues.comment_manually_pull_merged_at=ručně sloučený commit %[1]s do %[2]s %[3]s
issues.close_comment_issue=Okomentovat a zavřít
issues.reopen_issue=Znovuotevřít
@@ -1379,8 +1494,16 @@ issues.ref_closed_from=`uzavřel/a tento úkol %[4]s znovu otevřel/a tento úkol %[4]s %[2]s `
issues.ref_from=`z %[1]s`
issues.author=Autor
+issues.author_helper=Tento uživatel je autor.
issues.role.owner=Vlastník
+issues.role.owner_helper=Tento uživatel je vlastníkem tohoto repozitáře.
issues.role.member=Člen
+issues.role.member_helper=Tento uživatel je členem organizace vlastnící tento repositář.
+issues.role.collaborator=Spolupracovník
+issues.role.collaborator_helper=Tento uživatel byl pozván ke spolupráci v repozitáři.
+issues.role.first_time_contributor_helper=Toto je první příspěvek tohoto uživatele do repozitáře.
+issues.role.contributor=Přispěvatel
+issues.role.contributor_helper=Tento uživatel již dříve přispíval do repozitáře.
issues.re_request_review=Znovu požádat o posouzení
issues.is_stale=Od tohoto posouzení došlo ke změnám v tomto požadavku na natažení
issues.remove_request_review=Odstranit žádost o posouzení
@@ -1395,6 +1518,7 @@ issues.label_title=Název štítku
issues.label_description=Popis štítku
issues.label_color=Barva štítku
issues.label_exclusive=Exkluzivní
+issues.label_archived_filter=Zobrazit archivované popisky
issues.label_count=%d štítků
issues.label_open_issues=%d otevřených úkolů
issues.label_edit=Upravit
@@ -1447,6 +1571,7 @@ issues.tracking_already_started=`Již jste spustili sledování času na %[2]s#%[3]d `
@@ -1576,6 +1712,8 @@ pulls.tab_files=Změněné soubory
pulls.reopen_to_merge=Prosíme, otevřete znovu tento požadavek na natažení, aby se provedlo sloučení.
pulls.cant_reopen_deleted_branch=Tento požadavek na natažení nemůže být znovu otevřen protože větev byla smazána.
pulls.merged=Sloučený
+pulls.merged_success=Požadavek na natažení byl úspěšně sloučen a uzavřen
+pulls.closed=Požadavek na natažení uzavřen
pulls.manually_merged=Sloučeno ručně
pulls.merged_info_text=Větev %s může být nyní odstraněna.
pulls.is_closed=Požadavek na natažení byl uzavřen.
@@ -1592,6 +1730,12 @@ pulls.is_empty=Změny na této větvi jsou již na cílové větvi. Toto bude pr
pulls.required_status_check_failed=Některé požadované kontroly nebyly úspěšné.
pulls.required_status_check_missing=Některé požadované kontroly chybí.
pulls.required_status_check_administrator=Jako administrátor stále můžete sloučit tento požadavek na natažení.
+pulls.blocked_by_approvals=Tento požadavek na natažení ještě nemá dostatek schválení. Uděleno %d z %d schválení.
+pulls.blocked_by_rejection=Tento požadavek na natažení obsahuje změny požadované oficiálním posuzovatelem.
+pulls.blocked_by_official_review_requests=Tento požadavek na natažení obsahuje oficiální žádosti o posouzení.
+pulls.blocked_by_outdated_branch=Tento požadavek na natažení je zablokován, protože je zastaralý.
+pulls.blocked_by_changed_protected_files_1=Tento požadavek na natažení je zablokován, protože mění chráněný soubor:
+pulls.blocked_by_changed_protected_files_n=Tento požadavek na natažení je zablokován, protože mění chráněné soubory:
pulls.can_auto_merge_desc=Tento požadavek na natažení může být automaticky sloučen.
pulls.cannot_auto_merge_desc=Tento požadavek na natažení nemůže být automaticky sloučen, neboť se v něm nachází konflikty.
pulls.cannot_auto_merge_helper=Pro vyřešení konfliktů proveďte ruční sloučení.
@@ -1626,6 +1770,7 @@ pulls.rebase_conflict_summary=Chybové hlášení
pulls.unrelated_histories=Sloučení selhalo: Hlavní a základní revize nesdílí společnou historii. Tip: Zkuste jinou strategii
pulls.merge_out_of_date=Sloučení selhalo: Základ byl aktualizován při generování sloučení. Tip: Zkuste to znovu.
pulls.head_out_of_date=Sloučení selhalo: Hlavní revize byla aktualizován při generování sloučení. Tip: Zkuste to znovu.
+pulls.has_merged=Chyba: Požadavek na natažení byl sloučen, nelze znovu sloučit nebo změnit cílovou větev.
pulls.push_rejected=Sloučení selhalo: Nahrání bylo zamítnuto. Zkontrolujte háčky Gitu pro tento repozitář.
pulls.push_rejected_summary=Úplná zpráva o odmítnutí
pulls.push_rejected_no_message=Sloučení se nezdařilo: Nahrání bylo odmítnuto, ale nebyla nalezena žádná vzdálená zpráva. Zkontrolujte háčky gitu pro tento repozitář
@@ -1637,13 +1782,21 @@ pulls.status_checks_failure=Některé kontroly se nezdařily
pulls.status_checks_error=Některé kontroly nahlásily chyby
pulls.status_checks_requested=Požadováno
pulls.status_checks_details=Podrobnosti
+pulls.status_checks_hide_all=Skrýt všechny kontroly
+pulls.status_checks_show_all=Zobrazit všechny kontroly
pulls.update_branch=Aktualizovat větev sloučením
pulls.update_branch_rebase=Aktualizovat větev pomocí rebase
pulls.update_branch_success=Aktualizace větve byla úspěšná
pulls.update_not_allowed=Nemáte oprávnění aktualizovat větev
pulls.outdated_with_base_branch=Tato větev je zastaralá oproti základní větvi
+pulls.close=Zavřít požadavek na natažení
pulls.closed_at=`uzavřel/a tento požadavek na natažení %[2]s `
pulls.reopened_at=`znovuotevřel/a tento požadavek na natažení %[2]s `
+pulls.cmd_instruction_hint=`Zobrazit instrukce příkazové řádky .`
+pulls.cmd_instruction_checkout_desc=Z vašeho repositáře projektu se podívejte na novou větev a vyzkoušejte změny.
+pulls.cmd_instruction_merge_title=Sloučit
+pulls.cmd_instruction_merge_desc=Slučte změny a aktualizujte je na Gitea.
+pulls.clear_merge_message=Vymazat zprávu o sloučení
pulls.auto_merge_button_when_succeed=(Když kontroly uspějí)
pulls.auto_merge_when_succeed=Automaticky sloučit, když všechny kontroly uspějí
@@ -1661,9 +1814,11 @@ pulls.delete.title=Odstranit tento požadavek na natažení?
pulls.delete.text=Opravdu chcete tento požadavek na natažení smazat? (Tím se trvale odstraní veškerý obsah. Pokud jej hodláte archivovat, zvažte raději jeho uzavření.)
+pull.deleted_branch=(odstraněno):%s
milestones.new=Nový milník
milestones.closed=Zavřen dne %s
+milestones.update_ago=Aktualizováno %s
milestones.no_due_date=Bez lhůty dokončení
milestones.open=Otevřít
milestones.close=Zavřít
@@ -1674,18 +1829,35 @@ milestones.desc=Popis
milestones.due_date=Termín (volitelný)
milestones.clear=Zrušit
milestones.invalid_due_date_format=Termín dokončení musí být ve formátu 'rrrr-mm-dd'.
+milestones.create_success=Milník „%s“ byl vytvořen.
milestones.edit=Upravit milník
milestones.edit_subheader=Milník organizuje úkoly a sledují pokrok.
milestones.cancel=Zrušit
milestones.modify=Aktualizovat milník
+milestones.edit_success=Milník „%s“ byl aktualizován.
milestones.deletion=Smazat milník
milestones.deletion_desc=Odstranění milníku jej smaže ze všech souvisejících úkolů. Pokračovat?
milestones.deletion_success=Milník byl odstraněn.
+milestones.filter_sort.earliest_due_data=Nejstarší datum dokončení
+milestones.filter_sort.latest_due_date=Nejnovější datum dokončení
milestones.filter_sort.least_complete=Nejméně dokončené
milestones.filter_sort.most_complete=Nejvíce dokončené
milestones.filter_sort.most_issues=Nejvíce úkolů
milestones.filter_sort.least_issues=Nejméně úkolů
+signing.will_sign=Tento commit bude podepsána klíčem „%s“.
+signing.wont_sign.error=Došlo k chybě při kontrole, zda může být commit podepsán.
+signing.wont_sign.nokey=K podpisu tohoto commitu není k dispozici žádný klíč.
+signing.wont_sign.never=Commity nejsou nikdy podepsány.
+signing.wont_sign.always=Commity jsou vždy podepsány.
+signing.wont_sign.pubkey=Commit nebude podepsán, protože nemáte veřejný klíč spojený s vaším účtem.
+signing.wont_sign.twofa=Pro podepsání commitů musíte mít povoleno dvoufaktorové ověření.
+signing.wont_sign.parentsigned=Commit nebude podepsán, protože nadřazený commit není podepsán.
+signing.wont_sign.basesigned=Sloučení nebude podepsáno, protože základní commit není podepsaný.
+signing.wont_sign.headsigned=Sloučení nebude podepsáno, protože hlavní revize není podepsána.
+signing.wont_sign.commitssigned=Sloučení nebude podepsáno, protože všechny přidružené revize nejsou podepsány.
+signing.wont_sign.approved=Sloučení nebude podepsáno, protože požadavek na natažení není schválen.
+signing.wont_sign.not_signed_in=Nejste přihlášeni.
ext_wiki=Přístup k externí Wiki
ext_wiki.desc=Odkaz do externí Wiki.
@@ -1709,10 +1881,13 @@ wiki.file_revision=Revize stránky
wiki.wiki_page_revisions=Revize Wiki stránky
wiki.back_to_wiki=Zpět na wiki stránku
wiki.delete_page_button=Smazat stránku
+wiki.delete_page_notice_1=Odstranění Wiki stránky „%s“ nemůže být vráceno zpět. Pokračovat?
wiki.page_already_exists=Stránka Wiki se stejným názvem již existuje.
+wiki.reserved_page=Jméno Wiki stránky „%s“ je rezervováno.
wiki.pages=Stránky
wiki.last_updated=Naposledy aktualizováno: %s
wiki.page_name_desc=Zadejte název této Wiki stránky. Některé speciální názvy jsou: „Home“, „_Sidebar“ a „_Footer“.
+wiki.original_git_entry_tooltip=Zobrazit originální Git soubor namísto použití přátelského odkazu.
activity=Aktivita
activity.period.filter_label=Období:
@@ -1780,6 +1955,8 @@ activity.git_stats_and_deletions=a
activity.git_stats_deletion_1=%d odebrání
activity.git_stats_deletion_n=%d odebrání
+contributors.contribution_type.commits=Commity
+
search=Vyhledat
search.search_repo=Hledat repozitář
search.type.tooltip=Druh vyhledávání
@@ -1804,6 +1981,12 @@ settings.hooks=Webové háčky
settings.githooks=Háčky Gitu
settings.basic_settings=Základní nastavení
settings.mirror_settings=Nastavení zrcadla
+settings.mirror_settings.docs=Nastavte repozitář pro automatickou synchronizaci commitů, značek a větví s jiným repozitářem.
+settings.mirror_settings.docs.disabled_pull_mirror.instructions=Nastavte váš projekt pro automatické nahrávání commitů, značek a větví do jiného repozitáře. Správce webu zakázal zrcadla pro natažení.
+settings.mirror_settings.docs.disabled_push_mirror.instructions=Nastavte svůj projekt pro automatické natažení commitů, značek a větví z jiného repozitáře.
+settings.mirror_settings.docs.no_new_mirrors=Váš repozitář zrcadlí změny do nebo z jiného repozitáře. Mějte prosím na paměti, že v tuto chvíli nemůžete vytvořit žádná nová zrcadla.
+settings.mirror_settings.docs.can_still_use=I když nemůžete upravit stávající zrcadla nebo vytvořit nová, stále můžete použít své stávající zrcadlo.
+settings.mirror_settings.docs.more_information_if_disabled=Více informací o zrcadlech pro nahrání a natažení naleznete zde:
settings.mirror_settings.docs.doc_link_title=Jak mohu zrcadlit repozitáře?
settings.mirror_settings.docs.pulling_remote_title=Stažení ze vzdáleného úložiště
settings.mirror_settings.mirrored_repository=Zrcadlený repozitář
@@ -1814,6 +1997,7 @@ settings.mirror_settings.last_update=Poslední aktualizace
settings.mirror_settings.push_mirror.none=Nenastavena žádná zrcadla pro nahrání
settings.mirror_settings.push_mirror.remote_url=URL vzdáleného Git repozitáře
settings.mirror_settings.push_mirror.add=Přidat zrcadlo pro nahrání
+settings.mirror_settings.push_mirror.edit_sync_time=Upravit interval synchronizace zrcadla
settings.sync_mirror=Synchronizovat nyní
settings.site=Webová stránka
@@ -1851,8 +2035,11 @@ settings.pulls.ignore_whitespace=Ignorovat bílé znaky při konfliktech
settings.pulls.enable_autodetect_manual_merge=Povolit autodetekci ručních sloučení (Poznámka: V některých zvláštních případech může dojít k nesprávnému rozhodnutí)
settings.pulls.allow_rebase_update=Povolit aktualizaci větve požadavku na natažení pomocí rebase
settings.pulls.default_delete_branch_after_merge=Ve výchozím nastavení mazat větev požadavku na natažení po jeho sloučení
+settings.pulls.default_allow_edits_from_maintainers=Ve výchozím nastavení povolit úpravy od správců
+settings.releases_desc=Povolit vydání v repozitáři
settings.packages_desc=Povolit registr balíčků repozitáře
settings.projects_desc=Povolit projekty v repozitáři
+settings.actions_desc=Povolit akce repozitáře
settings.admin_settings=Nastavení správce
settings.admin_enable_health_check=Povolit kontrolu stavu repozitáře (git fsck)
settings.admin_code_indexer=Indexování kódu
@@ -1879,6 +2066,7 @@ settings.transfer.rejected=Převod repozitáře byl zamítnut.
settings.transfer.success=Převod repozitáře byl úspěšný.
settings.transfer_abort=Zrušit převod
settings.transfer_abort_invalid=Nemůžete zrušit neexistující převod repozitáře.
+settings.transfer_abort_success=Převod repozitáře do %s byl úspěšně zrušen.
settings.transfer_desc=Předat tento repozitář uživateli nebo organizaci, ve které máte administrátorská práva.
settings.transfer_form_title=Zadejte jméno repozitáře pro potvrzení:
settings.transfer_in_progress=V současné době probíhá převod. Zrušte jej, pokud chcete převést tento repozitář jinému uživateli.
@@ -1898,6 +2086,7 @@ settings.trust_model.collaborator.long=Spolupracovník: Důvěřovat podpisům s
settings.trust_model.collaborator.desc=Platné podpisy spolupracovníků tohoto repozitáře budou označeny jako „důvěryhodné“ - (ať se shodují s autorem, či nikoli). V opačném případě budou platné podpisy označeny jako „nedůvěryhodné“, pokud se podpis shoduje s přispěvatelem a „neodpovídající“, pokud ne.
settings.trust_model.committer=Přispěvatel
settings.trust_model.committer.long=Přispěvatel: Důvěřovat podpisům, které odpovídají autorům (což odpovídá GitHub a přinutí Giteu nastavit jako tvůrce pro Giteou podepsané revize)
+settings.trust_model.committer.desc=Platné podpisy budou označeny pouze jako „důvěryhodné“, pokud se shodují s přispěvatelem, jinak budou označeny jako „neodpovídající“. To přinutí Giteu, aby byla přispěvatelem podepsaných commitů se skutečným přispěvatelem označeným jako Co-authored-by: a Co-committed-by: na konci commitu. Výchozí klíč Gitea musí odpovídat uživateli v databázi.
settings.trust_model.collaboratorcommitter=Spolupracovník+Přispěvatel
settings.trust_model.collaboratorcommitter.long=Spolupracovník+Přispěvatel: Důvěřovat podpisům od spolupracovníků, které odpovídají tvůrci revize
settings.trust_model.collaboratorcommitter.desc=Platné podpisy spolupracovníků tohoto repozitáře budou označeny jako „důvěryhodné“, pokud se shodují s přispěvatelem. V opačném případě budou platné podpisy označeny jako "nedůvěryhodné", pokud se podpis shoduje s přispěvatelem a „neodpovídajícím“ v opačném případě. To přinutí Giteu, aby byla označena jako přispěvatel podepsaných commitů se skutečným přispěvatelem označeným jako Co-Authored-By: a Co-Committed-By: na konci commitu. Výchozí klíč Gitea musí odpovídat uživateli v databázi.
@@ -1913,6 +2102,7 @@ settings.delete_notices_2=- Tato operace trvale smaže repozitář %sdokumentace. Příklady: main, release/**
+settings.protect_patterns=Vzory
+settings.protect_protected_file_patterns=Vzory chráněných souborů (oddělené středníkem „;“):
+settings.protect_protected_file_patterns_desc=Chráněné soubory, které nemají povoleno být měněny přímo, i když uživatel má právo přidávat, upravovat nebo mazat soubory v této větvi. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na github.com/gobwas/glob dokumentaci pro syntaxi vzoru. Příklady: .drone.yml
, /docs/**/*.txt
.
+settings.protect_unprotected_file_patterns=Vzory nechráněných souborů (oddělené středníkem „;“):
+settings.protect_unprotected_file_patterns_desc=Nechráněné soubory, které je možné měnit přímo, pokud má uživatel právo zápisu, čímž se obejde omezení push. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na github.com/gobwas/glob dokumentaci pro syntaxi vzoru. Příklady: .drone.yml
, /docs/**/*.txt
.
settings.add_protected_branch=Zapnout ochranu
settings.delete_protected_branch=Vypnout ochranu
+settings.update_protect_branch_success=Ochrana větví pro větev „%s“ byla aktualizována.
+settings.remove_protected_branch_success=Ochrana větví pro větev „%s“ byla zakázána.
+settings.remove_protected_branch_failed=Odstranění ochranného pravidla větve „%s“ se nezdařilo.
settings.protected_branch_deletion=Zakázat ochranu větví
settings.protected_branch_deletion_desc=Zakázání ochrany větví umožní uživatelům s právem zápisu nahrávat do této větve. Pokračovat?
settings.block_rejected_reviews=Blokovat sloučení při zamítavých posouzeních
@@ -2106,10 +2315,13 @@ settings.block_on_official_review_requests_desc=Slučování nebude možné, pok
settings.block_outdated_branch=Blokovat sloučení, pokud je požadavek na natažení zastaralý
settings.block_outdated_branch_desc=Slučování nebude možné, pokud je hlavní větev za základní větví.
settings.default_branch_desc=Vybrat výchozí větev repozitáře pro požadavky na natažení a revize kódu:
+settings.merge_style_desc=Sloučit styly
settings.default_merge_style_desc=Výchozí styl sloučení pro požadavky na natažení:
settings.choose_branch=Vyberte větev…
settings.no_protected_branch=Nejsou tu žádné chráněné větve.
settings.edit_protected_branch=Upravit
+settings.protected_branch_required_rule_name=Požadovaný název pravidla
+settings.protected_branch_duplicate_rule_name=Duplikovat název pravidla
settings.protected_branch_required_approvals_min=Požadovaná schválení nesmí být záporné číslo.
settings.tags=Značky
settings.tags.protection=Ochrana značek
@@ -2120,8 +2332,10 @@ settings.tags.protection.allowed.teams=Povolené týmy
settings.tags.protection.allowed.noone=Nikdo
settings.tags.protection.create=Chránit značku
settings.tags.protection.none=Neexistují žádné chráněné značky.
+settings.tags.protection.pattern.description=Můžete použít jediné jméno nebo vzor glob nebo regulární výraz, který bude odpovídat více značek. Přečtěte si více v průvodci chráněnými značkami .
settings.bot_token=Token pro robota
settings.chat_id=ID chatu
+settings.thread_id=ID vlákna
settings.matrix.homeserver_url=URL adresa Homeserveru
settings.matrix.room_id=ID místnosti
settings.matrix.message_type=Typ zprávy
@@ -2132,6 +2346,11 @@ settings.archive.error=Nastala chyba při archivování repozitáře. Prohlédn
settings.archive.error_ismirror=Nemůžete archivovat zrcadlený repozitář.
settings.archive.branchsettings_unavailable=Nastavení větví není dostupné, pokud je repozitář archivovaný.
settings.archive.tagsettings_unavailable=Nastavení značek není k dispozici, pokud je repozitář archivován.
+settings.unarchive.button=Obnovit repozitář
+settings.unarchive.header=Obnovit tento repozitář
+settings.unarchive.text=Obnovení repozitáře vrátí možnost přijímání commitů a nahrávání. Stejně tak se obnoví i možnost zadávání nových úkolů a požadavků na natažení.
+settings.unarchive.success=Repozitář byl úspěšně obnoven.
+settings.unarchive.error=Nastala chyba při obnovování repozitáře. Prohlédněte si záznam pro více detailů.
settings.update_avatar_success=Avatar repozitáře byl aktualizován.
settings.lfs=LFS
settings.lfs_filelist=LFS soubory uložené v tomto repozitáři
@@ -2198,6 +2417,7 @@ diff.show_more=Zobrazit více
diff.load=Načíst rozdílové porovnání
diff.generated=vygenerováno
diff.vendored=vendorováno
+diff.comment.add_line_comment=Přidat jednořádkový komentář
diff.comment.placeholder=Zanechat komentář
diff.comment.markdown_info=Je podporována úprava vzhledu pomocí markdown.
diff.comment.add_single_comment=Přidat jeden komentář
@@ -2209,7 +2429,9 @@ diff.review.header=Odeslat posouzení
diff.review.placeholder=Posoudit komentář
diff.review.comment=Okomentovat
diff.review.approve=Schválit
+diff.review.self_reject=Autoři požadavků na natažení nemohou požadovat změny na svém vlastním požadavku na natažení
diff.review.reject=Požadovat změny
+diff.review.self_approve=Autoři požadavku na natažení nemohou schválit svůj vlastní požadavek na natažení
diff.committed_by=odevzdal
diff.protected=Chráněno
diff.image.side_by_side=Vedle sebe
@@ -2231,13 +2453,18 @@ release.compare=Porovnat
release.edit=upravit
release.ahead.commits=%d revizí
release.ahead.target=do %s od tohoto vydání
+tag.ahead.target=do %s od této značky
release.source_code=Zdrojový kód
release.new_subheader=Vydání organizuje verze projektu.
release.edit_subheader=Vydání organizuje verze projektu.
release.tag_name=Název značky
release.target=Cíl
release.tag_helper=Vyberte existující značku nebo vytvořte novou značku.
+release.tag_helper_new=Nová značka. Tato značka bude vytvořen z cíle.
+release.tag_helper_existing=Stávající značka.
release.title=Název vydání
+release.title_empty=Název nesmí být prázdný.
+release.message=Popište toto vydání
release.prerelease_desc=Označit jako předběžná verze
release.prerelease_helper=Označit vydání jako nevhodné pro produkční nasazení.
release.cancel=Zrušit
@@ -2247,6 +2474,7 @@ release.edit_release=Aktualizovat vydání
release.delete_release=Smazat vydání
release.delete_tag=Smazat značku
release.deletion=Smazat vydání
+release.deletion_desc=Smazání vydání jej pouze odebere z Gitea. Nebude to mít vliv na značku Git, obsah vašeho repozitáře nebo jeho historii. Pokračovat?
release.deletion_success=Vydání bylo odstraněno.
release.deletion_tag_desc=Odstraní tuto značku z repozitáře. Obsah repozitáře a historie zůstanou nezměněny. Pokračovat?
release.deletion_tag_success=Značka byla odstraněna.
@@ -2258,32 +2486,56 @@ release.downloads=Soubory ke stažení
release.download_count=Stažení: %s
release.add_tag_msg=Použít název a obsah vydání jako zprávu značky.
release.add_tag=Vytvořit pouze značku
+release.releases_for=Vydání pro %s
release.tags_for=Značky pro %s
branch.name=Jméno větve
+branch.already_exists=Větev pojmenovaná „%s“ již existuje.
branch.delete_head=Smazat
+branch.delete=Smazat větev „%s“
branch.delete_html=Smazat větev
+branch.delete_desc=Smazání větve je trvalé. Přestože zrušená větev může existovat i po krátkou dobu, než bude skutečně odstraněna, NELZE ji většinou vrátit. Pokračovat?
+branch.deletion_success=Větev „%s“ byla smazána.
+branch.deletion_failed=Nepodařilo se odstranit větev „%s“.
+branch.delete_branch_has_new_commits=Větev „%s“ nemůže být smazána, protože byly přidány nové commity po sloučení.
branch.create_branch=Vytvořit větev %s
+branch.create_from=z „%s“
+branch.create_success=Větev „%s“ byla vytvořena.
branch.branch_already_exists=Větev „%s“ již existuje v tomto repozitáři.
+branch.branch_name_conflict=Jméno větve „%s“ koliduje s již existující větví „%s“.
+branch.tag_collision=Větev „%s“ nemůže být vytvořena, protože v repozitáři existuje značka se stejným jménem.
branch.deleted_by=Odstranil %s
+branch.restore_success=Větev „%s“ byla obnovena.
+branch.restore_failed=Nepodařilo se obnovit větev „%s“.
+branch.protected_deletion_failed=Větev „%s“ je chráněna. Nemůže být smazána.
+branch.default_deletion_failed=Větev „%s“ je výchozí větev. Nelze ji odstranit.
+branch.restore=Obnovit větev „%s“
+branch.download=Stáhnout větev „%s“
+branch.rename=Přejmenovat větev „%s“
+branch.search=Hledat větev
branch.included_desc=Tato větev je součástí výchozí větve
branch.included=Zahrnuje
branch.create_new_branch=Vytvořit větev z větve:
branch.confirm_create_branch=Vytvořit větev
+branch.warning_rename_default_branch=Přejmenováváte výchozí větev.
+branch.rename_branch_to=Přejmenovat „%s“ na:
branch.confirm_rename_branch=Přejmenovat větev
branch.create_branch_operation=Vytvořit větev
branch.new_branch=Vytvořit novou větev
+branch.new_branch_from=Vytvořit novou větev z „%s“
branch.renamed=Větev %s byla přejmenována na %s.
tag.create_tag=Vytvořit značku %s
tag.create_tag_operation=Vytvořit značku
tag.confirm_create_tag=Vytvořit značku
+tag.create_tag_from=Vytvořit novou značku z „%s“
tag.create_success=Značka „%s“ byla vytvořena.
topic.manage_topics=Spravovat témata
topic.done=Hotovo
topic.count_prompt=Nelze vybrat více než 25 témat
+topic.format_prompt=Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a tečky („.“) a může být dlouhé až 35 znaků. Písmena musí být malá.
find_file.go_to_file=Přejít na soubor
find_file.no_matching=Nebyl nalezen žádný odpovídající soubor
@@ -2292,6 +2544,8 @@ error.csv.too_large=Tento soubor nelze vykreslit, protože je příliš velký.
error.csv.unexpected=Tento soubor nelze vykreslit, protože obsahuje neočekávaný znak na řádku %d ve sloupci %d.
error.csv.invalid_field_count=Soubor nelze vykreslit, protože má nesprávný počet polí na řádku %d.
+[graphs]
+
[org]
org_name_holder=Název organizace
org_full_name_holder=Celý název organizace
@@ -2315,23 +2569,28 @@ team_permission_desc=Oprávnění
team_unit_desc=Povolit přístup do částí repozitáře
team_unit_disabled=(zakázaná)
+form.name_reserved=Název organizace „%s“ je rezervován.
+form.name_pattern_not_allowed=Vzor „%s“ není povolený v názvu organizace.
form.create_org_not_allowed=Nemáte oprávnění vytvářet nové organizace.
settings=Nastavení
settings.options=Organizace
settings.full_name=Celé jméno
+settings.email=Kontaktní e-mail
settings.website=Webové stránky
settings.location=Umístění
settings.permission=Oprávnění
settings.repoadminchangeteam=Správce úložišť může týmům přidávat a odebírat přístup
settings.visibility=Viditelnost
settings.visibility.public=Veřejná
+settings.visibility.limited=Omezeno (Viditelné pouze pro ověřené uživatele)
settings.visibility.limited_shortname=Omezený
settings.visibility.private=Soukromá (viditelné jen členům organizace)
settings.visibility.private_shortname=Soukromý
settings.update_settings=Upravit nastavení
settings.update_setting_success=Nastavení organizace bylo upraveno.
+settings.change_orgname_prompt=Poznámka: Změna názvu organizace také změní adresu URL vaší organizace a uvolní staré jméno této organizace.
settings.change_orgname_redirect_prompt=Staré jméno bude přesměrovávat, dokud nebude znovu obsazeno.
settings.update_avatar_success=Avatar organizace byl aktualizován.
settings.delete=Smazat organizaci
@@ -2396,6 +2655,7 @@ teams.remove_all_repos_title=Odstranit všechny repozitáře týmu
teams.remove_all_repos_desc=Tímto odeberete všechny repozitáře z týmu.
teams.add_all_repos_title=Přidat všechny repozitáře
teams.add_all_repos_desc=Tímto přidáte do týmu všechny repozitáře organizace.
+teams.add_nonexistent_repo=Repositář, který se snažíte přidat, neexistuje. Nejdříve jej vytvořte, prosím.
teams.add_duplicate_users=Uživatel je již členem týmu.
teams.repos.none=Tento tým nemůže přistoupit k žádným repozitářům.
teams.members.none=Žádní členové v tomto týmu.
@@ -2406,15 +2666,18 @@ teams.all_repositories_helper=Tým má přístup ke všem repositářům. Výbě
teams.all_repositories_read_permission_desc=Tomuto týmu je udělen přístup pro Čtení všech repozitářů : členové mohou prohlížet a klonovat repozitáře.
teams.all_repositories_write_permission_desc=Tomuto týmu je udělen přístup pro Zápis do všech repozitářů : členové mohou prohlížet a nahrávat do repozitářů.
teams.all_repositories_admin_permission_desc=Tomuto týmu je udělen Administrátorský přístup do všech repozitářů : členové mohou prohlížet, nahrávat a přidávat spolupracovníky do repozitářů.
+teams.invite.title=Byli jste pozváni do týmu %s v organizaci %s .
teams.invite.by=Pozvání od %s
teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže.
[admin]
dashboard=Přehled
+identity_access=Identita a přístup
users=Uživatelské účty
organizations=Organizace
repositories=Repozitáře
hooks=Webové háčky
+integrations=Integrace
authentication=Zdroje ověření
emails=Uživatelské e-maily
config=Nastavení
@@ -2423,7 +2686,9 @@ monitor=Sledování
first_page=První
last_page=Poslední
total=Celkem: %d
+settings=Nastavení správce
+dashboard.new_version_hint=Gitea %s je nyní k dispozici, právě u vás běži %s. Podívej se na blogu pro více informací.
dashboard.statistic=Souhrn
dashboard.operations=Operace údržby
dashboard.system_status=Status systému
@@ -2432,13 +2697,15 @@ dashboard.operation_switch=Přepnout
dashboard.operation_run=Spustit
dashboard.clean_unbind_oauth=Vyčistit neprovázané OAuth spojení
dashboard.clean_unbind_oauth_success=Všechna neprovázaná OAuth spojení byla smazána.
-dashboard.task.started=Zahájen úkol: %[1]s
-dashboard.task.process=Úkol: %[1]s
-dashboard.task.error=Chyba v úkolu: %[1]s: %[3]s
-dashboard.task.finished=Úkol: %[1]s začalo %[2]s skončilo
-dashboard.task.unknown=Neznámý úkol: %[1]s
+dashboard.task.started=Zahájena úloha: %[1]s
+dashboard.task.process=Úloha: %[1]s
+dashboard.task.cancelled=Úloha: %[1]s zrušean: %[3]s
+dashboard.task.error=Chyba v úloze: %[1]s: %[3]s
+dashboard.task.finished=Úloha: %[1]s začala %[2]s skončila
+dashboard.task.unknown=Neznámá úloha: %[1]s
dashboard.cron.started=Začala naplánovaná úloha: %[1]s
dashboard.cron.process=Naplánovaná úloha: %[1]s
+dashboard.cron.cancelled=Naplánovaná úloha: %[1]s zrušena: %[3]s
dashboard.cron.error=Chyba v naplánované úloze: %s: %[3]s
dashboard.cron.finished=Naplánovaná úloha: %[1]s skončila
dashboard.delete_inactive_accounts=Smazat všechny neaktivované účty
@@ -2495,9 +2762,11 @@ dashboard.delete_old_actions=Odstranit všechny staré akce z databáze
dashboard.delete_old_actions.started=Začalo odstraňování všech starých akcí z databáze.
dashboard.update_checker=Kontrola aktualizací
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
-dashboard.stop_zombie_tasks=Zastavit zombie úkoly
-dashboard.stop_endless_tasks=Zastavit nekonečné úkoly
+dashboard.stop_zombie_tasks=Zastavit zombie úlohy
+dashboard.stop_endless_tasks=Zastavit nekonečné úlohy
dashboard.cancel_abandoned_jobs=Zrušit opuštěné úlohy
+dashboard.start_schedule_tasks=Spustit naplánované úlohy
+dashboard.sync_branch.started=Synchronizace větví byla spuštěna
users.user_manage_panel=Správa uživatelských účtů
users.new_account=Vytvořit uživatelský účet
@@ -2506,12 +2775,16 @@ users.full_name=Celé jméno
users.activated=Aktivován
users.admin=Správce
users.restricted=Omezený
+users.reserved=Rezervováno
+users.bot=Bot
+users.remote=Vzdálený
users.2fa=2FA
users.repos=Repozitáře
users.created=Vytvořen
users.last_login=Poslední přihlášení
users.never_login=Nikdy nepřihlášen
users.send_register_notify=Odeslat upozornění při registraci uživatele
+users.new_success=Uživatelský účet „%s“ byl vytvořen.
users.edit=Upravit
users.auth_source=Zdroj ověřování
users.local=Místní
@@ -2536,6 +2809,7 @@ users.still_own_repo=Tento uživatel stále vlastní jeden nebo více repozitá
users.still_has_org=Uživatel je člen organizace. Nejprve odstraňte uživatele ze všech organizací.
users.purge=Vymazat uživatele
users.purge_help=Vynuceně smazat uživatele a všechny repositáře, organizace a balíčky vlastněné uživatelem. Všechny komentáře budou také smazány.
+users.still_own_packages=Tento uživatel stále vlastní jeden nebo více balíčků, nejprve odstraňte tyto balíčky.
users.deletion_success=Uživatelský účet byl smazán.
users.reset_2fa=Resetovat 2FA
users.list_status_filter.menu_text=Filtr
@@ -2550,6 +2824,7 @@ users.list_status_filter.is_prohibit_login=Zakázat přihlášení
users.list_status_filter.not_prohibit_login=Povolit přihlášení
users.list_status_filter.is_2fa_enabled=2FA povoleno
users.list_status_filter.not_2fa_enabled=2FA zakázáno
+users.details=Detaily uživatele
emails.email_manage_panel=Správa e-mailů uživatele
emails.primary=Hlavní
@@ -2562,6 +2837,7 @@ emails.updated=E-mail aktualizován
emails.not_updated=Aktualizace požadované e-mailové adresy se nezdařila: %v
emails.duplicate_active=Tato e-mailová adresa je již aktivní pro jiného uživatele.
emails.change_email_header=Aktualizovat vlastnosti e-mailu
+emails.change_email_text=Opravdu chcete aktualizovat tuto e-mailovou adresu?
orgs.org_manage_panel=Správa organizací
orgs.name=Název
@@ -2580,9 +2856,12 @@ repos.stars=Oblíbení
repos.forks=Rozštěpení
repos.issues=Úkoly
repos.size=Velikost
+repos.lfs_size=Velikost LFS
packages.package_manage_panel=Správa balíčků
packages.total_size=Celková velikost: %s
+packages.unreferenced_size=Neodkazovaná velikost: %s
+packages.cleanup=Vyčistit prošlá data
packages.owner=Vlastník
packages.creator=Tvůrce
packages.name=Název
@@ -2688,6 +2967,7 @@ auths.sspi_default_language=Výchozí jazyk uživatele
auths.sspi_default_language_helper=Výchozí jazyk pro uživatele automaticky vytvořené pomocí SSPI auth metody. Pokud dáváte přednost automatickému zjištění jazyka, ponechte prázdné.
auths.tips=Tipy
auths.tips.oauth2.general=Ověřování OAuth2
+auths.tips.oauth2.general.tip=Při registraci nové OAuth2 autentizace by URL callbacku/přesměrování měla být:
auths.tip.oauth2_provider=Poskytovatel OAuth2
auths.tip.bitbucket=Vytvořte nového OAuth konzumenta na https://bitbucket.org/account/user//oauth-consumers/new a přidejte oprávnění „Account“ - „Read“
auths.tip.nextcloud=Zaregistrujte nového OAuth konzumenta na vaší instanci pomocí následujícího menu „Nastavení -> Zabezpečení -> OAuth 2.0 klient“
@@ -2699,10 +2979,12 @@ auths.tip.google_plus=Získejte klientské pověření OAuth2 z Google API konzo
auths.tip.openid_connect=Použijte OpenID URL pro objevování spojení (/.well-known/openid-configuration) k nastavení koncových bodů
auths.tip.twitter=Jděte na https://dev.twitter.com/apps, vytvořte aplikaci a ujistěte se, že volba „Allow this application to be used to Sign in with Twitter“ je povolená
auths.tip.discord=Registrujte novou aplikaci na https://discordapp.com/developers/applications/me
+auths.tip.gitea=Registrovat novou Oauth2 aplikaci. Návod naleznete na https://docs.gitea.com/development/oauth2-provider
auths.tip.yandex=Vytvořte novou aplikaci na https://oauth.yandex.com/client/new. Vyberte následující oprávnění z „Yandex.Passport API“ sekce: „Přístup k e-mailové adrese“, „Přístup k uživatelskému avataru“ a „Přístup k uživatelskému jménu, jménu a příjmení, pohlaví“
auths.tip.mastodon=Vložte vlastní URL instance pro mastodon, kterou se chcete autentizovat (nebo použijte výchozí)
auths.edit=Upravit zdroj ověřování
auths.activated=Tento zdroj ověřování je aktivován
+auths.new_success=Zdroj ověřování „%s“ byl přidán.
auths.update_success=Zdroj ověřování byl aktualizován.
auths.update=Aktualizovat zdroj ověřování
auths.delete=Smazat zdroj ověřování
@@ -2710,7 +2992,9 @@ auths.delete_auth_title=Smazat zdroj ověřování
auths.delete_auth_desc=Zamezíte přihlášení uživatelům pomocí tohoto zdroje ověřování, pokud ho smažete. Pokračovat?
auths.still_in_used=Zdroj ověřování je stále používán. Nejprve převeďte nebo smažte všechny uživatele, kteří používají tento způsob ověřování.
auths.deletion_success=Zdroj ověřování byl smazán.
+auths.login_source_exist=Zdroj ověřování „%s“ již existuje.
auths.login_source_of_type_exist=Zdroj ověřování tohoto typu již existuje.
+auths.unable_to_initialize_openid=Nelze inicializovat poskytovatele OpenID Connect: %s
auths.invalid_openIdConnectAutoDiscoveryURL=Neplatná URL adresa pro automatické vyhledání (musí být platná adresa URL začínající http:// nebo https://)
config.server_config=Nastavení serveru
@@ -2725,6 +3009,7 @@ config.disable_router_log=Vypnout log směrovače
config.run_user=Spustit jako uživatel
config.run_mode=Režim spouštění
config.git_version=Verze Gitu
+config.app_data_path=Cesta k datům aplikace
config.repo_root_path=Kořenový adresář repozitářů
config.lfs_root_path=Kořenový adresář LFS
config.log_file_root_path=Adresář logů
@@ -2799,6 +3084,9 @@ config.mailer_sendmail_timeout=Časový limit Sandmail
config.mailer_use_dummy=Fiktivní
config.test_email_placeholder=E-mail (např.: test@example.com)
config.send_test_mail=Odeslat zkušební e-mail
+config.send_test_mail_submit=Odeslat
+config.test_mail_failed=Odeslání testovacího e-mailu na „%s“ selhalo: %v
+config.test_mail_sent=Zkušební e-mail byl odeslán na „%s“.
config.oauth_config=Nastavení ověření OAuth
config.oauth_enabled=Zapnutý
@@ -2838,10 +3126,12 @@ config.git_gc_timeout=Časový limit operace GC
config.log_config=Nastavení logů
config.disabled_logger=Zakázané
config.access_log_mode=Režim logování přístupu
+config.access_log_template=Šablona záznamu přístupu
config.xorm_log_sql=Logovat SQL
config.set_setting_failed=Nastavení %s se nezdařilo
+monitor.stats=Statistiky
monitor.cron=Naplánované úlohy
monitor.name=Název
@@ -2851,6 +3141,7 @@ monitor.previous=Předešlý čas spuštění
monitor.execute_times=Vykonání
monitor.process=Spuštěné procesy
monitor.stacktrace=Výpisy zásobníku
+monitor.processes_count=%d procesů
monitor.desc=Popis
monitor.start=Čas zahájení
monitor.execute_time=Doba provádění
@@ -2868,6 +3159,7 @@ monitor.queue.exemplar=Typ vzoru
monitor.queue.numberworkers=Počet workerů
monitor.queue.maxnumberworkers=Maximální počet workerů
monitor.queue.numberinqueue=Číslo ve frontě
+monitor.queue.review_add=Posoudit / přidat workery
monitor.queue.settings.title=Nastavení fondu
monitor.queue.settings.maxnumberworkers=Maximální počet workerů
monitor.queue.settings.maxnumberworkers.placeholder=V současné době %[1]d
@@ -2892,6 +3184,7 @@ notices.desc=Popis
notices.op=Akce
notices.delete_success=Systémové upozornění bylo smazáno.
+
[action]
create_repo=vytvořil/a repozitář %s
rename_repo=přejmenoval/a repozitář z %[1]s
na %[3]s
@@ -2987,6 +3280,7 @@ desc=Správa balíčků repozitáře.
empty=Zatím nejsou žádné balíčky.
empty.documentation=Další informace o registru balíčků naleznete v dokumentaci .
empty.repo=Nahráli jste balíček, ale nezobrazil se zde? Přejděte na nastavení balíčku a propojte jej s tímto repozitářem.
+registry.documentation=Další informace o registru %s naleznete v dokumentaci .
filter.type=Typ
filter.type.all=Vše
filter.no_result=Váš filtr nepřinesl žádné výsledky.
@@ -3050,6 +3344,7 @@ debian.repository.distributions=Distribuce
debian.repository.components=Komponenty
debian.repository.architectures=Architektury
generic.download=Stáhnout balíček z příkazové řádky:
+go.install=Nainstalujte balíček z příkazové řádky:
helm.registry=Nastavte tento registr z příkazového řádku:
helm.install=Pro instalaci balíčku spusťte následující příkaz:
maven.registry=Nastavte tento registr ve vašem projektu pom.xml
souboru:
@@ -3071,7 +3366,11 @@ pub.install=Chcete-li nainstalovat balíček pomocí Dart, spusťte následujíc
pypi.requires=Vyžaduje Python
pypi.install=Pro instalaci balíčku pomocí pip spusťte následující příkaz:
rpm.registry=Nastavte tento registr z příkazového řádku:
+rpm.distros.redhat=na distribuce založené na RedHat
+rpm.distros.suse=na distribuce založené na SUSE
rpm.install=Pro instalaci balíčku spusťte následující příkaz:
+rpm.repository=Informace o repozitáři
+rpm.repository.architectures=Architektury
rubygems.install=Pro instalaci balíčku pomocí gem spusťte následující příkaz:
rubygems.install2=nebo ho přidejte do Gemfie:
rubygems.dependencies.runtime=Běhové závislosti
@@ -3079,6 +3378,8 @@ rubygems.dependencies.development=Vývojové závislosti
rubygems.required.ruby=Vyžaduje verzi Ruby
rubygems.required.rubygems=Vyžaduje verzi RubyGem
swift.registry=Nastavte tento registr z příkazového řádku:
+swift.install=Přidejte balíček do svého Package.swift
souboru:
+swift.install2=a spustit následující příkaz:
vagrant.install=Pro přidání Vagrant box spusťte následující příkaz:
settings.link=Propojit tento balíček s repozitářem
settings.link.description=Pokud propojíte balíček s repozitářem, je tento balíček uveden v seznamu balíčků repozitáře.
@@ -3093,6 +3394,7 @@ settings.delete.success=Balíček byl odstraněn.
settings.delete.error=Nepodařilo se odstranit balíček.
owner.settings.cargo.title=Index registru Cargo
owner.settings.cargo.initialize=Inicializovat index
+owner.settings.cargo.initialize.description=Pro použití Cargo registru je zapotřebí speciální index Git. Použití této možnosti (znovu)vytvoří repozitář a automaticky jej nastaví.
owner.settings.cargo.initialize.error=Nepodařilo se inicializovat Cargo index: %v
owner.settings.cargo.initialize.success=Index Cargo byl úspěšně vytvořen.
owner.settings.cargo.rebuild=Znovu vytvořit Index
@@ -3101,6 +3403,7 @@ owner.settings.cargo.rebuild.success=Cargo Index byl úspěšně obnoven.
owner.settings.cleanuprules.title=Spravovat pravidla pro čištění
owner.settings.cleanuprules.add=Přidat pravidlo pro čištění
owner.settings.cleanuprules.edit=Upravit pravidlo pro čištění
+owner.settings.cleanuprules.none=Nejsou k dispozici žádná pravidla čištění. Prohlédněte si prosím dokumentaci.
owner.settings.cleanuprules.preview=Náhled pravidla pro čištění
owner.settings.cleanuprules.preview.overview=%d balíčků má být odstraněno.
owner.settings.cleanuprules.preview.none=Pravidlo čištění neodpovídá žádným balíčkům.
@@ -3119,6 +3422,7 @@ owner.settings.cleanuprules.success.update=Pravidlo pro čištění bylo aktuali
owner.settings.cleanuprules.success.delete=Pravidlo pro čištění bylo odstraněno.
owner.settings.chef.title=Registr Chef
owner.settings.chef.keypair=Generovat pár klíčů
+owner.settings.chef.keypair.description=Pro autentizaci do registru Chef je zapotřebí pár klíčů. Pokud jste předtím vytvořili pár klíčů, nově vygenerovaný pár klíčů vyřadí starý pár klíčů.
[secrets]
secrets=Tajné klíče
@@ -3145,6 +3449,7 @@ status.waiting=Čekání
status.running=Probíhá
status.success=Úspěch
status.failure=Chyba
+status.cancelled=Zrušeno
status.skipped=Přeskočeno
status.blocked=Blokováno
@@ -3158,7 +3463,8 @@ runners.description=Popis
runners.labels=Štítky
runners.last_online=Poslední čas online
runners.runner_title=Runner
-runners.task_list=Nedávné úkoly na tomto runneru
+runners.task_list=Nedávné úlohy na tomto runneru
+runners.task_list.no_tasks=Zatím zde nejsou žádné úlohy.
runners.task_list.run=Spustit
runners.task_list.status=Status
runners.task_list.repository=Repozitář
@@ -3172,23 +3478,62 @@ runners.delete_runner=Odstranit tento runner
runners.delete_runner_success=Runner byl úspěšně odstraněn
runners.delete_runner_failed=Odstranění runneru selhalo
runners.delete_runner_header=Potvrdit odstranění tohoto runneru
+runners.delete_runner_notice=Pokud na tomto runneru běží úloha, bude ukončena a označena jako neúspěšná. Může dojít k přerušení vytváření pracovního postupu.
runners.status.unspecified=Neznámý
runners.status.idle=Nečinný
runners.status.active=Aktivní
runners.status.offline=Offline
runners.version=Verze
+runners.reset_registration_token=Resetovat registrační token
+runners.reset_registration_token_success=Registrační token runneru byl úspěšně obnoven
runs.all_workflows=Všechny pracovní postupy
runs.commit=Commit
+runs.scheduled=Naplánováno
+runs.invalid_workflow_helper=Konfigurační soubor pracovního postupu je neplatný. Zkontrolujte prosím konfigurační soubor: %s
+runs.no_matching_online_runner_helper=Žádný odpovídající online runner s popiskem: %s
+runs.actor=Aktér
runs.status=Status
+runs.actors_no_select=Všichni aktéři
+runs.status_no_select=Všechny stavy
+runs.no_results=Nebyly nalezeny žádné výsledky.
+runs.no_workflows=Zatím neexistují žádné pracovní postupy.
+runs.no_runs=Pracovní postup zatím nebyl spuštěn.
+runs.empty_commit_message=(prázdná zpráva commitu)
+
+workflow.disable=Zakázat pracovní postup
+workflow.disable_success=Pracovní postup „%s“ byl úspěšně deaktivován.
+workflow.enable=Povolit pracovní postup
+workflow.enable_success=Pracovní postup „%s“ byl úspěšně aktivován.
+workflow.disabled=Pracovní postup je zakázán.
-
+variables=Proměnné
+variables.management=Správa proměnných
+variables.creation=Přidat proměnnou
+variables.none=Zatím nejsou žádné proměnné.
+variables.deletion=Odstranit proměnnou
+variables.deletion.description=Odstranění proměnné je trvalé a nelze jej vrátit zpět. Pokračovat?
+variables.description=Proměnné budou předány určitým akcím a nelze je přečíst jinak.
+variables.edit=Upravit proměnnou
+variables.deletion.failed=Nepodařilo se odstranit proměnnou.
+variables.deletion.success=Proměnná byla odstraněna.
+variables.creation.failed=Přidání proměnné se nezdařilo.
+variables.creation.success=Proměnná „%s“ byla přidána.
+variables.update.failed=Úprava proměnné se nezdařila.
+variables.update.success=Proměnná byla upravena.
[projects]
+type-1.display_name=Samostatný projekt
+type-2.display_name=Projekt repozitíře
type-3.display_name=Projekt organizace
[git.filemode]
+changed_filemode=%[1]s → %[2]s
; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", …
+directory=Adresář
+normal_file=Normální soubor
+executable_file=Spustitelný soubor
symbolic_link=Symbolický odkaz
+submodule=Submodul
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index c24d25b1ac..fa10bfcb11 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -585,6 +585,7 @@ org_still_own_packages=Diese Organisation besitzt noch ein oder mehrere Pakete,
target_branch_not_exist=Der Ziel-Branch existiert nicht.
+
[user]
change_avatar=Profilbild ändern…
joined_on=Beigetreten am %s
@@ -1952,6 +1953,8 @@ activity.git_stats_and_deletions=und
activity.git_stats_deletion_1=%d Löschung
activity.git_stats_deletion_n=%d Löschungen
+contributors.contribution_type.commits=Commits
+
search=Suchen
search.search_repo=Repository durchsuchen
search.type.tooltip=Suchmodus
@@ -2550,6 +2553,8 @@ error.csv.too_large=Diese Datei kann nicht gerendert werden, da sie zu groß ist
error.csv.unexpected=Diese Datei kann nicht gerendert werden, da sie ein unerwartetes Zeichen in Zeile %d und Spalte %d enthält.
error.csv.invalid_field_count=Diese Datei kann nicht gerendert werden, da sie eine falsche Anzahl an Feldern in Zeile %d hat.
+[graphs]
+
[org]
org_name_holder=Name der Organisation
org_full_name_holder=Vollständiger Name der Organisation
@@ -3199,6 +3204,7 @@ notices.desc=Beschreibung
notices.op=Aktion
notices.delete_success=Diese Systemmeldung wurde gelöscht.
+
[action]
create_repo=hat das Repository %s erstellt
rename_repo=hat das Repository von %[1]s
zu %[3]s umbenannt
@@ -3383,6 +3389,8 @@ rpm.registry=Diese Registry über die Kommandozeile einrichten:
rpm.distros.redhat=auf RedHat-basierten Distributionen
rpm.distros.suse=auf SUSE-basierten Distributionen
rpm.install=Nutze folgenden Befehl, um das Paket zu installieren:
+rpm.repository=Repository-Informationen
+rpm.repository.architectures=Architekturen
rubygems.install=Um das Paket mit gem zu installieren, führe den folgenden Befehl aus:
rubygems.install2=oder füg es zum Gemfile hinzu:
rubygems.dependencies.runtime=Laufzeitabhängigkeiten
@@ -3530,7 +3538,6 @@ variables.none=Es gibt noch keine Variablen.
variables.deletion=Variable entfernen
variables.deletion.description=Das Entfernen einer Variable ist dauerhaft und kann nicht rückgängig gemacht werden. Fortfahren?
variables.description=Variablen werden an bestimmte Aktionen übergeben und können nicht anderweitig gelesen werden.
-variables.id_not_exist=Variable mit ID %d existiert nicht.
variables.edit=Variable bearbeiten
variables.deletion.failed=Fehler beim Entfernen der Variable.
variables.deletion.success=Die Variable wurde entfernt.
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 2424ee3fb6..2662a49cea 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -4,6 +4,7 @@ explore=Εξερεύνηση
help=Βοήθεια
logo=Λογότυπο
sign_in=Είσοδος
+sign_in_with_provider=Είσοδος με %s
sign_in_or=ή
sign_out=Έξοδος
sign_up=Εγγραφή
@@ -16,6 +17,7 @@ template=Πρότυπο
language=Γλώσσα
notifications=Ειδοποιήσεις
active_stopwatch=Ενεργή Καταγραφή Χρόνου
+tracked_time_summary=Περίληψη του χρόνου παρακολούθησης με βάση τα φίλτρα της λίστας ζητημάτων
create_new=Δημιουργία…
user_profile_and_more=Προφίλ και ρυθμίσεις…
signed_in_as=Είσοδος ως
@@ -79,6 +81,7 @@ milestones=Ορόσημα
ok=OK
cancel=Ακύρωση
+retry=Επανάληψη
rerun=Επανεκτέλεση
rerun_all=Επανεκτέλεση όλων
save=Αποθήκευση
@@ -88,12 +91,15 @@ remove=Αφαίρεση
remove_all=Αφαίρεση Όλων
remove_label_str=`Αφαίρεση του αντικειμένου "%s"`
edit=Επεξεργασία
+view=Προβολή
enabled=Ενεργοποιημένο
disabled=Απενεργοποιημένο
+locked=Κλειδωμένο
copy=Αντιγραφή
copy_url=Αντιγραφή URL
+copy_hash=Αντιγραφή hash
copy_content=Αντιγραφή περιεχομένου
copy_branch=Αντιγραφή ονόματος κλάδου
copy_success=Αντιγράφηκε!
@@ -106,6 +112,7 @@ loading=Φόρτωση…
error=Σφάλμα
error404=Η σελίδα που προσπαθείτε να φτάσετε είτε δεν υπάρχει είτε δεν είστε εξουσιοδοτημένοι για να την δείτε.
+go_back=Επιστροφή
never=Ποτέ
unknown=Άγνωστη
@@ -127,7 +134,9 @@ concept_user_organization=Οργανισμός
show_timestamps=Εμφάνιση χρονοσημάνσεων
show_log_seconds=Εμφάνιση δευτερολέπτων
show_full_screen=Εμφάνιση πλήρους οθόνης
+download_logs=Λήψη καταγραφών
+confirm_delete_selected=Επιβεβαιώνετε τη διαγραφή όλων των επιλεγμένων στοιχείων;
name=Όνομα
value=Τιμή
@@ -166,6 +175,7 @@ string.desc=Z - A
[error]
occurred=Παρουσιάστηκε ένα σφάλμα
+report_message=Αν πιστεύετε ότι αυτό είναι ένα πρόβλημα στο Gitea, παρακαλούμε αναζητήστε ζητήματα στο GitHub ή ανοίξτε ένα νέο ζήτημα εάν είναι απαραίτητο.
missing_csrf=Bad Request: δεν υπάρχει διακριτικό CSRF
invalid_csrf=Λάθος Αίτημα: μη έγκυρο διακριτικό CSRF
not_found=Ο προορισμός δεν βρέθηκε.
@@ -174,6 +184,7 @@ network_error=Σφάλμα δικτύου
[startpage]
app_desc=Μια ανώδυνη, αυτο-φιλοξενούμενη υπηρεσία Git
install=Εύκολο στην εγκατάσταση
+install_desc=Απλά εκτελέστε το αρχείο προγράμματος για την πλατφόρμα σας, χρήσιμοποιήστε το με το Docker , ή εγκαταστήστε το πακέτο .
platform=Πολυπλατφορμικό
platform_desc=Ο Gitea τρέχει οπουδήποτε Go μπορεί να γίνει compile για: Windows, macOS, Linux, ARM, κλπ. Επιλέξτε αυτό που αγαπάτε!
lightweight=Ελαφρύ
@@ -218,6 +229,7 @@ repo_path_helper=Τα απομακρυσμένα αποθετήρια Git θα
lfs_path=Ριζική Διαδρομή Git LFS
lfs_path_helper=Τα αρχεία που παρακολουθούνται από το Git LFS θα αποθηκεύονται σε αυτόν τον φάκελο. Αφήστε κενό για να το απενεργοποιήσετε.
run_user=Εκτέλεση Σαν Χρήστη
+run_user_helper=Το όνομα του χρήστη του λειτουργικού συστήματος ο οποίος εκτελεί το Gitea. Επισημαίνεται ότι αυτός ο χρήστης πρέπει να έχει πρόσβαση στο ριζικό φάκελο του αποθετηρίου.
domain=Domain Διακομιστή
domain_helper=Όνομα domain διακομιστή ή η διεύθυνση του.
ssh_port=Θύρα της υπηρεσίας SSH
@@ -290,6 +302,7 @@ password_algorithm_helper=Ορίστε τον αλγόριθμο κατακερ
enable_update_checker=Ενεργοποίηση Ελεγκτή Ενημερώσεων
enable_update_checker_helper=Ελέγχει περιοδικά για νέες εκδόσεις κάνοντας σύνδεση στο gitea.io.
env_config_keys=Ρυθμίσεις Περιβάλλοντος
+env_config_keys_prompt=Οι ακόλουθες μεταβλητές περιβάλλοντος θα εφαρμοστούν επίσης στο αρχείο ρυθμίσεων σας:
[home]
uname_holder=Όνομα Χρήστη ή Διεύθυνση Email
@@ -348,9 +361,11 @@ disable_register_prompt=Η εγγραφή είναι απενεργοποιημ
disable_register_mail=Η Επιβεβαίωση email για την εγγραφή είναι απενεργοποιημένη.
manual_activation_only=Επικοινωνήστε με το διαχειριστή της υπηρεσίας για να ολοκληρώσετε την ενεργοποίηση.
remember_me=Απομνημόνευση αυτής της συσκευής
+remember_me.compromised=Το διακριτικό σύνδεσης δεν είναι πλέον έγκυρο, αυτό ίσως υποδεικνύει έναν κλεμμένο λογαριασμό. Παρακαλώ ελέγξτε το λογαριασμό σας για ασυνήθιστες δραστηριότητες.
forgot_password_title=Ξέχασα Τον Κωδικό Πρόσβασης
forgot_password=Ξεχάσατε τον κωδικό πρόσβασης;
sign_up_now=Χρειάζεστε λογαριασμό; Εγγραφείτε τώρα.
+sign_up_successful=Ο λογαριασμός δημιουργήθηκε επιτυχώς. Καλώς ορίσατε!
confirmation_mail_sent_prompt=Ένα νέο email επιβεβαίωσης έχει σταλεί στο %s . Παρακαλώ ελέγξτε τα εισερχόμενα σας μέσα στις επόμενες %s για να ολοκληρώσετε τη διαδικασία εγγραφής.
must_change_password=Ενημερώστε τον κωδικό πρόσβασης σας
allow_password_change=Απαιτείται από το χρήστη να αλλάξει τον κωδικό πρόσβασης (συνιστόμενο)
@@ -358,6 +373,7 @@ reset_password_mail_sent_prompt=Ένα email επιβεβαίωσης έχει
active_your_account=Ενεργοποιήστε Το Λογαριασμό Σας
account_activated=Ο λογαριασμός έχει ενεργοποιηθεί
prohibit_login=Απαγορεύεται η Σύνδεση
+prohibit_login_desc=Ο λογαριασμός σας δεν επιτρέπεται να συνδεθεί, παρακαλούμε επικοινωνήστε με το διαχειριστή σας.
resent_limit_prompt=Έχετε ήδη ζητήσει ένα email ενεργοποίησης πρόσφατα. Παρακαλώ περιμένετε 3 λεπτά και προσπαθήστε ξανά.
has_unconfirmed_mail=Γεια σας %s, έχετε μια ανεπιβεβαίωτη διεύθυνση ηλεκτρονικού ταχυδρομείου (%s ). Εάν δεν έχετε λάβει email επιβεβαίωσης ή χρειάζεται να αποστείλετε εκ νέου ένα νέο, παρακαλώ κάντε κλικ στο παρακάτω κουμπί.
resend_mail=Κάντε κλικ εδώ για να στείλετε ξανά το email ενεργοποίησης
@@ -365,8 +381,10 @@ email_not_associate=Η διεύθυνση ηλεκτρονικού ταχυδρ
send_reset_mail=Αποστολή Email Ανάκτησης Λογαριασμού
reset_password=Ανάκτηση Λογαριασμού
invalid_code=Ο κωδικός επιβεβαίωσης δεν είναι έγκυρος ή έχει λήξει.
+invalid_code_forgot_password=Ο κωδικός επιβεβαίωσης δεν είναι έγκυρος ή έληξε. Πατήστε εδώ για να ξεκινήσετε νέα συνεδρία.
invalid_password=Ο κωδικός πρόσβασης σας δεν ταιριάζει με τον κωδικό που χρησιμοποιήθηκε για τη δημιουργία του λογαριασμού.
reset_password_helper=Ανάκτηση Λογαριασμού
+reset_password_wrong_user=Έχετε συνδεθεί ως %s, αλλά ο σύνδεσμος ανάκτησης λογαριασμού προορίζεται για το %s
password_too_short=Το μήκος του κωδικού πρόσβασης δεν μπορεί να είναι μικρότερο από %d χαρακτήρες.
non_local_account=Οι μη τοπικοί χρήστες δεν μπορούν να ενημερώσουν τον κωδικό πρόσβασής τους μέσω του διεπαφής web του Gitea.
verify=Επαλήθευση
@@ -391,6 +409,7 @@ openid_connect_title=Σύνδεση σε υπάρχων λογαριασμό
openid_connect_desc=Το επιλεγμένο OpenID URI είναι άγνωστο. Συνδέστε το με ένα νέο λογαριασμό εδώ.
openid_register_title=Δημιουργία νέου λογαριασμού
openid_register_desc=Το επιλεγμένο OpenID URI είναι άγνωστο. Συνδέστε το με ένα νέο λογαριασμό εδώ.
+openid_signin_desc=Εισάγετε το OpenID URI σας. Για παράδειγμα: alice.openid.example.org ή https://openid.example.org/alice.
disable_forgot_password_mail=Η ανάκτηση λογαριασμού είναι απενεργοποιημένη επειδή δεν έχει οριστεί email. Παρακαλούμε επικοινωνήστε με το διαχειριστή.
disable_forgot_password_mail_admin=Η ανάκτηση λογαριασμού είναι διαθέσιμη μόνο όταν έχει οριστεί το email. Παρακαλούμε ορίστει το email σας για να ενεργοποιήσετε την ανάκτηση λογαριασμού.
email_domain_blacklisted=Δεν μπορείτε να εγγραφείτε με τη διεύθυνση email σας.
@@ -400,7 +419,9 @@ authorize_application_created_by=Αυτή η εφαρμογή δημιουργή
authorize_application_description=Εάν παραχωρήσετε την πρόσβαση, θα μπορεί να έχει πρόσβαση και να γράφει σε όλες τις πληροφορίες του λογαριασμού σας, συμπεριλαμβανομένων των ιδιωτικών αποθετηρίων και οργανισμών.
authorize_title=Εξουσιοδότηση του "%s" για έχει πρόσβαση στο λογαριασμό σας;
authorization_failed=Αποτυχία εξουσιοδότησης
+authorization_failed_desc=Η εξουσιοδότηση απέτυχε επειδή εντοπίστηκε μια μη έγκυρη αίτηση. Παρακαλούμε επικοινωνήστε με το συντηρητή της εφαρμογής που προσπαθήσατε να εξουσιοδοτήσετε.
sspi_auth_failed=Αποτυχία ταυτοποίησης SSPI
+password_pwned=Ο κωδικός πρόσβασης που επιλέξατε είναι σε μια λίστα κλεμμένων κωδικών πρόσβασης που προηγουμένως εκτέθηκαν σε παραβίαση δημόσιων δεδομένων. Παρακαλώ δοκιμάστε ξανά με διαφορετικό κωδικό πρόσβασης και σκεφτείτε να αλλάξετε αυτόν τον κωδικό πρόσβασης όπου αλλού χρησιμοποιείται.
password_pwned_err=Δεν ήταν δυνατή η ολοκλήρωση του αιτήματος προς το HaveIBeenPwned
[mail]
@@ -415,6 +436,7 @@ activate_account.text_1=Γεια σας %[1]s , ευχαριστούμε
activate_account.text_2=Παρακαλούμε κάντε κλικ στον παρακάτω σύνδεσμο για να ενεργοποιήσετε το λογαριασμό σας μέσα σε %s :
activate_email=Επιβεβαιώστε τη διεύθυνση email σας
+activate_email.title=%s, παρακαλώ επαληθεύστε τη διεύθυνση email σας
activate_email.text=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για να επαληθεύσετε τη διεύθυνση email σας στο %s :
register_notify=Καλώς ήλθατε στο Gitea
@@ -566,6 +588,7 @@ org_still_own_packages=Αυτός ο οργανισμός κατέχει ακό
target_branch_not_exist=Ο κλάδος προορισμού δεν υπάρχει.
+
[user]
change_avatar=Αλλαγή του avatar σας…
joined_on=Εγγράφηκε την %s
@@ -584,6 +607,8 @@ user_bio=Βιογραφικό
disabled_public_activity=Αυτός ο χρήστης έχει απενεργοποιήσει τη δημόσια προβολή της δραστηριότητας.
email_visibility.limited=Η διεύθυνση email σας είναι ορατή σε όλους τους ταυτοποιημένους χρήστες
email_visibility.private=Η διεύθυνση email σας είναι ορατή μόνο σε εσάς και στους διαχειριστές
+show_on_map=Εμφάνιση της τοποθεσίας στο χάρτη
+settings=Ρυθμίσεις Χρήστη
form.name_reserved=Το όνομα χρήστη "%s" είναι δεσμευμένο.
form.name_pattern_not_allowed=Το μοτίβο "%s" δεν επιτρέπεται μέσα σε ένα όνομα χρήστη.
@@ -605,9 +630,13 @@ delete=Διαγραφή Λογαριασμού
twofa=Έλεγχος Ταυτότητας Δύο Παραγόντων
account_link=Συνδεδεμένοι Λογαριασμοί
organization=Οργανισμοί
+uid=UID
webauthn=Κλειδιά Ασφαλείας
public_profile=Δημόσιο Προφίλ
+biography_placeholder=Πείτε μας λίγο για τον εαυτό σας! (Μπορείτε να γράψετε με Markdown)
+location_placeholder=Μοιραστείτε την κατά προσέγγιση τοποθεσία σας με άλλους
+profile_desc=Ελέγξτε πώς εμφανίζεται το προφίλ σας σε άλλους χρήστες. Η κύρια διεύθυνση email σας θα χρησιμοποιηθεί για ειδοποιήσεις, ανάκτηση κωδικού πρόσβασης και λειτουργίες Git που βασίζονται στο web.
password_username_disabled=Οι μη τοπικοί χρήστες δεν επιτρέπεται να αλλάξουν το όνομα χρήστη τους. Επικοινωνήστε με το διαχειριστή σας για περισσότερες λεπτομέρειες.
full_name=Πλήρες Όνομα
website=Ιστοσελίδα
@@ -619,6 +648,8 @@ update_language_not_found=Η γλώσσα "%s" δεν είναι διαθέσι
update_language_success=Η γλώσσα ενημερώθηκε.
update_profile_success=Το προφίλ σας έχει ενημερωθεί.
change_username=Το όνομα χρήστη σας έχει αλλάξει.
+change_username_prompt=Σημείωση: Αλλάζοντας το όνομα χρήστη σας αλλάζει επίσης το URL του λογαριασμού σας.
+change_username_redirect_prompt=Το παλιό όνομα χρήστη θα ανακατευθύνει μέχρι να ζητηθεί ξανά.
continue=Συνέχεια
cancel=Ακύρωση
language=Γλώσσα
@@ -643,6 +674,7 @@ comment_type_group_project=Έργο
comment_type_group_issue_ref=Αναφορά ζητήματος
saved_successfully=Οι ρυθμίσεις σας αποθηκεύτηκαν επιτυχώς.
privacy=Απόρρητο
+keep_activity_private=Απόκρυψη Δραστηριότητας από τη σελίδα προφίλ
keep_activity_private_popup=Με αυτή την επιλογή η δραστηριότητα σας είναι ορατή μόνο σε εσάς και τους διαχειριστές
lookup_avatar_by_mail=Αναζήτηση ενός Avatar με διεύθυνση email
@@ -652,12 +684,14 @@ choose_new_avatar=Επιλέξτε νέα εικόνα
update_avatar=Ενημέρωση Εικόνας
delete_current_avatar=Διαγραφή Τρέχουσας Εικόνας
uploaded_avatar_not_a_image=Το αρχείο που ανεβάσατε δεν είναι εικόνα.
+uploaded_avatar_is_too_big=Το μέγεθος αρχείου που ανέβηκε (%d KiB) υπερβαίνει το μέγιστο μέγεθος (%d KiB).
update_avatar_success=Η εικόνα σας έχει ενημερωθεί.
update_user_avatar_success=Το avatar του χρήστη ενημερώθηκε.
change_password=Ενημέρωση Κωδικού Πρόσβασης
old_password=Τρέχων Κωδικός Πρόσβασης
new_password=Νέος Κωδικός Πρόσβασης
+retype_new_password=Επιβεβαίωση Νέου Κωδικού Πρόσβασης
password_incorrect=Ο τρέχων κωδικός πρόσβασης είναι λάθος.
change_password_success=Ο κωδικός πρόσβασής σας έχει ενημερωθεί. Από εδώ και τώρα συνδέεστε χρησιμοποιώντας τον νέο κωδικό πρόσβασής σας.
password_change_disabled=Οι μη τοπικοί χρήστες δεν μπορούν να ενημερώσουν τον κωδικό πρόσβασής τους μέσω του διεπαφής web του Gitea.
@@ -666,6 +700,7 @@ emails=Διευθύνσεις Email
manage_emails=Διαχείριση Διευθύνσεων Email
manage_themes=Επιλέξτε προεπιλεγμένο θέμα διεπαφής
manage_openid=Διαχείριση Διευθύνσεων OpenID
+email_desc=Η κύρια διεύθυνση ηλεκτρονικού ταχυδρομείου σας θα χρησιμοποιηθεί για ειδοποιήσεις, ανάκτηση του κωδικού πρόσβασης και, εφόσον δεν είναι κρυμμένη, λειτουργίες Git στον ιστότοπο.
theme_desc=Αυτό θα είναι το προεπιλεγμένο θέμα διεπαφής σας σε όλη την ιστοσελίδα.
primary=Κύριο
activated=Ενεργό
@@ -673,6 +708,7 @@ requires_activation=Απαιτείται ενεργοποίηση
primary_email=Αλλαγή κυριότητας
activate_email=Αποστολή Ενεργοποίησης
activations_pending=Εκκρεμούν Ενεργοποιήσεις
+can_not_add_email_activations_pending=Εκκρεμεί μια ενεργοποίηση, δοκιμάστε ξανά σε λίγα λεπτά αν θέλετε να προσθέσετε ένα νέο email.
delete_email=Αφαίρεση
email_deletion=Αφαίρεση Διεύθυνσης Email
email_deletion_desc=Η διεύθυνση ηλεκτρονικού ταχυδρομείου και οι σχετικές πληροφορίες θα αφαιρεθούν από τον λογαριασμό σας. Οι υποβολές Git από αυτή τη διεύθυνση email θα παραμείνουν αμετάβλητες. Συνέχεια;
@@ -691,6 +727,7 @@ add_email_success=Η νέα διεύθυνση email έχει προστεθεί
email_preference_set_success=Οι προτιμήσεις email έχουν οριστεί επιτυχώς.
add_openid_success=Προστέθηκε η νέα διεύθυνση OpenID.
keep_email_private=Απόκρυψη Διεύθυνσης Email
+keep_email_private_popup=Αυτό θα κρύψει τη διεύθυνση ηλεκτρονικού ταχυδρομείου σας από το προφίλ σας, καθώς και όταν κάνετε ένα pull request ή επεξεργαστείτε ένα αρχείο χρησιμοποιώντας τη διεπαφή ιστού. Οι ωθούμενες υποβολές δεν θα τροποποιηθούν. Χρησιμοποιήστε το %s στις υποβολές για να τις συσχετίσετε με το λογαριασμό σας.
openid_desc=Το OpenID σας επιτρέπει να αναθέσετε τον έλεγχο ταυτότητας σε έναν εξωτερικό πάροχο.
manage_ssh_keys=Διαχείριση SSH Κλειδιών
@@ -769,7 +806,9 @@ ssh_disabled=SSH Απενεργοποιημένο
ssh_signonly=Το SSH είναι απενεργοποιημένο αυτή τη στιγμή, έτσι αυτά τα κλειδιά είναι μόνο για την επαλήθευση υπογραφής των υποβολών.
ssh_externally_managed=Αυτό το κλειδί SSH διαχειρίζεται εξωτερικά για αυτόν το χρήστη
manage_social=Διαχείριση Συσχετιζόμενων Λογαριασμών Κοινωνικών Δικτύων
+social_desc=Αυτοί οι κοινωνικοί λογαριασμοί μπορούν να χρησιμοποιηθούν για να συνδεθείτε στο λογαριασμό σας. Βεβαιωθείτε ότι τους αναγνωρίζετε όλους.
unbind=Αποσύνδεση
+unbind_success=Ο κοινωνικός λογαριασμός έχει διαγραφεί επιτυχώς.
manage_access_token=Διαχείριση Διακριτικών Πρόσβασης
generate_new_token=Δημιουργία Νέου Διακριτικού
@@ -790,6 +829,8 @@ permissions_access_all=Όλα (δημόσια, ιδιωτικά, και περι
select_permissions=Επιλέξτε δικαιώματα
permission_no_access=Καμία Πρόσβαση
permission_read=Αναγνωσμένες
+permission_write=Ανάγνωση και Εγγραφή
+access_token_desc=Τα επιλεγμένα δικαιώματα διακριτικών περιορίζουν την άδεια μόνο στις αντίστοιχες διαδρομές API . Διαβάστε την τεκμηρίωση για περισσότερες πληροφορίες.
at_least_one_permission=Πρέπει να επιλέξετε τουλάχιστον ένα δικαίωμα για να δημιουργήσετε ένα διακριτικό
permissions_list=Δικαιώματα:
@@ -801,6 +842,8 @@ remove_oauth2_application_desc=Η αφαίρεση μιας εφαρμογής O
remove_oauth2_application_success=Η εφαρμογή έχει διαγραφεί.
create_oauth2_application=Δημιουργία νέας εφαρμογής OAuth2
create_oauth2_application_button=Δημιουργία Εφαρμογής
+create_oauth2_application_success=Έχετε δημιουργήσει με επιτυχία μια νέα εφαρμογή OAuth2.
+update_oauth2_application_success=Έχετε ενημερώσει με επιτυχία την εφαρμογή OAuth2.
oauth2_application_name=Όνομα Εφαρμογής
oauth2_confidential_client=Εμπιστευτικός Πελάτης. Επιλέξτε το για εφαρμογές που διατηρούν το μυστικό κωδικό κρυφό, όπως πχ οι εφαρμογές ιστού. Μην επιλέγετε για εγγενείς εφαρμογές, συμπεριλαμβανομένων εφαρμογών επιφάνειας εργασίας και εφαρμογών για κινητά.
oauth2_redirect_uris=URI Ανακατεύθυνσης. Χρησιμοποιήστε μια νέα γραμμή για κάθε URI.
@@ -809,19 +852,26 @@ oauth2_client_id=Ταυτότητα Πελάτη
oauth2_client_secret=Μυστικό Πελάτη
oauth2_regenerate_secret=Αναδημιουργία Μυστικού
oauth2_regenerate_secret_hint=Χάσατε το μυστικό σας;
+oauth2_client_secret_hint=Το μυστικό δε θα εμφανιστεί ξανά αν κλείσετε ή ανανεώσετε αυτή τη σελίδα. Παρακαλώ βεβαιωθείτε ότι το έχετε αποθηκεύσει.
oauth2_application_edit=Επεξεργασία
oauth2_application_create_description=Οι εφαρμογές OAuth2 δίνει πρόσβαση στην εξωτερική εφαρμογή σας σε λογαριασμούς χρηστών σε αυτή την υπηρεσία.
+oauth2_application_remove_description=Αφαιρώντας μια εφαρμογή OAuth2 θα αποτραπεί η πρόσβαση αυτής, σε εξουσιοδοτημένους λογαριασμούς χρηστών σε αυτή την υπηρεσία. Συνέχεια;
+oauth2_application_locked=Το Gitea κάνει προεγγραφή σε μερικές εφαρμογές OAuth2 κατά την εκκίνηση αν είναι ενεργοποιημένες στις ρυθμίσεις. Για την αποφυγή απροσδόκητης συμπεριφοράς, αυτές δεν μπορούν ούτε να επεξεργαστούν ούτε να καταργηθούν. Παρακαλούμε ανατρέξτε στην τεκμηρίωση OAuth2 για περισσότερες πληροφορίες.
authorized_oauth2_applications=Εξουσιοδοτημένες Εφαρμογές OAuth2
+authorized_oauth2_applications_description=Έχετε χορηγήσει πρόσβαση στον προσωπικό σας λογαριασμό σε αυτές τις εφαρμογές τρίτων. Ανακαλέστε την πρόσβαση για εφαρμογές που δεν χρειάζεστε πλέον.
revoke_key=Ανάκληση
revoke_oauth2_grant=Ανάκληση Πρόσβασης
revoke_oauth2_grant_description=Η ανάκληση πρόσβασης για αυτή την εξωτερική εφαρμογή θα αποτρέψει αυτή την εφαρμογή από την πρόσβαση στα δεδομένα σας. Σίγουρα;
+revoke_oauth2_grant_success=Η πρόσβαση ανακλήθηκε επιτυχώς.
twofa_desc=Ο έλεγχος ταυτότητας δύο παραγόντων ενισχύει την ασφάλεια του λογαριασμού σας.
+twofa_recovery_tip=Αν χάσετε τη συσκευή σας, θα είστε σε θέση να χρησιμοποιήσετε ένα κλειδί ανάκτησης μιας χρήσης για να ανακτήσετε την πρόσβαση στο λογαριασμό σας.
twofa_is_enrolled=Ο λογαριασμός σας είναι εγγεγραμμένος σε έλεγχο ταυτότητας δύο παραγόντων.
twofa_not_enrolled=Ο λογαριασμός σας δεν είναι εγγεγραμμένος σε έλεγχο ταυτότητας δύο παραγόντων.
twofa_disable=Απενεργοποίηση Ταυτοποίησης Δύο Παραμέτρων
twofa_scratch_token_regenerate=Αναδημιουργία Διακριτικού Μίας Χρήσης
+twofa_scratch_token_regenerated=Το κλειδί ανάκτησης μιας χρήσης είναι τώρα %s. Αποθηκεύστε το σε ασφαλές μέρος, καθώς δε θα εμφανιστεί ξανά.
twofa_enroll=Εγγραφή στην ταυτοποίηση δύο παραγόντων
twofa_disable_note=Μπορείτε να απενεργοποιήσετε την ταυτοποίηση δύο παραγόντων αν χρειαστεί.
twofa_disable_desc=Η απενεργοποίηση της ταυτοποίησης δύο παραγόντων θα καταστήσει τον λογαριασμό σας λιγότερο ασφαλή. Συνέχεια;
@@ -839,6 +889,8 @@ webauthn_register_key=Προσθήκη Κλειδιού Ασφαλείας
webauthn_nickname=Ψευδώνυμο
webauthn_delete_key=Αφαίρεση Κλειδιού Ασφαλείας
webauthn_delete_key_desc=Αν αφαιρέσετε ένα κλειδί ασφαλείας δεν μπορείτε πλέον να συνδεθείτε με αυτό. Συνέχεια;
+webauthn_key_loss_warning=Αν χάσετε τα κλειδιά ασφαλείας σας, θα χάσετε την πρόσβαση στο λογαριασμό σας.
+webauthn_alternative_tip=Μπορεί να θέλετε να ρυθμίσετε μια πρόσθετη μέθοδο ταυτοποίησης.
manage_account_links=Διαχείριση Συνδεδεμένων Λογαριασμών
manage_account_links_desc=Αυτοί οι εξωτερικοί λογαριασμοί είναι συνδεδεμένοι στον Gitea λογαριασμό σας.
@@ -848,8 +900,10 @@ remove_account_link=Αφαίρεση Συνδεδεμένου Λογαριασμ
remove_account_link_desc=Η κατάργηση ενός συνδεδεμένου λογαριασμού θα ανακαλέσει την πρόσβασή του στο λογαριασμό σας στο Gitea. Συνέχεια;
remove_account_link_success=Ο συνδεδεμένος λογαριασμός έχει αφαιρεθεί.
+hooks.desc=Προσθήκη webhooks που θα ενεργοποιούνται για όλα τα αποθετήρια που σας ανήκουν.
orgs_none=Δεν είστε μέλος σε κάποιο οργανισμό.
+repos_none=Δεν κατέχετε κάποιο αποθετήριο.
delete_account=Διαγραφή Του Λογαριασμού Σας
delete_prompt=Αυτή η ενέργεια θα διαγράψει μόνιμα το λογαριασμό σας. ΔΕΝ ΘΑ ΜΠΟΡΕΙ να επανέλθει.
@@ -868,9 +922,12 @@ visibility=Ορατότητα χρήστη
visibility.public=Δημόσια
visibility.public_tooltip=Ορατό σε όλους
visibility.limited=Περιορισμένη
+visibility.limited_tooltip=Ορατό μόνο στους ταυτοποιημένους χρήστες
visibility.private=Ιδιωτική
+visibility.private_tooltip=Ορατό μόνο στα μέλη των οργανισμών που συμμετέχετε
[repo]
+new_repo_helper=Ένα αποθετήριο περιέχει όλα τα αρχεία έργου, συμπεριλαμβανομένου του ιστορικού εκδόσεων. Ήδη φιλοξενείται αλλού; Μετεγκατάσταση αποθετηρίου.
owner=Ιδιοκτήτης
owner_helper=Ορισμένοι οργανισμοί ενδέχεται να μην εμφανίζονται στο αναπτυσσόμενο μενού λόγω του μέγιστου αριθμού αποθετηρίων.
repo_name=Όνομα αποθετηρίου
@@ -882,6 +939,7 @@ template_helper=Μετατροπή σε πρότυπο αποθετήριο
template_description=Τα πρότυπα αποθετήρια επιτρέπουν στους χρήστες να δημιουργήσουν νέα αποθετήρια με την ίδια δομή, αρχεία και προαιρετικές ρυθμίσεις.
visibility=Ορατότητα
visibility_description=Μόνο ο ιδιοκτήτης ή τα μέλη του οργανισμού εάν έχουν δικαιώματα, θα είναι σε θέση να το δουν.
+visibility_helper=Αλλάξτε το αποθετήριο σε ιδιωτικό
visibility_helper_forced=Ο διαχειριστής σας αναγκάζει τα νέα αποθετήρια να είναι ιδιωτικά.
visibility_fork_helper=(Αλλάζοντας αυτό θα επηρεάσει όλα τα forks.)
clone_helper=Χρειάζεστε βοήθεια για τη κλωνοποίηση; Επισκεφθείτε τη Βοήθεια .
@@ -890,6 +948,9 @@ fork_from=Fork Από Το
already_forked=Έχετε ήδη κάνει fork το %s
fork_to_different_account=Fork σε διαφορετικό λογαριασμό
fork_visibility_helper=Η ορατότητα ενός fork αποθετηρίου δεν μπορεί να αλλάξει.
+fork_branch=Κλάδος που θα κλωνοποιηθεί στο fork
+all_branches=Όλοι οι κλάδοι
+fork_no_valid_owners=Αυτό το αποθετήριο δεν μπορεί να γίνει fork επειδή δεν υπάρχουν έγκυροι ιδιοκτήτες.
use_template=Χρήση αυτού του πρότυπου
clone_in_vsc=Κλωνοποίηση στο VS Code
download_zip=Λήψη ZIP
@@ -918,6 +979,7 @@ trust_model_helper_collaborator_committer=Συνεργάτης+Υποβολέα
trust_model_helper_default=Προεπιλογή: Χρησιμοποιήστε το προεπιλεγμένο μοντέλο εμπιστοσύνης για αυτήν την εγκατάσταση
create_repo=Δημιουργία Αποθετηρίου
default_branch=Προεπιλεγμένος Κλάδος
+default_branch_label=προεπιλογή
default_branch_helper=Ο προεπιλεγμένος κλάδος είναι ο βασικός κλάδος για pull requests και υποβολές κώδικα.
mirror_prune=Καθαρισμός
mirror_prune_desc=Αφαίρεση παρωχημένων αναφορών απομακρυσμένης-παρακολούθησης
@@ -926,6 +988,8 @@ mirror_interval_invalid=Το χρονικό διάστημα του ειδώλο
mirror_sync_on_commit=Συγχρονισμός κατά την ώθηση
mirror_address=Κλωνοποίηση Από Το URL
mirror_address_desc=Τοποθετήστε όλα τα απαιτούμενα διαπιστευτήρια στην ενότητα Εξουσιοδότηση.
+mirror_address_url_invalid=Η διεύθυνση URL που δόθηκε δεν είναι έγκυρη. Πρέπει να κάνετε escape όλα τα στοιχεία του url σωστά.
+mirror_address_protocol_invalid=Η παρεχόμενη διεύθυνση URL δεν είναι έγκυρη. Μόνο οι τοποθεσίες http(s):// ή git:// μπορούν να χρησιμοποιηθούν για τη δημιουργία ειδώλου.
mirror_lfs=Large File Storage (LFS)
mirror_lfs_desc=Ενεργοποίηση αντικατοπτρισμού δεδομένων LFS.
mirror_lfs_endpoint=Άκρο LFS
@@ -951,13 +1015,20 @@ delete_preexisting=Διαγραφή αρχείων που προϋπήρχαν
delete_preexisting_content=Διαγραφή αρχείων στο %s
delete_preexisting_success=Διαγράφηκαν τα μη υιοθετημένα αρχεία στο %s
blame_prior=Προβολή ευθύνης πριν από αυτή την αλλαγή
+blame.ignore_revs=Αγνόηση των αναθεωρήσεων στο .git-blame-ignore-revs . Πατήστε εδώ για να το παρακάμψετε και να δείτε την κανονική προβολή ευθυνών.
+blame.ignore_revs.failed=Αποτυχία αγνόησης των αναθεωρήσεων στο .git-blame-ignore-revs .
author_search_tooltip=Εμφάνιση το πολύ 30 χρηστών
+tree_path_not_found_commit=Η διαδρομή %[1]s δεν υπάρχει στην υποβολή %[2]s
+tree_path_not_found_branch=Η διαδρομή %[1]s δεν υπάρχει στον κλάδο %[2]s
+tree_path_not_found_tag=Η διαδρομή %[1]s δεν υπάρχει στην ετικέτα %[2]s
transfer.accept=Αποδοχή Μεταφοράς
transfer.accept_desc=`Μεταφορά στο "%s"`
transfer.reject=Απόρριψη Μεταφοράς
transfer.reject_desc=`Ακύρωση μεταφοράς σε "%s"`
+transfer.no_permission_to_accept=Δεν έχετε άδεια να αποδεχτείτε αυτή τη μεταφορά.
+transfer.no_permission_to_reject=Δεν έχετε άδεια να απορρίψετε αυτή τη μεταφορά.
desc.private=Ιδιωτικό
desc.public=Δημόσιο
@@ -976,6 +1047,8 @@ template.issue_labels=Σήματα Ζητήματος
template.one_item=Πρέπει να επιλέξετε τουλάχιστον ένα αντικείμενο στο πρότυπο
template.invalid=Πρέπει να επιλέξετε ένα πρότυπο αποθετήριο
+archive.title=Αυτό το αποθετήρειο αρχειοθετήθηκε. Μπορείτε να προβάλετε αρχεία και να τα κλωνοποιήσετε, αλλά δεν μπορείτε να ωθήσετε ή να ανοίξετε ζητήματα ή pull requests.
+archive.title_date=Αυτό το αποθετήριο έχει αρχειοθετηθεί στο %s. Μπορείτε να προβάλετε αρχεία και να κλωνοποιήσετε, αλλά δεν μπορείτε να ωθήσετε ή να ανοίξετε ζητήματα ή pull requests.
archive.issue.nocomment=Αυτό το αποθετήριο αρχειοθετήθηκε. Δεν μπορείτε να σχολιάσετε σε ζητήματα.
archive.pull.nocomment=Αυτό το repo αρχειοθετήθηκε. Δεν μπορείτε να σχολιάσετε στα pull requests.
@@ -992,6 +1065,7 @@ migrate_options_lfs=Μεταφορά αρχείων LFS
migrate_options_lfs_endpoint.label=Άκρο LFS
migrate_options_lfs_endpoint.description=Η μεταφορά θα προσπαθήσει να χρησιμοποιήσει το Git remote για να καθορίσει τον διακομιστή LFS . Μπορείτε επίσης να καθορίσετε ένα δικό σας endpoint αν τα δεδομένα LFS του αποθετηρίου αποθηκεύονται κάπου αλλού.
migrate_options_lfs_endpoint.description.local=Μια διαδρομή στο τοπικό διακομιστή επίσης υποστηρίζεται.
+migrate_options_lfs_endpoint.placeholder=Αν αφεθεί κενό, το άκρο θα προκύψει από το URL του κλώνου
migrate_items=Στοιχεία Μεταφοράς
migrate_items_wiki=Wiki
migrate_items_milestones=Ορόσημα
@@ -1094,6 +1168,10 @@ file_view_rendered=Προβολή Απόδοσης
file_view_raw=Προβολή Ακατέργαστου
file_permalink=Permalink
file_too_large=Το αρχείο είναι πολύ μεγάλο για να εμφανιστεί.
+invisible_runes_header=`Αυτό το αρχείο περιέχει αόρατους χαρακτήρες Unicode `
+invisible_runes_description=`Αυτό το αρχείο περιέχει αόρατους χαρακτήρες Unicode που δεν διακρίνονται από ανθρώπους, αλλά μπορεί να επεξεργάζονται διαφορετικά από έναν υπολογιστή. Αν νομίζετε ότι αυτό είναι σκόπιμο, μπορείτε να αγνοήσετε με ασφάλεια αυτή την προειδοποίηση. Χρησιμοποιήστε το κουμπί Escape για να τους αποκαλύψετε.`
+ambiguous_runes_header=`Αυτό το αρχείο περιέχει ασαφείς χαρακτήρες Unicode `
+ambiguous_runes_description=`Αυτό το αρχείο περιέχει χαρακτήρες Unicode που μπορεί να συγχέονται με άλλους χαρακτήρες. Αν νομίζετε ότι αυτό είναι σκόπιμο, μπορείτε να αγνοήσετε με ασφάλεια αυτή την προειδοποίηση. Χρησιμοποιήστε το κουμπί Escape για να τους αποκαλύψετε.`
invisible_runes_line=`Αυτή η γραμμή έχει αόρατους χαρακτήρες unicode `
ambiguous_runes_line=`Αυτή η γραμμή έχει ασαφείς χαρακτήρες unicode `
ambiguous_character=`ο %[1]c [U+%04[1]X] μπορεί να μπερδευτεί με τον %[2]c [U+%04[2]X]`
@@ -1106,11 +1184,15 @@ video_not_supported_in_browser=Το πρόγραμμα περιήγησής σα
audio_not_supported_in_browser=Το πρόγραμμα περιήγησής σας δεν υποστηρίζει την ετικέτα HTML5 'audio'.
stored_lfs=Αποθηκεύτηκε με το Git LFS
symbolic_link=Symbolic link
+executable_file=Εκτελέσιμο Αρχείο
commit_graph=Γράφημα Υποβολών
commit_graph.select=Επιλογή κλάδων
commit_graph.hide_pr_refs=Απόκρυψη Pull Requests
commit_graph.monochrome=Μονόχρωμο
commit_graph.color=Έγχρωμο
+commit.contained_in=Αυτή η υποβολή περιλαμβάνεται σε:
+commit.contained_in_default_branch=Αυτή η υποβολή είναι μέρος του προεπιλεγμένου κλάδου
+commit.load_referencing_branches_and_tags=Φόρτωση κλάδων και ετικετών που παραπέμπουν σε αυτήν την υποβολή
blame=Ευθύνη
download_file=Λήψη αρχείου
normal_view=Κανονική Προβολή
@@ -1203,6 +1285,7 @@ commits.signed_by_untrusted_user=Υπογράφηκε από μη έμπιστο
commits.signed_by_untrusted_user_unmatched=Υπογράφηκε από ένα μη έμπιστο χρήστη ο οποίος δεν ταιριάζει με τον υποβολέα
commits.gpg_key_id=ID Κλειδιού GPG
commits.ssh_key_fingerprint=Αποτύπωμα Κλειδιού SSH
+commits.view_path=Προβολή σε αυτή τη στιγμή στο ιστορικό
commit.operations=Λειτουργίες
commit.revert=Απόσυρση
@@ -1330,6 +1413,7 @@ issues.delete_branch_at=`διέγραψε το κλάδο %s %s`
issues.filter_label=Σήμα
issues.filter_label_exclude=`Χρησιμοποιήστε alt
+ κάντε κλικ/Enter
για να εξαιρέσετε τις σημάνσεις`
issues.filter_label_no_select=Όλα τα σήματα
+issues.filter_label_select_no_label=Χωρίς ετικέτα
issues.filter_milestone=Ορόσημο
issues.filter_milestone_all=Όλα τα ορόσημα
issues.filter_milestone_none=Χωρίς ορόσημα
@@ -1363,6 +1447,7 @@ issues.filter_sort.moststars=Περισσότερα αστέρια
issues.filter_sort.feweststars=Λιγότερα αστέρια
issues.filter_sort.mostforks=Περισσότερα forks
issues.filter_sort.fewestforks=Λιγότερα forks
+issues.keyword_search_unavailable=Η αναζήτηση μέσω λέξεων κλειδιών δεν είναι διαθέσιμη. Παρακαλώ επικοινωνήστε με το διαχειριστή.
issues.action_open=Άνοιγμα
issues.action_close=Κλείσιμο
issues.action_label=Σήμα
@@ -1380,9 +1465,10 @@ issues.opened_by_fake=άνοιξε το %[1]s από %[2]s
issues.closed_by_fake=από %[2]s έκλεισαν %[1]s
issues.previous=Προηγούμενο
issues.next=Επόμενο
-issues.open_title=Ανοιχτά
+issues.open_title=Ανοικτό
issues.closed_title=Κλειστά
issues.draft_title=Προσχέδιο
+issues.num_comments_1=%d σχόλιο
issues.num_comments=%d σχόλια
issues.commented_at=`σχολίασε %s `
issues.delete_comment_confirm=Θέλετε σίγουρα να διαγράψετε αυτό το σχόλιο;
@@ -1391,6 +1477,7 @@ issues.context.quote_reply=Παράθεση Απάντησης
issues.context.reference_issue=Αναφορά σε νέο ζήτημα
issues.context.edit=Επεξεργασία
issues.context.delete=Διαγραφή
+issues.no_content=Δεν υπάρχει περιγραφή.
issues.close=Κλείσιμο Ζητήματος
issues.comment_pull_merged_at=συγχώνευσε την υποβολή %[1]s στο %[2]s %[3]s
issues.comment_manually_pull_merged_at=συγχώνευσε χειροκίνητα την υποβολή %[1]s στο %[2]s %[3]s
@@ -1409,8 +1496,17 @@ issues.ref_closed_from=`έκλεισε αυτό το ζήτημ
issues.ref_reopened_from=` άνοιξε ξανά αυτό το ζήτημα %[4]s %[2]s `
issues.ref_from=`από %[1]s`
issues.author=Συγγραφέας
+issues.author_helper=Αυτός ο χρήστης είναι ο συγγραφέας.
issues.role.owner=Ιδιοκτήτης
+issues.role.owner_helper=Αυτός ο χρήστης είναι ο ιδιοκτήτης αυτού του αποθετηρίου.
issues.role.member=Μέλος
+issues.role.member_helper=Αυτός ο χρήστης είναι μέλος του οργανισμού που κατέχει αυτό το αποθετήριο.
+issues.role.collaborator=Συνεργάτης
+issues.role.collaborator_helper=Αυτός ο χρήστης έχει προσκληθεί να συνεργαστεί στο αποθετήριο.
+issues.role.first_time_contributor=Συντελεστής για πρώτη φορά
+issues.role.first_time_contributor_helper=Αυτή είναι η πρώτη συνεισφορά αυτού του χρήστη στο αποθετήριο.
+issues.role.contributor=Συντελεστής
+issues.role.contributor_helper=Αυτός ο χρήστης έχει προηγούμενές υποβολές στο αποθετήριο.
issues.re_request_review=Επαναίτηση ανασκόπησης
issues.is_stale=Έχουν υπάρξει αλλαγές σε αυτό το PR από αυτή την αναθεώρηση
issues.remove_request_review=Αφαίρεση αιτήματος αναθεώρησης
@@ -1425,6 +1521,9 @@ issues.label_title=Όνομα σήματος
issues.label_description=Περιγραφή σήματος
issues.label_color=Χρώμα σήματος
issues.label_exclusive=Αποκλειστικό
+issues.label_archive=Αρχειοθέτηση Σήματος
+issues.label_archived_filter=Εμφάνιση αρχειοθετημένων σημάτων
+issues.label_archive_tooltip=Τα αρχειοθετημένα σήματα εξαιρούνται από τις προτάσεις στην αναζήτηση με σήματα.
issues.label_exclusive_desc=Ονομάστε το σήμα πεδίο/στοιχείο
για να το κάνετε αμοιβαία αποκλειστικό με άλλα σήματα πεδίου/
.
issues.label_exclusive_warning=Τυχόν συγκρουόμενα σήματα θα αφαιρεθούν κατά την επεξεργασία των σημάτων ενός ζητήματος ή pull request.
issues.label_count=%d σήματα
@@ -1479,6 +1578,7 @@ issues.tracking_already_started=`Έχετε ήδη ξεκινήσει την κ
issues.stop_tracking=Διακοπή Χρονομέτρου
issues.stop_tracking_history=`σταμάτησε να εργάζεται %s`
issues.cancel_tracking=Απόρριψη
+issues.cancel_tracking_history=`ακύρωσε τη παρακολούθηση χρόνου %s`
issues.add_time=Χειροκίνητη Προσθήκη Ώρας
issues.del_time=Διαγραφή αυτού του αρχείου χρόνου
issues.add_time_short=Προσθήκη Χρόνου
@@ -1502,6 +1602,7 @@ issues.due_date_form=εεεε-μμ-ηη
issues.due_date_form_add=Προσθήκη ημερομηνίας παράδοσης
issues.due_date_form_edit=Επεξεργασία
issues.due_date_form_remove=Διαγραφή
+issues.due_date_not_writer=Χρειάζεστε πρόσβαση εγγραφής στο αποθετήριο για να ενημερώσετε την ημερομηνία λήξης ενός προβλήματος.
issues.due_date_not_set=Δεν ορίστηκε ημερομηνία παράδοσης.
issues.due_date_added=πρόσθεσε την ημερομηνία παράδοσης %s %s
issues.due_date_modified=τροποποίησε την ημερομηνία παράδοσης από %[2]s σε %[1]s %[3]s
@@ -1557,6 +1658,9 @@ issues.review.pending.tooltip=Αυτό το σχόλιο προς το παρό
issues.review.review=Αξιολόγηση
issues.review.reviewers=Εξεταστές
issues.review.outdated=Παρωχημένο
+issues.review.outdated_description=Το περιεχόμενο άλλαξε αφού έγινε αυτό το σχόλιο
+issues.review.option.show_outdated_comments=Εμφάνιση παρωχημένων σχολίων
+issues.review.option.hide_outdated_comments=Απόκρυψη παρωχημένων σχολίων
issues.review.show_outdated=Εμφάνιση παροχημένων
issues.review.hide_outdated=Απόκρυψη παροχημένων
issues.review.show_resolved=Εμφάνιση επιλυμένων
@@ -1596,6 +1700,13 @@ pulls.switch_comparison_type=Αλλαγή τύπου σύγκρισης
pulls.switch_head_and_base=Αλλαγή κεφαλής και βάσης
pulls.filter_branch=Φιλτράρισμα κλάδου
pulls.no_results=Δεν βρέθηκαν αποτελέσματα.
+pulls.show_all_commits=Εμφάνιση όλων των υποβολών
+pulls.show_changes_since_your_last_review=Εμφάνιση αλλαγών από την τελευταία αξιολόγηση
+pulls.showing_only_single_commit=Εμφάνιση μόνο αλλαγών της υποβολής %[1]s
+pulls.showing_specified_commit_range=Εμφάνιση μόνο των αλλαγών μεταξύ %[1]s..%[2]s
+pulls.select_commit_hold_shift_for_range=Επιλέξτε υποβολή. Κρατήστε πατημένο το shift + κάντε κλικ για να επιλέξετε ένα εύρος
+pulls.review_only_possible_for_full_diff=Η αξιολόγηση είναι δυνατή μόνο κατά την προβολή της πλήρης διαφοράς
+pulls.filter_changes_by_commit=Φιλτράρισμα κατά υποβολή
pulls.nothing_to_compare=Αυτοί οι κλάδοι είναι όμοιοι. Δεν υπάρχει ανάγκη να δημιουργήσετε ένα pull request.
pulls.nothing_to_compare_and_allow_empty_pr=Αυτοί οι κλάδοι είναι ίσοι. Αυτό το PR θα είναι κενό.
pulls.has_pull_request=`Υπάρχει ήδη pull request μεταξύ αυτών των κλάδων: %[2]s#%[3]d `
@@ -1627,6 +1738,12 @@ pulls.is_empty=Οι αλλαγές σε αυτόν τον κλάδο είναι
pulls.required_status_check_failed=Ορισμένοι απαιτούμενοι έλεγχοι δεν ήταν επιτυχείς.
pulls.required_status_check_missing=Λείπουν ορισμένοι απαιτούμενοι έλεγχοι.
pulls.required_status_check_administrator=Ως διαχειριστής, μπορείτε ακόμα να συγχωνεύσετε αυτό το pull request.
+pulls.blocked_by_approvals=Το pull request δεν έχει ακόμα αρκετές εγκρίσεις. Δόθηκαν %d από %d εγκρίσεις.
+pulls.blocked_by_rejection=Αυτό το Pull Request έχει αλλαγές που ζητούνται από έναν επίσημο εξεταστή.
+pulls.blocked_by_official_review_requests=Αυτό το Pull Request έχει επίσημες αιτήσεις αξιολόγησης.
+pulls.blocked_by_outdated_branch=Αυτό το pull request έχει αποκλειστεί επειδή είναι παρωχημένο.
+pulls.blocked_by_changed_protected_files_1=Αυτό το pull request έχει αποκλειστεί επειδή αλλάζει ένα προστατευμένο αρχείο:
+pulls.blocked_by_changed_protected_files_n=Αυτό το pull request έχει αποκλειστεί επειδή αλλάζει προστατευμένα αρχεία:
pulls.can_auto_merge_desc=Αυτό το Pull Request μπορεί να συγχωνευθεί αυτόματα.
pulls.cannot_auto_merge_desc=Αυτό το pull request δεν μπορεί να συγχωνευθεί αυτόματα λόγω συγκρούσεων.
pulls.cannot_auto_merge_helper=Χειροκίνητη Συγχώνευση για την επίλυση των συγκρούσεων.
@@ -1661,6 +1778,7 @@ pulls.rebase_conflict_summary=Μήνυμα Σφάλματος
pulls.unrelated_histories=H Συγχώνευση Απέτυχε: Η κεφαλή και η βάση της συγχώνευσης δεν μοιράζονται μια κοινή ιστορία. Συμβουλή: Δοκιμάστε μια διαφορετική στρατηγική
pulls.merge_out_of_date=Η συγχώνευση απέτυχε: Κατά τη δημιουργία της συγχώνευσης, η βάση ενημερώθηκε. Συμβουλή: Δοκιμάστε ξανά.
pulls.head_out_of_date=Η συγχώνευση απέτυχε: Κατά τη δημιουργία της συγχώνευσης, το HEAD ενημερώθηκε. Συμβουλή: Δοκιμάστε ξανά.
+pulls.has_merged=Αποτυχία: Το pull request έχει συγχωνευθεί, δεν είναι δυνατή η συγχώνευση ξανά ή να αλλάξει ο κλάδος προορισμού.
pulls.push_rejected=Η συγχώνευση απέτυχε: Η ώθηση απορρίφθηκε. Ελέγξτε τα Άγκιστρα Git για αυτό το αποθετήριο.
pulls.push_rejected_summary=Μήνυμα Πλήρους Απόρριψης
pulls.push_rejected_no_message=H Συγχώνευση Aπέτυχε: Η ώθηση απορρίφθηκε, αλλά δεν υπήρχε απομακρυσμένο μήνυμα. Ελέγξτε τα Άγκιστρα Git για αυτό το αποθετήριο
@@ -1672,6 +1790,8 @@ pulls.status_checks_failure=Κάποιοι έλεγχοι απέτυχαν
pulls.status_checks_error=Ορισμένοι έλεγχοι ανέφεραν σφάλματα
pulls.status_checks_requested=Απαιτείται
pulls.status_checks_details=Λεπτομέρειες
+pulls.status_checks_hide_all=Απόκρυψη όλων των ελέγχων
+pulls.status_checks_show_all=Εμφάνιση όλων των ελέγχων
pulls.update_branch=Ενημέρωση κλάδου με συγχώνευση
pulls.update_branch_rebase=Ενημέρωση κλάδου με rebase
pulls.update_branch_success=Η ενημέρωση του κλάδου ήταν επιτυχής
@@ -1680,6 +1800,11 @@ pulls.outdated_with_base_branch=Αυτός ο κλάδος δεν είναι ε
pulls.close=Κλείσιμο Pull Request
pulls.closed_at=`έκλεισε αυτό το pull request %[2]s `
pulls.reopened_at=`άνοιξε ξανά αυτό το pull request %[2]s `
+pulls.cmd_instruction_hint=`Δείτε τις οδηγίες γραμμής εντολών .`
+pulls.cmd_instruction_checkout_title=Έλεγχος
+pulls.cmd_instruction_checkout_desc=Από το αποθετήριο του έργου σας, ελέγξτε έναν νέο κλάδο και δοκιμάστε τις αλλαγές.
+pulls.cmd_instruction_merge_title=Συγχώνευση
+pulls.cmd_instruction_merge_desc=Συγχώνευση των αλλαγών και ενημέρωση στο Gitea.
pulls.clear_merge_message=Εκκαθάριση μηνύματος συγχώνευσης
pulls.clear_merge_message_hint=Η εκκαθάριση του μηνύματος συγχώνευσης θα αφαιρέσει μόνο το περιεχόμενο του μηνύματος υποβολής και θα διατηρήσει τα παραγόμενα git trailers όπως "Co-Authored-By …".
@@ -1698,7 +1823,9 @@ pulls.auto_merge_canceled_schedule_comment=`ακύρωσε την αυτόματ
pulls.delete.title=Διαγραφή αυτού του pull request;
pulls.delete.text=Θέλετε πραγματικά να διαγράψετε αυτό το pull request; (Αυτό θα σβήσει οριστικά όλο το περιεχόμενο του. Εξετάστε αν θέλετε να το κλείσετε, αν σκοπεύεται να το αρχειοθετήσετε)
+pulls.recently_pushed_new_branches=Ωθήσατε στο κλάδο %[1]s %[2]s
+pull.deleted_branch=(διαγράφηκε):%s
milestones.new=Νέο Ορόσημο
milestones.closed=Έκλεισε %s
@@ -1706,6 +1833,7 @@ milestones.update_ago=Ενημερώθηκε %s
milestones.no_due_date=Δεν υπάρχει ημερομηνία παράδοσης
milestones.open=Άνοιγμα
milestones.close=Κλείσιμο
+milestones.new_subheader=Τα ορόσημα μπορούν να σας βοηθήσουν να οργανώσετε τα ζητήματα και να παρακολουθείτε την πρόοδό τους.
milestones.completeness=%d%% Ολοκληρώθηκε
milestones.create=Δημιουργία Ορόσημου
milestones.title=Τίτλος
@@ -1722,11 +1850,26 @@ milestones.edit_success=Το ορόσημο "%s" ενημερώθηκε.
milestones.deletion=Διαγραφή Ορόσημου
milestones.deletion_desc=Η διαγραφή ενός ορόσημου το αφαιρεί από όλα τα συναφή ζητήματα. Συνέχεια;
milestones.deletion_success=Το ορόσημο έχει διαγραφεί.
+milestones.filter_sort.earliest_due_data=Πλησιέστερη παράδοση
+milestones.filter_sort.latest_due_date=Απώτερη παράδοση
milestones.filter_sort.least_complete=Λιγότερο πλήρη
milestones.filter_sort.most_complete=Περισσότερο πλήρη
milestones.filter_sort.most_issues=Περισσότερα ζητήματα
milestones.filter_sort.least_issues=Λιγότερα ζητήματα
+signing.will_sign=Αυτή η υποβολή θα υπογραφεί με το κλειδί "%s".
+signing.wont_sign.error=Παρουσιάστηκε σφάλμα κατά τον έλεγχο για το αν η υποβολή μπορεί να υπογραφεί.
+signing.wont_sign.nokey=Δεν υπάρχει διαθέσιμο κλειδί για να υπογραφεί αυτή η υποβολή.
+signing.wont_sign.never=Οι υποβολές δεν υπογράφονται ποτέ.
+signing.wont_sign.always=Οι υποβολές υπογράφονται πάντα.
+signing.wont_sign.pubkey=Η υποβολή δε θα υπογραφεί επειδή δεν υπάρχει δημόσιο κλειδί που να συνδέεται με το λογαριασμό σας.
+signing.wont_sign.twofa=Πρέπει να έχετε ενεργοποιημένη την ταυτοποίηση δύο παραγόντων για να υπογράφεται υποβολές.
+signing.wont_sign.parentsigned=Η υποβολή δε θα υπογραφεί καθώς η γονική υποβολή δεν έχει υπογραφεί.
+signing.wont_sign.basesigned=Η συγχώνευση δε θα υπογραφεί καθώς η βασική υποβολή δεν έχει υπογραφή της βάσης.
+signing.wont_sign.headsigned=Η συγχώνευση δε θα υπογραφεί καθώς δεν έχει υπογραφή η υποβολή της κεφαλής.
+signing.wont_sign.commitssigned=Η συγχώνευση δε θα υπογραφεί καθώς όλες οι σχετικές υποβολές δεν έχουν υπογραφεί.
+signing.wont_sign.approved=Η συγχώνευση δε θα υπογραφεί καθώς το PR δεν έχει εγκριθεί.
+signing.wont_sign.not_signed_in=Δεν είστε συνδεδεμένοι.
ext_wiki=Πρόσβαση στο Εξωτερικό Wiki
ext_wiki.desc=Σύνδεση σε ένα εξωτερικό wiki.
@@ -1824,6 +1967,8 @@ activity.git_stats_and_deletions=και
activity.git_stats_deletion_1=%d διαγραφή
activity.git_stats_deletion_n=%d διαγραφές
+contributors.contribution_type.commits=Υποβολές
+
search=Αναζήτηση
search.search_repo=Αναζήτηση αποθετηρίου
search.type.tooltip=Τύπος αναζήτησης
@@ -1856,7 +2001,9 @@ settings.mirror_settings.docs.disabled_push_mirror.info=Τα είδωλα ώθη
settings.mirror_settings.docs.no_new_mirrors=Το αποθετήριο σας αντιγράφει τις αλλαγές προς ή από ένα άλλο αποθετήριο. Λάβετε υπόψη ότι δεν μπορείτε να δημιουργήσετε νέα είδωλα αυτή τη στιγμή.
settings.mirror_settings.docs.can_still_use=Αν και δεν μπορείτε να τροποποιήσετε τα υπάρχοντα είδωλα ή να δημιουργήσετε νέα, μπορείτε να χρησιμοποιείται ακόμα το υπάρχων είδωλο.
settings.mirror_settings.docs.pull_mirror_instructions=Για να ορίσετε έναν είδωλο έλξης, παρακαλούμε συμβουλευθείτε:
+settings.mirror_settings.docs.more_information_if_disabled=Μπορείτε να μάθετε περισσότερα για τα είδωλα ώθησης και έλξης εδώ:
settings.mirror_settings.docs.doc_link_title=Πώς μπορώ να αντιγράψω αποθετήρια;
+settings.mirror_settings.docs.doc_link_pull_section=το κεφάλαιο "Pulling from a remote repository" της τεκμηρίωσης.
settings.mirror_settings.docs.pulling_remote_title=Έλξη από ένα απομακρυσμένο αποθετήριο
settings.mirror_settings.mirrored_repository=Είδωλο αποθετηρίου
settings.mirror_settings.direction=Κατεύθυνση
@@ -1866,8 +2013,11 @@ settings.mirror_settings.last_update=Τελευταία ενημέρωση
settings.mirror_settings.push_mirror.none=Δεν έχουν ρυθμιστεί είδωλα ώθησης
settings.mirror_settings.push_mirror.remote_url=URL Απομακρυσμένου Αποθετηρίου Git
settings.mirror_settings.push_mirror.add=Προσθήκη Είδωλου Push
+settings.mirror_settings.push_mirror.edit_sync_time=Επεξεργασία διαστήματος συγχρονισμού ειδώλου
settings.sync_mirror=Συγχρονισμός Τώρα
+settings.pull_mirror_sync_in_progress=Έλκονται αλλαγές από το απομακρυσμένο %s αυτή τη στιγμή.
+settings.push_mirror_sync_in_progress=Ώθηση αλλαγών στο απομακρυσμένο %s αυτή τη στιγμή.
settings.site=Ιστοσελίδα
settings.update_settings=Ενημέρωση Ρυθμίσεων
settings.update_mirror_settings=Ενημέρωση Ρυθμίσεων Ειδώλου
@@ -1934,6 +2084,7 @@ settings.transfer.rejected=Η μεταβίβαση του αποθετηρίου
settings.transfer.success=Η μεταβίβαση του αποθετηρίου ήταν επιτυχής.
settings.transfer_abort=Ακύρωση μεταβίβασης
settings.transfer_abort_invalid=Δεν μπορείτε να ακυρώσετε μια ανύπαρκτη μεταβίβαση αποθετηρίου.
+settings.transfer_abort_success=Η μεταφορά αποθετηρίου στο %s ακυρώθηκε με επιτυχία.
settings.transfer_desc=Μεταβιβάστε αυτό το αποθετήριο σε έναν χρήστη ή σε έναν οργανισμό για τον οποίο έχετε δικαιώματα διαχειριστή.
settings.transfer_form_title=Εισάγετε το όνομα του αποθετηρίου ως επιβεβαίωση:
settings.transfer_in_progress=Αυτή τη στιγμή υπάρχει μια εν εξελίξει μεταβίβαση. Παρακαλούμε ακυρώστε την αν θέλετε να μεταβιβάσετε αυτό το αποθετήριο σε άλλο χρήστη.
@@ -2000,12 +2151,14 @@ settings.webhook_deletion_desc=Η αφαίρεση ενός webhook διαγρά
settings.webhook_deletion_success=Το webhook έχει αφαιρεθεί.
settings.webhook.test_delivery=Δοκιμή Παράδοσης
settings.webhook.test_delivery_desc=Δοκιμάστε αυτό το webhook με ένα ψεύτικο συμβάν.
+settings.webhook.test_delivery_desc_disabled=Για να δοκιμάσετε αυτό το webhook με μια ψεύτικη κλήση, ενεργοποιήστε το.
settings.webhook.request=Αίτημα
settings.webhook.response=Απάντηση
settings.webhook.headers=Κεφαλίδες
settings.webhook.payload=Περιεχόμενο
settings.webhook.body=Σώμα
settings.webhook.replay.description=Επανάληψη αυτού του webhook.
+settings.webhook.replay.description_disabled=Για να επαναλάβετε αυτό το webhook, ενεργοποιήστε το.
settings.webhook.delivery.success=Ένα γεγονός έχει προστεθεί στην ουρά παράδοσης. Μπορεί να χρειαστούν λίγα δευτερόλεπτα μέχρι να εμφανιστεί στο ιστορικό.
settings.githooks_desc=Τα Άγκιστρα Git παρέχονται από το ίδιο το Git. Μπορείτε να επεξεργαστείτε τα αρχεία αγκίστρων παρακάτω για να ρυθμίσετε προσαρμοσμένες λειτουργίες.
settings.githook_edit_desc=Αν το hook είναι ανενεργό, θα παρουσιαστεί ένα παράδειγμα. Αφήνοντας το περιεχόμενο του hook κενό θα το απενεργοποιήσετε.
@@ -2165,6 +2318,7 @@ settings.dismiss_stale_approvals_desc=Όταν οι νέες υποβολές π
settings.require_signed_commits=Απαιτούνται Υπογεγραμμένες Υποβολές
settings.require_signed_commits_desc=Απόρριψη νέων υποβολών σε αυτόν τον κλάδο εάν είναι μη υπογεγραμμένες ή μη επαληθεύσιμες.
settings.protect_branch_name_pattern=Μοτίβο Προστατευμένου Ονόματος Κλάδου
+settings.protect_branch_name_pattern_desc=Μοτίβα ονόματος προστατευμένων κλάδων. Δείτε την τεκμηρίωση για σύνταξη μοτίβου. Παραδείγματα: main, release/**
settings.protect_patterns=Μοτίβα
settings.protect_protected_file_patterns=Μοτίβα προστατευμένων αρχείων (διαχωρισμένα με ερωτηματικό ';'):
settings.protect_protected_file_patterns_desc=Τα προστατευόμενα αρχεία δεν επιτρέπεται να αλλάξουν άμεσα, ακόμη και αν ο χρήστης έχει δικαιώματα να προσθέσει, να επεξεργαστεί ή να διαγράψει αρχεία σε αυτόν τον κλάδο. Επιπλέων μοτίβα μπορούν να διαχωριστούν με ερωτηματικό (';'). Δείτε την τεκμηρίωση github.com/gobwas/glob για τη σύνταξη του μοτίβου. Πχ: .drone.yml
, /docs/**/*.txt
.
@@ -2201,18 +2355,26 @@ settings.tags.protection.allowed.teams=Επιτρεπόμενες ομάδες
settings.tags.protection.allowed.noone=Καμία
settings.tags.protection.create=Προστασία Ετικέτας
settings.tags.protection.none=Δεν υπάρχουν προστατευμένες ετικέτες.
+settings.tags.protection.pattern.description=Μπορείτε να χρησιμοποιήσετε ένα μόνο όνομα ή ένα μοτίβο τύπου glob ή κανονική έκφραση για να ταιριάξετε πολλαπλές ετικέτες. Διαβάστε περισσότερα στον οδηγό προστατευμένων ετικετών .
settings.bot_token=Διακριτικό Bot
settings.chat_id=ID Συνομιλίας
+settings.thread_id=ID Νήματος
settings.matrix.homeserver_url=Homeserver URL
settings.matrix.room_id=ID Δωματίου
settings.matrix.message_type=Τύπος Μηνύματος
settings.archive.button=Αρχειοθέτηση Αποθετηρίου
settings.archive.header=Αρχειοθέτηση Αυτού του Αποθετηρίου
+settings.archive.text=Η αρχειοθέτηση του αποθετηρίου θα το αλλάξει σε μόνο για ανάγνωση. Δε θα φαίνεται στον αρχικό πίνακα. Κανείς (ακόμα και εσείς!) δε θα μπορεί να κάνει νέες υποβολές, ή να ανοίξει ζητήματα ή pull request.
settings.archive.success=Το αποθετήριο αρχειοθετήθηκε με επιτυχία.
settings.archive.error=Παρουσιάστηκε σφάλμα κατά την προσπάθεια αρχειοθέτησης του αποθετηρίου. Δείτε το αρχείο καταγραφής για περισσότερες λεπτομέρειες.
settings.archive.error_ismirror=Δε μπορείτε να αρχειοθετήσετε ένα είδωλο αποθετηρίου.
settings.archive.branchsettings_unavailable=Οι ρυθμίσεις του κλάδου δεν είναι διαθέσιμες αν το αποθετήριο είναι αρχειοθετημένο.
settings.archive.tagsettings_unavailable=Οι ρυθμίσεις της ετικέτας δεν είναι διαθέσιμες αν το αποθετήριο είναι αρχειοθετημένο.
+settings.unarchive.button=Απο-Αρχειοθέτηση αποθετηρίου
+settings.unarchive.header=Απο-Αρχειοθέτηση του αποθετηρίου
+settings.unarchive.text=Η απο-αρχειοθέτηση του αποθετηρίου θα αποκαταστήσει την ικανότητά του να λαμβάνει υποβολές και ωθήσεις, καθώς και νέα ζητήματα και pull-requests.
+settings.unarchive.success=Το αποθετήριο απο-αρχειοθετήθηκε με επιτυχία.
+settings.unarchive.error=Παρουσιάστηκε σφάλμα κατά την προσπάθεια απο-αρχειοθέτησης του αποθετηρίου. Δείτε τις καταγραφές για περισσότερες λεπτομέρειες.
settings.update_avatar_success=Η εικόνα του αποθετηρίου έχει ενημερωθεί.
settings.lfs=LFS
settings.lfs_filelist=Αρχεία LFS σε αυτό το αποθετήριο
@@ -2279,6 +2441,7 @@ diff.show_more=Εμφάνιση Περισσότερων
diff.load=Φόρτωση Διαφορών
diff.generated=δημιουργημένο
diff.vendored=εξωτερικό
+diff.comment.add_line_comment=Προσθήκη σχολίου στη γραμμή
diff.comment.placeholder=Αφήστε ένα σχόλιο
diff.comment.markdown_info=Υποστηρίζεται στυλ με markdown.
diff.comment.add_single_comment=Προσθέστε ένα σχόλιο
@@ -2335,6 +2498,7 @@ release.edit_release=Ενημέρωση Κυκλοφορίας
release.delete_release=Διαγραφή Κυκλοφορίας
release.delete_tag=Διαγραφή Ετικέτας
release.deletion=Διαγραφή Κυκλοφορίας
+release.deletion_desc=Διαγράφοντας μια κυκλοφορία, αυτή αφαιρείται μόνο από το Gitea. Δε θα επηρεάσει την ετικέτα Git, τα περιεχόμενα του αποθετηρίου σας ή το ιστορικό της. Συνέχεια;
release.deletion_success=Η κυκλοφορία έχει διαγραφεί.
release.deletion_tag_desc=Θα διαγράψει αυτή την ετικέτα από το αποθετήριο. Τα περιεχόμενα του αποθετηρίου και το ιστορικό παραμένουν αμετάβλητα. Συνέχεια;
release.deletion_tag_success=Η ετικέτα έχει διαγραφεί.
@@ -2354,6 +2518,7 @@ branch.already_exists=Ήδη υπάρχει ένας κλάδος με το όν
branch.delete_head=Διαγραφή
branch.delete=`Διαγραφή του Κλάδου "%s"`
branch.delete_html=Διαγραφή Κλάδου
+branch.delete_desc=Η διαγραφή ενός κλάδου είναι μόνιμη. Αν και ο διαγραμμένος κλάδος μπορεί να συνεχίσει να υπάρχει για σύντομο χρονικό διάστημα πριν να αφαιρεθεί, ΔΕΝ ΜΠΟΡΕΙ να αναιρεθεί στις περισσότερες περιπτώσεις. Συνέχεια;
branch.deletion_success=Ο κλάδος "%s" διαγράφηκε.
branch.deletion_failed=Αποτυχία διαγραφής του κλάδου "%s".
branch.delete_branch_has_new_commits=Ο κλάδος "%s" δεν μπορεί να διαγραφεί επειδή προστέθηκαν νέες υποβολές μετά τη συγχώνευση.
@@ -2371,6 +2536,7 @@ branch.default_deletion_failed=Ο κλάδος "%s" είναι ο προεπιλ
branch.restore=`Επαναφορά του Κλάδου "%s"`
branch.download=`Λήψη του Κλάδου "%s"`
branch.rename=`Μετονομασία Κλάδου "%s"`
+branch.search=Αναζήτηση Κλάδου
branch.included_desc=Αυτός ο κλάδος είναι μέρος του προεπιλεγμένου κλάδου
branch.included=Περιλαμβάνεται
branch.create_new_branch=Δημιουργία κλάδου από κλάδο:
@@ -2393,6 +2559,7 @@ tag.create_success=Η ετικέτα "%s" δημιουργήθηκε.
topic.manage_topics=Διαχείριση Θεμάτων
topic.done=Ολοκληρώθηκε
topic.count_prompt=Δεν μπορείτε να επιλέξετε περισσότερα από 25 θέματα
+topic.format_prompt=Τα θέματα πρέπει να ξεκινούν με γράμμα ή αριθμό, μπορούν να περιλαμβάνουν παύλες ('-') και τελείες ('.'), μπορεί να είναι μέχρι 35 χαρακτήρες. Τα γράμματα πρέπει να είναι πεζά.
find_file.go_to_file=Αναζήτηση αρχείου
find_file.no_matching=Δεν ταιριάζει κανένα αρχείο
@@ -2401,6 +2568,8 @@ error.csv.too_large=Δεν είναι δυνατή η απόδοση αυτού
error.csv.unexpected=Δεν είναι δυνατή η απόδοση αυτού του αρχείου, επειδή περιέχει έναν μη αναμενόμενο χαρακτήρα στη γραμμή %d και στη στήλη %d.
error.csv.invalid_field_count=Δεν είναι δυνατή η απόδοση αυτού του αρχείου, επειδή έχει λάθος αριθμό πεδίων στη γραμμή %d.
+[graphs]
+
[org]
org_name_holder=Όνομα Οργανισμού
org_full_name_holder=Πλήρες Όνομα Οργανισμού
@@ -2431,6 +2600,7 @@ form.create_org_not_allowed=Δεν επιτρέπεται να δημιουργ
settings=Ρυθμίσεις
settings.options=Οργανισμός
settings.full_name=Πλήρες Όνομα
+settings.email=Email Επικοινωνίας
settings.website=Ιστοσελίδα
settings.location=Τοποθεσία
settings.permission=Δικαιώματα
@@ -2444,6 +2614,7 @@ settings.visibility.private_shortname=Ιδιωτικός
settings.update_settings=Ενημέρωση Ρυθμίσεων
settings.update_setting_success=Οι ρυθμίσεις του οργανισμού έχουν ενημερωθεί.
+settings.change_orgname_prompt=Σημείωση: Η αλλαγή του ονόματος του οργανισμού θα αλλάξει επίσης τη διεύθυνση URL του οργανισμού σας και θα απελευθερώσει το παλιό όνομα.
settings.change_orgname_redirect_prompt=Το παλιό όνομα θα ανακατευθύνει μέχρι να διεκδικηθεί.
settings.update_avatar_success=Η εικόνα του οργανισμού έχει ενημερωθεί.
settings.delete=Διαγραφή Οργανισμού
@@ -2519,15 +2690,19 @@ teams.all_repositories_helper=Η ομάδα έχει πρόσβαση σε όλ
teams.all_repositories_read_permission_desc=Αυτή η ομάδα χορηγεί πρόσβαση Ανάγνωσης σε όλα τα αποθετήρια : τα μέλη μπορούν να δουν και να κλωνοποιήσουν αποθετήρια.
teams.all_repositories_write_permission_desc=Αυτή η ομάδα χορηγεί πρόσβαση Εγγραφής σε όλα τα αποθετήρια : τα μέλη μπορούν να διαβάσουν και να κάνουν push σε αποθετήρια.
teams.all_repositories_admin_permission_desc=Αυτή η ομάδα παρέχει πρόσβαση Διαχείρισης σε όλα τα αποθετήρια : τα μέλη μπορούν να διαβάσουν, να κάνουν push και να προσθέσουν συνεργάτες στα αποθετήρια.
+teams.invite.title=Έχετε προσκληθεί να συμμετάσχετε στην ομάδα %s του οργανισμού %s .
teams.invite.by=Προσκλήθηκε από %s
teams.invite.description=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για συμμετοχή στην ομάδα.
[admin]
dashboard=Πίνακας Ελέγχου
+identity_access=Ταυτότητα & Πρόσβαση
users=Λογαριασμοί Χρήστη
organizations=Οργανισμοί
+assets=Στοιχεία Κώδικα
repositories=Αποθετήρια
hooks=Webhooks
+integrations=Ενσωματώσεις
authentication=Πηγές Ταυτοποίησης
emails=Email Χρήστη
config=Διαμόρφωση
@@ -2536,6 +2711,7 @@ monitor=Παρακολούθηση
first_page=Πρώτο
last_page=Τελευταίο
total=Σύνολο: %d
+settings=Ρυθμίσεις Διαχειριστή
dashboard.new_version_hint=Το Gitea %s είναι διαθέσιμο, τώρα εκτελείτε το %s. Ανατρέξτε στο blog για περισσότερες λεπτομέρειες.
dashboard.statistic=Περίληψη
@@ -2548,11 +2724,13 @@ dashboard.clean_unbind_oauth=Εκκαθάριση μη δεσμευμένων σ
dashboard.clean_unbind_oauth_success=Όλες οι μη δεσμευμένες συνδέσεις OAuth διαγράφηκαν.
dashboard.task.started=Εκκίνηση Εργασίας: %[1]s
dashboard.task.process=Εργασία: %[1]s
+dashboard.task.cancelled=Εργασία: %[1]ακυρώθηκε: %[3]s
dashboard.task.error=Σφάλμα στην Εργασία: %[1]s: %[3]s
dashboard.task.finished=Εργασία: %[1]s που εκκινήθηκε από %[2]s τελείωσε
dashboard.task.unknown=Άγνωστη εργασία: %[1]s
dashboard.cron.started=Εκκίνηση Προγραμματισμένης Εργασίας: %[1]s
dashboard.cron.process=Προγραμματισμένη Εργασία: %[1]s
+dashboard.cron.cancelled=Προγραμματισμένη εργασία: %[1]s ακυρώθηκε: %[3]s
dashboard.cron.error=Σφάλμα στη Προγραμματισμένη Εργασία: %s: %[3]s
dashboard.cron.finished=Προγραμματισμένη Εργασία: %[1]s τελείωσε
dashboard.delete_inactive_accounts=Διαγραφή όλων των μη ενεργοποιημένων λογαριασμών
@@ -2562,6 +2740,7 @@ dashboard.delete_repo_archives.started=Η διαγραφή όλων των αρ
dashboard.delete_missing_repos=Διαγραφή όλων των αποθετηρίων που δεν έχουν τα αρχεία Git τους
dashboard.delete_missing_repos.started=Η διαγραφή όλων των αποθετηρίων που δεν έχουν αρχεία Git τους, ξεκίνησε.
dashboard.delete_generated_repository_avatars=Διαγραφή δημιουργημένων εικόνων αποθετηρίων
+dashboard.sync_repo_branches=Συγχρονισμός κλάδων που λείπουν, από τα δεδομένα git στις βάσεις δεδομένων
dashboard.update_mirrors=Ενημέρωση Ειδώλων
dashboard.repo_health_check=Έλεγχος υγείας σε όλα τα αποθετήρια
dashboard.check_repo_stats=Έλεγχος όλων των στατιστικών αποθετηρίων
@@ -2576,6 +2755,7 @@ dashboard.reinit_missing_repos=Επανεκκινήστε όλα τα αποθε
dashboard.sync_external_users=Συγχρονισμός δεδομένων εξωτερικών χρηστών
dashboard.cleanup_hook_task_table=Εκκαθάριση πίνακα hook_task
dashboard.cleanup_packages=Εκκαθάριση ληγμένων πακέτων
+dashboard.cleanup_actions=Οι ενέργειες καθαρισμού καταγραφές και αντικείμενα
dashboard.server_uptime=Διάρκεια Διακομιστή
dashboard.current_goroutine=Τρέχουσες Goroutines
dashboard.current_memory_usage=Τρέχουσα Χρήση Μνήμης
@@ -2613,6 +2793,9 @@ dashboard.gc_lfs=Συλλογή απορριμάτων στα μετα-αντι
dashboard.stop_zombie_tasks=Διακοπή εργασιών ζόμπι
dashboard.stop_endless_tasks=Διακοπή ατελείωτων εργασιών
dashboard.cancel_abandoned_jobs=Ακύρωση εγκαταλελειμμένων εργασιών
+dashboard.start_schedule_tasks=Έναρξη προγραμματισμένων εργασιών
+dashboard.sync_branch.started=Ο Συγχρονισμός των Κλάδων ξεκίνησε
+dashboard.rebuild_issue_indexer=Αναδόμηση ευρετηρίου ζητημάτων
users.user_manage_panel=Διαχείριση Λογαριασμών Χρηστών
users.new_account=Δημιουργία Λογαριασμού Χρήστη
@@ -2621,6 +2804,9 @@ users.full_name=Πλήρες Όνομα
users.activated=Ενεργοποιήθηκε
users.admin=Διαχειριστής
users.restricted=Περιορισμένος
+users.reserved=Δεσμευμένο
+users.bot=Bot
+users.remote=Απομακρυσμένο
users.2fa=2FA
users.repos=Αποθετήρια
users.created=Δημιουργήθηκε
@@ -2667,6 +2853,7 @@ users.list_status_filter.is_prohibit_login=Απαγόρευση Σύνδεσης
users.list_status_filter.not_prohibit_login=Επιτρέπεται η Σύνδεση
users.list_status_filter.is_2fa_enabled=2FA Ενεργοποιημένο
users.list_status_filter.not_2fa_enabled=2FA Απενεργοποιημένο
+users.details=Λεπτομέρειες Χρήστη
emails.email_manage_panel=Διαχείριση Email Χρήστη
emails.primary=Κύριο
@@ -2679,6 +2866,7 @@ emails.updated=Το email ενημερώθηκε
emails.not_updated=Αποτυχία ενημέρωσης της ζητούμενης διεύθυνσης email: %v
emails.duplicate_active=Αυτή η διεύθυνση email είναι ήδη ενεργή σε διαφορετικό χρήστη.
emails.change_email_header=Ενημέρωση Ιδιοτήτων Email
+emails.change_email_text=Είστε βέβαιοι ότι θέλετε να ενημερώσετε αυτή τη διεύθυνση email;
orgs.org_manage_panel=Διαχείριση Οργανισμού
orgs.name=Όνομα
@@ -2697,10 +2885,13 @@ repos.stars=Αστέρια
repos.forks=Forks
repos.issues=Ζητήματα
repos.size=Μέγεθος
+repos.lfs_size=Μέγεθος LFS
packages.package_manage_panel=Διαχείριση Πακέτων
packages.total_size=Συνολικό Μέγεθος: %s
packages.unreferenced_size=Μέγεθος Χωρίς Αναφορά: %s
+packages.cleanup=Εκκαθάριση ληγμένων δεδομένων
+packages.cleanup.success=Επιτυχής εκκαθάριση δεδομένων που έχουν λήξει
packages.owner=Ιδιοκτήτης
packages.creator=Δημιουργός
packages.name=Όνομα
@@ -2711,10 +2902,12 @@ packages.size=Μέγεθος
packages.published=Δημοσιευμένα
defaulthooks=Προεπιλεγμένα Webhooks
+defaulthooks.desc=Τα Webhooks κάνουν αυτόματα αιτήσεις HTTP POST σε ένα διακομιστή όταν ενεργοποιούν ορισμένα γεγονότα στο Gitea. Τα Webhooks που ορίζονται εδώ είναι προκαθορισμένα και θα αντιγραφούν σε όλα τα νέα αποθετήρια. Διαβάστε περισσότερα στον οδηγό webhooks .
defaulthooks.add_webhook=Προσθήκη Προεπιλεγμένου Webhook
defaulthooks.update_webhook=Ενημέρωση Προεπιλεγμένου Webhook
systemhooks=Webhooks Συστήματος
+systemhooks.desc=Τα Webhooks κάνουν αυτόματα αιτήσεις HTTP POST σε ένα διακομιστή όταν ενεργοποιούνται ορισμένα γεγονότα στο Gitea. Τα Webhooks που ορίζονται εδώ θα ενεργούν σε όλα τα αποθετήρια του συστήματος, γι 'αυτό παρακαλώ εξετάστε τυχόν επιπτώσεις απόδοσης που μπορεί να έχει. Διαβάστε περισσότερα στον οδηγό webhooks .
systemhooks.add_webhook=Προσθήκη Webhook Συστήματος
systemhooks.update_webhook=Ενημέρωση Webhook Συστήματος
@@ -2807,6 +3000,7 @@ auths.sspi_default_language=Προεπιλεγμένη γλώσσα χρήστη
auths.sspi_default_language_helper=Προεπιλεγμένη γλώσσα για τους χρήστες που δημιουργούνται αυτόματα με τη μέθοδο ταυτοποίησης SSPI. Αφήστε κενό αν προτιμάτε η γλώσσα να εντοπιστεί αυτόματα.
auths.tips=Συμβουλές
auths.tips.oauth2.general=Ταυτοποίηση OAuth2
+auths.tips.oauth2.general.tip=Κατά την εγγραφή μιας νέας ταυτοποίησης OAuth2, το URL κλήσης/ανακατεύθυνσης πρέπει να είναι:
auths.tip.oauth2_provider=Πάροχος OAuth2
auths.tip.bitbucket=Καταχωρήστε ένα νέο καταναλωτή OAuth στο https://bitbucket.org/account/user//oauth-consumers/new και προσθέστε το δικαίωμα 'Account' - 'Read'
auths.tip.nextcloud=`Καταχωρήστε ένα νέο καταναλωτή OAuth στην υπηρεσία σας χρησιμοποιώντας το παρακάτω μενού "Settings -> Security -> OAuth 2.0 client"`
@@ -2818,6 +3012,7 @@ auths.tip.google_plus=Αποκτήστε τα διαπιστευτήρια πε
auths.tip.openid_connect=Χρησιμοποιήστε το OpenID Connect Discovery URL (/.well known/openid-configuration) για να καθορίσετε τα τελικά σημεία
auths.tip.twitter=Πηγαίνετε στο https://dev.twitter.com/apps, δημιουργήστε μια εφαρμογή και βεβαιωθείτε ότι η επιλογή “Allow this application to be used to Sign in with Twitter” είναι ενεργοποιημένη
auths.tip.discord=Καταχωρήστε μια νέα εφαρμογή στο https://discordapp.com/developers/applications/me
+auths.tip.gitea=Καταχωρήστε μια νέα εφαρμογή OAuth2. Μπορείτε να βρείτε τον οδηγό στο https://docs.gitea.com/development/oauth2-provider
auths.tip.yandex=`Δημιουργήστε μια νέα εφαρμογή στο https://oauth.yandex.com/client/new. Επιλέξτε τα ακόλουθα δικαιώματα από την ενότητα "Yandex.Passport API": "Access to email address", "Access to user avatar" και "Access to username, first name and surname, gender"`
auths.tip.mastodon=Εισαγάγετε ένα προσαρμομένο URL για την υπηρεσία mastodon με την οποία θέλετε να πιστοποιήσετε (ή να χρησιμοποιήσετε την προεπιλεγμένη)
auths.edit=Επεξεργασία Πηγής Ταυτοποίησης
@@ -2847,6 +3042,7 @@ config.disable_router_log=Απενεργοποίηση Καταγραφής Δρ
config.run_user=Εκτέλεση Σαν Χρήστη
config.run_mode=Λειτουργία Εκτέλεσης
config.git_version=Έκδοση Git
+config.app_data_path=Διαδρομή Δεδομένων Εφαρμογής
config.repo_root_path=Ριζική Διαδρομή Αποθετηρίων
config.lfs_root_path=Ριζική Διαδρομή LFS
config.log_file_root_path=Διαδρομή Καταγραφών
@@ -2996,8 +3192,10 @@ monitor.queue.name=Όνομα
monitor.queue.type=Τύπος
monitor.queue.exemplar=Τύπος Υποδείγματος
monitor.queue.numberworkers=Αριθμός Εργατών
+monitor.queue.activeworkers=Ενεργοί Εργάτες
monitor.queue.maxnumberworkers=Μέγιστος Αριθμός Εργατών
monitor.queue.numberinqueue=Πλήθος Ουράς
+monitor.queue.review_add=Εξέταση / Προσθήκη Εργατών
monitor.queue.settings.title=Ρυθμίσεις Δεξαμενής
monitor.queue.settings.desc=Οι δεξαμενές αυξάνονται δυναμικά όταν υπάρχει φραγή της ουράς των εργατών τους.
monitor.queue.settings.maxnumberworkers=Μέγιστος Αριθμός Εργατών
@@ -3023,6 +3221,7 @@ notices.desc=Περιγραφή
notices.op=Λειτ.
notices.delete_success=Οι ειδοποιήσεις του συστήματος έχουν διαγραφεί.
+
[action]
create_repo=δημιούργησε το αποθετήριο %s
rename_repo=μετονόμασε το αποθετήριο από %[1]s
σε %[3]s
@@ -3118,6 +3317,7 @@ desc=Διαχείριση πακέτων μητρώου.
empty=Δεν υπάρχουν πακέτα ακόμα.
empty.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο πακέτων, ανατρέξτε στην τεκμηρίωση .
empty.repo=Μήπως ανεβάσατε ένα πακέτο, αλλά δεν εμφανίζεται εδώ; Πηγαίνετε στις ρυθμίσεις πακέτων και συνδέστε το σε αυτό το αποθετήριο.
+registry.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο %s, ανατρέξτε στη τεκμηρίωση .
filter.type=Τύπος
filter.type.all=Όλα
filter.no_result=Το φίλτρο δεν παρήγαγε αποτελέσματα.
@@ -3203,7 +3403,11 @@ pub.install=Για να εγκαταστήσετε το πακέτο μέσω τ
pypi.requires=Απαιτεί Python
pypi.install=Για να εγκαταστήσετε το πακέτο χρησιμοποιώντας το pip, εκτελέστε την ακόλουθη εντολή:
rpm.registry=Ρυθμίστε αυτό το μητρώο από τη γραμμή εντολών:
+rpm.distros.redhat=σε διανομές βασισμένες στο RedHat
+rpm.distros.suse=σε διανομές με βάση το SUSE
rpm.install=Για να εγκαταστήσετε το πακέτο, εκτελέστε την ακόλουθη εντολή:
+rpm.repository=Πληροφορίες Αποθετηρίου
+rpm.repository.architectures=Αρχιτεκτονικές
rubygems.install=Για να εγκαταστήσετε το πακέτο χρησιμοποιώντας το gem, εκτελέστε την ακόλουθη εντολή:
rubygems.install2=ή προσθέστε το στο Gemfile:
rubygems.dependencies.runtime=Εξαρτήσεις Εκτέλεσης
@@ -3227,14 +3431,17 @@ settings.delete.success=Το πακέτο έχει διαγραφεί.
settings.delete.error=Αποτυχία διαγραφής του πακέτου.
owner.settings.cargo.title=Ευρετήριο Μητρώου Cargo
owner.settings.cargo.initialize=Αρχικοποίηση Ευρετηρίου
+owner.settings.cargo.initialize.description=Απαιτείται ένα ειδικό αποθετήριο ευρετηρίου Git για τη χρήση του μητρώου Cargo. Χρησιμοποιώντας αυτή την επιλογή θα δημιουργηθεί ξανά το αποθετήριο και θα ρυθμιστεί αυτόματα.
owner.settings.cargo.initialize.error=Αποτυχία αρχικοποίησης ευρετηρίου Cargo: %v
owner.settings.cargo.initialize.success=Ο ευρετήριο Cargo δημιουργήθηκε με επιτυχία.
owner.settings.cargo.rebuild=Αναδημιουργία Ευρετηρίου
+owner.settings.cargo.rebuild.description=Η ανοικοδόμηση μπορεί να είναι χρήσιμη εάν ο δείκτης δεν είναι συγχρονισμένος με τα αποθηκευμένα πακέτα Cargo.
owner.settings.cargo.rebuild.error=Αποτυχία αναδόμησης του ευρετηρίου Cargo: %v
owner.settings.cargo.rebuild.success=Το ευρετήριο Cargo αναδομήθηκε με επιτυχία.
owner.settings.cleanuprules.title=Διαχείριση Κανόνων Εκκαθάρισης
owner.settings.cleanuprules.add=Προσθήκη Κανόνα Εκκαθάρισης
owner.settings.cleanuprules.edit=Επεξεργασία Κανόνα Εκκαθάρισης
+owner.settings.cleanuprules.none=Δεν υπάρχουν διαθέσιμοι κανόνες εκκαθάρισης. Παρακαλούμε συμβουλευτείτε την τεκμηρίωση.
owner.settings.cleanuprules.preview=Προεπισκόπηση Κανόνα Εκκαθάρισης
owner.settings.cleanuprules.preview.overview=%d πακέτα έχουν προγραμματιστεί να αφαιρεθούν.
owner.settings.cleanuprules.preview.none=Ο κανόνας εκκαθάρισης δεν ταιριάζει με κανένα πακέτο.
@@ -3253,6 +3460,7 @@ owner.settings.cleanuprules.success.update=Ο κανόνας καθαρισμο
owner.settings.cleanuprules.success.delete=Ο κανόνας καθαρισμού διαγράφηκε.
owner.settings.chef.title=Μητρώο Chef
owner.settings.chef.keypair=Δημιουργία ζεύγους κλειδιών
+owner.settings.chef.keypair.description=Ένα ζεύγος κλειδιών είναι απαραίτητο για ταυτοποίηση στο μητρώο Chef. Αν έχετε δημιουργήσει ένα ζεύγος κλειδιών πριν, η δημιουργία ενός νέου ζεύγους κλειδιών θα απορρίψει το παλιό ζεύγος κλειδιών.
[secrets]
secrets=Μυστικά
@@ -3279,6 +3487,7 @@ status.waiting=Αναμονή
status.running=Εκτελείται
status.success=Επιτυχές
status.failure=Αποτυχία
+status.cancelled=Ακυρώθηκε
status.skipped=Παρακάμφθηκε
status.blocked=Αποκλείστηκε
@@ -3295,6 +3504,7 @@ runners.labels=Ετικέτες
runners.last_online=Τελευταία Ώρα Σύνδεσης
runners.runner_title=Εκτελεστής
runners.task_list=Πρόσφατες εργασίες στον εκτελεστή
+runners.task_list.no_tasks=Δεν υπάρχει καμία εργασία ακόμα.
runners.task_list.run=Εκτέλεση
runners.task_list.status=Κατάσταση
runners.task_list.repository=Αποθετήριο
@@ -3315,16 +3525,46 @@ runners.status.idle=Αδρανής
runners.status.active=Ενεργό
runners.status.offline=Χωρίς Σύνδεση
runners.version=Έκδοση
+runners.reset_registration_token=Επαναφορά διακριτικού εγγραφής
runners.reset_registration_token_success=Επιτυχής επανέκδοση διακριτικού εγγραφής του εκτελεστή
runs.all_workflows=Όλες Οι Ροές Εργασίας
runs.commit=Υποβολή
+runs.scheduled=Προγραμματισμένα
+runs.pushed_by=ωθήθηκε από
runs.invalid_workflow_helper=Το αρχείο ροής εργασίας δεν είναι έγκυρο. Ελέγξτε το αρχείο σας: %s
+runs.no_matching_online_runner_helper=Κανένας δικτυακός δρομέας με ετικέτα: %s
+runs.actor=Φορέας
runs.status=Κατάσταση
+runs.actors_no_select=Όλοι οι φορείς
+runs.status_no_select=Όλες οι καταστάσεις
+runs.no_results=Δεν βρέθηκαν αποτελέσματα.
+runs.no_workflows=Δεν υπάρχουν ροές εργασίας ακόμα.
+runs.no_runs=Η ροή εργασίας δεν έχει τρέξει ακόμα.
+runs.empty_commit_message=(κενό μήνυμα υποβολής)
+workflow.disable=Απενεργοποίηση Ροής Εργασιών
+workflow.disable_success=Η ροή εργασίας '%s' απενεργοποιήθηκε επιτυχώς.
+workflow.enable=Ενεργοποίηση Ροής Εργασίας
+workflow.enable_success=Η ροή εργασίας '%s' ενεργοποιήθηκε επιτυχώς.
+workflow.disabled=Η ροή εργασιών είναι απενεργοποιημένη.
need_approval_desc=Πρέπει να εγκριθεί η εκτέλεση ροών εργασίας για pull request από fork.
+variables=Μεταβλητές
+variables.management=Διαχείριση Μεταβλητών
+variables.creation=Προσθήκη Μεταβλητής
+variables.none=Δεν υπάρχουν μεταβλητές ακόμα.
+variables.deletion=Αφαίρεση μεταβλητής
+variables.deletion.description=Η αφαίρεση μιας μεταβλητής είναι μόνιμη και δεν μπορεί να αναιρεθεί. Συνέχεια;
+variables.description=Η μεταβλητές θα δίνονται σε ορισμένες δράσεις και δεν μπορούν να διαβαστούν αλλιώς.
+variables.edit=Επεξεργασία Μεταβλητής
+variables.deletion.failed=Αποτυχία αφαίρεσης της μεταβλητής.
+variables.deletion.success=Η μεταβλητή έχει αφαιρεθεί.
+variables.creation.failed=Αποτυχία προσθήκης μεταβλητής.
+variables.creation.success=Η μεταβλητή "%s" έχει προστεθεί.
+variables.update.failed=Αποτυχία επεξεργασίας μεταβλητής.
+variables.update.success=Η μεταβλητή έχει τροποποιηθεί.
[projects]
type-1.display_name=Ατομικό Έργο
@@ -3332,6 +3572,11 @@ type-2.display_name=Έργο Αποθετηρίου
type-3.display_name=Έργο Οργανισμού
[git.filemode]
+changed_filemode=%[1]s → %[2]s
; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", …
+directory=Φάκελος
+normal_file=Κανονικό αρχείο
+executable_file=Εκτελέσιμο αρχείο
symbolic_link=Symbolic link
+submodule=Υπομονάδα
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 9af4d70171..a0ad09f776 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -123,6 +123,7 @@ pin = Pin
unpin = Unpin
artifacts = Artifacts
+confirm_delete_artifact = Are you sure you want to delete the artifact '%s' ?
archived = Archived
@@ -246,6 +247,7 @@ email_title = Email Settings
smtp_addr = SMTP Host
smtp_port = SMTP Port
smtp_from = Send Email As
+smtp_from_invalid = The "Send Email As" address is invalid
smtp_from_helper = Email address Gitea will use. Enter a plain email address or use the "Name" format.
mailer_user = SMTP Username
mailer_password = SMTP Password
@@ -954,7 +956,7 @@ fork_branch = Branch to be cloned to the fork
all_branches = All branches
fork_no_valid_owners = This repository can not be forked because there are no valid owners.
use_template = Use this template
-clone_in_vsc = Clone in VS Code
+open_with_editor = Open with %s
download_zip = Download ZIP
download_tar = Download TAR.GZ
download_bundle = Download BUNDLE
@@ -1775,6 +1777,7 @@ pulls.merge_pull_request = Create merge commit
pulls.rebase_merge_pull_request = Rebase then fast-forward
pulls.rebase_merge_commit_pull_request = Rebase then create merge commit
pulls.squash_merge_pull_request = Create squash commit
+pulls.fast_forward_only_merge_pull_request = Fast-forward only
pulls.merge_manually = Manually merged
pulls.merge_commit_id = The merge commit ID
pulls.require_signed_wont_sign = The branch requires signed commits but this merge will not be signed
@@ -1911,6 +1914,10 @@ wiki.page_name_desc = Enter a name for this Wiki page. Some special names are: '
wiki.original_git_entry_tooltip = View original Git file instead of using friendly link.
activity = Activity
+activity.navbar.pulse = Pulse
+activity.navbar.code_frequency = Code Frequency
+activity.navbar.contributors = Contributors
+activity.navbar.recent_commits = Recent Commits
activity.period.filter_label = Period:
activity.period.daily = 1 day
activity.period.halfweekly = 3 days
@@ -1976,6 +1983,11 @@ activity.git_stats_and_deletions = and
activity.git_stats_deletion_1 = %d deletion
activity.git_stats_deletion_n = %d deletions
+contributors.contribution_type.filter_label = Contribution type:
+contributors.contribution_type.commits = Commits
+contributors.contribution_type.additions = Additions
+contributors.contribution_type.deletions = Deletions
+
search = Search
search.search_repo = Search repository
search.type.tooltip = Search type
@@ -2579,6 +2591,15 @@ error.csv.too_large = Can't render this file because it is too large.
error.csv.unexpected = Can't render this file because it contains an unexpected character in line %d and column %d.
error.csv.invalid_field_count = Can't render this file because it has a wrong number of fields in line %d.
+[graphs]
+component_loading = Loading %s...
+component_loading_failed = Could not load %s
+component_loading_info = This might take a bit…
+component_failed_to_load = An unexpected error happened.
+code_frequency.what = code frequency
+contributors.what = contributions
+recent_commits.what = recent commits
+
[org]
org_name_holder = Organization Name
org_full_name_holder = Organization Full Name
@@ -2716,6 +2737,8 @@ integrations = Integrations
authentication = Authentication Sources
emails = User Emails
config = Configuration
+config_summary = Summary
+config_settings = Settings
notices = System Notices
monitor = Monitoring
first_page = First
@@ -3155,6 +3178,7 @@ config.picture_config = Picture and Avatar Configuration
config.picture_service = Picture Service
config.disable_gravatar = Disable Gravatar
config.enable_federated_avatar = Enable Federated Avatars
+config.open_with_editor_app_help = The "Open with" editors for the clone menu. If left empty, the default will be used. Expand to see the default.
config.git_config = Git Configuration
config.git_disable_diff_highlight = Disable Diff Syntax Highlight
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index 1a82ce5b76..c013927157 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -585,6 +585,7 @@ org_still_own_packages=Esta organización todavía posee uno o más paquetes, el
target_branch_not_exist=La rama de destino no existe
+
[user]
change_avatar=Cambiar su avatar…
joined_on=Se unió el %s
@@ -1952,6 +1953,8 @@ activity.git_stats_and_deletions=y
activity.git_stats_deletion_1=%d eliminación
activity.git_stats_deletion_n=%d eliminaciones
+contributors.contribution_type.commits=Commits
+
search=Buscar
search.search_repo=Buscar repositorio
search.type.tooltip=Tipo de búsqueda
@@ -2550,6 +2553,8 @@ error.csv.too_large=No se puede renderizar este archivo porque es demasiado gran
error.csv.unexpected=No se puede procesar este archivo porque contiene un carácter inesperado en la línea %d y la columna %d.
error.csv.invalid_field_count=No se puede procesar este archivo porque tiene un número incorrecto de campos en la línea %d.
+[graphs]
+
[org]
org_name_holder=Nombre de la organización
org_full_name_holder=Nombre completo de la organización
@@ -3199,6 +3204,7 @@ notices.desc=Descripción
notices.op=Operación
notices.delete_success=Los avisos del sistema se han eliminado.
+
[action]
create_repo=creó el repositorio %s
rename_repo=repositorio renombrado de %[1]s
a %[3]s
@@ -3383,6 +3389,8 @@ rpm.registry=Configurar este registro desde la línea de comandos:
rpm.distros.redhat=en distribuciones basadas en RedHat
rpm.distros.suse=en distribuciones basadas en SUSE
rpm.install=Para instalar el paquete, ejecute el siguiente comando:
+rpm.repository=Información del repositorio
+rpm.repository.architectures=Arquitecturas
rubygems.install=Para instalar el paquete usando gem, ejecute el siguiente comando:
rubygems.install2=o añádelo al archivo Gemfile:
rubygems.dependencies.runtime=Dependencias en tiempo de ejecución
@@ -3530,7 +3538,6 @@ variables.none=Aún no hay variables.
variables.deletion=Eliminar variable
variables.deletion.description=Eliminar una variable es permanente y no se puede deshacer. ¿Continuar?
variables.description=Las variables se pasarán a ciertas acciones y no se podrán leer de otro modo.
-variables.id_not_exist=Variable con id %d no existe.
variables.edit=Editar variable
variables.deletion.failed=No se pudo eliminar la variable.
variables.deletion.success=La variable ha sido eliminada.
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index c9099299a0..d2db7a20e9 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -463,6 +463,7 @@ auth_failed=تشخیص هویت ناموفق: %v
target_branch_not_exist=شاخه مورد نظر وجود ندارد.
+
[user]
change_avatar=تغییر آواتار…
repositories=مخازن
@@ -1498,6 +1499,8 @@ activity.git_stats_and_deletions=و
activity.git_stats_deletion_1=%d مذحوف
activity.git_stats_deletion_n=%d مذحوف
+contributors.contribution_type.commits=کامیتها
+
search=جستجو
search.search_repo=جستجوی مخزن
search.fuzzy=درهم
@@ -1951,6 +1954,8 @@ error.csv.too_large=نمی توان این فایل را رندر کرد زیر
error.csv.unexpected=نمی توان این فایل را رندر کرد زیرا حاوی یک کاراکتر غیرمنتظره در خط %d و ستون %d است.
error.csv.invalid_field_count=نمی توان این فایل را رندر کرد زیرا تعداد فیلدهای آن در خط %d اشتباه است.
+[graphs]
+
[org]
org_name_holder=نام سازمان
org_full_name_holder=نام کامل سازمان
@@ -2501,6 +2506,7 @@ notices.desc=توضیحات
notices.op=عملیات.
notices.delete_success=گزارش سیستم حذف شده است.
+
[action]
create_repo=مخزن ایجاد شده %s
rename_repo=مخزن تغییر نام داد از %[1]s
به %[3]s
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index b6abb49a35..ab0dcc443d 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -425,6 +425,7 @@ auth_failed=Todennus epäonnistui: %v
target_branch_not_exist=Kohde branchia ei ole olemassa.
+
[user]
change_avatar=Vaihda profiilikuvasi…
repositories=Repot
@@ -1074,6 +1075,8 @@ activity.git_stats_and_deletions=ja
activity.git_stats_deletion_1=%d poisto
activity.git_stats_deletion_n=%d poistoa
+contributors.contribution_type.commits=Commitit
+
search=Haku
search.match=Osuma
search.code_no_results=Hakuehtoasi vastaavaa lähdekoodia ei löytynyt.
@@ -1314,6 +1317,8 @@ topic.done=Valmis
+[graphs]
+
[org]
org_name_holder=Organisaatio
org_full_name_holder=Organisaation täydellinen nimi
@@ -1659,6 +1664,7 @@ notices.type_1=Repo
notices.desc=Kuvaus
notices.op=Toiminta
+
[action]
create_repo=luotu repo %s
rename_repo=uudelleennimetty repo %[1]s
nimelle %[3]s
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index f3a264c1c8..7fd79446cc 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -123,6 +123,7 @@ pin=Épingler
unpin=Désépingler
artifacts=Artefacts
+confirm_delete_artifact=Êtes-vous sûr de vouloir supprimer l‘artefact « %s » ?
archived=Archivé
@@ -361,6 +362,7 @@ disable_register_prompt=Les inscriptions sont désactivées. Veuillez contacter
disable_register_mail=La confirmation par courriel à l’inscription est désactivée.
manual_activation_only=Contactez l'administrateur de votre site pour terminer l'activation.
remember_me=Mémoriser cet appareil
+remember_me.compromised=Le jeton de connexion n’est plus valide, ce qui peut indiquer un compte compromis. Veuillez inspecter les activités inhabituelles de votre compte.
forgot_password_title=Mot de passe oublié
forgot_password=Mot de passe oublié ?
sign_up_now=Pas de compte ? Inscrivez-vous maintenant.
@@ -587,6 +589,8 @@ org_still_own_packages=Cette organisation possède encore un ou plusieurs paquet
target_branch_not_exist=La branche cible n'existe pas.
+admin_cannot_delete_self=Vous ne pouvez pas vous supprimer vous-même lorsque vous êtes admin. Veuillez d’abord supprimer vos privilèges d’administrateur.
+
[user]
change_avatar=Changer votre avatar…
joined_on=Inscrit le %s
@@ -793,7 +797,7 @@ valid_until_date=Valable jusqu'au %s
valid_forever=Valide pour toujours
last_used=Dernière utilisation le
no_activity=Aucune activité récente
-can_read_info=Lue(s)
+can_read_info=Lecture
can_write_info=Écriture
key_state_desc=Cette clé a été utilisée au cours des 7 derniers jours
token_state_desc=Ce jeton a été utilisé au cours des 7 derniers jours
@@ -826,7 +830,7 @@ permissions_public_only=Publique uniquement
permissions_access_all=Tout (public, privé et limité)
select_permissions=Sélectionner les autorisations
permission_no_access=Aucun accès
-permission_read=Lue(s)
+permission_read=Lecture
permission_write=Lecture et écriture
access_token_desc=Les autorisations des jetons sélectionnées se limitent aux routes API correspondantes. Lisez la documentation pour plus d’informations.
at_least_one_permission=Vous devez sélectionner au moins une permission pour créer un jeton.
@@ -983,6 +987,7 @@ mirror_prune=Purger
mirror_prune_desc=Supprimer les références externes obsolètes
mirror_interval=Intervalle de synchronisation (les unités de temps valides sont 'h', 'm' et 's'). 0 pour désactiver la synchronisation automatique. (Intervalle minimum : %s)
mirror_interval_invalid=L'intervalle de synchronisation est invalide.
+mirror_sync=synchronisé
mirror_sync_on_commit=Synchroniser quand les révisions sont soumis
mirror_address=Cloner depuis une URL
mirror_address_desc=Insérez tous les identifiants requis dans la section Autorisation.
@@ -1033,6 +1038,7 @@ desc.public=Publique
desc.template=Modèle
desc.internal=Interne
desc.archived=Archivé
+desc.sha256=SHA256
template.items=Élément du modèle
template.git_content=Contenu Git (branche par défaut)
@@ -1183,6 +1189,8 @@ audio_not_supported_in_browser=Votre navigateur ne supporte pas la balise « au
stored_lfs=Stocké avec Git LFS
symbolic_link=Lien symbolique
executable_file=Fichiers exécutables
+vendored=Externe
+generated=Générée
commit_graph=Graphe des révisions
commit_graph.select=Sélectionner les branches
commit_graph.hide_pr_refs=Masquer les demandes d'ajout
@@ -1764,6 +1772,7 @@ pulls.merge_pull_request=Créer une révision de fusion
pulls.rebase_merge_pull_request=Rebaser puis avancer rapidement
pulls.rebase_merge_commit_pull_request=Rebaser puis créer une révision de fusion
pulls.squash_merge_pull_request=Créer une révision de concaténation
+pulls.fast_forward_only_merge_pull_request=Avance rapide uniquement
pulls.merge_manually=Fusionner manuellement
pulls.merge_commit_id=L'ID de la révision de fusion
pulls.require_signed_wont_sign=La branche nécessite des révisions signées mais cette fusion ne sera pas signée
@@ -1900,6 +1909,7 @@ wiki.page_name_desc=Entrez un nom pour cette page Wiki. Certains noms spéciaux
wiki.original_git_entry_tooltip=Voir le fichier Git original au lieu d'utiliser un lien convivial.
activity=Activité
+activity.navbar.contributors=Contributeurs
activity.period.filter_label=Période :
activity.period.daily=1 jour
activity.period.halfweekly=3 jours
@@ -1965,6 +1975,11 @@ activity.git_stats_and_deletions=et
activity.git_stats_deletion_1=%d suppression
activity.git_stats_deletion_n=%d suppressions
+contributors.contribution_type.filter_label=Type de contribution :
+contributors.contribution_type.commits=Révisions
+contributors.contribution_type.additions=Ajouts
+contributors.contribution_type.deletions=Suppressions
+
search=Chercher
search.search_repo=Rechercher dans le dépôt
search.type.tooltip=Type de recherche
@@ -2311,6 +2326,8 @@ settings.protect_approvals_whitelist_users=Évaluateurs autorisés :
settings.protect_approvals_whitelist_teams=Équipes d’évaluateurs autorisés :
settings.dismiss_stale_approvals=Révoquer automatiquement les approbations périmées
settings.dismiss_stale_approvals_desc=Lorsque des nouvelles révisions changent le contenu de la demande d’ajout, les approbations existantes sont révoquées.
+settings.ignore_stale_approvals=Ignorer les approbations obsolètes
+settings.ignore_stale_approvals_desc=Ignorer les approbations d’anciennes révisions (évaluations obsolètes) du décompte des approbations de la demande d’ajout. Non pertinent quand les évaluations obsolètes sont déjà révoquées.
settings.require_signed_commits=Exiger des révisions signées
settings.require_signed_commits_desc=Rejeter les soumissions sur cette branche lorsqu'ils ne sont pas signés ou vérifiables.
settings.protect_branch_name_pattern=Motif de nom de branche protégé
@@ -2366,6 +2383,7 @@ settings.archive.error=Une erreur s'est produite lors de l'archivage du dépôt.
settings.archive.error_ismirror=Vous ne pouvez pas archiver un dépôt en miroir.
settings.archive.branchsettings_unavailable=Le paramétrage des branches n'est pas disponible quand le dépôt est archivé.
settings.archive.tagsettings_unavailable=Le paramétrage des étiquettes n'est pas disponible si le dépôt est archivé.
+settings.archive.mirrors_unavailable=Les miroirs ne sont pas disponibles lorsque le dépôt est archivé.
settings.unarchive.button=Réhabiliter
settings.unarchive.header=Réhabiliter ce dépôt
settings.unarchive.text=Réhabiliter un dépôt dégèle les actions de révisions et de soumissions, la gestion des tickets et des demandes d'ajouts.
@@ -2564,6 +2582,13 @@ error.csv.too_large=Impossible de visualiser le fichier car il est trop volumine
error.csv.unexpected=Impossible de visualiser ce fichier car il contient un caractère inattendu ligne %d, colonne %d.
error.csv.invalid_field_count=Impossible de visualiser ce fichier car il contient un nombre de champs incorrect à la ligne %d.
+[graphs]
+component_loading=Chargement de %s…
+component_loading_failed=Impossible de charger %s.
+component_loading_info=Ça prend son temps…
+component_failed_to_load=Une erreur inattendue s’est produite.
+contributors.what=contributions
+
[org]
org_name_holder=Nom de l'organisation
org_full_name_holder=Nom complet de l'organisation
@@ -2690,6 +2715,7 @@ teams.invite.description=Veuillez cliquer sur le bouton ci-dessous pour rejoindr
[admin]
dashboard=Tableau de bord
+self_check=Autodiagnostique
identity_access=Identité et accès
users=Comptes utilisateurs
organizations=Organisations
@@ -2735,6 +2761,7 @@ dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git
dashboard.delete_missing_repos.started=Tâche de suppression de tous les dépôts sans fichiers Git démarrée.
dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés
dashboard.sync_repo_branches=Synchroniser les branches manquantes depuis Git vers la base de donnée.
+dashboard.sync_repo_tags=Synchroniser les étiquettes git depuis les dépôts vers la base de données
dashboard.update_mirrors=Actualiser les miroirs
dashboard.repo_health_check=Vérifier l'état de santé de tous les dépôts
dashboard.check_repo_stats=Voir les statistiques de tous les dépôts
@@ -2789,6 +2816,7 @@ dashboard.stop_endless_tasks=Arrêter les tâches sans fin
dashboard.cancel_abandoned_jobs=Annuler les jobs abandonnés
dashboard.start_schedule_tasks=Démarrer les tâches planifiées
dashboard.sync_branch.started=Début de la synchronisation des branches
+dashboard.sync_tag.started=Synchronisation des étiquettes
dashboard.rebuild_issue_indexer=Reconstruire l’indexeur des tickets
users.user_manage_panel=Gestion du compte utilisateur
@@ -3215,6 +3243,13 @@ notices.desc=Description
notices.op=Opération
notices.delete_success=Les informations systèmes ont été supprimées.
+self_check.no_problem_found=Aucun problème trouvé pour l’instant.
+self_check.database_collation_mismatch=Exige que la base de données utilise la collation %s.
+self_check.database_collation_case_insensitive=La base de données utilise la collation %s, insensible à la casse. Bien que Gitea soit compatible, il peut y avoir quelques rares cas qui ne fonctionnent pas comme prévu.
+self_check.database_inconsistent_collation_columns=La base de données utilise la collation %s, mais ces colonnes utilisent des collations différentes. Cela peut causer des problèmes imprévus.
+self_check.database_fix_mysql=Pour les utilisateurs de MySQL ou MariaDB, vous pouvez utiliser la commande « gitea doctor convert » dans un terminal ou exécuter une requête du type « ALTER … COLLATE ... » pour résoudre les problèmes de collation.
+self_check.database_fix_mssql=Pour les utilisateurs de MSSQL, vous ne pouvez résoudre le problème qu’en exécutant une requête SQL du type « ALTER … COLLATE … ».
+
[action]
create_repo=a créé le dépôt %s
rename_repo=a rebaptisé le dépôt %[1]s
en %[3]s
@@ -3399,6 +3434,9 @@ rpm.registry=Configurez ce registre à partir d'un terminal :
rpm.distros.redhat=sur les distributions basées sur RedHat
rpm.distros.suse=sur les distributions basées sur SUSE
rpm.install=Pour installer le paquet, exécutez la commande suivante :
+rpm.repository=Informations sur le Dépôt
+rpm.repository.architectures=Architectures
+rpm.repository.multiple_groups=Ce paquet est disponible en plusieurs groupes.
rubygems.install=Pour installer le paquet en utilisant gem, exécutez la commande suivante :
rubygems.install2=ou ajoutez-le au Gemfile :
rubygems.dependencies.runtime=Dépendances d'exécution
@@ -3531,8 +3569,8 @@ runs.actors_no_select=Tous les acteurs
runs.status_no_select=Touts les statuts
runs.no_results=Aucun résultat correspondant.
runs.no_workflows=Il n'y a pas encore de workflows.
-runs.no_workflows.quick_start=Vous ne savez pas comment commencer avec Gitea Action ? Consultez le guide de démarrage rapide .
-runs.no_workflows.documentation=Pour plus d’informations sur les Actions Gitea, voir la documentation .
+runs.no_workflows.quick_start=Vous découvrez les Actions Gitea ? Consultez le didacticiel .
+runs.no_workflows.documentation=Pour plus d’informations sur les actions Gitea, voir la documentation .
runs.no_runs=Le flux de travail n'a pas encore d'exécution.
runs.empty_commit_message=(message de révision vide)
@@ -3551,7 +3589,7 @@ variables.none=Il n'y a pas encore de variables.
variables.deletion=Retirer la variable
variables.deletion.description=La suppression d’une variable est permanente et ne peut être défaite. Continuer ?
variables.description=Les variables sont passées aux actions et ne peuvent être lues autrement.
-variables.id_not_exist=La variable numéro %d n’existe pas.
+variables.id_not_exist=La variable avec l’ID %d n’existe pas.
variables.edit=Modifier la variable
variables.deletion.failed=Impossible de retirer la variable.
variables.deletion.success=La variable a bien été retirée.
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index aee4b44edf..901690d9a0 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -369,6 +369,7 @@ auth_failed=A hitelesítés sikertelen: %v
target_branch_not_exist=Cél ág nem létezik.
+
[user]
change_avatar=Profilkép megváltoztatása…
repositories=Tárolók
@@ -1053,6 +1054,8 @@ activity.git_stats_and_deletions=és
activity.git_stats_deletion_1=%d törlés
activity.git_stats_deletion_n=%d törlés
+contributors.contribution_type.commits=Commit-ok
+
search=Keresés
search.search_repo=Tároló keresés
search.results=`"%s" találatok keresése itt: %s `
@@ -1168,6 +1171,8 @@ topic.done=Kész
+[graphs]
+
[org]
org_name_holder=Szervezet neve
org_full_name_holder=Szervezet teljes neve
@@ -1572,6 +1577,7 @@ notices.desc=Leírás
notices.op=Op.
notices.delete_success=A rendszer-értesítések törölve lettek.
+
[action]
create_repo=létrehozott tárolót: %s
rename_repo=átnevezte a(z) %[1]s
tárolót %[3]s -ra/re
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index 4dd7c299df..1aee871b67 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -293,6 +293,7 @@ auth_failed=Otentikasi gagal: %v
target_branch_not_exist=Target cabang tidak ada.
+
[user]
change_avatar=Ganti avatar anda…
repositories=Repositori
@@ -838,6 +839,8 @@ activity.title.releases_n=%d Rilis
activity.title.releases_published_by=%s dikeluarkan oleh %s
activity.published_release_label=Dikeluarkan
+contributors.contribution_type.commits=Melakukan
+
search=Cari
search.search_repo=Cari repositori
search.results=Cari hasil untuk "%s" dalam %s
@@ -953,6 +956,8 @@ branch.deleted_by=Dihapus oleh %s
+[graphs]
+
[org]
org_name_holder=Nama Organisasi
org_full_name_holder=Organisasi Nama Lengkap
@@ -1262,6 +1267,7 @@ notices.desc=Deskripsi
notices.op=Op.
notices.delete_success=Laporan sistem telah dihapus.
+
[action]
create_repo=repositori dibuat %s
rename_repo=ganti nama gudang penyimpanan dari %[1]s
ke %[3]s
diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini
index 2ba623dc12..f67541fe73 100644
--- a/options/locale/locale_is-IS.ini
+++ b/options/locale/locale_is-IS.ini
@@ -401,6 +401,7 @@ team_not_exist=Liðið er ekki til.
+
[user]
change_avatar=Breyttu notandamyndinni þinni…
repositories=Hugbúnaðarsöfn
@@ -989,6 +990,8 @@ activity.git_stats_and_deletions=og
activity.git_stats_deletion_1=%d eyðing
activity.git_stats_deletion_n=%d eyðingar
+contributors.contribution_type.commits=Framlög
+
search=Leita
search.fuzzy=Óljóst
search.code_no_results=Enginn samsvarandi frumkóði fannst eftur þínum leitarorðum.
@@ -1112,6 +1115,8 @@ topic.done=Í lagi
+[graphs]
+
[org]
repo_updated=Uppfært
members=Meðlimar
@@ -1278,6 +1283,7 @@ notices.type_1=Hugbúnaðarsafn
notices.type_2=Verkefni
notices.desc=Lýsing
+
[action]
create_issue=`opnaði vandamál %[3]s#%[2]s `
reopen_issue=`enduropnaði vandamál %[3]s#%[2]s `
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index a30232dd10..0e38c1ffb9 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -490,6 +490,7 @@ auth_failed=Autenticazione non riuscita: %v
target_branch_not_exist=Il ramo (branch) di destinazione non esiste.
+
[user]
change_avatar=Modifica il tuo avatar…
repositories=Repository
@@ -1623,6 +1624,8 @@ activity.git_stats_and_deletions=e
activity.git_stats_deletion_1=%d cancellazione
activity.git_stats_deletion_n=%d cancellazioni
+contributors.contribution_type.commits=Commit
+
search=Ricerca
search.search_repo=Ricerca repository
search.fuzzy=Fuzzy
@@ -2117,6 +2120,8 @@ error.csv.too_large=Impossibile visualizzare questo file perché è troppo grand
error.csv.unexpected=Impossibile visualizzare questo file perché contiene un carattere inatteso alla riga %d e alla colonna %d.
error.csv.invalid_field_count=Impossibile visualizzare questo file perché ha un numero errato di campi alla riga %d.
+[graphs]
+
[org]
org_name_holder=Nome dell'Organizzazione
org_full_name_holder=Nome completo dell'organizzazione
@@ -2703,6 +2708,7 @@ notices.desc=Descrizione
notices.op=Op.
notices.delete_success=Gli avvisi di sistema sono stati eliminati.
+
[action]
create_repo=ha creato il repository %s
rename_repo=repository rinominato da %[1]s
a [3]s
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 9216277955..5d9e21703e 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -588,6 +588,7 @@ org_still_own_packages=組織はまだ1つ以上のパッケージを所有し
target_branch_not_exist=ターゲットのブランチが存在していません。
+
[user]
change_avatar=アバターを変更…
joined_on=%sに登録
@@ -1966,6 +1967,8 @@ activity.git_stats_and_deletions=、
activity.git_stats_deletion_1=%d行削除
activity.git_stats_deletion_n=%d行削除
+contributors.contribution_type.commits=コミット
+
search=検索
search.search_repo=リポジトリを検索
search.type.tooltip=検索タイプ
@@ -2565,6 +2568,8 @@ error.csv.too_large=このファイルは大きすぎるため表示できませ
error.csv.unexpected=このファイルは %d 行目の %d 文字目に予期しない文字が含まれているため表示できません。
error.csv.invalid_field_count=このファイルは %d 行目のフィールドの数が正しくないため表示できません。
+[graphs]
+
[org]
org_name_holder=組織名
org_full_name_holder=組織のフルネーム
@@ -3216,6 +3221,7 @@ notices.desc=説明
notices.op=操作
notices.delete_success=システム通知を削除しました。
+
[action]
create_repo=がリポジトリ %s を作成しました
rename_repo=がリポジトリ名を %[1]s
から %[3]s へ変更しました
@@ -3400,6 +3406,8 @@ rpm.registry=このレジストリをコマンドラインからセットアッ
rpm.distros.redhat=RedHat系ディストリビューションの場合
rpm.distros.suse=SUSE系ディストリビューションの場合
rpm.install=パッケージをインストールするには、次のコマンドを実行します:
+rpm.repository=リポジトリ情報
+rpm.repository.architectures=Architectures
rubygems.install=gem を使用してパッケージをインストールするには、次のコマンドを実行します:
rubygems.install2=または Gemfile に追加します:
rubygems.dependencies.runtime=実行用依存関係
@@ -3532,8 +3540,6 @@ runs.actors_no_select=すべてのアクター
runs.status_no_select=すべてのステータス
runs.no_results=一致する結果はありません。
runs.no_workflows=ワークフローはまだありません。
-runs.no_workflows.quick_start=Gitea Action の始め方がわからない? クイックスタートガイド をご覧ください。
-runs.no_workflows.documentation=Gitea Action の詳細については、ドキュメント を参照してください。
runs.no_runs=ワークフローはまだ実行されていません。
runs.empty_commit_message=(空のコミットメッセージ)
@@ -3552,7 +3558,6 @@ variables.none=変数はまだありません。
variables.deletion=変数を削除
variables.deletion.description=変数の削除は恒久的で元に戻すことはできません。 続行しますか?
variables.description=変数は特定のActionsに渡されます。 それ以外で読み出されることはありません。
-variables.id_not_exist=idが%dの変数は存在しません。
variables.edit=変数の編集
variables.deletion.failed=変数を削除できませんでした。
variables.deletion.success=変数を削除しました。
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index 1c79ee6bc7..ed0bb897c4 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -349,6 +349,7 @@ auth_failed=인증 실패: %v
target_branch_not_exist=대상 브랜치가 존재하지 않습니다.
+
[user]
change_avatar=아바타 변경
repositories=저장소
@@ -949,6 +950,8 @@ activity.title.releases_n=%d 개의 릴리즈
activity.title.releases_published_by=%s 가 %s 에 의하여 배포되었습니다.
activity.published_release_label=배포됨
+contributors.contribution_type.commits=커밋
+
search=검색
search.search_repo=저장소 검색
search.results="%s 에서 \"%s\" 에 대한 검색 결과"
@@ -1161,6 +1164,8 @@ topic.count_prompt=25개 이상의 토픽을 선택하실 수 없습니다.
+[graphs]
+
[org]
org_name_holder=조직 이름
org_full_name_holder=조직 전체 이름
@@ -1521,6 +1526,7 @@ notices.desc=설명
notices.op=일.
notices.delete_success=시스템 알림이 삭제되었습니다.
+
[action]
create_repo=저장소를 만들었습니다. %s
rename_repo=%[1]s에서
에서 %[3]s 으로 저장소 이름을 바꾸었습니다.
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index e275b02ba0..3c3513ad48 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -17,10 +17,11 @@ template=Sagatave
language=Valoda
notifications=Paziņojumi
active_stopwatch=Aktīvā laika uzskaite
+tracked_time_summary=Izsekojamā laika apkopojums, kas ir balstīts uz pieteikumu saraksta atlasi
create_new=Izveidot…
user_profile_and_more=Profils un iestatījumi…
signed_in_as=Pieteicies kā
-enable_javascript=Šai lapas darbībai ir nepieciešams JavaScript.
+enable_javascript=Šai tīmekļvietnei ir nepieciešams JavaScript.
toc=Satura rādītājs
licenses=Licences
return_to_gitea=Atgriezties Gitea
@@ -40,12 +41,12 @@ webauthn_sign_in=Nospiediet pogu uz drošības atslēgas. Ja tai nav pogas, izņ
webauthn_press_button=Nospiediet drošības atslēgas pogu…
webauthn_use_twofa=Izmantot divfaktoru kodu no tālruņa
webauthn_error=Nevar nolasīt drošības atslēgu.
-webauthn_unsupported_browser=Jūsu pārlūkprogramma neatbalsta WebAuthn standartu.
+webauthn_unsupported_browser=Jūsu pārlūks neatbalsta WebAuthn standartu.
webauthn_error_unknown=Notikusi nezināma kļūda. Atkārtojiet darbību vēlreiz.
-webauthn_error_insecure=WebAuthn atbalsta tikai drošus savienojumus ar serveri
-webauthn_error_unable_to_process=Serveris nevar apstrādāt Jūsu pieprasījumu.
+webauthn_error_insecure=`WebAuthn atbalsta tikai drošus savienojumus. Pārbaudīšanai ar HTTP var izmantot izcelsmi "localhost" vai "127.0.0.1"`
+webauthn_error_unable_to_process=Serveris nevarēja apstrādāt pieprasījumu.
webauthn_error_duplicated=Drošības atslēga nav atļauta šim pieprasījumam. Pārliecinieties, ka šī atslēga jau nav reģistrēta.
-webauthn_error_empty=Norādiet atslēgas nosaukumu.
+webauthn_error_empty=Jānorāda šīs atslēgas nosaukums.
webauthn_error_timeout=Iestājusies noildze, mēģinot, nolasīt atslēgu. Pārlādējiet lapu un mēģiniet vēlreiz.
webauthn_reload=Pārlādēt
@@ -60,11 +61,11 @@ new_org=Jauna organizācija
new_project=Jauns projekts
new_project_column=Jauna kolonna
manage_org=Pārvaldīt organizācijas
-admin_panel=Lapas administrēšana
+admin_panel=Vietnes administrēšana
account_settings=Konta iestatījumi
settings=Iestatījumi
your_profile=Profils
-your_starred=Atzīmēts ar zvaigznīti
+your_starred=Pievienots izlasē
your_settings=Iestatījumi
all=Visi
@@ -90,9 +91,11 @@ remove=Noņemt
remove_all=Noņemt visus
remove_label_str=`Noņemt ierakstu "%s"`
edit=Labot
+view=Skatīt
enabled=Iespējots
disabled=Atspējots
+locked=Slēgts
copy=Kopēt
copy_url=Kopēt saiti
@@ -109,6 +112,7 @@ loading=Notiek ielāde…
error=Kļūda
error404=Lapa, ko vēlaties atvērt, neeksistē vai arī Jums nav tiesības to aplūkot.
+go_back=Atgriezties
never=Nekad
unknown=Nezināms
@@ -130,6 +134,7 @@ concept_user_organization=Organizācija
show_timestamps=Rādīt laika zīmogus
show_log_seconds=Rādīt sekundes
show_full_screen=Atvērt pilnā logā
+download_logs=Lejupielādēt žurnālus
confirm_delete_selected=Apstiprināt, lai izdzēstu visus atlasītos vienumus?
@@ -170,6 +175,7 @@ string.desc=Z - A
[error]
occurred=Radusies kļūda
+report_message=Ja ir pārliecība, ka šī ir Gitea nepilnība, lūgums pārbaudīt GitHub , vai tā jau nav zināma, vai izveidot jaunu pieteikumu, ja nepieciešams.
missing_csrf=Kļūdains pieprasījums: netika iesūtīta drošības pilnvara
invalid_csrf=Kļūdains pieprasījums: iesūtīta kļūdaina drošības pilnvara
not_found=Pieprasītie dati netika atrasti.
@@ -178,6 +184,7 @@ network_error=Tīkla kļūda
[startpage]
app_desc=Viegli uzstādāms Git serviss
install=Vienkārši instalējams
+install_desc=Vienkārši jāpalaiž izpildāmais fails vajadzīgajai platformai, jāizmanto Docker , vai jāiegūst pakotne .
platform=Pieejama dažādām platformām
platform_desc=Gitea iespējams uzstādīt jebkur, kam Go var nokompilēt: Windows, macOS, Linux, ARM utt. Izvēlies to, kas tev patīk!
lightweight=Viegla
@@ -222,6 +229,7 @@ repo_path_helper=Git repozitoriji tiks glabāti šajā direktorijā.
lfs_path=Git LFS glabāšanas vieta
lfs_path_helper=Faili, kas pievienoti Git LFS, tiks glabāti šajā direktorijā. Atstājiet tukšu, lai atspējotu.
run_user=Izpildes lietotājs
+run_user_helper=Operētājsistēms lietotājs, ar kuru tiks palaists Gitea. Jāņem vērā, ka šim lietotājam ir jābūt piekļuvei repozitorija atrašanās vietai.
domain=Servera domēns
domain_helper=Domēns vai servera adrese.
ssh_port=SSH servera ports
@@ -293,6 +301,8 @@ invalid_password_algorithm=Kļūdaina paroles jaucējfunkcija
password_algorithm_helper=Norādiet paroles jaucējalgoritmu. Algoritmi atšķirās pēc prasībām pret resursiem un stipruma. Argon2 algoritms ir drošs, bet tam nepieciešams daudz operatīvās atmiņas, līdz ar ko tas var nebūt piemērots sistēmām ar maz pieejamajiem resursiem.
enable_update_checker=Iespējot jaunu versiju paziņojumus
enable_update_checker_helper=Periodiski pārbaudīt jaunu version pieejamību, izgūstot datus no gitea.io.
+env_config_keys=Vides konfigurācija
+env_config_keys_prompt=Šie vides mainīgie tiks pielietoti arī konfigurācijas failā:
[home]
uname_holder=Lietotājvārds vai e-pasts
@@ -351,9 +361,11 @@ disable_register_prompt=Reģistrācija ir atspējota. Lūdzu, sazinieties ar vie
disable_register_mail=Reģistrācijas e-pasta apstiprināšana ir atspējota.
manual_activation_only=Sazinieties ar lapas administratoru, lai pabeigtu konta aktivizāciju.
remember_me=Atcerēties šo ierīci
+remember_me.compromised=Pieteikšanās pilnvara vairs nav derīga, kas var norādīt uz ļaunprātīgām darbībām kontā. Lūgums pārbaudīt, vai kontā nav neparastu darbību.
forgot_password_title=Aizmirsu paroli
forgot_password=Aizmirsi paroli?
sign_up_now=Nepieciešams konts? Reģistrējies tagad.
+sign_up_successful=Konts tika veiksmīgi izveidots. Laipni lūdzam!
confirmation_mail_sent_prompt=Jauns apstiprināšanas e-pasts ir nosūtīts uz %s , pārbaudies savu e-pasta kontu tuvāko %s laikā, lai pabeigtu reģistrācijas procesu.
must_change_password=Mainīt paroli
allow_password_change=Pieprasīt lietotājam mainīt paroli (ieteicams)
@@ -369,6 +381,7 @@ email_not_associate=Šī e-pasta adrese nav saistīta ar nevienu kontu.
send_reset_mail=Nosūtīt paroles atjaunošanas e-pastu
reset_password=Paroles atjaunošana
invalid_code=Jūsu apstiprināšanas kodam ir beidzies derīguma termiņš vai arī tas ir nepareizs.
+invalid_code_forgot_password=Apliecinājuma kods ir nederīgs vai tā derīgums ir beidzies. Nospiediet šeit , lai uzsāktu jaunu sesiju.
invalid_password=Jūsu parole neatbilst parolei, kas tika ievadīta veidojot so kontu.
reset_password_helper=Atjaunot paroli
reset_password_wrong_user=Jūs esat pieteicies kā %s, bet konta atkopšanas saite ir paredzēta lietotājam %s
@@ -396,6 +409,7 @@ openid_connect_title=Pievienoties jau esošam kontam
openid_connect_desc=Izvēlētais OpenID konts sistēmā netika atpazīts, bet Jūs to varat piesaistīt esošam kontam.
openid_register_title=Izveidot jaunu kontu
openid_register_desc=Izvēlētais OpenID konts sistēmā netika atpazīts, bet Jūs to varat piesaistīt esošam kontam.
+openid_signin_desc=Jāievada OpenID URI. Piemēram, anna.openid.example.org vai https://openid.example.org/anna.
disable_forgot_password_mail=Konta atjaunošana ir atspējota, jo nav uzstādīti e-pasta servera iestatījumi. Sazinieties ar lapas administratoru.
disable_forgot_password_mail_admin=Kontu atjaunošana ir pieejama tikai, ja ir veikta e-pasta servera iestatījumu konfigurēšana. Norādiet e-pasta servera iestatījumus, lai iespējotu kontu atjaunošanu.
email_domain_blacklisted=Nav atļauts reģistrēties ar šādu e-pasta adresi.
@@ -405,7 +419,9 @@ authorize_application_created_by=Šo lietotni izveidoja %s.
authorize_application_description=Ja piešķirsiet tiesības, tā varēs piekļūt un mainīt Jūsu konta informāciju, ieskaitot privātos repozitorijus un organizācijas.
authorize_title=Autorizēt "%s" piekļuvi jūsu kontam?
authorization_failed=Autorizācija neizdevās
+authorization_failed_desc=Autentifikācija neizdevās, jo tika veikts kļūdains pieprasījums. Sazinieties ar lietojumprogrammas, ar kuru mēģinājāt autentificēties, uzturētāju.
sspi_auth_failed=SSPI autentifikācija neizdevās
+password_pwned=Izvēlētā parole ir nozagto paroļu sarakstā , kas iepriekš ir atklāts publiskās datu noplūdēs. Lūgums mēģināt vēlreiz ar citu paroli un apsvērt to nomainīt arī citur.
password_pwned_err=Neizdevās pabeigt pieprasījumu uz HaveIBeenPwned
[mail]
@@ -420,6 +436,7 @@ activate_account.text_1=Sveiki %[1]s , esat reģistrējies %[2]s!
activate_account.text_2=Nospiediet uz saites, lai aktivizētu savu kontu lapā %s :
activate_email=Apstipriniet savu e-pasta adresi
+activate_email.title=%s, apstipriniet savu e-pasta adresi
activate_email.text=Nospiediet uz saites, lai apstiprinātu savu e-pasta adresi lapā %s :
register_notify=Laipni lūdzam Gitea
@@ -571,6 +588,7 @@ org_still_own_packages=Šai organizācijai pieder viena vai vārākas pakotnes,
target_branch_not_exist=Mērķa atzars neeksistē
+
[user]
change_avatar=Mainīt profila attēlu…
joined_on=Pievienojās %s
@@ -589,6 +607,8 @@ user_bio=Biogrāfija
disabled_public_activity=Šis lietotājs ir atslēdzies iespēju aplūkot tā aktivitāti.
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
+show_on_map=Rādīt šo vietu kartē
+settings=Lietotāja iestatījumi
form.name_reserved=Lietotājvārdu "%s" nedrīkst izmantot.
form.name_pattern_not_allowed=Lietotājvārds "%s" nav atļauts.
@@ -610,9 +630,13 @@ delete=Dzēst kontu
twofa=Divfaktoru autentifikācija
account_link=Saistītie konti
organization=Organizācijas
+uid=UID
webauthn=Drošības atslēgas
public_profile=Publiskais profils
+biography_placeholder=Pastāsti mums mazliet par sevi! (Var izmantot Markdown)
+location_placeholder=Kopīgot savu aptuveno atrašanās vietu ar citiem
+profile_desc=Norādīt, kā profils tiek attēlots citiem lietotājiem. Primārā e-pasta adrese tiks izmantota paziņojumiem, paroles atjaunošanai un Git tīmekļa darbībām.
password_username_disabled=Ne-lokāliem lietotājiem nav atļauts mainīt savu lietotāja vārdu. Sazinieties ar sistēmas administratoru, lai uzzinātu sīkāk.
full_name=Pilns vārds
website=Mājas lapa
@@ -624,6 +648,8 @@ update_language_not_found=Valoda "%s" nav pieejama.
update_language_success=Valoda tika nomainīta.
update_profile_success=Jūsu profila informācija tika saglabāta.
change_username=Lietotājvārds mainīts.
+change_username_prompt=Piezīme: lietotājvārda mainīšana maina arī konta URL.
+change_username_redirect_prompt=Iepriekšējais lietotājvārds tiks pārvirzīts, kamēr neviens cits to neizmanto.
continue=Turpināt
cancel=Atcelt
language=Valoda
@@ -648,6 +674,7 @@ comment_type_group_project=Projektus
comment_type_group_issue_ref=Problēmu atsauces
saved_successfully=Iestatījumi tika veiksmīgi saglabati.
privacy=Privātums
+keep_activity_private=Profila lapā paslēpt notikumus
keep_activity_private_popup=Savu aktivitāti redzēsiet tikai Jūs un administratori
lookup_avatar_by_mail=Meklēt profila bildes pēc e-pasta
@@ -657,12 +684,14 @@ choose_new_avatar=Izvēlēties jaunu profila attēlu
update_avatar=Saglabāt profila bildi
delete_current_avatar=Dzēst pašreizējo profila bildi
uploaded_avatar_not_a_image=Augšupielādētais fails nav attēls.
+uploaded_avatar_is_too_big=Augšupielādētā faila izmērs (%d KiB) pārsniedz pieļaujamo izmēru (%d KiB).
update_avatar_success=Profila attēls tika saglabāts.
update_user_avatar_success=Lietotāja profila attēls tika atjaunots.
change_password=Mainīt paroli
old_password=Pašreizējā parole
new_password=Jauna parole
+retype_new_password=Apstiprināt jauno paroli
password_incorrect=Ievadīta nepareiza pašreizējā parole.
change_password_success=Parole tika veiksmīgi nomainīta. Tagad varat pieteikties ar jauno paroli.
password_change_disabled=Ārējie konti nevar mainīt paroli, izmantojot, Gitea saskarni.
@@ -671,6 +700,7 @@ emails=E-pasta adreses
manage_emails=Pārvaldīt e-pasta adreses
manage_themes=Izvēlieties noklusējuma motīvu
manage_openid=Pārvaldīt OpenID adreses
+email_desc=Primārā e-pasta adrese tiks izmantota paziņojumiem, paroļu atjaunošanai un, ja tā nav paslēpta, Git tīmekļa darbībām.
theme_desc=Šis būs noklusējuma motīvs visiem lietotājiem.
primary=Primārā
activated=Aktivizēts
@@ -678,6 +708,7 @@ requires_activation=Nepieciešams aktivizēt
primary_email=Uzstādīt kā primāro
activate_email=Nosūtīt aktivizācijas e-pastu
activations_pending=Gaida aktivizāciju
+can_not_add_email_activations_pending=Ir nepabeigta aktivizācija. Pēc dažām minūtēm mēģiniet vēlreiz, ja ir vēlme pievienot jaunu e-pasta adresi.
delete_email=Noņemt
email_deletion=Dzēst e-pasta adresi
email_deletion_desc=E-pasta adrese un ar to saistītā informācija tiks dzēsta no šī konta. Git revīzijas ar šo e-pasta adresi netiks mainītas. Vai turpināt?
@@ -696,6 +727,7 @@ add_email_success=Jūsu jaunā e-pasta adrese tika veiksmīgi pievienota.
email_preference_set_success=E-pasta izvēle tika veiksmīgi saglabāta.
add_openid_success=Jūsu jaunā OpenID adrese tika veiksmīgi pievienota.
keep_email_private=Paslēpt e-pasta adresi
+keep_email_private_popup=Šis profilā paslēps e-pasta adresi, kā arī tad, kad tiks veikts izmaiņu pieprasījums vai tīmekļa saskarnē labota datne. Aizgādātie iesūtījumi netiks pārveidoti. Revīzijās jāizmanto %s, lai sasaistītu tos ar kontu.
openid_desc=Jūsu OpenID adreses ļauj autorizēties, izmantojot, Jūsu izvēlēto pakalpojumu sniedzēju.
manage_ssh_keys=Pārvaldīt SSH atslēgas
@@ -776,6 +808,7 @@ ssh_externally_managed=Šim lietotājam SSH atslēga tiek pāvaldīta attālinā
manage_social=Pārvaldīt piesaistītos sociālos kontus
social_desc=Šie sociālo tīklu konti var tikt izmantoti, lai pieteiktos. Pārliecinieties, ka visi ir atpazīstami.
unbind=Atsaistīt
+unbind_success=Sociālā tīkla konts tika veiksmīgi noņemts.
manage_access_token=Pārvaldīt piekļuves pilnvaras
generate_new_token=Izveidot jaunu pilnvaru
@@ -795,7 +828,9 @@ permissions_public_only=Tikai publiskie
permissions_access_all=Visi (publiskie, privātie un ierobežotie)
select_permissions=Norādiet tiesības
permission_no_access=Nav piekļuves
-permission_read=Izlasītie
+permission_read=Skatīšanās
+permission_write=Skatīšanās un raksīšanas
+access_token_desc=Atzīmētie pilnvaras apgabali ierobežo autentifikāciju tikai atbilstošiem API izsaukumiem. Sīkāka informācija pieejama dokumentācijā .
at_least_one_permission=Nepieciešams norādīt vismaz vienu tiesību, lai izveidotu pilnvaru
permissions_list=Tiesības:
@@ -807,6 +842,8 @@ remove_oauth2_application_desc=Noņemot OAuth2 lietotni, tiks noņemta piekļuve
remove_oauth2_application_success=Lietotne tika dzēsta.
create_oauth2_application=Izveidot jaunu OAuth2 lietotni
create_oauth2_application_button=Izveidot lietotni
+create_oauth2_application_success=Ir veiksmīgi izveidota jauna OAuth2 lietotne.
+update_oauth2_application_success=Ir veiksmīgi atjaunota OAuth2 lietotne.
oauth2_application_name=Lietotnes nosaukums
oauth2_confidential_client=Konfidenciāls klients. Norādiet lietotēm, kas glabā noslēpumu slepenībā, piemēram, tīmekļa lietotnēm. Nenorādiet instalējamām lietotnēm, tai skaitā darbavirsmas vai mobilajām lietotnēm.
oauth2_redirect_uris=Pārsūtīšanas URI. Norādiet katru URI savā rindā.
@@ -815,19 +852,26 @@ oauth2_client_id=Klienta ID
oauth2_client_secret=Klienta noslēpums
oauth2_regenerate_secret=Pārģenerēt noslēpumus
oauth2_regenerate_secret_hint=Pazaudēts noslēpums?
+oauth2_client_secret_hint=Pēc šīs lapas pamešanas vai atsvaidzināšanas noslēpums vairs netiks parādīts. Lūgums pārliecināties, ka tas ir saglabāts.
oauth2_application_edit=Labot
oauth2_application_create_description=OAuth2 lietotnes ļauj trešas puses lietotnēm piekļūt lietotāja kontiem šajā instancē.
+oauth2_application_remove_description=OAuth2 lietotnes noņemšana liegs tai piekļūt pilnvarotiem lietotāju kontiem šajā instancē. Vai turpināt?
+oauth2_application_locked=Gitea sāknēšanas brīdī reģistrē dažas OAuth2 lietotnes, ja tas ir iespējots konfigurācijā. Lai novērstu negaidītu uzvedību, tās nevar ne labot, ne noņemt. Lūgums vērsties OAuth2 dokumentācijā pēc vairāk informācijas.
authorized_oauth2_applications=Autorizētās OAuth2 lietotnes
+authorized_oauth2_applications_description=Ir ļauta piekļuve savam Gitea kontam šīm trešo pušu lietotnēm. Lūgums atsaukt piekļuvi lietotnēm, kas vairs nav nepieciešamas.
revoke_key=Atsaukt
revoke_oauth2_grant=Atsaukt piekļuvi
revoke_oauth2_grant_description=Atsaucot piekļuvi šai trešas puses lietotnei tiks liegta piekļuve Jūsu datiem. Vai turpināt?
+revoke_oauth2_grant_success=Piekļuve veiksmīgi atsaukta.
twofa_desc=Divfaktoru autentifikācija uzlabo konta drošību.
+twofa_recovery_tip=Ja ierīce tiek pazaudēta, iespējams izmantot vienreiz izmantojamo atkopšanas atslēgu, lai atgūtu piekļuvi savam kontam.
twofa_is_enrolled=Kontam ir ieslēgta divfaktoru autentifikācija.
twofa_not_enrolled=Kontam šobrīd nav ieslēgta divfaktoru autentifikācija.
twofa_disable=Atslēgt divfaktoru autentifikāciju
twofa_scratch_token_regenerate=Ģenerēt jaunu vienreizējo kodu
+twofa_scratch_token_regenerated=Vienreizējā pilnvara tagad ir %s. Tā ir jāglabā drošā vietā, tā vairs nekad netiks rādīta.
twofa_enroll=Ieslēgt divfaktoru autentifikāciju
twofa_disable_note=Nepieciešamības gadījumā divfaktoru autentifikāciju ir iespējams atslēgt.
twofa_disable_desc=Atslēdzot divfaktoru autentifikāciju, konts vairs nebūs tik drošs. Vai turpināt?
@@ -845,6 +889,8 @@ webauthn_register_key=Pievienot drošības atslēgu
webauthn_nickname=Segvārds
webauthn_delete_key=Noņemt drošības atslēgu
webauthn_delete_key_desc=Noņemot drošības atslēgu ar to vairs nebūs iespējams pieteikties. Vai turpināt?
+webauthn_key_loss_warning=Ja tiek pazaudētas drošības atslēgas, tiks zaudēta piekļuve kontam.
+webauthn_alternative_tip=Ir vēlams uzstādīt papildu autentifikācijas veidu.
manage_account_links=Pārvaldīt saistītos kontus
manage_account_links_desc=Šādi ārējie konti ir piesaistīti Jūsu Gitea kontam.
@@ -854,8 +900,10 @@ remove_account_link=Noņemt saistīto kontu
remove_account_link_desc=Noņemot saistīto kontu, tam tiks liegta piekļuve Jūsu Gitea kontam. Vai turpināt?
remove_account_link_success=Saistītais konts tika noņemts.
+hooks.desc=Pievienot tīmekļa āķus, kas izpildīsies visos repozitorijos , kas jums pieder.
orgs_none=Jūs neesat nevienas organizācijas biedrs.
+repos_none=Jums nepieder neviens repozitorijs.
delete_account=Dzēst savu kontu
delete_prompt=Šī darbība pilnībā izdzēsīs Jūsu kontu, kā arī tā ir NEATGRIEZENISKA .
@@ -874,9 +922,12 @@ visibility=Lietotāja redzamība
visibility.public=Publisks
visibility.public_tooltip=Redzams ikvienam
visibility.limited=Ierobežota
+visibility.limited_tooltip=Redzams tikai autentificētiem lietotājiem
visibility.private=Privāts
+visibility.private_tooltip=Redzams tikai organizāciju, kurām esi pievienojies, dalībniekiem
[repo]
+new_repo_helper=Repozitorijs satur visus projekta failus, tajā skaitā izmaiņu vēsturi. Jau tiek glabāts kaut kur citur? Pārnest repozitoriju.
owner=Īpašnieks
owner_helper=Ņemot vērā maksimālā repozitoriju skaita ierobežojumu, ne visas organizācijas var tikt parādītas sarakstā.
repo_name=Repozitorija nosaukums
@@ -888,6 +939,7 @@ template_helper=Padarīt repozitoriju par sagatavi
template_description=Sagatavju repozitoriji tiek izmantoti, lai balstoties uz tiem veidotu jaunus repozitorijus saglabājot direktoriju un failu struktūru.
visibility=Redzamība
visibility_description=Tikai organizācijas īpašnieks vai tās biedri, kam ir tiesības, varēs piekļūt šim repozitorijam.
+visibility_helper=Padarīt repozitoriju privātu
visibility_helper_forced=Jūsu sistēmas administrators ir noteicis, ka visiem no jauna izveidotajiem repozitorijiem ir jābūt privātiem.
visibility_fork_helper=(Šīs vērtības maiņa ietekmēs arī visus atdalītos repozitorijus.)
clone_helper=Nepieciešama palīdzība klonēšanā? Apmeklē palīdzības sadaļu.
@@ -896,6 +948,9 @@ fork_from=Atdalīt no
already_forked=Repozitorijs %s jau ir atdalīts
fork_to_different_account=Atdalīt uz citu kontu
fork_visibility_helper=Atdalītam repozitorijam nav iespējams mainīt tā redzamību.
+fork_branch=Atzars, ko klonēt atdalītajā repozitorijā
+all_branches=Visi atzari
+fork_no_valid_owners=Šim repozitorijam nevar izveidot atdalītu repozitoriju, jo tam nav spēkā esošu īpašnieku.
use_template=Izmantot šo sagatavi
clone_in_vsc=Atvērt VS Code
download_zip=Lejupielādēt ZIP
@@ -923,7 +978,8 @@ trust_model_helper_committer=Revīzijas iesūtītāja: Uzticēties parakstiem, k
trust_model_helper_collaborator_committer=Līdzstrādnieka un revīzijas iesūtītāja: Uzticēties līdzstrādnieku parakstiem, kas atbilst revīzijas iesūtītājam
trust_model_helper_default=Noklusētais: Izmantojiet šī servera noklusēto uzticamības modeli
create_repo=Izveidot repozitoriju
-default_branch=Noklusējuma atzars
+default_branch=Noklusētais atzars
+default_branch_label=noklusējuma
default_branch_helper=Noklusētais atzars nosaka pamata atzaru uz kuru tiks veidoti izmaiņu pieprasījumi un koda revīziju iesūtīšana.
mirror_prune=Izmest
mirror_prune_desc=Izdzēst visas ārējās atsauces, kas ārējā repozitorijā vairs neeksistē
@@ -932,6 +988,8 @@ mirror_interval_invalid=Nekorekts spoguļošanas intervāls.
mirror_sync_on_commit=Sinhronizēt, kad revīzijas tiek iesūtītas
mirror_address=Spoguļa adrese
mirror_address_desc=Pieslēgšanās rekvizītus norādiet autorizācijas sadaļā.
+mirror_address_url_invalid=Norādītais URL ir nederīgs. Visas URL daļas ir jānorāda pareizi.
+mirror_address_protocol_invalid=Norādītais URL ir nederīgs. Var spoguļot tikai no http(s):// vai git:// adresēm.
mirror_lfs=Lielu failu glabātuve (LFS)
mirror_lfs_desc=Aktivizēt LFS datu spoguļošanu.
mirror_lfs_endpoint=LFS galapunkts
@@ -942,7 +1000,7 @@ mirror_password_blank_placeholder=(nav uzstādīts)
mirror_password_help=Nomainiet lietotāju, lai izdzēstu saglabāto paroli.
watchers=Novērotāji
stargazers=Zvaigžņdevēji
-stars_remove_warning=Tiks noņemtas visas atzīmētās zvaigznes šim repozitorijam.
+stars_remove_warning=Šis repozitorijs tiks noņemts no visām izlasēm.
forks=Atdalītie repozitoriji
reactions_more=un vēl %d
unit_disabled=Administrators ir atspējojies šo repozitorija sadaļu.
@@ -957,19 +1015,27 @@ delete_preexisting=Dzēst jau eksistējošos failus
delete_preexisting_content=Dzēst failus direktorijā %s
delete_preexisting_success=Dzēst nepārņemtos failus direktorijā %s
blame_prior=Aplūkot vainīgo par izmaiņām pirms šīs revīzijas
+blame.ignore_revs=Neņem vērā izmaiņas no .git-blame-ignore-revs . Nospiediet šeit, lai to apietu un redzētu visu izmaiņu skatu.
+blame.ignore_revs.failed=Neizdevās neņemt vērā izmaiņas no .git-blam-ignore-revs .
author_search_tooltip=Tiks attēloti ne vairāk kā 30 lietotāji
+tree_path_not_found_commit=Revīzijā %[2]s neeksistē ceļš %[1]s
+tree_path_not_found_branch=Atzarā %[2]s nepastāv ceļš %[1]s
+tree_path_not_found_tag=Tagā %[2]s nepastāv ceļš %[1]s
transfer.accept=Apstiprināt īpašnieka maiņu
transfer.accept_desc=`Mainīt īpašnieku uz "%s"`
transfer.reject=Noraidīt īpašnieka maiņu
transfer.reject_desc=`Atcelt īpašnieka maiņu uz "%s"`
+transfer.no_permission_to_accept=Nav atļaujas pieņemt šo pārsūtīšanu.
+transfer.no_permission_to_reject=Nav atļaujas noraidīt šo pārsūtīšanu.
desc.private=Privāts
desc.public=Publisks
desc.template=Sagatave
desc.internal=Iekšējs
desc.archived=Arhivēts
+desc.sha256=SHA256
template.items=Sagataves ieraksti
template.git_content=Git saturs (noklusētais atzars)
@@ -982,6 +1048,8 @@ template.issue_labels=Problēmu etiķetes
template.one_item=Norādiet vismaz vienu sagataves vienību
template.invalid=Norādiet sagataves repozitoriju
+archive.title=Šis repozitorijs ir arhivēts. Ir iespējams aplūkot tā failus un to konēt, bet nav iespējams iesūtīt izmaiņas, kā arī izveidot jaunas problēmas vai izmaiņu pieprasījumus.
+archive.title_date=Šis repozitorijs tika arhivēts %s. Ir iespējams aplūkot tā failus un to konēt, bet nav iespējams iesūtīt izmaiņas, kā arī izveidot jaunas problēmas vai izmaiņu pieprasījumus.
archive.issue.nocomment=Repozitorijs ir arhivēts. Problēmām nevar pievienot jaunus komentārus.
archive.pull.nocomment=Repozitorijs ir arhivēts. Izmaiņu pieprasījumiem nevar pievienot jaunus komentārus.
@@ -998,6 +1066,7 @@ migrate_options_lfs=Migrēt LFS failus
migrate_options_lfs_endpoint.label=LFS galapunkts
migrate_options_lfs_endpoint.description=Migrācija mēģinās izmantot attālināto URL, lai noteiktu LFS serveri . Var norādīt arī citu galapunktu, ja repozitorija LFS dati ir izvietoti citā vietā.
migrate_options_lfs_endpoint.description.local=Iespējams norādīt arī servera ceļu.
+migrate_options_lfs_endpoint.placeholder=Ja nav norādīts, galamērķis tiks atvasināts no klonēšanas URL
migrate_items=Vienības, ko pārņemt
migrate_items_wiki=Vikivietni
migrate_items_milestones=Atskaites punktus
@@ -1048,11 +1117,11 @@ generated_from=ģenerēts no
fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks.
fork_guest_user=Piesakieties, lai atdalītu repozitoriju.
watch_guest_user=Piesakieties, lai sekotu šim repozitorijam.
-star_guest_user=Piesakieties, lai atzīmētu šo repozitoriju ar zvaigznīti.
+star_guest_user=Piesakieties, lai pievienotu šo repozitoriju izlasei.
unwatch=Nevērot
watch=Vērot
unstar=Noņemt zvaigznīti
-star=Pievienot zvaigznīti
+star=Pievienot izlasei
fork=Atdalīts
download_archive=Lejupielādēt repozitoriju
more_operations=Vairāk darbību
@@ -1100,6 +1169,10 @@ file_view_rendered=Skatīt rezultātu
file_view_raw=Rādīt neapstrādātu
file_permalink=Patstāvīgā saite
file_too_large=Šis fails ir par lielu, lai to parādītu.
+invisible_runes_header=`Šīs fails satur neredzamus unikoda simbolus`
+invisible_runes_description=`Šis fails satur neredzamus unikoda simbolus, kas ir neatšķirami cilvēkiem, bet dators tās var atstrādāt atšķirīgi. Ja šķiet, ka tas ir ar nolūku, šo brīdinājumu var droši neņemt vērā. Jāizmanto atsoļa taustiņš (Esc), lai atklātu tās.`
+ambiguous_runes_header=`Šis fails satur neviennozīmīgus unikoda simbolus`
+ambiguous_runes_description=`Šis fails satur unikoda simbolus, kas var tikt sajauktas ar citām rakstzīmēm. Ja šķiet, ka tas ir ar nolūku, šo brīdinājumu var droši neņemt vērā. Jāizmanto atsoļa taustiņš (Esc), lai atklātu tās.`
invisible_runes_line=`Šī līnija satur neredzamus unikoda simbolus`
ambiguous_runes_line=`Šī līnija satur neviennozīmīgus unikoda simbolus`
ambiguous_character=`%[1]c [U+%04[1]X] var tikt sajaukts ar %[2]c [U+%04[2]X]`
@@ -1112,11 +1185,15 @@ video_not_supported_in_browser=Jūsu pārlūks neatbalsta HTML5 video.
audio_not_supported_in_browser=Jūsu pārlūks neatbalsta HTML5 audio.
stored_lfs=Saglabāts Git LFS
symbolic_link=Simboliska saite
+executable_file=Izpildāmais fails
commit_graph=Revīziju grafs
commit_graph.select=Izvēlieties atzarus
commit_graph.hide_pr_refs=Paslēpt izmaiņu pieprasījumus
commit_graph.monochrome=Melnbalts
commit_graph.color=Krāsa
+commit.contained_in=Šī revīzija ir iekļauta:
+commit.contained_in_default_branch=Šī revīzija ir daļa no noklusētā atzara
+commit.load_referencing_branches_and_tags=Ielādēt atzarus un tagus, kas atsaucas uz šo revīziju
blame=Vainot
download_file=Lejupielādēt failu
normal_view=Parastais skats
@@ -1209,6 +1286,7 @@ commits.signed_by_untrusted_user=Parakstījis neuzticams lietotājs
commits.signed_by_untrusted_user_unmatched=Parakstījis neuzticams lietotājs, kas neatbilst izmaiņu autoram
commits.gpg_key_id=GPG atslēgas ID
commits.ssh_key_fingerprint=SSH atslēgas identificējošā zīmju virkne
+commits.view_path=Skatīt šajā vēstures punktā
commit.operations=Darbības
commit.revert=Atgriezt
@@ -1219,7 +1297,7 @@ commit.cherry-pick-header=Izlasīt: %s
commit.cherry-pick-content=Norādiet atzaru uz kuru izlasīt:
commitstatus.error=Kļūda
-commitstatus.failure=Neveiksmīgs
+commitstatus.failure=Kļūme
commitstatus.pending=Nav iesūtīts
commitstatus.success=Pabeigts
@@ -1336,14 +1414,15 @@ issues.delete_branch_at=`izdzēsa atzaru %s %s`
issues.filter_label=Etiķete
issues.filter_label_exclude=`Izmantojiet alt
+ peles klikšķis vai enter
, lai neiekļautu etiķeti`
issues.filter_label_no_select=Visas etiķetes
+issues.filter_label_select_no_label=Nav etiķetes
issues.filter_milestone=Atskaites punkts
issues.filter_milestone_all=Visi atskaites punkti
issues.filter_milestone_none=Nav atskaites punkta
issues.filter_milestone_open=Atvērtie atskaites punkti
issues.filter_milestone_closed=Aizvērtie atskaites punkti
-issues.filter_project=Projektus
+issues.filter_project=Projekts
issues.filter_project_all=Visi projekti
-issues.filter_project_none=Nav projektu
+issues.filter_project_none=Nav projekta
issues.filter_assignee=Atbildīgais
issues.filter_assginee_no_select=Visi atbildīgie
issues.filter_assginee_no_assignee=Nav atbildīgā
@@ -1369,6 +1448,7 @@ issues.filter_sort.moststars=Visvairāk atzīmētie
issues.filter_sort.feweststars=Vismazāk atzīmētie
issues.filter_sort.mostforks=Visvairāk atdalītie
issues.filter_sort.fewestforks=Vismazāk atdalītie
+issues.keyword_search_unavailable=Meklēšana pēc atslēgvārda pašreiz nav pieejama. Lūgums sazināties ar vietnes administratoru.
issues.action_open=Atvērt
issues.action_close=Aizvērt
issues.action_label=Etiķete
@@ -1389,6 +1469,7 @@ issues.next=Nākamā
issues.open_title=Atvērta
issues.closed_title=Slēgta
issues.draft_title=Melnraksts
+issues.num_comments_1=%d komentārs
issues.num_comments=%d komentāri
issues.commented_at=`komentēja %s `
issues.delete_comment_confirm=Vai patiešām vēlaties dzēst šo komentāru?
@@ -1397,6 +1478,7 @@ issues.context.quote_reply=Atbildēt citējot
issues.context.reference_issue=Atsaukties uz šo jaunā problēmā
issues.context.edit=Labot
issues.context.delete=Dzēst
+issues.no_content=Nav sniegts apraksts.
issues.close=Slēgt problēmu
issues.comment_pull_merged_at=saplidināta revīzija %[1]s atzarā %[2]s %[3]s
issues.comment_manually_pull_merged_at=manuāli saplidināta revīzija %[1]s atzarā %[2]s %[3]s
@@ -1415,8 +1497,17 @@ issues.ref_closed_from=`aizvēra problēmu %[4]s atkārtoti atvēra problēmu %[4]s %[2]s `
issues.ref_from=`no %[1]s`
issues.author=Autors
+issues.author_helper=Šis lietotājs ir autors.
issues.role.owner=Īpašnieks
-issues.role.member=Biedri
+issues.role.owner_helper=Šis lietotājs ir šī repozitorija īpašnieks.
+issues.role.member=Dalībnieks
+issues.role.member_helper=Šis lietotājs ir organizācijas, kurai pieder šis repozitorijs, dalībnieks.
+issues.role.collaborator=Līdzstrādnieks
+issues.role.collaborator_helper=Šis lietotājs ir uzaicināts līdzdarboties repozitorijā.
+issues.role.first_time_contributor=Pirmreizējs līdzradītājs
+issues.role.first_time_contributor_helper=Šis ir pirmais šī lietotāja ieguldījums šājā repozitorijā.
+issues.role.contributor=Līdzradītājs
+issues.role.contributor_helper=Šis lietotājs repozitorijā ir iepriekš veicis labojumus.
issues.re_request_review=Pieprasīt atkārtotu recenziju
issues.is_stale=Šajā izmaiņu pieprasījumā ir notikušas izmaiņās, kopš veicāt tā recenziju
issues.remove_request_review=Noņemt recenzijas pieprasījumu
@@ -1431,6 +1522,9 @@ issues.label_title=Etiķetes nosaukums
issues.label_description=Etiķetes apraksts
issues.label_color=Etiķetes krāsa
issues.label_exclusive=Ekskluzīvs
+issues.label_archive=Arhīvēt etiķeti
+issues.label_archived_filter=Rādīt arhivētās etiķetes
+issues.label_archive_tooltip=Arhivētās etiķetes pēc noklusējuma netiek iekļautas ieteikumos, kad meklē pēc nosaukuma.
issues.label_exclusive_desc=Nosauciet etiķeti grupa/nosaukums
, lai grupētu etiķētes un varētu norādīt tās kā ekskluzīvas ar citām grupa/
etiķetēm.
issues.label_exclusive_warning=Jebkura konfliktējoša ekskluzīvas grupas etiķete tiks noņemta, labojot pieteikumu vai izmaiņu pietikumu etiķetes.
issues.label_count=%d etiķetes
@@ -1485,6 +1579,7 @@ issues.tracking_already_started=`Jau ir uzsākta laika uzskaite par %[2]s#%[3]d `
@@ -1633,6 +1739,12 @@ pulls.is_empty=Mērķa atzars jau satur šī atzara izmaiņas. Šī revīzija b
pulls.required_status_check_failed=Dažas no pārbaudēm nebija veiksmīgas.
pulls.required_status_check_missing=Trūkst dažu obligāto pārbaužu.
pulls.required_status_check_administrator=Kā administrators Jūs varat sapludināt šo izmaiņu pieprasījumu.
+pulls.blocked_by_approvals=Šim izmaiņu pieprasījumam vēl nav pietiekami daudz apstiprinājumu. Nodrošināti %d no %d apstiprinājumiem.
+pulls.blocked_by_rejection=Šim izmaiņu pieprasījumam oficiālais recenzents ir pieprasījis labojumus.
+pulls.blocked_by_official_review_requests=Šim izmaiņu pieprasījumam ir oficiāli recenzijas pieprasījumi.
+pulls.blocked_by_outdated_branch=Šis izmaiņu pieprasījums ir bloķēts, jo tas ir novecojis.
+pulls.blocked_by_changed_protected_files_1=Šis izmaiņu pieprasījums ir bloķēts, jo tas izmaina aizsargāto failu:
+pulls.blocked_by_changed_protected_files_n=Šis izmaiņu pieprasījums ir bloķēts, jo tas izmaina aizsargātos failus:
pulls.can_auto_merge_desc=Šo izmaiņu pieprasījumu var automātiski sapludināt.
pulls.cannot_auto_merge_desc=Šis izmaiņu pieprasījums nevar tikt automātiski sapludināts konfliktu dēļ.
pulls.cannot_auto_merge_helper=Sapludiniet manuāli, lai atrisinātu konfliktus.
@@ -1667,6 +1779,7 @@ pulls.rebase_conflict_summary=Kļūdas paziņojums
pulls.unrelated_histories=Sapludināšana neizdevās: mērķa un bāzes atzariem nav kopējas vēstures. Ieteikums: izvēlieties citu sapludināšanas stratēģiju
pulls.merge_out_of_date=Sapludināšana neizdevās: sapludināšanas laikā, bāzes atzarā tika iesūtītas izmaiņas. Ieteikums: mēģiniet atkārtoti.
pulls.head_out_of_date=Sapludināšana neizdevās: sapludināšanas laikā, bāzes atzarā tika iesūtītas izmaiņas. Ieteikums: mēģiniet atkārtoti.
+pulls.has_merged=Neizdevās: izmaiņu pieprasījums jau ir sapludināts, nevar to darīt atkārtoti vai mainīt mērķa atzaru.
pulls.push_rejected=Sapludināšana neizdevās: iesūtīšana tika noraidīta. Pārbaudiet git āķus šim repozitorijam.
pulls.push_rejected_summary=Pilns noraidīšanas ziņojums
pulls.push_rejected_no_message=Sapludināšana neizdevās: Izmaiņu iesūtīšana tika noraidīta, bet serveris neatgrieza paziņojumu. Pārbaudiet git āķus šim repozitorijam
@@ -1678,6 +1791,8 @@ pulls.status_checks_failure=Dažas pārbaudes neizdevās izpildīt
pulls.status_checks_error=Dažu pārbaužu izpildes laikā, radās kļūdas
pulls.status_checks_requested=Obligāts
pulls.status_checks_details=Papildu informācija
+pulls.status_checks_hide_all=Paslēpt visas pārbaudes
+pulls.status_checks_show_all=Parādīt visas pārbaudes
pulls.update_branch=Atjaunot atzaru, izmantojot, sapludināšanu
pulls.update_branch_rebase=Atjaunot atzaru, izmantojot, pārbāzēšanu
pulls.update_branch_success=Atzara atjaunināšana veiksmīgi pabeigta
@@ -1686,6 +1801,11 @@ pulls.outdated_with_base_branch=Atzars ir novecojis salīdzinot ar bāzes atzaru
pulls.close=Aizvērt izmaiņu pieprasījumu
pulls.closed_at=`aizvēra šo izmaiņu pieprasījumu %[2]s `
pulls.reopened_at=`atkārtoti atvēra šo izmaiņu pieprasījumu %[2]s `
+pulls.cmd_instruction_hint=`Apskatīt komandrindas izmantošanas norādes .`
+pulls.cmd_instruction_checkout_title=Paņemt
+pulls.cmd_instruction_checkout_desc=Projekta repozitorijā jāizveido jauns atzars un jāpārbauda izmaiņas.
+pulls.cmd_instruction_merge_title=Sapludināt
+pulls.cmd_instruction_merge_desc=Sapludināt izmaiņas un atjaunot tās Gitea.
pulls.clear_merge_message=Notīrīt sapludināšanas ziņojumu
pulls.clear_merge_message_hint=Notīrot sapludināšanas ziņojumu tiks noņemts tikai pats ziņojums, bet tiks paturēti ģenerētie git ziņojumu, kā "Co-Authored-By …".
@@ -1704,7 +1824,9 @@ pulls.auto_merge_canceled_schedule_comment=`atcēla automātisko sapludināšanu
pulls.delete.title=Dzēst šo izmaiņu pieprasījumu?
pulls.delete.text=Vai patiešām vēlaties dzēst šo izmaiņu pieprasījumu? (Neatgriezeniski tiks izdzēsts viss saturs. Apsveriet iespēju to aizvērt, ja vēlaties informāciju saglabāt vēsturei)
+pulls.recently_pushed_new_branches=Tu iesūtīji izmaiņas atzarā %[1]s %[2]s
+pull.deleted_branch=(izdzēsts):%s
milestones.new=Jauns atskaites punkts
milestones.closed=Aizvērts %s
@@ -1712,6 +1834,7 @@ milestones.update_ago=Atjaunots %s
milestones.no_due_date=Bez termiņa
milestones.open=Atvērta
milestones.close=Aizvērt
+milestones.new_subheader=Atskaites punkti var palīdzēt pārvaldīt problēmas un sekot to virzībai.
milestones.completeness=%d%% pabeigti
milestones.create=Izveidot atskaites punktu
milestones.title=Virsraksts
@@ -1728,12 +1851,25 @@ milestones.edit_success=Izmaiņas atskaites punktā "%s" tika veiksmīgi saglab
milestones.deletion=Dzēst atskaites punktu
milestones.deletion_desc=Dzēšot šo atskaites punktu, tas tiks noņemts no visām saistītajām problēmām un izmaiņu pieprasījumiem. Vai turpināt?
milestones.deletion_success=Atskaites punkts tika veiksmīgi izdzēsts.
+milestones.filter_sort.earliest_due_data=Agrākais izpildes laiks
+milestones.filter_sort.latest_due_date=Vēlākais izpildes laiks
milestones.filter_sort.least_complete=Vismazāk pabeigtais
milestones.filter_sort.most_complete=Visvairāk pabeigtais
milestones.filter_sort.most_issues=Visvairāk problēmu
milestones.filter_sort.least_issues=Vismazāk problēmu
+signing.will_sign=Šī revīzija tiks parakstīta ar atslēgu "%s".
signing.wont_sign.error=Notika kļūda pārbaudot vai revīzija var tikt parakstīta.
+signing.wont_sign.nokey=Nav pieejamas atslēgas, ar ko parakstīt šo revīziju.
+signing.wont_sign.never=Revīzijas nekad netiek parakstītas.
+signing.wont_sign.always=Revīzijas vienmēr tiek parakstītas.
+signing.wont_sign.pubkey=Revīzija netiks parakstīta, jo kontam nav piesaistīta publiskā atslēga.
+signing.wont_sign.twofa=Jābūt iespējotai divfaktoru autentifikācijai, lai parakstītu revīzijas.
+signing.wont_sign.parentsigned=Revīzija netiks parakstīta, jo nav parakstīta vecāka revīzija.
+signing.wont_sign.basesigned=Sapludināšanas revīzija netiks parakstīta, jo pamata revīzija nav parakstīta.
+signing.wont_sign.headsigned=Sapludināšanas revīzija netiks parakstīta, jo galvenā revīzija nav parakstīta.
+signing.wont_sign.commitssigned=Sapludināšana netiks parakstīta, jo visas saistītās revīzijas nav parakstītas.
+signing.wont_sign.approved=Sapludināšana netiks parakstīta, jo izmaiņu pieprasījums nav apstiprināts.
signing.wont_sign.not_signed_in=Jūs neesat pieteicies.
ext_wiki=Piekļuve ārējai vikivietnei
@@ -1832,6 +1968,8 @@ activity.git_stats_and_deletions=un
activity.git_stats_deletion_1=%d dzēšana
activity.git_stats_deletion_n=%d dzēšanas
+contributors.contribution_type.commits=Revīzijas
+
search=Meklēt
search.search_repo=Meklēšana repozitorijā
search.type.tooltip=Meklēšanas veids
@@ -1864,6 +2002,7 @@ settings.mirror_settings.docs.disabled_push_mirror.info=Iesūtīšanas spoguļus
settings.mirror_settings.docs.no_new_mirrors=Šis repozitorijs spoguļo izmaiņas uz vai no cita repozitorija. Pašlaik vairāk nav iespējams izveidot jaunus spoguļa repozitorijus.
settings.mirror_settings.docs.can_still_use=Lai arī nav iespējams mainīt esošos vai izveidot jaunus spoguļa repozitorijus, esošie turpinās strādāt.
settings.mirror_settings.docs.pull_mirror_instructions=Lai ietatītu atvilkšanas spoguli, sekojiet instrukcijām:
+settings.mirror_settings.docs.more_information_if_disabled=Vairāk par piegādāšanas un saņemšanas spoguļiem var uzzināt šeit:
settings.mirror_settings.docs.doc_link_title=Kā spoguļot repozitorijus?
settings.mirror_settings.docs.doc_link_pull_section=dokumentācijas nodaļā "Pulling from a remote repository".
settings.mirror_settings.docs.pulling_remote_title=Atvilkt no attāla repozitorija
@@ -1875,8 +2014,11 @@ settings.mirror_settings.last_update=Pēdējās izmaiņas
settings.mirror_settings.push_mirror.none=Nav konfigurēts iesūtīšanas spogulis
settings.mirror_settings.push_mirror.remote_url=Git attālinātā repozitorija URL
settings.mirror_settings.push_mirror.add=Pievienot iesūtīšanas spoguli
+settings.mirror_settings.push_mirror.edit_sync_time=Labot spoguļa sinhronizācijas intervālu
settings.sync_mirror=Sinhronizēt tagad
+settings.pull_mirror_sync_in_progress=Pašlaik tiek saņemtas izmaiņas no attālā %s.
+settings.push_mirror_sync_in_progress=Pašlaik tiek piegādātas izmaiņas uz attālo %s.
settings.site=Mājas lapa
settings.update_settings=Mainīt iestatījumus
settings.update_mirror_settings=Atjaunot spoguļa iestatījumus
@@ -1943,6 +2085,7 @@ settings.transfer.rejected=Repozitorija īpašnieka maiņas pieprasījums tika n
settings.transfer.success=Repozitorija īpašnieka maiņa veiksmīga.
settings.transfer_abort=Atcelt īpašnieka maiņu
settings.transfer_abort_invalid=Nevar atcelt neeksistējoša repozitorija īpašnieka maiņu.
+settings.transfer_abort_success=Repozitorija īpašnieka maiņa uz %s tika veiksmīgi atcelta.
settings.transfer_desc=Mainīt šī repozitorija īpašnieku uz citu lietotāju vai organizāciju, kurai Jums ir administratora tiesības.
settings.transfer_form_title=Ievadiet repozitorija nosaukumu, lai apstiprinātu:
settings.transfer_in_progress=Pašlaik jau tiek veikta repozitorija īpašnieka maiņa. Atceliet iepriekšējo īpašnieka maiņu, ja vēlaties mainīt uz citu.
@@ -1967,12 +2110,12 @@ settings.trust_model.collaboratorcommitter=Līdzstrādnieka un revīzijas iesūt
settings.trust_model.collaboratorcommitter.long=Līdzstrādnieka un revīzijas iesūtītāja: Uzticēties līdzstrādnieku parakstiem, kas atbilst revīzijas iesūtītājam
settings.trust_model.collaboratorcommitter.desc=Derīgi līdzstrādnieku paraksti tiks atzīmēti kā "uzticami", ja tie atbilst revīzijas iesūtītājam, citos gadījumos tie tiks atzīmēti kā "neuzticami", ja paraksts atbilst revīzijas iesūtītajam, vai "nesakrītoši", ja neatbilst. Šis nozīmē, ka Gitea būs kā revīzijas iesūtītājs parakstītām revīzijām, kur īstais revīzijas iesūtītājs tiks atīzmēts revīzijas komentāra beigās ar tekstu Co-Authored-By: un Co-Committed-By:. Noklusētajai Gitea atslēgai ir jāatbilst lietotājam datubāzē.
settings.wiki_delete=Dzēst vikivietnes datus
-settings.wiki_delete_desc=Vikivietnes repozitorija dzēšana ir NEATGRIEZENISKA . Vai turpināt?
+settings.wiki_delete_desc=Vikivietnes repozitorija dzēšana ir neatgriezeniska un nav atsaucama.
settings.wiki_delete_notices_1=- Šī darbība dzēsīs un atspējos repozitorija %s vikivietni.
settings.confirm_wiki_delete=Dzēst vikivietnes datus
settings.wiki_deletion_success=Repozitorija vikivietnes dati tika izdzēsti.
settings.delete=Dzēst šo repozitoriju
-settings.delete_desc=Repozitorija dzēšana ir NEATGRIEZENISKA . Vai turpināt?
+settings.delete_desc=Repozitorija dzēšana ir neatgriezeniska un nav atsaucama.
settings.delete_notices_1=- Šī darbība ir NEATGRIEZENISKA .
settings.delete_notices_2=- Šī darbība neatgriezeniski izdzēsīs visu repozitorijā %s , tai skaitā problēmas, komentārus, vikivietni un līdzstrādnieku piesaisti.
settings.delete_notices_fork_1=- Visi atdalītie repozitoriju pēc dzēšanas kļūs neatkarīgi.
@@ -2009,12 +2152,14 @@ settings.webhook_deletion_desc=Noņemot tīmekļa āķi, tiks dzēsti visi tā i
settings.webhook_deletion_success=Tīmekļa āķis tika noņemts.
settings.webhook.test_delivery=Testa piegāde
settings.webhook.test_delivery_desc=Veikt viltus push-notikuma piegādi, lai notestētu Jūsu tīmekļa āķa iestatījumus.
+settings.webhook.test_delivery_desc_disabled=Lai pārbaudītu šo tīmekļa āķi ar neīstu notikumu, tas ir jāiespējo.
settings.webhook.request=Pieprasījums
settings.webhook.response=Atbilde
settings.webhook.headers=Galvenes
settings.webhook.payload=Saturs
settings.webhook.body=Saturs
settings.webhook.replay.description=Izpildīt atkārtoti šo tīmekļa āķi.
+settings.webhook.replay.description_disabled=Lai atkārtoti izpildītu šo tīmekļa āķi, tas ir jāiespējo.
settings.webhook.delivery.success=Notikums tika veiksmīgi pievienots piegādes rindai. Var paiet vairākas sekundes līdz tas parādās piegādes vēsturē.
settings.githooks_desc=Git āķus apstrādā pats Git. Jūs varat labot atbalstīto āku failus sarakstā zemāk, lai veiktu pielāgotas darbības.
settings.githook_edit_desc=Ja āķis nav aktīvs, tiks attēlots piemērs kā to izmantot. Atstājot āķa saturu tukšu, tas tiks atspējots.
@@ -2174,6 +2319,7 @@ settings.dismiss_stale_approvals_desc=Kad tiek iesūtītas jaunas revīzijas, ka
settings.require_signed_commits=Pieprasīt parakstītas revīzijas
settings.require_signed_commits_desc=Noraidīt iesūtītās izmaiņas šim atzaram, ja tās nav parakstītas vai nav iespējams pārbaudīt.
settings.protect_branch_name_pattern=Aizsargātā zara šablons
+settings.protect_branch_name_pattern_desc=Aizsargāto atzaru nosaukumu šabloni. Šablonu pierakstu skatīt dokumentācijā . Piemēri: main, release/**
settings.protect_patterns=Šabloni
settings.protect_protected_file_patterns=Aizsargāto failu šablons (vairākus var norādīt atdalot ar semikolu ';'):
settings.protect_protected_file_patterns_desc=Aizsargātie faili, ko nevar mainīt, pat ja lietotājam ir tiesības veidot jaunus, labot vai dzēst failus šajā atzarā. Vairākus šablons ir iespējams norādīt atdalot tos ar semikolu (';'). Sīkāka informācija par šabloniem pieejama github.com/gobwas/glob dokumentācijā. Piemēram, .drone.yml
, /docs/**/*.txt
.
@@ -2210,18 +2356,26 @@ settings.tags.protection.allowed.teams=Atļauts komandām
settings.tags.protection.allowed.noone=Nevienam
settings.tags.protection.create=Aizsargāt tagus
settings.tags.protection.none=Nav uzstādīta tagu aizsargāšana.
+settings.tags.protection.pattern.description=Var izmantot vienkāršu nosaukumu vai glob šablonu, vai regulāro izteiksmi, lai atbilstu vairākiem tagiem. Vairāk ir lasāms aizsargāto tagu šablonu dokumentācijā .
settings.bot_token=Bota pilnvara
settings.chat_id=Tērzēšanas ID
+settings.thread_id=Pavediena ID
settings.matrix.homeserver_url=Mājas servera URL
settings.matrix.room_id=Istabas ID
settings.matrix.message_type=Ziņas veids
settings.archive.button=Arhivēt
settings.archive.header=Arhivēt repozitoriju
+settings.archive.text=Repozitorija arhivēšana padarīs to tikai lasāmu. Tas nebūs redzams infopanelī. Neviens nevarēs izveidot jaunas revīzijas vai atvērt jaunus problēmu pieteikumus vai izmaiņu pieprasījumus.
settings.archive.success=Repozitorijs veiksmīgi arhivēts.
settings.archive.error=Arhivējot repozitoriju radās neparedzēta kļūda. Pārbaudiet kļūdu žurnālu, lai uzzinātu sīkāk.
settings.archive.error_ismirror=Nav iespējams arhivēt spoguļotus repozitorijus.
settings.archive.branchsettings_unavailable=Atzaru iestatījumi nav pieejami, ja repozitorijs ir arhivēts.
settings.archive.tagsettings_unavailable=Tagu iestatījumi nav pieejami, ja repozitorijs ir arhivēts.
+settings.unarchive.button=Atcelt repozitorija arhivēšanu
+settings.unarchive.header=Atcelt šī repozitorija arhivēšanu
+settings.unarchive.text=Repozitorija arhivēšanas atcelšana atjaunos tā spēju saņemt izmaiņas, kā arī jaunus problēmu pieteikumus un izmaiņu pieprasījumus.
+settings.unarchive.success=Repozitorijam veiksmīgi atcelta arhivācija.
+settings.unarchive.error=Repozitorija arhivēšanas atcelšanas laikā atgadījās kļūda. Vairāk ir redzams žurnālā.
settings.update_avatar_success=Repozitorija attēls tika atjaunināts.
settings.lfs=LFS
settings.lfs_filelist=LFS faili, kas saglabāti šajā repozitorijā
@@ -2288,6 +2442,7 @@ diff.show_more=Rādīt vairāk
diff.load=Ielādēt izmaiņas
diff.generated=ģenerēts
diff.vendored=ārējs
+diff.comment.add_line_comment=Pievienot rindas komentāru
diff.comment.placeholder=Ievadiet komentāru
diff.comment.markdown_info=Tiek atbalstīta formatēšana ar Markdown.
diff.comment.add_single_comment=Pievienot vienu komentāru
@@ -2344,6 +2499,7 @@ release.edit_release=Labot laidienu
release.delete_release=Dzēst laidienu
release.delete_tag=Dzēst tagu
release.deletion=Dzēst laidienu
+release.deletion_desc=Laidiena izdzēšana tikai noņem to no Gitea. Tā neietekmēs Git tagu, repozitorija saturu vai vēsturi. Vai turpināt?
release.deletion_success=Laidiens tika izdzēsts.
release.deletion_tag_desc=Tiks izdzēsts tags no repozitorija. Repozitorija saturs un vēsture netiks mainīta. Vai turpināt?
release.deletion_tag_success=Tags tika izdzēsts.
@@ -2363,6 +2519,7 @@ branch.already_exists=Atzars ar nosaukumu "%s" jau eksistē.
branch.delete_head=Dzēst
branch.delete=`Dzēst atzaru "%s"`
branch.delete_html=Dzēst atzaru
+branch.delete_desc=Atzara dzēšana ir neatgriezeniska. Kaut arī izdzēstais zars neilgu laiku var turpināt pastāvēt, pirms tas tiešām tiek noņemts, to vairumā gadījumu NEVAR atsaukt. Vai turpināt?
branch.deletion_success=Atzars "%s" tika izdzēsts.
branch.deletion_failed=Neizdevās izdzēst atzaru "%s".
branch.delete_branch_has_new_commits=Atzars "%s" nevar tik dzēsts, jo pēc sapludināšanas, tam ir pievienotas jaunas revīzijas.
@@ -2380,13 +2537,14 @@ branch.default_deletion_failed=Atzars "%s" ir noklusētais atzars un to nevar dz
branch.restore=`Atjaunot atzaru "%s"`
branch.download=`Lejupielādēt atzaru "%s"`
branch.rename=`Pārsaukt atzaru "%s"`
+branch.search=Meklēt atzarā
branch.included_desc=Šis atzars ir daļa no noklusēta atzara
branch.included=Iekļauts
branch.create_new_branch=Izveidot jaunu atzaru no atzara:
branch.confirm_create_branch=Izveidot atzaru
branch.warning_rename_default_branch=Tiks pārsaukts noklusētais atzars.
branch.rename_branch_to=Pārsaukt "%s" uz:
-branch.confirm_rename_branch=Pārsaukt atzaru
+branch.confirm_rename_branch=Pārdēvēt atzaru
branch.create_branch_operation=Izveidot atzaru
branch.new_branch=Izveidot jaunu atzaru
branch.new_branch_from=`Izveidot jaunu atzaru no "%s"`
@@ -2402,6 +2560,7 @@ tag.create_success=Tags "%s" tika izveidots.
topic.manage_topics=Pārvaldīt tēmas
topic.done=Gatavs
topic.count_prompt=Nevar pievienot vairāk kā 25 tēmas
+topic.format_prompt=Tēmai jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un punktus ('.') un var būt līdz 35 rakstzīmēm gara. Burtiem jābūt mazajiem.
find_file.go_to_file=Iet uz failu
find_file.no_matching=Atbilstošs fails netika atrasts
@@ -2410,6 +2569,12 @@ error.csv.too_large=Nevar attēlot šo failu, jo tas ir pārāk liels.
error.csv.unexpected=Nevar attēlot šo failu, jo tas satur neparedzētu simbolu %d. līnijas %d. kolonnā.
error.csv.invalid_field_count=Nevar attēlot šo failu, jo tas satur nepareizu skaitu ar laukiem %d. līnijā.
+[graphs]
+component_loading=Ielādē %s...
+component_loading_failed=Nevarēja ielādēt %s
+component_loading_info=Šis var aizņemt kādu brīdi…
+component_failed_to_load=Atgadījās neparedzēta kļūda.
+
[org]
org_name_holder=Organizācijas nosaukums
org_full_name_holder=Organizācijas pilnais nosaukums
@@ -2440,6 +2605,7 @@ form.create_org_not_allowed=Jums nav tiesību veidot jauno organizāciju.
settings=Iestatījumi
settings.options=Organizācija
settings.full_name=Pilns vārds, uzvārds
+settings.email=E-pasta adrese saziņai
settings.website=Mājas lapa
settings.location=Atrašanās vieta
settings.permission=Tiesības
@@ -2453,6 +2619,7 @@ settings.visibility.private_shortname=Privāta
settings.update_settings=Mainīt iestatījumus
settings.update_setting_success=Organizācijas iestatījumi tika saglabāti.
+settings.change_orgname_prompt=Piezīme: organizācijas nosaukuma maiņa izmainīs arī organizācijas URL un atbrīvos veco nosaukumu.
settings.change_orgname_redirect_prompt=Vecais vārds pārsūtīs uz jauno, kamēr vien tas nebūs izmantots.
settings.update_avatar_success=Organizācijas attēls tika saglabāts.
settings.delete=Dzēst organizāciju
@@ -2472,7 +2639,7 @@ members.private=Slēpts
members.private_helper=padarīt redzemu
members.member_role=Dalībnieka loma:
members.owner=Īpašnieks
-members.member=Biedri
+members.member=Dalībnieks
members.remove=Noņemt
members.remove.detail=Noņemt lietotāju %[1]s no organizācijas %[2]s?
members.leave=Atstāt
@@ -2528,15 +2695,20 @@ teams.all_repositories_helper=Šai komandai ir piekļuve visiem repozitorijiem.
teams.all_repositories_read_permission_desc=Šī komanda piešķirt skatīšanās tiesības visiem repozitorijiem : komandas biedri var skatīties un klonēt visus organizācijas repozitorijus.
teams.all_repositories_write_permission_desc=Šī komanda piešķirt labošanas tiesības visiem repozitorijiem : komandas biedri var skatīties un nosūtīt izmaiņas visiem organizācijas repozitorijiem.
teams.all_repositories_admin_permission_desc=Šī komanda piešķirt administratora tiesības visiem repozitorijiem : komandas biedri var skatīties, nosūtīt izmaiņas un mainīt iestatījumus visiem organizācijas repozitorijiem.
+teams.invite.title=Tu esi uzaicināts pievienoties organizācijas %[2]s komandai %[1]s .
teams.invite.by=Uzaicināja %s
teams.invite.description=Nospiediet pogu zemāk, lai pievienotos komandai.
[admin]
dashboard=Infopanelis
+self_check=Pašpārbaude
+identity_access=Identitāte un piekļuve
users=Lietotāju konti
organizations=Organizācijas
+assets=Koda aktīvi
repositories=Repozitoriji
hooks=Tīmekļa āķi
+integrations=Integrācijas
authentication=Autentificēšanas avoti
emails=Lietotāja e-pasts
config=Konfigurācija
@@ -2545,6 +2717,7 @@ monitor=Uzraudzība
first_page=Pirmā
last_page=Pēdējā
total=Kopā: %d
+settings=Administratora iestatījumi
dashboard.new_version_hint=Ir pieejama Gitea versija %s, pašreizējā versija %s. Papildus informācija par jauno versiju ir pieejama mājas lapā .
dashboard.statistic=Kopsavilkums
@@ -2557,11 +2730,13 @@ dashboard.clean_unbind_oauth=Notīrīt nepiesaistītos OAuth savienojumus
dashboard.clean_unbind_oauth_success=Visi nepiesaistītie OAuth savienojumu tika izdzēsti.
dashboard.task.started=Uzsākts uzdevums: %[1]s
dashboard.task.process=Uzdevums: %[1]s
+dashboard.task.cancelled=Uzdevums: %[1]s atcelts: %[3]s
dashboard.task.error=Kļūda uzdevuma izpildē: %[1]s: %[3]s
dashboard.task.finished=Uzdevums: %[1]s, ko iniciēja %[2]s ir izpildīts
dashboard.task.unknown=Nezināms uzdevums: %[1]s
dashboard.cron.started=Uzsākts Cron: %[1]s
dashboard.cron.process=Cron: %[1]s
+dashboard.cron.cancelled=Cron: %[1]s atcelts: %[3]s
dashboard.cron.error=Kļūda Cron: %s: %[3]s
dashboard.cron.finished=Cron: %[1]s pabeigts
dashboard.delete_inactive_accounts=Dzēst visus neaktivizētos kontus
@@ -2571,6 +2746,7 @@ dashboard.delete_repo_archives.started=Uzdevums visu repozitoriju arhīvu dzēš
dashboard.delete_missing_repos=Dzēst visus repozitorijus, kam trūkst Git failu
dashboard.delete_missing_repos.started=Uzdevums visu repozitoriju dzēšanai, kam trūkst git failu, uzsākts.
dashboard.delete_generated_repository_avatars=Dzēst ģenerētos repozitoriju attēlus
+dashboard.sync_repo_branches=Sinhronizācija ar dabubāzi izlaida atzarus no git datiem
dashboard.update_mirrors=Atjaunot spoguļus
dashboard.repo_health_check=Pārbaudīt visu repozitoriju veselību
dashboard.check_repo_stats=Pārbaudīt visu repozitoriju statistiku
@@ -2585,6 +2761,7 @@ dashboard.reinit_missing_repos=Atkārtoti inicializēt visus pazaudētos Git rep
dashboard.sync_external_users=Sinhronizēt ārējo lietotāju datus
dashboard.cleanup_hook_task_table=Iztīrīt tīmekļa āķu vēsturi
dashboard.cleanup_packages=Notīrīt novecojušās pakotnes
+dashboard.cleanup_actions=Notīrīt darbību izbeigušos žurnālus un artefaktus
dashboard.server_uptime=Servera darbības laiks
dashboard.current_goroutine=Izmantotās Gorutīnas
dashboard.current_memory_usage=Pašreiz izmantotā atmiņa
@@ -2622,6 +2799,9 @@ dashboard.gc_lfs=Veikt atkritumu uzkopšanas darbus LFS meta objektiem
dashboard.stop_zombie_tasks=Apturēt zombija uzdevumus
dashboard.stop_endless_tasks=Apturēt nepārtrauktus uzdevumus
dashboard.cancel_abandoned_jobs=Atcelt pamestus darbus
+dashboard.start_schedule_tasks=Sākt plānotos uzdevumus
+dashboard.sync_branch.started=Sākta atzaru sinhronizācija
+dashboard.rebuild_issue_indexer=Pārbūvēt problēmu indeksu
users.user_manage_panel=Lietotāju kontu pārvaldība
users.new_account=Izveidot lietotāja kontu
@@ -2630,6 +2810,9 @@ users.full_name=Vārds, uzvārds
users.activated=Aktivizēts
users.admin=Administrators
users.restricted=Ierobežots
+users.reserved=Aizņemts
+users.bot=Bots
+users.remote=Attāls
users.2fa=2FA
users.repos=Repozitoriji
users.created=Izveidots
@@ -2676,6 +2859,7 @@ users.list_status_filter.is_prohibit_login=Nav atļauta autorizēšanās
users.list_status_filter.not_prohibit_login=Atļaut autorizāciju
users.list_status_filter.is_2fa_enabled=2FA iespējots
users.list_status_filter.not_2fa_enabled=2FA nav iespējots
+users.details=Lietotāja informācija
emails.email_manage_panel=Lietotāju e-pastu pārvaldība
emails.primary=Primārais
@@ -2688,6 +2872,7 @@ emails.updated=E-pasts atjaunots
emails.not_updated=Neizdevās atjaunot pieprasīto e-pasta adresi: %v
emails.duplicate_active=E-pasta adrese jau ir aktīva citam lietotājam.
emails.change_email_header=Atjaunot e-pasta rekvizītus
+emails.change_email_text=Vai patiešām vēlaties atjaunot šo e-pasta adresi?
orgs.org_manage_panel=Organizāciju pārvaldība
orgs.name=Nosaukums
@@ -2702,14 +2887,17 @@ repos.owner=Īpašnieks
repos.name=Nosaukums
repos.private=Privāts
repos.watches=Vērošana
-repos.stars=Atzīmētās zvaigznītes
+repos.stars=Zvaigznes
repos.forks=Atdalītie
repos.issues=Problēmas
repos.size=Izmērs
+repos.lfs_size=LFS izmērs
packages.package_manage_panel=Pakotņu pārvaldība
packages.total_size=Kopējais izmērs: %s
packages.unreferenced_size=Izmērs bez atsauces: %s
+packages.cleanup=Notīrīt novecojušos datus
+packages.cleanup.success=Novecojuši dati veiksmīgi notīrīti
packages.owner=Īpašnieks
packages.creator=Izveidotājs
packages.name=Nosaukums
@@ -2720,10 +2908,12 @@ packages.size=Izmērs
packages.published=Publicēts
defaulthooks=Noklusētie tīmekļa āķi
+defaulthooks.desc=Tīmekļa āķi automātiski nosūta HTTP POST pieprasījumus serverim, kad iestājas noteikti Gitea notikumi. Šeit pievienotie tīmekļa āķi ir noklusējuma, un tie tiks pievienoti visiem jaunajiem repozitorijiem. Vairāk ir lasāms tīmekļa āķu dokumentācijā .
defaulthooks.add_webhook=Pievienot noklusēto tīmekļa āķi
defaulthooks.update_webhook=Mainīt noklusēto tīmekļa āķi
systemhooks=Sistēmas tīmekļa āķi
+systemhooks.desc=Tīmekļa āķi automātiski nosūta HTTP POST pieprasījumus serverim, kad iestājas noteikti Gitea notikumi. Šeit pievienotie tīmekļa āķi tiks izsaukti visiem sistēmas repozitorijiem, tādēļ lūgums apsvērt to iespējamo ietekmi uz veiktspēju. Vairāk ir lasāms tīmekļa āķu dokumentācijā .
systemhooks.add_webhook=Pievienot sistēmas tīmekļa āķi
systemhooks.update_webhook=Mainīt sistēmas tīmekļa āķi
@@ -2816,6 +3006,7 @@ auths.sspi_default_language=Noklusētā lietotāja valoda
auths.sspi_default_language_helper=Noklusētā valoda, ko uzstādīt automātiski izveidotajiem lietotājiem, kas izmanto SSPI autentifikācijas veidu. Atstājiet tukšu, ja vēlaties, lai valoda tiktu noteikta automātiski.
auths.tips=Padomi
auths.tips.oauth2.general=OAuth2 autentifikācija
+auths.tips.oauth2.general.tip=Kad tiek reģistrēta jauna OAuth2 autentifikācija, atzvanīšanas/pārvirzīšanas URL vajadzētu būt:
auths.tip.oauth2_provider=OAuth2 pakalpojuma sniedzējs
auths.tip.bitbucket=Reģistrējiet jaunu OAuth klientu adresē https://bitbucket.org/account/user//oauth-consumers/new un piešķiriet tam "Account" - "Read" tiesības
auths.tip.nextcloud=`Reģistrējiet jaunu OAuth klientu jūsu instances sadāļā "Settings -> Security -> OAuth 2.0 client"`
@@ -2827,6 +3018,7 @@ auths.tip.google_plus=Iegūstiet OAuth2 klienta pilnvaru no Google API konsoles
auths.tip.openid_connect=Izmantojiet OpenID pieslēgšanās atklāšanas URL (/.well-known/openid-configuration), lai norādītu galapunktus
auths.tip.twitter=Dodieties uz adresi https://dev.twitter.com/apps, izveidojiet lietotni un pārliecinieties, ka ir atzīmēts “Allow this application to be used to Sign in with Twitter”
auths.tip.discord=Reģistrējiet jaunu aplikāciju adresē https://discordapp.com/developers/applications/me
+auths.tip.gitea=Pievienot jaunu OAuth2 lietojumprogrammu. Dokumentācija ir pieejama https://docs.gitea.com/development/oauth2-provider
auths.tip.yandex=`Izveidojiet jaunu lietotni adresē https://oauth.yandex.com/client/new. Izvēlieties sekojošas tiesības "Yandex.Passport API" sadaļā: "Access to email address", "Access to user avatar" un "Access to username, first name and surname, gender"`
auths.tip.mastodon=Norādiet pielāgotu mastodon instances URL, ar kuru vēlaties autorizēties (vai izmantojiet noklusēto)
auths.edit=Labot autentifikācijas avotu
@@ -2856,6 +3048,7 @@ config.disable_router_log=Atspējot maršrutētāja žurnalizēšanu
config.run_user=Izpildes lietotājs
config.run_mode=Izpildes režīms
config.git_version=Git versija
+config.app_data_path=Lietotnes datu ceļš
config.repo_root_path=Repozitoriju glabāšanas vieta
config.lfs_root_path=LFS saknes ceļš
config.log_file_root_path=Žurnalizēšanas ceļš
@@ -3005,8 +3198,10 @@ monitor.queue.name=Nosaukums
monitor.queue.type=Veids
monitor.queue.exemplar=Eksemplāra veids
monitor.queue.numberworkers=Strādņu skaits
+monitor.queue.activeworkers=Darbojošies strādņi
monitor.queue.maxnumberworkers=Maksimālais strādņu skaits
monitor.queue.numberinqueue=Skaits rindā
+monitor.queue.review_add=Pārskatīt/pievienot strādņus
monitor.queue.settings.title=Pūla iestatījumi
monitor.queue.settings.desc=Pūls dinamiski tiek palielināts atkarībā no bloķētiem darbiem rindā.
monitor.queue.settings.maxnumberworkers=Maksimālais strādņu skaits
@@ -3032,6 +3227,8 @@ notices.desc=Apraksts
notices.op=Op.
notices.delete_success=Sistēmas paziņojumi ir dzēsti.
+self_check.no_problem_found=Pašlaik nav atrasta neviena problēma.
+
[action]
create_repo=izveidoja repozitoriju %s
rename_repo=pārsauca repozitoriju no %[1]s
uz %[3]s
@@ -3062,7 +3259,7 @@ publish_release=`izveidoja versiju "%[4]s" repozitorijā <
review_dismissed=`noraidīja lietotāja %[4]s recenziju izmaiņu pieprasījumam %[3]s#%[2]s `
review_dismissed_reason=Iemesls:
create_branch=izveidoja atzaru %[3]s repozitorijā %[4]s
-starred_repo=atzīmēja ar zvaigznīti %[2]s
+starred_repo=pievienoja izlasē %[2]s
watched_repo=sāka sekot %[2]s
[tool]
@@ -3127,6 +3324,7 @@ desc=Pārvaldīt repozitorija pakotnes.
empty=Pašlaik šeit nav nevienas pakotnes.
empty.documentation=Papildus informācija par pakotņu reģistru pieejama dokumentācijā .
empty.repo=Neparādās augšupielādēta pakotne? Apmeklējiet pakotņu iestatījumus , lai sasaistītu ar repozitoriju.
+registry.documentation=Vairāk informācija par %s reģistru ir pieejama dokumentācijā .
filter.type=Veids
filter.type.all=Visas
filter.no_result=Pēc norādītajiem kritērijiem nekas netika atrasts.
@@ -3212,7 +3410,11 @@ pub.install=Lai instalētu Dart pakotni, izpildiet sekojošu komandu:
pypi.requires=Nepieciešams Python
pypi.install=Lai instalētu pip pakotni, izpildiet sekojošu komandu:
rpm.registry=Konfigurējiet šo reģistru no komandrindas:
+rpm.distros.redhat=uz RedHat balstītās operētājsistēmās
+rpm.distros.suse=uz SUSE balstītās operētājsistēmās
rpm.install=Lai uzstādītu pakotni, ir jāizpilda šī komanda:
+rpm.repository=Repozitorija informācija
+rpm.repository.architectures=Arhitektūras
rubygems.install=Lai instalētu gem pakotni, izpildiet sekojošu komandu:
rubygems.install2=vai pievienojiet Gemfile:
rubygems.dependencies.runtime=Izpildlaika atkarības
@@ -3236,14 +3438,17 @@ settings.delete.success=Pakotne tika izdzēsta.
settings.delete.error=Neizdevās izdzēst pakotni.
owner.settings.cargo.title=Cargo reģistra inkdess
owner.settings.cargo.initialize=Inicializēt indeksu
+owner.settings.cargo.initialize.description=Ir nepieciešams īpašs indeksa Git repozitorijs, lai izmantotu Cargo reģistru. Šīs iespējas izmantošana (atkārtoti) izveidos repozitoriju un automātiski to iestatīs.
owner.settings.cargo.initialize.error=Neizdevās inicializēt Cargo indeksu: %v
owner.settings.cargo.initialize.success=Cargo indekss tika veiksmīgi inicializēts.
owner.settings.cargo.rebuild=Pārbūvēt indeksu
+owner.settings.cargo.rebuild.description=Pārbūvēšana var būt noderīga, ja indekss nav sinhronizēts ar saglabātajām Cargo pakotnēm.
owner.settings.cargo.rebuild.error=Neizdevās pārbūvēt Cargo indeksu: %v
owner.settings.cargo.rebuild.success=Cargo indekss tika veiksmīgi pārbūvēts.
owner.settings.cleanuprules.title=Pārvaldīt notīrīšanas noteikumus
owner.settings.cleanuprules.add=Pievienot notīrīšanas noteikumu
owner.settings.cleanuprules.edit=Labot notīrīšanas noteikumu
+owner.settings.cleanuprules.none=Nav pievienoti tīrīšanas noteikumi. Sīkāku informāciju iespējams iegūt dokumentācijā.
owner.settings.cleanuprules.preview=Notīrīšānas noteikuma priekšskatījums
owner.settings.cleanuprules.preview.overview=Ir ieplānota %d paku dzēšana.
owner.settings.cleanuprules.preview.none=Notīrīšanas noteikumam neatbilst neviena pakotne.
@@ -3262,6 +3467,7 @@ owner.settings.cleanuprules.success.update=Notīrīšanas noteikumi tika atjauno
owner.settings.cleanuprules.success.delete=Notīrīšanas noteikumi tika izdzēsti.
owner.settings.chef.title=Chef reģistrs
owner.settings.chef.keypair=Ģenerēt atslēgu pāri
+owner.settings.chef.keypair.description=Atslēgu pāris ir nepieciešams, lai autentificētos Chef reģistrā. Ja iepriekš ir izveidots atslēgu pāris, jauna pāra izveidošana veco atslēgu pāri padarīs nederīgu.
[secrets]
secrets=Noslēpumi
@@ -3288,6 +3494,7 @@ status.waiting=Gaida
status.running=Izpildās
status.success=Pabeigts
status.failure=Neveiksmīgs
+status.cancelled=Atcelts
status.skipped=Izlaists
status.blocked=Bloķēts
@@ -3300,11 +3507,12 @@ runners.id=ID
runners.name=Nosaukums
runners.owner_type=Veids
runners.description=Apraksts
-runners.labels=Etiķetes
+runners.labels=Iezīmes
runners.last_online=Pēdējo reizi tiešsaistē
runners.runner_title=Izpildītājs
runners.task_list=Pēdējās darbības, kas izpildītas
-runners.task_list.run=Palaist
+runners.task_list.no_tasks=Vēl nav uzdevumu.
+runners.task_list.run=Izpildīt
runners.task_list.status=Statuss
runners.task_list.repository=Repozitorijs
runners.task_list.commit=Revīzija
@@ -3324,16 +3532,47 @@ runners.status.idle=Dīkstāvē
runners.status.active=Aktīvs
runners.status.offline=Bezsaistē
runners.version=Versija
+runners.reset_registration_token=Atiestatīt reģistrācijas pilnvaru
runners.reset_registration_token_success=Izpildītāja reģistrācijas pilnvara tika veiksmīgi atiestatīta
runs.all_workflows=Visas darbaplūsmas
runs.commit=Revīzija
+runs.scheduled=Ieplānots
+runs.pushed_by=iesūtīja
runs.invalid_workflow_helper=Darbaplūsmas konfigurācijas fails ir kļūdains. Pārbaudiet konfiugrācijas failu: %s
+runs.no_matching_online_runner_helper=Nav pieejami izpildītāji, kas atbilstu šai iezīmei: %s
+runs.actor=Aktors
runs.status=Statuss
+runs.actors_no_select=Visi aktori
+runs.status_no_select=Visi stāvokļi
+runs.no_results=Netika atrasts nekas atbilstošs.
+runs.no_workflows=Vēl nav nevienas darbplūsmas.
+runs.no_runs=Darbplūsmai vēl nav nevienas izpildes.
+runs.empty_commit_message=(tukšs revīzijas ziņojums)
+workflow.disable=Atspējot darbplūsmu
+workflow.disable_success=Darbplūsma '%s' ir veiksmīgi atspējota.
+workflow.enable=Iespējot darbplūsmu
+workflow.enable_success=Darbplūsma '%s' ir veiksmīgi iespējota.
+workflow.disabled=Darbplūsma ir atspējota.
need_approval_desc=Nepieciešams apstiprinājums, lai izpildītu izmaiņu pieprasījumu darbaplūsmas no atdalītiem repozitorijiem.
+variables=Mainīgie
+variables.management=Mainīgo pārvaldība
+variables.creation=Pievienot mainīgo
+variables.none=Vēl nav neviena mainīgā.
+variables.deletion=Noņemt mainīgo
+variables.deletion.description=Mainīgā noņemšana ir neatgriezeniska un nav atsaucama. Vai turpināt?
+variables.description=Mainīgie tiks padoti noteiktām darbībām, un citādāk tos nevar nolasīt.
+variables.id_not_exist=Mainīgais ar identifikatoru %d nepastāv.
+variables.edit=Labot mainīgo
+variables.deletion.failed=Neizdevās noņemt mainīgo.
+variables.deletion.success=Mainīgais tika noņemts.
+variables.creation.failed=Neizdevās pievienot mainīgo.
+variables.creation.success=Mainīgais "%s" tika pievienots.
+variables.update.failed=Neizdevās labot mainīgo.
+variables.update.success=Mainīgais tika labots.
[projects]
type-1.display_name=Individuālais projekts
@@ -3341,6 +3580,11 @@ type-2.display_name=Repozitorija projekts
type-3.display_name=Organizācijas projekts
[git.filemode]
+changed_filemode=%[1]s → %[2]s
; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", …
+directory=Direktorija
+normal_file=Parasts fails
+executable_file=Izpildāmais fails
symbolic_link=Simboliska saite
+submodule=Apakšmodulis
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 43265c9c31..fc1da2b992 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -489,6 +489,7 @@ auth_failed=Verificatie mislukt: %v
target_branch_not_exist=Doel branch bestaat niet
+
[user]
change_avatar=Wijzig je profielfoto…
repositories=repositories
@@ -1618,6 +1619,8 @@ activity.git_stats_and_deletions=en
activity.git_stats_deletion_1=%d verwijdering
activity.git_stats_deletion_n=%d verwijderingen
+contributors.contribution_type.commits=Commits
+
search=Zoek
search.search_repo=Zoek repository
search.fuzzy=Vergelijkbaar
@@ -2031,6 +2034,8 @@ topic.count_prompt=Je kunt niet meer dan 25 onderwerpen selecteren
+[graphs]
+
[org]
org_name_holder=Organisatienaam
org_full_name_holder=Volledige naam organisatie
@@ -2537,6 +2542,7 @@ notices.desc=Beschrijving
notices.op=Op.
notices.delete_success=De systeemmeldingen zijn verwijderd.
+
[action]
create_repo=repository aangemaakt in %s
rename_repo=hernoemde repository van %[1]s
naar %[3]s
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index d713110a72..2af3ce1a11 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -474,6 +474,7 @@ auth_failed=Uwierzytelnienie się nie powiodło: %v
target_branch_not_exist=Gałąź docelowa nie istnieje.
+
[user]
change_avatar=Zmień swój awatar…
repositories=Repozytoria
@@ -1467,6 +1468,8 @@ activity.git_stats_and_deletions=i
activity.git_stats_deletion_1=%d usunięcie
activity.git_stats_deletion_n=%d usunięć
+contributors.contribution_type.commits=Commity
+
search=Szukaj
search.search_repo=Przeszukaj repozytorium
search.fuzzy=Fuzzy
@@ -1899,6 +1902,8 @@ error.csv.too_large=Nie można wyświetlić tego pliku, ponieważ jest on zbyt d
error.csv.unexpected=Nie można renderować tego pliku, ponieważ zawiera nieoczekiwany znak w wierszu %d i kolumnie %d.
error.csv.invalid_field_count=Nie można renderować tego pliku, ponieważ ma nieprawidłową liczbę pól w wierszu %d.
+[graphs]
+
[org]
org_name_holder=Nazwa organizacji
org_full_name_holder=Pełna nazwa organizacji
@@ -2425,6 +2430,7 @@ notices.desc=Opis
notices.op=Operacja
notices.delete_success=Powiadomienia systemu zostały usunięte.
+
[action]
create_repo=tworzy repozytorium %s
rename_repo=zmienia nazwę repozytorium %[1]s
na %[3]s
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index cf5fd0055c..11743f29a5 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -582,6 +582,7 @@ org_still_own_packages=Esta organização ainda possui pacotes, exclua-os primei
target_branch_not_exist=O branch de destino não existe.
+
[user]
change_avatar=Altere seu avatar...
joined_on=Inscreveu-se em %s
@@ -1927,6 +1928,8 @@ activity.git_stats_and_deletions=e
activity.git_stats_deletion_1=%d exclusão
activity.git_stats_deletion_n=%d exclusões
+contributors.contribution_type.commits=Commits
+
search=Pesquisar
search.search_repo=Pesquisar no repositório...
search.type.tooltip=Tipo de pesquisa
@@ -2484,6 +2487,8 @@ error.csv.too_large=Não é possível renderizar este arquivo porque ele é muit
error.csv.unexpected=Não é possível renderizar este arquivo porque ele contém um caractere inesperado na linha %d e coluna %d.
error.csv.invalid_field_count=Não é possível renderizar este arquivo porque ele tem um número errado de campos na linha %d.
+[graphs]
+
[org]
org_name_holder=Nome da organização
org_full_name_holder=Nome completo da organização
@@ -3110,6 +3115,7 @@ notices.desc=Descrição
notices.op=Op.
notices.delete_success=Os avisos do sistema foram excluídos.
+
[action]
create_repo=criou o repositório %s
rename_repo=renomeou o repositório %[1]s
para %[3]s
@@ -3293,6 +3299,8 @@ rpm.registry=Configure este registro pela linha de comando:
rpm.distros.redhat=em distribuições baseadas no RedHat
rpm.distros.suse=em distribuições baseadas no SUSE
rpm.install=Para instalar o pacote, execute o seguinte comando:
+rpm.repository=Informações do repositório
+rpm.repository.architectures=Arquiteturas
rubygems.install=Para instalar o pacote usando gem, execute o seguinte comando:
rubygems.install2=ou adicione-o ao Gemfile:
rubygems.dependencies.runtime=Dependências de Execução
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 863a1545c3..99165ed332 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -123,6 +123,7 @@ pin=Fixar
unpin=Desafixar
artifacts=Artefactos
+confirm_delete_artifact=Tem a certeza que quer eliminar este artefacto "%s"?
archived=Arquivado
@@ -423,6 +424,7 @@ authorization_failed_desc=A autorização falhou porque encontrámos um pedido i
sspi_auth_failed=Falhou a autenticação SSPI
password_pwned=A senha utilizada está numa lista de senhas roubadas anteriormente expostas em fugas de dados públicas. Tente novamente com uma senha diferente e considere também mudar esta senha nos outros sítios.
password_pwned_err=Não foi possível completar o pedido ao HaveIBeenPwned
+last_admin=Não pode remover o último administrador. Tem que existir pelo menos um administrador.
[mail]
view_it_on=Ver em %s
@@ -588,6 +590,8 @@ org_still_own_packages=Esta organização ainda possui um ou mais pacotes, elimi
target_branch_not_exist=O ramo de destino não existe.
+admin_cannot_delete_self=Não se pode auto-remover quando tem privilégios de administração. Remova esses privilégios primeiro.
+
[user]
change_avatar=Mude o seu avatar…
joined_on=Inscreveu-se em %s
@@ -967,6 +971,8 @@ issue_labels_helper=Escolha um conjunto de rótulos para as questões.
license=Licença
license_helper=Escolha um ficheiro de licença.
license_helper_desc=Uma licença rege o que os outros podem, ou não, fazer com o seu código fonte. Não tem a certeza sobre qual a mais indicada para o seu trabalho? Veja: Escolher uma licença.
+object_format=Formato dos elementos
+object_format_helper=Formato dos elementos do repositório. Não poderá ser alterado mais tarde. SHA1 é o mais compatível.
readme=README
readme_helper=Escolha um modelo de ficheiro README.
readme_helper_desc=Este é o sítio onde pode escrever uma descrição completa do seu trabalho.
@@ -984,6 +990,7 @@ mirror_prune=Podar
mirror_prune_desc=Remover referências obsoletas de seguimento remoto
mirror_interval=Intervalo entre sincronizações (as unidades de tempo válidas são 'h', 'm' e 's'). O valor zero desabilita a sincronização periódica. (Intervalo mínimo: %s)
mirror_interval_invalid=O intervalo entre sincronizações não é válido.
+mirror_sync=sincronizado
mirror_sync_on_commit=Sincronizar quando forem enviados cometimentos
mirror_address=Clonar a partir do URL
mirror_address_desc=Coloque, na secção de autorização, as credenciais que, eventualmente, sejam necessárias.
@@ -1034,6 +1041,7 @@ desc.public=Público
desc.template=Modelo
desc.internal=Interno
desc.archived=Arquivado
+desc.sha256=SHA256
template.items=Itens do modelo
template.git_content=Conteúdo Git (ramo principal)
@@ -1184,6 +1192,8 @@ audio_not_supported_in_browser=O seu navegador não suporta a etiqueta 'audio' d
stored_lfs=Armazenado com Git LFS
symbolic_link=Ligação simbólica
executable_file=Ficheiro executável
+vendored=Externo
+generated=Gerado
commit_graph=Gráfico de cometimentos
commit_graph.select=Escolher ramos
commit_graph.hide_pr_refs=Ocultar pedidos de integração
@@ -1707,6 +1717,7 @@ pulls.select_commit_hold_shift_for_range=Escolha o comentimento. Mantenha premid
pulls.review_only_possible_for_full_diff=A revisão só é possível ao visualizar o diff completo
pulls.filter_changes_by_commit=Filtrar por cometimento
pulls.nothing_to_compare=Estes ramos são iguais. Não há necessidade de criar um pedido de integração.
+pulls.nothing_to_compare_have_tag=O ramo/etiqueta escolhidos são iguais.
pulls.nothing_to_compare_and_allow_empty_pr=Estes ramos são iguais. Este pedido de integração ficará vazio.
pulls.has_pull_request=`Já existe um pedido de integração entre estes ramos: %[2]s#%[3]d `
pulls.create=Criar um pedido de integração
@@ -1765,6 +1776,7 @@ pulls.merge_pull_request=Criar um cometimento de integração
pulls.rebase_merge_pull_request=Mudar a base e avançar rapidamente
pulls.rebase_merge_commit_pull_request=Mudar a base e criar um cometimento de integração
pulls.squash_merge_pull_request=Criar cometimento de compactação
+pulls.fast_forward_only_merge_pull_request=Avançar rapidamente apenas
pulls.merge_manually=Integrado manualmente
pulls.merge_commit_id=O ID de cometimento da integração
pulls.require_signed_wont_sign=O ramo requer que os cometimentos sejam assinados mas esta integração não vai ser assinada
@@ -1901,6 +1913,8 @@ wiki.page_name_desc=Insira um nome para esta página Wiki. Alguns dos nomes espe
wiki.original_git_entry_tooltip=Ver o ficheiro Git original, ao invés de usar uma ligação amigável.
activity=Trabalho
+activity.navbar.pulse=Pulso
+activity.navbar.contributors=Contribuidores
activity.period.filter_label=Período:
activity.period.daily=1 dia
activity.period.halfweekly=3 dias
@@ -1966,6 +1980,11 @@ activity.git_stats_and_deletions=e
activity.git_stats_deletion_1=%d eliminação
activity.git_stats_deletion_n=%d eliminações
+contributors.contribution_type.filter_label=Tipo de contribuição:
+contributors.contribution_type.commits=Cometimentos
+contributors.contribution_type.additions=Adições
+contributors.contribution_type.deletions=Eliminações
+
search=Procurar
search.search_repo=Procurar repositório
search.type.tooltip=Tipo de pesquisa
@@ -2003,6 +2022,7 @@ settings.mirror_settings.docs.doc_link_title=Como é que eu replico repositório
settings.mirror_settings.docs.doc_link_pull_section=a parte "Puxar de um repositório remoto" da documentação.
settings.mirror_settings.docs.pulling_remote_title=Puxando a partir de um repositório remoto
settings.mirror_settings.mirrored_repository=Repositório replicado
+settings.mirror_settings.pushed_repository=Repositório enviado
settings.mirror_settings.direction=Sentido
settings.mirror_settings.direction.pull=Puxada
settings.mirror_settings.direction.push=Envio
@@ -2312,6 +2332,8 @@ settings.protect_approvals_whitelist_users=Revisores com permissão:
settings.protect_approvals_whitelist_teams=Equipas com permissão para rever:
settings.dismiss_stale_approvals=Descartar aprovações obsoletas
settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o conteúdo do pedido de integração forem enviados para o ramo, as aprovações antigas serão descartadas.
+settings.ignore_stale_approvals=Ignorar aprovações obsoletas
+settings.ignore_stale_approvals_desc=Não contar as aprovações feitas em cometimentos mais antigos (revisões obsoletas) para o número de aprovações do pedido de integração. É irrelevante se as revisões obsoletas já forem descartadas.
settings.require_signed_commits=Exigir cometimentos assinados
settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis.
settings.protect_branch_name_pattern=Padrão do nome do ramo protegido
@@ -2367,6 +2389,7 @@ settings.archive.error=Ocorreu um erro enquanto decorria o processo de arquivo d
settings.archive.error_ismirror=Não pode arquivar um repositório que tenha sido replicado.
settings.archive.branchsettings_unavailable=As configurações dos ramos não estão disponíveis quando o repositório está arquivado.
settings.archive.tagsettings_unavailable=As configurações sobre etiquetas não estão disponíveis quando o repositório está arquivado.
+settings.archive.mirrors_unavailable=As réplicas não estão disponíveis se o repositório estiver arquivado.
settings.unarchive.button=Desarquivar repositório
settings.unarchive.header=Desarquivar este repositório
settings.unarchive.text=Desarquivar o repositório irá restaurar a capacidade de receber cometimentos e envios, assim como novas questões e pedidos de integração.
@@ -2565,6 +2588,13 @@ error.csv.too_large=Não é possível apresentar este ficheiro por ser demasiado
error.csv.unexpected=Não é possível apresentar este ficheiro porque contém um caractere inesperado na linha %d e coluna %d.
error.csv.invalid_field_count=Não é possível apresentar este ficheiro porque tem um número errado de campos na linha %d.
+[graphs]
+component_loading=A carregar %s...
+component_loading_failed=Não foi possível carregar %s
+component_loading_info=Isto pode demorar um pouco…
+component_failed_to_load=Ocorreu um erro inesperado.
+contributors.what=contribuições
+
[org]
org_name_holder=Nome da organização
org_full_name_holder=Nome completo da organização
@@ -2691,6 +2721,7 @@ teams.invite.description=Clique no botão abaixo para se juntar à equipa.
[admin]
dashboard=Painel de controlo
+self_check=Auto-verificação
identity_access=Identidade e acesso
users=Contas de utilizador
organizations=Organizações
@@ -2736,6 +2767,7 @@ dashboard.delete_missing_repos=Eliminar todos os repositórios que não tenham o
dashboard.delete_missing_repos.started=Foi iniciada a tarefa de eliminação de todos os repositórios que não têm ficheiros git.
dashboard.delete_generated_repository_avatars=Eliminar avatares gerados do repositório
dashboard.sync_repo_branches=Sincronizar ramos perdidos de dados do git para bases de dados
+dashboard.sync_repo_tags=Sincronizar etiquetas dos dados do git para a base de dados
dashboard.update_mirrors=Sincronizar réplicas
dashboard.repo_health_check=Verificar a saúde de todos os repositórios
dashboard.check_repo_stats=Verificar as estatísticas de todos os repositórios
@@ -2790,6 +2822,7 @@ dashboard.stop_endless_tasks=Parar tarefas intermináveis
dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados
dashboard.start_schedule_tasks=Iniciar tarefas de agendamento
dashboard.sync_branch.started=Sincronização de ramos iniciada
+dashboard.sync_tag.started=Sincronização de etiquetas iniciada
dashboard.rebuild_issue_indexer=Reconstruir indexador de questões
users.user_manage_panel=Gestão das contas de utilizadores
@@ -3216,6 +3249,13 @@ notices.desc=Descrição
notices.op=Op.
notices.delete_success=As notificações do sistema foram eliminadas.
+self_check.no_problem_found=Nenhum problema encontrado até agora.
+self_check.database_collation_mismatch=Supor que a base de dados usa a colação: %s
+self_check.database_collation_case_insensitive=A base de dados está a usar a colação %s, que é insensível à diferença entre maiúsculas e minúsculas. Embora o Gitea possa trabalhar com ela, pode haver alguns casos raros que não funcionem como esperado.
+self_check.database_inconsistent_collation_columns=A base de dados está a usar a colação %s, mas estas colunas estão a usar colações diferentes. Isso poderá causar alguns problemas inesperados.
+self_check.database_fix_mysql=Para utilizadores do MySQL/MariaDB, pode usar o comando "gitea doctor convert" para resolver os problemas de colação. Também pode resolver o problema com comandos SQL "ALTER ... COLLATE ..." aplicados manualmente.
+self_check.database_fix_mssql=Para utilizadores do MSSQL só pode resolver o problema aplicando comandos SQL "ALTER ... COLLATE ..." manualmente, por enquanto.
+
[action]
create_repo=criou o repositório %s
rename_repo=renomeou o repositório de %[1]s
para %[3]s
@@ -3400,6 +3440,9 @@ rpm.registry=Configurar este registo usando a linha de comandos:
rpm.distros.redhat=em distribuições baseadas no RedHat
rpm.distros.suse=em distribuições baseadas no SUSE
rpm.install=Para instalar o pacote, execute o seguinte comando:
+rpm.repository=Informação do repositório
+rpm.repository.architectures=Arquitecturas
+rpm.repository.multiple_groups=Este pacote está disponível em vários grupos.
rubygems.install=Para instalar o pacote usando o gem, execute o seguinte comando:
rubygems.install2=ou adicione-o ao ficheiro Gemfile
:
rubygems.dependencies.runtime=Dependências do tempo de execução (runtime)
@@ -3532,8 +3575,8 @@ runs.actors_no_select=Todos os intervenientes
runs.status_no_select=Todos os estados
runs.no_results=Nenhum resultado obtido.
runs.no_workflows=Ainda não há sequências de trabalho.
-runs.no_workflows.quick_start=Não sabe como começar com o Gitea Action? Veja o guia de iniciação rápida .
-runs.no_workflows.documentation=Para mais informação sobre o Gitea Action, veja a documentação .
+runs.no_workflows.quick_start=Não sabe como começar com o Gitea Actions? Veja o guia de inicio rápido .
+runs.no_workflows.documentation=Para mais informação sobre o Gitea Actions veja a documentação .
runs.no_runs=A sequência de trabalho ainda não foi executada.
runs.empty_commit_message=(mensagem de cometimento vazia)
@@ -3552,7 +3595,7 @@ variables.none=Ainda não há variáveis.
variables.deletion=Remover variável
variables.deletion.description=Remover uma variável é permanente e não pode ser revertido. Quer continuar?
variables.description=As variáveis serão transmitidas a certas operações e não poderão ser lidas de outra forma.
-variables.id_not_exist=A variável com o id %d não existe.
+variables.id_not_exist=A variável com o ID %d não existe.
variables.edit=Editar variável
variables.deletion.failed=Falha ao remover a variável.
variables.deletion.success=A variável foi removida.
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index 0a466854d0..36b9d0e39e 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -586,6 +586,7 @@ org_still_own_packages=Эта организация всё ещё владее
target_branch_not_exist=Целевая ветка не существует.
+
[user]
change_avatar=Изменить свой аватар…
joined_on=Присоединил(ся/ась) %s
@@ -1926,6 +1927,8 @@ activity.git_stats_and_deletions=и
activity.git_stats_deletion_1=%d удаление
activity.git_stats_deletion_n=%d удалений
+contributors.contribution_type.commits=коммитов
+
search=Поиск
search.search_repo=Поиск по репозиторию
search.type.tooltip=Тип поиска
@@ -2515,6 +2518,8 @@ error.csv.too_large=Не удается отобразить этот файл,
error.csv.unexpected=Не удается отобразить этот файл, потому что он содержит неожиданный символ в строке %d и столбце %d.
error.csv.invalid_field_count=Не удается отобразить этот файл, потому что он имеет неправильное количество полей в строке %d.
+[graphs]
+
[org]
org_name_holder=Название организации
org_full_name_holder=Полное название организации
@@ -3153,6 +3158,7 @@ notices.desc=Описание
notices.op=Oп.
notices.delete_success=Уведомления системы были удалены.
+
[action]
create_repo=создал(а) репозиторий %s
rename_repo=переименовал(а) репозиторий из %[1]s
на %[3]s
@@ -3337,6 +3343,8 @@ rpm.registry=Настроить реестр из командной строк
rpm.distros.redhat=на дистрибутивах семейства RedHat
rpm.distros.suse=на дистрибутивах семейства SUSE
rpm.install=Чтобы установить пакет, выполните следующую команду:
+rpm.repository=О репозитории
+rpm.repository.architectures=Архитектуры
rubygems.install=Чтобы установить пакет с помощью gem, выполните следующую команду:
rubygems.install2=или добавьте его в Gemfile:
rubygems.dependencies.runtime=Зависимости времени выполнения
@@ -3464,8 +3472,6 @@ runs.status=Статус
runs.actors_no_select=Все акторы
runs.no_results=Ничего не найдено.
runs.no_workflows=Пока нет рабочих процессов.
-runs.no_workflows.quick_start=Не знаете, как начать использовать Действия Gitea? Читайте руководство по быстрому старту .
-runs.no_workflows.documentation=Чтобы узнать больше о Действиях Gitea, читайте документацию .
runs.no_runs=Рабочий поток ещё не запускался.
runs.empty_commit_message=(пустое сообщение коммита)
@@ -3484,7 +3490,6 @@ variables.none=Переменных пока нет.
variables.deletion=Удалить переменную
variables.deletion.description=Удаление переменной необратимо, его нельзя отменить. Продолжить?
variables.description=Переменные будут передаваться определенным действиям и не могут быть прочитаны иначе.
-variables.id_not_exist=Переменная с идентификатором %d не существует.
variables.edit=Изменить переменную
variables.deletion.failed=Не удалось удалить переменную.
variables.deletion.success=Переменная удалена.
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index 6d70bc385a..fb97daf5e0 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -450,6 +450,7 @@ auth_failed=සත්යාපන අසමත් විය: %v
target_branch_not_exist=ඉලක්කගත ශාඛාව නොපවතී.
+
[user]
change_avatar=ඔබගේ අවතාරය වෙනස් කරන්න…
repositories=කෝෂ්ඨ
@@ -1459,6 +1460,8 @@ activity.git_stats_and_deletions=සහ
activity.git_stats_deletion_1=%d මකාදැමීම
activity.git_stats_deletion_n=%d මකාදැමීම්
+contributors.contribution_type.commits=විවරයන්
+
search=සොයන්න
search.search_repo=කෝෂ්ඨය සොයන්න
search.fuzzy=සිනිඳු
@@ -1910,6 +1913,8 @@ error.csv.too_large=එය ඉතා විශාල නිසා මෙම ග
error.csv.unexpected=%d පේළියේ සහ %dතීරුවේ අනපේක්ෂිත චරිතයක් අඩංගු බැවින් මෙම ගොනුව විදැහුම්කරණය කළ නොහැක.
error.csv.invalid_field_count=මෙම ගොනුව රේඛාවේ වැරදි ක්ෂේත්ර සංඛ්යාවක් ඇති බැවින් එය විදැහුම්කරණය කළ නොහැක %d.
+[graphs]
+
[org]
org_name_holder=සංවිධානයේ නම
org_full_name_holder=සංවිධානයේ සම්පූර්ණ නම
@@ -2456,6 +2461,7 @@ notices.desc=සවිස්තරය
notices.op=ඔප්.
notices.delete_success=පද්ධති දැන්වීම් මකා දමා ඇත.
+
[action]
create_repo=නිර්මිත ගබඩාව %s
rename_repo=%[1]s
සිට %[3]s දක්වා නම් කරන ලද ගබඩාව
diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini
index 1c3ca5ae43..4a223ee90d 100644
--- a/options/locale/locale_sk-SK.ini
+++ b/options/locale/locale_sk-SK.ini
@@ -563,6 +563,7 @@ auth_failed=Overenie zlyhalo: %v
target_branch_not_exist=Cieľová vetva neexistuje.
+
[user]
change_avatar=Zmeniť svoj avatar…
joined_on=Pripojil/a sa %s
@@ -1144,6 +1145,8 @@ activity.unresolved_conv_label=Otvoriť
activity.git_stats_commit_1=%d commit
activity.git_stats_commit_n=%d commity
+contributors.contribution_type.commits=Commitov
+
search=Hľadať
search.type.tooltip=Typ vyhľadávania
search.fuzzy=Fuzzy
@@ -1246,6 +1249,8 @@ release.cancel=Zrušiť
+[graphs]
+
[org]
code=Kód
lower_repositories=repozitáre
@@ -1328,6 +1333,7 @@ monitor.process.cancel=Zrušiť proces
+
[action]
compare_commits=Porovnať %d commitov
compare_commits_general=Porovnať commity
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index 411a83ed75..0a484c9b79 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -390,6 +390,7 @@ auth_failed=Autentisering misslyckades: %v
target_branch_not_exist=Målgrenen finns inte.
+
[user]
change_avatar=Byt din avatar…
repositories=Utvecklingskataloger
@@ -1227,6 +1228,8 @@ activity.git_stats_and_deletions=och
activity.git_stats_deletion_1=%d borttagen
activity.git_stats_deletion_n=%d borttagningar
+contributors.contribution_type.commits=Incheckningar
+
search=Sök
search.search_repo=Sök utvecklingskatalog
search.results=Sökresultat för ”%s” i %s
@@ -1535,6 +1538,8 @@ topic.count_prompt=Du kan inte välja fler än 25 ämnen
+[graphs]
+
[org]
org_name_holder=Organisationsnamn
org_full_name_holder=Organisationens Fullständiga Namn
@@ -1971,6 +1976,7 @@ notices.desc=Beskrivning
notices.op=Op.
notices.delete_success=Systemnotifikationer har blivit raderade.
+
[action]
create_repo=skapade utvecklingskatalog %s
rename_repo=döpte om utvecklingskalatogen från %[1]s
till %[3]s
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index dd7d1b066e..3c8cb08726 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -17,6 +17,7 @@ template=Şablon
language=Dil
notifications=Bildirimler
active_stopwatch=Etkin Zaman Takibi
+tracked_time_summary=Konu listesi süzgeçlerine dayanan takip edilen zamanın özeti
create_new=Oluştur…
user_profile_and_more=Profil ve Ayarlar…
signed_in_as=Giriş yapan:
@@ -90,6 +91,7 @@ remove=Kaldır
remove_all=Tümünü Kaldır
remove_label_str=`"%s" öğesini kaldır`
edit=Düzenle
+view=Görüntüle
enabled=Aktifleştirilmiş
disabled=Devre Dışı
@@ -97,6 +99,7 @@ locked=Kilitli
copy=Kopyala
copy_url=URL'yi kopyala
+copy_hash=Hash'i kopyala
copy_content=İçeriği kopyala
copy_branch=Dal adını kopyala
copy_success=Kopyalandı!
@@ -109,6 +112,7 @@ loading=Yükleniyor…
error=Hata
error404=Ulaşmaya çalıştığınız sayfa mevcut değil veya görüntüleme yetkiniz yok .
+go_back=Geri Git
never=Asla
unknown=Bilinmiyor
@@ -180,6 +184,7 @@ network_error=Ağ hatası
[startpage]
app_desc=Zahmetsiz, kendi sunucunuzda barındırabileceğiniz Git servisi
install=Kurulumu kolay
+install_desc=Platformunuz için ikili dosyayı çalıştırın , Docker ile yükleyin veya paket olarak edinin.
platform=Farklı platformlarda çalışablir
platform_desc=Gitea Go ile derleme yapılabilecek her yerde çalışmaktadır: Windows, macOS, Linux, ARM, vb. Hangisini seviyorsanız onu seçin!
lightweight=Hafif
@@ -356,6 +361,7 @@ disable_register_prompt=Kayıt işlemi devre dışıdır. Lütfen site yönetici
disable_register_mail=Kayıt için e-posta doğrulama devre dışıdır.
manual_activation_only=Etkinleştirmeyi tamamlamak için site yöneticinizle bağlantıya geçin.
remember_me=Bu Aygıtı hatırla
+remember_me.compromised=Oturum açma tokeni artık geçerli değil, bu ele geçirilmiş bir hesaba işaret ediyor olabilir. Lütfen hesabınızda olağandışı faaliyet olup olmadığını denetleyin.
forgot_password_title=Şifremi unuttum
forgot_password=Şifrenizi mi unuttunuz?
sign_up_now=Bir hesaba mı ihtiyacınız var? Hemen kaydolun.
@@ -375,6 +381,7 @@ email_not_associate=Bu e-posta adresi hiçbir hesap ile ilişkilendirilmemiştir
send_reset_mail=Hesap Kurtarma E-postası Gönder
reset_password=Hesap Kurtarma
invalid_code=Doğrulama kodunuz geçersiz veya süresi dolmuş.
+invalid_code_forgot_password=Onay kodunuz hatalı veya süresi geçmiş. Yeni bir oturum başlatmak için buraya tıklayın.
invalid_password=Parolanız hesap oluşturulurken kullanılan parolayla eşleşmiyor.
reset_password_helper=Hesabı Kurtar
reset_password_wrong_user=%s olarak oturum açmışsınız, ancak hesap kurtarma bağlantısı %s için
@@ -581,6 +588,7 @@ org_still_own_packages=Bu organizasyon hala bir veya daha fazla pakete sahip, ö
target_branch_not_exist=Hedef dal mevcut değil.
+
[user]
change_avatar=Profil resmini değiştir…
joined_on=%s tarihinde katıldı
@@ -676,6 +684,7 @@ choose_new_avatar=Yeni Avatar Seç
update_avatar=Profil Resmini Güncelle
delete_current_avatar=Güncel Avatarı Sil
uploaded_avatar_not_a_image=Yüklenen dosya bir resim dosyası değil.
+uploaded_avatar_is_too_big=Yüklenen dosyanın boyutu (%d KiB), azami boyutu (%d KiB) aşıyor.
update_avatar_success=Profil resminiz değiştirildi.
update_user_avatar_success=Kullanıcının avatarı güncellendi.
@@ -857,6 +866,7 @@ revoke_oauth2_grant_description=Bu üçüncü taraf uygulamasına erişimin ipta
revoke_oauth2_grant_success=Erişim başarıyla kaldırıldı.
twofa_desc=İki faktörlü kimlik doğrulama, hesabınızın güvenliğini artırır.
+twofa_recovery_tip=Aygıtınızı kaybetmeniz durumunda, hesabınıza tekrar erişmek için tek kullanımlık kurtarma anahtarını kullanabileceksiniz.
twofa_is_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde kaydedilmiş .
twofa_not_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde kaydedilmemiş.
twofa_disable=İki Aşamalı Doğrulamayı Devre Dışı Bırak
@@ -879,6 +889,8 @@ webauthn_register_key=Güvenlik Anahtarı Ekle
webauthn_nickname=Takma Ad
webauthn_delete_key=Güvenlik Anahtarını Kaldır
webauthn_delete_key_desc=Bir güvenlik anahtarını kaldırırsanız, onunla artık giriş yapamazsınız. Devam edilsin mi?
+webauthn_key_loss_warning=Güvenlik anahtarlarınızı kaybederseniz, hesabınıza erişimi kaybedersiniz.
+webauthn_alternative_tip=Ek bir kimlik doğrulama yöntemi ayarlamak isteyebilirsiniz.
manage_account_links=Bağlı Hesapları Yönet
manage_account_links_desc=Bu harici hesaplar Gitea hesabınızla bağlantılı.
@@ -915,6 +927,7 @@ visibility.private=Özel
visibility.private_tooltip=Sadece katıldığınız organizasyonların üyeleri tarafından görünür
[repo]
+new_repo_helper=Bir depo, sürüm geçmişi dahil tüm proje dosyalarını içerir. Zaten başka bir yerde mi barındırıyorsunuz? Depoyu taşıyın.
owner=Sahibi
owner_helper=Bazı organizasyonlar, en çok depo sayısı sınırı nedeniyle açılır menüde görünmeyebilir.
repo_name=Depo İsmi
@@ -935,6 +948,8 @@ fork_from=Buradan Çatalla
already_forked=%s deposunu zaten çatalladınız
fork_to_different_account=Başka bir hesaba çatalla
fork_visibility_helper=Çatallanmış bir deponun görünürlüğü değiştirilemez.
+fork_branch=Çatala klonlanacak dal
+all_branches=Tüm dallar
fork_no_valid_owners=Geçerli bir sahibi olmadığı için bu depo çatallanamaz.
use_template=Bu şablonu kullan
clone_in_vsc=VS Code'ta klonla
@@ -964,6 +979,7 @@ trust_model_helper_collaborator_committer=Ortak çalışan+İşleyen: İşleyenl
trust_model_helper_default=Varsayılan: Bu kurulum için varsayılan güven modelini kullan
create_repo=Depo Oluştur
default_branch=Varsayılan Dal
+default_branch_label=varsayılan
default_branch_helper=Varsayılan dal, değişiklik istekleri ve kod işlemeleri için temel daldır.
mirror_prune=Buda
mirror_prune_desc=Kullanılmayan uzak depoları izleyen referansları kaldır
@@ -999,8 +1015,13 @@ delete_preexisting=Önceden var olan dosyaları sil
delete_preexisting_content=%s içindeki dosyaları sil
delete_preexisting_success=%s içindeki kabul edilmeyen dosyalar silindi
blame_prior=Bu değişiklikten önceki suçu görüntüle
+blame.ignore_revs=.git-blame-ignore-revs dosyasındaki sürümler yok sayılıyor. Bunun yerine normal sorumlu görüntüsü için buraya tıklayın .
+blame.ignore_revs.failed=.git-blame-ignore-revs dosyasındaki sürümler yok sayılamadı.
author_search_tooltip=En fazla 30 kullanıcı görüntüler
+tree_path_not_found_commit=%[1] yolu, %[2]s işlemesinde mevcut değil
+tree_path_not_found_branch=%[1] yolu, %[2]s dalında mevcut değil
+tree_path_not_found_tag=%[1] yolu, %[2]s etiketinde mevcut değil
transfer.accept=Aktarımı Kabul Et
transfer.accept_desc=`"%s" tarafına aktar`
@@ -1264,6 +1285,7 @@ commits.signed_by_untrusted_user=Güvenilmeyen kullanıcı tarafından imzaland
commits.signed_by_untrusted_user_unmatched=İşleyici ile eşleşmeyen güvenilmeyen kullanıcı tarafından imzalanmış
commits.gpg_key_id=GPG Anahtar Kimliği
commits.ssh_key_fingerprint=SSH Anahtar Parmak İzi
+commits.view_path=Geçmişte bu noktayı görüntüle
commit.operations=İşlemler
commit.revert=Geri Al
@@ -1474,8 +1496,17 @@ issues.ref_closed_from=`bu konuyu kapat%[4]s konuyu yeniden aç%[4]s %[2]s `
issues.ref_from=`%[1]s'den`
issues.author=Yazar
+issues.author_helper=Bu kullanıcı yazardır.
issues.role.owner=Sahibi
+issues.role.owner_helper=Bu kullanıcı bu deponun sahibidir.
issues.role.member=Üye
+issues.role.member_helper=Bu kullanıcı bu deponun sahibi olan organizasyonun üyesidir.
+issues.role.collaborator=Katkıcı
+issues.role.collaborator_helper=Kullanıcı bu depoya işbirliği için davet edildi.
+issues.role.first_time_contributor=İlk defa katkıcı
+issues.role.first_time_contributor_helper=Bu, bu kullanıcının bu depoya ilk katkısı.
+issues.role.contributor=Katılımcı
+issues.role.contributor_helper=Bu kullanıcı bu depoya daha önce işleme gönderdi.
issues.re_request_review=İncelemeyi yeniden iste
issues.is_stale=Bu incelemeden bu yana bu istekte değişiklikler oldu
issues.remove_request_review=İnceleme isteğini kaldır
@@ -1491,6 +1522,8 @@ issues.label_description=Etiket açıklaması
issues.label_color=Etiket rengi
issues.label_exclusive=Özel
issues.label_archive=Etiketi Arşivle
+issues.label_archived_filter=Arşivlenmiş etiketleri göster
+issues.label_archive_tooltip=Arşivlenmiş etiketler, etiket araması yapılırken varsayılan olarak önerilerin dışında tutuluyor.
issues.label_exclusive_desc=Kapsam/öğe
etiketini, diğer kapsam/
etiketleriyle ayrışık olacak şekilde adlandırın.
issues.label_exclusive_warning=Çakışan kapsamlı etiketler, bir konu veya değişiklik isteği etiketleri düzenlenirken kaldırılacaktır.
issues.label_count=%d etiket
@@ -1745,6 +1778,7 @@ pulls.rebase_conflict_summary=Hata Mesajı
pulls.unrelated_histories=Birleştirme Başarısız: Birleştirme başlığı ve tabanı ortak bir geçmişi paylaşmıyor. İpucu: Farklı bir strateji deneyin
pulls.merge_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, taban güncellendi. İpucu: Tekrar deneyin.
pulls.head_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, ana güncellendi. İpucu: Tekrar deneyin.
+pulls.has_merged=Başarısız: Değişiklik isteği birleştirildi, yeniden birleştiremez veya hedef dalı değiştiremezsiniz.
pulls.push_rejected=Birleştirme Başarısız Oldu: Gönderme reddedildi. Bu depo için Git İstemcilerini inceleyin.
pulls.push_rejected_summary=Tam Red Mesajı
pulls.push_rejected_no_message=Birleştirme başarısız oldu: Gönderme reddedildi, ancak uzak bir mesaj yoktu. Bu depo için Git İstemcilerini inceleyin
@@ -1756,6 +1790,8 @@ pulls.status_checks_failure=Bazı kontroller başarısız oldu
pulls.status_checks_error=Bazı kontroller hatalar bildirdi
pulls.status_checks_requested=Gerekli
pulls.status_checks_details=Ayrıntılar
+pulls.status_checks_hide_all=Tüm denetlemeleri gizle
+pulls.status_checks_show_all=Tüm denetlemeleri göster
pulls.update_branch=Dalı birleştirmeyle güncelle
pulls.update_branch_rebase=Dalı yeniden yapılandırmayla güncelle
pulls.update_branch_success=Dal güncellemesi başarıyla gerçekleştirildi
@@ -1764,6 +1800,11 @@ pulls.outdated_with_base_branch=Bu dal, temel dal ile güncel değil
pulls.close=Değişiklik İsteğini Kapat
pulls.closed_at=`%[2]s değişiklik isteğini kapattı`
pulls.reopened_at=`%[2]s değişiklik isteğini yeniden açtı`
+pulls.cmd_instruction_hint=`Komut satırı talimatlarını görüntüleyin.`
+pulls.cmd_instruction_checkout_title=Çekme
+pulls.cmd_instruction_checkout_desc=Proje deponuzdan yeni bir dalı çekin ve değişiklikleri test edin.
+pulls.cmd_instruction_merge_title=Birleştir
+pulls.cmd_instruction_merge_desc=Değişiklikleri birleştirin ve Gitea'da güncelleyin.
pulls.clear_merge_message=Birleştirme iletilerini temizle
pulls.clear_merge_message_hint=Birleştirme iletisini temizlemek sadece işleme ileti içeriğini kaldırır ama üretilmiş "Co-Authored-By …" gibi git fragmanlarını korur.
@@ -1809,6 +1850,8 @@ milestones.edit_success=`"%s" dönüm noktası güncellendi.`
milestones.deletion=Kilometre Taşını Sil
milestones.deletion_desc=Bir kilometre taşını silmek, onu ilgili tüm sorunlardan kaldırır. Devam edilsin mi?
milestones.deletion_success=Kilometre taşı silindi.
+milestones.filter_sort.earliest_due_data=En erken bitiş tarihi
+milestones.filter_sort.latest_due_date=En uzak bitiş tarihi
milestones.filter_sort.least_complete=En az tamamlama
milestones.filter_sort.most_complete=En çok tamamlama
milestones.filter_sort.most_issues=En çok konu
@@ -1924,6 +1967,8 @@ activity.git_stats_and_deletions=ve
activity.git_stats_deletion_1=%d silme oldu
activity.git_stats_deletion_n=%d silme oldu
+contributors.contribution_type.commits=İşleme
+
search=Ara
search.search_repo=Depo ara
search.type.tooltip=Arama türü
@@ -1971,6 +2016,8 @@ settings.mirror_settings.push_mirror.add=Yansı Gönderimi Ekle
settings.mirror_settings.push_mirror.edit_sync_time=Yansı eşzamanlama aralığını düzenle
settings.sync_mirror=Şimdi Eşitle
+settings.pull_mirror_sync_in_progress=Şu an %s uzak sunucusundan değişiklikler çekiliyor.
+settings.push_mirror_sync_in_progress=Şu an %s uzak sunucusuna değişiklikler itiliyor.
settings.site=Web Sitesi
settings.update_settings=Ayarları Güncelle
settings.update_mirror_settings=Yansı Ayarları Güncelle
@@ -2104,12 +2151,14 @@ settings.webhook_deletion_desc=Bir web isteğini kaldırmak, ayarlarını ve tes
settings.webhook_deletion_success=Web isteği silindi.
settings.webhook.test_delivery=Test Dağıtımı
settings.webhook.test_delivery_desc=Bu web isteğini sahte bir olayla test edin.
+settings.webhook.test_delivery_desc_disabled=Bu web istemcisini sahte bir olayla denemek için etkinleştirin.
settings.webhook.request=İstekler
settings.webhook.response=Cevaplar
settings.webhook.headers=Başlıklar
settings.webhook.payload=İçerik
settings.webhook.body=Gövde
settings.webhook.replay.description=Bu web kancasını tekrar çalıştır.
+settings.webhook.replay.description_disabled=Bu web istemcisini yeniden oynatmak için etkinleştirin.
settings.webhook.delivery.success=Teslim kuyruğuna bir olay eklendi. Teslim geçmişinde görünmesi birkaç saniye alabilir.
settings.githooks_desc=Git İstemcileri Git'in kendisi tarafından desteklenmektedir. Özel işlemler ayarlamak için aşağıdaki istemci dosyalarını düzenleyebilirsiniz.
settings.githook_edit_desc=İstek aktif değilse örnek içerik sunulacaktır. İçeriği boş bırakmak, isteği devre dışı bırakmayı beraberinde getirecektir.
@@ -2269,6 +2318,7 @@ settings.dismiss_stale_approvals_desc=Değişiklik isteğinin içeriğini deği
settings.require_signed_commits=İmzalı İşleme Gerekli
settings.require_signed_commits_desc=Reddetme, onlar imzasızsa veya doğrulanamazsa bu dala gönderir.
settings.protect_branch_name_pattern=Korunmuş Dal Adı Deseni
+settings.protect_branch_name_pattern_desc=Korunmuş dal isim desenleri. Desen sözdizimi için belgelere bakabilirsiniz. Örnekler: main, release/**
settings.protect_patterns=Desenler
settings.protect_protected_file_patterns=Korumalı dosya kalıpları (noktalı virgülle ayrılmış ';'):
settings.protect_protected_file_patterns_desc=Kullanıcının bu dalda dosya ekleme, düzenleme veya silme hakları olsa bile doğrudan değiştirilmesine izin verilmeyen korumalı dosyalar. Birden çok desen noktalı virgül (';') kullanılarak ayrılabilir. Desen sözdizimi için github.com/gobwas/glob belgelerine bakın. Örnekler: .drone.yml
, /docs/**/*.txt
.
@@ -2305,6 +2355,7 @@ settings.tags.protection.allowed.teams=İzin verilen takımlar
settings.tags.protection.allowed.noone=Hiç kimse
settings.tags.protection.create=Etiketi Koru
settings.tags.protection.none=Korumalı etiket yok.
+settings.tags.protection.pattern.description=Birden çok etiketi eşleştirmek için tek bir ad, glob deseni veya normal ifade kullanabilirsiniz. Daha fazlası için korumalı etiketler rehberini okuyun.
settings.bot_token=Bot Jetonu
settings.chat_id=Sohbet Kimliği
settings.thread_id=İş Parçacığı ID
@@ -2485,6 +2536,7 @@ branch.default_deletion_failed=`"%s" dalı varsayılan daldır. Silinemez.`
branch.restore=`"%s" Dalını Geri Yükle`
branch.download=`"%s" Dalını İndir`
branch.rename=`"%s" Dalının Adını Değiştir`
+branch.search=Dal Ara
branch.included_desc=Bu dal varsayılan dalın bir parçasıdır
branch.included=Dahil
branch.create_new_branch=Şu daldan dal oluştur:
@@ -2516,6 +2568,8 @@ error.csv.too_large=Bu dosya çok büyük olduğu için işlenemiyor.
error.csv.unexpected=%d satırı ve %d sütununda beklenmeyen bir karakter içerdiğinden bu dosya işlenemiyor.
error.csv.invalid_field_count=%d satırında yanlış sayıda alan olduğundan bu dosya işlenemiyor.
+[graphs]
+
[org]
org_name_holder=Organizasyon Adı
org_full_name_holder=Organizasyon Tam Adı
@@ -2701,6 +2755,7 @@ dashboard.reinit_missing_repos=Kayıtları bulunanlar için tüm eksik Git depol
dashboard.sync_external_users=Harici kullanıcı verisini senkronize et
dashboard.cleanup_hook_task_table=Hook_task tablosunu temizleme
dashboard.cleanup_packages=Süresi dolmuş paketleri temizleme
+dashboard.cleanup_actions=Eylemlerin süresi geçmiş günlük ve yapılarını temizle
dashboard.server_uptime=Sunucunun Ayakta Kalma Süresi
dashboard.current_goroutine=Güncel Goroutine'ler
dashboard.current_memory_usage=Güncel Bellek Kullanımı
@@ -2738,7 +2793,9 @@ dashboard.gc_lfs=LFS üst nesnelerin atıklarını temizle
dashboard.stop_zombie_tasks=Zombi görevleri durdur
dashboard.stop_endless_tasks=Daimi görevleri durdur
dashboard.cancel_abandoned_jobs=Terkedilmiş görevleri iptal et
+dashboard.start_schedule_tasks=Zamanlanmış görevleri başlat
dashboard.sync_branch.started=Dal Eşzamanlaması başladı
+dashboard.rebuild_issue_indexer=Konu indeksini yeniden oluştur
users.user_manage_panel=Kullanıcı Hesap Yönetimi
users.new_account=Yeni Kullanıcı Hesabı
@@ -2747,6 +2804,9 @@ users.full_name=Tam İsim
users.activated=Aktifleştirilmiş
users.admin=Yönetici
users.restricted=Kısıtlanmış
+users.reserved=Rezerve
+users.bot=Bot
+users.remote=Uzak
users.2fa=2FD
users.repos=Depolar
users.created=Oluşturuldu
@@ -2793,6 +2853,7 @@ users.list_status_filter.is_prohibit_login=Oturum Açmayı Önle
users.list_status_filter.not_prohibit_login=Oturum Açmaya İzin Ver
users.list_status_filter.is_2fa_enabled=2FA Etkin
users.list_status_filter.not_2fa_enabled=2FA Devre Dışı
+users.details=Kullanıcı Ayrıntıları
emails.email_manage_panel=Kullanıcı E-posta Yönetimi
emails.primary=Birincil
@@ -2805,6 +2866,7 @@ emails.updated=E-posta güncellendi
emails.not_updated=İstenen e-posta adresi güncellenemedi: %v
emails.duplicate_active=Bu e-posta adresi farklı bir kullanıcı için zaten aktif.
emails.change_email_header=E-posta Özelliklerini Güncelle
+emails.change_email_text=Bu e-posta adresini güncellemek istediğinizden emin misiniz?
orgs.org_manage_panel=Organizasyon Yönetimi
orgs.name=İsim
@@ -2829,6 +2891,7 @@ packages.package_manage_panel=Paket Yönetimi
packages.total_size=Toplam Boyut: %s
packages.unreferenced_size=Referanssız Boyut: %s
packages.cleanup=Süresi dolmuş veriyi temizle
+packages.cleanup.success=Süresi dolmuş veri başarıyla temizlendi
packages.owner=Sahibi
packages.creator=Oluşturan
packages.name=İsim
@@ -2839,10 +2902,12 @@ packages.size=Boyut
packages.published=Yayınlandı
defaulthooks=Varsayılan Web İstemcileri
+defaulthooks.desc=Web İstemcileri, belirli Gitea olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web İstemcileri varsayılandır ve tüm yeni depolara kopyalanır. web istemcileri kılavuzunda daha fazla bilgi edinin.
defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
systemhooks=Sistem Web İstemcileri
+systemhooks.desc=Belirli Gitea olayları tetiklendiğinde Web istemcileri otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web istemcileri sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. web istemcileri kılavuzunda daha fazla bilgi edinin.
systemhooks.add_webhook=Sistem Web İstemcisi Ekle
systemhooks.update_webhook=Sistem Web İstemcisi Güncelle
@@ -2947,6 +3012,7 @@ auths.tip.google_plus=OAuth2 istemci kimlik bilgilerini https://console.develope
auths.tip.openid_connect=Bitiş noktalarını belirlemek için OpenID Connect Discovery URL'sini kullanın (/.well-known/openid-configuration)
auths.tip.twitter=https://dev.twitter.com/apps adresine gidin, bir uygulama oluşturun ve “Bu uygulamanın Twitter ile oturum açmak için kullanılmasına izin ver” seçeneğinin etkin olduğundan emin olun
auths.tip.discord=https://discordapp.com/developers/applications/me adresinde yeni bir uygulama kaydedin
+auths.tip.gitea=Yeni bir OAuth2 uygulaması kaydedin. Rehber https://docs.gitea.com/development/oauth2-provider adresinde bulunabilir
auths.tip.yandex=`https://oauth.yandex.com/client/new adresinde yeni bir uygulama oluşturun. "Yandex.Passport API'sı" bölümünden aşağıdaki izinleri seçin: "E-posta adresine erişim", "Kullanıcı avatarına erişim" ve "Kullanıcı adına, ad ve soyadına, cinsiyete erişim"`
auths.tip.mastodon=Kimlik doğrulaması yapmak istediğiniz mastodon örneği için özel bir örnek URL girin (veya varsayılan olanı kullanın)
auths.edit=Kimlik Doğrulama Kaynağı Düzenle
@@ -3126,8 +3192,10 @@ monitor.queue.name=İsim
monitor.queue.type=Tür
monitor.queue.exemplar=Örnek Türü
monitor.queue.numberworkers=Çalışan Sayısı
+monitor.queue.activeworkers=Etkin Çalışanlar
monitor.queue.maxnumberworkers=En Fazla Çalışan Sayısı
monitor.queue.numberinqueue=Kuyruktaki Sayı
+monitor.queue.review_add=Çalışanları İncele / Ekle
monitor.queue.settings.title=Havuz Ayarları
monitor.queue.settings.desc=Havuzlar, çalışan kuyruğu tıkanmasına bir yanıt olarak dinamik olarak büyürler.
monitor.queue.settings.maxnumberworkers=En fazla çalışan Sayısı
@@ -3153,6 +3221,7 @@ notices.desc=Açıklama
notices.op=İşlem
notices.delete_success=Sistem bildirimleri silindi.
+
[action]
create_repo=depo %s oluşturuldu
rename_repo=%[1]s
olan depo adını %[3]s buna çevirdi
@@ -3337,6 +3406,8 @@ rpm.registry=Bu kütüğü komut satırını kullanarak kurun:
rpm.distros.redhat=RedHat tabanlı dağıtımlarda
rpm.distros.suse=SUSE tabanlı dağıtımlarda
rpm.install=Paketi kurmak için, aşağıdaki komutu çalıştırın:
+rpm.repository=Depo Bilgisi
+rpm.repository.architectures=Mimariler
rubygems.install=Paketi gem ile kurmak için, şu komutu çalıştırın:
rubygems.install2=veya paketi Gemfile dosyasına ekleyin:
rubygems.dependencies.runtime=Çalışma Zamanı Bağımlılıkları
@@ -3454,23 +3525,29 @@ runners.status.idle=Boşta
runners.status.active=Etkin
runners.status.offline=Çevrimdışı
runners.version=Sürüm
+runners.reset_registration_token=Kayıt tokenini sıfırla
runners.reset_registration_token_success=Çalıştırıcı kayıt belirteci başarıyla sıfırlandı
runs.all_workflows=Tüm İş Akışları
runs.commit=İşle
+runs.scheduled=Zamanlanmış
runs.pushed_by=iten
runs.invalid_workflow_helper=İş akışı yapılandırma dosyası geçersiz. Lütfen yapılandırma dosyanızı denetleyin: %s
+runs.no_matching_online_runner_helper=Şu etiket ile eşleşen çevrimiçi çalıştırıcı bulunamadı: %s
runs.actor=Aktör
runs.status=Durum
runs.actors_no_select=Tüm aktörler
runs.status_no_select=Tüm durumlar
runs.no_results=Eşleşen sonuç yok.
+runs.no_workflows=Henüz hiç bir iş akışı yok.
runs.no_runs=İş akışı henüz hiç çalıştırılmadı.
+runs.empty_commit_message=(boş işleme iletisi)
workflow.disable=İş Akışını Devre Dışı Bırak
workflow.disable_success='%s' iş akışı başarıyla devre dışı bırakıldı.
workflow.enable=İş Akışını Etkinleştir
workflow.enable_success='%s' iş akışı başarıyla etkinleştirildi.
+workflow.disabled=İş akışı devre dışı.
need_approval_desc=Değişiklik isteği çatalında iş akışı çalıştırmak için onay gerekiyor.
@@ -3481,7 +3558,6 @@ variables.none=Henüz hiçbir değişken yok.
variables.deletion=Değişkeni kaldır
variables.deletion.description=Bir değişkeni kaldırma kalıcıdır ve geri alınamaz. Devam edilsin mi?
variables.description=Değişkenler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
-variables.id_not_exist=%d kimlikli değişken mevcut değil.
variables.edit=Değişkeni Düzenle
variables.deletion.failed=Değişken kaldırılamadı.
variables.deletion.success=Değişken kaldırıldı.
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 4cd6c44571..9aa6d6a16e 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -466,6 +466,7 @@ auth_failed=Помилка автентифікації: %v
target_branch_not_exist=Цільової гілки не існує.
+
[user]
change_avatar=Змінити свій аватар…
repositories=Репозиторії
@@ -1508,6 +1509,8 @@ activity.git_stats_and_deletions=та
activity.git_stats_deletion_1=%d видалений
activity.git_stats_deletion_n=%d видалені
+contributors.contribution_type.commits=Коміти
+
search=Пошук
search.search_repo=Пошук репозиторію
search.fuzzy=Неточний
@@ -1961,6 +1964,8 @@ error.csv.too_large=Не вдається відобразити цей файл
error.csv.unexpected=Не вдається відобразити цей файл, тому що він містить неочікуваний символ в рядку %d і стовпці %d.
error.csv.invalid_field_count=Не вдається відобразити цей файл, тому що він має неправильну кількість полів у рядку %d.
+[graphs]
+
[org]
org_name_holder=Назва організації
org_full_name_holder=Повна назва організації
@@ -2510,6 +2515,7 @@ notices.desc=Опис
notices.op=Оп.
notices.delete_success=Сповіщення системи були видалені.
+
[action]
create_repo=створив(ла) репозиторій %s
rename_repo=репозиторій перейменовано з %[1]s
на %[3]s
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 6d22468c9d..7c8153cbb1 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -123,6 +123,7 @@ pin=固定
unpin=取消置顶
artifacts=制品
+confirm_delete_artifact=您确定要删除制品'%s'吗?
archived=已归档
@@ -423,6 +424,7 @@ authorization_failed_desc=因为检测到无效请求,授权失败。请尝试
sspi_auth_failed=SSPI 认证失败
password_pwned=此密码出现在 被盗密码 列表上并且曾经被公开。 请使用另一个密码再试一次。
password_pwned_err=无法完成对 HaveIBeenPwned 的请求
+last_admin=您不能删除最后一个管理员。必须至少保留一个管理员。
[mail]
view_it_on=在 %s 上查看
@@ -588,6 +590,8 @@ org_still_own_packages=该组织仍然是一个或多个软件包的拥有者,
target_branch_not_exist=目标分支不存在。
+admin_cannot_delete_self=当您是管理员时,您不能删除自己。请先移除您的管理员权限
+
[user]
change_avatar=修改头像
joined_on=加入于 %s
@@ -967,6 +971,8 @@ issue_labels_helper=选择一个工单标签集
license=授权许可
license_helper=选择授权许可文件。
license_helper_desc=许可证说明了其他人可以和不可以用您的代码做什么。不确定哪一个适合你的项目?见 选择一个许可证
+object_format=对象格式
+object_format_helper=仓库的对象格式。之后无法更改。SHA1 是最兼容的。
readme=自述
readme_helper=选择自述文件模板。
readme_helper_desc=这是您可以为您的项目撰写完整描述的地方。
@@ -984,6 +990,7 @@ mirror_prune=修剪
mirror_prune_desc=删除过时的远程跟踪引用
mirror_interval=镜像间隔 (有效的时间单位是 'h', 'm', 's')。0 禁用自动定期同步 (最短间隔: %s)
mirror_interval_invalid=镜像间隔无效。
+mirror_sync=已同步
mirror_sync_on_commit=推送提交时同步
mirror_address=从 URL 克隆
mirror_address_desc=在授权框中输入必要的凭据。
@@ -1034,6 +1041,7 @@ desc.public=公开
desc.template=模板
desc.internal=内部
desc.archived=已存档
+desc.sha256=SHA256
template.items=模板选项
template.git_content=Git数据(默认分支)
@@ -1184,6 +1192,8 @@ audio_not_supported_in_browser=您的浏览器不支持使用 HTML5 'video' 标
stored_lfs=存储到Git LFS
symbolic_link=符号链接
executable_file=可执行文件
+vendored=被供应的
+generated=已生成的
commit_graph=提交图
commit_graph.select=选择分支
commit_graph.hide_pr_refs=隐藏合并请求
@@ -1707,6 +1717,7 @@ pulls.select_commit_hold_shift_for_range=选择提交。按住 Shift + 单击选
pulls.review_only_possible_for_full_diff=只有在查看全部差异时才能进行审核
pulls.filter_changes_by_commit=按提交筛选
pulls.nothing_to_compare=分支内容相同,无需创建合并请求。
+pulls.nothing_to_compare_have_tag=所选分支/标签相同。
pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此合并请求将为空。
pulls.has_pull_request=这些分支之间的合并请求已存在: %[2]s#%[3]d
pulls.create=创建合并请求
@@ -1901,6 +1912,7 @@ wiki.page_name_desc=输入此 Wiki 页面的名称。特殊名称有:'Home', '
wiki.original_git_entry_tooltip=查看原始的 Git 文件而不是使用友好链接。
activity=动态
+activity.navbar.contributors=贡献者
activity.period.filter_label=周期:
activity.period.daily=1 天
activity.period.halfweekly=3 天
@@ -1966,6 +1978,11 @@ activity.git_stats_and_deletions=和
activity.git_stats_deletion_1=删除 %d 行
activity.git_stats_deletion_n=删除 %d 行
+contributors.contribution_type.filter_label=贡献类型:
+contributors.contribution_type.commits=提交
+contributors.contribution_type.additions=更多
+contributors.contribution_type.deletions=删除
+
search=搜索
search.search_repo=搜索仓库...
search.type.tooltip=搜索类型
@@ -2003,6 +2020,7 @@ settings.mirror_settings.docs.doc_link_title=如何镜像仓库?
settings.mirror_settings.docs.doc_link_pull_section=文档中的 “从远程仓库拉取” 部分。
settings.mirror_settings.docs.pulling_remote_title=从远程仓库拉取代码
settings.mirror_settings.mirrored_repository=镜像库
+settings.mirror_settings.pushed_repository=推送仓库
settings.mirror_settings.direction=方向
settings.mirror_settings.direction.pull=拉取
settings.mirror_settings.direction.push=推送
@@ -2312,6 +2330,8 @@ settings.protect_approvals_whitelist_users=审查者白名单:
settings.protect_approvals_whitelist_teams=审查团队白名单:
settings.dismiss_stale_approvals=取消过时的批准
settings.dismiss_stale_approvals_desc=当新的提交更改合并请求内容被推送到分支时,旧的批准将被撤销。
+settings.ignore_stale_approvals=忽略过期批准
+settings.ignore_stale_approvals_desc=对旧提交(过期审核)的批准将不计入 PR 的批准数。如果过期审查已被驳回,则与此无关。
settings.require_signed_commits=需要签名提交
settings.require_signed_commits_desc=拒绝推送未签名或无法验证的提交到分支
settings.protect_branch_name_pattern=受保护的分支名称模式
@@ -2367,6 +2387,7 @@ settings.archive.error=仓库在归档时出现异常。请通过日志获取详
settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢!
settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。
settings.archive.tagsettings_unavailable=已归档仓库的Git标签设置不可用。
+settings.archive.mirrors_unavailable=如果仓库已被归档,镜像将不可用。
settings.unarchive.button=撤销仓库归档
settings.unarchive.header=撤销此仓库归档
settings.unarchive.text=撤销归档将恢复仓库接收提交、推送,以及新工单和合并请求的能力。
@@ -2565,6 +2586,13 @@ error.csv.too_large=无法渲染此文件,因为它太大了。
error.csv.unexpected=无法渲染此文件,因为它包含了意外字符,其位于第 %d 行和第 %d 列。
error.csv.invalid_field_count=无法渲染此文件,因为它在第 %d 行中的字段数有误。
+[graphs]
+component_loading=正在加载 %s...
+component_loading_failed=无法加载 %s
+component_loading_info=这可能需要一点…
+component_failed_to_load=意外的错误发生了。
+contributors.what=贡献
+
[org]
org_name_holder=组织名称
org_full_name_holder=组织全名
@@ -2691,6 +2719,7 @@ teams.invite.description=请点击下面的按钮加入团队。
[admin]
dashboard=管理面板
+self_check=自我检查
identity_access=身份及认证
users=帐户管理
organizations=组织管理
@@ -2736,6 +2765,7 @@ dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库
dashboard.delete_missing_repos.started=删除所有丢失 Git 文件的仓库任务已启动。
dashboard.delete_generated_repository_avatars=删除生成的仓库头像
dashboard.sync_repo_branches=将缺少的分支从 git 数据同步到数据库
+dashboard.sync_repo_tags=从 git 数据同步标签到数据库
dashboard.update_mirrors=更新镜像仓库
dashboard.repo_health_check=健康检查所有仓库
dashboard.check_repo_stats=检查所有仓库统计
@@ -2790,6 +2820,7 @@ dashboard.stop_endless_tasks=停止永不停止的任务
dashboard.cancel_abandoned_jobs=取消丢弃的任务
dashboard.start_schedule_tasks=开始调度任务
dashboard.sync_branch.started=分支同步已开始
+dashboard.sync_tag.started=标签同步已开始
dashboard.rebuild_issue_indexer=重建工单索引
users.user_manage_panel=用户帐户管理
@@ -3216,6 +3247,11 @@ notices.desc=提示描述
notices.op=操作
notices.delete_success=系统通知已被删除。
+self_check.no_problem_found=尚未发现问题。
+self_check.database_collation_mismatch=期望数据库使用的校验方式:%s
+self_check.database_collation_case_insensitive=数据库正在使用一个校验 %s, 这是一个不敏感的校验. 虽然Gitea可以与它合作,但可能有一些罕见的情况不如预期的那样起作用。
+self_check.database_fix_mysql=对于MySQL/MariaDB用户,您可以使用“gitea doctor convert”命令来解决校验问题。 或者您也可以通过 "ALTER ... COLLATE ..." 这样的SQL 来手动解决这个问题。
+
[action]
create_repo=创建了仓库 %s
rename_repo=重命名仓库 %[1]s
为 %[3]s
@@ -3400,6 +3436,9 @@ rpm.registry=从命令行设置此注册中心:
rpm.distros.redhat=在基于 RedHat 的发行版
rpm.distros.suse=在基于 SUSE 的发行版
rpm.install=要安装包,请运行以下命令:
+rpm.repository=仓库信息
+rpm.repository.architectures=架构
+rpm.repository.multiple_groups=此软件包可在多个组中使用。
rubygems.install=要使用 gem 安装软件包,请运行以下命令:
rubygems.install2=或将它添加到 Gemfile:
rubygems.dependencies.runtime=运行时依赖
@@ -3532,8 +3571,8 @@ runs.actors_no_select=所有操作者
runs.status_no_select=所有状态
runs.no_results=没有匹配的结果。
runs.no_workflows=目前还没有工作流。
-runs.no_workflows.quick_start=不知道如何启动Gitea Action?请参阅 快速启动指南
-runs.no_workflows.documentation=更多有关 Gitea Action 的信息,请访问 文档 。
+runs.no_workflows.quick_start=不知道如何使用 Gitea Actions吗?请查看 快速启动指南 。
+runs.no_workflows.documentation=关于Gitea Actions的更多信息,请参阅 文档 。
runs.no_runs=工作流尚未运行过。
runs.empty_commit_message=(空白的提交消息)
@@ -3552,7 +3591,7 @@ variables.none=目前还没有变量。
variables.deletion=删除变量
variables.deletion.description=删除变量是永久性的,无法撤消。继续吗?
variables.description=变量将被传给特定的 Actions,其它情况将不能读取
-variables.id_not_exist=ID %d 变量不存在。
+variables.id_not_exist=ID为 %d 的变量不存在。
variables.edit=编辑变量
variables.deletion.failed=删除变量失败。
variables.deletion.success=变量已被删除。
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index d4074026fd..8c45e3157f 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -195,6 +195,7 @@ auth_failed=授權驗證失敗:%v
target_branch_not_exist=目標分支不存在
+
[user]
repositories=儲存庫列表
activity=公開活動
@@ -537,6 +538,8 @@ activity.merged_prs_label=已合併
activity.closed_issue_label=已關閉
activity.new_issues_count_1=建立問題
+contributors.contribution_type.commits=提交歷史
+
search=搜尋
settings=儲存庫設定
@@ -639,6 +642,8 @@ release.downloads=下載附件
+[graphs]
+
[org]
org_name_holder=組織名稱
org_full_name_holder=組織全名
@@ -915,6 +920,7 @@ notices.desc=描述
notices.op=操作
notices.delete_success=已刪除系統提示。
+
[action]
create_repo=建立了儲存庫 %s
rename_repo=重新命名儲存庫 %[1]s
為 %[3]s
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index ea79c45674..09eb262212 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -555,6 +555,7 @@ org_still_own_packages=此組織仍然擁有一個以上的套件,請先刪除
target_branch_not_exist=目標分支不存在
+
[user]
change_avatar=更改大頭貼...
repositories=儲存庫
@@ -1776,6 +1777,8 @@ activity.git_stats_and_deletions=和
activity.git_stats_deletion_1=刪除 %d 行
activity.git_stats_deletion_n=刪除 %d 行
+contributors.contribution_type.commits=提交歷史
+
search=搜尋
search.search_repo=搜尋儲存庫
search.type.tooltip=搜尋類型
@@ -2321,6 +2324,8 @@ error.csv.too_large=無法渲染此檔案,因為它太大了。
error.csv.unexpected=無法渲染此檔案,因為它包含了未預期的字元,於第 %d 行第 %d 列。
error.csv.invalid_field_count=無法渲染此檔案,因為它第 %d 行的欄位數量有誤。
+[graphs]
+
[org]
org_name_holder=組織名稱
org_full_name_holder=組織全名
@@ -2933,6 +2938,7 @@ notices.desc=描述
notices.op=操作
notices.delete_success=已刪除系統提示。
+
[action]
create_repo=建立了儲存庫 %s
rename_repo=重新命名儲存庫 %[1]s
為 %[3]s
@@ -3109,6 +3115,8 @@ pypi.requires=需要 Python
pypi.install=執行下列命令以使用 pip 安裝此套件:
rpm.registry=透過下列命令設定此註冊中心:
rpm.install=執行下列命令安裝此套件:
+rpm.repository=儲存庫資訊
+rpm.repository.architectures=架構
rubygems.install=執行下列命令以使用 gem 安裝此套件:
rubygems.install2=或將它加到 Gemfile:
rubygems.dependencies.runtime=執行階段相依性
diff --git a/package-lock.json b/package-lock.json
index 3572749b89..8f641edb5b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,59 +18,69 @@
"@webcomponents/custom-elements": "1.6.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
- "asciinema-player": "3.6.3",
+ "asciinema-player": "3.6.4",
+ "chart.js": "4.4.1",
+ "chartjs-adapter-dayjs-4": "1.0.4",
+ "chartjs-plugin-zoom": "2.0.1",
"clippie": "4.0.6",
"css-loader": "6.10.0",
+ "css-variables-parser": "1.0.1",
+ "dayjs": "1.11.10",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
"esbuild-loader": "4.0.3",
"escape-goat": "4.0.0",
"fast-glob": "3.3.2",
"htmx.org": "1.9.10",
+ "idiomorph": "0.3.0",
"jquery": "3.7.1",
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
- "lightningcss-loader": "2.1.0",
- "mermaid": "10.7.0",
+ "mermaid": "10.8.0",
"mini-css-extract-plugin": "2.8.0",
"minimatch": "9.0.3",
- "monaco-editor": "0.45.0",
+ "monaco-editor": "0.46.0",
"monaco-editor-webpack-plugin": "7.1.0",
- "pdfobject": "2.2.12",
+ "pdfobject": "2.3.0",
+ "postcss": "8.4.35",
+ "postcss-loader": "8.1.0",
"pretty-ms": "9.0.0",
"sortablejs": "1.15.2",
- "swagger-ui-dist": "5.11.2",
+ "swagger-ui-dist": "5.11.6",
+ "tailwindcss": "3.4.1",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.6.0",
"tippy.js": "6.3.7",
"toastify-js": "1.12.0",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
- "vue": "3.4.15",
+ "vue": "3.4.19",
"vue-bar-graph": "2.0.0",
+ "vue-chartjs": "5.3.0",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
- "webpack": "5.90.1",
+ "webpack": "5.90.2",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.1.0",
- "@playwright/test": "1.41.1",
+ "@playwright/test": "1.41.2",
"@stoplight/spectral-cli": "6.11.0",
- "@stylistic/eslint-plugin-js": "1.5.4",
+ "@stylistic/eslint-plugin-js": "1.6.2",
"@stylistic/stylelint-plugin": "2.0.0",
- "@vitejs/plugin-vue": "5.0.3",
+ "@vitejs/plugin-vue": "5.0.4",
"eslint": "8.56.0",
"eslint-plugin-array-func": "4.0.0",
+ "eslint-plugin-github": "4.10.1",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
"eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-regexp": "2.2.0",
- "eslint-plugin-sonarjs": "0.23.0",
- "eslint-plugin-unicorn": "50.0.1",
- "eslint-plugin-vitest": "0.3.21",
+ "eslint-plugin-sonarjs": "0.24.0",
+ "eslint-plugin-unicorn": "51.0.1",
+ "eslint-plugin-vitest": "0.3.22",
"eslint-plugin-vitest-globals": "1.4.0",
"eslint-plugin-vue": "9.21.1",
"eslint-plugin-vue-scoped-css": "2.7.2",
@@ -82,8 +92,8 @@
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.4",
"svgo": "3.2.0",
- "updates": "15.1.1",
- "vite-string-plugin": "1.1.3",
+ "updates": "15.1.2",
+ "vite-string-plugin": "1.1.5",
"vitest": "1.2.2"
},
"engines": {
@@ -99,6 +109,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@asyncapi/specs": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-4.3.1.tgz",
@@ -112,7 +133,6 @@
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
"integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
- "dev": true,
"dependencies": {
"@babel/highlight": "^7.23.4",
"chalk": "^2.4.2"
@@ -125,7 +145,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
@@ -137,7 +156,6 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -151,7 +169,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
"dependencies": {
"color-name": "1.1.3"
}
@@ -159,14 +176,12 @@
"node_modules/@babel/code-frame/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
"engines": {
"node": ">=0.8.0"
}
@@ -175,7 +190,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -184,7 +198,6 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
@@ -196,7 +209,6 @@
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -205,7 +217,6 @@
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
"integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
- "dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
@@ -219,7 +230,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
@@ -231,7 +241,6 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -245,7 +254,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
"dependencies": {
"color-name": "1.1.3"
}
@@ -253,14 +261,12 @@
"node_modules/@babel/highlight/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
"engines": {
"node": ">=0.8.0"
}
@@ -269,7 +275,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -277,14 +282,12 @@
"node_modules/@babel/highlight/node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/@babel/highlight/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
@@ -1017,6 +1020,12 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@github/browserslist-config": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz",
+ "integrity": "sha512-gIhjdJp/c2beaIWWIlsXdqXVRUz3r2BxBCpfz/F3JXHvSAQ1paMYjLH+maEATtENg+k5eLV7gA+9yPp762ieuw==",
+ "dev": true
+ },
"node_modules/@github/combobox-nav": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@github/combobox-nav/-/combobox-nav-2.3.1.tgz",
@@ -1099,7 +1108,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@@ -1116,7 +1124,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -1128,7 +1135,6 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -1139,14 +1145,12 @@
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@@ -1163,7 +1167,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
@@ -1178,7 +1181,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@@ -1217,9 +1219,9 @@
}
},
"node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"engines": {
"node": ">=6.0.0"
}
@@ -1279,6 +1281,11 @@
"jsep": "^0.4.0||^1.0.0"
}
},
+ "node_modules/@kurkle/color": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
+ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
+ },
"node_modules/@mcaptcha/core-glue": {
"version": "0.1.0-alpha-5",
"resolved": "https://registry.npmjs.org/@mcaptcha/core-glue/-/core-glue-0.1.0-alpha-5.tgz",
@@ -1364,19 +1371,30 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
"optional": true,
"engines": {
"node": ">=14"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@playwright/test": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.1.tgz",
- "integrity": "sha512-9g8EWTjiQ9yFBXc6HjCWe41msLpxEX0KhmfmPl9RPLJdfzL4F0lg2BdJ91O9azFdl11y1pmpwdjBiSxvqc+btw==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
+ "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
"dev": true,
"dependencies": {
- "playwright": "1.41.1"
+ "playwright": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -1447,9 +1465,9 @@
"dev": true
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz",
- "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.11.0.tgz",
+ "integrity": "sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==",
"cpu": [
"arm"
],
@@ -1460,9 +1478,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz",
- "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.11.0.tgz",
+ "integrity": "sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==",
"cpu": [
"arm64"
],
@@ -1473,9 +1491,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz",
- "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.11.0.tgz",
+ "integrity": "sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==",
"cpu": [
"arm64"
],
@@ -1486,9 +1504,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz",
- "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.11.0.tgz",
+ "integrity": "sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==",
"cpu": [
"x64"
],
@@ -1499,9 +1517,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz",
- "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.11.0.tgz",
+ "integrity": "sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==",
"cpu": [
"arm"
],
@@ -1512,9 +1530,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz",
- "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.11.0.tgz",
+ "integrity": "sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==",
"cpu": [
"arm64"
],
@@ -1525,9 +1543,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz",
- "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.11.0.tgz",
+ "integrity": "sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==",
"cpu": [
"arm64"
],
@@ -1538,9 +1556,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz",
- "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.11.0.tgz",
+ "integrity": "sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==",
"cpu": [
"riscv64"
],
@@ -1551,9 +1569,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz",
- "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.11.0.tgz",
+ "integrity": "sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==",
"cpu": [
"x64"
],
@@ -1564,9 +1582,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz",
- "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.11.0.tgz",
+ "integrity": "sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==",
"cpu": [
"x64"
],
@@ -1577,9 +1595,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz",
- "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.11.0.tgz",
+ "integrity": "sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==",
"cpu": [
"arm64"
],
@@ -1590,9 +1608,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz",
- "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.11.0.tgz",
+ "integrity": "sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==",
"cpu": [
"ia32"
],
@@ -1603,9 +1621,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz",
- "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.11.0.tgz",
+ "integrity": "sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==",
"cpu": [
"x64"
],
@@ -2073,11 +2091,12 @@
"dev": true
},
"node_modules/@stylistic/eslint-plugin-js": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz",
- "integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==",
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.2.tgz",
+ "integrity": "sha512-ndT6X2KgWGxv8101pdMOxL8pihlYIHcOv3ICd70cgaJ9exwkPn8hJj4YQwslxoAlre1TFHnXd/G1/hYXgDrjIA==",
"dev": true,
"dependencies": {
+ "@types/eslint": "^8.56.2",
"acorn": "^8.11.3",
"escape-string-regexp": "^4.0.0",
"eslint-visitor-keys": "^3.4.3",
@@ -2197,6 +2216,12 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
},
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
"node_modules/@types/marked": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz",
@@ -2216,9 +2241,9 @@
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
},
"node_modules/@types/node": {
- "version": "20.11.14",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.14.tgz",
- "integrity": "sha512-w3yWCcwULefjP9DmDDsgUskrMoOy5Z8MiwKHr1FvqGPtx7CvJzQvxD7eKpxNtklQxLruxSXWddyeRtyud0RcXQ==",
+ "version": "20.11.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
+ "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -2236,9 +2261,9 @@
"dev": true
},
"node_modules/@types/semver": {
- "version": "7.5.6",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
- "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz",
+ "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==",
"dev": true
},
"node_modules/@types/tern": {
@@ -2260,14 +2285,77 @@
"integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==",
"dev": true
},
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
- "integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
+ "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.20.0",
- "@typescript-eslint/visitor-keys": "6.20.0"
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -2277,10 +2365,37 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
+ "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@typescript-eslint/types": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
- "integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -2291,13 +2406,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
- "integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.20.0",
- "@typescript-eslint/visitor-keys": "6.20.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -2319,17 +2434,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
- "integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.20.0",
- "@typescript-eslint/types": "6.20.0",
- "@typescript-eslint/typescript-estree": "6.20.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
"semver": "^7.5.4"
},
"engines": {
@@ -2344,12 +2459,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
- "integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.20.0",
+ "@typescript-eslint/types": "6.21.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -2367,9 +2482,9 @@
"dev": true
},
"node_modules/@vitejs/plugin-vue": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.3.tgz",
- "integrity": "sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==",
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
+ "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==",
"dev": true,
"engines": {
"node": "^18.0.0 || >=20.0.0"
@@ -2449,9 +2564,9 @@
}
},
"node_modules/@vitest/snapshot/node_modules/magic-string": {
- "version": "0.30.6",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz",
- "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==",
+ "version": "0.30.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz",
+ "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -2503,46 +2618,46 @@
}
},
"node_modules/@vue/compiler-core": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz",
- "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz",
+ "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==",
"dependencies": {
- "@babel/parser": "^7.23.6",
- "@vue/shared": "3.4.15",
+ "@babel/parser": "^7.23.9",
+ "@vue/shared": "3.4.19",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-dom": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz",
- "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz",
+ "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==",
"dependencies": {
- "@vue/compiler-core": "3.4.15",
- "@vue/shared": "3.4.15"
+ "@vue/compiler-core": "3.4.19",
+ "@vue/shared": "3.4.19"
}
},
"node_modules/@vue/compiler-sfc": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz",
- "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz",
+ "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==",
"dependencies": {
- "@babel/parser": "^7.23.6",
- "@vue/compiler-core": "3.4.15",
- "@vue/compiler-dom": "3.4.15",
- "@vue/compiler-ssr": "3.4.15",
- "@vue/shared": "3.4.15",
+ "@babel/parser": "^7.23.9",
+ "@vue/compiler-core": "3.4.19",
+ "@vue/compiler-dom": "3.4.19",
+ "@vue/compiler-ssr": "3.4.19",
+ "@vue/shared": "3.4.19",
"estree-walker": "^2.0.2",
- "magic-string": "^0.30.5",
+ "magic-string": "^0.30.6",
"postcss": "^8.4.33",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-sfc/node_modules/magic-string": {
- "version": "0.30.6",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz",
- "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==",
+ "version": "0.30.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz",
+ "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
@@ -2551,57 +2666,57 @@
}
},
"node_modules/@vue/compiler-ssr": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz",
- "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz",
+ "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==",
"dependencies": {
- "@vue/compiler-dom": "3.4.15",
- "@vue/shared": "3.4.15"
+ "@vue/compiler-dom": "3.4.19",
+ "@vue/shared": "3.4.19"
}
},
"node_modules/@vue/reactivity": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz",
- "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz",
+ "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==",
"dependencies": {
- "@vue/shared": "3.4.15"
+ "@vue/shared": "3.4.19"
}
},
"node_modules/@vue/runtime-core": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz",
- "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz",
+ "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==",
"dependencies": {
- "@vue/reactivity": "3.4.15",
- "@vue/shared": "3.4.15"
+ "@vue/reactivity": "3.4.19",
+ "@vue/shared": "3.4.19"
}
},
"node_modules/@vue/runtime-dom": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz",
- "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz",
+ "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==",
"dependencies": {
- "@vue/runtime-core": "3.4.15",
- "@vue/shared": "3.4.15",
+ "@vue/runtime-core": "3.4.19",
+ "@vue/shared": "3.4.19",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz",
- "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz",
+ "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==",
"dependencies": {
- "@vue/compiler-ssr": "3.4.15",
- "@vue/shared": "3.4.15"
+ "@vue/compiler-ssr": "3.4.19",
+ "@vue/shared": "3.4.19"
},
"peerDependencies": {
- "vue": "3.4.15"
+ "vue": "3.4.19"
}
},
"node_modules/@vue/shared": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz",
- "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g=="
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
+ "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.6",
@@ -2960,19 +3075,53 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+ },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -2986,6 +3135,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/array-includes": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+ "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -2995,18 +3163,93 @@
"node": ">=8"
}
},
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
- "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+ "node_modules/array.prototype.filter": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz",
+ "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==",
"dev": true,
"dependencies": {
- "array-buffer-byte-length": "^1.0.0",
"call-bind": "^1.0.2",
"define-properties": "^1.2.0",
"es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-array-buffer": "^3.0.2",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz",
+ "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.2.1",
+ "get-intrinsic": "^1.2.3",
+ "is-array-buffer": "^3.0.4",
"is-shared-array-buffer": "^1.0.2"
},
"engines": {
@@ -3026,9 +3269,9 @@
}
},
"node_modules/asciinema-player": {
- "version": "3.6.3",
- "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.6.3.tgz",
- "integrity": "sha512-62aDgLpbuduhmpFfNgPOzf6fOluACLsftVnjpWJjUXX6dqhqTckFqWoJ+ayA0XjSlZ9l9wXTcJqRqvAAIpMblg==",
+ "version": "3.6.4",
+ "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.6.4.tgz",
+ "integrity": "sha512-yyMHTjoDuz82/BYPrc3J5GjOtlNI5t2VHTZWss8BmRcY/6nXv+Vilip+XzwIyRBa3/2SSn9FJIEg8bJXBc9o4w==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"solid-js": "^1.3.0"
@@ -3055,6 +3298,12 @@
"node": ">=4"
}
},
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true
+ },
"node_modules/astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -3073,6 +3322,15 @@
"astring": "bin/astring"
}
},
+ "node_modules/asynciterator.prototype": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
+ "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -3092,9 +3350,9 @@
}
},
"node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz",
+ "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==",
"dev": true,
"engines": {
"node": ">= 0.4"
@@ -3103,6 +3361,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axe-core": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
+ "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
+ "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -3135,6 +3411,14 @@
"node": "*"
}
},
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -3161,9 +3445,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.22.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
- "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
+ "version": "4.23.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+ "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
"funding": [
{
"type": "opencollective",
@@ -3179,8 +3463,8 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001580",
- "electron-to-chromium": "^1.4.648",
+ "caniuse-lite": "^1.0.30001587",
+ "electron-to-chromium": "^1.4.668",
"node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.13"
},
@@ -3247,14 +3531,19 @@
}
},
"node_modules/call-bind": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
- "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
"function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.1",
- "set-function-length": "^1.1.1"
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -3264,15 +3553,22 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
"engines": {
"node": ">=6"
}
},
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/caniuse-lite": {
- "version": "1.0.30001581",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz",
- "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==",
+ "version": "1.0.30001587",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
+ "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==",
"funding": [
{
"type": "opencollective",
@@ -3330,6 +3626,40 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/chart.js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
+ "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
+ "dependencies": {
+ "@kurkle/color": "^0.3.0"
+ },
+ "engines": {
+ "pnpm": ">=7"
+ }
+ },
+ "node_modules/chartjs-adapter-dayjs-4": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chartjs-adapter-dayjs-4/-/chartjs-adapter-dayjs-4-1.0.4.tgz",
+ "integrity": "sha512-yy9BAYW4aNzPVrCWZetbILegTRb7HokhgospPoC3b5iZ5qdlqNmXts2KdSp6AqnjkPAp/YWyHDxLvIvwt5x81w==",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "chart.js": ">=4.0.1",
+ "dayjs": "^1.9.7"
+ }
+ },
+ "node_modules/chartjs-plugin-zoom": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-2.0.1.tgz",
+ "integrity": "sha512-ogOmLu6e+Q7E1XWOCOz9YwybMslz9qNfGV2a+qjfmqJYpsw5ZMoRHZBUyW+NGhkpQ5PwwPA/+rikHpBZb7PZuA==",
+ "dependencies": {
+ "hammerjs": "^2.0.8"
+ },
+ "peerDependencies": {
+ "chart.js": ">=3.2.0"
+ }
+ },
"node_modules/check-error": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
@@ -3342,6 +3672,40 @@
"node": "*"
}
},
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/chrome-trace-event": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
@@ -3529,12 +3893,12 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/core-js-compat": {
- "version": "3.35.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz",
- "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==",
+ "version": "3.36.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz",
+ "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==",
"dev": true,
"dependencies": {
- "browserslist": "^4.22.2"
+ "browserslist": "^4.22.3"
},
"funding": {
"type": "opencollective",
@@ -3553,7 +3917,6 @@
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
- "dev": true,
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
@@ -3671,6 +4034,35 @@
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
+ "node_modules/css-variables-parser": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/css-variables-parser/-/css-variables-parser-1.0.1.tgz",
+ "integrity": "sha512-GWaqrwGtAWVr/yjjE17iyvbcy+W3voe0vko1/xLCwFeYd3kTLstzUdVH+g5TTXejrtlsb1FS4L9rP6PmeTa8wQ==",
+ "dependencies": {
+ "postcss": "^7.0.36"
+ }
+ },
+ "node_modules/css-variables-parser/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
+ },
+ "node_modules/css-variables-parser/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
@@ -3767,30 +4159,6 @@
"cytoscape": "^3.2.0"
}
},
- "node_modules/cytoscape-fcose": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
- "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
- "dependencies": {
- "cose-base": "^2.2.0"
- },
- "peerDependencies": {
- "cytoscape": "^3.2.0"
- }
- },
- "node_modules/cytoscape-fcose/node_modules/cose-base": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
- "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
- "dependencies": {
- "layout-base": "^2.0.0"
- }
- },
- "node_modules/cytoscape-fcose/node_modules/layout-base": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
- "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
- },
"node_modules/d3": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
@@ -4213,6 +4581,12 @@
"lodash-es": "^4.17.21"
}
},
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
"node_modules/data-uri-to-buffer": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
@@ -4308,17 +4682,20 @@
"dev": true
},
"node_modules/define-data-property": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
- "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"dependencies": {
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
@@ -4372,21 +4749,15 @@
"node": ">=6"
}
},
- "node_modules/detect-libc": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
- "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
- "bin": {
- "detect-libc": "bin/detect-libc.js"
- },
- "engines": {
- "node": ">=0.10"
- }
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
},
"node_modules/diff": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
- "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"engines": {
"node": ">=0.3.1"
}
@@ -4412,6 +4783,11 @@
"node": ">=8"
}
},
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -4496,8 +4872,7 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/easymde": {
"version": "2.18.0",
@@ -4512,9 +4887,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.653",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.653.tgz",
- "integrity": "sha512-wA2A2LQCqnEwQAvwADQq3KpMpNwgAUBnRmrFgRzHnPhbQUFArTR32Ab46f4p0MovDLcg4uqd4nCsN2hTltslpA=="
+ "version": "1.4.671",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.671.tgz",
+ "integrity": "sha512-UUlE+/rWbydmp+FW8xlnnTA5WNA0ZZd2XL8CuMS72rh+k4y1f8+z6yk3UQhEwqHQWj6IBdL78DwWOdGMvYfQyA=="
},
"node_modules/elkjs": {
"version": "0.9.1",
@@ -4561,15 +4936,14 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/envinfo": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz",
- "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==",
+ "version": "7.11.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz",
+ "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==",
"bin": {
"envinfo": "dist/cli.js"
},
@@ -4581,56 +4955,57 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/es-abstract": {
- "version": "1.22.3",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
- "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
+ "version": "1.22.4",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz",
+ "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==",
"dev": true,
"dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "arraybuffer.prototype.slice": "^1.0.2",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.5",
- "es-set-tostringtag": "^2.0.1",
+ "array-buffer-byte-length": "^1.0.1",
+ "arraybuffer.prototype.slice": "^1.0.3",
+ "available-typed-arrays": "^1.0.6",
+ "call-bind": "^1.0.7",
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.2",
"es-to-primitive": "^1.2.1",
"function.prototype.name": "^1.1.6",
- "get-intrinsic": "^1.2.2",
- "get-symbol-description": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "get-symbol-description": "^1.0.2",
"globalthis": "^1.0.3",
"gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
+ "has-property-descriptors": "^1.0.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
- "hasown": "^2.0.0",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
+ "hasown": "^2.0.1",
+ "internal-slot": "^1.0.7",
+ "is-array-buffer": "^3.0.4",
"is-callable": "^1.2.7",
"is-negative-zero": "^2.0.2",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.2",
"is-string": "^1.0.7",
- "is-typed-array": "^1.1.12",
+ "is-typed-array": "^1.1.13",
"is-weakref": "^1.0.2",
"object-inspect": "^1.13.1",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.1",
- "safe-array-concat": "^1.0.1",
- "safe-regex-test": "^1.0.0",
+ "object.assign": "^4.1.5",
+ "regexp.prototype.flags": "^1.5.2",
+ "safe-array-concat": "^1.1.0",
+ "safe-regex-test": "^1.0.3",
"string.prototype.trim": "^1.2.8",
"string.prototype.trimend": "^1.0.7",
"string.prototype.trimstart": "^1.0.7",
- "typed-array-buffer": "^1.0.0",
+ "typed-array-buffer": "^1.0.1",
"typed-array-byte-length": "^1.0.0",
"typed-array-byte-offset": "^1.0.0",
"typed-array-length": "^1.0.4",
"unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.13"
+ "which-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
@@ -4640,18 +5015,18 @@
}
},
"node_modules/es-aggregate-error": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.11.tgz",
- "integrity": "sha512-DCiZiNlMlbvofET/cE55My387NiLvuGToBEZDdK9U2G3svDCjL8WOgO5Il6lO83nQ8qmag/R9nArdpaFQ/m3lA==",
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.12.tgz",
+ "integrity": "sha512-j0PupcmELoVbYS2NNrsn5zcLLEsryQwP02x8fRawh7c2eEaPHwJFAxltZsqV7HJjsF57+SMpYyVRWgbVLfOagg==",
"dev": true,
"dependencies": {
- "define-data-property": "^1.1.0",
+ "define-data-property": "^1.1.1",
"define-properties": "^1.2.1",
- "es-abstract": "^1.22.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.1.0",
+ "function-bind": "^1.1.2",
"globalthis": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
+ "has-property-descriptors": "^1.0.1",
"set-function-name": "^2.0.1"
},
"engines": {
@@ -4661,6 +5036,59 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-array-method-boxes-properly": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "dev": true
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz",
+ "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==",
+ "dev": true,
+ "dependencies": {
+ "asynciterator.prototype": "^1.0.0",
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.4",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.2",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "iterator.prototype": "^1.1.2",
+ "safe-array-concat": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-module-lexer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
@@ -4680,6 +5108,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
"node_modules/es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
@@ -4752,9 +5189,9 @@
}
},
"node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"engines": {
"node": ">=6"
}
@@ -4852,6 +5289,18 @@
"eslint": ">=6.0.0"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -4910,6 +5359,92 @@
"eslint": ">=8.40.0"
}
},
+ "node_modules/eslint-plugin-escompat": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-escompat/-/eslint-plugin-escompat-3.4.0.tgz",
+ "integrity": "sha512-ufTPv8cwCxTNoLnTZBFTQ5SxU2w7E7wiMIS7PSxsgP1eAxFjtSaoZ80LRn64hI8iYziE6kJG6gX/ZCJVxh48Bg==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.14.1"
+ }
+ },
+ "node_modules/eslint-plugin-eslint-comments": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz",
+ "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5",
+ "ignore": "^5.0.5"
+ },
+ "engines": {
+ "node": ">=6.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=4.19.1"
+ }
+ },
+ "node_modules/eslint-plugin-eslint-comments/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint-plugin-filenames": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz",
+ "integrity": "sha512-tqxJTiEM5a0JmRCUYQmxw23vtTxrb2+a3Q2mMOPhFxvt7ZQQJmdiuMby9B/vUAuVMghyP7oET+nIf6EO6CBd/w==",
+ "dev": true,
+ "dependencies": {
+ "lodash.camelcase": "4.3.0",
+ "lodash.kebabcase": "4.1.1",
+ "lodash.snakecase": "4.1.1",
+ "lodash.upperfirst": "4.3.1"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/eslint-plugin-github": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.10.1.tgz",
+ "integrity": "sha512-1AqQBockOM+m0ZUpwfjWtX0lWdX5cRi/hwJnSNvXoOmz/Hh+ULH6QFz6ENWueTWjoWpgPv0af3bj+snps6o4og==",
+ "dev": true,
+ "dependencies": {
+ "@github/browserslist-config": "^1.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "@typescript-eslint/parser": "^6.0.0",
+ "aria-query": "^5.3.0",
+ "eslint-config-prettier": ">=8.0.0",
+ "eslint-plugin-escompat": "^3.3.3",
+ "eslint-plugin-eslint-comments": "^3.2.0",
+ "eslint-plugin-filenames": "^1.3.2",
+ "eslint-plugin-i18n-text": "^1.0.1",
+ "eslint-plugin-import": "^2.25.2",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-no-only-tests": "^3.0.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "eslint-rule-documentation": ">=1.0.0",
+ "jsx-ast-utils": "^3.3.2",
+ "prettier": "^3.0.0",
+ "svg-element-attributes": "^1.3.1"
+ },
+ "bin": {
+ "eslint-ignore-errors": "bin/eslint-ignore-errors.js"
+ },
+ "peerDependencies": {
+ "eslint": "^8.0.1"
+ }
+ },
"node_modules/eslint-plugin-i": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-i/-/eslint-plugin-i-2.29.1.tgz",
@@ -4957,6 +5492,98 @@
"node": "*"
}
},
+ "node_modules/eslint-plugin-i18n-text": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz",
+ "integrity": "sha512-3G3UetST6rdqhqW9SfcfzNYMpQXS7wNkJvp6dsXnjzGiku6Iu5hl3B0kmk6lIcFPwYjhQIY+tXVRtK9TlGT7RA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=5.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
+ "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlastindex": "^1.2.3",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.8.0",
+ "hasown": "^2.0.0",
+ "is-core-module": "^2.13.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.7",
+ "object.groupby": "^1.0.1",
+ "object.values": "^1.1.7",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/eslint-plugin-jquery": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jquery/-/eslint-plugin-jquery-1.5.1.tgz",
@@ -4966,6 +5593,64 @@
"eslint": ">=5.4.0"
}
},
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
+ "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "aria-query": "^5.3.0",
+ "array-includes": "^3.1.7",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "=4.7.0",
+ "axobject-query": "^3.2.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "es-iterator-helpers": "^1.0.15",
+ "hasown": "^2.0.0",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.7",
+ "object.fromentries": "^2.0.7"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/eslint-plugin-no-jquery": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.7.0.tgz",
@@ -4975,6 +5660,15 @@
"eslint": ">=2.3.0"
}
},
+ "node_modules/eslint-plugin-no-only-tests": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz",
+ "integrity": "sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==",
+ "dev": true,
+ "engines": {
+ "node": ">=5.0.0"
+ }
+ },
"node_modules/eslint-plugin-no-use-extend-native": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-use-extend-native/-/eslint-plugin-no-use-extend-native-0.5.0.tgz",
@@ -4990,6 +5684,36 @@
"node": ">=6.0.0"
}
},
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-regexp": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.2.0.tgz",
@@ -5012,21 +5736,21 @@
}
},
"node_modules/eslint-plugin-sonarjs": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz",
- "integrity": "sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg==",
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz",
+ "integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==",
"dev": true,
"engines": {
- "node": ">=14"
+ "node": ">=16"
},
"peerDependencies": {
"eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/eslint-plugin-unicorn": {
- "version": "50.0.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-50.0.1.tgz",
- "integrity": "sha512-KxenCZxqSYW0GWHH18okDlOQcpezcitm5aOSz6EnobyJ6BIByiPDviQRjJIUAjG/tMN11958MxaQ+qCoU6lfDA==",
+ "version": "51.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz",
+ "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.22.20",
@@ -5057,12 +5781,12 @@
}
},
"node_modules/eslint-plugin-vitest": {
- "version": "0.3.21",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.21.tgz",
- "integrity": "sha512-oYwR1MrwaBw/OG6CKU+SJYleAc442w6CWL1RTQl5WLwy8X3sh0bgHIQk5iEtmTak3Q+XAvZglr0bIoDOjFdkcw==",
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.22.tgz",
+ "integrity": "sha512-atkFGQ7aVgcuSeSMDqnyevIyUpfBPMnosksgEPrKE7Y8xQlqG/5z2IQ6UDau05zXaaFv7Iz8uzqvIuKshjZ0Zw==",
"dev": true,
"dependencies": {
- "@typescript-eslint/utils": "^6.20.0"
+ "@typescript-eslint/utils": "^6.21.0"
},
"engines": {
"node": "^18.0.0 || >= 20.0.0"
@@ -5146,6 +5870,15 @@
"eslint": ">=5"
}
},
+ "node_modules/eslint-rule-documentation": {
+ "version": "1.0.23",
+ "resolved": "https://registry.npmjs.org/eslint-rule-documentation/-/eslint-rule-documentation-1.0.23.tgz",
+ "integrity": "sha512-pWReu3fkohwyvztx/oQWWgld2iad25TfUdi6wvhhaDPIQjHU/pyvlKgXFw1kX31SQK2Nq9MH+vRDWB0ZLy8fYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
@@ -5383,9 +6116,9 @@
}
},
"node_modules/fastq": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
- "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==",
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
"dependencies": {
"reusify": "^1.0.4"
}
@@ -5516,7 +6249,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
- "dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@@ -5565,7 +6297,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -5640,16 +6371,20 @@
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
- "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"dependencies": {
+ "es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -5698,13 +6433,14 @@
}
},
"node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
},
"engines": {
"node": ">= 0.4"
@@ -5747,7 +6483,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -5908,6 +6643,14 @@
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.5.tgz",
"integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ=="
},
+ "node_modules/hammerjs": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+ "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/has-bigints": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
@@ -5926,12 +6669,12 @@
}
},
"node_modules/has-property-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
- "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"dependencies": {
- "get-intrinsic": "^1.2.2"
+ "es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -5962,12 +6705,12 @@
}
},
"node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"dependencies": {
- "has-symbols": "^1.0.2"
+ "has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -5982,9 +6725,9 @@
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg=="
},
"node_modules/hasown": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
- "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
+ "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -6061,9 +6804,9 @@
"integrity": "sha512-UgchasltTCrTuU2DQLom3ohHrBvwr7OqpwyAVJ9VxtNBng4XKkVsqrv0Qr3srqvM9ZNI3f1MmvVQQqK7KW/bTA=="
},
"node_modules/http-proxy-agent": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
- "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
"dependencies": {
"agent-base": "^7.1.0",
@@ -6074,9 +6817,9 @@
}
},
"node_modules/https-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz",
+ "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==",
"dev": true,
"dependencies": {
"agent-base": "^7.0.2",
@@ -6117,6 +6860,11 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/idiomorph": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/idiomorph/-/idiomorph-0.3.0.tgz",
+ "integrity": "sha512-UhV1Ey5xCxIwR9B+OgIjQa+1Jx99XQ1vQHUsKBU1RpQzCx1u+b+N6SOXgf5mEJDqemUI/ffccu6+71l2mJUsRA=="
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -6137,9 +6885,9 @@
]
},
"node_modules/ignore": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
- "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true,
"engines": {
"node": ">= 4"
@@ -6159,7 +6907,6 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@@ -6231,12 +6978,12 @@
}
},
"node_modules/internal-slot": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
- "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
"dev": true,
"dependencies": {
- "get-intrinsic": "^1.2.2",
+ "es-errors": "^1.3.0",
"hasown": "^2.0.0",
"side-channel": "^1.0.4"
},
@@ -6261,14 +7008,16 @@
}
},
"node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -6277,8 +7026,22 @@
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/is-bigint": {
"version": "1.0.4",
@@ -6292,6 +7055,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@@ -6369,6 +7143,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -6377,6 +7163,21 @@
"node": ">=8"
}
},
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-get-set-prop": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz",
@@ -6407,6 +7208,15 @@
"js-types": "^1.0.0"
}
},
+ "node_modules/is-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -6511,6 +7321,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-set": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -6566,12 +7385,12 @@
}
},
"node_modules/is-typed-array": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
- "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
"dev": true,
"dependencies": {
- "which-typed-array": "^1.1.11"
+ "which-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
@@ -6589,6 +7408,15 @@
"is-potential-custom-element-name": "^1.0.0"
}
},
+ "node_modules/is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -6601,6 +7429,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-weakset": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -6620,11 +7461,23 @@
"node": ">=0.10.0"
}
},
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.4",
+ "set-function-name": "^2.0.1"
+ }
+ },
"node_modules/jackspeak": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
- "dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
@@ -6665,6 +7518,14 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/jiti": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
+ "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
@@ -6677,9 +7538,9 @@
"dev": true
},
"node_modules/js-tokens": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.2.tgz",
- "integrity": "sha512-Olnt+V7xYdvGze9YTbGFZIfQXuGV4R3nQwwl8BrtgaPE/wq8UFpUHWuTNc05saowhSr1ZO6tx+V6RjE9D5YQog==",
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz",
+ "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==",
"dev": true
},
"node_modules/js-types": {
@@ -6850,6 +7711,21 @@
"node": ">=0.10.0"
}
},
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/just-extend": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-5.1.1.tgz",
@@ -6906,6 +7782,24 @@
"integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==",
"dev": true
},
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/layout-base": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
@@ -6993,229 +7887,18 @@
"node": ">=8"
}
},
- "node_modules/lightningcss": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.23.0.tgz",
- "integrity": "sha512-SEArWKMHhqn/0QzOtclIwH5pXIYQOUEkF8DgICd/105O+GCgd7jxjNod/QPnBCSWvpRHQBGVz5fQ9uScby03zA==",
- "dependencies": {
- "detect-libc": "^1.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-darwin-arm64": "1.23.0",
- "lightningcss-darwin-x64": "1.23.0",
- "lightningcss-freebsd-x64": "1.23.0",
- "lightningcss-linux-arm-gnueabihf": "1.23.0",
- "lightningcss-linux-arm64-gnu": "1.23.0",
- "lightningcss-linux-arm64-musl": "1.23.0",
- "lightningcss-linux-x64-gnu": "1.23.0",
- "lightningcss-linux-x64-musl": "1.23.0",
- "lightningcss-win32-x64-msvc": "1.23.0"
- }
- },
- "node_modules/lightningcss-darwin-arm64": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.23.0.tgz",
- "integrity": "sha512-kl4Pk3Q2lnE6AJ7Qaij47KNEfY2/UXRZBT/zqGA24B8qwkgllr/j7rclKOf1axcslNXvvUdztjo4Xqh39Yq1aA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-darwin-x64": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.23.0.tgz",
- "integrity": "sha512-KeRFCNoYfDdcolcFXvokVw+PXCapd2yHS1Diko1z1BhRz/nQuD5XyZmxjWdhmhN/zj5sH8YvWsp0/lPLVzqKpg==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-freebsd-x64": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.23.0.tgz",
- "integrity": "sha512-xhnhf0bWPuZxcqknvMDRFFo2TInrmQRWZGB0f6YoAsZX8Y+epfjHeeOIGCfAmgF0DgZxHwYc8mIR5tQU9/+ROA==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.23.0.tgz",
- "integrity": "sha512-fBamf/bULvmWft9uuX+bZske236pUZEoUlaHNBjnueaCTJ/xd8eXgb0cEc7S5o0Nn6kxlauMBnqJpF70Bgq3zg==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.23.0.tgz",
- "integrity": "sha512-RS7sY77yVLOmZD6xW2uEHByYHhQi5JYWmgVumYY85BfNoVI3DupXSlzbw+b45A9NnVKq45+oXkiN6ouMMtTwfg==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.23.0.tgz",
- "integrity": "sha512-cU00LGb6GUXCwof6ACgSMKo3q7XYbsyTj0WsKHLi1nw7pV0NCq8nFTn6ZRBYLoKiV8t+jWl0Hv8KkgymmK5L5g==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.23.0.tgz",
- "integrity": "sha512-q4jdx5+5NfB0/qMbXbOmuC6oo7caPnFghJbIAV90cXZqgV8Am3miZhC4p+sQVdacqxfd+3nrle4C8icR3p1AYw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.23.0.tgz",
- "integrity": "sha512-G9Ri3qpmF4qef2CV/80dADHKXRAQeQXpQTLx7AiQrBYQHqBjB75oxqj06FCIe5g4hNCqLPnM9fsO4CyiT1sFSQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-loader": {
+ "node_modules/lilconfig": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/lightningcss-loader/-/lightningcss-loader-2.1.0.tgz",
- "integrity": "sha512-mB+M/lvs/GdXT4yc8ZiNgLUAbYpPI9grDyC3ybz/Zo6s4GZv53iZnLTnkJT/Qm3Sh89dbFUm+omoHFXCfZtcXw==",
- "dependencies": {
- "browserslist": "^4.21.4",
- "lightningcss": "^1.16.0",
- "webpack-sources": "^3.2.3"
- },
- "peerDependencies": {
- "webpack": ">=5"
- }
- },
- "node_modules/lightningcss-loader/node_modules/webpack-sources": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
- "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
"engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.23.0",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.23.0.tgz",
- "integrity": "sha512-1rcBDJLU+obPPJM6qR5fgBUiCdZwZLafZM5f9kwjFLkb/UBNIzmae39uCSmh71nzPCTXZqHbvwu23OWnWEz+eg==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "node": ">=10"
}
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/linkify-it": {
"version": "5.0.0",
@@ -7293,12 +7976,30 @@
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA=="
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "dev": true
+ },
+ "node_modules/lodash.kebabcase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+ "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+ "dev": true
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "node_modules/lodash.snakecase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+ "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+ "dev": true
+ },
"node_modules/lodash.sortedlastindex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/lodash.sortedlastindex/-/lodash.sortedlastindex-4.1.0.tgz",
@@ -7334,6 +8035,12 @@
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
+ "node_modules/lodash.upperfirst": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+ "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+ "dev": true
+ },
"node_modules/loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@@ -7546,9 +8253,9 @@
"dev": true
},
"node_modules/meow": {
- "version": "13.1.0",
- "resolved": "https://registry.npmjs.org/meow/-/meow-13.1.0.tgz",
- "integrity": "sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA==",
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
+ "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
"dev": true,
"engines": {
"node": ">=18"
@@ -7571,16 +8278,15 @@
}
},
"node_modules/mermaid": {
- "version": "10.7.0",
- "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.7.0.tgz",
- "integrity": "sha512-PsvGupPCkN1vemAAjScyw4pw34p4/0dZkSrqvAB26hUvJulOWGIwt35FZWmT9wPIi4r0QLa5X0PB4YLIGn0/YQ==",
+ "version": "10.8.0",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.8.0.tgz",
+ "integrity": "sha512-9CzfSreRjdDJxX796+jW4zjEq0DVw5xVF0nWsqff8OTbrt+ml0TZ5PyYUjjUZJa2NYxYJZZXewEquxGiM8qZEA==",
"dependencies": {
"@braintree/sanitize-url": "^6.0.1",
"@types/d3-scale": "^4.0.3",
"@types/d3-scale-chromatic": "^3.0.0",
- "cytoscape": "^3.23.0",
+ "cytoscape": "^3.28.1",
"cytoscape-cose-bilkent": "^4.1.0",
- "cytoscape-fcose": "^2.1.0",
"d3": "^7.4.0",
"d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.10",
@@ -8116,7 +8822,6 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
- "dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
@@ -8134,9 +8839,9 @@
}
},
"node_modules/monaco-editor": {
- "version": "0.45.0",
- "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.45.0.tgz",
- "integrity": "sha512-mjv1G1ZzfEE3k9HZN0dQ2olMdwIfaeAAjFiwNprLfYNRSz7ctv9XuCT7gPtBGrMUeV1/iZzYKj17Khu1hxoHOA=="
+ "version": "0.46.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.46.0.tgz",
+ "integrity": "sha512-ADwtLIIww+9FKybWscd7OCfm9odsFYHImBRI1v9AviGce55QY8raT+9ihH8jX/E/e6QVSGM+pKj4jSUSRmALNQ=="
},
"node_modules/monaco-editor-webpack-plugin": {
"version": "7.1.0",
@@ -8168,6 +8873,16 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@@ -8311,7 +9026,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8378,6 +9092,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
@@ -8414,6 +9136,67 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.entries": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+ "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+ "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz",
+ "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.filter": "^1.0.3",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.0.0"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+ "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -8496,7 +9279,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
"dependencies": {
"callsites": "^3.0.0"
},
@@ -8508,7 +9290,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
@@ -8578,7 +9359,6 @@
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
- "dev": true,
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@@ -8594,7 +9374,6 @@
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
- "dev": true,
"engines": {
"node": "14 || >=16.14"
}
@@ -8624,9 +9403,9 @@
}
},
"node_modules/pdfobject": {
- "version": "2.2.12",
- "resolved": "https://registry.npmjs.org/pdfobject/-/pdfobject-2.2.12.tgz",
- "integrity": "sha512-D0oyD/sj8j82AMaJhoyMaY1aD5TkbpU3FbJC6w9/cpJlZRpYHqAkutXw1Ca/FKjYPZmTAu58uGIfgOEaDlbY8A=="
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pdfobject/-/pdfobject-2.3.0.tgz",
+ "integrity": "sha512-w/9pXDXTDs3IDmOri/w8lM/w6LHR0/F4fcBLLzH+4csSoyshQ5su0TE7k0FLHZO7aOjVLDGecqd1M89+PVpVAA=="
},
"node_modules/picocolors": {
"version": "1.0.0",
@@ -8644,6 +9423,22 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -8721,12 +9516,12 @@
"dev": true
},
"node_modules/playwright": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz",
- "integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
+ "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
"dev": true,
"dependencies": {
- "playwright-core": "1.41.1"
+ "playwright-core": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -8739,9 +9534,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.41.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz",
- "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==",
+ "version": "1.41.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
+ "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -8769,9 +9564,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.33",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
- "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
+ "version": "8.4.35",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
+ "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
"funding": [
{
"type": "opencollective",
@@ -8810,6 +9605,70 @@
"node": "^12 || >=14"
}
},
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-loader": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.0.tgz",
+ "integrity": "sha512-AbperNcX3rlob7Ay7A/HQcrofug1caABBkopoFeOQMspZBqcqj6giYn1Bwey/0uiOPAcR+NQD0I2HC7rXzk91w==",
+ "dependencies": {
+ "cosmiconfig": "^9.0.0",
+ "jiti": "^1.20.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || 1.x",
+ "postcss": "^7.0.0 || ^8.0.1",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
"node_modules/postcss-modules-extract-imports": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
@@ -8865,6 +9724,24 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/postcss-nested": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
+ "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.11"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
"node_modules/postcss-resolve-nested-selector": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
@@ -8958,6 +9835,33 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -9075,6 +9979,14 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"dev": true
},
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
"node_modules/read-pkg": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
@@ -9177,6 +10089,17 @@
"node": ">=8"
}
},
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
"node_modules/rechoir": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
@@ -9200,6 +10123,27 @@
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz",
+ "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.0.0",
+ "get-intrinsic": "^1.2.3",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
@@ -9228,14 +10172,15 @@
}
},
"node_modules/regexp.prototype.flags": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
- "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "set-function-name": "^2.0.0"
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -9336,7 +10281,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -9490,13 +10434,13 @@
]
},
"node_modules/safe-regex-test": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
- "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.5",
- "get-intrinsic": "^1.2.2",
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
"is-regex": "^1.1.4"
},
"engines": {
@@ -9568,9 +10512,9 @@
}
},
"node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+ "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -9609,14 +10553,15 @@
}
},
"node_modules/set-function-length": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
- "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
+ "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
"dev": true,
"dependencies": {
- "define-data-property": "^1.1.1",
+ "define-data-property": "^1.1.2",
+ "es-errors": "^1.3.0",
"function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.2",
+ "get-intrinsic": "^1.2.3",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.1"
},
@@ -9669,14 +10614,18 @@
}
},
"node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
+ "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -9692,7 +10641,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
"engines": {
"node": ">=14"
},
@@ -9739,9 +10687,9 @@
}
},
"node_modules/solid-js": {
- "version": "1.8.12",
- "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.12.tgz",
- "integrity": "sha512-sLE/i6M9FSWlov3a2pTC5ISzanH2aKwqXTZj+bbFt4SUrVb4iGEa7fpILBMOxsQjkv3eXqEk6JVLlogOdTe0UQ==",
+ "version": "1.8.15",
+ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.15.tgz",
+ "integrity": "sha512-d0QP/efr3UVcwGgWVPveQQ0IHOH6iU7yUhc2piy8arNG8wxKmvUy1kFxyF8owpmfCWGB87usDKMaVnsNYZm+Vw==",
"dependencies": {
"csstype": "^3.1.0",
"seroval": "^1.0.3",
@@ -9822,9 +10770,9 @@
}
},
"node_modules/spdx-exceptions": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz",
- "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw=="
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
@@ -9844,9 +10792,9 @@
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.16",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
- "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw=="
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
+ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg=="
},
"node_modules/spdx-ranges": {
"version": "2.1.1",
@@ -9903,7 +10851,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -9974,7 +10921,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -9982,6 +10928,15 @@
"node": ">=8"
}
},
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -10284,6 +11239,56 @@
"node": ">= 8"
}
},
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/superstruct": {
"version": "0.10.13",
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.10.13.tgz",
@@ -10324,6 +11329,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svg-element-attributes": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/svg-element-attributes/-/svg-element-attributes-1.3.1.tgz",
+ "integrity": "sha512-Bh05dSOnJBf3miNMqpsormfNtfidA/GxQVakhtn0T4DECWKeXQRQUceYjJ+OxYiiLdGe4Jo9iFV8wICFapFeIA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -10365,9 +11380,9 @@
}
},
"node_modules/swagger-ui-dist": {
- "version": "5.11.2",
- "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.2.tgz",
- "integrity": "sha512-jQG0cRgJNMZ7aCoiFofnoojeSaa/+KgWaDlfgs8QN+BXoGMpxeMVY5OEnjq4OlNvF3yjftO8c9GRAgcHlO+u7A=="
+ "version": "5.11.6",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.6.tgz",
+ "integrity": "sha512-K5BpYuMoPpJY7NwCHIWohH6tU9o0fs1+plNT5KJ+3BBlVEh4H1CpeKJV8o91lpscVY9oqb2jmaAassnW3wVoTg=="
},
"node_modules/symbol-tree": {
"version": "3.2.4",
@@ -10387,6 +11402,22 @@
"node": ">=14"
}
},
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/table": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
@@ -10403,6 +11434,87 @@
"node": ">=10.0.0"
}
},
+ "node_modules/tailwindcss": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
+ "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.19.1",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
+ "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -10412,9 +11524,9 @@
}
},
"node_modules/terser": {
- "version": "5.27.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz",
- "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==",
+ "version": "5.27.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz",
+ "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -10517,6 +11629,25 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/throttle-debounce": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
@@ -10546,9 +11677,9 @@
}
},
"node_modules/tinyspy": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz",
- "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz",
+ "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==",
"dev": true,
"engines": {
"node": ">=14.0.0"
@@ -10620,12 +11751,12 @@
"integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ=="
},
"node_modules/ts-api-utils": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
- "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz",
+ "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==",
"dev": true,
"engines": {
- "node": ">=16.13.0"
+ "node": ">=16"
},
"peerDependencies": {
"typescript": ">=4.2.0"
@@ -10639,6 +11770,35 @@
"node": ">=6.10"
}
},
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
@@ -10679,14 +11839,14 @@
}
},
"node_modules/typed-array-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
- "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz",
+ "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "is-typed-array": "^1.1.10"
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
@@ -10758,9 +11918,9 @@
}
},
"node_modules/typo-js": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.3.tgz",
- "integrity": "sha512-67Hyl94beZX8gmTap7IDPrG5hy2cHftgsCAcGvE1tzuxGT+kRB+zSBin0wIMwysYw8RUCBCvv9UfQl8TNM75dA=="
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.4.tgz",
+ "integrity": "sha512-Oy/k+tFle5NAA3J/yrrYGfvEnPVrDZ8s8/WCwjUE75k331QyKIsFss7byQ/PzBmXLY6h1moRnZbnaxWBe3I3CA=="
},
"node_modules/uc.micro": {
"version": "2.0.0",
@@ -10769,9 +11929,9 @@
"dev": true
},
"node_modules/ufo": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz",
- "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz",
+ "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==",
"dev": true
},
"node_modules/uint8-to-base64": {
@@ -10850,9 +12010,9 @@
}
},
"node_modules/updates": {
- "version": "15.1.1",
- "resolved": "https://registry.npmjs.org/updates/-/updates-15.1.1.tgz",
- "integrity": "sha512-dMz/4251b0lV7yR58tuydCKaiWxOa18YM8fnRgtiDVzQ5ALopTZhMckv00w0nSMj6OFMFKLshTZGkX4dAebaaw==",
+ "version": "15.1.2",
+ "resolved": "https://registry.npmjs.org/updates/-/updates-15.1.2.tgz",
+ "integrity": "sha512-+/JT4NChl82iexV9G80TY5HF3ubQ5O9UTOk3LlCo4Y4aRCYvo1h4bJE8YkP0PE7KiFRWIQq/rPmUYrY2QF8wVA==",
"dev": true,
"bin": {
"updates": "bin/updates.js"
@@ -10948,13 +12108,13 @@
}
},
"node_modules/vite": {
- "version": "5.0.12",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz",
- "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz",
+ "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==",
"dev": true,
"dependencies": {
"esbuild": "^0.19.3",
- "postcss": "^8.4.32",
+ "postcss": "^8.4.35",
"rollup": "^4.2.0"
},
"bin": {
@@ -11025,9 +12185,9 @@
}
},
"node_modules/vite-string-plugin": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.1.3.tgz",
- "integrity": "sha512-uHL8BV2tBf32T2slYpS0vRzGVrAS3iuivtGknjzyecvpSq2AiBSkyLAjEvvIZuZGDDGFHyGX+5+yc3OBPjWDlA==",
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.1.5.tgz",
+ "integrity": "sha512-KRCIFX3PWVUuEjpi9O7EKLT9E27OqOA3RimIvVx6cziLAUxvnk2VvHQfMrP+mKkqyqqSmnnYyTig3OyDnK/zlA==",
"dev": true
},
"node_modules/vite/node_modules/@types/estree": {
@@ -11051,9 +12211,9 @@
}
},
"node_modules/vite/node_modules/rollup": {
- "version": "4.9.6",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz",
- "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.11.0.tgz",
+ "integrity": "sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -11066,19 +12226,19 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.9.6",
- "@rollup/rollup-android-arm64": "4.9.6",
- "@rollup/rollup-darwin-arm64": "4.9.6",
- "@rollup/rollup-darwin-x64": "4.9.6",
- "@rollup/rollup-linux-arm-gnueabihf": "4.9.6",
- "@rollup/rollup-linux-arm64-gnu": "4.9.6",
- "@rollup/rollup-linux-arm64-musl": "4.9.6",
- "@rollup/rollup-linux-riscv64-gnu": "4.9.6",
- "@rollup/rollup-linux-x64-gnu": "4.9.6",
- "@rollup/rollup-linux-x64-musl": "4.9.6",
- "@rollup/rollup-win32-arm64-msvc": "4.9.6",
- "@rollup/rollup-win32-ia32-msvc": "4.9.6",
- "@rollup/rollup-win32-x64-msvc": "4.9.6",
+ "@rollup/rollup-android-arm-eabi": "4.11.0",
+ "@rollup/rollup-android-arm64": "4.11.0",
+ "@rollup/rollup-darwin-arm64": "4.11.0",
+ "@rollup/rollup-darwin-x64": "4.11.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.11.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.11.0",
+ "@rollup/rollup-linux-arm64-musl": "4.11.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.11.0",
+ "@rollup/rollup-linux-x64-gnu": "4.11.0",
+ "@rollup/rollup-linux-x64-musl": "4.11.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.11.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.11.0",
+ "@rollup/rollup-win32-x64-msvc": "4.11.0",
"fsevents": "~2.3.2"
}
},
@@ -11149,9 +12309,9 @@
}
},
"node_modules/vitest/node_modules/magic-string": {
- "version": "0.30.6",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz",
- "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==",
+ "version": "0.30.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz",
+ "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -11161,15 +12321,15 @@
}
},
"node_modules/vue": {
- "version": "3.4.15",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz",
- "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==",
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz",
+ "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==",
"dependencies": {
- "@vue/compiler-dom": "3.4.15",
- "@vue/compiler-sfc": "3.4.15",
- "@vue/runtime-dom": "3.4.15",
- "@vue/server-renderer": "3.4.15",
- "@vue/shared": "3.4.15"
+ "@vue/compiler-dom": "3.4.19",
+ "@vue/compiler-sfc": "3.4.19",
+ "@vue/runtime-dom": "3.4.19",
+ "@vue/server-renderer": "3.4.19",
+ "@vue/shared": "3.4.19"
},
"peerDependencies": {
"typescript": "*"
@@ -11189,6 +12349,15 @@
"vue": "^3.2.37"
}
},
+ "node_modules/vue-chartjs": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.0.tgz",
+ "integrity": "sha512-8XqX0JU8vFZ+WA2/knz4z3ThClduni2Nm0BMe2u0mXgTfd9pXrmJ07QBI+WAij5P/aPmPMX54HCE1seWL37ZdQ==",
+ "peerDependencies": {
+ "chart.js": "^4.1.1",
+ "vue": "^3.0.0-0 || ^2.7.0"
+ }
+ },
"node_modules/vue-eslint-parser": {
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
@@ -11294,9 +12463,9 @@
}
},
"node_modules/webpack": {
- "version": "5.90.1",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz",
- "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==",
+ "version": "5.90.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.2.tgz",
+ "integrity": "sha512-ziXu8ABGr0InCMEYFnHrYweinHK2PWrMqnwdHk2oK3rRhv/1B+2FnfwYv5oD+RrknK/Pp/Hmyvu+eAsaMYhzCw==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.5",
@@ -11555,17 +12724,58 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/which-typed-array": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
- "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
"dev": true,
"dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.4",
+ "function.prototype.name": "^1.1.5",
+ "has-tostringtag": "^1.0.0",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.0.5",
+ "is-finalizationregistry": "^1.0.2",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.1.4",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz",
+ "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.6",
+ "call-bind": "^1.0.5",
"for-each": "^0.3.3",
"gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
+ "has-tostringtag": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -11616,7 +12826,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -11754,6 +12963,14 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
+ "node_modules/yaml": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
+ "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/yargs": {
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz",
diff --git a/package.json b/package.json
index 3defca1a3d..3f0f9103cf 100644
--- a/package.json
+++ b/package.json
@@ -17,59 +17,69 @@
"@webcomponents/custom-elements": "1.6.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
- "asciinema-player": "3.6.3",
+ "asciinema-player": "3.6.4",
+ "chart.js": "4.4.1",
+ "chartjs-adapter-dayjs-4": "1.0.4",
+ "chartjs-plugin-zoom": "2.0.1",
"clippie": "4.0.6",
"css-loader": "6.10.0",
+ "css-variables-parser": "1.0.1",
+ "dayjs": "1.11.10",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
"esbuild-loader": "4.0.3",
"escape-goat": "4.0.0",
"fast-glob": "3.3.2",
"htmx.org": "1.9.10",
+ "idiomorph": "0.3.0",
"jquery": "3.7.1",
"katex": "0.16.9",
"license-checker-webpack-plugin": "0.2.1",
- "lightningcss-loader": "2.1.0",
- "mermaid": "10.7.0",
+ "mermaid": "10.8.0",
"mini-css-extract-plugin": "2.8.0",
"minimatch": "9.0.3",
- "monaco-editor": "0.45.0",
+ "monaco-editor": "0.46.0",
"monaco-editor-webpack-plugin": "7.1.0",
- "pdfobject": "2.2.12",
+ "pdfobject": "2.3.0",
+ "postcss": "8.4.35",
+ "postcss-loader": "8.1.0",
"pretty-ms": "9.0.0",
"sortablejs": "1.15.2",
- "swagger-ui-dist": "5.11.2",
+ "swagger-ui-dist": "5.11.6",
+ "tailwindcss": "3.4.1",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.6.0",
"tippy.js": "6.3.7",
"toastify-js": "1.12.0",
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
- "vue": "3.4.15",
+ "vue": "3.4.19",
"vue-bar-graph": "2.0.0",
+ "vue-chartjs": "5.3.0",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
- "webpack": "5.90.1",
+ "webpack": "5.90.2",
"webpack-cli": "5.1.4",
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.1.0",
- "@playwright/test": "1.41.1",
+ "@playwright/test": "1.41.2",
"@stoplight/spectral-cli": "6.11.0",
- "@stylistic/eslint-plugin-js": "1.5.4",
+ "@stylistic/eslint-plugin-js": "1.6.2",
"@stylistic/stylelint-plugin": "2.0.0",
- "@vitejs/plugin-vue": "5.0.3",
+ "@vitejs/plugin-vue": "5.0.4",
"eslint": "8.56.0",
"eslint-plugin-array-func": "4.0.0",
+ "eslint-plugin-github": "4.10.1",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
"eslint-plugin-no-use-extend-native": "0.5.0",
"eslint-plugin-regexp": "2.2.0",
- "eslint-plugin-sonarjs": "0.23.0",
- "eslint-plugin-unicorn": "50.0.1",
- "eslint-plugin-vitest": "0.3.21",
+ "eslint-plugin-sonarjs": "0.24.0",
+ "eslint-plugin-unicorn": "51.0.1",
+ "eslint-plugin-vitest": "0.3.22",
"eslint-plugin-vitest-globals": "1.4.0",
"eslint-plugin-vue": "9.21.1",
"eslint-plugin-vue-scoped-css": "2.7.2",
@@ -81,13 +91,11 @@
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.4",
"svgo": "3.2.0",
- "updates": "15.1.1",
- "vite-string-plugin": "1.1.3",
+ "updates": "15.1.2",
+ "vite-string-plugin": "1.1.5",
"vitest": "1.2.2"
},
"browserslist": [
- "defaults",
- "not ie > 0",
- "not ie_mob > 0"
+ "defaults"
]
}
diff --git a/poetry.lock b/poetry.lock
index 74d202c919..4cb58c6ef2 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -342,13 +342,13 @@ telegram = ["requests"]
[[package]]
name = "yamllint"
-version = "1.33.0"
+version = "1.35.0"
description = "A linter for YAML files."
optional = false
python-versions = ">=3.8"
files = [
- {file = "yamllint-1.33.0-py3-none-any.whl", hash = "sha256:28a19f5d68d28d8fec538a1db21bb2d84c7dc2e2ea36266da8d4d1c5a683814d"},
- {file = "yamllint-1.33.0.tar.gz", hash = "sha256:2dceab9ef2d99518a2fcf4ffc964d44250ac4459be1ba3ca315118e4a1a81f7d"},
+ {file = "yamllint-1.35.0-py3-none-any.whl", hash = "sha256:601b0adaaac6d9bacb16a2e612e7ee8d23caf941ceebf9bfe2cff0f196266004"},
+ {file = "yamllint-1.35.0.tar.gz", hash = "sha256:9bc99c3e9fe89b4c6ee26e17aa817cf2d14390de6577cb6e2e6ed5f72120c835"},
]
[package.dependencies]
@@ -361,4 +361,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "175c87d138a47ba190a2c3f16b801f694915cc6f2367a358585df9cd1b17ff96"
+content-hash = "ba1c2c4235872f67354b5f52aa5bf0cd616354961530d9dc907f9fba28cc1ece"
diff --git a/public/assets/img/favicon.svg b/public/assets/img/favicon.svg
index afeeacb77c..43291345df 100644
--- a/public/assets/img/favicon.svg
+++ b/public/assets/img/favicon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/assets/img/logo.svg b/public/assets/img/logo.svg
index afeeacb77c..43291345df 100644
--- a/public/assets/img/logo.svg
+++ b/public/assets/img/logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-discord.svg b/public/assets/img/svg/gitea-discord.svg
index 6ebbdcdcc3..2edcb4fed7 100644
--- a/public/assets/img/svg/gitea-discord.svg
+++ b/public/assets/img/svg/gitea-discord.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-open-with-jetbrains.svg b/public/assets/img/svg/gitea-open-with-jetbrains.svg
new file mode 100644
index 0000000000..2b1491b541
--- /dev/null
+++ b/public/assets/img/svg/gitea-open-with-jetbrains.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-open-with-vscode.svg b/public/assets/img/svg/gitea-open-with-vscode.svg
new file mode 100644
index 0000000000..151c45e210
--- /dev/null
+++ b/public/assets/img/svg/gitea-open-with-vscode.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-open-with-vscodium.svg b/public/assets/img/svg/gitea-open-with-vscodium.svg
new file mode 100644
index 0000000000..9f70878ba6
--- /dev/null
+++ b/public/assets/img/svg/gitea-open-with-vscodium.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-vscode.svg b/public/assets/img/svg/gitea-vscode.svg
deleted file mode 100644
index 453b9befcc..0000000000
--- a/public/assets/img/svg/gitea-vscode.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index d999a1476c..bef41d6266 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,7 +9,7 @@ python = "^3.8"
[tool.poetry.group.dev.dependencies]
djlint = "1.34.1"
-yamllint = "1.33.0"
+yamllint = "1.35.0"
[tool.djlint]
profile="golang"
diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go
index 3363c4c0e8..9fbd3f045d 100644
--- a/routers/api/actions/artifacts.go
+++ b/routers/api/actions/artifacts.go
@@ -63,6 +63,7 @@ package actions
import (
"crypto/md5"
+ "errors"
"fmt"
"net/http"
"strconv"
@@ -426,7 +427,19 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
var items []downloadArtifactResponseItem
for _, artifact := range artifacts {
- downloadURL := ar.buildArtifactURL(runID, strconv.FormatInt(artifact.ID, 10), "download")
+ var downloadURL string
+ if setting.Actions.ArtifactStorage.MinioConfig.ServeDirect {
+ u, err := ar.fs.URL(artifact.StoragePath, artifact.ArtifactName)
+ if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
+ log.Error("Error getting serve direct url: %v", err)
+ }
+ if u != nil {
+ downloadURL = u.String()
+ }
+ }
+ if downloadURL == "" {
+ downloadURL = ar.buildArtifactURL(runID, strconv.FormatInt(artifact.ID, 10), "download")
+ }
item := downloadArtifactResponseItem{
Path: util.PathJoinRel(itemPath, artifact.ArtifactPath),
ItemType: "file",
diff --git a/routers/api/packages/alpine/alpine.go b/routers/api/packages/alpine/alpine.go
index bb14c5163a..3fd8288c01 100644
--- a/routers/api/packages/alpine/alpine.go
+++ b/routers/api/packages/alpine/alpine.go
@@ -72,7 +72,7 @@ func GetRepositoryFile(ctx *context.Context) {
ctx,
pv,
&packages_service.PackageFileInfo{
- Filename: alpine_service.IndexFilename,
+ Filename: alpine_service.IndexArchiveFilename,
CompositeKey: fmt.Sprintf("%s|%s|%s", ctx.Params("branch"), ctx.Params("repository"), ctx.Params("architecture")),
},
)
@@ -182,19 +182,38 @@ func UploadPackageFile(ctx *context.Context) {
}
func DownloadPackageFile(ctx *context.Context) {
- pfs, _, err := packages_model.SearchFiles(ctx, &packages_model.PackageFileSearchOptions{
+ branch := ctx.Params("branch")
+ repository := ctx.Params("repository")
+ architecture := ctx.Params("architecture")
+
+ opts := &packages_model.PackageFileSearchOptions{
OwnerID: ctx.Package.Owner.ID,
PackageType: packages_model.TypeAlpine,
Query: ctx.Params("filename"),
- CompositeKey: fmt.Sprintf("%s|%s|%s", ctx.Params("branch"), ctx.Params("repository"), ctx.Params("architecture")),
- })
+ CompositeKey: fmt.Sprintf("%s|%s|%s", branch, repository, architecture),
+ }
+ pfs, _, err := packages_model.SearchFiles(ctx, opts)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
- if len(pfs) != 1 {
- apiError(ctx, http.StatusNotFound, nil)
- return
+ if len(pfs) == 0 {
+ // Try again with architecture 'noarch'
+ if architecture == alpine_module.NoArch {
+ apiError(ctx, http.StatusNotFound, nil)
+ return
+ }
+
+ opts.CompositeKey = fmt.Sprintf("%s|%s|%s", branch, repository, alpine_module.NoArch)
+ if pfs, _, err = packages_model.SearchFiles(ctx, opts); err != nil {
+ apiError(ctx, http.StatusInternalServerError, err)
+ return
+ }
+
+ if len(pfs) == 0 {
+ apiError(ctx, http.StatusNotFound, nil)
+ return
+ }
}
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
diff --git a/routers/api/packages/chef/auth.go b/routers/api/packages/chef/auth.go
index 3aef8281a4..a790e9a363 100644
--- a/routers/api/packages/chef/auth.go
+++ b/routers/api/packages/chef/auth.go
@@ -8,6 +8,7 @@ import (
"crypto"
"crypto/rsa"
"crypto/sha1"
+ "crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
@@ -26,8 +27,6 @@ import (
chef_module "code.gitea.io/gitea/modules/packages/chef"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/auth"
-
- "github.com/minio/sha256-simd"
)
const (
diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go
index 0b93382b01..5106395eb1 100644
--- a/routers/api/packages/maven/maven.go
+++ b/routers/api/packages/maven/maven.go
@@ -6,6 +6,7 @@ package maven
import (
"crypto/md5"
"crypto/sha1"
+ "crypto/sha256"
"crypto/sha512"
"encoding/hex"
"encoding/xml"
@@ -26,8 +27,6 @@ import (
maven_module "code.gitea.io/gitea/modules/packages/maven"
"code.gitea.io/gitea/routers/api/packages/helper"
packages_service "code.gitea.io/gitea/services/packages"
-
- "github.com/minio/sha256-simd"
)
const (
diff --git a/routers/api/packages/swift/swift.go b/routers/api/packages/swift/swift.go
index 427e262d06..6ad289e51e 100644
--- a/routers/api/packages/swift/swift.go
+++ b/routers/api/packages/swift/swift.go
@@ -157,7 +157,7 @@ func EnumeratePackageVersions(ctx *context.Context) {
}
type Resource struct {
- Name string `json:"id"`
+ Name string `json:"name"`
Type string `json:"type"`
Checksum string `json:"checksum"`
}
diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go
index 272996f43d..2ce7651a09 100644
--- a/routers/api/v1/admin/user.go
+++ b/routers/api/v1/admin/user.go
@@ -21,7 +21,6 @@ import (
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/utils"
@@ -117,11 +116,8 @@ func CreateUser(ctx *context.APIContext) {
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
- IsActive: util.OptionalBoolTrue,
- }
-
- if form.Restricted != nil {
- overwriteDefault.IsRestricted = util.OptionalBoolOf(*form.Restricted)
+ IsActive: optional.Some(true),
+ IsRestricted: optional.FromPtr(form.Restricted),
}
if form.Visibility != "" {
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index cb1803f7c6..e7bdef1489 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -6,9 +6,9 @@
//
// This documentation describes the Gitea API.
//
-// Schemes: http, https
+// Schemes: https, http
// BasePath: /api/v1
-// Version: {{AppVer | JSEscape | Safe}}
+// Version: {{AppVer | JSEscape}}
// License: MIT http://opensource.org/licenses/MIT
//
// Consumes:
@@ -811,7 +811,7 @@ func individualPermsChecker(ctx *context.APIContext) {
// check for and warn against deprecated authentication options
func checkDeprecatedAuthMethods(ctx *context.APIContext) {
if ctx.FormString("token") != "" || ctx.FormString("access_token") != "" {
- ctx.Resp.Header().Set("Warning", "token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization.")
+ ctx.Resp.Header().Set("X-Gitea-Warning", "token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization.")
}
}
@@ -1235,6 +1235,7 @@ func Routes() *web.Route {
m.Group("/{ref}", func() {
m.Get("/status", repo.GetCombinedCommitStatusByRef)
m.Get("/statuses", repo.GetCommitStatusesByRef)
+ m.Get("/pull", repo.GetCommitPullRequest)
}, context.ReferencesGitRepo())
}, reqRepoReader(unit.TypeCode))
m.Group("/git", func() {
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index bd02a8afc4..2cdbcd25a2 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -17,9 +17,9 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/optional"
repo_module "code.gitea.io/gitea/modules/repository"
api "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/convert"
@@ -141,7 +141,7 @@ func DeleteBranch(ctx *context.APIContext) {
// check whether branches of this repository has been synced
totalNumOfBranches, err := db.Count[git_model.Branch](ctx, git_model.FindBranchOptions{
RepoID: ctx.Repo.Repository.ID,
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
})
if err != nil {
ctx.Error(http.StatusInternalServerError, "CountBranches", err)
@@ -340,7 +340,7 @@ func ListBranches(ctx *context.APIContext) {
branchOpts := git_model.FindBranchOptions{
ListOptions: listOptions,
RepoID: ctx.Repo.Repository.ID,
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
}
var err error
totalNumOfBranches, err = db.Count[git_model.Branch](ctx, branchOpts)
diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go
index 43b6400009..d01cf6b8bc 100644
--- a/routers/api/v1/repo/commits.go
+++ b/routers/api/v1/repo/commits.go
@@ -10,6 +10,7 @@ import (
"net/http"
"strconv"
+ issues_model "code.gitea.io/gitea/models/issues"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
@@ -323,3 +324,53 @@ func DownloadCommitDiffOrPatch(ctx *context.APIContext) {
return
}
}
+
+// GetCommitPullRequest returns the pull request of the commit
+func GetCommitPullRequest(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/commits/{sha}/pull repository repoGetCommitPullRequest
+ // ---
+ // summary: Get the pull request of the commit
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the repo
+ // type: string
+ // required: true
+ // - name: repo
+ // in: path
+ // description: name of the repo
+ // type: string
+ // required: true
+ // - name: sha
+ // in: path
+ // description: SHA of the commit to get
+ // type: string
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/PullRequest"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ pr, err := issues_model.GetPullRequestByMergedCommit(ctx, ctx.Repo.Repository.ID, ctx.Params(":sha"))
+ if err != nil {
+ if issues_model.IsErrPullRequestNotExist(err) {
+ ctx.Error(http.StatusNotFound, "GetPullRequestByMergedCommit", err)
+ } else {
+ ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
+ }
+ return
+ }
+
+ if err = pr.LoadBaseRepo(ctx); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
+ return
+ }
+ if err = pr.LoadHeadRepo(ctx); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, convert.ToAPIPullRequest(ctx, pr, ctx.Doer))
+}
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 065d6bf8b2..317213c946 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -408,7 +408,7 @@ func canReadFiles(r *context.Repository) bool {
return r.Permission.CanRead(unit.TypeCode)
}
-func base64Reader(s string) (io.Reader, error) {
+func base64Reader(s string) (io.ReadSeeker, error) {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return nil, err
@@ -762,13 +762,13 @@ func changeFilesCommitMessage(ctx *context.APIContext, files []*files_service.Ch
}
message := ""
if len(createFiles) != 0 {
- message += ctx.Tr("repo.editor.add", strings.Join(createFiles, ", ")+"\n")
+ message += ctx.Locale.TrString("repo.editor.add", strings.Join(createFiles, ", ")+"\n")
}
if len(updateFiles) != 0 {
- message += ctx.Tr("repo.editor.update", strings.Join(updateFiles, ", ")+"\n")
+ message += ctx.Locale.TrString("repo.editor.update", strings.Join(updateFiles, ", ")+"\n")
}
if len(deleteFiles) != 0 {
- message += ctx.Tr("repo.editor.delete", strings.Join(deleteFiles, ", "))
+ message += ctx.Locale.TrString("repo.editor.delete", strings.Join(deleteFiles, ", "))
}
return strings.Trim(message, "\n")
}
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index 4db2c68a79..2b7a8f7ba1 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -395,7 +395,7 @@ func CreateIssueComment(ctx *context.APIContext) {
}
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
- ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
+ ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Locale.TrString("repo.issues.comment_on_locked")))
return
}
diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go
index 07d8f4877b..6338651aae 100644
--- a/routers/api/v1/repo/pull_review.go
+++ b/routers/api/v1/repo/pull_review.go
@@ -362,6 +362,7 @@ func CreatePullReview(ctx *context.APIContext) {
true, // pending review
0, // no reply
opts.CommitID,
+ nil,
); err != nil {
ctx.Error(http.StatusInternalServerError, "CreateCodeComment", err)
return
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 2efdccb569..40de8853d8 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -8,6 +8,7 @@ import (
"fmt"
"net/http"
"slices"
+ "strconv"
"strings"
"time"
@@ -884,6 +885,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
AllowRebase: true,
AllowRebaseMerge: true,
AllowSquash: true,
+ AllowFastForwardOnly: true,
AllowManualMerge: true,
AutodetectManualMerge: false,
AllowRebaseUpdate: true,
@@ -910,6 +912,9 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
if opts.AllowSquash != nil {
config.AllowSquash = *opts.AllowSquash
}
+ if opts.AllowFastForwardOnly != nil {
+ config.AllowFastForwardOnly = *opts.AllowFastForwardOnly
+ }
if opts.AllowManualMerge != nil {
config.AllowManualMerge = *opts.AllowManualMerge
}
@@ -1161,12 +1166,11 @@ func GetIssueTemplates(ctx *context.APIContext) {
// "$ref": "#/responses/IssueTemplates"
// "404":
// "$ref": "#/responses/notFound"
- ret, err := issue.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "GetTemplatesFromDefaultBranch", err)
- return
+ ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
+ if cnt := len(ret.TemplateErrors); cnt != 0 {
+ ctx.Resp.Header().Add("X-Gitea-Warning", "error occurs when parsing issue template: count="+strconv.Itoa(cnt))
}
- ctx.JSON(http.StatusOK, ret)
+ ctx.JSON(http.StatusOK, ret.IssueTemplates)
}
// GetIssueConfig returns the issue config for a repo
diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go
index 29e2d1f21d..08ba7fabac 100644
--- a/routers/api/v1/repo/repo_test.go
+++ b/routers/api/v1/repo/repo_test.go
@@ -35,6 +35,7 @@ func TestRepoEdit(t *testing.T) {
allowRebase := false
allowRebaseMerge := false
allowSquashMerge := false
+ allowFastForwardOnlyMerge := false
archived := true
opts := api.EditRepoOption{
Name: &ctx.Repo.Repository.Name,
@@ -50,6 +51,7 @@ func TestRepoEdit(t *testing.T) {
AllowRebase: &allowRebase,
AllowRebaseMerge: &allowRebaseMerge,
AllowSquash: &allowSquashMerge,
+ AllowFastForwardOnly: &allowFastForwardOnlyMerge,
Archived: &archived,
}
diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go
index 2299cdc247..5e80190017 100644
--- a/routers/api/v1/utils/git.go
+++ b/routers/api/v1/utils/git.go
@@ -72,7 +72,7 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str
// ConvertToObjectID returns a full-length SHA1 from a potential ID string
func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID string) (git.ObjectID, error) {
- objectFormat, _ := repo.GitRepo.GetObjectFormat()
+ objectFormat := repo.GetObjectFormat()
if len(commitID) == objectFormat.FullLength() && objectFormat.IsValid(commitID) {
sha, err := git.NewIDFromString(commitID)
if err == nil {
diff --git a/routers/install/install.go b/routers/install/install.go
index 5c0290d2cc..decf74cecb 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -7,6 +7,7 @@ package install
import (
"fmt"
"net/http"
+ "net/mail"
"os"
"os/exec"
"path/filepath"
@@ -25,12 +26,12 @@ import (
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/user"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/routers/common"
@@ -409,7 +410,7 @@ func SubmitInstall(ctx *context.Context) {
cfg.Section("server").Key("LFS_START_SERVER").SetValue("true")
cfg.Section("lfs").Key("PATH").SetValue(form.LFSRootPath)
var lfsJwtSecret string
- if _, lfsJwtSecret, err = generate.NewJwtSecretBase64(); err != nil {
+ if _, lfsJwtSecret, err = generate.NewJwtSecretWithBase64(); err != nil {
ctx.RenderWithErr(ctx.Tr("install.lfs_jwt_secret_failed", err), tplInstall, &form)
return
}
@@ -419,6 +420,11 @@ func SubmitInstall(ctx *context.Context) {
}
if len(strings.TrimSpace(form.SMTPAddr)) > 0 {
+ if _, err := mail.ParseAddress(form.SMTPFrom); err != nil {
+ ctx.RenderWithErr(ctx.Tr("install.smtp_from_invalid"), tplInstall, &form)
+ return
+ }
+
cfg.Section("mailer").Key("ENABLED").SetValue("true")
cfg.Section("mailer").Key("SMTP_ADDR").SetValue(form.SMTPAddr)
cfg.Section("mailer").Key("SMTP_PORT").SetValue(form.SMTPPort)
@@ -533,8 +539,8 @@ func SubmitInstall(ctx *context.Context) {
IsAdmin: true,
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
- IsRestricted: util.OptionalBoolFalse,
- IsActive: util.OptionalBoolTrue,
+ IsRestricted: optional.Some(false),
+ IsActive: optional.Some(true),
}
if err = user_model.CreateUser(ctx, u, overwriteDefault); err != nil {
diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go
index 1b274ae154..8b954a8130 100644
--- a/routers/private/hook_post_receive.go
+++ b/routers/private/hook_post_receive.go
@@ -124,7 +124,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
// post update for agit pull request
// FIXME: use pr.Flow to test whether it's an Agit PR or a GH PR
- if git.SupportProcReceive && refFullName.IsPull() {
+ if git.DefaultFeatures.SupportProcReceive && refFullName.IsPull() {
if repo == nil {
repo = loadRepository(ctx, ownerName, repoName)
if ctx.Written() {
diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go
index 90d8287f06..ad52f35084 100644
--- a/routers/private/hook_pre_receive.go
+++ b/routers/private/hook_pre_receive.go
@@ -122,7 +122,7 @@ func HookPreReceive(ctx *gitea_context.PrivateContext) {
preReceiveBranch(ourCtx, oldCommitID, newCommitID, refFullName)
case refFullName.IsTag():
preReceiveTag(ourCtx, oldCommitID, newCommitID, refFullName)
- case git.SupportProcReceive && refFullName.IsFor():
+ case git.DefaultFeatures.SupportProcReceive && refFullName.IsFor():
preReceiveFor(ourCtx, oldCommitID, newCommitID, refFullName)
default:
ourCtx.AssertCanWriteCode()
@@ -145,7 +145,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
repo := ctx.Repo.Repository
gitRepo := ctx.Repo.GitRepo
- objectFormat, _ := gitRepo.GetObjectFormat()
+ objectFormat := ctx.Repo.GetObjectFormat()
if branchName == repo.DefaultBranch && newCommitID == objectFormat.EmptyObjectID().String() {
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
diff --git a/routers/private/hook_proc_receive.go b/routers/private/hook_proc_receive.go
index 5577120770..5805202bb5 100644
--- a/routers/private/hook_proc_receive.go
+++ b/routers/private/hook_proc_receive.go
@@ -18,7 +18,7 @@ import (
// HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present
func HookProcReceive(ctx *gitea_context.PrivateContext) {
opts := web.GetForm(ctx).(*private.HookOptions)
- if !git.SupportProcReceive {
+ if !git.DefaultFeatures.SupportProcReceive {
ctx.Status(http.StatusNotFound)
return
}
diff --git a/routers/private/serv.go b/routers/private/serv.go
index 00731947a5..3812ccb52b 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -297,7 +297,7 @@ func ServCommand(ctx *context.PrivateContext) {
}
} else {
// Because of the special ref "refs/for" we will need to delay write permission check
- if git.SupportProcReceive && unitType == unit.TypeCode {
+ if git.DefaultFeatures.SupportProcReceive && unitType == unit.TypeCode {
mode = perm.AccessModeRead
}
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index d31cb1cd25..9fbd429f74 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -28,13 +28,14 @@ import (
)
const (
- tplDashboard base.TplName = "admin/dashboard"
- tplSelfCheck base.TplName = "admin/self_check"
- tplCron base.TplName = "admin/cron"
- tplQueue base.TplName = "admin/queue"
- tplStacktrace base.TplName = "admin/stacktrace"
- tplQueueManage base.TplName = "admin/queue_manage"
- tplStats base.TplName = "admin/stats"
+ tplDashboard base.TplName = "admin/dashboard"
+ tplSystemStatus base.TplName = "admin/system_status"
+ tplSelfCheck base.TplName = "admin/self_check"
+ tplCron base.TplName = "admin/cron"
+ tplQueue base.TplName = "admin/queue"
+ tplStacktrace base.TplName = "admin/stacktrace"
+ tplQueueManage base.TplName = "admin/queue_manage"
+ tplStats base.TplName = "admin/stats"
)
var sysStatus struct {
@@ -72,7 +73,7 @@ var sysStatus struct {
// Garbage collector statistics.
NextGC string // next run in HeapAlloc time (bytes)
- LastGC string // last run in absolute time (ns)
+ LastGCTime string // last run time
PauseTotalNs string
PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
NumGC uint32
@@ -110,7 +111,7 @@ func updateSystemStatus() {
sysStatus.OtherSys = base.FileSize(int64(m.OtherSys))
sysStatus.NextGC = base.FileSize(int64(m.NextGC))
- sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000)
+ sysStatus.LastGCTime = time.Unix(0, int64(m.LastGC)).Format(time.RFC3339)
sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000)
sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000)
sysStatus.NumGC = m.NumGC
@@ -132,7 +133,6 @@ func Dashboard(ctx *context.Context) {
ctx.Data["PageIsAdminDashboard"] = true
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate(ctx)
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion(ctx)
- // FIXME: update periodically
updateSystemStatus()
ctx.Data["SysStatus"] = sysStatus
ctx.Data["SSH"] = setting.SSH
@@ -140,6 +140,12 @@ func Dashboard(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplDashboard)
}
+func SystemStatus(ctx *context.Context) {
+ updateSystemStatus()
+ ctx.Data["SysStatus"] = sysStatus
+ ctx.HTML(http.StatusOK, tplSystemStatus)
+}
+
// DashboardPost run an admin operation
func DashboardPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.AdminDashboardForm)
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 2cf63c646d..7fdd18dfae 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -210,16 +210,16 @@ func parseOAuth2Config(form forms.AuthenticationForm) *oauth2.Source {
func parseSSPIConfig(ctx *context.Context, form forms.AuthenticationForm) (*sspi.Source, error) {
if util.IsEmptyString(form.SSPISeparatorReplacement) {
ctx.Data["Err_SSPISeparatorReplacement"] = true
- return nil, errors.New(ctx.Tr("form.SSPISeparatorReplacement") + ctx.Tr("form.require_error"))
+ return nil, errors.New(ctx.Locale.TrString("form.SSPISeparatorReplacement") + ctx.Locale.TrString("form.require_error"))
}
if separatorAntiPattern.MatchString(form.SSPISeparatorReplacement) {
ctx.Data["Err_SSPISeparatorReplacement"] = true
- return nil, errors.New(ctx.Tr("form.SSPISeparatorReplacement") + ctx.Tr("form.alpha_dash_dot_error"))
+ return nil, errors.New(ctx.Locale.TrString("form.SSPISeparatorReplacement") + ctx.Locale.TrString("form.alpha_dash_dot_error"))
}
if form.SSPIDefaultLanguage != "" && !langCodePattern.MatchString(form.SSPIDefaultLanguage) {
ctx.Data["Err_SSPIDefaultLanguage"] = true
- return nil, errors.New(ctx.Tr("form.lang_select_error"))
+ return nil, errors.New(ctx.Locale.TrString("form.lang_select_error"))
}
return &sspi.Source{
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index c827f2a4f5..47f9201504 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -7,11 +7,11 @@ package admin
import (
"net/http"
"net/url"
+ "strconv"
"strings"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
@@ -24,7 +24,10 @@ import (
"gitea.com/go-chi/session"
)
-const tplConfig base.TplName = "admin/config"
+const (
+ tplConfig base.TplName = "admin/config"
+ tplConfigSettings base.TplName = "admin/config_settings"
+)
// SendTestMail send test mail to confirm mail service is OK
func SendTestMail(ctx *context.Context) {
@@ -98,8 +101,9 @@ func shadowPassword(provider, cfgItem string) string {
// Config show admin config page
func Config(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("admin.config")
+ ctx.Data["Title"] = ctx.Tr("admin.config_summary")
ctx.Data["PageIsAdminConfig"] = true
+ ctx.Data["PageIsAdminConfigSummary"] = true
ctx.Data["CustomConf"] = setting.CustomConf
ctx.Data["AppUrl"] = setting.AppURL
@@ -161,23 +165,70 @@ func Config(ctx *context.Context) {
ctx.Data["Loggers"] = log.GetManager().DumpLoggers()
config.GetDynGetter().InvalidateCache()
- ctx.Data["SystemConfig"] = setting.Config()
prepareDeprecatedWarningsAlert(ctx)
ctx.HTML(http.StatusOK, tplConfig)
}
+func ConfigSettings(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("admin.config_settings")
+ ctx.Data["PageIsAdminConfig"] = true
+ ctx.Data["PageIsAdminConfigSettings"] = true
+ ctx.Data["DefaultOpenWithEditorAppsString"] = setting.DefaultOpenWithEditorApps().ToTextareaString()
+ ctx.HTML(http.StatusOK, tplConfigSettings)
+}
+
func ChangeConfig(ctx *context.Context) {
key := strings.TrimSpace(ctx.FormString("key"))
value := ctx.FormString("value")
cfg := setting.Config()
- allowedKeys := container.SetOf(cfg.Picture.DisableGravatar.DynKey(), cfg.Picture.EnableFederatedAvatar.DynKey())
- if !allowedKeys.Contains(key) {
+
+ marshalBool := func(v string) (string, error) {
+ if b, _ := strconv.ParseBool(v); b {
+ return "true", nil
+ }
+ return "false", nil
+ }
+ marshalOpenWithApps := func(value string) (string, error) {
+ lines := strings.Split(value, "\n")
+ var openWithEditorApps setting.OpenWithEditorAppsType
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if line == "" {
+ continue
+ }
+ displayName, openURL, ok := strings.Cut(line, "=")
+ displayName, openURL = strings.TrimSpace(displayName), strings.TrimSpace(openURL)
+ if !ok || displayName == "" || openURL == "" {
+ continue
+ }
+ openWithEditorApps = append(openWithEditorApps, setting.OpenWithEditorApp{
+ DisplayName: strings.TrimSpace(displayName),
+ OpenURL: strings.TrimSpace(openURL),
+ })
+ }
+ b, err := json.Marshal(openWithEditorApps)
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+ }
+ marshallers := map[string]func(string) (string, error){
+ cfg.Picture.DisableGravatar.DynKey(): marshalBool,
+ cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool,
+ cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps,
+ }
+ marshaller, hasMarshaller := marshallers[key]
+ if !hasMarshaller {
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
return
}
- if err := system_model.SetSettings(ctx, map[string]string{key: value}); err != nil {
- log.Error("set setting failed: %v", err)
+ marshaledValue, err := marshaller(value)
+ if err != nil {
+ ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
+ return
+ }
+ if err = system_model.SetSettings(ctx, map[string]string{key: marshaledValue}); err != nil {
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
return
}
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index af184fa9eb..adb9799c01 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -140,7 +140,7 @@ func NewUserPost(ctx *context.Context) {
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
- IsActive: util.OptionalBoolTrue,
+ IsActive: optional.Some(true),
Visibility: &form.Visibility,
}
diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go
index 3de1f3373d..a30ee0ce54 100644
--- a/routers/web/auth/auth.go
+++ b/routers/web/auth/auth.go
@@ -7,6 +7,7 @@ package auth
import (
"errors"
"fmt"
+ "html/template"
"net/http"
"strings"
@@ -37,12 +38,10 @@ import (
)
const (
- // tplSignIn template for sign in page
- tplSignIn base.TplName = "user/auth/signin"
- // tplSignUp template path for sign up page
- tplSignUp base.TplName = "user/auth/signup"
- // TplActivate template path for activate user
- TplActivate base.TplName = "user/auth/activate"
+ tplSignIn base.TplName = "user/auth/signin" // for sign in page
+ tplSignUp base.TplName = "user/auth/signup" // for sign up page
+ TplActivate base.TplName = "user/auth/activate" // for activate user
+ TplActivatePrompt base.TplName = "user/auth/activate_prompt" // for showing a message for user activation
)
// autoSignIn reads cookie and try to auto-login.
@@ -613,72 +612,83 @@ func handleUserCreated(ctx *context.Context, u *user_model.User, gothUser *goth.
}
}
- // Send confirmation email
- if !u.IsActive && u.ID > 1 {
- if setting.Service.RegisterManualConfirm {
- ctx.Data["ManualActivationOnly"] = true
- ctx.HTML(http.StatusOK, TplActivate)
- return false
- }
+ // for active user or the first (admin) user, we don't need to send confirmation email
+ if u.IsActive || u.ID == 1 {
+ return true
+ }
- mailer.SendActivateAccountMail(ctx.Locale, u)
-
- ctx.Data["IsSendRegisterMail"] = true
- ctx.Data["Email"] = u.Email
- ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
- ctx.HTML(http.StatusOK, TplActivate)
-
- if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
- log.Error("Set cache(MailResendLimit) fail: %v", err)
- }
+ if setting.Service.RegisterManualConfirm {
+ renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.manual_activation_only"))
return false
}
- return true
+ sendActivateEmail(ctx, u)
+ return false
+}
+
+func renderActivationPromptMessage(ctx *context.Context, msg template.HTML) {
+ ctx.Data["ActivationPromptMessage"] = msg
+ ctx.HTML(http.StatusOK, TplActivatePrompt)
+}
+
+func sendActivateEmail(ctx *context.Context, u *user_model.User) {
+ if ctx.Cache.IsExist("MailResendLimit_" + u.LowerName) {
+ renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.resent_limit_prompt"))
+ return
+ }
+
+ if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
+ log.Error("Set cache(MailResendLimit) fail: %v", err)
+ renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.resent_limit_prompt"))
+ return
+ }
+
+ mailer.SendActivateAccountMail(ctx.Locale, u)
+
+ activeCodeLives := timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
+ msgHTML := ctx.Locale.Tr("auth.confirmation_mail_sent_prompt", u.Email, activeCodeLives)
+ renderActivationPromptMessage(ctx, msgHTML)
+}
+
+func renderActivationVerifyPassword(ctx *context.Context, code string) {
+ ctx.Data["ActivationCode"] = code
+ ctx.Data["NeedVerifyLocalPassword"] = true
+ ctx.HTML(http.StatusOK, TplActivate)
}
// Activate render activate user page
func Activate(ctx *context.Context) {
code := ctx.FormString("code")
- if len(code) == 0 {
- ctx.Data["IsActivatePage"] = true
- if ctx.Doer == nil || ctx.Doer.IsActive {
- ctx.NotFound("invalid user", nil)
+ if code == "" {
+ if ctx.Doer == nil {
+ ctx.Redirect(setting.AppSubURL + "/user/login")
+ return
+ } else if ctx.Doer.IsActive {
+ ctx.Redirect(setting.AppSubURL + "/")
return
}
- // Resend confirmation email.
- if setting.Service.RegisterEmailConfirm {
- if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
- ctx.Data["ResendLimited"] = true
- } else {
- ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale)
- mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
- if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
- log.Error("Set cache(MailResendLimit) fail: %v", err)
- }
- }
- } else {
- ctx.Data["ServiceNotEnabled"] = true
+ if setting.MailService == nil || !setting.Service.RegisterEmailConfirm {
+ renderActivationPromptMessage(ctx, ctx.Tr("auth.disable_register_mail"))
+ return
}
- ctx.HTML(http.StatusOK, TplActivate)
+
+ // Resend confirmation email.
+ sendActivateEmail(ctx, ctx.Doer)
return
}
+ // TODO: ctx.Doer/ctx.Data["SignedUser"] could be nil or not the same user as the one being activated
user := user_model.VerifyUserActiveCode(ctx, code)
- // if code is wrong
- if user == nil {
- ctx.Data["IsCodeInvalid"] = true
- ctx.HTML(http.StatusOK, TplActivate)
+ if user == nil { // if code is wrong
+ renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.invalid_code"))
return
}
// if account is local account, verify password
if user.LoginSource == 0 {
- ctx.Data["Code"] = code
- ctx.Data["NeedsPassword"] = true
- ctx.HTML(http.StatusOK, TplActivate)
+ renderActivationVerifyPassword(ctx, code)
return
}
@@ -688,31 +698,28 @@ func Activate(ctx *context.Context) {
// ActivatePost handles account activation with password check
func ActivatePost(ctx *context.Context) {
code := ctx.FormString("code")
- if len(code) == 0 {
+ if code == "" || (ctx.Doer != nil && ctx.Doer.IsActive) {
ctx.Redirect(setting.AppSubURL + "/user/activate")
return
}
+ // TODO: ctx.Doer/ctx.Data["SignedUser"] could be nil or not the same user as the one being activated
user := user_model.VerifyUserActiveCode(ctx, code)
- // if code is wrong
- if user == nil {
- ctx.Data["IsCodeInvalid"] = true
- ctx.HTML(http.StatusOK, TplActivate)
+ if user == nil { // if code is wrong
+ renderActivationPromptMessage(ctx, ctx.Locale.Tr("auth.invalid_code"))
return
}
// if account is local account, verify password
if user.LoginSource == 0 {
password := ctx.FormString("password")
- if len(password) == 0 {
- ctx.Data["Code"] = code
- ctx.Data["NeedsPassword"] = true
- ctx.HTML(http.StatusOK, TplActivate)
+ if password == "" {
+ renderActivationVerifyPassword(ctx, code)
return
}
if !user.ValidatePassword(password) {
- ctx.Data["IsPasswordInvalid"] = true
- ctx.HTML(http.StatusOK, TplActivate)
+ ctx.Flash.Error(ctx.Locale.Tr("auth.invalid_password"), true)
+ renderActivationVerifyPassword(ctx, code)
return
}
}
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 07140b6674..33a4ae9192 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"html"
+ "html/template"
"io"
"net/http"
"net/url"
@@ -499,11 +500,11 @@ func AuthorizeOAuth(ctx *context.Context) {
ctx.Data["Scope"] = form.Scope
ctx.Data["Nonce"] = form.Nonce
if user != nil {
- ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`@%s `, html.EscapeString(user.HomeLink()), html.EscapeString(user.Name))
+ ctx.Data["ApplicationCreatorLinkHTML"] = template.HTML(fmt.Sprintf(`@%s `, html.EscapeString(user.HomeLink()), html.EscapeString(user.Name)))
} else {
- ctx.Data["ApplicationCreatorLinkHTML"] = fmt.Sprintf(`%s `, html.EscapeString(setting.AppSubURL+"/"), html.EscapeString(setting.AppName))
+ ctx.Data["ApplicationCreatorLinkHTML"] = template.HTML(fmt.Sprintf(`%s `, html.EscapeString(setting.AppSubURL+"/"), html.EscapeString(setting.AppName)))
}
- ctx.Data["ApplicationRedirectDomainHTML"] = "" + html.EscapeString(form.RedirectURI) + " "
+ ctx.Data["ApplicationRedirectDomainHTML"] = template.HTML("" + html.EscapeString(form.RedirectURI) + " ")
// TODO document SESSION <=> FORM
err = ctx.Session.Set("client_id", app.ClientID)
if err != nil {
@@ -579,16 +580,8 @@ func GrantApplicationOAuth(ctx *context.Context) {
// OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities
func OIDCWellKnown(ctx *context.Context) {
- t, err := ctx.Render.TemplateLookup("user/auth/oidc_wellknown", nil)
- if err != nil {
- ctx.ServerError("unable to find template", err)
- return
- }
- ctx.Resp.Header().Set("Content-Type", "application/json")
ctx.Data["SigningKey"] = oauth2.DefaultSigningKey
- if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
- ctx.ServerError("unable to execute template", err)
- }
+ ctx.JSONTemplate("user/auth/oidc_wellknown")
}
// OIDCKeys generates the JSON Web Key Set
@@ -986,7 +979,7 @@ func SignInOAuthCallback(ctx *context.Context) {
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
- IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm && !setting.Service.RegisterManualConfirm),
+ IsActive: optional.Some(!setting.OAuth2Client.RegisterEmailConfirm && !setting.Service.RegisterManualConfirm),
}
source := authSource.Cfg.(*oauth2.Source)
diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go
index 5af1696a64..1f2d133282 100644
--- a/routers/web/auth/password.go
+++ b/routers/web/auth/password.go
@@ -37,7 +37,7 @@ func ForgotPasswd(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("auth.forgot_password_title")
if setting.MailService == nil {
- log.Warn(ctx.Tr("auth.disable_forgot_password_mail_admin"))
+ log.Warn("no mail service configured")
ctx.Data["IsResetDisable"] = true
ctx.HTML(http.StatusOK, tplForgotPassword)
return
@@ -204,7 +204,7 @@ func ResetPasswdPost(ctx *context.Context) {
Password: optional.Some(ctx.FormString("password")),
MustChangePassword: optional.Some(false),
}
- if err := user_service.UpdateAuth(ctx, ctx.Doer, opts); err != nil {
+ if err := user_service.UpdateAuth(ctx, u, opts); err != nil {
ctx.Data["IsResetForm"] = true
ctx.Data["Err_Password"] = true
switch {
diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go
index 66b01d3680..1e040ed819 100644
--- a/routers/web/feed/convert.go
+++ b/routers/web/feed/convert.go
@@ -6,6 +6,7 @@ package feed
import (
"fmt"
"html"
+ "html/template"
"net/http"
"net/url"
"strconv"
@@ -79,119 +80,120 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
// title
title = act.ActUser.DisplayName() + " "
+ var titleExtra template.HTML
switch act.OpType {
case activities_model.ActionCreateRepo:
- title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.create_repo", act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
link.Href = act.GetRepoAbsoluteLink(ctx)
case activities_model.ActionRenameRepo:
- title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.rename_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
link.Href = act.GetRepoAbsoluteLink(ctx)
case activities_model.ActionCommitRepo:
link.Href = toBranchLink(ctx, act)
if len(act.Content) != 0 {
- title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.commit_repo", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx))
} else {
- title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.create_branch", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx))
}
case activities_model.ActionCreateIssue:
link.Href = toIssueLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.create_issue", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.create_issue", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionCreatePullRequest:
link.Href = toPullLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionTransferRepo:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.transfer_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx))
case activities_model.ActionPushTag:
link.Href = toTagLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetTag(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.push_tag", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetTag(), act.ShortRepoPath(ctx))
case activities_model.ActionCommentIssue:
issueLink := toIssueLink(ctx, act)
if link.Href == "#" {
link.Href = issueLink
}
- title += ctx.TrHTMLEscapeArgs("action.comment_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.comment_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionMergePullRequest:
pullLink := toPullLink(ctx, act)
if link.Href == "#" {
link.Href = pullLink
}
- title += ctx.TrHTMLEscapeArgs("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionAutoMergePullRequest:
pullLink := toPullLink(ctx, act)
if link.Href == "#" {
link.Href = pullLink
}
- title += ctx.TrHTMLEscapeArgs("action.auto_merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.auto_merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionCloseIssue:
issueLink := toIssueLink(ctx, act)
if link.Href == "#" {
link.Href = issueLink
}
- title += ctx.TrHTMLEscapeArgs("action.close_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.close_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionReopenIssue:
issueLink := toIssueLink(ctx, act)
if link.Href == "#" {
link.Href = issueLink
}
- title += ctx.TrHTMLEscapeArgs("action.reopen_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.reopen_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionClosePullRequest:
pullLink := toPullLink(ctx, act)
if link.Href == "#" {
link.Href = pullLink
}
- title += ctx.TrHTMLEscapeArgs("action.close_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.close_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionReopenPullRequest:
pullLink := toPullLink(ctx, act)
if link.Href == "#" {
link.Href = pullLink
}
- title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionDeleteTag:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoAbsoluteLink(ctx), act.GetTag(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.delete_tag", act.GetRepoAbsoluteLink(ctx), act.GetTag(), act.ShortRepoPath(ctx))
case activities_model.ActionDeleteBranch:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoAbsoluteLink(ctx), html.EscapeString(act.GetBranch()), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.delete_branch", act.GetRepoAbsoluteLink(ctx), html.EscapeString(act.GetBranch()), act.ShortRepoPath(ctx))
case activities_model.ActionMirrorSyncPush:
srcLink := toSrcLink(ctx, act)
if link.Href == "#" {
link.Href = srcLink
}
- title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.mirror_sync_push", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx))
case activities_model.ActionMirrorSyncCreate:
srcLink := toSrcLink(ctx, act)
if link.Href == "#" {
link.Href = srcLink
}
- title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.mirror_sync_create", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx))
case activities_model.ActionMirrorSyncDelete:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoAbsoluteLink(ctx), act.GetBranch(), act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.mirror_sync_delete", act.GetRepoAbsoluteLink(ctx), act.GetBranch(), act.ShortRepoPath(ctx))
case activities_model.ActionApprovePullRequest:
pullLink := toPullLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionRejectPullRequest:
pullLink := toPullLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.reject_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.reject_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionCommentPull:
pullLink := toPullLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.comment_pull", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.comment_pull", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx))
case activities_model.ActionPublishRelease:
releaseLink := toReleaseLink(ctx, act)
if link.Href == "#" {
link.Href = releaseLink
}
- title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoAbsoluteLink(ctx), releaseLink, act.ShortRepoPath(ctx), act.Content)
+ titleExtra = ctx.Locale.Tr("action.publish_release", act.GetRepoAbsoluteLink(ctx), releaseLink, act.ShortRepoPath(ctx), act.Content)
case activities_model.ActionPullReviewDismissed:
pullLink := toPullLink(ctx, act)
- title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx), act.GetIssueInfos()[1])
+ titleExtra = ctx.Locale.Tr("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx), act.GetIssueInfos()[1])
case activities_model.ActionStarRepo:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.starred_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx))
case activities_model.ActionWatchRepo:
link.Href = act.GetRepoAbsoluteLink(ctx)
- title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx))
+ titleExtra = ctx.Locale.Tr("action.watched_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx))
default:
return nil, fmt.Errorf("unknown action type: %v", act.OpType)
}
@@ -233,7 +235,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
case activities_model.ActionCloseIssue, activities_model.ActionReopenIssue, activities_model.ActionClosePullRequest, activities_model.ActionReopenPullRequest:
desc = act.GetIssueTitle(ctx)
case activities_model.ActionPullReviewDismissed:
- desc = ctx.Tr("action.review_dismissed_reason") + "\n\n" + act.GetIssueInfos()[2]
+ desc = ctx.Locale.TrString("action.review_dismissed_reason") + "\n\n" + act.GetIssueInfos()[2]
}
}
if len(content) == 0 {
@@ -241,7 +243,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio
}
items = append(items, &feeds.Item{
- Title: title,
+ Title: template.HTMLEscapeString(title) + string(titleExtra),
Link: link,
Description: desc,
IsPermaLink: "false",
diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go
index 04f84c0c8d..3feca68d61 100644
--- a/routers/web/feed/profile.go
+++ b/routers/web/feed/profile.go
@@ -56,7 +56,7 @@ func showUserFeed(ctx *context.Context, formatType string) {
}
feed := &feeds.Feed{
- Title: ctx.Tr("home.feed_of", ctx.ContextUser.DisplayName()),
+ Title: ctx.Locale.TrString("home.feed_of", ctx.ContextUser.DisplayName()),
Link: &feeds.Link{Href: ctx.ContextUser.HTMLURL()},
Description: ctxUserDescription,
Created: time.Now(),
diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go
index 57b0c92766..558c03dba7 100644
--- a/routers/web/feed/release.go
+++ b/routers/web/feed/release.go
@@ -28,10 +28,10 @@ func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleas
var link *feeds.Link
if isReleasesOnly {
- title = ctx.Tr("repo.release.releases_for", repo.FullName())
+ title = ctx.Locale.TrString("repo.release.releases_for", repo.FullName())
link = &feeds.Link{Href: repo.HTMLURL() + "/release"}
} else {
- title = ctx.Tr("repo.release.tags_for", repo.FullName())
+ title = ctx.Locale.TrString("repo.release.tags_for", repo.FullName())
link = &feeds.Link{Href: repo.HTMLURL() + "/tags"}
}
diff --git a/routers/web/feed/repo.go b/routers/web/feed/repo.go
index 5fcad26779..51c24510c7 100644
--- a/routers/web/feed/repo.go
+++ b/routers/web/feed/repo.go
@@ -27,7 +27,7 @@ func ShowRepoFeed(ctx *context.Context, repo *repo_model.Repository, formatType
}
feed := &feeds.Feed{
- Title: ctx.Tr("home.feed_of", repo.FullName()),
+ Title: ctx.Locale.TrString("home.feed_of", repo.FullName()),
Link: &feeds.Link{Href: repo.HTMLURL()},
Description: repo.Description,
Created: time.Now(),
diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go
index 54c93763f6..ac5496ce91 100644
--- a/routers/web/misc/misc.go
+++ b/routers/web/misc/misc.go
@@ -15,7 +15,7 @@ import (
)
func SSHInfo(rw http.ResponseWriter, req *http.Request) {
- if !git.SupportProcReceive {
+ if !git.DefaultFeatures.SupportProcReceive {
rw.WriteHeader(http.StatusNotFound)
return
}
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index 8bf02b2c42..36f543dc45 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -11,7 +11,6 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
- user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
@@ -46,17 +45,6 @@ func Home(ctx *context.Context) {
ctx.Data["PageIsUserProfile"] = true
ctx.Data["Title"] = org.DisplayName()
- if len(org.Description) != 0 {
- desc, err := markdown.RenderString(&markup.RenderContext{
- Ctx: ctx,
- Metas: map[string]string{"mode": "document"},
- }, org.Description)
- if err != nil {
- ctx.ServerError("RenderString", err)
- return
- }
- ctx.Data["RenderedDescription"] = desc
- }
var orderBy db.SearchOrderBy
ctx.Data["SortType"] = ctx.FormString("sort")
@@ -131,18 +119,12 @@ func Home(ctx *context.Context) {
return
}
- var isFollowing bool
- if ctx.Doer != nil {
- isFollowing = user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
- }
-
ctx.Data["Repos"] = repos
ctx.Data["Total"] = count
ctx.Data["Members"] = members
ctx.Data["Teams"] = ctx.Org.Teams
ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull
ctx.Data["PageIsViewRepositories"] = true
- ctx.Data["IsFollowing"] = isFollowing
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
diff --git a/routers/web/org/org.go b/routers/web/org/org.go
index 52f8df8a1c..1e4544730e 100644
--- a/routers/web/org/org.go
+++ b/routers/web/org/org.go
@@ -29,7 +29,7 @@ func Create(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("new_org")
ctx.Data["DefaultOrgVisibilityMode"] = setting.Service.DefaultOrgVisibilityMode
if !ctx.Doer.CanCreateOrganization() {
- ctx.ServerError("Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
+ ctx.ServerError("Not allowed", errors.New(ctx.Locale.TrString("org.form.create_org_not_allowed")))
return
}
ctx.HTML(http.StatusOK, tplCreateOrg)
@@ -41,7 +41,7 @@ func CreatePost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("new_org")
if !ctx.Doer.CanCreateOrganization() {
- ctx.ServerError("Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
+ ctx.ServerError("Not allowed", errors.New(ctx.Locale.TrString("org.form.create_org_not_allowed")))
return
}
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 03798a712c..f062127d24 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -353,7 +353,7 @@ func ViewProject(ctx *context.Context) {
}
if boards[0].ID == 0 {
- boards[0].Title = ctx.Tr("repo.projects.type.uncategorized")
+ boards[0].Title = ctx.Locale.TrString("repo.projects.type.uncategorized")
}
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
@@ -377,16 +377,16 @@ func ViewProject(ctx *context.Context) {
linkedPrsMap := make(map[int64][]*issues_model.Issue)
for _, issuesList := range issuesMap {
for _, issue := range issuesList {
- var referencedIds []int64
+ var referencedIDs []int64
for _, comment := range issue.Comments {
if comment.RefIssueID != 0 && comment.RefIsPull {
- referencedIds = append(referencedIds, comment.RefIssueID)
+ referencedIDs = append(referencedIDs, comment.RefIssueID)
}
}
- if len(referencedIds) > 0 {
+ if len(referencedIDs) > 0 {
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{
- IssueIDs: referencedIds,
+ IssueIDs: referencedIDs,
IsPull: util.OptionalBoolTrue,
}); err == nil {
linkedPrsMap[issue.ID] = linkedPrs
@@ -679,7 +679,7 @@ func MoveIssues(ctx *context.Context) {
board = &project_model.Board{
ID: 0,
ProjectID: project.ID,
- Title: ctx.Tr("repo.projects.type.uncategorized"),
+ Title: ctx.Locale.TrString("repo.projects.type.uncategorized"),
}
} else {
board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
diff --git a/routers/web/passkey.go b/routers/web/passkey.go
new file mode 100644
index 0000000000..95874dfc48
--- /dev/null
+++ b/routers/web/passkey.go
@@ -0,0 +1,24 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package web
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+type passkeyEndpointsType struct {
+ Enroll string `json:"enroll"`
+ Manage string `json:"manage"`
+}
+
+func passkeyEndpoints(ctx *context.Context) {
+ url := setting.AppURL + "user/settings/security"
+ ctx.JSON(http.StatusOK, passkeyEndpointsType{
+ Enroll: url,
+ Manage: url,
+ })
+}
diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go
index fe528a483b..19aca26711 100644
--- a/routers/web/repo/actions/actions.go
+++ b/routers/web/repo/actions/actions.go
@@ -61,17 +61,17 @@ func List(ctx *context.Context) {
var workflows []Workflow
if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("IsEmpty", err)
return
} else if !empty {
commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("GetBranchCommit", err)
return
}
entries, err := actions.ListWorkflows(commit)
if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("ListWorkflows", err)
return
}
@@ -95,12 +95,12 @@ func List(ctx *context.Context) {
workflow := Workflow{Entry: *entry}
content, err := actions.GetContentFromEntry(entry)
if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("GetContentFromEntry", err)
return
}
wf, err := model.ReadWorkflow(bytes.NewReader(content))
if err != nil {
- workflow.ErrMsg = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", err.Error())
+ workflow.ErrMsg = ctx.Locale.TrString("actions.runs.invalid_workflow_helper", err.Error())
workflows = append(workflows, workflow)
continue
}
@@ -115,7 +115,7 @@ func List(ctx *context.Context) {
continue
}
if !allRunnerLabels.Contains(ro) {
- workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_online_runner_helper", ro)
+ workflow.ErrMsg = ctx.Locale.TrString("actions.runs.no_matching_online_runner_helper", ro)
break
}
}
@@ -172,7 +172,7 @@ func List(ctx *context.Context) {
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)
if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("FindAndCount", err)
return
}
@@ -181,7 +181,7 @@ func List(ctx *context.Context) {
}
if err := actions_model.RunList(runs).LoadTriggerUser(ctx); err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("LoadTriggerUser", err)
return
}
@@ -189,7 +189,7 @@ func List(ctx *context.Context) {
actors, err := actions_model.GetActors(ctx, ctx.Repo.Repository.ID)
if err != nil {
- ctx.Error(http.StatusInternalServerError, err.Error())
+ ctx.ServerError("GetActors", err)
return
}
ctx.Data["Actors"] = repo.MakeSelfOnTop(ctx.Doer, actors)
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 9cda30d23d..49387362b3 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -57,15 +57,16 @@ type ViewRequest struct {
type ViewResponse struct {
State struct {
Run struct {
- Link string `json:"link"`
- Title string `json:"title"`
- Status string `json:"status"`
- CanCancel bool `json:"canCancel"`
- CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
- CanRerun bool `json:"canRerun"`
- Done bool `json:"done"`
- Jobs []*ViewJob `json:"jobs"`
- Commit ViewCommit `json:"commit"`
+ Link string `json:"link"`
+ Title string `json:"title"`
+ Status string `json:"status"`
+ CanCancel bool `json:"canCancel"`
+ CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
+ CanRerun bool `json:"canRerun"`
+ CanDeleteArtifact bool `json:"canDeleteArtifact"`
+ Done bool `json:"done"`
+ Jobs []*ViewJob `json:"jobs"`
+ Commit ViewCommit `json:"commit"`
} `json:"run"`
CurrentJob struct {
Title string `json:"title"`
@@ -146,6 +147,7 @@ func ViewPost(ctx *context_module.Context) {
resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.CanRerun = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
+ resp.State.Run.CanDeleteArtifact = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.Done = run.Status.IsDone()
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
resp.State.Run.Status = run.Status.String()
@@ -168,8 +170,8 @@ func ViewPost(ctx *context_module.Context) {
Link: run.RefLink(),
}
resp.State.Run.Commit = ViewCommit{
- LocaleCommit: ctx.Tr("actions.runs.commit"),
- LocalePushedBy: ctx.Tr("actions.runs.pushed_by"),
+ LocaleCommit: ctx.Locale.TrString("actions.runs.commit"),
+ LocalePushedBy: ctx.Locale.TrString("actions.runs.pushed_by"),
ShortSha: base.ShortSha(run.CommitSHA),
Link: fmt.Sprintf("%s/commit/%s", run.Repo.Link(), run.CommitSHA),
Pusher: pusher,
@@ -194,7 +196,7 @@ func ViewPost(ctx *context_module.Context) {
resp.State.CurrentJob.Title = current.Name
resp.State.CurrentJob.Detail = current.Status.LocaleString(ctx.Locale)
if run.NeedApproval {
- resp.State.CurrentJob.Detail = ctx.Locale.Tr("actions.need_approval_desc")
+ resp.State.CurrentJob.Detail = ctx.Locale.TrString("actions.need_approval_desc")
}
resp.State.CurrentJob.Steps = make([]*ViewJobStep, 0) // marshal to '[]' instead fo 'null' in json
resp.Logs.StepsLog = make([]*ViewStepLog, 0) // marshal to '[]' instead fo 'null' in json
@@ -535,6 +537,29 @@ func ArtifactsView(ctx *context_module.Context) {
ctx.JSON(http.StatusOK, artifactsResponse)
}
+func ArtifactsDeleteView(ctx *context_module.Context) {
+ if !ctx.Repo.CanWrite(unit.TypeActions) {
+ ctx.Error(http.StatusForbidden, "no permission")
+ return
+ }
+
+ runIndex := ctx.ParamsInt64("run")
+ artifactName := ctx.Params("artifact_name")
+
+ run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
+ if err != nil {
+ ctx.NotFoundOrServerError("GetRunByIndex", func(err error) bool {
+ return errors.Is(err, util.ErrNotExist)
+ }, err)
+ return
+ }
+ if err = actions_model.SetArtifactNeedDelete(ctx, run.ID, artifactName); err != nil {
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+ ctx.JSON(http.StatusOK, struct{}{})
+}
+
func ArtifactsDownloadView(ctx *context_module.Context) {
runIndex := ctx.ParamsInt64("run")
artifactName := ctx.Params("artifact_name")
@@ -562,6 +587,14 @@ func ArtifactsDownloadView(ctx *context_module.Context) {
return
}
+ // if artifacts status is not uploaded-confirmed, treat it as not found
+ for _, art := range artifacts {
+ if art.Status != int64(actions_model.ArtifactStatusUploadConfirmed) {
+ ctx.Error(http.StatusNotFound, "artifact not found")
+ return
+ }
+ }
+
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.zip; filename*=UTF-8''%s.zip", url.PathEscape(artifactName), artifactName))
writer := zip.NewWriter(ctx.Resp)
diff --git a/routers/web/repo/activity.go b/routers/web/repo/activity.go
index 3d030edaca..af99c4ed98 100644
--- a/routers/web/repo/activity.go
+++ b/routers/web/repo/activity.go
@@ -22,6 +22,8 @@ func Activity(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.activity")
ctx.Data["PageIsActivity"] = true
+ ctx.Data["PageIsPulse"] = true
+
ctx.Data["Period"] = ctx.Params("period")
timeUntil := time.Now()
diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go
index d414779a14..7602b30d2b 100644
--- a/routers/web/repo/blame.go
+++ b/routers/web/repo/blame.go
@@ -20,6 +20,7 @@ import (
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
+ files_service "code.gitea.io/gitea/services/repository/files"
)
type blameRow struct {
@@ -131,11 +132,8 @@ type blameResult struct {
}
func performBlame(ctx *context.Context, repoPath string, commit *git.Commit, file string, bypassBlameIgnore bool) (*blameResult, error) {
- objectFormat, err := ctx.Repo.GitRepo.GetObjectFormat()
- if err != nil {
- ctx.NotFound("CreateBlameReader", err)
- return nil, err
- }
+ objectFormat := ctx.Repo.GetObjectFormat()
+
blameReader, err := git.CreateBlameReader(ctx, objectFormat, repoPath, commit, file, bypassBlameIgnore)
if err != nil {
return nil, err
@@ -247,31 +245,11 @@ func processBlameParts(ctx *context.Context, blameParts []*git.BlamePart) map[st
func renderBlame(ctx *context.Context, blameParts []*git.BlamePart, commitNames map[string]*user_model.UserCommit) {
repoLink := ctx.Repo.RepoLink
- language := ""
-
- indexFilename, worktree, deleteTemporaryFile, err := ctx.Repo.GitRepo.ReadTreeToTemporaryIndex(ctx.Repo.CommitID)
- if err == nil {
- defer deleteTemporaryFile()
-
- filename2attribute2info, err := ctx.Repo.GitRepo.CheckAttribute(git.CheckAttributeOpts{
- CachedOnly: true,
- Attributes: []string{"linguist-language", "gitlab-language"},
- Filenames: []string{ctx.Repo.TreePath},
- IndexFile: indexFilename,
- WorkTree: worktree,
- })
- if err != nil {
- log.Error("Unable to load attributes for %-v:%s. Error: %v", ctx.Repo.Repository, ctx.Repo.TreePath, err)
- }
-
- language = filename2attribute2info[ctx.Repo.TreePath]["linguist-language"]
- if language == "" || language == "unspecified" {
- language = filename2attribute2info[ctx.Repo.TreePath]["gitlab-language"]
- }
- if language == "unspecified" {
- language = ""
- }
+ language, err := files_service.TryGetContentLanguage(ctx.Repo.GitRepo, ctx.Repo.CommitID, ctx.Repo.TreePath)
+ if err != nil {
+ log.Error("Unable to get file language for %-v:%s. Error: %v", ctx.Repo.Repository, ctx.Repo.TreePath, err)
}
+
lines := make([]string, 0)
rows := make([]*blameRow, 0)
escapeStatus := &charset.EscapeStatus{}
diff --git a/routers/web/repo/cherry_pick.go b/routers/web/repo/cherry_pick.go
index 25dd881219..8de54d569f 100644
--- a/routers/web/repo/cherry_pick.go
+++ b/routers/web/repo/cherry_pick.go
@@ -104,9 +104,9 @@ func CherryPickPost(ctx *context.Context) {
message := strings.TrimSpace(form.CommitSummary)
if message == "" {
if form.Revert {
- message = ctx.Tr("repo.commit.revert-header", sha)
+ message = ctx.Locale.TrString("repo.commit.revert-header", sha)
} else {
- message = ctx.Tr("repo.commit.cherry-pick-header", sha)
+ message = ctx.Locale.TrString("repo.commit.cherry-pick-header", sha)
}
}
diff --git a/routers/web/repo/code_frequency.go b/routers/web/repo/code_frequency.go
new file mode 100644
index 0000000000..48ade655b7
--- /dev/null
+++ b/routers/web/repo/code_frequency.go
@@ -0,0 +1,41 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+ "errors"
+ "net/http"
+
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ contributors_service "code.gitea.io/gitea/services/repository"
+)
+
+const (
+ tplCodeFrequency base.TplName = "repo/activity"
+)
+
+// CodeFrequency renders the page to show repository code frequency
+func CodeFrequency(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("repo.activity.navbar.code_frequency")
+
+ ctx.Data["PageIsActivity"] = true
+ ctx.Data["PageIsCodeFrequency"] = true
+ ctx.PageData["repoLink"] = ctx.Repo.RepoLink
+
+ ctx.HTML(http.StatusOK, tplCodeFrequency)
+}
+
+// CodeFrequencyData returns JSON of code frequency data
+func CodeFrequencyData(ctx *context.Context) {
+ if contributorStats, err := contributors_service.GetContributorStats(ctx, ctx.Cache, ctx.Repo.Repository, ctx.Repo.CommitID); err != nil {
+ if errors.Is(err, contributors_service.ErrAwaitGeneration) {
+ ctx.Status(http.StatusAccepted)
+ return
+ }
+ ctx.ServerError("GetCodeFrequencyData", err)
+ } else {
+ ctx.JSON(http.StatusOK, contributorStats["total"].Weeks)
+ }
+}
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index a3593815b8..535487d5fd 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -31,6 +31,7 @@ import (
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/typesniffer"
@@ -126,7 +127,7 @@ func setCsvCompareContext(ctx *context.Context) {
return CsvDiffResult{nil, ""}
}
- errTooLarge := errors.New(ctx.Locale.Tr("repo.error.csv.too_large"))
+ errTooLarge := errors.New(ctx.Locale.TrString("repo.error.csv.too_large"))
csvReaderFromCommit := func(ctx *markup.RenderContext, blob *git.Blob) (*csv.Reader, io.Closer, error) {
if blob == nil {
@@ -311,14 +312,14 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
baseIsCommit := ctx.Repo.GitRepo.IsCommitExist(ci.BaseBranch)
baseIsBranch := ctx.Repo.GitRepo.IsBranchExist(ci.BaseBranch)
baseIsTag := ctx.Repo.GitRepo.IsTagExist(ci.BaseBranch)
- objectFormat, _ := ctx.Repo.GitRepo.GetObjectFormat()
+
if !baseIsCommit && !baseIsBranch && !baseIsTag {
// Check if baseBranch is short sha commit hash
if baseCommit, _ := ctx.Repo.GitRepo.GetCommit(ci.BaseBranch); baseCommit != nil {
ci.BaseBranch = baseCommit.ID.String()
ctx.Data["BaseBranch"] = ci.BaseBranch
baseIsCommit = true
- } else if ci.BaseBranch == objectFormat.EmptyObjectID().String() {
+ } else if ci.BaseBranch == ctx.Repo.GetObjectFormat().EmptyObjectID().String() {
if isSameRepo {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
} else {
@@ -700,7 +701,7 @@ func getBranchesAndTagsForRepo(ctx gocontext.Context, repo *repo_model.Repositor
ListOptions: db.ListOptions{
ListAll: true,
},
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
})
if err != nil {
return nil, nil, err
@@ -757,7 +758,7 @@ func CompareDiff(ctx *context.Context) {
ListOptions: db.ListOptions{
ListAll: true,
},
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
})
if err != nil {
ctx.ServerError("GetBranches", err)
diff --git a/routers/web/repo/contributors.go b/routers/web/repo/contributors.go
new file mode 100644
index 0000000000..bcfef7580a
--- /dev/null
+++ b/routers/web/repo/contributors.go
@@ -0,0 +1,44 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+ "errors"
+ "net/http"
+
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ contributors_service "code.gitea.io/gitea/services/repository"
+)
+
+const (
+ tplContributors base.TplName = "repo/activity"
+)
+
+// Contributors render the page to show repository contributors graph
+func Contributors(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("repo.activity.navbar.contributors")
+
+ ctx.Data["PageIsActivity"] = true
+ ctx.Data["PageIsContributors"] = true
+
+ ctx.PageData["contributionType"] = "commits"
+
+ ctx.PageData["repoLink"] = ctx.Repo.RepoLink
+
+ ctx.HTML(http.StatusOK, tplContributors)
+}
+
+// ContributorsData renders JSON of contributors along with their weekly commit statistics
+func ContributorsData(ctx *context.Context) {
+ if contributorStats, err := contributors_service.GetContributorStats(ctx, ctx.Cache, ctx.Repo.Repository, ctx.Repo.CommitID); err != nil {
+ if errors.Is(err, contributors_service.ErrAwaitGeneration) {
+ ctx.Status(http.StatusAccepted)
+ return
+ }
+ ctx.ServerError("GetContributorStats", err)
+ } else {
+ ctx.JSON(http.StatusOK, contributorStats)
+ }
+}
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index 85d40e7820..28644fbe3d 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -161,9 +161,6 @@ func editFile(ctx *context.Context, isNewFile bool) {
}
d, _ := io.ReadAll(dataRc)
- if err := dataRc.Close(); err != nil {
- log.Error("Error whilst closing blob data: %v", err)
- }
buf = append(buf, d...)
if content, err := charset.ToUTF8(buf, charset.ConvertOpts{KeepBOM: true}); err != nil {
@@ -262,9 +259,9 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
message := strings.TrimSpace(form.CommitSummary)
if len(message) == 0 {
if isNewFile {
- message = ctx.Tr("repo.editor.add", form.TreePath)
+ message = ctx.Locale.TrString("repo.editor.add", form.TreePath)
} else {
- message = ctx.Tr("repo.editor.update", form.TreePath)
+ message = ctx.Locale.TrString("repo.editor.update", form.TreePath)
}
}
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
@@ -415,7 +412,7 @@ func DiffPreviewPost(ctx *context.Context) {
}
if diff.NumFiles == 0 {
- ctx.PlainText(http.StatusOK, ctx.Tr("repo.editor.no_changes_to_show"))
+ ctx.PlainText(http.StatusOK, ctx.Locale.TrString("repo.editor.no_changes_to_show"))
return
}
ctx.Data["File"] = diff.Files[0]
@@ -482,7 +479,7 @@ func DeleteFilePost(ctx *context.Context) {
message := strings.TrimSpace(form.CommitSummary)
if len(message) == 0 {
- message = ctx.Tr("repo.editor.delete", ctx.Repo.TreePath)
+ message = ctx.Locale.TrString("repo.editor.delete", ctx.Repo.TreePath)
}
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
if len(form.CommitMessage) > 0 {
@@ -691,7 +688,7 @@ func UploadFilePost(ctx *context.Context) {
if dir == "" {
dir = "/"
}
- message = ctx.Tr("repo.editor.upload_files_to_dir", dir)
+ message = ctx.Locale.TrString("repo.editor.upload_files_to_dir", dir)
}
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go
index f52abbfb02..27c7f4961d 100644
--- a/routers/web/repo/githttp.go
+++ b/routers/web/repo/githttp.go
@@ -183,7 +183,7 @@ func httpBase(ctx *context.Context) *serviceHandler {
if repoExist {
// Because of special ref "refs/for" .. , need delay write permission check
- if git.SupportProcReceive {
+ if git.DefaultFeatures.SupportProcReceive {
accessMode = perm.AccessModeRead
}
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index c8c9924a9e..46d48c4638 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -32,6 +32,7 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
issue_template "code.gitea.io/gitea/modules/issue/template"
@@ -711,16 +712,12 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
tmp.ItemID = -review.ReviewerTeamID
}
- if ctx.Repo.IsAdmin() {
- // Admin can dismiss or re-request any review requests
+ if canChooseReviewer {
+ // Users who can choose reviewers can also remove review requests
tmp.CanChange = true
} else if ctx.Doer != nil && ctx.Doer.ID == review.ReviewerID && review.Type == issues_model.ReviewTypeRequest {
// A user can refuse review requests
tmp.CanChange = true
- } else if (canChooseReviewer || (ctx.Doer != nil && ctx.Doer.ID == issue.PosterID)) && review.Type != issues_model.ReviewTypeRequest &&
- ctx.Doer.ID != review.ReviewerID {
- // The poster of the PR, a manager, or official reviewers can re-request review from other reviewers
- tmp.CanChange = true
}
pullReviews = append(pullReviews, tmp)
@@ -993,17 +990,17 @@ func NewIssue(ctx *context.Context) {
}
ctx.Data["Tags"] = tags
- _, templateErrs := issue_service.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
+ ret := issue_service.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
templateLoaded, errs := setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
for k, v := range errs {
- templateErrs[k] = v
+ ret.TemplateErrors[k] = v
}
if ctx.Written() {
return
}
- if len(templateErrs) > 0 {
- ctx.Flash.Warning(renderErrorOfTemplates(ctx, templateErrs), true)
+ if len(ret.TemplateErrors) > 0 {
+ ctx.Flash.Warning(renderErrorOfTemplates(ctx, ret.TemplateErrors), true)
}
ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWrite(unit.TypeIssues)
@@ -1036,7 +1033,7 @@ func renderErrorOfTemplates(ctx *context.Context, errs map[string]error) string
})
if err != nil {
log.Debug("render flash error: %v", err)
- flashError = ctx.Tr("repo.issues.choose.ignore_invalid_templates")
+ flashError = ctx.Locale.TrString("repo.issues.choose.ignore_invalid_templates")
}
return flashError
}
@@ -1046,11 +1043,11 @@ func NewIssueChooseTemplate(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
ctx.Data["PageIsIssueList"] = true
- issueTemplates, errs := issue_service.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
- ctx.Data["IssueTemplates"] = issueTemplates
+ ret := issue_service.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
+ ctx.Data["IssueTemplates"] = ret.IssueTemplates
- if len(errs) > 0 {
- ctx.Flash.Warning(renderErrorOfTemplates(ctx, errs), true)
+ if len(ret.TemplateErrors) > 0 {
+ ctx.Flash.Warning(renderErrorOfTemplates(ctx, ret.TemplateErrors), true)
}
if !issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo) {
@@ -1439,7 +1436,7 @@ func ViewIssue(ctx *context.Context) {
return
}
- ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, issue.Title)
+ ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, emoji.ReplaceAliases(issue.Title))
iw := new(issues_model.IssueWatch)
if ctx.Doer != nil {
@@ -1525,18 +1522,9 @@ func ViewIssue(ctx *context.Context) {
}
if issue.IsPull {
- canChooseReviewer := ctx.Repo.CanWrite(unit.TypePullRequests)
+ canChooseReviewer := false
if ctx.Doer != nil && ctx.IsSigned {
- if !canChooseReviewer {
- canChooseReviewer = ctx.Doer.ID == issue.PosterID
- }
- if !canChooseReviewer {
- canChooseReviewer, err = issues_model.IsOfficialReviewer(ctx, issue, ctx.Doer)
- if err != nil {
- ctx.ServerError("IsOfficialReviewer", err)
- return
- }
- }
+ canChooseReviewer = issue_service.CanDoerChangeReviewRequests(ctx, ctx.Doer, repo, issue)
}
RetrieveRepoReviewers(ctx, repo, issue, canChooseReviewer)
@@ -1655,7 +1643,7 @@ func ViewIssue(ctx *context.Context) {
}
ghostMilestone := &issues_model.Milestone{
ID: -1,
- Name: ctx.Tr("repo.issues.deleted_milestone"),
+ Name: ctx.Locale.TrString("repo.issues.deleted_milestone"),
}
if comment.OldMilestoneID > 0 && comment.OldMilestone == nil {
comment.OldMilestone = ghostMilestone
@@ -1672,7 +1660,7 @@ func ViewIssue(ctx *context.Context) {
ghostProject := &project_model.Project{
ID: -1,
- Title: ctx.Tr("repo.issues.deleted_project"),
+ Title: ctx.Locale.TrString("repo.issues.deleted_project"),
}
if comment.OldProjectID > 0 && comment.OldProject == nil {
@@ -1730,6 +1718,10 @@ func ViewIssue(ctx *context.Context) {
for _, codeComments := range comment.Review.CodeComments {
for _, lineComments := range codeComments {
for _, c := range lineComments {
+ if err := c.LoadAttachments(ctx); err != nil {
+ ctx.ServerError("LoadAttachments", err)
+ return
+ }
// Check tag.
role, ok = marked[c.PosterID]
if ok {
@@ -1862,6 +1854,8 @@ func ViewIssue(ctx *context.Context) {
mergeStyle = repo_model.MergeStyleRebaseMerge
} else if prConfig.AllowSquash {
mergeStyle = repo_model.MergeStyleSquash
+ } else if prConfig.AllowFastForwardOnly {
+ mergeStyle = repo_model.MergeStyleFastForwardOnly
} else if prConfig.AllowManualMerge {
mergeStyle = repo_model.MergeStyleManuallyMerged
}
diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go
index 0f376db145..0939af487c 100644
--- a/routers/web/repo/issue_content_history.go
+++ b/routers/web/repo/issue_content_history.go
@@ -56,12 +56,12 @@ func GetContentHistoryList(ctx *context.Context) {
for _, item := range items {
var actionText string
if item.IsDeleted {
- actionTextDeleted := ctx.Locale.Tr("repo.issues.content_history.deleted")
+ actionTextDeleted := ctx.Locale.TrString("repo.issues.content_history.deleted")
actionText = "" + actionTextDeleted + " "
} else if item.IsFirstCreated {
- actionText = ctx.Locale.Tr("repo.issues.content_history.created")
+ actionText = ctx.Locale.TrString("repo.issues.content_history.created")
} else {
- actionText = ctx.Locale.Tr("repo.issues.content_history.edited")
+ actionText = ctx.Locale.TrString("repo.issues.content_history.edited")
}
username := item.UserName
diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go
index e0d49e44e1..742f12114d 100644
--- a/routers/web/repo/issue_label_test.go
+++ b/routers/web/repo/issue_label_test.go
@@ -123,7 +123,7 @@ func TestDeleteLabel(t *testing.T) {
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
unittest.AssertNotExistsBean(t, &issues_model.Label{ID: 2})
unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{LabelID: 2})
- assert.Equal(t, ctx.Tr("repo.issues.label_deletion_success"), ctx.Flash.SuccessMsg)
+ assert.EqualValues(t, ctx.Tr("repo.issues.label_deletion_success"), ctx.Flash.SuccessMsg)
}
func TestUpdateIssueLabel_Clear(t *testing.T) {
diff --git a/routers/web/repo/middlewares.go b/routers/web/repo/middlewares.go
index ee49649654..d70a53030e 100644
--- a/routers/web/repo/middlewares.go
+++ b/routers/web/repo/middlewares.go
@@ -98,23 +98,15 @@ func SetWhitespaceBehavior(ctx *context.Context) {
// SetShowOutdatedComments set the show outdated comments option as context variable
func SetShowOutdatedComments(ctx *context.Context) {
showOutdatedCommentsValue := ctx.FormString("show-outdated")
- // var showOutdatedCommentsValue string
-
if showOutdatedCommentsValue != "true" && showOutdatedCommentsValue != "false" {
// invalid or no value for this form string -> use default or stored user setting
+ showOutdatedCommentsValue = "true"
if ctx.IsSigned {
- showOutdatedCommentsValue, _ = user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, "false")
- } else {
- // not logged in user -> use the default value
- showOutdatedCommentsValue = "false"
+ showOutdatedCommentsValue, _ = user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, showOutdatedCommentsValue)
}
- } else {
+ } else if ctx.IsSigned {
// valid value -> update user setting if user is logged in
- if ctx.IsSigned {
- _ = user_model.SetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, showOutdatedCommentsValue)
- }
+ _ = user_model.SetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyShowOutdatedComments, showOutdatedCommentsValue)
}
-
- showOutdatedComments, _ := strconv.ParseBool(showOutdatedCommentsValue)
- ctx.Data["ShowOutdatedComments"] = showOutdatedComments
+ ctx.Data["ShowOutdatedComments"], _ = strconv.ParseBool(showOutdatedCommentsValue)
}
diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go
index 19db2abd68..400748b963 100644
--- a/routers/web/repo/milestone.go
+++ b/routers/web/repo/milestone.go
@@ -294,8 +294,8 @@ func MilestoneIssuesAndPulls(ctx *context.Context) {
issues(ctx, milestoneID, projectID, util.OptionalBoolNone)
- ret, _ := issue.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
- ctx.Data["NewIssueChooseTemplate"] = len(ret) > 0
+ ret := issue.ParseTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo)
+ ctx.Data["NewIssueChooseTemplate"] = len(ret.IssueTemplates) > 0
ctx.Data["CanWriteIssues"] = ctx.Repo.CanWriteIssuesOrPulls(false)
ctx.Data["CanWritePulls"] = ctx.Repo.CanWriteIssuesOrPulls(true)
diff --git a/routers/web/repo/patch.go b/routers/web/repo/patch.go
index c04435cf1b..00bd45aaec 100644
--- a/routers/web/repo/patch.go
+++ b/routers/web/repo/patch.go
@@ -79,7 +79,7 @@ func NewDiffPatchPost(ctx *context.Context) {
// `message` will be both the summary and message combined
message := strings.TrimSpace(form.CommitSummary)
if len(message) == 0 {
- message = ctx.Tr("repo.editor.patch")
+ message = ctx.Locale.TrString("repo.editor.patch")
}
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 4908bb796d..cc0127e7e1 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -315,7 +315,7 @@ func ViewProject(ctx *context.Context) {
}
if boards[0].ID == 0 {
- boards[0].Title = ctx.Tr("repo.projects.type.uncategorized")
+ boards[0].Title = ctx.Locale.TrString("repo.projects.type.uncategorized")
}
issuesMap, err := issues_model.LoadIssuesFromBoardList(ctx, boards)
@@ -339,16 +339,16 @@ func ViewProject(ctx *context.Context) {
linkedPrsMap := make(map[int64][]*issues_model.Issue)
for _, issuesList := range issuesMap {
for _, issue := range issuesList {
- var referencedIds []int64
+ var referencedIDs []int64
for _, comment := range issue.Comments {
if comment.RefIssueID != 0 && comment.RefIsPull {
- referencedIds = append(referencedIds, comment.RefIssueID)
+ referencedIDs = append(referencedIDs, comment.RefIssueID)
}
}
- if len(referencedIds) > 0 {
+ if len(referencedIDs) > 0 {
if linkedPrs, err := issues_model.Issues(ctx, &issues_model.IssuesOptions{
- IssueIDs: referencedIds,
+ IssueIDs: referencedIDs,
IsPull: util.OptionalBoolTrue,
}); err == nil {
linkedPrsMap[issue.ID] = linkedPrs
@@ -633,7 +633,7 @@ func MoveIssues(ctx *context.Context) {
board = &project_model.Board{
ID: 0,
ProjectID: project.ID,
- Title: ctx.Tr("repo.projects.type.uncategorized"),
+ Title: ctx.Locale.TrString("repo.projects.type.uncategorized"),
}
} else {
board, err = project_model.GetBoard(ctx, ctx.ParamsInt64(":boardID"))
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index b265cf4754..af626dad30 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -28,10 +28,12 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
issue_template "code.gitea.io/gitea/modules/issue/template"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/upload"
@@ -186,7 +188,7 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
ListOptions: db.ListOptions{
ListAll: true,
},
- IsDeletedBranch: util.OptionalBoolFalse,
+ IsDeletedBranch: optional.Some(false),
// Add it as the first option
ExcludeBranchNames: []string{ctx.Repo.Repository.DefaultBranch},
})
@@ -334,7 +336,7 @@ func getPullInfo(ctx *context.Context) (issue *issues_model.Issue, ok bool) {
ctx.ServerError("LoadRepo", err)
return nil, false
}
- ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, issue.Title)
+ ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, emoji.ReplaceAliases(issue.Title))
ctx.Data["Issue"] = issue
if !issue.IsPull {
@@ -652,6 +654,24 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
}
if pb != nil && pb.EnableStatusCheck {
+
+ var missingRequiredChecks []string
+ for _, requiredContext := range pb.StatusCheckContexts {
+ contextFound := false
+ matchesRequiredContext := createRequiredContextMatcher(requiredContext)
+ for _, presentStatus := range commitStatuses {
+ if matchesRequiredContext(presentStatus.Context) {
+ contextFound = true
+ break
+ }
+ }
+
+ if !contextFound {
+ missingRequiredChecks = append(missingRequiredChecks, requiredContext)
+ }
+ }
+ ctx.Data["MissingRequiredChecks"] = missingRequiredChecks
+
ctx.Data["is_context_required"] = func(context string) bool {
for _, c := range pb.StatusCheckContexts {
if c == context {
@@ -720,10 +740,22 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
return compareInfo
}
+func createRequiredContextMatcher(requiredContext string) func(string) bool {
+ if gp, err := glob.Compile(requiredContext); err == nil {
+ return func(contextToCheck string) bool {
+ return gp.Match(contextToCheck)
+ }
+ }
+
+ return func(contextToCheck string) bool {
+ return requiredContext == contextToCheck
+ }
+}
+
type pullCommitList struct {
Commits []pull_service.CommitInfo `json:"commits"`
LastReviewCommitSha string `json:"last_review_commit_sha"`
- Locale map[string]string `json:"locale"`
+ Locale map[string]any `json:"locale"`
}
// GetPullCommits get all commits for given pull request
@@ -741,7 +773,7 @@ func GetPullCommits(ctx *context.Context) {
}
// Get the needed locale
- resp.Locale = map[string]string{
+ resp.Locale = map[string]any{
"lang": ctx.Locale.Language(),
"show_all_commits": ctx.Tr("repo.pulls.show_all_commits"),
"stats_num_commits": ctx.TrN(len(commits), "repo.activity.git_stats_commit_1", "repo.activity.git_stats_commit_n", len(commits)),
@@ -938,6 +970,19 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
return
}
+ for _, file := range diff.Files {
+ for _, section := range file.Sections {
+ for _, line := range section.Lines {
+ for _, comment := range line.Comments {
+ if err := comment.LoadAttachments(ctx); err != nil {
+ ctx.ServerError("LoadAttachments", err)
+ return
+ }
+ }
+ }
+ }
+ }
+
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
if err != nil {
ctx.ServerError("LoadProtectedBranch", err)
@@ -1253,19 +1298,19 @@ func MergePullRequest(ctx *context.Context) {
return
}
ctx.Flash.Error(flashError)
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else if models.IsErrMergeUnrelatedHistories(err) {
log.Debug("MergeUnrelatedHistories error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.unrelated_histories"))
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else if git.IsErrPushOutOfDate(err) {
log.Debug("MergePushOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.merge_out_of_date"))
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else if models.IsErrSHADoesNotMatch(err) {
log.Debug("MergeHeadOutOfDate error: %v", err)
ctx.Flash.Error(ctx.Tr("repo.pulls.head_out_of_date"))
- ctx.Redirect(issue.Link())
+ ctx.JSONRedirect(issue.Link())
} else if git.IsErrPushRejected(err) {
log.Debug("MergePushRejected error: %v", err)
pushrejErr := err.(*git.ErrPushRejected)
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index a6b3bd1c8d..92665af7e7 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/upload"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
pull_service "code.gitea.io/gitea/services/pull"
@@ -22,6 +23,7 @@ import (
const (
tplDiffConversation base.TplName = "repo/diff/conversation"
+ tplConversationOutdated base.TplName = "repo/diff/conversation_outdated"
tplTimelineConversation base.TplName = "repo/issue/view_content/conversation"
tplNewComment base.TplName = "repo/diff/new_comment"
)
@@ -49,6 +51,8 @@ func RenderNewCodeCommentForm(ctx *context.Context) {
return
}
ctx.Data["AfterCommitID"] = pullHeadCommitID
+ ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
+ upload.AddUploadContext(ctx, "comment")
ctx.HTML(http.StatusOK, tplNewComment)
}
@@ -74,6 +78,11 @@ func CreateCodeComment(ctx *context.Context) {
signedLine *= -1
}
+ var attachments []string
+ if setting.Attachment.Enabled {
+ attachments = form.Files
+ }
+
comment, err := pull_service.CreateCodeComment(ctx,
ctx.Doer,
ctx.Repo.GitRepo,
@@ -84,6 +93,7 @@ func CreateCodeComment(ctx *context.Context) {
!form.SingleReview,
form.Reply,
form.LatestCommitID,
+ attachments,
)
if err != nil {
ctx.ServerError("CreateCodeComment", err)
@@ -155,17 +165,28 @@ func UpdateResolveConversation(ctx *context.Context) {
func renderConversation(ctx *context.Context, comment *issues_model.Comment, origin string) {
ctx.Data["PageIsPullFiles"] = origin == "diff"
- comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, ctx.Data["ShowOutdatedComments"].(bool))
+ showOutdatedComments := origin == "timeline" || ctx.Data["ShowOutdatedComments"].(bool)
+ comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, showOutdatedComments)
if err != nil {
ctx.ServerError("FetchCodeCommentsByLine", err)
return
}
if len(comments) == 0 {
- // if the comments are empty (deleted, outdated, etc), it doesn't need to render anything, just return an empty body to replace "conversation-holder" on the page
- ctx.Resp.WriteHeader(http.StatusOK)
+ // if the comments are empty (deleted, outdated, etc), it's better to tell the users that it is outdated
+ ctx.HTML(http.StatusOK, tplConversationOutdated)
return
}
+ for _, c := range comments {
+ if err := c.LoadAttachments(ctx); err != nil {
+ ctx.ServerError("LoadAttachments", err)
+ return
+ }
+ }
+
+ ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
+ upload.AddUploadContext(ctx, "comment")
+
ctx.Data["comments"] = comments
if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, comment.Issue, ctx.Doer); err != nil {
ctx.ServerError("CanMarkConversation", err)
@@ -218,9 +239,9 @@ func SubmitReview(ctx *context.Context) {
if issue.IsPoster(ctx.Doer.ID) {
var translated string
if reviewType == issues_model.ReviewTypeApprove {
- translated = ctx.Tr("repo.issues.review.self.approval")
+ translated = ctx.Locale.TrString("repo.issues.review.self.approval")
} else {
- translated = ctx.Tr("repo.issues.review.self.rejection")
+ translated = ctx.Locale.TrString("repo.issues.review.self.rejection")
}
ctx.Flash.Error(translated)
diff --git a/routers/web/repo/pull_review_test.go b/routers/web/repo/pull_review_test.go
new file mode 100644
index 0000000000..8fc9cecaf3
--- /dev/null
+++ b/routers/web/repo/pull_review_test.go
@@ -0,0 +1,76 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+ "net/http/httptest"
+ "testing"
+
+ "code.gitea.io/gitea/models/db"
+ issues_model "code.gitea.io/gitea/models/issues"
+ "code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/contexttest"
+ "code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/services/pull"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestRenderConversation(t *testing.T) {
+ unittest.PrepareTestEnv(t)
+
+ pr, _ := issues_model.GetPullRequestByID(db.DefaultContext, 2)
+ _ = pr.LoadIssue(db.DefaultContext)
+ _ = pr.Issue.LoadPoster(db.DefaultContext)
+ _ = pr.Issue.LoadRepo(db.DefaultContext)
+
+ run := func(name string, cb func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder)) {
+ t.Run(name, func(t *testing.T) {
+ ctx, resp := contexttest.MockContext(t, "/", contexttest.MockContextOption{Render: templates.HTMLRenderer()})
+ contexttest.LoadUser(t, ctx, pr.Issue.PosterID)
+ contexttest.LoadRepo(t, ctx, pr.BaseRepoID)
+ contexttest.LoadGitRepo(t, ctx)
+ defer ctx.Repo.GitRepo.Close()
+ cb(t, ctx, resp)
+ })
+ }
+
+ var preparedComment *issues_model.Comment
+ run("prepare", func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder) {
+ comment, err := pull.CreateCodeComment(ctx, pr.Issue.Poster, ctx.Repo.GitRepo, pr.Issue, 1, "content", "", false, 0, pr.HeadCommitID, nil)
+ if !assert.NoError(t, err) {
+ return
+ }
+ comment.Invalidated = true
+ err = issues_model.UpdateCommentInvalidate(ctx, comment)
+ if !assert.NoError(t, err) {
+ return
+ }
+ preparedComment = comment
+ })
+ if !assert.NotNil(t, preparedComment) {
+ return
+ }
+ run("diff with outdated", func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder) {
+ ctx.Data["ShowOutdatedComments"] = true
+ renderConversation(ctx, preparedComment, "diff")
+ assert.Contains(t, resp.Body.String(), `
-
-
-
diff --git a/templates/admin/config_settings.tmpl b/templates/admin/config_settings.tmpl
new file mode 100644
index 0000000000..22ad5c24ac
--- /dev/null
+++ b/templates/admin/config_settings.tmpl
@@ -0,0 +1,42 @@
+{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}}
+
+
+
+
+
+{{template "admin/layout_footer" .}}
diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl
index f43b4c5385..cc7d338589 100644
--- a/templates/admin/dashboard.tmpl
+++ b/templates/admin/dashboard.tmpl
@@ -2,7 +2,7 @@
{{if .NeedUpdate}}
-
{{(ctx.Locale.Tr "admin.dashboard.new_version_hint" .RemoteVersion AppVer) | Str2html}}
+
{{ctx.Locale.Tr "admin.dashboard.new_version_hint" .RemoteVersion AppVer}}
{{end}}
{{end}}
-
- {{ctx.Locale.Tr "admin.config"}}
-
+
+ {{ctx.Locale.Tr "admin.config"}}
+
+
{{ctx.Locale.Tr "admin.notices"}}
diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl
index 5cfd9ddefa..cf860dab2a 100644
--- a/templates/admin/packages/list.tmpl
+++ b/templates/admin/packages/list.tmpl
@@ -88,7 +88,7 @@
{{ctx.Locale.Tr "packages.settings.delete"}}
- {{ctx.Locale.Tr "packages.settings.delete.notice" ` ` ` ` | Safe}}
+ {{ctx.Locale.Tr "packages.settings.delete.notice" (` `|SafeHTML) (` `|SafeHTML)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl
index fdba0734a2..e11247aed4 100644
--- a/templates/admin/repo/list.tmpl
+++ b/templates/admin/repo/list.tmpl
@@ -101,7 +101,7 @@
{{ctx.Locale.Tr "repo.settings.delete_desc"}}
- {{ctx.Locale.Tr "repo.settings.delete_notices_2" `
` | Safe}}
+ {{ctx.Locale.Tr "repo.settings.delete_notices_2" (`
`|SafeHTML)}}
{{ctx.Locale.Tr "repo.settings.delete_notices_fork_1"}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/admin/stacktrace.tmpl b/templates/admin/stacktrace.tmpl
index 894e41f8d7..42944615c3 100644
--- a/templates/admin/stacktrace.tmpl
+++ b/templates/admin/stacktrace.tmpl
@@ -39,7 +39,7 @@
{{ctx.Locale.Tr "admin.monitor.process.cancel"}}
-
{{ctx.Locale.Tr "admin.monitor.process.cancel_notices" ` ` | Safe}}
+
{{ctx.Locale.Tr "admin.monitor.process.cancel_notices" (` `|SafeHTML)}}
{{ctx.Locale.Tr "admin.monitor.process.cancel_desc"}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/admin/system_status.tmpl b/templates/admin/system_status.tmpl
new file mode 100644
index 0000000000..7b5c9be6cc
--- /dev/null
+++ b/templates/admin/system_status.tmpl
@@ -0,0 +1,62 @@
+
+ {{ctx.Locale.Tr "admin.dashboard.server_uptime"}}
+ {{.SysStatus.StartTime}}
+ {{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}
+ {{.SysStatus.NumGoroutine}}
+
+ {{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}
+ {{.SysStatus.MemAllocated}}
+ {{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}
+ {{.SysStatus.MemTotal}}
+ {{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}
+ {{.SysStatus.MemSys}}
+ {{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}
+ {{.SysStatus.Lookups}}
+ {{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}
+ {{.SysStatus.MemMallocs}}
+ {{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}
+ {{.SysStatus.MemFrees}}
+
+ {{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}
+ {{.SysStatus.HeapAlloc}}
+ {{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}
+ {{.SysStatus.HeapSys}}
+ {{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}
+ {{.SysStatus.HeapIdle}}
+ {{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}
+ {{.SysStatus.HeapInuse}}
+ {{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}
+ {{.SysStatus.HeapReleased}}
+ {{ctx.Locale.Tr "admin.dashboard.heap_objects"}}
+ {{.SysStatus.HeapObjects}}
+
+ {{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}
+ {{.SysStatus.StackInuse}}
+ {{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}
+ {{.SysStatus.StackSys}}
+ {{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}
+ {{.SysStatus.MSpanInuse}}
+ {{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}
+ {{.SysStatus.MSpanSys}}
+ {{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}
+ {{.SysStatus.MCacheInuse}}
+ {{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}
+ {{.SysStatus.MCacheSys}}
+ {{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}
+ {{.SysStatus.BuckHashSys}}
+ {{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}
+ {{.SysStatus.GCSys}}
+ {{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}
+ {{.SysStatus.OtherSys}}
+
+ {{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}
+ {{.SysStatus.NextGC}}
+ {{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}
+ {{.SysStatus.LastGCTime}}
+ {{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}
+ {{.SysStatus.PauseTotalNs}}
+ {{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}
+ {{.SysStatus.PauseNs}}
+ {{ctx.Locale.Tr "admin.dashboard.gc_times"}}
+ {{.SysStatus.NumGC}}
+
diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl
index 81f70511d0..bcb53d8131 100644
--- a/templates/admin/user/new.tmpl
+++ b/templates/admin/user/new.tmpl
@@ -26,7 +26,7 @@
{{ctx.Locale.Tr "settings.visibility"}}
-
+
{{if .DefaultUserVisibilityMode.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}}
{{if .DefaultUserVisibilityMode.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}}
diff --git a/templates/base/footer.tmpl b/templates/base/footer.tmpl
index d65a3626a4..fed426a469 100644
--- a/templates/base/footer.tmpl
+++ b/templates/base/footer.tmpl
@@ -16,6 +16,5 @@
{{template "custom/footer" .}}
- {{ctx.DataRaceCheck $.Context}}
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index b9c050fdd5..2de8f58235 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -2,7 +2,7 @@
-
{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}
+
{{if .Title}}{{.Title}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}
{{if .ManifestData}}
{{end}}
@@ -29,8 +29,7 @@
{{template "base/head_style" .}}
{{template "custom/header" .}}
-
- {{ctx.DataRaceCheck $.Context}}
+
{{template "custom/body_outer_pre" .}}
diff --git a/templates/code/searchcombo.tmpl b/templates/code/searchcombo.tmpl
index 48dc13b47b..d451bc0ad8 100644
--- a/templates/code/searchcombo.tmpl
+++ b/templates/code/searchcombo.tmpl
@@ -7,7 +7,7 @@
{{else if .SearchResults}}
- {{ctx.Locale.Tr "explore.code_search_results" (.Keyword|Escape) | Str2html}}
+ {{ctx.Locale.Tr "explore.code_search_results" .Keyword}}
{{template "code/searchresults" .}}
{{else if .Keyword}}
diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl
index 73293ddf48..ccf188609c 100644
--- a/templates/devtest/gitea-ui.tmpl
+++ b/templates/devtest/gitea-ui.tmpl
@@ -275,6 +275,12 @@
ps: no JS code attached, so just a layout
{{template "shared/combomarkdowneditor" .}}
+
+
Tailwind CSS Demo
+
+ Button
+
+
{{template "base/footer" .}}
diff --git a/templates/explore/repo_search.tmpl b/templates/explore/repo_search.tmpl
index eaf2e7a090..e268670e93 100644
--- a/templates/explore/repo_search.tmpl
+++ b/templates/explore/repo_search.tmpl
@@ -36,7 +36,7 @@
{{if and .PageIsExploreRepositories .OnlyShowRelevant}}
- {{ctx.Locale.Tr "explore.relevant_repositories" ((printf "?only_show_relevant=0&sort=%s&q=%s&language=%s" $.SortType (QueryEscape $.Keyword) (QueryEscape $.Language))|Escape) | Safe}}
+ {{ctx.Locale.Tr "explore.relevant_repositories" (printf "?only_show_relevant=0&sort=%s&q=%s&language=%s" $.SortType (QueryEscape $.Keyword) (QueryEscape $.Language))}}
{{end}}
diff --git a/templates/explore/user_list.tmpl b/templates/explore/user_list.tmpl
index 9abbff6d9c..0d661d53cb 100644
--- a/templates/explore/user_list.tmpl
+++ b/templates/explore/user_list.tmpl
@@ -21,7 +21,7 @@
{{.Email}}
{{end}}
- {{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix) | Safe}}
+ {{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix)}}
diff --git a/templates/home.tmpl b/templates/home.tmpl
index 78364431e9..1e5369e7ee 100644
--- a/templates/home.tmpl
+++ b/templates/home.tmpl
@@ -17,7 +17,7 @@
{{svg "octicon-flame"}} {{ctx.Locale.Tr "startpage.install"}}
- {{ctx.Locale.Tr "startpage.install_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.install_desc"}}
@@ -25,7 +25,7 @@
{{svg "octicon-device-desktop"}} {{ctx.Locale.Tr "startpage.platform"}}
- {{ctx.Locale.Tr "startpage.platform_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.platform_desc"}}
@@ -35,7 +35,7 @@
{{svg "octicon-rocket"}} {{ctx.Locale.Tr "startpage.lightweight"}}
- {{ctx.Locale.Tr "startpage.lightweight_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.lightweight_desc"}}
@@ -43,7 +43,7 @@
{{svg "octicon-code"}} {{ctx.Locale.Tr "startpage.license"}}
- {{ctx.Locale.Tr "startpage.license_desc" | Str2html}}
+ {{ctx.Locale.Tr "startpage.license_desc"}}
diff --git a/templates/install.tmpl b/templates/install.tmpl
index e9b267fa1c..05a74cc788 100644
--- a/templates/install.tmpl
+++ b/templates/install.tmpl
@@ -8,7 +8,7 @@
{{template "base/alert" .}}
-
{{ctx.Locale.Tr "install.docker_helper" "https://docs.gitea.com/installation/install-with-docker" | Safe}}
+
{{ctx.Locale.Tr "install.docker_helper" "https://docs.gitea.com/installation/install-with-docker"}}
@@ -72,7 +72,7 @@
{{ctx.Locale.Tr "install.path"}}
- {{ctx.Locale.Tr "install.sqlite_helper" | Safe}}
+ {{ctx.Locale.Tr "install.sqlite_helper"}}
diff --git a/templates/mail/auth/activate.tmpl b/templates/mail/auth/activate.tmpl
index a15afe3d49..b1bb4cb463 100644
--- a/templates/mail/auth/activate.tmpl
+++ b/templates/mail/auth/activate.tmpl
@@ -8,8 +8,8 @@
{{$activate_url := printf "%suser/activate?code=%s" AppUrl (QueryEscape .Code)}}
- {{.locale.Tr "mail.activate_account.text_1" (.DisplayName|DotEscape) AppName | Str2html}}
- {{.locale.Tr "mail.activate_account.text_2" .ActiveCodeLives | Str2html}}
{{$activate_url}}
+ {{.locale.Tr "mail.activate_account.text_1" (.DisplayName|DotEscape) AppName}}
+ {{.locale.Tr "mail.activate_account.text_2" .ActiveCodeLives}}
{{$activate_url}}
{{.locale.Tr "mail.link_not_working_do_paste"}}
© {{AppName}}
diff --git a/templates/mail/auth/activate_email.tmpl b/templates/mail/auth/activate_email.tmpl
index b15cc2a68a..3d32f80a4e 100644
--- a/templates/mail/auth/activate_email.tmpl
+++ b/templates/mail/auth/activate_email.tmpl
@@ -8,8 +8,8 @@
{{$activate_url := printf "%suser/activate_email?code=%s&email=%s" AppUrl (QueryEscape .Code) (QueryEscape .Email)}}
- {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}
- {{.locale.Tr "mail.activate_email.text" .ActiveCodeLives | Str2html}}
{{$activate_url}}
+ {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape)}}
+ {{.locale.Tr "mail.activate_email.text" .ActiveCodeLives}}
{{$activate_url}}
{{.locale.Tr "mail.link_not_working_do_paste"}}
© {{AppName}}
diff --git a/templates/mail/auth/register_notify.tmpl b/templates/mail/auth/register_notify.tmpl
index 3cdb456fb3..62dbf7d927 100644
--- a/templates/mail/auth/register_notify.tmpl
+++ b/templates/mail/auth/register_notify.tmpl
@@ -8,10 +8,10 @@
{{$set_pwd_url := printf "%[1]suser/forgot_password" AppUrl}}
- {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}
+ {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape)}}
{{.locale.Tr "mail.register_notify.text_1" AppName}}
{{.locale.Tr "mail.register_notify.text_2" .Username}}
{{AppUrl}}user/login
- {{.locale.Tr "mail.register_notify.text_3" ($set_pwd_url | Escape) | Str2html}}
+ {{.locale.Tr "mail.register_notify.text_3" $set_pwd_url}}
© {{AppName}}
diff --git a/templates/mail/auth/reset_passwd.tmpl b/templates/mail/auth/reset_passwd.tmpl
index 172844c954..55b1ecec3f 100644
--- a/templates/mail/auth/reset_passwd.tmpl
+++ b/templates/mail/auth/reset_passwd.tmpl
@@ -8,8 +8,8 @@
{{$recover_url := printf "%suser/recover_account?code=%s" AppUrl (QueryEscape .Code)}}
- {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}
- {{.locale.Tr "mail.reset_password.text" .ResetPwdCodeLives | Str2html}}
{{$recover_url}}
+ {{.locale.Tr "mail.hi_user_x" (.DisplayName|DotEscape)}}
+ {{.locale.Tr "mail.reset_password.text" .ResetPwdCodeLives}}
{{$recover_url}}
{{.locale.Tr "mail.link_not_working_do_paste"}}
© {{AppName}}
diff --git a/templates/mail/issue/assigned.tmpl b/templates/mail/issue/assigned.tmpl
index d02ea39918..5720319ee8 100644
--- a/templates/mail/issue/assigned.tmpl
+++ b/templates/mail/issue/assigned.tmpl
@@ -8,14 +8,14 @@
{{.Subject}}
-{{$repo_url := printf "%s " (Escape .Issue.Repo.HTMLURL) (Escape .Issue.Repo.FullName)}}
-{{$link := printf "#%d " (Escape .Link) .Issue.Index}}
+{{$repo_url := HTMLFormat "%s " .Issue.Repo.HTMLURL .Issue.Repo.FullName}}
+{{$link := HTMLFormat "#%d " .Link .Issue.Index}}
{{if .IsPull}}
- {{.locale.Tr "mail.issue_assigned.pull" .Doer.Name $link $repo_url | Str2html}}
+ {{.locale.Tr "mail.issue_assigned.pull" .Doer.Name $link $repo_url}}
{{else}}
- {{.locale.Tr "mail.issue_assigned.issue" .Doer.Name $link $repo_url | Str2html}}
+ {{.locale.Tr "mail.issue_assigned.issue" .Doer.Name $link $repo_url}}
{{end}}