Compare commits

...

59 Commits

Author SHA1 Message Date
ChristopherHX 9fa5b73531
Merge 0395d5c9f5 into 29b28002aa 2025-06-23 17:18:00 +08:00
GiteaBot 29b28002aa [skip ci] Updated translations via Crowdin 2025-06-23 00:40:49 +00:00
Zettat123 618e2d8106
Fix required contexts and commit status matching bug (#34815)
Fix #34504

Since one required context can match more than one commit statuses, we
should not directly compare the lengths of `requiredCommitStatuses` and
`requiredContexts`

---------

Signed-off-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-22 23:31:46 +00:00
NorthRealm 485d8f1121
Add "Cancel workflow run" button to Actions list page (#34817) 2025-06-22 19:05:16 -04:00
Kilisei 181db69e0c
Use `shallowRef` instead of `ref` in `.vue` files where possible (#34813)
This PR improves some `.vue` components by using `shallowRef instead of
ref`, which `should improve performance`. It's probably not significant,
but it's an improvement because Vue no longer deep watches the ref
(shallowRef). Also i used `useTemplateRef` instead of `ref`.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-22 21:37:03 +08:00
Brecht Van Lommel a46b16f10f
Edit file workflow for creating a fork and proposing changes (#34240)
When viewing a file that the user can't edit because they can't write to
the branch, the new, upload, patch, edit and delete functionality is no
longer disabled.

If no user fork of the repository exists, there is now a page to create one.
It will automatically create a fork with a single branch matching the one
being viewed, and a unique repository name will be automatically picked.

When a fork exists, but it's archived, a mirror or the user can't write
code to it, there will instead be a message explaining the situation.

If the usable fork exists, a message will appear at the top of the edit page
explaining that the changes will be applied to a branch in the fork. The
base repository branch will be pushed to a new branch to the fork, and
then the edits will be applied on top.

The suggestion to fork happens when accessing /_edit/, so that for
example online documentation can have an "edit this page" link to
the base repository that does the right thing.

Also includes changes to properly report errors when trying to commit
to a new branch that is protected, and when trying to commit to an
existing branch when choosing the new branch option.

Resolves #9017, #20882

---------

Co-authored-by: Brecht Van Lommel <brecht@blender.org>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-22 12:43:43 +00:00
wxiaoguang 1748045285
Refactor packages (#34777) 2025-06-22 19:22:51 +08:00
wxiaoguang f114c388ff
Refactor wiki (#34805)
Remove unclear code
2025-06-22 18:53:33 +08:00
GiteaBot 94c6d46faa [skip ci] Updated translations via Crowdin 2025-06-22 00:42:06 +00:00
Yarden Shoham 7436c6297d
Upgrade htmx to 2.0.5 (#34809)
Release notes:
https://github.com/bigskysoftware/htmx/releases/tag/v2.0.5

Tested Star, Watch, and the admin dashboard page. All functionality
remains unchanged.

Signed-off-by: Yarden Shoham <git@yardenshoham.com>
2025-06-21 13:06:55 -07:00
Lunny Xiao ddd1e6ca83
Forks repository list page follow other repositories page (#34784)
Replace #24130 

Before:


![image](https://github.com/user-attachments/assets/98c39bce-bdbf-4fc1-b476-527c5139e01f)

After:

![image](https://github.com/user-attachments/assets/65fef5b8-63b9-4283-b8ea-2ac2f27cb001)
2025-06-21 12:27:25 -07:00
Kerwin Bryant 0548c10293
Add post-installation redirect based on admin account status (#34493)
This PR adds a feature to direct users to appropriate pages after system
installation:
- If no admin credentials were provided during installation, redirect to
the registration page with a prominent notice about creating the first
administrative account
- If admin credentials were already set, redirect directly to the login
page


![4d396ad132d9b57fc4f45a62117177f1](https://github.com/user-attachments/assets/3a5d8700-9194-4d3b-a862-e64c8c347932)

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-21 18:48:06 +00:00
Lunny Xiao 7de114a332
Rework delete org and rename org UI (#34762)
# What's the problem of the original implementation

Renaming organization will mix with organization's information change
make the operation difficult to keep consistent.

This PR created a danger zone like what's repository setting. It also
moved organization's `rename` and `delete` operations to this zone. The
original updating repository will not change the name any more.

This is also a step to extract the `updaterepository` function
completely.

Before:


![image](https://github.com/user-attachments/assets/d097dfdf-07be-4d79-8fcf-e78822515575)

![image](https://github.com/user-attachments/assets/42ee832c-cb44-41ec-9fe3-92a1c94747d2)

After:


![image](https://github.com/user-attachments/assets/f7700ed7-f104-4302-a924-09e118f24be3)

![image](https://github.com/user-attachments/assets/4c49952a-578e-4d14-bd01-4a68c9e02412)

![image](https://github.com/user-attachments/assets/814829d3-00fe-4e87-ae05-625c129170d2)

![image](https://github.com/user-attachments/assets/b067b263-c909-4b48-b23c-73481c32d350)

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-21 18:21:48 +00:00
wxiaoguang 4fc626daa1
Refactor editor (#34780)
A complete rewrite
2025-06-21 19:20:51 +08:00
wxiaoguang 81adb01713
Improve img lazy loading (#34804)
Related #32051 and #13526
2025-06-21 14:53:22 +08:00
GiteaBot 0990eb44ce [skip ci] Updated translations via Crowdin 2025-06-21 00:37:09 +00:00
Snowball_233 40dec17b5c
Fix Feishu webhook signature verification (#34788)
# Fix Feishu Webhook Signature Verification

This PR implements proper signature verification for Feishu (Lark)
webhooks according to the [official
documentation](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot).

## Changes

- Implemented the `GenSign` function based on Feishu's official Go
sample code
- Modified the webhook request creation to include timestamp and
signature in the payload when a secret is configured
- Fixed the signature generation algorithm to properly use HMAC-SHA256
with the correct string format

## Implementation Details

The signature verification works as follows:
1. When a webhook secret is provided, a timestamp is generated
2. The signature string is created using `timestamp + "\n" + secret`
3. The HMAC-SHA256 algorithm is applied to an empty string using the
signature string as the key
4. The result is Base64 encoded to produce the final signature
5. Both timestamp and signature are added to the payload

According to Feishu's documentation, the timestamp must be within 1 hour
(3600 seconds) of the current time to be considered valid.

## Security Note

Feishu emphasizes the importance of keeping webhook URLs secure. Do not
disclose them on GitHub, blogs, or any public sites to prevent
unauthorized use.

## References

- [Feishu Custom Bot
Documentation](https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot)

---------

Co-authored-by: hiifong <i@hiif.ong>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-20 13:09:03 -07:00
Lunny Xiao 90eb831418
Upgrade chi to v5.2.2 (#34798) 2025-06-20 18:23:46 +00:00
Kerwin Bryant 1c28c470f8
Fix the issue of abnormal interface when there is no issue-item on the project page (#34791) 2025-06-20 10:27:56 -07:00
wxiaoguang e0f3b30895
Fix container range bug (#34795)
Fix #34792 and add new tests
2025-06-21 01:13:34 +08:00
wxiaoguang 719b151058
Fix OCI manifest parser (#34797)
Do not parse the media type we don't know.
2025-06-21 00:27:35 +08:00
yp05327 4f32d32812
Bump poetry feature to new url for dev container (#34787) 2025-06-20 12:33:12 +00:00
ChristopherHX cda90eca31
Add workflow_run api + webhook (#33964)
Implements 
- https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#list-jobs-for-a-workflow-run--code-samples
- https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#get-a-job-for-a-workflow-run--code-samples
- https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository
- https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#get-a-workflow-run
  - `/actions/runs` for global + user + org (Gitea only)
  - `/actions/jobs` for global + user + org + repository (Gitea only)
  - workflow_run webhook + action trigger
    - limitations
- workflow id is assigned to a string, this may result into problems in
strongly typed clients

Fixes
- workflow_job webhook url to no longer contain the `runs/<run>` part to
align with api
- workflow instance does now use it's name inside the file instead of
filename if set

Refactoring
- Moved a lot of logic from workflows/workflow_job into a shared module
used by both webhook and api

TODO
- [x] Verify Keda Compatibility
- [x] Edit Webhook API bug is resolved
 
Closes https://github.com/go-gitea/gitea/issues/23670
Closes https://github.com/go-gitea/gitea/issues/23796
Closes https://github.com/go-gitea/gitea/issues/24898
Replaces https://github.com/go-gitea/gitea/pull/28047 and is much more
complete

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-20 20:14:00 +08:00
GiteaBot d462ce149d [skip ci] Updated translations via Crowdin 2025-06-20 00:37:18 +00:00
Dan Čermák b8c9a0c323
Add ff_only parameter to POST /repos/{owner}/{repo}/merge-upstream (#34770)
The merge-upstream route was so far performing any kind of merge, even
those that would create merge commits and thus make your branch diverge
from upstream, requiring manual intervention via the git cli to undo the
damage.

With the new optional parameter ff_only, we can instruct gitea to error
out, if a non-fast-forward merge would be performed.
2025-06-19 12:29:10 -07:00
bytedream 7346ae7cd4
Add repo file tree item link behavior (#34730)
Converts the repo file tree items into `<a>` elements to have default
link behavior. Dynamic content load is still done when no special key is
pressed while clicking on an item.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-20 02:28:19 +08:00
wxiaoguang 0ea958dc58
Fix tag target (#34781)
Fix #34779
2025-06-19 10:33:30 -07:00
GiteaBot 67083437cd [skip ci] Updated translations via Crowdin 2025-06-19 00:37:30 +00:00
silverwind b18c047d62
Upgrade `gopls` to v0.19.0, add `make fix` (#34772)
Upgrade to
[v0.19.0](https://github.com/golang/tools/releases/tag/gopls%2Fv0.19.0)
and fix issues. Runs with new `warning` serverity setting. This likely
does less checks than before. Additionally, add `make fix` which runs
modernize. This is also verified on CI.

For the record, here are the issues discoverd when running with `info`
severity, in case we want to fix these:

```
tests/integration/repo_test.go:95:5-14: could use tagged switch on i
tests/integration/api_packages_generic_test.go:149:4-64: could use tagged switch on setting.Packages.Storage.Type
services/webhook/msteams_test.go:33:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:59:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:85:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:111:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:138:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:161:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:187:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:213:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:239:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:266:4-33: could use tagged switch on fact.Name
services/webhook/msteams_test.go:407:4-33: could use tagged switch on fact.Name
tests/integration/api_packages_conan_test.go:350:6-33: could use tagged switch on pf.Name
models/issues/tracked_time_test.go:98:3-18: could use tagged switch on user.ID
tests/integration/api_token_test.go:505:5-43: could use tagged switch on minRequiredLevel
services/gitdiff/gitdiff.go:220:33-46: method "getLineLegacy" is unused
```

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-06-18 19:30:40 +00:00
wxiaoguang 8efc4ca334
Refactor packages (func name & UI) (#34773)
1. Use `OpenXxx` instead of `GetXxx` because the returned readers should
be correctly closed, and clarify the behaviors of the functions: they
increase the download counter
2. Use `packages-content` styles instead of `issue-content`
2025-06-18 19:04:24 +00:00
silverwind 46a1d52235
Fix remaining issues after `gopls modernize` formatting (#34771)
Followup https://github.com/go-gitea/gitea/pull/34751, fix all remaining
marked issues.

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-06-18 11:37:49 -07:00
wxiaoguang a2ae7c69da
Fix some package registry problems (#34759)
1. Fix #33787
2. Fix container image display
2025-06-19 00:32:43 +08:00
wxiaoguang 7954f25290
Fix incorrect cli default values and default command (#34765) 2025-06-18 23:25:11 +08:00
Kemal Zebari 416ff1fd31
Support annotated tags when using create release API (#31840)
This adds a new field, "tag_message", that represents the message of the
annotated tag.

Resolves #31835.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-18 05:12:38 +00:00
anthony-zh 0e6c1224e5
when using rules to delete packages, remove unclean bugs (#34632)
By default, the code extracts 200 package versions. If too many packages
are generated every day or if rule cleaning is enabled later, which
means there are more than 200 versions corresponding to the library
package, it may not be cleaned up completely, resulting in residue

Fix #31961

---------

Co-authored-by: yeyuanjie <yecao100@126.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-18 04:47:49 +00:00
wxiaoguang b38813878c
Fix readme path and markdown link paste (#34755) 2025-06-18 04:19:54 +00:00
Philip Peterson 08c634b7b7
Remove unused param `doer` (#34545) 2025-06-18 03:12:16 +00:00
silverwind dfea75371c
Improve alignment of commit status icon on commit page (#34750)
Before, icon vertically misaligned:

<img width="243" alt="Screenshot 2025-06-17 at 18 14 26"
src="https://github.com/user-attachments/assets/ac515c6d-25bd-44da-88be-a1d93c137ed0"
/>

After, icon correctly vertically centered:

<img width="244" alt="Screenshot 2025-06-17 at 18 14 40"
src="https://github.com/user-attachments/assets/41556d52-aa15-4bfb-82e2-91ed774cf2b0"
/>

I think it's fine to single out this one case and not alter
`flex-text-inline` because that class seems to work well in other
places.
2025-06-18 02:14:11 +00:00
silverwind 1f35435b81
Run `gopls modernize` on codebase (#34751)
Recent modernize fixes:
https://github.com/golang/tools/commits/master/gopls/internal/analysis/modernize
2025-06-18 01:48:09 +00:00
wxiaoguang 71e4740946
Refactor some file edit related code (#34744)
Follow up #34350

---------

Co-authored-by: delvh <dev.lh@web.de>
2025-06-18 01:18:07 +00:00
GiteaBot ecc6685c20 [skip ci] Updated translations via Crowdin 2025-06-18 00:37:12 +00:00
Lunny Xiao a14db5c5e3
Fix ghost user in feeds when pushing in an actions, it should be gitea-actions (#34703) 2025-06-17 23:44:35 +00:00
Lunny Xiao ee334886f3
upgrade orgmode to v1.8.0 (#34721) 2025-06-17 19:30:43 +00:00
endo0911engineer 1376cf7481
Support title and body query parameters for new PRs (#34537)
Currently, Gitea supports title and body query parameters when creating
new issues, allowing pre-filling those fields via URL parameters.
However, similar support for pull requests (PRs) does not exist.

This feature adds support for the title, body, and quick_pull query
parameters in the new pull request creation page. These parameters work
similarly to GitHub’s behavior, allowing users to pre-populate the PR
title and body, and optionally expand the PR creation form
automatically.

By supporting these query parameters, it improves the usability and
automation capabilities when creating pull requests via direct URLs,
aligning Gitea more closely with GitHub’s user experience.

---------

Co-authored-by: root <root@DESKTOP-UPANUTP>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-17 12:05:10 -07:00
wxiaoguang f214bb40a3
Improve nuget/rubygems package registries (#34741)
1. Add some missing (optional) fields for nuget v2, and sort the fields
to make it easier to maintain
2. Add missing "platform" for rubygems: `VERSION-PLATFORM` and
`VERSION_PLATFORM`

Co-authored-by: Giteabot <teabot@gitea.io>
2025-06-17 19:42:00 +02:00
Lunny Xiao 224aa64cd9
Replace update repository function in some places (#34566)
`UpdateAllCols` is dangerous, the columns should be updated when
necessary.

This PR replaces some `updateRepository` invokes to reduce possible
problems and wrongly updated time. Some parts have been fixed in #34388,
but some are hidden in the function `updateRepository`. Alternatively,
using `UpdateRepositoryColsNoAutoTime` to update the changed columns.

Some `UpdateRepoSize` invokes are duplicated, so they will be removed
when extracting from `updateRepository`.
2025-06-17 09:54:25 -07:00
Lunny Xiao 1e644e39f9
remove unnecessary duplicate code (#34733) 2025-06-17 12:23:56 -04:00
MaxWebZ 037f72bdb3
fix: prevent double markdown link brackets when pasting URL (#34745)
When adding a link using the "Add a link" button in comment editor,
pasting a URL resulted in incorrect Markdown formatting (double
brackets) instead of replacing the placeholder text.

This fix adds a context check to prevent creating a new markdown link
when we're already inside an existing one.

Fixes #34740

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-06-17 21:33:50 +08:00
wxiaoguang 4cbb482554
Fix JS error for "select" dropdown (#34743)
Regression of recent dropdown filter change.
2025-06-17 19:19:08 +08:00
GiteaBot 439ebe7031 [skip ci] Updated translations via Crowdin 2025-06-17 00:37:42 +00:00
bytedream 3a37d63d61
Allow renaming/moving binary/LFS files in the UI (#34350)
Adds the ability to rename/move binary files like binary blobs or images
and files that are too large in the web ui.
This was purposed in #24722, along with the ability edit images via an
upload of a new image, which I didn't implement here (could be done in a
separate PR).

Binary file content:

![binary](https://github.com/user-attachments/assets/61d9ff71-25d3-4832-9288-452cdefc7283)

File too large:

![toolarge](https://github.com/user-attachments/assets/3b42dbd0-e76a-4c3c-92d2-52ebffedea64)

GitHub does the same (I've copied the text from there):

![gh](https://github.com/user-attachments/assets/e1499813-fb71-4544-9d58-086046a5f13e)
2025-06-16 17:15:07 -07:00
wxiaoguang 24ce2058e8
Clean bindata (#34728)
Follow #34692
2025-06-16 12:03:51 +00:00
wxiaoguang 6b8b580218
Refactor container and UI (#34736) 2025-06-16 16:27:01 +08:00
Kerwin Bryant bbee652e29
Prevent duplicate form submissions when creating forks (#34714)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-06-16 04:19:16 +00:00
wxiaoguang 637070e07b
Fix container range bug (#34725)
Fix #34724
2025-06-15 21:55:11 +03:00
GiteaBot 0d3e9956cd [skip ci] Updated translations via Crowdin 2025-06-15 00:41:44 +00:00
GiteaBot 28debdbe00 [skip ci] Updated translations via Crowdin 2025-06-14 00:35:48 +00:00
silverwind dcc9206a59
Raise minimum Node.js version to 20, test on 24 (#34713)
- Node.js 18 is now EOL, so raise minimum version to current LTS v20
- Test on 24
- Change devcontainers to use LTS version (currently 22),
[ref](https://github.com/devcontainers/features/tree/main/src/node)
2025-06-13 13:40:39 -04:00
ChristopherHX 0395d5c9f5
Actions FetchTask concurrently picked jobs is an error for the runner
* Before this Gitea claimed no job is available to be picked in this case
* The runner had to wait for an external taskversion increment
* Now act_runner is notified about an error and retries the request later without updating its taskversion
2025-02-04 23:09:26 +01:00
495 changed files with 8418 additions and 5272 deletions

View File

@ -4,10 +4,10 @@
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
"version": "lts"
},
"ghcr.io/devcontainers/features/git-lfs:1.2.2": {},
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
"ghcr.io/devcontainers-extra/features/poetry:2": {},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12"
},

View File

@ -36,15 +36,6 @@ _testmain.go
coverage.all
cpu.out
/modules/migration/bindata.go
/modules/migration/bindata.go.hash
/modules/options/bindata.go
/modules/options/bindata.go.hash
/modules/public/bindata.go
/modules/public/bindata.go.hash
/modules/templates/bindata.go
/modules/templates/bindata.go.hash
*.db
*.log

View File

@ -37,7 +37,7 @@ jobs:
python-version: "3.12"
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: pip install poetry
@ -66,7 +66,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend
@ -137,7 +137,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend
@ -186,7 +186,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend

View File

@ -25,7 +25,7 @@ jobs:
check-latest: true
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend frontend deps-backend

View File

@ -22,7 +22,7 @@ jobs:
check-latest: true
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend deps-backend

View File

@ -23,7 +23,7 @@ jobs:
check-latest: true
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend deps-backend

View File

@ -27,7 +27,7 @@ jobs:
check-latest: true
- uses: actions/setup-node@v4
with:
node-version: 22
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- run: make deps-frontend deps-backend

View File

@ -1,9 +1,6 @@
*.min.css
*.min.js
/assets/*.json
/modules/options/bindata.go
/modules/public/bindata.go
/modules/templates/bindata.go
/options/gitignore
/options/license
/public/assets

View File

@ -36,7 +36,8 @@ XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.17.1
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.0
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.0
DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest
@ -120,7 +121,7 @@ WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat
BINDATA_DEST_WILDCARD := modules/migration/bindata.* modules/public/bindata.* modules/options/bindata.* modules/templates/bindata.*
GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go
@ -219,7 +220,7 @@ clean-all: clean ## delete backend, frontend and integration files
.PHONY: clean
clean: ## delete backend and integration files
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST_WILDCARD) \
integrations*.test \
e2e*.test \
tests/integration/gitea-integration-* \
@ -230,7 +231,7 @@ clean: ## delete backend and integration files
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
.PHONY: fmt
fmt: ## format the Go code
fmt: ## format the Go and template code
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
@ -249,6 +250,19 @@ fmt-check: fmt
exit 1; \
fi
.PHONY: fix
fix: ## apply automated fixes to Go code
$(GO) run $(GOPLS_MODERNIZE_PACKAGE) -fix ./...
.PHONY: fix-check
fix-check: fix
@diff=$$(git diff --color=always $(GO_SOURCES)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fix' and commit the result:"; \
printf "%s" "$${diff}"; \
exit 1; \
fi
.PHONY: $(TAGS_EVIDENCE)
$(TAGS_EVIDENCE):
@mkdir -p $(MAKE_EVIDENCE_DIR)
@ -288,7 +302,7 @@ checks: checks-frontend checks-backend ## run various consistency checks
checks-frontend: lockfile-check svg-check ## check frontend files
.PHONY: checks-backend
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check ## check backend files
checks-backend: tidy-check swagger-check fmt-check fix-check swagger-validate security-check ## check backend files
.PHONY: lint
lint: lint-frontend lint-backend lint-spell ## lint everything
@ -809,6 +823,7 @@ deps-tools: ## install tool dependencies
$(GO) install $(GOVULNCHECK_PACKAGE) & \
$(GO) install $(ACTIONLINT_PACKAGE) & \
$(GO) install $(GOPLS_PACKAGE) & \
$(GO) install $(GOPLS_MODERNIZE_PACKAGE) & \
wait
node_modules: package-lock.json

View File

@ -39,12 +39,10 @@ func smtpCLIFlags() []cli.Flag {
&cli.BoolFlag{
Name: "force-smtps",
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
Value: true,
},
&cli.BoolFlag{
Name: "skip-verify",
Usage: "Skip TLS verify.",
Value: true,
},
&cli.StringFlag{
Name: "helo-hostname",
@ -54,7 +52,6 @@ func smtpCLIFlags() []cli.Flag {
&cli.BoolFlag{
Name: "disable-helo",
Usage: "Disable SMTP helo.",
Value: true,
},
&cli.StringFlag{
Name: "allowed-domains",
@ -64,7 +61,6 @@ func smtpCLIFlags() []cli.Flag {
&cli.BoolFlag{
Name: "skip-local-2fa",
Usage: "Skip 2FA to log on.",
Value: true,
},
&cli.BoolFlag{
Name: "active",

View File

@ -60,10 +60,8 @@ func TestAddSMTP(t *testing.T) {
Auth: "PLAIN",
Host: "localhost",
Port: 25,
// ForceSMTPS: true,
// SkipVerify: true,
},
TwoFactorPolicy: "skip",
TwoFactorPolicy: "",
},
},
{
@ -73,12 +71,12 @@ func TestAddSMTP(t *testing.T) {
"--host", "localhost",
"--port", "25",
"--auth-type", "LOGIN",
"--force-smtps=false",
"--skip-verify=false",
"--force-smtps",
"--skip-verify",
"--helo-hostname", "example.com",
"--disable-helo=false",
"--disable-helo=true",
"--allowed-domains", "example.com,example.org",
"--skip-local-2fa=false",
"--skip-local-2fa",
"--active=false",
},
source: &auth_model.Source{
@ -89,13 +87,13 @@ func TestAddSMTP(t *testing.T) {
Auth: "LOGIN",
Host: "localhost",
Port: 25,
ForceSMTPS: false,
SkipVerify: false,
ForceSMTPS: true,
SkipVerify: true,
HeloHostname: "example.com",
DisableHelo: false,
DisableHelo: true,
AllowedDomains: "example.com,example.org",
},
TwoFactorPolicy: "",
TwoFactorPolicy: "skip",
},
},
}
@ -157,13 +155,10 @@ func TestUpdateSMTP(t *testing.T) {
Name: "old name",
IsActive: true,
Cfg: &smtp.Source{
Auth: "PLAIN",
Host: "old host",
Port: 26,
ForceSMTPS: true,
SkipVerify: true,
Auth: "PLAIN",
Host: "old host",
Port: 26,
},
TwoFactorPolicy: "",
},
args: []string{
"--id", "1",
@ -177,13 +172,10 @@ func TestUpdateSMTP(t *testing.T) {
Name: "test",
IsActive: true,
Cfg: &smtp.Source{
Auth: "PLAIN",
Host: "localhost",
Port: 25,
ForceSMTPS: true,
SkipVerify: true,
Auth: "PLAIN",
Host: "localhost",
Port: 25,
},
TwoFactorPolicy: "skip",
},
},
{
@ -197,10 +189,7 @@ func TestUpdateSMTP(t *testing.T) {
Auth: "PLAIN",
Host: "old host",
Port: 26,
ForceSMTPS: true,
SkipVerify: true,
HeloHostname: "old.example.com",
DisableHelo: false,
AllowedDomains: "old.example.com",
},
TwoFactorPolicy: "",
@ -211,12 +200,12 @@ func TestUpdateSMTP(t *testing.T) {
"--host", "localhost",
"--port", "25",
"--auth-type", "LOGIN",
"--force-smtps=false",
"--skip-verify=false",
"--force-smtps",
"--skip-verify",
"--helo-hostname", "example.com",
"--disable-helo=true",
"--disable-helo",
"--allowed-domains", "example.com,example.org",
"--skip-local-2fa=true",
"--skip-local-2fa",
"--active=false",
},
authSource: &auth_model.Source{
@ -228,8 +217,8 @@ func TestUpdateSMTP(t *testing.T) {
Auth: "LOGIN",
Host: "localhost",
Port: 25,
ForceSMTPS: false,
SkipVerify: false,
ForceSMTPS: true,
SkipVerify: true,
HeloHostname: "example.com",
DisableHelo: true,
AllowedDomains: "example.com,example.org",
@ -252,11 +241,8 @@ func TestUpdateSMTP(t *testing.T) {
Name: "test",
IsActive: true,
Cfg: &smtp.Source{
Auth: "PLAIN",
SkipVerify: true,
ForceSMTPS: true,
Auth: "PLAIN",
},
TwoFactorPolicy: "skip",
}, nil
},

View File

@ -156,8 +156,8 @@ func runCert(_ context.Context, c *cli.Command) error {
BasicConstraintsValid: true,
}
hosts := strings.Split(c.String("host"), ",")
for _, h := range hosts {
hosts := strings.SplitSeq(c.String("host"), ",")
for h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {

View File

@ -132,3 +132,13 @@ func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(context.Context, *cl
return ctx, nil
}
}
func isValidDefaultSubCommand(cmd *cli.Command) (string, bool) {
// Dirty patch for urfave/cli's strange design.
// "./gitea bad-cmd" should not start the web server.
rootArgs := cmd.Root().Args().Slice()
if len(rootArgs) != 0 && rootArgs[0] != cmd.Name {
return rootArgs[0], false
}
return "", true
}

38
cmd/cmd_test.go Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
)
func TestDefaultCommand(t *testing.T) {
test := func(t *testing.T, args []string, expectedRetName string, expectedRetValid bool) {
called := false
cmd := &cli.Command{
DefaultCommand: "test",
Commands: []*cli.Command{
{
Name: "test",
Action: func(ctx context.Context, command *cli.Command) error {
retName, retValid := isValidDefaultSubCommand(command)
assert.Equal(t, expectedRetName, retName)
assert.Equal(t, expectedRetValid, retValid)
called = true
return nil
},
},
},
}
assert.NoError(t, cmd.Run(t.Context(), args))
assert.True(t, called)
}
test(t, []string{"./gitea"}, "", true)
test(t, []string{"./gitea", "test"}, "", true)
test(t, []string{"./gitea", "other"}, "other", false)
}

View File

@ -137,8 +137,8 @@ func runDumpRepository(ctx context.Context, cmd *cli.Command) error {
opts.PullRequests = true
opts.ReleaseAssets = true
} else {
units := strings.Split(cmd.String("units"), ",")
for _, unit := range units {
units := strings.SplitSeq(cmd.String("units"), ",")
for unit := range units {
switch strings.ToLower(strings.TrimSpace(unit)) {
case "":
continue

View File

@ -480,7 +480,7 @@ func hookPrintResult(output, isCreate bool, branch, url string) {
func pushOptions() map[string]string {
opts := make(map[string]string)
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
for idx := 0; idx < pushCount; idx++ {
for idx := range pushCount {
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
kv := strings.SplitN(opt, "=", 2)
if len(kv) == 2 {
@ -732,7 +732,7 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
// read prefix
lengthBytes := make([]byte, 4)
for i := 0; i < 4; i++ {
for i := range 4 {
lengthBytes[i], err = in.ReadByte()
if err != nil {
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)

View File

@ -152,6 +152,8 @@ func NewMainApp(appVer AppVersion) *cli.Command {
CmdDocs,
}
// TODO: we should eventually drop the default command,
// but not sure whether it would break Windows users who used to double-click the EXE to run.
app.DefaultCommand = CmdWeb.Name
app.Flags = append(app.Flags, cli.VersionFlag)

View File

@ -119,7 +119,6 @@ var (
Name: "rotate",
Aliases: []string{"r"},
Usage: "Rotate logs",
Value: true,
},
&cli.Int64Flag{
Name: "max-size",
@ -130,7 +129,6 @@ var (
Name: "daily",
Aliases: []string{"d"},
Usage: "Rotate logs daily",
Value: true,
},
&cli.IntFlag{
Name: "max-days",
@ -141,7 +139,6 @@ var (
Name: "compress",
Aliases: []string{"z"},
Usage: "Compress rotated logs",
Value: true,
},
&cli.IntFlag{
Name: "compression-level",

View File

@ -251,6 +251,10 @@ func runWeb(_ context.Context, cmd *cli.Command) error {
}
}()
if subCmdName, valid := isValidDefaultSubCommand(cmd); !valid {
return fmt.Errorf("unknown command: %s", subCmdName)
}
managerCtx, cancel := context.WithCancel(context.Background())
graceful.InitManager(managerCtx)
defer cancel()

View File

@ -337,8 +337,8 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out))
return "", "", fmt.Errorf("unable to determine forked remote: %w", err)
}
lines := strings.Split(string(out), "\n")
for _, line := range lines {
lines := strings.SplitSeq(string(out), "\n")
for line := range lines {
fields := strings.Split(line, "\t")
name, remote := fields[0], fields[1]
// only look at pushers
@ -356,12 +356,12 @@ func determineRemote(ctx context.Context, forkUser string) (string, string, erro
if !strings.Contains(remote, forkUser) {
continue
}
if strings.HasPrefix(remote, "git@github.com:") {
forkUser = strings.TrimPrefix(remote, "git@github.com:")
} else if strings.HasPrefix(remote, "https://github.com/") {
forkUser = strings.TrimPrefix(remote, "https://github.com/")
} else if strings.HasPrefix(remote, "https://www.github.com/") {
forkUser = strings.TrimPrefix(remote, "https://www.github.com/")
if after, ok := strings.CutPrefix(remote, "git@github.com:"); ok {
forkUser = after
} else if after, ok := strings.CutPrefix(remote, "https://github.com/"); ok {
forkUser = after
} else if after, ok := strings.CutPrefix(remote, "https://www.github.com/"); ok {
forkUser = after
} else if forkUser == "" {
return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote)
}

4
go.mod
View File

@ -51,7 +51,7 @@ require (
github.com/gliderlabs/ssh v0.3.8
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
github.com/go-chi/chi/v5 v5.2.1
github.com/go-chi/chi/v5 v5.2.2
github.com/go-chi/cors v1.2.1
github.com/go-co-op/gocron v1.37.0
github.com/go-enry/go-enry/v2 v2.9.2
@ -91,7 +91,7 @@ require (
github.com/minio/minio-go/v7 v7.0.91
github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.63
github.com/niklasfasching/go-org v1.7.0
github.com/niklasfasching/go-org v1.8.0
github.com/olivere/elastic/v7 v7.0.32
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.1

8
go.sum
View File

@ -289,8 +289,8 @@ github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5La
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
@ -551,8 +551,8 @@ github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o=
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=

View File

@ -166,6 +166,17 @@ func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, err
return nil, fmt.Errorf("event %s is not a pull request event", run.Event)
}
func (run *ActionRun) GetWorkflowRunEventPayload() (*api.WorkflowRunPayload, error) {
if run.Event == webhook_module.HookEventWorkflowRun {
var payload api.WorkflowRunPayload
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
return nil, err
}
return &payload, nil
}
return nil, fmt.Errorf("event %s is not a workflow run event", run.Event)
}
func (run *ActionRun) IsSchedule() bool {
return run.ScheduleID > 0
}

View File

@ -80,22 +80,31 @@ type FindRunJobOptions struct {
func (opts FindRunJobOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.RunID > 0 {
cond = cond.And(builder.Eq{"run_id": opts.RunID})
cond = cond.And(builder.Eq{"`action_run_job`.run_id": opts.RunID})
}
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
cond = cond.And(builder.Eq{"`action_run_job`.repo_id": opts.RepoID})
}
if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"commit_sha": opts.CommitSHA})
cond = cond.And(builder.Eq{"`action_run_job`.commit_sha": opts.CommitSHA})
}
if len(opts.Statuses) > 0 {
cond = cond.And(builder.In("status", opts.Statuses))
cond = cond.And(builder.In("`action_run_job`.status", opts.Statuses))
}
if opts.UpdatedBefore > 0 {
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
}
return cond
}
func (opts FindRunJobOptions) ToJoins() []db.JoinFunc {
if opts.OwnerID > 0 {
return []db.JoinFunc{
func(sess db.Engine) error {
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
return nil
},
}
}
return nil
}

View File

@ -72,39 +72,50 @@ type FindRunOptions struct {
TriggerEvent webhook_module.HookEventType
Approved bool // not util.OptionalBool, it works only when it's true
Status []Status
CommitSHA string
}
func (opts FindRunOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
cond = cond.And(builder.Eq{"`action_run`.repo_id": opts.RepoID})
}
if opts.WorkflowID != "" {
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowID})
cond = cond.And(builder.Eq{"`action_run`.workflow_id": opts.WorkflowID})
}
if opts.TriggerUserID > 0 {
cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID})
cond = cond.And(builder.Eq{"`action_run`.trigger_user_id": opts.TriggerUserID})
}
if opts.Approved {
cond = cond.And(builder.Gt{"approved_by": 0})
cond = cond.And(builder.Gt{"`action_run`.approved_by": 0})
}
if len(opts.Status) > 0 {
cond = cond.And(builder.In("status", opts.Status))
cond = cond.And(builder.In("`action_run`.status", opts.Status))
}
if opts.Ref != "" {
cond = cond.And(builder.Eq{"ref": opts.Ref})
cond = cond.And(builder.Eq{"`action_run`.ref": opts.Ref})
}
if opts.TriggerEvent != "" {
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent})
cond = cond.And(builder.Eq{"`action_run`.trigger_event": opts.TriggerEvent})
}
if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
}
return cond
}
func (opts FindRunOptions) ToJoins() []db.JoinFunc {
if opts.OwnerID > 0 {
return []db.JoinFunc{func(sess db.Engine) error {
sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID)
return nil
}}
}
return nil
}
func (opts FindRunOptions) ToOrders() string {
return "`id` DESC"
return "`action_run`.`id` DESC"
}
type StatusInfo struct {

View File

@ -4,6 +4,8 @@
package actions
import (
"slices"
"code.gitea.io/gitea/modules/translation"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
@ -88,12 +90,7 @@ func (s Status) IsBlocked() bool {
// In returns whether s is one of the given statuses
func (s Status) In(statuses ...Status) bool {
for _, v := range statuses {
if s == v {
return true
}
}
return false
return slices.Contains(statuses, s)
}
func (s Status) AsResult() runnerv1.Result {

View File

@ -318,7 +318,7 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
if n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}); err != nil {
return nil, false, err
} else if n != 1 {
return nil, false, nil
return nil, false, fmt.Errorf("other runner picked up our job")
}
task.Job = job

View File

@ -9,6 +9,7 @@ import (
"fmt"
"net/url"
"path"
"slices"
"strconv"
"strings"
"time"
@ -125,12 +126,7 @@ func (at ActionType) String() string {
}
func (at ActionType) InActions(actions ...string) bool {
for _, action := range actions {
if action == at.String() {
return true
}
}
return false
return slices.Contains(actions, at.String())
}
// Action represents user operation type and other information to
@ -191,7 +187,7 @@ func (a *Action) LoadActUser(ctx context.Context) {
return
}
var err error
a.ActUser, err = user_model.GetUserByID(ctx, a.ActUserID)
a.ActUser, err = user_model.GetPossibleUserByID(ctx, a.ActUserID)
if err == nil {
return
} else if user_model.IsErrUserNotExist(err) {

View File

@ -208,10 +208,7 @@ func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.Repository
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
left := len(repoIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", repoIDs[:limit]).
Rows(new(repo_model.Repository))
@ -282,10 +279,7 @@ func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
issues := make(map[int64]*issues_model.Issue, len(issueIDs))
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", issueIDs[:limit]).
Rows(new(issues_model.Issue))
@ -377,10 +371,7 @@ func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) {
users := make(map[int64]*user_model.User, len(userIDs))
left := len(userIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", userIDs[:limit]).
Rows(new(user_model.User))
@ -428,10 +419,7 @@ func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
comments := make(map[int64]*issues_model.Comment, len(commentIDs))
left := len(commentIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", commentIDs[:limit]).
Rows(new(issues_model.Comment))

View File

@ -139,10 +139,7 @@ func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository
return v[i].Commits > v[j].Commits
})
cnt := count
if cnt > len(v) {
cnt = len(v)
}
cnt := min(count, len(v))
return v[:cnt], nil
}

View File

@ -213,12 +213,7 @@ func GetRequiredScopes(level AccessTokenScopeLevel, scopeCategories ...AccessTok
// ContainsCategory checks if a list of categories contains a specific category
func ContainsCategory(categories []AccessTokenScopeCategory, category AccessTokenScopeCategory) bool {
for _, c := range categories {
if c == category {
return true
}
}
return false
return slices.Contains(categories, category)
}
// GetScopeLevelFromAccessMode converts permission access mode to scope level

View File

@ -12,6 +12,7 @@ import (
"fmt"
"net"
"net/url"
"slices"
"strings"
"code.gitea.io/gitea/models/db"
@ -511,12 +512,7 @@ func (grant *OAuth2Grant) IncreaseCounter(ctx context.Context) error {
// ScopeContains returns true if the grant scope contains the specified scope
func (grant *OAuth2Grant) ScopeContains(scope string) bool {
for _, currentScope := range strings.Split(grant.Scope, " ") {
if scope == currentScope {
return true
}
}
return false
return slices.Contains(strings.Split(grant.Scope, " "), scope)
}
// SetNonce updates the current nonce value of a grant

View File

@ -67,7 +67,7 @@ func contextSafetyCheck(e Engine) {
_ = e.SQL("SELECT 1").Iterate(&m{}, func(int, any) error {
callers := make([]uintptr, 32)
callerNum := runtime.Callers(1, callers)
for i := 0; i < callerNum; i++ {
for i := range callerNum {
if funcName := runtime.FuncForPC(callers[i]).Name(); funcName == "xorm.io/xorm.(*Session).Iterate" {
contextSafetyDeniedFuncPCs = append(contextSafetyDeniedFuncPCs, callers[i])
}
@ -82,7 +82,7 @@ func contextSafetyCheck(e Engine) {
// it should be very fast: xxxx ns/op
callers := make([]uintptr, 32)
callerNum := runtime.Callers(3, callers) // skip 3: runtime.Callers, contextSafetyCheck, GetEngine
for i := 0; i < callerNum; i++ {
for i := range callerNum {
if slices.Contains(contextSafetyDeniedFuncPCs, callers[i]) {
panic(errors.New("using database context in an iterator would cause corrupted results"))
}

View File

@ -5,6 +5,7 @@ package db
import (
"fmt"
"slices"
"strings"
"unicode/utf8"
@ -80,10 +81,8 @@ func IsUsableName(reservedNames, reservedPatterns []string, name string) error {
return util.NewInvalidArgumentErrorf("name is empty")
}
for i := range reservedNames {
if name == reservedNames[i] {
return ErrNameReserved{name}
}
if slices.Contains(reservedNames, name) {
return ErrNameReserved{name}
}
for _, pat := range reservedPatterns {

View File

@ -46,10 +46,7 @@ func (f *file) readAt(fileMeta *dbfsMeta, offset int64, p []byte) (n int, err er
blobPos := int(offset % f.blockSize)
blobOffset := offset - int64(blobPos)
blobRemaining := int(f.blockSize) - blobPos
needRead := len(p)
if needRead > blobRemaining {
needRead = blobRemaining
}
needRead := min(len(p), blobRemaining)
if blobOffset+int64(blobPos)+int64(needRead) > fileMeta.FileSize {
needRead = int(fileMeta.FileSize - blobOffset - int64(blobPos))
}
@ -66,14 +63,8 @@ func (f *file) readAt(fileMeta *dbfsMeta, offset int64, p []byte) (n int, err er
blobData = nil
}
canCopy := len(blobData) - blobPos
if canCopy <= 0 {
canCopy = 0
}
realRead := needRead
if realRead > canCopy {
realRead = canCopy
}
canCopy := max(len(blobData)-blobPos, 0)
realRead := min(needRead, canCopy)
if realRead > 0 {
copy(p[:realRead], fileData.BlobData[blobPos:blobPos+realRead])
}
@ -113,10 +104,7 @@ func (f *file) Write(p []byte) (n int, err error) {
blobPos := int(f.offset % f.blockSize)
blobOffset := f.offset - int64(blobPos)
blobRemaining := int(f.blockSize) - blobPos
needWrite := len(p)
if needWrite > blobRemaining {
needWrite = blobRemaining
}
needWrite := min(len(p), blobRemaining)
buf := make([]byte, f.blockSize)
readBytes, err := f.readAt(fileMeta, blobOffset, buf)
if err != nil && !errors.Is(err, io.EOF) {

View File

@ -9,6 +9,7 @@
ref: "refs/heads/master"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
@ -28,6 +29,7 @@
ref: "refs/heads/master"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
@ -47,6 +49,7 @@
ref: "refs/heads/master"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 6 # running
started: 1683636528
@ -66,6 +69,47 @@
ref: "refs/heads/test"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 802
title: "workflow run list"
repo_id: 5
owner_id: 3
workflow_id: "test.yaml"
index: 191
trigger_user_id: 1
ref: "refs/heads/test"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 803
title: "workflow run list for user"
repo_id: 2
owner_id: 0
workflow_id: "test.yaml"
index: 192
trigger_user_id: 1
ref: "refs/heads/test"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
@ -86,6 +130,7 @@
ref: "refs/heads/test"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
trigger_event: "push"
is_fork_pull_request: 0
status: 2
started: 1683636528

View File

@ -99,3 +99,33 @@
status: 2
started: 1683636528
stopped: 1683636626
-
id: 203
run_id: 802
repo_id: 5
owner_id: 0
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
name: job2
attempt: 1
job_id: job2
needs: '["job1"]'
task_id: 51
status: 5
started: 1683636528
stopped: 1683636626
-
id: 204
run_id: 803
repo_id: 2
owner_id: 0
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
name: job2
attempt: 1
job_id: job2
needs: '["job1"]'
task_id: 51
status: 5
started: 1683636528
stopped: 1683636626

View File

@ -201,3 +201,15 @@
is_deleted: false
deleted_by_id: 0
deleted_unix: 0
-
id: 25
repo_id: 54
name: 'master'
commit_id: '73cf03db6ece34e12bf91e8853dc58f678f2f82d'
commit_message: 'Initial commit'
commit_time: 1671663402
pusher_id: 2
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

View File

@ -112,7 +112,6 @@ type LFSMetaObject struct {
ID int64 `xorm:"pk autoincr"`
lfs.Pointer `xorm:"extends"`
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
Existing bool `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
@ -146,7 +145,6 @@ func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMet
if err != nil {
return nil, err
} else if exist {
m.Existing = true
return m, committer.Commit()
}

View File

@ -246,7 +246,7 @@ func (protectBranch *ProtectedBranch) GetUnprotectedFilePatterns() []glob.Glob {
func getFilePatterns(filePatterns string) []glob.Glob {
extarr := make([]glob.Glob, 0, 10)
for _, expr := range strings.Split(strings.ToLower(filePatterns), ";") {
for expr := range strings.SplitSeq(strings.ToLower(filePatterns), ";") {
expr = strings.TrimSpace(expr)
if expr != "" {
if g, err := glob.Compile(expr, '.', '/'); err != nil {

View File

@ -9,6 +9,7 @@ import (
"context"
"fmt"
"html/template"
"slices"
"strconv"
"unicode/utf8"
@ -196,12 +197,7 @@ func (t CommentType) HasMailReplySupport() bool {
}
func (t CommentType) CountedAsConversation() bool {
for _, ct := range ConversationCountedCommentType() {
if t == ct {
return true
}
}
return false
return slices.Contains(ConversationCountedCommentType(), t)
}
// ConversationCountedCommentType returns the comment types that are counted as a conversation
@ -614,7 +610,7 @@ func UpdateCommentAttachments(ctx context.Context, c *Comment, uuids []string) e
if err != nil {
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err)
}
for i := 0; i < len(attachments); i++ {
for i := range attachments {
attachments[i].IssueID = c.IssueID
attachments[i].CommentID = c.ID
if err := repo_model.UpdateAttachment(ctx, attachments[i]); err != nil {

View File

@ -57,10 +57,7 @@ func (comments CommentList) loadLabels(ctx context.Context) error {
commentLabels := make(map[int64]*Label, len(labelIDs))
left := len(labelIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", labelIDs[:limit]).
Rows(new(Label))
@ -107,10 +104,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
left := len(milestoneIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
err := db.GetEngine(ctx).
In("id", milestoneIDs[:limit]).
Find(&milestoneMaps)
@ -146,10 +140,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
left := len(milestoneIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
err := db.GetEngine(ctx).
In("id", milestoneIDs[:limit]).
Find(&milestoneMaps)
@ -184,10 +175,7 @@ func (comments CommentList) loadAssignees(ctx context.Context) error {
assignees := make(map[int64]*user_model.User, len(assigneeIDs))
left := len(assigneeIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", assigneeIDs[:limit]).
Rows(new(user_model.User))
@ -256,10 +244,7 @@ func (comments CommentList) LoadIssues(ctx context.Context) error {
issues := make(map[int64]*Issue, len(issueIDs))
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("id", issueIDs[:limit]).
Rows(new(Issue))
@ -313,10 +298,7 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error {
issues := make(map[int64]*Issue, len(issueIDs))
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := e.
In("id", issueIDs[:limit]).
Rows(new(Issue))
@ -392,10 +374,7 @@ func (comments CommentList) LoadAttachments(ctx context.Context) (err error) {
commentsIDs := comments.getAttachmentCommentIDs()
left := len(commentsIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("comment_id", commentsIDs[:limit]).
Rows(new(repo_model.Attachment))

View File

@ -42,10 +42,7 @@ func (issues IssueList) LoadRepositories(ctx context.Context) (repo_model.Reposi
repoMaps := make(map[int64]*repo_model.Repository, len(repoIDs))
left := len(repoIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
err := db.GetEngine(ctx).
In("id", repoIDs[:limit]).
Find(&repoMaps)
@ -116,10 +113,7 @@ func (issues IssueList) LoadLabels(ctx context.Context) error {
issueIDs := issues.getIssueIDs()
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).Table("label").
Join("LEFT", "issue_label", "issue_label.label_id = label.id").
In("issue_label.issue_id", issueIDs[:limit]).
@ -171,10 +165,7 @@ func (issues IssueList) LoadMilestones(ctx context.Context) error {
milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs))
left := len(milestoneIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
err := db.GetEngine(ctx).
In("id", milestoneIDs[:limit]).
Find(&milestoneMaps)
@ -203,10 +194,7 @@ func (issues IssueList) LoadProjects(ctx context.Context) error {
}
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
projects := make([]*projectWithIssueID, 0, limit)
err := db.GetEngine(ctx).
@ -245,10 +233,7 @@ func (issues IssueList) LoadAssignees(ctx context.Context) error {
issueIDs := issues.getIssueIDs()
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).Table("issue_assignees").
Join("INNER", "`user`", "`user`.id = `issue_assignees`.assignee_id").
In("`issue_assignees`.issue_id", issueIDs[:limit]).OrderBy(user_model.GetOrderByName()).
@ -306,10 +291,7 @@ func (issues IssueList) LoadPullRequests(ctx context.Context) error {
pullRequestMaps := make(map[int64]*PullRequest, len(issuesIDs))
left := len(issuesIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("issue_id", issuesIDs[:limit]).
Rows(new(PullRequest))
@ -354,10 +336,7 @@ func (issues IssueList) LoadAttachments(ctx context.Context) (err error) {
issuesIDs := issues.getIssueIDs()
left := len(issuesIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).
In("issue_id", issuesIDs[:limit]).
Rows(new(repo_model.Attachment))
@ -399,10 +378,7 @@ func (issues IssueList) loadComments(ctx context.Context, cond builder.Cond) (er
issuesIDs := issues.getIssueIDs()
left := len(issuesIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
rows, err := db.GetEngine(ctx).Table("comment").
Join("INNER", "issue", "issue.id = comment.issue_id").
In("issue.id", issuesIDs[:limit]).
@ -466,10 +442,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
left := len(ids)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
// select issue_id, sum(time) from tracked_time where issue_id in (<issue ids in current page>) group by issue_id
rows, err := db.GetEngine(ctx).Table("tracked_time").

View File

@ -73,8 +73,8 @@ func (o *IssuesOptions) Copy(edit ...func(options *IssuesOptions)) *IssuesOption
// sortType string
func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) {
// Since this sortType is dynamically created, it has to be treated specially.
if strings.HasPrefix(sortType, ScopeSortPrefix) {
scope := strings.TrimPrefix(sortType, ScopeSortPrefix)
if after, ok := strings.CutPrefix(sortType, ScopeSortPrefix); ok {
scope := after
sess.Join("LEFT", "issue_label", "issue.id = issue_label.issue_id")
// "exclusive_order=0" means "no order is set", so exclude it from the JOIN criteria and then "LEFT JOIN" result is also null
sess.Join("LEFT", "label", "label.id = issue_label.label_id AND label.exclusive_order <> 0 AND label.name LIKE ?", scope+"/%")

View File

@ -94,10 +94,7 @@ func GetIssueStats(ctx context.Context, opts *IssuesOptions) (*IssueStats, error
// ids in a temporary table and join from them.
accum := &IssueStats{}
for i := 0; i < len(opts.IssueIDs); {
chunk := i + MaxQueryParameters
if chunk > len(opts.IssueIDs) {
chunk = len(opts.IssueIDs)
}
chunk := min(i+MaxQueryParameters, len(opts.IssueIDs))
stats, err := getIssueStatsChunk(ctx, opts, opts.IssueIDs[i:chunk])
if err != nil {
return nil, err

View File

@ -5,6 +5,7 @@ package issues_test
import (
"fmt"
"slices"
"sort"
"sync"
"testing"
@ -270,7 +271,7 @@ func TestIssue_ResolveMentions(t *testing.T) {
for i, user := range resolved {
ids[i] = user.ID
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
slices.Sort(ids)
assert.Equal(t, expected, ids)
}
@ -292,7 +293,7 @@ func TestResourceIndex(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
for i := range 100 {
wg.Add(1)
go func(i int) {
testInsertIssue(t, fmt.Sprintf("issue %d", i+1), "my issue", 0)
@ -314,7 +315,7 @@ func TestCorrectIssueStats(t *testing.T) {
issueAmount := issues_model.MaxQueryParameters + 10
var wg sync.WaitGroup
for i := 0; i < issueAmount; i++ {
for i := range issueAmount {
wg.Add(1)
go func(i int) {
testInsertIssue(t, fmt.Sprintf("Issue %d", i+1), "Bugs are nasty", 0)

View File

@ -304,7 +304,7 @@ func UpdateIssueAttachments(ctx context.Context, issueID int64, uuids []string)
if err != nil {
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err)
}
for i := 0; i < len(attachments); i++ {
for i := range attachments {
attachments[i].IssueID = issueID
if err := repo_model.UpdateAttachment(ctx, attachments[i]); err != nil {
return fmt.Errorf("update attachment [id: %d]: %w", attachments[i].ID, err)

View File

@ -649,12 +649,6 @@ func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*P
return pulls, err
}
// Update updates all fields of pull request.
func (pr *PullRequest) Update(ctx context.Context) error {
_, err := db.GetEngine(ctx).ID(pr.ID).AllCols().Update(pr)
return err
}
// UpdateCols updates specific fields of pull request.
func (pr *PullRequest) UpdateCols(ctx context.Context, cols ...string) error {
_, err := db.GetEngine(ctx).ID(pr.ID).Cols(cols...).Update(pr)

View File

@ -248,19 +248,6 @@ func TestGetPullRequestByIssueID(t *testing.T) {
assert.True(t, issues_model.IsErrPullRequestNotExist(err))
}
func TestPullRequest_Update(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
pr.BaseBranch = "baseBranch"
pr.HeadBranch = "headBranch"
pr.Update(db.DefaultContext)
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.Equal(t, "baseBranch", pr.BaseBranch)
assert.Equal(t, "headBranch", pr.HeadBranch)
unittest.CheckConsistencyFor(t, pr)
}
func TestPullRequest_UpdateCols(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
pr := &issues_model.PullRequest{

View File

@ -22,7 +22,7 @@ type ReviewList []*Review
// LoadReviewers loads reviewers
func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
reviewerIDs := make([]int64, len(reviews))
for i := 0; i < len(reviews); i++ {
for i := range reviews {
reviewerIDs[i] = reviews[i].ReviewerID
}
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIDs)

View File

@ -350,10 +350,7 @@ func GetIssueTotalTrackedTime(ctx context.Context, opts *IssuesOptions, isClosed
// we get the statistics in smaller chunks and get accumulates
var accum int64
for i := 0; i < len(opts.IssueIDs); {
chunk := i + MaxQueryParameters
if chunk > len(opts.IssueIDs) {
chunk = len(opts.IssueIDs)
}
chunk := min(i+MaxQueryParameters, len(opts.IssueIDs))
time, err := getIssueTotalTrackedTimeChunk(ctx, opts, isClosed, opts.IssueIDs[i:chunk])
if err != nil {
return 0, err

View File

@ -518,7 +518,7 @@ func ModifyColumn(x *xorm.Engine, tableName string, col *schemas.Column) error {
func removeAllWithRetry(dir string) error {
var err error
for i := 0; i < 20; i++ {
for range 20 {
err = os.RemoveAll(dir)
if err == nil {
break

View File

@ -5,6 +5,7 @@ package v1_11 //nolint
import (
"fmt"
"slices"
"xorm.io/xorm"
)
@ -344,10 +345,8 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
}
return AccessModeWrite <= perm.UnitsMode[UnitTypeCode], nil
}
for _, id := range protectedBranch.ApprovalsWhitelistUserIDs {
if id == reviewer.ID {
return true, nil
}
if slices.Contains(protectedBranch.ApprovalsWhitelistUserIDs, reviewer.ID) {
return true, nil
}
// isUserInTeams

View File

@ -146,7 +146,7 @@ func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error)
return "", fmt.Errorf("io.ReadAll: %w", err)
}
newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userID, md5.Sum(data)))))
newAvatar := fmt.Sprintf("%x", md5.Sum(fmt.Appendf(nil, "%d-%x", userID, md5.Sum(data))))
if newAvatar == oldAvatar {
return newAvatar, nil
}

View File

@ -329,7 +329,7 @@ func ConvertScopedAccessTokens(x *xorm.Engine) error {
for _, token := range tokens {
var scopes []string
allNewScopesMap := make(map[AccessTokenScope]bool)
for _, oldScope := range strings.Split(token.Scope, ",") {
for oldScope := range strings.SplitSeq(token.Scope, ",") {
if newScopes, exists := accessTokenScopeMap[OldAccessTokenScope(oldScope)]; exists {
for _, newScope := range newScopes {
allNewScopesMap[newScope] = true

View File

@ -4,7 +4,6 @@
package v1_22 //nolint
import (
"slices"
"testing"
"code.gitea.io/gitea/models/migrations/base"
@ -44,7 +43,7 @@ func Test_AddUniqueIndexForProjectIssue(t *testing.T) {
for _, index := range tables[0].Indexes {
if index.Type == schemas.UniqueType {
found = true
slices.Equal(index.Cols, []string{"project_id", "issue_id"})
assert.ElementsMatch(t, index.Cols, []string{"project_id", "issue_id"})
break
}
}

View File

@ -25,6 +25,7 @@ type BlobSearchOptions struct {
Digest string
Tag string
IsManifest bool
OnlyLead bool
Repository string
}
@ -43,7 +44,10 @@ func (opts *BlobSearchOptions) toConds() builder.Cond {
cond = cond.And(builder.Eq{"package_version.lower_version": strings.ToLower(opts.Tag)})
}
if opts.IsManifest {
cond = cond.And(builder.Eq{"package_file.lower_name": ManifestFilename})
cond = cond.And(builder.Eq{"package_file.lower_name": container_module.ManifestFilename})
}
if opts.OnlyLead {
cond = cond.And(builder.Eq{"package_file.is_lead": true})
}
if opts.Digest != "" {
var propsCond builder.Cond = builder.Eq{
@ -73,11 +77,9 @@ func GetContainerBlob(ctx context.Context, opts *BlobSearchOptions) (*packages.P
pfds, err := getContainerBlobsLimit(ctx, opts, 1)
if err != nil {
return nil, err
}
if len(pfds) != 1 {
} else if len(pfds) == 0 {
return nil, ErrContainerBlobNotExist
}
return pfds[0], nil
}
@ -233,7 +235,7 @@ func SearchImageTags(ctx context.Context, opts *ImageTagsSearchOptions) ([]*pack
func SearchExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) ([]*packages.PackageFile, error) {
var cond builder.Cond = builder.Eq{
"package_version.is_internal": true,
"package_version.lower_version": UploadVersion,
"package_version.lower_version": container_module.UploadVersion,
"package.type": packages.TypeContainer,
}
cond = cond.And(builder.Lt{"package_file.created_unix": time.Now().Add(-olderThan).Unix()})

View File

@ -103,10 +103,10 @@ func (pd *PackageDescriptor) CalculateBlobSize() int64 {
// GetPackageDescriptor gets the package description for a version
func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDescriptor, error) {
return getPackageDescriptor(ctx, pv, cache.NewEphemeralCache())
return GetPackageDescriptorWithCache(ctx, pv, cache.NewEphemeralCache())
}
func getPackageDescriptor(ctx context.Context, pv *PackageVersion, c *cache.EphemeralCache) (*PackageDescriptor, error) {
func GetPackageDescriptorWithCache(ctx context.Context, pv *PackageVersion, c *cache.EphemeralCache) (*PackageDescriptor, error) {
p, err := cache.GetWithEphemeralCache(ctx, c, "package", pv.PackageID, GetPackageByID)
if err != nil {
return nil, err
@ -270,7 +270,7 @@ func GetPackageDescriptors(ctx context.Context, pvs []*PackageVersion) ([]*Packa
func getPackageDescriptors(ctx context.Context, pvs []*PackageVersion, c *cache.EphemeralCache) ([]*PackageDescriptor, error) {
pds := make([]*PackageDescriptor, 0, len(pvs))
for _, pv := range pvs {
pd, err := getPackageDescriptor(ctx, pv, c)
pd, err := GetPackageDescriptorWithCache(ctx, pv, c)
if err != nil {
return nil, err
}

View File

@ -33,7 +33,7 @@ func SearchVersions(ctx context.Context, opts *packages_model.PackageSearchOptio
Where(cond).
OrderBy("package.name ASC")
if opts.Paginator != nil {
skip, take := opts.GetSkipTake()
skip, take := opts.Paginator.GetSkipTake()
inner = inner.Limit(take, skip)
}

View File

@ -115,6 +115,11 @@ func DeleteFileByID(ctx context.Context, fileID int64) error {
return err
}
func UpdateFile(ctx context.Context, pf *PackageFile, cols []string) error {
_, err := db.GetEngine(ctx).ID(pf.ID).Cols(cols...).Update(pf)
return err
}
// PackageFileSearchOptions are options for SearchXXX methods
type PackageFileSearchOptions struct {
OwnerID int64

View File

@ -66,6 +66,20 @@ func UpdateProperty(ctx context.Context, pp *PackageProperty) error {
return err
}
func InsertOrUpdateProperty(ctx context.Context, refType PropertyType, refID int64, name, value string) error {
pp := PackageProperty{RefType: refType, RefID: refID, Name: name}
ok, err := db.GetEngine(ctx).Get(&pp)
if err != nil {
return err
}
if ok {
_, err = db.GetEngine(ctx).Where("ref_type=? AND ref_id=? AND name=?", refType, refID, name).Cols("value").Update(&PackageProperty{Value: value})
return err
}
_, err = InsertProperty(ctx, refType, refID, name, value)
return err
}
// DeleteAllProperties deletes all properties of a ref
func DeleteAllProperties(ctx context.Context, refType PropertyType, refID int64) error {
_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ?", refType, refID).Delete(&PackageProperty{})
@ -78,8 +92,8 @@ func DeletePropertyByID(ctx context.Context, propertyID int64) error {
return err
}
// DeletePropertyByName deletes properties by name
func DeletePropertyByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
// DeletePropertiesByName deletes properties by name
func DeletePropertiesByName(ctx context.Context, refType PropertyType, refID int64, name string) error {
_, err := db.GetEngine(ctx).Where("ref_type = ? AND ref_id = ? AND name = ?", refType, refID, name).Delete(&PackageProperty{})
return err
}

View File

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
"xorm.io/xorm"
)
// ErrDuplicatePackageVersion indicates a duplicated package version error
@ -187,7 +188,7 @@ type PackageSearchOptions struct {
HasFileWithName string // only results are found which are associated with a file with the specific name
HasFiles optional.Option[bool] // only results are found which have associated files
Sort VersionSort
db.Paginator
Paginator db.Paginator
}
func (opts *PackageSearchOptions) ToConds() builder.Cond {
@ -282,6 +283,18 @@ func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) {
e.Desc("package_version.id") // Sort by id for stable order with duplicates in the other field
}
func searchVersionsBySession(sess *xorm.Session, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) {
opts.configureOrderBy(sess)
pvs := make([]*PackageVersion, 0, 10)
if opts.Paginator != nil {
sess = db.SetSessionPagination(sess, opts.Paginator)
count, err := sess.FindAndCount(&pvs)
return pvs, count, err
}
err := sess.Find(&pvs)
return pvs, int64(len(pvs)), err
}
// SearchVersions gets all versions of packages matching the search options
func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*PackageVersion, int64, error) {
sess := db.GetEngine(ctx).
@ -289,16 +302,7 @@ func SearchVersions(ctx context.Context, opts *PackageSearchOptions) ([]*Package
Table("package_version").
Join("INNER", "package", "package.id = package_version.package_id").
Where(opts.ToConds())
opts.configureOrderBy(sess)
if opts.Paginator != nil {
sess = db.SetSessionPagination(sess, opts)
}
pvs := make([]*PackageVersion, 0, 10)
count, err := sess.FindAndCount(&pvs)
return pvs, count, err
return searchVersionsBySession(sess, opts)
}
// SearchLatestVersions gets the latest version of every package matching the search options
@ -316,15 +320,7 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
Join("INNER", "package", "package.id = package_version.package_id").
Where(builder.In("package_version.id", in))
opts.configureOrderBy(sess)
if opts.Paginator != nil {
sess = db.SetSessionPagination(sess, opts)
}
pvs := make([]*PackageVersion, 0, 10)
count, err := sess.FindAndCount(&pvs)
return pvs, count, err
return searchVersionsBySession(sess, opts)
}
// ExistVersion checks if a version matching the search options exist

View File

@ -110,7 +110,7 @@ func Test_NewColumn(t *testing.T) {
assert.NoError(t, err)
assert.Len(t, columns, 3)
for i := 0; i < maxProjectColumns-3; i++ {
for i := range maxProjectColumns - 3 {
err := NewColumn(db.DefaultContext, &Column{
Title: fmt.Sprintf("column-%d", i+4),
ProjectID: project1.ID,

View File

@ -6,6 +6,7 @@ package pull
import (
"context"
"fmt"
"maps"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
@ -100,9 +101,7 @@ func mergeFiles(oldFiles, newFiles map[string]ViewedState) map[string]ViewedStat
return oldFiles
}
for file, viewed := range newFiles {
oldFiles[file] = viewed
}
maps.Copy(oldFiles, newFiles)
return oldFiles
}

View File

@ -180,7 +180,7 @@ func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs
}
attachments[i].ReleaseID = releaseID
// No assign value could be 0, so ignore AllCols().
if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil {
if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Cols("release_id").Update(attachments[i]); err != nil {
return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
}
}

View File

@ -653,7 +653,7 @@ func (repo *Repository) AllowsPulls(ctx context.Context) bool {
// CanEnableEditor returns true if repository meets the requirements of web editor.
func (repo *Repository) CanEnableEditor() bool {
return !repo.IsMirror
return !repo.IsMirror && !repo.IsArchived
}
// DescriptionHTML does special handles to description and return HTML string.

View File

@ -449,7 +449,7 @@ func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
if opts.Keyword != "" {
// separate keyword
subQueryCond := builder.NewCond()
for _, v := range strings.Split(opts.Keyword, ",") {
for v := range strings.SplitSeq(opts.Keyword, ",") {
if opts.TopicOnly {
subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(v)})
} else {
@ -464,7 +464,7 @@ func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
keywordCond := builder.In("id", subQuery)
if !opts.TopicOnly {
likes := builder.NewCond()
for _, v := range strings.Split(opts.Keyword, ",") {
for v := range strings.SplitSeq(opts.Keyword, ",") {
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
// If the string looks like "org/repo", match against that pattern too

View File

@ -185,10 +185,8 @@ func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool {
}
func (cfg *ActionsConfig) DisableWorkflow(file string) {
for _, workflow := range cfg.DisabledWorkflows {
if file == workflow {
return
}
if slices.Contains(cfg.DisabledWorkflows, file) {
return
}
cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file)

View File

@ -42,12 +42,18 @@ func UpdateRepositoryUpdatedTime(ctx context.Context, repoID int64, updateTime t
// UpdateRepositoryColsWithAutoTime updates repository's columns
func UpdateRepositoryColsWithAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
if len(cols) == 0 {
return nil
}
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo)
return err
}
// UpdateRepositoryColsNoAutoTime updates repository's columns and but applies time change automatically
func UpdateRepositoryColsNoAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
if len(cols) == 0 {
return nil
}
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).NoAutoTime().Update(repo)
return err
}

View File

@ -124,7 +124,7 @@ func DeleteUploads(ctx context.Context, uploads ...*Upload) (err error) {
defer committer.Close()
ids := make([]int64, len(uploads))
for i := 0; i < len(uploads); i++ {
for i := range uploads {
ids[i] = uploads[i].ID
}
if err = db.DeleteByIDs[Upload](ctx, ids...); err != nil {

View File

@ -6,6 +6,7 @@ package unit
import (
"errors"
"fmt"
"slices"
"strings"
"sync/atomic"
@ -204,22 +205,12 @@ func LoadUnitConfig() error {
// UnitGlobalDisabled checks if unit type is global disabled
func (u Type) UnitGlobalDisabled() bool {
for _, ud := range DisabledRepoUnitsGet() {
if u == ud {
return true
}
}
return false
return slices.Contains(DisabledRepoUnitsGet(), u)
}
// CanBeDefault checks if the unit type can be a default repo unit
func (u *Type) CanBeDefault() bool {
for _, nadU := range NotAllowedDefaultRepoUnits {
if *u == nadU {
return false
}
}
return true
return !slices.Contains(NotAllowedDefaultRepoUnits, *u)
}
// Unit is a section of one repository

View File

@ -4,6 +4,7 @@
package user_test
import (
"slices"
"testing"
"code.gitea.io/gitea/models/db"
@ -100,12 +101,7 @@ func TestListEmails(t *testing.T) {
assert.Greater(t, count, int64(5))
contains := func(match func(s *user_model.SearchEmailResult) bool) bool {
for _, v := range emails {
if match(v) {
return true
}
}
return false
return slices.ContainsFunc(emails, match)
}
assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 18 }))

View File

@ -831,6 +831,20 @@ type CountUserFilter struct {
IsActive optional.Option[bool]
}
// HasUsers checks whether there are any users in the database, or only one user exists.
func HasUsers(ctx context.Context) (ret struct {
HasAnyUser, HasOnlyOneUser bool
}, err error,
) {
res, err := db.GetEngine(ctx).Table(&User{}).Cols("id").Limit(2).Query()
if err != nil {
return ret, fmt.Errorf("error checking user existence: %w", err)
}
ret.HasAnyUser = len(res) != 0
ret.HasOnlyOneUser = len(res) == 1
return ret, nil
}
// CountUsers returns number of users.
func CountUsers(ctx context.Context, opts *CountUserFilter) int64 {
return countUsers(ctx, opts)

View File

@ -17,10 +17,7 @@ func GetUsersMapByIDs(ctx context.Context, userIDs []int64) (map[int64]*User, er
left := len(userIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
limit := min(left, db.DefaultMaxInSize)
err := db.GetEngine(ctx).
In("id", userIDs[:limit]).
Find(&userMaps)

View File

@ -204,9 +204,9 @@ func TestHashPasswordDeterministic(t *testing.T) {
b := make([]byte, 16)
u := &user_model.User{}
algos := hash.RecommendedHashAlgorithms
for j := 0; j < len(algos); j++ {
for j := range algos {
u.PasswdHashAlgo = algos[j]
for i := 0; i < 50; i++ {
for range 50 {
// generate a random password
rand.Read(b)
pass := string(b)

View File

@ -240,7 +240,7 @@ func CreateWebhooks(ctx context.Context, ws []*Webhook) error {
if len(ws) == 0 {
return nil
}
for i := 0; i < len(ws); i++ {
for i := range ws {
ws[i].Type = strings.TrimSpace(ws[i].Type)
}
return db.Insert(ctx, ws)

View File

@ -73,7 +73,7 @@ func TestWebhook_EventsArray(t *testing.T) {
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
"pull_request_review_comment", "pull_request_sync", "pull_request_review_request", "wiki", "repository", "release",
"package", "status", "workflow_job",
"package", "status", "workflow_run", "workflow_job",
},
(&Webhook{
HookEvent: &webhook_module.HookEvent{SendEverything: true},

View File

@ -6,6 +6,7 @@ package actions
import (
"bytes"
"io"
"slices"
"strings"
"code.gitea.io/gitea/modules/git"
@ -245,6 +246,10 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
webhook_module.HookEventPackage:
return matchPackageEvent(payload.(*api.PackagePayload), evt)
case // workflow_run
webhook_module.HookEventWorkflowRun:
return matchWorkflowRunEvent(payload.(*api.WorkflowRunPayload), evt)
default:
log.Warn("unsupported event %q", triggedEvent)
return false
@ -564,21 +569,12 @@ func matchPullRequestReviewEvent(prPayload *api.PullRequestPayload, evt *jobpars
actions = append(actions, "submitted", "edited")
}
matched := false
for _, val := range vals {
for _, action := range actions {
if glob.MustCompile(val, '/').Match(action) {
matched = true
break
}
}
if matched {
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
matchTimes++
break
}
}
if matched {
matchTimes++
}
default:
log.Warn("pull request review event unsupported condition %q", cond)
}
@ -613,21 +609,12 @@ func matchPullRequestReviewCommentEvent(prPayload *api.PullRequestPayload, evt *
actions = append(actions, "created", "edited")
}
matched := false
for _, val := range vals {
for _, action := range actions {
if glob.MustCompile(val, '/').Match(action) {
matched = true
break
}
}
if matched {
if slices.ContainsFunc(actions, glob.MustCompile(val, '/').Match) {
matchTimes++
break
}
}
if matched {
matchTimes++
}
default:
log.Warn("pull request review comment event unsupported condition %q", cond)
}
@ -708,3 +695,53 @@ func matchPackageEvent(payload *api.PackagePayload, evt *jobparser.Event) bool {
}
return matchTimes == len(evt.Acts())
}
func matchWorkflowRunEvent(payload *api.WorkflowRunPayload, evt *jobparser.Event) bool {
// with no special filter parameters
if len(evt.Acts()) == 0 {
return true
}
matchTimes := 0
// all acts conditions should be satisfied
for cond, vals := range evt.Acts() {
switch cond {
case "types":
action := payload.Action
for _, val := range vals {
if glob.MustCompile(val, '/').Match(action) {
matchTimes++
break
}
}
case "workflows":
workflow := payload.Workflow
patterns, err := workflowpattern.CompilePatterns(vals...)
if err != nil {
break
}
if !workflowpattern.Skip(patterns, []string{workflow.Name}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
case "branches":
patterns, err := workflowpattern.CompilePatterns(vals...)
if err != nil {
break
}
if !workflowpattern.Skip(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
case "branches-ignore":
patterns, err := workflowpattern.CompilePatterns(vals...)
if err != nil {
break
}
if !workflowpattern.Filter(patterns, []string{payload.WorkflowRun.HeadBranch}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
default:
log.Warn("workflow run event unsupported condition %q", cond)
}
}
return matchTimes == len(evt.Acts())
}

View File

@ -101,7 +101,7 @@ func Generate(n int) (string, error) {
buffer := make([]byte, n)
maxInt := big.NewInt(int64(len(validChars)))
for {
for j := 0; j < n; j++ {
for j := range n {
rnd, err := rand.Int(rand.Reader, maxInt)
if err != nil {
return "", err

View File

@ -50,7 +50,7 @@ func TestComplexity_Generate(t *testing.T) {
test := func(t *testing.T, modes []string) {
testComplextity(modes)
for i := 0; i < maxCount; i++ {
for range maxCount {
pwd, err := Generate(pwdLen)
assert.NoError(t, err)
assert.Len(t, pwd, pwdLen)

View File

@ -101,7 +101,7 @@ func (c *Client) CheckPassword(pw string, padding bool) (int, error) {
}
defer resp.Body.Close()
for _, pair := range strings.Split(string(body), "\n") {
for pair := range strings.SplitSeq(string(body), "\n") {
parts := strings.Split(pair, ":")
if len(parts) != 2 {
continue

View File

@ -24,8 +24,8 @@ func drawBlock(img *image.Paletted, x, y, size, angle int, points []int) {
rotate(points, m, m, angle)
}
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
for i := range size {
for j := range size {
if pointInPolygon(i, j, points) {
img.SetColorIndex(x+i, y+j, 1)
}

View File

@ -134,7 +134,7 @@ func drawBlocks(p *image.Paletted, size int, c, b1, b2 blockFunc, b1Angle, b2Ang
// then we make it left-right mirror, so we didn't draw 3/6/9 before
for x := 0; x < size/2; x++ {
for y := 0; y < size; y++ {
for y := range size {
p.SetColorIndex(size-x, y, p.ColorIndexAt(x, y))
}
}

View File

@ -24,7 +24,7 @@ func Init() error {
if err != nil {
return err
}
for i := 0; i < 10; i++ {
for range 10 {
if err = c.Ping(); err == nil {
break
}

View File

@ -164,7 +164,7 @@ func DetectEncoding(content []byte) (string, error) {
}
times := 1024 / len(content)
detectContent = make([]byte, 0, times*len(content))
for i := 0; i < times; i++ {
for range times {
detectContent = append(detectContent, content...)
}
} else {

View File

@ -242,7 +242,7 @@ func stringMustEndWith(t *testing.T, expected, value string) {
func TestToUTF8WithFallbackReader(t *testing.T) {
resetDefaultCharsetsOrder()
for testLen := 0; testLen < 2048; testLen++ {
for testLen := range 2048 {
pattern := " test { () }\n"
input := ""
for len(input) < testLen {

View File

@ -277,8 +277,8 @@ func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommits
var keywords, authors, committers []string
var after, before string
fields := strings.Fields(searchString)
for _, k := range fields {
fields := strings.FieldsSeq(searchString)
for k := range fields {
switch {
case strings.HasPrefix(k, "author:"):
authors = append(authors, strings.TrimPrefix(k, "author:"))

View File

@ -7,8 +7,7 @@ package git
import (
"context"
"fmt"
"io"
"maps"
"path"
"sort"
@ -40,9 +39,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
return nil, nil, err
}
for pth, found := range commits {
revs[pth] = found
}
maps.Copy(revs, commits)
}
} else {
sort.Strings(entryPaths)
@ -124,48 +121,25 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
return nil, err
}
batchStdinWriter, batchReader, cancel, err := commit.repo.CatFileBatch(ctx)
if err != nil {
return nil, err
}
defer cancel()
commitsMap := map[string]*Commit{}
commitsMap[commit.ID.String()] = commit
commitCommits := map[string]*Commit{}
for path, commitID := range revs {
if len(commitID) == 0 {
continue
}
c, ok := commitsMap[commitID]
if ok {
commitCommits[path] = c
continue
}
if len(commitID) == 0 {
continue
}
_, err := batchStdinWriter.Write([]byte(commitID + "\n"))
c, err := commit.repo.GetCommit(commitID) // Ensure the commit exists in the repository
if err != nil {
return nil, err
}
_, typ, size, err := ReadBatchLine(batchReader)
if err != nil {
return nil, err
}
if typ != "commit" {
if err := DiscardFull(batchReader, size+1); err != nil {
return nil, err
}
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
}
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))
if err != nil {
return nil, err
}
if _, err := batchReader.Discard(1); err != nil {
return nil, err
}
commitCommits[path] = c
}

View File

@ -154,7 +154,7 @@ func TestCutDiffAroundLine(t *testing.T) {
}
func BenchmarkCutDiffAroundLine(b *testing.B) {
for n := 0; n < b.N; n++ {
for b.Loop() {
CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
}
}

View File

@ -76,7 +76,7 @@ func (f Format) Parser(r io.Reader) *Parser {
// would turn into "%0a%00".
func (f Format) hexEscaped(delim []byte) string {
escaped := ""
for i := 0; i < len(delim); i++ {
for i := range delim {
escaped += "%" + hex.EncodeToString([]byte{delim[i]})
}
return escaped

View File

@ -8,6 +8,7 @@ import (
"errors"
"os"
"path/filepath"
"slices"
"strings"
"code.gitea.io/gitea/modules/util"
@ -25,12 +26,7 @@ var ErrNotValidHook = errors.New("not a valid Git hook")
// IsValidHookName returns true if given name is a valid Git hook.
func IsValidHookName(name string) bool {
for _, hn := range hookNames {
if hn == name {
return true
}
}
return false
return slices.Contains(hookNames, name)
}
// Hook represents a Git hook.

View File

@ -13,7 +13,7 @@ import (
)
func getCacheKey(repoPath, commitID, entryPath string) string {
hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, commitID, entryPath)))
hashBytes := sha256.Sum256(fmt.Appendf(nil, "%s:%s:%s", repoPath, commitID, entryPath))
return fmt.Sprintf("last_commit:%x", hashBytes)
}

View File

@ -346,10 +346,7 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
results := make([]string, len(paths))
remaining := len(paths)
nextRestart := (len(paths) * 3) / 4
if nextRestart > 70 {
nextRestart = 70
}
nextRestart := min((len(paths)*3)/4, 70)
lastEmptyParent := head.ID.String()
commitSinceLastEmptyParent := uint64(0)
commitSinceNextRestart := uint64(0)

View File

@ -109,8 +109,8 @@ func (ref RefName) IsFor() bool {
}
func (ref RefName) nameWithoutPrefix(prefix string) string {
if strings.HasPrefix(string(ref), prefix) {
return strings.TrimPrefix(string(ref), prefix)
if after, ok := strings.CutPrefix(string(ref), prefix); ok {
return after
}
return ""
}

View File

@ -44,9 +44,9 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) ([]*Commit, erro
return commits, nil
}
parts := bytes.Split(logs, []byte{'\n'})
parts := bytes.SplitSeq(logs, []byte{'\n'})
for _, commitID := range parts {
for commitID := range parts {
commit, err := repo.GetCommit(string(commitID))
if err != nil {
return nil, err

View File

@ -547,11 +547,11 @@ func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID s
return "", runErr
}
parts := bytes.Split(bytes.TrimSpace(stdout), []byte{'\n'})
parts := bytes.SplitSeq(bytes.TrimSpace(stdout), []byte{'\n'})
// 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)
if err != nil {
return "", err

View File

@ -86,7 +86,7 @@ func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
return nil, err
}
filelist := make([]string, 0, len(filenames))
for _, line := range bytes.Split(res, []byte{'\000'}) {
for line := range bytes.SplitSeq(res, []byte{'\000'}) {
filelist = append(filelist, string(line))
}

View File

@ -39,8 +39,8 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
return "", err
}
tagRefs := strings.Split(stdout, "\n")
for _, tagRef := range tagRefs {
tagRefs := strings.SplitSeq(stdout, "\n")
for tagRef := range tagRefs {
if len(strings.TrimSpace(tagRef)) > 0 {
fields := strings.Fields(tagRef)
if strings.HasPrefix(fields[0], sha) && strings.HasPrefix(fields[1], TagPrefix) {
@ -62,7 +62,7 @@ func (repo *Repository) GetTagID(name string) (string, error) {
return "", err
}
// Make sure exact match is used: "v1" != "release/v1"
for _, line := range strings.Split(stdout, "\n") {
for line := range strings.SplitSeq(stdout, "\n") {
fields := strings.Fields(line)
if len(fields) == 2 && fields[1] == "refs/tags/"+name {
return fields[0], nil

View File

@ -56,7 +56,7 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error
return nil, err
}
filelist := make([]string, 0, len(filenames))
for _, line := range bytes.Split(res, []byte{'\000'}) {
for line := range bytes.SplitSeq(res, []byte{'\000'}) {
filelist = append(filelist, string(line))
}

View File

@ -78,7 +78,7 @@ func (te *TreeEntry) FollowLinks(optLimit ...int) (*TreeEntry, error) {
}
limit := util.OptionalArg(optLimit, 10)
entry := te
for i := 0; i < limit; i++ {
for range limit {
if !entry.IsLink() {
break
}

Some files were not shown because too many files have changed in this diff Show More