mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-13 04:54:43 +02:00
Merge branch 'main' into feat/add-oauth-management-to-api-for-iac-tooling
This commit is contained in:
commit
2ac420f9da
@ -4,10 +4,10 @@
|
||||
"features": {
|
||||
// installs nodejs into container
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
"version": "lts"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.2.2": {},
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers-extra/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "3.12"
|
||||
},
|
||||
|
@ -36,15 +36,6 @@ _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
|
||||
|
||||
*.db
|
||||
*.log
|
||||
|
||||
|
@ -91,6 +91,7 @@ module.exports = {
|
||||
plugins: ['@vitest/eslint-plugin'],
|
||||
globals: vitestPlugin.environments.env.globals,
|
||||
rules: {
|
||||
'github/unescaped-html-literal': [0],
|
||||
'@vitest/consistent-test-filename': [0],
|
||||
'@vitest/consistent-test-it': [0],
|
||||
'@vitest/expect-expect': [0],
|
||||
@ -325,6 +326,7 @@ module.exports = {
|
||||
'@typescript-eslint/no-unnecessary-type-arguments': [0],
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': [2],
|
||||
'@typescript-eslint/no-unnecessary-type-constraint': [2],
|
||||
'@typescript-eslint/no-unnecessary-type-conversion': [2],
|
||||
'@typescript-eslint/no-unsafe-argument': [0],
|
||||
'@typescript-eslint/no-unsafe-assignment': [0],
|
||||
'@typescript-eslint/no-unsafe-call': [0],
|
||||
@ -423,7 +425,7 @@ module.exports = {
|
||||
'github/no-useless-passive': [2],
|
||||
'github/prefer-observers': [2],
|
||||
'github/require-passive-events': [2],
|
||||
'github/unescaped-html-literal': [0],
|
||||
'github/unescaped-html-literal': [2],
|
||||
'grouped-accessor-pairs': [2],
|
||||
'guard-for-in': [0],
|
||||
'id-blacklist': [0],
|
||||
@ -644,7 +646,7 @@ module.exports = {
|
||||
'no-multi-str': [2],
|
||||
'no-negated-condition': [0],
|
||||
'no-nested-ternary': [0],
|
||||
'no-new-func': [2],
|
||||
'no-new-func': [0], // handled by @typescript-eslint/no-implied-eval
|
||||
'no-new-native-nonconstructor': [2],
|
||||
'no-new-object': [2],
|
||||
'no-new-symbol': [2],
|
||||
|
10
.github/labeler.yml
vendored
10
.github/labeler.yml
vendored
@ -81,3 +81,13 @@ docs-update-needed:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "custom/conf/app.example.ini"
|
||||
|
||||
topic/code-linting:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ".eslintrc.cjs"
|
||||
- ".golangci.yml"
|
||||
- ".markdownlint.yaml"
|
||||
- ".spectral.yaml"
|
||||
- ".yamllint.yaml"
|
||||
- "stylelint.config.js"
|
||||
|
8
.github/workflows/pull-compliance.yml
vendored
8
.github/workflows/pull-compliance.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
python-version: "3.12"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: pip install poetry
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
@ -137,7 +137,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
@ -186,7 +186,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
|
2
.github/workflows/pull-db-tests.yml
vendored
2
.github/workflows/pull-db-tests.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
pgsql:
|
||||
image: postgres:12
|
||||
image: postgres:14
|
||||
env:
|
||||
POSTGRES_DB: test
|
||||
POSTGRES_PASSWORD: postgres
|
||||
|
6
.github/workflows/pull-e2e-tests.yml
vendored
6
.github/workflows/pull-e2e-tests.yml
vendored
@ -12,7 +12,9 @@ jobs:
|
||||
uses: ./.github/workflows/files-changed.yml
|
||||
|
||||
test-e2e:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
# the "test-e2e" won't pass, and it seems that there is no useful test, so skip
|
||||
# if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
if: false
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -23,7 +25,7 @@ jobs:
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
|
2
.github/workflows/release-nightly.yml
vendored
2
.github/workflows/release-nightly.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
2
.github/workflows/release-tag-rc.yml
vendored
2
.github/workflows/release-tag-rc.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
2
.github/workflows/release-tag-version.yml
vendored
2
.github/workflows/release-tag-version.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -22,6 +22,9 @@ _test
|
||||
.vscode
|
||||
__debug_bin*
|
||||
|
||||
# Visual Studio
|
||||
/.vs/
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
@ -39,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
|
||||
|
@ -45,7 +45,13 @@ linters:
|
||||
desc: do not use the ini package, use gitea's config system instead
|
||||
- pkg: gitea.com/go-chi/cache
|
||||
desc: do not use the go-chi cache package, use gitea's cache system
|
||||
nolintlint:
|
||||
allow-unused: false
|
||||
require-explanation: true
|
||||
require-specific: true
|
||||
gocritic:
|
||||
enabled-checks:
|
||||
- equalFold
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- singleCaseSwitch # Every time this occurred in the code, there was no other way.
|
||||
@ -83,6 +89,10 @@ linters:
|
||||
- name: unreachable-code
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
arguments:
|
||||
- [] # AllowList - do not remove as args for the rule are positional and won't work without lists first
|
||||
- [] # DenyList
|
||||
- - skip-package-name-checks: true # supress errors from underscore in migration packages
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
|
3
.ignore
3
.ignore
@ -1,9 +1,6 @@
|
||||
*.min.css
|
||||
*.min.js
|
||||
/assets/*.json
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
||||
/options/gitignore
|
||||
/options/license
|
||||
/public/assets
|
||||
|
423
CHANGELOG.md
423
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
|
||||
|
@ -30,7 +30,7 @@ These are the values to which people in the Gitea community should aspire.
|
||||
- **Be constructive.**
|
||||
- Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
|
||||
- Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
|
||||
- Avoid snarking (pithy, unproductive, sniping comments)
|
||||
- Avoid snarking (pithy, unproductive, sniping comments).
|
||||
- Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
|
||||
- Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
|
||||
- **Be responsible.**
|
||||
@ -42,7 +42,7 @@ People are complicated. You should expect to be misunderstood and to misundersta
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
|
@ -591,7 +591,7 @@ be reviewed by two maintainers and must pass the automatic tests.
|
||||
## Releasing Gitea
|
||||
|
||||
- Let $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin will be kept the same as milestones on github or gitea in future.
|
||||
- Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on Discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody against in about serval hours.
|
||||
- Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on Discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody is against it in about several hours.
|
||||
- If this is a big version first you have to create PR for changelog on branch `main` with PRs with label `changelog` and after it has been merged do following steps:
|
||||
- Create `-dev` tag as `git tag -s -F release.notes v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
|
||||
- When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.24-alpine3.21 AS build-env
|
||||
FROM docker.io/library/golang:1.24-alpine3.22 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
@ -39,9 +39,8 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||
/tmp/local/etc/s6/.s6-svscan/* \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.21
|
||||
FROM docker.io/library/alpine:3.22
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 22 3000
|
||||
@ -83,4 +82,3 @@ CMD ["/usr/bin/s6-svscan", "/etc/s6"]
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.24-alpine3.21 AS build-env
|
||||
FROM docker.io/library/golang:1.24-alpine3.22 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
@ -37,9 +37,8 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||
/tmp/local/usr/local/bin/gitea \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.21
|
||||
FROM docker.io/library/alpine:3.22
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 2222 3000
|
||||
@ -52,6 +51,7 @@ RUN apk --no-cache add \
|
||||
git \
|
||||
curl \
|
||||
gnupg \
|
||||
openssh-keygen \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN addgroup \
|
||||
@ -71,7 +71,6 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
||||
# git:git
|
||||
USER 1000:1000
|
||||
|
@ -64,3 +64,4 @@ Rowan Bohde <rowan.bohde@gmail.com> (@bohde)
|
||||
hiifong <i@hiif.ong> (@hiifong)
|
||||
metiftikci <metiftikci@hotmail.com> (@metiftikci)
|
||||
Christopher Homberger <christopher.homberger@web.de> (@ChristopherHX)
|
||||
Tobias Balle-Petersen <tobiasbp@gmail.com> (@tobiasbp)
|
||||
|
49
Makefile
49
Makefile
@ -26,17 +26,18 @@ COMMA := ,
|
||||
XGO_VERSION := go-1.24.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.2
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.32.3
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.1
|
||||
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.1
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
@ -80,7 +81,6 @@ ifeq ($(RACE_ENABLED),true)
|
||||
endif
|
||||
|
||||
STORED_VERSION_FILE := VERSION
|
||||
HUGO_VERSION ?= 0.111.3
|
||||
|
||||
GITHUB_REF_TYPE ?= branch
|
||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
@ -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_WILDCARD := modules/migration/bindata.* modules/public/bindata.* modules/options/bindata.* modules/templates/bindata.*
|
||||
|
||||
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_WILDCARD) \
|
||||
integrations*.test \
|
||||
e2e*.test \
|
||||
tests/integration/gitea-integration-* \
|
||||
@ -237,7 +230,7 @@ clean: ## delete backend and integration files
|
||||
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## format the Go code
|
||||
fmt: ## format the Go and template code
|
||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||
@ -256,6 +249,19 @@ fmt-check: fmt
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: fix
|
||||
fix: ## apply automated fixes to Go code
|
||||
$(GO) run $(GOPLS_MODERNIZE_PACKAGE) -fix ./...
|
||||
|
||||
.PHONY: fix-check
|
||||
fix-check: fix
|
||||
@diff=$$(git diff --color=always $(GO_SOURCES)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make fix' and commit the result:"; \
|
||||
printf "%s" "$${diff}"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: $(TAGS_EVIDENCE)
|
||||
$(TAGS_EVIDENCE):
|
||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||
@ -268,7 +274,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
|
||||
@ -295,7 +301,7 @@ checks: checks-frontend checks-backend ## run various consistency checks
|
||||
checks-frontend: lockfile-check svg-check ## check frontend files
|
||||
|
||||
.PHONY: checks-backend
|
||||
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check ## check backend files
|
||||
checks-backend: tidy-check swagger-check fmt-check fix-check swagger-validate security-check ## check backend files
|
||||
|
||||
.PHONY: lint
|
||||
lint: lint-frontend lint-backend lint-spell ## lint everything
|
||||
@ -373,7 +379,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:
|
||||
@ -816,6 +822,7 @@ deps-tools: ## install tool dependencies
|
||||
$(GO) install $(GOVULNCHECK_PACKAGE) & \
|
||||
$(GO) install $(ACTIONLINT_PACKAGE) & \
|
||||
$(GO) install $(GOPLS_PACKAGE) & \
|
||||
$(GO) install $(GOPLS_MODERNIZE_PACKAGE) & \
|
||||
wait
|
||||
|
||||
node_modules: package-lock.json
|
||||
|
@ -80,9 +80,9 @@ Expected workflow is: Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
[](https://translate.gitea.com)
|
||||
|
||||
Translations are done through [Crowdin](https://translate.gitea.com). If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there.
|
||||
Translations are done through [Crowdin](https://translate.gitea.com). If you want to translate to a new language, ask one of the managers in the Crowdin project to add a new language there.
|
||||
|
||||
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
|
||||
You can also just create an issue for adding a language or ask on Discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty, but we hope to fill it as questions pop up.
|
||||
|
||||
Get more information from [documentation](https://docs.gitea.com/contributing/localization).
|
||||
|
||||
|
54
SECURITY.md
54
SECURITY.md
@ -14,12 +14,12 @@ Please **DO NOT** file a public issue, instead send your report privately to `se
|
||||
|
||||
Due to the sensitive nature of security information, you can use the below GPG public key to encrypt your mail body.
|
||||
|
||||
The PGP key is valid until July 9, 2025.
|
||||
The PGP key is valid until July 4, 2026.
|
||||
|
||||
```
|
||||
Key ID: 6FCD2D5B
|
||||
Key Type: RSA
|
||||
Expires: 7/9/2025
|
||||
Expires: 7/4/2026
|
||||
Key Size: 4096/4096
|
||||
Fingerprint: 3DE0 3D1E 144A 7F06 9359 99DC AAFD 2381 6FCD 2D5B
|
||||
```
|
||||
@ -42,18 +42,18 @@ lzpAjnN9/KLtQroutrm+Ft0mdjDiJUeFVl1cOHDhoyfCsQh62HumoyZoZvqzQd6e
|
||||
AbN11nq6aViMe2Q3je1AbiBnRnQSHxt1Tc8X4IshO3MQK1Sk7oPI6LA5oQARAQAB
|
||||
tCJHaXRlYSBTZWN1cml0eSA8c2VjdXJpdHlAZ2l0ZWEuaW8+iQJXBBMBCABBAhsD
|
||||
BQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAFiEEPeA9HhRKfwaTWZncqv0jgW/N
|
||||
LVsFAmaMse0FCQW4fW8ACgkQqv0jgW/NLVtXLg/+PF4G9Jhlui15BTNlEBJAV2P/
|
||||
1QlAV2krk0fP7tykn0FR9RfGIfVV/kwC1f+ouosYPQDDevl9LWdUIM+g94DtNo2o
|
||||
7ACpcL3morvt5lVGpIZHL8TbX0qmFRXL/pB/cB+K6IwYvh2mrbp2zH+r4SCRyFYq
|
||||
BjgXYFTI1MylJ1ShAjU6Z+m3oJ+2xs5LzHS0X6zkTjzA2Zl4zQzciQ9T+wJcE7Zi
|
||||
HXdM1+YMF8KGNP8J9Rpug5oNDJ98lgZirRY7c3A/1xmYBiPnULwuuymdqEZO7l70
|
||||
SeAlE1RWYX8kbOBnBb/KY4XwE3Vic1oEzc9DiPWVH1ElX86WNNsFzuyULiwoBoWg
|
||||
pqZGhL9x1p5+46RGQSDczsHM7YGVtfYOiDo2PAVrmwsT0BnXnK8Oe3YIkvmUPEJu
|
||||
OkLt0Z6A5n8pz8zhQzuApwBsK4ncJ8zTCpvz/pfKKqZC/Vnoh3gKGhDGvOZ+b5IJ
|
||||
0kUTe2JsbnwFixDUMDtacQ1op8XOyLoLVmgqLn0+Pws4XPBlMof2bioFir3yHKnP
|
||||
gNchsF1agrlSIo5GA8u4ga+IlCSfvFIKrl7+cxacKcJYt/vbOU5KcvVJI5EtHKCG
|
||||
xfHjHY2ah1Qww7SxW6IXiRZZzPpsL2mBM2CD7N3qh9bV2s27wxYCdUodsIZbiyHe
|
||||
oWPzfBnkmiAN8KlZxHm5Ag0EYrVn/gEQALrFLQjCR3GjuHSindz0rd3Fnx/t7Sen
|
||||
LVsFAmhoHmkFCQeT6esACgkQqv0jgW/NLVuFLRAAmjBQSKRAgs2bFIEj7HLAbDp4
|
||||
f+XkdH+GsT3jRPOZ9QZgmtM+TfoE4yNgIVfOl+s4RdjM/W4QzqZuPQ55hbEHd056
|
||||
cJmm7B+6GsHFcdrPmh65sOCEIyh4+t45dUfeWpFsDPqm9j1UHXAJQIpB8vDEVAPH
|
||||
t+3wLCk8GMPJs1o5tIyMmaO23ngvkwn8eG7KgY+rp2PzObrb5g7ppci0ILzILkrp
|
||||
HVjZsEfUWRgSVF7LuU5ppqDKrlcqwUpQq6n3kGMZcLrCp6ACKP04TBmTfUxNwdL7
|
||||
I0N7apI2Pbct9T1Gv/lYAUFWyU2c3gh/EBLbO6BukaLOFRQHrtNfdJV/YnMPlcXr
|
||||
LUJjK9K4eAH9DsrZqrisz/LthsC2BaNIN3KRMTk5YTYgmIh8GXzSgihORmtDFELC
|
||||
RroID3pTuS0zjXh+wpY9GuPTh7UW23p42Daxca4fAT4k5EclvDRUrL21xMopPMiL
|
||||
HuNdELz4FVchRTy05PjzKVyjVInDNojE2KUxnjxZDzYJ6aT/g+coD5yfntYm8BEj
|
||||
+ZzL0ndZES54hzKLpv7zwBQwFzam68clZYmDPILOPTflQDfpGEWmJK4undFU5obz
|
||||
ZsQRz0R3ulspChATbZxO0d5LX2obLpKO9X3b5VoO1KF+R8Vjw1Y0KxrNZ6rIcfqH
|
||||
Z50QVQKSe9dm08K0ON+5Ag0EYrVn/gEQALrFLQjCR3GjuHSindz0rd3Fnx/t7Sen
|
||||
T+p07yCSSoSlmnJHCQmwh4vfg1blyz0zZ4vkIhtpHsEgc+ZAG+WQXSsJ2iRz+eSN
|
||||
GwoOQl4XC3n+QWkc1ws+btr48+6UqXIQU+F8TPQyx/PIgi2nZXJB7f5+mjCqsk46
|
||||
XvH4nTr4kJjuqMSR/++wvre2qNQRa/q/dTsK0OaN/mJsdX6Oi+aGNaQJUhIG7F+E
|
||||
@ -65,19 +65,19 @@ s+GsP9I3cmWWQcKYxWHtE8xTXnNCVPFZQj2nwhJzae8ypfOtulBRA3dUKWGKuDH/
|
||||
axFENhUsT397aOU3qkP/od4a64JyNIEo4CTTSPVeWd7njsGqli2U3A4xL2CcyYvt
|
||||
D/MWcMBGEoLSNTswwKdom4FaJpn5KThnK/T0bQcmJblJhoCtppXisbexZnCpuS0x
|
||||
Zdlm2T14KJ3LABEBAAGJAjwEGAEIACYCGwwWIQQ94D0eFEp/BpNZmdyq/SOBb80t
|
||||
WwUCZoyyjQUJBbh+DwAKCRCq/SOBb80tW18XD/9MXztmf01MT+1kZdBouZ/7Rp/7
|
||||
9kuqo//B1G+RXau4oFtPqb67kNe2WaIc3u5B73PUHsMf3i6z4ib2KbMhZZerLn0O
|
||||
dRglcuPeNWmsASY3dH/XVG0cT0zvvWegagd12TJEl3Vs+7XNrOw4cwDj9L1+GH9m
|
||||
kSt4uaANWn/6a3RvMRhiVEYuNwhAzcKaactPmYqrLJgoVLbRSDkgyHaMQ2jKgLxk
|
||||
ifS/fvluGV0ub2Po6DJiqfRpd1tDvPhe9y1+r1WFDZsOcvTcZUfSt/7dXMGfqGu0
|
||||
2daVFlfeSXSALrDE5uc0UxodHCpP3sqRYDZevGLBRaaTkIjYXG/+N898+7K5WJF4
|
||||
xXOLWxM2cwGkG7eC9pugcDnBp9XlF7O+GBiZ05JUe5flXDQFZ+h3exjopu6KHF1B
|
||||
RnzNy8LC0UKb+AuvRIOLV92a9Q9wGWU/jaVDu6nZ0umAeuSzxiHoDsonm0Fl9QAz
|
||||
2/xCokebuoeLrEK7R2af3X86mqq3sVO4ax+HPYChzOaVQBiHUW/TAldWcldYYphR
|
||||
/e2WsbmQfvCRtz/bZfo+aUVnrHNjzVMtF2SszdVmA/04Y8pS28MqtuRqhm5DPOOd
|
||||
g1YeUywK5jRZ1twyo1kzJEFPLaoeaXaycsR1PMVBW0Urik5mrR/pOWq7PPoZoKb2
|
||||
lXYLE8bwkuQTmsyL1g==
|
||||
=9i7d
|
||||
WwUCaGgeJAUJB5PppgAKCRCq/SOBb80tW/NWEACB6Jrf0gWlk7e+hNCdnbM0ZVWU
|
||||
f2sHNFfXxxsdhpcDgKbNHtkZb8nZgv8AX+5fTtUwMVa3vKcdw30xFiIM5N7cCIPV
|
||||
vg/5z5BtfEaitnabEUG2iiVDIy8IHXIcK10rX+7BosA3QDl2PsiBHwyi5G13lRk8
|
||||
zGTSNDuOalug33h5/lr2dPigamkq74Aoy29q8Rjad6GfWHipL2bFimgtY+Zdi0BH
|
||||
NLk4EJXxj1SgVx5dtkQzWJReBA5M+FQ4QYQZBO+f4TDoOLmjui152uhkoLBQbGAa
|
||||
WWJFTVxm0bG5MXloEL3gA8DfU7XDwuW/sHJC5pBko8RpQViooOhckMepZV3Y83DK
|
||||
bwLYa3JmPgj2rEv4993dvrJbQhpGd082HOxOsllCs8pgNq1SnXpWYfcGTgGKC3ts
|
||||
U8YZUUJUQ7mi2L8Tv3ix20c9EiGmA30JAmA8eZTC3cWup91ZkkVBFRml2czTXajd
|
||||
RWZ6GbHV5503ueDQcB8yBVgF3CSixs67+dGSbD3p86OqGrjAcJzM5TFbNKcnGLdE
|
||||
kGbZpNwAISy750lXzXKmyrh5RTCeTOQerbwCMBvHZO+HAevA/LXDTw2OAiSIQlP5
|
||||
sYA4sFYLQ30OAkgJcmdp/pSgVj/erNtSN07ClrOpDb/uFpQymO6K2h0Pst3feNVK
|
||||
9M2VbqL9C51z/wyHLg==
|
||||
=SfZA
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
```
|
||||
|
29
assets/go-licenses.json
generated
29
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
11
build.go
11
build.go
@ -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"
|
||||
)
|
||||
|
@ -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")
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Println("usage: ./generate-bindata {local-directory} {bindata-filename}")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
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])
|
||||
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)
|
||||
}
|
||||
|
||||
update, newHash := needsUpdate(dir, filename)
|
||||
|
||||
if !update {
|
||||
fmt.Printf("bindata for %s already up-to-date\n", packageName)
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
_ = os.WriteFile(filename+".hash", newHash, 0o666)
|
||||
}
|
||||
|
@ -4,12 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -17,7 +18,7 @@ var (
|
||||
CmdActions = &cli.Command{
|
||||
Name: "actions",
|
||||
Usage: "Manage Gitea Actions",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdActionsGenRunnerToken,
|
||||
},
|
||||
}
|
||||
@ -38,10 +39,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runGenerateActionsRunnerToken(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runGenerateActionsRunnerToken(ctx context.Context, c *cli.Command) error {
|
||||
setting.MustInstalled()
|
||||
|
||||
scope := c.String("scope")
|
||||
|
43
cmd/admin.go
43
cmd/admin.go
@ -15,7 +15,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -23,7 +23,7 @@ var (
|
||||
CmdAdmin = &cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Perform common administrative operations",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdUser,
|
||||
subcmdRepoSyncReleases,
|
||||
subcmdRegenerate,
|
||||
@ -41,7 +41,7 @@ var (
|
||||
subcmdRegenerate = &cli.Command{
|
||||
Name: "regenerate",
|
||||
Usage: "Regenerate specific files",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
microcmdRegenHooks,
|
||||
microcmdRegenKeys,
|
||||
},
|
||||
@ -50,15 +50,15 @@ var (
|
||||
subcmdAuth = &cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Modify external auth providers",
|
||||
Subcommands: []*cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
microcmdAuthAddLdapBindDn,
|
||||
microcmdAuthUpdateLdapBindDn,
|
||||
microcmdAuthAddLdapSimpleAuth,
|
||||
microcmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthAddSMTP,
|
||||
microcmdAuthUpdateSMTP,
|
||||
Commands: []*cli.Command{
|
||||
microcmdAuthAddOauth(),
|
||||
microcmdAuthUpdateOauth(),
|
||||
microcmdAuthAddLdapBindDn(),
|
||||
microcmdAuthUpdateLdapBindDn(),
|
||||
microcmdAuthAddLdapSimpleAuth(),
|
||||
microcmdAuthUpdateLdapSimpleAuth(),
|
||||
microcmdAuthAddSMTP(),
|
||||
microcmdAuthUpdateSMTP(),
|
||||
microcmdAuthList,
|
||||
microcmdAuthDelete,
|
||||
},
|
||||
@ -70,9 +70,9 @@ var (
|
||||
Action: runSendMail,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "title",
|
||||
Usage: `a title of a message`,
|
||||
Value: "",
|
||||
Name: "title",
|
||||
Usage: "a title of a message",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "content",
|
||||
@ -86,17 +86,16 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
idFlag = &cli.Int64Flag{
|
||||
func idFlag() *cli.Int64Flag {
|
||||
return &cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}
|
||||
)
|
||||
|
||||
func runRepoSyncReleases(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -107,7 +106,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
|
||||
|
||||
log.Trace("Synchronizing repository releases (this may take a while)")
|
||||
for page := 1; ; page++ {
|
||||
repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{
|
||||
repos, count, err := repo_model.SearchRepositoryByName(ctx, repo_model.SearchRepoOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
PageSize: repo_model.RepositoryListDefaultPageSize,
|
||||
Page: page,
|
||||
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -13,14 +14,14 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
auth_service "code.gitea.io/gitea/services/auth"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
microcmdAuthDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Flags: []cli.Flag{idFlag()},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
microcmdAuthList = &cli.Command{
|
||||
@ -56,10 +57,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runListAuth(ctx context.Context, c *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -90,14 +88,11 @@ func runListAuth(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
func runDeleteAuth(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -23,8 +24,8 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
commonLdapCLIFlags = []cli.Flag{
|
||||
func commonLdapCLIFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Authentication name.",
|
||||
@ -102,8 +103,10 @@ var (
|
||||
Usage: "The attribute of the user’s LDAP record containing the user’s avatar.",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
ldapBindDnCLIFlags = append(commonLdapCLIFlags,
|
||||
func ldapBindDnCLIFlags() []cli.Flag {
|
||||
return append(commonLdapCLIFlags(),
|
||||
&cli.StringFlag{
|
||||
Name: "bind-dn",
|
||||
Usage: "The DN to bind to the LDAP server with when searching for the user.",
|
||||
@ -156,49 +159,59 @@ var (
|
||||
Name: "group-team-map-removal",
|
||||
Usage: "Remove users from synchronized teams if user does not belong to corresponding LDAP group",
|
||||
})
|
||||
}
|
||||
|
||||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
||||
func ldapSimpleAuthCLIFlags() []cli.Flag {
|
||||
return append(commonLdapCLIFlags(),
|
||||
&cli.StringFlag{
|
||||
Name: "user-dn",
|
||||
Usage: "The user's DN.",
|
||||
})
|
||||
}
|
||||
|
||||
microcmdAuthAddLdapBindDn = &cli.Command{
|
||||
func microcmdAuthAddLdapBindDn() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "add-ldap",
|
||||
Usage: "Add new LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().addLdapBindDn(c)
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().addLdapBindDn(ctx, cmd)
|
||||
},
|
||||
Flags: ldapBindDnCLIFlags,
|
||||
Flags: ldapBindDnCLIFlags(),
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthUpdateLdapBindDn = &cli.Command{
|
||||
func microcmdAuthUpdateLdapBindDn() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "update-ldap",
|
||||
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().updateLdapBindDn(c)
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().updateLdapBindDn(ctx, cmd)
|
||||
},
|
||||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
||||
Flags: append([]cli.Flag{idFlag()}, ldapBindDnCLIFlags()...),
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||
func microcmdAuthAddLdapSimpleAuth() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "add-ldap-simple",
|
||||
Usage: "Add new LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().addLdapSimpleAuth(c)
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().addLdapSimpleAuth(ctx, cmd)
|
||||
},
|
||||
Flags: ldapSimpleAuthCLIFlags,
|
||||
Flags: ldapSimpleAuthCLIFlags(),
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||
func microcmdAuthUpdateLdapSimpleAuth() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "update-ldap-simple",
|
||||
Usage: "Update existing LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
return newAuthService().updateLdapSimpleAuth(c)
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().updateLdapSimpleAuth(ctx, cmd)
|
||||
},
|
||||
Flags: append([]cli.Flag{idFlag}, ldapSimpleAuthCLIFlags...),
|
||||
Flags: append([]cli.Flag{idFlag()}, ldapSimpleAuthCLIFlags()...),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// newAuthService creates a service with default functions.
|
||||
func newAuthService() *authService {
|
||||
@ -210,8 +223,8 @@ func newAuthService() *authService {
|
||||
}
|
||||
}
|
||||
|
||||
// parseAuthSource assigns values on authSource according to command line flags.
|
||||
func parseAuthSource(c *cli.Context, authSource *auth.Source) {
|
||||
// parseAuthSourceLdap assigns values on authSource according to command line flags.
|
||||
func parseAuthSourceLdap(c *cli.Command, authSource *auth.Source) {
|
||||
if c.IsSet("name") {
|
||||
authSource.Name = c.String("name")
|
||||
}
|
||||
@ -227,10 +240,11 @@ func parseAuthSource(c *cli.Context, authSource *auth.Source) {
|
||||
if c.IsSet("disable-synchronize-users") {
|
||||
authSource.IsSyncEnabled = !c.Bool("disable-synchronize-users")
|
||||
}
|
||||
authSource.TwoFactorPolicy = util.Iif(c.Bool("skip-local-2fa"), "skip", "")
|
||||
}
|
||||
|
||||
// parseLdapConfig assigns values on config according to command line flags.
|
||||
func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
|
||||
func parseLdapConfig(c *cli.Command, config *ldap.Source) error {
|
||||
if c.IsSet("name") {
|
||||
config.Name = c.String("name")
|
||||
}
|
||||
@ -243,7 +257,7 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
|
||||
if c.IsSet("security-protocol") {
|
||||
p, ok := findLdapSecurityProtocolByName(c.String("security-protocol"))
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown security protocol name: %s", c.String("security-protocol"))
|
||||
return fmt.Errorf("unknown security protocol name: %s", c.String("security-protocol"))
|
||||
}
|
||||
config.SecurityProtocol = p
|
||||
}
|
||||
@ -298,9 +312,6 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
|
||||
if c.IsSet("allow-deactivate-all") {
|
||||
config.AllowDeactivateAll = c.Bool("allow-deactivate-all")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
config.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
if c.IsSet("enable-groups") {
|
||||
config.GroupsEnabled = c.Bool("enable-groups")
|
||||
}
|
||||
@ -338,32 +349,27 @@ func findLdapSecurityProtocolByName(name string) (ldap.SecurityProtocol, bool) {
|
||||
|
||||
// getAuthSource gets the login source by its id defined in the command line flags.
|
||||
// It returns an error if the id is not set, does not match any source or if the source is not of expected type.
|
||||
func (a *authService) getAuthSource(ctx context.Context, c *cli.Context, authType auth.Type) (*auth.Source, error) {
|
||||
func (a *authService) getAuthSource(ctx context.Context, c *cli.Command, authType auth.Type) (*auth.Source, error) {
|
||||
if err := argsSet(c, "id"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authSource, err := a.getAuthSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if authSource.Type != authType {
|
||||
return nil, fmt.Errorf("Invalid authentication type. expected: %s, actual: %s", authType.String(), authSource.Type.String())
|
||||
return nil, fmt.Errorf("invalid authentication type. expected: %s, actual: %s", authType.String(), authSource.Type.String())
|
||||
}
|
||||
|
||||
return authSource, nil
|
||||
}
|
||||
|
||||
// addLdapBindDn adds a new LDAP via Bind DN authentication source.
|
||||
func (a *authService) addLdapBindDn(c *cli.Context) error {
|
||||
func (a *authService) addLdapBindDn(ctx context.Context, c *cli.Command) error {
|
||||
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-search-base", "user-filter", "email-attribute"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -376,7 +382,7 @@ func (a *authService) addLdapBindDn(c *cli.Context) error {
|
||||
},
|
||||
}
|
||||
|
||||
parseAuthSource(c, authSource)
|
||||
parseAuthSourceLdap(c, authSource)
|
||||
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -385,10 +391,7 @@ func (a *authService) addLdapBindDn(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP via Bind DN authentication source.
|
||||
func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func (a *authService) updateLdapBindDn(ctx context.Context, c *cli.Command) error {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -398,7 +401,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
parseAuthSource(c, authSource)
|
||||
parseAuthSourceLdap(c, authSource)
|
||||
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -407,14 +410,11 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// addLdapSimpleAuth adds a new LDAP (simple auth) authentication source.
|
||||
func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
func (a *authService) addLdapSimpleAuth(ctx context.Context, c *cli.Command) error {
|
||||
if err := argsSet(c, "name", "security-protocol", "host", "port", "user-dn", "user-filter", "email-attribute"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -427,7 +427,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
},
|
||||
}
|
||||
|
||||
parseAuthSource(c, authSource)
|
||||
parseAuthSourceLdap(c, authSource)
|
||||
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -436,10 +436,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// updateLdapSimpleAuth updates a new LDAP (simple auth) authentication source.
|
||||
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func (a *authService) updateLdapSimpleAuth(ctx context.Context, c *cli.Command) error {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -449,7 +446,7 @@ func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
parseAuthSource(c, authSource)
|
||||
parseAuthSourceLdap(c, authSource)
|
||||
if err := parseLdapConfig(c, authSource.Cfg.(*ldap.Source)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -8,17 +8,16 @@ import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestAddLdapBindDn(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
osExiter := cli.OsExiter
|
||||
defer func() { cli.OsExiter = osExiter }()
|
||||
cli.OsExiter = func(code int) {}
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
@ -135,7 +134,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
"--user-filter", "(memberOf=cn=user-group,ou=example,dc=domain,dc=org)",
|
||||
"--email-attribute", "mail",
|
||||
},
|
||||
errMsg: "Unknown security protocol name: zzzzz",
|
||||
errMsg: "unknown security protocol name: zzzzz",
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
@ -239,12 +238,13 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthAddLdapBindDn.Flags
|
||||
app.Action = service.addLdapBindDn
|
||||
app := cli.Command{
|
||||
Flags: microcmdAuthAddLdapBindDn().Flags,
|
||||
Action: service.addLdapBindDn,
|
||||
}
|
||||
|
||||
// Run it
|
||||
err := app.Run(c.args)
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
@ -256,9 +256,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
|
||||
func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
osExiter := cli.OsExiter
|
||||
defer func() { cli.OsExiter = osExiter }()
|
||||
cli.OsExiter = func(code int) {}
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
@ -348,12 +346,12 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
"--name", "ldap (simple auth) source",
|
||||
"--security-protocol", "zzzzz",
|
||||
"--host", "ldap-server",
|
||||
"--port", "123",
|
||||
"--port", "1234",
|
||||
"--user-filter", "(&(objectClass=posixAccount)(cn=%s))",
|
||||
"--email-attribute", "mail",
|
||||
"--user-dn", "cn=%s,ou=Users,dc=domain,dc=org",
|
||||
},
|
||||
errMsg: "Unknown security protocol name: zzzzz",
|
||||
errMsg: "unknown security protocol name: zzzzz",
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
@ -470,12 +468,13 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthAddLdapSimpleAuth.Flags
|
||||
app.Action = service.addLdapSimpleAuth
|
||||
app := &cli.Command{
|
||||
Flags: microcmdAuthAddLdapSimpleAuth().Flags,
|
||||
Action: service.addLdapSimpleAuth,
|
||||
}
|
||||
|
||||
// Run it
|
||||
err := app.Run(c.args)
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
@ -487,9 +486,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
|
||||
func TestUpdateLdapBindDn(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
osExiter := cli.OsExiter
|
||||
defer func() { cli.OsExiter = osExiter }()
|
||||
cli.OsExiter = func(code int) {}
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
@ -864,7 +861,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
"--id", "1",
|
||||
"--security-protocol", "xxxxx",
|
||||
},
|
||||
errMsg: "Unknown security protocol name: xxxxx",
|
||||
errMsg: "unknown security protocol name: xxxxx",
|
||||
},
|
||||
// case 22
|
||||
{
|
||||
@ -883,7 +880,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
Type: auth.OAuth2,
|
||||
Cfg: &ldap.Source{},
|
||||
},
|
||||
errMsg: "Invalid authentication type. expected: LDAP (via BindDN), actual: OAuth2",
|
||||
errMsg: "invalid authentication type. expected: LDAP (via BindDN), actual: OAuth2",
|
||||
},
|
||||
// case 24
|
||||
{
|
||||
@ -947,12 +944,12 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthUpdateLdapBindDn.Flags
|
||||
app.Action = service.updateLdapBindDn
|
||||
|
||||
app := cli.Command{
|
||||
Flags: microcmdAuthUpdateLdapBindDn().Flags,
|
||||
Action: service.updateLdapBindDn,
|
||||
}
|
||||
// Run it
|
||||
err := app.Run(c.args)
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
@ -964,9 +961,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
|
||||
func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
// Mock cli functions to do not exit on error
|
||||
osExiter := cli.OsExiter
|
||||
defer func() { cli.OsExiter = osExiter }()
|
||||
cli.OsExiter = func(code int) {}
|
||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||||
|
||||
// Test cases
|
||||
cases := []struct {
|
||||
@ -1257,7 +1252,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
"--id", "1",
|
||||
"--security-protocol", "xxxxx",
|
||||
},
|
||||
errMsg: "Unknown security protocol name: xxxxx",
|
||||
errMsg: "unknown security protocol name: xxxxx",
|
||||
},
|
||||
// case 18
|
||||
{
|
||||
@ -1276,7 +1271,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
Type: auth.PAM,
|
||||
Cfg: &ldap.Source{},
|
||||
},
|
||||
errMsg: "Invalid authentication type. expected: LDAP (simple auth), actual: PAM",
|
||||
errMsg: "invalid authentication type. expected: LDAP (simple auth), actual: PAM",
|
||||
},
|
||||
// case 20
|
||||
{
|
||||
@ -1337,12 +1332,12 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthUpdateLdapSimpleAuth.Flags
|
||||
app.Action = service.updateLdapSimpleAuth
|
||||
|
||||
app := cli.Command{
|
||||
Flags: microcmdAuthUpdateLdapSimpleAuth().Flags,
|
||||
Action: service.updateLdapSimpleAuth,
|
||||
}
|
||||
// Run it
|
||||
err := app.Run(c.args)
|
||||
err := app.Run(t.Context(), c.args)
|
||||
if c.errMsg != "" {
|
||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||
} else {
|
||||
|
@ -4,18 +4,20 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
func oauthCLIFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
@ -85,6 +87,14 @@ var (
|
||||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ssh-public-key-claim-name",
|
||||
Usage: "Claim name that provides SSH public keys",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "full-name-claim-name",
|
||||
Usage: "Claim name that provides user's full name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
@ -120,23 +130,34 @@ var (
|
||||
Usage: "Activate automatic team membership removal depending on groups",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
func microcmdAuthAddOauth() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().runAddOauth(ctx, cmd)
|
||||
},
|
||||
Flags: oauthCLIFlags(),
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
func microcmdAuthUpdateOauth() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().runUpdateOauth(ctx, cmd)
|
||||
},
|
||||
Flags: append(oauthCLIFlags()[:1], append([]cli.Flag{&cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}}, oauthCLIFlags()[1:]...)...),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
func parseOAuth2Config(c *cli.Command) *oauth2.Source {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
@ -156,7 +177,6 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
@ -165,14 +185,13 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
RestrictedGroup: c.String("restricted-group"),
|
||||
GroupTeamMap: c.String("group-team-map"),
|
||||
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
|
||||
SSHPublicKeyClaimName: c.String("ssh-public-key-claim-name"),
|
||||
FullNameClaimName: c.String("full-name-claim-name"),
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
func (a *authService) runAddOauth(ctx context.Context, c *cli.Command) error {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -184,27 +203,25 @@ func runAddOauth(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
return a.createAuthSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
TwoFactorPolicy: util.Iif(c.Bool("skip-local-2fa"), "skip", ""),
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
func (a *authService) runUpdateOauth(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
source, err := a.getAuthSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -261,6 +278,12 @@ func runUpdateOauth(c *cli.Context) error {
|
||||
if c.IsSet("group-team-map-removal") {
|
||||
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
|
||||
}
|
||||
if c.IsSet("ssh-public-key-claim-name") {
|
||||
oAuth2Config.SSHPublicKeyClaimName = c.String("ssh-public-key-claim-name")
|
||||
}
|
||||
if c.IsSet("full-name-claim-name") {
|
||||
oAuth2Config.FullNameClaimName = c.String("full-name-claim-name")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
customURLMapping := &oauth2.CustomURLMapping{}
|
||||
@ -294,6 +317,6 @@ func runUpdateOauth(c *cli.Context) error {
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(ctx, source)
|
||||
source.TwoFactorPolicy = util.Iif(c.Bool("skip-local-2fa"), "skip", "")
|
||||
return a.updateAuthSource(ctx, source)
|
||||
}
|
||||
|
343
cmd/admin_auth_oauth_test.go
Normal file
343
cmd/admin_auth_oauth_test.go
Normal file
@ -0,0 +1,343 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestAddOauth(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
source *auth_model.Source
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "valid config",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--provider", "github",
|
||||
"--key", "some_key",
|
||||
"--secret", "some_secret",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Scopes: []string{},
|
||||
Provider: "github",
|
||||
ClientID: "some_key",
|
||||
ClientSecret: "some_secret",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config with openid connect",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--provider", "openidConnect",
|
||||
"--key", "some_key",
|
||||
"--secret", "some_secret",
|
||||
"--auto-discover-url", "https://example.com",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Scopes: []string{},
|
||||
Provider: "openidConnect",
|
||||
ClientID: "some_key",
|
||||
ClientSecret: "some_secret",
|
||||
OpenIDConnectAutoDiscoveryURL: "https://example.com",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config with options",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--provider", "gitlab",
|
||||
"--key", "some_key",
|
||||
"--secret", "some_secret",
|
||||
"--use-custom-urls", "true",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
"--custom-tenant-id", "some_tenant",
|
||||
"--icon-url", "https://example.com/icon",
|
||||
"--scopes", "scope1,scope2",
|
||||
"--skip-local-2fa", "true",
|
||||
"--required-claim-name", "claim_name",
|
||||
"--required-claim-value", "claim_value",
|
||||
"--group-claim-name", "group_name",
|
||||
"--admin-group", "admin",
|
||||
"--restricted-group", "restricted",
|
||||
"--group-team-map", `{"group1": [1,2]}`,
|
||||
"--group-team-map-removal=true",
|
||||
"--ssh-public-key-claim-name", "attr_ssh_pub_key",
|
||||
"--full-name-claim-name", "attr_full_name",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "gitlab",
|
||||
ClientID: "some_key",
|
||||
ClientSecret: "some_secret",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
TokenURL: "https://example.com/token",
|
||||
AuthURL: "https://example.com/auth",
|
||||
ProfileURL: "https://example.com/profile",
|
||||
EmailURL: "https://example.com/email",
|
||||
Tenant: "some_tenant",
|
||||
},
|
||||
IconURL: "https://example.com/icon",
|
||||
Scopes: []string{"scope1", "scope2"},
|
||||
RequiredClaimName: "claim_name",
|
||||
RequiredClaimValue: "claim_value",
|
||||
GroupClaimName: "group_name",
|
||||
AdminGroup: "admin",
|
||||
RestrictedGroup: "restricted",
|
||||
GroupTeamMap: `{"group1": [1,2]}`,
|
||||
GroupTeamMapRemoval: true,
|
||||
SSHPublicKeyClaimName: "attr_ssh_pub_key",
|
||||
FullNameClaimName: "attr_full_name",
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var createdSource *auth_model.Source
|
||||
a := &authService{
|
||||
initDB: func(ctx context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, source *auth_model.Source) error {
|
||||
createdSource = source
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
app := &cli.Command{
|
||||
Flags: microcmdAuthAddOauth().Flags,
|
||||
Action: a.runAddOauth,
|
||||
}
|
||||
|
||||
args := []string{"oauth-test"}
|
||||
args = append(args, tc.args...)
|
||||
|
||||
err := app.Run(t.Context(), args)
|
||||
|
||||
if tc.errMsg != "" {
|
||||
assert.EqualError(t, err, tc.errMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.source, createdSource)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOauth(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
id int64
|
||||
existingAuthSource *auth_model.Source
|
||||
authSource *auth_model.Source
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "missing id",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
},
|
||||
errMsg: "--id flag is missing",
|
||||
},
|
||||
{
|
||||
name: "valid config",
|
||||
id: 1,
|
||||
existingAuthSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "old name",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "github",
|
||||
ClientID: "old_key",
|
||||
ClientSecret: "old_secret",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
args: []string{
|
||||
"--id", "1",
|
||||
"--name", "test",
|
||||
"--provider", "gitlab",
|
||||
"--key", "new_key",
|
||||
"--secret", "new_secret",
|
||||
},
|
||||
authSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "gitlab",
|
||||
ClientID: "new_key",
|
||||
ClientSecret: "new_secret",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config with options",
|
||||
id: 1,
|
||||
existingAuthSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "old name",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "gitlab",
|
||||
ClientID: "old_key",
|
||||
ClientSecret: "old_secret",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
TokenURL: "https://old.example.com/token",
|
||||
AuthURL: "https://old.example.com/auth",
|
||||
ProfileURL: "https://old.example.com/profile",
|
||||
EmailURL: "https://old.example.com/email",
|
||||
Tenant: "old_tenant",
|
||||
},
|
||||
IconURL: "https://old.example.com/icon",
|
||||
Scopes: []string{"old_scope1", "old_scope2"},
|
||||
RequiredClaimName: "old_claim_name",
|
||||
RequiredClaimValue: "old_claim_value",
|
||||
GroupClaimName: "old_group_name",
|
||||
AdminGroup: "old_admin",
|
||||
RestrictedGroup: "old_restricted",
|
||||
GroupTeamMap: `{"old_group1": [1,2]}`,
|
||||
GroupTeamMapRemoval: true,
|
||||
SSHPublicKeyClaimName: "old_ssh_pub_key",
|
||||
FullNameClaimName: "old_full_name",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
args: []string{
|
||||
"--id", "1",
|
||||
"--name", "test",
|
||||
"--provider", "github",
|
||||
"--key", "new_key",
|
||||
"--secret", "new_secret",
|
||||
"--use-custom-urls", "true",
|
||||
"--custom-token-url", "https://example.com/token",
|
||||
"--custom-auth-url", "https://example.com/auth",
|
||||
"--custom-profile-url", "https://example.com/profile",
|
||||
"--custom-email-url", "https://example.com/email",
|
||||
"--custom-tenant-id", "new_tenant",
|
||||
"--icon-url", "https://example.com/icon",
|
||||
"--scopes", "scope1,scope2",
|
||||
"--skip-local-2fa=true",
|
||||
"--required-claim-name", "claim_name",
|
||||
"--required-claim-value", "claim_value",
|
||||
"--group-claim-name", "group_name",
|
||||
"--admin-group", "admin",
|
||||
"--restricted-group", "restricted",
|
||||
"--group-team-map", `{"group1": [1,2]}`,
|
||||
"--group-team-map-removal=false",
|
||||
"--ssh-public-key-claim-name", "new_ssh_pub_key",
|
||||
"--full-name-claim-name", "new_full_name",
|
||||
},
|
||||
authSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
Provider: "github",
|
||||
ClientID: "new_key",
|
||||
ClientSecret: "new_secret",
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{
|
||||
TokenURL: "https://example.com/token",
|
||||
AuthURL: "https://example.com/auth",
|
||||
ProfileURL: "https://example.com/profile",
|
||||
EmailURL: "https://example.com/email",
|
||||
Tenant: "new_tenant",
|
||||
},
|
||||
IconURL: "https://example.com/icon",
|
||||
Scopes: []string{"scope1", "scope2"},
|
||||
RequiredClaimName: "claim_name",
|
||||
RequiredClaimValue: "claim_value",
|
||||
GroupClaimName: "group_name",
|
||||
AdminGroup: "admin",
|
||||
RestrictedGroup: "restricted",
|
||||
GroupTeamMap: `{"group1": [1,2]}`,
|
||||
GroupTeamMapRemoval: false,
|
||||
SSHPublicKeyClaimName: "new_ssh_pub_key",
|
||||
FullNameClaimName: "new_full_name",
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
a := &authService{
|
||||
initDB: func(ctx context.Context) error {
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth_model.Source, error) {
|
||||
return &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &oauth2.Source{
|
||||
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
}, nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, source *auth_model.Source) error {
|
||||
assert.Equal(t, tc.authSource, source)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
app := &cli.Command{
|
||||
Flags: microcmdAuthUpdateOauth().Flags,
|
||||
Action: a.runUpdateOauth,
|
||||
}
|
||||
|
||||
args := []string{"oauth-test"}
|
||||
args = append(args, tc.args...)
|
||||
|
||||
err := app.Run(t.Context(), args)
|
||||
|
||||
if tc.errMsg != "" {
|
||||
assert.EqualError(t, err, tc.errMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
@ -11,11 +12,11 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
smtpCLIFlags = []cli.Flag{
|
||||
func smtpCLIFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
@ -38,12 +39,10 @@ var (
|
||||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
@ -53,7 +52,6 @@ var (
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
@ -63,7 +61,6 @@ var (
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
@ -71,23 +68,34 @@ var (
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthAddSMTP = &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: runAddSMTP,
|
||||
Flags: smtpCLIFlags,
|
||||
func microcmdAuthUpdateSMTP() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().runUpdateSMTP(ctx, cmd)
|
||||
},
|
||||
Flags: append(smtpCLIFlags()[:1], append([]cli.Flag{&cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}}, smtpCLIFlags()[1:]...)...),
|
||||
}
|
||||
}
|
||||
|
||||
microcmdAuthUpdateSMTP = &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: runUpdateSMTP,
|
||||
Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
|
||||
func microcmdAuthAddSMTP() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return newAuthService().runAddSMTP(ctx, cmd)
|
||||
},
|
||||
Flags: smtpCLIFlags(),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
func parseSMTPConfig(c *cli.Command, conf *smtp.Source) error {
|
||||
if c.IsSet("auth-type") {
|
||||
conf.Auth = c.String("auth-type")
|
||||
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
|
||||
@ -117,17 +125,11 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
if c.IsSet("disable-helo") {
|
||||
conf.DisableHelo = c.Bool("disable-helo")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTP(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
func (a *authService) runAddSMTP(ctx context.Context, c *cli.Command) error {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -155,27 +157,25 @@ func runAddSMTP(c *cli.Context) error {
|
||||
smtpConfig.Auth = "PLAIN"
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
return a.createAuthSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
TwoFactorPolicy: util.Iif(c.Bool("skip-local-2fa"), "skip", ""),
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateSMTP(c *cli.Context) error {
|
||||
func (a *authService) runUpdateSMTP(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
if err := a.initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
source, err := a.getAuthSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -195,6 +195,6 @@ func runUpdateSMTP(c *cli.Context) error {
|
||||
}
|
||||
|
||||
source.Cfg = smtpConfig
|
||||
|
||||
return auth_model.UpdateSource(ctx, source)
|
||||
source.TwoFactorPolicy = util.Iif(c.Bool("skip-local-2fa"), "skip", "")
|
||||
return a.updateAuthSource(ctx, source)
|
||||
}
|
271
cmd/admin_auth_smtp_test.go
Normal file
271
cmd/admin_auth_smtp_test.go
Normal file
@ -0,0 +1,271 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestAddSMTP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
source *auth_model.Source
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "missing name",
|
||||
args: []string{
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
},
|
||||
errMsg: "name must be set",
|
||||
},
|
||||
{
|
||||
name: "missing host",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--port", "25",
|
||||
},
|
||||
errMsg: "host must be set",
|
||||
},
|
||||
{
|
||||
name: "missing port",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
},
|
||||
errMsg: "port must be set",
|
||||
},
|
||||
{
|
||||
name: "valid config",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config with options",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
"--auth-type", "LOGIN",
|
||||
"--force-smtps",
|
||||
"--skip-verify",
|
||||
"--helo-hostname", "example.com",
|
||||
"--disable-helo=true",
|
||||
"--allowed-domains", "example.com,example.org",
|
||||
"--skip-local-2fa",
|
||||
"--active=false",
|
||||
},
|
||||
source: &auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: "test",
|
||||
IsActive: false,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "LOGIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
HeloHostname: "example.com",
|
||||
DisableHelo: true,
|
||||
AllowedDomains: "example.com,example.org",
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
a := &authService{
|
||||
initDB: func(ctx context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, source *auth_model.Source) error {
|
||||
assert.Equal(t, tc.source, source)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cli.Command{
|
||||
Flags: microcmdAuthAddSMTP().Flags,
|
||||
Action: a.runAddSMTP,
|
||||
}
|
||||
|
||||
args := []string{"smtp-test"}
|
||||
args = append(args, tc.args...)
|
||||
|
||||
t.Log(args)
|
||||
err := cmd.Run(t.Context(), args)
|
||||
|
||||
if tc.errMsg != "" {
|
||||
assert.EqualError(t, err, tc.errMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateSMTP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
existingAuthSource *auth_model.Source
|
||||
authSource *auth_model.Source
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "missing id",
|
||||
args: []string{
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
},
|
||||
errMsg: "--id flag is missing",
|
||||
},
|
||||
{
|
||||
name: "valid config",
|
||||
existingAuthSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.SMTP,
|
||||
Name: "old name",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "old host",
|
||||
Port: 26,
|
||||
},
|
||||
},
|
||||
args: []string{
|
||||
"--id", "1",
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
},
|
||||
authSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.SMTP,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config with options",
|
||||
existingAuthSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.SMTP,
|
||||
Name: "old name",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
Host: "old host",
|
||||
Port: 26,
|
||||
HeloHostname: "old.example.com",
|
||||
AllowedDomains: "old.example.com",
|
||||
},
|
||||
TwoFactorPolicy: "",
|
||||
},
|
||||
args: []string{
|
||||
"--id", "1",
|
||||
"--name", "test",
|
||||
"--host", "localhost",
|
||||
"--port", "25",
|
||||
"--auth-type", "LOGIN",
|
||||
"--force-smtps",
|
||||
"--skip-verify",
|
||||
"--helo-hostname", "example.com",
|
||||
"--disable-helo",
|
||||
"--allowed-domains", "example.com,example.org",
|
||||
"--skip-local-2fa",
|
||||
"--active=false",
|
||||
},
|
||||
authSource: &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.SMTP,
|
||||
Name: "test",
|
||||
IsActive: false,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "LOGIN",
|
||||
Host: "localhost",
|
||||
Port: 25,
|
||||
ForceSMTPS: true,
|
||||
SkipVerify: true,
|
||||
HeloHostname: "example.com",
|
||||
DisableHelo: true,
|
||||
AllowedDomains: "example.com,example.org",
|
||||
},
|
||||
TwoFactorPolicy: "skip",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
a := &authService{
|
||||
initDB: func(ctx context.Context) error {
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth_model.Source, error) {
|
||||
return &auth_model.Source{
|
||||
ID: 1,
|
||||
Type: auth_model.SMTP,
|
||||
Name: "test",
|
||||
IsActive: true,
|
||||
Cfg: &smtp.Source{
|
||||
Auth: "PLAIN",
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
updateAuthSource: func(ctx context.Context, source *auth_model.Source) error {
|
||||
assert.Equal(t, tc.authSource, source)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
app := &cli.Command{
|
||||
Flags: microcmdAuthUpdateSMTP().Flags,
|
||||
Action: a.runUpdateSMTP,
|
||||
}
|
||||
args := []string{"smtp-tests"}
|
||||
args = append(args, tc.args...)
|
||||
|
||||
err := app.Run(t.Context(), args)
|
||||
|
||||
if tc.errMsg != "" {
|
||||
assert.EqualError(t, err, tc.errMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -4,11 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -25,20 +27,14 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runRegenerateHooks(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRegenerateHooks(ctx context.Context, _ *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||
}
|
||||
|
||||
func runRegenerateKeys(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRegenerateKeys(ctx context.Context, _ *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4,18 +4,18 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var subcmdUser = &cli.Command{
|
||||
Name: "user",
|
||||
Usage: "Modify users",
|
||||
Subcommands: []*cli.Command{
|
||||
microcmdUserCreate,
|
||||
Commands: []*cli.Command{
|
||||
microcmdUserCreate(),
|
||||
microcmdUserList,
|
||||
microcmdUserChangePassword,
|
||||
microcmdUserDelete,
|
||||
microcmdUserChangePassword(),
|
||||
microcmdUserDelete(),
|
||||
microcmdUserGenerateAccessToken,
|
||||
microcmdUserMustChangePassword,
|
||||
microcmdUserMustChangePassword(),
|
||||
},
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
@ -13,44 +14,41 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
user_service "code.gitea.io/gitea/services/user"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserChangePassword = &cli.Command{
|
||||
Name: "change-password",
|
||||
Usage: "Change a user's password",
|
||||
Action: runChangePassword,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Value: "",
|
||||
Usage: "The user to change password for",
|
||||
func microcmdUserChangePassword() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "change-password",
|
||||
Usage: "Change a user's password",
|
||||
Action: runChangePassword,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "The user to change password for",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "New password to set for user",
|
||||
Required: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password (can be disabled by --must-change-password=false)",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Aliases: []string{"p"},
|
||||
Value: "",
|
||||
Usage: "New password to set for user",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password (can be disabled by --must-change-password=false)",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runChangePassword(c *cli.Context) error {
|
||||
if err := argsSet(c, "username", "password"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
func runChangePassword(ctx context.Context, c *cli.Command) error {
|
||||
if !setting.IsInTesting {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
user, err := user_model.GetUserByName(ctx, c.String("username"))
|
||||
|
91
cmd/admin_user_change_password_test.go
Normal file
91
cmd/admin_user_change_password_test.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestChangePasswordCommand(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
}()
|
||||
|
||||
t.Run("change password successfully", func(t *testing.T) {
|
||||
// defer func() {
|
||||
// require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
// }()
|
||||
// Prepare test user
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
err := microcmdUserCreate().Run(ctx, []string{"create", "--username", "testuser", "--email", "testuser@gitea.local", "--random-password"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// load test user
|
||||
userBase := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
|
||||
// Change the password
|
||||
err = microcmdUserChangePassword().Run(ctx, []string{"change-password", "--username", "testuser", "--password", "newpassword"})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify the password has been changed
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.NotEqual(t, userBase.Passwd, user.Passwd)
|
||||
assert.NotEqual(t, userBase.Salt, user.Salt)
|
||||
|
||||
// Additional check for must-change-password flag
|
||||
require.NoError(t, microcmdUserChangePassword().Run(ctx, []string{"change-password", "--username", "testuser", "--password", "anotherpassword", "--must-change-password=false"}))
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.False(t, user.MustChangePassword)
|
||||
|
||||
require.NoError(t, microcmdUserChangePassword().Run(ctx, []string{"change-password", "--username", "testuser", "--password", "yetanotherpassword", "--must-change-password"}))
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.True(t, user.MustChangePassword)
|
||||
})
|
||||
|
||||
t.Run("failure cases", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "user does not exist",
|
||||
args: []string{"change-password", "--username", "nonexistentuser", "--password", "newpassword"},
|
||||
expectedErr: "user does not exist",
|
||||
},
|
||||
{
|
||||
name: "missing username",
|
||||
args: []string{"change-password", "--password", "newpassword"},
|
||||
expectedErr: `"username" not set`,
|
||||
},
|
||||
{
|
||||
name: "missing password",
|
||||
args: []string{"change-password", "--username", "testuser"},
|
||||
expectedErr: `"password" not set`,
|
||||
},
|
||||
{
|
||||
name: "too short password",
|
||||
args: []string{"change-password", "--username", "testuser", "--password", "1"},
|
||||
expectedErr: "password is not long enough",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := microcmdUserChangePassword().Run(ctx, tc.args)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErr)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
@ -16,87 +16,95 @@ import (
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserCreate = &cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create a new user in database",
|
||||
Action: runCreateUser,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Username. DEPRECATED: use username instead",
|
||||
func microcmdUserCreate() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create a new user in database",
|
||||
Action: runCreateUser,
|
||||
MutuallyExclusiveFlags: []cli.MutuallyExclusiveFlags{
|
||||
{
|
||||
Flags: [][]cli.Flag{
|
||||
{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Username. DEPRECATED: use username instead",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Usage: "Username",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Usage: "Username",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "user-type",
|
||||
Usage: "Set user's type: individual or bot",
|
||||
Value: "individual",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Usage: "User password",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Usage: "User email address",
|
||||
Required: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "admin",
|
||||
Usage: "User is an admin",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "random-password",
|
||||
Usage: "Generate a random password for the user",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password after initial login, defaults to true for all users except the first one (can be disabled by --must-change-password=false)",
|
||||
HideDefault: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "random-password-length",
|
||||
Usage: "Length of the random password to be generated",
|
||||
Value: 12,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "access-token",
|
||||
Usage: "Generate access token for the user",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "access-token-name",
|
||||
Usage: `Name of the generated access token`,
|
||||
Value: "gitea-admin",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "access-token-scopes",
|
||||
Usage: `Scopes of the generated access token, comma separated. Examples: "all", "public-only,read:issue", "write:repository,write:user"`,
|
||||
Value: "all",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "restricted",
|
||||
Usage: "Make a restricted user account",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fullname",
|
||||
Usage: `The full, human-readable name of the user`,
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "user-type",
|
||||
Usage: "Set user's type: individual or bot",
|
||||
Value: "individual",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Usage: "User password",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Usage: "User email address",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "admin",
|
||||
Usage: "User is an admin",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "random-password",
|
||||
Usage: "Generate a random password for the user",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password after initial login, defaults to true for all users except the first one (can be disabled by --must-change-password=false)",
|
||||
DisableDefaultText: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "random-password-length",
|
||||
Usage: "Length of the random password to be generated",
|
||||
Value: 12,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "access-token",
|
||||
Usage: "Generate access token for the user",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "access-token-name",
|
||||
Usage: `Name of the generated access token`,
|
||||
Value: "gitea-admin",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "access-token-scopes",
|
||||
Usage: `Scopes of the generated access token, comma separated. Examples: "all", "public-only,read:issue", "write:repository,write:user"`,
|
||||
Value: "all",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "restricted",
|
||||
Usage: "Make a restricted user account",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fullname",
|
||||
Usage: `The full, human-readable name of the user`,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runCreateUser(c *cli.Context) error {
|
||||
func runCreateUser(ctx context.Context, c *cli.Command) error {
|
||||
// this command highly depends on the many setting options (create org, visibility, etc.), so it must have a full setting load first
|
||||
// duplicate setting loading should be safe at the moment, but it should be refactored & improved in the future.
|
||||
setting.LoadSettings()
|
||||
|
||||
if err := argsSet(c, "email"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userTypes := map[string]user_model.UserType{
|
||||
"individual": user_model.UserTypeIndividual,
|
||||
"bot": user_model.UserTypeBot,
|
||||
@ -113,12 +121,6 @@ func runCreateUser(c *cli.Context) error {
|
||||
return errors.New("password can only be set for individual users")
|
||||
}
|
||||
}
|
||||
if c.IsSet("name") && c.IsSet("username") {
|
||||
return errors.New("cannot set both --name and --username flags")
|
||||
}
|
||||
if !c.IsSet("name") && !c.IsSet("username") {
|
||||
return errors.New("one of --name or --username flags must be set")
|
||||
}
|
||||
|
||||
if c.IsSet("password") && c.IsSet("random-password") {
|
||||
return errors.New("cannot set both -random-password and -password flags")
|
||||
@ -129,16 +131,12 @@ func runCreateUser(c *cli.Context) error {
|
||||
username = c.String("username")
|
||||
} else {
|
||||
username = c.String("name")
|
||||
_, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
|
||||
_, _ = fmt.Fprintf(c.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
|
||||
}
|
||||
|
||||
ctx := c.Context
|
||||
if !setting.IsInTesting {
|
||||
// FIXME: need to refactor the "installSignals/initDB" related code later
|
||||
// FIXME: need to refactor the "initDB" related code later
|
||||
// it doesn't make sense to call it in (almost) every command action function
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = installSignals()
|
||||
defer cancel()
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ import (
|
||||
)
|
||||
|
||||
func TestAdminUserCreate(t *testing.T) {
|
||||
app := NewMainApp(AppVersion{})
|
||||
|
||||
reset := func() {
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
|
||||
@ -31,8 +29,9 @@ func TestAdminUserCreate(t *testing.T) {
|
||||
IsAdmin bool
|
||||
MustChangePassword bool
|
||||
}
|
||||
|
||||
createCheck := func(name, args string) check {
|
||||
require.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %s@gitea.local %s --password foobar", name, name, args))))
|
||||
require.NoError(t, microcmdUserCreate().Run(t.Context(), strings.Fields(fmt.Sprintf("create --username %s --email %s@gitea.local %s --password foobar", name, name, args))))
|
||||
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
|
||||
return check{IsAdmin: u.IsAdmin, MustChangePassword: u.MustChangePassword}
|
||||
}
|
||||
@ -51,7 +50,7 @@ func TestAdminUserCreate(t *testing.T) {
|
||||
})
|
||||
|
||||
createUser := func(name string, args ...string) error {
|
||||
return app.Run(append([]string{"./gitea", "admin", "user", "create", "--username", name, "--email", name + "@gitea.local"}, args...))
|
||||
return microcmdUserCreate().Run(t.Context(), append([]string{"create", "--username", name, "--email", name + "@gitea.local"}, args...))
|
||||
}
|
||||
|
||||
t.Run("UserType", func(t *testing.T) {
|
||||
|
@ -4,53 +4,56 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
user_service "code.gitea.io/gitea/services/user"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific user by id, name or email",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of user of the user to delete",
|
||||
func microcmdUserDelete() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific user by id, name or email",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of user of the user to delete",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "Username of the user to delete",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "Email of the user to delete",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "purge",
|
||||
Usage: "Purge user, all their repositories, organizations and comments",
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "Username of the user to delete",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "Email of the user to delete",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "purge",
|
||||
Usage: "Purge user, all their repositories, organizations and comments",
|
||||
},
|
||||
},
|
||||
Action: runDeleteUser,
|
||||
Action: runDeleteUser,
|
||||
}
|
||||
}
|
||||
|
||||
func runDeleteUser(c *cli.Context) error {
|
||||
func runDeleteUser(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
|
||||
return errors.New("You must provide the id, username or email of a user to delete")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
if !setting.IsInTesting {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := storage.Init(); err != nil {
|
||||
@ -70,11 +73,11 @@ func runDeleteUser(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
if c.IsSet("username") && user.LowerName != strings.ToLower(strings.TrimSpace(c.String("username"))) {
|
||||
return fmt.Errorf("The user %s who has email %s does not match the provided username %s", user.Name, c.String("email"), c.String("username"))
|
||||
return fmt.Errorf("the user %s who has email %s does not match the provided username %s", user.Name, c.String("email"), c.String("username"))
|
||||
}
|
||||
|
||||
if c.IsSet("id") && user.ID != c.Int64("id") {
|
||||
return fmt.Errorf("The user %s does not match the provided id %d", user.Name, c.Int64("id"))
|
||||
return fmt.Errorf("the user %s does not match the provided id %d", user.Name, c.Int64("id"))
|
||||
}
|
||||
|
||||
return user_service.DeleteUser(ctx, user, c.Bool("purge"))
|
||||
|
111
cmd/admin_user_delete_test.go
Normal file
111
cmd/admin_user_delete_test.go
Normal file
@ -0,0 +1,111 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAdminUserDelete(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
defer func() {
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &auth_model.AccessToken{}))
|
||||
}()
|
||||
|
||||
setupTestUser := func(t *testing.T) {
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
err := microcmdUserCreate().Run(t.Context(), []string{"create", "--username", "testuser", "--email", "testuser@gitea.local", "--random-password"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
t.Run("delete user by id", func(t *testing.T) {
|
||||
setupTestUser(t)
|
||||
|
||||
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
err := microcmdUserDelete().Run(ctx, []string{"delete-test", "--id", strconv.FormatInt(u.ID, 10)})
|
||||
require.NoError(t, err)
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
})
|
||||
t.Run("delete user by username", func(t *testing.T) {
|
||||
setupTestUser(t)
|
||||
|
||||
err := microcmdUserDelete().Run(ctx, []string{"delete-test", "--username", "testuser"})
|
||||
require.NoError(t, err)
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
})
|
||||
t.Run("delete user by email", func(t *testing.T) {
|
||||
setupTestUser(t)
|
||||
|
||||
err := microcmdUserDelete().Run(ctx, []string{"delete-test", "--email", "testuser@gitea.local"})
|
||||
require.NoError(t, err)
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
})
|
||||
t.Run("delete user by all 3 attributes", func(t *testing.T) {
|
||||
setupTestUser(t)
|
||||
|
||||
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
err := microcmdUserDelete().Run(ctx, []string{"delete", "--id", strconv.FormatInt(u.ID, 10), "--username", "testuser", "--email", "testuser@gitea.local"})
|
||||
require.NoError(t, err)
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdminUserDeleteFailure(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "no user to delete",
|
||||
args: []string{"delete", "--username", "nonexistentuser"},
|
||||
expectedErr: "user does not exist",
|
||||
},
|
||||
{
|
||||
name: "user exists but provided username does not match",
|
||||
args: []string{"delete", "--email", "testuser@gitea.local", "--username", "wrongusername"},
|
||||
expectedErr: "the user testuser who has email testuser@gitea.local does not match the provided username wrongusername",
|
||||
},
|
||||
{
|
||||
name: "user exists but provided id does not match",
|
||||
args: []string{"delete", "--username", "testuser", "--id", "999"},
|
||||
expectedErr: "the user testuser does not match the provided id 999",
|
||||
},
|
||||
{
|
||||
name: "no required flags are provided",
|
||||
args: []string{"delete"},
|
||||
expectedErr: "You must provide the id, username or email of a user to delete",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
if strings.Contains(tc.name, "user exists") {
|
||||
unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"})
|
||||
err := microcmdUserCreate().Run(t.Context(), []string{"create", "--username", "testuser", "--email", "testuser@gitea.local", "--random-password"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
err := microcmdUserDelete().Run(ctx, tc.args)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErr)
|
||||
})
|
||||
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &auth_model.AccessToken{}))
|
||||
}
|
||||
}
|
@ -4,13 +4,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserGenerateAccessToken = &cli.Command{
|
||||
@ -41,14 +42,11 @@ var microcmdUserGenerateAccessToken = &cli.Command{
|
||||
Action: runGenerateAccessToken,
|
||||
}
|
||||
|
||||
func runGenerateAccessToken(c *cli.Context) error {
|
||||
func runGenerateAccessToken(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("you must provide a username to generate a token for")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4,13 +4,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserList = &cli.Command{
|
||||
@ -25,10 +26,7 @@ var microcmdUserList = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func runListUsers(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runListUsers(ctx context.Context, c *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -4,40 +4,41 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var microcmdUserMustChangePassword = &cli.Command{
|
||||
Name: "must-change-password",
|
||||
Usage: "Set the must change password flag for the provided users or all users",
|
||||
Action: runMustChangePassword,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "all",
|
||||
Aliases: []string{"A"},
|
||||
Usage: "All users must change password, except those explicitly excluded with --exclude",
|
||||
func microcmdUserMustChangePassword() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "must-change-password",
|
||||
Usage: "Set the must change password flag for the provided users or all users",
|
||||
Action: runMustChangePassword,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "all",
|
||||
Aliases: []string{"A"},
|
||||
Usage: "All users must change password, except those explicitly excluded with --exclude",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "exclude",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "Do not change the must-change-password flag for these users",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "unset",
|
||||
Usage: "Instead of setting the must-change-password flag, unset it",
|
||||
},
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "exclude",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "Do not change the must-change-password flag for these users",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "unset",
|
||||
Usage: "Instead of setting the must-change-password flag, unset it",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runMustChangePassword(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runMustChangePassword(ctx context.Context, c *cli.Command) error {
|
||||
if c.NArg() == 0 && !c.IsSet("all") {
|
||||
return errors.New("either usernames or --all must be provided")
|
||||
}
|
||||
@ -46,8 +47,10 @@ func runMustChangePassword(c *cli.Context) error {
|
||||
all := c.Bool("all")
|
||||
exclude := c.StringSlice("exclude")
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
if !setting.IsInTesting {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
n, err := user_model.SetMustChangePassword(ctx, all, mustChangePassword, c.Args().Slice(), exclude)
|
||||
|
78
cmd/admin_user_must_change_password_test.go
Normal file
78
cmd/admin_user_must_change_password_test.go
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMustChangePassword(t *testing.T) {
|
||||
defer func() {
|
||||
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
}()
|
||||
err := microcmdUserCreate().Run(t.Context(), []string{"create", "--username", "testuser", "--email", "testuser@gitea.local", "--random-password"})
|
||||
require.NoError(t, err)
|
||||
err = microcmdUserCreate().Run(t.Context(), []string{"create", "--username", "testuserexclude", "--email", "testuserexclude@gitea.local", "--random-password"})
|
||||
require.NoError(t, err)
|
||||
// Reset password change flag
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--all", "--unset"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.False(t, testUser.MustChangePassword)
|
||||
testUserExclude := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.False(t, testUserExclude.MustChangePassword)
|
||||
|
||||
// Make all users change password
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--all"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.True(t, testUser.MustChangePassword)
|
||||
testUserExclude = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.True(t, testUserExclude.MustChangePassword)
|
||||
|
||||
// Reset password change flag but exclude all tested users
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--all", "--unset", "--exclude", "testuser,testuserexclude"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.True(t, testUser.MustChangePassword)
|
||||
testUserExclude = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.True(t, testUserExclude.MustChangePassword)
|
||||
|
||||
// Reset password change flag by listing multiple users
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--unset", "testuser", "testuserexclude"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.False(t, testUser.MustChangePassword)
|
||||
testUserExclude = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.False(t, testUserExclude.MustChangePassword)
|
||||
|
||||
// Exclude a user from all user
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--all", "--exclude", "testuserexclude"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.True(t, testUser.MustChangePassword)
|
||||
testUserExclude = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.False(t, testUserExclude.MustChangePassword)
|
||||
|
||||
// Unset a flag for single user
|
||||
err = microcmdUserMustChangePassword().Run(t.Context(), []string{"change-test", "--unset", "testuser"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testUser = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuser"})
|
||||
assert.False(t, testUser.MustChangePassword)
|
||||
testUserExclude = unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "testuserexclude"})
|
||||
assert.False(t, testUserExclude.MustChangePassword)
|
||||
}
|
128
cmd/cert.go
128
cmd/cert.go
@ -6,6 +6,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
@ -13,6 +14,7 @@ import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"net"
|
||||
@ -20,47 +22,59 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdCert represents the available cert sub-command.
|
||||
var CmdCert = &cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
// cmdCert represents the available cert sub-command.
|
||||
func cmdCert() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
Action: runCert,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "",
|
||||
Usage: "Comma-separated hostnames and IPs to generate a certificate for",
|
||||
Action: runCert,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Usage: "Comma-separated hostnames and IPs to generate a certificate for",
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ecdsa-curve",
|
||||
Value: "",
|
||||
Usage: "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "rsa-bits",
|
||||
Value: 3072,
|
||||
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "start-date",
|
||||
Value: "",
|
||||
Usage: "Creation date formatted as Jan 1 15:04:05 2011",
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "duration",
|
||||
Value: 365 * 24 * time.Hour,
|
||||
Usage: "Duration that certificate is valid for",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "ca",
|
||||
Usage: "whether this cert should be its own Certificate Authority",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Value: "cert.pem",
|
||||
Usage: "Path to the file where there certificate will be saved",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "keyout",
|
||||
Value: "key.pem",
|
||||
Usage: "Path to the file where there certificate key will be saved",
|
||||
},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ecdsa-curve",
|
||||
Value: "",
|
||||
Usage: "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "rsa-bits",
|
||||
Value: 3072,
|
||||
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "start-date",
|
||||
Value: "",
|
||||
Usage: "Creation date formatted as Jan 1 15:04:05 2011",
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "duration",
|
||||
Value: 365 * 24 * time.Hour,
|
||||
Usage: "Duration that certificate is valid for",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "ca",
|
||||
Usage: "whether this cert should be its own Certificate Authority",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func publicKey(priv any) any {
|
||||
@ -89,11 +103,7 @@ func pemBlockForKey(priv any) *pem.Block {
|
||||
}
|
||||
}
|
||||
|
||||
func runCert(c *cli.Context) error {
|
||||
if err := argsSet(c, "host"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runCert(_ context.Context, c *cli.Command) error {
|
||||
var priv any
|
||||
var err error
|
||||
switch c.String("ecdsa-curve") {
|
||||
@ -108,17 +118,17 @@ func runCert(c *cli.Context) error {
|
||||
case "P521":
|
||||
priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
|
||||
default:
|
||||
log.Fatalf("Unrecognized elliptic curve: %q", c.String("ecdsa-curve"))
|
||||
err = fmt.Errorf("unrecognized elliptic curve: %q", c.String("ecdsa-curve"))
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate private key: %v", err)
|
||||
return fmt.Errorf("failed to generate private key: %w", err)
|
||||
}
|
||||
|
||||
var notBefore time.Time
|
||||
if startDate := c.String("start-date"); startDate != "" {
|
||||
notBefore, err = time.Parse("Jan 2 15:04:05 2006", startDate)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse creation date: %v", err)
|
||||
return fmt.Errorf("failed to parse creation date %w", err)
|
||||
}
|
||||
} else {
|
||||
notBefore = time.Now()
|
||||
@ -129,7 +139,7 @@ func runCert(c *cli.Context) error {
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate serial number: %v", err)
|
||||
return fmt.Errorf("failed to generate serial number: %w", err)
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
@ -146,8 +156,8 @@ func runCert(c *cli.Context) error {
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
hosts := strings.Split(c.String("host"), ",")
|
||||
for _, h := range hosts {
|
||||
hosts := strings.SplitSeq(c.String("host"), ",")
|
||||
for h := range hosts {
|
||||
if ip := net.ParseIP(h); ip != nil {
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
} else {
|
||||
@ -162,35 +172,35 @@ func runCert(c *cli.Context) error {
|
||||
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create certificate: %v", err)
|
||||
return fmt.Errorf("failed to create certificate: %w", err)
|
||||
}
|
||||
|
||||
certOut, err := os.Create("cert.pem")
|
||||
certOut, err := os.Create(c.String("out"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open cert.pem for writing: %v", err)
|
||||
return fmt.Errorf("failed to open %s for writing: %w", c.String("keyout"), err)
|
||||
}
|
||||
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encode certificate: %v", err)
|
||||
return fmt.Errorf("failed to encode certificate: %w", err)
|
||||
}
|
||||
err = certOut.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to write cert: %v", err)
|
||||
return fmt.Errorf("failed to write cert: %w", err)
|
||||
}
|
||||
log.Println("Written cert.pem")
|
||||
fmt.Fprintf(c.Writer, "Written cert to %s\n", c.String("out"))
|
||||
|
||||
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
||||
keyOut, err := os.OpenFile(c.String("keyout"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open key.pem for writing: %v", err)
|
||||
return fmt.Errorf("failed to open %s for writing: %w", c.String("keyout"), err)
|
||||
}
|
||||
err = pem.Encode(keyOut, pemBlockForKey(priv))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to encode key: %v", err)
|
||||
return fmt.Errorf("failed to encode key: %w", err)
|
||||
}
|
||||
err = keyOut.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to write key: %v", err)
|
||||
return fmt.Errorf("failed to write key: %w", err)
|
||||
}
|
||||
log.Println("Written key.pem")
|
||||
fmt.Fprintf(c.Writer, "Written key to %s\n", c.String("keyout"))
|
||||
return nil
|
||||
}
|
||||
|
123
cmd/cert_test.go
Normal file
123
cmd/cert_test.go
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCertCommand(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args []string
|
||||
}{
|
||||
{
|
||||
name: "RSA cert generation",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost",
|
||||
"--rsa-bits", "2048",
|
||||
"--duration", "1h",
|
||||
"--start-date", "Jan 1 00:00:00 2024",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ECDSA cert generation",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost",
|
||||
"--ecdsa-curve", "P256",
|
||||
"--duration", "1h",
|
||||
"--start-date", "Jan 1 00:00:00 2024",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mixed host, certificate authority",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost,127.0.0.1",
|
||||
"--duration", "1h",
|
||||
"--start-date", "Jan 1 00:00:00 2024",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
app := cmdCert()
|
||||
tempDir := t.TempDir()
|
||||
|
||||
certFile := filepath.Join(tempDir, "cert.pem")
|
||||
keyFile := filepath.Join(tempDir, "key.pem")
|
||||
|
||||
err := app.Run(t.Context(), append(c.args, "--out", certFile, "--keyout", keyFile))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.FileExists(t, certFile)
|
||||
assert.FileExists(t, keyFile)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertCommandFailures(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args []string
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
name: "Start Date Parsing failure",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost",
|
||||
"--start-date", "invalid-date",
|
||||
},
|
||||
errMsg: "parsing time",
|
||||
},
|
||||
{
|
||||
name: "Unknown curve",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost",
|
||||
"--ecdsa-curve", "invalid-curve",
|
||||
},
|
||||
errMsg: "unrecognized elliptic curve",
|
||||
},
|
||||
{
|
||||
name: "Key generation failure",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
"--host", "localhost",
|
||||
"--rsa-bits", "invalid-bits",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Missing parameters",
|
||||
args: []string{
|
||||
"cert-test",
|
||||
},
|
||||
errMsg: `"host" not set`,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
app := cmdCert()
|
||||
tempDir := t.TempDir()
|
||||
|
||||
certFile := filepath.Join(tempDir, "cert.pem")
|
||||
keyFile := filepath.Join(tempDir, "key.pem")
|
||||
err := app.Run(t.Context(), append(c.args, "--out", certFile, "--keyout", keyFile))
|
||||
require.Error(t, err)
|
||||
if c.errMsg != "" {
|
||||
assert.ErrorContains(t, err, c.errMsg)
|
||||
}
|
||||
assert.NoFileExists(t, certFile)
|
||||
assert.NoFileExists(t, keyFile)
|
||||
})
|
||||
}
|
||||
}
|
25
cmd/cmd.go
25
cmd/cmd.go
@ -18,20 +18,19 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// argsSet checks that all the required arguments are set. args is a list of
|
||||
// arguments that must be set in the passed Context.
|
||||
func argsSet(c *cli.Context, args ...string) error {
|
||||
func argsSet(c *cli.Command, args ...string) error {
|
||||
for _, a := range args {
|
||||
if !c.IsSet(a) {
|
||||
return errors.New(a + " is not set")
|
||||
}
|
||||
|
||||
if util.IsEmptyString(c.String(a)) {
|
||||
if c.Value(a) == nil {
|
||||
return errors.New(a + " is required")
|
||||
}
|
||||
}
|
||||
@ -109,7 +108,7 @@ func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
|
||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||
}
|
||||
|
||||
func globalBool(c *cli.Context, name string) bool {
|
||||
func globalBool(c *cli.Command, name string) bool {
|
||||
for _, ctx := range c.Lineage() {
|
||||
if ctx.Bool(name) {
|
||||
return true
|
||||
@ -120,8 +119,8 @@ func globalBool(c *cli.Context, name string) bool {
|
||||
|
||||
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
|
||||
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever.
|
||||
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
|
||||
return func(c *cli.Context) error {
|
||||
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(context.Context, *cli.Command) (context.Context, error) {
|
||||
return func(ctx context.Context, c *cli.Command) (context.Context, error) {
|
||||
level := defaultLevel
|
||||
if globalBool(c, "quiet") {
|
||||
level = log.FATAL
|
||||
@ -130,6 +129,16 @@ func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error
|
||||
level = log.TRACE
|
||||
}
|
||||
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
||||
return nil
|
||||
return ctx, nil
|
||||
}
|
||||
}
|
||||
|
||||
func isValidDefaultSubCommand(cmd *cli.Command) (string, bool) {
|
||||
// Dirty patch for urfave/cli's strange design.
|
||||
// "./gitea bad-cmd" should not start the web server.
|
||||
rootArgs := cmd.Root().Args().Slice()
|
||||
if len(rootArgs) != 0 && rootArgs[0] != cmd.Name {
|
||||
return rootArgs[0], false
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
38
cmd/cmd_test.go
Normal file
38
cmd/cmd_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestDefaultCommand(t *testing.T) {
|
||||
test := func(t *testing.T, args []string, expectedRetName string, expectedRetValid bool) {
|
||||
called := false
|
||||
cmd := &cli.Command{
|
||||
DefaultCommand: "test",
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "test",
|
||||
Action: func(ctx context.Context, command *cli.Command) error {
|
||||
retName, retValid := isValidDefaultSubCommand(command)
|
||||
assert.Equal(t, expectedRetName, retName)
|
||||
assert.Equal(t, expectedRetValid, retValid)
|
||||
called = true
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, cmd.Run(t.Context(), args))
|
||||
assert.True(t, called)
|
||||
}
|
||||
test(t, []string{"./gitea"}, "", true)
|
||||
test(t, []string{"./gitea", "test"}, "", true)
|
||||
test(t, []string{"./gitea", "other"}, "other", false)
|
||||
}
|
18
cmd/docs.go
18
cmd/docs.go
@ -4,11 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
cli_docs "github.com/urfave/cli-docs/v3"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdDocs represents the available docs sub-command.
|
||||
@ -30,16 +32,16 @@ var CmdDocs = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func runDocs(ctx *cli.Context) error {
|
||||
docs, err := ctx.App.ToMarkdown()
|
||||
if ctx.Bool("man") {
|
||||
docs, err = ctx.App.ToMan()
|
||||
func runDocs(_ context.Context, cmd *cli.Command) error {
|
||||
docs, err := cli_docs.ToMarkdown(cmd.Root())
|
||||
if cmd.Bool("man") {
|
||||
docs, err = cli_docs.ToMan(cmd.Root())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ctx.Bool("man") {
|
||||
if !cmd.Bool("man") {
|
||||
// Clean up markdown. The following bug was fixed in v2, but is present in v1.
|
||||
// It affects markdown output (even though the issue is referring to man pages)
|
||||
// https://github.com/urfave/cli/issues/1040
|
||||
@ -51,8 +53,8 @@ func runDocs(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
out := os.Stdout
|
||||
if ctx.String("output") != "" {
|
||||
fi, err := os.Create(ctx.String("output"))
|
||||
if cmd.String("output") != "" {
|
||||
fi, err := os.Create(cmd.String("output"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/doctor"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
@ -30,7 +30,7 @@ var CmdDoctor = &cli.Command{
|
||||
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
||||
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
cmdDoctorCheck,
|
||||
cmdRecreateTable,
|
||||
cmdDoctorConvert,
|
||||
@ -93,16 +93,13 @@ You should back-up your database before doing this and ensure that your database
|
||||
Action: runRecreateTable,
|
||||
}
|
||||
|
||||
func runRecreateTable(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRecreateTable(ctx context.Context, cmd *cli.Command) error {
|
||||
// Redirect the default golog to here
|
||||
golog.SetFlags(0)
|
||||
golog.SetPrefix("")
|
||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
||||
|
||||
debug := ctx.Bool("debug")
|
||||
debug := cmd.Bool("debug")
|
||||
setting.MustInstalled()
|
||||
setting.LoadDBSetting()
|
||||
|
||||
@ -113,15 +110,15 @@ func runRecreateTable(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
setting.Database.LogSQL = debug
|
||||
if err := db.InitEngine(stdCtx); err != nil {
|
||||
if err := db.InitEngine(ctx); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Println("Check if you are using the right config file. You can use a --config directive to specify one.")
|
||||
return nil
|
||||
}
|
||||
|
||||
args := ctx.Args()
|
||||
names := make([]string, 0, ctx.NArg())
|
||||
for i := 0; i < ctx.NArg(); i++ {
|
||||
args := cmd.Args()
|
||||
names := make([]string, 0, cmd.NArg())
|
||||
for i := 0; i < cmd.NArg(); i++ {
|
||||
names = append(names, args.Get(i))
|
||||
}
|
||||
|
||||
@ -131,7 +128,7 @@ func runRecreateTable(ctx *cli.Context) error {
|
||||
}
|
||||
recreateTables := migrate_base.RecreateTables(beans...)
|
||||
|
||||
return db.InitEngineWithMigration(stdCtx, func(ctx context.Context, x *xorm.Engine) error {
|
||||
return db.InitEngineWithMigration(ctx, func(ctx context.Context, x *xorm.Engine) error {
|
||||
if err := migrations.EnsureUpToDate(ctx, x); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -139,11 +136,11 @@ func runRecreateTable(ctx *cli.Context) error {
|
||||
})
|
||||
}
|
||||
|
||||
func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
||||
func setupDoctorDefaultLogger(cmd *cli.Command, colorize bool) {
|
||||
// Silence the default loggers
|
||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
||||
|
||||
logFile := ctx.String("log-file")
|
||||
logFile := cmd.String("log-file")
|
||||
switch logFile {
|
||||
case "":
|
||||
return // if no doctor log-file is set, do not show any log from default logger
|
||||
@ -161,23 +158,20 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func runDoctorCheck(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runDoctorCheck(ctx context.Context, cmd *cli.Command) error {
|
||||
colorize := log.CanColorStdout
|
||||
if ctx.IsSet("color") {
|
||||
colorize = ctx.Bool("color")
|
||||
if cmd.IsSet("color") {
|
||||
colorize = cmd.Bool("color")
|
||||
}
|
||||
|
||||
setupDoctorDefaultLogger(ctx, colorize)
|
||||
setupDoctorDefaultLogger(cmd, colorize)
|
||||
|
||||
// Finally redirect the default golang's log to here
|
||||
golog.SetFlags(0)
|
||||
golog.SetPrefix("")
|
||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
||||
|
||||
if ctx.IsSet("list") {
|
||||
if cmd.IsSet("list") {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
||||
_, _ = w.Write([]byte("Default\tName\tTitle\n"))
|
||||
doctor.SortChecks(doctor.Checks)
|
||||
@ -195,12 +189,12 @@ func runDoctorCheck(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
var checks []*doctor.Check
|
||||
if ctx.Bool("all") {
|
||||
if cmd.Bool("all") {
|
||||
checks = make([]*doctor.Check, len(doctor.Checks))
|
||||
copy(checks, doctor.Checks)
|
||||
} else if ctx.IsSet("run") {
|
||||
addDefault := ctx.Bool("default")
|
||||
runNamesSet := container.SetOf(ctx.StringSlice("run")...)
|
||||
} else if cmd.IsSet("run") {
|
||||
addDefault := cmd.Bool("default")
|
||||
runNamesSet := container.SetOf(cmd.StringSlice("run")...)
|
||||
for _, check := range doctor.Checks {
|
||||
if (addDefault && check.IsDefault) || runNamesSet.Contains(check.Name) {
|
||||
checks = append(checks, check)
|
||||
@ -217,5 +211,5 @@ func runDoctorCheck(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
return doctor.RunChecks(stdCtx, colorize, ctx.Bool("fix"), checks)
|
||||
return doctor.RunChecks(ctx, colorize, cmd.Bool("fix"), checks)
|
||||
}
|
||||
|
@ -4,13 +4,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// cmdDoctorConvert represents the available convert sub-command.
|
||||
@ -21,11 +22,8 @@ var cmdDoctorConvert = &cli.Command{
|
||||
Action: runDoctorConvert,
|
||||
}
|
||||
|
||||
func runDoctorConvert(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(stdCtx); err != nil {
|
||||
func runDoctorConvert(ctx context.Context, cmd *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"code.gitea.io/gitea/services/doctor"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestDoctorRun(t *testing.T) {
|
||||
@ -22,12 +22,13 @@ func TestDoctorRun(t *testing.T) {
|
||||
|
||||
SkipDatabaseInitialization: true,
|
||||
})
|
||||
app := cli.NewApp()
|
||||
app.Commands = []*cli.Command{cmdDoctorCheck}
|
||||
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
||||
app := &cli.Command{
|
||||
Commands: []*cli.Command{cmdDoctorCheck},
|
||||
}
|
||||
err := app.Run(t.Context(), []string{"./gitea", "check", "--run", "test-check"})
|
||||
assert.NoError(t, err)
|
||||
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
||||
err = app.Run(t.Context(), []string{"./gitea", "check", "--run", "no-such"})
|
||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
||||
err = app.Run(t.Context(), []string{"./gitea", "check", "--run", "test-check,no-such"})
|
||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||
}
|
||||
|
36
cmd/dump.go
36
cmd/dump.go
@ -5,6 +5,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@ -20,7 +21,7 @@ import (
|
||||
|
||||
"gitea.com/go-chi/session"
|
||||
"github.com/mholt/archiver/v3"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdDump represents the available dump sub-command.
|
||||
@ -101,17 +102,17 @@ func fatal(format string, args ...any) {
|
||||
log.Fatal(format, args...)
|
||||
}
|
||||
|
||||
func runDump(ctx *cli.Context) error {
|
||||
func runDump(ctx context.Context, cmd *cli.Command) error {
|
||||
setting.MustInstalled()
|
||||
|
||||
quite := ctx.Bool("quiet")
|
||||
verbose := ctx.Bool("verbose")
|
||||
quite := cmd.Bool("quiet")
|
||||
verbose := cmd.Bool("verbose")
|
||||
if verbose && quite {
|
||||
fatal("Option --quiet and --verbose cannot both be set")
|
||||
}
|
||||
|
||||
// outFileName is either "-" or a file name (will be made absolute)
|
||||
outFileName, outType := dump.PrepareFileNameAndType(ctx.String("file"), ctx.String("type"))
|
||||
outFileName, outType := dump.PrepareFileNameAndType(cmd.String("file"), cmd.String("type"))
|
||||
if outType == "" {
|
||||
fatal("Invalid output type")
|
||||
}
|
||||
@ -136,10 +137,7 @@ func runDump(ctx *cli.Context) error {
|
||||
setting.DisableLoggerInit()
|
||||
setting.LoadSettings() // cannot access session settings otherwise
|
||||
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
err := db.InitEngine(stdCtx)
|
||||
err := db.InitEngine(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -165,7 +163,7 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
dumper.GlobalExcludeAbsPath(outFileName)
|
||||
|
||||
if ctx.IsSet("skip-repository") && ctx.Bool("skip-repository") {
|
||||
if cmd.IsSet("skip-repository") && cmd.Bool("skip-repository") {
|
||||
log.Info("Skip dumping local repositories")
|
||||
} else {
|
||||
log.Info("Dumping local repositories... %s", setting.RepoRootPath)
|
||||
@ -173,7 +171,7 @@ func runDump(ctx *cli.Context) error {
|
||||
fatal("Failed to include repositories: %v", err)
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") {
|
||||
if cmd.IsSet("skip-lfs-data") && cmd.Bool("skip-lfs-data") {
|
||||
log.Info("Skip dumping LFS data")
|
||||
} else if !setting.LFS.StartServer {
|
||||
log.Info("LFS isn't enabled. Skip dumping LFS data")
|
||||
@ -188,12 +186,12 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Bool("skip-db") {
|
||||
if cmd.Bool("skip-db") {
|
||||
// Ensure that we don't dump the database file that may reside in setting.AppDataPath or elsewhere.
|
||||
dumper.GlobalExcludeAbsPath(setting.Database.Path)
|
||||
log.Info("Skipping database")
|
||||
} else {
|
||||
tmpDir := ctx.String("tempdir")
|
||||
tmpDir := cmd.String("tempdir")
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
fatal("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
@ -209,7 +207,7 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
}()
|
||||
|
||||
targetDBType := ctx.String("database")
|
||||
targetDBType := cmd.String("database")
|
||||
if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() {
|
||||
log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType)
|
||||
} else {
|
||||
@ -230,7 +228,7 @@ func runDump(ctx *cli.Context) error {
|
||||
fatal("Failed to include specified app.ini: %v", err)
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-custom-dir") && ctx.Bool("skip-custom-dir") {
|
||||
if cmd.IsSet("skip-custom-dir") && cmd.Bool("skip-custom-dir") {
|
||||
log.Info("Skipping custom directory")
|
||||
} else {
|
||||
customDir, err := os.Stat(setting.CustomPath)
|
||||
@ -263,7 +261,7 @@ func runDump(ctx *cli.Context) error {
|
||||
excludes = append(excludes, opts.ProviderConfig)
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-index") && ctx.Bool("skip-index") {
|
||||
if cmd.IsSet("skip-index") && cmd.Bool("skip-index") {
|
||||
excludes = append(excludes, setting.Indexer.RepoPath)
|
||||
excludes = append(excludes, setting.Indexer.IssuePath)
|
||||
}
|
||||
@ -278,7 +276,7 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
|
||||
if cmd.IsSet("skip-attachment-data") && cmd.Bool("skip-attachment-data") {
|
||||
log.Info("Skip dumping attachment data")
|
||||
} else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error {
|
||||
info, err := object.Stat()
|
||||
@ -290,7 +288,7 @@ func runDump(ctx *cli.Context) error {
|
||||
fatal("Failed to dump attachments: %v", err)
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") {
|
||||
if cmd.IsSet("skip-package-data") && cmd.Bool("skip-package-data") {
|
||||
log.Info("Skip dumping package data")
|
||||
} else if !setting.Packages.Enabled {
|
||||
log.Info("Packages isn't enabled. Skip dumping package data")
|
||||
@ -307,7 +305,7 @@ func runDump(ctx *cli.Context) error {
|
||||
// Doesn't check if LogRootPath exists before processing --skip-log intentionally,
|
||||
// ensuring that it's clear the dump is skipped whether the directory's initialized
|
||||
// yet or not.
|
||||
if ctx.IsSet("skip-log") && ctx.Bool("skip-log") {
|
||||
if cmd.IsSet("skip-log") && cmd.Bool("skip-log") {
|
||||
log.Info("Skip dumping log files")
|
||||
} else {
|
||||
isExist, err := util.IsExist(setting.Log.RootPath)
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
"code.gitea.io/gitea/services/migrations"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdDumpRepository represents the available dump repository sub-command.
|
||||
@ -79,11 +79,13 @@ wiki, issues, labels, releases, release_assets, milestones, pull_requests, comme
|
||||
},
|
||||
}
|
||||
|
||||
func runDumpRepository(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
func runDumpRepository(ctx context.Context, cmd *cli.Command) error {
|
||||
setupConsoleLogger(log.INFO, log.CanColorStderr, os.Stderr)
|
||||
|
||||
if err := initDB(stdCtx); err != nil {
|
||||
setting.DisableLoggerInit()
|
||||
setting.LoadSettings() // cannot access skip_tls_verify settings otherwise
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -100,8 +102,8 @@ func runDumpRepository(ctx *cli.Context) error {
|
||||
|
||||
var (
|
||||
serviceType structs.GitServiceType
|
||||
cloneAddr = ctx.String("clone_addr")
|
||||
serviceStr = ctx.String("git_service")
|
||||
cloneAddr = cmd.String("clone_addr")
|
||||
serviceStr = cmd.String("git_service")
|
||||
)
|
||||
|
||||
if strings.HasPrefix(strings.ToLower(cloneAddr), "https://github.com/") {
|
||||
@ -119,13 +121,13 @@ func runDumpRepository(ctx *cli.Context) error {
|
||||
opts := base.MigrateOptions{
|
||||
GitServiceType: serviceType,
|
||||
CloneAddr: cloneAddr,
|
||||
AuthUsername: ctx.String("auth_username"),
|
||||
AuthPassword: ctx.String("auth_password"),
|
||||
AuthToken: ctx.String("auth_token"),
|
||||
RepoName: ctx.String("repo_name"),
|
||||
AuthUsername: cmd.String("auth_username"),
|
||||
AuthPassword: cmd.String("auth_password"),
|
||||
AuthToken: cmd.String("auth_token"),
|
||||
RepoName: cmd.String("repo_name"),
|
||||
}
|
||||
|
||||
if len(ctx.String("units")) == 0 {
|
||||
if len(cmd.String("units")) == 0 {
|
||||
opts.Wiki = true
|
||||
opts.Issues = true
|
||||
opts.Milestones = true
|
||||
@ -135,8 +137,8 @@ func runDumpRepository(ctx *cli.Context) error {
|
||||
opts.PullRequests = true
|
||||
opts.ReleaseAssets = true
|
||||
} else {
|
||||
units := strings.Split(ctx.String("units"), ",")
|
||||
for _, unit := range units {
|
||||
units := strings.SplitSeq(cmd.String("units"), ",")
|
||||
for unit := range units {
|
||||
switch strings.ToLower(strings.TrimSpace(unit)) {
|
||||
case "":
|
||||
continue
|
||||
@ -164,7 +166,7 @@ func runDumpRepository(ctx *cli.Context) error {
|
||||
|
||||
// the repo_dir will be removed if error occurs in DumpRepository
|
||||
// make sure the directory doesn't exist or is empty, prevent from deleting user files
|
||||
repoDir := ctx.String("repo_dir")
|
||||
repoDir := cmd.String("repo_dir")
|
||||
if exists, err := util.IsExist(repoDir); err != nil {
|
||||
return fmt.Errorf("unable to stat repo_dir %q: %w", repoDir, err)
|
||||
} else if exists {
|
||||
@ -179,7 +181,7 @@ func runDumpRepository(ctx *cli.Context) error {
|
||||
if err := migrations.DumpRepository(
|
||||
context.Background(),
|
||||
repoDir,
|
||||
ctx.String("owner_name"),
|
||||
cmd.String("owner_name"),
|
||||
opts,
|
||||
); err != nil {
|
||||
log.Fatal("Failed to dump repository: %v", err)
|
||||
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -19,7 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdEmbedded represents the available extract sub-command.
|
||||
@ -28,7 +29,7 @@ var (
|
||||
Name: "embedded",
|
||||
Usage: "Extract embedded resources",
|
||||
Description: "A command for extracting embedded resources, like templates and images",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdList,
|
||||
subcmdView,
|
||||
subcmdExtract,
|
||||
@ -100,7 +101,7 @@ type assetFile struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func initEmbeddedExtractor(c *cli.Context) error {
|
||||
func initEmbeddedExtractor(c *cli.Command) error {
|
||||
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr)
|
||||
|
||||
patterns, err := compileCollectPatterns(c.Args().Slice())
|
||||
@ -115,31 +116,31 @@ func initEmbeddedExtractor(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runList(c *cli.Context) 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
|
||||
}
|
||||
|
||||
func runView(c *cli.Context) 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
|
||||
}
|
||||
|
||||
func runExtract(c *cli.Context) 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
|
||||
}
|
||||
|
||||
func runListDo(c *cli.Context) error {
|
||||
func runListDo(c *cli.Command) error {
|
||||
if err := initEmbeddedExtractor(c); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -151,7 +152,7 @@ func runListDo(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runViewDo(c *cli.Context) error {
|
||||
func runViewDo(c *cli.Command) error {
|
||||
if err := initEmbeddedExtractor(c); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -174,7 +175,7 @@ func runViewDo(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runExtractDo(c *cli.Context) error {
|
||||
func runExtractDo(c *cli.Command) error {
|
||||
if err := initEmbeddedExtractor(c); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -216,7 +217,7 @@ func runExtractDo(c *cli.Context) 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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +272,7 @@ func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectAssetFilesByPattern(c *cli.Context, globs []glob.Glob, path string, layer *assetfs.Layer) {
|
||||
func collectAssetFilesByPattern(c *cli.Command, globs []glob.Glob, path string, layer *assetfs.Layer) {
|
||||
fs := assetfs.Layered(layer)
|
||||
files, err := fs.ListAllFiles(".", true)
|
||||
if err != nil {
|
||||
@ -294,16 +295,14 @@ func collectAssetFilesByPattern(c *cli.Context, globs []glob.Glob, path string,
|
||||
}
|
||||
}
|
||||
|
||||
func compileCollectPatterns(args []string) ([]glob.Glob, error) {
|
||||
func compileCollectPatterns(args []string) (_ []glob.Glob, err error) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"**"}
|
||||
}
|
||||
pat := make([]glob.Glob, len(args))
|
||||
for i := range args {
|
||||
if g, err := glob.Compile(args[i], '/'); err != nil {
|
||||
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
|
||||
} else { //nolint:revive
|
||||
pat[i] = g
|
||||
if pat[i], err = glob.Compile(args[i], '/'); err != nil {
|
||||
return nil, fmt.Errorf("invalid glob patterh %q: %w", args[i], err)
|
||||
}
|
||||
}
|
||||
return pat, nil
|
||||
|
@ -5,13 +5,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -19,7 +20,7 @@ var (
|
||||
CmdGenerate = &cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "Generate Gitea's secrets/keys/tokens",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdSecret,
|
||||
},
|
||||
}
|
||||
@ -27,7 +28,7 @@ var (
|
||||
subcmdSecret = &cli.Command{
|
||||
Name: "secret",
|
||||
Usage: "Generate a secret token",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
microcmdGenerateInternalToken,
|
||||
microcmdGenerateLfsJwtSecret,
|
||||
microcmdGenerateSecretKey,
|
||||
@ -54,7 +55,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runGenerateInternalToken(c *cli.Context) error {
|
||||
func runGenerateInternalToken(_ context.Context, c *cli.Command) error {
|
||||
internalToken, err := generate.NewInternalToken()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -69,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
func runGenerateLfsJwtSecret(_ context.Context, c *cli.Command) error {
|
||||
_, jwtSecretBase64, err := generate.NewJwtSecretWithBase64()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -84,7 +85,7 @@ func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGenerateSecretKey(c *cli.Context) error {
|
||||
func runGenerateSecretKey(_ context.Context, c *cli.Command) error {
|
||||
secretKey, err := generate.NewSecretKey()
|
||||
if err != nil {
|
||||
return err
|
||||
|
29
cmd/hook.go
29
cmd/hook.go
@ -20,11 +20,11 @@ import (
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
hookBatchSize = 30
|
||||
hookBatchSize = 500
|
||||
)
|
||||
|
||||
var (
|
||||
@ -32,9 +32,10 @@ var (
|
||||
CmdHook = &cli.Command{
|
||||
Name: "hook",
|
||||
Usage: "(internal) Should only be called by Git",
|
||||
Hidden: true, // internal commands shouldn't be visible
|
||||
Description: "Delegate commands to corresponding Git hooks",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdHookPreReceive,
|
||||
subcmdHookUpdate,
|
||||
subcmdHookPostReceive,
|
||||
@ -161,12 +162,10 @@ func (n *nilWriter) WriteString(s string) (int, error) {
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
func runHookPreReceive(c *cli.Context) error {
|
||||
func runHookPreReceive(ctx context.Context, c *cli.Command) error {
|
||||
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
|
||||
return nil
|
||||
}
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
@ -292,7 +291,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
// runHookUpdate avoid to do heavy operations on update hook because it will be
|
||||
// invoked for every ref update which does not like pre-receive and post-receive
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
func runHookUpdate(_ context.Context, c *cli.Command) error {
|
||||
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
|
||||
return nil
|
||||
}
|
||||
@ -309,15 +308,12 @@ func runHookUpdate(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHookPostReceive(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runHookPostReceive(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
// First of all run update-server-info no matter what
|
||||
if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
|
||||
return fmt.Errorf("Failed to call 'git update-server-info': %w", err)
|
||||
return fmt.Errorf("failed to call 'git update-server-info': %w", err)
|
||||
}
|
||||
|
||||
// Now if we're an internal don't do anything else
|
||||
@ -485,7 +481,7 @@ func hookPrintResult(output, isCreate bool, branch, url string) {
|
||||
func pushOptions() map[string]string {
|
||||
opts := make(map[string]string)
|
||||
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
|
||||
for idx := 0; idx < pushCount; idx++ {
|
||||
for idx := range pushCount {
|
||||
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
|
||||
kv := strings.SplitN(opt, "=", 2)
|
||||
if len(kv) == 2 {
|
||||
@ -496,10 +492,7 @@ func pushOptions() map[string]string {
|
||||
return opts
|
||||
}
|
||||
|
||||
func runHookProcReceive(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runHookProcReceive(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
@ -740,7 +733,7 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
||||
|
||||
// read prefix
|
||||
lengthBytes := make([]byte, 4)
|
||||
for i := 0; i < 4; i++ {
|
||||
for i := range 4 {
|
||||
lengthBytes[i], err = in.ReadByte()
|
||||
if err != nil {
|
||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
||||
|
11
cmd/keys.go
11
cmd/keys.go
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
@ -11,13 +12,14 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdKeys represents the available keys sub-command
|
||||
var CmdKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "(internal) Should only be called by SSH server",
|
||||
Hidden: true, // internal commands shouldn't not be visible
|
||||
Description: "Queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runKeys,
|
||||
@ -49,7 +51,7 @@ var CmdKeys = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func runKeys(c *cli.Context) error {
|
||||
func runKeys(ctx context.Context, c *cli.Command) error {
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("No username provided")
|
||||
}
|
||||
@ -68,9 +70,6 @@ func runKeys(c *cli.Context) error {
|
||||
return errors.New("No key type and content provided")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||
@ -78,6 +77,6 @@ func runKeys(c *cli.Context) error {
|
||||
if extra.Error != nil {
|
||||
return extra.Error
|
||||
}
|
||||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString.Text))
|
||||
_, _ = fmt.Fprintln(c.Root().Writer, strings.TrimSpace(authorizedString.Text))
|
||||
return nil
|
||||
}
|
||||
|
@ -4,24 +4,18 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func runSendMail(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runSendMail(ctx context.Context, c *cli.Command) error {
|
||||
setting.MustInstalled()
|
||||
|
||||
if err := argsSet(c, "title"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subject := c.String("title")
|
||||
confirmSkiped := c.Bool("force")
|
||||
body := c.String("content")
|
||||
|
183
cmd/main.go
183
cmd/main.go
@ -4,36 +4,40 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// cmdHelp is our own help subcommand with more information
|
||||
// Keep in mind that the "./gitea help"(subcommand) is different from "./gitea --help"(flag), the flag doesn't parse the config or output "DEFAULT CONFIGURATION:" information
|
||||
func cmdHelp() *cli.Command {
|
||||
c := &cli.Command{
|
||||
Name: "help",
|
||||
Aliases: []string{"h"},
|
||||
Usage: "Shows a list of commands or help for one command",
|
||||
ArgsUsage: "[command]",
|
||||
Action: func(c *cli.Context) (err error) {
|
||||
lineage := c.Lineage() // The order is from child to parent: help, doctor, Gitea, {Command:nil}
|
||||
targetCmdIdx := 0
|
||||
if c.Command.Name == "help" {
|
||||
targetCmdIdx = 1
|
||||
}
|
||||
if lineage[targetCmdIdx+1].Command != nil {
|
||||
err = cli.ShowCommandHelp(lineage[targetCmdIdx+1], lineage[targetCmdIdx].Command.Name)
|
||||
} else {
|
||||
err = cli.ShowAppHelp(c)
|
||||
}
|
||||
_, _ = fmt.Fprintf(c.App.Writer, `
|
||||
var cliHelpPrinterOld = cli.HelpPrinter
|
||||
|
||||
func init() {
|
||||
cli.HelpPrinter = cliHelpPrinterNew
|
||||
}
|
||||
|
||||
// cliHelpPrinterNew helps to print "DEFAULT CONFIGURATION" for the following cases ( "-c" can apper in any position):
|
||||
// * ./gitea -c /dev/null -h
|
||||
// * ./gitea -c help /dev/null help
|
||||
// * ./gitea help -c /dev/null
|
||||
// * ./gitea help -c /dev/null web
|
||||
// * ./gitea help web -c /dev/null
|
||||
// * ./gitea web help -c /dev/null
|
||||
// * ./gitea web -h -c /dev/null
|
||||
func cliHelpPrinterNew(out io.Writer, templ string, data any) {
|
||||
cmd, _ := data.(*cli.Command)
|
||||
if cmd != nil {
|
||||
prepareWorkPathAndCustomConf(cmd)
|
||||
}
|
||||
cliHelpPrinterOld(out, templ, data)
|
||||
if setting.CustomConf != "" {
|
||||
_, _ = fmt.Fprintf(out, `
|
||||
DEFAULT CONFIGURATION:
|
||||
AppPath: %s
|
||||
WorkPath: %s
|
||||
@ -41,94 +45,71 @@ DEFAULT CONFIGURATION:
|
||||
ConfigFile: %s
|
||||
|
||||
`, setting.AppPath, setting.AppWorkPath, setting.CustomPath, setting.CustomConf)
|
||||
return err
|
||||
},
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func appGlobalFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
// make the builtin flags at the top
|
||||
cli.HelpFlag,
|
||||
|
||||
// shared configuration flags, they are for global and for each sub-command at the same time
|
||||
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
|
||||
// keep in mind that the short flags like "-C", "-c" and "-w" are globally polluted, they can't be used for sub-commands anymore.
|
||||
&cli.StringFlag{
|
||||
Name: "custom-path",
|
||||
Aliases: []string{"C"},
|
||||
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "work-path",
|
||||
Aliases: []string{"w"},
|
||||
Usage: "Set Gitea's working path (defaults to the Gitea's binary directory)",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func prepareSubcommandWithConfig(command *cli.Command, globalFlags []cli.Flag) {
|
||||
command.Flags = append(append([]cli.Flag{}, globalFlags...), command.Flags...)
|
||||
command.Action = prepareWorkPathAndCustomConf(command.Action)
|
||||
command.HideHelp = true
|
||||
if command.Name != "help" {
|
||||
command.Subcommands = append(command.Subcommands, cmdHelp())
|
||||
}
|
||||
for i := range command.Subcommands {
|
||||
prepareSubcommandWithConfig(command.Subcommands[i], globalFlags)
|
||||
}
|
||||
}
|
||||
|
||||
// prepareWorkPathAndCustomConf wraps the Action to prepare the work path and custom config
|
||||
// It can't use "Before", because each level's sub-command's Before will be called one by one, so the "init" would be done multiple times
|
||||
func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context) error {
|
||||
return func(ctx *cli.Context) error {
|
||||
var args setting.ArgWorkPathAndCustomConf
|
||||
// from children to parent, check the global flags
|
||||
for _, curCtx := range ctx.Lineage() {
|
||||
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
||||
args.WorkPath = curCtx.String("work-path")
|
||||
}
|
||||
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
||||
args.CustomPath = curCtx.String("custom-path")
|
||||
}
|
||||
if curCtx.IsSet("config") && args.CustomConf == "" {
|
||||
args.CustomConf = curCtx.String("config")
|
||||
}
|
||||
func prepareSubcommandWithGlobalFlags(originCmd *cli.Command) {
|
||||
originBefore := originCmd.Before
|
||||
originCmd.Before = func(ctx context.Context, cmd *cli.Command) (context.Context, error) {
|
||||
prepareWorkPathAndCustomConf(cmd)
|
||||
if originBefore != nil {
|
||||
return originBefore(ctx, cmd)
|
||||
}
|
||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||
if ctx.Bool("help") || action == nil {
|
||||
// the default behavior of "urfave/cli": "nil action" means "show help"
|
||||
return cmdHelp().Action(ctx)
|
||||
}
|
||||
return action(ctx)
|
||||
return ctx, nil
|
||||
}
|
||||
}
|
||||
|
||||
// prepareWorkPathAndCustomConf tries to prepare the work path, custom path and custom config from various inputs:
|
||||
// command line flags, environment variables, config file
|
||||
func prepareWorkPathAndCustomConf(cmd *cli.Command) {
|
||||
var args setting.ArgWorkPathAndCustomConf
|
||||
if cmd.IsSet("work-path") {
|
||||
args.WorkPath = cmd.String("work-path")
|
||||
}
|
||||
if cmd.IsSet("custom-path") {
|
||||
args.CustomPath = cmd.String("custom-path")
|
||||
}
|
||||
if cmd.IsSet("config") {
|
||||
args.CustomConf = cmd.String("config")
|
||||
}
|
||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||
}
|
||||
|
||||
type AppVersion struct {
|
||||
Version string
|
||||
Extra string
|
||||
}
|
||||
|
||||
func NewMainApp(appVer AppVersion) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = "Gitea"
|
||||
app.HelpName = "gitea"
|
||||
func NewMainApp(appVer AppVersion) *cli.Command {
|
||||
app := &cli.Command{}
|
||||
app.Name = "gitea" // must be lower-cased because it appears in the "USAGE" section like "gitea doctor [command [command options]]"
|
||||
app.Usage = "A painless self-hosted Git service"
|
||||
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
|
||||
app.Version = appVer.Version + appVer.Extra
|
||||
app.EnableBashCompletion = true
|
||||
|
||||
// these sub-commands need to use config file
|
||||
app.EnableShellCompletion = true
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "work-path",
|
||||
Aliases: []string{"w"},
|
||||
TakesFile: true,
|
||||
Usage: "Set Gitea's working path (defaults to the Gitea's binary directory)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
TakesFile: true,
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-path",
|
||||
Aliases: []string{"C"},
|
||||
TakesFile: true,
|
||||
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
||||
},
|
||||
}
|
||||
// these sub-commands need to use a config file
|
||||
subCmdWithConfig := []*cli.Command{
|
||||
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
||||
CmdWeb,
|
||||
CmdServ,
|
||||
CmdHook,
|
||||
@ -147,20 +128,18 @@ func NewMainApp(appVer AppVersion) *cli.App {
|
||||
|
||||
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||
subCmdStandalone := []*cli.Command{
|
||||
CmdCert,
|
||||
cmdCert(),
|
||||
CmdGenerate,
|
||||
CmdDocs,
|
||||
}
|
||||
|
||||
// TODO: we should eventually drop the default command,
|
||||
// but not sure whether it would break Windows users who used to double-click the EXE to run.
|
||||
app.DefaultCommand = CmdWeb.Name
|
||||
|
||||
globalFlags := appGlobalFlags()
|
||||
app.Flags = append(app.Flags, cli.VersionFlag)
|
||||
app.Flags = append(app.Flags, globalFlags...)
|
||||
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
||||
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
||||
for i := range subCmdWithConfig {
|
||||
prepareSubcommandWithConfig(subCmdWithConfig[i], globalFlags)
|
||||
prepareSubcommandWithGlobalFlags(subCmdWithConfig[i])
|
||||
}
|
||||
app.Commands = append(app.Commands, subCmdWithConfig...)
|
||||
app.Commands = append(app.Commands, subCmdStandalone...)
|
||||
@ -169,8 +148,10 @@ func NewMainApp(appVer AppVersion) *cli.App {
|
||||
return app
|
||||
}
|
||||
|
||||
func RunMainApp(app *cli.App, args ...string) error {
|
||||
err := app.Run(args)
|
||||
func RunMainApp(app *cli.Command, args ...string) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
err := app.Run(ctx, args)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -16,7 +17,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@ -27,10 +28,10 @@ func makePathOutput(workPath, customPath, customConf string) string {
|
||||
return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
|
||||
}
|
||||
|
||||
func newTestApp(testCmdAction func(ctx *cli.Context) error) *cli.App {
|
||||
func newTestApp(testCmdAction cli.ActionFunc) *cli.Command {
|
||||
app := NewMainApp(AppVersion{})
|
||||
testCmd := &cli.Command{Name: "test-cmd", Action: testCmdAction}
|
||||
prepareSubcommandWithConfig(testCmd, appGlobalFlags())
|
||||
prepareSubcommandWithGlobalFlags(testCmd)
|
||||
app.Commands = append(app.Commands, testCmd)
|
||||
app.DefaultCommand = testCmd.Name
|
||||
return app
|
||||
@ -42,7 +43,7 @@ type runResult struct {
|
||||
ExitCode int
|
||||
}
|
||||
|
||||
func runTestApp(app *cli.App, args ...string) (runResult, error) {
|
||||
func runTestApp(app *cli.Command, args ...string) (runResult, error) {
|
||||
outBuf := new(strings.Builder)
|
||||
errBuf := new(strings.Builder)
|
||||
app.Writer = outBuf
|
||||
@ -65,7 +66,7 @@ func TestCliCmd(t *testing.T) {
|
||||
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
|
||||
|
||||
cli.CommandHelpTemplate = "(command help template)"
|
||||
cli.AppHelpTemplate = "(app help template)"
|
||||
cli.RootCommandHelpTemplate = "(app help template)"
|
||||
cli.SubcommandHelpTemplate = "(subcommand help template)"
|
||||
|
||||
cases := []struct {
|
||||
@ -73,12 +74,56 @@ func TestCliCmd(t *testing.T) {
|
||||
cmd string
|
||||
exp string
|
||||
}{
|
||||
// main command help
|
||||
// help commands
|
||||
{
|
||||
cmd: "./gitea -h",
|
||||
exp: "DEFAULT CONFIGURATION:",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea help",
|
||||
exp: "DEFAULT CONFIGURATION:",
|
||||
},
|
||||
|
||||
{
|
||||
cmd: "./gitea -c /dev/null -h",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
|
||||
{
|
||||
cmd: "./gitea -c /dev/null help",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea help -c /dev/null",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
|
||||
{
|
||||
cmd: "./gitea -c /dev/null test-cmd -h",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea test-cmd -c /dev/null -h",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea test-cmd -h -c /dev/null",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
|
||||
{
|
||||
cmd: "./gitea -c /dev/null test-cmd help",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea test-cmd -c /dev/null help",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
{
|
||||
cmd: "./gitea test-cmd help -c /dev/null",
|
||||
exp: "ConfigFile: /dev/null",
|
||||
},
|
||||
|
||||
// parse paths
|
||||
{
|
||||
cmd: "./gitea test-cmd",
|
||||
@ -109,12 +154,12 @@ func TestCliCmd(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
app := newTestApp(func(ctx *cli.Context) error {
|
||||
_, _ = fmt.Fprint(ctx.App.Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
||||
return nil
|
||||
})
|
||||
for _, c := range cases {
|
||||
t.Run(c.cmd, func(t *testing.T) {
|
||||
app := newTestApp(func(ctx context.Context, cmd *cli.Command) error {
|
||||
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
||||
return nil
|
||||
})
|
||||
for k, v := range c.env {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
@ -128,28 +173,28 @@ func TestCliCmd(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCliCmdError(t *testing.T) {
|
||||
app := newTestApp(func(ctx *cli.Context) error { return errors.New("normal error") })
|
||||
app := newTestApp(func(ctx context.Context, cmd *cli.Command) error { return errors.New("normal error") })
|
||||
r, err := runTestApp(app, "./gitea", "test-cmd")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, 1, r.ExitCode)
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
||||
app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return cli.Exit("exit error", 2) })
|
||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, 2, r.ExitCode)
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Equal(t, "exit error\n", r.Stderr)
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||
app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return nil })
|
||||
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, 1, r.ExitCode)
|
||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
||||
assert.Empty(t, r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
||||
assert.Empty(t, r.Stdout)
|
||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stderr)
|
||||
|
||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||
app = newTestApp(func(ctx context.Context, cmd *cli.Command) error { return nil })
|
||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
||||
|
@ -4,12 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -18,7 +19,7 @@ var (
|
||||
Name: "manager",
|
||||
Usage: "Manage the running gitea process",
|
||||
Description: "This is a command for managing the running gitea process",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
subcmdShutdown,
|
||||
subcmdRestart,
|
||||
subcmdReloadTemplates,
|
||||
@ -108,46 +109,31 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runShutdown(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runShutdown(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Shutdown(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runRestart(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRestart(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Restart(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runReloadTemplates(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runReloadTemplates(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.ReloadTemplates(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runFlushQueues(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runFlushQueues(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runProcesses(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runProcesses(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
||||
return handleCliResponseExtra(extra)
|
||||
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -11,7 +12,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -60,7 +61,7 @@ var (
|
||||
subcmdLogging = &cli.Command{
|
||||
Name: "logging",
|
||||
Usage: "Adjust logging commands",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "pause",
|
||||
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
|
||||
@ -104,7 +105,7 @@ var (
|
||||
}, {
|
||||
Name: "add",
|
||||
Usage: "Add a logger",
|
||||
Subcommands: []*cli.Command{
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "file",
|
||||
Usage: "Add a file logger",
|
||||
@ -118,7 +119,6 @@ var (
|
||||
Name: "rotate",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "Rotate logs",
|
||||
Value: true,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "max-size",
|
||||
@ -129,7 +129,6 @@ var (
|
||||
Name: "daily",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Rotate logs daily",
|
||||
Value: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "max-days",
|
||||
@ -140,7 +139,6 @@ var (
|
||||
Name: "compress",
|
||||
Aliases: []string{"z"},
|
||||
Usage: "Compress rotated logs",
|
||||
Value: true,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "compression-level",
|
||||
@ -195,10 +193,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func runRemoveLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRemoveLogger(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
logger := c.String("logger")
|
||||
if len(logger) == 0 {
|
||||
@ -210,10 +205,7 @@ func runRemoveLogger(c *cli.Context) error {
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runAddConnLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runAddConnLogger(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]any{}
|
||||
mode := "conn"
|
||||
@ -237,13 +229,10 @@ func runAddConnLogger(c *cli.Context) error {
|
||||
if c.IsSet("reconnect-on-message") {
|
||||
vals["reconnectOnMsg"] = c.Bool("reconnect-on-message")
|
||||
}
|
||||
return commonAddLogger(c, mode, vals)
|
||||
return commonAddLogger(ctx, c, mode, vals)
|
||||
}
|
||||
|
||||
func runAddFileLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runAddFileLogger(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]any{}
|
||||
mode := "file"
|
||||
@ -270,10 +259,10 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
if c.IsSet("compression-level") {
|
||||
vals["compressionLevel"] = c.Int("compression-level")
|
||||
}
|
||||
return commonAddLogger(c, mode, vals)
|
||||
return commonAddLogger(ctx, c, mode, vals)
|
||||
}
|
||||
|
||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||
func commonAddLogger(ctx context.Context, c *cli.Command, mode string, vals map[string]any) error {
|
||||
if len(c.String("level")) > 0 {
|
||||
vals["level"] = log.LevelFromString(c.String("level")).String()
|
||||
}
|
||||
@ -300,46 +289,33 @@ func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||
if c.IsSet("writer") {
|
||||
writer = c.String("writer")
|
||||
}
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
extra := private.AddLogger(ctx, logger, writer, mode, vals)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
|
||||
func runPauseLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runPauseLogging(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.PauseLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runResumeLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runResumeLogging(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.ResumeLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runReleaseReopenLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runReleaseReopenLogging(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.ReleaseReopenLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSetLogSQL(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
func runSetLogSQL(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
extra := private.SetLogSQL(ctx, !c.Bool("off"))
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/versioned_migration"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdMigrate represents the available migrate sub-command.
|
||||
@ -22,11 +22,8 @@ var CmdMigrate = &cli.Command{
|
||||
Action: runMigrate,
|
||||
}
|
||||
|
||||
func runMigrate(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(stdCtx); err != nil {
|
||||
func runMigrate(ctx context.Context, c *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
"code.gitea.io/gitea/services/versioned_migration"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdMigrateStorage represents the available migrate storage sub-command.
|
||||
@ -213,11 +213,8 @@ func migrateActionsArtifacts(ctx context.Context, dstStorage storage.ObjectStora
|
||||
})
|
||||
}
|
||||
|
||||
func runMigrateStorage(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(stdCtx); err != nil {
|
||||
func runMigrateStorage(ctx context.Context, cmd *cli.Command) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -238,51 +235,51 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
|
||||
var dstStorage storage.ObjectStorage
|
||||
var err error
|
||||
switch strings.ToLower(ctx.String("storage")) {
|
||||
switch strings.ToLower(cmd.String("storage")) {
|
||||
case "":
|
||||
fallthrough
|
||||
case string(setting.LocalStorageType):
|
||||
p := ctx.String("path")
|
||||
p := cmd.String("path")
|
||||
if p == "" {
|
||||
log.Fatal("Path must be given when storage is local")
|
||||
return nil
|
||||
}
|
||||
dstStorage, err = storage.NewLocalStorage(
|
||||
stdCtx,
|
||||
ctx,
|
||||
&setting.Storage{
|
||||
Path: p,
|
||||
})
|
||||
case string(setting.MinioStorageType):
|
||||
dstStorage, err = storage.NewMinioStorage(
|
||||
stdCtx,
|
||||
ctx,
|
||||
&setting.Storage{
|
||||
MinioConfig: setting.MinioStorageConfig{
|
||||
Endpoint: ctx.String("minio-endpoint"),
|
||||
AccessKeyID: ctx.String("minio-access-key-id"),
|
||||
SecretAccessKey: ctx.String("minio-secret-access-key"),
|
||||
Bucket: ctx.String("minio-bucket"),
|
||||
Location: ctx.String("minio-location"),
|
||||
BasePath: ctx.String("minio-base-path"),
|
||||
UseSSL: ctx.Bool("minio-use-ssl"),
|
||||
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
|
||||
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
|
||||
BucketLookUpType: ctx.String("minio-bucket-lookup-type"),
|
||||
Endpoint: cmd.String("minio-endpoint"),
|
||||
AccessKeyID: cmd.String("minio-access-key-id"),
|
||||
SecretAccessKey: cmd.String("minio-secret-access-key"),
|
||||
Bucket: cmd.String("minio-bucket"),
|
||||
Location: cmd.String("minio-location"),
|
||||
BasePath: cmd.String("minio-base-path"),
|
||||
UseSSL: cmd.Bool("minio-use-ssl"),
|
||||
InsecureSkipVerify: cmd.Bool("minio-insecure-skip-verify"),
|
||||
ChecksumAlgorithm: cmd.String("minio-checksum-algorithm"),
|
||||
BucketLookUpType: cmd.String("minio-bucket-lookup-type"),
|
||||
},
|
||||
})
|
||||
case string(setting.AzureBlobStorageType):
|
||||
dstStorage, err = storage.NewAzureBlobStorage(
|
||||
stdCtx,
|
||||
ctx,
|
||||
&setting.Storage{
|
||||
AzureBlobConfig: setting.AzureBlobStorageConfig{
|
||||
Endpoint: ctx.String("azureblob-endpoint"),
|
||||
AccountName: ctx.String("azureblob-account-name"),
|
||||
AccountKey: ctx.String("azureblob-account-key"),
|
||||
Container: ctx.String("azureblob-container"),
|
||||
BasePath: ctx.String("azureblob-base-path"),
|
||||
Endpoint: cmd.String("azureblob-endpoint"),
|
||||
AccountName: cmd.String("azureblob-account-name"),
|
||||
AccountKey: cmd.String("azureblob-account-key"),
|
||||
Container: cmd.String("azureblob-container"),
|
||||
BasePath: cmd.String("azureblob-base-path"),
|
||||
},
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))
|
||||
return fmt.Errorf("unsupported storage type: %s", cmd.String("storage"))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@ -299,14 +296,14 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
"actions-artifacts": migrateActionsArtifacts,
|
||||
}
|
||||
|
||||
tp := strings.ToLower(ctx.String("type"))
|
||||
tp := strings.ToLower(cmd.String("type"))
|
||||
if m, ok := migratedMethods[tp]; ok {
|
||||
if err := m(stdCtx, dstStorage); err != nil {
|
||||
if err := m(ctx, dstStorage); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("%s files have successfully been copied to the new storage.", tp)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("unsupported storage: %s", ctx.String("type"))
|
||||
return fmt.Errorf("unsupported storage: %s", cmd.String("type"))
|
||||
}
|
||||
|
@ -4,12 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdRestoreRepository represents the available restore a repository sub-command.
|
||||
@ -48,10 +49,7 @@ wiki, issues, labels, releases, release_assets, milestones, pull_requests, comme
|
||||
},
|
||||
}
|
||||
|
||||
func runRestoreRepository(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runRestoreRepository(ctx context.Context, c *cli.Command) error {
|
||||
setting.MustInstalled()
|
||||
var units []string
|
||||
if s := c.String("units"); s != "" {
|
||||
|
99
cmd/serv.go
99
cmd/serv.go
@ -11,7 +11,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -20,7 +19,7 @@ import (
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/lfstransfer"
|
||||
@ -34,15 +33,7 @@ import (
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/kballard/go-shellquote"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
verbUploadPack = "git-upload-pack"
|
||||
verbUploadArchive = "git-upload-archive"
|
||||
verbReceivePack = "git-receive-pack"
|
||||
verbLfsAuthenticate = "git-lfs-authenticate"
|
||||
verbLfsTransfer = "git-lfs-transfer"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// CmdServ represents the available serv sub-command.
|
||||
@ -50,6 +41,7 @@ var CmdServ = &cli.Command{
|
||||
Name: "serv",
|
||||
Usage: "(internal) Should only be called by SSH shell",
|
||||
Description: "Serv provides access auth for repositories",
|
||||
Hidden: true, // Internal commands shouldn't be visible in help
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runServ,
|
||||
Flags: []cli.Flag{
|
||||
@ -78,22 +70,6 @@ func setup(ctx context.Context, debug bool) {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// keep getAccessMode() in sync
|
||||
allowedCommands = container.SetOf(
|
||||
verbUploadPack,
|
||||
verbUploadArchive,
|
||||
verbReceivePack,
|
||||
verbLfsAuthenticate,
|
||||
verbLfsTransfer,
|
||||
)
|
||||
allowedCommandsLfs = container.SetOf(
|
||||
verbLfsAuthenticate,
|
||||
verbLfsTransfer,
|
||||
)
|
||||
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
|
||||
)
|
||||
|
||||
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
||||
// The output will be passed to git client and shown to user.
|
||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error {
|
||||
@ -139,19 +115,20 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
|
||||
|
||||
func getAccessMode(verb, lfsVerb string) perm.AccessMode {
|
||||
switch verb {
|
||||
case verbUploadPack, verbUploadArchive:
|
||||
case git.CmdVerbUploadPack, git.CmdVerbUploadArchive:
|
||||
return perm.AccessModeRead
|
||||
case verbReceivePack:
|
||||
case git.CmdVerbReceivePack:
|
||||
return perm.AccessModeWrite
|
||||
case verbLfsAuthenticate, verbLfsTransfer:
|
||||
case git.CmdVerbLfsAuthenticate, git.CmdVerbLfsTransfer:
|
||||
switch lfsVerb {
|
||||
case "upload":
|
||||
case git.CmdSubVerbLfsUpload:
|
||||
return perm.AccessModeWrite
|
||||
case "download":
|
||||
case git.CmdSubVerbLfsDownload:
|
||||
return perm.AccessModeRead
|
||||
}
|
||||
}
|
||||
// should be unreachable
|
||||
setting.PanicInDevOrTesting("unknown verb: %s %s", verb, lfsVerb)
|
||||
return perm.AccessModeNone
|
||||
}
|
||||
|
||||
@ -176,10 +153,7 @@ func getLFSAuthToken(ctx context.Context, lfsVerb string, results *private.ServC
|
||||
return "Bearer " + tokenString, nil
|
||||
}
|
||||
|
||||
func runServ(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runServ(ctx context.Context, c *cli.Command) error {
|
||||
// FIXME: This needs to internationalised
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
@ -230,41 +204,37 @@ func runServ(c *cli.Context) error {
|
||||
log.Debug("SSH_ORIGINAL_COMMAND: %s", os.Getenv("SSH_ORIGINAL_COMMAND"))
|
||||
}
|
||||
|
||||
words, err := shellquote.Split(cmd)
|
||||
sshCmdArgs, err := shellquote.Split(cmd)
|
||||
if err != nil {
|
||||
return fail(ctx, "Error parsing arguments", "Failed to parse arguments: %v", err)
|
||||
}
|
||||
|
||||
if len(words) < 2 {
|
||||
if len(sshCmdArgs) < 2 {
|
||||
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
|
||||
}
|
||||
}
|
||||
return fail(ctx, "Too few arguments", "Too few arguments in cmd: %s", cmd)
|
||||
}
|
||||
|
||||
verb := words[0]
|
||||
repoPath := strings.TrimPrefix(words[1], "/")
|
||||
|
||||
var lfsVerb string
|
||||
|
||||
rr := strings.SplitN(repoPath, "/", 2)
|
||||
if len(rr) != 2 {
|
||||
repoPath := strings.TrimPrefix(sshCmdArgs[1], "/")
|
||||
repoPathFields := strings.SplitN(repoPath, "/", 2)
|
||||
if len(repoPathFields) != 2 {
|
||||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||
}
|
||||
|
||||
username := rr[0]
|
||||
reponame := strings.TrimSuffix(rr[1], ".git")
|
||||
username := repoPathFields[0]
|
||||
reponame := strings.TrimSuffix(repoPathFields[1], ".git") // “the-repo-name" or "the-repo-name.wiki"
|
||||
|
||||
// LowerCase and trim the repoPath as that's how they are stored.
|
||||
// This should be done after splitting the repoPath into username and reponame
|
||||
// so that username and reponame are not affected.
|
||||
repoPath = strings.ToLower(strings.TrimSpace(repoPath))
|
||||
|
||||
if alphaDashDotPattern.MatchString(reponame) {
|
||||
if !repo.IsValidSSHAccessRepoName(reponame) {
|
||||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
||||
}
|
||||
|
||||
@ -286,22 +256,23 @@ func runServ(c *cli.Context) error {
|
||||
}()
|
||||
}
|
||||
|
||||
if allowedCommands.Contains(verb) {
|
||||
if allowedCommandsLfs.Contains(verb) {
|
||||
if !setting.LFS.StartServer {
|
||||
return fail(ctx, "LFS Server is not enabled", "")
|
||||
}
|
||||
if verb == verbLfsTransfer && !setting.LFS.AllowPureSSH {
|
||||
return fail(ctx, "LFS SSH transfer is not enabled", "")
|
||||
}
|
||||
if len(words) > 2 {
|
||||
lfsVerb = words[2]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
verb, lfsVerb := sshCmdArgs[0], ""
|
||||
if !git.IsAllowedVerbForServe(verb) {
|
||||
return fail(ctx, "Unknown git command", "Unknown git command %s", verb)
|
||||
}
|
||||
|
||||
if git.IsAllowedVerbForServeLfs(verb) {
|
||||
if !setting.LFS.StartServer {
|
||||
return fail(ctx, "LFS Server is not enabled", "")
|
||||
}
|
||||
if verb == git.CmdVerbLfsTransfer && !setting.LFS.AllowPureSSH {
|
||||
return fail(ctx, "LFS SSH transfer is not enabled", "")
|
||||
}
|
||||
if len(sshCmdArgs) > 2 {
|
||||
lfsVerb = sshCmdArgs[2]
|
||||
}
|
||||
}
|
||||
|
||||
requestedMode := getAccessMode(verb, lfsVerb)
|
||||
|
||||
results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
|
||||
@ -310,7 +281,7 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// LFS SSH protocol
|
||||
if verb == verbLfsTransfer {
|
||||
if verb == git.CmdVerbLfsTransfer {
|
||||
token, err := getLFSAuthToken(ctx, lfsVerb, results)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -319,7 +290,7 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// LFS token authentication
|
||||
if verb == verbLfsAuthenticate {
|
||||
if verb == git.CmdVerbLfsAuthenticate {
|
||||
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
|
||||
|
||||
token, err := getLFSAuthToken(ctx, lfsVerb, results)
|
||||
|
32
cmd/web.go
32
cmd/web.go
@ -28,7 +28,7 @@ import (
|
||||
"code.gitea.io/gitea/routers/install"
|
||||
|
||||
"github.com/felixge/fgprof"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// PIDFile could be set from build tag
|
||||
@ -130,19 +130,19 @@ func showWebStartupMessage(msg string) {
|
||||
}
|
||||
}
|
||||
|
||||
func serveInstall(ctx *cli.Context) error {
|
||||
func serveInstall(cmd *cli.Command) error {
|
||||
showWebStartupMessage("Prepare to run install page")
|
||||
|
||||
routers.InitWebInstallPage(graceful.GetManager().HammerContext())
|
||||
|
||||
// Flag for port number in case first time run conflict
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
if cmd.IsSet("port") {
|
||||
if err := setPort(cmd.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ctx.IsSet("install-port") {
|
||||
if err := setPort(ctx.String("install-port")); err != nil {
|
||||
if cmd.IsSet("install-port") {
|
||||
if err := setPort(cmd.String("install-port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ func serveInstall(ctx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func serveInstalled(ctx *cli.Context) error {
|
||||
func serveInstalled(c *cli.Command) error {
|
||||
setting.InitCfgProvider(setting.CustomConf)
|
||||
setting.LoadCommonSettings()
|
||||
setting.MustInstalled()
|
||||
@ -218,8 +218,8 @@ func serveInstalled(ctx *cli.Context) error {
|
||||
setting.AppDataTempDir("").RemoveOutdated(3 * 24 * time.Hour)
|
||||
|
||||
// Override the provided port number within the configuration
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
if c.IsSet("port") {
|
||||
if err := setPort(c.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -244,13 +244,17 @@ func servePprof() {
|
||||
finished()
|
||||
}
|
||||
|
||||
func runWeb(ctx *cli.Context) error {
|
||||
func runWeb(_ context.Context, cmd *cli.Command) error {
|
||||
defer func() {
|
||||
if panicked := recover(); panicked != nil {
|
||||
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
||||
}
|
||||
}()
|
||||
|
||||
if subCmdName, valid := isValidDefaultSubCommand(cmd); !valid {
|
||||
return fmt.Errorf("unknown command: %s", subCmdName)
|
||||
}
|
||||
|
||||
managerCtx, cancel := context.WithCancel(context.Background())
|
||||
graceful.InitManager(managerCtx)
|
||||
defer cancel()
|
||||
@ -262,12 +266,12 @@ func runWeb(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
// Set pid file setting
|
||||
if ctx.IsSet("pid") {
|
||||
createPIDFile(ctx.String("pid"))
|
||||
if cmd.IsSet("pid") {
|
||||
createPIDFile(cmd.String("pid"))
|
||||
}
|
||||
|
||||
if !setting.InstallLock {
|
||||
if err := serveInstall(ctx); err != nil {
|
||||
if err := serveInstall(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@ -278,7 +282,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
go servePprof()
|
||||
}
|
||||
|
||||
return serveInstalled(ctx)
|
||||
return serveInstalled(cmd)
|
||||
}
|
||||
|
||||
func setPort(port string) error {
|
||||
|
@ -23,12 +23,6 @@ func NoHTTPRedirector() {
|
||||
graceful.GetManager().InformCleanup()
|
||||
}
|
||||
|
||||
// NoMainListener tells our cleanup routine that we will not be using a possibly provided listener
|
||||
// for our main HTTP/HTTPS service
|
||||
func NoMainListener() {
|
||||
graceful.GetManager().InformCleanup()
|
||||
}
|
||||
|
||||
// NoInstallListener tells our cleanup routine that we will not be using a possibly provided listener
|
||||
// for our install HTTP/HTTPS service
|
||||
func NoInstallListener() {
|
||||
|
@ -1,17 +0,0 @@
|
||||
Bash and Zsh completion
|
||||
=======================
|
||||
|
||||
From within the gitea root run:
|
||||
|
||||
```bash
|
||||
source contrib/autocompletion/bash_autocomplete
|
||||
```
|
||||
|
||||
or for zsh run:
|
||||
|
||||
```bash
|
||||
source contrib/autocompletion/zsh_autocomplete
|
||||
```
|
||||
|
||||
These scripts will check if gitea is on the path and if so add autocompletion for `gitea`. Or if not autocompletion will work for `./gitea`.
|
||||
If gitea has been installed as a different program pass in the `PROG` environment variable to set the correct program name.
|
@ -1,30 +0,0 @@
|
||||
#! /bin/bash
|
||||
# Heavily inspired by https://github.com/urfave/cli
|
||||
|
||||
_cli_bash_autocomplete() {
|
||||
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
|
||||
local cur opts base
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
if [[ "$cur" == "-"* ]]; then
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
|
||||
else
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||
fi
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -z "$PROG" ] && [ ! "$(command -v gitea &> /dev/null)" ] ; then
|
||||
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete gitea
|
||||
elif [ -z "$PROG" ]; then
|
||||
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete ./gitea
|
||||
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete "$PWD/gitea"
|
||||
else
|
||||
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete "$PROG"
|
||||
unset PROG
|
||||
fi
|
||||
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
#compdef ${PROG:=gitea}
|
||||
|
||||
|
||||
# Heavily inspired by https://github.com/urfave/cli
|
||||
|
||||
_cli_zsh_autocomplete() {
|
||||
|
||||
local -a opts
|
||||
local cur
|
||||
cur=${words[-1]}
|
||||
if [[ "$cur" == "-"* ]]; then
|
||||
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
|
||||
else
|
||||
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}")
|
||||
fi
|
||||
|
||||
if [[ "${opts[1]}" != "" ]]; then
|
||||
_describe 'values' opts
|
||||
else
|
||||
_files
|
||||
fi
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if [ -z $PROG ] ; then
|
||||
compdef _cli_zsh_autocomplete gitea
|
||||
else
|
||||
compdef _cli_zsh_autocomplete $(basename $PROG)
|
||||
fi
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//nolint:forbidigo
|
||||
//nolint:forbidigo // use of print functions is allowed in cli
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -12,21 +12,19 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/go-github/v61/github"
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/google/go-github/v71/github"
|
||||
"github.com/urfave/cli/v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const defaultVersion = "v1.18" // to backport to
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app := &cli.Command{}
|
||||
app.Name = "backport"
|
||||
app.Usage = "Backport provided PR-number on to the current or previous released version"
|
||||
app.Description = `Backport will look-up the PR in Gitea's git log and attempt to cherry-pick it on the current version`
|
||||
@ -91,7 +89,7 @@ func main() {
|
||||
Usage: "Set this flag to continue from a git cherry-pick that has broken",
|
||||
},
|
||||
}
|
||||
cli.AppHelpTemplate = `NAME:
|
||||
cli.RootCommandHelpTemplate = `NAME:
|
||||
{{.Name}} - {{.Usage}}
|
||||
USAGE:
|
||||
{{.HelpName}} {{if .VisibleFlags}}[options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||
@ -105,16 +103,12 @@ OPTIONS:
|
||||
`
|
||||
|
||||
app.Action = runBackport
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
if err := app.Run(context.Background(), os.Args); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to backport: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runBackport(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
func runBackport(ctx context.Context, c *cli.Command) error {
|
||||
continuing := c.Bool("continue")
|
||||
|
||||
var pr string
|
||||
@ -343,8 +337,8 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
|
||||
fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out))
|
||||
return "", "", fmt.Errorf("unable to determine forked remote: %w", err)
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
for _, line := range lines {
|
||||
lines := strings.SplitSeq(string(out), "\n")
|
||||
for line := range lines {
|
||||
fields := strings.Split(line, "\t")
|
||||
name, remote := fields[0], fields[1]
|
||||
// only look at pushers
|
||||
@ -362,12 +356,12 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
|
||||
if !strings.Contains(remote, forkUser) {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(remote, "git@github.com:") {
|
||||
forkUser = strings.TrimPrefix(remote, "git@github.com:")
|
||||
} else if strings.HasPrefix(remote, "https://github.com/") {
|
||||
forkUser = strings.TrimPrefix(remote, "https://github.com/")
|
||||
} else if strings.HasPrefix(remote, "https://www.github.com/") {
|
||||
forkUser = strings.TrimPrefix(remote, "https://www.github.com/")
|
||||
if after, ok := strings.CutPrefix(remote, "git@github.com:"); ok {
|
||||
forkUser = after
|
||||
} else if after, ok := strings.CutPrefix(remote, "https://github.com/"); ok {
|
||||
forkUser = after
|
||||
} else if after, ok := strings.CutPrefix(remote, "https://www.github.com/"); ok {
|
||||
forkUser = after
|
||||
} else if forkUser == "" {
|
||||
return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote)
|
||||
}
|
||||
@ -460,25 +454,3 @@ func determineSHAforPR(ctx context.Context, prStr, accessToken string) (string,
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func installSignals() (context.Context, context.CancelFunc) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
// install notify
|
||||
signalChannel := make(chan os.Signal, 1)
|
||||
|
||||
signal.Notify(
|
||||
signalChannel,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
)
|
||||
select {
|
||||
case <-signalChannel:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
cancel()
|
||||
signal.Reset()
|
||||
}()
|
||||
|
||||
return ctx, cancel
|
||||
}
|
||||
|
@ -4,16 +4,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app := cli.Command{}
|
||||
app.Name = "environment-to-ini"
|
||||
app.Usage = "Use provided environment to update configuration ini"
|
||||
app.Description = `As a helper to allow docker users to update the gitea configuration
|
||||
@ -72,13 +73,13 @@ func main() {
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
err := app.Run(os.Args)
|
||||
err := app.Run(context.Background(), os.Args)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
||||
}
|
||||
}
|
||||
|
||||
func runEnvironmentToIni(c *cli.Context) error {
|
||||
func runEnvironmentToIni(_ context.Context, c *cli.Command) error {
|
||||
// the config system may change the environment variables, so get a copy first, to be used later
|
||||
env := append([]string{}, os.Environ()...)
|
||||
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
||||
|
@ -63,14 +63,19 @@ RUN_USER = ; git
|
||||
;PROTOCOL = http
|
||||
;;
|
||||
;; Set the domain for the server.
|
||||
;; Most users should set it to the real website domain of their Gitea instance.
|
||||
;DOMAIN = localhost
|
||||
;;
|
||||
;; The AppURL used by Gitea to generate absolute links, defaults to "{PROTOCOL}://{DOMAIN}:{HTTP_PORT}/".
|
||||
;; The AppURL is used to generate public URL links, defaults to "{PROTOCOL}://{DOMAIN}:{HTTP_PORT}/".
|
||||
;; Most users should set it to the real website URL of their Gitea instance when there is a reverse proxy.
|
||||
;; When it is empty, Gitea will use HTTP "Host" header to generate ROOT_URL, and fall back to the default one if no "Host" header.
|
||||
;ROOT_URL =
|
||||
;;
|
||||
;; Controls how to detect the public URL.
|
||||
;; Although it defaults to "legacy" (to avoid breaking existing users), most instances should use the "auto" behavior,
|
||||
;; especially when the Gitea instance needs to be accessed in a container network.
|
||||
;; * legacy: detect the public URL from "Host" header if "X-Forwarded-Proto" header exists, otherwise use "ROOT_URL".
|
||||
;; * auto: always use "Host" header, and also use "X-Forwarded-Proto" header if it exists. If no "Host" header, use "ROOT_URL".
|
||||
;PUBLIC_URL_DETECTION = legacy
|
||||
;;
|
||||
;; For development purpose only. It makes Gitea handle sub-path ("/sub-path/owner/repo/...") directly when debugging without a reverse proxy.
|
||||
;; DO NOT USE IT IN PRODUCTION!!!
|
||||
;USE_SUB_URL_PATH = false
|
||||
@ -181,17 +186,13 @@ RUN_USER = ; git
|
||||
;; If you intend to use the AuthorizedPrincipalsCommand functionality then you should turn this off.
|
||||
;SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = true
|
||||
;;
|
||||
;; For the built-in SSH server, choose the ciphers to support for SSH connections,
|
||||
;; for system SSH this setting has no effect
|
||||
;SSH_SERVER_CIPHERS = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com
|
||||
;;
|
||||
;; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
||||
;; for system SSH this setting has no effect
|
||||
;SSH_SERVER_KEY_EXCHANGES = curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
|
||||
;;
|
||||
;; For the built-in SSH server, choose the MACs to support for SSH connections,
|
||||
;; for system SSH this setting has no effect
|
||||
;SSH_SERVER_MACS = hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1
|
||||
;; For the builtin SSH server, choose the supported ciphers/key-exchange-algorithms/MACs for SSH connections.
|
||||
;; The supported names are listed in https://github.com/golang/crypto/blob/master/ssh/common.go.
|
||||
;; Leave them empty to use the Golang crypto's recommended default values.
|
||||
;; For system SSH (non-builtin SSH server), this setting has no effect.
|
||||
;SSH_SERVER_CIPHERS =
|
||||
;SSH_SERVER_KEY_EXCHANGES =
|
||||
;SSH_SERVER_MACS =
|
||||
;;
|
||||
;; For the built-in SSH server, choose the keypair to offer as the host key
|
||||
;; The private key should be at SSH_SERVER_HOST_KEY and the public SSH_SERVER_HOST_KEY.pub
|
||||
@ -519,6 +520,10 @@ INTERNAL_TOKEN =
|
||||
;;
|
||||
;; On user registration, record the IP address and user agent of the user to help identify potential abuse.
|
||||
;; RECORD_USER_SIGNUP_METADATA = false
|
||||
;;
|
||||
;; Set the two-factor auth behavior.
|
||||
;; Set to "enforced", to force users to enroll into Two-Factor Authentication, users without 2FA have no access to repositories via API or web.
|
||||
;TWO_FACTOR_AUTH =
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@ -1150,6 +1155,10 @@ LEVEL = Info
|
||||
;;
|
||||
;; Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo.
|
||||
;RETARGET_CHILDREN_ON_MERGE = true
|
||||
;;
|
||||
;; Delay mergeable check until page view or API access, for pull requests that have not been updated in the specified days when their base branches get updated.
|
||||
;; Use "-1" to always check all pull requests (old behavior). Use "0" to always delay the checks.
|
||||
;DELAY_CHECK_FOR_INACTIVE_DAYS = 7
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@ -1177,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
|
||||
@ -1214,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 =
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@ -2439,6 +2462,8 @@ LEVEL = Info
|
||||
;DEFAULT_GIT_TREES_PER_PAGE = 1000
|
||||
;; Default max size of a blob returned by the blobs API (default is 10MiB)
|
||||
;DEFAULT_MAX_BLOB_SIZE = 10485760
|
||||
;; Default max combined size of all blobs returned by the files API (default is 100MiB)
|
||||
;DEFAULT_MAX_RESPONSE_SIZE = 104857600
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1739214665,
|
||||
"narHash": "sha256-26L8VAu3/1YRxS8MHgBOyOM8xALdo6N0I04PgorE7UM=",
|
||||
"lastModified": 1747179050,
|
||||
"narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "64e75cd44acf21c7933d61d7721e812eac1b5a0a",
|
||||
"rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
178
go.mod
178
go.mod
@ -1,6 +1,6 @@
|
||||
module code.gitea.io/gitea
|
||||
|
||||
go 1.24
|
||||
go 1.24.5
|
||||
|
||||
// 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:
|
||||
@ -10,7 +10,7 @@ godebug x509negativeserial=1
|
||||
require (
|
||||
code.gitea.io/actions-proto-go v0.4.1
|
||||
code.gitea.io/gitea-vet v0.2.3
|
||||
code.gitea.io/sdk/gitea v0.20.0
|
||||
code.gitea.io/sdk/gitea v0.21.0
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.18.1
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
||||
@ -21,20 +21,20 @@ require (
|
||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||
github.com/42wim/httpsig v1.2.2
|
||||
github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||
github.com/ProtonMail/go-crypto v1.1.6
|
||||
github.com/PuerkitoBio/goquery v1.10.2
|
||||
github.com/ProtonMail/go-crypto v1.2.0
|
||||
github.com/PuerkitoBio/goquery v1.10.3
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3
|
||||
github.com/alecthomas/chroma/v2 v2.15.0
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.62
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.1
|
||||
github.com/alecthomas/chroma/v2 v2.17.0
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.2
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.4.2
|
||||
github.com/blevesearch/bleve/v2 v2.5.0
|
||||
github.com/bohde/codel v0.2.0
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
||||
github.com/caddyserver/certmagic v0.22.0
|
||||
github.com/caddyserver/certmagic v0.23.0
|
||||
github.com/charmbracelet/git-lfs-transfer v0.2.0
|
||||
github.com/chi-middleware/proxy v1.1.1
|
||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
||||
@ -47,28 +47,27 @@ require (
|
||||
github.com/emirpasic/gods v1.18.1
|
||||
github.com/ethantkoenig/rupture v1.0.1
|
||||
github.com/felixge/fgprof v0.9.5
|
||||
github.com/fsnotify/fsnotify v1.8.0
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/gliderlabs/ssh v0.3.8
|
||||
github.com/go-ap/activitypub v0.0.0-20250212090640-aeb6499ba581
|
||||
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
github.com/go-chi/chi/v5 v5.2.2
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-enry/go-enry/v2 v2.9.2
|
||||
github.com/go-git/go-billy/v5 v5.6.2
|
||||
github.com/go-git/go-git/v5 v5.14.0
|
||||
github.com/go-ldap/ldap/v3 v3.4.10
|
||||
github.com/go-git/go-git/v5 v5.16.0
|
||||
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.1
|
||||
github.com/go-swagger/go-swagger v0.31.0
|
||||
github.com/go-webauthn/webauthn v0.12.2
|
||||
github.com/go-sql-driver/mysql v1.9.2
|
||||
github.com/go-webauthn/webauthn v0.12.3
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/google/go-github/v61 v61.0.0
|
||||
github.com/google/go-github/v71 v71.0.0
|
||||
github.com/google/licenseclassifier/v2 v2.0.0
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.2.0
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
@ -82,52 +81,51 @@ require (
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/klauspost/cpuid/v2 v2.2.10
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/markbates/goth v1.80.0
|
||||
github.com/markbates/goth v1.81.0
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/meilisearch/meilisearch-go v0.31.0
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/microsoft/go-mssqldb v1.8.0
|
||||
github.com/minio/minio-go/v7 v7.0.88
|
||||
github.com/minio/minio-go/v7 v7.0.91
|
||||
github.com/msteinert/pam v1.2.0
|
||||
github.com/nektos/act v0.2.63
|
||||
github.com/niklasfasching/go-org v1.7.0
|
||||
github.com/niklasfasching/go-org v1.8.0
|
||||
github.com/olivere/elastic/v7 v7.0.32
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/prometheus/client_golang v1.21.1
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/quasoft/websspi v1.1.2
|
||||
github.com/redis/go-redis/v9 v9.7.3
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
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
|
||||
github.com/ulikunitz/xz v0.5.12
|
||||
github.com/urfave/cli/v2 v2.27.6
|
||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
|
||||
github.com/urfave/cli/v3 v3.3.3
|
||||
github.com/wneessen/go-mail v0.6.2
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
github.com/yuin/goldmark v1.7.10
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/image v0.25.0
|
||||
golang.org/x/net v0.38.0
|
||||
golang.org/x/oauth2 v0.28.0
|
||||
golang.org/x/sync v0.12.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/text v0.23.0
|
||||
golang.org/x/tools v0.31.0
|
||||
google.golang.org/grpc v1.71.0
|
||||
google.golang.org/protobuf v1.36.5
|
||||
gitlab.com/gitlab-org/api/client-go v0.127.0
|
||||
golang.org/x/crypto v0.39.0
|
||||
golang.org/x/image v0.26.0
|
||||
golang.org/x/net v0.40.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sync v0.15.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/text v0.26.0
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
mvdan.cc/xurls/v2 v2.6.0
|
||||
@ -141,17 +139,13 @@ require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/DataDog/zstd v1.5.6 // 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/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/DataDog/zstd v1.5.7 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.9.4 // 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
|
||||
@ -159,34 +153,34 @@ require (
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
|
||||
github.com/blevesearch/geo v0.1.20 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.20 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
|
||||
github.com/blevesearch/geo v0.2.0 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
github.com/blevesearch/vellum v1.0.10 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.1.5 // indirect
|
||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||
github.com/blevesearch/zapx/v11 v11.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v12 v12.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.4.1 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.2.3 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.2 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
||||
github.com/couchbase/gomemcached v0.3.3 // indirect
|
||||
github.com/couchbase/goutils v0.1.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
@ -194,33 +188,19 @@ 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.7.0 // 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-20250124135319-3da8adefd4a9 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||
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.19 // indirect
|
||||
github.com/go-webauthn/x v0.1.20 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/geo v0.0.0-20250321002858-2bb09a976f49 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // 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,59 +216,41 @@ 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 v0.2.3 // 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
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/mholt/acmez/v3 v3.1.0 // indirect
|
||||
github.com/miekg/dns v1.1.64 // indirect
|
||||
github.com/mholt/acmez/v3 v3.1.2 // indirect
|
||||
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.3 // 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
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.0 // indirect
|
||||
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.8.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.0 // 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
|
||||
@ -297,28 +258,25 @@ require (
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
github.com/zeebo/assert v1.3.0 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
go.etcd.io/bbolt v1.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
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // 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
|
||||
)
|
||||
|
||||
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.4
|
||||
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
|
||||
replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0
|
||||
@ -326,6 +284,8 @@ replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-tra
|
||||
// TODO: This could be removed after https://github.com/mholt/archiver/pull/396 merged
|
||||
replace github.com/mholt/archiver/v3 => github.com/anchore/archiver/v3 v3.5.2
|
||||
|
||||
replace git.sr.ht/~mariusor/go-xsd-duration => gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078
|
||||
|
||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
||||
|
||||
exclude github.com/gofrs/uuid v4.0.0+incompatible
|
||||
|
362
go.sum
362
go.sum
@ -4,8 +4,8 @@ code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLr
|
||||
code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
code.gitea.io/sdk/gitea v0.20.0 h1:Zm/QDwwZK1awoM4AxdjeAQbxolzx2rIP8dDfmKu+KoU=
|
||||
code.gitea.io/sdk/gitea v0.20.0/go.mod h1:faouBHC/zyx5wLgjmRKR62ydyvMzwWf3QnU0bH7Cw6U=
|
||||
code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
|
||||
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
|
||||
@ -14,12 +14,12 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||
gitea.com/gitea/act v0.261.4 h1:Tf9eLlvsYFtKcpuxlMvf9yT3g4Hshb2Beqw6C1STuH8=
|
||||
gitea.com/gitea/act v0.261.4/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
||||
gitea.com/gitea/act v0.261.6 h1:CjZwKOyejonNFDmsXOw3wGm5Vet573hHM6VMLsxtvPY=
|
||||
gitea.com/gitea/act v0.261.6/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
||||
gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
|
||||
gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
|
||||
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:BAFmdZpRW7zMQZQDClaCWobRj9uL1MR3MzpCVJvc5s4=
|
||||
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
|
||||
gitea.com/go-chi/cache v0.2.1 h1:bfAPkvXlbcZxPCpcmDVCWoHgiBSBmZN/QosnZvEC0+g=
|
||||
@ -40,12 +40,12 @@ github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815 h1:5EoemV++kUK2Sw98yW
|
||||
github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815/go.mod h1:zjsWZdDLrcDojDIfpQg7A6J4YZLT0cbwuAD26AppDBo=
|
||||
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U=
|
||||
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 h1:DSDNVxqkoXJiko6x8a90zidoYqnYYa6c1MTzDKzKkTo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1/go.mod h1:zGqV2R4Cr/k8Uye5w+dgQ06WJtEcbQG/8J7BB6hnCr4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw=
|
||||
@ -56,36 +56,30 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 h1:UXT0o77lXQrikd1kg
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY=
|
||||
github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
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=
|
||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/PuerkitoBio/goquery v1.10.2 h1:7fh2BdHcG6VFZsK7toXBT/Bh1z5Wmy8Q9MV9HqT2AM8=
|
||||
github.com/PuerkitoBio/goquery v1.10.2/go.mod h1:0guWGjcLu9AYC7C1GHnpysHy056u9aEkUHwhdnePMCU=
|
||||
github.com/ProtonMail/go-crypto v1.2.0 h1:+PhXXn4SPGd+qk76TlEePBfOfivE0zkWFenhGhFLzWs=
|
||||
github.com/ProtonMail/go-crypto v1.2.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
|
||||
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
|
||||
github.com/RoaringBitmap/roaring v1.9.4 h1:yhEIoH4YezLYT04s1nHehNO64EKFTop/wBhxv2QzDdQ=
|
||||
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3 h1:BP0HiyNT3AQEYi+if3wkRcIdQFHtsw6xX3Kx0glckgA=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2gdDuLqnqveP+mfhUSaBdoBcr2I7Zt0E=
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc=
|
||||
github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio=
|
||||
github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI=
|
||||
github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
@ -103,18 +97,16 @@ 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.62 h1:fvtQY3zFzYJ9CfixuAQ96IxDrBajbBWGqjNTCa79ocU=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.62/go.mod h1:ElETBxIQqcxej++Cs8GyPBbgMys5DgQPTwo7cUPDKt8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.1 h1:NNOxK3fdcLeE+meE7Ry4TwEzBL2Yh4HVnC63Nlj/NYg=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.1/go.mod h1:JsdLne5QNlqJdCQFm2DbHLNmNfEWSU7HnTuvi8SIl+E=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.2 h1:enL75gIdaPAoBztv/GDuMgOocEUpO2jYc45qp2Uweqs=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.2/go.mod h1:JsdLne5QNlqJdCQFm2DbHLNmNfEWSU7HnTuvi8SIl+E=
|
||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
@ -129,15 +121,15 @@ github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/blevesearch/bleve/v2 v2.0.5/go.mod h1:ZjWibgnbRX33c+vBRgla9QhPb4QOjD6fdVJ+R1Bk8LM=
|
||||
github.com/blevesearch/bleve/v2 v2.4.2 h1:NooYP1mb3c0StkiY9/xviiq2LGSaE8BQBCc/pirMx0U=
|
||||
github.com/blevesearch/bleve/v2 v2.4.2/go.mod h1:ATNKj7Yl2oJv/lGuF4kx39bST2dveX6w0th2FFYLkc8=
|
||||
github.com/blevesearch/bleve/v2 v2.5.0 h1:HzYqBy/5/M9Ul9ESEmXzN/3Jl7YpmWBdHM/+zzv/3k4=
|
||||
github.com/blevesearch/bleve/v2 v2.5.0/go.mod h1:PcJzTPnEynO15dCf9isxOga7YFRa/cMSsbnRwnszXUk=
|
||||
github.com/blevesearch/bleve_index_api v1.0.0/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||
github.com/blevesearch/go-faiss v1.0.20 h1:AIkdTQFWuZ5LQmKQSebgMR4RynGNw8ZseJXaan5kvtI=
|
||||
github.com/blevesearch/go-faiss v1.0.20/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
|
||||
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
|
||||
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||
github.com/blevesearch/geo v0.2.0 h1:f+IE3/C3mGeXDyhtMbWel6BgqBqaOUz43GtWg26GlB0=
|
||||
github.com/blevesearch/geo v0.2.0/go.mod h1:k8Hyfz12kM8QmeWLhgX7VMMCoVFmttBnr62V5zniXak=
|
||||
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
||||
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
@ -146,8 +138,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+
|
||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.0.1/go.mod h1:lq7yK2jQy1yQjtjTfU931aVqz7pYxEudHaDwOt1tXfU=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 h1:prV17iU/o+A8FiZi9MXmqbagd8I0bCqM7OKUYPbnb5Y=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15/go.mod h1:db0cmP03bPNadXrCDuVkKLV6ywFSiRgPFT1YVrestBc=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 h1:Yqk0XD1mE0fDZAJXTjawJ8If/85JxnLd8v5vG/jWE/s=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
@ -158,25 +150,25 @@ github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMG
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ=
|
||||
github.com/blevesearch/vellum v1.0.3/go.mod h1:2u5ax02KeDuNWu4/C+hVQMD6uLN4txH1JbtpaDNLJRo=
|
||||
github.com/blevesearch/vellum v1.0.4/go.mod h1:cMhywHI0de50f7Nj42YgvyD6bFJ2WkNRvNBlNMrEVgY=
|
||||
github.com/blevesearch/vellum v1.0.10 h1:HGPJDT2bTva12hrHepVT3rOyIKFFF4t7Gf6yMxyMIPI=
|
||||
github.com/blevesearch/vellum v1.0.10/go.mod h1:ul1oT0FhSMDIExNjIxHqJoGpVrBpKCdgDQNxfqgJt7k=
|
||||
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
||||
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
||||
github.com/blevesearch/zapx/v11 v11.2.0/go.mod h1:gN/a0alGw1FZt/YGTo1G6Z6XpDkeOfujX5exY9sCQQM=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10 h1:hvjgj9tZ9DeIqBCxKhi70TtSZYMdcFn7gDb71Xo/fvk=
|
||||
github.com/blevesearch/zapx/v11 v11.3.10/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ=
|
||||
github.com/blevesearch/zapx/v11 v11.4.1 h1:qFCPlFbsEdwbbckJkysptSQOsHn4s6ZOHL5GMAIAVHA=
|
||||
github.com/blevesearch/zapx/v11 v11.4.1/go.mod h1:qNOGxIqdPC1MXauJCD9HBG487PxviTUUbmChFOAosGs=
|
||||
github.com/blevesearch/zapx/v12 v12.2.0/go.mod h1:fdjwvCwWWwJW/EYTYGtAp3gBA0geCYGLcVTtJEZnY6A=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10 h1:yHfj3vXLSYmmsBleJFROXuO08mS3L1qDCdDK81jDl8s=
|
||||
github.com/blevesearch/zapx/v12 v12.3.10/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs=
|
||||
github.com/blevesearch/zapx/v12 v12.4.1 h1:K77bhypII60a4v8mwvav7r4IxWA8qxhNjgF9xGdb9eQ=
|
||||
github.com/blevesearch/zapx/v12 v12.4.1/go.mod h1:QRPrlPOzAxBNMI0MkgdD+xsTqx65zbuPr3Ko4Re49II=
|
||||
github.com/blevesearch/zapx/v13 v13.2.0/go.mod h1:o5rAy/lRS5JpAbITdrOHBS/TugWYbkcYZTz6VfEinAQ=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIqMGahDE8=
|
||||
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
|
||||
github.com/blevesearch/zapx/v13 v13.4.1 h1:EnkEMZFUK0lsW/jOJJF2xOcp+W8TjEsyeN5BeAZEYYE=
|
||||
github.com/blevesearch/zapx/v13 v13.4.1/go.mod h1:e6duBMlCvgbH9rkzNMnUa9hRI9F7ri2BRcHfphcmGn8=
|
||||
github.com/blevesearch/zapx/v14 v14.2.0/go.mod h1:GNgZusc1p4ot040cBQMRGEZobvwjCquiEKYh1xLFK9g=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
||||
github.com/blevesearch/zapx/v14 v14.4.1 h1:G47kGCshknBZzZAtjcnIAMn3oNx8XBLxp8DMq18ogyE=
|
||||
github.com/blevesearch/zapx/v14 v14.4.1/go.mod h1:O7sDxiaL2r2PnCXbhh1Bvm7b4sP+jp4unE9DDPWGoms=
|
||||
github.com/blevesearch/zapx/v15 v15.2.0/go.mod h1:MmQceLpWfME4n1WrBFIwplhWmaQbQqLQARpaKUEOs/A=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||
github.com/blevesearch/zapx/v16 v16.1.5 h1:b0sMcarqNFxuXvjoXsF8WtwVahnxyhEvBSRJi/AUHjU=
|
||||
github.com/blevesearch/zapx/v16 v16.1.5/go.mod h1:J4mSF39w1QELc11EWRSBFkPeZuO7r/NPKkHzDCoiaI8=
|
||||
github.com/blevesearch/zapx/v15 v15.4.1 h1:B5IoTMUCEzFdc9FSQbhVOxAY+BO17c05866fNruiI7g=
|
||||
github.com/blevesearch/zapx/v15 v15.4.1/go.mod h1:b/MreHjYeQoLjyY2+UaM0hGZZUajEbE0xhnr1A2/Q6Y=
|
||||
github.com/blevesearch/zapx/v16 v16.2.3 h1:7Y0r+a3diEvlazsncexq1qoFOcBd64xwMS7aDm4lo1s=
|
||||
github.com/blevesearch/zapx/v16 v16.2.3/go.mod h1:wVJ+GtURAaRG9KQAMNYyklq0egV+XJlGcXNCE0OFjjA=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
|
||||
@ -185,16 +177,16 @@ github.com/bohde/codel v0.2.0/go.mod h1:Idb1IRvTdwkRjIjguLIo+FXhIBhcpGl94o7xra6g
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
|
||||
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf h1:TqhNAT4zKbTdLa62d2HDBFdvgSbIGB3eJE8HqhgiL9I=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.8 h1:QN/daUob6cmK8GcdKnwn9+YTlPr1vNj+oeAIiJK6fPc=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.8/go.mod h1:+k1KVKROZocrTLsEQ9PEf9A+8+X8uaVV5iO1ZIOwKYM=
|
||||
github.com/caddyserver/certmagic v0.22.0 h1:hi2skv2jouUw9uQUEyYSTTmqPZPHgf61dOANSIVCLOw=
|
||||
github.com/caddyserver/certmagic v0.22.0/go.mod h1:Vc0msarAPhOagbDc/SU6M2zbzdwVuZ0lkTh2EqtH4vs=
|
||||
github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||
github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4=
|
||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
|
||||
@ -209,8 +201,8 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@ -223,8 +215,8 @@ github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9B
|
||||
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
|
||||
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
@ -274,35 +266,31 @@ 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.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-ap/activitypub v0.0.0-20250212090640-aeb6499ba581 h1:73sFEdBsWBTBut0aDMPgt8HRuMO+ML0fd8AA/zjO8BQ=
|
||||
github.com/go-ap/activitypub v0.0.0-20250212090640-aeb6499ba581/go.mod h1:IO2PtAsxfGXN5IHrPuOslENFbq7MprYLNOyiiOELoRQ=
|
||||
github.com/go-ap/errors v0.0.0-20250124135319-3da8adefd4a9 h1:AJBGzuJVgfkKF3LoXCNQfH9yWmsVDV/oPDJE/zeXOjE=
|
||||
github.com/go-ap/errors v0.0.0-20250124135319-3da8adefd4a9/go.mod h1:Vkh+Z3f24K8nMsJKXo1FHn5ebPsXvB/WDH5JRtYqdNo=
|
||||
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d h1:IWrWGnmKzpHqginJ18ljKkty/X8glxM8Mg3pk6bkb8g=
|
||||
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d/go.mod h1:EUtZuXtHo4yKkTJmcbAZYW+X1G2poeT8icmBh24eq7o=
|
||||
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 h1:tlwla5IQUea0CuktkBd2FLDwVzts4OeTWPPkhQPSK5Q=
|
||||
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650/go.mod h1:Vkh+Z3f24K8nMsJKXo1FHn5ebPsXvB/WDH5JRtYqdNo=
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw=
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||
@ -319,34 +307,12 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||
github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ=
|
||||
github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
||||
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.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
||||
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-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-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=
|
||||
@ -355,19 +321,15 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkvQ1EkZKA=
|
||||
github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ=
|
||||
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
|
||||
github.com/go-sql-driver/mysql v1.9.1/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-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-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.2 h1:yLaNPgBUEXDQtWnOjhsGhMMCEWbXwjg/aNkC8riJQI8=
|
||||
github.com/go-webauthn/webauthn v0.12.2/go.mod h1:Q8SZPPj4sZ469fNTcQXxRpzJOdb30jQrn/36FX8jilA=
|
||||
github.com/go-webauthn/x v0.1.19 h1:IUfdHiBRoTdujpBA/14qbrMXQ3LGzYe/PRGWdZcmudg=
|
||||
github.com/go-webauthn/x v0.1.19/go.mod h1:C5arLuTQ3pVHKPw89v7CDGnqAZSZJj+4Jnr40dsn7tk=
|
||||
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=
|
||||
github.com/go-webauthn/x v0.1.20/go.mod h1:n/gAc8ssZJGATM0qThE+W+vfgXiMedsWi3wf/C4lld0=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
@ -388,8 +350,6 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/geo v0.0.0-20250321002858-2bb09a976f49 h1:JJ32MDIC/hIQ/Fq8Ej9Hgh1s3D82FYNMt54WYViOI7Y=
|
||||
github.com/golang/geo v0.0.0-20250321002858-2bb09a976f49/go.mod h1:J+F9/3Ofc8ysEOY2/cNjxTMl2eB1gvPIywEHUplPgDA=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -422,8 +382,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go=
|
||||
github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY=
|
||||
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
|
||||
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
|
||||
@ -434,8 +394,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
||||
github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0gDxNpog0pyeA=
|
||||
github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto4NGCAc+ZSwbeThazEtM=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416 h1:1/qwHx8P72glDXdyCKesJ+/c40x71SY4q2avOxJ2iYQ=
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -448,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=
|
||||
@ -458,7 +416,6 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -472,7 +429,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
@ -501,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=
|
||||
@ -542,18 +496,16 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
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 v0.2.3 h1:ba30K4ObwMGB/QTmqUxf3H4/GmUrCAIkMWejeGl12v8=
|
||||
github.com/libdns/libdns v0.2.3/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/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/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=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE=
|
||||
github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o=
|
||||
github.com/markbates/goth v1.80.0 h1:NnvatczZDzOs1hn9Ug+dVYf2Viwwkp/ZDX5K+GLjan8=
|
||||
github.com/markbates/goth v1.80.0/go.mod h1:4/GYHo+W6NWisrMPZnq0Yr2Q70UntNLn7KXEFhrIdAY=
|
||||
github.com/markbates/goth v1.81.0 h1:XVcCkeGWokynPV7MXvgb8pd2s3r7DS40P7931w6kdnE=
|
||||
github.com/markbates/goth v1.81.0/go.mod h1:+6z31QyUms84EHmuBY7iuqYSxyoN3njIgg9iCF/lR1k=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
@ -563,32 +515,28 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/meilisearch/meilisearch-go v0.31.0 h1:yZRhY1qJqdH8h6GFZALGtkDLyj8f9v5aJpsNMyrUmnY=
|
||||
github.com/meilisearch/meilisearch-go v0.31.0/go.mod h1:aNtyuwurDg/ggxQIcKqWH6G9g2ptc8GyY7PLY4zMn/g=
|
||||
github.com/mholt/acmez/v3 v3.1.0 h1:RlOx2SSZ8dIAM5GfkMe8TdaxjjkiHTGorlMUt8GeMzg=
|
||||
github.com/mholt/acmez/v3 v3.1.0/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
github.com/microsoft/go-mssqldb v1.8.0 h1:7cyZ/AT7ycDsEoWPIXibd+aVKFtteUNhDGf3aobP+tw=
|
||||
github.com/microsoft/go-mssqldb v1.8.0/go.mod h1:6znkekS3T2vp0waiMhen4GPU1BiAsrP+iXHcE7a7rFo=
|
||||
github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
|
||||
github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/minio/crc64nvme v1.0.1 h1:DHQPrYPdqK7jQG/Ls5CTBZWeex/2FMS3G5XGkycuFrY=
|
||||
github.com/minio/crc64nvme v1.0.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.88 h1:v8MoIJjwYxOkehp+eiLIuvXk87P2raUtoU5klrAAshs=
|
||||
github.com/minio/minio-go/v7 v7.0.88/go.mod h1:33+O8h0tO7pCeCWwBVa07RhVVfB/3vS4kEX7rwYKmIg=
|
||||
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/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/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=
|
||||
@ -603,16 +551,14 @@ github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
||||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
|
||||
github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o=
|
||||
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
|
||||
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
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=
|
||||
@ -633,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.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
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=
|
||||
@ -651,14 +595,14 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
|
||||
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw=
|
||||
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
@ -678,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=
|
||||
@ -686,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.8.0 h1:mXaMVw7IqxNBxfv3LdWt9MDmcWDQ1fagDH918lOdVaQ=
|
||||
github.com/sagikazarmark/locafero v0.8.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=
|
||||
@ -696,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=
|
||||
@ -711,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.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
|
||||
github.com/spf13/viper v1.20.0/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=
|
||||
@ -749,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=
|
||||
@ -765,8 +688,10 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
|
||||
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6 h1:w/l/N0xw1rO/aHRIGXJ0lDwwYFOzilup1qGvIytP3BI=
|
||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6/go.mod h1:p7Z4lg8FSTrPB9GTaNyTrK3ygffHZcK3w0cU2VE+mzU=
|
||||
github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I=
|
||||
github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
|
||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
@ -786,8 +711,6 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
||||
@ -796,8 +719,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.10 h1:S+LrtBjRmqMac2UdtB6yyCEJm+UILZ2fefI4p7o0QpI=
|
||||
github.com/yuin/goldmark v1.7.10/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
|
||||
@ -808,13 +731,11 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0 h1:VV5TdkF6pMbEdFGvbR2CwEgJwg6qdg1u3bj5eD2tiWk=
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAjE7UeNatu2VWHRf4/LE=
|
||||
gitlab.com/gitlab-org/api/client-go v0.127.0 h1:8xnxcNKGF2gDazEoMs+hOZfOspSSw8D0vAoWhQk9U+U=
|
||||
gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAjE7UeNatu2VWHRf4/LE=
|
||||
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=
|
||||
@ -833,19 +754,18 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
|
||||
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@ -855,12 +775,11 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
@ -875,10 +794,10 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -892,8 +811,8 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -926,8 +845,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@ -939,8 +858,8 @@ golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@ -952,8 +871,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -966,24 +885,24 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -1005,6 +924,7 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
|
2
main.go
2
main.go
@ -21,7 +21,7 @@ import (
|
||||
_ "code.gitea.io/gitea/modules/markup/markdown"
|
||||
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
// these flags will be set by the build flags
|
||||
|
@ -30,6 +30,25 @@ const (
|
||||
ArtifactStatusDeleted // 6, ArtifactStatusDeleted is the status of an artifact that is deleted
|
||||
)
|
||||
|
||||
func (status ArtifactStatus) ToString() string {
|
||||
switch status {
|
||||
case ArtifactStatusUploadPending:
|
||||
return "upload is not yet completed"
|
||||
case ArtifactStatusUploadConfirmed:
|
||||
return "upload is completed"
|
||||
case ArtifactStatusUploadError:
|
||||
return "upload failed"
|
||||
case ArtifactStatusExpired:
|
||||
return "expired"
|
||||
case ArtifactStatusPendingDeletion:
|
||||
return "pending deletion"
|
||||
case ArtifactStatusDeleted:
|
||||
return "deleted"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(ActionArtifact))
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@ -165,12 +166,24 @@ func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, err
|
||||
return nil, fmt.Errorf("event %s is not a pull request event", run.Event)
|
||||
}
|
||||
|
||||
func (run *ActionRun) GetWorkflowRunEventPayload() (*api.WorkflowRunPayload, error) {
|
||||
if run.Event == webhook_module.HookEventWorkflowRun {
|
||||
var payload api.WorkflowRunPayload
|
||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &payload, nil
|
||||
}
|
||||
return nil, fmt.Errorf("event %s is not a workflow run event", run.Event)
|
||||
}
|
||||
|
||||
func (run *ActionRun) IsSchedule() bool {
|
||||
return run.ScheduleID > 0
|
||||
}
|
||||
|
||||
func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error {
|
||||
_, err := db.GetEngine(ctx).ID(repo.ID).
|
||||
NoAutoTime().
|
||||
SetExpr("num_action_runs",
|
||||
builder.Select("count(*)").From("action_run").
|
||||
Where(builder.Eq{"repo_id": repo.ID}),
|
||||
@ -342,13 +355,13 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func GetRunByID(ctx context.Context, id int64) (*ActionRun, error) {
|
||||
func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) {
|
||||
var run ActionRun
|
||||
has, err := db.GetEngine(ctx).Where("id=?", id).Get(&run)
|
||||
has, err := db.GetEngine(ctx).Where("id=? AND repo_id=?", runID, repoID).Get(&run)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, fmt.Errorf("run with id %d: %w", id, util.ErrNotExist)
|
||||
return nil, fmt.Errorf("run with id %d: %w", runID, util.ErrNotExist)
|
||||
}
|
||||
|
||||
return &run, nil
|
||||
@ -419,17 +432,10 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error {
|
||||
|
||||
if run.Status != 0 || slices.Contains(cols, "status") {
|
||||
if run.RepoID == 0 {
|
||||
run, err = GetRunByID(ctx, run.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setting.PanicInDevOrTesting("RepoID should not be 0")
|
||||
}
|
||||
if run.Repo == nil {
|
||||
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
run.Repo = repo
|
||||
if err = run.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil {
|
||||
return err
|
||||
|
@ -51,7 +51,7 @@ func (job *ActionRunJob) Duration() time.Duration {
|
||||
|
||||
func (job *ActionRunJob) LoadRun(ctx context.Context) error {
|
||||
if job.Run == nil {
|
||||
run, err := GetRunByID(ctx, job.RunID)
|
||||
run, err := GetRunByRepoAndID(ctx, job.RepoID, job.RunID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -142,7 +142,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
|
||||
{
|
||||
// Other goroutines may aggregate the status of the run and update it too.
|
||||
// So we need load the run and its jobs before updating the run.
|
||||
run, err := GetRunByID(ctx, job.RunID)
|
||||
run, err := GetRunByRepoAndID(ctx, job.RepoID, job.RunID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -185,10 +185,10 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
|
||||
return StatusSuccess
|
||||
case hasCancelled:
|
||||
return StatusCancelled
|
||||
case hasFailure:
|
||||
return StatusFailure
|
||||
case hasRunning:
|
||||
return StatusRunning
|
||||
case hasFailure:
|
||||
return StatusFailure
|
||||
case hasWaiting:
|
||||
return StatusWaiting
|
||||
case hasBlocked:
|
||||
|
@ -80,22 +80,31 @@ type FindRunJobOptions struct {
|
||||
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RunID > 0 {
|
||||
cond = cond.And(builder.Eq{"run_id": opts.RunID})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.run_id": opts.RunID})
|
||||
}
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.CommitSHA != "" {
|
||||
cond = cond.And(builder.Eq{"commit_sha": opts.CommitSHA})
|
||||
cond = cond.And(builder.Eq{"`action_run_job`.commit_sha": opts.CommitSHA})
|
||||
}
|
||||
if len(opts.Statuses) > 0 {
|
||||
cond = cond.And(builder.In("status", opts.Statuses))
|
||||
cond = cond.And(builder.In("`action_run_job`.status", opts.Statuses))
|
||||
}
|
||||
if opts.UpdatedBefore > 0 {
|
||||
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
|
||||
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
func (opts FindRunJobOptions) ToJoins() []db.JoinFunc {
|
||||
if opts.OwnerID > 0 {
|
||||
return []db.JoinFunc{
|
||||
func(sess db.Engine) error {
|
||||
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -58,14 +58,14 @@ func TestAggregateJobStatus(t *testing.T) {
|
||||
{[]Status{StatusCancelled, StatusRunning}, StatusCancelled},
|
||||
{[]Status{StatusCancelled, StatusBlocked}, StatusCancelled},
|
||||
|
||||
// failure with other status, fail fast
|
||||
// Should "running" win? Maybe no: old code does make "running" win, but GitHub does fail fast.
|
||||
// failure with other status, usually fail fast, but "running" wins to match GitHub's behavior
|
||||
// another reason that we can't make "failure" wins over "running": it would cause a weird behavior that user cannot cancel a workflow or get current running workflows correctly by filter after a job fail.
|
||||
{[]Status{StatusFailure}, StatusFailure},
|
||||
{[]Status{StatusFailure, StatusSuccess}, StatusFailure},
|
||||
{[]Status{StatusFailure, StatusSkipped}, StatusFailure},
|
||||
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
|
||||
{[]Status{StatusFailure, StatusWaiting}, StatusFailure},
|
||||
{[]Status{StatusFailure, StatusRunning}, StatusFailure},
|
||||
{[]Status{StatusFailure, StatusRunning}, StatusRunning},
|
||||
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
|
||||
|
||||
// skipped with other status
|
||||
|
@ -72,39 +72,50 @@ type FindRunOptions struct {
|
||||
TriggerEvent webhook_module.HookEventType
|
||||
Approved bool // not util.OptionalBool, it works only when it's true
|
||||
Status []Status
|
||||
CommitSHA string
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.WorkflowID != "" {
|
||||
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.workflow_id": opts.WorkflowID})
|
||||
}
|
||||
if opts.TriggerUserID > 0 {
|
||||
cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID})
|
||||
cond = cond.And(builder.Eq{"`action_run`.trigger_user_id": opts.TriggerUserID})
|
||||
}
|
||||
if opts.Approved {
|
||||
cond = cond.And(builder.Gt{"approved_by": 0})
|
||||
cond = cond.And(builder.Gt{"`action_run`.approved_by": 0})
|
||||
}
|
||||
if len(opts.Status) > 0 {
|
||||
cond = cond.And(builder.In("status", opts.Status))
|
||||
cond = cond.And(builder.In("`action_run`.status", opts.Status))
|
||||
}
|
||||
if opts.Ref != "" {
|
||||
cond = cond.And(builder.Eq{"ref": opts.Ref})
|
||||
cond = cond.And(builder.Eq{"`action_run`.ref": opts.Ref})
|
||||
}
|
||||
if opts.TriggerEvent != "" {
|
||||
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent})
|
||||
cond = cond.And(builder.Eq{"`action_run`.trigger_event": opts.TriggerEvent})
|
||||
}
|
||||
if opts.CommitSHA != "" {
|
||||
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToJoins() []db.JoinFunc {
|
||||
if opts.OwnerID > 0 {
|
||||
return []db.JoinFunc{func(sess db.Engine) error {
|
||||
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
|
||||
return nil
|
||||
}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opts FindRunOptions) ToOrders() string {
|
||||
return "`id` DESC"
|
||||
return "`action_run`.`id` DESC"
|
||||
}
|
||||
|
||||
type StatusInfo struct {
|
||||
|
@ -5,6 +5,7 @@ package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -298,6 +299,23 @@ func DeleteRunner(ctx context.Context, id int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteEphemeralRunner deletes a ephemeral runner by given ID.
|
||||
func DeleteEphemeralRunner(ctx context.Context, id int64) error {
|
||||
runner, err := GetRunnerByID(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if !runner.Ephemeral {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = db.DeleteByID[ActionRunner](ctx, id)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateRunner creates new runner.
|
||||
func CreateRunner(ctx context.Context, t *ActionRunner) error {
|
||||
if t.OwnerID != 0 && t.RepoID != 0 {
|
||||
|
@ -4,6 +4,8 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
@ -88,12 +90,7 @@ func (s Status) IsBlocked() bool {
|
||||
|
||||
// In returns whether s is one of the given statuses
|
||||
func (s Status) In(statuses ...Status) bool {
|
||||
for _, v := range statuses {
|
||||
if s == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(statuses, s)
|
||||
}
|
||||
|
||||
func (s Status) AsResult() runnerv1.Result {
|
||||
|
@ -278,14 +278,13 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
var workflowJob *jobparser.Job
|
||||
if gots, err := jobparser.Parse(job.WorkflowPayload); err != nil {
|
||||
parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err)
|
||||
} else if len(gots) != 1 {
|
||||
} else if len(parsedWorkflows) != 1 {
|
||||
return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID)
|
||||
} else { //nolint:revive
|
||||
_, workflowJob = gots[0].Job()
|
||||
}
|
||||
_, workflowJob := parsedWorkflows[0].Job()
|
||||
|
||||
if _, err := e.Insert(task); err != nil {
|
||||
return nil, false, err
|
||||
@ -336,6 +335,11 @@ func UpdateTask(ctx context.Context, task *ActionTask, cols ...string) error {
|
||||
sess.Cols(cols...)
|
||||
}
|
||||
_, err := sess.Update(task)
|
||||
|
||||
// Automatically delete the ephemeral runner if the task is done
|
||||
if err == nil && task.Status.IsDone() && util.SliceContainsString(cols, "status") {
|
||||
return DeleteEphemeralRunner(ctx, task.RunnerID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ func (tasks TaskList) LoadAttributes(ctx context.Context) error {
|
||||
type FindTaskOptions struct {
|
||||
db.ListOptions
|
||||
RepoID int64
|
||||
JobID int64
|
||||
OwnerID int64
|
||||
CommitSHA string
|
||||
Status Status
|
||||
@ -61,6 +62,9 @@ func (opts FindTaskOptions) ToConds() builder.Cond {
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.JobID > 0 {
|
||||
cond = cond.And(builder.Eq{"job_id": opts.JobID})
|
||||
}
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
}
|
||||
|
@ -82,3 +82,22 @@ func calculateDuration(started, stopped timeutil.TimeStamp, status Status) time.
|
||||
}
|
||||
return timeSince(s).Truncate(time.Second)
|
||||
}
|
||||
|
||||
// best effort function to convert an action schedule to action run, to be used in GenerateGiteaContext
|
||||
func (s *ActionSchedule) ToActionRun() *ActionRun {
|
||||
return &ActionRun{
|
||||
Title: s.Title,
|
||||
RepoID: s.RepoID,
|
||||
Repo: s.Repo,
|
||||
OwnerID: s.OwnerID,
|
||||
WorkflowID: s.WorkflowID,
|
||||
TriggerUserID: s.TriggerUserID,
|
||||
TriggerUser: s.TriggerUser,
|
||||
Ref: s.Ref,
|
||||
CommitSHA: s.CommitSHA,
|
||||
Event: s.Event,
|
||||
EventPayload: s.EventPayload,
|
||||
Created: s.Created,
|
||||
Updated: s.Updated,
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -125,12 +126,7 @@ func (at ActionType) String() string {
|
||||
}
|
||||
|
||||
func (at ActionType) InActions(actions ...string) bool {
|
||||
for _, action := range actions {
|
||||
if action == at.String() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(actions, at.String())
|
||||
}
|
||||
|
||||
// Action represents user operation type and other information to
|
||||
@ -191,7 +187,7 @@ func (a *Action) LoadActUser(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
a.ActUser, err = user_model.GetUserByID(ctx, a.ActUserID)
|
||||
a.ActUser, err = user_model.GetPossibleUserByID(ctx, a.ActUserID)
|
||||
if err == nil {
|
||||
return
|
||||
} else if user_model.IsErrUserNotExist(err) {
|
||||
@ -530,7 +526,7 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
|
||||
|
||||
if opts.RequestedTeam != nil {
|
||||
env := repo_model.AccessibleTeamReposEnv(organization.OrgFromUser(opts.RequestedUser), opts.RequestedTeam)
|
||||
teamRepoIDs, err := env.RepoIDs(ctx, 1, opts.RequestedUser.NumRepos)
|
||||
teamRepoIDs, err := env.RepoIDs(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetTeamRepositories: %w", err)
|
||||
}
|
||||
|
@ -208,10 +208,7 @@ func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.Repository
|
||||
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
|
||||
left := len(repoIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", repoIDs[:limit]).
|
||||
Rows(new(repo_model.Repository))
|
||||
@ -282,10 +279,7 @@ func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
|
||||
issues := make(map[int64]*issues_model.Issue, len(issueIDs))
|
||||
left := len(issueIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", issueIDs[:limit]).
|
||||
Rows(new(issues_model.Issue))
|
||||
@ -377,10 +371,7 @@ func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) {
|
||||
users := make(map[int64]*user_model.User, len(userIDs))
|
||||
left := len(userIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", userIDs[:limit]).
|
||||
Rows(new(user_model.User))
|
||||
@ -428,10 +419,7 @@ func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
|
||||
comments := make(map[int64]*issues_model.Comment, len(commentIDs))
|
||||
left := len(commentIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
limit := min(left, db.DefaultMaxInSize)
|
||||
rows, err := db.GetEngine(ctx).
|
||||
In("id", commentIDs[:limit]).
|
||||
Rows(new(issues_model.Comment))
|
||||
|
@ -139,10 +139,7 @@ func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository
|
||||
return v[i].Commits > v[j].Commits
|
||||
})
|
||||
|
||||
cnt := count
|
||||
if cnt > len(v) {
|
||||
cnt = len(v)
|
||||
}
|
||||
cnt := min(count, len(v))
|
||||
|
||||
return v[:cnt], nil
|
||||
}
|
||||
|
@ -17,13 +17,16 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/models/webhook"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
)
|
||||
|
||||
// Statistic contains the database statistics
|
||||
type Statistic struct {
|
||||
Counter struct {
|
||||
User, Org, PublicKey,
|
||||
UsersActive, UsersNotActive,
|
||||
Org, PublicKey,
|
||||
Repo, Watch, Star, Access,
|
||||
Issue, IssueClosed, IssueOpen,
|
||||
Comment, Oauth, Follow,
|
||||
@ -53,8 +56,20 @@ type IssueByRepositoryCount struct {
|
||||
// GetStatistic returns the database statistics
|
||||
func GetStatistic(ctx context.Context) (stats Statistic) {
|
||||
e := db.GetEngine(ctx)
|
||||
stats.Counter.User = user_model.CountUsers(ctx, nil)
|
||||
stats.Counter.Org, _ = db.Count[organization.Organization](ctx, organization.FindOrgOptions{IncludePrivate: true})
|
||||
|
||||
// Number of active users
|
||||
usersActiveOpts := user_model.CountUserFilter{
|
||||
IsActive: optional.Some(true),
|
||||
}
|
||||
stats.Counter.UsersActive = user_model.CountUsers(ctx, &usersActiveOpts)
|
||||
|
||||
// Number of inactive users
|
||||
usersNotActiveOpts := user_model.CountUserFilter{
|
||||
IsActive: optional.Some(false),
|
||||
}
|
||||
stats.Counter.UsersNotActive = user_model.CountUsers(ctx, &usersNotActiveOpts)
|
||||
|
||||
stats.Counter.Org, _ = db.Count[organization.Organization](ctx, organization.FindOrgOptions{IncludeVisibility: structs.VisibleTypePrivate})
|
||||
stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey))
|
||||
stats.Counter.Repo, _ = repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{})
|
||||
stats.Counter.Watch, _ = e.Count(new(repo_model.Watch))
|
||||
|
@ -66,7 +66,7 @@ func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organi
|
||||
Select(groupBy+" AS timestamp, count(user_id) as contributions").
|
||||
Table("action").
|
||||
Where(cond).
|
||||
And("created_unix > ?", timeutil.TimeStampNow()-31536000).
|
||||
And("created_unix > ?", timeutil.TimeStampNow()-(366+7)*86400). // (366+7) days to include the first week for the heatmap
|
||||
GroupBy(groupByName).
|
||||
OrderBy("timestamp").
|
||||
Find(&hdata)
|
||||
|
@ -91,7 +91,7 @@ func AddGPGKey(ctx context.Context, ownerID int64, content, token, signature str
|
||||
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil)
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Unable to validate token signature. Error: %v", err)
|
||||
log.Debug("AddGPGKey CheckArmoredDetachedSignature failed: %v", err)
|
||||
return nil, ErrGPGInvalidTokenSignature{
|
||||
ID: ekeys[0].PrimaryKey.KeyIdString(),
|
||||
Wrapped: err,
|
||||
|
@ -15,25 +15,6 @@ import (
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
)
|
||||
|
||||
// __________________ ________ ____ __.
|
||||
// / _____/\______ \/ _____/ | |/ _|____ ___.__.
|
||||
// / \ ___ | ___/ \ ___ | <_/ __ < | |
|
||||
// \ \_\ \| | \ \_\ \ | | \ ___/\___ |
|
||||
// \______ /|____| \______ / |____|__ \___ > ____|
|
||||
// \/ \/ \/ \/\/
|
||||
// _________ .__ __
|
||||
// \_ ___ \ ____ _____ _____ |__|/ |_
|
||||
// / \ \/ / _ \ / \ / \| \ __\
|
||||
// \ \___( <_> ) Y Y \ Y Y \ || |
|
||||
// \______ /\____/|__|_| /__|_| /__||__|
|
||||
// \/ \/ \/
|
||||
// ____ ____ .__ _____.__ __ .__
|
||||
// \ \ / /___________|__|/ ____\__| ____ _____ _/ |_|__| ____ ____
|
||||
// \ Y // __ \_ __ \ \ __\| |/ ___\\__ \\ __\ |/ _ \ / \
|
||||
// \ /\ ___/| | \/ || | | \ \___ / __ \| | | ( <_> ) | \
|
||||
// \___/ \___ >__| |__||__| |__|\___ >____ /__| |__|\____/|___| /
|
||||
// \/ \/ \/ \/
|
||||
|
||||
// This file provides functions relating commit verification
|
||||
|
||||
// CommitVerification represents a commit validation of signature
|
||||
@ -41,8 +22,8 @@ type CommitVerification struct {
|
||||
Verified bool
|
||||
Warning bool
|
||||
Reason string
|
||||
SigningUser *user_model.User
|
||||
CommittingUser *user_model.User
|
||||
SigningUser *user_model.User // if Verified, then SigningUser is non-nil
|
||||
CommittingUser *user_model.User // if Verified, then CommittingUser is non-nil
|
||||
SigningEmail string
|
||||
SigningKey *GPGKey
|
||||
SigningSSHKey *PublicKey
|
||||
|
@ -85,7 +85,7 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st
|
||||
}
|
||||
|
||||
if signer == nil {
|
||||
log.Error("Unable to validate token signature. Error: %v", err)
|
||||
log.Debug("VerifyGPGKey failed: no signer")
|
||||
return "", ErrGPGInvalidTokenSignature{
|
||||
ID: key.KeyID,
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user