Compare commits

...

120 Commits

Author SHA1 Message Date
Lunny Xiao
de7026528b Release of Gitea 1.23.4 (#33621)
---------

Co-authored-by: Zettat123 <zettat123@gmail.com>
2025-02-19 01:16:26 +00:00
Lunny Xiao
ee3f5e8fac fix: add missing locale (#33641) (#33642) 2025-02-19 00:57:14 +00:00
Giteabot
b2707bcd18 Make actions URL in commit status webhooks absolute (#33620) (#33632)
Backport #33620 by lunny

Fix #33603

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-18 02:46:08 +00:00
Giteabot
0512b02b01 Fix project issues list and counting (#33594) (#33619)
Backport #33594 by lunny

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-18 00:59:32 +08:00
Giteabot
99545ae2fd Fix mirror bug (#33597) (#33607)
Backport #33597 by @ericLemanissier

follows-up be4e961240883778c44d9651eaaf9ab8723bbbb0

This is the same modification as
be4e961240
but for force-pushes.
It is needed, because `git fetch` reveals force pushes for github
mirrors:
```
$ git fetch --tags origin
remote: Enumerating objects: 22, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 5), reused 8 (delta 5), pack-reused 0 (from 0)
Unpacking objects: 100% (9/9), 1.70 KiB | 12.00 KiB/s, done.
From https://github.com/conan-io/conan-center-index
   729f0f1b8f..48184eddeb  refs/pull/26595/head  -> refs/pull/26595/head
 + 0c31ab60a3...1283cca9e7 refs/pull/26595/merge -> refs/pull/26595/merge  (forced update)
```

Fix https://github.com/go-gitea/gitea/issues/33200

PS: I did not test the modification, but it is the exact same change as
the last hunk in
https://github.com/go-gitea/gitea/pull/33224/files#diff-bb5cdb90db0f0e7f6716c0e6d0b9cbb67f08d82052b03ab3a7b5e23a1d76aed7
, just moved to the previous case of the switch

Co-authored-by: ericLemanissier <ericLemanissier@users.noreply.github.com>
2025-02-15 21:17:34 -08:00
Giteabot
7697df9f93 Use default Git timeout when checking repo health (#33593) (#33598)
Backport #33593 by @Zettat123

Use `git.timeout.DEFAULT` configuration instead of 60 seconds.

Co-authored-by: Zettat123 <zettat123@gmail.com>
2025-02-14 15:38:55 +00:00
wxiaoguang
d17f8ffcc1 Fix PR's target branch dropdown (#33589) (#33591)
Backport #33589
2025-02-14 08:38:33 +00:00
Giteabot
5e9cc919cf Performance optimization for pull request files loading comments attachments (#33585) (#33592)
Backport #33585 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-02-14 00:06:46 -08:00
Giteabot
cc6ec56738 Only show the latest version in the Arch index (#33262) (#33580)
Backport #33262 by ExplodingDragon

Only show the latest version of the package in the arch repo.

closes #33534

Co-authored-by: Exploding Dragon <explodingfkl@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-13 20:02:28 +08:00
Giteabot
76bd60fc1d Fix various problems (artifact order, api empty slice, assignee check, fuzzy prompt, mirror proxy, adopt git) (#33569) (#33577)
Backport #33569 by @wxiaoguang

* Make artifact list output has stable order
* Fix #33506
* Fix #33521
* Fix #33288
* Fix #33196
* Fix #33561

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-13 07:33:11 +08:00
wxiaoguang
744f7c8200 Skip deletion error for action artifacts (#33476) (#33568)
Fix #33567
2025-02-13 03:27:37 +08:00
Lunny Xiao
da33b708af Add a transaction to pickTask (#33543) (#33563)
Backport #33543 

In the old `pickTask`, when getting secrets or variables failed, the
task could get stuck in the `running` status (task status is `running`
but the runner did not fetch the task). To fix this issue, these steps
should be in one transaction.

---------

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-12 11:53:56 +08:00
wxiaoguang
8fa3925874 Fix context usage (#33554) (#33557)
Backport #33554
2025-02-11 19:46:27 +08:00
Lunny Xiao
7794ff0874 Enhance routers for the Actions runner operations (#33549) (#33555)
Backport #33549 

- Find the runner before deleting
- Move the main logic from `routers/web/repo/setting/runners.go` to
`routers/web/shared/actions/runners.go`.

Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-11 15:25:56 +08:00
Lunny Xiao
7c17d0a73e Enhance routers for the Actions variable operations (#33547) (#33553)
Backport #33547

Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2025-02-11 03:52:09 +00:00
Giteabot
a014d071e4 Rework suggestion backend (#33538) (#33546)
Backport #33538 by @lunny

Fix #33522 

The suggestion backend logic now is

- If the keyword is empty, returned the latest 5 issues/prs with index
desc order
- If the keyword is digital, find all issues/prs which `index` has a
prefix with that, with index asc order
- If the keyword is non-digital or if the queried records less than 5,
searching issues/prs title with a `like`, with index desc order

## Empty keyword
<img width="310" alt="image"
src="https://github.com/user-attachments/assets/1912c634-0d98-4eeb-8542-d54240901f77"
/>

## Digital
<img width="479" alt="image"
src="https://github.com/user-attachments/assets/0356a936-7110-4a24-b21e-7400201bf9b8"
/>

## Digital and title contains the digital
<img width="363" alt="image"
src="https://github.com/user-attachments/assets/6e12f908-28fe-48de-8ccc-09cbeab024d4"
/>

## non-Digital
<img width="435" alt="image"
src="https://github.com/user-attachments/assets/2722bb53-baa2-4d67-a224-522a65f73856"
/>
<img width="477" alt="image"
src="https://github.com/user-attachments/assets/06708dd9-80d1-4a88-b32b-d29072dd1ba6"
/>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-11 01:22:39 +08:00
Lunny Xiao
312565e3c2 Add changelog for 1.23.3 (#33515)
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2025-02-06 12:32:13 +08:00
Lunny Xiao
58daaf66e8 Fix a bug caused by status webhook template (#33512)
Fix #33511
2025-02-06 08:48:22 +08:00
Lunny Xiao
f076ada601 Add changelog for 1.23.2 (#33494)
Wait 
- #33499
- #33493
- #33503

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-06 02:09:17 +08:00
Lunny Xiao
92436b8b2a add timetzdata build tag to binary releases (#33463) (#33503)
Backport #33463

Co-authored-by: techknowlogick <techknowlogick@gitea.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-05 19:06:58 +08:00
Giteabot
2df7d0835a Fix unnecessary comment when moving issue on the same project column (#33496) (#33499)
Backport #33496 by @lunny

Fix #33482

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-02-05 04:41:48 +00:00
Lunny Xiao
200cb6140d Fix commit status events (#33320) (#33493)
Fix #32873
Fix #33201
~Fix #33244~
~Fix #33302~

depends on ~#33396~
backport #33320
2025-02-05 11:35:47 +08:00
Giteabot
2746c6f1aa Correct bot label vertical-align (#33477) (#33480) 2025-02-02 15:08:59 -05:00
Lunny Xiao
23971a77a0 Add tests for webhook and fix some webhook bugs (#33396) (#33442)
This PR created a mock webhook server in the tests and added integration
tests for generic webhooks.
It also fixes bugs in package webhooks and pull request comment
webhooks.

This also corrected an error on the package webhook. The previous
implementation uses a `User` struct as an organization, now it has been
corrected but it will not be consistent with the previous
implementation, some fields which not belong to the organization have
been removed.

Backport #33396
Backport part of #33337
2025-02-02 14:44:50 +08:00
Giteabot
ebac324ff2 Fix GetCommitBranchStart bug (#33298) (#33421)
Backport #33298 by Zettat123

Fix #33265
Fix #33370

This PR also fixes some bugs in `TestGitGeneral`.

---------

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-02-01 09:43:10 +01:00
Giteabot
7df1204795 Fix SSH LFS memory usage (#33455) (#33460)
Backport #33455 by wxiaoguang

Fix #33448

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-31 11:30:16 +00:00
Giteabot
159544a950 Revert empty lfs ref name (#33454) (#33457)
Backport #33454 by wxiaoguang

Fix #33453

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-31 10:27:23 +00:00
Giteabot
9780da583d Fix issue sidebar dropdown keyboard support (#33447) (#33450)
Backport #33447 by wxiaoguang

Just a quick fix, fix #33444

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-31 10:11:51 +08:00
wxiaoguang
a8eaf43f97 Fix user avatar (#33439) 2025-01-30 17:11:13 +08:00
Giteabot
b6fd8741ee Fix system admin cannot fork or get private fork with API (#33401) (#33417)
Backport #33401 by @lunny

Fix #33368

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-01-27 18:43:16 +00:00
Giteabot
2674d27fb8 Add pubdate for repository rss and add some tests (#33411) (#33416)
Backport #33411 by @lunny

Fix #33291

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-01-27 17:42:47 +00:00
Giteabot
6f3837284d Fix flex width (#33414) (#33418)
Backport #33414 by wxiaoguang

Fix #33409

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-27 17:16:21 +00:00
wxiaoguang
c30f4f4be5 Fix issue suggestion bug (#33389) (#33391)
Backport #33389
2025-01-27 19:11:13 +08:00
Giteabot
4578288ea3 Use ProtonMail/go-crypto to replace keybase/go-crypto (#33402) (#33410)
Backport #33402 by wxiaoguang

Fix #33400

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-27 02:50:00 +00:00
Giteabot
826fffb59e Add missed auto merge feed message on dashboard (#33309) (#33405)
Backport #33309 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-01-26 18:57:45 +00:00
Giteabot
2196ba5e42 Clone button enhancements (#33362) (#33404)
Backport #33362 by @silverwind

- Add box-shadow to default tippy theme
- Make colors for tabs match the ones from `.ui.tabular.menu`
- Remove tippy arrow and slightly offset tooltip closer to the button
- Fix setting of `aria-haspopup` when default role is used with tippy

<img width="335" alt="image"
src="https://github.com/user-attachments/assets/8633ebac-a43f-457a-86bd-7a88a83519ee"
/>

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-26 19:20:57 +01:00
Giteabot
12347f07ae Repo homepage styling tweaks (#33289) (#33381)
Backport #33289 by @silverwind

Reduce it to a value that results in `.repo-home-sidebar-top` and
`.repo-home-sidebar-bottom` having 240px content width, the same as
GitHub.

Co-authored-by: silverwind <me@silverwind.io>
2025-01-24 13:41:01 -05:00
silverwind
a3c5358d35 Update katex to latest version (#33361)
Partial backport of https://github.com/go-gitea/gitea/pull/33359.
Upgrade katex because there were a number of security problems fixed in
recent versions.
2025-01-23 01:21:58 +01:00
silverwind
987d014468 Update go tool dependencies (#32916) (#33355)
Clean cherry-pick of https://github.com/go-gitea/gitea/pull/32916.
Update all go tool dependencies to latest version.
2025-01-22 11:37:47 -05:00
Giteabot
e08eed9040 Fix code button alignment (#33345) (#33351)
Backport #33345 by silverwind

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-22 15:18:34 +08:00
wxiaoguang
4ffa49aa04 Make issue suggestion work for all editors (#33340) (#33342)
Backport #33340

And do not handle special keys when the text-expander popup exists
2025-01-21 21:09:37 +08:00
Giteabot
72837530bf Fix issue count (#33338) (#33341)
Backport #33338 by wxiaoguang

Fix #33336

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-21 11:18:22 +00:00
wxiaoguang
eef635523a Make tracked time representation display as hours (#33315) (#33334)
Try to backport #33315, the only trivial conflict is in the helper
functions map in the helper.go

Fix #33333

Co-authored-by: Sysoev, Vladimir <i@vsysoev.ru>
2025-01-21 06:49:58 +08:00
wxiaoguang
8f45a11919 Improve sync fork behavior (#33319) (#33332)
Backport #33319
Fix #33271

The only conflict is `reqctx` in
`services/repository/merge_upstream.go`, which could keep using
`context.Context` in 1.23
2025-01-20 07:50:38 +00:00
Giteabot
e72d001708 Fix Account linking page (#33325) (#33327)
Backport #33325 by CrimsonEdgeHope

Fix password form missing whilst linking account even with
`ENABLE_PASSWORD_SIGNIN_FORM = true`.

Remove redundant empty box in account linking sign up page when
`LinkAccountMode` is true.

Co-authored-by: CrimsonEdgeHope <92579614+CrimsonEdgeHope@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-19 13:02:33 +00:00
wxiaoguang
8d9ea68f19 Fix push message behavior (#33215) (#33317)
Backport #33215

Manually resolved "reqctx" conflict

---------

Co-authored-by: Chai-Shi <changchaishi@gmail.com>
2025-01-19 10:48:28 +08:00
wxiaoguang
bf664c2e85 Trivial fixes (#33304) (#33312)
Backport #33304

The only conflict is caused by `templates/shared/issueicon.tmpl`
2025-01-18 03:09:17 +08:00
wxiaoguang
52d298890b Fix "stop time tracking button" on navbar (#33084) (#33300)
Backport #33084 (no conflict)
Fix #33299, and remove incorrect translations
2025-01-17 04:48:31 +08:00
wxiaoguang
c09e43acf5 Fix closed dependency title (#33285) (#33287)
Backport #33285
2025-01-15 16:05:01 +00:00
Giteabot
3b4af01633 Fix sidebar milestone link (#33269) (#33272)
Backport #33269 by wxiaoguang

Fix  #33266

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-15 00:19:37 +00:00
Giteabot
b4e2d5e8ee Add a confirm dialog for "sync fork" (#33270) (#33273)
Backport #33270 by @wxiaoguang

Try to quickly fix #33264

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-15 00:51:17 +02:00
Giteabot
2984a7c121 Fix missing license when sync mirror (#33255) (#33258)
Backport #33255 by yp05327

Fix #33222

Co-authored-by: yp05327 <576951401@qq.com>
2025-01-14 06:26:27 +00:00
wxiaoguang
80cc87b3d8 Fix tag route and empty repo (#33253) 2025-01-14 14:01:30 +08:00
Giteabot
10b6047498 Fix upload file form (#33230) (#33233)
Backport #33230 by @wxiaoguang

Fix #33228

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-13 01:49:56 +02:00
Giteabot
2c47b06869 Fix mirror bug (#33224) (#33225)
Backport #33224 by lunny

Fix #33200

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-12 11:11:02 +00:00
Giteabot
31f2a325dc fix(cache): cache test triggered by non memory cache (#33220) (#33221)
Backport #33220 by TheFox0x7

Change SlowCacheThreshold to 30 milliseconds so it doesn't trigger on
non memory cache

Closes: https://github.com/go-gitea/gitea/issues/33190
Closes: https://github.com/go-gitea/gitea/issues/32657

Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
2025-01-12 09:19:37 +08:00
Lunny Xiao
fcbbc24cc4 Change log for 1.23.1 (#33191) 2025-01-10 16:06:45 +08:00
wxiaoguang
1454e1b6eb Fix editor markdown not incrementing in a numbered list (#33187) (#33193)
Backport #33187 (no conflict)

Co-authored-by: Harry Vince <47283812+harryvince@users.noreply.github.com>
2025-01-10 16:00:22 +08:00
Giteabot
d70348836b Fix sync fork for consistency (#33147) (#33192)
Backport #33147 by changchaishi

Fixes #33145

An integration test could be added.

---------

Co-authored-by: Chai-Shi <changchaishi@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-10 15:11:45 +08:00
Giteabot
940a930d13 Use updated path to s6-svscan after alpine upgrade (#33185) (#33188)
Backport #33185 by @techknowlogick

Fix #33163

Co-authored-by: techknowlogick <techknowlogick@gitea.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-10 02:48:52 +00:00
Giteabot
45d21a0d5c Fix raw file API ref handling (#33172) (#33189)
Backport #33172 by wxiaoguang

Fix #33164 and add more tests

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-10 02:41:28 +00:00
Giteabot
15ad001aef Fix branch dropdown not display ref name (#33159) (#33183)
Backport #33159 by @yp05327

Before:

![image](https://github.com/user-attachments/assets/899d25a9-80e9-48d5-a820-79c911c858e9)
After:

![image](https://github.com/user-attachments/assets/cf2a7407-909a-41db-9957-19d9214af57e)

Co-authored-by: yp05327 <576951401@qq.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-10 01:41:52 +00:00
Giteabot
ed1828ca92 Fix ACME panic (#33178) (#33186)
Backport #33178 by @wxiaoguang

Fix #33177, Manually tested:

````
1.7364311850484018e+09	info	maintenance	started background certificate maintenance	{"cache": "0x1400ca64180"}
1.736431185054049e+09	info	obtain	acquiring lock	{"identifier": "example.com"}
1.736431185058073e+09	info	obtain	lock acquired	{"identifier": "example.com"}
1.736431185058133e+09	info	obtain	obtaining certificate	{"identifier": "example.com"}
````

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-10 09:06:40 +08:00
Giteabot
3cfff5af0d Move repo size to sidebar (#33155) (#33182)
Backport #33155 by @yp05327


![image](https://github.com/user-attachments/assets/8b14dbb7-ec36-4596-a6aa-72c14d93309d)

Co-authored-by: yp05327 <576951401@qq.com>
2025-01-09 20:29:37 +00:00
Giteabot
6f6c66a07d Fix assignee list overlapping in Issue sidebar (#33176) (#33181)
Backport #33176 by wxiaoguang

Fix  #33170

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-09 18:36:32 +00:00
Giteabot
d65af69c2b Fix pam auth test regression (#33169) (#33174)
Backport #33169 by TheFox0x7

fixes: https://github.com/go-gitea/gitea/issues/33168

Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
2025-01-09 13:33:50 +00:00
Giteabot
12c24c2189 Fix fuzz test (#33156) (#33158)
Backport #33156 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-01-09 07:40:35 +00:00
Lunny Xiao
a330f42f01 Update changelog for v1.23.0 (#33130) 2025-01-09 09:24:34 +08:00
wxiaoguang
531f36ea4a Fix git remote error check, fix dependencies, fix js error (#33129) (#33133)
And update some dependencies to fix bugs.

Backport  #33129, #33136

Fix #32889
Fix #33141
Fix #33139

---------

Co-authored-by: yp05327 <576951401@qq.com>
2025-01-08 05:08:44 +00:00
Giteabot
b4f0eed969 Filter reviews of one pull request in memory instead of database to reduce slow response because of lacking database index (#33106) (#33128)
Backport #33106 by @lunny

This PR fixes a performance problem when reviewing a pull request in a
big instance which have many records in the `review` table.
Traditionally, we should add more indexes in that table. But since
dismissed reviews of 1 pull request will not be too many as expected in
a common repository. Filtering reviews in the memory should be more
quick .

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-08 10:43:46 +08:00
Giteabot
63b3a33bf2 fix empty repo updated time (#33120) (#33124)
Backport #33120 by changchaishi

fixes #33119 


Co-authored-by: Chai-Shi <changchaishi@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-06 23:55:04 +00:00
Lunny Xiao
9899989ece Add missing transaction when set merge (#33113)
backport from #33079 

`SetMerged` should be in a database transaction otherwise it's possible
to have dirty data.
2025-01-06 18:21:14 +00:00
wxiaoguang
0fad40dd8c Fix package error handling and npm meta and empty repo guide (#33112) 2025-01-06 14:17:28 +08:00
wxiaoguang
e637008fe3 Fix empty git repo handling logic and fix mobile view (#33101) (#33102)
Backport #33101 and UI fix from main (including #33108)
2025-01-05 23:18:02 +08:00
wxiaoguang
fd281518ae Fix line-number and scroll bugs (#33094) (#33095)
Partially backport #33094 

Fix the scroll bug in issue/pr view page.

Fix a JS error when line number exceeds the max
2025-01-03 23:50:39 +02:00
wxiaoguang
e10d222434 Fix bleve fuzziness search (#33078) (#33087) 2025-01-02 21:45:14 +00:00
wxiaoguang
7a35f90b29 Fix broken forms (#33082) 2025-01-03 03:57:34 +08:00
Giteabot
d371aa3031 Try to fix ACME directory problem (#33072) (#33077)
Backport #33072 by wxiaoguang

Haven't really confirmed, but I think it might fix #32191

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-01-02 05:02:46 +00:00
wxiaoguang
81768675d4 Inherit submodules from template repository content (#16237) (#33068)
Backport #16237 (it more likely a bug fix)

Co-authored-by: Steffen Schröter <steffen@vexar.de>
2025-01-02 12:17:05 +08:00
Giteabot
39cc72562b feat(action): issue change title notifications (#33050) (#33065)
Backport #33050 by appleboy

action file as below:

```yaml
name: Semantic Pull Request

on:
  pull_request_target:
    types: [edited]
```

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-31 12:33:08 +00:00
Giteabot
bc83fb26ef Use project's redirect url instead of composing url (#33058) (#33064)
Backport #33058 by lunny

Fix #32992

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-31 20:06:35 +08:00
wxiaoguang
68736ec292 Refactor maven package registry (#33049) (#33057)
Backport #33049
2024-12-31 15:22:09 +08:00
Giteabot
3df11c07a8 Make issue suggestion work for new PR page (#33035) (#33056)
Backport #33035 by wxiaoguang

Fix #33026

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-31 03:56:34 +00:00
Giteabot
96fff862dc Fix duplicate co-author in squashed merge commit messages (#33020) (#33054) 2024-12-31 03:04:47 +00:00
Giteabot
968c04c7da Fix issue comment number (#30556) (#33055)
Backport #30556 by @lunny

Fix #22419

Only comments with types `CommentTypeComment` and `CommentTypeReview`
will be counted as conversations of the pull request.
`CommentTypeReview` was missed in the previous implementation.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-31 07:54:40 +08:00
Giteabot
27de60381d Fix settings not being loaded at CLI (#26402) (#33048)
Backport #26402 by cassiozareck

Closes #25898

Signed-off-by: cassiozareck <cassiomilczareck@gmail.com>
Co-authored-by: cassio zareck <121526696+cassiozareck@users.noreply.github.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-30 07:39:59 +00:00
Giteabot
d2d763318c Remove aws go sdk package dependency (#33029) (#33047)
Backport #33029 by lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-30 06:55:06 +00:00
Giteabot
610b2fb88d Use gitrepo.GetTreePathLatestCommit to get file lastest commit instead from latest commit cache (#32987) (#33046) 2024-12-30 05:17:07 +00:00
Giteabot
0858a36016 use -s -w ldflags for release artifacts (#33041) (#33042)
Backport #33041 by @techknowlogick

fix #33030

Co-authored-by: techknowlogick <techknowlogick@gitea.com>
2024-12-30 04:17:17 +00:00
Giteabot
fef364e7d6 Fix bug automerge cannot be chosed when there is only 1 merge style (#33040) (#33043)
Backport #33040 by @lunny

This is a quick bug fix. Even if there is only 1 merge style, the
dropdown menu will still be displayed to allow users to choose
automerge.

Fix #32448

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-30 11:42:08 +08:00
wxiaoguang
ce6a60a38b Refactor testfixtures (#33028)
Partial backport of #33024
2024-12-30 02:49:49 +00:00
Giteabot
74159a8855 Fix templating in pull request comparison (#33025) (#33038)
Backport #33025 by TheFox0x7

Adds test for expected behavior

Closes: https://github.com/go-gitea/gitea/issues/33013

---

Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
2024-12-29 18:24:22 +00:00
wxiaoguang
ce6464123f fix toggle commit body button ui when latest commit message is long (#32997) (#33034)
backport #32997 and #33002
2024-12-29 17:54:23 +00:00
Giteabot
7f0050cf39 Fix review code comment avatar alignment (#33031) (#33032)
Backport #33031 by henrygoodman

Fixes #33017

Co-authored-by: Henry Goodman <79623665+henrygoodman@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-30 00:58:40 +08:00
Giteabot
c102e344f3 Fix bug on activities (#33008) (#33016)
Backport #33008 by @lunny

A repository with no issue will display a random number on activities
page. This is caused by wrong usage of `And` and `Or`.


![9cdbbf81d50aa5d9bd16604e0dab5eb0](https://github.com/user-attachments/assets/828cebdc-bd35-4716-a58c-c1b43ddf8bf0)

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-28 05:04:07 +00:00
Giteabot
f27128bf94 fix scoped label ui when contains emoji (#33007) (#33014)
Backport #33007 by metiftikci

Co-authored-by: metiftikci <metiftikci@hotmail.com>
2024-12-28 04:34:53 +00:00
Giteabot
f35ab5cd52 Fix Agit pull request permission check (#32999) (#33005)
Backport #32999 by @a1012112796

user with read permission should also can create agit flow pull request.
looks this logic was broken in
https://github.com/go-gitea/gitea/pull/31033 this pull request try fix
it and add test code.

Signed-off-by: a1012112796 <1012112796@qq.com>
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-28 11:34:28 +08:00
Giteabot
0137bc4e5c Support for email addresses containing uppercase characters when activating user account (#32998) (#33001)
Backport #32998 by Zettat123

Fix #32807

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-27 11:41:41 +00:00
Giteabot
eed0968c37 Support org labels when adding labels by label names (#32988) (#32996)
Backport #32988 by @Zettat123

Fix #32891

Co-authored-by: Zettat123 <zettat123@gmail.com>
2024-12-27 08:35:36 +08:00
Giteabot
a0b65ed17f Do not render truncated links in markdown (#32980) (#32983)
Backport #32980 by wxiaoguang

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-26 01:12:18 +08:00
Giteabot
ad1b76540e demilestone should not include milestone (#32923) (#32979)
Backport #32923 by @lunny

Fix #32887

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-25 08:03:18 +00:00
Giteabot
6636b37a9c Fix Azure blob object Seek (#32974) (#32975)
Backport #32974 by Zettat123

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-25 06:17:27 +00:00
Giteabot
af5e5e8f00 Fix maven pom inheritance (#32943) (#32976)
Backport #32943 by wxiaoguang

Fix  #30568

At the moment, here only `GroupID` (no `Version`) is parsed & used

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-25 05:47:51 +00:00
Giteabot
0e0ebf68d7 fix textarea newline handle (#32966) (#32977)
Backport #32966 by metiftikci

Co-authored-by: metiftikci <metiftikci@hotmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-25 13:10:14 +08:00
Giteabot
90bd08ceef Use env GITEA_RUNNER_REGISTRATION_TOKEN as global runner token (#32946) (#32964)
Backport #32946 by wxiaoguang

Fix #23703

When Gitea starts, it reads GITEA_RUNNER_REGISTRATION_TOKEN
or GITEA_RUNNER_REGISTRATION_TOKEN_FILE to add registration token.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-24 00:37:11 +08:00
Giteabot
0c581106d2 Fix outdated tmpl code (#32953) (#32961)
Backport #32953 by wxiaoguang

Some PRs were before tmpl ctx refactoring and used outdated code

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-23 07:57:36 +00:00
Giteabot
e18e31d557 Fix commit range paging (#32944) (#32962)
Backport #32944 by wxiaoguang

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-23 15:32:29 +08:00
Giteabot
e1026feddc Fix repo avatar conflict (#32958) (#32960)
Backport #32958 by wxiaoguang

Continue even if the avatar deleting fails

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-23 03:17:38 +00:00
Giteabot
d670820722 Use Alpine 3.21 for the docker images (#32924) (#32951) 2024-12-22 22:16:34 +00:00
Giteabot
a8f98fd3be fix trailing comma not matched in the case of alphanumeric issue (#32945) (#32959)
Backport #32945 by @katsusan

Fix #32428.

Patch the regex to match `,`besides `.` `"` `'` `:` and space.

Co-authored-by: katsu <evergonuaa@gmail.com>
2024-12-23 06:08:35 +08:00
Giteabot
c442c682ef Use primary as button color (#32949) (#32950)
Backport #32949 by wxiaoguang

* Fix #32871
* Fix #32948

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-22 15:28:36 +00:00
Giteabot
57868c2315 Fix locale (#32937) (#32942) 2024-12-21 19:10:42 -05:00
Giteabot
b1c21880c1 Update i18n.go - Language Picker (#32933) (#32935) 2024-12-21 10:24:17 -05:00
wxiaoguang
1e71ad89ce Deprecated gopid in log (#32932) 2024-12-20 16:20:51 +00:00
Giteabot
c20642fa99 Relax the version checking for Arch packages (#32908) (#32913)
Backport #32908 by ExplodingDragon

It is mentioned in https://man.archlinux.org/man/PKGBUILD.5: 'The
variable is not allowed to contain colons, forward slashes, hyphens, or
whitespace.'

`_` is also an allowed character, and some software in the Arch Linux
AUR uses this naming convention.

Co-authored-by: Exploding Dragon <explodingfkl@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-19 19:02:58 +08:00
Giteabot
a4291fd553 Add more load functions to make sure the reference object loaded (#32901) (#32912)
Backport #32901 by @lunny

Fix #32897

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-12-19 10:14:04 +01:00
techknowlogick
fa5a064559 bump x/net (#32896) (#32899)
backport #32896 to 1.23
2024-12-18 22:44:55 +00:00
Giteabot
cb42232080 Fix Arch package metadata introduced incorrect field (#32881) (#32882)
Backport #32881 by ExplodingDragon

Incorrect content was introduced while generating the index, which has
now been removed, and the missing fields have been added.

Co-authored-by: Exploding Dragon <explodingfkl@gmail.com>
2024-12-18 12:56:47 +01:00
Lunny Xiao
c8ffe777cf Add 1.23.0-rc0 changelog (#32863)
Notice: some of pull requests haven't been added to the changelog

- Which have been backported to v1.22
-
https://github.com/go-gitea/gitea/pulls?q=sort%3Aupdated-desc+is%3Apr+milestone%3A1.23.0+is%3Amerged+label%3Abackport%2Fv1.22
- Which have skip-changelog
-
https://github.com/go-gitea/gitea/pulls?q=sort%3Aupdated-desc+is%3Apr+milestone%3A1.23.0+is%3Amerged+-label%3Abackport%2Fv1.22+label%3Askip-changelog
- Build and Testing
-
https://github.com/go-gitea/gitea/pulls?q=sort%3Aupdated-desc+is%3Apr+milestone%3A1.23.0+is%3Amerged+label%3Abackport%2Fv1.22+label%3Atype%2Ftesting
-
https://github.com/go-gitea/gitea/pulls?q=sort%3Aupdated-desc+is%3Apr+milestone%3A1.23.0+is%3Amerged+label%3Abackport%2Fv1.22+label%3Atopic%2Fbuild
- No `type` label marked may be missed, I need to check one by one, but
I believe those are not too many.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2024-12-17 12:00:55 +08:00
wxiaoguang
e98dd6ee5b Backport 1.23 (#32868)
Co-authored-by: delvh <dev.lh@web.de>
2024-12-17 11:58:27 +08:00
371 changed files with 6813 additions and 2593 deletions

View File

@ -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 webhooks 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

View File

@ -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

View File

@ -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

View File

@ -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)

File diff suppressed because one or more lines are too long

View File

@ -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
} }

View File

@ -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,
} }

View File

@ -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 {

View File

@ -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 != "" {

View File

@ -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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -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
View File

@ -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
View File

@ -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
View 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"

View File

@ -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

View File

@ -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},

View File

@ -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 {

View File

@ -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 {

View File

@ -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
} }

View File

@ -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:

View File

@ -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
} }

View File

@ -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))

View File

@ -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)

View File

@ -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"
) )
// __________________ ________ ____ __. // __________________ ________ ____ __.

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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
} }
} }

View File

@ -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 {

View File

@ -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)
}

View File

@ -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)

View File

@ -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
} }

View File

@ -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
), ),
) )
} }

View File

@ -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").

View File

@ -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
} }

View File

@ -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()

View File

@ -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
} }

View File

@ -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))
} }

View File

@ -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 {

View File

@ -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{

View File

@ -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{

View File

@ -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))

View File

@ -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")

View File

@ -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 ""
} }

View File

@ -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'",
}, },

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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
} }

View 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
}

View File

@ -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()
} }

View File

@ -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))
}

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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
}

View 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)
}

View File

@ -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},
} }
} }

View File

@ -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},

View File

@ -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)
} }

View File

@ -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")

View File

@ -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) {

View File

@ -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{}
} }

View File

@ -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
View 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
}

View File

@ -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

View File

@ -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
} }

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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
View 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
}

View 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)
}

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,4 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true

View File

@ -0,0 +1,2 @@
x<01><>[
Β0EύΞ*ζ_<CEB6>ι$MΡ5tifBk IΕ•Ή7ζk~ήΓ9ά<39>—εά ό¦π.jΦΘ Ε δΙ"zΒ`ί#I<>irF…µΝΉΐΨ$%ΉΒης|4)°―?tΌΙ=”Λ:K¦ο­#[$DΏ―ϋΏ^<5E><>…΅®Σy½HU/<2F>f?G

View File

@ -0,0 +1 @@
e1e59caba97193d48862d6809912043871f37437

View File

@ -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))
}

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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())
}

View File

@ -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()
} }

View File

@ -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)

View File

@ -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)

View File

@ -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)
} }

View File

@ -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))
}) })
} }

View File

@ -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 {

View File

@ -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,

View File

@ -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 {

View File

@ -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)
} }

View File

@ -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)

View File

@ -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
} }

View File

@ -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 {

View File

@ -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))
} }

View File

@ -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