mirror of
https://github.com/go-gitea/gitea.git
synced 2025-04-20 08:28:58 +03:00
Compare commits
120 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
de7026528b | ||
![]() |
ee3f5e8fac | ||
![]() |
b2707bcd18 | ||
![]() |
0512b02b01 | ||
![]() |
99545ae2fd | ||
![]() |
7697df9f93 | ||
![]() |
d17f8ffcc1 | ||
![]() |
5e9cc919cf | ||
![]() |
cc6ec56738 | ||
![]() |
76bd60fc1d | ||
![]() |
744f7c8200 | ||
![]() |
da33b708af | ||
![]() |
8fa3925874 | ||
![]() |
7794ff0874 | ||
![]() |
7c17d0a73e | ||
![]() |
a014d071e4 | ||
![]() |
312565e3c2 | ||
![]() |
58daaf66e8 | ||
![]() |
f076ada601 | ||
![]() |
92436b8b2a | ||
![]() |
2df7d0835a | ||
![]() |
200cb6140d | ||
![]() |
2746c6f1aa | ||
![]() |
23971a77a0 | ||
![]() |
ebac324ff2 | ||
![]() |
7df1204795 | ||
![]() |
159544a950 | ||
![]() |
9780da583d | ||
![]() |
a8eaf43f97 | ||
![]() |
b6fd8741ee | ||
![]() |
2674d27fb8 | ||
![]() |
6f3837284d | ||
![]() |
c30f4f4be5 | ||
![]() |
4578288ea3 | ||
![]() |
826fffb59e | ||
![]() |
2196ba5e42 | ||
![]() |
12347f07ae | ||
![]() |
a3c5358d35 | ||
![]() |
987d014468 | ||
![]() |
e08eed9040 | ||
![]() |
4ffa49aa04 | ||
![]() |
72837530bf | ||
![]() |
eef635523a | ||
![]() |
8f45a11919 | ||
![]() |
e72d001708 | ||
![]() |
8d9ea68f19 | ||
![]() |
bf664c2e85 | ||
![]() |
52d298890b | ||
![]() |
c09e43acf5 | ||
![]() |
3b4af01633 | ||
![]() |
b4e2d5e8ee | ||
![]() |
2984a7c121 | ||
![]() |
80cc87b3d8 | ||
![]() |
10b6047498 | ||
![]() |
2c47b06869 | ||
![]() |
31f2a325dc | ||
![]() |
fcbbc24cc4 | ||
![]() |
1454e1b6eb | ||
![]() |
d70348836b | ||
![]() |
940a930d13 | ||
![]() |
45d21a0d5c | ||
![]() |
15ad001aef | ||
![]() |
ed1828ca92 | ||
![]() |
3cfff5af0d | ||
![]() |
6f6c66a07d | ||
![]() |
d65af69c2b | ||
![]() |
12c24c2189 | ||
![]() |
a330f42f01 | ||
![]() |
531f36ea4a | ||
![]() |
b4f0eed969 | ||
![]() |
63b3a33bf2 | ||
![]() |
9899989ece | ||
![]() |
0fad40dd8c | ||
![]() |
e637008fe3 | ||
![]() |
fd281518ae | ||
![]() |
e10d222434 | ||
![]() |
7a35f90b29 | ||
![]() |
d371aa3031 | ||
![]() |
81768675d4 | ||
![]() |
39cc72562b | ||
![]() |
bc83fb26ef | ||
![]() |
68736ec292 | ||
![]() |
3df11c07a8 | ||
![]() |
96fff862dc | ||
![]() |
968c04c7da | ||
![]() |
27de60381d | ||
![]() |
d2d763318c | ||
![]() |
610b2fb88d | ||
![]() |
0858a36016 | ||
![]() |
fef364e7d6 | ||
![]() |
ce6a60a38b | ||
![]() |
74159a8855 | ||
![]() |
ce6464123f | ||
![]() |
7f0050cf39 | ||
![]() |
c102e344f3 | ||
![]() |
f27128bf94 | ||
![]() |
f35ab5cd52 | ||
![]() |
0137bc4e5c | ||
![]() |
eed0968c37 | ||
![]() |
a0b65ed17f | ||
![]() |
ad1b76540e | ||
![]() |
6636b37a9c | ||
![]() |
af5e5e8f00 | ||
![]() |
0e0ebf68d7 | ||
![]() |
90bd08ceef | ||
![]() |
0c581106d2 | ||
![]() |
e18e31d557 | ||
![]() |
e1026feddc | ||
![]() |
d670820722 | ||
![]() |
a8f98fd3be | ||
![]() |
c442c682ef | ||
![]() |
57868c2315 | ||
![]() |
b1c21880c1 | ||
![]() |
1e71ad89ce | ||
![]() |
c20642fa99 | ||
![]() |
a4291fd553 | ||
![]() |
fa5a064559 | ||
![]() |
cb42232080 | ||
![]() |
c8ffe777cf | ||
![]() |
e98dd6ee5b |
481
CHANGELOG.md
481
CHANGELOG.md
@ -4,6 +4,487 @@ 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
|
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).
|
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||||
|
|
||||||
|
## [1.23.4](https://github.com/go-gitea/gitea/releases/tag/v1.23.4) - 2025-02-16
|
||||||
|
|
||||||
|
* SECURITY
|
||||||
|
* Enhance routers for the Actions variable operations (#33547) (#33553)
|
||||||
|
* Enhance routers for the Actions runner operations (#33549) (#33555)
|
||||||
|
* Fix project issues list and counting (#33594) #33619
|
||||||
|
* PERFORMANCES
|
||||||
|
* Performance optimization for pull request files loading comments attachments (#33585) (#33592)
|
||||||
|
* BUGFIXES
|
||||||
|
* Add a transaction to `pickTask` (#33543) (#33563)
|
||||||
|
* Fix mirror bug (#33597) (#33607)
|
||||||
|
* Use default Git timeout when checking repo health (#33593) (#33598)
|
||||||
|
* Fix PR's target branch dropdown (#33589) (#33591)
|
||||||
|
* Fix various problems (artifact order, api empty slice, assignee check, fuzzy prompt, mirror proxy, adopt git) (#33569) (#33577)
|
||||||
|
* Rework suggestion backend (#33538) (#33546)
|
||||||
|
* Fix context usage (#33554) (#33557)
|
||||||
|
* Only show the latest version in the Arch index (#33262) (#33580)
|
||||||
|
* Skip deletion error for action artifacts (#33476) (#33568)
|
||||||
|
* Make actions URL in commit status webhooks absolute (#33620) #33632
|
||||||
|
* Add missing locale (#33641) #33642
|
||||||
|
|
||||||
|
## [1.23.3](https://github.com/go-gitea/gitea/releases/tag/v1.23.3) - 2025-02-06
|
||||||
|
|
||||||
|
* Security
|
||||||
|
* Build Gitea with Golang v1.23.6 to fix security bugs
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix a bug caused by status webhook template #33512
|
||||||
|
|
||||||
|
## [1.23.2](https://github.com/go-gitea/gitea/releases/tag/1.23.2) - 2025-02-04
|
||||||
|
|
||||||
|
* BREAKING
|
||||||
|
* Add tests for webhook and fix some webhook bugs (#33396) (#33442)
|
||||||
|
* Package webhook’s Organization was incorrectly used as the User struct. This PR fixes the issue.
|
||||||
|
* This changelog is just a hint. The change is not really breaking because most fields are the same, most users are not affected.
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Clone button enhancements (#33362) (#33404)
|
||||||
|
* Repo homepage styling tweaks (#33289) (#33381)
|
||||||
|
* Add a confirm dialog for "sync fork" (#33270) (#33273)
|
||||||
|
* Make tracked time representation display as hours (#33315) (#33334)
|
||||||
|
* Improve sync fork behavior (#33319) (#33332)
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix code button alignment (#33345) (#33351)
|
||||||
|
* Correct bot label `vertical-align` (#33477) (#33480)
|
||||||
|
* Fix SSH LFS memory usage (#33455) (#33460)
|
||||||
|
* Fix issue sidebar dropdown keyboard support (#33447) (#33450)
|
||||||
|
* Fix user avatar (#33439)
|
||||||
|
* Fix `GetCommitBranchStart` bug (#33298) (#33421)
|
||||||
|
* Add pubdate for repository rss and add some tests (#33411) (#33416)
|
||||||
|
* Add missed auto merge feed message on dashboard (#33309) (#33405)
|
||||||
|
* Fix issue suggestion bug (#33389) (#33391)
|
||||||
|
* Make issue suggestion work for all editors (#33340) (#33342)
|
||||||
|
* Fix issue count (#33338) (#33341)
|
||||||
|
* Fix Account linking page (#33325) (#33327)
|
||||||
|
* Fix closed dependency title (#33285) (#33287)
|
||||||
|
* Fix sidebar milestone link (#33269) (#33272)
|
||||||
|
* Fix missing license when sync mirror (#33255) (#33258)
|
||||||
|
* Fix upload file form (#33230) (#33233)
|
||||||
|
* Fix mirror bug (#33224) (#33225)
|
||||||
|
* Fix system admin cannot fork or get private fork with API (#33401) (#33417)
|
||||||
|
* Fix push message behavior (#33215) (#33317)
|
||||||
|
* Trivial fixes (#33304) (#33312)
|
||||||
|
* Fix "stop time tracking button" on navbar (#33084) (#33300)
|
||||||
|
* Fix tag route and empty repo (#33253)
|
||||||
|
* Fix cache test triggered by non memory cache (#33220) (#33221)
|
||||||
|
* Revert empty lfs ref name (#33454) (#33457)
|
||||||
|
* Fix flex width (#33414) (#33418)
|
||||||
|
* Fix commit status events (#33320) #33493
|
||||||
|
* Fix unnecessary comment when moving issue on the same project column (#33496) #33499
|
||||||
|
* Add timetzdata build tag to binary releases (#33463) #33503
|
||||||
|
* MISC
|
||||||
|
* Use ProtonMail/go-crypto to replace keybase/go-crypto (#33402) (#33410)
|
||||||
|
* Update katex to latest version (#33361)
|
||||||
|
* Update go tool dependencies (#32916) (#33355)
|
||||||
|
|
||||||
|
## [1.23.1](https://github.com/go-gitea/gitea/releases/tag/v1.23.1) - 2025-01-09
|
||||||
|
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Move repo size to sidebar (#33155) (#33182)
|
||||||
|
* BUGFIXES
|
||||||
|
* Use updated path to s6-svscan after alpine upgrade (#33185) (#33188)
|
||||||
|
* Fix fuzz test (#33156) (#33158)
|
||||||
|
* Fix raw file API ref handling (#33172) (#33189)
|
||||||
|
* Fix ACME panic (#33178) (#33186)
|
||||||
|
* Fix branch dropdown not display ref name (#33159) (#33183)
|
||||||
|
* Fix assignee list overlapping in Issue sidebar (#33176) (#33181)
|
||||||
|
* Fix sync fork for consistency (#33147) #33192
|
||||||
|
* Fix editor markdown not incrementing in a numbered list (#33187) #33193
|
||||||
|
|
||||||
|
## [1.23.0](https://github.com/go-gitea/gitea/releases/tag/v1.23.0) - 2025-01-08
|
||||||
|
|
||||||
|
* BREAKING
|
||||||
|
* Rename config option `[camo].Allways` to `[camo].Always` (#32097)
|
||||||
|
* Remove SHA1 for support for ssh rsa signing (#31857)
|
||||||
|
* Use UTC as default timezone when schedule Actions cron tasks (#31742)
|
||||||
|
* Delete Actions logs older than 1 year by default (#31735)
|
||||||
|
* Make OIDC introspection authentication strictly require Client ID and secret (#31632)
|
||||||
|
|
||||||
|
* SECURITY
|
||||||
|
* Include file extension checks in attachment API (#32151)
|
||||||
|
* Include all security fixes which have been backported to v1.22
|
||||||
|
|
||||||
|
* FEATURES
|
||||||
|
* Allow to fork repository into the same owner (#32819)
|
||||||
|
* Support "merge upstream branch" (Sync fork) (#32741)
|
||||||
|
* Add Arch package registry (#32692)
|
||||||
|
* Allow to disable the password-based login (sign-in) form (#32687)
|
||||||
|
* Allow cropping an avatar before setting it (#32565)
|
||||||
|
* Support quote selected comments to reply (#32431)
|
||||||
|
* Add reviewers selection to new pull request (#32403)
|
||||||
|
* Suggestions for issues (#32327)
|
||||||
|
* Add priority to protected branch (#32286)
|
||||||
|
* Included tag search capabilities (#32045)
|
||||||
|
* Add option to filter board cards by labels and assignees (#31999)
|
||||||
|
* Add automatic light/dark option for the colorblind theme (#31997)
|
||||||
|
* Support migration from AWS CodeCommit (#31981)
|
||||||
|
* Introduce globallock as distributed locks (#31908 & #31813)
|
||||||
|
* Support compression for Actions logs & enable by default (#31761 & #32013)
|
||||||
|
* Add pure SSH LFS support (#31516)
|
||||||
|
* Add Passkey login support (#31504)
|
||||||
|
* Actions support workflow dispatch event (#28163)
|
||||||
|
* Support repo license (#24872)
|
||||||
|
* Issue time estimate, meaningful time tracking (#23113)
|
||||||
|
* GitHub like repo home page (#32213 & #32847)
|
||||||
|
* Rearrange Clone Panel (#31142)
|
||||||
|
* Enhancing Gitea OAuth2 Provider with Granular Scopes for Resource Access (#32573)
|
||||||
|
* Use env GITEA_RUNNER_REGISTRATION_TOKEN as global runner token (#32946) #32964
|
||||||
|
* Update i18n.go - Language Picker (#32933) #32935
|
||||||
|
|
||||||
|
* PERFORMANCE
|
||||||
|
* Perf: add extra index to notification table (#32395)
|
||||||
|
* Introduce OrgList and add LoadTeams, optimaze Load teams for orgs (#32543)
|
||||||
|
* Improve performance of diffs (#32393)
|
||||||
|
* Make LFS http_client parallel within a batch. (#32369)
|
||||||
|
* Add new index for action to resolve the performance problem (#32333)
|
||||||
|
* Improve get feed with pagination (#31821)
|
||||||
|
* Performance improvements for pull request list API (#30490)
|
||||||
|
* Use batch database operations instead of one by one to optimze api pulls (#32680)
|
||||||
|
* Use gitrepo.GetTreePathLatestCommit to get file lastest commit instead from latest commit cache (#32987) #33046
|
||||||
|
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Code
|
||||||
|
* Remove unnecessary border in repo home page sidebar (#32767)
|
||||||
|
* Add 'Copy path' button to file view (#32584)
|
||||||
|
* Improve diff file tree (#32658)
|
||||||
|
* Add new [lfs_client].BATCH_SIZE and [server].LFS_MAX_BATCH_SIZE config settings. (#32307)
|
||||||
|
* Updated tokenizer to better matching when search for code snippets (#32261)
|
||||||
|
* Change the code search to sort results by relevance (#32134)
|
||||||
|
* Support migrating GitHub/GitLab PR draft status (#32242)
|
||||||
|
* Move lock icon position and add additional tooltips to branch list page (#31839)
|
||||||
|
* Add tag name in the commits list (#31082)
|
||||||
|
* Add `MAX_ROWS` option for CSV rendering (#30268)
|
||||||
|
* Allow code search by filename (#32210)
|
||||||
|
* Make git push options accept short name (#32245)
|
||||||
|
* Repo file list enhancements (#32835)
|
||||||
|
|
||||||
|
* Markdown & Editor
|
||||||
|
* Refactor markdown math render, add dollor-backquote syntax support (#32831)
|
||||||
|
* Make Monaco theme follow browser, fully type codeeditor.ts (#32756)
|
||||||
|
* Refactor markdown editor and use it for milestone description editor (#32688)
|
||||||
|
* Add some handy markdown editor features (#32400)
|
||||||
|
* Improve markdown textarea for indentation and lists (#31406)
|
||||||
|
|
||||||
|
* Issue
|
||||||
|
* Add label/author/assignee filters to the user/org home issue list (#32779)
|
||||||
|
* Refactor issue filter (labels, poster, assignee) (#32771)
|
||||||
|
* Style unification for the issue_management area (#32605)
|
||||||
|
* Add "View all branches/tags" entry to Branch Selector (#32653)
|
||||||
|
* Improve textarea paste (#31948)
|
||||||
|
* Add avif image file support (#32508)
|
||||||
|
* Prevent from submitting issue/comment on uploading (#32263)
|
||||||
|
* Issue Templates: add option to have dropdown printed list (#31577)
|
||||||
|
* Allow searching issues by ID (#31479)
|
||||||
|
* Add `is_archived` option for issue indexer (#32735)
|
||||||
|
* Improve attachment upload methods (#30513)
|
||||||
|
* Support issue template assignees (#31083)
|
||||||
|
* Prevent simultaneous editing of comments and issues (#31053)
|
||||||
|
* Add issue comment when moving issues from one column to another of the project (#29311)
|
||||||
|
|
||||||
|
* Pull Request
|
||||||
|
* Display head branch more comfortable on pull request view (#32000)
|
||||||
|
* Simplify review UI (#31062)
|
||||||
|
* Allow force push to protected branches (#28086)
|
||||||
|
* Add line-through for deleted branch on pull request view page (#32500)
|
||||||
|
* Support requested_reviewers data in comment webhook events (#26178)
|
||||||
|
* Allow maintainers to view and edit files of private repos when "Allow maintainers to edit" is enabled (#32215)
|
||||||
|
* Allow including `Reviewed-on`/`Reviewed-by` lines for custom merge messages (#31211)
|
||||||
|
|
||||||
|
* Actions
|
||||||
|
* Render job title as commit message (#32748)
|
||||||
|
* Refactor RepoActionView.vue, add `::group::` support (#32713)
|
||||||
|
* Make RepoActionView.vue support `##[group]` (#32770)
|
||||||
|
* Support `pull_request_target` event for commit status (#31703)
|
||||||
|
* Detect whether action view branch was deleted (#32764)
|
||||||
|
* Allow users with write permission to run actions (#32644)
|
||||||
|
* Show latest run when visit /run/latest (#31808)
|
||||||
|
|
||||||
|
* Packages
|
||||||
|
* Improve rubygems package registry (#31357)
|
||||||
|
* Add support for npm bundleDependencies (#30751)
|
||||||
|
* Add signature support for the RPM module (#27069)
|
||||||
|
* Extract and display readme and comments for Composer packages (#30927)
|
||||||
|
|
||||||
|
* Project
|
||||||
|
* Add title to project view page (#32747)
|
||||||
|
* Set the columns height to hug all its contents (#31726)
|
||||||
|
* Rename project `board` -> `column` to make the UI less confusing (#30170)
|
||||||
|
|
||||||
|
* User & Organazition
|
||||||
|
* Use better name for userinfo structure (#32544)
|
||||||
|
* Use user.FullName in Oauth2 id_token response (#32542)
|
||||||
|
* Limit org member view of restricted users (#32211)
|
||||||
|
* Allow disabling authentication related user features (#31535)
|
||||||
|
* Add option to change mail from user display name (#31528)
|
||||||
|
* Use FullName in Emails to address the recipient if possible (#31527)
|
||||||
|
|
||||||
|
* Administration
|
||||||
|
* Add support for a credentials chain for minio access (#31051)
|
||||||
|
* Move admin routers from /admin to /-/admin (#32189)
|
||||||
|
* Add cache test for admins (#31265)
|
||||||
|
* Add option for mailer to override mail headers (#27860)
|
||||||
|
* Azure blob storage support (#30995)
|
||||||
|
* Supports forced use of S3 virtual-hosted style (#30969)
|
||||||
|
* Move repository visibility to danger zone in the settings area (#31126)
|
||||||
|
|
||||||
|
* Others
|
||||||
|
* Remove urls from translations (#31950)
|
||||||
|
* Simplify 404/500 page (#31409)
|
||||||
|
* Optimize installation-page experience (#32558)
|
||||||
|
* Refactor login page (#31530)
|
||||||
|
* Add new event commit status creation and webhook implementation (#27151)
|
||||||
|
* Repo Activity: count new issues that were closed (#31776)
|
||||||
|
* Set manual `tabindex`es on login page (#31689)
|
||||||
|
* Add `YEAR`, `MONTH`, `MONTH_ENGLISH`, `DAY` variables for template repos (#31584)
|
||||||
|
* Add typescript guideline and typescript-specific eslint plugins and fix issues (#31521)
|
||||||
|
* Make toast support preventDuplicates (#31501)
|
||||||
|
* Fix tautological conditions (#30735)
|
||||||
|
* Issue change title notifications (#33050) #33065
|
||||||
|
|
||||||
|
* API
|
||||||
|
* Implement update branch API (#32433)
|
||||||
|
* Fix missing outputs for jobs with matrix (#32823)
|
||||||
|
* Make API "compare" accept commit IDs (#32801)
|
||||||
|
* Add github compatible tarball download API endpoints (#32572)
|
||||||
|
* Harden runner updateTask and updateLog api (#32462)
|
||||||
|
* Add `DISABLE_ORGANIZATIONS_PAGE` and `DISABLE_CODE_PAGE` settings for explore pages and fix an issue related to user search (#32288)
|
||||||
|
* Make admins adhere to branch protection rules (#32248)
|
||||||
|
* Calculate `PublicOnly` for org membership only once (#32234)
|
||||||
|
* Allow filtering PRs by poster in the ListPullRequests API (#32209)
|
||||||
|
* Return 404 instead of error when commit not exist (#31977)
|
||||||
|
* Save initial signup information for users to aid in spam prevention (#31852)
|
||||||
|
* Fix upload maven pacakge parallelly (#31851)
|
||||||
|
* Fix null requested_reviewer from API (#31773)
|
||||||
|
* Add permission description for API to add repo collaborator (#31744)
|
||||||
|
* Add return type to GetRawFileOrLFS and GetRawFile (#31680)
|
||||||
|
* Add skip secondary authorization option for public oauth2 clients (#31454)
|
||||||
|
* Add tag protection via rest api #17862 (#31295)
|
||||||
|
* Document possible action types for the user activity feed API (#31196)
|
||||||
|
* Add topics for repository API (#31127)
|
||||||
|
* Add support for searching users by email (#30908)
|
||||||
|
* Add API endpoints for getting action jobs status (#26673)
|
||||||
|
|
||||||
|
* REFACTOR
|
||||||
|
* Update JS and PY dependencies (#31940)
|
||||||
|
* Enable `no-jquery/no-parse-html-literal` and fix violation (#31684)
|
||||||
|
* Refactor image diff (#31444)
|
||||||
|
* Refactor CSRF token (#32216)
|
||||||
|
* Fix some typescript issues (#32586)
|
||||||
|
* Refactor names (#31405)
|
||||||
|
* Use per package global lock for container uploads instead of memory lock (#31860)
|
||||||
|
* Move team related functions to service layer (#32537)
|
||||||
|
* Move GetFeeds to service layer (#32526)
|
||||||
|
* Resolve lint for unused parameter and unnecessary type arguments (#30750)
|
||||||
|
* Reimplement GetUserOrgsList to make it simple and clear (#32486)
|
||||||
|
* Move some functions from issue.go to standalone files (#32468)
|
||||||
|
* Refactor sidebar assignee&milestone&project selectors (#32465)
|
||||||
|
* Refactor sidebar label selector (#32460)
|
||||||
|
* Fix a number of typescript issues (#32459)
|
||||||
|
* Refactor language menu and dom utils (#32450)
|
||||||
|
* Refactor issue page info (#32445)
|
||||||
|
* Split issue sidebar into small templates (#32444)
|
||||||
|
* Refactor template ctx and render utils (#32422)
|
||||||
|
* Refactor repo legacy (#32404)
|
||||||
|
* Refactor markup package (#32399)
|
||||||
|
* Refactor markup render system (#32533 & #32589 & #32612)
|
||||||
|
* Refactor the DB migration system slightly (#32344)
|
||||||
|
* Remove jQuery import from some files (#32512)
|
||||||
|
* Strict pagination check (#32548)
|
||||||
|
* Split mail sender sub package from mailer service package (#32618)
|
||||||
|
* Remove outdated code about fixture generation (#32708)
|
||||||
|
* Refactor RepoBranchTagSelector (#32681)
|
||||||
|
* Refactor issue list (#32755)
|
||||||
|
* Refactor LabelEdit (#32752)
|
||||||
|
* Split issue/pull view router function as multiple smaller functions (#32749)
|
||||||
|
* Refactor some LDAP code (#32849)
|
||||||
|
* Unify repo search order by logic (#30876)
|
||||||
|
* Remove duplicate empty repo check in delete branch API (#32569)
|
||||||
|
* Replace deprecated `math/rand` functions (#30733)
|
||||||
|
* Remove fomantic dimmer module (#30723)
|
||||||
|
* Add types to fetch,toast,bootstrap,svg (#31627)
|
||||||
|
* Refactor webhook (#31587)
|
||||||
|
* Move AddCollabrator and CreateRepositoryByExample to service layer (#32419)
|
||||||
|
* Refactor RepoRefByType (#32413)
|
||||||
|
* Refactor: remove redundant err declarations (#32381)
|
||||||
|
* Refactor markup code (#31399)
|
||||||
|
* Refactor render system (orgmode) (#32671)
|
||||||
|
* Refactor render system (#32492)
|
||||||
|
* Refactor markdown render (#32736 & #32728)
|
||||||
|
* Refactor repo unit "disabled" check (#31389)
|
||||||
|
* Refactor route path normalization (#31381)
|
||||||
|
* Refactor to use UnsafeStringToBytes (#31358)
|
||||||
|
* Migrate vue components to setup (#32329)
|
||||||
|
* Refactor globallock (#31933)
|
||||||
|
* Use correct function name (#31887)
|
||||||
|
* Use a common message template instead of a special one (#31878)
|
||||||
|
* Fix a number of Typescript issues (#31877)
|
||||||
|
* Refactor dropzone (#31482)
|
||||||
|
* Move custom `tw-` helpers to tailwind plugin (#31184)
|
||||||
|
* Replace `gt-word-break` with `tw-break-anywhere` (#31183)
|
||||||
|
* Drop `IDOrderDesc` for listing Actions task and always order by `id DESC` (#31150)
|
||||||
|
* Split common-global.js into separate files (#31438)
|
||||||
|
* Improve detecting empty files (#31332)
|
||||||
|
* Use `querySelector` over alternative DOM methods (#31280)
|
||||||
|
* Remove jQuery `.text()` (#30506)
|
||||||
|
* Use repo as of renderctx's member rather than a repoPath on metas (#29222)
|
||||||
|
* Refactor some frontend problems (#32646)
|
||||||
|
* Refactor DateUtils and merge TimeSince (#32409)
|
||||||
|
* Replace DateTime with proper functions (#32402)
|
||||||
|
* Replace DateTime with DateUtils (#32383)
|
||||||
|
* Convert frontend code to typescript (#31559)
|
||||||
|
* Refactor maven package registry (#33049) #33057
|
||||||
|
* Refactor testfixtures #33028
|
||||||
|
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix issues with inconsistent spacing in areas (#32607)
|
||||||
|
* Fix incomplete Actions status aggregations (#32859)
|
||||||
|
* In some lfs server implementations, they require the ref attribute. (#32838)
|
||||||
|
* Update the list of watchers and stargazers when clicking watch/unwatch or star/unstar (#32570)
|
||||||
|
* Fix `recentupdate` sorting bugs (#32505)
|
||||||
|
* Fix incorrect "Target branch does not exist" in PR title (#32222)
|
||||||
|
* Handle "close" actionable references for manual merges (#31879)
|
||||||
|
* render plain text file if the LFS object doesn't exist (#31812)
|
||||||
|
* Fix Null Pointer error for CommitStatusesHideActionsURL (#31731)
|
||||||
|
* Fix loadRepository error when access user dashboard (#31719)
|
||||||
|
* Hide the "Details" link of commit status when the user cannot access actions (#30156)
|
||||||
|
* Fix duplicate dropdown dividers (#32760)
|
||||||
|
* Fix SSPI button visibility when SSPI is the only enabled method (#32841)
|
||||||
|
* Fix overflow on org header (#32837)
|
||||||
|
* Exclude protected branches from recently pushed (#31748)
|
||||||
|
* Fix large image overflow in comment page (#31740)
|
||||||
|
* Fix milestone deadline and date related problems (#32339)
|
||||||
|
* Fix markdown preview $$ support (#31514)
|
||||||
|
* Fix a compilation error in the Gitpod environment (#32559)
|
||||||
|
* Fix PR diff review form submit (#32596)
|
||||||
|
* Fix a number of typescript issues (#32308)
|
||||||
|
* Fix some function names in comment (#32300)
|
||||||
|
* Fix absolute-date (#32375)
|
||||||
|
* Clarify Actions resources ownership (#31724)
|
||||||
|
* Try to fix ACME directory problem (#33072) #33077
|
||||||
|
* Inherit submodules from template repository content (#16237) #33068
|
||||||
|
* Use project's redirect url instead of composing url (#33058) #33064
|
||||||
|
* Fix toggle commit body button ui when latest commit message is long (#32997) #33034
|
||||||
|
* Fix package error handling and npm meta and empty repo guide #33112
|
||||||
|
* Fix empty git repo handling logic and fix mobile view (#33101) #33102
|
||||||
|
* Fix line-number and scroll bugs (#33094) #33095
|
||||||
|
* Fix bleve fuzziness search (#33078) #33087
|
||||||
|
* Fix broken forms #33082
|
||||||
|
* Fix empty repo updated time (#33120) #33124
|
||||||
|
* Add missing transaction when set merge #33113
|
||||||
|
* Fix issue comment number (#30556) #33055
|
||||||
|
* Fix duplicate co-author in squashed merge commit messages (#33020) #33054
|
||||||
|
* Fix Agit pull request permission check (#32999) #33005
|
||||||
|
* Fix scoped label ui when contains emoji (#33007) #33014
|
||||||
|
* Fix bug on activities (#33008) #33016
|
||||||
|
* Fix review code comment avatar alignment (#33031) #33032
|
||||||
|
* Fix templating in pull request comparison (#33025) #33038
|
||||||
|
* Fix bug automerge cannot be chosed when there is only 1 merge style (#33040) #33043
|
||||||
|
* Fix settings not being loaded at CLI (#26402) #33048
|
||||||
|
* Support for email addresses containing uppercase characters when activating user account (#32998) #33001
|
||||||
|
* Support org labels when adding labels by label names (#32988) #32996
|
||||||
|
* Do not render truncated links in markdown (#32980) #32983
|
||||||
|
* Demilestone should not include milestone (#32923) #32979
|
||||||
|
* Fix Azure blob object Seek (#32974) #32975
|
||||||
|
* Fix maven pom inheritance (#32943) #32976
|
||||||
|
* Fix textarea newline handle (#32966) #32977
|
||||||
|
* Fix outdated tmpl code (#32953) #32961
|
||||||
|
* Fix commit range paging (#32944) #32962
|
||||||
|
* Fix repo avatar conflict (#32958) #32960
|
||||||
|
* Fix trailing comma not matched in the case of alphanumeric issue (#32945)
|
||||||
|
* Relax the version checking for Arch packages (#32908) #32913
|
||||||
|
* Add more load functions to make sure the reference object loaded (#32901) #32912
|
||||||
|
* Filter reviews of one pull request in memory instead of database to reduce slow response because of lacking database index (#33106) #33128
|
||||||
|
* Fix git remote error check, fix dependencies, fix js error (#33129) #33133
|
||||||
|
|
||||||
|
* MISC
|
||||||
|
* Optimize branch protection rule loading (#32280)
|
||||||
|
* Bump to go 1.23 (#31855)
|
||||||
|
* Remove unused call to $.HeadRepo in view_title template (#32317)
|
||||||
|
* Do not display `attestation-manifest` and use short sha256 instead of full sha256 (#32851)
|
||||||
|
* Upgrade htmx to 2.0.4 (#32834)
|
||||||
|
* Improve JSX/TSX support in code editor (#32833)
|
||||||
|
* Add User-Agent for gitea's self-implemented lfs client. (#32832)
|
||||||
|
* Use errors.New to replace fmt.Errorf with no parameters (#32800)
|
||||||
|
* Add "n commits" link to contributors in contributors graph page (#32799)
|
||||||
|
* Update dependencies, tweak eslint (#32719)
|
||||||
|
* Remove all "floated" CSS styles (#32691)
|
||||||
|
* Show tag name on branch/tag selector if repo shown from tag ref (#32689)
|
||||||
|
* Use new mail package instead of an unmintained one (#32682)
|
||||||
|
* Optimize the styling of icon buttons within file-header-right (#32675)
|
||||||
|
* Validate OAuth Redirect URIs (#32643)
|
||||||
|
* Support optional/configurable IAMEndpoint for Minio Client (#32581) (#32581)
|
||||||
|
* Make search box in issue sidebar dropdown list always show when scrolling (#32576)
|
||||||
|
* Bump CI,Flake and Snap to Node 22 (#32487)
|
||||||
|
* Update `github.com/meilisearch/meilisearch-go` (#32484)
|
||||||
|
* Add `DEFAULT_MIRROR_REPO_UNITS` and `DEFAULT_TEMPLATE_REPO_UNITS` options (#32416)
|
||||||
|
* Update go dependencies (#32389)
|
||||||
|
* Update JS and PY dependencies (#32388)
|
||||||
|
* Upgrade rollup to 4.24.0 (#32312)
|
||||||
|
* Upgrade vue to 3.5.12 (#32311)
|
||||||
|
* Improve the maintainblity of the reserved username list (#32229)
|
||||||
|
* Upgrade htmx to 2.0.3 (#32192)
|
||||||
|
* Count typescript files as frontend for labeling (#32088)
|
||||||
|
* Only use Host header from reverse proxy (#32060)
|
||||||
|
* Failed authentications are logged to level Warning (#32016)
|
||||||
|
* Enhance USER_DISABLED_FEATURES to allow disabling change username or full name (#31959)
|
||||||
|
* Distinguish official vs non-official reviews, add tool tips, and upgr… (#31924)
|
||||||
|
* Update mermaid to v11 (#31913)
|
||||||
|
* Bump relative-time-element to v4.4.3 (#31910)
|
||||||
|
* Upgrade `htmx` to `2.0.2` (#31847)
|
||||||
|
* Add warning message in merge instructions when `AutodetectManualMerge` was not enabled (#31805)
|
||||||
|
* Add types to various low-level functions (#31781)
|
||||||
|
* Update JS dependencies (#31766)
|
||||||
|
* Remove unused code from models/repos/release.go (#31756)
|
||||||
|
* Support delete user email in admin panel (#31690)
|
||||||
|
* Add `username` to OIDC introspection response (#31688)
|
||||||
|
* Use GetDisplayName() instead of DisplayName() to generate rss feeds (#31687)
|
||||||
|
* Code editor theme enhancements (#31629)
|
||||||
|
* Update JS dependencies (#31616)
|
||||||
|
* Add types for js globals (#31586)
|
||||||
|
* Add back esbuild-loader for .js files (#31585)
|
||||||
|
* Don't show hidden labels when filling out an issue template (#31576)
|
||||||
|
* Allow synchronizing user status from OAuth2 login providers (#31572)
|
||||||
|
* Display app name in the registration email title (#31562)
|
||||||
|
* Use stable version of fabric (#31526)
|
||||||
|
* Support legacy _links LFS batch responses (#31513)
|
||||||
|
* Fix JS error with disabled attachment and easymde (#31511)
|
||||||
|
* Always use HTML attributes for avatar size (#31509)
|
||||||
|
* Use nolyfill to remove some polyfills (#31468)
|
||||||
|
* Disable issue/PR comment button given empty input (#31463)
|
||||||
|
* Add simple JS init performance trace (#31459)
|
||||||
|
* Bump htmx to 2.0.0 (#31413)
|
||||||
|
* Update JS dependencies, remove `eslint-plugin-jquery` (#31402)
|
||||||
|
* Split org Propfile README to a new tab `overview` (#31373)
|
||||||
|
* Update nix flake and add gofumpt (#31320)
|
||||||
|
* Code optimization (#31315)
|
||||||
|
* Enable poetry non-package mode (#31282)
|
||||||
|
* Optimize profile layout to enhance visual experience (#31278)
|
||||||
|
* Update `golang.org/x/net` (#31260)
|
||||||
|
* Bump `@github/relative-time-element` to v4.4.1 (#31232)
|
||||||
|
* Remove unnecessary inline style for tab-size (#31224)
|
||||||
|
* Update golangci-lint to v1.59.0 (#31221)
|
||||||
|
* Update chroma to v2.14.0 (#31177)
|
||||||
|
* Update JS dependencies (#31120)
|
||||||
|
* Improve the handling of `jobs.<job_id>.if` (#31070)
|
||||||
|
* Clean up revive linter config, tweak golangci output (#30980)
|
||||||
|
* Use CSS `inset` shorthand (#30939)
|
||||||
|
* Forbid deprecated `break-word` in CSS (#30934)
|
||||||
|
* Remove obsolete monaco workaround (#30893)
|
||||||
|
* Update JS dependencies, add new eslint rules (#30840)
|
||||||
|
* Fix body margin shifting with modals, fix error on project column edit (#30831)
|
||||||
|
* Remove disk-clean workflow (#30741)
|
||||||
|
* Bump `github.com/google/go-github` to v61 (#30738)
|
||||||
|
* Add built js files to eslint ignore (#30737)
|
||||||
|
* Use `ProtonMail/go-crypto` for `opengpg` in tests (#30736)
|
||||||
|
* Upgrade xorm to v1.3.9 and improve some migrations Sync (#29899)
|
||||||
|
* Added default sorting milestones by name (#27084)
|
||||||
|
* Enable `unparam` linter (#31277)
|
||||||
|
* Use Alpine 3.21 for the docker images (#32924) #32951
|
||||||
|
* Bump x/net (#32896) #32899
|
||||||
|
* Use -s -w ldflags for release artifacts (#33041) #33042
|
||||||
|
* Remove aws go sdk package dependency (#33029) #33047
|
||||||
|
|
||||||
## [1.22.4](https://github.com/go-gitea/gitea/releases/tag/v1.22.4) - 2024-11-14
|
## [1.22.4](https://github.com/go-gitea/gitea/releases/tag/v1.22.4) - 2024-11-14
|
||||||
|
|
||||||
* SECURITY
|
* SECURITY
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Build stage
|
# Build stage
|
||||||
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
|
FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY=${GOPROXY:-direct}
|
||||||
@ -41,7 +41,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
|||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.20
|
FROM docker.io/library/alpine:3.21
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="maintainers@gitea.io"
|
||||||
|
|
||||||
EXPOSE 22 3000
|
EXPOSE 22 3000
|
||||||
@ -78,7 +78,7 @@ ENV GITEA_CUSTOM=/data/gitea
|
|||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
CMD ["/usr/bin/s6-svscan", "/etc/s6"]
|
||||||
|
|
||||||
COPY --from=build-env /tmp/local /
|
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/gitea /app/gitea/gitea
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Build stage
|
# Build stage
|
||||||
FROM docker.io/library/golang:1.23-alpine3.20 AS build-env
|
FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY=${GOPROXY:-direct}
|
||||||
@ -39,7 +39,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
|||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.20
|
FROM docker.io/library/alpine:3.21
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
LABEL maintainer="maintainers@gitea.io"
|
||||||
|
|
||||||
EXPOSE 2222 3000
|
EXPOSE 2222 3000
|
||||||
|
18
Makefile
18
Makefile
@ -26,17 +26,17 @@ COMMA := ,
|
|||||||
XGO_VERSION := go-1.23.x
|
XGO_VERSION := go-1.23.x
|
||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
|
||||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12
|
||||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
|
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
|
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
|
||||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
|
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.15.3
|
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.0
|
||||||
|
|
||||||
DOCKER_IMAGE ?= gitea/gitea
|
DOCKER_IMAGE ?= gitea/gitea
|
||||||
DOCKER_TAG ?= latest
|
DOCKER_TAG ?= latest
|
||||||
@ -806,22 +806,22 @@ $(DIST_DIRS):
|
|||||||
|
|
||||||
.PHONY: release-windows
|
.PHONY: release-windows
|
||||||
release-windows: | $(DIST_DIRS)
|
release-windows: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
||||||
ifeq (,$(findstring gogit,$(TAGS)))
|
ifeq (,$(findstring gogit,$(TAGS)))
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: release-linux
|
.PHONY: release-linux
|
||||||
release-linux: | $(DIST_DIRS)
|
release-linux: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
||||||
|
|
||||||
.PHONY: release-darwin
|
.PHONY: release-darwin
|
||||||
release-darwin: | $(DIST_DIRS)
|
release-darwin: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
|
||||||
|
|
||||||
.PHONY: release-freebsd
|
.PHONY: release-freebsd
|
||||||
release-freebsd: | $(DIST_DIRS)
|
release-freebsd: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w $(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
|
||||||
|
|
||||||
.PHONY: release-copy
|
.PHONY: release-copy
|
||||||
release-copy: | $(DIST_DIRS)
|
release-copy: | $(DIST_DIRS)
|
||||||
|
77
assets/go-licenses.json
generated
77
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@ -69,6 +69,10 @@ var microcmdUserCreate = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCreateUser(c *cli.Context) error {
|
func runCreateUser(c *cli.Context) 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 {
|
if err := argsSet(c, "email"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
var CmdMigrate = &cli.Command{
|
var CmdMigrate = &cli.Command{
|
||||||
Name: "migrate",
|
Name: "migrate",
|
||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
Description: `This is a command for migrating the database, so that you can run "gitea admin create user" before starting the server.`,
|
||||||
Action: runMigrate,
|
Action: runMigrate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
cmd/web.go
11
cmd/web.go
@ -12,6 +12,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
||||||
|
|
||||||
@ -115,6 +116,16 @@ func showWebStartupMessage(msg string) {
|
|||||||
log.Info("* CustomPath: %s", setting.CustomPath)
|
log.Info("* CustomPath: %s", setting.CustomPath)
|
||||||
log.Info("* ConfigFile: %s", setting.CustomConf)
|
log.Info("* ConfigFile: %s", setting.CustomConf)
|
||||||
log.Info("%s", msg) // show startup message
|
log.Info("%s", msg) // show startup message
|
||||||
|
|
||||||
|
if setting.CORSConfig.Enabled {
|
||||||
|
log.Info("CORS Service Enabled")
|
||||||
|
}
|
||||||
|
if setting.DefaultUILocation != time.Local {
|
||||||
|
log.Info("Default UI Location is %v", setting.DefaultUILocation.String())
|
||||||
|
}
|
||||||
|
if setting.MailService != nil {
|
||||||
|
log.Info("Mail Service Enabled: RegisterEmailConfirm=%v, Service.EnableNotifyMail=%v", setting.Service.RegisterEmailConfirm, setting.Service.EnableNotifyMail)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveInstall(ctx *cli.Context) error {
|
func serveInstall(ctx *cli.Context) error {
|
||||||
|
@ -54,8 +54,10 @@ func runACME(listenAddr string, m http.Handler) error {
|
|||||||
altTLSALPNPort = p
|
altTLSALPNPort = p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: this path is not right, it uses "AppWorkPath" incorrectly, and writes the data into "AppWorkPath/https"
|
||||||
|
// Ideally it should migrate to AppDataPath write to "AppDataPath/https"
|
||||||
|
certmagic.Default.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
|
||||||
magic := certmagic.NewDefault()
|
magic := certmagic.NewDefault()
|
||||||
magic.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
|
|
||||||
// Try to use private CA root if provided, otherwise defaults to system's trust
|
// Try to use private CA root if provided, otherwise defaults to system's trust
|
||||||
var certPool *x509.CertPool
|
var certPool *x509.CertPool
|
||||||
if setting.AcmeCARoot != "" {
|
if setting.AcmeCARoot != "" {
|
||||||
|
@ -1482,6 +1482,10 @@ LEVEL = Info
|
|||||||
;REPO_INDEXER_EXCLUDE =
|
;REPO_INDEXER_EXCLUDE =
|
||||||
;;
|
;;
|
||||||
;MAX_FILE_SIZE = 1048576
|
;MAX_FILE_SIZE = 1048576
|
||||||
|
;;
|
||||||
|
;; Bleve engine has performance problems with fuzzy search, so we limit the fuzziness to 0 by default to disable it.
|
||||||
|
;; If you'd like to enable it, you can set it to a value between 0 and 2.
|
||||||
|
;TYPE_BLEVE_MAX_FUZZINESS = 0
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -37,5 +37,5 @@ done
|
|||||||
if [ $# -gt 0 ]; then
|
if [ $# -gt 0 ]; then
|
||||||
exec "$@"
|
exec "$@"
|
||||||
else
|
else
|
||||||
exec /bin/s6-svscan /etc/s6
|
exec /usr/bin/s6-svscan /etc/s6
|
||||||
fi
|
fi
|
||||||
|
38
go.mod
38
go.mod
@ -24,11 +24,10 @@ require (
|
|||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||||
github.com/ProtonMail/go-crypto v1.0.0
|
github.com/ProtonMail/go-crypto v1.1.4
|
||||||
github.com/PuerkitoBio/goquery v1.10.0
|
github.com/PuerkitoBio/goquery v1.10.0
|
||||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0
|
github.com/alecthomas/chroma/v2 v2.15.0
|
||||||
github.com/aws/aws-sdk-go v1.55.5
|
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.42
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.42
|
||||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.27.3
|
github.com/aws/aws-sdk-go-v2/service/codecommit v1.27.3
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
@ -55,13 +54,12 @@ require (
|
|||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-co-op/gocron v1.37.0
|
github.com/go-co-op/gocron v1.37.0
|
||||||
github.com/go-enry/go-enry/v2 v2.9.1
|
github.com/go-enry/go-enry/v2 v2.9.1
|
||||||
github.com/go-git/go-billy/v5 v5.6.0
|
github.com/go-git/go-billy/v5 v5.6.1
|
||||||
github.com/go-git/go-git/v5 v5.12.0
|
github.com/go-git/go-git/v5 v5.13.1
|
||||||
github.com/go-ldap/ldap/v3 v3.4.8
|
github.com/go-ldap/ldap/v3 v3.4.8
|
||||||
github.com/go-redsync/redsync/v4 v4.13.0
|
github.com/go-redsync/redsync/v4 v4.13.0
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/go-swagger/go-swagger v0.31.0
|
github.com/go-swagger/go-swagger v0.31.0
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0
|
|
||||||
github.com/go-webauthn/webauthn v0.11.2
|
github.com/go-webauthn/webauthn v0.11.2
|
||||||
github.com/gobwas/glob v0.2.3
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||||
@ -81,7 +79,6 @@ require (
|
|||||||
github.com/jhillyerd/enmime v1.3.0
|
github.com/jhillyerd/enmime v1.3.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
|
||||||
github.com/klauspost/compress v1.17.11
|
github.com/klauspost/compress v1.17.11
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8
|
github.com/klauspost/cpuid/v2 v2.2.8
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
@ -109,7 +106,7 @@ require (
|
|||||||
github.com/sassoftware/go-rpmutils v0.4.0
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
github.com/ulikunitz/xz v0.5.12
|
github.com/ulikunitz/xz v0.5.12
|
||||||
@ -121,14 +118,14 @@ require (
|
|||||||
github.com/yuin/goldmark v1.7.8
|
github.com/yuin/goldmark v1.7.8
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
github.com/yuin/goldmark-meta v1.1.0
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.32.0
|
||||||
golang.org/x/image v0.21.0
|
golang.org/x/image v0.21.0
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.34.0
|
||||||
golang.org/x/oauth2 v0.23.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
golang.org/x/sync v0.10.0
|
golang.org/x/sync v0.10.0
|
||||||
golang.org/x/sys v0.28.0
|
golang.org/x/sys v0.29.0
|
||||||
golang.org/x/text v0.21.0
|
golang.org/x/text v0.21.0
|
||||||
golang.org/x/tools v0.26.0
|
golang.org/x/tools v0.29.0
|
||||||
google.golang.org/grpc v1.67.1
|
google.golang.org/grpc v1.67.1
|
||||||
google.golang.org/protobuf v1.35.1
|
google.golang.org/protobuf v1.35.1
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
@ -145,8 +142,6 @@ require (
|
|||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // 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/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||||
github.com/ClickHouse/ch-go v0.63.1 // indirect
|
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0 // indirect
|
|
||||||
github.com/DataDog/zstd v1.5.6 // indirect
|
github.com/DataDog/zstd v1.5.6 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||||
@ -191,7 +186,7 @@ require (
|
|||||||
github.com/couchbase/gomemcached v0.3.2 // indirect
|
github.com/couchbase/gomemcached v0.3.2 // indirect
|
||||||
github.com/couchbase/goutils v0.1.2 // indirect
|
github.com/couchbase/goutils v0.1.2 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
@ -204,8 +199,6 @@ require (
|
|||||||
github.com/go-ap/errors v0.0.0-20240910140019-1e9d33cc1568 // indirect
|
github.com/go-ap/errors v0.0.0-20240910140019-1e9d33cc1568 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||||
github.com/go-faster/city v1.0.1 // indirect
|
|
||||||
github.com/go-faster/errors v0.7.1 // indirect
|
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // 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-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
@ -226,7 +219,7 @@ require (
|
|||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
@ -261,6 +254,7 @@ require (
|
|||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
|
github.com/mmcloughlin/avo v0.6.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||||
@ -270,10 +264,9 @@ require (
|
|||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/paulmach/orb v0.11.1 // indirect
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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.1 // indirect
|
||||||
github.com/prometheus/common v0.60.1 // indirect
|
github.com/prometheus/common v0.60.1 // indirect
|
||||||
@ -285,7 +278,6 @@ require (
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
|
||||||
github.com/shopspring/decimal v1.4.0 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
@ -310,13 +302,11 @@ require (
|
|||||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||||
go.etcd.io/bbolt v1.3.11 // indirect
|
go.etcd.io/bbolt v1.3.11 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.17.1 // indirect
|
go.mongodb.org/mongo-driver v1.17.1 // indirect
|
||||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
142
go.sum
142
go.sum
@ -59,10 +59,6 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS
|
|||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/ClickHouse/ch-go v0.63.1 h1:s2JyZvWLTCSAGdtjMBBmAgQQHMco6pawLJMOXi0FODM=
|
|
||||||
github.com/ClickHouse/ch-go v0.63.1/go.mod h1:I1kJJCL3WJcBMGe1m+HVK0+nREaG+JOYYBWjrDrF3R0=
|
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0 h1:L/n/pVVpk95KtkHOiKuSnO7cu2ckeW4gICbbOh5qs74=
|
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys+fBkdD1UMRnXlwmhijhQ=
|
|
||||||
github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY=
|
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.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
|
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
|
||||||
@ -75,8 +71,8 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC
|
|||||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
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 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
github.com/ProtonMail/go-crypto v1.1.4 h1:G5U5asvD5N/6/36oIw3k2bOfBn5XVcZrb7PBjzzKKoE=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
github.com/ProtonMail/go-crypto v1.1.4/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||||
github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4=
|
github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4=
|
||||||
github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4=
|
github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4=
|
||||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||||
@ -85,11 +81,11 @@ github.com/RoaringBitmap/roaring v1.9.4 h1:yhEIoH4YezLYT04s1nHehNO64EKFTop/wBhxv
|
|||||||
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||||
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 h1:BP0HiyNT3AQEYi+if3wkRcIdQFHtsw6xX3Kx0glckgA=
|
||||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2gdDuLqnqveP+mfhUSaBdoBcr2I7Zt0E=
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2gdDuLqnqveP+mfhUSaBdoBcr2I7Zt0E=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
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.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc=
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio=
|
||||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
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 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
@ -109,8 +105,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
|
|||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
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 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
|
||||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
|
github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
|
github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM=
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM=
|
||||||
@ -194,7 +188,6 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
|||||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.3 h1:IGuJjboHjuMLWOGsKZKNxbbn41emOLiHzXPmQZk31fk=
|
github.com/buildkite/terminal-to-html/v3 v3.16.3 h1:IGuJjboHjuMLWOGsKZKNxbbn41emOLiHzXPmQZk31fk=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.3/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
|
github.com/buildkite/terminal-to-html/v3 v3.16.3/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
|
||||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
|
||||||
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
||||||
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
||||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
@ -211,7 +204,6 @@ 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/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
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/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
|
||||||
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
|
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
|
||||||
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
@ -229,16 +221,14 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
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/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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
|
||||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 h1:PdsjTl0Cg+ZJgOx/CFV5NNgO1ThTreqdgKYiDCMHJwA=
|
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 h1:PdsjTl0Cg+ZJgOx/CFV5NNgO1ThTreqdgKYiDCMHJwA=
|
||||||
@ -262,8 +252,8 @@ github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72/go.mod h1:11Gm+ccJ
|
|||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2/go.mod h1:7dvD3GCm7eBw53xZ/lsiq72LqobdMg3ITbMBxnmJmqY=
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2/go.mod h1:7dvD3GCm7eBw53xZ/lsiq72LqobdMg3ITbMBxnmJmqY=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
|
||||||
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
||||||
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
|
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
|
||||||
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
|
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
|
||||||
@ -317,20 +307,16 @@ github.com/go-enry/go-enry/v2 v2.9.1 h1:G9iDteJ/Mc0F4Di5NeQknf83R2OkRbwY9cAYmcqV
|
|||||||
github.com/go-enry/go-enry/v2 v2.9.1/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
|
github.com/go-enry/go-enry/v2 v2.9.1/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
|
||||||
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
|
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
|
||||||
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
|
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
|
||||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
|
||||||
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
|
|
||||||
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
|
|
||||||
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5HqlEWMLIcDmLpIELlG4iGbd0s8iqgPi8=
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5HqlEWMLIcDmLpIELlG4iGbd0s8iqgPi8=
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
|
||||||
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
|
||||||
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 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-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
|
||||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
|
||||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
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-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
|
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
|
||||||
@ -372,8 +358,6 @@ github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/
|
|||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
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 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0 h1:XxQr8AnPORcZkyNd7go5UNLPD3dULN8ixYISlzrlfEQ=
|
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0/go.mod h1:THmudHF1Ixq++J2/UodcJpxUphfyEd77m83TvDtryqE=
|
|
||||||
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
||||||
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
||||||
github.com/go-webauthn/x v0.1.15 h1:eG1OhggBJTkDE8gUeOlGRbRe8E/PSVG26YG4AyFbwkU=
|
github.com/go-webauthn/x v0.1.15 h1:eG1OhggBJTkDE8gUeOlGRbRe8E/PSVG26YG4AyFbwkU=
|
||||||
@ -385,7 +369,6 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
|
|||||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0=
|
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0=
|
||||||
@ -400,8 +383,8 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei
|
|||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I=
|
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I=
|
||||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U=
|
github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
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=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
@ -410,7 +393,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
|||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
@ -497,22 +479,6 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI
|
|||||||
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
|
||||||
github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w=
|
|
||||||
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM=
|
|
||||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
|
||||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
|
||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
|
||||||
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag=
|
|
||||||
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
|
||||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
|
||||||
github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw=
|
|
||||||
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
|
||||||
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
|
|
||||||
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
|
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
@ -533,10 +499,6 @@ github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bB
|
|||||||
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
|
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 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
|
||||||
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
|
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
|
||||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
@ -548,13 +510,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
|
|||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 h1:cTxwSmnaqLoo+4tLukHoB9iqHOu3LmLhRmgUxZo6Vp4=
|
|
||||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
|
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
@ -624,12 +581,13 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
|
|||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
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 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY=
|
||||||
|
github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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 h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM=
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM=
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||||
@ -670,9 +628,6 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
|
|||||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
|
||||||
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
|
||||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
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 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||||
@ -680,8 +635,8 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG
|
|||||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
github.com/pjbgf/sha1cd v0.3.1 h1:Dh2GYdpJnO84lIw0LJwTFXjcNbasP/bklicSznyAaPI=
|
||||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
github.com/pjbgf/sha1cd v0.3.1/go.mod h1:Y8t7jSB/dEI/lQE04A1HVKteqjj9bX5O4+Cex0TCu8s=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
@ -735,8 +690,6 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6Ng
|
|||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
|
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=
|
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||||
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
|
||||||
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
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 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
@ -783,21 +736,19 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
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 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
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 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
|
||||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
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 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
|
||||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||||
@ -823,9 +774,6 @@ github.com/xanzy/go-gitlab v0.112.0 h1:6Z0cqEooCvBMfBIHw+CgO4AKGRV8na/9781xOb0+D
|
|||||||
github.com/xanzy/go-gitlab v0.112.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
github.com/xanzy/go-gitlab v0.112.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
|
||||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
|
||||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
@ -842,9 +790,7 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
|
|||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
||||||
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
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.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.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
@ -863,13 +809,8 @@ github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l
|
|||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
|
||||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
||||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
|
||||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
|
||||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
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 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
@ -886,16 +827,14 @@ 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-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-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.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
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.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
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/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||||
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||||
@ -909,8 +848,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.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.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.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
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-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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@ -922,18 +861,16 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -941,7 +878,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
@ -974,8 +910,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -985,14 +919,12 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
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/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
@ -1000,15 +932,13 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|||||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||||
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
@ -1022,16 +952,14 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
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.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1046,8 +974,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
|||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
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.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
16
main_timezones.go
Normal file
16
main_timezones.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// Golang has the ability to load OS's timezone data from most UNIX systems (https://github.com/golang/go/blob/master/src/time/zoneinfo_unix.go)
|
||||||
|
// Even if the timezone data is missing, users could install the related packages to get it.
|
||||||
|
// But on Windows, although `zoneinfo_windows.go` tries to load the timezone data from Windows registry,
|
||||||
|
// some users still suffer from the issue that the timezone data is missing: https://github.com/go-gitea/gitea/issues/33235
|
||||||
|
// So we import the tzdata package to make sure the timezone data is included in the binary.
|
||||||
|
//
|
||||||
|
// For non-Windows package builders, they could still use the "TAGS=timetzdata" to include the tzdata package in the binary.
|
||||||
|
// If we decided to add the tzdata for other platforms, modify the "go:build" directive above.
|
||||||
|
import _ "time/tzdata"
|
@ -114,6 +114,12 @@ type FindArtifactsOptions struct {
|
|||||||
Status int
|
Status int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (opts FindArtifactsOptions) ToOrders() string {
|
||||||
|
return "id"
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ db.FindOptionsOrder = (*FindArtifactsOptions)(nil)
|
||||||
|
|
||||||
func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
if opts.RepoID > 0 {
|
if opts.RepoID > 0 {
|
||||||
@ -132,7 +138,7 @@ func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
|||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActionArtifactMeta is the meta data of an artifact
|
// ActionArtifactMeta is the meta-data of an artifact
|
||||||
type ActionArtifactMeta struct {
|
type ActionArtifactMeta struct {
|
||||||
ArtifactName string
|
ArtifactName string
|
||||||
FileSize int64
|
FileSize int64
|
||||||
|
@ -69,7 +69,7 @@ func TestAggregateJobStatus(t *testing.T) {
|
|||||||
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
|
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
|
||||||
|
|
||||||
// skipped with other status
|
// skipped with other status
|
||||||
// TODO: need to clarify whether a PR with "skipped" job status is considered as "mergeable" or not.
|
// "all skipped" is also considered as "mergeable" by "services/actions.toCommitStatus", the same as GitHub
|
||||||
{[]Status{StatusSkipped}, StatusSkipped},
|
{[]Status{StatusSkipped}, StatusSkipped},
|
||||||
{[]Status{StatusSkipped, StatusSuccess}, StatusSuccess},
|
{[]Status{StatusSkipped, StatusSuccess}, StatusSuccess},
|
||||||
{[]Status{StatusSkipped, StatusFailure}, StatusFailure},
|
{[]Status{StatusSkipped, StatusFailure}, StatusFailure},
|
||||||
|
@ -167,6 +167,7 @@ func init() {
|
|||||||
|
|
||||||
type FindRunnerOptions struct {
|
type FindRunnerOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
|
IDs []int64
|
||||||
RepoID int64
|
RepoID int64
|
||||||
OwnerID int64 // it will be ignored if RepoID is set
|
OwnerID int64 // it will be ignored if RepoID is set
|
||||||
Sort string
|
Sort string
|
||||||
@ -178,6 +179,14 @@ type FindRunnerOptions struct {
|
|||||||
func (opts FindRunnerOptions) ToConds() builder.Cond {
|
func (opts FindRunnerOptions) ToConds() builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
|
|
||||||
|
if len(opts.IDs) > 0 {
|
||||||
|
if len(opts.IDs) == 1 {
|
||||||
|
cond = cond.And(builder.Eq{"id": opts.IDs[0]})
|
||||||
|
} else {
|
||||||
|
cond = cond.And(builder.In("id", opts.IDs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if opts.RepoID > 0 {
|
if opts.RepoID > 0 {
|
||||||
c := builder.NewCond().And(builder.Eq{"repo_id": opts.RepoID})
|
c := builder.NewCond().And(builder.Eq{"repo_id": opts.RepoID})
|
||||||
if opts.WithAvailable {
|
if opts.WithAvailable {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
@ -51,7 +52,7 @@ func GetRunnerToken(ctx context.Context, token string) (*ActionRunnerToken, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, fmt.Errorf("runner token %q: %w", token, util.ErrNotExist)
|
return nil, fmt.Errorf(`runner token "%s...": %w`, base.TruncateString(token, 3), util.ErrNotExist)
|
||||||
}
|
}
|
||||||
return &runnerToken, nil
|
return &runnerToken, nil
|
||||||
}
|
}
|
||||||
@ -68,19 +69,15 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRunnerToken creates a new active runner token and invalidate all old tokens
|
// NewRunnerTokenWithValue creates a new active runner token and invalidate all old tokens
|
||||||
// ownerID will be ignored and treated as 0 if repoID is non-zero.
|
// ownerID will be ignored and treated as 0 if repoID is non-zero.
|
||||||
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
func NewRunnerTokenWithValue(ctx context.Context, ownerID, repoID int64, token string) (*ActionRunnerToken, error) {
|
||||||
if ownerID != 0 && repoID != 0 {
|
if ownerID != 0 && repoID != 0 {
|
||||||
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
|
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
ownerID = 0
|
ownerID = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := util.CryptoRandomString(40)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
runnerToken := &ActionRunnerToken{
|
runnerToken := &ActionRunnerToken{
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
@ -95,11 +92,19 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.GetEngine(ctx).Insert(runnerToken)
|
_, err := db.GetEngine(ctx).Insert(runnerToken)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||||
|
token, err := util.CryptoRandomString(40)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewRunnerTokenWithValue(ctx, ownerID, repoID, token)
|
||||||
|
}
|
||||||
|
|
||||||
// GetLatestRunnerToken returns the latest runner token
|
// GetLatestRunnerToken returns the latest runner token
|
||||||
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||||
if ownerID != 0 && repoID != 0 {
|
if ownerID != 0 && repoID != 0 {
|
||||||
|
@ -58,6 +58,7 @@ func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data strin
|
|||||||
|
|
||||||
type FindVariablesOpts struct {
|
type FindVariablesOpts struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
|
IDs []int64
|
||||||
RepoID int64
|
RepoID int64
|
||||||
OwnerID int64 // it will be ignored if RepoID is set
|
OwnerID int64 // it will be ignored if RepoID is set
|
||||||
Name string
|
Name string
|
||||||
@ -65,6 +66,15 @@ type FindVariablesOpts struct {
|
|||||||
|
|
||||||
func (opts FindVariablesOpts) ToConds() builder.Cond {
|
func (opts FindVariablesOpts) ToConds() builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
|
|
||||||
|
if len(opts.IDs) > 0 {
|
||||||
|
if len(opts.IDs) == 1 {
|
||||||
|
cond = cond.And(builder.Eq{"id": opts.IDs[0]})
|
||||||
|
} else {
|
||||||
|
cond = cond.And(builder.In("id", opts.IDs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Since we now support instance-level variables,
|
// Since we now support instance-level variables,
|
||||||
// there is no need to check for null values for `owner_id` and `repo_id`
|
// there is no need to check for null values for `owner_id` and `repo_id`
|
||||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||||
@ -85,12 +95,12 @@ func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariab
|
|||||||
return db.Find[ActionVariable](ctx, opts)
|
return db.Find[ActionVariable](ctx, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) {
|
func UpdateVariableCols(ctx context.Context, variable *ActionVariable, cols ...string) (bool, error) {
|
||||||
count, err := db.GetEngine(ctx).ID(variable.ID).Cols("name", "data").
|
variable.Name = strings.ToUpper(variable.Name)
|
||||||
Update(&ActionVariable{
|
count, err := db.GetEngine(ctx).
|
||||||
Name: variable.Name,
|
ID(variable.ID).
|
||||||
Data: variable.Data,
|
Cols(cols...).
|
||||||
})
|
Update(variable)
|
||||||
return count != 0, err
|
return count != 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ func (at ActionType) String() string {
|
|||||||
case ActionRenameRepo:
|
case ActionRenameRepo:
|
||||||
return "rename_repo"
|
return "rename_repo"
|
||||||
case ActionStarRepo:
|
case ActionStarRepo:
|
||||||
return "star_repo"
|
return "star_repo" // will not displayed in feeds.tmpl
|
||||||
case ActionWatchRepo:
|
case ActionWatchRepo:
|
||||||
return "watch_repo"
|
return "watch_repo" // will not displayed in feeds.tmpl
|
||||||
case ActionCommitRepo:
|
case ActionCommitRepo:
|
||||||
return "commit_repo"
|
return "commit_repo"
|
||||||
case ActionCreateIssue:
|
case ActionCreateIssue:
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -337,8 +338,10 @@ func newlyCreatedIssues(ctx context.Context, repoID int64, fromTime time.Time) *
|
|||||||
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||||
And("issue.is_pull = ?", false).
|
And("issue.is_pull = ?", false).
|
||||||
And("issue.created_unix >= ?", fromTime.Unix()).
|
And(builder.Or(
|
||||||
Or("issue.closed_unix >= ?", fromTime.Unix())
|
builder.Gte{"issue.created_unix": fromTime.Unix()},
|
||||||
|
builder.Gte{"issue.closed_unix": fromTime.Unix()},
|
||||||
|
))
|
||||||
|
|
||||||
return sess
|
return sess
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/keybase/go-crypto/openpgp"
|
"github.com/ProtonMail/go-crypto/openpgp"
|
||||||
"github.com/keybase/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -141,7 +141,11 @@ func parseGPGKey(ctx context.Context, ownerID int64, e *openpgp.Entity, verified
|
|||||||
// Parse Subkeys
|
// Parse Subkeys
|
||||||
subkeys := make([]*GPGKey, len(e.Subkeys))
|
subkeys := make([]*GPGKey, len(e.Subkeys))
|
||||||
for i, k := range e.Subkeys {
|
for i, k := range e.Subkeys {
|
||||||
subs, err := parseSubGPGKey(ownerID, pubkey.KeyIdString(), k.PublicKey, expiry)
|
subkeyExpiry := expiry
|
||||||
|
if k.Sig.KeyLifetimeSecs != nil {
|
||||||
|
subkeyExpiry = k.PublicKey.CreationTime.Add(time.Duration(*k.Sig.KeyLifetimeSecs) * time.Second)
|
||||||
|
}
|
||||||
|
subs, err := parseSubGPGKey(ownerID, pubkey.KeyIdString(), k.PublicKey, subkeyExpiry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrGPGKeyParsing{ParseError: err}
|
return nil, ErrGPGKeyParsing{ParseError: err}
|
||||||
}
|
}
|
||||||
@ -156,7 +160,7 @@ func parseGPGKey(ctx context.Context, ownerID int64, e *openpgp.Entity, verified
|
|||||||
|
|
||||||
emails := make([]*user_model.EmailAddress, 0, len(e.Identities))
|
emails := make([]*user_model.EmailAddress, 0, len(e.Identities))
|
||||||
for _, ident := range e.Identities {
|
for _, ident := range e.Identities {
|
||||||
if ident.Revocation != nil {
|
if ident.Revoked(time.Now()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
email := strings.ToLower(strings.TrimSpace(ident.UserId.Email))
|
email := strings.ToLower(strings.TrimSpace(ident.UserId.Email))
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
"github.com/keybase/go-crypto/openpgp"
|
"github.com/ProtonMail/go-crypto/openpgp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// __________________ ________ ____ __.
|
// __________________ ________ ____ __.
|
||||||
@ -83,12 +83,12 @@ func AddGPGKey(ctx context.Context, ownerID int64, content, token, signature str
|
|||||||
verified := false
|
verified := false
|
||||||
// Handle provided signature
|
// Handle provided signature
|
||||||
if signature != "" {
|
if signature != "" {
|
||||||
signer, err := openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token), strings.NewReader(signature))
|
signer, err := openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token), strings.NewReader(signature), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\n"), strings.NewReader(signature))
|
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\n"), strings.NewReader(signature), nil)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature))
|
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to validate token signature. Error: %v", err)
|
log.Error("Unable to validate token signature. Error: %v", err)
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/keybase/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// __________________ ________ ____ __.
|
// __________________ ________ ____ __.
|
||||||
|
@ -13,9 +13,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/keybase/go-crypto/openpgp"
|
"github.com/ProtonMail/go-crypto/openpgp"
|
||||||
"github.com/keybase/go-crypto/openpgp/armor"
|
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||||
"github.com/keybase/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// __________________ ________ ____ __.
|
// __________________ ________ ____ __.
|
||||||
@ -80,7 +80,7 @@ func base64DecPubKey(content string) (*packet.PublicKey, error) {
|
|||||||
return pkey, nil
|
return pkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getExpiryTime extract the expire time of primary key based on sig
|
// getExpiryTime extract the expiry time of primary key based on sig
|
||||||
func getExpiryTime(e *openpgp.Entity) time.Time {
|
func getExpiryTime(e *openpgp.Entity) time.Time {
|
||||||
expiry := time.Time{}
|
expiry := time.Time{}
|
||||||
// Extract self-sign for expire date based on : https://github.com/golang/crypto/blob/master/openpgp/keys.go#L165
|
// Extract self-sign for expire date based on : https://github.com/golang/crypto/blob/master/openpgp/keys.go#L165
|
||||||
@ -88,12 +88,12 @@ func getExpiryTime(e *openpgp.Entity) time.Time {
|
|||||||
for _, ident := range e.Identities {
|
for _, ident := range e.Identities {
|
||||||
if selfSig == nil {
|
if selfSig == nil {
|
||||||
selfSig = ident.SelfSignature
|
selfSig = ident.SelfSignature
|
||||||
} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
|
} else if ident.SelfSignature != nil && ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
|
||||||
selfSig = ident.SelfSignature
|
selfSig = ident.SelfSignature
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if selfSig.KeyLifetimeSecs != nil {
|
if selfSig != nil && selfSig.KeyLifetimeSecs != nil {
|
||||||
expiry = e.PrimaryKey.CreationTime.Add(time.Duration(*selfSig.KeyLifetimeSecs) * time.Second)
|
expiry = e.PrimaryKey.CreationTime.Add(time.Duration(*selfSig.KeyLifetimeSecs) * time.Second)
|
||||||
}
|
}
|
||||||
return expiry
|
return expiry
|
||||||
|
@ -13,7 +13,8 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/keybase/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp"
|
||||||
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -403,3 +404,25 @@ func TestTryGetKeyIDFromSignature(t *testing.T) {
|
|||||||
IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c},
|
IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseGPGKey(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
assert.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "email1@example.com", IsActivated: true}))
|
||||||
|
|
||||||
|
// create a key for test email
|
||||||
|
e, err := openpgp.NewEntity("name", "comment", "email1@example.com", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
k, err := parseGPGKey(db.DefaultContext, 1, e, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, k.KeyID)
|
||||||
|
assert.NotEmpty(t, k.Emails) // the key is valid, matches the email
|
||||||
|
|
||||||
|
// then revoke the key
|
||||||
|
for _, id := range e.Identities {
|
||||||
|
id.Revocations = append(id.Revocations, &packet.Signature{RevocationReason: util.ToPointer(packet.KeyCompromised)})
|
||||||
|
}
|
||||||
|
k, err = parseGPGKey(db.DefaultContext, 1, e, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, k.KeyID)
|
||||||
|
assert.Empty(t, k.Emails) // the key is revoked, matches no email
|
||||||
|
}
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
name: job2
|
name: job2
|
||||||
attempt: 1
|
attempt: 1
|
||||||
job_id: job2
|
job_id: job2
|
||||||
needs: [job1]
|
needs: '["job1"]'
|
||||||
task_id: 51
|
task_id: 51
|
||||||
status: 5
|
status: 5
|
||||||
started: 1683636528
|
started: 1683636528
|
||||||
|
@ -96,3 +96,14 @@
|
|||||||
num_issues: 0
|
num_issues: 0
|
||||||
num_closed_issues: 0
|
num_closed_issues: 0
|
||||||
archived_unix: 0
|
archived_unix: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 10
|
||||||
|
repo_id: 3
|
||||||
|
org_id: 0
|
||||||
|
name: repo3label1
|
||||||
|
color: '#112233'
|
||||||
|
exclusive: false
|
||||||
|
num_issues: 0
|
||||||
|
num_closed_issues: 0
|
||||||
|
archived_unix: 0
|
||||||
|
@ -2,23 +2,23 @@
|
|||||||
id: 1
|
id: 1
|
||||||
repo_id: 4
|
repo_id: 4
|
||||||
name_pattern: /v.+/
|
name_pattern: /v.+/
|
||||||
allowlist_user_i_ds: []
|
allowlist_user_i_ds: "[]"
|
||||||
allowlist_team_i_ds: []
|
allowlist_team_i_ds: "[]"
|
||||||
created_unix: 1715596037
|
created_unix: 1715596037
|
||||||
updated_unix: 1715596037
|
updated_unix: 1715596037
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
repo_id: 1
|
repo_id: 1
|
||||||
name_pattern: v-*
|
name_pattern: v-*
|
||||||
allowlist_user_i_ds: []
|
allowlist_user_i_ds: "[]"
|
||||||
allowlist_team_i_ds: []
|
allowlist_team_i_ds: "[]"
|
||||||
created_unix: 1715596037
|
created_unix: 1715596037
|
||||||
updated_unix: 1715596037
|
updated_unix: 1715596037
|
||||||
-
|
-
|
||||||
id: 3
|
id: 3
|
||||||
repo_id: 1
|
repo_id: 1
|
||||||
name_pattern: v-1.1
|
name_pattern: v-1.1
|
||||||
allowlist_user_i_ds: [2]
|
allowlist_user_i_ds: "[2]"
|
||||||
allowlist_team_i_ds: []
|
allowlist_team_i_ds: "[]"
|
||||||
created_unix: 1715596037
|
created_unix: 1715596037
|
||||||
updated_unix: 1715596037
|
updated_unix: 1715596037
|
||||||
|
@ -167,6 +167,9 @@ func GetBranch(ctx context.Context, repoID int64, branchName string) (*Branch, e
|
|||||||
BranchName: branchName,
|
BranchName: branchName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// FIXME: this design is not right: it doesn't check `branch.IsDeleted`, it doesn't make sense to make callers to check IsDeleted again and again.
|
||||||
|
// It causes inconsistency with `GetBranches` and `git.GetBranch`, and will lead to strange bugs
|
||||||
|
// In the future, there should be 2 functions: `GetBranchExisting` and `GetBranchWithDeleted`
|
||||||
return &branch, nil
|
return &branch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,6 +443,8 @@ type FindRecentlyPushedNewBranchesOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RecentlyPushedNewBranch struct {
|
type RecentlyPushedNewBranch struct {
|
||||||
|
BranchRepo *repo_model.Repository
|
||||||
|
BranchName string
|
||||||
BranchDisplayName string
|
BranchDisplayName string
|
||||||
BranchLink string
|
BranchLink string
|
||||||
BranchCompareURL string
|
BranchCompareURL string
|
||||||
@ -540,7 +545,9 @@ func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, o
|
|||||||
branchDisplayName = fmt.Sprintf("%s:%s", branch.Repo.FullName(), branchDisplayName)
|
branchDisplayName = fmt.Sprintf("%s:%s", branch.Repo.FullName(), branchDisplayName)
|
||||||
}
|
}
|
||||||
newBranches = append(newBranches, &RecentlyPushedNewBranch{
|
newBranches = append(newBranches, &RecentlyPushedNewBranch{
|
||||||
|
BranchRepo: branch.Repo,
|
||||||
BranchDisplayName: branchDisplayName,
|
BranchDisplayName: branchDisplayName,
|
||||||
|
BranchName: branch.Name,
|
||||||
BranchLink: fmt.Sprintf("%s/src/branch/%s", branch.Repo.Link(), util.PathEscapeSegments(branch.Name)),
|
BranchLink: fmt.Sprintf("%s/src/branch/%s", branch.Repo.Link(), util.PathEscapeSegments(branch.Name)),
|
||||||
BranchCompareURL: branch.Repo.ComposeBranchCompareURL(opts.BaseRepo, branch.Name),
|
BranchCompareURL: branch.Repo.ComposeBranchCompareURL(opts.BaseRepo, branch.Name),
|
||||||
CommitTime: branch.CommitTime,
|
CommitTime: branch.CommitTime,
|
||||||
|
@ -197,6 +197,20 @@ func (t CommentType) HasMailReplySupport() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t CommentType) CountedAsConversation() bool {
|
||||||
|
for _, ct := range ConversationCountedCommentType() {
|
||||||
|
if t == ct {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConversationCountedCommentType returns the comment types that are counted as a conversation
|
||||||
|
func ConversationCountedCommentType() []CommentType {
|
||||||
|
return []CommentType{CommentTypeComment, CommentTypeReview}
|
||||||
|
}
|
||||||
|
|
||||||
// RoleInRepo presents the user's participation in the repo
|
// RoleInRepo presents the user's participation in the repo
|
||||||
type RoleInRepo string
|
type RoleInRepo string
|
||||||
|
|
||||||
@ -893,7 +907,7 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment
|
|||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case CommentTypeComment:
|
case CommentTypeComment:
|
||||||
if _, err = db.Exec(ctx, "UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", opts.Issue.ID); err != nil {
|
if err := UpdateIssueNumComments(ctx, opts.Issue.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -1182,8 +1196,8 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment.Type == CommentTypeComment {
|
if comment.Type.CountedAsConversation() {
|
||||||
if _, err := e.ID(comment.IssueID).Decr("num_comments").Update(new(Issue)); err != nil {
|
if err := UpdateIssueNumComments(ctx, comment.IssueID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1300,6 +1314,21 @@ func (c *Comment) HasOriginalAuthor() bool {
|
|||||||
return c.OriginalAuthor != "" && c.OriginalAuthorID != 0
|
return c.OriginalAuthor != "" && c.OriginalAuthorID != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpdateIssueNumCommentsBuilder(issueID int64) *builder.Builder {
|
||||||
|
subQuery := builder.Select("COUNT(*)").From("`comment`").Where(
|
||||||
|
builder.Eq{"issue_id": issueID}.And(
|
||||||
|
builder.In("`type`", ConversationCountedCommentType()),
|
||||||
|
))
|
||||||
|
|
||||||
|
return builder.Update(builder.Eq{"num_comments": subQuery}).
|
||||||
|
From("`issue`").Where(builder.Eq{"id": issueID})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateIssueNumComments(ctx context.Context, issueID int64) error {
|
||||||
|
_, err := db.GetEngine(ctx).Exec(UpdateIssueNumCommentsBuilder(issueID))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// InsertIssueComments inserts many comments of issues.
|
// InsertIssueComments inserts many comments of issues.
|
||||||
func InsertIssueComments(ctx context.Context, comments []*Comment) error {
|
func InsertIssueComments(ctx context.Context, comments []*Comment) error {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
@ -1332,8 +1361,7 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, issueID := range issueIDs {
|
for _, issueID := range issueIDs {
|
||||||
if _, err := db.Exec(ctx, "UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ? AND `type`=?) WHERE id = ?",
|
if err := UpdateIssueNumComments(ctx, issueID); err != nil {
|
||||||
issueID, CommentTypeComment, issueID); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,11 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
|
|||||||
ids = append(ids, comment.ReviewID)
|
ids = append(ids, comment.ReviewID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(ids) > 0 {
|
||||||
if err := e.In("id", ids).Find(&reviews); err != nil {
|
if err := e.In("id", ids).Find(&reviews); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
|
@ -97,3 +97,12 @@ func TestMigrate_InsertIssueComments(t *testing.T) {
|
|||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &issues_model.Issue{})
|
unittest.CheckConsistencyFor(t, &issues_model.Issue{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_UpdateIssueNumComments(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
|
||||||
|
assert.NoError(t, issues_model.UpdateIssueNumComments(db.DefaultContext, issue2.ID))
|
||||||
|
issue2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
assert.EqualValues(t, 1, issue2.NumComments)
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/container"
|
"code.gitea.io/gitea/modules/container"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
@ -531,6 +532,45 @@ func GetIssueByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
|||||||
return issue, nil
|
return issue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isPullToCond(isPull optional.Option[bool]) builder.Cond {
|
||||||
|
if isPull.Has() {
|
||||||
|
return builder.Eq{"is_pull": isPull.Value()}
|
||||||
|
}
|
||||||
|
return builder.NewCond()
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindLatestUpdatedIssues(ctx context.Context, repoID int64, isPull optional.Option[bool], pageSize int) (IssueList, error) {
|
||||||
|
issues := make([]*Issue, 0, pageSize)
|
||||||
|
err := db.GetEngine(ctx).Where("repo_id = ?", repoID).
|
||||||
|
And(isPullToCond(isPull)).
|
||||||
|
OrderBy("updated_unix DESC").
|
||||||
|
Limit(pageSize).
|
||||||
|
Find(&issues)
|
||||||
|
return issues, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindIssuesSuggestionByKeyword(ctx context.Context, repoID int64, keyword string, isPull optional.Option[bool], excludedID int64, pageSize int) (IssueList, error) {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
if excludedID > 0 {
|
||||||
|
cond = cond.And(builder.Neq{"`id`": excludedID})
|
||||||
|
}
|
||||||
|
|
||||||
|
// It seems that GitHub searches both title and content (maybe sorting by the search engine's ranking system?)
|
||||||
|
// The first PR (https://github.com/go-gitea/gitea/pull/32327) uses "search indexer" to search "name(title) + content"
|
||||||
|
// But it seems that searching "content" (especially LIKE by DB engine) generates worse (unusable) results.
|
||||||
|
// So now (https://github.com/go-gitea/gitea/pull/33538) it only searches "name(title)", leave the improvements to the future.
|
||||||
|
cond = cond.And(db.BuildCaseInsensitiveLike("`name`", keyword))
|
||||||
|
|
||||||
|
issues := make([]*Issue, 0, pageSize)
|
||||||
|
err := db.GetEngine(ctx).Where("repo_id = ?", repoID).
|
||||||
|
And(isPullToCond(isPull)).
|
||||||
|
And(cond).
|
||||||
|
OrderBy("updated_unix DESC, `index` DESC").
|
||||||
|
Limit(pageSize).
|
||||||
|
Find(&issues)
|
||||||
|
return issues, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetIssueWithAttrsByIndex returns issue by index in a repository.
|
// GetIssueWithAttrsByIndex returns issue by index in a repository.
|
||||||
func GetIssueWithAttrsByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
func GetIssueWithAttrsByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
||||||
issue, err := GetIssueByIndex(ctx, repoID, index)
|
issue, err := GetIssueByIndex(ctx, repoID, index)
|
||||||
|
@ -38,13 +38,30 @@ func (issue *Issue) projectID(ctx context.Context) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProjectColumnID return project column id if issue was assigned to one
|
// ProjectColumnID return project column id if issue was assigned to one
|
||||||
func (issue *Issue) ProjectColumnID(ctx context.Context) int64 {
|
func (issue *Issue) ProjectColumnID(ctx context.Context) (int64, error) {
|
||||||
var ip project_model.ProjectIssue
|
var ip project_model.ProjectIssue
|
||||||
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
|
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
|
||||||
if err != nil || !has {
|
if err != nil {
|
||||||
return 0
|
return 0, err
|
||||||
|
} else if !has {
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
return ip.ProjectColumnID
|
return ip.ProjectColumnID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadProjectIssueColumnMap(ctx context.Context, projectID, defaultColumnID int64) (map[int64]int64, error) {
|
||||||
|
issues := make([]project_model.ProjectIssue, 0)
|
||||||
|
if err := db.GetEngine(ctx).Where("project_id=?", projectID).Find(&issues); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := make(map[int64]int64, len(issues))
|
||||||
|
for _, issue := range issues {
|
||||||
|
if issue.ProjectColumnID == 0 {
|
||||||
|
issue.ProjectColumnID = defaultColumnID
|
||||||
|
}
|
||||||
|
result[issue.IssueID] = issue.ProjectColumnID
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssuesFromColumn load issues assigned to this column
|
// LoadIssuesFromColumn load issues assigned to this column
|
||||||
@ -59,11 +76,11 @@ func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column, opts *Is
|
|||||||
}
|
}
|
||||||
|
|
||||||
if b.Default {
|
if b.Default {
|
||||||
issues, err := Issues(ctx, &IssuesOptions{
|
issues, err := Issues(ctx, opts.Copy(func(o *IssuesOptions) {
|
||||||
ProjectColumnID: db.NoConditionID,
|
o.ProjectColumnID = db.NoConditionID
|
||||||
ProjectID: b.ProjectID,
|
o.ProjectID = b.ProjectID
|
||||||
SortType: "project-column-sorting",
|
o.SortType = "project-column-sorting"
|
||||||
})
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -77,19 +94,6 @@ func LoadIssuesFromColumn(ctx context.Context, b *project_model.Column, opts *Is
|
|||||||
return issueList, nil
|
return issueList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssuesFromColumnList load issues assigned to the columns
|
|
||||||
func LoadIssuesFromColumnList(ctx context.Context, bs project_model.ColumnList, opts *IssuesOptions) (map[int64]IssueList, error) {
|
|
||||||
issuesMap := make(map[int64]IssueList, len(bs))
|
|
||||||
for i := range bs {
|
|
||||||
il, err := LoadIssuesFromColumn(ctx, bs[i], opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
issuesMap[bs[i].ID] = il
|
|
||||||
}
|
|
||||||
return issuesMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IssueAssignOrRemoveProject changes the project associated with an issue
|
// IssueAssignOrRemoveProject changes the project associated with an issue
|
||||||
// If newProjectID is 0, the issue is removed from the project
|
// If newProjectID is 0, the issue is removed from the project
|
||||||
func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID, newColumnID int64) error {
|
func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID, newColumnID int64) error {
|
||||||
@ -110,7 +114,7 @@ func IssueAssignOrRemoveProject(ctx context.Context, issue *Issue, doer *user_mo
|
|||||||
return util.NewPermissionDeniedErrorf("issue %d can't be accessed by project %d", issue.ID, newProject.ID)
|
return util.NewPermissionDeniedErrorf("issue %d can't be accessed by project %d", issue.ID, newProject.ID)
|
||||||
}
|
}
|
||||||
if newColumnID == 0 {
|
if newColumnID == 0 {
|
||||||
newDefaultColumn, err := newProject.GetDefaultColumn(ctx)
|
newDefaultColumn, err := newProject.MustDefaultColumn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,9 @@ type IssuesOptions struct { //nolint
|
|||||||
// prioritize issues from this repo
|
// prioritize issues from this repo
|
||||||
PriorityRepoID int64
|
PriorityRepoID int64
|
||||||
IsArchived optional.Option[bool]
|
IsArchived optional.Option[bool]
|
||||||
Org *organization.Organization // issues permission scope
|
Owner *user_model.User // issues permission scope, it could be an organization or a user
|
||||||
Team *organization.Team // issues permission scope
|
Team *organization.Team // issues permission scope
|
||||||
User *user_model.User // issues permission scope
|
Doer *user_model.User // issues permission scope
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of the options.
|
// Copy returns a copy of the options.
|
||||||
@ -273,8 +273,12 @@ func applyConditions(sess *xorm.Session, opts *IssuesOptions) {
|
|||||||
|
|
||||||
applyLabelsCondition(sess, opts)
|
applyLabelsCondition(sess, opts)
|
||||||
|
|
||||||
if opts.User != nil {
|
if opts.Owner != nil {
|
||||||
sess.And(issuePullAccessibleRepoCond("issue.repo_id", opts.User.ID, opts.Org, opts.Team, opts.IsPull.Value()))
|
sess.And(repo_model.UserOwnedRepoCond(opts.Owner.ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Doer != nil && !opts.Doer.IsAdmin {
|
||||||
|
sess.And(issuePullAccessibleRepoCond("issue.repo_id", opts.Doer.ID, opts.Owner, opts.Team, opts.IsPull.Value()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,20 +325,20 @@ func teamUnitsRepoCond(id string, userID, orgID, teamID int64, units ...unit.Typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
|
// issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
|
||||||
func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organization.Organization, team *organization.Team, isPull bool) builder.Cond {
|
func issuePullAccessibleRepoCond(repoIDstr string, userID int64, owner *user_model.User, team *organization.Team, isPull bool) builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
unitType := unit.TypeIssues
|
unitType := unit.TypeIssues
|
||||||
if isPull {
|
if isPull {
|
||||||
unitType = unit.TypePullRequests
|
unitType = unit.TypePullRequests
|
||||||
}
|
}
|
||||||
if org != nil {
|
if owner != nil && owner.IsOrganization() {
|
||||||
if team != nil {
|
if team != nil {
|
||||||
cond = cond.And(teamUnitsRepoCond(repoIDstr, userID, org.ID, team.ID, unitType)) // special team member repos
|
cond = cond.And(teamUnitsRepoCond(repoIDstr, userID, owner.ID, team.ID, unitType)) // special team member repos
|
||||||
} else {
|
} else {
|
||||||
cond = cond.And(
|
cond = cond.And(
|
||||||
builder.Or(
|
builder.Or(
|
||||||
repo_model.UserOrgUnitRepoCond(repoIDstr, userID, org.ID, unitType), // team member repos
|
repo_model.UserOrgUnitRepoCond(repoIDstr, userID, owner.ID, unitType), // team member repos
|
||||||
repo_model.UserOrgPublicUnitRepoCond(userID, org.ID), // user org public non-member repos, TODO: check repo has issues
|
repo_model.UserOrgPublicUnitRepoCond(userID, owner.ID), // user org public non-member repos, TODO: check repo has issues
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -349,6 +349,17 @@ func GetLabelIDsInRepoByNames(ctx context.Context, repoID int64, labelNames []st
|
|||||||
Find(&labelIDs)
|
Find(&labelIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLabelIDsInOrgByNames returns a list of labelIDs by names in a given org.
|
||||||
|
func GetLabelIDsInOrgByNames(ctx context.Context, orgID int64, labelNames []string) ([]int64, error) {
|
||||||
|
labelIDs := make([]int64, 0, len(labelNames))
|
||||||
|
return labelIDs, db.GetEngine(ctx).Table("label").
|
||||||
|
Where("org_id = ?", orgID).
|
||||||
|
In("name", labelNames).
|
||||||
|
Asc("name").
|
||||||
|
Cols("id").
|
||||||
|
Find(&labelIDs)
|
||||||
|
}
|
||||||
|
|
||||||
// BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names
|
// BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names
|
||||||
func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
|
func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
|
||||||
return builder.Select("issue_label.issue_id").
|
return builder.Select("issue_label.issue_id").
|
||||||
|
@ -301,7 +301,7 @@ func (pr *PullRequest) LoadRequestedReviewers(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
reviews, err := GetReviewsByIssueID(ctx, pr.Issue.ID)
|
reviews, _, err := GetReviewsByIssueID(ctx, pr.Issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -320,7 +320,7 @@ func (pr *PullRequest) LoadRequestedReviewers(ctx context.Context) error {
|
|||||||
|
|
||||||
// LoadRequestedReviewersTeams loads the requested reviewers teams.
|
// LoadRequestedReviewersTeams loads the requested reviewers teams.
|
||||||
func (pr *PullRequest) LoadRequestedReviewersTeams(ctx context.Context) error {
|
func (pr *PullRequest) LoadRequestedReviewersTeams(ctx context.Context) error {
|
||||||
reviews, err := GetReviewsByIssueID(ctx, pr.Issue.ID)
|
reviews, _, err := GetReviewsByIssueID(ctx, pr.Issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -639,6 +639,10 @@ func InsertReviews(ctx context.Context, reviews []*Review) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := UpdateIssueNumComments(ctx, review.IssueID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
|
@ -5,6 +5,8 @@ package issues
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"slices"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
organization_model "code.gitea.io/gitea/models/organization"
|
organization_model "code.gitea.io/gitea/models/organization"
|
||||||
@ -153,43 +155,60 @@ func CountReviews(ctx context.Context, opts FindReviewOptions) (int64, error) {
|
|||||||
return db.GetEngine(ctx).Where(opts.toCond()).Count(&Review{})
|
return db.GetEngine(ctx).Where(opts.toCond()).Count(&Review{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReviewersFromOriginalAuthorsByIssueID gets the latest review of each original authors for a pull request
|
|
||||||
func GetReviewersFromOriginalAuthorsByIssueID(ctx context.Context, issueID int64) (ReviewList, error) {
|
|
||||||
reviews := make([]*Review, 0, 10)
|
|
||||||
|
|
||||||
// Get latest review of each reviewer, sorted in order they were made
|
|
||||||
if err := db.GetEngine(ctx).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND original_author_id <> 0 GROUP BY issue_id, original_author_id) ORDER BY review.updated_unix ASC",
|
|
||||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest).
|
|
||||||
Find(&reviews); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return reviews, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetReviewsByIssueID gets the latest review of each reviewer for a pull request
|
// GetReviewsByIssueID gets the latest review of each reviewer for a pull request
|
||||||
func GetReviewsByIssueID(ctx context.Context, issueID int64) (ReviewList, error) {
|
// The first returned parameter is the latest review of each individual reviewer or team
|
||||||
|
// The second returned parameter is the latest review of each original author which is migrated from other systems
|
||||||
|
// The reviews are sorted by updated time
|
||||||
|
func GetReviewsByIssueID(ctx context.Context, issueID int64) (latestReviews, migratedOriginalReviews ReviewList, err error) {
|
||||||
reviews := make([]*Review, 0, 10)
|
reviews := make([]*Review, 0, 10)
|
||||||
|
|
||||||
sess := db.GetEngine(ctx)
|
// Get all reviews for the issue id
|
||||||
|
if err := db.GetEngine(ctx).Where("issue_id=?", issueID).OrderBy("updated_unix ASC").Find(&reviews); err != nil {
|
||||||
// Get latest review of each reviewer, sorted in order they were made
|
return nil, nil, err
|
||||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC",
|
|
||||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, false).
|
|
||||||
Find(&reviews); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filter them in memory to get the latest review of each reviewer
|
||||||
|
// Since the reviews should not be too many for one issue, less than 100 commonly, it's acceptable to do this in memory
|
||||||
|
// And since there are too less indexes in review table, it will be very slow to filter in the database
|
||||||
|
reviewersMap := make(map[int64][]*Review) // key is reviewer id
|
||||||
|
originalReviewersMap := make(map[int64][]*Review) // key is original author id
|
||||||
|
reviewTeamsMap := make(map[int64][]*Review) // key is reviewer team id
|
||||||
|
countedReivewTypes := []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest}
|
||||||
|
for _, review := range reviews {
|
||||||
|
if review.ReviewerTeamID == 0 && slices.Contains(countedReivewTypes, review.Type) && !review.Dismissed {
|
||||||
|
if review.OriginalAuthorID != 0 {
|
||||||
|
originalReviewersMap[review.OriginalAuthorID] = append(originalReviewersMap[review.OriginalAuthorID], review)
|
||||||
|
} else {
|
||||||
|
reviewersMap[review.ReviewerID] = append(reviewersMap[review.ReviewerID], review)
|
||||||
|
}
|
||||||
|
} else if review.ReviewerTeamID != 0 && review.OriginalAuthorID == 0 {
|
||||||
|
reviewTeamsMap[review.ReviewerTeamID] = append(reviewTeamsMap[review.ReviewerTeamID], review)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
individualReviews := make([]*Review, 0, 10)
|
||||||
|
for _, reviews := range reviewersMap {
|
||||||
|
individualReviews = append(individualReviews, reviews[len(reviews)-1])
|
||||||
|
}
|
||||||
|
sort.Slice(individualReviews, func(i, j int) bool {
|
||||||
|
return individualReviews[i].UpdatedUnix < individualReviews[j].UpdatedUnix
|
||||||
|
})
|
||||||
|
|
||||||
|
originalReviews := make([]*Review, 0, 10)
|
||||||
|
for _, reviews := range originalReviewersMap {
|
||||||
|
originalReviews = append(originalReviews, reviews[len(reviews)-1])
|
||||||
|
}
|
||||||
|
sort.Slice(originalReviews, func(i, j int) bool {
|
||||||
|
return originalReviews[i].UpdatedUnix < originalReviews[j].UpdatedUnix
|
||||||
|
})
|
||||||
|
|
||||||
teamReviewRequests := make([]*Review, 0, 5)
|
teamReviewRequests := make([]*Review, 0, 5)
|
||||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id <> 0 AND original_author_id = 0 GROUP BY issue_id, reviewer_team_id) ORDER BY review.updated_unix ASC",
|
for _, reviews := range reviewTeamsMap {
|
||||||
issueID).
|
teamReviewRequests = append(teamReviewRequests, reviews[len(reviews)-1])
|
||||||
Find(&teamReviewRequests); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
sort.Slice(teamReviewRequests, func(i, j int) bool {
|
||||||
|
return teamReviewRequests[i].UpdatedUnix < teamReviewRequests[j].UpdatedUnix
|
||||||
|
})
|
||||||
|
|
||||||
if len(teamReviewRequests) > 0 {
|
return append(individualReviews, teamReviewRequests...), originalReviews, nil
|
||||||
reviews = append(reviews, teamReviewRequests...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return reviews, nil
|
|
||||||
}
|
}
|
||||||
|
@ -162,8 +162,9 @@ func TestGetReviewersByIssueID(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
allReviews, err := issues_model.GetReviewsByIssueID(db.DefaultContext, issue.ID)
|
allReviews, migratedReviews, err := issues_model.GetReviewsByIssueID(db.DefaultContext, issue.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, migratedReviews)
|
||||||
for _, review := range allReviews {
|
for _, review := range allReviews {
|
||||||
assert.NoError(t, review.LoadReviewer(db.DefaultContext))
|
assert.NoError(t, review.LoadReviewer(db.DefaultContext))
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func (s Stopwatch) Seconds() int64 {
|
|||||||
|
|
||||||
// Duration returns a human-readable duration string based on local server time
|
// Duration returns a human-readable duration string based on local server time
|
||||||
func (s Stopwatch) Duration() string {
|
func (s Stopwatch) Duration() string {
|
||||||
return util.SecToTime(s.Seconds())
|
return util.SecToHours(s.Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, exists bool, err error) {
|
func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, exists bool, err error) {
|
||||||
@ -201,7 +201,7 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
|
|||||||
Doer: user,
|
Doer: user,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
Content: util.SecToTime(timediff),
|
Content: util.SecToHours(timediff),
|
||||||
Type: CommentTypeStopTracking,
|
Type: CommentTypeStopTracking,
|
||||||
TimeID: tt.ID,
|
TimeID: tt.ID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -248,6 +248,18 @@ func GetPackageByID(ctx context.Context, packageID int64) (*Package, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePackageNameByID updates the package's name, it is only for internal usage, for example: rename some legacy packages
|
||||||
|
func UpdatePackageNameByID(ctx context.Context, ownerID int64, packageType Type, packageID int64, name string) error {
|
||||||
|
var cond builder.Cond = builder.Eq{
|
||||||
|
"package.id": packageID,
|
||||||
|
"package.owner_id": ownerID,
|
||||||
|
"package.type": packageType,
|
||||||
|
"package.is_internal": false,
|
||||||
|
}
|
||||||
|
_, err := db.GetEngine(ctx).Where(cond).Update(&Package{Name: name, LowerName: strings.ToLower(name)})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// GetPackageByName gets a package by name
|
// GetPackageByName gets a package by name
|
||||||
func GetPackageByName(ctx context.Context, ownerID int64, packageType Type, name string) (*Package, error) {
|
func GetPackageByName(ctx context.Context, ownerID int64, packageType Type, name string) (*Package, error) {
|
||||||
var cond builder.Cond = builder.Eq{
|
var cond builder.Cond = builder.Eq{
|
||||||
|
@ -48,6 +48,8 @@ type Column struct {
|
|||||||
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
||||||
CreatorID int64 `xorm:"NOT NULL"`
|
CreatorID int64 `xorm:"NOT NULL"`
|
||||||
|
|
||||||
|
NumIssues int64 `xorm:"-"`
|
||||||
|
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||||
}
|
}
|
||||||
@ -57,20 +59,6 @@ func (Column) TableName() string {
|
|||||||
return "project_board" // TODO: the legacy table name should be project_column
|
return "project_board" // TODO: the legacy table name should be project_column
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumIssues return counter of all issues assigned to the column
|
|
||||||
func (c *Column) NumIssues(ctx context.Context) int {
|
|
||||||
total, err := db.GetEngine(ctx).Table("project_issue").
|
|
||||||
Where("project_id=?", c.ProjectID).
|
|
||||||
And("project_board_id=?", c.ID).
|
|
||||||
GroupBy("issue_id").
|
|
||||||
Cols("issue_id").
|
|
||||||
Count()
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return int(total)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Column) GetIssues(ctx context.Context) ([]*ProjectIssue, error) {
|
func (c *Column) GetIssues(ctx context.Context) ([]*ProjectIssue, error) {
|
||||||
issues := make([]*ProjectIssue, 0, 5)
|
issues := make([]*ProjectIssue, 0, 5)
|
||||||
if err := db.GetEngine(ctx).Where("project_id=?", c.ProjectID).
|
if err := db.GetEngine(ctx).Where("project_id=?", c.ProjectID).
|
||||||
@ -192,7 +180,7 @@ func deleteColumnByID(ctx context.Context, columnID int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defaultColumn, err := project.GetDefaultColumn(ctx)
|
defaultColumn, err := project.MustDefaultColumn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -257,8 +245,8 @@ func (p *Project) GetColumns(ctx context.Context) (ColumnList, error) {
|
|||||||
return columns, nil
|
return columns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultColumn return default column and ensure only one exists
|
// getDefaultColumn return default column and ensure only one exists
|
||||||
func (p *Project) GetDefaultColumn(ctx context.Context) (*Column, error) {
|
func (p *Project) getDefaultColumn(ctx context.Context) (*Column, error) {
|
||||||
var column Column
|
var column Column
|
||||||
has, err := db.GetEngine(ctx).
|
has, err := db.GetEngine(ctx).
|
||||||
Where("project_id=? AND `default` = ?", p.ID, true).
|
Where("project_id=? AND `default` = ?", p.ID, true).
|
||||||
@ -270,6 +258,33 @@ func (p *Project) GetDefaultColumn(ctx context.Context) (*Column, error) {
|
|||||||
if has {
|
if has {
|
||||||
return &column, nil
|
return &column, nil
|
||||||
}
|
}
|
||||||
|
return nil, ErrProjectColumnNotExist{ColumnID: 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustDefaultColumn returns the default column for a project.
|
||||||
|
// If one exists, it is returned
|
||||||
|
// If none exists, the first column will be elevated to the default column of this project
|
||||||
|
func (p *Project) MustDefaultColumn(ctx context.Context) (*Column, error) {
|
||||||
|
c, err := p.getDefaultColumn(ctx)
|
||||||
|
if err != nil && !IsErrProjectColumnNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c != nil {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var column Column
|
||||||
|
has, err := db.GetEngine(ctx).Where("project_id=?", p.ID).OrderBy("sorting, id").Get(&column)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if has {
|
||||||
|
column.Default = true
|
||||||
|
if _, err := db.GetEngine(ctx).ID(column.ID).Cols("`default`").Update(&column); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &column, nil
|
||||||
|
}
|
||||||
|
|
||||||
// create a default column if none is found
|
// create a default column if none is found
|
||||||
column = Column{
|
column = Column{
|
||||||
|
@ -20,19 +20,19 @@ func TestGetDefaultColumn(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// check if default column was added
|
// check if default column was added
|
||||||
column, err := projectWithoutDefault.GetDefaultColumn(db.DefaultContext)
|
column, err := projectWithoutDefault.MustDefaultColumn(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(5), column.ProjectID)
|
assert.Equal(t, int64(5), column.ProjectID)
|
||||||
assert.Equal(t, "Uncategorized", column.Title)
|
assert.Equal(t, "Done", column.Title)
|
||||||
|
|
||||||
projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6)
|
projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// check if multiple defaults were removed
|
// check if multiple defaults were removed
|
||||||
column, err = projectWithMultipleDefaults.GetDefaultColumn(db.DefaultContext)
|
column, err = projectWithMultipleDefaults.MustDefaultColumn(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(6), column.ProjectID)
|
assert.Equal(t, int64(6), column.ProjectID)
|
||||||
assert.Equal(t, int64(9), column.ID)
|
assert.Equal(t, int64(9), column.ID) // there are 2 default columns in the test data, use the latest one
|
||||||
|
|
||||||
// set 8 as default column
|
// set 8 as default column
|
||||||
assert.NoError(t, SetDefaultColumn(db.DefaultContext, column.ProjectID, 8))
|
assert.NoError(t, SetDefaultColumn(db.DefaultContext, column.ProjectID, 8))
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,48 +33,6 @@ func deleteProjectIssuesByProjectID(ctx context.Context, projectID int64) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumIssues return counter of all issues assigned to a project
|
|
||||||
func (p *Project) NumIssues(ctx context.Context) int {
|
|
||||||
c, err := db.GetEngine(ctx).Table("project_issue").
|
|
||||||
Where("project_id=?", p.ID).
|
|
||||||
GroupBy("issue_id").
|
|
||||||
Cols("issue_id").
|
|
||||||
Count()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("NumIssues: %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return int(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumClosedIssues return counter of closed issues assigned to a project
|
|
||||||
func (p *Project) NumClosedIssues(ctx context.Context) int {
|
|
||||||
c, err := db.GetEngine(ctx).Table("project_issue").
|
|
||||||
Join("INNER", "issue", "project_issue.issue_id=issue.id").
|
|
||||||
Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, true).
|
|
||||||
Cols("issue_id").
|
|
||||||
Count()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("NumClosedIssues: %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return int(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumOpenIssues return counter of open issues assigned to a project
|
|
||||||
func (p *Project) NumOpenIssues(ctx context.Context) int {
|
|
||||||
c, err := db.GetEngine(ctx).Table("project_issue").
|
|
||||||
Join("INNER", "issue", "project_issue.issue_id=issue.id").
|
|
||||||
Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false).
|
|
||||||
Cols("issue_id").
|
|
||||||
Count()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("NumOpenIssues: %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return int(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Column) moveIssuesToAnotherColumn(ctx context.Context, newColumn *Column) error {
|
func (c *Column) moveIssuesToAnotherColumn(ctx context.Context, newColumn *Column) error {
|
||||||
if c.ProjectID != newColumn.ProjectID {
|
if c.ProjectID != newColumn.ProjectID {
|
||||||
return fmt.Errorf("columns have to be in the same project")
|
return fmt.Errorf("columns have to be in the same project")
|
||||||
|
@ -97,6 +97,9 @@ type Project struct {
|
|||||||
Type Type
|
Type Type
|
||||||
|
|
||||||
RenderedContent template.HTML `xorm:"-"`
|
RenderedContent template.HTML `xorm:"-"`
|
||||||
|
NumOpenIssues int64 `xorm:"-"`
|
||||||
|
NumClosedIssues int64 `xorm:"-"`
|
||||||
|
NumIssues int64 `xorm:"-"`
|
||||||
|
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||||
@ -126,6 +129,14 @@ func (p *Project) LoadRepo(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ProjectLinkForOrg(org *user_model.User, projectID int64) string { //nolint
|
||||||
|
return fmt.Sprintf("%s/-/projects/%d", org.HomeLink(), projectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProjectLinkForRepo(repo *repo_model.Repository, projectID int64) string { //nolint
|
||||||
|
return fmt.Sprintf("%s/projects/%d", repo.Link(), projectID)
|
||||||
|
}
|
||||||
|
|
||||||
// Link returns the project's relative URL.
|
// Link returns the project's relative URL.
|
||||||
func (p *Project) Link(ctx context.Context) string {
|
func (p *Project) Link(ctx context.Context) string {
|
||||||
if p.OwnerID > 0 {
|
if p.OwnerID > 0 {
|
||||||
@ -134,7 +145,7 @@ func (p *Project) Link(ctx context.Context) string {
|
|||||||
log.Error("LoadOwner: %v", err)
|
log.Error("LoadOwner: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/-/projects/%d", p.Owner.HomeLink(), p.ID)
|
return ProjectLinkForOrg(p.Owner, p.ID)
|
||||||
}
|
}
|
||||||
if p.RepoID > 0 {
|
if p.RepoID > 0 {
|
||||||
err := p.LoadRepo(ctx)
|
err := p.LoadRepo(ctx)
|
||||||
@ -142,7 +153,7 @@ func (p *Project) Link(ctx context.Context) string {
|
|||||||
log.Error("LoadRepo: %v", err)
|
log.Error("LoadRepo: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/projects/%d", p.Repo.Link(), p.ID)
|
return ProjectLinkForRepo(p.Repo, p.ID)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import (
|
|||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initialize model
|
// Init initialize model
|
||||||
@ -27,7 +29,7 @@ func Init(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type repoChecker struct {
|
type repoChecker struct {
|
||||||
querySQL func(ctx context.Context) ([]map[string][]byte, error)
|
querySQL func(ctx context.Context) ([]int64, error)
|
||||||
correctSQL func(ctx context.Context, id int64) error
|
correctSQL func(ctx context.Context, id int64) error
|
||||||
desc string
|
desc string
|
||||||
}
|
}
|
||||||
@ -38,8 +40,7 @@ func repoStatsCheck(ctx context.Context, checker *repoChecker) {
|
|||||||
log.Error("Select %s: %v", checker.desc, err)
|
log.Error("Select %s: %v", checker.desc, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, result := range results {
|
for _, id := range results {
|
||||||
id, _ := strconv.ParseInt(string(result["id"]), 10, 64)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Warn("CheckRepoStats: Cancelled before checking %s for with id=%d", checker.desc, id)
|
log.Warn("CheckRepoStats: Cancelled before checking %s for with id=%d", checker.desc, id)
|
||||||
@ -54,21 +55,23 @@ func repoStatsCheck(ctx context.Context, checker *repoChecker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatsCorrectSQL(ctx context.Context, sql string, id int64) error {
|
func StatsCorrectSQL(ctx context.Context, sql any, ids ...any) error {
|
||||||
_, err := db.GetEngine(ctx).Exec(sql, id, id)
|
args := []any{sql}
|
||||||
|
args = append(args, ids...)
|
||||||
|
_, err := db.GetEngine(ctx).Exec(args...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoStatsCorrectNumWatches(ctx context.Context, id int64) error {
|
func repoStatsCorrectNumWatches(ctx context.Context, id int64) error {
|
||||||
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?", id)
|
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?", id, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoStatsCorrectNumStars(ctx context.Context, id int64) error {
|
func repoStatsCorrectNumStars(ctx context.Context, id int64) error {
|
||||||
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", id)
|
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", id, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func labelStatsCorrectNumIssues(ctx context.Context, id int64) error {
|
func labelStatsCorrectNumIssues(ctx context.Context, id int64) error {
|
||||||
return StatsCorrectSQL(ctx, "UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?", id)
|
return StatsCorrectSQL(ctx, "UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?", id, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func labelStatsCorrectNumIssuesRepo(ctx context.Context, id int64) error {
|
func labelStatsCorrectNumIssuesRepo(ctx context.Context, id int64) error {
|
||||||
@ -105,11 +108,11 @@ func milestoneStatsCorrectNumIssuesRepo(ctx context.Context, id int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func userStatsCorrectNumRepos(ctx context.Context, id int64) error {
|
func userStatsCorrectNumRepos(ctx context.Context, id int64) error {
|
||||||
return StatsCorrectSQL(ctx, "UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", id)
|
return StatsCorrectSQL(ctx, "UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", id, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoStatsCorrectIssueNumComments(ctx context.Context, id int64) error {
|
func repoStatsCorrectIssueNumComments(ctx context.Context, id int64) error {
|
||||||
return StatsCorrectSQL(ctx, "UPDATE `issue` SET num_comments=(SELECT COUNT(*) FROM `comment` WHERE issue_id=? AND type=0) WHERE id=?", id)
|
return StatsCorrectSQL(ctx, issues_model.UpdateIssueNumCommentsBuilder(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoStatsCorrectNumIssues(ctx context.Context, id int64) error {
|
func repoStatsCorrectNumIssues(ctx context.Context, id int64) error {
|
||||||
@ -128,9 +131,12 @@ func repoStatsCorrectNumClosedPulls(ctx context.Context, id int64) error {
|
|||||||
return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true)
|
return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statsQuery(args ...any) func(context.Context) ([]map[string][]byte, error) {
|
// statsQuery returns a function that queries the database for a list of IDs
|
||||||
return func(ctx context.Context) ([]map[string][]byte, error) {
|
// sql could be a string or a *builder.Builder
|
||||||
return db.GetEngine(ctx).Query(args...)
|
func statsQuery(sql any, args ...any) func(context.Context) ([]int64, error) {
|
||||||
|
return func(ctx context.Context) ([]int64, error) {
|
||||||
|
var ids []int64
|
||||||
|
return ids, db.GetEngine(ctx).SQL(sql, args...).Find(&ids)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +207,16 @@ func CheckRepoStats(ctx context.Context) error {
|
|||||||
},
|
},
|
||||||
// Issue.NumComments
|
// Issue.NumComments
|
||||||
{
|
{
|
||||||
statsQuery("SELECT `issue`.id FROM `issue` WHERE `issue`.num_comments!=(SELECT COUNT(*) FROM `comment` WHERE issue_id=`issue`.id AND type=0)"),
|
statsQuery(builder.Select("`issue`.id").From("`issue`").Where(
|
||||||
|
builder.Neq{
|
||||||
|
"`issue`.num_comments": builder.Select("COUNT(*)").From("`comment`").Where(
|
||||||
|
builder.Expr("issue_id = `issue`.id").And(
|
||||||
|
builder.In("type", issues_model.ConversationCountedCommentType()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
repoStatsCorrectIssueNumComments,
|
repoStatsCorrectIssueNumComments,
|
||||||
"issue count 'num_comments'",
|
"issue count 'num_comments'",
|
||||||
},
|
},
|
||||||
|
@ -54,6 +54,7 @@ func UpdateRepoLicenses(ctx context.Context, repo *Repository, commitID string,
|
|||||||
for _, o := range oldLicenses {
|
for _, o := range oldLicenses {
|
||||||
// Update already existing license
|
// Update already existing license
|
||||||
if o.License == license {
|
if o.License == license {
|
||||||
|
o.CommitID = commitID
|
||||||
if _, err := db.GetEngine(ctx).ID(o.ID).Cols("`commit_id`").Update(o); err != nil {
|
if _, err := db.GetEngine(ctx).ID(o.ID).Cols("`commit_id`").Update(o); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -276,6 +276,8 @@ func (repo *Repository) IsBroken() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarkAsBrokenEmpty marks the repo as broken and empty
|
// MarkAsBrokenEmpty marks the repo as broken and empty
|
||||||
|
// FIXME: the status "broken" and "is_empty" were abused,
|
||||||
|
// The code always set them together, no way to distinguish whether a repo is really "empty" or "broken"
|
||||||
func (repo *Repository) MarkAsBrokenEmpty() {
|
func (repo *Repository) MarkAsBrokenEmpty() {
|
||||||
repo.Status = RepositoryBroken
|
repo.Status = RepositoryBroken
|
||||||
repo.IsEmpty = true
|
repo.IsEmpty = true
|
||||||
|
@ -46,6 +46,12 @@ func UpdateRepositoryCols(ctx context.Context, repo *Repository, cols ...string)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateRepositoryColsNoAutoTime updates repository's columns and but applies time change automatically
|
||||||
|
func UpdateRepositoryColsNoAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
|
||||||
|
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).NoAutoTime().Update(repo)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
|
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
|
||||||
type ErrReachLimitOfRepo struct {
|
type ErrReachLimitOfRepo struct {
|
||||||
Limit int
|
Limit int
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -22,3 +23,16 @@ func TestDoctorUserStarNum(t *testing.T) {
|
|||||||
|
|
||||||
assert.NoError(t, DoctorUserStarNum(db.DefaultContext))
|
assert.NoError(t, DoctorUserStarNum(db.DefaultContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_repoStatsCorrectIssueNumComments(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
assert.NotNil(t, issue2)
|
||||||
|
assert.EqualValues(t, 0, issue2.NumComments) // the fixture data is wrong, but we don't fix it here
|
||||||
|
|
||||||
|
assert.NoError(t, repoStatsCorrectIssueNumComments(db.DefaultContext, 2))
|
||||||
|
// reload the issue
|
||||||
|
issue2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
assert.EqualValues(t, 1, issue2.NumComments)
|
||||||
|
}
|
||||||
|
@ -6,19 +6,21 @@ package unittest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/auth/password/hash"
|
"code.gitea.io/gitea/modules/auth/password/hash"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/go-testfixtures/testfixtures/v3"
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fixturesLoader *testfixtures.Loader
|
type FixturesLoader interface {
|
||||||
|
Load() error
|
||||||
|
}
|
||||||
|
|
||||||
|
var fixturesLoader FixturesLoader
|
||||||
|
|
||||||
// GetXORMEngine gets the XORM engine
|
// GetXORMEngine gets the XORM engine
|
||||||
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
||||||
@ -31,38 +33,7 @@ func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
|||||||
// InitFixtures initialize test fixtures for a test database
|
// InitFixtures initialize test fixtures for a test database
|
||||||
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
||||||
e := GetXORMEngine(engine...)
|
e := GetXORMEngine(engine...)
|
||||||
var fixtureOptionFiles func(*testfixtures.Loader) error
|
fixturesLoader, err = NewFixturesLoader(e, opts)
|
||||||
if opts.Dir != "" {
|
|
||||||
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
|
|
||||||
} else {
|
|
||||||
fixtureOptionFiles = testfixtures.Files(opts.Files...)
|
|
||||||
}
|
|
||||||
dialect := "unknown"
|
|
||||||
switch e.Dialect().URI().DBType {
|
|
||||||
case schemas.POSTGRES:
|
|
||||||
dialect = "postgres"
|
|
||||||
case schemas.MYSQL:
|
|
||||||
dialect = "mysql"
|
|
||||||
case schemas.MSSQL:
|
|
||||||
dialect = "mssql"
|
|
||||||
case schemas.SQLITE:
|
|
||||||
dialect = "sqlite3"
|
|
||||||
default:
|
|
||||||
fmt.Println("Unsupported RDBMS for integration tests")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
loaderOptions := []func(loader *testfixtures.Loader) error{
|
|
||||||
testfixtures.Database(e.DB().DB),
|
|
||||||
testfixtures.Dialect(dialect),
|
|
||||||
testfixtures.DangerousSkipTestDatabaseCheck(),
|
|
||||||
fixtureOptionFiles,
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.Dialect().URI().DBType == schemas.POSTGRES {
|
|
||||||
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
|
|
||||||
}
|
|
||||||
|
|
||||||
fixturesLoader, err = testfixtures.New(loaderOptions...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
201
models/unittest/fixtures_loader.go
Normal file
201
models/unittest/fixtures_loader.go
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package unittest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"xorm.io/xorm"
|
||||||
|
"xorm.io/xorm/schemas"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fixtureItem struct {
|
||||||
|
tableName string
|
||||||
|
tableNameQuoted string
|
||||||
|
sqlInserts []string
|
||||||
|
sqlInsertArgs [][]any
|
||||||
|
|
||||||
|
mssqlHasIdentityColumn bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type fixturesLoaderInternal struct {
|
||||||
|
db *sql.DB
|
||||||
|
dbType schemas.DBType
|
||||||
|
files []string
|
||||||
|
fixtures map[string]*fixtureItem
|
||||||
|
quoteObject func(string) string
|
||||||
|
paramPlaceholder func(idx int) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixturesLoaderInternal) mssqlTableHasIdentityColumn(db *sql.DB, tableName string) (bool, error) {
|
||||||
|
row := db.QueryRow(`SELECT COUNT(*) FROM sys.identity_columns WHERE OBJECT_ID = OBJECT_ID(?)`, tableName)
|
||||||
|
var count int
|
||||||
|
if err := row.Scan(&count); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return count > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixturesLoaderInternal) preprocessFixtureRow(row []map[string]any) (err error) {
|
||||||
|
for _, m := range row {
|
||||||
|
for k, v := range m {
|
||||||
|
if s, ok := v.(string); ok {
|
||||||
|
if strings.HasPrefix(s, "0x") {
|
||||||
|
if m[k], err = hex.DecodeString(s[2:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixturesLoaderInternal) prepareFixtureItem(file string) (_ *fixtureItem, err error) {
|
||||||
|
fixture := &fixtureItem{}
|
||||||
|
fixture.tableName, _, _ = strings.Cut(filepath.Base(file), ".")
|
||||||
|
fixture.tableNameQuoted = f.quoteObject(fixture.tableName)
|
||||||
|
|
||||||
|
if f.dbType == schemas.MSSQL {
|
||||||
|
fixture.mssqlHasIdentityColumn, err = f.mssqlTableHasIdentityColumn(f.db, fixture.tableName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read file %q: %w", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rows []map[string]any
|
||||||
|
if err = yaml.Unmarshal(data, &rows); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal yaml data from %q: %w", file, err)
|
||||||
|
}
|
||||||
|
if err = f.preprocessFixtureRow(rows); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to preprocess fixture rows from %q: %w", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sqlBuf []byte
|
||||||
|
var sqlArguments []any
|
||||||
|
for _, row := range rows {
|
||||||
|
sqlBuf = append(sqlBuf, fmt.Sprintf("INSERT INTO %s (", fixture.tableNameQuoted)...)
|
||||||
|
for k, v := range row {
|
||||||
|
sqlBuf = append(sqlBuf, f.quoteObject(k)...)
|
||||||
|
sqlBuf = append(sqlBuf, ","...)
|
||||||
|
sqlArguments = append(sqlArguments, v)
|
||||||
|
}
|
||||||
|
sqlBuf = sqlBuf[:len(sqlBuf)-1]
|
||||||
|
sqlBuf = append(sqlBuf, ") VALUES ("...)
|
||||||
|
paramIdx := 1
|
||||||
|
for range row {
|
||||||
|
sqlBuf = append(sqlBuf, f.paramPlaceholder(paramIdx)...)
|
||||||
|
sqlBuf = append(sqlBuf, ',')
|
||||||
|
paramIdx++
|
||||||
|
}
|
||||||
|
sqlBuf[len(sqlBuf)-1] = ')'
|
||||||
|
fixture.sqlInserts = append(fixture.sqlInserts, string(sqlBuf))
|
||||||
|
fixture.sqlInsertArgs = append(fixture.sqlInsertArgs, slices.Clone(sqlArguments))
|
||||||
|
sqlBuf = sqlBuf[:0]
|
||||||
|
sqlArguments = sqlArguments[:0]
|
||||||
|
}
|
||||||
|
return fixture, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, file string) (err error) {
|
||||||
|
fixture := f.fixtures[file]
|
||||||
|
if fixture == nil {
|
||||||
|
if fixture, err = f.prepareFixtureItem(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.fixtures[file] = fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(fmt.Sprintf("DELETE FROM %s", fixture.tableNameQuoted)) // sqlite3 doesn't support truncate
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fixture.mssqlHasIdentityColumn {
|
||||||
|
_, err = tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s ON", fixture.tableNameQuoted))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() { _, err = tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s OFF", fixture.tableNameQuoted)) }()
|
||||||
|
}
|
||||||
|
for i := range fixture.sqlInserts {
|
||||||
|
_, err = tx.Exec(fixture.sqlInserts[i], fixture.sqlInsertArgs[i]...)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixturesLoaderInternal) Load() error {
|
||||||
|
tx, err := f.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() { _ = tx.Rollback() }()
|
||||||
|
|
||||||
|
for _, file := range f.files {
|
||||||
|
if err := f.loadFixtures(tx, file); err != nil {
|
||||||
|
return fmt.Errorf("failed to load fixtures from %s: %w", file, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func FixturesFileFullPaths(dir string, files []string) ([]string, error) {
|
||||||
|
if files != nil && len(files) == 0 {
|
||||||
|
return nil, nil // load nothing
|
||||||
|
}
|
||||||
|
files = slices.Clone(files)
|
||||||
|
if len(files) == 0 {
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, e := range entries {
|
||||||
|
files = append(files, e.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, file := range files {
|
||||||
|
if !filepath.IsAbs(file) {
|
||||||
|
files[i] = filepath.Join(dir, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFixturesLoader(x *xorm.Engine, opts FixturesOptions) (FixturesLoader, error) {
|
||||||
|
files, err := FixturesFileFullPaths(opts.Dir, opts.Files)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get fixtures files: %w", err)
|
||||||
|
}
|
||||||
|
f := &fixturesLoaderInternal{db: x.DB().DB, dbType: x.Dialect().URI().DBType, files: files, fixtures: map[string]*fixtureItem{}}
|
||||||
|
switch f.dbType {
|
||||||
|
case schemas.SQLITE:
|
||||||
|
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
|
||||||
|
f.paramPlaceholder = func(idx int) string { return "?" }
|
||||||
|
case schemas.POSTGRES:
|
||||||
|
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
|
||||||
|
f.paramPlaceholder = func(idx int) string { return fmt.Sprintf(`$%d`, idx) }
|
||||||
|
case schemas.MYSQL:
|
||||||
|
f.quoteObject = func(s string) string { return fmt.Sprintf("`%s`", s) }
|
||||||
|
f.paramPlaceholder = func(idx int) string { return "?" }
|
||||||
|
case schemas.MSSQL:
|
||||||
|
f.quoteObject = func(s string) string { return fmt.Sprintf("[%s]", s) }
|
||||||
|
f.paramPlaceholder = func(idx int) string { return "?" }
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
@ -38,27 +38,30 @@ func GenerateRandomAvatar(ctx context.Context, u *User) error {
|
|||||||
|
|
||||||
u.Avatar = avatars.HashEmail(seed)
|
u.Avatar = avatars.HashEmail(seed)
|
||||||
|
|
||||||
|
_, err = storage.Avatars.Stat(u.CustomAvatarRelativePath())
|
||||||
|
if err != nil {
|
||||||
|
// If unable to Stat the avatar file (usually it means non-existing), then try to save a new one
|
||||||
// Don't share the images so that we can delete them easily
|
// Don't share the images so that we can delete them easily
|
||||||
if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
|
if err := storage.SaveFrom(storage.Avatars, u.CustomAvatarRelativePath(), func(w io.Writer) error {
|
||||||
if err := png.Encode(w, img); err != nil {
|
if err := png.Encode(w, img); err != nil {
|
||||||
log.Error("Encode: %v", err)
|
log.Error("Encode: %v", err)
|
||||||
}
|
}
|
||||||
return err
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("Failed to create dir %s: %w", u.CustomAvatarRelativePath(), err)
|
return fmt.Errorf("failed to save avatar %s: %w", u.CustomAvatarRelativePath(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := db.GetEngine(ctx).ID(u.ID).Cols("avatar").Update(u); err != nil {
|
if _, err := db.GetEngine(ctx).ID(u.ID).Cols("avatar").Update(u); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("New random avatar created: %d", u.ID)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvatarLinkWithSize returns a link to the user's avatar with size. size <= 0 means default size
|
// AvatarLinkWithSize returns a link to the user's avatar with size. size <= 0 means default size
|
||||||
func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
|
func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string {
|
||||||
if u.IsGhost() {
|
if u.IsGhost() || u.IsGiteaActions() {
|
||||||
return avatars.DefaultAvatarLink()
|
return avatars.DefaultAvatarLink()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,19 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUserAvatarLink(t *testing.T) {
|
func TestUserAvatarLink(t *testing.T) {
|
||||||
@ -26,3 +32,37 @@ func TestUserAvatarLink(t *testing.T) {
|
|||||||
link = u.AvatarLink(db.DefaultContext)
|
link = u.AvatarLink(db.DefaultContext)
|
||||||
assert.Equal(t, "https://localhost/sub-path/avatars/avatar.png", link)
|
assert.Equal(t, "https://localhost/sub-path/avatars/avatar.png", link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserAvatarGenerate(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
var err error
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
storage.Avatars, err = storage.NewLocalStorage(context.Background(), &setting.Storage{Path: tmpDir})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
u := unittest.AssertExistsAndLoadBean(t, &User{ID: 2})
|
||||||
|
|
||||||
|
// there was no avatar, generate a new one
|
||||||
|
assert.Empty(t, u.Avatar)
|
||||||
|
err = GenerateRandomAvatar(db.DefaultContext, u)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, u.Avatar)
|
||||||
|
|
||||||
|
// make sure the generated one exists
|
||||||
|
oldAvatarPath := u.CustomAvatarRelativePath()
|
||||||
|
_, err = storage.Avatars.Stat(u.CustomAvatarRelativePath())
|
||||||
|
require.NoError(t, err)
|
||||||
|
// and try to change its content
|
||||||
|
_, err = storage.Avatars.Save(u.CustomAvatarRelativePath(), strings.NewReader("abcd"), 4)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// try to generate again
|
||||||
|
err = GenerateRandomAvatar(db.DefaultContext, u)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, oldAvatarPath, u.CustomAvatarRelativePath())
|
||||||
|
f, err := storage.Avatars.Open(u.CustomAvatarRelativePath())
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer f.Close()
|
||||||
|
content, _ := io.ReadAll(f)
|
||||||
|
assert.Equal(t, "abcd", string(content))
|
||||||
|
}
|
||||||
|
@ -357,8 +357,8 @@ func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddres
|
|||||||
if user := GetVerifyUser(ctx, code); user != nil {
|
if user := GetVerifyUser(ctx, code); user != nil {
|
||||||
// time limit code
|
// time limit code
|
||||||
prefix := code[:base.TimeLimitCodeLength]
|
prefix := code[:base.TimeLimitCodeLength]
|
||||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
opts := &TimeLimitCodeOptions{Purpose: TimeLimitCodeActivateEmail, NewEmail: email}
|
||||||
|
data := makeTimeLimitCodeHashData(opts, user)
|
||||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||||
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
||||||
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
|
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
|
||||||
@ -486,10 +486,10 @@ func ActivateUserEmail(ctx context.Context, userID int64, email string, activate
|
|||||||
|
|
||||||
// Activate/deactivate a user's primary email address and account
|
// Activate/deactivate a user's primary email address and account
|
||||||
if addr.IsPrimary {
|
if addr.IsPrimary {
|
||||||
user, exist, err := db.Get[User](ctx, builder.Eq{"id": userID, "email": email})
|
user, exist, err := db.Get[User](ctx, builder.Eq{"id": userID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !exist {
|
} else if !exist || !strings.EqualFold(user.Email, email) {
|
||||||
return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
|
return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,8 @@ func (u *User) BeforeUpdate() {
|
|||||||
u.MaxRepoCreation = -1
|
u.MaxRepoCreation = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Organization does not need email
|
// FIXME: this email doesn't need to be in lowercase, because the emails are mainly managed by the email table with lower_email field
|
||||||
|
// This trick could be removed in new releases to display the user inputed email as-is.
|
||||||
u.Email = strings.ToLower(u.Email)
|
u.Email = strings.ToLower(u.Email)
|
||||||
if !u.IsOrganization() {
|
if !u.IsOrganization() {
|
||||||
if len(u.AvatarEmail) == 0 {
|
if len(u.AvatarEmail) == 0 {
|
||||||
@ -310,17 +311,6 @@ func (u *User) OrganisationLink() string {
|
|||||||
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
|
|
||||||
func (u *User) GenerateEmailActivateCode(email string) string {
|
|
||||||
code := base.CreateTimeLimitCode(
|
|
||||||
fmt.Sprintf("%d%s%s%s%s", u.ID, email, u.LowerName, u.Passwd, u.Rands),
|
|
||||||
setting.Service.ActiveCodeLives, time.Now(), nil)
|
|
||||||
|
|
||||||
// Add tail hex username
|
|
||||||
code += hex.EncodeToString([]byte(u.LowerName))
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserFollowers returns range of user's followers.
|
// GetUserFollowers returns range of user's followers.
|
||||||
func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
|
func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
|
||||||
sess := db.GetEngine(ctx).
|
sess := db.GetEngine(ctx).
|
||||||
@ -848,12 +838,38 @@ func GetVerifyUser(ctx context.Context, code string) (user *User) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyUserActiveCode verifies active code when active account
|
type TimeLimitCodePurpose string
|
||||||
func VerifyUserActiveCode(ctx context.Context, code string) (user *User) {
|
|
||||||
|
const (
|
||||||
|
TimeLimitCodeActivateAccount TimeLimitCodePurpose = "activate_account"
|
||||||
|
TimeLimitCodeActivateEmail TimeLimitCodePurpose = "activate_email"
|
||||||
|
TimeLimitCodeResetPassword TimeLimitCodePurpose = "reset_password"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TimeLimitCodeOptions struct {
|
||||||
|
Purpose TimeLimitCodePurpose
|
||||||
|
NewEmail string
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTimeLimitCodeHashData(opts *TimeLimitCodeOptions, u *User) string {
|
||||||
|
return fmt.Sprintf("%s|%d|%s|%s|%s|%s", opts.Purpose, u.ID, strings.ToLower(util.IfZero(opts.NewEmail, u.Email)), u.LowerName, u.Passwd, u.Rands)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateUserTimeLimitCode generates a time-limit code based on user information and given e-mail.
|
||||||
|
// TODO: need to use cache or db to store it to make sure a code can only be consumed once
|
||||||
|
func GenerateUserTimeLimitCode(opts *TimeLimitCodeOptions, u *User) string {
|
||||||
|
data := makeTimeLimitCodeHashData(opts, u)
|
||||||
|
code := base.CreateTimeLimitCode(data, setting.Service.ActiveCodeLives, time.Now(), nil)
|
||||||
|
code += hex.EncodeToString([]byte(u.LowerName)) // Add tail hex username
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyUserTimeLimitCode verifies the time-limit code
|
||||||
|
func VerifyUserTimeLimitCode(ctx context.Context, opts *TimeLimitCodeOptions, code string) (user *User) {
|
||||||
if user = GetVerifyUser(ctx, code); user != nil {
|
if user = GetVerifyUser(ctx, code); user != nil {
|
||||||
// time limit code
|
// time limit code
|
||||||
prefix := code[:base.TimeLimitCodeLength]
|
prefix := code[:base.TimeLimitCodeLength]
|
||||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, user.LowerName, user.Passwd, user.Rands)
|
data := makeTimeLimitCodeHashData(opts, user)
|
||||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,10 @@ func NewGhostUser() *User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsGhostUserName(name string) bool {
|
||||||
|
return strings.EqualFold(name, GhostUserName)
|
||||||
|
}
|
||||||
|
|
||||||
// IsGhost check if user is fake user for a deleted account
|
// IsGhost check if user is fake user for a deleted account
|
||||||
func (u *User) IsGhost() bool {
|
func (u *User) IsGhost() bool {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
@ -48,6 +52,10 @@ const (
|
|||||||
ActionsEmail = "teabot@gitea.io"
|
ActionsEmail = "teabot@gitea.io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func IsGiteaActionsUserName(name string) bool {
|
||||||
|
return strings.EqualFold(name, ActionsUserName)
|
||||||
|
}
|
||||||
|
|
||||||
// NewActionsUser creates and returns a fake user for running the actions.
|
// NewActionsUser creates and returns a fake user for running the actions.
|
||||||
func NewActionsUser() *User {
|
func NewActionsUser() *User {
|
||||||
return &User{
|
return &User{
|
||||||
@ -65,6 +73,16 @@ func NewActionsUser() *User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) IsActions() bool {
|
func (u *User) IsGiteaActions() bool {
|
||||||
return u != nil && u.ID == ActionsUserID
|
return u != nil && u.ID == ActionsUserID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSystemUserByName(name string) *User {
|
||||||
|
if IsGhostUserName(name) {
|
||||||
|
return NewGhostUser()
|
||||||
|
}
|
||||||
|
if IsGiteaActionsUserName(name) {
|
||||||
|
return NewActionsUser()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
32
models/user/user_system_test.go
Normal file
32
models/user/user_system_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSystemUser(t *testing.T) {
|
||||||
|
u, err := GetPossibleUserByID(db.DefaultContext, -1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "Ghost", u.Name)
|
||||||
|
assert.Equal(t, "ghost", u.LowerName)
|
||||||
|
assert.True(t, u.IsGhost())
|
||||||
|
assert.True(t, IsGhostUserName("gHost"))
|
||||||
|
|
||||||
|
u, err = GetPossibleUserByID(db.DefaultContext, -2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "gitea-actions", u.Name)
|
||||||
|
assert.Equal(t, "gitea-actions", u.LowerName)
|
||||||
|
assert.True(t, u.IsGiteaActions())
|
||||||
|
assert.True(t, IsGiteaActionsUserName("Gitea-actionS"))
|
||||||
|
|
||||||
|
_, err = GetPossibleUserByID(db.DefaultContext, -3)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
@ -299,6 +299,11 @@ func (w *Webhook) HasPackageEvent() bool {
|
|||||||
(w.ChooseEvents && w.HookEvents.Package)
|
(w.ChooseEvents && w.HookEvents.Package)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Webhook) HasStatusEvent() bool {
|
||||||
|
return w.SendEverything ||
|
||||||
|
(w.ChooseEvents && w.HookEvents.Status)
|
||||||
|
}
|
||||||
|
|
||||||
// HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event.
|
// HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event.
|
||||||
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
|
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
|
||||||
return w.SendEverything ||
|
return w.SendEverything ||
|
||||||
@ -337,6 +342,7 @@ func (w *Webhook) EventCheckers() []struct {
|
|||||||
{w.HasReleaseEvent, webhook_module.HookEventRelease},
|
{w.HasReleaseEvent, webhook_module.HookEventRelease},
|
||||||
{w.HasPackageEvent, webhook_module.HookEventPackage},
|
{w.HasPackageEvent, webhook_module.HookEventPackage},
|
||||||
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
|
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
|
||||||
|
{w.HasStatusEvent, webhook_module.HookEventStatus},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func TestWebhook_EventsArray(t *testing.T) {
|
|||||||
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
||||||
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
||||||
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
|
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
|
||||||
"package", "pull_request_review_request",
|
"package", "pull_request_review_request", "status",
|
||||||
},
|
},
|
||||||
(&Webhook{
|
(&Webhook{
|
||||||
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
||||||
|
@ -15,5 +15,5 @@ func TestPamAuth(t *testing.T) {
|
|||||||
result, err := Auth("gitea", "user1", "false-pwd")
|
result, err := Auth("gitea", "user1", "false-pwd")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.EqualError(t, err, "Authentication failure")
|
assert.EqualError(t, err, "Authentication failure")
|
||||||
assert.Len(t, result)
|
assert.Empty(t, result)
|
||||||
}
|
}
|
||||||
|
7
modules/cache/cache.go
vendored
7
modules/cache/cache.go
vendored
@ -38,9 +38,14 @@ func Init() error {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
testCacheKey = "DefaultCache.TestKey"
|
testCacheKey = "DefaultCache.TestKey"
|
||||||
SlowCacheThreshold = 100 * time.Microsecond
|
// SlowCacheThreshold marks cache tests as slow
|
||||||
|
// set to 30ms per discussion: https://github.com/go-gitea/gitea/issues/33190
|
||||||
|
// TODO: Replace with metrics histogram
|
||||||
|
SlowCacheThreshold = 30 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Test performs delete, put and get operations on a predefined key
|
||||||
|
// returns
|
||||||
func Test() (time.Duration, error) {
|
func Test() (time.Duration, error) {
|
||||||
if defaultCache == nil {
|
if defaultCache == nil {
|
||||||
return 0, fmt.Errorf("default cache not initialized")
|
return 0, fmt.Errorf("default cache not initialized")
|
||||||
|
3
modules/cache/cache_test.go
vendored
3
modules/cache/cache_test.go
vendored
@ -43,7 +43,8 @@ func TestTest(t *testing.T) {
|
|||||||
elapsed, err := Test()
|
elapsed, err := Test()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// mem cache should take from 300ns up to 1ms on modern hardware ...
|
// mem cache should take from 300ns up to 1ms on modern hardware ...
|
||||||
assert.Less(t, elapsed, time.Millisecond)
|
assert.Positive(t, elapsed)
|
||||||
|
assert.Less(t, elapsed, SlowCacheThreshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCache(t *testing.T) {
|
func TestGetCache(t *testing.T) {
|
||||||
|
@ -253,7 +253,7 @@ func BinToHex(objectFormat ObjectFormat, sha, out []byte) []byte {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseTreeLine reads an entry from a tree in a cat-file --batch stream
|
// ParseCatFileTreeLine reads an entry from a tree in a cat-file --batch stream
|
||||||
// This carefully avoids allocations - except where fnameBuf is too small.
|
// This carefully avoids allocations - except where fnameBuf is too small.
|
||||||
// It is recommended therefore to pass in an fnameBuf large enough to avoid almost all allocations
|
// It is recommended therefore to pass in an fnameBuf large enough to avoid almost all allocations
|
||||||
//
|
//
|
||||||
@ -261,7 +261,7 @@ func BinToHex(objectFormat ObjectFormat, sha, out []byte) []byte {
|
|||||||
// <mode-in-ascii-dropping-initial-zeros> SP <fname> NUL <binary HASH>
|
// <mode-in-ascii-dropping-initial-zeros> SP <fname> NUL <binary HASH>
|
||||||
//
|
//
|
||||||
// We don't attempt to convert the raw HASH to save a lot of time
|
// We don't attempt to convert the raw HASH to save a lot of time
|
||||||
func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fname, sha []byte, n int, err error) {
|
func ParseCatFileTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBuf, shaBuf []byte) (mode, fname, sha []byte, n int, err error) {
|
||||||
var readBytes []byte
|
var readBytes []byte
|
||||||
|
|
||||||
// Read the Mode & fname
|
// Read the Mode & fname
|
||||||
@ -271,7 +271,7 @@ func ParseTreeLine(objectFormat ObjectFormat, rd *bufio.Reader, modeBuf, fnameBu
|
|||||||
}
|
}
|
||||||
idx := bytes.IndexByte(readBytes, ' ')
|
idx := bytes.IndexByte(readBytes, ' ')
|
||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
log.Debug("missing space in readBytes ParseTreeLine: %s", readBytes)
|
log.Debug("missing space in readBytes ParseCatFileTreeLine: %s", readBytes)
|
||||||
return mode, fname, sha, n, &ErrNotExist{}
|
return mode, fname, sha, n, &ErrNotExist{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,5 +360,5 @@ func Test_GetCommitBranchStart(t *testing.T) {
|
|||||||
startCommitID, err := repo.GetCommitBranchStart(os.Environ(), "branch1", commit.ID.String())
|
startCommitID, err := repo.GetCommitBranchStart(os.Environ(), "branch1", commit.ID.String())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, startCommitID)
|
assert.NotEmpty(t, startCommitID)
|
||||||
assert.EqualValues(t, "9c9aef8dd84e02bc7ec12641deb4c930a7c30185", startCommitID)
|
assert.EqualValues(t, "95bb4d39648ee7e325106df01a621c530863a653", startCommitID)
|
||||||
}
|
}
|
||||||
|
78
modules/git/parse.go
Normal file
78
modules/git/parse.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sepSpace = []byte{' '}
|
||||||
|
|
||||||
|
type LsTreeEntry struct {
|
||||||
|
ID ObjectID
|
||||||
|
EntryMode EntryMode
|
||||||
|
Name string
|
||||||
|
Size optional.Option[int64]
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseLsTreeLine(line []byte) (*LsTreeEntry, error) {
|
||||||
|
// expect line to be of the form:
|
||||||
|
// <mode> <type> <sha> <space-padded-size>\t<filename>
|
||||||
|
// <mode> <type> <sha>\t<filename>
|
||||||
|
|
||||||
|
var err error
|
||||||
|
posTab := bytes.IndexByte(line, '\t')
|
||||||
|
if posTab == -1 {
|
||||||
|
return nil, fmt.Errorf("invalid ls-tree output (no tab): %q", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := new(LsTreeEntry)
|
||||||
|
|
||||||
|
entryAttrs := line[:posTab]
|
||||||
|
entryName := line[posTab+1:]
|
||||||
|
|
||||||
|
entryMode, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
|
||||||
|
_ /* entryType */, entryAttrs, _ = bytes.Cut(entryAttrs, sepSpace) // the type is not used, the mode is enough to determine the type
|
||||||
|
entryObjectID, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
|
||||||
|
if len(entryAttrs) > 0 {
|
||||||
|
entrySize := entryAttrs // the last field is the space-padded-size
|
||||||
|
size, _ := strconv.ParseInt(strings.TrimSpace(string(entrySize)), 10, 64)
|
||||||
|
entry.Size = optional.Some(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch string(entryMode) {
|
||||||
|
case "100644":
|
||||||
|
entry.EntryMode = EntryModeBlob
|
||||||
|
case "100755":
|
||||||
|
entry.EntryMode = EntryModeExec
|
||||||
|
case "120000":
|
||||||
|
entry.EntryMode = EntryModeSymlink
|
||||||
|
case "160000":
|
||||||
|
entry.EntryMode = EntryModeCommit
|
||||||
|
case "040000", "040755": // git uses 040000 for tree object, but some users may get 040755 for unknown reasons
|
||||||
|
entry.EntryMode = EntryModeTree
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown type: %v", string(entryMode))
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.ID, err = NewIDFromString(string(entryObjectID))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(entryName) > 0 && entryName[0] == '"' {
|
||||||
|
entry.Name, err = strconv.Unquote(string(entryName))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid ls-tree output (invalid name): %q, err: %w", line, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry.Name = string(entryName)
|
||||||
|
}
|
||||||
|
return entry, nil
|
||||||
|
}
|
@ -10,8 +10,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
@ -21,71 +19,30 @@ func ParseTreeEntries(data []byte) ([]*TreeEntry, error) {
|
|||||||
return parseTreeEntries(data, nil)
|
return parseTreeEntries(data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sepSpace = []byte{' '}
|
// parseTreeEntries FIXME this function's design is not right, it should make the caller read all data into memory
|
||||||
|
|
||||||
func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
|
func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
|
||||||
var err error
|
|
||||||
entries := make([]*TreeEntry, 0, bytes.Count(data, []byte{'\n'})+1)
|
entries := make([]*TreeEntry, 0, bytes.Count(data, []byte{'\n'})+1)
|
||||||
for pos := 0; pos < len(data); {
|
for pos := 0; pos < len(data); {
|
||||||
// expect line to be of the form:
|
|
||||||
// <mode> <type> <sha> <space-padded-size>\t<filename>
|
|
||||||
// <mode> <type> <sha>\t<filename>
|
|
||||||
posEnd := bytes.IndexByte(data[pos:], '\n')
|
posEnd := bytes.IndexByte(data[pos:], '\n')
|
||||||
if posEnd == -1 {
|
if posEnd == -1 {
|
||||||
posEnd = len(data)
|
posEnd = len(data)
|
||||||
} else {
|
} else {
|
||||||
posEnd += pos
|
posEnd += pos
|
||||||
}
|
}
|
||||||
|
|
||||||
line := data[pos:posEnd]
|
line := data[pos:posEnd]
|
||||||
posTab := bytes.IndexByte(line, '\t')
|
lsTreeLine, err := parseLsTreeLine(line)
|
||||||
if posTab == -1 {
|
|
||||||
return nil, fmt.Errorf("invalid ls-tree output (no tab): %q", line)
|
|
||||||
}
|
|
||||||
|
|
||||||
entry := new(TreeEntry)
|
|
||||||
entry.ptree = ptree
|
|
||||||
|
|
||||||
entryAttrs := line[:posTab]
|
|
||||||
entryName := line[posTab+1:]
|
|
||||||
|
|
||||||
entryMode, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
|
|
||||||
_ /* entryType */, entryAttrs, _ = bytes.Cut(entryAttrs, sepSpace) // the type is not used, the mode is enough to determine the type
|
|
||||||
entryObjectID, entryAttrs, _ := bytes.Cut(entryAttrs, sepSpace)
|
|
||||||
if len(entryAttrs) > 0 {
|
|
||||||
entrySize := entryAttrs // the last field is the space-padded-size
|
|
||||||
entry.size, _ = strconv.ParseInt(strings.TrimSpace(string(entrySize)), 10, 64)
|
|
||||||
entry.sized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
switch string(entryMode) {
|
|
||||||
case "100644":
|
|
||||||
entry.entryMode = EntryModeBlob
|
|
||||||
case "100755":
|
|
||||||
entry.entryMode = EntryModeExec
|
|
||||||
case "120000":
|
|
||||||
entry.entryMode = EntryModeSymlink
|
|
||||||
case "160000":
|
|
||||||
entry.entryMode = EntryModeCommit
|
|
||||||
case "040000", "040755": // git uses 040000 for tree object, but some users may get 040755 for unknown reasons
|
|
||||||
entry.entryMode = EntryModeTree
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown type: %v", string(entryMode))
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.ID, err = NewIDFromString(string(entryObjectID))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid ls-tree output (invalid object id): %q, err: %w", line, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
entry := &TreeEntry{
|
||||||
if len(entryName) > 0 && entryName[0] == '"' {
|
ptree: ptree,
|
||||||
entry.name, err = strconv.Unquote(string(entryName))
|
ID: lsTreeLine.ID,
|
||||||
if err != nil {
|
entryMode: lsTreeLine.EntryMode,
|
||||||
return nil, fmt.Errorf("invalid ls-tree output (invalid name): %q, err: %w", line, err)
|
name: lsTreeLine.Name,
|
||||||
|
size: lsTreeLine.Size.Value(),
|
||||||
|
sized: lsTreeLine.Size.Has(),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
entry.name = string(entryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = posEnd + 1
|
pos = posEnd + 1
|
||||||
entries = append(entries, entry)
|
entries = append(entries, entry)
|
||||||
}
|
}
|
||||||
@ -100,7 +57,7 @@ func catBatchParseTreeEntries(objectFormat ObjectFormat, ptree *Tree, rd *bufio.
|
|||||||
|
|
||||||
loop:
|
loop:
|
||||||
for sz > 0 {
|
for sz > 0 {
|
||||||
mode, fname, sha, count, err := ParseTreeLine(objectFormat, rd, modeBuf, fnameBuf, shaBuf)
|
mode, fname, sha, count, err := ParseCatFileTreeLine(objectFormat, rd, modeBuf, fnameBuf, shaBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break loop
|
break loop
|
||||||
|
@ -114,7 +114,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||||||
case "tree":
|
case "tree":
|
||||||
var n int64
|
var n int64
|
||||||
for n < size {
|
for n < size {
|
||||||
mode, fname, binObjectID, count, err := git.ParseTreeLine(objectID.Type(), batchReader, modeBuf, fnameBuf, workingShaBuf)
|
mode, fname, binObjectID, count, err := git.ParseCatFileTreeLine(objectID.Type(), batchReader, modeBuf, fnameBuf, workingShaBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ func TestRefName(t *testing.T) {
|
|||||||
|
|
||||||
// Test pull names
|
// Test pull names
|
||||||
assert.Equal(t, "1", RefName("refs/pull/1/head").PullName())
|
assert.Equal(t, "1", RefName("refs/pull/1/head").PullName())
|
||||||
|
assert.True(t, RefName("refs/pull/1/head").IsPull())
|
||||||
|
assert.True(t, RefName("refs/pull/1/merge").IsPull())
|
||||||
assert.Equal(t, "my/pull", RefName("refs/pull/my/pull/head").PullName())
|
assert.Equal(t, "my/pull", RefName("refs/pull/my/pull/head").PullName())
|
||||||
|
|
||||||
// Test for branch names
|
// Test for branch names
|
||||||
|
@ -5,6 +5,7 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
giturl "code.gitea.io/gitea/modules/git/url"
|
giturl "code.gitea.io/gitea/modules/git/url"
|
||||||
)
|
)
|
||||||
@ -37,3 +38,12 @@ func GetRemoteURL(ctx context.Context, repoPath, remoteName string) (*giturl.Git
|
|||||||
}
|
}
|
||||||
return giturl.Parse(addr)
|
return giturl.Parse(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRemoteNotExistError checks the prefix of the error message to see whether a remote does not exist.
|
||||||
|
func IsRemoteNotExistError(err error) bool {
|
||||||
|
// see: https://github.com/go-gitea/gitea/issues/32889#issuecomment-2571848216
|
||||||
|
// Should not add space in the end, sometimes git will add a `:`
|
||||||
|
prefix1 := "exit status 128 - fatal: No such remote" // git < 2.30
|
||||||
|
prefix2 := "exit status 2 - error: No such remote" // git >= 2.30
|
||||||
|
return strings.HasPrefix(err.Error(), prefix1) || strings.HasPrefix(err.Error(), prefix2)
|
||||||
|
}
|
||||||
|
@ -216,8 +216,6 @@ type CommitsByFileAndRangeOptions struct {
|
|||||||
|
|
||||||
// CommitsByFileAndRange return the commits according revision file and the page
|
// CommitsByFileAndRange return the commits according revision file and the page
|
||||||
func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) ([]*Commit, error) {
|
func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) ([]*Commit, error) {
|
||||||
skip := (opts.Page - 1) * setting.Git.CommitsRangeSize
|
|
||||||
|
|
||||||
stdoutReader, stdoutWriter := io.Pipe()
|
stdoutReader, stdoutWriter := io.Pipe()
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = stdoutReader.Close()
|
_ = stdoutReader.Close()
|
||||||
@ -226,8 +224,8 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
|||||||
go func() {
|
go func() {
|
||||||
stderr := strings.Builder{}
|
stderr := strings.Builder{}
|
||||||
gitCmd := NewCommand(repo.Ctx, "rev-list").
|
gitCmd := NewCommand(repo.Ctx, "rev-list").
|
||||||
AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize*opts.Page).
|
AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
|
||||||
AddOptionFormat("--skip=%d", skip)
|
AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize)
|
||||||
gitCmd.AddDynamicArguments(opts.Revision)
|
gitCmd.AddDynamicArguments(opts.Revision)
|
||||||
|
|
||||||
if opts.Not != "" {
|
if opts.Not != "" {
|
||||||
@ -521,6 +519,7 @@ func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCommitBranchStart returns the commit where the branch diverged
|
||||||
func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) {
|
func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) {
|
||||||
cmd := NewCommand(repo.Ctx, "log", prettyLogFormat)
|
cmd := NewCommand(repo.Ctx, "log", prettyLogFormat)
|
||||||
cmd.AddDynamicArguments(endCommitID)
|
cmd.AddDynamicArguments(endCommitID)
|
||||||
@ -535,7 +534,8 @@ func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID s
|
|||||||
|
|
||||||
parts := bytes.Split(bytes.TrimSpace(stdout), []byte{'\n'})
|
parts := bytes.Split(bytes.TrimSpace(stdout), []byte{'\n'})
|
||||||
|
|
||||||
var startCommitID string
|
// check the commits one by one until we find a commit contained by another branch
|
||||||
|
// and we think this commit is the divergence point
|
||||||
for _, commitID := range parts {
|
for _, commitID := range parts {
|
||||||
branches, err := repo.getBranches(env, string(commitID), 2)
|
branches, err := repo.getBranches(env, string(commitID), 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -543,11 +543,9 @@ func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID s
|
|||||||
}
|
}
|
||||||
for _, b := range branches {
|
for _, b := range branches {
|
||||||
if b != branch {
|
if b != branch {
|
||||||
return startCommitID, nil
|
return string(commitID), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startCommitID = string(commitID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
return "", nil
|
||||||
|
@ -8,7 +8,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRepository_GetCommitBranches(t *testing.T) {
|
func TestRepository_GetCommitBranches(t *testing.T) {
|
||||||
@ -126,3 +130,21 @@ func TestGetRefCommitID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommitsByFileAndRange(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.Git.CommitsRangeSize, 2)()
|
||||||
|
|
||||||
|
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||||
|
bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer bareRepo1.Close()
|
||||||
|
|
||||||
|
// "foo" has 3 commits in "master" branch
|
||||||
|
commits, err := bareRepo1.CommitsByFileAndRange(CommitsByFileAndRangeOptions{Revision: "master", File: "foo", Page: 1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, commits, 2)
|
||||||
|
|
||||||
|
commits, err = bareRepo1.CommitsByFileAndRange(CommitsByFileAndRangeOptions{Revision: "master", File: "foo", Page: 2})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, commits, 1)
|
||||||
|
}
|
||||||
|
66
modules/git/submodule.go
Normal file
66
modules/git/submodule.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TemplateSubmoduleCommit struct {
|
||||||
|
Path string
|
||||||
|
Commit string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTemplateSubmoduleCommits returns a list of submodules paths and their commits from a repository
|
||||||
|
// This function is only for generating new repos based on existing template, the template couldn't be too large.
|
||||||
|
func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submoduleCommits []TemplateSubmoduleCommit, _ error) {
|
||||||
|
stdoutReader, stdoutWriter, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opts := &RunOpts{
|
||||||
|
Dir: repoPath,
|
||||||
|
Stdout: stdoutWriter,
|
||||||
|
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
||||||
|
_ = stdoutWriter.Close()
|
||||||
|
defer stdoutReader.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(stdoutReader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
entry, err := parseLsTreeLine(scanner.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if entry.EntryMode == EntryModeCommit {
|
||||||
|
submoduleCommits = append(submoduleCommits, TemplateSubmoduleCommit{Path: entry.Name, Commit: entry.ID.String()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scanner.Err()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = NewCommand(ctx, "ls-tree", "-r", "--", "HEAD").Run(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetTemplateSubmoduleCommits: error running git ls-tree: %v", err)
|
||||||
|
}
|
||||||
|
return submoduleCommits, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTemplateSubmoduleIndexes Adds the given submodules to the git index.
|
||||||
|
// It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir.
|
||||||
|
func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||||
|
for _, submodule := range submodules {
|
||||||
|
cmd := NewCommand(ctx, "update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||||
|
if stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}); err != nil {
|
||||||
|
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
48
modules/git/submodule_test.go
Normal file
48
modules/git/submodule_test.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetTemplateSubmoduleCommits(t *testing.T) {
|
||||||
|
testRepoPath := filepath.Join(testReposDir, "repo4_submodules")
|
||||||
|
submodules, err := GetTemplateSubmoduleCommits(DefaultContext, testRepoPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, submodules, 2)
|
||||||
|
|
||||||
|
assert.EqualValues(t, "<°)))><", submodules[0].Path)
|
||||||
|
assert.EqualValues(t, "d2932de67963f23d43e1c7ecf20173e92ee6c43c", submodules[0].Commit)
|
||||||
|
|
||||||
|
assert.EqualValues(t, "libtest", submodules[1].Path)
|
||||||
|
assert.EqualValues(t, "1234567890123456789012345678901234567890", submodules[1].Commit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddTemplateSubmoduleIndexes(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
var err error
|
||||||
|
_, _, err = NewCommand(ctx, "init").RunStdString(&RunOpts{Dir: tmpDir})
|
||||||
|
require.NoError(t, err)
|
||||||
|
_ = os.Mkdir(filepath.Join(tmpDir, "new-dir"), 0o755)
|
||||||
|
err = AddTemplateSubmoduleIndexes(ctx, tmpDir, []TemplateSubmoduleCommit{{Path: "new-dir", Commit: "1234567890123456789012345678901234567890"}})
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, _, err = NewCommand(ctx, "add", "--all").RunStdString(&RunOpts{Dir: tmpDir})
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, _, err = NewCommand(ctx, "-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(&RunOpts{Dir: tmpDir})
|
||||||
|
require.NoError(t, err)
|
||||||
|
submodules, err := GetTemplateSubmoduleCommits(DefaultContext, tmpDir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, submodules, 1)
|
||||||
|
assert.EqualValues(t, "new-dir", submodules[0].Path)
|
||||||
|
assert.EqualValues(t, "1234567890123456789012345678901234567890", submodules[0].Commit)
|
||||||
|
}
|
1
modules/git/tests/repos/repo4_submodules/HEAD
Normal file
1
modules/git/tests/repos/repo4_submodules/HEAD
Normal file
@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/master
|
4
modules/git/tests/repos/repo4_submodules/config
Normal file
4
modules/git/tests/repos/repo4_submodules/config
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = true
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,2 @@
|
|||||||
|
x<01><>[
|
||||||
|
Β0EύΞ*ζ_<CEB6>ι$MΡ5tifBk IΕ•Ή7ζk~ήΓ9ά<39>—εά ό¦π.jΦΘ ΕOΪδΙ"zΒ`ί#I<>irF…µΝΉΐΨ$%ΉΒης|4)°―?tΌΙ=”Λ:K¦ο#[$DΏ―ϋΏ^<5E><>…΅®Σ’y½HU/<2F>f?G
|
@ -0,0 +1 @@
|
|||||||
|
e1e59caba97193d48862d6809912043871f37437
|
@ -62,3 +62,14 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error
|
|||||||
|
|
||||||
return filelist, err
|
return filelist, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTreePathLatestCommit returns the latest commit of a tree path
|
||||||
|
func (repo *Repository) GetTreePathLatestCommit(refName, treePath string) (*Commit, error) {
|
||||||
|
stdout, _, err := NewCommand(repo.Ctx, "rev-list", "-1").
|
||||||
|
AddDynamicArguments(refName).AddDashesAndList(treePath).
|
||||||
|
RunStdString(&RunOpts{Dir: repo.Path})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return repo.GetCommit(strings.TrimSpace(stdout))
|
||||||
|
}
|
||||||
|
@ -17,7 +17,6 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
|
|||||||
ptree: t,
|
ptree: t,
|
||||||
ID: t.ID,
|
ID: t.ID,
|
||||||
name: "",
|
name: "",
|
||||||
fullName: "",
|
|
||||||
entryMode: EntryModeTree,
|
entryMode: EntryModeTree,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,16 @@ import "code.gitea.io/gitea/modules/log"
|
|||||||
// TreeEntry the leaf in the git tree
|
// TreeEntry the leaf in the git tree
|
||||||
type TreeEntry struct {
|
type TreeEntry struct {
|
||||||
ID ObjectID
|
ID ObjectID
|
||||||
|
|
||||||
ptree *Tree
|
ptree *Tree
|
||||||
|
|
||||||
entryMode EntryMode
|
entryMode EntryMode
|
||||||
name string
|
name string
|
||||||
|
|
||||||
size int64
|
size int64
|
||||||
sized bool
|
sized bool
|
||||||
fullName string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the entry
|
// Name returns the name of the entry
|
||||||
func (te *TreeEntry) Name() string {
|
func (te *TreeEntry) Name() string {
|
||||||
if te.fullName != "" {
|
|
||||||
return te.fullName
|
|
||||||
}
|
|
||||||
return te.name
|
return te.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,3 +25,18 @@ func TestSubTree_Issue29101(t *testing.T) {
|
|||||||
assert.True(t, IsErrNotExist(err))
|
assert.True(t, IsErrNotExist(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_GetTreePathLatestCommit(t *testing.T) {
|
||||||
|
repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo6_blame"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer repo.Close()
|
||||||
|
|
||||||
|
commitID, err := repo.GetBranchCommitID("master")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, "544d8f7a3b15927cddf2299b4b562d6ebd71b6a7", commitID)
|
||||||
|
|
||||||
|
commit, err := repo.GetTreePathLatestCommit("master", "blame.txt")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, commit)
|
||||||
|
assert.EqualValues(t, "45fb6cbc12f970b04eacd5cd4165edd11c8d7376", commit.ID.String())
|
||||||
|
}
|
||||||
|
@ -99,10 +99,10 @@ func (r *Request) Param(key, value string) *Request {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body adds request raw body.
|
// Body adds request raw body. It supports string, []byte and io.Reader as body.
|
||||||
// it supports string and []byte.
|
|
||||||
func (r *Request) Body(data any) *Request {
|
func (r *Request) Body(data any) *Request {
|
||||||
switch t := data.(type) {
|
switch t := data.(type) {
|
||||||
|
case nil: // do nothing
|
||||||
case string:
|
case string:
|
||||||
bf := bytes.NewBufferString(t)
|
bf := bytes.NewBufferString(t)
|
||||||
r.req.Body = io.NopCloser(bf)
|
r.req.Body = io.NopCloser(bf)
|
||||||
@ -111,6 +111,12 @@ func (r *Request) Body(data any) *Request {
|
|||||||
bf := bytes.NewBuffer(t)
|
bf := bytes.NewBuffer(t)
|
||||||
r.req.Body = io.NopCloser(bf)
|
r.req.Body = io.NopCloser(bf)
|
||||||
r.req.ContentLength = int64(len(t))
|
r.req.ContentLength = int64(len(t))
|
||||||
|
case io.ReadCloser:
|
||||||
|
r.req.Body = t
|
||||||
|
case io.Reader:
|
||||||
|
r.req.Body = io.NopCloser(t)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported request body type %T", t))
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -141,7 +147,7 @@ func (r *Request) getResponse() (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
} else if r.req.Method == "POST" && r.req.Body == nil && len(paramBody) > 0 {
|
} else if r.req.Method == "POST" && r.req.Body == nil && len(paramBody) > 0 {
|
||||||
r.Header("Content-Type", "application/x-www-form-urlencoded")
|
r.Header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
r.Body(paramBody)
|
r.Body(paramBody) // string
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -185,6 +191,7 @@ func (r *Request) getResponse() (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Response executes request client gets response manually.
|
// Response executes request client gets response manually.
|
||||||
|
// Caller MUST close the response body if no error occurs
|
||||||
func (r *Request) Response() (*http.Response, error) {
|
func (r *Request) Response() (*http.Response, error) {
|
||||||
return r.getResponse()
|
return r.getResponse()
|
||||||
}
|
}
|
||||||
|
@ -123,13 +123,12 @@ func Init() {
|
|||||||
for _, indexerData := range items {
|
for _, indexerData := range items {
|
||||||
log.Trace("IndexerData Process Repo: %d", indexerData.RepoID)
|
log.Trace("IndexerData Process Repo: %d", indexerData.RepoID)
|
||||||
if err := index(ctx, indexer, indexerData.RepoID); err != nil {
|
if err := index(ctx, indexer, indexerData.RepoID); err != nil {
|
||||||
unhandled = append(unhandled, indexerData)
|
|
||||||
if !setting.IsInTesting {
|
if !setting.IsInTesting {
|
||||||
log.Error("Codes indexer handler: index error for repo %v: %v", indexerData.RepoID, err)
|
log.Error("Codes indexer handler: index error for repo %v: %v", indexerData.RepoID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unhandled
|
return nil // do not re-queue the failed items, otherwise some broken repo will block the queue
|
||||||
}
|
}
|
||||||
|
|
||||||
indexerQueue = queue.CreateUniqueQueue(ctx, "code_indexer", handler)
|
indexerQueue = queue.CreateUniqueQueue(ctx, "code_indexer", handler)
|
||||||
|
@ -15,6 +15,8 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/indexer/code/bleve"
|
"code.gitea.io/gitea/modules/indexer/code/bleve"
|
||||||
"code.gitea.io/gitea/modules/indexer/code/elasticsearch"
|
"code.gitea.io/gitea/modules/indexer/code/elasticsearch"
|
||||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
@ -279,7 +281,7 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
|||||||
|
|
||||||
func TestBleveIndexAndSearch(t *testing.T) {
|
func TestBleveIndexAndSearch(t *testing.T) {
|
||||||
unittest.PrepareTestEnv(t)
|
unittest.PrepareTestEnv(t)
|
||||||
|
defer test.MockVariableValue(&setting.Indexer.TypeBleveMaxFuzzniess, 2)()
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
||||||
idx := bleve.NewIndexer(dir)
|
idx := bleve.NewIndexer(dir)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/blevesearch/bleve/v2"
|
"github.com/blevesearch/bleve/v2"
|
||||||
@ -54,9 +55,9 @@ func openIndexer(path string, latestVersion int) (bleve.Index, int, error) {
|
|||||||
return index, 0, nil
|
return index, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method test the GuessFuzzinessByKeyword method. The fuzziness is based on the levenshtein distance and determines how many chars
|
// GuessFuzzinessByKeyword guesses fuzziness based on the levenshtein distance and determines how many chars
|
||||||
// may be different on two string and they still be considered equivalent.
|
// may be different on two string, and they still be considered equivalent.
|
||||||
// Given a phrasse, its shortest word determines its fuzziness. If a phrase uses CJK (eg: `갃갃갃` `啊啊啊`), the fuzziness is zero.
|
// Given a phrase, its shortest word determines its fuzziness. If a phrase uses CJK (eg: `갃갃갃` `啊啊啊`), the fuzziness is zero.
|
||||||
func GuessFuzzinessByKeyword(s string) int {
|
func GuessFuzzinessByKeyword(s string) int {
|
||||||
tokenizer := unicode_tokenizer.NewUnicodeTokenizer()
|
tokenizer := unicode_tokenizer.NewUnicodeTokenizer()
|
||||||
tokens := tokenizer.Tokenize([]byte(s))
|
tokens := tokenizer.Tokenize([]byte(s))
|
||||||
@ -85,5 +86,5 @@ func guessFuzzinessByKeyword(s string) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return min(maxFuzziness, len(s)/4)
|
return min(min(setting.Indexer.TypeBleveMaxFuzzniess, maxFuzziness), len(s)/4)
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBleveGuessFuzzinessByKeyword(t *testing.T) {
|
func TestBleveGuessFuzzinessByKeyword(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.Indexer.TypeBleveMaxFuzzniess, 2)()
|
||||||
|
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
Input string
|
Input string
|
||||||
Fuzziness int // See util.go for the definition of fuzziness in this particular context
|
Fuzziness int // See util.go for the definition of fuzziness in this particular context
|
||||||
@ -46,7 +51,7 @@ func TestBleveGuessFuzzinessByKeyword(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, scenario := range scenarios {
|
for _, scenario := range scenarios {
|
||||||
t.Run(fmt.Sprintf("ensure fuzziness of '%s' is '%d'", scenario.Input, scenario.Fuzziness), func(t *testing.T) {
|
t.Run(fmt.Sprintf("Fuziniess:%s=%d", scenario.Input, scenario.Fuzziness), func(t *testing.T) {
|
||||||
assert.Equal(t, scenario.Fuzziness, GuessFuzzinessByKeyword(scenario.Input))
|
assert.Equal(t, scenario.Fuzziness, GuessFuzzinessByKeyword(scenario.Input))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -73,9 +73,9 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
|
|||||||
UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(),
|
UpdatedBeforeUnix: options.UpdatedBeforeUnix.Value(),
|
||||||
PriorityRepoID: 0,
|
PriorityRepoID: 0,
|
||||||
IsArchived: options.IsArchived,
|
IsArchived: options.IsArchived,
|
||||||
Org: nil,
|
Owner: nil,
|
||||||
Team: nil,
|
Team: nil,
|
||||||
User: nil,
|
Doer: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(options.MilestoneIDs) == 1 && options.MilestoneIDs[0] == 0 {
|
if len(options.MilestoneIDs) == 1 && options.MilestoneIDs[0] == 0 {
|
||||||
|
@ -92,6 +92,11 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
|
|||||||
projectID = issue.Project.ID
|
projectID = issue.Project.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
projectColumnID, err := issue.ProjectColumnID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
return &internal.IndexerData{
|
return &internal.IndexerData{
|
||||||
ID: issue.ID,
|
ID: issue.ID,
|
||||||
RepoID: issue.RepoID,
|
RepoID: issue.RepoID,
|
||||||
@ -106,7 +111,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
|
|||||||
NoLabel: len(labels) == 0,
|
NoLabel: len(labels) == 0,
|
||||||
MilestoneID: issue.MilestoneID,
|
MilestoneID: issue.MilestoneID,
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
ProjectColumnID: issue.ProjectColumnID(ctx),
|
ProjectColumnID: projectColumnID,
|
||||||
PosterID: issue.PosterID,
|
PosterID: issue.PosterID,
|
||||||
AssigneeID: issue.AssigneeID,
|
AssigneeID: issue.AssigneeID,
|
||||||
MentionIDs: mentionIDs,
|
MentionIDs: mentionIDs,
|
||||||
|
@ -72,10 +72,14 @@ func (c *HTTPClient) batch(ctx context.Context, operation string, objects []Poin
|
|||||||
|
|
||||||
url := fmt.Sprintf("%s/objects/batch", c.endpoint)
|
url := fmt.Sprintf("%s/objects/batch", c.endpoint)
|
||||||
|
|
||||||
|
// Original: In some lfs server implementations, they require the ref attribute. #32838
|
||||||
// `ref` is an "optional object describing the server ref that the objects belong to"
|
// `ref` is an "optional object describing the server ref that the objects belong to"
|
||||||
// but some (incorrect) lfs servers require it, so maybe adding an empty ref here doesn't break the correct ones.
|
// but some (incorrect) lfs servers like aliyun require it, so maybe adding an empty ref here doesn't break the correct ones.
|
||||||
// https://github.com/git-lfs/git-lfs/blob/a32a02b44bf8a511aa14f047627c49e1a7fd5021/docs/api/batch.md?plain=1#L37
|
// https://github.com/git-lfs/git-lfs/blob/a32a02b44bf8a511aa14f047627c49e1a7fd5021/docs/api/batch.md?plain=1#L37
|
||||||
request := &BatchRequest{operation, c.transferNames(), &Reference{}, objects}
|
//
|
||||||
|
// UPDATE: it can't use "empty ref" here because it breaks others like https://github.com/go-gitea/gitea/issues/33453
|
||||||
|
request := &BatchRequest{operation, c.transferNames(), nil, objects}
|
||||||
|
|
||||||
payload := new(bytes.Buffer)
|
payload := new(bytes.Buffer)
|
||||||
err := json.NewEncoder(payload).Encode(request)
|
err := json.NewEncoder(payload).Encode(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -29,7 +28,7 @@ var Capabilities = []string{
|
|||||||
"locking",
|
"locking",
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ transfer.Backend = &GiteaBackend{}
|
var _ transfer.Backend = (*GiteaBackend)(nil)
|
||||||
|
|
||||||
// GiteaBackend is an adapter between git-lfs-transfer library and Gitea's internal LFS API
|
// GiteaBackend is an adapter between git-lfs-transfer library and Gitea's internal LFS API
|
||||||
type GiteaBackend struct {
|
type GiteaBackend struct {
|
||||||
@ -78,17 +77,17 @@ func (g *GiteaBackend) Batch(_ string, pointers []transfer.BatchItem, args trans
|
|||||||
headerAccept: mimeGitLFS,
|
headerAccept: mimeGitLFS,
|
||||||
headerContentType: mimeGitLFS,
|
headerContentType: mimeGitLFS,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Log("http request error", err)
|
g.logger.Log("http request error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
g.logger.Log("http statuscode error", resp.StatusCode, statusCodeToErr(resp.StatusCode))
|
g.logger.Log("http statuscode error", resp.StatusCode, statusCodeToErr(resp.StatusCode))
|
||||||
return nil, statusCodeToErr(resp.StatusCode)
|
return nil, statusCodeToErr(resp.StatusCode)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
|
||||||
respBytes, err := io.ReadAll(resp.Body)
|
respBytes, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Log("http read error", err)
|
g.logger.Log("http read error", err)
|
||||||
@ -158,8 +157,7 @@ func (g *GiteaBackend) Batch(_ string, pointers []transfer.BatchItem, args trans
|
|||||||
return pointers, nil
|
return pointers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download implements transfer.Backend. The returned reader must be closed by the
|
// Download implements transfer.Backend. The returned reader must be closed by the caller.
|
||||||
// caller.
|
|
||||||
func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser, int64, error) {
|
func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser, int64, error) {
|
||||||
idMapStr, exists := args[argID]
|
idMapStr, exists := args[argID]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -187,25 +185,25 @@ func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser,
|
|||||||
headerGiteaInternalAuth: g.internalAuth,
|
headerGiteaInternalAuth: g.internalAuth,
|
||||||
headerAccept: mimeOctetStream,
|
headerAccept: mimeOctetStream,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodGet, headers, nil)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodGet, headers, nil)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, fmt.Errorf("failed to get response: %w", err)
|
||||||
}
|
}
|
||||||
|
// no need to close the body here by "defer resp.Body.Close()", see below
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return nil, 0, statusCodeToErr(resp.StatusCode)
|
return nil, 0, statusCodeToErr(resp.StatusCode)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
|
||||||
respBytes, err := io.ReadAll(resp.Body)
|
respSize, err := strconv.ParseInt(resp.Header.Get("X-Gitea-LFS-Content-Length"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, fmt.Errorf("failed to parse content length: %w", err)
|
||||||
}
|
}
|
||||||
respSize := int64(len(respBytes))
|
// transfer.Backend will check io.Closer interface and close this Body reader
|
||||||
respBuf := io.NopCloser(bytes.NewBuffer(respBytes))
|
return resp.Body, respSize, nil
|
||||||
return respBuf, respSize, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartUpload implements transfer.Backend.
|
// Upload implements transfer.Backend.
|
||||||
func (g *GiteaBackend) Upload(oid string, size int64, r io.Reader, args transfer.Args) error {
|
func (g *GiteaBackend) Upload(oid string, size int64, r io.Reader, args transfer.Args) error {
|
||||||
idMapStr, exists := args[argID]
|
idMapStr, exists := args[argID]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -234,15 +232,14 @@ func (g *GiteaBackend) Upload(oid string, size int64, r io.Reader, args transfer
|
|||||||
headerContentType: mimeOctetStream,
|
headerContentType: mimeOctetStream,
|
||||||
headerContentLength: strconv.FormatInt(size, 10),
|
headerContentLength: strconv.FormatInt(size, 10),
|
||||||
}
|
}
|
||||||
reqBytes, err := io.ReadAll(r)
|
|
||||||
if err != nil {
|
req := newInternalRequestLFS(g.ctx, url, http.MethodPut, headers, nil)
|
||||||
return err
|
req.Body(r)
|
||||||
}
|
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodPut, headers, reqBytes)
|
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return statusCodeToErr(resp.StatusCode)
|
return statusCodeToErr(resp.StatusCode)
|
||||||
}
|
}
|
||||||
@ -284,11 +281,12 @@ func (g *GiteaBackend) Verify(oid string, size int64, args transfer.Args) (trans
|
|||||||
headerAccept: mimeGitLFS,
|
headerAccept: mimeGitLFS,
|
||||||
headerContentType: mimeGitLFS,
|
headerContentType: mimeGitLFS,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return transfer.NewStatus(transfer.StatusInternalServerError), err
|
return transfer.NewStatus(transfer.StatusInternalServerError), err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return transfer.NewStatus(uint32(resp.StatusCode), http.StatusText(resp.StatusCode)), statusCodeToErr(resp.StatusCode)
|
return transfer.NewStatus(uint32(resp.StatusCode), http.StatusText(resp.StatusCode)), statusCodeToErr(resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func (g *giteaLockBackend) Create(path, refname string) (transfer.Lock, error) {
|
|||||||
headerAccept: mimeGitLFS,
|
headerAccept: mimeGitLFS,
|
||||||
headerContentType: mimeGitLFS,
|
headerContentType: mimeGitLFS,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Log("http request error", err)
|
g.logger.Log("http request error", err)
|
||||||
@ -102,7 +102,7 @@ func (g *giteaLockBackend) Unlock(lock transfer.Lock) error {
|
|||||||
headerAccept: mimeGitLFS,
|
headerAccept: mimeGitLFS,
|
||||||
headerContentType: mimeGitLFS,
|
headerContentType: mimeGitLFS,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Log("http request error", err)
|
g.logger.Log("http request error", err)
|
||||||
@ -185,7 +185,7 @@ func (g *giteaLockBackend) queryLocks(v url.Values) ([]transfer.Lock, string, er
|
|||||||
headerAccept: mimeGitLFS,
|
headerAccept: mimeGitLFS,
|
||||||
headerContentType: mimeGitLFS,
|
headerContentType: mimeGitLFS,
|
||||||
}
|
}
|
||||||
req := newInternalRequest(g.ctx, url, http.MethodGet, headers, nil)
|
req := newInternalRequestLFS(g.ctx, url, http.MethodGet, headers, nil)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Log("http request error", err)
|
g.logger.Log("http request error", err)
|
||||||
|
@ -5,15 +5,12 @@ package backend
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/httplib"
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
"code.gitea.io/gitea/modules/proxyprotocol"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/git-lfs-transfer/transfer"
|
"github.com/charmbracelet/git-lfs-transfer/transfer"
|
||||||
)
|
)
|
||||||
@ -89,53 +86,19 @@ func statusCodeToErr(code int) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInternalRequest(ctx context.Context, url, method string, headers map[string]string, body []byte) *httplib.Request {
|
func newInternalRequestLFS(ctx context.Context, url, method string, headers map[string]string, body any) *httplib.Request {
|
||||||
req := httplib.NewRequest(url, method).
|
req := private.NewInternalRequest(ctx, url, method)
|
||||||
SetContext(ctx).
|
|
||||||
SetTimeout(10*time.Second, 60*time.Second).
|
|
||||||
SetTLSClientConfig(&tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
if setting.Protocol == setting.HTTPUnix {
|
|
||||||
req.SetTransport(&http.Transport{
|
|
||||||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
|
||||||
var d net.Dialer
|
|
||||||
conn, err := d.DialContext(ctx, "unix", setting.HTTPAddr)
|
|
||||||
if err != nil {
|
|
||||||
return conn, err
|
|
||||||
}
|
|
||||||
if setting.LocalUseProxyProtocol {
|
|
||||||
if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
|
|
||||||
_ = conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return conn, err
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else if setting.LocalUseProxyProtocol {
|
|
||||||
req.SetTransport(&http.Transport{
|
|
||||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
||||||
var d net.Dialer
|
|
||||||
conn, err := d.DialContext(ctx, network, address)
|
|
||||||
if err != nil {
|
|
||||||
return conn, err
|
|
||||||
}
|
|
||||||
if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
|
|
||||||
_ = conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, err
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range headers {
|
for k, v := range headers {
|
||||||
req.Header(k, v)
|
req.Header(k, v)
|
||||||
}
|
}
|
||||||
|
switch body := body.(type) {
|
||||||
req.Body(body)
|
case nil: // do nothing
|
||||||
|
case []byte:
|
||||||
|
req.Body(body) // []byte
|
||||||
|
case io.Reader:
|
||||||
|
req.Body(body) // io.Reader or io.ReadCloser
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unsupported request body type %T", body))
|
||||||
|
}
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
type Event struct {
|
type Event struct {
|
||||||
Time time.Time
|
Time time.Time
|
||||||
|
|
||||||
GoroutinePid string
|
|
||||||
Caller string
|
Caller string
|
||||||
Filename string
|
Filename string
|
||||||
Line int
|
Line int
|
||||||
@ -218,18 +217,17 @@ func EventFormatTextMessage(mode *WriterMode, event *Event, msgFormat string, ms
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&Lgopid == Lgopid {
|
if flags&Lgopid == Lgopid {
|
||||||
if event.GoroutinePid != "" {
|
deprecatedGoroutinePid := "no-gopid" // use a dummy value to avoid breaking the log format
|
||||||
buf = append(buf, '[')
|
buf = append(buf, '[')
|
||||||
if mode.Colorize {
|
if mode.Colorize {
|
||||||
buf = append(buf, ColorBytes(FgHiYellow)...)
|
buf = append(buf, ColorBytes(FgHiYellow)...)
|
||||||
}
|
}
|
||||||
buf = append(buf, event.GoroutinePid...)
|
buf = append(buf, deprecatedGoroutinePid...)
|
||||||
if mode.Colorize {
|
if mode.Colorize {
|
||||||
buf = append(buf, resetBytes...)
|
buf = append(buf, resetBytes...)
|
||||||
}
|
}
|
||||||
buf = append(buf, ']', ' ')
|
buf = append(buf, ']', ' ')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
buf = append(buf, msg...)
|
buf = append(buf, msg...)
|
||||||
|
|
||||||
if event.Stacktrace != "" && mode.StacktraceLevel <= event.Level {
|
if event.Stacktrace != "" && mode.StacktraceLevel <= event.Level {
|
||||||
|
@ -28,14 +28,13 @@ func TestEventFormatTextMessage(t *testing.T) {
|
|||||||
Caller: "caller",
|
Caller: "caller",
|
||||||
Filename: "filename",
|
Filename: "filename",
|
||||||
Line: 123,
|
Line: 123,
|
||||||
GoroutinePid: "pid",
|
|
||||||
Level: ERROR,
|
Level: ERROR,
|
||||||
Stacktrace: "stacktrace",
|
Stacktrace: "stacktrace",
|
||||||
},
|
},
|
||||||
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.Equal(t, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [pid] msg format: arg0 arg1
|
assert.Equal(t, `[PREFIX] 2020/01/02 03:04:05.000000 filename:123:caller [E] [no-gopid] msg format: arg0 arg1
|
||||||
stacktrace
|
stacktrace
|
||||||
|
|
||||||
`, string(res))
|
`, string(res))
|
||||||
@ -46,12 +45,11 @@ func TestEventFormatTextMessage(t *testing.T) {
|
|||||||
Caller: "caller",
|
Caller: "caller",
|
||||||
Filename: "filename",
|
Filename: "filename",
|
||||||
Line: 123,
|
Line: 123,
|
||||||
GoroutinePid: "pid",
|
|
||||||
Level: ERROR,
|
Level: ERROR,
|
||||||
Stacktrace: "stacktrace",
|
Stacktrace: "stacktrace",
|
||||||
},
|
},
|
||||||
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
"msg format: %v %v", "arg0", NewColoredValue("arg1", FgBlue),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.Equal(t, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mpid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n", string(res))
|
assert.Equal(t, "[PREFIX] \x1b[36m2020/01/02 03:04:05.000000 \x1b[0m\x1b[32mfilename:123:\x1b[32mcaller\x1b[0m \x1b[1;31m[E]\x1b[0m [\x1b[93mno-gopid\x1b[0m] msg format: arg0 \x1b[34marg1\x1b[0m\n\tstacktrace\n\n", string(res))
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ const (
|
|||||||
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
|
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
|
||||||
Llevelinitial // Initial character of the provided level in brackets, eg. [I] for info
|
Llevelinitial // Initial character of the provided level in brackets, eg. [I] for info
|
||||||
Llevel // Provided level in brackets [INFO]
|
Llevel // Provided level in brackets [INFO]
|
||||||
Lgopid // the Goroutine-PID of the context
|
Lgopid // the Goroutine-PID of the context, deprecated and it is always a const value
|
||||||
|
|
||||||
Lmedfile = Lshortfile | Llongfile // last 20 characters of the filename
|
Lmedfile = Lshortfile | Llongfile // last 20 characters of the filename
|
||||||
LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial // default
|
LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial // default
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user