diff options
60 files changed, 2552 insertions, 1371 deletions
diff --git a/.gitignore b/.gitignore index 272ea2b5ed..0791a17c71 100644 --- a/.gitignore +++ b/.gitignore @@ -42,14 +42,10 @@ _testmain.go coverage.all cpu.out -/modules/migration/bindata.go -/modules/migration/bindata.go.hash -/modules/options/bindata.go -/modules/options/bindata.go.hash -/modules/public/bindata.go -/modules/public/bindata.go.hash -/modules/templates/bindata.go -/modules/templates/bindata.go.hash +/modules/migration/bindata.* +/modules/options/bindata.* +/modules/public/bindata.* +/modules/templates/bindata.* *.db *.log diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2e67929c..b72ac4849a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,429 @@ This changelog goes through the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.com). +## [1.24.0](https://github.com/go-gitea/gitea/releases/tag/1.24.0) - 2025-05-26 + +* BREAKING + * Make Gitea always use its internal config, ignore `/etc/gitconfig` (#33076) + * Improve log format (#33814) + * Fix markdown render behaviors (#34122) + * Add package version api endpoints (#34173) + +* FEATURES + * Enforce two-factor auth (2FA: TOTP or WebAuthn) (#34187) + * Add fullscreen mode as a more efficient operation way to view projects (#34081) + * Add anonymous access support for private/unlisted repositories (#34051) + * Support public code/issue access for private repositories (#33127) + * Add middleware for request prioritization (#33951) + * Add cli flags LDAP group configuration (#33933) + * Add file tree to file view page (#32721) + * Add material icons for file list (#33837) + * Artifacts download api for artifact actions v4 (#33510) + * Support choose email when creating a commit via web UI (#33432) + * Add basic auth support to rss/atom feeds (#33371) + * Add sorting by exclusive labels (issue priority) (#33206) + * Add sub issue list support (#32940) + * Private README.md for organization (#32872) + * Email option to embed images as base64 instead of link (#32061) + * Option to delay conflict checking of old pull requests until page view (#27779) + * Worktime tracking for the organization level (#19808) + +* PERFORMANCE + * Add cache for common package queries (#22491) + * Move issue pin to an standalone table for querying performance (#33452) + * Improve commits list performance to reduce unnecessary database queries (#33528) + * Optimize total count of feed when loading activities in user dashboard. (#33841) + * Optimize heatmap query (#33853) + * Only use prev and next buttons for pagination on user dashboard (#33981) + * Improve pull request list API performance (#34052) + * Cache GPG keys, emails and users when list commits (#34086) + * Refactor Git Attribute & performance optimization (#34154) + * Performance optimization for tags synchronization (#34355) #34522 + +* ENHANCEMENTS + * Code + * Display when a release attachment was uploaded (#34261) + * Support creating relative link to raw path in markdown (#34105) + * Improve code block readability and isolate copy button (#34009) + * Improve repository commit view (#33877) + * Full-file syntax highlighting for diff pages (#33766) + * Clone repository with Tea CLI (#33725) + * Improve sync fork behavior (#33319) + * Make git clone URL could use current signed-in user (#33091) + * Add submodule diff links (#33097) + * Link to tree views of submodules if possible (#33424) + * Only keep popular licenses (#33832) + * De-emphasize signed commits (#31160) + + * Actions + * Add flat-square action badge style (#34062) + * Update action status badge layout (#34018) + * Download actions job logs from API (#33858) + * Always show the "rerun" button for action jobs (#33692) + * Add auto-expanding running actions step (#30058) + * Update status check for all supported on.pull_request.types in Gitea (#33117) + * Workflow_dispatch use workflow from trigger branch (#33098) + * Add action auto-scroll (#30057) + * Add workflow_job webhook (#33694) + * Add a button editing action secret (#34462) + + * Pull Request + * Auto expand "New PR" form (#33971) + * Mark parent directory as viewed when all files are viewed (#33958) + * Show info about maintainers are allowed to edit a PR (#33738) + * Automerge supports deleting branch automatically after merging (#32343) + * Add additional command hints for PowerShell & CMD (#33548) + + * Issues + * Allow filtering issues by any assignee (#33343) + * Show warning on navigation if currently editing comment or title (#32920) + * Make tracked time representation display as hours (#33315) + * Add No Results Prompt Message on Issue List Page (#33699) + * Add sort option recentclose for issues and pulls (#34525) #34539 + + * Packages + * Link to nuget dependencies (#26554) + * Add composor source field (#33502) + + * Administration + * Improve navbar: add "admin" tip, add "active" style (#32927) + * Add a option "--user-type bot" to admin user create, improve role display (#27885) + * Improve admin user view page (#33735) + * Support performance trace (#32973) + * Change pprof labels to be prometheus compatible (#32865) + * Allow admins and org owners to change org member public status (#28294) + * Optimize the installation page (#32994) + * Make public URL generation configurable (#34250) + * Add a --fullname arg to gitea admin user create. (#34241) + + * Others + * Improve oauth2 error handling (#33969) + * Fail mirroring more gracefully (#34002) + * Align User Details Page Header Layout with Design Specifications (#34192) + * Webhook add X-Gitea-Hook-Installation-Target-Type Header (#33752) + * Optimize the dashboard (#32990) + * Improve button layout on small screens (#33633) + * Add cropping support when modifying the user/org/repo avatar (#33498) + * Make ROOT_URL support using request Host header (#32564) + * Add `show more` organizations icon in user's profile (#32986) + * Introduce `--page-space-bottom` at 64px (#30692) + * Improve theme display (#30671) + * Add alphabetical project sorting (#33504) + * Add global lock for migrations to make upgrade more safe with multiple replications (#33706) + * Add descriptions for private repo public access settings and improve the UI (#34057) + +* API + * Actions Runner rest api (#33873) + * Inclusion of rename organization api (#33303) + * Add API to support link package to repository and unlink it (#33481) + * Add API endpoint to request contents of multiple files simultaniously (#34139) + * Actions artifacts API list/download check status upload confirmed (#34273) + * Add API routes to lock and unlock issues (#34165) + * Fix some user name usages (#33689) + * Allow filtering /repos/{owner}/{repo}/pulls by target base branch queryparam (#33684) + * Improve swagger generation (#33664) + * Support Ephemeral action runners (#33570) + * Support workflow event dispatch via API (#33545) + * Support workflow event dispatch via API (#32059) + * Added Description Field for Secrets and Variables (#33526) + * Reject star-related requests if stars are disabled (#33208) + * Let API create and edit system webhooks, attempt 2 (#33180) + * Use `Project-URL` metadata field to get a PyPI package's homepage URL (#33089) + * Add `last_committer_date` and `last_author_date` for file contents API (#32921) + +* REFACTORS + * Remove context from git struct (#33793) + * Refactor admin/common.ts (#33788) + * Refactor repo-settings.ts (#33785) + * Refactor repo-issue.ts (#33784) + * Small refactor to reduce unnecessary database queries and remove duplicated functions (#33779) + * Refactor initRepoBranchTagSelector to use new init framework (#33776) + * Refactor buttons to use new init framework (#33774) + * Refactor markup and pdf-viewer to use new init framework (#33772) + * Refactor error system (#33771) + * Refactor mail code (#33768) + * Update TypeScript types (#33799) + * Refactor older tests to use testify (#33140) + * Move notifywatch to service layer (#33825) + * Decouple context from repository related structs (#33823) + * Remove context from mail struct (#33811) + * Refactor dropdown ellipsis (#34123) + * Refactor functions to reduce repopath expose (#33892) + * Refactor repo-diff.ts (#33746) + * Refactor web route handler (#33488) + * Refactor user & avatar (#33433) + * Refactor user package (#33423) + * Refactor decouple context from migration structs (#33399) + * Refactor context flash msg and global variables (#33375) + * Refactor response writer & access logger (#33323) + * Refactor ref type (#33242) + * Refactor context repository (#33202) + * Refactor legacy JS (#33115) + * Refactor legacy line-number and scroll code (#33094) + * Refactor env var related code (#33075) + * Move SetMerged to service layer (#33045) + * Merge updatecommentattachment functions (#33044) + * Refactor pull-request compare&create page (#33071) + * Refactor repo-new.ts (#33070) + * Refactor pagination (#33037) + * Refactor tests (#33021) + * Refactor markup render to fix various path problems (#34114) + * Refactor Branch struct in package modules/git (#33980) + * Don't create duplicated functions for code repositories and wiki repositories (#33924) + * Move git references checking to gitrepo packages to reduce expose of repository path (#33891) + * Refactor cache-control (#33861) + * Decouple diff stats query from actual diffing (#33810) + * Move part of updating protected branch logic to service layer (#33742) + * Decouple Batch from git.Repository to simplify usage without requiring the creation of a Repository struct. (#34001) + * Refactor tmpl and blob_excerpt (#32967) + * Refactor template & test related code (#32938) + * Refactor db package and remove unnecessary `DumpTables` (#32930) + * Refactor pprof labels and process desc (#32909) + * Refactor repo-projects.ts (#32892) + * Refactor getpatch/getdiff functions and remove unnecessary fallback (#32817) + * Uniform all temporary directories and allow customizing temp path (#32352) + * Remove context from retry downloader (#33871) + * Refactor global init code and add more comments (#33755) + * Remove some unnecessary template helpers (#33069) + * Move and rename UpdateRepository (#34136) + * Move hooks function to gitrepo and reduce expose repopath (#33890) + * Add abstraction layer to delete repository from disk (#33879) + * Add abstraction layer to check if the repository exists on disk (#33874) + * Move ParseCommitWithSSHSignature to service layer (#34087) + * Move duplicated functions (#33977) + * Extract code to their own functions for push update (#33944) + * Move gitgraph from modules to services layer (#33527) + * Move commits signature and verify functions to service layers (#33605) + * Use `CloseIssue` and `ReopenIssue` instead of `ChangeStatus` (#32467) + * Refactor arch route handlers (#32993) + * Refactor "string truncate" (#32984) + * Refactor arch route handlers (#32972) + * Clarify path param naming (#32969) + * Refactor request context (#32956) + * Move some errors to their own sub packages (#32880) + * Move RepoTransfer from models to models/repo sub package (#32506) + * Move delete deploy keys into service layer (#32201) + * Refactor webhook events (#33337) + * Move some Actions related functions from `routers` to `services` (#33280) + * Refactor RefName (#33234) + * Refactor context RefName and RepoAssignment (#33226) + * Refactor repository transfer (#33211) + * Refactor error system (#33626) + * Refactor error system (#33610) + * Refactor package (routes and error handling, npm peer dependency) (#33111) + * Use test context in tests and new loop system in benchmarks (#33648) + * Some small refactors (#33144) + * Simplify context ref name (#33267) + +* BUGFIXES + * Fix some dropdown problems on the issue sidebar (#34308) #34327 + * Do not return archive download URLs in API if downloads are disabled (#34324) #34338 + * Fix LFS files being editable in web UI (#34356) #34362 + * Fix only text/* being viewable in web UI (#34374) #34378 + * Fix LFS file not stored in LFS when uploaded/edited via API or web UI (#34367) + * Grey out expired artifact on Artifacts list (#34314) #34404 + * Fix incorrect divergence cache after switching default branch (#34370) #34406 + * Refactor commit message rendering and fix bugs (#34412) #34414 + * Merge and tweak markup editor expander CSS (#34409) #34415 + * Fix GetUsersByEmails (#34423) #34425 + * Only git operations should update last changed of a repository (#34388) #34427 + * Fix comment textarea scroll issue in Firefox (#34438) #34446 + * Fix repo broken check (#34444) #34452 + * Fix remove org user failure on mssql (#34449) #34453 + * Fix Workflow run Not Found page (#34459) #34466 + * When updating comment, if the content is the same, just return and not update the database (#34422) #34464 + * Fix project board view (#34470) #34475 + * Fix get / delete runner to use consistent http 404 and 500 status (#34480) #34488 + * Fix url validation in webhook add/edit API (#34492) #34496 + * Fix edithook api can not update package, status and workflow_job events (#34495) #34499 + * Fix ephemeral runner deletion (#34447) #34513 + * Don't display error log when .git-blame-ignore-revs doesn't exist (#34457) + * Only allow admins to rename default/protected branches (#33276) + * Improve "lock conversation" UI (#34207) + * Fix incorrect file links (#34189) + * Optimize Overflow Menu (#34183) + * Check user/org repo limit instead of doer (#34147) + * Make markdown render match GitHub's behavior (#34129) + * Fix team permission (#34128) + * Correctly handle submodule view and avoid throwing 500 error (#34121) + * Fix users being able bypass limits with repo transfers (#34031) + * Avoid creating unnecessary temporary cat file sub process (#33942) + * Refactor organization menu (#33928) + * Fix various Fomantic UI and htmx problems (#33851) + * Fix 500 error when error occurred in migration page (#33256) + * Validate that the tag doesn't exist when creating a tag via the web (#33241) + * Add missed transaction on setmerged (#33079) + * Rework create/fork/adopt/generate repository to make sure resources will be cleanup once failed (#31035) + * Valid email address should only start with alphanumeric (#28174) + * Fix webhook url (#34186) + * Fix "toAbsoluteLocaleDate" test when system locale is not en-US (#33939) + * Fix file name could not be searched if the file was not a text file when using the Bleve indexer (#33959) + * Fix cannot delete runners via the modal dialog (#33895) + * Fix unpin hint on the pinned pull requests (#33207) + * Fix parentCommit invalid memory address or nil pointer dereference. (#33204) + * Fix comment header padding (#33377) + * Fix some migration and repo name problems (#33986) + * Fix various trivial frontend problems (#34263) + * Fix Set Email Preference dropdown and button placement (#34255) + * Fix quoted replies incorrectly render user input as part of the quote (#34216) + * Fix button alignments and remove unnecessary styles (#34206) + * Restore form inputs on organization create error (#34201) + * Try to fix ACME (3rd) (#33807) + * Fix incorrect ref "blob" (#33240) + * Fix dynamic content loading init problem (#33748) + * Fix git empty check and HEAD request (#33690) + * Fix Untranslated Text on Actions Page (#33635) + * Fix issue label delete incorrect labels webhook payload (#34575) + * Fix incorrect page navigation with up and down arrow on last item of dashboard repos (#34570) + * Fix/improve avatar sync from LDAP (#34573) + * Fix some trivial problems (#34579) + * Retain issue sort type when a keyword search is introduced (#34559) + * Always use an empty line to separate the commit message and trailer (#34512) + * Fix line-button issue after file selection in file tree (#34574) + * Fix doctor deleting orphaned issues attachments (#34142) + * Add webhook assigning test and fix possible bug (#34420) + * Fix possible nil description of pull request when migrating from CodeCommit (#34541) + * Refactor commit reader (#34542) + * Fix possible pull request broken when leave the page immediately after clicking the update button #34509 + * Ignore "Close" error when uploading container blob (#34620) + * Fix missed merge commit sha and time when migrating from codecommit (#34645) + * Fix GetUsersByEmails (#34643) + * Misc CSS fixes (#34638) + * Add codecommit to supported services in api docs (#34626) + * Validate hex colors when creating/editing labels (#34623) + * Fix possible pull request broken when leave the page immediately after clicking the update button (#34509) + * Fix margin issue in markup paragraph rendering (#34599) + * Fix migration pull request title too long (#34577) + * Fix footnote jump behavior on the issue page. (#34621) + * Fix "oras" OCI client compatibility (#34666) + * Fix last admin check when syncing users (#34649) + * Fix skip paths check on tag push events in workflows (#34602) #34670 + +* MISC + + * Bump to alpine 3.22 (#34613) + * Make pull request and issue history more compact (#34588) + * Run integration tests against postgres 14 (#34514) #34536 + * Enable addtional linters (#34085) + * Enable testifylint rules (#34075) + * Enable staticcheck QFxxxx rules (#34064) + * Improve Actions test (#32883) + * Drop fomantic build (#33845) + * Go1.24 (#33562) + * Run yamllint with strict mode, fix issue (#33551) + * Disable cron task to update license (#33486) + * Optimize makefile help information generation (#33390) + * Convert github.com/xanzy/go-gitlab into gitlab.com/gitlab-org/api/client-go (#33126) + * Add missed changelogs (#33649) + * Update .changelog file to add performance label group (#33472) + * Add missing POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES in app.example.ini (#33363) + * Update README screenshots (#33347) + * Update unrs-resolver (#34279) + * Update go&js dependencies (#34262) + * Optimize the calling code of queryElems (#34235) + * Update protected_branch.tmpl (#34193) + * Feat/optimize span svg layout (#34185) + * Set MERMAID_MAX_SOURCE_CHARACTERS to 50000 (#34152) + * Update JS and PY deps (#34143) + * Add Chinese translations for README files (#34132) + * Use `overflow-wrap: anywhere` to replace `word-break: break-all` (#34126) + * Clarify ownership in password change error messages (#34092) + * Add toggleClass function in dom.ts (#34063) + * Update to golangci-lint v2 (#34054) + * Update Makefile test comments (#34013) + * Update go mod dependencies (#33988) + * Use filepath.Join instead of path.Join for file system file operations (#33978) + * Prepare common tmpl functions in a middleware (#33957) + * Remove unused or abused styles (#33918) + * Update JS and PY deps, misc tweaks (#33903) + * Try to figure out attribute checker problem (#33901) + * Add lock for a repository pull mirror (#33876) + * Fine tune push mirror UI (#33866) + * Improve issue & code search (#33860) + * Use pullrequestlist instead of []*pullrequest (#33765) + * Upgrade act to 0.261.4 and actions-proto-go to v0.4.1 (#33760) + * Align sidebar gears to the right (#33721) + * Update Go dependencies (skip blevesearch, meilisearch) (#33655) + * Add migrations and doctor fixes (#33556) + * Remove "class-name" from svg icon (#33540) + * Update MAINTAINERS (#33529) + * Add "No data available" display when list is empty (#33517) + * Use `git diff-tree` for `DiffFileTree` on diff pages (#33514) + * Give organisation members access to organisation feeds (#33508) + * Update feishu icon (#33470) + * Hide/disable unusable UI elements when a repository is archived (#33459) + * Update `@github/text-expander-element` to 2.9.0 (#33435) + * Do not access GitRepo when a repo is being created (#33380) + * Fix incorrect ref usages (#33301) + * Prepare for support performance trace (#33286) + * Enable Typescript `noImplicitThis` (#33250) + * Remove unused CSS styles and move some styles to proper files (#33217) + * Add .run to gitignore (#33175) + * Fix typo in gitea downloader test and add missing codebase in `ToGitServiceType` (#33146) + * Remove extended glob pattern from branch protection UI (#33125) + * Clean up legacy form CSS styles (#33081) + * Unset XDG_HOME_CONFIG as gitea manages configuration locations (#33067) + * Add IntelliJ Gateway's .uuid to gitignore (#33052) + * User facing messages for AGit errors (#33012) + * Always show assignees on right (#33006) + * Fix eslint (#33002) + * Update JS dependencies (#32914) + * Bump x/net (#32896) (#32900) + * Only activity tab needs heatmap data loading (#34652) + +## [1.23.8](https://github.com/go-gitea/gitea/releases/tag/1.23.8) - 2025-05-11 + +* SECURITY + * Fix a bug when uploading file via lfs ssh command (#34408) (#34411) + * Update net package (#34228) (#34232) +* BUGFIXES + * Fix releases sidebar navigation link (#34436) #34439 + * Fix bug webhook milestone is not right. (#34419) #34429 + * Fix two missed null value checks on the wiki page. (#34205) (#34215) + * Swift files can be passed either as file or as form value (#34068) (#34236) + * Fix bug when API get pull changed files for deleted head repository (#34333) (#34368) + * Upgrade github v61 -> v71 to fix migrating bug (#34389) + * Fix bug when visiting comparation page (#34334) (#34364) + * Fix wrong review requests when updating the pull request (#34286) (#34304) + * Fix github migration error when using multiple tokens (#34144) (#34302) + * Explicitly not update indexes when sync database schemas (#34281) (#34295) + * Fix panic when comment is nil (#34257) (#34277) + * Fix project board links to related Pull Requests (#34213) (#34222) + * Don't assume the default wiki branch is master in the wiki API (#34244) (#34245) +* DOCUMENTATION + * Update token creation API swagger documentation (#34288) (#34296) +* MISC + * Fix CI Build (#34315) + * Add riscv64 support (#34199) (#34204) + * Bump go version in go.mod (#34160) + * remove hardcoded 'code' string in clone_panel.tmpl (#34153) (#34158) + +## [1.23.7](https://github.com/go-gitea/gitea/releases/tag/1.23.7) - 2025-04-07 + +* Enhancements + * Add a config option to block "expensive" pages for anonymous users (#34024) (#34071) + * Also check default ssh-cert location for host (#34099) (#34100) (#34116) +* BUGFIXES + * Fix discord webhook 400 status code when description limit is exceeded (#34084) (#34124) + * Get changed files based on merge base when checking `pull_request` actions trigger (#34106) (#34120) + * Fix invalid version in RPM package path (#34112) (#34115) + * Return default avatar url when user id is zero rather than updating database (#34094) (#34095) + * Add additional ReplaceAll in pathsep to cater for different pathsep (#34061) (#34070) + * Try to fix check-attr bug (#34029) (#34033) + * Git client will follow 301 but 307 (#34005) (#34010) + * Fix block expensive for 1.23 (#34127) + * Fix markdown frontmatter rendering (#34102) (#34107) + * Add new CLI flags to set name and scopes when creating a user with access token (#34080) (#34103) + * Do not show 500 error when default branch doesn't exist (#34096) (#34097) + * Hide activity contributors, recent commits and code frequrency left tabs if there is no code permission (#34053) (#34065) + * Simplify emoji rendering (#34048) (#34049) + * Adjust the layout of the toolbar on the Issues/Projects page (#33667) (#34047) + * Pull request updates will also trigger code owners review requests (#33744) (#34045) + * Fix org repo creation being limited by user limits (#34030) (#34044) + * Fix git client accessing renamed repo (#34034) (#34043) + * Fix the issue with error message logging for the `check-attr` command on Windows OS. (#34035) (#34036) + * Polyfill WeakRef (#34025) (#34028) + ## [1.23.6](https://github.com/go-gitea/gitea/releases/tag/v1.23.6) - 2025-03-24 * SECURITY @@ -120,8 +120,7 @@ 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 -BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go -BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST)) +BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go @@ -149,14 +148,8 @@ SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini 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 += $(shell find $(GO_DIRS) -type f -name "*.go") GO_SOURCES += $(GENERATED_GO_DEST) -GO_SOURCES_NO_BINDATA := $(GO_SOURCES) - -ifeq ($(filter $(TAGS_SPLIT),bindata),bindata) - GO_SOURCES += $(BINDATA_DEST) - GENERATED_GO_DEST += $(BINDATA_DEST) -endif # Force installation of playwright dependencies by setting this flag ifdef DEPS_PLAYWRIGHT @@ -226,7 +219,7 @@ clean-all: clean ## delete backend, frontend and integration files .PHONY: clean clean: ## delete backend and integration files - rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \ + rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \ integrations*.test \ e2e*.test \ tests/integration/gitea-integration-* \ @@ -268,7 +261,7 @@ endif .PHONY: generate-swagger generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comments -$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA) $(SWAGGER_SPEC_INPUT) +$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT) $(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)' .PHONY: swagger-check @@ -373,7 +366,7 @@ lint-go-gitea-vet: ## lint go files with gitea-vet .PHONY: lint-go-gopls lint-go-gopls: ## lint go files with gopls @echo "Running gopls check..." - @GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA) + @GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES) .PHONY: lint-editorconfig lint-editorconfig: @@ -5,19 +5,10 @@ package main -// Libraries that are included to vendor utilities used during build. +// Libraries that are included to vendor utilities used during Makefile build. // These libraries will not be included in a normal compilation. import ( - // for embed - _ "github.com/shurcooL/vfsgen" - - // for cover merge - _ "golang.org/x/tools/cover" - // for vet _ "code.gitea.io/gitea-vet" - - // for swagger - _ "github.com/go-swagger/go-swagger/cmd/swagger" ) diff --git a/build/generate-bindata.go b/build/generate-bindata.go index 2fcb7c2f2a..2553770762 100644 --- a/build/generate-bindata.go +++ b/build/generate-bindata.go @@ -6,87 +6,22 @@ package main import ( - "bytes" - "crypto/sha1" "fmt" - "log" - "net/http" "os" - "path/filepath" - "strconv" - "github.com/shurcooL/vfsgen" + "code.gitea.io/gitea/modules/assetfs" ) -func needsUpdate(dir, filename string) (bool, []byte) { - needRegen := false - _, err := os.Stat(filename) - if err != nil { - needRegen = true - } - - oldHash, err := os.ReadFile(filename + ".hash") - if err != nil { - oldHash = []byte{} - } - - hasher := sha1.New() - - err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err - } - info, err := d.Info() - if err != nil { - return err - } - _, _ = hasher.Write([]byte(d.Name())) - _, _ = hasher.Write([]byte(info.ModTime().String())) - _, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16))) - return nil - }) - if err != nil { - return true, oldHash - } - - newHash := hasher.Sum([]byte{}) - - if bytes.Compare(oldHash, newHash) != 0 { - return true, newHash - } - - return needRegen, newHash -} - func main() { - if len(os.Args) < 4 { - log.Fatal("Insufficient number of arguments. Need: directory packageName filename") - } - - dir, packageName, filename := os.Args[1], os.Args[2], os.Args[3] - var useGlobalModTime bool - if len(os.Args) == 5 { - useGlobalModTime, _ = strconv.ParseBool(os.Args[4]) - } - - update, newHash := needsUpdate(dir, filename) - - if !update { - fmt.Printf("bindata for %s already up-to-date\n", packageName) - return + if len(os.Args) != 3 { + fmt.Println("usage: ./generate-bindata {local-directory} {bindata-filename}") + os.Exit(1) } - fmt.Printf("generating bindata for %s\n", packageName) - var fsTemplates http.FileSystem = http.Dir(dir) - err := vfsgen.Generate(fsTemplates, vfsgen.Options{ - PackageName: packageName, - BuildTags: "bindata", - VariableName: "Assets", - Filename: filename, - UseGlobalModTime: useGlobalModTime, - }) - if err != nil { - log.Fatalf("%v\n", err) + dir, filename := os.Args[1], os.Args[2] + fmt.Printf("generating bindata for %s to %s\n", dir, filename) + if err := assetfs.GenerateEmbedBindata(dir, filename); err != nil { + fmt.Printf("failed: %s\n", err.Error()) + os.Exit(1) } - _ = os.WriteFile(filename+".hash", newHash, 0o666) } diff --git a/cmd/embedded.go b/cmd/embedded.go index 086bc06863..6a2fa07a93 100644 --- a/cmd/embedded.go +++ b/cmd/embedded.go @@ -118,7 +118,7 @@ func initEmbeddedExtractor(c *cli.Command) error { func runList(_ context.Context, c *cli.Command) error { if err := runListDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -126,7 +126,7 @@ func runList(_ context.Context, c *cli.Command) error { func runView(_ context.Context, c *cli.Command) error { if err := runViewDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -134,7 +134,7 @@ func runView(_ context.Context, c *cli.Command) error { func runExtract(_ context.Context, c *cli.Command) error { if err := runExtractDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -217,7 +217,7 @@ func runExtractDo(c *cli.Command) error { for _, a := range matchedAssetFiles { if err := extractAsset(destdir, a, overwrite, rename); err != nil { // Non-fatal error - fmt.Fprintf(os.Stderr, "%s: %v", a.path, err) + _, _ = fmt.Fprintf(os.Stderr, "%s: %v\n", a.path, err) } } diff --git a/cmd/serv.go b/cmd/serv.go index e4434450d6..8c6001e727 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -212,7 +212,7 @@ func runServ(ctx context.Context, c *cli.Command) error { if git.DefaultFeatures().SupportProcReceive { // for AGit Flow if cmd == "ssh_info" { - fmt.Print(`{"type":"gitea","version":1}`) + fmt.Print(`{"type":"agit","version":1}`) return nil } } diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index e9a378e877..aa2fcee765 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1186,17 +1186,24 @@ LEVEL = Info ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; GPG key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey +;; GPG or SSH key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey +;; Depending on the value of SIGNING_FORMAT this is either: +;; - openpgp: the GPG key ID +;; - ssh: the path to the ssh public key "/path/to/key.pub": where "/path/to/key" is the private key, use ssh-keygen -t ed25519 to generate a new key pair without password ;; run in the context of the RUN_USER ;; Switch to none to stop signing completely ;SIGNING_KEY = default ;; -;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer. +;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer and the signing format. ;; These should match a publicized name and email address for the key. (When SIGNING_KEY is default these are set to -;; the results of git config --get user.name and git config --get user.email respectively and can only be overridden +;; the results of git config --get user.name, git config --get user.email and git config --default openpgp --get gpg.format respectively and can only be overridden ;; by setting the SIGNING_KEY ID to the correct ID.) ;SIGNING_NAME = ;SIGNING_EMAIL = +;; SIGNING_FORMAT can be one of: +;; - openpgp (default): use GPG to sign commits +;; - ssh: use SSH to sign commits +;SIGNING_FORMAT = openpgp ;; ;; Sets the default trust model for repositories. Options are: collaborator, committer, collaboratorcommitter ;DEFAULT_TRUST_MODEL = collaborator @@ -1223,6 +1230,13 @@ LEVEL = Info ;; - commitssigned: require that all the commits in the head branch are signed. ;; - approved: only sign when merging an approved pr to a protected branch ;MERGES = pubkey, twofa, basesigned, commitssigned +;; +;; Determines which additional ssh keys are trusted for all signed commits regardless of the user +;; This is useful for ssh signing key rotation. +;; Exposes the provided SIGNING_NAME and SIGNING_EMAIL as the signer, regardless of the SIGNING_FORMAT value. +;; Multiple keys should be comma separated. +;; E.g."ssh-<algorithm> <key>". or "ssh-<algorithm> <key1>, ssh-<algorithm> <key2>". +;TRUSTED_SSH_KEYS = ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1,6 +1,6 @@ module code.gitea.io/gitea -go 1.24.2 +go 1.24.4 // rfc5280 said: "The serial number is an integer assigned by the CA to each certificate." // But some CAs use negative serial number, just relax the check. related: @@ -60,7 +60,6 @@ require ( github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-redsync/redsync/v4 v4.13.0 github.com/go-sql-driver/mysql v1.9.2 - github.com/go-swagger/go-swagger v0.31.0 github.com/go-webauthn/webauthn v0.12.3 github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f @@ -105,7 +104,6 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/sassoftware/go-rpmutils v0.4.0 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 - github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 github.com/stretchr/testify v1.10.0 github.com/syndtr/goleveldb v1.0.0 github.com/tstranex/u2f v1.0.0 @@ -126,7 +124,6 @@ require ( golang.org/x/sync v0.15.0 golang.org/x/sys v0.33.0 golang.org/x/text v0.26.0 - golang.org/x/tools v0.33.0 google.golang.org/grpc v1.72.0 google.golang.org/protobuf v1.36.6 gopkg.in/ini.v1 v1.67.0 @@ -144,15 +141,11 @@ require ( git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/DataDog/zstd v1.5.7 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect - github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect @@ -195,7 +188,6 @@ require ( github.com/dlclark/regexp2 v1.11.5 // indirect github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect github.com/fatih/color v1.18.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect @@ -204,18 +196,6 @@ require ( github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-ini/ini v1.67.0 // indirect - github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/errors v0.22.1 // indirect - github.com/go-openapi/inflect v0.21.2 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.22.0 // indirect - github.com/go-openapi/runtime v0.28.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/strfmt v0.23.0 // indirect - github.com/go-openapi/swag v0.23.1 // indirect - github.com/go-openapi/validate v0.24.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/go-webauthn/x v0.1.20 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect @@ -229,7 +209,6 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.3 // indirect github.com/gorilla/css v1.0.1 // indirect - github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -237,12 +216,9 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jessevdk/go-flags v1.6.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/libdns/libdns v1.0.0-beta.1 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/markbates/going v1.0.3 // indirect @@ -253,19 +229,15 @@ require ( github.com/miekg/dns v1.1.65 // indirect github.com/minio/crc64nvme v1.0.1 // indirect github.com/minio/md5-simd v1.1.2 // 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 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -274,22 +246,11 @@ require ( github.com/prometheus/procfs v0.16.1 // indirect github.com/rhysd/actionlint v1.7.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/shopspring/decimal v1.4.0 // indirect - github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/spf13/viper v1.20.1 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -300,7 +261,6 @@ require ( github.com/zeebo/assert v1.3.0 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.etcd.io/bbolt v1.4.0 // indirect - go.mongodb.org/mongo-driver v1.17.3 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect @@ -308,6 +268,7 @@ require ( golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect + golang.org/x/tools v0.33.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -315,8 +276,6 @@ require ( replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1 -replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 - replace github.com/nektos/act => gitea.com/gitea/act v0.261.6 // TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why @@ -62,12 +62,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE= github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= -github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -103,8 +97,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= @@ -274,12 +266,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= @@ -325,28 +313,6 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM= -github.com/go-openapi/inflect v0.21.2/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= @@ -357,13 +323,9 @@ github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkv github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU= github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= -github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc= -github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE= github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY= github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw= @@ -446,8 +408,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= -github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= -github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= @@ -497,8 +457,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= -github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw= github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -540,8 +498,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI= -github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= @@ -577,14 +533,10 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.91 h1:tWLZnEfo3OZl5PoXQwcwTAPNNrjyWwOh6cbZitW5JQc= github.com/minio/minio-go/v7 v7.0.91/go.mod h1:uvMUcGrpgeSAAI6+sD3818508nUyMULw94j2Nxku/Go= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -607,8 +559,6 @@ github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWk github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E= @@ -629,8 +579,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -674,7 +622,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= @@ -682,8 +629,6 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= @@ -692,10 +637,6 @@ github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLS github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= -github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= -github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -707,22 +648,12 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc= @@ -745,13 +676,9 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= -github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ= github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -809,8 +736,6 @@ gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAj go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= -go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= -go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= diff --git a/modules/assetfs/embed.go b/modules/assetfs/embed.go new file mode 100644 index 0000000000..95176372d1 --- /dev/null +++ b/modules/assetfs/embed.go @@ -0,0 +1,375 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package assetfs + +import ( + "bytes" + "compress/gzip" + "io" + "io/fs" + "os" + "path" + "path/filepath" + "strings" + "sync" + "time" + + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/util" +) + +type EmbeddedFile interface { + io.ReadSeeker + fs.ReadDirFile + ReadDir(n int) ([]fs.DirEntry, error) +} + +type EmbeddedFileInfo interface { + fs.FileInfo + fs.DirEntry + GetGzipContent() ([]byte, bool) +} + +type decompressor interface { + io.Reader + Close() error + Reset(io.Reader) error +} + +type embeddedFileInfo struct { + fs *embeddedFS + fullName string + data []byte + + BaseName string `json:"n"` + OriginSize int64 `json:"s,omitempty"` + DataBegin int64 `json:"b,omitempty"` + DataLen int64 `json:"l,omitempty"` + Children []*embeddedFileInfo `json:"c,omitempty"` +} + +func (fi *embeddedFileInfo) GetGzipContent() ([]byte, bool) { + // when generating the bindata, if the compressed data equals or is larger than the original data, we store the original data + if fi.DataLen == fi.OriginSize { + return nil, false + } + return fi.data, true +} + +type EmbeddedFileBase struct { + info *embeddedFileInfo + dataReader io.ReadSeeker + seekPos int64 +} + +func (f *EmbeddedFileBase) ReadDir(n int) ([]fs.DirEntry, error) { + // this method is used to satisfy the "func (f ioFile) ReadDir(...)" in httpfs + l, err := f.info.fs.ReadDir(f.info.fullName) + if err != nil { + return nil, err + } + if n < 0 || n > len(l) { + return l, nil + } + return l[:n], nil +} + +type EmbeddedOriginFile struct { + EmbeddedFileBase +} + +type EmbeddedCompressedFile struct { + EmbeddedFileBase + decompressor decompressor + decompressorPos int64 +} + +type embeddedFS struct { + meta func() *EmbeddedMeta + + files map[string]*embeddedFileInfo + filesMu sync.RWMutex + + data []byte +} + +type EmbeddedMeta struct { + Root *embeddedFileInfo +} + +func NewEmbeddedFS(data []byte) fs.ReadDirFS { + efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)} + efs.meta = sync.OnceValue(func() *EmbeddedMeta { + var meta EmbeddedMeta + p := bytes.LastIndexByte(data, '\n') + if p < 0 { + return &meta + } + if err := json.Unmarshal(data[p+1:], &meta); err != nil { + panic("embedded file is not valid") + } + return &meta + }) + return efs +} + +var _ fs.ReadDirFS = (*embeddedFS)(nil) + +func (e *embeddedFS) ReadDir(name string) (l []fs.DirEntry, err error) { + fi, err := e.getFileInfo(name) + if err != nil { + return nil, err + } + if !fi.IsDir() { + return nil, fs.ErrNotExist + } + l = make([]fs.DirEntry, len(fi.Children)) + for i, child := range fi.Children { + l[i], err = e.getFileInfo(name + "/" + child.BaseName) + if err != nil { + return nil, err + } + } + return l, nil +} + +func (e *embeddedFS) getFileInfo(fullName string) (*embeddedFileInfo, error) { + // no need to do heavy "path.Clean()" because we don't want to support "foo/../bar" or absolute paths + fullName = strings.TrimPrefix(fullName, "./") + if fullName == "" { + fullName = "." + } + + e.filesMu.RLock() + fi := e.files[fullName] + e.filesMu.RUnlock() + if fi != nil { + return fi, nil + } + + fields := strings.Split(fullName, "/") + fi = e.meta().Root + if fullName != "." { + found := true + for _, field := range fields { + for _, child := range fi.Children { + if found = child.BaseName == field; found { + fi = child + break + } + } + if !found { + return nil, fs.ErrNotExist + } + } + } + + e.filesMu.Lock() + defer e.filesMu.Unlock() + if fi != nil { + fi.fs = e + fi.fullName = fullName + fi.data = e.data[fi.DataBegin : fi.DataBegin+fi.DataLen] + e.files[fullName] = fi // do not cache nil, otherwise keeping accessing random non-existing file will cause OOM + return fi, nil + } + return nil, fs.ErrNotExist +} + +func (e *embeddedFS) Open(name string) (fs.File, error) { + info, err := e.getFileInfo(name) + if err != nil { + return nil, err + } + base := EmbeddedFileBase{info: info} + base.dataReader = bytes.NewReader(base.info.data) + if info.DataLen != info.OriginSize { + decomp, err := gzip.NewReader(base.dataReader) + if err != nil { + return nil, err + } + return &EmbeddedCompressedFile{EmbeddedFileBase: base, decompressor: decomp}, nil + } + return &EmbeddedOriginFile{base}, nil +} + +var ( + _ EmbeddedFileInfo = (*embeddedFileInfo)(nil) + _ EmbeddedFile = (*EmbeddedOriginFile)(nil) + _ EmbeddedFile = (*EmbeddedCompressedFile)(nil) +) + +func (f *EmbeddedOriginFile) Read(p []byte) (n int, err error) { + return f.dataReader.Read(p) +} + +func (f *EmbeddedCompressedFile) Read(p []byte) (n int, err error) { + if f.decompressorPos > f.seekPos { + if err = f.decompressor.Reset(bytes.NewReader(f.info.data)); err != nil { + return 0, err + } + f.decompressorPos = 0 + } + if f.decompressorPos < f.seekPos { + if _, err = io.CopyN(io.Discard, f.decompressor, f.seekPos-f.decompressorPos); err != nil { + return 0, err + } + f.decompressorPos = f.seekPos + } + n, err = f.decompressor.Read(p) + f.decompressorPos += int64(n) + f.seekPos = f.decompressorPos + return n, err +} + +func (f *EmbeddedFileBase) Seek(offset int64, whence int) (int64, error) { + switch whence { + case io.SeekStart: + f.seekPos = offset + case io.SeekCurrent: + f.seekPos += offset + case io.SeekEnd: + f.seekPos = f.info.OriginSize + offset + } + return f.seekPos, nil +} + +func (f *EmbeddedFileBase) Stat() (fs.FileInfo, error) { + return f.info, nil +} + +func (f *EmbeddedOriginFile) Close() error { + return nil +} + +func (f *EmbeddedCompressedFile) Close() error { + return f.decompressor.Close() +} + +func (fi *embeddedFileInfo) Name() string { + return fi.BaseName +} + +func (fi *embeddedFileInfo) Size() int64 { + return fi.OriginSize +} + +func (fi *embeddedFileInfo) Mode() fs.FileMode { + return util.Iif(fi.IsDir(), fs.ModeDir|0o555, 0o444) +} + +func (fi *embeddedFileInfo) ModTime() time.Time { + return getExecutableModTime() +} + +func (fi *embeddedFileInfo) IsDir() bool { + return fi.Children != nil +} + +func (fi *embeddedFileInfo) Sys() any { + return nil +} + +func (fi *embeddedFileInfo) Type() fs.FileMode { + return util.Iif(fi.IsDir(), fs.ModeDir, 0) +} + +func (fi *embeddedFileInfo) Info() (fs.FileInfo, error) { + return fi, nil +} + +// getExecutableModTime returns the modification time of the executable file. +// In bindata, we can't use the ModTime of the files because we need to make the build reproducible +var getExecutableModTime = sync.OnceValue(func() (modTime time.Time) { + exePath, err := os.Executable() + if err != nil { + return modTime + } + exePath, err = filepath.Abs(exePath) + if err != nil { + return modTime + } + exePath, err = filepath.EvalSymlinks(exePath) + if err != nil { + return modTime + } + st, err := os.Stat(exePath) + if err != nil { + return modTime + } + return st.ModTime() +}) + +func GenerateEmbedBindata(fsRootPath, outputFile string) error { + output, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + if err != nil { + return err + } + defer output.Close() + + meta := &EmbeddedMeta{} + meta.Root = &embeddedFileInfo{} + var outputOffset int64 + var embedFiles func(parent *embeddedFileInfo, fsPath, embedPath string) error + embedFiles = func(parent *embeddedFileInfo, fsPath, embedPath string) error { + dirEntries, err := os.ReadDir(fsPath) + if err != nil { + return err + } + for _, dirEntry := range dirEntries { + if err != nil { + return err + } + if dirEntry.IsDir() { + child := &embeddedFileInfo{ + BaseName: dirEntry.Name(), + Children: []*embeddedFileInfo{}, // non-nil means it's a directory + } + parent.Children = append(parent.Children, child) + if err = embedFiles(child, filepath.Join(fsPath, dirEntry.Name()), path.Join(embedPath, dirEntry.Name())); err != nil { + return err + } + } else { + data, err := os.ReadFile(filepath.Join(fsPath, dirEntry.Name())) + if err != nil { + return err + } + var compressed bytes.Buffer + gz, _ := gzip.NewWriterLevel(&compressed, gzip.BestCompression) + if _, err = gz.Write(data); err != nil { + return err + } + if err = gz.Close(); err != nil { + return err + } + + // only use the compressed data if it is smaller than the original data + outputBytes := util.Iif(len(compressed.Bytes()) < len(data), compressed.Bytes(), data) + child := &embeddedFileInfo{ + BaseName: dirEntry.Name(), + OriginSize: int64(len(data)), + DataBegin: outputOffset, + DataLen: int64(len(outputBytes)), + } + if _, err = output.Write(outputBytes); err != nil { + return err + } + outputOffset += child.DataLen + parent.Children = append(parent.Children, child) + } + } + return nil + } + + if err = embedFiles(meta.Root, fsRootPath, ""); err != nil { + return err + } + jsonBuf, err := json.Marshal(meta) // can't use json.NewEncoder here because it writes extra EOL + if err != nil { + return err + } + _, _ = output.Write([]byte{'\n'}) + _, err = output.Write(jsonBuf) + return err +} diff --git a/modules/assetfs/embed_test.go b/modules/assetfs/embed_test.go new file mode 100644 index 0000000000..06598da4c4 --- /dev/null +++ b/modules/assetfs/embed_test.go @@ -0,0 +1,98 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package assetfs + +import ( + "bytes" + "io/fs" + "net/http" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestEmbed(t *testing.T) { + tmpDir := t.TempDir() + tmpDataDir := tmpDir + "/data" + _ = os.MkdirAll(tmpDataDir+"/foo/bar", 0o755) + _ = os.WriteFile(tmpDataDir+"/a.txt", []byte("a"), 0o644) + _ = os.WriteFile(tmpDataDir+"/foo/bar/b.txt", bytes.Repeat([]byte("a"), 1000), 0o644) + _ = os.WriteFile(tmpDataDir+"/foo/c.txt", []byte("c"), 0o644) + require.NoError(t, GenerateEmbedBindata(tmpDataDir, tmpDir+"/out.dat")) + + data, err := os.ReadFile(tmpDir + "/out.dat") + require.NoError(t, err) + efs := NewEmbeddedFS(data) + + // test a non-existing file + _, err = fs.ReadFile(efs, "not exist") + assert.ErrorIs(t, err, fs.ErrNotExist) + + // test a normal file (no compression) + content, err := fs.ReadFile(efs, "a.txt") + require.NoError(t, err) + assert.Equal(t, "a", string(content)) + fi, err := fs.Stat(efs, "a.txt") + require.NoError(t, err) + _, ok := fi.(EmbeddedFileInfo).GetGzipContent() + assert.False(t, ok) + + // test a compressed file + content, err = fs.ReadFile(efs, "foo/bar/b.txt") + require.NoError(t, err) + assert.Equal(t, bytes.Repeat([]byte("a"), 1000), content) + fi, err = fs.Stat(efs, "foo/bar/b.txt") + require.NoError(t, err) + assert.False(t, fi.Mode().IsDir()) + assert.True(t, fi.Mode().IsRegular()) + gzipContent, ok := fi.(EmbeddedFileInfo).GetGzipContent() + assert.True(t, ok) + assert.Greater(t, len(gzipContent), 1) + assert.Less(t, len(gzipContent), 1000) + + // test list root directory + entries, err := fs.ReadDir(efs, ".") + require.NoError(t, err) + assert.Len(t, entries, 2) + assert.Equal(t, "a.txt", entries[0].Name()) + assert.False(t, entries[0].IsDir()) + + // test list subdirectory + entries, err = fs.ReadDir(efs, "foo") + require.NoError(t, err) + require.Len(t, entries, 2) + assert.Equal(t, "bar", entries[0].Name()) + assert.True(t, entries[0].IsDir()) + assert.Equal(t, "c.txt", entries[1].Name()) + assert.False(t, entries[1].IsDir()) + + // test directory mode + fi, err = fs.Stat(efs, "foo") + require.NoError(t, err) + assert.True(t, fi.IsDir()) + assert.True(t, fi.Mode().IsDir()) + assert.False(t, fi.Mode().IsRegular()) + + // test httpfs + hfs := http.FS(efs) + hf, err := hfs.Open("foo/bar/b.txt") + require.NoError(t, err) + hi, err := hf.Stat() + require.NoError(t, err) + fiEmbedded, ok := hi.(EmbeddedFileInfo) + require.True(t, ok) + gzipContent, ok = fiEmbedded.GetGzipContent() + assert.True(t, ok) + assert.Greater(t, len(gzipContent), 1) + assert.Less(t, len(gzipContent), 1000) + + // test httpfs directory listing + hf, err = hfs.Open("foo") + require.NoError(t, err) + dirs, err := hf.Readdir(1) + require.NoError(t, err) + assert.Len(t, dirs, 1) +} diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go index 4f3811ba2b..ce55475bd9 100644 --- a/modules/assetfs/layered.go +++ b/modules/assetfs/layered.go @@ -52,8 +52,8 @@ func Local(name, base string, sub ...string) *Layer { } // Bindata returns a new Layer with the given name, it serves files from the given bindata asset. -func Bindata(name string, fs http.FileSystem) *Layer { - return &Layer{name: name, fs: fs} +func Bindata(name string, fs fs.FS) *Layer { + return &Layer{name: name, fs: http.FS(fs)} } // LayeredFS is a layered asset file-system. It works like http.FileSystem, but it can have multiple layers. diff --git a/modules/git/command.go b/modules/git/command.go index eaaa4969d0..22f1d02339 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -47,6 +47,7 @@ type Command struct { globalArgsLength int brokenArgs []string cmd *exec.Cmd // for debug purpose only + configArgs []string } func logArgSanitize(arg string) string { @@ -196,6 +197,16 @@ func (c *Command) AddDashesAndList(list ...string) *Command { return c } +func (c *Command) AddConfig(key, value string) *Command { + kv := key + "=" + value + if !isSafeArgumentValue(kv) { + c.brokenArgs = append(c.brokenArgs, key) + } else { + c.configArgs = append(c.configArgs, "-c", kv) + } + return c +} + // ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs // In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead func ToTrustedCmdArgs(args []string) TrustedCmdArgs { @@ -321,7 +332,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error { startTime := time.Now() - cmd := exec.CommandContext(ctx, c.prog, c.args...) + cmd := exec.CommandContext(ctx, c.prog, append(c.configArgs, c.args...)...) c.cmd = cmd // for debug purpose only if opts.Env == nil { cmd.Env = os.Environ() diff --git a/modules/git/key.go b/modules/git/key.go new file mode 100644 index 0000000000..2513c048b7 --- /dev/null +++ b/modules/git/key.go @@ -0,0 +1,15 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat +const ( + SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli + SigningKeyFormatSSH = "ssh" +) + +type SigningKey struct { + KeyID string + Format string +} diff --git a/modules/git/repo.go b/modules/git/repo.go index 45937a8d5f..239866fe9d 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -28,6 +28,7 @@ type GPGSettings struct { Email string Name string PublicKeyContent string + Format string } const prettyLogFormat = `--pretty=format:%H` diff --git a/modules/git/repo_gpg.go b/modules/git/repo_gpg.go index 8f91b4dce5..0021a7bda7 100644 --- a/modules/git/repo_gpg.go +++ b/modules/git/repo_gpg.go @@ -6,6 +6,7 @@ package git import ( "fmt" + "os" "strings" "code.gitea.io/gitea/modules/process" @@ -13,6 +14,14 @@ import ( // LoadPublicKeyContent will load the key from gpg func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { + if gpgSettings.Format == SigningKeyFormatSSH { + content, err := os.ReadFile(gpgSettings.KeyID) + if err != nil { + return fmt.Errorf("unable to read SSH public key file: %s, %w", gpgSettings.KeyID, err) + } + gpgSettings.PublicKeyContent = string(content) + return nil + } content, stderr, err := process.GetManager().Exec( "gpg -a --export", "gpg", "-a", "--export", gpgSettings.KeyID) @@ -44,6 +53,9 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) gpgSettings.KeyID = strings.TrimSpace(signingKey) + format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + gpgSettings.Format = strings.TrimSpace(format) + defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) gpgSettings.Email = strings.TrimSpace(defaultEmail) diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go index 70e5aee023..309a73d759 100644 --- a/modules/git/repo_tree.go +++ b/modules/git/repo_tree.go @@ -15,7 +15,7 @@ import ( type CommitTreeOpts struct { Parents []string Message string - KeyID string + Key *SigningKey NoGPGSign bool AlwaysSign bool } @@ -43,8 +43,13 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt _, _ = messageBytes.WriteString(opts.Message) _, _ = messageBytes.WriteString("\n") - if opts.KeyID != "" || opts.AlwaysSign { - cmd.AddOptionFormat("-S%s", opts.KeyID) + if opts.Key != nil { + if opts.Key.Format != "" { + cmd.AddConfig("gpg.format", opts.Key.Format) + } + cmd.AddOptionFormat("-S%s", opts.Key.KeyID) + } else if opts.AlwaysSign { + cmd.AddOptionFormat("-S") } if opts.NoGPGSign { diff --git a/modules/migration/schemas_bindata.go b/modules/migration/schemas_bindata.go index c5db3b3461..695c2c1135 100644 --- a/modules/migration/schemas_bindata.go +++ b/modules/migration/schemas_bindata.go @@ -3,6 +3,28 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas bindata.dat + package migration -//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas migration bindata.go +import ( + "io" + "io/fs" + "path" + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() fs.FS { + return assetfs.NewEmbeddedFS(bindata) +}) + +func openSchema(filename string) (io.ReadCloser, error) { + return BuiltinAssets().Open(path.Base(filename)) +} diff --git a/modules/migration/schemas_static.go b/modules/migration/schemas_static.go deleted file mode 100644 index 8a0c340a65..0000000000 --- a/modules/migration/schemas_static.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package migration - -import ( - "io" - "path" -) - -func openSchema(filename string) (io.ReadCloser, error) { - return Assets.Open(path.Base(filename)) -} diff --git a/modules/options/options_bindata.go b/modules/options/options_bindata.go index 29151cb3cb..b2321d7eb5 100644 --- a/modules/options/options_bindata.go +++ b/modules/options/options_bindata.go @@ -3,6 +3,21 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../options bindata.dat + package options -//go:generate go run ../../build/generate-bindata.go ../../options options bindata.go +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/options/dynamic.go b/modules/options/options_dynamic.go index 085492d11c..085492d11c 100644 --- a/modules/options/dynamic.go +++ b/modules/options/options_dynamic.go diff --git a/modules/options/static.go b/modules/options/static.go deleted file mode 100644 index 72b28e990e..0000000000 --- a/modules/options/static.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package options - -import ( - "code.gitea.io/gitea/modules/assetfs" -) - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/public/public.go b/modules/public/public.go index 7f8ce29056..2bc55b7869 100644 --- a/modules/public/public.go +++ b/modules/public/public.go @@ -89,19 +89,16 @@ func handleRequest(w http.ResponseWriter, req *http.Request, fs http.FileSystem, servePublicAsset(w, req, fi, fi.ModTime(), f) } -type GzipBytesProvider interface { - GzipBytes() []byte -} - // servePublicAsset serve http content func servePublicAsset(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) { setWellKnownContentType(w, fi.Name()) httpcache.SetCacheControlInHeader(w.Header(), httpcache.CacheControlForPublicStatic()) encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding")) - if encodings.Contains("gzip") { - // try to provide gzip content directly from bindata (provided by vfsgenÛ°CompressedFileInfo) - if compressed, ok := fi.(GzipBytesProvider); ok { - rdGzip := bytes.NewReader(compressed.GzipBytes()) + fiEmbedded, _ := fi.(assetfs.EmbeddedFileInfo) + if encodings.Contains("gzip") && fiEmbedded != nil { + // try to provide gzip content directly from bindata + if gzipBytes, ok := fiEmbedded.GetGzipContent(); ok { + rdGzip := bytes.NewReader(gzipBytes) // all gzipped static files (from bindata) are managed by Gitea, so we can make sure every file has the correct ext name // then we can get the correct Content-Type, we do not need to do http.DetectContentType on the decompressed data if w.Header().Get("Content-Type") == "" { diff --git a/modules/public/public_bindata.go b/modules/public/public_bindata.go index 4878f88ad1..2dcf3e72e4 100644 --- a/modules/public/public_bindata.go +++ b/modules/public/public_bindata.go @@ -5,4 +5,19 @@ package public -//go:generate go run ../../build/generate-bindata.go ../../public public bindata.go true +//go:generate go run ../../build/generate-bindata.go ../../public bindata.dat + +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/public/serve_dynamic.go b/modules/public/public_dynamic.go index a668b17c34..a668b17c34 100644 --- a/modules/public/serve_dynamic.go +++ b/modules/public/public_dynamic.go diff --git a/modules/public/serve_static.go b/modules/public/serve_static.go deleted file mode 100644 index e79085021e..0000000000 --- a/modules/public/serve_static.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package public - -import ( - "time" - - "code.gitea.io/gitea/modules/assetfs" - "code.gitea.io/gitea/modules/timeutil" -) - -var _ GzipBytesProvider = (*vfsgenÛ°CompressedFileInfo)(nil) - -// GlobalModTime provide a global mod time for embedded asset files -func GlobalModTime(filename string) time.Time { - return timeutil.GetExecutableModTime() -} - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/setting/repository.go b/modules/setting/repository.go index c6bdc65b32..318cf41108 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -100,11 +100,13 @@ var ( SigningKey string SigningName string SigningEmail string + SigningFormat string InitialCommit []string CRUDActions []string `ini:"CRUD_ACTIONS"` Merges []string Wiki []string DefaultTrustModel string + TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"` } `ini:"repository.signing"` }{ DetectedCharsetsOrder: []string{ @@ -242,20 +244,24 @@ var ( SigningKey string SigningName string SigningEmail string + SigningFormat string InitialCommit []string CRUDActions []string `ini:"CRUD_ACTIONS"` Merges []string Wiki []string DefaultTrustModel string + TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"` }{ SigningKey: "default", SigningName: "", SigningEmail: "", + SigningFormat: "openpgp", // git.SigningKeyFormatOpenPGP InitialCommit: []string{"always"}, CRUDActions: []string{"pubkey", "twofa", "parentsigned"}, Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"}, Wiki: []string{"never"}, DefaultTrustModel: "collaborator", + TrustedSSHKeys: []string{}, }, } RepoRootPath string diff --git a/modules/templates/static.go b/modules/templates/static.go deleted file mode 100644 index b5a7e561ec..0000000000 --- a/modules/templates/static.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package templates - -import ( - "time" - - "code.gitea.io/gitea/modules/assetfs" - "code.gitea.io/gitea/modules/timeutil" -) - -// GlobalModTime provide a global mod time for embedded asset files -func GlobalModTime(filename string) time.Time { - return timeutil.GetExecutableModTime() -} - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/templates/templates_bindata.go b/modules/templates/templates_bindata.go index 6f1d3cf539..a919591ecf 100644 --- a/modules/templates/templates_bindata.go +++ b/modules/templates/templates_bindata.go @@ -3,6 +3,21 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../templates bindata.dat + package templates -//go:generate go run ../../build/generate-bindata.go ../../templates templates bindata.go true +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/templates/dynamic.go b/modules/templates/templates_dynamic.go index e1babd83c9..e1babd83c9 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/templates_dynamic.go diff --git a/modules/timeutil/executable.go b/modules/timeutil/executable.go deleted file mode 100644 index 57ae8b2a9d..0000000000 --- a/modules/timeutil/executable.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package timeutil - -import ( - "os" - "path/filepath" - "sync" - "time" - - "code.gitea.io/gitea/modules/log" -) - -var ( - executablModTime = time.Now() - executablModTimeOnce sync.Once -) - -// GetExecutableModTime get executable file modified time of current process. -func GetExecutableModTime() time.Time { - executablModTimeOnce.Do(func() { - exePath, err := os.Executable() - if err != nil { - log.Error("os.Executable: %v", err) - return - } - - exePath, err = filepath.Abs(exePath) - if err != nil { - log.Error("filepath.Abs: %v", err) - return - } - - exePath, err = filepath.EvalSymlinks(exePath) - if err != nil { - log.Error("filepath.EvalSymlinks: %v", err) - return - } - - st, err := os.Stat(exePath) - if err != nil { - log.Error("os.Stat: %v", err) - return - } - - executablModTime = st.ModTime() - }) - return executablModTime -} diff --git a/modules/zstd/zstd_test.go b/modules/zstd/zstd_test.go index c3ca8e78f7..7fd30484ca 100644 --- a/modules/zstd/zstd_test.go +++ b/modules/zstd/zstd_test.go @@ -16,7 +16,7 @@ import ( ) func TestWriterReader(t *testing.T) { - testData := prepareTestData(t, 20_000_000) + testData := prepareTestData(t, 1_000_000) result := bytes.NewBuffer(nil) @@ -64,7 +64,7 @@ func TestWriterReader(t *testing.T) { } func TestSeekableWriterReader(t *testing.T) { - testData := prepareTestData(t, 20_000_000) + testData := prepareTestData(t, 2_000_000) result := bytes.NewBuffer(nil) @@ -109,7 +109,7 @@ func TestSeekableWriterReader(t *testing.T) { reader, err := NewSeekableReader(assertReader) require.NoError(t, err) - _, err = reader.Seek(10_000_000, io.SeekStart) + _, err = reader.Seek(1_000_000, io.SeekStart) require.NoError(t, err) data := make([]byte, 1000) @@ -117,7 +117,7 @@ func TestSeekableWriterReader(t *testing.T) { require.NoError(t, err) require.NoError(t, reader.Close()) - assert.Equal(t, testData[10_000_000:10_000_000+1000], data) + assert.Equal(t, testData[1_000_000:1_000_000+1000], data) // Should seek 3 times, // the first two times are for getting the index, diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index 79df1d26d0..3804339585 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -1652,6 +1652,7 @@ issues.save=Sábháil issues.label_title=Ainm issues.label_description=Cur sÃos issues.label_color=Dath +issues.label_color_invalid=Dath neamhbhailà issues.label_exclusive=Eisiach issues.label_archive=Lipéad Cartlann issues.label_archived_filter=Taispeáin lipéid cartlainne diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index da38ca30b0..a73322bc2a 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -31,7 +31,7 @@ username=Ім'Ñ ÐºÑ€Ð¸Ñтувача email=ÐдреÑа електронної пошти password=Пароль access_token=Токен доÑтупу -re_type=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ +re_type=Підтвердити пароль captcha=CAPTCHA twofa=Двофакторна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ twofa_scratch=Двофакторний одноразовий пароль @@ -287,48 +287,48 @@ register_confirm=Вимагати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð mail_notify=Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою server_service_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñервера Ñ– Ñторонніх ÑервіÑів offline_mode=Увімкнути локальний режим -offline_mode_popup=Відключити Ñторонні мережі доÑтавки контенту Ñ– обÑлуговувати вÑÑ– реÑурÑи локально. +offline_mode_popup=Вимкнути Ñторонні мережі доÑтавки контенту та обÑлуговувати вÑÑ– реÑурÑи локально. disable_gravatar=Вимкнути Gravatar -disable_gravatar_popup=Відключити Gravatar Ñ– Ñторонні джерела аватарів. Якщо кориÑтувач не завантажить аватар локально то за замовчуваннÑм буде викориÑтовуватиÑÑ Ñтандартний аватар. -federated_avatar_lookup=Увімкнути федеративні аватари -federated_avatar_lookup_popup=Увімкнути зовнішний Ðватар за допомогою Libravatar. -disable_registration=Вимкнути ÑамоÑтійну реєÑтрацію -disable_registration_popup=Вимкнути ÑамоÑтійну реєÑтрацію кориÑтувачів, тільки адмініÑтратор може Ñтворювати нові облікові запиÑи. +disable_gravatar_popup=Вимкнути Gravatar та Ñторонні джерела аватарок. Якщо кориÑтувач локально не завантажить аватар, буде викориÑтовуватиÑÑ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¸Ð¹ аватар. +federated_avatar_lookup=Увімкнути зовнішні аватари +federated_avatar_lookup_popup=Увімкнути пошук об'єднаних аватарів за допомогою Libravatar. +disable_registration=Вимкнути реєÑтрацію +disable_registration_popup=Вимкнути реєÑтрацію кориÑтувачів, тільки адмініÑтратор може Ñтворювати нові облікові запиÑи. allow_only_external_registration_popup=Дозволити реєÑтрацію тільки через Ñторонні ÑервіÑи -openid_signin=Увімкнути реєÑтрацію за допомогою OpenID -openid_signin_popup=Увімкнути вхід за допомогою OpenID. +openid_signin=Увімкнути вхід за допомогою OpenID +openid_signin_popup=Увімкнути вхід кориÑтувачів за допомогою OpenID. openid_signup=Увімкнути ÑамоÑтійну реєÑтрацію за допомогою OpenID openid_signup_popup=Увімкнути ÑамореєÑтрацію кориÑтувачів на оÑнові OpenID. -enable_captcha=Увімкнути CAPTCHA при реєÑтрації -enable_captcha_popup=Вимагати перевірку CAPTCHA при ÑамоÑтійній реєÑтрації кориÑтувача. +enable_captcha=Увімкнути CAPTCHA Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації +enable_captcha_popup=Вимагати CAPTCHA Ð´Ð»Ñ ÑамореєÑтрації кориÑтувачів. require_sign_in_view=Вимагати авторизації Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду Ñторінок admin_setting_desc=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора необов'Ñзково. Перший зареєÑтрований кориÑтувач автоматично Ñтає адмініÑтратором. admin_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора admin_name=Ім'Ñ ÐºÑ€Ð¸Ñтувача ÐдмініÑтратора admin_password=Пароль -confirm_password=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ +confirm_password=Підтвердити пароль admin_email=ÐдреÑа електронної пошти -install_btn_confirm=Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Gitea -test_git_failed=Ðе в змозі перевірити 'git' команду: %v +install_btn_confirm=Ð’Ñтановити Gitea +test_git_failed=Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ команду 'git': %v sqlite3_not_available=Ð¦Ñ Ð²ÐµÑ€ÑÑ–Ñ Gitea не підтримує SQLite3. Будь лаÑка, завантажте офіційну бінарну верÑÑ–ÑŽ з %s (не верÑÑ–ÑŽ gobuild). -invalid_db_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних Ñ” некоректними: %v -invalid_db_table=Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ '%s' бази даних Ñ” недійÑною: %v -invalid_repo_path=Помилковий шлÑÑ… до ÐºÐ¾Ñ€ÐµÐ½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ: %v -invalid_app_data_path=Ðекоректний шлÑÑ… до даних програми: %v -run_user_not_match=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'run as' не Ñ” поточним ім'Ñм кориÑтувача: %s -> %s -internal_token_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ внутрішній токен: %v -secret_key_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ Ñекретний ключ: %v -save_config_failed=Ðе в змозі зберегти конфігурацію: %v -invalid_admin_setting=ÐеприпуÑтимі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора: %v -invalid_log_root_path=ÐеприпуÑтимий шлÑÑ… Ð´Ð»Ñ Ð»Ð¾Ð³Ñ–Ð²: %v -default_keep_email_private=Приховати адреÑу електронної пошти за замовчуваннÑм -default_keep_email_private_popup=Приховати адреÑу електронної пошти нових облікових запиÑів за замовчуваннÑм. -default_allow_create_organization=Дозволити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ð¹ за замовчуваннÑм -default_allow_create_organization_popup=Дозволити новим обліковим запиÑам кориÑтувачів Ñтворювати організації за замовчуваннÑм. -default_enable_timetracking=Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу за замовчуваннÑм -default_enable_timetracking_popup=Включити відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… репозиторіїв за замовчуваннÑм. +invalid_db_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних недійÑні: %v +invalid_db_table=База даних таблиці "%s" Ñ” недійÑною: %v +invalid_repo_path=Кореневий шлÑÑ… до Ñховища невірний: %v +invalid_app_data_path=ШлÑÑ… до даних додатка невірний: %v +run_user_not_match=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача “Виконати Ñк†не Ñ” поточним ім'Ñм кориÑтувача: %s -> %s +internal_token_failed=Ðе вдалоÑÑ Ñтворити внутрішній токен: %v +secret_key_failed=Ðе вдалоÑÑ Ñтворити Ñекретний ключ: %v +save_config_failed=Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ конфігурацію: %v +invalid_admin_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора Ñ” недійÑним: %v +invalid_log_root_path=Ðеправильний шлÑÑ… до журналу: %v +default_keep_email_private=Типово приховувати адреÑи електронної пошти +default_keep_email_private_popup=Типово приховувати адреÑи електронної пошти нових облікових запиÑів. +default_allow_create_organization=За замовчуваннÑм дозволити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ð¹ +default_allow_create_organization_popup=За замовчуваннÑм дозволити новим кориÑтувачам Ñтворювати організації. +default_enable_timetracking=За замовчуваннÑм увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу +default_enable_timetracking_popup=Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… Ñховищ за замовчуваннÑм. no_reply_address=Прихований поштовий домен -no_reply_address_helper=Доменне ім'Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів із прихованою електронною адреÑою. Ðаприклад, ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'joe' буде входити в Git Ñк 'joe@noreply.example.org', Ñкщо Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ…Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ домену електронної пошти вÑтановлено 'noreply.example.org'. +no_reply_address_helper=Доменне ім'Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів із прихованою електронною адреÑою. Ðаприклад, ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'Joe' буде зображатиÑÑ Ð² Git Ñк 'joe@noreply.example.org', Ñкщо прихований домен електронної пошти вÑтановлено 'noreply.example.org'. password_algorithm=Ðлгоритм Ñ…ÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ invalid_password_algorithm=ÐедійÑний хеш-алгоритм Ð¿Ð°Ñ€Ð¾Ð»Ñ enable_update_checker=Увімкнути перевірку оновлень @@ -338,35 +338,35 @@ config_write_file_prompt=Ці параметри будуть запиÑані Ð [home] nav_menu=Меню навігації -uname_holder=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або Ел. пошта +uname_holder=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або адреÑа електронної пошти password_holder=Пароль switch_dashboard_context=Переключити контекÑÑ‚ панелі ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ -my_repos=Репозиторії -show_more_repos=Показати більше репозиторіїв… -collaborative_repos=Спільні репозиторії +my_repos=Сховища +show_more_repos=Показати більше Ñховищ… +collaborative_repos=Спільні Ñховища my_orgs=Мої організації my_mirrors=Мої дзеркала view_home=ПереглÑнути %s filter=Інші фільтри -filter_by_team_repositories=Фільтрувати за репозиторіÑми команд +filter_by_team_repositories=Фільтрувати за Ñховищами команд feed_of=`Стрічка "%s"` show_archived=Ðрхівовані -show_both_archived_unarchived=Показано архівовані Ñ– не архівовані +show_both_archived_unarchived=Показано архівовані Ñ– неархівовані show_only_archived=Показано тільки архівовані -show_only_unarchived=Показано тільки не архівовані +show_only_unarchived=Показано тільки неархівовані show_private=Приватні show_both_private_public=Показано публічні та приватні show_only_private=Показано тільки приватні show_only_public=Показано тільки публічні -issues.in_your_repos=Ð’ ваших репозиторіÑÑ… +issues.in_your_repos=У ваших Ñховищах guide_title=Жодної активноÑті [explore] -repos=Репозиторії +repos=Сховища users=КориÑтувачі organizations=Організації code=Код @@ -374,100 +374,100 @@ code_last_indexed_at=ОÑтанні індекÑовані %s [auth] create_new_account=РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -disable_register_prompt=Вибачте, можливіÑть реєÑтрації відключена. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. +disable_register_prompt=РеєÑтрацію вимкнено. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. disable_register_mail=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÑ”Ñтрації електронною поштою вимкнено. remember_me=Запам’Ñтати цей приÑтрій forgot_password_title=Забув пароль forgot_password=Забули пароль? -must_change_password=Оновіть Ñвій пароль -allow_password_change=Вимагати в кориÑтувача змінити пароль (рекомендуєтьÑÑ) -reset_password_mail_sent_prompt=Електронний лиÑÑ‚ із підтвердженнÑм надіÑлано <b>%s</b>. Перевірте папку 'Вхідні' в межах наÑтупних %s, щоб завершити Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. +must_change_password=Оновити пароль +allow_password_change=Вимагати від кориÑтувача змінити пароль (рекомендовано) +reset_password_mail_sent_prompt=Ðа адреÑу <b>%s</b> було надіÑлано лиÑÑ‚ із підтвердженнÑм. Будь лаÑка, перевірте Ñвою поштову Ñкриньку протÑгом наÑтупних %s, щоб завершити Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. active_your_account=Ðктивувати обліковий Ð·Ð°Ð¿Ð¸Ñ account_activated=Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð¾ -prohibit_login=Вхід заборонений -resent_limit_prompt=Вибачте, ви вже запроÑили активацію по електронній пошті нещодавно. Будь лаÑка, зачекайте 3 хвилини, а потім Ñпробуйте ще раз. -has_unconfirmed_mail=Привіт %s, у Ð²Ð°Ñ Ñ” непідтверджена електронна адреÑа (<b>%s </b>). Якщо ви не отримали електронний лиÑÑ‚ із підтвердженнÑм або вам потрібно надіÑлати новий, натиÑніть на кнопку нижче. -resend_mail=ÐатиÑніть тут, щоб виÑлати лиÑÑ‚ активації знову -email_not_associate=Ð¦Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð° пошта не пов'Ñзана ні з одним обліковим запиÑом. -send_reset_mail=ÐадіÑлати електронний лиÑÑ‚ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +prohibit_login=Вхід заборонено +resent_limit_prompt=Ви вже надÑилали запит на активацію нещодавно. Зачекайте 3 хвилини Ñ– Ñпробуйте ще раз. +has_unconfirmed_mail= +Привіт %s, у Ð²Ð°Ñ Ð½ÐµÐ¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð° адреÑа електронної пошти (<b>%s</b>). Якщо ви не отримали лиÑта з підтвердженнÑм або вам потрібно надіÑлати новий, будь лаÑка, натиÑніть кнопку нижче. +resend_mail=ÐатиÑніть тут, щоб повторно надіÑлати лиÑÑ‚ з активацією +email_not_associate=Ð¦Ñ Ð°Ð´Ñ€ÐµÑа електронної пошти не пов'Ñзана з жодним обліковим запиÑом. +send_reset_mail=ÐадіÑлати лиÑÑ‚ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу reset_password=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -invalid_code=Цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ñ–Ð¹Ñний або закінчивÑÑ. +invalid_code=Ваш код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ñ–Ð¹Ñний або його термін дії закінчивÑÑ. reset_password_helper=Відновити обліковий Ð·Ð°Ð¿Ð¸Ñ password_too_short=Довжина Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ може бути меншою за %d Ñимволів. -non_local_account=Ðелокальні акаунти не можуть змінити пароль через Gitea. +non_local_account=Ðелокальні кориÑтувачі не можуть оновити Ñвій пароль через Ð²ÐµÐ±Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Gitea. verify=Підтвердити scratch_code=Одноразовий пароль -use_scratch_code=ВикориÑтовувати одноразовий пароль -twofa_scratch_used=Ви викориÑтовували одноразовий пароль. Ви були перенаправлені на Ñторінку налаштувань Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ— нового коду або Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð²ÑƒÑ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації. -twofa_passcode_incorrect=Ваш пароль Ñ” невірним. Якщо ви втратили приÑтрій, викориÑтовуйте ваш одноразовий пароль. +use_scratch_code=СкориÑтатиÑÑŒ одноразовим паролем +twofa_scratch_used=Ви ÑкориÑталиÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ð¸Ð¼ паролем. Ð’Ð°Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¾ на Ñторінку налаштувань двофакторної автентифікації, щоб видалити приÑтрій або згенерувати новий одноразовий пароль. +twofa_passcode_incorrect=Ваш пароль неправильний. Якщо ви загубили Ñвій приÑтрій, ÑкориÑтайтеÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ð¸Ð¼ паролем. twofa_scratch_token_incorrect=Ðевірний одноразовий пароль. login_userpass=Увійти login_openid=OpenID oauth_signup_tab=ЗареєÑтрувати обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signup_title=Повний новий обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signup_submit=Повний обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signin_tab=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñ–Ñнуючий обліковий Ð·Ð°Ð¿Ð¸Ñ +oauth_signup_title=Завершити реєÑтрацію облікового запиÑу +oauth_signup_submit=Поповнити обліковий Ð·Ð°Ð¿Ð¸Ñ +oauth_signin_tab=Прив'Ñзати до Ñ–Ñнуючого облікового запиÑу oauth_signin_title=Увійдіть щоб авторизувати пов'Ñзаний обліковий Ð·Ð°Ð¿Ð¸Ñ oauth_signin_submit=Прив'Ñзати обліковий Ð·Ð°Ð¿Ð¸Ñ openid_connect_submit=Під’єднатиÑÑ openid_connect_title=ПідключитиÑÑ Ð´Ð¾ Ñ–Ñнуючого облікового запиÑу -openid_connect_desc=Вибраний OpenID URI невідомий. Пов'Ñжіть його з новим обліковим запиÑом тут. +openid_connect_desc=Обраний OpenID URI невідомий. Зв'Ñжіть його тут з новим обліковим запиÑом. openid_register_title=Створити новий обліковий Ð·Ð°Ð¿Ð¸Ñ -openid_register_desc=Вибраний OpenID URI невідомий. Пов'Ñжіть йогоз новим обліковим запиÑом тут. +openid_register_desc=Обраний OpenID URI невідомий. Зв'Ñжіть його тут з новим обліковим запиÑом. disable_forgot_password_mail=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу вимкнено, оÑкільки не налаштована електронна пошта. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. -disable_forgot_password_mail_admin=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу доÑтупне лише піÑÐ»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти. Будь лаÑка, налаштуйте ел. пошту Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. -email_domain_blacklisted=З вказаним email реєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð°. +disable_forgot_password_mail_admin=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу доÑтупне лише за наÑвноÑті електронної пошти. Будь лаÑка, налаштуйте електронну пошту, щоб увімкнути Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. +email_domain_blacklisted=Ви не можете зареєÑтруватиÑÑ Ð· адреÑою електронної пошти. authorize_application=Ðвторизувати програму authorize_redirect_notice=Ð’Ð°Ñ Ð±ÑƒÐ´Ðµ переадреÑовано до %s, Ñкщо ви авторизуєте цю програму. authorize_application_created_by=Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° Ñтворена %s. -authorize_application_description=Якщо ви надаÑте цей доÑтуп, то він матиме доÑтуп до вÑÑ–Ñ… ваших даних облікового запиÑу, включаючи приватні репозиторії та організації. -authorize_title=Ðвторизуйвати "%s" Ð´Ð»Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу? +authorize_application_description=Якщо ви авторизуєте цю програму, їй буде надано дозвіл на Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ñієї інформації вашого облікового запиÑу, включно з приватними Ñховищами та організаціÑми. +authorize_title=Ðвторизувати "%s" Ð´Ð»Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу? authorization_failed=Помилка авторизації -sspi_auth_failed=Помилка SSPI-автентифікації +sspi_auth_failed=Помилка автентифікації SSPI password_pwned_err=Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ запит до HaveIBeenPwed [mail] view_it_on=ПереглÑнути на %s reply=або надішліть відповідь безпоÑередньо на цей електронний лиÑÑ‚ -link_not_working_do_paste=Ðе працює? Спробуйте Ñкопіювати та вÑтавити його в Ñвій браузер. +link_not_working_do_paste=Ðе працює? Спробуйте Ñкопіювати та вÑтавити його у браузер. hi_user_x=Привіт <b>%s</b>, activate_account=Будь лаÑка, активуйте ваш обліковий Ð·Ð°Ð¿Ð¸Ñ activate_account.title=%s, будь лаÑка, активуйте Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ activate_account.text_1=Привіт, <b>%[1]s</b>, дÑкуємо за реєÑтрацію на %[2]s! -activate_account.text_2=Перейдіть за цим поÑиланнÑм, щоб активувати ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð² <b>%s</b>: +activate_account.text_2=Будь лаÑка, перейдіть за наÑтупним поÑиланнÑм, щоб активувати Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ñ‚Ñгом <b>%s</b>: -activate_email=Підтвердить вашу адреÑу електронної пошти +activate_email=Підтвердіть адреÑу електронної пошти activate_email.title=%s, будь лаÑка, підтвердіть вашу адреÑу електронної пошти -activate_email.text=Перейдіть за цим поÑиланнÑм, щоб підтвердити вашу електронну адреÑу в <b>%s</b>: +activate_email.text=Будь лаÑка, перейдіть за наÑтупним поÑиланнÑм протÑгом <b>%s</b>, щоб підтвердити Ñвою електронну адреÑу: register_notify.title=%[1]s, лаÑкаво проÑимо до %[2]s -register_notify.text_1=це ваша е-пошта Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÑ”Ñтрації Ð´Ð»Ñ %s! +register_notify.text_1=це лиÑÑ‚ з підтвердженнÑм реєÑтрації на %s! register_notify.text_2=Тепер ви можете увійти Ñк: %s. -register_notify.text_3=Якщо цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ Ñтворено Ð´Ð»Ñ Ð²Ð°Ñ, будь лаÑка, Ñпочатку <a href="%s">вÑтановіть Ñвій пароль</a>. +register_notify.text_3=Якщо цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ñтворено Ð´Ð»Ñ Ð²Ð°Ñ, будь лаÑка, Ñпершу <a href="%s">вÑтановіть пароль</a>. -reset_password=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ облікового запиÑу -reset_password.title=%s, ви відправили запит на Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -reset_password.text=Перейдіть за цим поÑиланнÑм, щоб відновити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð² <b>%s</b>: +reset_password=Відновити обліковий Ð·Ð°Ð¿Ð¸Ñ +reset_password.title=%s, ви надіÑлали запит на Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +reset_password.text=Щоб відновити обліковий запиÑ, перейдіть за наÑтупним поÑиланнÑм протÑгом <b>%s</b>: register_success=РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ ÑƒÑпішна -issue_assigned.pull=@%[1]s призначив вам запит Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %[2]s в репозиторії %[3]s. -issue_assigned.issue=@%[1]s призначив вам задачу %[2]s у репозиторії %[3]s. +issue_assigned.pull=@%[1]s призначив вам запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %[2]s в Ñховищі %[3]s. +issue_assigned.issue=@%[1]s призначив вам задачу %[2]s в Ñховищі %[3]s. issue.x_mentioned_you=<b>@%s</b> згадав ваÑ: -issue.action.force_push=<b>%[1]s</b> force-pushed <b>%[2]s</b> з %[3]s в %[4]s. -issue.action.push_1=<b>@%[1]s</b> надіÑлав %[3]d коміти %[2]s -issue.action.push_n=<b>@%[1]s</b> відправив %[3]d коміти до %[2]s -issue.action.close=<b>@%[1]s</b> закрито #%[2]d. +issue.action.push_1=<b>@%[1]s</b> надіÑлав %[3]d коміт в %[2]s +issue.action.push_n=<b>@%[1]s</b> надіÑлав %[3]d коміти до %[2]s +issue.action.close=<b>@%[1]s</b> закрив #%[2]d. issue.action.reopen=<b>@%[1]s</b> заново відкрив #%[2]d. issue.action.merge=<b>@%[1]s</b> об'єднав #%[2]d до %[3]s. -issue.action.approve=<b>@%[1]s</b> затвердили цей запит на злиттÑ. -issue.action.reject=<b>@%[1]s</b> запитують зміни на цей запит на злиттÑ. -issue.action.review=<b>@%[1]s</b> прокоментували цей запит на злиттÑ. -issue.action.review_dismissed=<b>@%[1]s</b> відхилено оÑтанній відгук від %[2]s Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ. -issue.action.ready_for_review=<b>@%[1]s</b> позначили цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñк готовий до розглÑду. -issue.action.new=<b>@%[1]s</b> Ñтворили #%[2]d. +issue.action.approve=<b>@%[1]s</b> затвердив цей запит на злиттÑ. +issue.action.reject=<b>@%[1]s</b> запроÑив зміни у цьому запиті на злиттÑ. +issue.action.review=<b>@%[1]s</b> прокоментував цей запит на злиттÑ. +issue.action.review_dismissed=<b>@%[1]s</b> відхилив оÑтанній відгук від %[2]s на цей запит на злиттÑ. +issue.action.ready_for_review=<b>@%[1]s</b> позначив цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñк готовий до розглÑду. +issue.action.new=<b>@%[1]s</b> Ñтворив #%[2]d. issue.in_tree_path=Ð’ %s: release.new.subject=%s в %s випущено @@ -478,13 +478,13 @@ release.downloads=ЗвантаженнÑ: release.download.zip=Вихідний код (ZIP) release.download.targz=Вихідний код (TAR.GZ) -repo.transfer.subject_to=%s бажає передати"%s" в %s -repo.transfer.subject_to_you=%s бажає передати"%s" вам +repo.transfer.subject_to=%s хоче перенеÑти "%s" в %s +repo.transfer.subject_to_you=%s хоче передати"%s" вам repo.transfer.to_you=вам repo.transfer.body=Щоб прийнÑти або відхилити перейдіть до %s або проÑто ігноруйте. repo.collaborator.added.subject=%s додав Ð²Ð°Ñ Ð´Ð¾ %s -repo.collaborator.added.text=Ви були додані в ÑкоÑті Ñпівавтора репозиторію: +repo.collaborator.added.text=Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸ Ñк Ñпівавтора до Ñховища: team_invite.subject=%[1]s запрошує Ð²Ð°Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ організації %[2]s team_invite.text_1=%[1]s запрошує Ð²Ð°Ñ Ð´Ð¾ команди %[2]s в організації %[3]s. @@ -495,22 +495,22 @@ yes=Так no=ÐÑ– confirm=Підтвердити cancel=Відмінити -modify=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ +modify=Оновити [form] UserName=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача -RepoName=Ðазва репозиторію +RepoName=Ðазва Ñховища Email=ÐдреÑа електронної пошти Password=Пароль -Retype=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ -SSHTitle=Iм'Ñ SSH ключа +Retype=Підтвердити пароль +SSHTitle=Ðазва ключа SSH HttpsUrl=ÐдреÑа HTTPS PayloadUrl=URL обробника TeamName=Ðазва команди AuthName=Ðазва авторизації -AdminEmail=Email адмініÑтратора +AdminEmail=ÐдреÑа електронної пошти адмініÑтратора -NewBranchName=Ім'Ñ Ð½Ð¾Ð²Ð¾Ñ— гілки +NewBranchName=Ðазва нової гілки CommitSummary=Резюме коміту CommitMessage=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ CommitChoice=Вибір коміта @@ -520,58 +520,58 @@ Content=ЗміÑÑ‚ SSPISeparatorReplacement=Розділювач SSPIDefaultLanguage=Типова мова -require_error=` не може бути пуÑтим.` -alpha_dash_error=` повинен міÑтити тільки літерно-цифрові Ñимволи, Ð´ÐµÑ„Ñ–Ñ ('-') та підкреÑÐ»ÐµÐ½Ð½Ñ ('_'). ` -alpha_dash_dot_error=` повинен міÑтити тільки літерно-цифрові Ñимволи, Ð´ÐµÑ„Ñ–Ñ ('-') , підкреÑÐ»ÐµÐ½Ð½Ñ ('_') та точки ('.'). ` -git_ref_name_error=` повинен бути правильним поÑилальним ім'Ñм Git.` +require_error=` не може бути порожнім.` +alpha_dash_error=` повинен міÑтити тільки алфавітно-цифрові Ñимволи, Ð´ÐµÑ„Ñ–Ñ ('-') та підкреÑÐ»ÐµÐ½Ð½Ñ ('_').` +alpha_dash_dot_error=` повинен міÑтити тільки алфавітно-цифрові Ñимволи, Ð´ÐµÑ„Ñ–Ñ ('-'), підкреÑÐ»ÐµÐ½Ð½Ñ ('_') та крапку ('.').` +git_ref_name_error=` повинен бути правильно Ñформованим ім'Ñм-поÑиланнÑм на Git.` size_error=` повинен бути розмір %s.` -min_size_error=` повинен бути принаймні %s Ñимволів.` -max_size_error=` повинен бути не більш Ñк %s Ñимволів.` -email_error=` не Ñ” адреÑою електронної пошти.` +min_size_error=` має міÑтити принаймні %s Ñимволів.` +max_size_error=` має міÑтити не більше %s Ñимволів.` +email_error=` не Ñ” дійÑною адреÑою електронної пошти.` url_error=`"%s" не Ñ” дійÑною URL-адреÑою.` include_error=` повинен міÑтити підрÑдок "%s".` -glob_pattern_error=` неприпуÑтимий шаблон glob: %s.` -regex_pattern_error=` неприпуÑтимий шаблон regex: %s.` +glob_pattern_error=` недійÑний шаблон glob: %s.` +regex_pattern_error=` недійÑний шаблон регулÑрного виразу: %s.` unknown_error=Ðевідома помилка: captcha_incorrect=Код CAPTCHA неправильний. -password_not_match=Паролі не Ñпівпадають. -lang_select_error=Оберіть мову з переліку. +password_not_match=Паролі не збігаютьÑÑ. +lang_select_error=Оберіть мову зі ÑпиÑку. -username_been_taken=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже зайнÑто. -username_change_not_local_user=Ðелокальні кориÑтувачі не можуть змінити Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. +username_been_taken=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача вже зайнÑте. +username_change_not_local_user=Ðелокальні кориÑтувачі не можуть змінювати Ñвоє ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача. username_has_not_been_changed=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача не змінено -repo_name_been_taken=Ім'Ñ Ñ€ÐµÐ¿Ð¾Ð·Ñ–Ñ‚Ð¾Ñ€Ñ–ÑŽ вже викориÑтовуєтьÑÑ. -repository_files_already_exist=Файли вже Ñ–Ñнують Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ репозитарію. ЗвернітьÑÑ Ð´Ð¾ ÑиÑтемного адмініÑтратора. -repository_files_already_exist.adopt=Файли вже Ñ–Ñнують Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ репозиторію Ñ– можуть бути лише прийнÑті. -repository_files_already_exist.delete=Файли вже Ñ–Ñнують Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñховища. Ви повинні видалити Ñ—Ñ…. -repository_files_already_exist.adopt_or_delete=Файли вже Ñ–Ñнують Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ репозиторію. Їх можливо прийнÑти або видалити. -visit_rate_limit=ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ñті віддаленого доÑтупу. -2fa_auth_required=Ð”Ð»Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ доÑтупу необхідна двуфакторна аутентифікаціÑ. -org_name_been_taken=Ðазва організації вже зайнÑто. -team_name_been_taken=Ðазва команди вже зайнÑто. -team_no_units_error=Дозволити доÑтуп до принаймні одного розділу репозитарію. -email_been_used=Ð¦Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð° адреÑа вже викориÑтовуєтьÑÑ. -email_invalid=ÐдреÑа електронної пошти помилкова. +repo_name_been_taken=Ðазва Ñховища вже викориÑтовуєтьÑÑ. +repository_files_already_exist=Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñховища вже Ñ–Ñнують файли. ЗвернітьÑÑ Ð´Ð¾ ÑиÑтемного адмініÑтратора. +repository_files_already_exist.adopt=Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñховища вже Ñ–Ñнують файли, Ñ– Ñ—Ñ… можна лише прийнÑти. +repository_files_already_exist.delete=Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñховища вже Ñ–Ñнують файли. Ви повинні видалити Ñ—Ñ…. +repository_files_already_exist.adopt_or_delete=Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñховища вже Ñ–Ñнують файли. Прийміть Ñ—Ñ… або видаліть. +visit_rate_limit=Віддалений доÑтуп відхилено у зв'Ñзку з обмеженнÑм кількоÑті Ñпроб. +2fa_auth_required=Ð”Ð»Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ доÑтупу необхідна двофакторна автентифікаціÑ. +org_name_been_taken=Ðазва організації вже зайнÑта. +team_name_been_taken=Ðазва команди вже зайнÑта. +team_no_units_error=Дозволити доÑтуп до принаймні одного розділу Ñховища. +email_been_used=ÐдреÑа електронної пошти вже викориÑтовуєтьÑÑ. +email_invalid=ÐдреÑа електронної пошти недійÑна. openid_been_used=ÐдреÑа OpenID '%s' вже викориÑтовуєтьÑÑ. username_password_incorrect=Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або пароль. -password_complexity=Пароль не відповідає вимогам до ÑкладноÑті: -password_lowercase_one=Принаймні одна буква в нижньому регіÑтрі -password_uppercase_one=Принаймні одна буква в верхньому регіÑтрі +password_complexity=Пароль не відповідає вимогам ÑкладноÑті: +password_lowercase_one=Принаймні один Ñимвол нижнього регіÑтру +password_uppercase_one=Принаймні один Ñимвол верхнього регіÑтру password_digit_one=Принаймні одна цифра -password_special_one=Принаймні один Ñпеціальний Ñимвол (пунктуаціÑ, дужки, лапки тощо) -enterred_invalid_repo_name=Ðевірно введено ім'Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ. -enterred_invalid_org_name=Ðевірно введено ім'Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ—. -enterred_invalid_owner_name=Ім'Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ влаÑника не Ñ” дійÑним. -enterred_invalid_password=Введений вами пароль некоректний. +password_special_one=Принаймні один Ñпеціальний Ñимвол (розділові знаки, дужки, лапки тощо) +enterred_invalid_repo_name=Ви ввели неправильну назву Ñховища. +enterred_invalid_org_name=Ви ввели неправильну назву організації. +enterred_invalid_owner_name=Ім'Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ влаÑника недійÑне. +enterred_invalid_password=Ви ввели неправильний пароль. unset_password=КориÑтувач не вÑтановив пароль. -user_not_exist=Даний кориÑтувач не Ñ–Ñнує. +user_not_exist=КориÑтувач не Ñ–Ñнує. team_not_exist=Команда не Ñ–Ñнує. -last_org_owner=Ви не можете видалити оÑтаннього кориÑтувача з команди 'влаÑники'. У кожній команді має бути принаймні один влаÑник. +last_org_owner=Ви не можете видалити оÑтаннього кориÑтувача з групи 'влаÑників'. Ð’ організації має бути принаймні один влаÑник. cannot_add_org_to_team=Організацію неможливо додати Ñк учаÑника команди. -invalid_ssh_key=Ðеможливо перевірити ваш SSH ключ: %s -invalid_gpg_key=Ðеможливо перевірити ваш GPG ключ: %s -invalid_ssh_principal=Ðекоректний відповідальний: %s +invalid_ssh_key=Ðе вдаєтьÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ ключ SSH: %s +invalid_gpg_key=Ðе вдаєтьÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ ключ GPG: %s +invalid_ssh_principal=Ðевірна ідентичніÑть: %s auth_failed=Помилка автентифікації: %v @@ -581,21 +581,20 @@ target_ref_not_exist=Цільове поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ðµ Ñ–Ñнує %s admin_cannot_delete_self=Ви не можете видалити Ñебе, допоки ви адмініÑтратор. Будь лаÑка, Ñпочатку видаліть права адмініÑтратора. [user] -change_avatar=Змінити Ñвій аватар… -repositories=Репозиторії +change_avatar=Змінити аватар… +repositories=Сховища activity=Публічна активніÑть -followers=Читачі +followers=ПоÑлідовники show_more=Показати більше -starred=Обрані Репозиторії -watched=ВідÑтежувані репозиторії +starred=Обрані Ñховища +watched=ВідÑтежувані Ñховища code=Код -projects=Проєкт +projects=Проєкти overview=ОглÑд -following=Читає -follow=ПідпиÑатиÑÑ -unfollow=ВідпиÑатиÑÑ +follow=Стежити +unfollow=Ðе Ñтежити user_bio=Ð‘Ñ–Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ñ -disabled_public_activity=Цей кориÑтувач вимкнув публічний показ діÑльноÑті. +disabled_public_activity=Цей кориÑтувач вимкнув публічну видиміÑть активноÑті. show_on_map=Показати це міÑце на карті settings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача @@ -625,7 +624,7 @@ appearance=Зовнішній виглÑд password=Пароль security=Безпека avatar=Ðватар -ssh_gpg_keys=SSH / GPG ключі +ssh_gpg_keys=Ключі SSH / GPG social=Соціальні облікові запиÑи applications=Додатки orgs=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñми @@ -644,7 +643,7 @@ update_profile=Оновити профіль update_language=Оновити мову update_language_success=Мову оновлено. update_profile_success=Профіль уÑпішно оновлено. -change_username=Ваше Ім'Ñ ÐºÑ€Ð¸Ñтувача було змінено. +change_username=Ваше ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача змінено. continue=Продовжити cancel=Відмінити language=Мова @@ -670,13 +669,13 @@ keep_activity_private_popup=Показувати вашу активніÑть Ð lookup_avatar_by_mail=Знайти Ðватар за адреÑою електронної пошти federated_avatar_lookup=Знайти зовнішній аватар -enable_custom_avatar=Увімкнути кориÑтувацькі аватари -choose_new_avatar=Оберіть новий аватар +enable_custom_avatar=Увімкнути кориÑтувацький аватар +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_avatar_success=Ваш аватар оновлено. update_user_avatar_success=Ðватар кориÑтувача оновлено. cropper_prompt=Ви можете відредагувати Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ збереженнÑм. Відредаговане Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ збережено Ñк PNG. @@ -685,64 +684,64 @@ old_password=Поточний пароль new_password=Ðовий пароль retype_new_password=Підтвердити новий пароль password_incorrect=Поточний пароль неправильний. -change_password_success=Ваш пароль був оновлений. Тепер увійдіть в ÑиÑтему, викориÑтовуючи новий пароль. -password_change_disabled=Ðелокальні акаунти не можуть змінити пароль через Gitea. +change_password_success=Ваш пароль оновлено. Відтепер входьте в ÑиÑтему, викориÑтовуючи новий пароль. +password_change_disabled=Ðелокальні кориÑтувачі не можуть оновити Ñвій пароль через Ð²ÐµÐ±Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Gitea. emails=ÐдреÑа електронної пошти -manage_emails=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑами ел. пошти -manage_themes=Виберіть тему за замовчуваннÑм -manage_openid=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ OpenID +manage_emails=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑами електронної пошти +manage_themes=Обрати типову тему +manage_openid=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑами OpenID theme_desc=Ð¦Ñ Ñ‚ÐµÐ¼Ð° буде типовою Ð´Ð»Ñ Ð²Ñього Ñайту. primary=ОÑновний activated=Ðктивовано requires_activation=Потрібна Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ -primary_email=Зробити оÑновним +primary_email=Зробити оÑновною activate_email=ÐадіÑлати активацію -activations_pending=Ðктивації в очікуванні +activations_pending=ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— delete_email=Видалити email_deletion=Видалити адреÑу електронної пошти -email_deletion_desc=Електронна адреÑа та пов'Ñзана з нею Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ видалена з вашого облікового запиÑу. Git коміти, здійÑнені через цю електронну адреÑу, залишитьÑÑ Ð±ÐµÐ· змін. Продовжити? -email_deletion_success=ÐдреÑу електронної пошти було видалено. +email_deletion_desc=ÐдреÑа електронної пошти та пов'Ñзана з нею Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ видалена з вашого облікового запиÑу. Коміти Git, здійÑнені через цю адреÑу електронну пошту, залишитьÑÑ Ð±ÐµÐ· змін. Продовжити? +email_deletion_success=ÐдреÑу електронної пошти видалено. theme_update_success=Тему оновлено. -theme_update_error=Вибрана тема не Ñ–Ñнує. +theme_update_error=Обрана тема не Ñ–Ñнує. openid_deletion=Видалити адреÑу OpenID -openid_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— OpenID-адреÑи з вашого облікового запиÑу заборонÑÑ” вам входити з ним. Продовжити? -openid_deletion_success=ÐдреÑа OpenID була видалена. +openid_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— адреÑи OpenID не дозволить вам увійти за нею. Продовжити? +openid_deletion_success=ÐдреÑу OpenID видалено. add_new_email=Додати нову адреÑу електронної пошти add_new_openid=Додати новий OpenID URI add_email=Додати адреÑу електронної пошти add_openid=Додати OpenID URI add_email_success=Додано нову адреÑу електронної пошти. -email_preference_set_success=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти уÑпішно вÑтановлені. -add_openid_success=Ðова адреÑа OpenID була додана. +email_preference_set_success=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти уÑпішно вÑтановлено. +add_openid_success=Додано нову адреÑу OpenID. keep_email_private=Приховати адреÑу електронної пошти -openid_desc=OpenID дозволÑÑ” делегувати аутентифікацію зовнішньому поÑтачальнику поÑлуг. +openid_desc=OpenID дозволÑÑ” делегувати автентифікацію зовнішньому поÑтачальнику поÑлуг. -manage_ssh_keys=Керувати SSH ключами -manage_ssh_principals=Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ SSH Ñертифікатами кориÑтувачів -manage_gpg_keys=Керувати GPG ключами +manage_ssh_keys=Керувати ключами SSH +manage_ssh_principals=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ‡Ð½Ð¾ÑÑ‚Ñми Ñертифікатів SSH +manage_gpg_keys=Керувати ключами SSH add_key=Додати ключ -ssh_desc=Ці відкриті SSH-ключі пов'Ñзані з вашим обліковим запиÑом. Відповідні приватні ключі дозволÑють отримати повний доÑтуп до ваших репозиторіїв. -principal_desc=Ці наÑтройки SSH Ñертифікатів вказані у вашому обліковому запиÑÑ– та надають повний доÑтуп до ваших репозиторіїв. -gpg_desc=Ці публічні ключі GPG пов'Ñзані з вашим обліковим запиÑом. Тримайте Ñвої приватні ключі в безпеці, оÑкільки вони дозволÑють здійÑнювати перевірку комітів. -ssh_helper=<strong>Потрібна допомога?</strong> ДивітьÑÑ Ð³Ñ–Ð´ на GitHub з <a href="%s"> генерації ключів SSH</a> або Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ <a href="%s">типових неполадок SSH</a>. -gpg_helper=<strong> Потрібна допомога? </strong> ПереглÑньте поÑібник GitHub <a href="%s"> про GPG </a>. -add_new_key=Додати SSH ключ -add_new_gpg_key=Додати GPG ключ +ssh_desc=Ці публічні ключі SSH пов'Ñзані з вашим обліковим запиÑом. Відповідні приватні ключі надають повний доÑтуп до ваших Ñховищ. +principal_desc=Ці ідентифікатори Ñертифікатів SSH прив'Ñзані до вашого облікового запиÑу Ñ– надають повний доÑтуп до ваших Ñховищ. +gpg_desc=Ці публічні ключі GPG пов'Ñзані з вашим обліковим запиÑом. Зберігайте Ñвої приватні ключі в безпеці, оÑкільки вони дозволÑють підтверджувати коміти. +ssh_helper=<strong>Потрібна допомога?</strong> ОзнайомтеÑÑ Ð· інÑтрукцією GitHub щодо <a href="%s">ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñних ключів SSH</a> або Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ <a href="%s">типових неполадок SSH.</a> +gpg_helper=<strong>Потрібна допомога?</strong> ПереглÑньте поÑібник GitHub <a href="%s">про GPG</a>. +add_new_key=Додати ключ SSH +add_new_gpg_key=Додати ключ GPG key_content_ssh_placeholder=ПочинаєтьÑÑ Ð· 'ssh-ed25519', 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'sk-ecdsa-sha2-nistp256@openssh.com', або 'sk-ssh-ed25519@openssh.com' key_content_gpg_placeholder=ПочинаєтьÑÑ Ð· '-----BEGIN PGP PUBLIC KEY BLOCK-----' -add_new_principal=Додати кориÑтувача -ssh_key_been_used=Цей SSH ключ вже був додано до Ñервера. +add_new_principal=Додати ідентичніÑть +ssh_key_been_used=Цей ключ SSH вже було додано до Ñервера. ssh_key_name_used=Ключ SSH з таким ім'Ñм вже Ñ–Ñнує у вашому обліковому запиÑÑ–. -ssh_principal_been_used=Цей кориÑтувач вже був доданий на Ñервер. +ssh_principal_been_used=Цю ідентичніÑть вже було додано до Ñервера. gpg_key_id_used=Публічний ключ GPG з таким Ñамим ідентифікатором вже Ñ–Ñнує. -gpg_no_key_email_found=Цей ключ GPG не відповідає жодній активованій поштовій адреÑÑ–, Ñка пов'Ñзана з вашим обліковим запиÑом. Його вÑе рівно можна додати, Ñкщо ви підпишете наданий токен. -gpg_key_matched_identities=Відповідні отримувачі: -gpg_key_matched_identities_long=Вбудовані ідентифікатори цього ключа збігаютьÑÑ Ð· наÑтупними активованими адреÑами електронної пошти вказаного кориÑтувача. Коміти, Ñкі відповідають цим адреÑам, можуть бути підтверджені цим ключем. +gpg_no_key_email_found=Цей ключ GPG не відповідає жодній активованій адреÑÑ– електронної пошти, пов'Ñзаній з вашим обліковим запиÑом. Його вÑе одно можна додати, Ñкщо ви підпишете наданий токен. +gpg_key_matched_identities=Відповідні ідентичноÑті: +gpg_key_matched_identities_long=Вбудовані ідентифікатори цього ключа збігаютьÑÑ Ð· наÑтупними активованими адреÑами електронної пошти цього кориÑтувача. За допомогою цього ключа можна перевірÑти коміти, що відповідають цим адреÑам електронної пошти. gpg_key_verified=Перевірений ключ -gpg_key_verified_long=Ключ перевірений за допомогою токена Ñ– може бути викориÑтано Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñ–Ð², Ñкі відповідають будь-Ñкій з активованих Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача, на додачу до будь-Ñких відповідних ідентифікацій Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ключа. +gpg_key_verified_long=Ключ був перевірений токеном Ñ– може бути викориÑтаний Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ комітів, що відповідають будь-Ñким активованим адреÑам електронної пошти Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача, а також будь-Ñких ідентифікаторів, що відповідають цьому ключу. gpg_key_verify=Підтвердити -gpg_invalid_token_signature=Ðаданий ключ GPG, Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ñ– токен не Ñпівпадають або токен заÑтарів. +gpg_invalid_token_signature=Ðадані ключ GPG, Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ñ– токен не збігаютьÑÑ Ð°Ð±Ð¾ токен заÑтарілий. gpg_token_required=Вам потрібно надати Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð´Ð»Ñ Ð½Ð¸Ð¶Ñ‡ÐµÐ²ÐºÐ°Ð·Ð°Ð½Ð¾Ð³Ð¾ токена gpg_token=Токен gpg_token_help=Ви можете Ñтворити Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð·Ð° допомогою: @@ -750,101 +749,101 @@ gpg_token_signature=ТекÑтовий (armored) Ð¿Ñ–Ð´Ð¿Ð¸Ñ GPG key_signature_gpg_placeholder=`ПочинаєтьÑÑ Ð· "-----BEGIN PGP SIGNATURE-----"` verify_gpg_key_success=Ключ GPG '%s' перевірено. ssh_key_verified=Перевірений ключ -ssh_key_verify=Підтвердити +ssh_key_verify=Перевірити ssh_token_required=Вам потрібно надати Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð´Ð»Ñ Ð½Ð¸Ð¶Ñ‡ÐµÐ²ÐºÐ°Ð·Ð°Ð½Ð¾Ð³Ð¾ токена ssh_token=Токен ssh_token_help=Ви можете Ñтворити Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð·Ð° допомогою: verify_ssh_key_success=Ключ SSH '%s' перевірено. subkeys=Підключі -key_id=ID ключа -key_name=Ім'Ñ ÐºÐ»ÑŽÑ‡Ð° +key_id=Ідентифікатор ключа +key_name=Ðазва ключа key_content=ЗміÑÑ‚ principal_content=ЗміÑÑ‚ -add_key_success=SSH ключ '%s' додано. -add_gpg_key_success=GPG ключ '%s' додано. +add_key_success=Ключ SSH '%s' додано. +add_gpg_key_success=Ключ GPG '%s' додано. delete_key=Видалити -ssh_key_deletion=Видалити SSH ключ -gpg_key_deletion=Видалити GPG ключ -ssh_principal_deletion=Видалити SSH Ñертифікат кориÑтувача +ssh_key_deletion=Видалити ключ SSH +gpg_key_deletion=Видалити ключ GPG +ssh_principal_deletion=Видалити ідентичніÑть Ñертифікату SSH ssh_key_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° SSH ÑкаÑовує доÑтуп до вашого облікового запиÑу. Продовжити? -gpg_key_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ GPG ключа ÑкаÑовує перевірку підпиÑаних ним комітів. Продовжити? -ssh_principal_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° SSH ÑкаÑовує доÑтуп до вашого облікового запиÑу. Продовжити? -ssh_key_deletion_success=SSH ключ був видалений. -gpg_key_deletion_success=GPG було видалено. -ssh_principal_deletion_success=КориÑтувача видалено. +gpg_key_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ð° GPG ÑкаÑовує перевірку підпиÑаних ним комітів. Продовжити? +ssh_principal_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ‡Ð½Ð¾Ñті Ñертифіката SSH ÑкаÑовує доÑтуп до вашого облікового запиÑу. Продовжити? +ssh_key_deletion_success=Ключ SSH видалено. +gpg_key_deletion_success=Ключ GPG видалено. +ssh_principal_deletion_success=ІдентичніÑть видалено. added_on=Додано %s valid_until_date=ДійÑно до %s valid_forever=ДійÑний завжди -last_used=ОÑтаннє викориÑÑ‚Ð°Ð½Ð½Ñ -no_activity=Жодної діÑльноÑті -can_read_info=Читати -can_write_info=ÐапиÑати -key_state_desc=Цей ключ викориÑтовувавÑÑ Ð² оÑтанні 7 днів -token_state_desc=Цей токен викориÑтовувавÑÑ Ð² оÑтанні 7 днів -principal_state_desc=УчаÑтник був на Ñайті в оÑтанні 7 днів +last_used=ВоÑтаннє викориÑтано +no_activity=ÐÐµÑ‰Ð¾Ð´Ð°Ð²Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–Ñть відÑÑƒÑ‚Ð½Ñ +can_read_info=Ð§Ð¸Ñ‚Ð°Ð½Ð½Ñ +can_write_info=Ð—Ð°Ð¿Ð¸Ñ +key_state_desc=Цей ключ викориÑтовувавÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом оÑтанніх 7 днів +token_state_desc=Цей токен викориÑтовувавÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом оÑтанніх 7 днів +principal_state_desc=Ð¦Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ‡Ð½Ñ–Ñть викориÑтовувалаÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом оÑтанніх 7 днів show_openid=Показати у профілю -hide_openid=Ðе показувати у профілі +hide_openid=Приховати з профілю ssh_disabled=SSH вимкнено ssh_signonly=SSH наразі вимкнено, тому ці ключі викориÑтовуютьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ підпиÑу комітів. -ssh_externally_managed=Цей ключ SSH має зовнішнє ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача -manage_social=Керувати зв'Ñзаними обліковими запиÑами Ñоціальних мереж +ssh_externally_managed=Цей ключ SSH керуєтьÑÑ Ð·Ð·Ð¾Ð²Ð½Ñ– Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача +manage_social=Керувати пов'Ñзаними обліковими запиÑами Ñоціальних мереж unbind=Від'єднати -manage_access_token=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð°Ð¼Ð¸ доÑтупу -generate_new_token=Згенерувати новий токен -tokens_desc=Ці токени надають доÑтуп до вашого облікового запиÑу за допомогою Gitea API. -token_name=Ім'Ñ Ñ‚Ð¾ÐºÐµÐ½Ñƒ +manage_access_token=Керувати токенами доÑтупу +generate_new_token=Створити новий токен +tokens_desc=Ці токени надають доÑтуп до вашого облікового запиÑу за допомогою API Gitea. +token_name=Ðазва токену generate_token=Згенерувати токен -generate_token_success=Ваш новий токен був Ñтворений. Скопіюйте його зараз, оÑкільки він не буде показаний знову. +generate_token_success=Ваш новий токен Ñтворено. Скопіюйте його зараз, оÑкільки він не буде показаний знову. generate_token_name_duplicate=Ðазва програми <strong>%s</strong> вже викориÑтовуєтьÑÑ. Будь лаÑка, викориÑтайте нову. delete_token=Видалити access_token_deletion=Видалити токен доÑтупу access_token_deletion_cancel_action=Відмінити access_token_deletion_confirm_action=Видалити -delete_token_success=Токен був знищений. Програми, що викориÑтовують його, більше не мають доÑтупу до вашого облікового запиÑу. +delete_token_success=Токен знищено. Додатки, що викориÑтовують його, більше не мають доÑтупу до вашого облікового запиÑу. permissions_access_all=Ð’ÑÑ– (загальнодоÑтупні, приватні та з обмеженим доÑтупом) permission_not_set=Ðе вÑтановлено permission_no_access=Ðемає доÑтупу permission_read=Прочитані permission_write=Ð§Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ– Ð·Ð°Ð¿Ð¸Ñ permission_anonymous_read=Ðнонімне Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ -permission_everyone_read=УÑÑ– читають -permission_everyone_write=УÑÑ– пишуть +permission_everyone_read=Ð§Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… +permission_everyone_write=Ð—Ð°Ð¿Ð¸Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… permissions_list=Дозволи: -manage_oauth2_applications=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð°Ð¼Ð¸ OAuth2 -edit_oauth2_application=Редагувати програму OAuth2 -oauth2_applications_desc=Програми OAuth2 дають можливіÑть вашим Ñтороннім програмам надійно аутентифікувати кориÑтувачів у цьому екземплÑрі Gitea. -remove_oauth2_application=Видалити програму OAuth2 -remove_oauth2_application_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸ OAuth2 ÑкаÑовує доÑтуп до вÑÑ–Ñ… підпиÑаних маркерів доÑтупу. Продовжити? -remove_oauth2_application_success=Програму видалено. -create_oauth2_application=Створити нову програму OAuth2 -create_oauth2_application_button=Створити програму +manage_oauth2_applications=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ°Ð¼Ð¸ OAuth2 +edit_oauth2_application=Редагувати додаток OAuth2 +oauth2_applications_desc=Додатки OAuth2 дозволÑють вашому Ñторонньому додатку безпечно автентифікувати кориÑтувачів у цьому екземплÑрі Gitea. +remove_oauth2_application=Видалити додаток OAuth2 +remove_oauth2_application_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ° OAuth2 ÑкаÑує доÑтуп до вÑÑ–Ñ… підпиÑаних токенів доÑтупу. Продовжити? +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_application_name=Ðазва додатка save_application=Зберегти -oauth2_client_id=ID Клієнта +oauth2_client_id=Ідентифікатор клієнта oauth2_client_secret=Ключ клієнта oauth2_regenerate_secret=Відновити ключ -oauth2_regenerate_secret_hint=Ви втратили Ñвій ключ? +oauth2_regenerate_secret_hint=Втратили ключ? oauth2_application_edit=Редагувати oauth2_application_create_description=Програми OAuth2 надають вашим Ñтороннім програмам доÑтуп до облікових запиÑів кориÑтувачів у цьому екземплÑрі. authorized_oauth2_applications=Ðвторизовані програми OAuth2 revoke_key=Відкликати revoke_oauth2_grant=СкаÑувати доÑтуп -revoke_oauth2_grant_description=СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— програми третьої Ñторони не дозволить їй отримувати доÑтуп до ваших даних. Ви впевнені? +revoke_oauth2_grant_description=СкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñтороннього додатка не дозволить йому отримувати доÑтуп до ваших даних. Ви впевнені? -twofa_is_enrolled=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° даний Ñ‡Ð°Ñ <strong>викориÑтовує</strong> двофакторну автентифікацію. -twofa_not_enrolled=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– не викориÑтовує двофакторну автентифікаціїю. +twofa_is_enrolled=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– <strong>викориÑтовує</strong> двофакторну автентифікацію. +twofa_not_enrolled=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– не викориÑтовує двофакторну автентифікацію. twofa_disable=Вимкнути двофакторну автентифікацію twofa_enroll=Увімкнути двофакторну автентифікацію -twofa_disable_note=При необхідноÑті можна відключити двофакторну автентифікацію. +twofa_disable_note=За потреби ви можете вимкнути двофакторну автентифікацію. twofa_disable_desc=Ð’Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації зробить ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¼ÐµÐ½Ñˆ безпечним. Продовжити? -twofa_disabled=Двофакторна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð°. -scan_this_image=ПроÑкануйте це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ додатком Ð´Ð»Ñ Ð´Ð²ÑƒÑ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації: -or_enter_secret=Ðбо введіть Ñекрет: %s +twofa_disabled=Двофакторну автентифікацію вимкнено. +scan_this_image=ВідÑкануйте це Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ð¼ додатком Ð´Ð»Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації: +or_enter_secret=Ðбо введіть код: %s then_enter_passcode=І введіть пароль, Ñкий відображаєтьÑÑ Ð² додатку: passcode_invalid=Ðекоректний пароль. Спробуй ще раз. twofa_failed_get_secret=Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ñекрет. diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 9593e9d442..c90711f903 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -91,7 +91,7 @@ add=æ·»åŠ add_all=æ·»åŠ æ‰€æœ‰ remove=移除 remove_all=移除所有 -remove_label_str=åˆ é™¤æ ‡ç¾ã€Œ%s〠+remove_label_str=åˆ é™¤æ ‡è®°ã€Œ%s〠edit=编辑 view=查看 test=测试 @@ -262,7 +262,7 @@ host=æ•°æ®åº“主机 user=用户å password=æ•°æ®åº“用户密ç db_name=æ•°æ®åº“åç§° -db_schema=Schema +db_schema=æž¶æž„ db_schema_helper=留空则数æ®åº“ä¸é»˜è®¤å€¼ä¸º("public")。 ssl_mode=SSL path=æ•°æ®åº“文件路径 @@ -637,7 +637,7 @@ unset_password=登录用户没有设置密ç 。 unsupported_login_type=æ¤ç™»å½•ç±»åž‹ä¸æ”¯æŒæ‰‹åŠ¨åˆ é™¤å¸æˆ·ã€‚ user_not_exist=该用户ä¸å˜åœ¨ team_not_exist=团队ä¸å˜åœ¨ -last_org_owner=您ä¸èƒ½ä»Ž "所有者" 团队ä¸åˆ 除最åŽä¸€ä¸ªç”¨æˆ·ã€‚组织ä¸å¿…须至少有一个所有者。 +last_org_owner=您ä¸èƒ½ä»Žã€Œæ‰€æœ‰è€…ã€å›¢é˜Ÿä¸åˆ 除最åŽä¸€ä¸ªç”¨æˆ·ã€‚组织ä¸å¿…须至少有一个所有者。 cannot_add_org_to_team=组织ä¸èƒ½åŠ å…¥åˆ°å›¢é˜Ÿä¸ã€‚ duplicate_invite_to_team=æ¤ç”¨æˆ·å·²è¢«é‚€è¯·ä¸ºå›¢é˜Ÿæˆå‘˜ã€‚ organization_leave_success=您已æˆåŠŸç¦»å¼€ç»„ç»‡ %s。 @@ -752,11 +752,11 @@ cancel=å–æ¶ˆæ“作 language=界é¢è¯è¨€ ui=主题 hidden_comment_types=éšè—的评论类型 -hidden_comment_types_description=æ¤å¤„选ä¸çš„æ³¨é‡Šç±»åž‹ä¸ä¼šæ˜¾ç¤ºåœ¨å·¥å•页é¢ä¸ã€‚æ¯”å¦‚ï¼Œå‹¾é€‰ã€Œæ ‡ç¾ã€åˆ 除所有「{user} æ·»åŠ /åˆ é™¤çš„ {label}ã€æ³¨é‡Šã€‚ +hidden_comment_types_description=æ¤å¤„选ä¸çš„æ³¨é‡Šç±»åž‹ä¸ä¼šæ˜¾ç¤ºåœ¨å·¥å•页é¢ä¸ã€‚æ¯”å¦‚ï¼Œå‹¾é€‰ã€Œæ ‡è®°ã€åˆ 除所有「{user} æ·»åŠ /åˆ é™¤çš„ {label}ã€æ³¨é‡Šã€‚ hidden_comment_types.ref_tooltip=注释æ¤é—®é¢˜åœ¨ä½•处被æåŠè¿‡ï¼Œå¦‚å¦ä¸€ä¸ªé—®é¢˜ã€ä»£ç æäº¤ç‰ hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与æ¤é—®é¢˜ç›¸å…³è”的分支/æ ‡ç¾ comment_type_group_reference=引用 -comment_type_group_label=æ ‡ç¾ +comment_type_group_label=æ ‡è®° comment_type_group_milestone=里程碑 comment_type_group_assignee=被指派人 comment_type_group_title=æ ‡é¢˜ @@ -801,7 +801,7 @@ manage_openid=ç®¡ç† OpenID åœ°å€ email_desc=您的主邮箱地å€å°†ç”¨äºŽé€šçŸ¥ã€å¯†ç æ¢å¤ä»¥åŠåŸºäºŽç½‘页的 Git æ“作(如果它未设为éšè—)。 theme_desc=这将是您在整个网站上的默认主题。 theme_colorblindness_help=颜色障ç¢ä¸»é¢˜æ”¯æŒ -theme_colorblindness_prompt=Gitea åªèƒ½èŽ·å¾—ä¸€äº›åŸºæœ¬çš„é¢œè‰²éšœç¢æ”¯æŒï¼Œè¿™äº›ä¸»é¢˜åªå®šä¹‰äº†å°‘数颜色。 这项工作ä»åœ¨è¿›è¡Œä¸ï¼Œå¯ä»¥é€šè¿‡åœ¨ä¸»é¢˜çš„ CSS 文件ä¸å®šä¹‰æ›´å¤šé¢œè‰²æ¥åšæ›´å¤šçš„æ”¹è¿›ã€‚ +theme_colorblindness_prompt=Gitea åªèƒ½èŽ·å¾—ä¸€äº›åŸºæœ¬çš„é¢œè‰²éšœç¢æ”¯æŒï¼Œè¿™äº›ä¸»é¢˜åªå®šä¹‰äº†å°‘数颜色。这项工作ä»åœ¨è¿›è¡Œä¸ï¼Œå¯ä»¥é€šè¿‡åœ¨ä¸»é¢˜çš„ CSS 文件ä¸å®šä¹‰æ›´å¤šé¢œè‰²æ¥åšæ›´å¤šçš„æ”¹è¿›ã€‚ primary=ä¸»è¦ activated=已激活 requires_activation=éœ€è¦æ¿€æ´» @@ -817,7 +817,7 @@ theme_update_success=您的主题已更新。 theme_update_error=所选主题ä¸å˜åœ¨ã€‚ openid_deletion=移除 OpenID åœ°å€ openid_deletion_desc=åˆ é™¤æ¤ OpenID 地å€å°†ä¼šé˜»æ¢æ‚¨ä½¿ç”¨å®ƒè¿›è¡Œç™»å½•。您确定è¦ç»§ç»å—? -openid_deletion_success=OpenID地å€å·²ç§»é™¤ã€‚ +openid_deletion_success=OpenID 地å€å·²ç§»é™¤ã€‚ add_new_email=æ·»åŠ æ–°çš„é‚®ç®±åœ°å€ add_new_openid=æ·»åŠ æ–°çš„ OpenID URI add_email=æ–°å¢žé‚®ç®±åœ°å€ @@ -831,23 +831,23 @@ keep_email_private_popup=这将会éšè—您的邮箱地å€ï¼Œä¸ä»…在您的个ä openid_desc=OpenID 让您å¯ä»¥å°†è®¤è¯è½¬å‘到外部æœåŠ¡ã€‚ manage_ssh_keys=ç®¡ç† SSH 密钥 -manage_ssh_principals=管ç†SSHè¯ä¹¦è§„则 +manage_ssh_principals=ç®¡ç† SSH è¯ä¹¦è§„则 manage_gpg_keys=ç®¡ç† GPG 密钥 add_key=å¢žåŠ å¯†é’¥ ssh_desc=这些 SSH 公钥已ç»å…³è”到您的账å·ã€‚相应的ç§é’¥æ‹¥æœ‰å®Œå…¨æ“作您仓库的æƒé™ã€‚ -principal_desc=这些SSHè¯ä¹¦è§„则已关è”到您的账å·å°†å…许完全访问您所有仓库。 +principal_desc=这些 SSH è¯ä¹¦è§„则已关è”到您的账å·å°†å…许完全访问您所有仓库。 gpg_desc=这些 GPG 公钥已ç»å…³è”到您的账å·ã€‚请妥善ä¿ç®¡æ‚¨çš„ç§é’¥å› ä¸ºä»–ä»¬å°†è¢«ç”¨äºŽè®¤è¯æäº¤ã€‚ ssh_helper=<strong>需è¦å¸®åŠ©ï¼Ÿ</strong> 请查看有关 <a href="%s">å¦‚ä½•ç”Ÿæˆ SSH 密钥</a> 或 <a href="%s">å¸¸è§ SSH 问题</a> å¯»æ‰¾ç”æ¡ˆã€‚ -gpg_helper=<strong>需è¦å¸®åŠ©å—?</strong>看一看 GitHub <a href="%s">关于GPG</a> 的指导。 +gpg_helper=<strong>需è¦å¸®åŠ©å—?</strong>看一看 GitHub <a href="%s">关于 GPG</a> 的指导。 add_new_key=å¢žåŠ SSH 密钥 add_new_gpg_key=æ·»åŠ çš„ GPG 密钥 key_content_ssh_placeholder=以 'ssh-ed25519'〠'ssh-rsa'〠'ecdsa-sha2-nistp256'ã€'ecdsa-sha2-nistp384'ã€'ecdsa-sha2-nistp521'〠'sk-ecdsa-sha2-nistp256@openssh.com' 或 'sk-ssh-ed25519@openssh.com' 开头 key_content_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 add_new_principal=æ·»åŠ è§„åˆ™ ssh_key_been_used=æ¤ SSH å¯†é’¥å·²æ·»åŠ åˆ°æœåŠ¡å™¨ã€‚ -ssh_key_name_used=使用相åŒåç§°çš„SSH公钥已ç»å˜åœ¨ï¼ +ssh_key_name_used=使用相åŒåç§°çš„ SSH 公钥已ç»å˜åœ¨ã€‚ ssh_principal_been_used=æ¤è§„则已ç»åŠ å…¥åˆ°äº†æœåŠ¡å™¨ã€‚ -gpg_key_id_used=使用相åŒåç§°çš„GPG公钥已ç»å˜åœ¨ï¼ +gpg_key_id_used=使用相åŒåç§°çš„ GPG 公钥已ç»å˜åœ¨ã€‚ gpg_no_key_email_found=æ¤ GPG å¯†é’¥ä¸Žæ‚¨å¸æˆ·å…³è”的任何已激活邮箱地å€å‡ä¸åŒ¹é…。如果您已对æä¾›çš„令牌进行ç¾å,ä»å¯æ·»åŠ è¯¥å¯†é’¥ã€‚ gpg_key_matched_identities=匹é…的身份: gpg_key_matched_identities_long=æ¤å¯†é’¥ä¸åŒ…å«çš„身份信æ¯ä¸Žä»¥ä¸‹æ¤ç”¨æˆ·å·²æ¿€æ´»é‚®ç®±åœ°å€åŒ¹é…。与这些邮箱地å€ç›¸åŒ¹é…çš„æäº¤å¯é€šè¿‡æ¤å¯†é’¥è¿›è¡ŒéªŒè¯ã€‚ @@ -872,13 +872,13 @@ ssh_token_signature=增强 SSH ç¾å key_signature_ssh_placeholder=以 '-----BEGIN SSH SIGNATURE -----' 开头 verify_ssh_key_success=SSH 密钥「%sã€å·²éªŒè¯ã€‚ subkeys=å项 -key_id=é”®ID +key_id=密钥 ID key_name=密钥åç§° key_content=密钥内容 principal_content=内容 add_key_success=SSH 密钥「%sã€æ·»åŠ æˆåŠŸã€‚ add_gpg_key_success=GPG 密钥「%sã€æ·»åŠ æˆåŠŸã€‚ -add_principal_success=SSHè¯ä¹¦è§„则「%sã€æ·»åŠ æˆåŠŸã€‚ +add_principal_success=SSH è¯ä¹¦è§„则「%sã€æ·»åŠ æˆåŠŸã€‚ delete_key=åˆ é™¤ ssh_key_deletion=åˆ é™¤ SSH 密钥 gpg_key_deletion=åˆ é™¤ GPG 密钥 @@ -924,7 +924,7 @@ access_token_deletion_desc=åˆ é™¤ä»¤ç‰Œå°†æ’¤é”€ç¨‹åºå¯¹æ‚¨è´¦æˆ·çš„访问æƒé™ delete_token_success=令牌已ç»è¢«åˆ 除。使用该令牌的应用将ä¸å†èƒ½å¤Ÿè®¿é—®æ‚¨çš„è´¦å·ã€‚ repo_and_org_access=仓库和组织访问æƒé™ permissions_public_only=仅公开 -permissions_access_all=全部(公开ã€ç§æœ‰å’Œå—é™) +permissions_access_all=全部(公开ã€ç§æœ‰å’Œå—é™ï¼‰ permission_not_set=未设置 permission_no_access=æ— è®¿é—®æƒé™ permission_read=å¯è¯» @@ -1003,7 +1003,7 @@ remove_account_link=åˆ é™¤å·²ç»‘å®šçš„è´¦å· remove_account_link_desc=åˆ é™¤å·²ç»‘å®šå¸æˆ·å°†åŠé”€å…¶å¯¹æ‚¨çš„ Gitea 叿ˆ·çš„访问æƒé™ã€‚ç»§ç»ï¼Ÿ remove_account_link_success=已喿¶ˆç»‘å®šå¸æˆ·ã€‚ -hooks.desc=æ·»åŠ Webhooks,它们将会在您拥有的<strong>所有仓库</strong>ä¸Šè§¦å‘ +hooks.desc=æ·»åŠ Web é’©å,它们将会在您拥有的<strong>所有仓库</strong>上触å‘。 orgs_none=æ‚¨çŽ°åœ¨è¿˜ä¸æ˜¯ä»»ä½•组织的æˆå‘˜ã€‚ repos_none=æ‚¨å¹¶ä¸æ‹¥æœ‰ä»»ä½•仓库。 @@ -1036,7 +1036,7 @@ owner_helper=由于最大仓库数é‡é™åˆ¶ï¼Œä¸€äº›ç»„织å¯èƒ½ä¸ä¼šæ˜¾ç¤ºåœ¨ä repo_name=仓库åç§° repo_name_profile_public_hint=.profile 是一个特殊的仓库,您å¯ä»¥ä½¿ç”¨å®ƒå°† README.md æ·»åŠ åˆ°æ‚¨çš„å…¬å…±ç»„ç»‡èµ„æ–™ä¸ï¼Œä»»ä½•人都å¯ä»¥çœ‹åˆ°ã€‚请确ä¿å®ƒæ˜¯å…¬å¼€çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 repo_name_profile_private_hint=.profile-private 是一个特殊的仓库,您å¯ä»¥ä½¿ç”¨å®ƒå‘您的组织æˆå‘˜ä¸ªäººèµ„æ–™æ·»åŠ README.md,仅对组织æˆå‘˜å¯è§ã€‚请确ä¿å®ƒæ˜¯ç§æœ‰çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 -repo_name_helper=ç†æƒ³çš„仓库å称应由简çŸã€æœ‰æ„义和独特的关键è¯ç»„æˆã€‚".profile" å’Œ ".profile-private" å¯ç”¨äºŽä¸ºç”¨æˆ·/ç»„ç»‡æ·»åŠ README.md。 +repo_name_helper=ç†æƒ³çš„仓库å称应由简çŸã€æœ‰æ„义和独特的关键è¯ç»„æˆã€‚「.profileã€å’Œã€Œ.profile-privateã€å¯ç”¨äºŽä¸ºç”¨æˆ·/ç»„ç»‡æ·»åŠ README.md。 repo_size=ä»“åº“å¤§å° template=æ¨¡æ¿ template_select=é€‰æ‹©æ¨¡æ¿ @@ -1053,7 +1053,7 @@ fork_from=派生自 already_forked=æ‚¨å·²ç»æ´¾ç”Ÿè¿‡ %s fork_to_different_account=æ´¾ç”Ÿåˆ°å…¶ä»–è´¦å· fork_visibility_helper=æ— æ³•æ›´æ”¹æ´¾ç”Ÿä»“åº“çš„å¯è§æ€§ã€‚ -fork_branch=è¦å…‹éš†åˆ° Fork 的分支 +fork_branch=è¦å…‹éš†ä¸ºæ´¾ç”Ÿçš„分支 all_branches=所有分支 view_all_branches=查看所有分支 view_all_tags=æŸ¥çœ‹æ‰€æœ‰æ ‡ç¾ @@ -1066,14 +1066,14 @@ download_tar=下载 TAR.GZ download_bundle=下载 BUNDLE generate_repo=生æˆä»“库 generate_from=生æˆè‡ª -repo_desc=仓库æè¿° +repo_desc=æè¿° repo_desc_helper=è¾“å…¥ç®€è¦æè¿° (å¯é€‰) repo_no_desc=æ— è¯¦ç»†ä¿¡æ¯ -repo_lang=编程è¯è¨€ +repo_lang=è¯è¨€ repo_gitignore_helper=选择 .gitignore 模æ¿ã€‚ repo_gitignore_helper_desc=从常è§è¯è¨€çš„æ¨¡æ¿åˆ—表ä¸é€‰æ‹©å¿½ç•¥è·Ÿè¸ªçš„æ–‡ä»¶ã€‚é»˜è®¤æƒ…å†µä¸‹ï¼Œç”±å¼€å‘æˆ–构建工具生æˆçš„特殊文件都包å«åœ¨ .gitignore ä¸ã€‚ -issue_labels=工啿 ‡ç¾ -issue_labels_helper=é€‰æ‹©ä¸€ä¸ªå·¥å•æ ‡ç¾é›† +issue_labels=工啿 ‡è®° +issue_labels_helper=é€‰æ‹©ä¸€ä¸ªå·¥å•æ ‡è®°é›†ã€‚ license=授æƒè®¸å¯ license_helper=选择授æƒè®¸å¯æ–‡ä»¶ã€‚ license_helper_desc=许å¯è¯è¯´æ˜Žäº†å…¶ä»–人å¯ä»¥å’Œä¸å¯ä»¥ç”¨æ‚¨çš„代ç åšä»€ä¹ˆã€‚ä¸ç¡®å®šå“ªä¸€ä¸ªé€‚åˆæ‚¨çš„é¡¹ç›®ï¼Ÿè§ <a target="_blank" rel="noopener noreferrer" href="%s">选择一个许å¯è¯</a> @@ -1083,7 +1083,7 @@ object_format_helper=ä»“åº“çš„å¯¹è±¡æ ¼å¼ã€‚ä¹‹åŽæ— 法更改。SHA1 是最兼 readme=自述 readme_helper=选择自述文件模æ¿ã€‚ readme_helper_desc=这是您å¯ä»¥ä¸ºæ‚¨çš„项目撰写完整æè¿°çš„地方。 -auto_init=åˆå§‹åŒ–仓库(æ·»åŠ . gitignoreã€è®¸å¯è¯å’Œè‡ªè¿°æ–‡ä»¶) +auto_init=åˆå§‹åŒ–ä»“åº“ï¼ˆæ·»åŠ .gitignoreã€è®¸å¯è¯å’Œè‡ªè¿°æ–‡ä»¶ï¼‰ trust_model_helper=选择ç¾å验è¯çš„信任模型。å¯èƒ½çš„选项是: trust_model_helper_collaborator=å作者:信任å作者的ç¾å trust_model_helper_committer=æäº¤è€…:信任与æäº¤è€…相符的ç¾å @@ -1151,25 +1151,25 @@ desc.archived=å·²å˜æ¡£ desc.sha256=SHA256 template.items=模æ¿é€‰é¡¹ -template.git_content=Gitæ•°æ®(默认分支) +template.git_content=Git æ•°æ®ï¼ˆé»˜è®¤åˆ†æ”¯ï¼‰ template.git_hooks=Git é’©å -template.git_hooks_tooltip=æ‚¨ç›®å‰æ— æ³•ä¿®æ”¹æˆ–åˆ é™¤è¢«æ·»åŠ è¿‡çš„ Git Hook。仅当您信任模æ¿ä»“库时æ‰å¯ä»¥é€‰æ‹©æ¤é¡¹ã€‚ +template.git_hooks_tooltip=æ‚¨ç›®å‰æ— æ³•ä¿®æ”¹æˆ–åˆ é™¤è¢«æ·»åŠ è¿‡çš„ Git é’©å。仅当您信任模æ¿ä»“库时æ‰å¯ä»¥é€‰æ‹©æ¤é¡¹ã€‚ template.webhooks=Web é’©å template.topics=主题 template.avatar=å¤´åƒ -template.issue_labels=工啿 ‡ç¾ +template.issue_labels=工啿 ‡è®° template.one_item=必须至少选择一个模æ¿é¡¹ template.invalid=必须选择一个模æ¿ä»“库 -archive.title=该仓库已被归档。您å¯ä»¥æŸ¥çœ‹æ–‡ä»¶å’Œå…‹éš†å®ƒï¼Œä½†ä¸èƒ½æŽ¨é€ã€åˆ›å»ºå·¥å•或åˆå¹¶è¯·æ±‚。 -archive.title_date=该仓库已于 %s 归档。您å¯ä»¥æŸ¥çœ‹æ–‡ä»¶æˆ–克隆它,但ä¸èƒ½æŽ¨é€ã€åˆ›å»ºå·¥å•或åˆå¹¶è¯·æ±‚。 +archive.title=该仓库已被归档。您å¯ä»¥æŸ¥çœ‹æ–‡ä»¶å’Œå…‹éš†å®ƒï¼Œä½†ä¸èƒ½æŽ¨é€ã€æ‰“开工啿ˆ–åˆå¹¶è¯·æ±‚。 +archive.title_date=该仓库已于 %s 归档。您å¯ä»¥æŸ¥çœ‹æ–‡ä»¶æˆ–克隆它,但ä¸èƒ½æŽ¨é€ã€æ‰“开工啿ˆ–åˆå¹¶è¯·æ±‚。 archive.issue.nocomment=æ¤ä»“åº“å·²å˜æ¡£ï¼Œæ‚¨ä¸èƒ½åœ¨æ¤å·¥å•æ·»åŠ è¯„è®ºã€‚ archive.pull.nocomment=æ¤ä»“åº“å·²å˜æ¡£ï¼Œæ‚¨ä¸èƒ½åœ¨æ¤åˆå¹¶è¯·æ±‚æ·»åŠ è¯„è®ºã€‚ form.reach_limit_of_creation_1=您已ç»è¾¾åˆ°äº† %d 仓库的上é™ã€‚ form.reach_limit_of_creation_n=您已ç»è¾¾åˆ°äº† %d 个仓库的上é™ã€‚ form.name_reserved=仓库åç§° %s 是ä¿ç•™çš„。 -form.name_pattern_not_allowed=仓库åç§°ä¸ä¸å…许使用 %s æ ¼å¼ã€‚ +form.name_pattern_not_allowed=仓库åä¸ä¸å…许使用「%sã€æ ¼å¼ã€‚ need_auth=æŽˆæƒ migrate_options=è¿ç§»é€‰é¡¹ @@ -1183,7 +1183,7 @@ migrate_options_lfs_endpoint.placeholder=如果留空,网å€å°†ä»Žå…‹éš† URL ä migrate_items=è¿ç§»é¡¹ç›® migrate_items_wiki=百科 migrate_items_milestones=里程碑 -migrate_items_labels=æ ‡ç¾ +migrate_items_labels=æ ‡è®° migrate_items_issues=å·¥å• migrate_items_pullrequests=åˆå¹¶è¯·æ±‚ migrate_items_merge_requests=åˆå¹¶è¯·æ±‚ @@ -1222,7 +1222,7 @@ migrate.codecommit.https_git_credentials_password=HTTPS Git 凿®å¯†ç migrate.migrating_git=è¿ç§»Gitæ•°æ® migrate.migrating_topics=è¿ç§»ä¸»é¢˜ migrate.migrating_milestones=è¿ç§»é‡Œç¨‹ç¢‘ -migrate.migrating_labels=è¿ç§»æ ‡ç¾ +migrate.migrating_labels=è¿ç§»æ ‡è®° migrate.migrating_releases=è¿ç§»å‘布 migrate.migrating_issues=è¿ç§»å·¥å• migrate.migrating_pulls=è¿ç§»åˆå¹¶è¯·æ±‚ @@ -1261,7 +1261,7 @@ branch=分支 tree=ç›®å½•æ ‘ clear_ref=`清除当å‰å¼•用` filter_branch_and_tag=è¿‡æ»¤åˆ†æ”¯æˆ–æ ‡ç¾ -find_tag=查找Gitæ ‡ç¾ +find_tag=æŸ¥æ‰¾æ ‡ç¾ branches=分支列表 tags=æ ‡ç¾åˆ—表 issues=å·¥å• @@ -1269,8 +1269,8 @@ pulls=åˆå¹¶è¯·æ±‚ projects=项目 packages=软件包 actions=å·¥ä½œæµ -labels=æ ‡ç¾ -org_labels_desc=ç»„ç»‡çº§åˆ«çš„æ ‡ç¾ï¼Œå¯ä»¥è¢«æœ¬ç»„织下的 <strong>所有仓库</strong> 使用 +labels=æ ‡è®° +org_labels_desc=ç»„ç»‡çº§åˆ«çš„æ ‡è®°ï¼Œå¯ä»¥è¢«æœ¬ç»„织下的 <strong>所有仓库</strong> 使用 org_labels_desc_manage=ç®¡ç† milestone=里程碑 @@ -1279,7 +1279,7 @@ commits=æäº¤ commit=æäº¤ release=å‘布 releases=å‘布 -tag=Gitæ ‡ç¾ +tag=æ ‡ç¾ released_this=å‘布 tagged_this=å·²æ ‡è®° file.title=%s ä½äºŽ %s @@ -1336,12 +1336,12 @@ editor.cannot_edit_non_text_files=网页ä¸èƒ½ç¼–辑二进制文件。 editor.edit_this_file=编辑文件 editor.this_file_locked=文件已é”定 editor.must_be_on_a_branch=您必须在æŸä¸ªåˆ†æ”¯ä¸Šæ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作。 -editor.fork_before_edit=您必须在派生这个仓库æ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作 +editor.fork_before_edit=您必须派生这个仓库æ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作。 editor.delete_this_file=åˆ é™¤æ–‡ä»¶ editor.must_have_write_access=您必须具有写æƒé™æ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作。 editor.file_delete_success=文件「%sã€å·²åˆ 除。 editor.name_your_file=命忖‡ä»¶... -editor.filename_help=通过键入åç§°åŽè·Ÿæ–œçº¿ ("/") æ¥æ·»åŠ ç›®å½•ã€‚é€šè¿‡åœ¨è¾“å…¥æ¡†çš„å¼€å¤´é”®å…¥ "é€€æ ¼" æ¥åˆ 除目录。 +editor.filename_help=通过键入åç§°åŽè·Ÿæ–œçº¿ ("/") æ¥æ·»åŠ ç›®å½•ã€‚é€šè¿‡åœ¨è¾“å…¥æ¡†çš„å¼€å¤´é”®å…¥ã€Œé€€æ ¼ã€æ¥åˆ 除目录。 editor.or=或 editor.cancel_lower=å–æ¶ˆ editor.commit_signed_changes=æäº¤å·²ç¾å的更改 @@ -1359,7 +1359,7 @@ editor.signoff_desc=在æäº¤æ—¥å¿—æ¶ˆæ¯æœ«å°¾æ·»åŠ ç¾ç½²äººä¿¡æ¯ã€‚ editor.commit_directly_to_this_branch=直接æäº¤è‡³ <strong class="branch-name">%s</strong> 分支。 editor.create_new_branch=ä¸ºæ¤æäº¤åˆ›å»ºä¸€ä¸ª <strong>新的分支</strong> å¹¶å‘èµ·åˆå¹¶è¯·æ±‚。 editor.create_new_branch_np=ä¸ºæ¤æäº¤åˆ›å»º <strong>新分支</strong>。 -editor.propose_file_change=æè®®æ–‡ä»¶æ›´æ”¹ +editor.propose_file_change=拟议文件更改 editor.new_branch_name=为这次æäº¤çš„æ–°åˆ†æ”¯å‘½å editor.new_branch_name_desc=新的分支åç§°... editor.cancel=å–æ¶ˆ @@ -1376,15 +1376,15 @@ editor.file_editing_no_longer_exists=æ£åœ¨ç¼–辑的文件「%sã€å·²ä¸å˜åœ¨äº editor.file_deleting_no_longer_exists=æ£åœ¨åˆ 除的文件「%sã€å·²ä¸å˜åœ¨äºŽæ¤ä»“库。 editor.file_changed_while_editing=文件内容在您进行编辑时已ç»å‘生å˜åŠ¨ã€‚<a target="_blank" rel="noopener noreferrer" href="%s">å•击æ¤å¤„</a> 查看å˜åŠ¨çš„å…·ä½“å†…å®¹ï¼Œæˆ–è€… <strong>冿¬¡æäº¤</strong> 覆盖已å‘生的å˜åŠ¨ã€‚ editor.file_already_exists=æ¤ä»“库已ç»å˜åœ¨å为「%sã€çš„æ–‡ä»¶ã€‚ -editor.commit_id_not_matching=æäº¤ID与您开始编辑时的IDä¸åŒ¹é…。请æäº¤åˆ°è¡¥ä¸åˆ†æ”¯ç„¶åŽåˆå¹¶ã€‚ +editor.commit_id_not_matching=æäº¤ ID 与您开始编辑时的 ID ä¸åŒ¹é…。请æäº¤åˆ°è¡¥ä¸åˆ†æ”¯ç„¶åŽåˆå¹¶ã€‚ editor.push_out_of_date=推é€ä¼¼ä¹Žå·²ç»è¿‡æ—¶ã€‚ editor.commit_empty_file_header=æäº¤ä¸€ä¸ªç©ºæ–‡ä»¶ editor.commit_empty_file_text=æ‚¨è¦æäº¤çš„æ–‡ä»¶æ˜¯ç©ºçš„ï¼Œç»§ç»å—? editor.no_changes_to_show=没有å¯ä»¥æ˜¾ç¤ºçš„å˜æ›´ã€‚ editor.fail_to_update_file=æ›´æ–°/创建文件「%sã€å¤±è´¥ã€‚ editor.fail_to_update_file_summary=错误信æ¯ï¼š -editor.push_rejected_no_message=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»å¹¶ä¸”没有å馈消æ¯ã€‚请检查 Git Hook。 -editor.push_rejected=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»ã€‚请检查 Git Hook。 +editor.push_rejected_no_message=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»å¹¶ä¸”没有å馈消æ¯ã€‚请检查 Git é’©å。 +editor.push_rejected=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»ã€‚请检查 Git é’©å。 editor.push_rejected_summary=详细拒ç»ä¿¡æ¯ï¼š editor.add_subdir=æ·»åŠ ç›®å½• editor.unable_to_upload_files=ä¸Šä¼ æ–‡ä»¶è‡³ã€Œ%sã€å¤±è´¥ï¼š%v @@ -1474,19 +1474,19 @@ issues.desc=组织 bug 报告ã€ä»»åŠ¡å’Œé‡Œç¨‹ç¢‘ã€‚ issues.filter_assignees=ç›é€‰æŒ‡æ´¾äºº issues.filter_milestones=ç›é€‰é‡Œç¨‹ç¢‘ issues.filter_projects=ç›é€‰é¡¹ç›® -issues.filter_labels=ç›é€‰æ ‡ç¾ +issues.filter_labels=ç›é€‰æ ‡è®° issues.filter_reviewers=ç›é€‰å®¡æ ¸è€… issues.filter_no_results=没有结果 issues.filter_no_results_placeholder=请å°è¯•调整您的æœç´¢è¿‡æ»¤å™¨ã€‚ -issues.new=åˆ›å»ºå·¥å• +issues.new=æ‰“å¼€å·¥å• issues.new.title_empty=æ ‡é¢˜ä¸èƒ½ä¸ºç©º -issues.new.labels=æ ‡ç¾ -issues.new.no_label=æœªé€‰æ‹©æ ‡ç¾ -issues.new.clear_labels=æ¸…é™¤é€‰ä¸æ ‡ç¾ +issues.new.labels=æ ‡è®° +issues.new.no_label=æœªé€‰æ‹©æ ‡è®° +issues.new.clear_labels=æ¸…é™¤é€‰ä¸æ ‡è®° issues.new.projects=项目 issues.new.clear_projects=清除项目 issues.new.no_projects=æš‚æ— é¡¹ç›® -issues.new.open_projects=å¼€å¯ä¸çš„项目 +issues.new.open_projects=已打开项目 issues.new.closed_projects=已关é—的项目 issues.new.no_items=æ— å¯é€‰é¡¹ issues.new.milestone=里程碑 @@ -1496,32 +1496,32 @@ issues.new.assignees=指派æˆå‘˜ issues.new.clear_assignees=å–æ¶ˆæŒ‡æ´¾æˆå‘˜ issues.new.no_assignees=未指派æˆå‘˜ issues.new.no_reviewers=æ— å®¡æ ¸è€… -issues.new.blocked_user=æ— æ³•åˆ›å»ºå·¥å•ï¼Œå› ä¸ºæ‚¨å·²è¢«ä»“åº“æ‰€æœ‰è€…å±è”½ã€‚ +issues.new.blocked_user=æ— æ³•æ‰“å¼€å·¥å•ï¼Œå› ä¸ºæ‚¨å·²è¢«ä»“åº“æ‰€æœ‰è€…å±è”½ã€‚ issues.edit.already_changed=æ— æ³•ä¿å˜å¯¹å·¥å•的更改。其内容似乎已被其他用户更改。 请刷新页é¢å¹¶é‡æ–°ç¼–辑以é¿å…覆盖他们的更改 issues.edit.blocked_user=æ— æ³•ç¼–è¾‘å†…å®¹ï¼Œå› ä¸ºæ‚¨å·²è¢«ä»“åº“æ‰€æœ‰è€…æˆ–å·¥å•创建者å±è”½ã€‚ issues.choose.get_started=开始 -issues.choose.open_external_link=å¼€å¯ +issues.choose.open_external_link=打开 issues.choose.blank=é»˜è®¤æ¨¡æ¿ issues.choose.blank_about=从默认模æ¿åˆ›å»ºä¸€ä¸ªå·¥å•。 issues.choose.ignore_invalid_templates=å·²å¿½ç•¥æ— æ•ˆæ¨¡æ¿ issues.choose.invalid_templates=å‘现了 %v ä¸ªæ— æ•ˆæ¨¡æ¿ issues.choose.invalid_config=问题é…置包å«é”™è¯¯ï¼š issues.no_ref=分支/æ ‡è®°æœªæŒ‡å®š -issues.create=åˆ›å»ºå·¥å• -issues.new_label=åˆ›å»ºæ ‡ç¾ -issues.new_label_placeholder=æ ‡ç¾åç§° +issues.create=æ‰“å¼€å·¥å• +issues.new_label=åˆ›å»ºæ ‡è®° +issues.new_label_placeholder=æ ‡è®°åç§° issues.new_label_desc_placeholder=æè¿° -issues.create_label=åˆ›å»ºæ ‡ç¾ -issues.label_templates.title=åŠ è½½é¢„å®šä¹‰çš„æ ‡ç¾æ¨¡æ¿ -issues.label_templates.info=è¿˜æ²¡æœ‰ä»»ä½•æ ‡ç¾ã€‚您å¯ä»¥ä½¿ç”¨'åˆ›å»ºæ ‡ç¾'æŒ‰é’®æˆ–è€…åŠ è½½é¢„å®šä¹‰çš„æ ‡ç¾é›†åˆ›å»ºæ ‡ç¾ -issues.label_templates.helper=é€‰æ‹©æ ‡ç¾æ¨¡æ¿ -issues.label_templates.use=ä½¿ç”¨æ ‡ç¾é›† -issues.label_templates.fail_to_load_file=åŠ è½½æ ‡ç¾æ¨¡æ¿æ–‡ä»¶ã€Œ%sã€æ—¶å‘生错误:%v -issues.add_label=于 %[2]s æ·»åŠ äº†æ ‡ç¾ %[1]s -issues.add_labels=于 %[2]s æ·»åŠ äº†æ ‡ç¾ %[1]s -issues.remove_label=于 %[2]s åˆ é™¤äº†æ ‡ç¾ %[1]s -issues.remove_labels=于 %[2]s åˆ é™¤äº†æ ‡ç¾ %[1]s -issues.add_remove_labels=于 %[3]s æ·»åŠ äº†æ ‡ç¾ %[1]s ï¼Œåˆ é™¤äº†æ ‡ç¾ %[2]s +issues.create_label=åˆ›å»ºæ ‡è®° +issues.label_templates.title=åŠ è½½é¢„å®šä¹‰çš„æ ‡è®°æ¨¡æ¿ +issues.label_templates.info=è¿˜æ²¡æœ‰ä»»ä½•æ ‡è®°ã€‚æ‚¨å¯ä»¥ä½¿ç”¨ã€Œåˆ›å»ºæ ‡è®°ã€æŒ‰é’®æˆ–è€…åŠ è½½é¢„å®šä¹‰çš„æ ‡è®°é›†åˆ›å»ºæ ‡è®°ï¼š +issues.label_templates.helper=é€‰æ‹©æ ‡è®°æ¨¡æ¿ +issues.label_templates.use=ä½¿ç”¨æ ‡è®°é›† +issues.label_templates.fail_to_load_file=åŠ è½½æ ‡è®°æ¨¡æ¿æ–‡ä»¶ã€Œ%sã€æ—¶å‘生错误:%v +issues.add_label=于 %[2]s æ·»åŠ äº†æ ‡è®° %[1]s +issues.add_labels=于 %[2]s æ·»åŠ äº†æ ‡è®° %[1]s +issues.remove_label=于 %[2]s åˆ é™¤äº†æ ‡è®° %[1]s +issues.remove_labels=于 %[2]s åˆ é™¤äº†æ ‡è®° %[1]s +issues.add_remove_labels=于 %[3]s æ·»åŠ äº†æ ‡è®° %[1]s ï¼Œåˆ é™¤äº†æ ‡è®° %[2]s issues.add_milestone_at=`于 %[2]s æ·»åŠ äº†é‡Œç¨‹ç¢‘ <b>%[1]s</b>` issues.add_project_at=`于 %[2]s å°†æ¤æ·»åŠ åˆ° <b>%[1]s</b> 项目` issues.move_to_column_of_project=`å°†æ¤å¯¹è±¡ç§»è‡³ %s çš„ %s ä¸åœ¨ %s 上` @@ -1540,10 +1540,10 @@ issues.change_ref_at=`将引用从 <b><strike>%s</strike></b> 更改为了 <b>%s issues.remove_ref_at=`åˆ é™¤äº†å¼•ç”¨ <b>%s</b> %s` issues.add_ref_at=`æ·»åŠ äº†å¼•ç”¨ <b>%s</b> %s` issues.delete_branch_at=`于 %[2]s åˆ é™¤äº†åˆ†æ”¯ <b>%[1]s</b>` -issues.filter_label=æ ‡ç¾ç›é€‰ -issues.filter_label_exclude=`使用 <code>alt</code> + <code>é¼ æ ‡å·¦é”® / 回车</code> æŽ’é™¤æ ‡ç¾` -issues.filter_label_no_select=æ‰€æœ‰æ ‡ç¾ -issues.filter_label_select_no_label=æ— æ ‡ç¾ +issues.filter_label=æ ‡è®°ç›é€‰ +issues.filter_label_exclude=`使用 <code>alt</code> + <code>é¼ æ ‡å·¦é”® / 回车</code> æŽ’é™¤æ ‡è®°` +issues.filter_label_no_select=æ‰€æœ‰æ ‡è®° +issues.filter_label_select_no_label=æ— æ ‡è®° issues.filter_milestone=里程碑ç›é€‰ issues.filter_milestone_all=所有里程碑 issues.filter_milestone_none=æ— é‡Œç¨‹ç¢‘ @@ -1579,9 +1579,9 @@ issues.filter_sort.moststars=点赞由多到少 issues.filter_sort.feweststars=点赞由少到多 issues.filter_sort.mostforks=派生由多到少 issues.filter_sort.fewestforks=派生由少到多 -issues.action_open=å¼€å¯ +issues.action_open=打开 issues.action_close=å…³é— -issues.action_label=æ ‡ç¾ +issues.action_label=æ ‡è®° issues.action_milestone=里程碑 issues.action_milestone_no_select=æ— é‡Œç¨‹ç¢‘ issues.action_assignee=指派人ç›é€‰ @@ -1596,7 +1596,7 @@ issues.opened_by_fake=ç”± %[2]s 于 %[1]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 评论 @@ -1613,8 +1613,8 @@ 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 issues.close_comment_issue=è¯„è®ºå¹¶å…³é— -issues.reopen_issue=釿–°å¼€å¯ -issues.reopen_comment_issue=è¯„è®ºå¹¶é‡æ–°å¼€å¯ +issues.reopen_issue=釿–°æ‰“å¼€ +issues.reopen_comment_issue=è¯„è®ºå¹¶é‡æ–°æ‰“å¼€ issues.create_comment=评论 issues.comment.blocked_user=æ— æ³•åˆ›å»ºæˆ–ç¼–è¾‘è¯„è®ºï¼Œå› ä¸ºæ‚¨å·²è¢«ä»“åº“æ‰€æœ‰è€…æˆ–å·¥å•创建者å±è”½ã€‚ issues.closed_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 关闿¤å·¥å•` @@ -1649,26 +1649,26 @@ issues.sign_in_require_desc=<a href="%s">登录</a> å¹¶å‚与到对è¯ä¸ã€‚ issues.edit=编辑 issues.cancel=å–æ¶ˆ issues.save=ä¿å˜ -issues.label_title=æ ‡ç¾åç§° -issues.label_description=æ ‡ç¾æè¿° -issues.label_color=æ ‡ç¾é¢œè‰² +issues.label_title=åç§° +issues.label_description=æè¿° +issues.label_color=颜色 issues.label_color_invalid=æ— æ•ˆçš„é¢œè‰² -issues.label_exclusive=äº’æ–¥æ ‡ç¾ -issues.label_archive=å½’æ¡£æ ‡ç¾ -issues.label_archived_filter=æ˜¾ç¤ºå˜æ¡£æ ‡ç¾ -issues.label_archive_tooltip=åœ¨æ ‡ç¾æœç´¢æ—¶ï¼Œé»˜è®¤æƒ…å†µä¸‹å˜æ¡£æ ‡ç¾å°†è¢«æŽ’除在外。 -issues.label_exclusive_desc=å‘½åæ ‡ç¾ä¸º <code>scope/item</code> 以使其与其他以 <code>scope/</code> å¼€å¤´çš„æ ‡ç¾äº’斥。 -issues.label_exclusive_warning=åœ¨ç¼–è¾‘å·¥å•æˆ–åˆå¹¶è¯·æ±‚çš„æ ‡ç¾æ—¶ï¼Œä»»ä½•冲çªçš„èŒƒå›´æ ‡ç¾éƒ½å°†è¢«åˆ 除。 +issues.label_exclusive=互斥 +issues.label_archive=å½’æ¡£æ ‡è®° +issues.label_archived_filter=æ˜¾ç¤ºå·²å½’æ¡£æ ‡è®° +issues.label_archive_tooltip=åœ¨æ ‡è®°æœç´¢æ—¶ï¼Œé»˜è®¤æƒ…å†µä¸‹å·²å½’æ¡£æ ‡è®°å°†è¢«æŽ’é™¤åœ¨å¤–ã€‚ +issues.label_exclusive_desc=å‘½åæ ‡è®°ä¸º <code>scope/item</code> 以使其与其他以 <code>scope/</code> å¼€å¤´çš„æ ‡è®°äº’æ–¥ã€‚ +issues.label_exclusive_warning=åœ¨ç¼–è¾‘å·¥å•æˆ–åˆå¹¶è¯·æ±‚çš„æ ‡è®°æ—¶ï¼Œä»»ä½•å†²çªçš„èŒƒå›´æ ‡è®°éƒ½å°†è¢«åˆ é™¤ã€‚ issues.label_exclusive_order=排åºé¡ºåº -issues.label_exclusive_order_tooltip=在åŒä¸€ä¸ªèŒƒå›´å†…çš„äº’æ–¥æ ‡ç¾å°†æŒ‰ç…§è¿™ä¸ªæ•°å—è¿›è¡ŒæŽ’åº -issues.label_count=%d ä¸ªæ ‡ç¾ -issues.label_open_issues=%d 个开å¯çš„å·¥å• +issues.label_exclusive_order_tooltip=在åŒä¸€ä¸ªèŒƒå›´å†…çš„äº’æ–¥æ ‡è®°å°†æŒ‰ç…§è¿™ä¸ªæ•°å—进行排åºã€‚ +issues.label_count=%d ä¸ªæ ‡è®° +issues.label_open_issues=%d 个已打开工å•/åˆå¹¶è¯·æ±‚ issues.label_edit=编辑 issues.label_delete=åˆ é™¤ -issues.label_modify=ç¼–è¾‘æ ‡ç¾ -issues.label_deletion=åˆ é™¤æ ‡ç¾ -issues.label_deletion_desc=åˆ é™¤æ ‡ç¾ä¼šå°†å…¶ä»Žæ‰€æœ‰é—®é¢˜ä¸åˆ 除。继ç»ï¼Ÿ -issues.label_deletion_success=è¯¥æ ‡ç¾å·²åˆ 除。 +issues.label_modify=ç¼–è¾‘æ ‡è®° +issues.label_deletion=åˆ é™¤æ ‡è®° +issues.label_deletion_desc=åˆ é™¤æ ‡è®°ä¼šå°†å…¶ä»Žæ‰€æœ‰å·¥å•ä¸åˆ 除。继ç»ï¼Ÿ +issues.label_deletion_success=è¯¥æ ‡è®°å·²åˆ é™¤ã€‚ issues.label.filter_sort.alphabetically=æŒ‰å—æ¯é¡ºåºæŽ’åº issues.label.filter_sort.reverse_alphabetically=æŒ‰å—æ¯é€†åºæŽ’åº issues.label.filter_sort.by_size=最å°å°ºå¯¸ @@ -1733,7 +1733,7 @@ issues.time_spent_total=总用时 issues.time_spent_from_all_authors=`总花费时间:%s` issues.due_date=到期时间 -issues.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是 'yyyy-mm-dd' 的形å¼ã€‚ +issues.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是「yyyy-mm-ddã€çš„å½¢å¼ã€‚ issues.error_modifying_due_date=修改到期时间失败。 issues.error_removing_due_date=åˆ é™¤åˆ°æœŸæ—¶é—´å¤±è´¥ã€‚ issues.push_commit_1=于 %[2]s 推é€äº† %[1]d 个æäº¤ @@ -1960,7 +1960,7 @@ pulls.cmd_instruction_merge_title=åˆå¹¶ pulls.cmd_instruction_merge_desc=åˆå¹¶å˜æ›´å¹¶æ›´æ–°åˆ° Gitea 上 pulls.cmd_instruction_merge_warning=è¦å‘Šï¼šæ¤æ“作ä¸èƒ½åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚ï¼Œå› ä¸ºã€Œè‡ªåŠ¨æ£€æµ‹æ‰‹åŠ¨åˆå¹¶ã€æœªå¯ç”¨ pulls.clear_merge_message=清除åˆå¹¶ä¿¡æ¯ -pulls.clear_merge_message_hint=清除åˆå¹¶æ¶ˆæ¯åªä¼šåˆ 除æäº¤æ¶ˆæ¯å†…容,并ä¿ç•™ç”Ÿæˆçš„ Git é™„åŠ å†…å®¹ï¼Œå¦‚ã€ŒCo-Authored-By …ã€ã€‚ +pulls.clear_merge_message_hint=清除åˆå¹¶æ¶ˆæ¯åªä¼šåˆ 除æäº¤æ¶ˆæ¯å†…容,并ä¿ç•™ç”Ÿæˆçš„ Git é™„åŠ å†…å®¹ï¼Œå¦‚ã€ŒCo-Authored-By…ã€ã€‚ pulls.auto_merge_button_when_succeed=(当检查æˆåŠŸæ—¶) pulls.auto_merge_when_succeed=在所有检查æˆåŠŸåŽè‡ªåЍåˆå¹¶ @@ -1975,7 +1975,7 @@ pulls.auto_merge_newly_scheduled_comment=`已于 %[1]s 设置æ¤åˆå¹¶è¯·æ±‚在æ pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s å–æ¶ˆäº†è‡ªåЍåˆå¹¶è®¾ç½® ` pulls.delete.title=åˆ é™¤æ¤åˆå¹¶è¯·æ±‚? -pulls.delete.text=您真的è¦åˆ 除这个åˆå¹¶è¯·æ±‚å—? (è¿™å°†æ°¸ä¹…åˆ é™¤æ‰€æœ‰å†…å®¹ã€‚å¦‚æžœæ‚¨æ‰“ç®—å°†å†…å®¹å˜æ¡£ï¼Œè¯·è€ƒè™‘å…³é—它) +pulls.delete.text=您真的è¦åˆ 除这个åˆå¹¶è¯·æ±‚å—ï¼Ÿï¼ˆè¿™å°†æ°¸ä¹…åˆ é™¤æ‰€æœ‰å†…å®¹ã€‚å¦‚æžœæ‚¨æ‰“ç®—å°†å†…å®¹å˜æ¡£ï¼Œè¯·è€ƒè™‘å…³é—它) pulls.recently_pushed_new_branches=您已ç»äºŽ%[2]s推é€äº†åˆ†æ”¯ <strong>%[1]s</strong> pulls.upstream_diverging_prompt_behind_1=该分支è½åŽäºŽ %[2]s %[1]d 个æäº¤ @@ -1993,7 +1993,7 @@ milestones.new=新的里程碑 milestones.closed=于 %så…³é— milestones.update_ago=已更新 %s milestones.no_due_date=æš‚æ— æˆªæ¢æ—¥æœŸ -milestones.open=å¼€å¯ +milestones.open=打开 milestones.close=å…³é— milestones.new_subheader=里程碑å¯ä»¥å¸®åŠ©æ‚¨ç»„ç»‡å·¥å•并跟踪其进度。 milestones.completeness=<strong>%d%%</strong> å·²å®Œæˆ @@ -2002,7 +2002,7 @@ milestones.title=æ ‡é¢˜ milestones.desc=æè¿° milestones.due_date=æˆªæ¢æ—¥æœŸï¼ˆå¯é€‰ï¼‰ milestones.clear=清除 -milestones.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是 'yyyy-mm-dd' 的形å¼ã€‚ +milestones.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是「yyyy-mm-ddã€çš„å½¢å¼ã€‚ milestones.create_success=里程碑「%sã€åˆ›å»ºæˆåŠŸã€‚ milestones.edit=编辑里程碑 milestones.edit_subheader=里程碑组织工å•,åˆå¹¶è¯·æ±‚和跟踪进度。 @@ -2020,7 +2020,7 @@ milestones.filter_sort.most_complete=完æˆåº¦ä»Žé«˜åˆ°ä½Ž milestones.filter_sort.most_issues=å·¥å•从多到少 milestones.filter_sort.least_issues=å·¥å•从少到多 -signing.will_sign=这个æäº¤å°†ç”¨å¯†é’¥ 「%sã€ç¾å。 +signing.will_sign=这个æäº¤å°†ç”¨å¯†é’¥ã€Œ%sã€ç¾å。 signing.wont_sign.error=在检查æäº¤æ˜¯å¦å¯ä»¥è¢«ç¾å时出错。 signing.wont_sign.nokey=没有å¯ç”¨çš„密钥æ¥ç¾ç½²è¿™ä¸ªæäº¤ã€‚ signing.wont_sign.never=æäº¤ä»Žæœªç¾å。 @@ -2035,10 +2035,10 @@ signing.wont_sign.approved=åˆå¹¶å°†ä¸ä¼šè¢«ç¾åï¼Œå› ä¸ºåˆå¹¶è¯·æ±‚æœªè¢«æ‰ signing.wont_sign.not_signed_in=您还没有登录。 ext_wiki=访问外部百科 -ext_wiki.desc=链接到外部 wiki。 +ext_wiki.desc=链接到外部百科。 wiki=百科 -wiki.welcome=欢迎æ¥åˆ°ç™¾ç§‘! +wiki.welcome=欢迎æ¥åˆ°ç™¾ç§‘。 wiki.welcome_desc=百科å…许您撰写和与å作者分享文档。 wiki.desc=撰写和与å作者分享文档 wiki.create_first_page=åˆ›å»ºç¬¬ä¸€ä¸ªé¡µé¢ @@ -2061,37 +2061,37 @@ wiki.page_already_exists=相åŒåç§°çš„ Wiki 页é¢å·²ç»å˜åœ¨ã€‚ wiki.reserved_page=百科页é¢å称「%sã€æ˜¯ä¿ç•™çš„。 wiki.pages=æ‰€æœ‰é¡µé¢ wiki.last_updated=æœ€åŽæ›´æ–°äºŽ %s -wiki.page_name_desc=è¾“å…¥æ¤ Wiki 页é¢çš„å称。特殊å称有:'Home', '_Sidebar' å’Œ '_Footer'。 +wiki.page_name_desc=输入æ¤ç™¾ç§‘页é¢çš„å称。特殊å称有:「Homeã€ï¼Œã€Œ_Sidebarã€å’Œã€Œ_Footerã€ã€‚ wiki.original_git_entry_tooltip=查看原始的 Git æ–‡ä»¶è€Œä¸æ˜¯ä½¿ç”¨å‹å¥½é“¾æŽ¥ã€‚ activity=活动 activity.navbar.pulse=活动 activity.navbar.code_frequency=代ç 频率 activity.navbar.contributors=贡献者 -activity.navbar.recent_commits=最近的æäº¤ +activity.navbar.recent_commits=最近æäº¤ activity.period.filter_label=周期: activity.period.daily=1 天 activity.period.halfweekly=3 天 -activity.period.weekly=1周 -activity.period.monthly=1 个月 -activity.period.quarterly=3个月 -activity.period.semiyearly=6 个月 -activity.period.yearly=1å¹´ +activity.period.weekly=1 周 +activity.period.monthly=1 月 +activity.period.quarterly=3 月 +activity.period.semiyearly=6 月 +activity.period.yearly=1 å¹´ activity.overview=概览 activity.active_prs_count_1=<strong>%d</strong> 个åˆå¹¶è¯·æ±‚ activity.active_prs_count_n=<strong>%d</strong> 个åˆå¹¶è¯·æ±‚ -activity.merged_prs_count_1=åˆå¹¶è¯·æ±‚ -activity.merged_prs_count_n=åˆå¹¶è¯·æ±‚ -activity.opened_prs_count_1=æ–°åˆå¹¶è¯·æ±‚ -activity.opened_prs_count_n=æ–°åˆå¹¶è¯·æ±‚ +activity.merged_prs_count_1=å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚ +activity.merged_prs_count_n=å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚ +activity.opened_prs_count_1=拟议的åˆå¹¶è¯·æ±‚ +activity.opened_prs_count_n=拟议的åˆå¹¶è¯·æ±‚ activity.title.user_1=%d ä½ç”¨æˆ· activity.title.user_n=%d ä½ç”¨æˆ· activity.title.prs_1=%d 个åˆå¹¶è¯·æ±‚ activity.title.prs_n=%d 个åˆå¹¶è¯·æ±‚ activity.title.prs_merged_by=%[2]s ç”± %[1]s åˆå¹¶ -activity.title.prs_opened_by=%[2]s 创建了 %[1]s +activity.title.prs_opened_by=%[2]s 拟议了 %[1]s activity.merged_prs_label=å·²åˆå¹¶ -activity.opened_prs_label=已创建 +activity.opened_prs_label=æ‹Ÿè®®ä¸ activity.active_issues_count_1=<strong>%d</strong> å¼ å·¥å• activity.active_issues_count_n=<strong>%d</strong> å¼ å·¥å• activity.closed_issues_count_1=已关é—çš„å·¥å• @@ -2101,8 +2101,8 @@ activity.title.issues_n=%d å¼ å·¥å• activity.title.issues_closed_from=%s 从 %s å…³é— activity.title.issues_created_by=%[2]s 创建了 %[1]s activity.closed_issue_label=å·²å…³é— -activity.new_issues_count_1=åˆ›å»ºå·¥å• -activity.new_issues_count_n=åˆ›å»ºå·¥å• +activity.new_issues_count_1=å·²æ‰“å¼€çš„å·¥å• +activity.new_issues_count_n=å·²æ‰“å¼€çš„å·¥å• activity.new_issue_label=打开的 activity.title.unresolved_conv_1=%d æœªè§£å†³çš„ä¼šè¯ activity.title.unresolved_conv_n=%d æœªè§£å†³çš„ä¼šè¯ @@ -2113,11 +2113,11 @@ activity.title.releases_n=%d 个å‘布 activity.title.releases_published_by=%[2]s å‘布了 %[1]s activity.published_release_label=å·²å‘布 activity.no_git_activity=åœ¨æ¤æœŸé—´æ²¡æœ‰ä»»ä½•æäº¤æ´»åŠ¨ã€‚ -activity.git_stats_exclude_merges=排除åˆå¹¶ï¼Œ +activity.git_stats_exclude_merges=排除åˆå¹¶åŽï¼Œ activity.git_stats_author_1=%d ä½ä½œè€… activity.git_stats_author_n=%d ä½ä½œè€… -activity.git_stats_pushed_1=å·²ç»æŽ¨é€ -activity.git_stats_pushed_n=å·²ç»æŽ¨é€ +activity.git_stats_pushed_1=å·²æŽ¨é€ +activity.git_stats_pushed_n=å·²æŽ¨é€ activity.git_stats_commit_1=%d 次æäº¤ activity.git_stats_commit_n=%d 次æäº¤ activity.git_stats_push_to_branch=到 %s å’Œ @@ -2125,14 +2125,14 @@ activity.git_stats_push_to_all_branches=到所有分支。 activity.git_stats_on_default_branch=在 %s 上, activity.git_stats_file_1=%d 个文件 activity.git_stats_file_n=%d 个文件 -activity.git_stats_files_changed_1=å·²ç»æ”¹å˜ -activity.git_stats_files_changed_n=å·²ç»æ”¹å˜ -activity.git_stats_additions=而且 -activity.git_stats_addition_1=新增 %d 行 -activity.git_stats_addition_n=新增 %d 行 +activity.git_stats_files_changed_1=已修改 +activity.git_stats_files_changed_n=已修改 +activity.git_stats_additions=并且已有 +activity.git_stats_addition_1=%d 行新增 +activity.git_stats_addition_n=%d 行新增 activity.git_stats_and_deletions=å’Œ -activity.git_stats_deletion_1=åˆ é™¤ %d 行 -activity.git_stats_deletion_n=åˆ é™¤ %d 行 +activity.git_stats_deletion_1=%d è¡Œåˆ é™¤ +activity.git_stats_deletion_n=%d è¡Œåˆ é™¤ contributors.contribution_type.filter_label=贡献类型: contributors.contribution_type.commits=æäº¤ @@ -2196,12 +2196,12 @@ settings.use_internal_wiki=使用内置百科 settings.default_wiki_branch_name=默认百科分支åç§° settings.failed_to_change_default_wiki_branch=更改百科默认分支失败。 settings.use_external_wiki=使用外部百科 -settings.external_wiki_url=外部 Wiki 链接 +settings.external_wiki_url=外部百科链接 settings.external_wiki_url_error=å¤–éƒ¨ç™¾ç§‘é“¾æŽ¥æ— æ•ˆ settings.external_wiki_url_desc=å½“ç‚¹å‡»ç™¾ç§‘æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部百科系统的 URL。 settings.issues_desc=å¯ç”¨å·¥å•系统 -settings.use_internal_issue_tracker=使用内置的轻é‡çº§å·¥å•管ç†ç³»ç»Ÿ -settings.use_external_issue_tracker=使用外部的工å•管ç†ç³»ç»Ÿ +settings.use_internal_issue_tracker=使用内置工å•系统 +settings.use_external_issue_tracker=使用外部工å•系统 settings.external_tracker_url=外部工å•系统 URL settings.external_tracker_url_error=å¤–éƒ¨ç™¾ç§‘é“¾æŽ¥æ— æ•ˆ settings.external_tracker_url_desc=å½“ç‚¹å‡»å·¥å•æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部工å•系统的 URL。 @@ -2211,7 +2211,7 @@ settings.tracker_issue_style=外部工å•管ç†ç³»ç»Ÿçš„ç¼–å·æ ¼å¼ settings.tracker_issue_style.numeric=纯数å—å½¢å¼ settings.tracker_issue_style.alphanumeric=è‹±æ–‡å—æ¯æ•°å—组åˆå½¢å¼ settings.tracker_issue_style.regexp=æ£åˆ™è¡¨è¾¾å¼ -settings.tracker_issue_style.regexp_pattern=æ£åˆ™è¡¨è¾¾å¼æ¨¡å¼ +settings.tracker_issue_style.regexp_pattern=æ£åˆ™è¡¨è¾¾å¼ settings.tracker_issue_style.regexp_pattern_desc=第一个被æ•获的组将å–代 <code>{index}</code>。 settings.tracker_url_format_desc=使用å ä½ç¬¦ <code>{user}</code>, <code>{repo}</code> å’Œ <code>{index}</code> 作为用户åã€ä»“库å和工å•索引。 settings.enable_timetracker=å¯ç”¨æ—¶é—´è·Ÿè¸ª @@ -2221,7 +2221,7 @@ settings.pulls.ignore_whitespace=å¿½ç•¥ç©ºç™½å†²çª settings.pulls.enable_autodetect_manual_merge=å¯ç”¨è‡ªåŠ¨æ£€æµ‹æ‰‹åŠ¨åˆå¹¶ (注æ„:在æŸäº›ç‰¹æ®Šæƒ…况下å¯èƒ½å‘生错误判æ–) settings.pulls.allow_rebase_update=å…许通过å˜åŸºæ›´æ–°åˆå¹¶è¯·æ±‚分支 settings.pulls.default_delete_branch_after_merge=默认åˆå¹¶åŽåˆ 除åˆå¹¶è¯·æ±‚分支 -settings.pulls.default_allow_edits_from_maintainers=默认开å¯å…许维护者编辑 +settings.pulls.default_allow_edits_from_maintainers=默认å…许维护者编辑 settings.releases_desc=å¯ç”¨ä»“库å‘布 settings.packages_desc=å¯ç”¨ä»“库软件包注册ä¸å¿ƒ settings.projects_desc=å¯ç”¨é¡¹ç›® @@ -2330,10 +2330,10 @@ settings.webhook.response=å“应内容 settings.webhook.headers=å¤´ä¿¡æ¯ settings.webhook.payload=内容 settings.webhook.body=å“应体 -settings.webhook.replay.description=釿”¾æ¤ webhook。 +settings.webhook.replay.description=釿”¾æ¤ Web é’©å。 settings.webhook.replay.description_disabled=è‹¥è¦é‡æ–°è¿è¡Œæ¤ Web é’©å,请激活它。 settings.webhook.delivery.success=ä¸€ä¸ªäº‹ä»¶å·²æ·»åŠ åˆ°æŽ¨é€é˜Ÿåˆ—。å¯èƒ½éœ€è¦è¿‡å‡ ç§’é’Ÿæ‰ä¼šæ˜¾ç¤ºåœ¨æŽ¨é€è®°å½•ä¸ã€‚ -settings.githooks_desc=Git Hook 是 Git 本身æä¾›çš„功能。您å¯ä»¥åœ¨ä¸‹æ–¹ç¼–辑 hook 文件以设置自定义æ“作。 +settings.githooks_desc=Git é’©åæ˜¯ Git 本身æä¾›çš„功能。您å¯ä»¥åœ¨ä¸‹æ–¹ç¼–辑 hook 文件以设置自定义æ“作。 settings.githook_edit_desc=å¦‚æžœé’©åæœªå¯åŠ¨ï¼Œåˆ™ä¼šæ˜¾ç¤ºæ ·ä¾‹æ–‡ä»¶ä¸çš„内容。如果想è¦åˆ 除æŸä¸ªé’©å,则æäº¤ç©ºç™½æ–‡æœ¬å³å¯ã€‚ settings.githook_name=é’©ååç§° settings.githook_content=é’©åæ–‡æœ¬ @@ -2341,7 +2341,7 @@ settings.update_githook=æ›´æ–°é’©å设置 settings.add_webhook_desc=Gitea å°†å‘ç›®æ ‡ URL å‘é€å…·æœ‰æŒ‡å®šå†…容类型的 <code>POST</code> 请求。在 <a target="_blank" rel="noopener noreferrer" href="%s">webhooks 指å—</a> ä¸é˜…读更多内容。 settings.payload_url=ç›®æ ‡ URL settings.http_method=HTTP 方法 -settings.content_type=POST Content Type +settings.content_type=POST 内容类型 settings.secret=密钥 settings.slack_username=æœåŠ¡åç§° settings.slack_icon_url=å›¾æ ‡ URL @@ -2376,7 +2376,7 @@ settings.event_issues_desc=å·¥å•已打开ã€å·²å…³é—ã€å·²é‡æ–°æ‰“å¼€æˆ–å·²ç¼ settings.event_issue_assign=å·¥å•已指派 settings.event_issue_assign_desc=å·¥å•å·²æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ settings.event_issue_label=å·²æ ‡è®°å·¥å• -settings.event_issue_label_desc=工啿 ‡ç¾å·²æ›´æ–°æˆ–清除。 +settings.event_issue_label_desc=工啿 ‡è®°å·²æ›´æ–°æˆ–清除。 settings.event_issue_milestone=å·¥å•å·²æ”¶å…¥é‡Œç¨‹ç¢‘ä¸ settings.event_issue_milestone_desc=å·¥å•å·²æ”¶å…¥æˆ–å–æ¶ˆæ”¶å…¥é‡Œç¨‹ç¢‘ä¸ã€‚ settings.event_issue_comment=å·¥å•评论 @@ -2386,8 +2386,8 @@ settings.event_pull_request=åˆå¹¶è¯·æ±‚ settings.event_pull_request_desc=åˆå¹¶è¯·æ±‚已打开ã€å…³é—ã€é‡æ–°æ‰“开或编辑。 settings.event_pull_request_assign=åˆå¹¶è¯·æ±‚已指派 settings.event_pull_request_assign_desc=åˆå¹¶è¯·æ±‚å·²æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ -settings.event_pull_request_label=åˆå¹¶è¯·æ±‚å·²è´´ä¸Šæ ‡ç¾ -settings.event_pull_request_label_desc=åˆå¹¶è¯·æ±‚çš„æ ‡ç¾å·²æ›´æ–°æˆ–清除。 +settings.event_pull_request_label=åˆå¹¶è¯·æ±‚å·²æ ‡è®° +settings.event_pull_request_label_desc=åˆå¹¶è¯·æ±‚æ ‡è®°å·²æ›´æ–°æˆ–æ¸…é™¤ã€‚ settings.event_pull_request_milestone=åˆå¹¶è¯·æ±‚å·²è®°å½•äºŽé‡Œç¨‹ç¢‘ä¸ settings.event_pull_request_milestone_desc=åˆå¹¶è¯·æ±‚å·²è®°å½•æˆ–å–æ¶ˆè®°å½•于里程碑ä¸ã€‚ settings.event_pull_request_comment=åˆå¹¶è¯·æ±‚已评论 @@ -2406,7 +2406,7 @@ settings.event_workflow_job_desc=Gitea 工作æµé˜Ÿåˆ—ä¸ã€ç‰å¾…ä¸ã€æ£åœ¨è¿ settings.event_package=软件包 settings.event_package_desc=软件包在仓库ä¸å·²åˆ›å»ºæˆ–åˆ é™¤ã€‚ settings.branch_filter=分支过滤 -settings.branch_filter_desc=推é€ã€åˆ›å»ºï¼Œåˆ 除分支事件的分支白åå•,使用 glob 模å¼åŒ¹é…指定。若为空或 <code>*</code>ï¼Œåˆ™å°†æŠ¥å‘Šæ‰€æœ‰åˆ†æ”¯çš„äº‹ä»¶ã€‚è¯æ³•æ–‡æ¡£è§ <a href="%[1]s">%[2]s</a>。示例:<code>master</code>,<code>{master,release*}</code>。 +settings.branch_filter_desc=推é€ã€åˆ›å»ºï¼Œåˆ 除分支事件的分支白åå•,使用 glob 表达å¼åŒ¹é…指定。若为空或 <code>*</code>ï¼Œåˆ™ä¼šæŠ¥å‘Šæ‰€æœ‰åˆ†æ”¯çš„äº‹ä»¶ã€‚è¯æ³•æ–‡æ¡£è§ <a href="%[1]s">%[2]s</a>。示例:<code>master</code>,<code>{master,release*}</code>。 settings.authorization_header=æŽˆæƒæ ‡å¤´ settings.authorization_header_desc=当å˜åœ¨æ—¶å°†è¢«ä½œä¸ºæŽˆæƒæ ‡å¤´åŒ…å«åœ¨å†…。例如: %s。 settings.active=激活 @@ -2460,7 +2460,7 @@ settings.protected_branch_can_push_yes=您å¯ä»¥æŽ¨é€ settings.protected_branch_can_push_no=您ä¸èƒ½æŽ¨é€ settings.branch_protection=分支「<b>%s</b>ã€çš„ä¿æŠ¤è§„åˆ™ settings.protect_this_branch=å¯ç”¨åˆ†æ”¯ä¿æŠ¤ -settings.protect_this_branch_desc=阻æ¢åˆ 除并é™åˆ¶Git推é€å’Œåˆå¹¶åˆ°åˆ†æ”¯ã€‚ +settings.protect_this_branch_desc=阻æ¢åˆ 除并é™åˆ¶ Git 推é€å’Œåˆå¹¶åˆ°åˆ†æ”¯ã€‚ settings.protect_disable_push=ç¦ç”¨æŽ¨é€ settings.protect_disable_push_desc=æ¤åˆ†æ”¯ä¸å…许推é€ã€‚ settings.protect_disable_force_push=ç¦ç”¨å¼ºåˆ¶æŽ¨é€ @@ -2486,13 +2486,13 @@ settings.protect_merge_whitelist_committers_desc=ä»…å…许白åå•用户或团é settings.protect_merge_whitelist_users=åˆå¹¶ç™½åå•用户: settings.protect_merge_whitelist_teams=åˆå¹¶ç™½åå•团队: settings.protect_check_status_contexts=å¯ç”¨çŠ¶æ€æ£€æŸ¥ -settings.protect_status_check_patterns=çŠ¶æ€æ£€æŸ¥æ¨¡å¼ï¼š -settings.protect_status_check_patterns_desc=输入模å¼ï¼ŒæŒ‡å®šå“ªäº›çŠ¶æ€æ£€æŸ¥å¿…须通过,æ‰èƒ½å°†åˆ†æ”¯åˆå¹¶åˆ°ç¬¦åˆæ¤è§„则的分支ä¸åŽ»ã€‚æ¯ä¸€è¡ŒæŒ‡å®šä¸€ä¸ªæ¨¡å¼ï¼Œæ¨¡å¼ä¸èƒ½ä¸ºç©ºã€‚ +settings.protect_status_check_patterns=çŠ¶æ€æ£€æŸ¥è¡¨è¾¾å¼ï¼š +settings.protect_status_check_patterns_desc=输入表达å¼ä»¥æŒ‡å®šåœ¨åˆ†æ”¯åˆå¹¶åˆ°åŒ¹é…æ¤è§„则的分支之å‰å¿…é¡»é€šè¿‡å“ªäº›çŠ¶æ€æ£€æŸ¥ã€‚æ¯ä¸€è¡ŒæŒ‡å®šä¸€ä¸ªè¡¨è¾¾å¼ä¸”表达å¼ä¸èƒ½ä¸ºç©ºã€‚ settings.protect_check_status_contexts_desc=è¦æ±‚çŠ¶æ€æ£€æŸ¥é€šè¿‡æ‰èƒ½åˆå¹¶ã€‚如果å¯ç”¨ï¼Œæäº¤å¿…须先推é€åˆ°å¦ä¸€ä¸ªåˆ†æ”¯ï¼Œç„¶åŽå†åˆå¹¶æˆ–推é€åˆ°åŒ¹é…è¿™äº›ä¿æŠ¤è§„åˆ™çš„åˆ†æ”¯ã€‚å¦‚æžœæ²¡æœ‰é€‰æ‹©å…·ä½“çš„çŠ¶æ€æ£€æŸ¥ä¸Šä¸‹æ–‡ï¼Œåˆ™æ‰€æœ‰çš„çŠ¶æ€æ£€æŸ¥éƒ½é€šè¿‡æ‰èƒ½åˆå¹¶ã€‚ settings.protect_check_status_contexts_list=æ¤ä»“åº“ä¸Šå‘¨è¿›è¡Œè¿‡çš„çŠ¶æ€æ£€æŸ¥ settings.protect_status_check_matched=åŒ¹é… -settings.protect_invalid_status_check_pattern=æ— æ•ˆçš„çŠ¶æ€æ£€æŸ¥è§„则:「%sã€ã€‚ -settings.protect_no_valid_status_check_patterns=æ²¡æœ‰æœ‰æ•ˆçš„çŠ¶æ€æ£€æŸ¥è§„则。 +settings.protect_invalid_status_check_pattern=æ— æ•ˆçš„çŠ¶æ€æ£€æŸ¥è¡¨è¾¾å¼ï¼šã€Œ%sã€ã€‚ +settings.protect_no_valid_status_check_patterns=æ²¡æœ‰æœ‰æ•ˆçš„çŠ¶æ€æ£€æŸ¥è¡¨è¾¾å¼ã€‚ settings.protect_required_approvals=所需的批准: settings.protect_required_approvals_desc=åªå…许åˆå¹¶æœ‰è¶³å¤Ÿå®¡æ ¸çš„åˆå¹¶è¯·æ±‚ã€‚è¦æ±‚çš„å®¡æ ¸å¿…é¡»æ¥è‡ªç™½å啿ˆ–者有æƒé™çš„用户或团队。 settings.protect_approvals_whitelist_enabled=仅列入白åå•的用户或团队æ‰å¯æ‰¹å‡† @@ -2505,13 +2505,13 @@ settings.ignore_stale_approvals=忽略过期批准 settings.ignore_stale_approvals_desc=对旧æäº¤ï¼ˆè¿‡æœŸå®¡æ ¸ï¼‰çš„æ‰¹å‡†å°†ä¸è®¡å…¥ PR çš„æ‰¹å‡†æ•°ã€‚å¦‚æžœè¿‡æœŸå®¡æŸ¥å·²è¢«é©³å›žï¼Œåˆ™ä¸Žæ¤æ— 关。 settings.require_signed_commits=需è¦ç¾åæäº¤ settings.require_signed_commits_desc=æ‹’ç»æŽ¨é€æœªç¾åæˆ–æ— æ³•éªŒè¯çš„æäº¤åˆ°åˆ†æ”¯ -settings.protect_branch_name_pattern=å—ä¿æŠ¤çš„åˆ†æ”¯åç§°æ¨¡å¼ -settings.protect_branch_name_pattern_desc=åˆ†æ”¯ä¿æŠ¤çš„å称匹é…è§„åˆ™ã€‚è¯æ³•请å‚阅 <a href="%s">文档</a> 。如:main, release/** -settings.protect_patterns=规则 -settings.protect_protected_file_patterns=å—ä¿æŠ¤çš„æ–‡ä»¶æ¨¡å¼(ä½¿ç”¨åˆ†å· ';' 分隔): -settings.protect_protected_file_patterns_desc=å³ä½¿ç”¨æˆ·æœ‰æƒæ·»åŠ ã€ç¼–è¾‘æˆ–åˆ é™¤æ¤åˆ†æ”¯ä¸çš„æ–‡ä»¶ï¼Œä¹Ÿä¸å…许直接更改å—ä¿æŠ¤çš„æ–‡ä»¶ã€‚ å¯ä»¥ä½¿ç”¨åˆ†å· (';') 分隔多个模å¼ã€‚ è§<a href='%[1]s'>%[2]s</a>文档了解模å¼è¯æ³•。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code> -settings.protect_unprotected_file_patterns=ä¸å—ä¿æŠ¤çš„æ–‡ä»¶æ¨¡å¼(ä½¿ç”¨åˆ†å· ';' 分隔): -settings.protect_unprotected_file_patterns_desc=如果用户有写æƒé™ï¼Œåˆ™å…许直接更改的ä¸å—ä¿æŠ¤çš„æ–‡ä»¶ï¼Œä»¥ç»•è¿‡æŽ¨é€é™åˆ¶ã€‚å¯ä»¥ä½¿ç”¨åˆ†å·åˆ†éš”å¤šä¸ªæ¨¡å¼ (';')。 è§ <a href='%[1]s'>%[2]s</a> 文档了解模å¼è¯æ³•。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code> +settings.protect_branch_name_pattern=å—ä¿æŠ¤çš„åˆ†æ”¯åç§°è¡¨è¾¾å¼ +settings.protect_branch_name_pattern_desc=åˆ†æ”¯ä¿æŠ¤çš„å称匹é…表达å¼ã€‚è¯æ³•请å‚阅 <a href="%s">文档</a> 。如:main, release/** +settings.protect_patterns=è¡¨è¾¾å¼ +settings.protect_protected_file_patterns=å—ä¿æŠ¤çš„æ–‡ä»¶è¡¨è¾¾å¼ï¼ˆä½¿ç”¨åˆ†å·ã€Œ;ã€åˆ†éš”): +settings.protect_protected_file_patterns_desc=å³ä½¿ç”¨æˆ·æœ‰æƒæ·»åŠ ã€ç¼–è¾‘æˆ–åˆ é™¤æ¤åˆ†æ”¯ä¸çš„æ–‡ä»¶ï¼Œä¹Ÿä¸å…许直接更改å—ä¿æŠ¤çš„æ–‡ä»¶ã€‚ å¯ä»¥ä½¿ç”¨åˆ†å·ã€Œ;ã€åˆ†éš”多个表达å¼ã€‚ è§<a href='%[1]s'>%[2]s</a>文档了解表达å¼è¯æ³•。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>。 +settings.protect_unprotected_file_patterns=ä¸å—ä¿æŠ¤çš„æ–‡ä»¶è¡¨è¾¾å¼ï¼ˆä½¿ç”¨åˆ†å·ã€Œ;ã€åˆ†éš”): +settings.protect_unprotected_file_patterns_desc=如果用户有写æƒé™ï¼Œåˆ™å…许直接更改的ä¸å—ä¿æŠ¤çš„æ–‡ä»¶ï¼Œä»¥ç»•è¿‡æŽ¨é€é™åˆ¶ã€‚å¯ä»¥ä½¿ç”¨åˆ†å·åˆ†éš”多个表达å¼ã€Œ;ã€ã€‚ è§ <a href='%[1]s'>%[2]s</a> 文档了解表达å¼è¯æ³•。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>。 settings.add_protected_branch=å¯ç”¨ä¿æŠ¤ settings.delete_protected_branch=ç¦ç”¨ä¿æŠ¤ settings.update_protect_branch_success=åˆ†æ”¯ä¿æŠ¤è§„åˆ™ã€Œ%sã€æ›´æ–°æˆåŠŸã€‚ @@ -2537,15 +2537,15 @@ settings.protected_branch_required_rule_name=必须填写规则åç§° settings.protected_branch_duplicate_rule_name=规则åç§°å·²å˜åœ¨ settings.protected_branch_required_approvals_min=所需的审批数ä¸èƒ½ä¸ºè´Ÿæ•°ã€‚ settings.tags=æ ‡ç¾ -settings.tags.protection=Gitæ ‡ç¾ä¿æŠ¤ -settings.tags.protection.pattern=Gitæ ‡ç¾æ¨¡å¼ +settings.tags.protection=æ ‡ç¾ä¿æŠ¤ +settings.tags.protection.pattern=æ ‡ç¾è¡¨è¾¾å¼ settings.tags.protection.allowed=å…许列表 settings.tags.protection.allowed.users=å…è®¸çš„è´¦å· settings.tags.protection.allowed.teams=å…许的团队 settings.tags.protection.allowed.noone=æ— -settings.tags.protection.create=ä¿æŠ¤Gitæ ‡ç¾ -settings.tags.protection.none=没有å—ä¿æŠ¤çš„Gitæ ‡ç¾ -settings.tags.protection.pattern.description=您å¯ä»¥ä½¿ç”¨å•个å称或 glob 模å¼åŒ¹é…或æ£åˆ™è¡¨è¾¾å¼æ¥åŒ¹é…å¤šä¸ªæ ‡ç¾ã€‚了解详情请访问 <a target="_blank" rel="noopener" href="%s">ä¿æŠ¤ Git æ ‡ç¾æŒ‡å—</a>。 +settings.tags.protection.create=ä¿æŠ¤æ ‡ç¾ +settings.tags.protection.none=没有å—ä¿æŠ¤çš„æ ‡ç¾ã€‚ +settings.tags.protection.pattern.description=您å¯ä»¥ä½¿ç”¨å•个å称或 glob 表达å¼åŒ¹é…或æ£åˆ™è¡¨è¾¾å¼æ¥åŒ¹é…å¤šä¸ªæ ‡ç¾ã€‚了解详情请访问 <a target="_blank" rel="noopener" href="%s">ä¿æŠ¤æ ‡ç¾æŒ‡å—</a>。 settings.bot_token=Bot 令牌 settings.chat_id=èŠå¤© ID settings.thread_id=线程 ID @@ -2571,7 +2571,7 @@ settings.archive.success=仓库已æˆåŠŸå½’æ¡£ã€‚ settings.archive.error=仓库在归档时出现异常。请通过日志获å–详细信æ¯ã€‚ settings.archive.error_ismirror=请ä¸è¦å¯¹é•œåƒä»“åº“å½’æ¡£ï¼Œè°¢è°¢ï¼ settings.archive.branchsettings_unavailable=å·²å½’æ¡£ä»“åº“æ— æ³•è¿›è¡Œåˆ†æ”¯è®¾ç½®ã€‚ -settings.archive.tagsettings_unavailable=已归档仓库的Gitæ ‡ç¾è®¾ç½®ä¸å¯ç”¨ã€‚ +settings.archive.tagsettings_unavailable=å·²å½’æ¡£ä»“åº“çš„æ ‡ç¾è®¾ç½®ä¸å¯ç”¨ã€‚ settings.archive.mirrors_unavailable=如果仓库已归档,镜åƒå°†ä¸å¯ç”¨ã€‚ settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销æ¤ä»“库归档 @@ -2672,7 +2672,7 @@ diff.submodule_updated=忍¡å— %[1]s 已更新:%[2]s releases.desc=跟踪项目版本和下载。 release.releases=å‘布 release.detail=å‘布详情 -release.tags=Gitæ ‡ç¾ +release.tags=æ ‡ç¾ release.new_release=å‘布新版 release.draft=è‰ç¨¿ release.prerelease=预å‘布 @@ -2701,16 +2701,16 @@ release.publish=å‘布版本 release.save_draft=ä¿å˜è‰ç¨¿ release.edit_release=ä¿å˜æ¤æ¬¡å‘布 release.delete_release=åˆ é™¤å‘布 -release.delete_tag=åˆ é™¤ Gitæ ‡ç¾ +release.delete_tag=åˆ é™¤æ ‡ç¾ release.deletion=åˆ é™¤å‘布 -release.deletion_desc=åˆ é™¤ç‰ˆæœ¬å‘布åªä¼šä»Ž Gitea ä¸ç§»é™¤ã€‚è¿™ä¸ä¼šå½±å“ Git çš„æ ‡ç¾ä»¥åŠæ‚¨ä»“库的内容和历å²ã€‚是å¦ç»§ç»ï¼Ÿ +release.deletion_desc=åˆ é™¤å‘布åªä¼šä»Ž Gitea ä¸ç§»é™¤å‘布。这ä¸ä¼šå½±å“ Git çš„æ ‡ç¾ä»¥åŠæ‚¨ä»“库的内容和历å²ã€‚是å¦ç»§ç»ï¼Ÿ release.deletion_success=该å‘å¸ƒå·²åˆ é™¤ã€‚ -release.deletion_tag_desc=将从仓库ä¸åˆ é™¤æ¤ Gitæ ‡ç¾ã€‚仓库内容和历å²è®°å½•ä¿æŒä¸å˜ã€‚ç»§ç»å—? -release.deletion_tag_success=该 Gitæ ‡ç¾å·²åˆ 除。 +release.deletion_tag_desc=将从仓库ä¸åˆ é™¤æ¤æ ‡ç¾ã€‚仓库内容和历å²è®°å½•ä¿æŒä¸å˜ã€‚ç»§ç»å—? +release.deletion_tag_success=è¯¥æ ‡ç¾å·²åˆ 除。 release.tag_name_already_exist=ä½¿ç”¨æ¤æ ‡ç¾åç§°çš„å‘布已ç»å˜åœ¨ã€‚ release.tag_name_invalid=æ ‡ç¾åç§°æ— æ•ˆã€‚ -release.tag_name_protected=Gitæ ‡ç¾åç§°å·²å—ä¿æŠ¤ã€‚ -release.tag_already_exist=æ¤ Gitæ ‡ç¾åç§°å·²å˜åœ¨ã€‚ +release.tag_name_protected=æ ‡ç¾åå·²å—ä¿æŠ¤ã€‚ +release.tag_already_exist=æ¤æ ‡ç¾åå·²å˜åœ¨ã€‚ release.downloads=下载附件 release.download_count=下载:%s release.add_tag_msg=使用å‘å¸ƒçš„æ ‡é¢˜å’Œå†…å®¹ä½œä¸ºæ ‡ç¾æ¶ˆæ¯ã€‚ @@ -2809,7 +2809,7 @@ team_unit_desc=å…许访问仓库å•å…ƒ team_unit_disabled=(å·²ç¦ç”¨) form.name_reserved=组织å称「%sã€æ˜¯ä¿ç•™çš„。 -form.name_pattern_not_allowed=仓库åç§°ä¸ä¸å…许使用「%sã€ã€‚ +form.name_pattern_not_allowed=组织åä¸ä¸å…许使用「%sã€æ ¼å¼ã€‚ form.create_org_not_allowed=æ¤è´¦å·ç¦æ¢åˆ›å»ºç»„织 settings=组织设置 @@ -2840,7 +2840,7 @@ settings.delete_org_title=åˆ é™¤ç»„ç»‡ settings.delete_org_desc=æ¤ç»„ç»‡å°†ä¼šæ°¸ä¹…åˆ é™¤ï¼Œç¡®è®¤ç»§ç»å—? settings.hooks_desc=在æ¤å¤„æ·»åŠ çš„ Web é’©å将会应用到该组织下的 <strong>所有仓库</strong>。 -settings.labels_desc=æ·»åŠ èƒ½å¤Ÿè¢«è¯¥ç»„ç»‡ä¸‹çš„ <strong>所有仓库</strong> 的工å•ä½¿ç”¨çš„æ ‡ç¾ã€‚ +settings.labels_desc=æ·»åŠ èƒ½å¤Ÿè¢«è¯¥ç»„ç»‡ä¸‹çš„ <strong>所有仓库</strong> 的工å•ä½¿ç”¨çš„æ ‡è®°ã€‚ members.membership_visibility=æˆå‘˜å¯è§æ€§ï¼š members.public=å¯è§ @@ -2960,11 +2960,11 @@ dashboard.task.cancelled=任务: %[1]s 已喿¶ˆ: %[3]s dashboard.task.error=任务ä¸çš„错误: %[1]s: %[3]s dashboard.task.finished=任务: %[2]s å¯åŠ¨çš„ %[1]s å·²å®Œæˆ dashboard.task.unknown=未知任务: %[1]s -dashboard.cron.started=已开始计划任务:%[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.cron.cancelled=计划任务:%[1]s 已喿¶ˆï¼š%[3]s +dashboard.cron.error=计划任务错误: %s: %[3]s +dashboard.cron.finished=计划任务:%[1]s å·²å®Œæˆ dashboard.delete_inactive_accounts=åˆ é™¤æ‰€æœ‰æœªæ¿€æ´»çš„å¸æˆ· dashboard.delete_inactive_accounts.started=åˆ é™¤æ‰€æœ‰æœªæ¿€æ´»çš„è´¦æˆ·ä»»åŠ¡å·²å¯åŠ¨ã€‚ dashboard.delete_repo_archives=åˆ é™¤æ‰€æœ‰ä»“åº“çš„å˜æ¡£ï¼ˆZIPã€TARã€GZç‰ï¼‰ @@ -3023,9 +3023,9 @@ dashboard.delete_old_actions.started=已开始从数æ®åº“ä¸åˆ 除所有旧工ä dashboard.update_checker=更新检查器 dashboard.delete_old_system_notices=从数æ®åº“ä¸åˆ 除所有旧系统通知 dashboard.gc_lfs=垃圾回收 LFS å…ƒæ•°æ® -dashboard.stop_zombie_tasks=åœæ¢åƒµå°¸ä»»åŠ¡ -dashboard.stop_endless_tasks=åœæ¢æ— é™å¾ªçŽ¯çš„å·¥ä½œæµ -dashboard.cancel_abandoned_jobs=å–æ¶ˆå·²æ”¾å¼ƒçš„å·¥ä½œæµ +dashboard.stop_zombie_tasks=åœæ¢åƒµå°¸å·¥ä½œæµä»»åŠ¡ +dashboard.stop_endless_tasks=åœæ¢æ— é™å¾ªçŽ¯çš„å·¥ä½œæµä»»åŠ¡ +dashboard.cancel_abandoned_jobs=å–æ¶ˆå·²æ”¾å¼ƒçš„工作æµä»»åŠ¡ dashboard.start_schedule_tasks=å¯åŠ¨å·¥ä½œæµè®¡åˆ’任务 dashboard.sync_branch.started=åˆ†æ”¯åŒæ¥å·²å¼€å§‹ dashboard.sync_tag.started=æ ‡ç¾åŒæ¥å·²å¼€å§‹ @@ -3098,7 +3098,7 @@ emails.filter_sort.email_reverse=邮箱(倒åºï¼‰ emails.filter_sort.name=用户å emails.filter_sort.name_reverse=用户å(倒åº) emails.updated=邮箱已更新 -emails.not_updated=æ— æ³•æ›´æ–°è¯·æ±‚çš„é‚®ç®±åœ°å€ï¼š %v +emails.not_updated=æ— æ³•æ›´æ–°è¯·æ±‚çš„é‚®ç®±åœ°å€ï¼š%v emails.duplicate_active=æ¤é‚®ç®±åœ°å€å·²è¢«å¦ä¸€ä¸ªç”¨æˆ·æ¿€æ´»ä½¿ç”¨ã€‚ emails.change_email_header=更新邮箱属性 emails.change_email_text=æ‚¨ç¡®å®šè¦æ›´æ–°è¯¥é‚®ç®±åœ°å€å—? @@ -3208,8 +3208,8 @@ auths.openIdConnectAutoDiscoveryURL=OpenID 连接自动å‘现 URL auths.oauth2_use_custom_url=使用自定义的 URL è€Œä¸æ˜¯é»˜è®¤çš„ URL auths.oauth2_tokenURL=令牌 URL auths.oauth2_authURL=æŽˆæƒ URL -auths.oauth2_profileURL=Profile URL -auths.oauth2_emailURL=邮件 URL +auths.oauth2_profileURL=个人资料 URL +auths.oauth2_emailURL=邮箱 URL auths.skip_local_two_fa=跳过本地两æ¥éªŒè¯ auths.skip_local_two_fa_helper=ä¸è®¾ç½®æ„味ç€è®¾ç½®äº†ä¸¤æ¥éªŒè¯çš„æœ¬åœ°ç”¨æˆ·ä»ç„¶éœ€è¦é€šè¿‡ä¸¤æ¥éªŒè¯æ‰èƒ½ç™»å½• auths.oauth2_tenant=租户 @@ -3264,7 +3264,7 @@ auths.deletion_success=è®¤è¯æºå·²ç»æ›´æ–°ã€‚ auths.login_source_exist=è®¤è¯æºã€Œ%sã€å·²ç»å˜åœ¨ã€‚ auths.login_source_of_type_exist=æ¤ç±»åž‹çš„è®¤è¯æºå·²å˜åœ¨ã€‚ auths.unable_to_initialize_openid=æ— æ³•åˆå§‹åŒ– OpenID Connect æä¾›å•†ï¼š%s -auths.invalid_openIdConnectAutoDiscoveryURL=æ— æ•ˆçš„ Auto Discovery URL (这必须是一个以 http:// 或 https://开头的有效的 URL) +auths.invalid_openIdConnectAutoDiscoveryURL=æ— æ•ˆçš„è‡ªåŠ¨å‘现 URL(这必须是一个以 http:// 或 https:// 开头的有效的 URL) config.server_config=æœåС噍é…ç½® config.app_name=站点åç§° @@ -3305,7 +3305,7 @@ config.db_type=类型 config.db_host=主机 config.db_name=æ•°æ®åº“åç§° config.db_user=用户å -config.db_schema=æž¶æž„æ¨¡å¼ +config.db_schema=æž¶æž„ config.db_ssl_mode=SSL config.db_path=æ•°æ®åº“路径 @@ -3314,7 +3314,7 @@ config.register_email_confirm=需è¦é‚®ä»¶ç¡®è®¤æ³¨å†Œ config.disable_register=ç¦æ¢ç”¨æˆ·æ³¨å†Œ config.allow_only_internal_registration=ä»…å…许通过 Gitea 进行注册 config.allow_only_external_registration=ä»…å…许通过外部æœåŠ¡æ³¨å†Œ -config.enable_openid_signup=å¯ç”¨ OpenID 自注册 +config.enable_openid_signup=å¯ç”¨ OpenID 自助注册 config.enable_openid_signin=å¯ç”¨ OpenID 登录 config.show_registration_button=显示注册按钮 config.require_sign_in_view=å¯ç”¨ç™»å½•访问é™åˆ¶ @@ -3406,7 +3406,7 @@ config.set_setting_failed=设置 %s 失败 monitor.stats=统计 -monitor.cron=Cron 任务 +monitor.cron=计划任务 monitor.name=任务åç§° monitor.schedule=任务安排 monitor.next=下次执行时间 @@ -3476,10 +3476,10 @@ rename_repo=é‡å‘½å仓库 <code>%[1]s</code> 为 <a href="%[2]s">%[3]s</a> commit_repo=推é€åˆ°äº†ä»“库 <a href="%[1]s">%[4]s</a> çš„ <a href="%[2]s">%[3]s</a> 分支 create_issue=`åˆ›å»ºäº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>` close_issue=`å…³é—äº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>` -reopen_issue=`釿–°å¼€å¯äº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>` +reopen_issue=`釿–°æ‰“å¼€äº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>` create_pull_request=`创建了åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` close_pull_request=`å…³é—了åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` -reopen_pull_request=`釿–°å¼€å¯äº†åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` +reopen_pull_request=`釿–°æ‰“开了åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` comment_issue=`è¯„è®ºäº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>` comment_pull=`评论了åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` merge_pull_request=`åˆå¹¶äº†åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>` @@ -3624,7 +3624,7 @@ container.images=é•œåƒ container.digest=æ‘˜è¦ container.multi_arch=OS / Arch container.layers=镜åƒå±‚ -container.labels=æ ‡ç¾ +container.labels=æ ‡è®° container.labels.key=é”® container.labels.value=值 cran.registry=在您的 <code>Rprofile.site</code> 文件ä¸è®¾ç½®æ¤æ³¨å†Œä¸å¿ƒï¼š @@ -3690,8 +3690,8 @@ settings.delete.error=åˆ é™¤è½¯ä»¶åŒ…å¤±è´¥ã€‚ owner.settings.cargo.title=Cargo 注册ä¸å¿ƒç´¢å¼• owner.settings.cargo.initialize=åˆå§‹åŒ–索引 owner.settings.cargo.initialize.description=使用 Cargo 注册ä¸å¿ƒæ—¶éœ€è¦ä¸€ä¸ªç‰¹æ®Šç´¢å¼•çš„ Git 仓库。使用æ¤é€‰é¡¹å°†ï¼ˆé‡æ–°ï¼‰åˆ›å»ºä»“库并自动é…置它。 -owner.settings.cargo.initialize.error=åˆå§‹åŒ–Cargo索引失败: %v -owner.settings.cargo.initialize.success=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 @@ -3704,7 +3704,7 @@ owner.settings.cleanuprules.preview=清ç†è§„则预览 owner.settings.cleanuprules.preview.overview=%d ä¸ªè½¯ä»¶åŒ…è®¡åˆ’è¢«åˆ é™¤ã€‚ owner.settings.cleanuprules.preview.none=清ç†è§„则与任何软件包都ä¸åŒ¹é…。 owner.settings.cleanuprules.enabled=å¯ç”¨ -owner.settings.cleanuprules.pattern_full_match=应用规则到完整软件包åç§° +owner.settings.cleanuprules.pattern_full_match=应用表达å¼åˆ°å®Œæ•´è½¯ä»¶åŒ…åç§° owner.settings.cleanuprules.keep.title=与这些规则相匹é…的版本å³ä½¿ä¸Žä¸‹é¢çš„åˆ é™¤è§„åˆ™ç›¸åŒ¹é…,也将予以ä¿ç•™ã€‚ owner.settings.cleanuprules.keep.count=ä¿ç•™æœ€æ–°çš„ owner.settings.cleanuprules.keep.count.1=æ¯ä¸ªè½¯ä»¶åŒ…1个版本 @@ -3727,8 +3727,8 @@ none=还没有密钥。 ; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=组织æè¿° -creation.name_placeholder=ä¸åŒºåˆ†å¤§å°å†™ï¼Œå—æ¯æ•°å—或下划线ä¸èƒ½ä»¥ GITEA_ 或 GITHUB_ 开头。 -creation.value_placeholder=输入任何内容,开头和结尾的空白都会被çœç•¥ +creation.name_placeholder=ä¸åŒºåˆ†å¤§å°å†™ï¼Œä»…é™å—æ¯æ•°å—或下划线且ä¸èƒ½ä»¥ GITEA_ 或 GITHUB_ 开头 +creation.value_placeholder=输入任何内容,开头和结尾的空白将会被忽略。 creation.description_placeholder=è¾“å…¥ç®€çŸæè¿°ï¼ˆå¯é€‰ï¼‰ã€‚ save_success=密钥「%sã€ä¿å˜æˆåŠŸã€‚ @@ -3737,8 +3737,8 @@ save_failed=密钥ä¿å˜å¤±è´¥ã€‚ add_secret=æ·»åŠ å¯†é’¥ edit_secret=编辑密钥 deletion=åˆ é™¤å¯†é’¥ -deletion.description=åˆ é™¤å¯†é’¥æ˜¯æ°¸ä¹…æ€§çš„ï¼Œæ— æ³•æ’¤æ¶ˆã€‚ç»§ç»å—? -deletion.success=æ¤å¯†é’¥å·²è¢«åˆ 除。 +deletion.description=åˆ é™¤å¯†é’¥æ˜¯æ°¸ä¹…æ€§çš„ä¸”æ— æ³•æ’¤æ¶ˆã€‚ç»§ç»ï¼Ÿ +deletion.success=æ¤å¯†é’¥å·²åˆ 除。 deletion.failed=åˆ é™¤å¯†é’¥å¤±è´¥ã€‚ management=å¯†é’¥ç®¡ç† @@ -3765,7 +3765,7 @@ runners.id=ID runners.name=åç§° runners.owner_type=类型 runners.description=æè¿° -runners.labels=æ ‡ç¾ +runners.labels=æ ‡è®° runners.last_online=上次在线时间 runners.runner_title=è¿è¡Œå™¨ runners.task_list=最近在æ¤è¿è¡Œå™¨ä¸Šçš„任务 @@ -3799,7 +3799,7 @@ runs.commit=æäº¤ runs.scheduled=已计划的 runs.pushed_by=推é€è€… runs.invalid_workflow_helper=工作æµé…ç½®æ–‡ä»¶æ— æ•ˆã€‚è¯·æ£€æŸ¥æ‚¨çš„é…置文件:%s -runs.no_matching_online_runner_helper=æ²¡æœ‰åŒ¹é… %s æ ‡ç¾çš„在线è¿è¡Œå™¨ +runs.no_matching_online_runner_helper=æ²¡æœ‰åŒ¹é… %s æ ‡è®°çš„åœ¨çº¿è¿è¡Œå™¨ runs.no_job_without_needs=工作æµå¿…须包å«è‡³å°‘一个没有ä¾èµ–关系的作业。 runs.no_job=工作æµå¿…须包å«è‡³å°‘一个作业 runs.actor=æ“作者 diff --git a/package-lock.json b/package-lock.json index 780b95d592..8a2f3e0db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,16 +37,16 @@ "license-checker-webpack-plugin": "0.2.1", "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", - "minimatch": "10.0.1", + "minimatch": "10.0.2", "monaco-editor": "0.52.2", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.3.1", "perfect-debounce": "1.0.0", - "postcss": "8.5.4", + "postcss": "8.5.5", "postcss-loader": "8.1.1", - "postcss-nesting": "13.0.1", + "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.24.0", + "swagger-ui-dist": "5.24.1", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -66,7 +66,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.52.0", + "@playwright/test": "1.53.0", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", "@stylistic/stylelint-plugin": "3.1.2", @@ -80,25 +80,25 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.33.1", - "@typescript-eslint/parser": "8.33.1", + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", "@vitejs/plugin-vue": "5.2.4", - "@vitest/eslint-plugin": "1.2.1", + "@vitest/eslint-plugin": "1.2.2", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.15.1", + "eslint-plugin-import-x": "4.15.2", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", - "eslint-plugin-regexp": "2.8.0", + "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "happy-dom": "17.6.3", + "happy-dom": "18.0.1", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.23.0", "nolyfill": "1.0.44", @@ -113,7 +113,7 @@ "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.2.2", + "vitest": "3.2.3", "vue-tsc": "2.2.10" }, "engines": { @@ -1054,10 +1054,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/eslintrc/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1177,10 +1184,17 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@humanwhocodes/config-array/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1546,9 +1560,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", - "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", "dev": true, "license": "MIT", "optional": true, @@ -1624,13 +1638,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", - "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.0.tgz", + "integrity": "sha512-15hjKreZDcp7t6TL/7jkAo6Df5STZN09jGiv5dbP9A6vMVncXRqE7/B2SncsyOwrkZRBH2i6/TPOL8BVmm3c7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.52.0" + "playwright": "1.53.0" }, "bin": { "playwright": "cli.js" @@ -1706,9 +1720,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", - "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz", + "integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==", "cpu": [ "arm" ], @@ -1720,9 +1734,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", - "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz", + "integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==", "cpu": [ "arm64" ], @@ -1734,9 +1748,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", - "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz", + "integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==", "cpu": [ "arm64" ], @@ -1748,9 +1762,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", - "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz", + "integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==", "cpu": [ "x64" ], @@ -1762,9 +1776,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", - "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz", + "integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==", "cpu": [ "arm64" ], @@ -1776,9 +1790,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", - "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz", + "integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==", "cpu": [ "x64" ], @@ -1790,9 +1804,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", - "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz", + "integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==", "cpu": [ "arm" ], @@ -1804,9 +1818,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", - "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz", + "integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==", "cpu": [ "arm" ], @@ -1818,9 +1832,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", - "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz", + "integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==", "cpu": [ "arm64" ], @@ -1832,9 +1846,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", - "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz", + "integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==", "cpu": [ "arm64" ], @@ -1846,9 +1860,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", - "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", + "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", "cpu": [ "loong64" ], @@ -1860,9 +1874,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", - "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", + "integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==", "cpu": [ "ppc64" ], @@ -1874,9 +1888,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", - "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", + "integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==", "cpu": [ "riscv64" ], @@ -1888,9 +1902,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", - "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz", + "integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==", "cpu": [ "riscv64" ], @@ -1902,9 +1916,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", - "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz", + "integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==", "cpu": [ "s390x" ], @@ -1916,9 +1930,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", - "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz", + "integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==", "cpu": [ "x64" ], @@ -1930,9 +1944,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", - "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz", + "integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==", "cpu": [ "x64" ], @@ -1944,9 +1958,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", - "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz", + "integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==", "cpu": [ "arm64" ], @@ -1958,9 +1972,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", - "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz", + "integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==", "cpu": [ "ia32" ], @@ -1972,9 +1986,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", - "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz", + "integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==", "cpu": [ "x64" ], @@ -2221,10 +2235,17 @@ "node": "^12.20 || >=14.13" } }, + "node_modules/@stoplight/spectral-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@stoplight/spectral-core/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -3005,12 +3026,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz", + "integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/normalize-package-data": { @@ -3167,18 +3188,25 @@ "node": ">= 8" } }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", - "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", + "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/type-utils": "8.33.1", - "@typescript-eslint/utils": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/type-utils": "8.34.0", + "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -3192,7 +3220,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.1", + "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -3208,16 +3236,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", - "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", + "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3233,14 +3261,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", - "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", + "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.1", - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/tsconfig-utils": "^8.34.0", + "@typescript-eslint/types": "^8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3255,14 +3283,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", - "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", + "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1" + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3273,9 +3301,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", - "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", + "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", "dev": true, "license": "MIT", "engines": { @@ -3290,14 +3318,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz", - "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", + "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/utils": "8.33.1", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/utils": "8.34.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3314,9 +3342,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", - "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", + "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", "dev": true, "license": "MIT", "engines": { @@ -3328,16 +3356,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", - "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", + "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.1", - "@typescript-eslint/tsconfig-utils": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/project-service": "8.34.0", + "@typescript-eslint/tsconfig-utils": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3356,6 +3384,23 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3373,16 +3418,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", - "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", + "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1" + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3397,13 +3442,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", - "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", + "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/types": "8.34.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3421,10 +3466,38 @@ "dev": true, "license": "ISC" }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz", + "integrity": "sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz", + "integrity": "sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.11.tgz", - "integrity": "sha512-i3/wlWjQJXMh1uiGtiv7k1EYvrrS3L1hdwmWJJiz1D8jWy726YFYPIxQWbEIVPVAgrfRR0XNlLrTQwq17cuCGw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz", + "integrity": "sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==", "cpu": [ "arm64" ], @@ -3436,9 +3509,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.11.tgz", - "integrity": "sha512-8XXyFvc6w6kmMmi6VYchZhjd5CDcp+Lv6Cn1YmUme0ypsZ/0Kzd+9ESrWtDrWibKPTgSteDTxp75cvBOY64FQQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz", + "integrity": "sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==", "cpu": [ "x64" ], @@ -3450,9 +3523,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.11.tgz", - "integrity": "sha512-0qJBYzP8Qk24CZ05RSWDQUjdiQUeIJGfqMMzbtXgCKl/a5xa6thfC0MQkGIr55LCLd6YmMyO640ifYUa53lybQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz", + "integrity": "sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==", "cpu": [ "x64" ], @@ -3464,9 +3537,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.11.tgz", - "integrity": "sha512-1sGwpgvx+WZf0GFT6vkkOm6UJ+mlsVnjw+Yv9esK71idWeRAG3bbpkf3AoY8KIqKqmnzJExi0uKxXpakQ5Pcbg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz", + "integrity": "sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==", "cpu": [ "arm" ], @@ -3478,9 +3551,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.11.tgz", - "integrity": "sha512-D/1F/2lTe+XAl3ohkYj51NjniVly8sIqkA/n1aOND3ZMO418nl2JNU95iVa1/RtpzaKcWEsNTtHRogykrUflJg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz", + "integrity": "sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==", "cpu": [ "arm" ], @@ -3492,9 +3565,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.11.tgz", - "integrity": "sha512-7vFWHLCCNFLEQlmwKQfVy066ohLLArZl+AV/AdmrD1/pD1FlmqM+FKbtnONnIwbHtgetFUCV/SRi1q4D49aTlw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz", + "integrity": "sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==", "cpu": [ "arm64" ], @@ -3506,9 +3579,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.11.tgz", - "integrity": "sha512-tYkGIx8hjWPh4zcn17jLEHU8YMmdP2obRTGkdaB3BguGHh31VCS3ywqC4QjTODjmhhNyZYkj/1Dz/+0kKvg9YA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz", + "integrity": "sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==", "cpu": [ "arm64" ], @@ -3520,9 +3593,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.11.tgz", - "integrity": "sha512-6F328QIUev29vcZeRX6v6oqKxfUoGwIIAhWGD8wSysnBYFY0nivp25jdWmAb1GildbCCaQvOKEhCok7YfWkj4Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz", + "integrity": "sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==", "cpu": [ "ppc64" ], @@ -3534,9 +3607,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.11.tgz", - "integrity": "sha512-NqhWmiGJGdzbZbeucPZIG9Iav4lyYLCarEnxAceguMx9qlpeEF7ENqYKOwB8Zqk7/CeuYMEcLYMaW2li6HyDzQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz", + "integrity": "sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==", "cpu": [ "riscv64" ], @@ -3548,9 +3621,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.11.tgz", - "integrity": "sha512-J2RPIFKMdTrLtBdfR1cUMKl8Gcy05nlQ+bEs/6al7EdWLk9cs3tnDREHZ7mV9uGbeghpjo4i8neNZNx3PYUY9w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz", + "integrity": "sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==", "cpu": [ "riscv64" ], @@ -3562,9 +3635,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.11.tgz", - "integrity": "sha512-bDpGRerHvvHdhun7MmFUNDpMiYcJSqWckwAVVRTJf8F+RyqYJOp/mx04PDc7DhpNPeWdnTMu91oZRMV+gGaVcQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz", + "integrity": "sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==", "cpu": [ "s390x" ], @@ -3576,9 +3649,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.11.tgz", - "integrity": "sha512-G9U7bVmylzRLma3cK39RBm3guoD1HOvY4o0NS4JNm37AD0lS7/xyMt7kn0JejYyc0Im8J+rH69/dXGM9DAJcSQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz", + "integrity": "sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==", "cpu": [ "x64" ], @@ -3590,9 +3663,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.11.tgz", - "integrity": "sha512-7qL20SBKomekSunm7M9Fe5L93bFbn+FbHiGJbfTlp0RKhPVoJDP73vOxf1QrmJHyDPECsGWPFnKa/f8fO2FsHw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz", + "integrity": "sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==", "cpu": [ "x64" ], @@ -3604,9 +3677,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.11.tgz", - "integrity": "sha512-jisvIva8MidjI+B1lFRZZMfCPaCISePgTyR60wNT1MeQvIh5Ksa0G3gvI+Iqyj3jqYbvOHByenpa5eDGcSdoSg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz", + "integrity": "sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==", "cpu": [ "wasm32" ], @@ -3614,16 +3687,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.10" + "@napi-rs/wasm-runtime": "^0.2.11" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.11.tgz", - "integrity": "sha512-G+H5nQZ8sRZ8ebMY6mRGBBvTEzMYEcgVauLsNHpvTUavZoCCRVP1zWkCZgOju2dW3O22+8seTHniTdl1/uLz3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz", + "integrity": "sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==", "cpu": [ "arm64" ], @@ -3635,9 +3708,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.11.tgz", - "integrity": "sha512-Hfy46DBfFzyv0wgR0MMOwFFib2W2+Btc8oE5h4XlPhpelnSyA6nFxkVIyTgIXYGTdFaLoZFNn62fmqx3rjEg3A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz", + "integrity": "sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==", "cpu": [ "ia32" ], @@ -3649,9 +3722,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.11.tgz", - "integrity": "sha512-7L8NdsQlCJ8T106Gbz/AjzM4QKWVsoQbKpB9bMBGcIZswUuAnJMHpvbqGW3RBqLHCIwX4XZ5fxSBHEFcK2h9wA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz", + "integrity": "sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==", "cpu": [ "x64" ], @@ -3677,9 +3750,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.1.tgz", - "integrity": "sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.2.tgz", + "integrity": "sha512-R8NwW+VxyKqVGcMfYsUbdThQyMbtNcoeg+jJeTgMHqWdFdcS0nrODAQXhkplvWzgd7jIJ+GQeydGqFLibsxMxg==", "dev": true, "license": "MIT", "dependencies": { @@ -3700,15 +3773,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", - "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz", + "integrity": "sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3717,13 +3790,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.3.tgz", + "integrity": "sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.2", + "@vitest/spy": "3.2.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3771,9 +3844,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", - "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", + "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", "dev": true, "license": "MIT", "dependencies": { @@ -3784,27 +3857,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", - "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.3.tgz", + "integrity": "sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.2", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.3", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", - "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.3.tgz", + "integrity": "sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3823,9 +3897,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", - "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.3.tgz", + "integrity": "sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==", "dev": true, "license": "MIT", "dependencies": { @@ -3836,13 +3910,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", - "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.3.tgz", + "integrity": "sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -3974,6 +4048,23 @@ } } }, + "node_modules/@vue/language-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@vue/language-core/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -4256,9 +4347,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4622,10 +4713,13 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", + "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", + "license": "MIT", + "engines": { + "node": ">= 16" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -4676,12 +4770,15 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.1.tgz", + "integrity": "sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^3.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/braces": { @@ -4799,9 +4896,9 @@ } }, "node_modules/cacheable": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.9.0.tgz", - "integrity": "sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.0.tgz", + "integrity": "sha512-SSgQTAnhd7WlJXnGlIi4jJJOiHzgnM5wRMEPaXAU4kECTAMpBoYKoZ9i5zHmclIEZbxcu3j7yY/CF8DTmwIsHg==", "dev": true, "license": "MIT", "dependencies": { @@ -4810,9 +4907,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.3.tgz", - "integrity": "sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", + "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", "dev": true, "license": "MIT", "dependencies": { @@ -4838,9 +4935,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", "funding": [ { "type": "opencollective", @@ -5241,13 +5338,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -6282,9 +6379,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.166", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz", + "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -6817,21 +6914,21 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.1.tgz", - "integrity": "sha512-JfVpNg1qMkPD66iaSgmMoSYeUCGS8UFSm3GwHV0IbuV3Knar/SyK5qqCct9+AxoMIzaM+KSO7KK5pOeOkC/3GQ==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.2.tgz", + "integrity": "sha512-J5gx7sN6DTm0LRT//eP3rVVQ2Yi4hrX0B+DbWxa5er8PZ6JjLo9GUBwogIFvEDdwJaSqZplpQT+haK/cXhb7VQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/types": "^8.34.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", - "eslint-import-context": "^0.1.7", + "eslint-import-context": "^0.1.8", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", "stable-hash-x": "^0.1.1", - "unrs-resolver": "^1.7.10" + "unrs-resolver": "^1.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6853,10 +6950,17 @@ } } }, + "node_modules/eslint-plugin-import/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -6940,10 +7044,17 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7051,9 +7162,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.8.0.tgz", - "integrity": "sha512-xme90IvkMgdyS+NJC21FM0H6ek4urGsdlIFTXpZRqH2BKJKVSd8hRbyrCpbcqfGBi2jth3eQoLiO3RC1gxZHiw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz", + "integrity": "sha512-9WqJMnOq8VlE/cK+YAo9C9YHhkOtcEtEk9d12a+H7OSZFwlpI6stiHmYPGa2VE0QhTzodJyhlyprUaXDZLgHBw==", "dev": true, "license": "MIT", "dependencies": { @@ -7093,6 +7204,23 @@ "eslint": "^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-sonarjs/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-sonarjs/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/eslint-plugin-sonarjs/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -7260,9 +7388,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -7289,10 +7417,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7352,15 +7487,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7811,10 +7946,16 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause" }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/glob/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -7967,19 +8108,37 @@ } }, "node_modules/happy-dom": { - "version": "17.6.3", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.6.3.tgz", - "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz", + "integrity": "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==", "dev": true, "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0", + "@types/node": "^20.0.0", + "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" }, "engines": { "node": ">=20.0.0" } }, + "node_modules/happy-dom/node_modules/@types/node": { + "version": "20.19.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.0.tgz", + "integrity": "sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/happy-dom/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -8880,10 +9039,16 @@ "webpack": "^4.4.0 || ^5.4.0" } }, + "node_modules/license-checker-webpack-plugin/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/license-checker-webpack-plugin/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9991,12 +10156,12 @@ } }, "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.2.tgz", + "integrity": "sha512-+9TJCIYXgZ2Dm5LxVCFsa8jOm+evMwXHFI0JM1XROmkfkpz8/iLLDh+TwSmyIBrs6C6Xu9294/fq8cBA+P6AqA==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^4.0.1" }, "engines": { "node": "20 || >=22" @@ -10694,13 +10859,13 @@ } }, "node_modules/playwright": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", - "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.0.tgz", + "integrity": "sha512-ghGNnIEYZC4E+YtclRn4/p6oYbdPiASELBIYkBXfaTVKreQUYbMUYQDwS12a8F0/HtIjr/CkGjtwABeFPGcS4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.52.0" + "playwright-core": "1.53.0" }, "bin": { "playwright": "cli.js" @@ -10713,9 +10878,9 @@ } }, "node_modules/playwright-core": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", - "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.0.tgz", + "integrity": "sha512-mGLg8m0pm4+mmtB7M89Xw/GSqoNC+twivl8ITteqvAndachozYe2ZA7srU6uleV1vEdAHYqjq+SV8SNxRRFYBw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10762,9 +10927,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", + "integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==", "funding": [ { "type": "opencollective", @@ -10983,9 +11148,9 @@ } }, "node_modules/postcss-nesting": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", - "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", "funding": [ { "type": "github", @@ -10998,7 +11163,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-resolve-nested": "^3.1.0", "@csstools/selector-specificity": "^5.0.0", "postcss-selector-parser": "^7.0.0" }, @@ -12215,6 +12380,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -12424,25 +12602,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.0.tgz", - "integrity": "sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", + "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.9" + "flat-cache": "^6.1.10" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.9.tgz", - "integrity": "sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.10.tgz", + "integrity": "sha512-B6/v1f0NwjxzmeOhzfXPGWpKBVA207LS7lehaVKQnFrVktcFRfkzjZZ2gwj2i1TkEUMQht7ZMJbABUT5N+V1Nw==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.9.0", + "cacheable": "^1.10.0", "flatted": "^3.3.3", - "hookified": "^1.8.2" + "hookified": "^1.9.1" } }, "node_modules/stylelint/node_modules/ignore": { @@ -12565,6 +12743,21 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/sucrase/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/sucrase/node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -12779,9 +12972,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.0.tgz", - "integrity": "sha512-okwN8vf14TOgBTUyGgCXEAoHnrwwp/042dC00B3kPu2OAe9zD75BtSbLlgAK1Y5e3csJhs+AdnIxJYZN9uvptg==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.1.tgz", + "integrity": "sha512-ITeWc7CCAfK53u8jnV39UNqStQZjSt+bVYtJHsOEL3vVj/WV9/8HmsF8Ej4oD8r+Xk1HpWyeW/t59r1QNeAcUQ==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -12915,9 +13108,9 @@ } }, "node_modules/terser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz", - "integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz", + "integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -13046,9 +13239,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -13268,9 +13461,9 @@ "license": "ISC" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/universalify": { @@ -13284,9 +13477,9 @@ } }, "node_modules/unrs-resolver": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.11.tgz", - "integrity": "sha512-OhuAzBImFPjKNgZ2JwHMfGFUA6NSbRegd1+BPjC1Y0E6X9Y/vJ4zKeGmIMqmlYboj6cMNEwKI+xQisrg4J0HaQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", + "integrity": "sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13297,23 +13490,25 @@ "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-darwin-arm64": "1.7.11", - "@unrs/resolver-binding-darwin-x64": "1.7.11", - "@unrs/resolver-binding-freebsd-x64": "1.7.11", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.11", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.11", - "@unrs/resolver-binding-linux-arm64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-arm64-musl": "1.7.11", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-riscv64-musl": "1.7.11", - "@unrs/resolver-binding-linux-s390x-gnu": "1.7.11", - "@unrs/resolver-binding-linux-x64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-x64-musl": "1.7.11", - "@unrs/resolver-binding-wasm32-wasi": "1.7.11", - "@unrs/resolver-binding-win32-arm64-msvc": "1.7.11", - "@unrs/resolver-binding-win32-ia32-msvc": "1.7.11", - "@unrs/resolver-binding-win32-x64-msvc": "1.7.11" + "@unrs/resolver-binding-android-arm-eabi": "1.9.0", + "@unrs/resolver-binding-android-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-x64": "1.9.0", + "@unrs/resolver-binding-freebsd-x64": "1.9.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.9.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-musl": "1.9.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-musl": "1.9.0", + "@unrs/resolver-binding-wasm32-wasi": "1.9.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.9.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.9.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.9.0" } }, "node_modules/update-browserslist-db": { @@ -13508,9 +13703,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.2.tgz", - "integrity": "sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz", + "integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13545,9 +13740,9 @@ "license": "MIT" }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -13588,9 +13783,9 @@ } }, "node_modules/vite/node_modules/rollup": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", - "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz", + "integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==", "dev": true, "license": "MIT", "dependencies": { @@ -13604,44 +13799,44 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.42.0", - "@rollup/rollup-android-arm64": "4.42.0", - "@rollup/rollup-darwin-arm64": "4.42.0", - "@rollup/rollup-darwin-x64": "4.42.0", - "@rollup/rollup-freebsd-arm64": "4.42.0", - "@rollup/rollup-freebsd-x64": "4.42.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", - "@rollup/rollup-linux-arm-musleabihf": "4.42.0", - "@rollup/rollup-linux-arm64-gnu": "4.42.0", - "@rollup/rollup-linux-arm64-musl": "4.42.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-musl": "4.42.0", - "@rollup/rollup-linux-s390x-gnu": "4.42.0", - "@rollup/rollup-linux-x64-gnu": "4.42.0", - "@rollup/rollup-linux-x64-musl": "4.42.0", - "@rollup/rollup-win32-arm64-msvc": "4.42.0", - "@rollup/rollup-win32-ia32-msvc": "4.42.0", - "@rollup/rollup-win32-x64-msvc": "4.42.0", + "@rollup/rollup-android-arm-eabi": "4.43.0", + "@rollup/rollup-android-arm64": "4.43.0", + "@rollup/rollup-darwin-arm64": "4.43.0", + "@rollup/rollup-darwin-x64": "4.43.0", + "@rollup/rollup-freebsd-arm64": "4.43.0", + "@rollup/rollup-freebsd-x64": "4.43.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", + "@rollup/rollup-linux-arm-musleabihf": "4.43.0", + "@rollup/rollup-linux-arm64-gnu": "4.43.0", + "@rollup/rollup-linux-arm64-musl": "4.43.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-musl": "4.43.0", + "@rollup/rollup-linux-s390x-gnu": "4.43.0", + "@rollup/rollup-linux-x64-gnu": "4.43.0", + "@rollup/rollup-linux-x64-musl": "4.43.0", + "@rollup/rollup-win32-arm64-msvc": "4.43.0", + "@rollup/rollup-win32-ia32-msvc": "4.43.0", + "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" } }, "node_modules/vitest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz", - "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.3.tgz", + "integrity": "sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.2", - "@vitest/mocker": "3.2.2", - "@vitest/pretty-format": "^3.2.2", - "@vitest/runner": "3.2.2", - "@vitest/snapshot": "3.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/expect": "3.2.3", + "@vitest/mocker": "3.2.3", + "@vitest/pretty-format": "^3.2.3", + "@vitest/runner": "3.2.3", + "@vitest/snapshot": "3.2.3", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -13655,7 +13850,7 @@ "tinypool": "^1.1.0", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.2", + "vite-node": "3.2.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -13671,8 +13866,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.2", - "@vitest/ui": "3.2.2", + "@vitest/browser": "3.2.3", + "@vitest/ui": "3.2.3", "happy-dom": "*", "jsdom": "*" }, @@ -13846,9 +14041,9 @@ } }, "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -13916,14 +14111,10 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/webpack": { "version": "5.99.9", @@ -14104,12 +14295,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/whatwg-url/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 0f12b831fa..96ade30f37 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,16 @@ "license-checker-webpack-plugin": "0.2.1", "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", - "minimatch": "10.0.1", + "minimatch": "10.0.2", "monaco-editor": "0.52.2", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.3.1", "perfect-debounce": "1.0.0", - "postcss": "8.5.4", + "postcss": "8.5.5", "postcss-loader": "8.1.1", - "postcss-nesting": "13.0.1", + "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.24.0", + "swagger-ui-dist": "5.24.1", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -65,7 +65,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.52.0", + "@playwright/test": "1.53.0", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", "@stylistic/stylelint-plugin": "3.1.2", @@ -79,25 +79,25 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.33.1", - "@typescript-eslint/parser": "8.33.1", + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", "@vitejs/plugin-vue": "5.2.4", - "@vitest/eslint-plugin": "1.2.1", + "@vitest/eslint-plugin": "1.2.2", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.15.1", + "eslint-plugin-import-x": "4.15.2", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", - "eslint-plugin-regexp": "2.8.0", + "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "happy-dom": "17.6.3", + "happy-dom": "18.0.1", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.23.0", "nolyfill": "1.0.44", @@ -112,7 +112,7 @@ "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.2.2", + "vitest": "3.2.3", "vue-tsc": "2.2.10" }, "browserslist": [ diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 95512cb9b6..2c138ad61a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -971,7 +971,8 @@ func Routes() *web.Router { // Misc (public accessible) m.Group("", func() { m.Get("/version", misc.Version) - m.Get("/signing-key.gpg", misc.SigningKey) + m.Get("/signing-key.gpg", misc.SigningKeyGPG) + m.Get("/signing-key.pub", misc.SigningKeySSH) m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup) m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw) @@ -1427,7 +1428,8 @@ func Routes() *web.Router { m.Combo("/file-contents", reqRepoReader(unit.TypeCode), context.ReferencesGitRepo()). Get(repo.GetFileContentsGet). Post(bind(api.GetFilesOptions{}), repo.GetFileContentsPost) // POST method requires "write" permission, so we also support "GET" method above - m.Get("/signing-key.gpg", misc.SigningKey) + m.Get("/signing-key.gpg", misc.SigningKeyGPG) + m.Get("/signing-key.pub", misc.SigningKeySSH) m.Group("/topics", func() { m.Combo("").Get(repo.ListTopics). Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics) diff --git a/routers/api/v1/misc/signing.go b/routers/api/v1/misc/signing.go index 667396e39c..db70e04b8f 100644 --- a/routers/api/v1/misc/signing.go +++ b/routers/api/v1/misc/signing.go @@ -4,14 +4,35 @@ package misc import ( - "fmt" - + "code.gitea.io/gitea/modules/git" asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/context" ) -// SigningKey returns the public key of the default signing key if it exists -func SigningKey(ctx *context.APIContext) { +func getSigningKey(ctx *context.APIContext, expectedFormat string) { + // if the handler is in the repo's route group, get the repo's signing key + // otherwise, get the global signing key + path := "" + if ctx.Repo != nil && ctx.Repo.Repository != nil { + path = ctx.Repo.Repository.RepoPath() + } + content, format, err := asymkey_service.PublicSigningKey(ctx, path) + if err != nil { + ctx.APIErrorInternal(err) + return + } + if format == "" { + ctx.APIErrorNotFound("no signing key") + return + } else if format != expectedFormat { + ctx.APIErrorNotFound("signing key format is " + format) + return + } + _, _ = ctx.Write([]byte(content)) +} + +// SigningKeyGPG returns the public key of the default signing key if it exists +func SigningKeyGPG(ctx *context.APIContext) { // swagger:operation GET /signing-key.gpg miscellaneous getSigningKey // --- // summary: Get default signing-key.gpg @@ -44,19 +65,42 @@ func SigningKey(ctx *context.APIContext) { // description: "GPG armored public key" // schema: // type: string + getSigningKey(ctx, git.SigningKeyFormatOpenPGP) +} - path := "" - if ctx.Repo != nil && ctx.Repo.Repository != nil { - path = ctx.Repo.Repository.RepoPath() - } +// SigningKeySSH returns the public key of the default signing key if it exists +func SigningKeySSH(ctx *context.APIContext) { + // swagger:operation GET /signing-key.pub miscellaneous getSigningKeySSH + // --- + // summary: Get default signing-key.pub + // produces: + // - text/plain + // responses: + // "200": + // description: "ssh public key" + // schema: + // type: string - content, err := asymkey_service.PublicSigningKey(ctx, path) - if err != nil { - ctx.APIErrorInternal(err) - return - } - _, err = ctx.Write([]byte(content)) - if err != nil { - ctx.APIErrorInternal(fmt.Errorf("Error writing key content %w", err)) - } + // swagger:operation GET /repos/{owner}/{repo}/signing-key.pub repository repoSigningKeySSH + // --- + // summary: Get signing-key.pub for given repository + // produces: + // - text/plain + // 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 + // responses: + // "200": + // description: "ssh public key" + // schema: + // type: string + getSigningKey(ctx, git.SigningKeyFormatSSH) } diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go index d42afafe9e..59b97c1717 100644 --- a/routers/web/misc/misc.go +++ b/routers/web/misc/misc.go @@ -20,7 +20,7 @@ func SSHInfo(rw http.ResponseWriter, req *http.Request) { return } rw.Header().Set("content-type", "text/json;charset=UTF-8") - _, err := rw.Write([]byte(`{"type":"gitea","version":1}`)) + _, err := rw.Write([]byte(`{"type":"agit","version":1}`)) if err != nil { log.Error("fail to write result: err: %v", err) rw.WriteHeader(http.StatusInternalServerError) diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 5552a8726c..6602685e94 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -62,7 +62,7 @@ func SettingsCtxData(ctx *context.Context) { ctx.Data["CanConvertFork"] = ctx.Repo.Repository.IsFork && ctx.Doer.CanCreateRepoIn(ctx.Repo.Repository.Owner) signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) - ctx.Data["SigningKeyAvailable"] = len(signing) > 0 + ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled @@ -105,7 +105,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) - ctx.Data["SigningKeyAvailable"] = len(signing) > 0 + ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled diff --git a/routers/web/repo/view_file.go b/routers/web/repo/view_file.go index 3df6051975..f43433fb0d 100644 --- a/routers/web/repo/view_file.go +++ b/routers/web/repo/view_file.go @@ -140,13 +140,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["LFSLockHint"] = ctx.Tr("repo.editor.this_file_locked") } - // Assume file is not editable first. - if fInfo.isLFSFile { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files") - } else if !isRepresentableAsText { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files") - } - // read all needed attributes which will be used later // there should be no performance different between reading 2 or 4 here attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{ @@ -243,21 +236,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["FileContent"] = fileContent ctx.Data["LineEscapeStatus"] = statuses } - if !fInfo.isLFSFile { - if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { - if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { - ctx.Data["CanEditFile"] = false - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") - } else { - ctx.Data["CanEditFile"] = true - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file") - } - } else if !ctx.Repo.RefFullName.IsBranch() { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit") - } - } case fInfo.st.IsPDF(): ctx.Data["IsPDFFile"] = true @@ -307,17 +285,49 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { } } - if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { - if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { - ctx.Data["CanDeleteFile"] = false - ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") - } else { - ctx.Data["CanDeleteFile"] = true - ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file") - } - } else if !ctx.Repo.RefFullName.IsBranch() { + prepareToRenderButtons(ctx, fInfo.isLFSFile, isRepresentableAsText, lfsLock) +} + +func prepareToRenderButtons(ctx *context.Context, isLFSFile, isRepresentableAsText bool, lfsLock *git_model.LFSLock) { + // archived or mirror repository, the buttons should not be shown + if ctx.Repo.Repository.IsArchived || !ctx.Repo.Repository.CanEnableEditor() { + return + } + + // The buttons should not be shown if it's not a branch + if !ctx.Repo.RefFullName.IsBranch() { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + return + } + + if isLFSFile { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files") + } else if !isRepresentableAsText { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files") + } + + if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + if !isLFSFile { // lfs file cannot be edited after fork + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit") + } ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_have_write_access") + return + } + + // it's a lfs file and the user is not the owner of the lock + if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { + ctx.Data["CanEditFile"] = false + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") + ctx.Data["CanDeleteFile"] = false + ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") + return + } + + if !isLFSFile { // lfs file cannot be edited + ctx.Data["CanEditFile"] = true + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file") } + ctx.Data["CanDeleteFile"] = true + ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file") } diff --git a/services/asymkey/commit.go b/services/asymkey/commit.go index 105782a93a..148f51fd10 100644 --- a/services/asymkey/commit.go +++ b/services/asymkey/commit.go @@ -6,6 +6,7 @@ package asymkey import ( "context" "fmt" + "slices" "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -359,24 +360,39 @@ func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, si return nil } +func verifySSHCommitVerificationByInstanceKey(c *git.Commit, committerUser, signerUser *user_model.User, committerGitEmail, publicKeyContent string) *asymkey_model.CommitVerification { + fingerprint, err := asymkey_model.CalcFingerprint(publicKeyContent) + if err != nil { + log.Error("Error calculating the fingerprint public key %q, err: %v", publicKeyContent, err) + return nil + } + sshPubKey := &asymkey_model.PublicKey{ + Verified: true, + Content: publicKeyContent, + Fingerprint: fingerprint, + HasUsed: true, + } + return verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, sshPubKey, committerUser, signerUser, committerGitEmail) +} + // ParseCommitWithSSHSignature check if signature is good against keystore. -func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification { +func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committerUser *user_model.User) *asymkey_model.CommitVerification { // Now try to associate the signature with the committer, if present - if committer.ID != 0 { + if committerUser.ID != 0 { keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ - OwnerID: committer.ID, + OwnerID: committerUser.ID, NotKeytype: asymkey_model.KeyTypePrincipal, }) if err != nil { // Skipping failed to get ssh keys of user log.Error("ListPublicKeys: %v", err) return &asymkey_model.CommitVerification{ - CommittingUser: committer, + CommittingUser: committerUser, Verified: false, Reason: "gpg.error.failed_retrieval_gpg_keys", } } - committerEmailAddresses, err := cache.GetWithContextCache(ctx, cachegroup.UserEmailAddresses, committer.ID, user_model.GetEmailAddresses) + committerEmailAddresses, err := cache.GetWithContextCache(ctx, cachegroup.UserEmailAddresses, committerUser.ID, user_model.GetEmailAddresses) if err != nil { log.Error("GetEmailAddresses: %v", err) } @@ -391,7 +407,7 @@ func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer * for _, k := range keys { if k.Verified && activated { - commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committer, committer, c.Committer.Email) + commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committerUser, committerUser, c.Committer.Email) if commitVerification != nil { return commitVerification } @@ -399,8 +415,45 @@ func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer * } } + // Try the pre-set trusted keys (for key-rotation purpose) + // At the moment, we still use the SigningName&SigningEmail for the rotated keys. + // Maybe in the future we can extend the key format to "ssh-xxx .... old-user@example.com" to support different signer emails. + for _, k := range setting.Repository.Signing.TrustedSSHKeys { + signerUser := &user_model.User{ + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + } + commitVerification := verifySSHCommitVerificationByInstanceKey(c, committerUser, signerUser, c.Committer.Email, k) + if commitVerification != nil && commitVerification.Verified { + return commitVerification + } + } + + // Try the configured instance-wide SSH public key + if setting.Repository.Signing.SigningFormat == git.SigningKeyFormatSSH && !slices.Contains([]string{"", "default", "none"}, setting.Repository.Signing.SigningKey) { + gpgSettings := git.GPGSettings{ + Sign: true, + KeyID: setting.Repository.Signing.SigningKey, + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + Format: setting.Repository.Signing.SigningFormat, + } + signerUser := &user_model.User{ + Name: gpgSettings.Name, + Email: gpgSettings.Email, + } + if err := gpgSettings.LoadPublicKeyContent(); err != nil { + log.Error("Error getting instance-wide SSH signing key %q, err: %v", gpgSettings.KeyID, err) + } else { + commitVerification := verifySSHCommitVerificationByInstanceKey(c, committerUser, signerUser, gpgSettings.Email, gpgSettings.PublicKeyContent) + if commitVerification != nil && commitVerification.Verified { + return commitVerification + } + } + } + return &asymkey_model.CommitVerification{ - CommittingUser: committer, + CommittingUser: committerUser, Verified: false, Reason: asymkey_model.NoKeyFound, } diff --git a/services/asymkey/commit_test.go b/services/asymkey/commit_test.go new file mode 100644 index 0000000000..0438209a61 --- /dev/null +++ b/services/asymkey/commit_test.go @@ -0,0 +1,54 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package asymkey + +import ( + "strings" + "testing" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseCommitWithSSHSignature(t *testing.T) { + // Here we only test the TrustedSSHKeys. The complete signing test is in tests/integration/gpg_ssh_git_test.go + t.Run("TrustedSSHKey", func(t *testing.T) { + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() + defer test.MockVariableValue(&setting.Repository.Signing.TrustedSSHKeys, []string{"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH6Y4idVaW3E+bLw1uqoAfJD7o5Siu+HqS51E9oQLPE9"})() + + commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree 9a93ffa76e8b72bdb6431910b3a506fa2b39f42e +author User Two <user2@example.com> 1749230009 +0200 +committer User Two <user2@example.com> 1749230009 +0200 +gpgsig -----BEGIN SSH SIGNATURE----- + U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgfpjiJ1VpbcT5svDW6qgB8kPujl + KK74epLnUT2hAs8T0AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 + AAAAQDX2t2iHuuLxEWHLJetYXKsgayv3c43r0pJNfAzdLN55Q65pC5M7rG6++gT2bxcpOu + Y6EXbpLqia9sunEF3+LQY= + -----END SSH SIGNATURE----- + +Initial commit with signed file +`)) + require.NoError(t, err) + committingUser := &user_model.User{ + ID: 2, + Name: "User Two", + Email: "user2@example.com", + } + ret := ParseCommitWithSSHSignature(t.Context(), commit, committingUser) + require.NotNil(t, ret) + assert.True(t, ret.Verified) + assert.False(t, ret.Warning) + assert.Equal(t, committingUser, ret.CommittingUser) + if assert.NotNil(t, ret.SigningUser) { + assert.Equal(t, "gitea", ret.SigningUser.Name) + assert.Equal(t, "gitea@fake.local", ret.SigningUser.Email) + } + }) +} diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 2216bca54a..f94462ea46 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -6,6 +6,7 @@ package asymkey import ( "context" "fmt" + "os" "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -85,9 +86,9 @@ func IsErrWontSign(err error) bool { } // SigningKey returns the KeyID and git Signature for the repo -func SigningKey(ctx context.Context, repoPath string) (string, *git.Signature) { +func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Signature) { if setting.Repository.Signing.SigningKey == "none" { - return "", nil + return nil, nil } if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { @@ -95,53 +96,77 @@ func SigningKey(ctx context.Context, repoPath string) (string, *git.Signature) { value, _, _ := git.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) sign, valid := git.ParseBool(strings.TrimSpace(value)) if !sign || !valid { - return "", nil + return nil, nil } + format, _, _ := git.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingKey, _, _ := git.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingName, _, _ := git.NewCommand("config", "--get", "user.name").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingEmail, _, _ := git.NewCommand("config", "--get", "user.email").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - return strings.TrimSpace(signingKey), &git.Signature{ - Name: strings.TrimSpace(signingName), - Email: strings.TrimSpace(signingEmail), + + if strings.TrimSpace(signingKey) == "" { + return nil, nil } + + return &git.SigningKey{ + KeyID: strings.TrimSpace(signingKey), + Format: strings.TrimSpace(format), + }, &git.Signature{ + Name: strings.TrimSpace(signingName), + Email: strings.TrimSpace(signingEmail), + } } - return setting.Repository.Signing.SigningKey, &git.Signature{ - Name: setting.Repository.Signing.SigningName, - Email: setting.Repository.Signing.SigningEmail, + if setting.Repository.Signing.SigningKey == "" { + return nil, nil } + + return &git.SigningKey{ + KeyID: setting.Repository.Signing.SigningKey, + Format: setting.Repository.Signing.SigningFormat, + }, &git.Signature{ + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + } } // PublicSigningKey gets the public signing key within a provided repository directory -func PublicSigningKey(ctx context.Context, repoPath string) (string, error) { +func PublicSigningKey(ctx context.Context, repoPath string) (content, format string, err error) { signingKey, _ := SigningKey(ctx, repoPath) - if signingKey == "" { - return "", nil + if signingKey == nil { + return "", "", nil + } + if signingKey.Format == git.SigningKeyFormatSSH { + content, err := os.ReadFile(signingKey.KeyID) + if err != nil { + log.Error("Unable to read SSH public key file in %s: %s, %v", repoPath, signingKey, err) + return "", signingKey.Format, err + } + return string(content), signingKey.Format, nil } content, stderr, err := process.GetManager().ExecDir(ctx, -1, repoPath, - "gpg --export -a", "gpg", "--export", "-a", signingKey) + "gpg --export -a", "gpg", "--export", "-a", signingKey.KeyID) if err != nil { log.Error("Unable to get default signing key in %s: %s, %s, %v", repoPath, signingKey, stderr, err) - return "", err + return "", signingKey.Format, err } - return content, nil + return content, signingKey.Format, nil } // SignInitialCommit determines if we should sign the initial commit to this repository -func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, string, *git.Signature, error) { +func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.InitialCommit) signingKey, sig := SigningKey(ctx, repoPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -150,18 +175,18 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } } } @@ -169,19 +194,19 @@ Loop: } // SignWikiCommit determines if we should sign the commits to this repository wiki -func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, string, *git.Signature, error) { +func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { repoWikiPath := repo.WikiPath() rules := signingModeFromStrings(setting.Repository.Signing.Wiki) signingKey, sig := SigningKey(ctx, repoWikiPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -190,35 +215,35 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case parentSigned: gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo()) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() commit, err := gitRepo.GetCommit("HEAD") if err != nil { - return false, "", nil, err + return false, nil, nil, err } if commit.Signature == nil { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } } } @@ -226,18 +251,18 @@ Loop: } // SignCRUDAction determines if we should sign a CRUD commit to this repository -func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, string, *git.Signature, error) { +func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions) signingKey, sig := SigningKey(ctx, repoPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -246,35 +271,35 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case parentSigned: gitRepo, err := git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() commit, err := gitRepo.GetCommit(parentCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if commit.Signature == nil { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } } } @@ -282,16 +307,16 @@ Loop: } // SignMerge determines if we should sign a PR merge commit to the base repository -func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, string, *git.Signature, error) { +func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, *git.SigningKey, *git.Signature, error) { if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to get Base Repo for pull request") - return false, "", nil, err + return false, nil, nil, err } repo := pr.BaseRepo signingKey, signer := SigningKey(ctx, repo.RepoPath()) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } rules := signingModeFromStrings(setting.Repository.Signing.Merges) @@ -302,7 +327,7 @@ Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -311,91 +336,91 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case approved: protectedBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, pr.BaseBranch) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if protectedBranch == nil { - return false, "", nil, &ErrWontSign{approved} + return false, nil, nil, &ErrWontSign{approved} } if issues_model.GetGrantedApprovalsCount(ctx, protectedBranch, pr) < 1 { - return false, "", nil, &ErrWontSign{approved} + return false, nil, nil, &ErrWontSign{approved} } case baseSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(baseCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{baseSigned} + return false, nil, nil, &ErrWontSign{baseSigned} } case headSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{headSigned} + return false, nil, nil, &ErrWontSign{headSigned} } case commitsSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{commitsSigned} + return false, nil, nil, &ErrWontSign{commitsSigned} } // need to work out merge-base mergeBaseCommit, _, err := gitRepo.GetMergeBase("", baseCommit, headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } commitList, err := commit.CommitsBeforeUntil(mergeBaseCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } for _, commit := range commitList { verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{commitsSigned} + return false, nil, nil, &ErrWontSign{commitsSigned} } } } diff --git a/services/context/repo.go b/services/context/repo.go index 61841aa90b..32d54c88ff 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -101,7 +101,7 @@ type CanCommitToBranchResults struct { UserCanPush bool RequireSigned bool WillSign bool - SigningKey string + SigningKey *git.SigningKey WontSignReason string } @@ -123,7 +123,8 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use sign, keyID, _, err := asymkey_service.SignCRUDAction(ctx, r.Repository.RepoPath(), doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName) - canCommit := r.CanEnableEditor(ctx, doer) && userCanPush + canEnableEditor := r.CanEnableEditor(ctx, doer) + canCommit := canEnableEditor && userCanPush if requireSigned { canCommit = canCommit && sign } @@ -139,7 +140,7 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use return CanCommitToBranchResults{ CanCommitToBranch: canCommit, - EditorEnabled: r.CanEnableEditor(ctx, doer), + EditorEnabled: canEnableEditor, UserCanPush: userCanPush, RequireSigned: requireSigned, WillSign: sign, diff --git a/services/pull/merge.go b/services/pull/merge.go index 829d4b7ee1..2a2f47e880 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -432,10 +432,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use func commitAndSignNoAuthor(ctx *mergeContext, message string) error { cmdCommit := git.NewCommand("commit").AddOptionFormat("--message=%s", message) - if ctx.signKeyID == "" { + if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { - cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID) + if ctx.signKey.Format != "" { + cmdCommit.AddConfig("gpg.format", ctx.signKey.Format) + } + cmdCommit.AddOptionFormat("-S%s", ctx.signKey.KeyID) } if err := cmdCommit.Run(ctx, ctx.RunOpts()); err != nil { log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 719cc6b965..31a1e13734 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -27,7 +27,7 @@ type mergeContext struct { doer *user_model.User sig *git.Signature committer *git.Signature - signKeyID string // empty for no-sign, non-empty to sign + signKey *git.SigningKey env []string } @@ -99,9 +99,9 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque mergeCtx.committer = mergeCtx.sig // Determine if we should sign - sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch) + sign, key, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch) if sign { - mergeCtx.signKeyID = keyID + mergeCtx.signKey = key if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { mergeCtx.committer = signer } diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go index 119b28736c..0049c0b117 100644 --- a/services/pull/merge_squash.go +++ b/services/pull/merge_squash.go @@ -71,10 +71,13 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { cmdCommit := git.NewCommand("commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email). AddOptionFormat("--message=%s", message) - if ctx.signKeyID == "" { + if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { - cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID) + if ctx.signKey.Format != "" { + cmdCommit.AddConfig("gpg.format", ctx.signKey.Format) + } + cmdCommit.AddOptionFormat("-S%s", ctx.signKey.KeyID) } if err := cmdCommit.Run(ctx, ctx.RunOpts()); err != nil { log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 493ff9998d..1cf30edc7b 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -293,15 +293,18 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit } var sign bool - var keyID string + var key *git.SigningKey var signer *git.Signature if opts.ParentCommitID != "" { - sign, keyID, signer, _ = asymkey_service.SignCRUDAction(ctx, t.repo.RepoPath(), opts.DoerUser, t.basePath, opts.ParentCommitID) + sign, key, signer, _ = asymkey_service.SignCRUDAction(ctx, t.repo.RepoPath(), opts.DoerUser, t.basePath, opts.ParentCommitID) } else { - sign, keyID, signer, _ = asymkey_service.SignInitialCommit(ctx, t.repo.RepoPath(), opts.DoerUser) + sign, key, signer, _ = asymkey_service.SignInitialCommit(ctx, t.repo.RepoPath(), opts.DoerUser) } if sign { - cmdCommitTree.AddOptionFormat("-S%s", keyID) + if key.Format != "" { + cmdCommitTree.AddConfig("gpg.format", key.Format) + } + cmdCommitTree.AddOptionFormat("-S%s", key.KeyID) if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email { // Add trailers diff --git a/services/repository/init.go b/services/repository/init.go index bd777b8a2f..1eeeb4aa4f 100644 --- a/services/repository/init.go +++ b/services/repository/init.go @@ -42,9 +42,12 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi cmd := git.NewCommand("commit", "--message=Initial commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) - sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) + sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) if sign { - cmd.AddOptionFormat("-S%s", keyID) + if key.Format != "" { + cmd.AddConfig("gpg.format", key.Format) + } + cmd.AddOptionFormat("-S%s", key.KeyID) if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { // need to set the committer to the KeyID owner diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 9405f7cfc8..0a955406e2 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -194,7 +194,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { - commitTreeOpts.KeyID = signingKey + commitTreeOpts.Key = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { committer = signer } @@ -316,7 +316,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { - commitTreeOpts.KeyID = signingKey + commitTreeOpts.Key = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { committer = signer } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 68b09c484b..cc9abd92bd 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15164,6 +15164,42 @@ } } }, + "/repos/{owner}/{repo}/signing-key.pub": { + "get": { + "produces": [ + "text/plain" + ], + "tags": [ + "repository" + ], + "summary": "Get signing-key.pub for given repository", + "operationId": "repoSigningKeySSH", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ssh public key", + "schema": { + "type": "string" + } + } + } + } + }, "/repos/{owner}/{repo}/stargazers": { "get": { "produces": [ @@ -16997,6 +17033,26 @@ } } }, + "/signing-key.pub": { + "get": { + "produces": [ + "text/plain" + ], + "tags": [ + "miscellaneous" + ], + "summary": "Get default signing-key.pub", + "operationId": "getSigningKeySSH", + "responses": { + "200": { + "description": "ssh public key", + "schema": { + "type": "string" + } + } + } + } + }, "/teams/{id}": { "get": { "produces": [ diff --git a/tests/integration/gpg_git_test.go b/tests/integration/gpg_ssh_git_test.go index 32de200f63..56f9f87783 100644 --- a/tests/integration/gpg_git_test.go +++ b/tests/integration/gpg_ssh_git_test.go @@ -4,7 +4,10 @@ package integration import ( + "crypto/ed25519" + "crypto/rand" "encoding/base64" + "encoding/pem" "fmt" "net/url" "os" @@ -23,6 +26,7 @@ import ( "github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/crypto/ssh" ) func TestGPGGit(t *testing.T) { @@ -42,6 +46,37 @@ func TestGPGGit(t *testing.T) { defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})() defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})() + testGitSigning(t) +} + +func TestSSHGit(t *testing.T) { + tmpDir := t.TempDir() // use a temp dir to store the SSH keys + err := os.Chmod(tmpDir, 0o700) + assert.NoError(t, err) + + pub, priv, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err, "ed25519.GenerateKey") + sshPubKey, err := ssh.NewPublicKey(pub) + require.NoError(t, err, "ssh.NewPublicKey") + + err = os.WriteFile(tmpDir+"/id_ed25519.pub", ssh.MarshalAuthorizedKey(sshPubKey), 0o600) + require.NoError(t, err, "os.WriteFile id_ed25519.pub") + block, err := ssh.MarshalPrivateKey(priv, "") + require.NoError(t, err, "ssh.MarshalPrivateKey") + err = os.WriteFile(tmpDir+"/id_ed25519", pem.EncodeToMemory(block), 0o600) + require.NoError(t, err, "os.WriteFile id_ed25519") + + defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, tmpDir+"/id_ed25519.pub")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningFormat, "ssh")() + defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})() + defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})() + + testGitSigning(t) +} + +func testGitSigning(t *testing.T) { username := "user2" user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: username}) baseAPITestContext := NewAPITestContext(t, username, "repo1") diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index b983855630..8f92a51749 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -2,7 +2,7 @@ overflow: hidden; font-size: 16px; line-height: 1.5 !important; - overflow-wrap: anywhere; + overflow-wrap: break-word; } .markup > *:first-child { diff --git a/web_src/css/repo/home.css b/web_src/css/repo/home.css index 61b0a1f962..ee371f1b1c 100644 --- a/web_src/css/repo/home.css +++ b/web_src/css/repo/home.css @@ -67,6 +67,7 @@ .repo-view-content { flex: 1; + min-width: 0; } .language-stats { diff --git a/web_src/fomantic/build/components/dropdown.js b/web_src/fomantic/build/components/dropdown.js index 9d0e07b33b..85530c7991 100644 --- a/web_src/fomantic/build/components/dropdown.js +++ b/web_src/fomantic/build/components/dropdown.js @@ -525,6 +525,7 @@ $.fn.dropdown = function(parameters) { return true; } if(settings.onShow.call(element) !== false) { + settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items module.animate.show(function() { if( module.can.click() ) { module.bind.intent(); diff --git a/web_src/js/features/common-fetch-action.ts b/web_src/js/features/common-fetch-action.ts index 2da481e521..a4a69540a8 100644 --- a/web_src/js/features/common-fetch-action.ts +++ b/web_src/js/features/common-fetch-action.ts @@ -56,8 +56,12 @@ async function fetchActionDoRequest(actionElem: HTMLElement, url: string, opt: R actionElem.classList.remove('is-loading', 'loading-icon-2px'); } -async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { +async function onFormFetchActionSubmit(formEl: HTMLFormElement, e: SubmitEvent) { e.preventDefault(); + await submitFormFetchAction(formEl, submitEventSubmitter(e)); +} + +export async function submitFormFetchAction(formEl: HTMLFormElement, formSubmitter?: HTMLElement) { if (formEl.classList.contains('is-loading')) return; formEl.classList.add('is-loading'); @@ -68,7 +72,6 @@ async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { const formMethod = formEl.getAttribute('method') || 'get'; const formActionUrl = formEl.getAttribute('action'); const formData = new FormData(formEl); - const formSubmitter = submitEventSubmitter(e); const [submitterName, submitterValue] = [formSubmitter?.getAttribute('name'), formSubmitter?.getAttribute('value')]; if (submitterName) { formData.append(submitterName, submitterValue || ''); @@ -96,7 +99,7 @@ async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { await fetchActionDoRequest(formEl, reqUrl, reqOpt); } -async function linkAction(el: HTMLElement, e: Event) { +async function onLinkActionClick(el: HTMLElement, e: Event) { // A "link-action" can post AJAX request to its "data-url" // Then the browser is redirected to: the "redirect" in response, or "data-redirect" attribute, or current URL by reloading. // If the "link-action" has "data-modal-confirm" attribute, a confirm modal dialog will be shown before taking action. @@ -126,6 +129,6 @@ async function linkAction(el: HTMLElement, e: Event) { } export function initGlobalFetchAction() { - addDelegatedEventListener(document, 'submit', '.form-fetch-action', formFetchAction); - addDelegatedEventListener(document, 'click', '.link-action', linkAction); + addDelegatedEventListener(document, 'submit', '.form-fetch-action', onFormFetchActionSubmit); + addDelegatedEventListener(document, 'click', '.link-action', onLinkActionClick); } diff --git a/web_src/js/features/comp/LabelEdit.ts b/web_src/js/features/comp/LabelEdit.ts index a5bb750cdb..141c5eecfe 100644 --- a/web_src/js/features/comp/LabelEdit.ts +++ b/web_src/js/features/comp/LabelEdit.ts @@ -1,5 +1,6 @@ import {toggleElem} from '../../utils/dom.ts'; import {fomanticQuery} from '../../modules/fomantic/base.ts'; +import {submitFormFetchAction} from '../common-fetch-action.ts'; function nameHasScope(name: string): boolean { return /.*[^/]\/[^/].*/.test(name); @@ -70,7 +71,7 @@ export function initCompLabelEdit(pageSelector: string) { form.reportValidity(); return false; } - form.dispatchEvent(new Event('submit', {bubbles: true})); + submitFormFetchAction(form); }, }).modal('show'); }; |