Compare commits

..

159 Commits

Author SHA1 Message Date
6543
f4729e2418 Add Changelog v1.16.7 (#19575)
Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-05-02 05:41:09 +02:00
6543
f7330fd027 Dont overwrite err with nil (part #19572) (#19574)
* Dont overwrite err with nil (part #19572)


Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-05-02 01:54:20 +02:00
6543
755d8e21ad Migration: only write commit-graph if wiki clone was successfull (#19563) (#19568) 2022-05-01 00:22:42 +02:00
Jimmy Praet
7c0bf06d96 Respect DefaultUserIsRestricted system default when creating new user (#19310 ) (#19560) 2022-04-30 15:00:14 +02:00
Gusted
0d196e29e8 Don't error when branch's commit doesn't exist (#19547) (#19548)
- Backport #19547
  - If one of the branches no longer exists, don't throw an error, it's possible that the branch was destroyed during the process. Simply skip it and disregard it.
  - Resolves #19541
2022-04-29 12:25:19 +02:00
wxiaoguang
b86606fa38 Support hostname:port to pass host matcher's check (#19543) (#19544)
Backport #19543 
hostmatcher: split the hostname from the hostname:port string, use the correct hostname to do the match.
2022-04-29 01:41:58 +08:00
zeripath
74602bb487 Prevent intermittent race in attribute reader close (#19537) (#19539)
Backport #19537

There is a potential rare race possible whereby the c.running channel could
be closed twice. Looking at the code I do not see a need for this c.running
channel and therefore I think we can remove this. (I think the c.running
might have been some attempt to prevent a hang but the use of os.Pipes should
prevent that.)

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-04-28 17:00:01 +02:00
Gusted
1465e0cbb2 Fix 64-bit atomic operations on 32-bit machines (#19531) (#19532)
- Backport #19531
  - Doing 64-bit atomic operations on 32-bit machines is a bit tricky by golang, as they can only be done under certain set of conditions(https://pkg.go.dev/sync/atomic#pkg-note-BUG).
  - This PR fixes such case whereby the conditions weren't met, it moves the int64 to the first field of the struct, which will 64-bit operations happening on this property on 32-bit machines.
  - Resolves #19518
2022-04-27 10:32:28 -05:00
Lunny Xiao
928b603d19 Fix migrate release from github (#19510) (#19523)
* Fix migrate release from github

* Fix bug
2022-04-27 14:46:00 +02:00
Lunny Xiao
8ff542c1a2 When view _Siderbar or _Footer, just display once (#19501) (#19522)
Co-authored-by: zeripath <art27@cantab.net>
2022-04-27 14:04:53 +02:00
zeripath
39a0db6ecf Prevent dangling archiver goroutine (#19516) (#19526)
Backport #19516

Within doArchive there is a service goroutine that performs the
archiving function.  This goroutine reports its error using a `chan
error` called `done`. Prior to this PR this channel had 0 capacity
meaning that the goroutine would block until the `done` channel was
cleared - however there are a couple of ways in which this channel might
not be read.

The simplest solution is to add a single space of capacity to the
goroutine which will mean that the goroutine will always complete and
even if the `done` channel is not read it will be simply garbage
collected away.

(The PR also contains two other places when setting up the indexers
which do not leak but where the blocking of the sending goroutine is
also unnecessary and so we should just add a small amount of capacity
and let the sending goroutine complete as soon as it can.)

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: 6543 <6543@obermui.de>

Co-authored-by: 6543 <6543@obermui.de>
2022-04-27 16:05:52 +08:00
techknowlogick
9cc93c05cd Unset git author/committer variables when running integration tests (#19512) (#19519)
TestAPIGitTag (and likely others) will fail if the running environment contains
GIT_AUTHOR_NAME and other env variables like it.

This PR simply unsets these when running the integration tests.

Fix #14247

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2022-04-26 19:23:54 -04:00
Lunny Xiao
b31418edd9 Fix blame page select range error and some typos (#19503)
Partially back port from #19500 and fix two typos.
2022-04-26 20:19:52 +01:00
6543
242f7f1a52 Add notags to fetch (#19487) (#19490)
* Add notags to fetch (#19487)

* gofumpt
2022-04-25 20:26:17 +02:00
6543
8d7f1e430a User specific repoID or xorm builder conditions for issue search (#19475) (#19476) 2022-04-25 15:28:47 +02:00
Pilou
a6b32adc45 [doctor] authorized-keys: fix displayed check name (backport #19464) (#19484)
The registered check name is authorized-keys, not authorized_keys.
2022-04-25 13:45:18 +02:00
Gusted
1f0dca4614 Mark TemplateLoading error as "UnprocessableEntity" (#19445) (#19446)
* Mark TemplateLoading error as "UnprocessableEntity" (#19445)

- Backport #19445
  - Don't return Internal Server error if the user provide incorrect label template, instead return UnprocessableEntity.
  - Resolves #19399

- dep: upgrade: github.com/gogs/chardet
2022-04-22 21:07:57 +02:00
6543
1d665da32f Prevent dangling cat-file calls (goroutine alternative) (#19454) (#19466)
If an `os/exec.Command` is passed non `*os.File` as an input/output, go
will create `os.Pipe`s and wait for their closure in `cmd.Wait()`.  If
the code following this is responsible for closing `io.Pipe`s or other
handlers then on process death from context cancellation the `Wait` can
hang.

There are two possible solutions:

1. use `os.Pipe` as the input/output as `cmd.Wait` does not wait for these.
2. create a goroutine waiting on the context cancellation that will close the inputs.

This PR provides the second option - which is a simpler change that can
be more easily backported.

Closes #19448

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2022-04-22 16:58:50 +01:00
Gusted
09adc26eb6 Set correct PR status on 3way on conflict checking (#19457) (#19458)
- Backport #19457
  - When 3-way merge is enabled for conflict checking, it has a new interesting behavior that it doesn't return any error when it found a conflict, so we change the condition to not check for the error, but instead check if conflictedfiles is populated, this fixes a issue whereby PR status wasn't correctly on conflicted PR's.
  - Refactor the mergeable property(which was incorrectly set and lead me this bug) to be more maintainable.
  - Add a dedicated test for conflicting checking, so it should prevent future issues with this.
  - Ref: Fix the latest error for https://gitea.com/gitea/go-sdk/pulls/579

Co-authored-by: zeripath <art27@cantab.net>
2022-04-22 09:11:42 +08:00
6543
297346a762 RepoAssignment ensure to close before overwrite (#19449) (#19460)
* check if GitRepo already open and close if

* Only run RepoAssignment once
2022-04-21 18:55:44 +02:00
6543
acd648061d Add Changelog v1.16.6 (#19339)
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>
2022-04-21 01:33:50 +02:00
6543
c5fe0a096d When dumping trim the standard suffices instead of a random suffix (#19440) (#19447)
* When dumping trim the standard suffices instead of a random suffix

Instead of using the `path.Ext()` to trim the last "extension" suffix, just iterate
through the supported suffices and trim those.

Fix #19424

Signed-off-by: Andrew Thornton <art27@cantab.net>

* fix enum with to have correct supported types only

Co-authored-by: 6543 <6543@obermui.de>

Co-authored-by: zeripath <art27@cantab.net>
2022-04-20 23:26:03 +01:00
Gusted
0c7bf6801f Fix DELETE request for non-existent public key (#19443) (#19444)
- Backport #19443
  - Add a return for the first "block" of errors, which fixes the double error messages.
  - Add a return for `externallyManaged`.
  - Resolves #19398

Co-authored-by: 6543 <6543@obermui.de>
2022-04-20 23:24:56 +01:00
Gusted
5863f7e048 Don't panic on ErrEmailInvalid (#19441) (#19442)
- Backport #19441
  - Don't panic on `ErrEmailInvalid`, this was caused due that we were trying to force `ErrEmailCharIsNotSupported` interface, which panics.
  - Resolves #19397

Co-authored-by: 6543 <6543@obermui.de>
2022-04-20 23:24:07 +01:00
6543
a785c46ca8 Add uploadpack.allowAnySHA1InWant to allow --filter=blob:none with older git clients (#19430) (#19438)
Older git clients need uploadpack.allowAnySHA1InWant if partial cloning is allowed.

Fix #19118

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: zeripath <art27@cantab.net>
2022-04-20 20:54:36 +02:00
6543
6bddfd3086 Warn on SSH connection for incorrect configuration (#19317) (#19437)
Backport #19317

- Warn on SSH connection for incorrect configuration
- When `setting.RepoRootPath` cannot be found(most likely due to
incorrect configuration) show "Gitea: Incorrect configuration" on the
client-side to help easier with debugging the problem.

Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-04-20 19:18:23 +02:00
6543
dd8a726b25 API: Search Issues, dont show 500 if filter result in empty list (#19244) (#19436)
Backport #19244

* remove error who is none

* use setupSessionNoLimit instead of setupSessionWithLimit when no pagination

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-04-20 18:30:42 +02:00
zeripath
08eecba32b When updating mirror repo intervals by API reschedule next update too (#19429) (#19433)
Backport #19429

When a mirror repo interval is updated by the UI it is rescheduled with that interval
however the API does not do this. The API also lacks the enable_prune option.

This PR adds this functionality in to the API Edit Repo endpoint.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-04-20 16:04:26 +02:00
wxiaoguang
9c2212df15 Fix nil error when some pages are rendered outside request context (#19428) 2022-04-19 19:30:16 -04:00
Lunny Xiao
9b4746967c Only request write when necessary (#18657) (#19422)
* Only request write when necessary

- Only request write for `INTERNAL_TOKEN_URI` when no token was found.
- Resolves #18655

* Fix perm

* Update setting.go

* Update setting.go

* Update setting.go

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>

Co-authored-by: Gusted <williamzijl7@hotmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>
2022-04-19 12:10:24 -04:00
Gusted
00da1facc4 Fix double blob-hunk on diff page (#19404) (#19405)
- Don't show the blob-hunk twice on diff page
- Backport #19404
2022-04-15 11:27:04 +08:00
techknowlogick
b461993775 go get -u crypto (#19388) 2022-04-12 22:45:58 -04:00
Vasiliy Bukharev
b885e57762 Update locale_ru-RU.ini (#19383) (#19387)
Signed-off-by: bvp <bvp-yar@ya.ru>
2022-04-13 08:15:03 +08:00
Gusted
081449d7a5 Don't allow merging PR's which are being conflict checked (#19357) (#19358)
* Don't allow merging PR's which are being conflict checked (#19357)

- Backport of #19357
  - When a PR is still being conflict checked, don't allow the PR to be merged(the merge button could already be visible before e.g. a new commit was pushed to the PR).
  - Resolves #19352

* Update error message
2022-04-13 00:38:41 +08:00
Gusted
ee3a21a537 Fix middleware function's placements for /user/... (#19377) (#19378)
- Backport #19377
  - Add reqSignIn to `/user/task/{task}` as it specific to a logged in user currently not-logged in user could cause a NPE.
  - Remove `/user/active` reqSignIn middleware, because when you want to active a account you're not "signed in" so it doesn't make sense to add that middleware.
2022-04-12 11:06:07 +08:00
silverwind
61c7732e12 Disable service worker by default (#18914) (#19342)
The service worker causes a lot of issues with JS errors after instance
upgrades while not bringing any real performance gain over regular HTTP
caching.

Disable it by default for this reason. Maybe later we can remove it
completely, as I simply see no benefit in having it.
2022-04-07 20:08:24 +02:00
wxiaoguang
57c2ca7f26 Fix invalid CSRF token bug, make sure CSRF tokens can be up-to-date (#19338)
There was a bug that the CSRF token wouldn't in 24h. This fix just does what the CSRF function comment says: If this request is a GET request, it will generate a new token. Then the CSRF token can be kept up-to-date.
2022-04-06 23:47:58 +08:00
Lunny Xiao
0704009dd7 Revert the minimal golang version requirement from 1.17 to 1.16 and add a warning in Makefile (#19319)
* Revert the minimal golang version requirement from 1.17 to 1.16 and add a warning in Makefile

* Apply suggestions from code review

Co-authored-by: John Olheiser <john.olheiser@gmail.com>

* 1.16

* Update modules/util/net.go

Co-authored-by: Gusted <williamzijl7@hotmail.com>

* correct bool conditional

yay tests for catching this :)

* Update hostmatcher.go

Co-authored-by: John Olheiser <john.olheiser@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-04-05 13:32:24 -04:00
zeripath
14a6aafb50 Restore user autoregistration with email addresses (#19261) (#19312)
Backport #19261

Unfortunately #18789 disabled autoregistration using email addresses as they would
be shortcut to email address does not exist.

This PR attempts to restore autoregistration by allowing an unknown email address
to percolate through to the autoregistration path of UserSignin.

Fix #19256

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-04-02 20:36:47 -04:00
Lunny Xiao
471a1e8111 Performance improvement for add team user when org has more than 1000 repositories (#19227) (#19289) 2022-04-01 11:36:12 +03:00
6543
123c254b84 Move checks for pulls before merge into own function (#19271) (#19277)
Backport #19271

Fix:
* The API does ignore issue dependencies where Web does not
* The API checks if "IsSignedIfRequired" where Web does not - UI probably do but nothing will some to craft custom requests
* Default merge message is crafted a bit different between API and Web if not set on specific cases ...
2022-03-31 16:57:13 +02:00
zeripath
db43f63c53 Use full output of git show-ref --tags to get tags for PushUpdateAddTag (#19235) (#19236)
* Use full output of git show-ref --tags to get tags for PushUpdateAddTag (#19235)

Strangely #19038 appears to relate to an issue whereby a tag appears to
be listed in `git show-ref --tags` but then does not appear when `git
show-ref --tags -- short_name` is called.

As a solution though I propose to stop the second call as it is
unnecessary and only likely to cause problems.

I've also noticed that the tags calls are wildly inefficient and aren't using the common cat-files - so these have been added.

I've also noticed that the git commit-graph is not being written on mirroring - so I've also added writing this to the migration which should improve mirror rendering somewhat.

Fix #19038

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: 6543 <6543@obermui.de>

* fix rebase relict

Co-authored-by: 6543 <6543@obermui.de>
2022-03-29 23:19:57 +03:00
John Olheiser
3ecd520f8e Granular webhook events in editHook (#19251) (#19257)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2022-03-29 18:26:51 +02:00
zeripath
e9935d358c Only send webhook events to active system webhooks and only deliver to active hooks (#19234) (#19248)
Backport #19234

There is a bug in the system webhooks whereby the active state is not checked when
webhooks are prepared and there is a bug that deactivating webhooks do not prevent
queued deliveries.

* Only add SystemWebhooks to the prepareWebhooks list if they are active
* At the time of delivery if the underlying webhook is not active mark it
as "delivered" but with a failed delivery so it does not get delivered.

Fix #19220

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-29 14:12:56 +02:00
wxiaoguang
8d653b148b Check go and nodejs version by go.mod and package.json (#19197) (#19254)
* Check go and nodejs version by go.mod and package.json 
* Update Go official site URL 

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: gesangtome <gesangtome@foxmail.com>
2022-03-29 15:32:38 +08:00
wxiaoguang
b702f2dac3 Fix clone url JS error for the empty repo page (#19209)
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: zeripath <art27@cantab.net>
2022-03-29 11:04:29 +08:00
6543
d59b8541f2 Use goproxy.io instead of goproxy.cn (#19242) (#19246)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-03-29 02:22:55 +01:00
zeripath
efd34d0d7d Prevent intermittent failures in RepoIndexerTest (#19225 #19229) (#19228)
Backport #19225
Backport #19229

The RepoIndexerTest is failing with considerable frequency due to a race inherrent in
its design. This PR adjust this test to avoid the reliance on waiting for the populate
repo indexer to run and forcibly adds the repo to the queue. It then flushes the queue.

It may be worth separating out the tests somewhat by testing the Index function
directly away from the queue however, this forceful method should solve the current
problem.

Fix #19162

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-28 01:01:53 +02:00
zeripath
2ec2935f78 Touch mirrors on even on fail to update (#19217) (#19233)
Backport #19217

If a mirror fails to be synchronised it should be pushed to the bottom of the queue
of the awaiting mirrors to be synchronised. At present if there LIMIT number of
broken mirrors they can effectively prevent all other mirrors from being synchronized
as their last_updated time will remain earlier than other mirrors.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-27 23:08:28 +02:00
Lunny Xiao
540541caa2 Hide sensitive content on admin panel progress monitor (#19218 & #19226) (#19231)
* Hide sensitive content on admin panel progress monitor (#19218)

Sanitize urls within git process descriptions.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Andrew Thornton <art27@cantab.net>

* Do not include global arguments in process manager (#19226)

Backport #19226

The git command by default adds a number of global arguments. These are not
helpful to be displayed in the process manager and so should be skipped for
default process descriptions.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Andrew Thornton <art27@cantab.net>
2022-03-27 18:21:59 +01:00
Robert Kaussow
a13d64bf98 Bump goldmark to v1.4.11 (#19201) (#19203)
* Bump goldmark to v1.4.11

* fix go.sum

Signed-off-by: Andrew Thornton <art27@cantab.net>

* add testcase

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Andrew Thornton <art27@cantab.net>
2022-03-24 11:47:40 -04:00
zeripath
bab7d885aa Changelog for 1.16.5 (#19189)
* Changelog for 1.16.5

 ## [1.16.5](https://github.com/go-gitea/gitea/releases/tag/1.16.5) - 2022-03-23

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: 6543 <6543@obermui.de>
2022-03-24 01:13:52 +01:00
6543
42229dc0b8 Fix showing issues in your repositories (#18916) (#19191)
- Make a restriction on which issues can be shown based on if you the user or team has write permission to the repository.
- Fixes a issue whereby you wouldn't see any associated issues with a specific team on a organization if you wasn't a member(fixed by zeroing the User{ID} in the options).
- Resolves #18913

Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-03-24 00:36:38 +01:00
zeripath
e3d8e92bdc Prevent redirect to Host (2) (#19175) (#19186)
Backport #19175

Unhelpfully Locations starting with `/\` will be converted by the
browser to `//` because ... well I do not fully understand. Certainly
the RFCs and MDN do not indicate that this would be expected. Providing
"compatibility" with the (mis)behaviour of a certain proprietary OS is
my suspicion. However, we clearly have to protect against this.

Therefore we should reject redirection locations that match the regular
expression: `^/[\\\\/]+`

Reference #9678

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-23 20:01:23 +00:00
zeripath
6fc73a8433 Fix compare link in active feeds for new branch (#19149) (#19185)
Backport #19149

When a new branch is pushed the old SHA is always listed as the empty sha and thus the compare link that is created does not work correctly.

Therefore when creating the compare link for new branches:

1. Attempt to get the parent of the first commit and use that as the basis
for the compare link.
2. If this is not possible make a comparison to the default branch
3. Finally if that is not possible simply do not show a compare link.

However, there are multiple broken compare links remaining therefore, in order for these to not break we will simply make the compare link redirect to the default branch.

Fix #19144

Signed-off-by: a1012112796 <1012112796@qq.com>
Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: a1012112796 <1012112796@qq.com>
2022-03-23 19:04:50 +00:00
zeripath
b1a0a78a51 Redirect .wiki/* ui link to /wiki (#18831) (#19184)
Backport #18831

Redirect .wiki/* ui link to /wiki

fix #18590

Signed-off-by: a1012112796 <1012112796@qq.com>
Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: a1012112796 <1012112796@qq.com>
2022-03-23 16:46:08 +00:00
Andrew Thornton
9c7d8b3096 Prevent start panic due to missing DotEscape function
Unfortunately #19169 causing a panic at startup in prod mode. This was hidden by dev
mode because the templates are compiled dynamically there. The issue is that DotEscape
is not in the original FuncMap at the time of compilation which causes a panic.

Ref #19169

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-23 16:09:57 +00:00
zeripath
93feb1a666 Fix the bug: deploy key with write access can not push (#19010) (#19182)
Backport #19010

Use DeployKeyID to replace the IsDeployKey, then CanWriteCode uses the DeployKeyID to check the write permission.

Fix #19009

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-23 13:44:41 +00:00
zeripath
bb0e2121a3 Try to prevent autolinking of displaynames by email readers (#19169) (#19183)
Backport #19169

Unfortunately many email readers will (helpfully) detect url or url-like names and
automatically create links to them, even in HTML emails. This is not ideal when
usernames can have dots in them.

This PR tries to prevent this behaviour by sticking ZWJ characters between dots and
also set the meta tag to prevent format detection.

Not every email template has been changed in this way - just the activation emails but
it may be that we should be setting the above meta tag in all of our emails too.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-23 15:18:11 +02:00
zeripath
d21b7fd3af Clean paths when looking in Storage (#19124) (#19179)
Backport #19124

* Clean paths when looking in Storage

Ensure paths are clean for minio aswell as local storage.

Use url.Path not RequestURI/EscapedPath in storageHandler.

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Apply suggestions from code review

Co-authored-by: Lauris BH <lauris@nix.lv>
2022-03-23 09:23:00 +00:00
Norwin
743553f3e9 Cleanup protected branches when deleting users & teams (#19158) (#19174)
* Clean up protected_branches when deleting user

fixes #19094

* Clean up protected_branches when deleting teams

* fix issue

Co-authored-by: Lauris BH <lauris@nix.lv>

Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-23 13:56:53 +08:00
zeripath
a3ccbb5b7f Ensure that setting.LocalURL always has a trailing slash (#19171) (#19177)
Backport #19171

Fix #19166

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-03-23 12:56:52 +08:00
zeripath
4b7cb813e6 Use the new/choose link for New Issue on project page (#19172) (#19176)
Backport #19172

Extend issues/new/choose to pass the project id and change New Issue
link on project page to use new/choose

Fix #19170

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-23 09:41:12 +08:00
zeripath
23b8214549 Use IterateBufferSize whilst querying repositories during adoption check (#19140) (#19160)
Backport #19140

The adoption page checks directories to see if they are repositories by querying the
db on a per user basis. This can lead to problems if a user has a large number of
repositories or putative repositories.

This PR changes the buffering to check the db in IterataeBufferSize batches instead.

Fix #19137

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-22 09:11:22 +08:00
zeripath
08feb6b664 Ensure isSSH is set whenever DISABLE_HTTP_GIT is set (#19028) (#19146)
Backport #19028

When DISABLE_HTTP_GIT is set we should always show the SSH button

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-03-21 08:59:55 +08:00
Abheek Dhawan
1aa5dc75df Use custom favicon when viewing static files if it exists (#19130) (#19152)
Redirect `/favicon.ico` to `/assets/img/favicon.png`.

Fix #19109

Co-authored-by: zeripath <art27@cantab.net>
2022-03-20 20:28:35 -04:00
Gusted
ee234aff61 Fix NPE /repos/issues/search when not signed in (#19154) (#19155)
- Backport #19154

  - Don't panic when on `/repos/issues/search?{created,assigned,mentioned,review_requested}=true` when client didn't pass any authentication.
  - Resolves #19115
2022-03-20 22:42:31 +01:00
zeripath
a3f3e310fb Fix wrong scopes caused by empty scope input (#19029) (#19145)
Backport #19029
Fix #18972 Gitea prepends requested openid scope with + after updating authentication source
2022-03-21 03:13:18 +08:00
zeripath
ea56bdca5f Fix the editor height in review box (#19003) (#19147)
Backport #19003

Fix the height problem in  https://github.com/go-gitea/gitea/pull/18862#issuecomment-1059329539

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-20 10:29:49 +08:00
zeripath
45c836badc Do not send notification emails to inactive users (#19131) (#19139)
Backport #19131
Backport #19142

Emails should not be sent to inactive users except for Activate and ResetPassword
messages.

Fix #18950

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-19 18:33:32 +00:00
techknowlogick
f9ea4ab69a Bump to build with go1.18 (#19120 et al) (#19127)
Backport #19120 
Backport #19099 
Backport #18874 
Backport #18420
Backport #19128
Backport #18270 

Bump to build with go1.18

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Jelle Hulter <jellehulter@gmail.com>
2022-03-19 18:46:47 +01:00
zeripath
e6d46eeb55 Make migrations SKIP_TLS_VERIFY apply to git too (#19132) (#19141)
Backport #19132

Make SKIP_TLS_VERIFY apply to git data migrations too through adding the `-c http.sslVerify=false` option to the git clone command.

Fix #18998

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-19 16:20:26 +00:00
zeripath
5bb0c92b6c Do not send activation email if manual confirm is set (#19119) (#19122)
Backport #19119

If the mailer is configured then even if Manual confirm is set an activation email
is still being sent because `handleUserCreated` is not checking for this case.

Fix #17263

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-19 14:20:42 +00:00
Gusted
c1e6be47d7 Update golang.org/x/crypto (#19097) (#19098)
Backport #19097

* Update golang.org/x/crypto (#19097)

- Backport #19097

* Fix deprecation notice

* Backport workaround removal
2022-03-19 12:16:15 +00:00
Lunny Xiao
79a5e68816 Handle email address not exist (#19089) (#19121)
Backport #19089

* Handle email address not exist. (#19089)

* Fix lint about strings.Title

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
2022-03-19 11:35:23 +00:00
Gusted
9bcbbd419f Update json-iterator (#18644) (#19100)
- Backport #18644
2022-03-15 17:29:06 -04:00
6543
f460b7543e Changelog v1.16.4 (#19081) 2022-03-14 21:55:33 +01:00
6543
1cb649525d Restrict email address validation (#17688) (#19085)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-03-14 20:51:58 +01:00
6543
99861e3e06 Fix lfs bug (#19072) (#19080)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-03-14 15:59:54 +01:00
Gusted
66b8a43e5f Refactor mirror code & fix StartToMirror (#18904) (#19075)
- Backport #18904.
2022-03-14 20:04:41 +08:00
zeripath
d285905826 Update the webauthn_credential_id_sequence in Postgres (#19048) (#19060)
Backport #19048

There is (yet) another problem with v210 in that Postgres will silently allow preset
ID insertions ... but it will not update the sequence value.

This PR simply adds a little step to the end of the v210 migration to update the
sequence number.

Users who have already migrated who find that they cannot insert new
webauthn_credentials into the DB can either run:

```bash
gitea doctor recreate-table webauthn_credential
```

or

```bash
SELECT setval('webauthn_credential_id_seq', COALESCE((SELECT MAX(id)+1 FROM `webauthn_credential`), 1), false)
```

which will fix the bad sequence.

Fix #19012

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: 6543 <6543@obermui.de>
2022-03-13 12:02:19 +08:00
zeripath
4df2320ba6 Prevent 500 when there is an error during new auth source post (#19041) (#19059)
Backport #19041

Fix #19036

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-13 03:42:31 +01:00
zeripath
0fe99cc00c If rendering has failed due to a net.OpError stop rendering (attempt 2) (#19049) (#19056)
Backport #19049

Unfortunately #18642 does not work because a `*net.OpError` does not implement
the `Is` interface to make `errors.Is` work correctly - thus leading to the
irritating conclusion that a `*net.OpError` is not a `*net.OpError`.

Here we keep the `errors.Is` because presumably this will be fixed at
some point in the golang main source code but also we add a simply type
cast to also check.

Fix #18629

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-10 22:13:55 +01:00
Norwin
580401ecbf Fix flag validation (#19046) (#19051)
Regression from #5785
2022-03-10 20:23:55 +00:00
zeripath
7aa29720f0 Improve SyncMirrors logging (#19045) (#19050)
Backport #19045

Yet another issue has come up where the logging from SyncMirrors does not provide
enough context. This PR adds more context to these logging events.

Related #19038

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-10 16:06:35 +01:00
6543
3e5c844a77 fix pam authorization (#19040) (#19047)
Backport #19040 

The PAM module has previously only checked the results of the authentication module.

However, in normal PAM practice most users will expect account module authorization to also be checked. Without doing this check in almost every configuration expired accounts and accounts with expired passwords will still be able to login.

This is likely to represent a significant gotcha in most configurations and cause most users configurations to be potentially insecure. Therefore we should add in the account authorization check.

## ⚠️ **BREAKING** ⚠️ 

Users of the PAM module who rely on account modules not being checked will need to change their PAM configuration.

However, as it is likely that the vast majority of users of PAM will be expecting account authorization to be checked in addition to authentication we should make this breaking change to make the default behaviour correct for the majority.

---

I suggest we backport this despite the BREAKING nature because of the surprising nature of this.

Thanks to @ysf for bringing this to our attention.


Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: ysf <34326+ysf@users.noreply.github.com>
2022-03-10 08:15:35 +00:00
zeripath
4047c5c068 Ignore missing comment for user notifications (#18954) (#19043) 2022-03-10 01:48:27 -05:00
zeripath
03d924238c Set rel="nofollow noindex" on new issue links (#19023) (#19042)
Backport #19023

Fix #19018

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-03-09 23:01:30 +00:00
Lunny Xiao
bc1248ed9e Upgrading binding package (#19034) (#19035)
Backport #19034

Fix #18855
2022-03-09 18:07:46 +00:00
zeripath
dd52c08b74 Don't show context cancelled errors in attribute reader (#19006) (#19027)
Backport #19006

Fix #18997

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-08 19:20:37 +08:00
Lunny Xiao
b811b819e2 Fix update hint bug (#19002) 2022-03-04 18:28:17 +00:00
Otto Richter (fnetX)
da985b25ce Fix potential assignee query for repo (#18994) (#18999)
* Fix potential assignee query for repo

* Add tests for `GetRepoAssignees`

- As per https://github.com/go-gitea/gitea/pull/18994#issuecomment-1058506640

Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-03-05 00:12:34 +08:00
6543
ae9c51df7c allow overwrite artifacts for github releases (#18987) (#18988) 2022-03-03 16:18:55 +01:00
Lunny Xiao
ff1c5815bb Changelog for v1.16.3 (#18966)
* Changelog for v1.16.3

* Update CHANGELOG.md

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Gusted <williamzijl7@hotmail.com>

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-03-03 10:50:36 +08:00
6543
87f8d37be5 git backend ignore replace objects (#18979) (#18980)
Co-authored-by: zeripath <art27@cantab.net>
2022-03-02 21:31:50 +00:00
Otto Richter (fnetX)
f4b96c1041 Set max text height to prevent overflow (#18862) (#18977)
Sets a max height for review text boxes to prevent a very annoying bug where users cannot access the "submit" button.

Before:
![image](https://user-images.githubusercontent.com/12700993/155253001-e1dab086-aaf3-4338-889d-6a861728274a.png)

After:
![image](https://user-images.githubusercontent.com/12700993/155253144-5b9a3547-9582-412f-867f-41a45a14a0fe.png)

Interestingly, I don't see this bug on Firefox.

Co-authored-by: Kyle D <kdumontnu@gmail.com>
2022-03-02 20:12:48 +00:00
Otto Richter (fnetX)
a3f72303d1 Fix problem when self-assign notification (#18797) (#18976)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-03-02 20:11:55 +00:00
6543
4317806ade backport fix of #18973 (#18974) 2022-03-02 19:42:02 +00:00
Otto Richter (fnetX)
578f19a682 Refactor admin user filter query parameters (#18965) (#18975)
Only pass `status_filter` on admin page
Use a more general method to pass query parameters, remove hard-coded keys

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-03-02 19:57:18 +01:00
6543
f9b6404950 Accounts with WebAuthn only (no TOTP) now exist ... fix code to handle that case (#18897) (#18964) 2022-03-02 07:22:02 -06:00
Gusted
52517e3e23 Send 404 on /{org}.gpg (#18959) (#18962) 2022-03-01 20:37:47 -05:00
Otto Richter (fnetX)
36e96e3481 Fix admin user list pagination (#18957) (#18960) 2022-03-01 23:00:03 +00:00
Lunny Xiao
a765410d0f Fix lfs management setting (#18947) 2022-03-01 14:14:18 -05:00
6543
43fc2e528c Backport locales from master (#18944)
* update

* clean

* clean2

* clean2

* clean-next

* cleanup

* finish cleanup
2022-02-28 21:19:19 +00:00
Lunny Xiao
cb90eda213 Fix login with email panic when email is not exist (#18942)
Co-authored-by: 6543 <6543@obermui.de>
2022-02-28 18:14:50 +00:00
zeripath
5f9c18b2b3 Adjust error for already locked db and prevent level db lock on malformed connstr (#18923) (#18938)
Backport #18923

This PR adjusts the error returned when there is failure to lock the level db, and
permits a connections to the same leveldb where there is a different connection string.

Reference #18921
Reference #18917

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-28 15:45:38 +00:00
Gusted
4384b85046 Update go-org to v1.6.1 (#18932) (#18933)
Backport #18932
2022-02-27 16:57:06 +00:00
Gusted
e0973a84a0 Fix <strong> html in translation (#18929) (#18931)
Backport #18929
2022-02-27 15:46:34 +00:00
qwerty287
054bc55a1c Fix page and missing return on unadopted repos API (#18848) (#18927)
* Fix page and missing return on unadopted repos API

Page must be 1 if it's not specified and it should return after sending an internal server error.

* Allow ignore pages
2022-02-27 20:18:23 +08:00
Gusted
4fb718d405 Don't treat BOM escape sequence as hidden character. (#18909) (#18910)
* Don't treat BOM escape sequence as hidden character. (#18909)

Backport #18909
2022-02-26 23:15:04 +01:00
Gusted
df35049196 Allow adminstrator teams members to see other teams (#18918) (#18919)
Allow adminstrator teams members to see other teams (#18918)
2022-02-26 22:45:34 +01:00
silverwind
ce75461380 Correctly link URLs to users/repos with dashes, dots or underscores (#18890) (#18908)
* Add tests for references with dashes

This commit adds tests for full URLs referencing repos names and user
names containing a dash.

* Extend regex to match URLs to repos/users with dashes

Co-authored-by: Alexander Neumann <62751754+rtpt-alexanderneumann@users.noreply.github.com>
2022-02-26 06:45:09 +01:00
Gusted
cea85c30a4 Don't update email for organisation (#18905) (#18906)
Backport #18905
2022-02-26 03:10:21 +01:00
Otto Richter (fnetX)
6039138323 Fix redirect when using lowercase reponame (#18775) (#18902)
* Previously,  `GET {username}/{reponame}/raw///file-path` (the middle two slashes are blank to get the default branch) when the repo name has uppercase letters, e.g., https://try.gitea.io/AbdulrhmnGhanem/CH330_Hardware, using a lowercase version of the name redirected to the correct URL
* In other words both
   * `GET https://try.gitea.io/AbdulrhmnGhanem/CH330_Hardware/raw///images/back.png`
   * `GET https://try.gitea.io/AbdulrhmnGhanem/ch330_hardware/raw///images/back.png`
were redirecting to ` GET https://try.gitea.io/AbdulrhmnGhanem/CH330_Hardware/raw/branch/master/images/back.png`
This isn't the case after  #17551. Specifically because of this [line](cbd5eecd14/modules/context/repo.go (L860)).

Co-authored-by: Ghanem <37152329+AbdulrhmnGhanem@users.noreply.github.com>
2022-02-26 08:16:22 +08:00
Lunny Xiao
eb43e73785 Fix team management UI (#18887) 2022-02-25 21:51:22 +01:00
Lunny Xiao
c077a0361a Fix migration v210 (#18893) 2022-02-25 15:08:00 +01:00
Jimmy Praet
6f21a94d18 BeforeSourcePath should point to base commit (#18880) 2022-02-25 14:45:20 +08:00
Lunny Xiao
8ebf0e68ec Add changelog for v1.16.2 (#18840)
Add changelog for v1.16.2

Co-authored-by: 6543 <6543@obermui.de>
2022-02-24 20:03:08 +01:00
Lunny Xiao
3685cc7660 Fix ldap user sync missed email in email_address table (#18786) (#18876)
* Fix ldap user sync missed email in email_address table (#18786)
2022-02-24 19:07:52 +01:00
zeripath
9d9ccdbe43 Don't report signal: killed errors in serviceRPC (#18850) (#18865)
Backport #18850

Fix #18849

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-24 16:59:50 +08:00
zeripath
81b29d6263 Update assignees check to include any writing team and change org sidebar (#18680) (#18873)
Backport #18680

Following the merging of #17811 teams can now have differing write and readonly permissions, however the assignee list will not include teams which have mixed perms.

Further the org sidebar is no longer helpful as it can't describe these mixed permissions situations.

Fix #18572

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-24 09:22:46 +08:00
Lunny Xiao
6591f87b28 Fix login with email for ldap users (#18800) (#18836)
`authenticator.Authenticate` has assume the login name is not an email, but `username` maybe an email. So when we find the user via email address, we should use `user.LoginName` instead of `username` which is an email address.

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-02-22 18:04:57 -05:00
Lunny Xiao
efc78c18c1 Fix ldap edit bug (#18859) 2022-02-22 17:31:29 -05:00
Lunny Xiao
f5a3c0dd6c Fix ldap loginname (#18789) (#18804)
* Use email_address table to check user's email when login with email adress

* Update services/auth/signin.go

* Fix test

* Fix test

* Fix logging in with ldap username != loginname

* Fix if user does not exist yet

* Make more clear this is loginName

* Fix formatting

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>

Co-authored-by: Johan Van de Wauw <johan@gisky.be>
Co-authored-by: zeripath <art27@cantab.net>
2022-02-22 14:33:06 +01:00
zeripath
382101ecc7 In disk_channel queues synchronously push to disk on shutdown (#18415) (#18788)
Partial Backport of #18415

Instead of using an asynchronous goroutine to push to disk on shutdown
just close the datachan and immediately push to the disk.

Prevents messages of incompletely flushed queues.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-22 20:08:35 +08:00
Lunny Xiao
86c3481eff Fix bug for get user by email (#18834)
Backport #18833

Fix #18830
2022-02-21 18:34:22 +00:00
zeripath
039eb66c8c Update go-org to 1.6.0 (#18824) (#18839)
Backport #18824

Fix #14074

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-21 22:21:43 +08:00
Wim
36148ed083 Show fullname on issue edits and gpg/ssh signing info (#18828)
Co-authored-by: zeripath <art27@cantab.net>
2022-02-20 21:47:17 +00:00
Lunny Xiao
db4c7dcf15 Put buttons back in org dashboard (#18817) (#18825)
Backport #18817

Fix #18523
2022-02-20 19:51:01 +00:00
zeripath
bec566282e Immediately Hammer if second kill is sent (#18823) (#18826)
Backport #18823

Currently Gitea will wait for HammerTime or nice shutdown if kill -1 or kill -2
is sent. We should just immediately hammer if there is a second kill.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-20 01:37:52 +08:00
zeripath
fa9be55018 Fix panic in EscapeReader (#18820) (#18821)
Backport #18820

There is a potential panic due to a mistaken resetting of the length parameter when
multibyte characters go over a read boundary.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-19 23:34:32 +08:00
singuliere
458239b46d remove redundant call to UpdateRepoStats during migration (#18591) (#18794)
There is no need to call UpdateRepoStats in the InsertIssues and
InsertPullRequests function. They are only called during migration by
the CreateIssues and CreateReviews methods of the gitea uploader.

The UpdateRepoStats function will be called by the Finish method of
the gitea uploader after all reviews and issues are inserted. Calling
it before is therefore redundant and the associated SQL requests are
not cheap.

The statistics tests done after inserting an issue or a pull request
are also removed. They predate the implementation of UpdateRepoStats,
back when the calculation of the statistics was an integral part of
the migration function. The UpdateRepoStats is now tested
independantly and these tests are no longer necessary.

Signed-off-by: singuliere <singuliere@autistici.org>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-02-17 17:57:05 +00:00
silverwind
ae85ee1c6f Allow mermaid render error to wrap (#18791) 2022-02-17 15:42:29 +08:00
zeripath
08d5a836ef Attempt to fix the webauthn migration again - part 3 (#18770) (#18771)
Backport #18770 

v208.go is seriously broken as it misses an ID() check. We need to no-op and remigrate all of the u2f keys.

See #18756

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-16 21:15:49 +00:00
Lunny Xiao
ad789542b8 Fix template bug of LFS lock (#18784) (#18787)
Backport #18784 

Fix #18782
2022-02-16 17:16:04 +00:00
silverwind
1f7802db97 Various Mermaid improvements (#18776) (#18780)
* Various Mermaid improvments

- Render into iframe for improved security
- Use built-in dark theme instead of color inversion
- Remove flexbox attributes, resulting in more consistent size rendering
- Update API usage and update to latest version

* restart ci

* misc tweaks

* remove unneccesary declaration

* make it work without allow-same-origin, add loading=lazy

* remove loading attribute, does not seem to work

* rename variable

* skip roundtrip to DOM for rendering

* don't guess chart height

* update comment to make it clear it's intentional

* tweak

* replace deprecated 'scrolling' property

* remove unused css file

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-16 17:26:53 +08:00
zeripath
c876124efe Ensure git tag tests and others create test repos in tmpdir (#18447) (#18767)
Backport #18447

* Ensure git tag tests and other create test repos in tmpdir

There are a few places where tests appear to reuse testing repos which
causes random CI failures.

This PR simply changes these tests to ensure that cloning always happens
into new temporary directories.

Fix #18444

* Change log root for integration tests to use the REPO_TEST_DIR

There is a potential race in the drone integration tests whereby test-mysql etc
will start writing to log files causing make test-check fail.

Fix #18077

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: 6543 <6543@obermui.de>
2022-02-15 19:16:38 +08:00
zeripath
3a78ac4b32 Increase the size of the webauthn_credential credential_id field (#18739) (#18756)
* Increase the size of the webauthn_credential credential_id field (#18739)

Backport #18739

Unfortunately credentialIDs in u2f are 255 bytes long which with base32 encoding
becomes 408 bytes. The default size of a xorm string field is only a VARCHAR(255)

This problem is not apparent on SQLite because strings get mapped to TEXT there.

Fix #18727

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Ignore the migrate if u2f_registration is not exist (#18760)

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-14 21:08:49 +00:00
zeripath
7ebc3da7cb Prevent dangling GetAttribute calls (#18754) (#18755)
* Prevent dangling GetAttribute calls

It appears possible that there could be a hang due to unread data from the
repo-attribute command pipes. This PR simply closes these during the defer.

Signed-off-by: Andrew Thornton <art27@cantab.net>

* move close into the defer

Signed-off-by: Andrew Thornton <art27@cantab.net>

* lets try again

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-14 15:27:55 -05:00
zeripath
2e36ba0a00 Send mail to issue/pr assignee/reviewer also when OnMention is set (#18707) (#18765)
Backport #18707

Addresses #17892, where emails notifications are not sent to assignees (issue and PR) and reviewers (PR) when they have the email setting Only email on mention enabled.

From the user experience perspective, when a user gets a issue/PR assigned or a PR review request, he/she would expect to be implicitly mentioned since the assignment or request is personal and targeting a single person only. Thus I see #17892 as a bug. Could we therefore mark this ticket as such?

The changed code just explicitly checks for the EmailNotificationsOnMention setting beside the existing EmailNotificationsEnabled check. Too rude?

@lunny mentioned a mock mail server for tests, is there something ready. How could I make use of it?

See #12774 (comment)

Fix #17892

Co-authored-by: flozzone <flozzone@gmail.com>
2022-02-14 21:13:41 +08:00
wxiaoguang
69a158dcc2 Fix a broken link in commits_list_small.tmpl (#18764) 2022-02-14 12:03:51 +00:00
Lunny Xiao
913d6f3ff3 Fix isempty detection of git repository (#18746) (#18750)
* Fix isempty detection of git repository

* Fix IsEmpty check
2022-02-14 00:33:35 +08:00
zeripath
044cb09ae8 Prevent double encoding of branch names in delete branch (#18714) (#18738)
Backport #18714

* Prevent double encoding of branch names in delete branch

There is a double encoding issue in branch template whereby the branch name
ends up double encoded.

Fix #18709

Signed-off-by: Andrew Thornton <art27@cantab.net>

* and tag name

Signed-off-by: Andrew Thornton <art27@cantab.net>

* And fix #18704

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-12 15:17:45 +00:00
Lunny Xiao
9da8e478dd Fix forked repositories missed tags (#18719) (#18735)
* Fix forked repositories missed tags

* Add missed close

* Use ctx

Co-authored-by: 6543 <6543@obermui.de>
2022-02-12 13:48:38 +00:00
zeripath
c8f3672a88 Always set PullRequestWorkInProgressPrefixes in PrepareViewPullInfo (#18713) (#18737)
Backport #18713

Move setting PullRequestWorkInProgressPrefixes to the start of PrepareViewPullInfo.

Fix #18706

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-12 12:55:34 +00:00
Jimmy Praet
edf85b820d Fix source code line highlighting (#18729) (#18740)
Backport #18729

When the issues repo unit is disabled, or an external issue tracker is used, there is no "a.ref-in-new-issue".

Fixes #18721
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-02-12 12:24:49 +00:00
silverwind
c04a4afac1 Reduce CI go module downloads, add make targets (#18708, #18475, #18443) (#18741)
Backport #18708 
Backport #18475 
Backport #18443 

The CI currently downloads all go modules in each pipeline step because go modules reside outside the project directory. Fix this by introducing a volume for the `/go` directory [1] so modules are only downloaded once per pipeline using a new `deps-backend` make target.

For completeness, I also included new `deps` and `deps-frontend` targets and the frontend one is also triggered explicitly on CI where needed.

[1] https://docs.drone.io/pipeline/kubernetes/examples/language/golang/#dependencies

* Also backports #18475 and #18443 so that is was able to merge cleanly.
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-02-12 10:43:08 +00:00
zeripath
65ad6362d7 Separate the details links of commit-statuses in headers (#18661) (#18730)
Backport #18661
2022-02-12 11:40:55 +08:00
Lunny Xiao
f9a0ae1dd4 Fix release typo (#18728) (#18731) 2022-02-11 20:15:34 -05:00
wxiaoguang
fb26b01688 Update object repo with the migrated repository (#18684) (#18726)
When migrating a repository (from GitHub) using the API (**POST** `repos/migrate`), the Code Indexer is not updated. Searching in the user interface will not return any results.

When migrating the same repository using **+/New Migration** in the web interface, the search index is updated and searching works as expected.

Caused by the fact that object `repo` is never updated with the migrated repo so `setting.Indexer.RepoIndexerEnabled && !repo.IsEmpty` in `modules/notification/indexer/indexer.go:NotifyMigrateRepository` always evaluates to `false`.

Tested with gitea:1.16.1, MariaDB:10, Breve in `Run Mode: Dev`.

Co-authored-by: Hugo Hoitink <10838836+hoitih@users.noreply.github.com>
2022-02-11 17:23:41 +01:00
Lunny Xiao
63628fdf1c Fix bug for version update hint (#18701) (#18705)
* Fix bug for version update hint (#18701)
* Add translation for zh-CN

Co-authored-by: silverwind <me@silverwind.io>
2022-02-10 18:35:24 +00:00
zeripath
2e317d3f6e Prevent security failure due to bad APP_ID (#18678) (#18682)
Backport #18678

WebAuthn may cause a security exception if the provided APP_ID is not allowed for the
current origin. Therefore we should reattempt authentication without the appid
extension.

Also we should allow [u2f] as-well as [U2F] sections.

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-10 16:17:44 +01:00
zeripath
ce69882180 Fix issue with docker-rootless shimming script (#18690) (#18699)
Backport #18690

There is a problem with the current shimming script in that it will double quote the
provided GITEA_APP_INI due to a mistake in the bash. Here we change this to use a bash array.

Fix https://gitea.com/gitea/helm-chart/issues/287

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-10 19:37:53 +08:00
silverwind
649abeda40 C preprocessor colors improvement (#18671) (#18696)
* C preprocessor colors improvement

Fixes #18670

* Update web_src/less/chroma/light.less

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>

* typo

missing semi

* add color for #include filenames

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>

Co-authored-by: Bruno Raoult <braoult@users.noreply.github.com>
Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-10 10:12:03 +08:00
Gusted
4cfd62cddf Let return correct perm (#18675) (#18689)
Backport of #18675
2022-02-09 20:19:48 +00:00
zeripath
38fc6c75f3 Restart zero worker if there is still work to do (#18658) (#18672)
* Restart zero worker if there is still work to do (#18658)

Backport #18658

It is possible for the zero worker to timeout before all the work is finished.
This may mean that work may take a long time to complete because a worker will only
be induced on repushing.

Also ensure that requested count is reset after pulls and push mirror sync requests and add some more trace logging to the queue push.

Fix #18607

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Update modules/queue/workerpool.go
2022-02-08 23:28:21 +02:00
wxiaoguang
8671602ba9 Backport: fix the missing i18n key for update checker (#18646) (#18665) 2022-02-08 11:03:47 +02:00
wxiaoguang
3d08e3a08c No longer show the db-downgrade SQL in production (#18654) 2022-02-07 15:07:11 +01:00
zeripath
d4a075d738 If rendering has failed due to a net.OpError stop rendering (#18642) (#18645)
Backport #18642

When a net.OpError occurs during rendering the underlying connection is essentially
dead and therefore attempting to render further data will only cause further errors.

Therefore in serverErrorInternal detect if the passed in error is an OpError and
if so do not attempt any further rendering.

Fix #18629

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-07 09:25:05 +08:00
255 changed files with 4978 additions and 2077 deletions

View File

@@ -13,12 +13,25 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
steps:
- name: deps-frontend
pull: always
image: node:16
pull: always
commands:
- make node_modules
- make deps-frontend
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: lint-frontend
image: node:16
@@ -27,36 +40,46 @@ steps:
depends_on: [deps-frontend]
- name: lint-backend
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: lint-backend-windows
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make golangci-lint vet
- make golangci-lint-windows vet
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
GOOS: windows
GOARCH: amd64
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: lint-backend-gogit
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: checks-frontend
image: node:16
@@ -65,11 +88,13 @@ steps:
depends_on: [deps-frontend]
- name: checks-backend
pull: always
image: golang:1.17
image: golang:1.18
commands:
- make checks-backend
depends_on: [lint-backend]
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: test-frontend
image: node:16
@@ -84,50 +109,62 @@ steps:
depends_on: [test-frontend]
- name: build-backend-no-gcc
pull: always
image: golang:1.16 # this step is kept as the lowest version of golang that we support
pull: always
environment:
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
commands:
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
depends_on: [checks-backend]
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-arm64
image: golang:1.17
image: golang:1.18
environment:
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: arm64
TAGS: bindata gogit
commands:
- make backend # test cross compile
- rm ./gitea # clean
depends_on: [checks-backend]
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-windows
image: golang:1.17
image: golang:1.18
environment:
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
GOOS: windows
GOARCH: amd64
TAGS: bindata gogit
commands:
- go build -o gitea_windows
depends_on: [checks-backend]
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-386
image: golang:1.17
image: golang:1.18
environment:
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: 386
commands:
- go build -o gitea_linux_386 # test if compatible with 32 bit
depends_on: [checks-backend]
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
---
kind: pipeline
@@ -147,21 +184,28 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
services:
- name: mysql
image: mysql:5.7
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test
- name: mysql8
image: mysql:8
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: testgitea
- name: mssql
image: mcr.microsoft.com/mssql/server:latest
pull: always
environment:
ACCEPT_EULA: Y
MSSQL_PID: Standard
@@ -169,14 +213,17 @@ services:
- name: ldap
image: gitea/test-openldap:latest
pull: always
- name: elasticsearch
image: elasticsearch:7.5.0
pull: always
environment:
discovery.type: single-node
image: elasticsearch:7.5.0
- name: minio
image: minio/minio:RELEASE.2021-03-12T00-00-47Z
pull: always
commands:
- minio server /data
environment:
@@ -186,6 +233,7 @@ services:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
@@ -193,30 +241,41 @@ steps:
exclude:
- pull_request
- name: tag-pre-condition
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: tag-pre-condition
image: drone/git
pull: always
commands:
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
- name: prepare-test-env
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
depends_on:
- prepare-test-env
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: unit-test
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -224,24 +283,31 @@ steps:
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata sqlite sqlite_unlock_notify
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: unit-test-gogit
pull: always
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-mysql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -249,14 +315,16 @@ steps:
commands:
- make test-mysql-migration integration-test-coverage
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
depends_on:
- build
depends_on: [build]
volumes:
- name: deps
path: /go
- name: test-mysql8
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -264,13 +332,15 @@ steps:
commands:
- timeout -s ABRT 40m make test-mysql8-migration test-mysql8
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on:
- build
depends_on: [build]
volumes:
- name: deps
path: /go
- name: test-mssql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
@@ -278,24 +348,24 @@ steps:
commands:
- make test-mssql-migration test-mssql
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on:
- build
depends_on: [build]
volumes:
- name: deps
path: /go
- name: generate-coverage
image: golang:1.17
image: golang:1.18
commands:
- make coverage
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata
depends_on:
- unit-test
- test-mysql
depends_on: [unit-test, test-mysql]
when:
branch:
- main
@@ -304,15 +374,14 @@ steps:
- pull_request
- name: coverage-codecov
image: woodpeckerci/plugin-codecov:next-alpine
pull: always
image: plugins/codecov
settings:
files:
- coverage.all
token:
from_secret: codecov_token
depends_on:
- generate-coverage
depends_on: [generate-coverage]
when:
branch:
- main
@@ -337,6 +406,10 @@ trigger:
- tag
- pull_request
volumes:
- name: deps
temp: {}
services:
- name: pgsql
pull: default
@@ -352,6 +425,7 @@ services:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
@@ -359,24 +433,35 @@ steps:
exclude:
- pull_request
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
pull: always
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on:
- prepare-test-env
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-sqlite
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
@@ -384,13 +469,15 @@ steps:
commands:
- timeout -s ABRT 40m make test-sqlite-migration test-sqlite
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
TEST_TAGS: gogit sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
depends_on:
- build
depends_on: [build]
volumes:
- name: deps
path: /go
- name: test-pgsql
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
@@ -398,14 +485,16 @@ steps:
commands:
- timeout -s ABRT 40m make test-pgsql-migration test-pgsql
environment:
GOPROXY: https://goproxy.cn
GOPROXY: https://goproxy.io
TAGS: bindata gogit
RACE_ENABLED: true
TEST_TAGS: gogit
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on:
- build
depends_on: [build]
volumes:
- name: deps
path: /go
---
kind: pipeline
@@ -425,8 +514,8 @@ trigger:
steps:
- name: download
pull: always
image: jonasfranz/crowdin
pull: always
settings:
download: true
export_dir: options/locale/
@@ -437,14 +526,14 @@ steps:
from_secret: crowdin_key
- name: update
pull: default
image: alpine:3.13
pull: always
commands:
- ./build/update-locales.sh
- name: push
pull: always
image: appleboy/drone-git-push
pull: always
settings:
author_email: "teabot@gitea.io"
author_name: GiteaBot
@@ -457,8 +546,8 @@ steps:
from_secret: git_push_ssh_key
- name: upload_translations
pull: always
image: jonasfranz/crowdin
pull: always
settings:
files:
locale_en-US.ini: options/locale/locale_en-US.ini
@@ -487,13 +576,14 @@ trigger:
steps:
- name: download
image: golang:1.17
image: golang:1.18
pull: always
commands:
- timeout -s ABRT 40m make generate-license generate-gitignore
- name: push
pull: always
image: appleboy/drone-git-push
pull: always
settings:
author_email: "teabot@gitea.io"
author_name: GiteaBot
@@ -529,26 +619,49 @@ depends_on:
- testing-amd64
- testing-arm64
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: static
- name: deps-frontend
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: static
image: techknowlogick/xgo:go-1.18.x
pull: always
image: techknowlogick/xgo:go-1.17.x
commands:
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
- export PATH=$PATH:$GOPATH/bin
- make release
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
volumes:
- name: deps
path: /go
- name: gpg-sign
pull: always
image: plugins/gpgsign:1
pull: always
settings:
detach_sign: true
excludes:
@@ -562,8 +675,8 @@ steps:
from_secret: gpgsign_passphrase
- name: release-branch
pull: always
image: woodpeckerci/plugin-s3:latest
pull: always
settings:
acl: public-read
bucket: gitea-artifacts
@@ -624,27 +737,50 @@ depends_on:
- testing-arm64
- testing-amd64
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
pull: default
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: static
- name: deps-frontend
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: static
image: techknowlogick/xgo:go-1.18.x
pull: always
image: techknowlogick/xgo:go-1.17.x
commands:
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
- export PATH=$PATH:$GOPATH/bin
- make release
environment:
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [fetch-tags]
volumes:
- name: deps
path: /go
- name: gpg-sign
pull: always
image: plugins/gpgsign:1
pull: always
settings:
detach_sign: true
excludes:
@@ -656,10 +792,11 @@ steps:
from_secret: gpgsign_key
GPGSIGN_PASSPHRASE:
from_secret: gpgsign_passphrase
depends_on: [static]
- name: release-tag
pull: always
image: woodpeckerci/plugin-s3:latest
pull: always
settings:
acl: public-read
bucket: gitea-artifacts
@@ -673,16 +810,19 @@ steps:
from_secret: aws_access_key_id
AWS_SECRET_ACCESS_KEY:
from_secret: aws_secret_access_key
depends_on: [gpg-sign]
- name: github
image: plugins/github-release:latest
pull: always
image: plugins/github-release:1
settings:
files:
- "dist/release/*"
file_exists: overwrite
environment:
GITHUB_TOKEN:
from_secret: github_token
depends_on: [gpg-sign]
---
kind: pipeline
@@ -704,16 +844,16 @@ trigger:
steps:
- name: build-docs
pull: always
image: plugins/hugo:latest
pull: always
commands:
- apk add --no-cache make bash curl
- cd docs
- make trans-copy clean build
- name: publish-docs
pull: always
image: techknowlogick/drone-netlify:latest
pull: always
settings:
path: docs/public/
site_id: d2260bae-7861-4c02-8646-8f6440b12672
@@ -749,18 +889,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -778,7 +919,7 @@ steps:
auto_tag_suffix: linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -811,18 +952,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: dev-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -840,7 +982,7 @@ steps:
tags: dev-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -872,18 +1014,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -901,7 +1044,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -929,14 +1072,14 @@ trigger:
steps:
- name: dryrun
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
dry_run: true
repo: gitea/gitea
tags: linux-arm64
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
@@ -967,18 +1110,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: true
auto_tag_suffix: linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -996,7 +1140,7 @@ steps:
auto_tag_suffix: linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -1029,18 +1173,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: dev-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -1058,7 +1203,7 @@ steps:
tags: dev-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -1090,18 +1235,19 @@ trigger:
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
pull: always
image: techknowlogick/drone-docker:latest
pull: always
settings:
auto_tag: false
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -1119,7 +1265,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.cn
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
@@ -1140,8 +1286,8 @@ platform:
steps:
- name: manifest-rootless
pull: always
image: plugins/manifest
pull: always
settings:
auto_tag: true
ignore_missing: true
@@ -1186,6 +1332,7 @@ steps:
- name: manifest-rootless
pull: always
image: plugins/manifest
pull: always
settings:
auto_tag: false
ignore_missing: true
@@ -1260,8 +1407,8 @@ depends_on:
steps:
- name: discord
pull: always
image: appleboy/drone-discord:1.2.4
pull: always
settings:
message: "{{#success build.status}} ✅ Build #{{build.number}} of `{{repo.name}}` succeeded.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{else}} ❌ Build #{{build.number}} of `{{repo.name}}` failed.\n\n📝 Commit by {{commit.author}} on `{{commit.branch}}`:\n``` {{commit.message}} ```\n\n🌐 {{ build.link }} {{/success}}\n"
webhook_id:

2
.gitignore vendored
View File

@@ -36,6 +36,8 @@ _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

View File

@@ -13,7 +13,7 @@ linters:
#- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
- gofmt
- misspell
- gocritic
#- gocritic # TODO: disabled until fixed with go 1.18
- bidichk
- ineffassign
- revive
@@ -22,7 +22,11 @@ linters:
fast: false
run:
timeout: 3m
timeout: 10m
skip-dirs:
- node_modules
- public
- web_src
linters-settings:
gocritic:
@@ -57,6 +61,9 @@ linters-settings:
- name: errorf
- name: duplicated-imports
- name: modifies-value-receiver
gofumpt:
extra-rules: true
lang-version: 1.18
issues:
exclude-rules:
@@ -144,3 +151,11 @@ issues:
- path: models/user/openid.go
linters:
- golint
- linters: staticcheck
text: "strings.Title is deprecated: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead."
- linters: staticcheck
text: "util.FindClosure is deprecated: This function can not handle newlines. Many elements can be existed over multiple lines(e.g. link labels). Use text.Reader.FindClosure."
- linters: staticcheck
text: "gossh.SigAlgoRSASHA2256 is deprecated: use KeyAlgoRSASHA256."
- linters: staticcheck
text: "gossh.SigAlgoRSASHA2512 is deprecated: use KeyAlgoRSASHA512."

View File

@@ -4,6 +4,194 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.16.7](https://github.com/go-gitea/gitea/releases/tag/v1.16.7) - 2022-05-02
* SECURITY
* Escape git fetch remote (#19487) (#19490)
* BUGFIXES
* Don't overwrite err with nil (#19572) (#19574)
* On Migrations, only write commit-graph if wiki clone was successful (#19563) (#19568)
* Respect DefaultUserIsRestricted system default when creating new user (#19310) (#19560)
* Don't error when branch's commit doesn't exist (#19547) (#19548)
* Support `hostname:port` to pass host matcher's check (#19543) (#19544)
* Prevent intermittent race in attribute reader close (#19537) (#19539)
* Fix 64-bit atomic operations on 32-bit machines (#19531) (#19532)
* Prevent dangling archiver goroutine (#19516) (#19526)
* Fix migrate release from github (#19510) (#19523)
* When view _Siderbar or _Footer, just display once (#19501) (#19522)
* Fix blame page select range error and some typos (#19503)
* Fix name of doctor fix "authorized-keys" in hints (#19464) (#19484)
* User specific repoID or xorm builder conditions for issue search (#19475) (#19476)
* Prevent dangling cat-file calls (goroutine alternative) (#19454) (#19466)
* RepoAssignment ensure to close before overwrite (#19449) (#19460)
* Set correct PR status on 3way on conflict checking (#19457) (#19458)
* Mark TemplateLoading error as "UnprocessableEntity" (#19445) (#19446)
## [1.16.6](https://github.com/go-gitea/gitea/releases/tag/v1.16.6) - 2022-04-20
* ENHANCEMENTS
* Only request write when necessary (#18657) (#19422)
* Disable service worker by default (#18914) (#19342)
* BUGFIXES
* When dumping trim the standard suffices instead of a random suffix (#19440) (#19447)
* Fix DELETE request for non-existent public key (#19443) (#19444)
* Don't panic on ErrEmailInvalid (#19441) (#19442)
* Add uploadpack.allowAnySHA1InWant to allow --filter=blob:none with older git clients (#19430) (#19438)
* Warn on SSH connection for incorrect configuration (#19317) (#19437)
* Search Issues via API, dont show 500 if filter result in empty list (#19244) (#19436)
* When updating mirror repo intervals by API reschedule next update too (#19429) (#19433)
* Fix nil error when some pages are rendered outside request context (#19427) (#19428)
* Fix double blob-hunk on diff page (#19404) (#19405)
* Don't allow merging PR's which are being conflict checked (#19357) (#19358)
* Fix middleware function's placements (#19377) (#19378)
* Fix invalid CSRF token bug, make sure CSRF tokens can be up-to-date (#19338)
* Restore user autoregistration with email addresses (#19261) (#19312)
* Move checks for pulls before merge into own function (#19271) (#19277)
* Granular webhook events in editHook (#19251) (#19257)
* Only send webhook events to active system webhooks and only deliver to active hooks (#19234) (#19248)
* Use full output of git show-ref --tags to get tags for PushUpdateAddTag (#19235) (#19236)
* Touch mirrors on even on fail to update (#19217) (#19233)
* Hide sensitive content on admin panel progress monitor (#19218 & #19226) (#19231)
* Fix clone url JS error for the empty repo page (#19209)
* Bump goldmark to v1.4.11 (#19201) (#19203)
* TESTING
* Prevent intermittent failures in RepoIndexerTest (#19225 #19229) (#19228)
* BUILD
* Revert the minimal golang version requirement from 1.17 to 1.16 and add a warning in Makefile (#19319)
* MISC
* Performance improvement for add team user when org has more than 1000 repositories (#19227) (#19289)
* Check go and nodejs version by go.mod and package.json (#19197) (#19254)
## [1.16.5](https://github.com/go-gitea/gitea/releases/tag/v1.16.5) - 2022-03-23
* BREAKING
* Bump to build with go1.18 (#19120 et al) (#19127)
* SECURITY
* Prevent redirect to Host (2) (#19175) (#19186)
* Try to prevent autolinking of displaynames by email readers (#19169) (#19183)
* Clean paths when looking in Storage (#19124) (#19179)
* Do not send notification emails to inactive users (#19131) (#19139)
* Do not send activation email if manual confirm is set (#19119) (#19122)
* ENHANCEMENTS
* Use the new/choose link for New Issue on project page (#19172) (#19176)
* BUGFIXES
* Fix showing issues in your repositories (#18916) (#19191)
* Fix compare link in active feeds for new branch (#19149) (#19185)
* Redirect .wiki/* ui link to /wiki (#18831) (#19184)
* Ensure deploy keys with write access can push (#19010) (#19182)
* Ensure that setting.LocalURL always has a trailing slash (#19171) (#19177)
* Cleanup protected branches when deleting users & teams (#19158) (#19174)
* Use IterateBufferSize whilst querying repositories during adoption check (#19140) (#19160)
* Fix NPE /repos/issues/search when not signed in (#19154) (#19155)
* Use custom favicon when viewing static files if it exists (#19130) (#19152)
* Fix the editor height in review box (#19003) (#19147)
* Ensure isSSH is set whenever DISABLE_HTTP_GIT is set (#19028) (#19146)
* Fix wrong scopes caused by empty scope input (#19029) (#19145)
* Make migrations SKIP_TLS_VERIFY apply to git too (#19132) (#19141)
* Handle email address not exist (#19089) (#19121)
* MISC
* Update json-iterator to allow compilation with go1.18 (#18644) (#19100)
* Update golang.org/x/crypto (#19097) (#19098)
## [1.16.4](https://github.com/go-gitea/gitea/releases/tag/v1.16.4) - 2022-03-14
* SECURITY
* Restrict email address validation (#17688) (#19085)
* Fix lfs bug (#19072) (#19080)
* ENHANCEMENTS
* Improve SyncMirrors logging (#19045) (#19050)
* BUGFIXES
* Refactor mirror code & fix `StartToMirror` (#18904) (#19075)
* Update the webauthn_credential_id_sequence in Postgres (#19048) (#19060)
* Prevent 500 when there is an error during new auth source post (#19041) (#19059)
* If rendering has failed due to a net.OpError stop rendering (attempt 2) (#19049) (#19056)
* Fix flag validation (#19046) (#19051)
* Add pam account authorization check (#19040) (#19047)
* Ignore missing comment for user notifications (#18954) (#19043)
* Set `rel="nofollow noindex"` on new issue links (#19023) (#19042)
* Upgrading binding package (#19034) (#19035)
* Don't show context cancelled errors in attribute reader (#19006) (#19027)
* Fix update hint bug (#18996) (#19002)
* MISC
* Fix potential assignee query for repo (#18994) (#18999)
## [1.16.3](https://github.com/go-gitea/gitea/releases/tag/v1.16.3) - 2022-03-02
* SECURITY
* Git backend ignore replace objects (#18979) (#18980)
* ENHANCEMENTS
* Adjust error for already locked db and prevent level db lock on malformed connstr (#18923) (#18938)
* BUGFIXES
* Set max text height to prevent overflow (#18862) (#18977)
* Fix newAttachmentPaths deletion for DeleteRepository() (#18973) (#18974)
* Accounts with WebAuthn only (no TOTP) now exist ... fix code to handle that case (#18897) (#18964)
* Send 404 on `/{org}.gpg` (#18959) (#18962)
* Fix admin user list pagination (#18957) (#18960)
* Fix lfs management setting (#18947) (#18946)
* Fix login with email panic when email is not exist (#18942)
* Update go-org to v1.6.1 (#18932) (#18933)
* Fix `<strong>` html in translation (#18929) (#18931)
* Fix page and missing return on unadopted repos API (#18848) (#18927)
* Allow adminstrator teams members to see other teams (#18918) (#18919)
* Don't treat BOM escape sequence as hidden character. (#18909) (#18910)
* Correctly link URLs to users/repos with dashes, dots or underscores (… (#18908)
* Fix redirect when using lowercase repo name (#18775) (#18902)
* Fix migration v210 (#18893) (#18892)
* Fix team management UI (#18887) (18886)
* BeforeSourcePath should point to base commit (#18880) (#18799)
* TRANSLATION
* Backport locales from master (#18944)
* MISC
* Don't update email for organisation (#18905) (#18906)
## [1.16.2](https://github.com/go-gitea/gitea/releases/tag/v1.16.2) - 2022-02-24
* ENHANCEMENTS
* Show fullname on issue edits and gpg/ssh signing info (#18828)
* Immediately Hammer if second kill is sent (#18823) (#18826)
* Allow mermaid render error to wrap (#18791)
* BUGFIXES
* Fix ldap user sync missed email in email_address table (#18786) (#18876)
* Update assignees check to include any writing team and change org sidebar (#18680) (#18873)
* Don't report signal: killed errors in serviceRPC (#18850) (#18865)
* Fix bug where certain LDAP settings were reverted (#18859)
* Update go-org to 1.6.0 (#18824) (#18839)
* Fix login with email for ldap users (#18800) (#18836)
* Fix bug for get user by email (#18834)
* Fix panic in EscapeReader (#18820) (#18821)
* Fix ldap loginname (#18789) (#18804)
* Remove redundant call to UpdateRepoStats during migration (#18591) (#18794)
* In disk_channel queues synchronously push to disk on shutdown (#18415) (#18788)
* Fix template bug of LFS lock (#18784) (#18787)
* Attempt to fix the webauthn migration again - part 3 (#18770) (#18771)
* Send mail to issue/pr assignee/reviewer also when OnMention is set (#18707) (#18765)
* Fix a broken link in commits_list_small.tmpl (#18763) (#18764)
* Increase the size of the webauthn_credential credential_id field (#18739) (#18756)
* Prevent dangling GetAttribute calls (#18754) (#18755)
* Fix isempty detection of git repository (#18746) (#18750)
* Fix source code line highlighting on external tracker (#18729) (#18740)
* Prevent double encoding of branch names in delete branch (#18714) (#18738)
* Always set PullRequestWorkInProgressPrefixes in PrepareViewPullInfo (#18713) (#18737)
* Fix forked repositories missed tags (#18719) (#18735)
* Fix release typo (#18728) (#18731)
* Separate the details links of commit-statuses in headers (#18661) (#18730)
* Update object repo with the migrated repository (#18684) (#18726)
* Fix bug for version update hint (#18701) (#18705)
* Fix issue with docker-rootless shimming script (#18690) (#18699)
* Let `MinUnitAccessMode` return correct perm (#18675) (#18689)
* Prevent security failure due to bad APP_ID (#18678) (#18682)
* Restart zero worker if there is still work to do (#18658) (#18672)
* If rendering has failed due to a net.OpError stop rendering (#18642) (#18645)
* TESTING
* Ensure git tag tests and others create test repos in tmpdir (#18447) (#18767)
* BUILD
* Reduce CI go module downloads, add make targets (#18708, #18475, #18443) (#18741)
* MISC
* Put buttons back in org dashboard (#18817) (#18825)
* Various Mermaid improvements (#18776) (#18780)
* C preprocessor colors improvement (#18671) (#18696)
* Fix the missing i18n key for update checker (#18646) (#18665)
## [1.16.1](https://github.com/go-gitea/gitea/releases/tag/v1.16.1) - 2022-02-06
* SECURITY

View File

@@ -1,7 +1,5 @@
###################################
#Build stage - temporarily using techknowlogick image until we upgrade to latest official alpine/go image
FROM techknowlogick/go:1.17-alpine3.13 AS build-env
#Build stage
FROM golang:1.18-alpine3.15 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}

View File

@@ -1,7 +1,5 @@
###################################
#Build stage - temporarily using techknowlogick image until we upgrade to latest official alpine/go image
FROM techknowlogick/go:1.17-alpine3.13 AS build-env
#Build stage
FROM golang:1.18-alpine3.15 AS build-env
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}

127
Makefile
View File

@@ -24,10 +24,17 @@ SHASUM ?= shasum -a 256
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
COMMA := ,
XGO_VERSION := go-1.17.x
MIN_GO_VERSION := 001016000
MIN_NODE_VERSION := 012017000
MIN_GOLANGCI_LINT_VERSION := 001043000
XGO_VERSION := go-1.18.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.29.0
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.4.0
ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.0
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.3.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.44.2
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.29.0
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest
@@ -125,8 +132,6 @@ ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
GO_SOURCES += $(BINDATA_DEST)
endif
#To update swagger use: GO111MODULE=on go get -u github.com/go-swagger/go-swagger/cmd/swagger
SWAGGER := $(GO) run github.com/go-swagger/go-swagger/cmd/swagger
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
@@ -166,6 +171,9 @@ help:
@echo " - watch-backend watch backend files and continuously rebuild"
@echo " - clean delete backend and integration files"
@echo " - clean-all delete backend, frontend and integration files"
@echo " - deps install dependencies"
@echo " - deps-frontend install frontend dependencies"
@echo " - deps-backend install backend dependencies"
@echo " - lint lint everything"
@echo " - lint-frontend lint frontend files"
@echo " - lint-backend lint backend files"
@@ -193,10 +201,15 @@ help:
.PHONY: go-check
go-check:
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9.]+' | tr '.' ' ');))
$(eval MIN_GO_VERSION_STR := $(shell grep -Eo '^go\s+[0-9]+\.[0-9.]+' go.mod | cut -d' ' -f2))
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
$(eval GO_VERSION_STR := $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9.]+'))
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell echo '$(GO_VERSION_STR)' | tr '.' ' ')))
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
echo "Gitea requires Go 1.16 or greater to build. You can get it at https://golang.org/dl/"; \
echo "Gitea requires Go $(MIN_GO_VERSION_STR) or greater to build, but $(GO_VERSION) was found. You can get an updated version at https://go.dev/dl/"; \
exit 1; \
else \
echo "WARNING: Please ensure Go $(GO_VERSION_STR) is still maintained to avoid possible security problems. You can check it at https://go.dev/dl/"; \
fi
.PHONY: git-check
@@ -208,11 +221,12 @@ git-check:
.PHONY: node-check
node-check:
$(eval MIN_NODE_VERSION_STR := $(shell grep -Eo '"node":.*[0-9.]+"' package.json | sed -n 's/.*[^0-9.]\([0-9.]*\)"/\1/p'))
$(eval MIN_NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell echo '$(MIN_NODE_VERSION_STR)' | tr '.' ' ')))
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
$(eval MIN_NODE_VER_FMT := $(shell printf "%g.%g.%g" $(shell echo $(MIN_NODE_VERSION) | grep -o ...)))
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
echo "Gitea requires Node.js $(MIN_NODE_VER_FMT) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
echo "Gitea requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
exit 1; \
fi
@@ -231,8 +245,8 @@ clean:
.PHONY: fmt
fmt:
@echo "Running gitea-fmt(with gofmt)..."
@$(GO) run build/code-batch-process.go gitea-fmt -s -w '{file-list}'
@echo "Running gitea-fmt (with gofumpt)..."
@MISSPELL_PACKAGE=$(MISSPELL_PACKAGE) GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
.PHONY: vet
vet:
@@ -251,7 +265,7 @@ endif
.PHONY: generate-swagger
generate-swagger:
$(SWAGGER) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
$(GO) run $(SWAGGER_PACKAGE) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
@@ -267,21 +281,18 @@ swagger-check: generate-swagger
.PHONY: swagger-validate
swagger-validate:
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
$(SWAGGER) validate './$(SWAGGER_SPEC)'
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
.PHONY: errcheck
errcheck:
@hash errcheck > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install github.com/kisielk/errcheck@8ddee489636a8311a376fc92e27a6a13c6658344; \
fi
@echo "Running errcheck..."
@errcheck $(GO_PACKAGES)
$(GO) run $(ERRCHECK_PACKAGE) $(GO_PACKAGES)
.PHONY: fmt-check
fmt-check:
# get all go files and run gitea-fmt (with gofmt) on them
@diff=$$($(GO) run build/code-batch-process.go gitea-fmt -s -d '{file-list}'); \
@diff=$$(MISSPELL_PACKAGE=$(MISSPELL_PACKAGE) GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -l '{file-list}'); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
@@ -320,10 +331,7 @@ watch-frontend: node-check node_modules
.PHONY: watch-backend
watch-backend: go-check
@hash air > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install github.com/cosmtrek/air@bedc18201271882c2be66d216d0e1a275b526ec4; \
fi
air -c .air.toml
$(GO) run $(AIR_PACKAGE) -c .air.toml
.PHONY: test
test: test-frontend test-backend
@@ -396,6 +404,11 @@ test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test
.PHONY: test-sqlite-migration\#%
test-sqlite-migration\#%: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./migrations.individual.sqlite.test -test.run $(subst .,/,$*)
generate-ini-mysql:
sed -e 's|{{TEST_MYSQL_HOST}}|${TEST_MYSQL_HOST}|g' \
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
@@ -591,12 +604,9 @@ $(DIST_DIRS):
.PHONY: release-windows
release-windows: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install src.techknowlogick.com/xgo@latest; \
fi
CGO_CFLAGS="$(CGO_CFLAGS)" xgo -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo 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 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
ifeq (,$(findstring gogit,$(TAGS)))
CGO_CFLAGS="$(CGO_CFLAGS)" xgo -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo 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 'netgo osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
endif
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
@@ -604,20 +614,14 @@ endif
.PHONY: release-linux
release-linux: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install src.techknowlogick.com/xgo@latest; \
fi
CGO_CFLAGS="$(CGO_CFLAGS)" xgo -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 '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
.PHONY: release-darwin
release-darwin: | $(DIST_DIRS)
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install src.techknowlogick.com/xgo@latest; \
fi
CGO_CFLAGS="$(CGO_CFLAGS)" xgo -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 '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
@@ -632,10 +636,7 @@ release-check: | $(DIST_DIRS)
.PHONY: release-compress
release-compress: | $(DIST_DIRS)
@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install github.com/ulikunitz/xz/cmd/gxz@v0.5.10; \
fi
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done;
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done;
.PHONY: release-sources
release-sources: | $(DIST_DIRS)
@@ -656,6 +657,25 @@ docs:
fi
cd docs; make trans-copy clean build-offline;
.PHONY: deps
deps: deps-frontend deps-backend
.PHONY: deps-frontend
deps-frontend: node_modules
.PHONY: deps-backend
deps-backend:
$(GO) mod download
$(GO) install $(AIR_PACKAGE)
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
$(GO) install $(ERRCHECK_PACKAGE)
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(GXZ_PAGAGE)
$(GO) install $(MISSPELL_PACKAGE)
$(GO) install $(SWAGGER_PACKAGE)
$(GO) install $(XGO_PACKAGE)
node_modules: package-lock.json
npm install --no-save
@touch node_modules
@@ -748,22 +768,19 @@ pr\#%: clean-all
$(GO) run contrib/pr/checkout.go $*
.PHONY: golangci-lint
golangci-lint: golangci-lint-check
golangci-lint run --timeout 10m
golangci-lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
.PHONY: golangci-lint-check
golangci-lint-check:
$(eval GOLANGCI_LINT_VERSION := $(shell printf "%03d%03d%03d" $(shell golangci-lint --version | grep -Eo '[0-9]+\.[0-9.]+' | tr '.' ' ');))
$(eval MIN_GOLANGCI_LINT_VER_FMT := $(shell printf "%g.%g.%g" $(shell echo $(MIN_GOLANGCI_LINT_VERSION) | grep -o ...)))
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
echo "Downloading golangci-lint v${MIN_GOLANGCI_LINT_VER_FMT}"; \
export BINARY="golangci-lint"; \
curl -sfL "https://raw.githubusercontent.com/golangci/golangci-lint/v${MIN_GOLANGCI_LINT_VER_FMT}/install.sh" | sh -s -- -b $(GOPATH)/bin v$(MIN_GOLANGCI_LINT_VER_FMT); \
elif [ "$(GOLANGCI_LINT_VERSION)" -lt "$(MIN_GOLANGCI_LINT_VERSION)" ]; then \
echo "Downloading newer version of golangci-lint v${MIN_GOLANGCI_LINT_VER_FMT}"; \
export BINARY="golangci-lint"; \
curl -sfL "https://raw.githubusercontent.com/golangci/golangci-lint/v${MIN_GOLANGCI_LINT_VER_FMT}/install.sh" | sh -s -- -b $(GOPATH)/bin v$(MIN_GOLANGCI_LINT_VER_FMT); \
fi
# workaround step for the lint-backend-windows CI task because 'go run' can not
# have distinct GOOS/GOARCH for its build and run steps
.PHONY: golangci-lint-windows
golangci-lint-windows:
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
golangci-lint run
.PHONY: editorconfig-checker
editorconfig-checker:
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates
.PHONY: docker
docker:

View File

@@ -73,7 +73,7 @@ or if SQLite support is required:
The `build` target is split into two sub-targets:
- `make backend` which requires [Go 1.16](https://golang.org/dl/) or greater.
- `make backend` which requires [Go 1.17](https://go.dev/dl/) or greater.
- `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater and Internet connectivity to download npm dependencies.
When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js and Internet connectivity.

View File

@@ -40,7 +40,7 @@ func passThroughCmd(cmd string, args []string) error {
}
c := exec.Cmd{
Path: foundCmd,
Args: args,
Args: append([]string{cmd}, args...),
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
@@ -270,9 +270,10 @@ func main() {
if containsString(subArgs, "-w") {
cmdErrors = append(cmdErrors, giteaFormatGoImports(files))
}
cmdErrors = append(cmdErrors, passThroughCmd("gofmt", substArgs))
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-l"), containsString(subArgs, "-w")))
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", "1.17"}, substArgs...)))
case "misspell":
cmdErrors = append(cmdErrors, passThroughCmd("misspell", substArgs))
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("MISSPELL_PACKAGE")}, substArgs...)))
default:
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
}

View File

@@ -25,6 +25,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/auth/source/smtp"
@@ -113,6 +114,10 @@ var (
Name: "access-token",
Usage: "Generate access token for the user",
},
cli.BoolFlag{
Name: "restricted",
Usage: "Make a restricted user account",
},
},
}
@@ -537,17 +542,26 @@ func runCreateUser(c *cli.Context) error {
changePassword = c.Bool("must-change-password")
}
restricted := util.OptionalBoolNone
if c.IsSet("restricted") {
restricted = util.OptionalBoolOf(c.Bool("restricted"))
}
u := &user_model.User{
Name: username,
Email: c.String("email"),
Passwd: password,
IsActive: true,
IsAdmin: c.Bool("admin"),
MustChangePassword: changePassword,
Theme: setting.UI.DefaultTheme,
}
if err := user_model.CreateUser(u); err != nil {
overwriteDefault := &user_model.CreateUserOverwriteOptions{
IsActive: util.OptionalBoolTrue,
IsRestricted: restricted,
}
if err := user_model.CreateUser(u, overwriteDefault); err != nil {
return fmt.Errorf("CreateUser: %v", err)
}

View File

@@ -31,7 +31,7 @@ func argsSet(c *cli.Context, args ...string) error {
return errors.New(a + " is not set")
}
if util.IsEmptyString(a) {
if util.IsEmptyString(c.String(a)) {
return errors.New(a + " is required")
}
}

View File

@@ -86,7 +86,7 @@ func (o outputType) String() string {
}
var outputTypeEnum = &outputType{
Enum: []string{"zip", "rar", "tar", "sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4"},
Enum: []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4"},
Default: "zip",
}
@@ -160,7 +160,12 @@ func runDump(ctx *cli.Context) error {
fatal("Deleting default logger failed. Can not write to stdout: %v", err)
}
} else {
fileName = strings.TrimSuffix(fileName, path.Ext(fileName))
for _, suffix := range outputTypeEnum.Enum {
if strings.HasSuffix(fileName, "."+suffix) {
fileName = strings.TrimSuffix(fileName, "."+suffix)
break
}
}
fileName += "." + outType
}
setting.LoadFromExisting()

View File

@@ -185,7 +185,7 @@ Gitea or set your environment appropriately.`, "")
reponame := os.Getenv(models.EnvRepoName)
userID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
prID, _ := strconv.ParseInt(os.Getenv(models.EnvPRID), 10, 64)
isDeployKey, _ := strconv.ParseBool(os.Getenv(models.EnvIsDeployKey))
deployKeyID, _ := strconv.ParseInt(os.Getenv(models.EnvDeployKeyID), 10, 64)
hookOptions := private.HookOptions{
UserID: userID,
@@ -194,7 +194,7 @@ Gitea or set your environment appropriately.`, "")
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
GitPushOptions: pushOptions(),
PullRequestID: prID,
IsDeployKey: isDeployKey,
DeployKeyID: deployKeyID,
}
scanner := bufio.NewScanner(os.Stdin)

View File

@@ -243,7 +243,7 @@ func runServ(c *cli.Context) error {
os.Setenv(models.EnvPusherID, strconv.FormatInt(results.UserID, 10))
os.Setenv(models.EnvRepoID, strconv.FormatInt(results.RepoID, 10))
os.Setenv(models.EnvPRID, fmt.Sprintf("%d", 0))
os.Setenv(models.EnvIsDeployKey, fmt.Sprintf("%t", results.IsDeployKey))
os.Setenv(models.EnvDeployKeyID, fmt.Sprintf("%d", results.DeployKeyID))
os.Setenv(models.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
os.Setenv(models.EnvAppURL, setting.AppURL)
@@ -297,6 +297,15 @@ func runServ(c *cli.Context) error {
gitcmd = exec.CommandContext(ctx, verb, repoPath)
}
// Check if setting.RepoRootPath exists. It could be the case that it doesn't exist, this can happen when
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
if _, err := os.Stat(setting.RepoRootPath); err != nil {
if os.IsNotExist(err) {
return fail("Incorrect configuration.",
"Directory `[repository]` `ROOT` was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository]` `ROOT` an absolute value.")
}
}
gitcmd.Dir = setting.RepoRootPath
gitcmd.Stdout = os.Stdout
gitcmd.Stdin = os.Stdin

View File

@@ -33,10 +33,8 @@ for i in "$@"; do
done
if [ -z "$APP_INI_SET" ]; then
CONF_ARG="-c \"$APP_INI\""
CONF_ARG=("-c" "${GITEA_APP_INI:-$APP_INI}")
fi
# Provide FHS compliant defaults
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" $CONF_ARG "$@"
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" "${CONF_ARG[@]}" "$@"

View File

@@ -1075,7 +1075,7 @@ PATH =
;SEARCH_REPO_DESCRIPTION = true
;;
;; Whether to enable a Service Worker to cache frontend assets
;USE_SERVICE_WORKER = true
;USE_SERVICE_WORKER = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@@ -32,11 +32,9 @@ for i in "$@"; do
done
if [ -z "$APP_INI_SET" ]; then
CONF_ARG="-c \"${GITEA_APP_INI:-$APP_INI}\""
CONF_ARG=("-c" "${GITEA_APP_INI:-$APP_INI}")
fi
# Provide docker defaults
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" $CONF_ARG "$@"
GITEA_WORK_DIR="${GITEA_WORK_DIR:-$WORK_DIR}" exec -a "$0" "$GITEA" "${CONF_ARG[@]}" "$@"

View File

@@ -18,9 +18,9 @@ params:
description: Git with a cup of tea
author: The Gitea Authors
website: https://docs.gitea.io
version: 1.16.0
version: 1.16.4
minGoVersion: 1.16
goVersion: 1.17
goVersion: 1.18
minNodeVersion: 12.17
outputs:

View File

@@ -189,7 +189,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
add it to this config.
- `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
- `USE_SERVICE_WORKER`: **true**: Whether to enable a Service Worker to cache frontend assets.
- `USE_SERVICE_WORKER`: **false**: Whether to enable a Service Worker to cache frontend assets.
### UI - Admin (`ui.admin`)

View File

@@ -42,7 +42,7 @@ To maintain understandable code and avoid circular dependencies it is important
- `modules/setting`: Store all system configurations read from ini files and has been referenced by everywhere. But they should be used as function parameters when possible.
- `modules/git`: Package to interactive with `Git` command line or Gogit package.
- `public`: Compiled frontend files (javascript, images, css, etc.)
- `routers`: Handling of server requests. As it uses other Gitea packages to serve the request, other packages (models, modules or services) shall not depend on routers.
- `routers`: Handling of server requests. As it uses other Gitea packages to serve the request, other packages (models, modules or services) must not depend on routers.
- `routers/api` Contains routers for `/api/v1` aims to handle RESTful API requests.
- `routers/install` Could only respond when system is in INSTALL mode (INSTALL_LOCK=false).
- `routers/private` will only be invoked by internal sub commands, especially `serv` and `hooks`.
@@ -106,10 +106,20 @@ i.e. `servcies/user`, `models/repository`.
Since there are some packages which use the same package name, it is possible that you find packages like `modules/user`, `models/user`, and `services/user`. When these packages are imported in one Go file, it's difficult to know which package we are using and if it's a variable name or an import name. So, we always recommend to use import aliases. To differ from package variables which are commonly in camelCase, just use **snake_case** for import aliases.
i.e. `import user_service "code.gitea.io/gitea/services/user"`
### Important Gotchas
- Never write `x.Update(exemplar)` without an explicit `WHERE` clause:
- This will cause all rows in the table to be updated with the non-zero values of the exemplar - including IDs.
- You should usually write `x.ID(id).Update(exemplar)`.
- If during a migration you are inserting into a table using `x.Insert(exemplar)` where the ID is preset:
- You will need to ``SET IDENTITY_INSERT `table` ON`` for the MSSQL variant (the migration will fail otherwise)
- However, you will also need to update the id sequence for postgres - the migration will silently pass here but later insertions will fail:
``SELECT setval('table_name_id_seq', COALESCE((SELECT MAX(id)+1 FROM `table_name`), 1), false)``
### Future Tasks
Currently, we are creating some refactors to do the following things:
- Correct that codes which doesn't follow the rules.
- There are too many files in `models`, so we are moving some of them into a sub package `models/xxx`.
- Some `modules` sub packages should be moved to `services` because they depends on `models`.
- Some `modules` sub packages should be moved to `services` because they depend on `models`.

View File

@@ -185,8 +185,6 @@ Before committing, make sure the linters pass:
make lint-frontend
```
Note: When working on frontend code, set `USE_SERVICE_WORKER` to `false` in `app.ini` to prevent undesirable caching of frontend assets.
### Building and adding SVGs
SVG icons are built using the `make svg` target which compiles the icon sources defined in `build/generate-svg.js` into the output directory `public/img/svg`. Custom icons can be added in the `web_src/svg` directory.

View File

@@ -43,7 +43,7 @@ Vous devriez avoir une instance fonctionnelle de Gitea. Pour accèder à l'inter
## Named Volumes
Ce guide aboutira à une installation avec les données Gita et PostgreSQL stockées dans des volumes nommés. Cela permet une sauvegarde, une restauration et des mises à niveau en toute simplicité.
Ce guide aboutira à une installation avec les données Gitea et PostgreSQL stockées dans des volumes nommés. Cela permet une sauvegarde, une restauration et des mises à niveau en toute simplicité.
### The Database

152
go.mod
View File

@@ -3,31 +3,21 @@ module code.gitea.io/gitea
go 1.16
require (
cloud.google.com/go v0.78.0 // indirect
code.gitea.io/gitea-vet v0.2.1
code.gitea.io/sdk/gitea v0.15.1
gitea.com/go-chi/binding v0.0.0-20211013065440-d16dc407c2be
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb
gitea.com/go-chi/cache v0.0.0-20211013020926-78790b11abf1
gitea.com/go-chi/captcha v0.0.0-20211013065431-70641c1a35d5
gitea.com/go-chi/session v0.0.0-20211218221615-e3605d8b28b8
gitea.com/lunny/levelqueue v0.4.1
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/NYTimes/gziphandler v1.1.1
github.com/ProtonMail/go-crypto v0.0.0-20210705153151-cc34b1f6908b // indirect
github.com/PuerkitoBio/goquery v1.7.0
github.com/alecthomas/chroma v0.9.4
github.com/andybalholm/brotli v1.0.3 // indirect
github.com/andybalholm/cascadia v1.2.0 // indirect
github.com/blevesearch/bleve/v2 v2.3.0
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/caddyserver/certmagic v0.15.2
github.com/PuerkitoBio/goquery v1.8.0
github.com/alecthomas/chroma v0.10.0
github.com/blevesearch/bleve/v2 v2.3.1
github.com/caddyserver/certmagic v0.15.4
github.com/chi-middleware/proxy v1.1.1
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
github.com/couchbase/gomemcached v0.1.2 // indirect
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect
github.com/denisenkom/go-mssqldb v0.10.0
github.com/denisenkom/go-mssqldb v0.12.0
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
github.com/duo-labs/webauthn v0.0.0-20220122034320-81aea484c951
@@ -36,8 +26,7 @@ require (
github.com/emirpasic/gods v1.12.0
github.com/ethantkoenig/rupture v1.0.0
github.com/gliderlabs/ssh v0.3.3
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
github.com/go-chi/chi/v5 v5.0.4
github.com/go-chi/chi/v5 v5.0.7
github.com/go-chi/cors v1.2.0
github.com/go-enry/go-enry/v2 v2.7.1
github.com/go-git/go-billy/v5 v5.3.1
@@ -48,90 +37,68 @@ require (
github.com/go-swagger/go-swagger v0.27.0
github.com/go-testfixtures/testfixtures/v3 v3.6.1
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v4 v4.2.0
github.com/golang/snappy v0.0.4 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0
github.com/google/go-github/v39 v39.2.0
github.com/google/uuid v1.3.0
github.com/gorilla/feeds v1.1.1
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/sessions v1.2.1
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
github.com/hashicorp/go-version v1.3.1
github.com/hashicorp/go-version v1.4.0
github.com/hashicorp/golang-lru v0.5.4
github.com/huandu/xstrings v1.3.2
github.com/jaytaylor/html2text v0.0.0-20200412013138-3577fbdbcff7
github.com/json-iterator/go v1.1.11
github.com/json-iterator/go v1.1.12
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/kevinburke/ssh_config v1.1.0 // indirect
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
github.com/klauspost/compress v1.13.1
github.com/klauspost/compress v1.13.6
github.com/klauspost/cpuid/v2 v2.0.9
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/lib/pq v1.10.2
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
github.com/markbates/goth v1.68.0
github.com/mattn/go-isatty v0.0.13
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-sqlite3 v1.14.8
github.com/mholt/archiver/v3 v3.5.0
github.com/microcosm-cc/bluemonday v1.0.16
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.12
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/msteinert/pam v0.0.0-20201130170657-e61372126161
github.com/markbates/goth v1.69.0
github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-sqlite3 v1.14.12
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.18
github.com/minio/minio-go/v7 v7.0.23
github.com/msteinert/pam v1.0.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/niklasfasching/go-org v1.5.0
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/niklasfasching/go-org v1.6.2
github.com/oliamb/cutter v0.2.2
github.com/olivere/elastic/v7 v7.0.25
github.com/pelletier/go-toml v1.9.0 // indirect
github.com/pierrec/lz4/v4 v4.1.8 // indirect
github.com/olivere/elastic/v7 v7.0.31
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0
github.com/prometheus/client_golang v1.11.0
github.com/quasoft/websspi v1.0.0
github.com/rs/xid v1.3.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/prometheus/client_golang v1.12.1
github.com/quasoft/websspi v1.1.2
github.com/sergi/go-diff v1.2.0
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.0
github.com/tstranex/u2f v1.0.0
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/unknwon/com v1.0.1
github.com/unknwon/i18n v0.0.0-20210321134014-0ebbf2df1c44
github.com/unknwon/paginater v0.0.0-20200328080006-042474bd0eae
github.com/unrolled/render v1.4.0
github.com/urfave/cli v1.22.5
github.com/xanzy/go-gitlab v0.50.1
github.com/xanzy/go-gitlab v0.58.0
github.com/yohcop/openid-go v1.0.0
github.com/yuin/goldmark v1.4.0
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01
github.com/yuin/goldmark-meta v1.0.0
go.etcd.io/bbolt v1.3.6 // indirect
github.com/yuin/goldmark v1.4.11
github.com/yuin/goldmark-highlighting v0.0.0-20220208100518-594be1970594
github.com/yuin/goldmark-meta v1.1.0
go.jolheiser.com/hcaptcha v0.0.4
go.jolheiser.com/pwn v0.0.3
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9
golang.org/x/text v0.3.7
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect
golang.org/x/tools v0.1.0
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
golang.org/x/tools v0.1.9
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.62.0
gopkg.in/ini.v1 v1.66.2
gopkg.in/yaml.v2 v2.4.0
mvdan.cc/xurls/v2 v2.2.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
@@ -139,6 +106,55 @@ require (
xorm.io/xorm v1.2.5
)
require (
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bits-and-blooms/bitset v1.2.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/cloudflare/cfssl v1.6.1 // indirect
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
github.com/couchbase/gomemcached v0.1.2 // indirect
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
github.com/go-openapi/analysis v0.21.2 // indirect
github.com/go-openapi/errors v0.20.2 // indirect
github.com/go-openapi/runtime v0.21.1 // indirect
github.com/go-openapi/strfmt v0.21.1 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
github.com/kevinburke/ssh_config v1.1.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mholt/acmez v1.0.2 // indirect
github.com/miekg/dns v1.1.46 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/rs/xid v1.3.0 // indirect
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/spf13/afero v1.8.0 // indirect
github.com/spf13/cobra v1.3.0 // indirect
github.com/spf13/viper v1.10.1 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/xanzy/ssh-agent v0.3.1 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.mongodb.org/mongo-driver v1.8.2 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
)
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
replace github.com/markbates/goth v1.68.0 => github.com/zeripath/goth v1.68.1-0.20220109111530-754359885dce

873
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ func TestAPIPrivateServ(t *testing.T) {
results, err := private.ServCommand(ctx, 1, "user2", "repo1", perm.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
assert.Zero(t, results.DeployKeyID)
assert.Equal(t, int64(1), results.KeyID)
assert.Equal(t, "user2@localhost", results.KeyName)
assert.Equal(t, "user2", results.UserName)
@@ -70,7 +70,7 @@ func TestAPIPrivateServ(t *testing.T) {
results, err = private.ServCommand(ctx, 1, "user15", "big_test_public_1", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.False(t, results.IsDeployKey)
assert.Zero(t, results.DeployKeyID)
assert.Equal(t, int64(1), results.KeyID)
assert.Equal(t, "user2@localhost", results.KeyName)
assert.Equal(t, "user2", results.UserName)
@@ -92,7 +92,7 @@ func TestAPIPrivateServ(t *testing.T) {
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_1", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.NotZero(t, results.DeployKeyID)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)
@@ -129,7 +129,7 @@ func TestAPIPrivateServ(t *testing.T) {
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", perm.AccessModeRead, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.NotZero(t, results.DeployKeyID)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)
@@ -142,7 +142,7 @@ func TestAPIPrivateServ(t *testing.T) {
results, err = private.ServCommand(ctx, deployKey.KeyID, "user15", "big_test_private_2", perm.AccessModeWrite, "git-upload-pack", "")
assert.NoError(t, err)
assert.False(t, results.IsWiki)
assert.True(t, results.IsDeployKey)
assert.NotZero(t, results.DeployKeyID)
assert.Equal(t, deployKey.KeyID, results.KeyID)
assert.Equal(t, "test-deploy", results.KeyName)
assert.Equal(t, "user15", results.UserName)

View File

@@ -445,7 +445,6 @@ func TestAPIRepoTransfer(t *testing.T) {
expectedStatus int
}{
// Disclaimer for test story: "user1" is an admin, "user2" is normal user and part of in owner team of org "user3"
// Transfer to a user with teams in another org should fail
{ctxUserID: 1, newOwner: "user3", teams: &[]int64{5}, expectedStatus: http.StatusForbidden},
// Transfer to a user with non-existent team IDs should fail

View File

@@ -69,6 +69,12 @@ func TestAPIAddEmail(t *testing.T) {
Primary: false,
},
}, emails)
opts = api.CreateEmailOption{
Emails: []string{"notAEmail"},
}
req = NewRequestWithJSON(t, "POST", "/api/v1/user/emails?token="+token, &opts)
session.MakeRequest(t, req, http.StatusUnprocessableEntity)
}
func TestAPIDeleteEmail(t *testing.T) {

View File

@@ -112,6 +112,13 @@ func TestMain(m *testing.M) {
}
}
os.Unsetenv("GIT_AUTHOR_NAME")
os.Unsetenv("GIT_AUTHOR_EMAIL")
os.Unsetenv("GIT_AUTHOR_DATE")
os.Unsetenv("GIT_COMMITTER_NAME")
os.Unsetenv("GIT_COMMITTER_EMAIL")
os.Unsetenv("GIT_COMMITTER_DATE")
err := unittest.InitFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(filepath.Dir(setting.AppPath), "models/fixtures/"),

View File

@@ -83,7 +83,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mssql/data/sessions
[log]
MODE = test,file
ROOT_PATH = mssql-log
ROOT_PATH = {{REPO_TEST_DIR}}mssql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -101,7 +101,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mysql/data/sessions
[log]
MODE = test,file
ROOT_PATH = mysql-log
ROOT_PATH = {{REPO_TEST_DIR}}mysql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -80,7 +80,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-mysql8/data/sessions
[log]
MODE = test,file
ROOT_PATH = mysql8-log
ROOT_PATH = {{REPO_TEST_DIR}}mysql8-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -84,7 +84,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-pgsql/data/sessions
[log]
MODE = test,file
ROOT_PATH = pgsql-log
ROOT_PATH = {{REPO_TEST_DIR}}pgsql-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -25,6 +25,8 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/stretchr/testify/assert"
"github.com/unknwon/i18n"
@@ -65,7 +67,7 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
func TestPullMerge(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
hookTasks, err := webhook.HookTasks(1, 1) //Retrieve previous hook number
hookTasks, err := webhook.HookTasks(1, 1) // Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
@@ -87,7 +89,7 @@ func TestPullMerge(t *testing.T) {
func TestPullRebase(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
hookTasks, err := webhook.HookTasks(1, 1) //Retrieve previous hook number
hookTasks, err := webhook.HookTasks(1, 1) // Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
@@ -109,7 +111,7 @@ func TestPullRebase(t *testing.T) {
func TestPullRebaseMerge(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
hookTasks, err := webhook.HookTasks(1, 1) //Retrieve previous hook number
hookTasks, err := webhook.HookTasks(1, 1) // Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
@@ -131,7 +133,7 @@ func TestPullRebaseMerge(t *testing.T) {
func TestPullSquash(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
hookTasks, err := webhook.HookTasks(1, 1) //Retrieve previous hook number
hookTasks, err := webhook.HookTasks(1, 1) // Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
@@ -335,3 +337,74 @@ func TestCantMergeUnrelated(t *testing.T) {
gitRepo.Close()
})
}
func TestConflictChecking(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User)
// Create new clean repo to test conflict checking.
baseRepo, err := repo_service.CreateRepository(user, user, models.CreateRepoOptions{
Name: "conflict-checking",
Description: "Tempo repo",
AutoInit: true,
Readme: "Default",
DefaultBranch: "main",
})
assert.NoError(t, err)
assert.NotEmpty(t, baseRepo)
// create a commit on new branch.
_, err = files_service.CreateOrUpdateRepoFile(baseRepo, user, &files_service.UpdateRepoFileOptions{
TreePath: "important_file",
Message: "Add a important file",
Content: "Just a non-important file",
IsNewFile: true,
OldBranch: "main",
NewBranch: "important-secrets",
})
assert.NoError(t, err)
// create a commit on main branch.
_, err = files_service.CreateOrUpdateRepoFile(baseRepo, user, &files_service.UpdateRepoFileOptions{
TreePath: "important_file",
Message: "Add a important file",
Content: "Not the same content :P",
IsNewFile: true,
OldBranch: "main",
NewBranch: "main",
})
assert.NoError(t, err)
// create Pull to merge the important-secrets branch into main branch.
pullIssue := &models.Issue{
RepoID: baseRepo.ID,
Title: "PR with conflict!",
PosterID: user.ID,
Poster: user,
IsPull: true,
}
pullRequest := &models.PullRequest{
HeadRepoID: baseRepo.ID,
BaseRepoID: baseRepo.ID,
HeadBranch: "important-secrets",
BaseBranch: "main",
HeadRepo: baseRepo,
BaseRepo: baseRepo,
Type: models.PullRequestGitea,
}
err = pull.NewPullRequest(baseRepo, pullIssue, nil, nil, pullRequest, nil)
assert.NoError(t, err)
issue := unittest.AssertExistsAndLoadBean(t, &models.Issue{Title: "PR with conflict!"}).(*models.Issue)
conflictingPR, err := models.GetPullRequestByIssueID(issue.ID)
assert.NoError(t, err)
// Ensure conflictedFiles is populated.
assert.Equal(t, 1, len(conflictingPR.ConflictedFiles))
// Check if status is correct.
assert.Equal(t, models.PullRequestStatusConflict, conflictingPR.Status)
// Ensure that mergeable returns false
assert.False(t, conflictingPR.Mergeable())
})
}

View File

@@ -51,8 +51,6 @@ func TestSignin(t *testing.T) {
{username: "wrongUsername", password: "password", message: i18n.Tr("en", "form.username_password_incorrect")},
{username: "user15", password: "wrongPassword", message: i18n.Tr("en", "form.username_password_incorrect")},
{username: "user1@example.com", password: "wrongPassword", message: i18n.Tr("en", "form.username_password_incorrect")},
// test for duplicate email
{username: "user2@example.com", password: "password", message: i18n.Tr("en", "form.email_been_used")},
}
for _, s := range samples {

View File

@@ -79,7 +79,7 @@ PROVIDER_CONFIG = integrations/gitea-integration-sqlite/data/sessions
[log]
MODE = test,file
ROOT_PATH = sqlite-log
ROOT_PATH = {{REPO_TEST_DIR}}sqlite-log
ROUTER = ,
XORM = file
ENABLE_SSH_LOG = true

View File

@@ -58,7 +58,7 @@ func (key *DeployKey) GetContent() error {
return nil
}
// IsReadOnly checks if the key can only be used for read operations
// IsReadOnly checks if the key can only be used for read operations, used by template
func (key *DeployKey) IsReadOnly() bool {
return key.Mode == perm.AccessModeRead
}
@@ -203,12 +203,6 @@ func UpdateDeployKeyCols(key *DeployKey, cols ...string) error {
return err
}
// UpdateDeployKey updates deploy key information.
func UpdateDeployKey(key *DeployKey) error {
_, err := db.GetEngine(db.DefaultContext).ID(key.ID).AllCols().Update(key)
return err
}
// ListDeployKeysOptions are options for ListDeployKeys
type ListDeployKeysOptions struct {
db.ListOptions

View File

@@ -43,7 +43,7 @@ type WebAuthnCredential struct {
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX"`
CredentialID string `xorm:"INDEX VARCHAR(410)"`
PublicKey []byte
AttestationType string
AAGUID []byte

View File

@@ -23,8 +23,8 @@ const (
EnvPusherName = "GITEA_PUSHER_NAME"
EnvPusherEmail = "GITEA_PUSHER_EMAIL"
EnvPusherID = "GITEA_PUSHER_ID"
EnvKeyID = "GITEA_KEY_ID"
EnvIsDeployKey = "GITEA_IS_DEPLOY_KEY"
EnvKeyID = "GITEA_KEY_ID" // public key ID
EnvDeployKeyID = "GITEA_DEPLOY_KEY_ID"
EnvPRID = "GITEA_PR_ID"
EnvIsInternal = "GITEA_INTERNAL_PUSH"
EnvAppURL = "GITEA_ROOT_URL"

View File

@@ -1165,7 +1165,8 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {
// IssuesOptions represents options of an issue.
type IssuesOptions struct {
db.ListOptions
RepoIDs []int64 // include all repos if empty
RepoID int64 // overwrites RepoCond if not 0
RepoCond builder.Cond
AssigneeID int64
PosterID int64
MentionedID int64
@@ -1238,7 +1239,7 @@ func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64
}
}
func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
func (opts *IssuesOptions) setupSessionWithLimit(sess *xorm.Session) {
if opts.Page >= 0 && opts.PageSize > 0 {
var start int
if opts.Page == 0 {
@@ -1248,20 +1249,23 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
}
sess.Limit(opts.PageSize, start)
}
opts.setupSessionNoLimit(sess)
}
func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {
if len(opts.IssueIDs) > 0 {
sess.In("issue.id", opts.IssueIDs)
}
if len(opts.RepoIDs) > 0 {
applyReposCondition(sess, opts.RepoIDs)
if opts.RepoID != 0 {
opts.RepoCond = builder.Eq{"issue.repo_id": opts.RepoID}
}
if opts.RepoCond != nil {
sess.And(opts.RepoCond)
}
switch opts.IsClosed {
case util.OptionalBoolTrue:
sess.And("issue.is_closed=?", true)
case util.OptionalBoolFalse:
sess.And("issue.is_closed=?", false)
if !opts.IsClosed.IsNone() {
sess.And("issue.is_closed=?", opts.IsClosed.IsTrue())
}
if opts.AssigneeID > 0 {
@@ -1380,10 +1384,6 @@ func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *Organizati
return cond
}
func applyReposCondition(sess *xorm.Session, repoIDs []int64) *xorm.Session {
return sess.In("issue.repo_id", repoIDs)
}
func applyAssigneeCondition(sess *xorm.Session, assigneeID int64) *xorm.Session {
return sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
And("issue_assignees.assignee_id = ?", assigneeID)
@@ -1414,7 +1414,7 @@ func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) {
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSession(sess)
opts.setupSessionNoLimit(sess)
countsSlice := make([]*struct {
RepoID int64
@@ -1424,7 +1424,7 @@ func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) {
Select("issue.repo_id AS repo_id, COUNT(*) AS count").
Table("issue").
Find(&countsSlice); err != nil {
return nil, err
return nil, fmt.Errorf("unable to CountIssuesByRepo: %w", err)
}
countMap := make(map[int64]int64, len(countsSlice))
@@ -1441,14 +1441,14 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]i
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSession(sess)
opts.setupSessionNoLimit(sess)
accessCond := accessibleRepositoryCondition(user)
if err := sess.Where(accessCond).
Distinct("issue.repo_id").
Table("issue").
Find(&repoIDs); err != nil {
return nil, err
return nil, fmt.Errorf("unable to GetRepoIDsForIssuesOptions: %w", err)
}
return repoIDs, nil
@@ -1459,17 +1459,16 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
e := db.GetEngine(db.DefaultContext)
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSession(sess)
opts.setupSessionWithLimit(sess)
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
issues := make([]*Issue, 0, opts.ListOptions.PageSize)
if err := sess.Find(&issues); err != nil {
return nil, fmt.Errorf("Find: %v", err)
return nil, fmt.Errorf("unable to query Issues: %w", err)
}
sess.Close()
if err := IssueList(issues).LoadAttributes(); err != nil {
return nil, fmt.Errorf("LoadAttributes: %v", err)
return nil, fmt.Errorf("unable to LoadAttributes for Issues: %w", err)
}
return issues, nil
@@ -1480,18 +1479,17 @@ func CountIssues(opts *IssuesOptions) (int64, error) {
e := db.GetEngine(db.DefaultContext)
countsSlice := make([]*struct {
RepoID int64
Count int64
Count int64
}, 0, 1)
sess := e.Select("COUNT(issue.id) AS count").Table("issue")
sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSession(sess)
opts.setupSessionNoLimit(sess)
if err := sess.Find(&countsSlice); err != nil {
return 0, fmt.Errorf("Find: %v", err)
return 0, fmt.Errorf("unable to CountIssues: %w", err)
}
if len(countsSlice) < 1 {
return 0, fmt.Errorf("there is less than one result sql record")
if len(countsSlice) != 1 {
return 0, fmt.Errorf("unable to get one row result when CountIssues, row count=%d", len(countsSlice))
}
return countsSlice[0].Count, nil
}
@@ -1551,6 +1549,7 @@ const (
FilterModeCreate
FilterModeMention
FilterModeReviewRequested
FilterModeYourRepositories
)
func parseCountResult(results []map[string][]byte) int64 {
@@ -1695,6 +1694,7 @@ type UserIssueStatsOptions struct {
IssueIDs []int64
IsArchived util.OptionalBool
LabelIDs []int64
RepoCond builder.Cond
Org *Organization
Team *Team
}
@@ -1712,6 +1712,9 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
if len(opts.IssueIDs) > 0 {
cond = cond.And(builder.In("issue.id", opts.IssueIDs))
}
if opts.RepoCond != nil {
cond = cond.And(opts.RepoCond)
}
if opts.UserID > 0 {
cond = cond.And(issuePullAccessibleRepoCond("issue.repo_id", opts.UserID, opts.Org, opts.Team, opts.IsPull))
@@ -1733,7 +1736,7 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
}
switch opts.FilterMode {
case FilterModeAll:
case FilterModeAll, FilterModeYourRepositories:
stats.OpenCount, err = sess(cond).
And("issue.is_closed = ?", false).
Count(new(Issue))

View File

@@ -101,12 +101,9 @@ func (label *Label) CalOpenIssues() {
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
func (label *Label) CalOpenOrgIssues(repoID, labelID int64) {
repoIDs := []int64{repoID}
labelIDs := []int64{labelID}
counts, _ := CountIssuesByRepo(&IssuesOptions{
RepoIDs: repoIDs,
LabelIDs: labelIDs,
RepoID: repoID,
LabelIDs: []int64{labelID},
})
for _, count := range counts {

View File

@@ -17,6 +17,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"github.com/stretchr/testify/assert"
"xorm.io/builder"
)
func TestIssue_ReplaceLabels(t *testing.T) {
@@ -153,7 +154,7 @@ func TestIssues(t *testing.T) {
},
{
IssuesOptions{
RepoIDs: []int64{1, 3},
RepoCond: builder.In("repo_id", 1, 3),
SortType: "oldest",
ListOptions: db.ListOptions{
Page: 1,
@@ -340,7 +341,7 @@ func TestGetRepoIDsForIssuesOptions(t *testing.T) {
},
{
IssuesOptions{
RepoIDs: []int64{1, 2},
RepoCond: builder.In("repo_id", 1, 2),
},
[]int64{1, 2},
},

View File

@@ -137,6 +137,7 @@ func QueryIssueContentHistoryEditedCountMap(dbCtx context.Context, issueID int64
type IssueContentListItem struct {
UserID int64
UserName string
UserFullName string
UserAvatarLink string
HistoryID int64
@@ -148,7 +149,7 @@ type IssueContentListItem struct {
// FetchIssueContentHistoryList fetch list
func FetchIssueContentHistoryList(dbCtx context.Context, issueID, commentID int64) ([]*IssueContentListItem, error) {
res := make([]*IssueContentListItem, 0)
err := db.GetEngine(dbCtx).Select("u.id as user_id, u.name as user_name,"+
err := db.GetEngine(dbCtx).Select("u.id as user_id, u.name as user_name, u.full_name as user_full_name,"+
"h.id as history_id, h.edited_unix, h.is_first_created, h.is_deleted").
Table([]string{"issue_content_history", "h"}).
Join("LEFT", []string{"user", "u"}, "h.poster_id = u.id").

View File

@@ -43,8 +43,9 @@ func TestContentHistory(t *testing.T) {
when the refactor of models are done, this test will be possible to be run then with a real `User` model.
*/
type User struct {
ID int64
Name string
ID int64
Name string
FullName string
}
_ = dbEngine.Sync2(&User{})

View File

@@ -193,12 +193,13 @@ func LFSAutoAssociate(metas []*LFSMetaObject, user *user_model.User, repoID int6
// admin can associate any LFS object to any repository, and we do not care about errors (eg: duplicated unique key),
// even if error occurs, it won't hurt users and won't make things worse
for i := range metas {
p := lfs.Pointer{Oid: metas[i].Oid, Size: metas[i].Size}
_, err = sess.Insert(&LFSMetaObject{
Pointer: lfs.Pointer{Oid: metas[i].Oid, Size: metas[i].Size},
Pointer: p,
RepositoryID: repoID,
})
if err != nil {
log.Warn("failed to insert LFS meta object into database, err=%v", err)
log.Warn("failed to insert LFS meta object %-v for repo_id: %d into database, err=%v", p, repoID, err)
}
}
}

View File

@@ -52,10 +52,6 @@ func InsertIssues(issues ...*Issue) error {
return err
}
}
err = UpdateRepoStats(ctx, issues[0].RepoID)
if err != nil {
return err
}
return committer.Commit()
}
@@ -147,11 +143,6 @@ func InsertPullRequests(prs ...*PullRequest) error {
return err
}
}
err = UpdateRepoStats(ctx, prs[0].Issue.RepoID)
if err != nil {
return err
}
return committer.Commit()
}

View File

@@ -32,8 +32,9 @@ func TestMigrate_InsertMilestones(t *testing.T) {
unittest.CheckConsistencyFor(t, &Milestone{})
}
func assertCreateIssues(t *testing.T, reponame string, isPull bool) {
func assertCreateIssues(t *testing.T, isPull bool) {
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User)
label := unittest.AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
@@ -63,38 +64,14 @@ func assertCreateIssues(t *testing.T, reponame string, isPull bool) {
i := unittest.AssertExistsAndLoadBean(t, &Issue{Title: title}).(*Issue)
unittest.AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: owner.ID, IssueID: i.ID})
labelModified := unittest.AssertExistsAndLoadBean(t, &Label{ID: 1}).(*Label)
assert.EqualValues(t, label.NumIssues+1, labelModified.NumIssues)
assert.EqualValues(t, label.NumClosedIssues+1, labelModified.NumClosedIssues)
milestoneModified := unittest.AssertExistsAndLoadBean(t, &Milestone{ID: milestone.ID}).(*Milestone)
assert.EqualValues(t, milestone.NumIssues+1, milestoneModified.NumIssues)
assert.EqualValues(t, milestone.NumClosedIssues+1, milestoneModified.NumClosedIssues)
}
func TestMigrate_CreateIssuesIsPullFalse(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
assertCreateIssues(t, reponame, false)
repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}).(*repo_model.Repository)
assert.EqualValues(t, repo.NumIssues+1, repoModified.NumIssues)
assert.EqualValues(t, repo.NumClosedIssues+1, repoModified.NumClosedIssues)
assertCreateIssues(t, false)
}
func TestMigrate_CreateIssuesIsPullTrue(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
reponame := "repo1"
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
assertCreateIssues(t, reponame, true)
repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}).(*repo_model.Repository)
assert.EqualValues(t, repo.NumPulls+1, repoModified.NumPulls)
assert.EqualValues(t, repo.NumClosedPulls+1, repoModified.NumClosedPulls)
assertCreateIssues(t, true)
}
func TestMigrate_InsertIssueComments(t *testing.T) {

View File

@@ -0,0 +1,12 @@
-
id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 2
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 3
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
-
id: 4
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="

View File

@@ -0,0 +1,21 @@
-
id: 1
name: "u2fkey-correctly-migrated"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 2
name: "u2fkey-incorrectly-migrated"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 3
name: "u2fkey-deleted"
user_id: 1
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0
- id: 4
name: "u2fkey-wrong-user-id"
user_id: 2
raw: 0x05040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf240efe2e213b889daf3fc88e3952e8dd6b4cfd82f1a1212e2ab4b19389455ecf3e67f0aeafc91b9c0d413c9d6215a45177c1d5076358aa6ee20e1b30e3d7467cae2308202bd308201a5a00302010202041e8f8734300d06092a864886f70d01010b0500302e312c302a0603550403132359756269636f2055324620526f6f742043412053657269616c203435373230303633313020170d3134303830313030303030305a180f32303530303930343030303030305a306e310b300906035504061302534531123010060355040a0c0959756269636f20414231223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e3127302506035504030c1e59756269636f205532462045452053657269616c203531323732323734303059301306072a8648ce3d020106082a8648ce3d03010703420004a879f82338ed1494bac0704bcc7fc663d1b271715976243101c7605115d7c1529e281c1c67322d384b5cd55dd3e9818d5fd85c22af326e0c64fc20afe33f2366a36c306a302206092b0601040182c40a020415312e332e362e312e342e312e34313438322e312e373013060b2b0601040182e51c0201010404030204303021060b2b0601040182e51c010104041204102fc0579f811347eab116bb5a8db9202a300c0603551d130101ff04023000300d06092a864886f70d01010b050003820101008693ff62df0d5779d4748d7fc8d10227318a8e580e6a3a57c108e94e03c38568b366894fce5624be4a3efd7f34118b3d993743f792a1989160c8fc9ae0b04e3df9ee15e3e88c04fc82a8dcbf5818e108dcc2968577ae79ff662b94734e3dec4597305d73e6e55ee2beb9cd9678ca0935e533eb638f8e26fabb817cda441fbe9831832ae5f6e2ad992f9ebbdb4c62238b8f8d7ab481d6d3263bcdbf9e4a57550370988ad5813440fa032cadb6723cadd8f8d7ba809f75b43cffa0a5b9add14232ef9d9e14812638233c4ca4a873b9f8ac98e32ba19167606e15909fcddb4a2dffbdae4620249f9a6646ac81e4832d1119febfaa731a882da25a77827d46d190173046022100b579338a44c236d3f214b2e150011a08cf251193ecfae2244edb0a5794e9b301022100fab468862c47d98204d437cf2be8c54a5a4ecd1ebb1c61a6c23da7b9c75f6841
counter: 0

View File

@@ -0,0 +1,30 @@
-
id: 1
lower_name: "u2fkey-correctly-migrated"
name: "u2fkey-correctly-migrated"
user_id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8AQ8KBNO7AGEOQOL9NE43GR63HTEHJSLOG="
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false
-
id: 2
lower_name: "u2fkey-incorrectly-migrated"
name: "u2fkey-incorrectly-migrated"
user_id: 1
credential_id: "TVHE44TOH7DF7V48SEAIT3EMMJ7TGBOQ289E5AQB34S98LFCUFJ7U2NAVI8RJG6K2F4TC8A"
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false
-
id: 4
lower_name: "u2fkey-wrong-user-id"
name: "u2fkey-wrong-user-id"
user_id: 1
credential_id: "THIS SHOULD CHANGE"
public_key: 0x040d0967a2cad045011631187576492a0beb5b377954b4f694c5afc8bdf25270f87f09a9ab6ce9c282f447ba71b2f2bae2105b32b847e0704f310f48644e3eddf2
attestation_type: 'fido-u2f'
sign_count: 1
clone_warning: false

View File

@@ -61,7 +61,6 @@ type Version struct {
// update minDBVersion accordingly
var migrations = []Migration{
// Gitea 1.5.0 ends at v69
// v70 -> v71
NewMigration("add issue_dependencies", addIssueDependencies),
// v71 -> v72
@@ -367,9 +366,13 @@ var migrations = []Migration{
// v206 -> v207
NewMigration("Add authorize column to team_unit table", addAuthorizeColForTeamUnit),
// v207 -> v208
NewMigration("Add webauthn table and migrate u2f data to webauthn", addWebAuthnCred),
NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", addWebAuthnCred),
// v208 -> v209
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive", useBase32HexForCredIDInWebAuthnCredential),
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", useBase32HexForCredIDInWebAuthnCredential),
// v209 -> v210
NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", increaseCredentialIDTo410),
// v210 -> v211
NewMigration("v208 was completely broken - remigrate", remigrateU2FCredentials),
}
// GetCurrentDBVersion returns the current db version
@@ -450,9 +453,12 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
// Downgrading Gitea's database version not supported
if int(v-minDBVersion) > len(migrations) {
msg := fmt.Sprintf("Downgrading database version from '%d' to '%d' is not supported and may result in loss of data integrity.\nIf you really know what you're doing, execute `UPDATE version SET version=%d WHERE id=1;`\n",
v, minDBVersion+len(migrations), minDBVersion+len(migrations))
fmt.Fprint(os.Stderr, msg)
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, minDBVersion+len(migrations))
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
if !setting.IsProd {
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations))
}
_, _ = fmt.Fprintln(os.Stderr, msg)
log.Fatal(msg)
return nil
}

View File

@@ -5,87 +5,11 @@
package migrations
import (
"crypto/elliptic"
"encoding/base64"
"strings"
"code.gitea.io/gitea/modules/timeutil"
"github.com/tstranex/u2f"
"xorm.io/xorm"
)
func addWebAuthnCred(x *xorm.Engine) error {
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX"`
PublicKey []byte
AttestationType string
AAGUID []byte
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
// Now migrate the old u2f registrations to the new format
type u2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
var start int
regs := make([]*u2fRegistration, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
for _, reg := range regs {
parsed := new(u2f.Registration)
err = parsed.UnmarshalBinary(reg.Raw)
if err != nil {
continue
}
c := &webauthnCredential{
ID: reg.ID,
Name: reg.Name,
LowerName: strings.ToLower(reg.Name),
UserID: reg.UserID,
CredentialID: base64.RawStdEncoding.EncodeToString(parsed.KeyHandle),
PublicKey: elliptic.Marshal(elliptic.P256(), parsed.PubKey.X, parsed.PubKey.Y),
AttestationType: "fido-u2f",
AAGUID: []byte{},
SignCount: reg.Counter,
}
_, err := x.Insert(c)
if err != nil {
return err
}
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
// NO-OP Don't migrate here - let v210 do this.
return nil
}

View File

@@ -5,47 +5,10 @@
package migrations
import (
"encoding/base32"
"encoding/base64"
"xorm.io/xorm"
)
func useBase32HexForCredIDInWebAuthnCredential(x *xorm.Engine) error {
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
CredentialID string `xorm:"INDEX"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
var start int
regs := make([]*webauthnCredential, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
for _, reg := range regs {
credID, _ := base64.RawStdEncoding.DecodeString(reg.CredentialID)
reg.CredentialID = base32.HexEncoding.EncodeToString(credID)
_, err := x.Update(reg)
if err != nil {
return err
}
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
// noop
return nil
}

17
models/migrations/v209.go Normal file
View File

@@ -0,0 +1,17 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"xorm.io/xorm"
)
func increaseCredentialIDTo410(x *xorm.Engine) error {
// no-op
// V208 is badly broken
// So now we have to no-op again.
return nil
}

184
models/migrations/v210.go Normal file
View File

@@ -0,0 +1,184 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"crypto/elliptic"
"encoding/base32"
"fmt"
"strings"
"code.gitea.io/gitea/modules/timeutil"
"github.com/tstranex/u2f"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
// v208 migration was completely broken
func remigrateU2FCredentials(x *xorm.Engine) error {
// Create webauthnCredential table
type webauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
PublicKey []byte
AttestationType string
AAGUID []byte
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
if err := x.Sync2(&webauthnCredential{}); err != nil {
return err
}
switch x.Dialect().URI().DBType {
case schemas.MYSQL:
_, err := x.Exec("ALTER TABLE webauthn_credential MODIFY COLUMN credential_id VARCHAR(410)")
if err != nil {
return err
}
case schemas.ORACLE:
_, err := x.Exec("ALTER TABLE webauthn_credential MODIFY credential_id VARCHAR(410)")
if err != nil {
return err
}
case schemas.MSSQL:
// This column has an index on it. I could write all of the code to attempt to change the index OR
// I could just use recreate table.
sess := x.NewSession()
if err := sess.Begin(); err != nil {
_ = sess.Close()
return err
}
if err := recreateTable(sess, new(webauthnCredential)); err != nil {
_ = sess.Close()
return err
}
if err := sess.Commit(); err != nil {
_ = sess.Close()
return err
}
if err := sess.Close(); err != nil {
return err
}
case schemas.POSTGRES:
_, err := x.Exec("ALTER TABLE webauthn_credential ALTER COLUMN credential_id TYPE VARCHAR(410)")
if err != nil {
return err
}
default:
// SQLite doesn't support ALTER COLUMN, and it already makes String _TEXT_ by default so no migration needed
// nor is there any need to re-migrate
}
exist, err := x.IsTableExist("u2f_registration")
if err != nil {
return err
}
if !exist {
return nil
}
// Now migrate the old u2f registrations to the new format
type u2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
var start int
regs := make([]*u2fRegistration, 0, 50)
for {
err := x.OrderBy("id").Limit(50, start).Find(&regs)
if err != nil {
return err
}
err = func() error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return fmt.Errorf("unable to allow start session. Error: %w", err)
}
if x.Dialect().URI().DBType == schemas.MSSQL {
if _, err := sess.Exec("SET IDENTITY_INSERT `webauthn_credential` ON"); err != nil {
return fmt.Errorf("unable to allow identity insert on webauthn_credential. Error: %w", err)
}
}
for _, reg := range regs {
parsed := new(u2f.Registration)
err = parsed.UnmarshalBinary(reg.Raw)
if err != nil {
continue
}
remigrated := &webauthnCredential{
ID: reg.ID,
Name: reg.Name,
LowerName: strings.ToLower(reg.Name),
UserID: reg.UserID,
CredentialID: base32.HexEncoding.EncodeToString(parsed.KeyHandle),
PublicKey: elliptic.Marshal(elliptic.P256(), parsed.PubKey.X, parsed.PubKey.Y),
AttestationType: "fido-u2f",
AAGUID: []byte{},
SignCount: reg.Counter,
UpdatedUnix: reg.UpdatedUnix,
CreatedUnix: reg.CreatedUnix,
}
has, err := sess.ID(reg.ID).Get(new(webauthnCredential))
if err != nil {
return fmt.Errorf("unable to get webauthn_credential[%d]. Error: %w", reg.ID, err)
}
if !has {
has, err := sess.Where("`lower_name`=?", remigrated.LowerName).And("`user_id`=?", remigrated.UserID).Exist(new(webauthnCredential))
if err != nil {
return fmt.Errorf("unable to check webauthn_credential[lower_name: %s, user_id:%v]. Error: %w", remigrated.LowerName, remigrated.UserID, err)
}
if !has {
_, err = sess.Insert(remigrated)
if err != nil {
return fmt.Errorf("unable to (re)insert webauthn_credential[%d]. Error: %w", reg.ID, err)
}
continue
}
}
_, err = sess.ID(remigrated.ID).AllCols().Update(remigrated)
if err != nil {
return fmt.Errorf("unable to update webauthn_credential[%d]. Error: %w", reg.ID, err)
}
}
return sess.Commit()
}()
if err != nil {
return err
}
if len(regs) < 50 {
break
}
start += 50
regs = regs[:0]
}
if x.Dialect().URI().DBType == schemas.POSTGRES {
if _, err := x.Exec("SELECT setval('webauthn_credential_id_seq', COALESCE((SELECT MAX(id)+1 FROM `webauthn_credential`), 1), false)"); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,75 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"testing"
"code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert"
"xorm.io/xorm/schemas"
)
func Test_remigrateU2FCredentials(t *testing.T) {
// Create webauthnCredential table
type WebauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
Name string
LowerName string `xorm:"unique(s)"`
UserID int64 `xorm:"INDEX unique(s)"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
PublicKey []byte
AttestationType string
SignCount uint32 `xorm:"BIGINT"`
CloneWarning bool
}
// Now migrate the old u2f registrations to the new format
type U2fRegistration struct {
ID int64 `xorm:"pk autoincr"`
Name string
UserID int64 `xorm:"INDEX"`
Raw []byte
Counter uint32 `xorm:"BIGINT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}
type ExpectedWebauthnCredential struct {
ID int64 `xorm:"pk autoincr"`
CredentialID string `xorm:"INDEX VARCHAR(410)"` // CredentalID in U2F is at most 255bytes / 5 * 8 = 408 - add a few extra characters for safety
}
// Prepare and load the testing database
x, deferable := prepareTestEnv(t, 0, new(WebauthnCredential), new(U2fRegistration), new(ExpectedWebauthnCredential))
if x == nil || t.Failed() {
defer deferable()
return
}
defer deferable()
if x.Dialect().URI().DBType == schemas.SQLITE {
return
}
// Run the migration
if err := remigrateU2FCredentials(x); err != nil {
assert.NoError(t, err)
return
}
expected := []ExpectedWebauthnCredential{}
if err := x.Table("expected_webauthn_credential").Asc("id").Find(&expected); !assert.NoError(t, err) {
return
}
got := []ExpectedWebauthnCredential{}
if err := x.Table("webauthn_credential").Select("id, credential_id").Asc("id").Find(&got); !assert.NoError(t, err) {
return
}
assert.EqualValues(t, expected, got)
}

View File

@@ -498,14 +498,15 @@ func (n *Notification) APIURL() string {
type NotificationList []*Notification
// LoadAttributes load Repo Issue User and Comment if not loaded
func (nl NotificationList) LoadAttributes() (err error) {
func (nl NotificationList) LoadAttributes() error {
var err error
for i := 0; i < len(nl); i++ {
err = nl[i].LoadAttributes()
if err != nil && !IsErrCommentNotExist(err) {
return
return err
}
}
return
return nil
}
func (nl NotificationList) getPendingRepoIDs() []int64 {

View File

@@ -19,6 +19,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
)
@@ -776,8 +777,45 @@ func DeleteTeam(t *Team) error {
return err
}
if err := t.removeAllRepositories(ctx); err != nil {
return err
// update branch protections
{
protections := make([]*ProtectedBranch, 0, 10)
err := sess.In("repo_id",
builder.Select("id").From("repository").Where(builder.Eq{"owner_id": t.OrgID})).
Find(&protections)
if err != nil {
return fmt.Errorf("findProtectedBranches: %v", err)
}
for _, p := range protections {
var matched1, matched2, matched3 bool
if len(p.WhitelistTeamIDs) != 0 {
p.WhitelistTeamIDs, matched1 = util.RemoveIDFromList(
p.WhitelistTeamIDs, t.ID)
}
if len(p.ApprovalsWhitelistTeamIDs) != 0 {
p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList(
p.ApprovalsWhitelistTeamIDs, t.ID)
}
if len(p.MergeWhitelistTeamIDs) != 0 {
p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList(
p.MergeWhitelistTeamIDs, t.ID)
}
if matched1 || matched2 || matched3 {
if _, err = sess.ID(p.ID).Cols(
"whitelist_team_i_ds",
"merge_whitelist_team_i_ds",
"approvals_whitelist_team_i_ds",
).Update(p); err != nil {
return fmt.Errorf("updateProtectedBranches: %v", err)
}
}
}
}
if !t.IncludesAllRepositories {
if err := t.removeAllRepositories(ctx); err != nil {
return err
}
}
// Delete team-user.
@@ -902,11 +940,6 @@ func AddTeamMember(team *Team, userID int64) error {
return err
}
// Get team and its repositories.
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
return err
}
ctx, committer, err := db.TxContext()
if err != nil {
return err
@@ -928,17 +961,51 @@ func AddTeamMember(team *Team, userID int64) error {
team.NumMembers++
// Give access to team repositories.
for _, repo := range team.Repos {
if err := recalculateUserAccess(ctx, repo, userID); err != nil {
return err
}
if setting.Service.AutoWatchNewRepos {
if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
return err
// update exist access if mode become bigger
subQuery := builder.Select("repo_id").From("team_repo").
Where(builder.Eq{"team_id": team.ID})
if _, err := sess.Where("user_id=?", userID).
In("repo_id", subQuery).
And("mode < ?", team.AccessMode).
SetExpr("mode", team.AccessMode).
Update(new(Access)); err != nil {
return fmt.Errorf("update user accesses: %v", err)
}
// for not exist access
var repoIDs []int64
accessSubQuery := builder.Select("repo_id").From("access").Where(builder.Eq{"user_id": userID})
if err := sess.SQL(subQuery.And(builder.NotIn("repo_id", accessSubQuery))).Find(&repoIDs); err != nil {
return fmt.Errorf("select id accesses: %v", err)
}
accesses := make([]*Access, 0, 100)
for i, repoID := range repoIDs {
accesses = append(accesses, &Access{RepoID: repoID, UserID: userID, Mode: team.AccessMode})
if (i%100 == 0 || i == len(repoIDs)-1) && len(accesses) > 0 {
if err = db.Insert(ctx, accesses); err != nil {
return fmt.Errorf("insert new user accesses: %v", err)
}
accesses = accesses[:0]
}
}
// watch could be failed, so run it in a goroutine
if setting.Service.AutoWatchNewRepos {
// Get team and its repositories.
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
log.Error("getRepositories failed: %v", err)
}
go func(repos []*repo_model.Repository) {
for _, repo := range repos {
if err = repo_model.WatchRepoCtx(db.DefaultContext, userID, repo.ID, true); err != nil {
log.Error("watch repo failed: %v", err)
}
}
}(team.Repos)
}
return committer.Commit()
}

View File

@@ -222,22 +222,19 @@ func (pr *PullRequest) loadProtectedBranch(ctx context.Context) (err error) {
}
// GetDefaultMergeMessage returns default message used when merging pull request
func (pr *PullRequest) GetDefaultMergeMessage() string {
func (pr *PullRequest) GetDefaultMergeMessage() (string, error) {
if pr.HeadRepo == nil {
var err error
pr.HeadRepo, err = repo_model.GetRepositoryByID(pr.HeadRepoID)
if err != nil {
log.Error("GetRepositoryById[%d]: %v", pr.HeadRepoID, err)
return ""
return "", fmt.Errorf("GetRepositoryById[%d]: %v", pr.HeadRepoID, err)
}
}
if err := pr.LoadIssue(); err != nil {
log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err)
return ""
return "", fmt.Errorf("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err)
}
if err := pr.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err)
return ""
return "", fmt.Errorf("LoadBaseRepo: %v", err)
}
issueReference := "#"
@@ -246,10 +243,10 @@ func (pr *PullRequest) GetDefaultMergeMessage() string {
}
if pr.BaseRepoID == pr.HeadRepoID {
return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch)
return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadBranch, pr.BaseBranch), nil
}
return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch)
return fmt.Sprintf("Merge pull request '%s' (%s%d) from %s:%s into %s", pr.Issue.Title, issueReference, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch), nil
}
// ReviewCount represents a count of Reviews
@@ -335,19 +332,17 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error {
}
// GetDefaultSquashMessage returns default message used when squash and merging pull request
func (pr *PullRequest) GetDefaultSquashMessage() string {
func (pr *PullRequest) GetDefaultSquashMessage() (string, error) {
if err := pr.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err)
return ""
return "", fmt.Errorf("LoadIssue: %v", err)
}
if err := pr.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err)
return ""
return "", fmt.Errorf("LoadBaseRepo: %v", err)
}
if pr.BaseRepo.UnitEnabled(unit.TypeExternalTracker) {
return fmt.Sprintf("%s (!%d)", pr.Issue.Title, pr.Issue.Index)
return fmt.Sprintf("%s (!%d)", pr.Issue.Title, pr.Issue.Index), nil
}
return fmt.Sprintf("%s (#%d)", pr.Issue.Title, pr.Issue.Index)
return fmt.Sprintf("%s (#%d)", pr.Issue.Title, pr.Issue.Index), nil
}
// GetGitRefName returns git ref for hidden pull request branch
@@ -702,3 +697,14 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string {
}
return pr.HeadRepo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(pr.HeadBranch)
}
// Mergeable returns if the pullrequest is mergeable.
func (pr *PullRequest) Mergeable() bool {
// If a pull request isn't mergable if it's:
// - Being conflict checked.
// - Has a conflict.
// - Received a error while being conflict checked.
// - Is a work-in-progress pull request.
return pr.Status != PullRequestStatusChecking && pr.Status != PullRequestStatusConflict &&
pr.Status != PullRequestStatusError && !pr.IsWorkInProgress()
}

View File

@@ -261,11 +261,15 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
pr := unittest.AssertExistsAndLoadBean(t, &PullRequest{ID: 2}).(*PullRequest)
assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", pr.GetDefaultMergeMessage())
msg, err := pr.GetDefaultMergeMessage()
assert.NoError(t, err)
assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", msg)
pr.BaseRepoID = 1
pr.HeadRepoID = 2
assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", pr.GetDefaultMergeMessage())
msg, err = pr.GetDefaultMergeMessage()
assert.NoError(t, err)
assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", msg)
}
func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) {
@@ -283,9 +287,13 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) {
pr := unittest.AssertExistsAndLoadBean(t, &PullRequest{ID: 2, BaseRepo: baseRepo}).(*PullRequest)
assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", pr.GetDefaultMergeMessage())
msg, err := pr.GetDefaultMergeMessage()
assert.NoError(t, err)
assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", msg)
pr.BaseRepoID = 1
pr.HeadRepoID = 2
assert.Equal(t, "Merge pull request 'issue3' (!3) from user2/repo1:branch2 into master", pr.GetDefaultMergeMessage())
msg, err = pr.GetDefaultMergeMessage()
assert.NoError(t, err)
assert.Equal(t, "Merge pull request 'issue3' (!3) from user2/repo1:branch2 into master", msg)
}

View File

@@ -150,27 +150,56 @@ func getRepoAssignees(ctx context.Context, repo *repo_model.Repository) (_ []*us
}
e := db.GetEngine(ctx)
accesses := make([]*Access, 0, 10)
if err = e.
userIDs := make([]int64, 0, 10)
if err = e.Table("access").
Where("repo_id = ? AND mode >= ?", repo.ID, perm.AccessModeWrite).
Find(&accesses); err != nil {
Select("user_id").
Find(&userIDs); err != nil {
return nil, err
}
additionalUserIDs := make([]int64, 0, 10)
if err = e.Table("team_user").
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
Where("`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?", repo.ID, perm.AccessModeWrite).
Distinct("`team_user`.uid").
Select("`team_user`.uid").
Find(&additionalUserIDs); err != nil {
return nil, err
}
uidMap := map[int64]bool{}
i := 0
for _, uid := range userIDs {
if uidMap[uid] {
continue
}
uidMap[uid] = true
userIDs[i] = uid
i++
}
userIDs = userIDs[:i]
userIDs = append(userIDs, additionalUserIDs...)
for _, uid := range additionalUserIDs {
if uidMap[uid] {
continue
}
userIDs[i] = uid
i++
}
userIDs = userIDs[:i]
// Leave a seat for owner itself to append later, but if owner is an organization
// and just waste 1 unit is cheaper than re-allocate memory once.
users := make([]*user_model.User, 0, len(accesses)+1)
if len(accesses) > 0 {
userIDs := make([]int64, len(accesses))
for i := 0; i < len(accesses); i++ {
userIDs[i] = accesses[i].UserID
}
users := make([]*user_model.User, 0, len(userIDs)+1)
if len(userIDs) > 0 {
if err = e.In("id", userIDs).Find(&users); err != nil {
return nil, err
}
}
if !repo.Owner.IsOrganization() {
if !repo.Owner.IsOrganization() && !uidMap[repo.OwnerID] {
users = append(users, repo.Owner)
}
@@ -948,7 +977,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
// Remove attachment with no issue_id and release_id.
for i := range newAttachmentPaths {
admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", attachmentPaths[i])
admin_model.RemoveStorageWithNotice(db.DefaultContext, storage.Attachments, "Delete issue attachment", newAttachmentPaths[i])
}
if len(repo.Avatar) > 0 {

View File

@@ -6,6 +6,7 @@
package repo
import (
"context"
"errors"
"fmt"
"time"
@@ -115,6 +116,13 @@ func UpdateMirror(m *Mirror) error {
return updateMirror(db.GetEngine(db.DefaultContext), m)
}
// TouchMirror updates the mirror updatedUnix
func TouchMirror(ctx context.Context, m *Mirror) error {
m.UpdatedUnix = timeutil.TimeStampNow()
_, err := db.GetEngine(ctx).ID(m.ID).Cols("updated_unix").Update(m)
return err
}
// DeleteMirrorByRepoID deletes a mirror by repoID
func DeleteMirrorByRepoID(repoID int64) error {
_, err := db.GetEngine(db.DefaultContext).Delete(&Mirror{RepoID: repoID})

View File

@@ -167,3 +167,21 @@ func TestLinkedRepository(t *testing.T) {
})
}
}
func TestRepoAssignees(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository)
users, err := GetRepoAssignees(repo2)
assert.NoError(t, err)
assert.Len(t, users, 1)
assert.Equal(t, users[0].ID, int64(2))
repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}).(*repo_model.Repository)
users, err = GetRepoAssignees(repo21)
assert.NoError(t, err)
assert.Len(t, users, 3)
assert.Equal(t, users[0].ID, int64(15))
assert.Equal(t, users[1].ID, int64(18))
assert.Equal(t, users[2].ID, int64(16))
}

View File

@@ -328,7 +328,12 @@ func AllUnitKeyNames() []string {
// MinUnitAccessMode returns the minial permission of the permission map
func MinUnitAccessMode(unitsMap map[Type]perm.AccessMode) perm.AccessMode {
res := perm.AccessModeNone
for _, mode := range unitsMap {
for t, mode := range unitsMap {
// Don't allow `TypeExternal{Tracker,Wiki}` to influence this as they can only be set to READ perms.
if t == TypeExternalTracker || t == TypeExternalWiki {
continue
}
// get the minial permission great than AccessModeNone except all are AccessModeNone
if mode > perm.AccessModeNone && (res == perm.AccessModeNone || mode < res) {
res = mode

View File

@@ -18,6 +18,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
)
@@ -130,6 +131,50 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
}
}
// ***** START: Branch Protections *****
{
const batchSize = 50
for start := 0; ; start += batchSize {
protections := make([]*ProtectedBranch, 0, batchSize)
// @perf: We can't filter on DB side by u.ID, as those IDs are serialized as JSON strings.
// We could filter down with `WHERE repo_id IN (reposWithPushPermission(u))`,
// though that query will be quite complex and tricky to maintain (compare `getRepoAssignees()`).
// Also, as we didn't update branch protections when removing entries from `access` table,
// it's safer to iterate all protected branches.
if err = e.Limit(batchSize, start).Find(&protections); err != nil {
return fmt.Errorf("findProtectedBranches: %v", err)
}
if len(protections) == 0 {
break
}
for _, p := range protections {
var matched1, matched2, matched3 bool
if len(p.WhitelistUserIDs) != 0 {
p.WhitelistUserIDs, matched1 = util.RemoveIDFromList(
p.WhitelistUserIDs, u.ID)
}
if len(p.ApprovalsWhitelistUserIDs) != 0 {
p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList(
p.ApprovalsWhitelistUserIDs, u.ID)
}
if len(p.MergeWhitelistUserIDs) != 0 {
p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList(
p.MergeWhitelistUserIDs, u.ID)
}
if matched1 || matched2 || matched3 {
if _, err = e.ID(p.ID).Cols(
"whitelist_user_i_ds",
"merge_whitelist_user_i_ds",
"approvals_whitelist_user_i_ds",
).Update(p); err != nil {
return fmt.Errorf("updateProtectedBranches: %v", err)
}
}
}
}
}
// ***** END: Branch Protections *****
// ***** START: PublicKey *****
if _, err = e.Delete(&asymkey_model.PublicKey{OwnerID: u.ID}); err != nil {
return fmt.Errorf("deletePublicKeys: %v", err)

View File

@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"net/mail"
"regexp"
"strings"
"code.gitea.io/gitea/models/db"
@@ -21,10 +22,23 @@ import (
"xorm.io/builder"
)
var (
// ErrEmailNotActivated e-mail address has not been activated error
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
)
// ErrEmailNotActivated e-mail address has not been activated error
var ErrEmailNotActivated = errors.New("e-mail address has not been activated")
// ErrEmailCharIsNotSupported e-mail address contains unsupported character
type ErrEmailCharIsNotSupported struct {
Email string
}
// IsErrEmailCharIsNotSupported checks if an error is an ErrEmailCharIsNotSupported
func IsErrEmailCharIsNotSupported(err error) bool {
_, ok := err.(ErrEmailCharIsNotSupported)
return ok
}
func (err ErrEmailCharIsNotSupported) Error() string {
return fmt.Sprintf("e-mail address contains unsupported character [email: %s]", err.Email)
}
// ErrEmailInvalid represents an error where the email address does not comply with RFC 5322
type ErrEmailInvalid struct {
@@ -108,12 +122,24 @@ func (email *EmailAddress) BeforeInsert() {
}
}
var emailRegexp = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
// ValidateEmail check if email is a allowed address
func ValidateEmail(email string) error {
if len(email) == 0 {
return nil
}
if !emailRegexp.MatchString(email) {
return ErrEmailCharIsNotSupported{email}
}
if !(email[0] >= 'a' && email[0] <= 'z') &&
!(email[0] >= 'A' && email[0] <= 'Z') &&
!(email[0] >= '0' && email[0] <= '9') {
return ErrEmailInvalid{email}
}
if _, err := mail.ParseAddress(email); err != nil {
return ErrEmailInvalid{email}
}

View File

@@ -252,3 +252,58 @@ func TestListEmails(t *testing.T) {
assert.Len(t, emails, 5)
assert.Greater(t, count, int64(len(emails)))
}
func TestEmailAddressValidate(t *testing.T) {
kases := map[string]error{
"abc@gmail.com": nil,
"132@hotmail.com": nil,
"1-3-2@test.org": nil,
"1.3.2@test.org": nil,
"a_123@test.org.cn": nil,
`first.last@iana.org`: nil,
`first!last@iana.org`: nil,
`first#last@iana.org`: nil,
`first$last@iana.org`: nil,
`first%last@iana.org`: nil,
`first&last@iana.org`: nil,
`first'last@iana.org`: nil,
`first*last@iana.org`: nil,
`first+last@iana.org`: nil,
`first/last@iana.org`: nil,
`first=last@iana.org`: nil,
`first?last@iana.org`: nil,
`first^last@iana.org`: nil,
"first`last@iana.org": nil,
`first{last@iana.org`: nil,
`first|last@iana.org`: nil,
`first}last@iana.org`: nil,
`first~last@iana.org`: nil,
`first;last@iana.org`: ErrEmailCharIsNotSupported{`first;last@iana.org`},
".233@qq.com": ErrEmailInvalid{".233@qq.com"},
"!233@qq.com": ErrEmailInvalid{"!233@qq.com"},
"#233@qq.com": ErrEmailInvalid{"#233@qq.com"},
"$233@qq.com": ErrEmailInvalid{"$233@qq.com"},
"%233@qq.com": ErrEmailInvalid{"%233@qq.com"},
"&233@qq.com": ErrEmailInvalid{"&233@qq.com"},
"'233@qq.com": ErrEmailInvalid{"'233@qq.com"},
"*233@qq.com": ErrEmailInvalid{"*233@qq.com"},
"+233@qq.com": ErrEmailInvalid{"+233@qq.com"},
"/233@qq.com": ErrEmailInvalid{"/233@qq.com"},
"=233@qq.com": ErrEmailInvalid{"=233@qq.com"},
"?233@qq.com": ErrEmailInvalid{"?233@qq.com"},
"^233@qq.com": ErrEmailInvalid{"^233@qq.com"},
"`233@qq.com": ErrEmailInvalid{"`233@qq.com"},
"{233@qq.com": ErrEmailInvalid{"{233@qq.com"},
"|233@qq.com": ErrEmailInvalid{"|233@qq.com"},
"}233@qq.com": ErrEmailInvalid{"}233@qq.com"},
"~233@qq.com": ErrEmailInvalid{"~233@qq.com"},
";233@qq.com": ErrEmailCharIsNotSupported{";233@qq.com"},
"Foo <foo@bar.com>": ErrEmailCharIsNotSupported{"Foo <foo@bar.com>"},
string([]byte{0xE2, 0x84, 0xAA}): ErrEmailCharIsNotSupported{string([]byte{0xE2, 0x84, 0xAA})},
}
for kase, err := range kases {
t.Run(kase, func(t *testing.T) {
assert.EqualValues(t, err, ValidateEmail(kase))
})
}
}

View File

@@ -30,13 +30,19 @@ func (users UserList) GetTwoFaStatus() map[int64]bool {
for _, user := range users {
results[user.ID] = false // Set default to false
}
tokenMaps, err := users.loadTwoFactorStatus(db.GetEngine(db.DefaultContext))
if err == nil {
if tokenMaps, err := users.loadTwoFactorStatus(db.GetEngine(db.DefaultContext)); err == nil {
for _, token := range tokenMaps {
results[token.UID] = true
}
}
if ids, err := users.userIDsWithWebAuthn(db.GetEngine(db.DefaultContext)); err == nil {
for _, id := range ids {
results[id] = true
}
}
return results
}
@@ -47,15 +53,23 @@ func (users UserList) loadTwoFactorStatus(e db.Engine) (map[int64]*auth.TwoFacto
userIDs := users.GetUserIDs()
tokenMaps := make(map[int64]*auth.TwoFactor, len(userIDs))
err := e.
In("uid", userIDs).
Find(&tokenMaps)
if err != nil {
if err := e.In("uid", userIDs).Find(&tokenMaps); err != nil {
return nil, fmt.Errorf("find two factor: %v", err)
}
return tokenMaps, nil
}
func (users UserList) userIDsWithWebAuthn(e db.Engine) ([]int64, error) {
if len(users) == 0 {
return nil, nil
}
ids := make([]int64, 0, len(users))
if err := e.Table(new(auth.WebAuthnCredential)).In("user_id", users.GetUserIDs()).Select("user_id").Distinct("user_id").Find(&ids); err != nil {
return nil, fmt.Errorf("find two factor: %v", err)
}
return ids, nil
}
// GetUsersByIDs returns all resolved users from a list of Ids.
func GetUsersByIDs(ids []int64) (UserList, error) {
ous := make([]*User, 0, len(ids))

View File

@@ -20,6 +20,7 @@ import (
// SearchUserOptions contains the options for searching
type SearchUserOptions struct {
db.ListOptions
Keyword string
Type UserType
UID int64
@@ -33,6 +34,8 @@ type SearchUserOptions struct {
IsRestricted util.OptionalBool
IsTwoFactorEnabled util.OptionalBool
IsProhibitLogin util.OptionalBool
ExtraParamStrings map[string]string
}
func (opts *SearchUserOptions) toSearchQueryBase() *xorm.Session {

View File

@@ -622,7 +622,14 @@ func IsUsableUsername(name string) error {
// CreateUserOverwriteOptions are an optional options who overwrite system defaults on user creation
type CreateUserOverwriteOptions struct {
Visibility structs.VisibleType
KeepEmailPrivate util.OptionalBool
Visibility *structs.VisibleType
AllowCreateOrganization util.OptionalBool
EmailNotificationsPreference *string
MaxRepoCreation *int
Theme *string
IsRestricted util.OptionalBool
IsActive util.OptionalBool
}
// CreateUser creates record of a new user.
@@ -638,10 +645,45 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
u.MaxRepoCreation = -1
u.Theme = setting.UI.DefaultTheme
u.IsRestricted = setting.Service.DefaultUserIsRestricted
u.IsActive = !(setting.Service.RegisterEmailConfirm || setting.Service.RegisterManualConfirm)
// overwrite defaults if set
if len(overwriteDefault) != 0 && overwriteDefault[0] != nil {
u.Visibility = overwriteDefault[0].Visibility
overwrite := overwriteDefault[0]
if !overwrite.KeepEmailPrivate.IsNone() {
u.KeepEmailPrivate = overwrite.KeepEmailPrivate.IsTrue()
}
if overwrite.Visibility != nil {
u.Visibility = *overwrite.Visibility
}
if !overwrite.AllowCreateOrganization.IsNone() {
u.AllowCreateOrganization = overwrite.AllowCreateOrganization.IsTrue()
}
if overwrite.EmailNotificationsPreference != nil {
u.EmailNotificationsPreference = *overwrite.EmailNotificationsPreference
}
if overwrite.MaxRepoCreation != nil {
u.MaxRepoCreation = *overwrite.MaxRepoCreation
}
if overwrite.Theme != nil {
u.Theme = *overwrite.Theme
}
if !overwrite.IsRestricted.IsNone() {
u.IsRestricted = overwrite.IsRestricted.IsTrue()
}
if !overwrite.IsActive.IsNone() {
u.IsActive = overwrite.IsActive.IsTrue()
}
}
// validate data
if err := validateUser(u); err != nil {
return err
}
if err := ValidateEmail(u.Email); err != nil {
return err
}
ctx, committer, err := db.TxContext()
@@ -652,11 +694,6 @@ func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err e
sess := db.GetEngine(ctx)
// validate data
if err := validateUser(u); err != nil {
return err
}
isExist, err := isUserExist(sess, 0, u.Name)
if err != nil {
return err
@@ -827,8 +864,9 @@ func validateUser(u *User) error {
return ValidateEmail(u.Email)
}
func updateUser(ctx context.Context, u *User, changePrimaryEmail bool) error {
if err := validateUser(u); err != nil {
func updateUser(ctx context.Context, u *User, changePrimaryEmail bool, cols ...string) error {
err := validateUser(u)
if err != nil {
return err
}
@@ -860,15 +898,35 @@ func updateUser(ctx context.Context, u *User, changePrimaryEmail bool) error {
}); err != nil {
return err
}
} else if !u.IsOrganization() { // check if primary email in email_address table
primaryEmailExist, err := e.Where("uid=? AND is_primary=?", u.ID, true).Exist(&EmailAddress{})
if err != nil {
return err
}
if !primaryEmailExist {
if _, err = e.Insert(&EmailAddress{
Email: u.Email,
UID: u.ID,
IsActivated: true,
IsPrimary: true,
}); err != nil {
return err
}
}
}
_, err := e.ID(u.ID).AllCols().Update(u)
if len(cols) == 0 {
_, err = e.ID(u.ID).AllCols().Update(u)
} else {
_, err = e.ID(u.ID).Cols(cols...).Update(u)
}
return err
}
// UpdateUser updates user's information.
func UpdateUser(u *User, emailChanged bool) error {
return updateUser(db.DefaultContext, u, emailChanged)
func UpdateUser(u *User, emailChanged bool, cols ...string) error {
return updateUser(db.DefaultContext, u, emailChanged, cols...)
}
// UpdateUserCols update user according special columns
@@ -1104,19 +1162,9 @@ func GetUserByEmailContext(ctx context.Context, email string) (*User, error) {
}
email = strings.ToLower(email)
// First try to find the user by primary email
user := &User{Email: email}
has, err := db.GetEngine(ctx).Get(user)
if err != nil {
return nil, err
}
if has {
return user, nil
}
// Otherwise, check in alternative list for activated email addresses
emailAddress := &EmailAddress{Email: email, IsActivated: true}
has, err = db.GetEngine(ctx).Get(emailAddress)
emailAddress := &EmailAddress{LowerEmail: email, IsActivated: true}
has, err := db.GetEngine(ctx).Get(emailAddress)
if err != nil {
return nil, err
}

View File

@@ -232,7 +232,21 @@ func TestCreateUserInvalidEmail(t *testing.T) {
err := CreateUser(user)
assert.Error(t, err)
assert.True(t, IsErrEmailInvalid(err))
assert.True(t, IsErrEmailCharIsNotSupported(err))
}
func TestCreateUserEmailAlreadyUsed(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
user := unittest.AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
// add new user with user2's email
user.Name = "testuser"
user.LowerName = strings.ToLower(user.Name)
user.ID = 0
err := CreateUser(user)
assert.Error(t, err)
assert.True(t, IsErrEmailAlreadyUsed(err))
}
func TestGetUserIDsByNames(t *testing.T) {

View File

@@ -497,14 +497,19 @@ func GetSystemOrDefaultWebhook(id int64) (*Webhook, error) {
}
// GetSystemWebhooks returns all admin system webhooks.
func GetSystemWebhooks() ([]*Webhook, error) {
return getSystemWebhooks(db.GetEngine(db.DefaultContext))
func GetSystemWebhooks(isActive util.OptionalBool) ([]*Webhook, error) {
return getSystemWebhooks(db.GetEngine(db.DefaultContext), isActive)
}
func getSystemWebhooks(e db.Engine) ([]*Webhook, error) {
func getSystemWebhooks(e db.Engine, isActive util.OptionalBool) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
if isActive.IsNone() {
return webhooks, e.
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
Find(&webhooks)
}
return webhooks, e.
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
Find(&webhooks)
}

View File

@@ -35,6 +35,10 @@ func Auth(serviceName, userName, passwd string) (string, error) {
if err = t.Authenticate(0); err != nil {
return "", err
}
if err = t.AcctMgmt(0); err != nil {
return "", err
}
// PAM login names might suffer transformations in the PAM stack.
// We should take whatever the PAM stack returns for it.

View File

@@ -63,6 +63,7 @@ func EscapeControlBytes(text []byte) (EscapeStatus, []byte) {
func EscapeControlReader(text io.Reader, output io.Writer) (escaped EscapeStatus, err error) {
buf := make([]byte, 4096)
readStart := 0
runeCount := 0
var n int
var writePos int
@@ -74,10 +75,13 @@ readingloop:
for err == nil {
n, err = text.Read(buf[readStart:])
bs := buf[:n+readStart]
n = len(bs)
i := 0
for i < len(bs) {
r, size := utf8.DecodeRune(bs[i:])
runeCount++
// Now handle the codepoints
switch {
case r == utf8.RuneError:
@@ -112,6 +116,8 @@ readingloop:
lineHasRTLScript = false
lineHasLTRScript = false
case runeCount == 1 && r == 0xFEFF: // UTF BOM
// the first BOM is safe
case r == '\r' || r == '\t' || r == ' ':
// These are acceptable control characters and space characters
case unicode.IsSpace(r):
@@ -143,7 +149,8 @@ readingloop:
return
}
writePos = i + size
case unicode.Is(unicode.C, r):
// 65279 == BOM rune.
case unicode.Is(unicode.C, r) && r != rune(65279):
escaped.Escaped = true
escaped.HasControls = true
if writePos < i {

View File

@@ -129,6 +129,14 @@ then resh (ר), and finally heh (ה) (which should appear leftmost).`,
"\n" + `if access_level != "user<span class="escaped-code-point" data-escaped="[U+202E]"><span class="char">` + "\u202e" + `</span></span> <span class="escaped-code-point" data-escaped="[U+2066]"><span class="char">` + "\u2066" + `</span></span>// Check if admin<span class="escaped-code-point" data-escaped="[U+2069]"><span class="char">` + "\u2069" + `</span></span> <span class="escaped-code-point" data-escaped="[U+2066]"><span class="char">` + "\u2066" + `</span></span>" {` + "\n",
status: EscapeStatus{Escaped: true, HasBIDI: true, BadBIDI: true, HasLTRScript: true, HasRTLScript: true},
},
{
// UTF-8/16/32 all use the same codepoint for BOM
// Gitea could read UTF-16/32 content and convert into UTF-8 internally then render it, so we only process UTF-8 internally
name: "UTF BOM",
text: "\xef\xbb\xbftest",
result: "\xef\xbb\xbftest",
status: EscapeStatus{HasLTRScript: true},
},
}
func TestEscapeControlString(t *testing.T) {
@@ -163,10 +171,18 @@ func TestEscapeControlReader(t *testing.T) {
// lets add some control characters to the tests
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
copy(tests, escapeControlTests)
// if there is a BOM, we should keep the BOM
addPrefix := func(prefix, s string) string {
if strings.HasPrefix(s, "\xef\xbb\xbf") {
return s[:3] + prefix + s[3:]
}
return prefix + s
}
for _, test := range escapeControlTests {
test.name += " (+Control)"
test.text = "\u001E" + test.text
test.result = `<span class="escaped-code-point" data-escaped="[U+001E]"><span class="char">` + "\u001e" + `</span></span>` + test.result
test.text = addPrefix("\u001E", test.text)
test.result = addPrefix(`<span class="escaped-code-point" data-escaped="[U+001E]"><span class="char">`+"\u001e"+`</span></span>`, test.result)
test.status.Escaped = true
test.status.HasControls = true
tests = append(tests, test)
@@ -174,8 +190,8 @@ func TestEscapeControlReader(t *testing.T) {
for _, test := range escapeControlTests {
test.name += " (+Mark)"
test.text = "\u0300" + test.text
test.result = `<span class="escaped-code-point" data-escaped="[U+0300]"><span class="char">` + "\u0300" + `</span></span>` + test.result
test.text = addPrefix("\u0300", test.text)
test.result = addPrefix(`<span class="escaped-code-point" data-escaped="[U+0300]"><span class="char">`+"\u0300"+`</span></span>`, test.result)
test.status.Escaped = true
test.status.HasMarks = true
tests = append(tests, test)
@@ -200,3 +216,12 @@ func TestEscapeControlReader(t *testing.T) {
})
}
}
func TestEscapeControlReader_panic(t *testing.T) {
bs := make([]byte, 0, 20479)
bs = append(bs, 'A')
for i := 0; i < 6826; i++ {
bs = append(bs, []byte("—")...)
}
_, _ = EscapeControlBytes(bs)
}

View File

@@ -9,9 +9,11 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"html"
"html/template"
"io"
"net"
"net/http"
"net/url"
"path"
@@ -179,6 +181,12 @@ func (ctx *Context) RedirectToFirst(location ...string) {
continue
}
// Unfortunately browsers consider a redirect Location with preceding "//" and "/\" as meaning redirect to "http(s)://REST_OF_PATH"
// Therefore we should ignore these redirect locations to prevent open redirects
if len(loc) > 1 && loc[0] == '/' && (loc[1] == '/' || loc[1] == '\\') {
continue
}
u, err := url.Parse(loc)
if err != nil || ((u.Scheme != "" || u.Host != "") && !strings.HasPrefix(strings.ToLower(loc), strings.ToLower(setting.AppURL))) {
continue
@@ -264,6 +272,12 @@ func (ctx *Context) ServerError(logMsg string, logErr error) {
func (ctx *Context) serverErrorInternal(logMsg string, logErr error) {
if logErr != nil {
log.ErrorWithSkip(2, "%s: %v", logMsg, logErr)
if _, ok := logErr.(*net.OpError); ok || errors.Is(logErr, &net.OpError{}) {
// This is an error within the underlying connection
// and further rendering will not work so just return
return
}
if !setting.IsProd {
ctx.Data["ErrorMsg"] = logErr
}

View File

@@ -229,6 +229,7 @@ func Csrfer(opt CsrfOptions, ctx *Context) CSRF {
}
}
needsNew = needsNew || ctx.Req.Method == "GET" // If this request is a Get request, it will generate a new token, make sure the token is always up-to-date.
if needsNew {
// FIXME: actionId.
x.Token = GenerateToken(x.Secret, x.ID, "POST")

View File

@@ -129,7 +129,23 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
// Team.
if ctx.Org.IsMember {
shouldSeeAllTeams := false
if ctx.Org.IsOwner {
shouldSeeAllTeams = true
} else {
teams, err := org.GetUserTeams(ctx.User.ID)
if err != nil {
ctx.ServerError("GetUserTeams", err)
return
}
for _, team := range teams {
if team.IncludesAllRepositories && team.AccessMode >= perm.AccessModeAdmin {
shouldSeeAllTeams = true
break
}
}
}
if shouldSeeAllTeams {
ctx.Org.Teams, err = org.LoadTeams()
if err != nil {
ctx.ServerError("LoadTeams", err)

View File

@@ -410,6 +410,12 @@ func RepoIDAssignment() func(ctx *Context) {
// RepoAssignment returns a middleware to handle repository assignment
func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
log.Trace("RepoAssignment was exec already, skipping second call ...")
return
}
ctx.Data["repoAssignmentExecuted"] = true
var (
owner *user_model.User
err error
@@ -440,6 +446,26 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Repo.Owner = owner
ctx.Data["Username"] = ctx.Repo.Owner.Name
// redirect link to wiki
if strings.HasSuffix(repoName, ".wiki") {
// ctx.Req.URL.Path does not have the preceding appSubURL - any redirect must have this added
// Now we happen to know that all of our paths are: /:username/:reponame/whatever_else
originalRepoName := ctx.Params(":reponame")
redirectRepoName := strings.TrimSuffix(repoName, ".wiki")
redirectRepoName += originalRepoName[len(redirectRepoName)+5:]
redirectPath := strings.Replace(
ctx.Req.URL.EscapedPath(),
url.PathEscape(userName)+"/"+url.PathEscape(originalRepoName),
url.PathEscape(userName)+"/"+url.PathEscape(redirectRepoName)+"/wiki",
1,
)
if ctx.Req.URL.RawQuery != "" {
redirectPath += "?" + ctx.Req.URL.RawQuery
}
ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
return
}
// Get repository.
repo, err := repo_model.GetRepositoryByName(owner.ID, repoName)
if err != nil {
@@ -572,6 +598,9 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
return
}
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
ctx.Repo.GitRepo = gitRepo
// We opened it, we should close it
@@ -911,7 +940,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
if refType == RepoRefLegacy {
// redirect from old URL scheme to new URL scheme
prefix := strings.TrimPrefix(setting.AppSubURL+strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")), ctx.Repo.RepoLink)
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*"))), strings.ToLower(ctx.Repo.RepoLink))
ctx.Redirect(path.Join(
ctx.Repo.RepoLink,

View File

@@ -67,6 +67,7 @@ func ToAPIPullRequest(pr *models.PullRequest, doer *user_model.User) *api.PullRe
PatchURL: pr.Issue.PatchURL(),
HasMerged: pr.HasMerged,
MergeBase: pr.MergeBase,
Mergeable: pr.Mergeable(),
Deadline: apiIssue.Deadline,
Created: pr.Issue.CreatedUnix.AsTimePtr(),
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
@@ -190,10 +191,6 @@ func ToAPIPullRequest(pr *models.PullRequest, doer *user_model.User) *api.PullRe
}
}
if pr.Status != models.PullRequestStatusChecking {
mergeable := !(pr.Status == models.PullRequestStatusConflict || pr.Status == models.PullRequestStatusError) && !pr.IsWorkInProgress()
apiPullRequest.Mergeable = mergeable
}
if pr.HasMerged {
apiPullRequest.Merged = pr.MergedUnix.AsTimePtr()
apiPullRequest.MergedCommitID = &pr.MergedCommitID

View File

@@ -71,8 +71,8 @@ func checkAuthorizedKeys(logger log.Logger, autofix bool) error {
"authorized_keys file %q is out of date.\nRegenerate it with:\n\t\"%s\"\nor\n\t\"%s\"",
fPath,
"gitea admin regenerate keys",
"gitea doctor --run authorized_keys --fix")
return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized_keys --fix"`)
"gitea doctor --run authorized-keys --fix")
return fmt.Errorf(`authorized_keys is out of date and should be regenerated with "gitea admin regenerate keys" or "gitea doctor --run authorized-keys --fix"`)
}
logger.Warn("authorized_keys is out of date. Attempting rewrite...")
err = asymkey_model.RewriteAllPublicKeys()

View File

@@ -54,6 +54,12 @@ func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
<-closed
}
// Ensure cancel is called as soon as the provided context is cancelled
go func() {
<-ctx.Done()
cancel()
}()
_, filename, line, _ := runtime.Caller(2)
filename = strings.TrimPrefix(filename, callerPrefix)
@@ -93,6 +99,12 @@ func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
<-closed
}
// Ensure cancel is called as soon as the provided context is cancelled
go func() {
<-ctx.Done()
cancel()
}()
_, filename, line, _ := runtime.Caller(2)
filename = strings.TrimPrefix(filename, callerPrefix)

View File

@@ -17,6 +17,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/util"
)
var (
@@ -32,10 +33,11 @@ const DefaultLocale = "C"
// Command represents a command with its subcommands or arguments.
type Command struct {
name string
args []string
parentContext context.Context
desc string
name string
args []string
parentContext context.Context
desc string
globalArgsLength int
}
func (c *Command) String() string {
@@ -56,9 +58,10 @@ func NewCommandContext(ctx context.Context, args ...string) *Command {
cargs := make([]string, len(GlobalCommandArgs))
copy(cargs, GlobalCommandArgs)
return &Command{
name: GitExecutable,
args: append(cargs, args...),
parentContext: ctx,
name: GitExecutable,
args: append(cargs, args...),
parentContext: ctx,
globalArgsLength: len(GlobalCommandArgs),
}
}
@@ -145,7 +148,21 @@ func (c *Command) RunWithContext(rc *RunContext) error {
desc := c.desc
if desc == "" {
desc = fmt.Sprintf("%s %s [repo_path: %s]", c.name, strings.Join(c.args, " "), rc.Dir)
args := c.args[c.globalArgsLength:]
var argSensitiveURLIndexes []int
for i, arg := range c.args {
if strings.Contains(arg, "://") && strings.Contains(arg, "@") {
argSensitiveURLIndexes = append(argSensitiveURLIndexes, i)
}
}
if len(argSensitiveURLIndexes) > 0 {
args = make([]string, len(c.args))
copy(args, c.args)
for _, urlArgIndex := range argSensitiveURLIndexes {
args[urlArgIndex] = util.NewStringURLSanitizer(args[urlArgIndex], true).Replace(args[urlArgIndex])
}
}
desc = fmt.Sprintf("%s %s [repo_path: %s]", c.name, strings.Join(args, " "), rc.Dir)
}
ctx, cancel, finished := process.GetManager().AddContextTimeout(c.parentContext, rc.Timeout, desc)
@@ -163,6 +180,8 @@ func (c *Command) RunWithContext(rc *RunContext) error {
fmt.Sprintf("LC_ALL=%s", DefaultLocale),
// avoid prompting for credentials interactively, supported since git v2.3
"GIT_TERMINAL_PROMPT=0",
// ignore replace references (https://git-scm.com/docs/git-replace)
"GIT_NO_REPLACE_OBJECTS=1",
)
// TODO: verify if this is still needed in golang 1.15

View File

@@ -16,20 +16,25 @@ import (
"github.com/stretchr/testify/assert"
)
const testReposDir = "tests/repos/"
const benchmarkReposDir = "benchmark/repos/"
const (
testReposDir = "tests/repos/"
)
func cloneRepo(url, dir, name string) (string, error) {
repoDir := filepath.Join(dir, name)
if _, err := os.Stat(repoDir); err == nil {
return repoDir, nil
func cloneRepo(url, name string) (string, error) {
repoDir, err := os.MkdirTemp("", name)
if err != nil {
return "", err
}
return repoDir, Clone(url, repoDir, CloneRepoOptions{
if err := Clone(url, repoDir, CloneRepoOptions{
Mirror: false,
Bare: false,
Quiet: true,
Timeout: 5 * time.Minute,
})
}); err != nil {
_ = util.RemoveAll(repoDir)
return "", err
}
return repoDir, nil
}
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
@@ -59,20 +64,35 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
for _, testCase := range testCases {
commit, err := repo1.GetCommit(testCase.CommitID)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err, "Unable to get commit: %s from testcase due to error: %v", testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
assert.NotNil(t, commit)
assert.NotNil(t, commit.Tree)
assert.NotNil(t, commit.Tree.repo)
tree, err := commit.Tree.SubTree(testCase.Path)
if err != nil {
assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NoError(t, err)
entries, err := tree.ListEntries()
assert.NoError(t, err)
commitsInfo, treeCommit, err := entries.GetCommitsInfo(context.Background(), commit, testCase.Path, nil)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
continue
}
// FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain.
commitsInfo, treeCommit, err := entries.GetCommitsInfo(context.TODO(), commit, testCase.Path, nil)
assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
if err != nil {
t.FailNow()
}
@@ -98,40 +118,52 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
testGetCommitsInfo(t, bareRepo1)
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestEntries_GetCommitsInfo")
assert.NoError(t, err)
clonedPath, err := cloneRepo(bareRepo1Path, "repo1_TestEntries_GetCommitsInfo")
if err != nil {
assert.NoError(t, err)
}
defer util.RemoveAll(clonedPath)
clonedRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
}
defer clonedRepo1.Close()
testGetCommitsInfo(t, clonedRepo1)
}
func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
benchmarks := []struct {
type benchmarkType struct {
url string
name string
}{
}
benchmarks := []benchmarkType{
{url: "https://github.com/go-gitea/gitea.git", name: "gitea"},
{url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"},
{url: "https://github.com/moby/moby.git", name: "moby"},
{url: "https://github.com/golang/go.git", name: "go"},
{url: "https://github.com/torvalds/linux.git", name: "linux"},
}
for _, benchmark := range benchmarks {
doBenchmark := func(benchmark benchmarkType) {
var commit *Commit
var entries Entries
var repo *Repository
if repoPath, err := cloneRepo(benchmark.url, benchmarkReposDir, benchmark.name); err != nil {
repoPath, err := cloneRepo(benchmark.url, benchmark.name)
if err != nil {
b.Fatal(err)
} else if repo, err = OpenRepository(repoPath); err != nil {
}
defer util.RemoveAll(repoPath)
if repo, err = OpenRepository(repoPath); err != nil {
b.Fatal(err)
} else if commit, err = repo.GetBranchCommit("master"); err != nil {
repo.Close()
}
defer repo.Close()
if commit, err = repo.GetBranchCommit("master"); err != nil {
b.Fatal(err)
} else if entries, err = commit.Tree.ListEntries(); err != nil {
repo.Close()
b.Fatal(err)
}
entries.Sort()
@@ -144,6 +176,9 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
}
}
})
repo.Close()
}
for _, benchmark := range benchmarks {
doBenchmark(benchmark)
}
}

View File

@@ -112,8 +112,8 @@ func SetExecutablePath(path string) error {
// VersionInfo returns git version information
func VersionInfo() string {
var format = "Git Version: %s"
var args = []interface{}{gitVersion.Original()}
format := "Git Version: %s"
args := []interface{}{gitVersion.Original()}
// Since git wire protocol has been released from git v2.18
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
format += ", Wire Protocol %s Enabled"
@@ -148,7 +148,7 @@ func Init(ctx context.Context) error {
// By default partial clones are disabled, enable them from git v2.22
if !setting.Git.DisablePartialClone && CheckGitVersionAtLeast("2.22") == nil {
GlobalCommandArgs = append(GlobalCommandArgs, "-c", "uploadpack.allowfilter=true")
GlobalCommandArgs = append(GlobalCommandArgs, "-c", "uploadpack.allowfilter=true", "-c", "uploadpack.allowAnySHA1InWant=true")
}
// Save current git version on init to gitVersion otherwise it would require an RWMutex

View File

@@ -19,6 +19,7 @@ import (
"time"
"code.gitea.io/gitea/modules/proxy"
"code.gitea.io/gitea/modules/util"
)
// GPGSettings represents the default GPG settings for this repository
@@ -80,33 +81,33 @@ func InitRepository(repoPath string, bare bool) error {
// IsEmpty Check if repository is empty.
func (repo *Repository) IsEmpty() (bool, error) {
var errbuf, output strings.Builder
if err := NewCommandContext(repo.Ctx, "rev-list", "--all", "--count", "--max-count=1").RunWithContext(&RunContext{
if err := NewCommandContext(repo.Ctx, "show-ref", "--head", "^HEAD$").RunWithContext(&RunContext{
Timeout: -1,
Dir: repo.Path,
Stdout: &output,
Stderr: &errbuf,
}); err != nil {
if err.Error() == "exit status 1" && errbuf.String() == "" {
return true, nil
}
return true, fmt.Errorf("check empty: %v - %s", err, errbuf.String())
}
c, err := strconv.Atoi(strings.TrimSpace(output.String()))
if err != nil {
return true, fmt.Errorf("check empty: convert %s to count failed: %v", output.String(), err)
}
return c == 0, nil
return strings.TrimSpace(output.String()) == "", nil
}
// CloneRepoOptions options when clone a repository
type CloneRepoOptions struct {
Timeout time.Duration
Mirror bool
Bare bool
Quiet bool
Branch string
Shared bool
NoCheckout bool
Depth int
Filter string
Timeout time.Duration
Mirror bool
Bare bool
Quiet bool
Branch string
Shared bool
NoCheckout bool
Depth int
Filter string
SkipTLSVerify bool
}
// Clone clones original repository to target path.
@@ -129,6 +130,9 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
}
cmd := NewCommandContextNoGlobals(ctx, args...).AddArguments("clone")
if opts.SkipTLSVerify {
cmd.AddArguments("-c", "http.sslVerify=false")
}
if opts.Mirror {
cmd.AddArguments("--mirror")
}
@@ -155,6 +159,12 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
}
cmd.AddArguments("--", from, to)
if strings.Contains(from, "://") && strings.Contains(from, "@") {
cmd.SetDescription(fmt.Sprintf("clone branch %s from %s to %s (shared: %t, mirror: %t, depth: %d)", opts.Branch, util.NewStringURLSanitizer(from, true).Replace(from), to, opts.Shared, opts.Mirror, opts.Depth))
} else {
cmd.SetDescription(fmt.Sprintf("clone branch %s from %s to %s (shared: %t, mirror: %t, depth: %d)", opts.Branch, from, to, opts.Shared, opts.Mirror, opts.Depth))
}
if opts.Timeout <= 0 {
opts.Timeout = -1
}
@@ -231,6 +241,11 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
if len(opts.Branch) > 0 {
cmd.AddArguments(opts.Branch)
}
if strings.Contains(opts.Remote, "://") && strings.Contains(opts.Remote, "@") {
cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, util.NewStringURLSanitizer(opts.Remote, true).Replace(opts.Remote), opts.Force, opts.Mirror))
} else {
cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, opts.Remote, opts.Force, opts.Mirror))
}
var outbuf, errbuf strings.Builder
if opts.Timeout == 0 {

View File

@@ -87,7 +87,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
return nil, fmt.Errorf("wrong number of fields in return from check-attr")
}
var name2attribute2info = make(map[string]map[string]string)
name2attribute2info := make(map[string]map[string]string)
for i := 0; i < (len(fields) / 3); i++ {
filename := string(fields[3*i])
@@ -119,12 +119,10 @@ type CheckAttributeReader struct {
env []string
ctx context.Context
cancel context.CancelFunc
running chan struct{}
}
// Init initializes the cmd
func (c *CheckAttributeReader) Init(ctx context.Context) error {
c.running = make(chan struct{})
cmdArgs := []string{"check-attr", "--stdin", "-z"}
if len(c.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil {
@@ -179,17 +177,16 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
// Run run cmd
func (c *CheckAttributeReader) Run() error {
defer func() {
_ = c.Close()
_ = c.stdinReader.Close()
_ = c.stdOut.Close()
}()
stdErr := new(bytes.Buffer)
err := c.cmd.RunInDirTimeoutEnvFullPipelineFunc(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader, func(_ context.Context, _ context.CancelFunc) error {
close(c.running)
return nil
})
if err != nil && c.ctx.Err() != nil && err.Error() != "signal: killed" {
err := c.cmd.RunInDirTimeoutEnvFullPipeline(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader)
if err != nil && // If there is an error we need to return but:
c.ctx.Err() != err && // 1. Ignore the context error if the context is cancelled or exceeds the deadline (RunWithContext could return c.ctx.Err() which is Canceled or DeadlineExceeded)
err.Error() != "signal: killed" { // 2. We should not pass up errors due to the program being killed
return fmt.Errorf("failed to run attr-check. Error: %w\nStderr: %s", err, stdErr.String())
}
return nil
}
@@ -204,7 +201,7 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
select {
case <-c.ctx.Done():
return nil, c.ctx.Err()
case <-c.running:
default:
}
if _, err = c.stdinWriter.Write([]byte(path + "\x00")); err != nil {
@@ -229,15 +226,8 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
// Close close pip after use
func (c *CheckAttributeReader) Close() error {
err := c.stdinWriter.Close()
_ = c.stdinReader.Close()
_ = c.stdOut.Close()
c.cancel()
select {
case <-c.running:
default:
close(c.running)
}
err := c.stdinWriter.Close()
return err
}

View File

@@ -13,6 +13,7 @@ import (
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// IsObjectExist returns true if given reference exists in the repository.
@@ -82,7 +83,8 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
}
// WalkReferences walks all the references from the repository
func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) error) (int, error) {
// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
repo, err := OpenRepositoryCtx(ctx, repoPath)
if err != nil {
return 0, err
@@ -97,9 +99,45 @@ func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) er
defer iter.Close()
err = iter.ForEach(func(ref *plumbing.Reference) error {
err := walkfn(string(ref.Name()))
err := walkfn(ref.Hash().String(), string(ref.Name()))
i++
return err
})
return i, err
}
// WalkReferences walks all the references from the repository
func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
i := 0
var iter storer.ReferenceIter
var err error
switch arg {
case ObjectTag:
iter, err = repo.gogitRepo.Tags()
case ObjectBranch:
iter, err = repo.gogitRepo.Branches()
default:
iter, err = repo.gogitRepo.References()
}
if err != nil {
return i, err
}
defer iter.Close()
err = iter.ForEach(func(ref *plumbing.Reference) error {
if i < skip {
i++
return nil
}
err := walkfn(ref.Hash().String(), string(ref.Name()))
i++
if err != nil {
return err
}
if limit != 0 && i >= skip+limit {
return storer.ErrStop
}
return nil
})
return i, err
}

View File

@@ -68,13 +68,29 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
}
// WalkReferences walks all the references from the repository
func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) error) (int, error) {
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
return walkShowRef(ctx, repoPath, "", 0, 0, walkfn)
}
// WalkReferences walks all the references from the repository
// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
var arg string
switch refType {
case ObjectTag:
arg = "--tags"
case ObjectBranch:
arg = "--heads"
default:
arg = ""
}
return walkShowRef(repo.Ctx, repo.Path, arg, skip, limit, walkfn)
}
// callShowRef return refs, if limit = 0 it will not limit
func callShowRef(ctx context.Context, repoPath, prefix, arg string, skip, limit int) (branchNames []string, countAll int, err error) {
countAll, err = walkShowRef(ctx, repoPath, arg, skip, limit, func(branchName string) error {
countAll, err = walkShowRef(ctx, repoPath, arg, skip, limit, func(_, branchName string) error {
branchName = strings.TrimPrefix(branchName, prefix)
branchNames = append(branchNames, branchName)
@@ -83,7 +99,7 @@ func callShowRef(ctx context.Context, repoPath, prefix, arg string, skip, limit
return
}
func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, walkfn func(string) error) (countAll int, err error) {
func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
stdoutReader, stdoutWriter := io.Pipe()
defer func() {
_ = stdoutReader.Close()
@@ -125,11 +141,7 @@ func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, wal
for limit == 0 || i < skip+limit {
// The output of show-ref is simply a list:
// <sha> SP <ref> LF
_, err := bufReader.ReadSlice(' ')
for err == bufio.ErrBufferFull {
// This shouldn't happen but we'll tolerate it for the sake of peace
_, err = bufReader.ReadSlice(' ')
}
sha, err := bufReader.ReadString(' ')
if err == io.EOF {
return i, nil
}
@@ -149,7 +161,12 @@ func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, wal
if len(branchName) > 0 {
branchName = branchName[:len(branchName)-1]
}
err = walkfn(branchName)
if len(sha) > 0 {
sha = sha[:len(sha)-1]
}
err = walkfn(sha, branchName)
if err != nil {
return i, err
}

View File

@@ -0,0 +1,21 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"context"
"fmt"
)
// WriteCommitGraph write commit graph to speed up repo access
// this requires git v2.18 to be installed
func WriteCommitGraph(ctx context.Context, repoPath string) error {
if CheckGitVersionAtLeast("2.18") == nil {
if _, err := NewCommandContext(ctx, "commit-graph", "write").RunInDir(repoPath); err != nil {
return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err)
}
}
return nil
}

View File

@@ -17,17 +17,33 @@ import (
func TestGetFormatPatch(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestGetFormatPatch")
clonedPath, err := cloneRepo(bareRepo1Path, "repo1_TestGetFormatPatch")
if err != nil {
assert.NoError(t, err)
return
}
defer util.RemoveAll(clonedPath)
assert.NoError(t, err)
repo, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
defer repo.Close()
assert.NoError(t, err)
rd := &bytes.Buffer{}
err = repo.GetPatch("8d92fc95^", "8d92fc95", rd)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
patchb, err := io.ReadAll(rd)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
patch := string(patchb)
assert.Regexp(t, "^From 8d92fc95", patch)
assert.Contains(t, patch, "Subject: [PATCH] Add file2.txt")
@@ -37,17 +53,25 @@ func TestReadPatch(t *testing.T) {
// Ensure we can read the patch files
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
if err != nil {
assert.NoError(t, err)
return
}
defer repo.Close()
assert.NoError(t, err)
// This patch doesn't exist
noFile, err := repo.ReadPatchCommit(0)
assert.Error(t, err)
// This patch is an empty one (sometimes it's a 404)
noCommit, err := repo.ReadPatchCommit(1)
assert.Error(t, err)
// This patch is legit and should return a commit
oldCommit, err := repo.ReadPatchCommit(2)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.Empty(t, noFile)
assert.Empty(t, noCommit)
@@ -58,23 +82,45 @@ func TestReadPatch(t *testing.T) {
func TestReadWritePullHead(t *testing.T) {
// Ensure we can write SHA1 head corresponding to PR and open them
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err)
// As we are writing we should clone the repository first
clonedPath, err := cloneRepo(bareRepo1Path, "TestReadWritePullHead")
if err != nil {
assert.NoError(t, err)
return
}
defer util.RemoveAll(clonedPath)
repo, err := OpenRepository(clonedPath)
if err != nil {
assert.NoError(t, err)
return
}
defer repo.Close()
// Try to open non-existing Pull
_, err = repo.GetRefCommitID(PullPrefix + "0/head")
assert.Error(t, err)
// Write a fake sha1 with only 40 zeros
newCommit := "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"
err = repo.SetReference(PullPrefix+"1/head", newCommit)
assert.NoError(t, err)
// Remove file after the test
defer func() {
_ = repo.RemoveReference(PullPrefix + "1/head")
}()
if err != nil {
assert.NoError(t, err)
return
}
// Read the file created
headContents, err := repo.GetRefCommitID(PullPrefix + "1/head")
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.Len(t, string(headContents), 40)
assert.True(t, string(headContents) == newCommit)
// Remove file after the test
err = repo.RemoveReference(PullPrefix + "1/head")
assert.NoError(t, err)
}

View File

@@ -88,7 +88,10 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
}
}()
}
defer cancel()
defer func() {
_ = checker.Close()
cancel()
}()
}
}

View File

@@ -10,7 +10,6 @@ import (
"fmt"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)
@@ -34,69 +33,6 @@ func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error
return err
}
func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
t, ok := repo.tagCache.Get(tagID.String())
if ok {
log.Debug("Hit cache: %s", tagID)
tagClone := *t.(*Tag)
tagClone.Name = name // This is necessary because lightweight tags may have same id
return &tagClone, nil
}
tp, err := repo.GetTagType(tagID)
if err != nil {
return nil, err
}
// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
commitIDStr, err := repo.GetTagCommitID(name)
if err != nil {
// every tag should have a commit ID so return all errors
return nil, err
}
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}
// If type is "commit, the tag is a lightweight tag
if ObjectType(tp) == ObjectCommit {
commit, err := repo.GetCommit(commitIDStr)
if err != nil {
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: commitID,
Type: tp,
Tagger: commit.Committer,
Message: commit.Message(),
}
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}
// The tag is an annotated tag with a message.
data, err := NewCommandContext(repo.Ctx, "cat-file", "-p", tagID.String()).RunInDirBytes(repo.Path)
if err != nil {
return nil, err
}
tag, err := parseTagData(data)
if err != nil {
return nil, err
}
tag.Name = name
tag.ID = tagID
tag.Type = tp
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}
// GetTagNameBySHA returns the name of a tag from its tag object SHA or commit SHA
func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
if len(sha) < 5 {
@@ -159,6 +95,20 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
return tag, nil
}
// GetTagWithID returns a Git tag by given name and ID
func (repo *Repository) GetTagWithID(idStr, name string) (*Tag, error) {
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}
tag, err := repo.getTag(id, name)
if err != nil {
return nil, err
}
return tag, nil
}
// GetTagInfos returns all tag infos of the repository.
func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
// TODO this a slow implementation, makes one git command per tag
@@ -192,19 +142,6 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
return tags, tagsTotal, nil
}
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
func (repo *Repository) GetTagType(id SHA1) (string, error) {
// Get tag type
stdout, err := NewCommandContext(repo.Ctx, "cat-file", "-t", id.String()).RunInDir(repo.Path)
if err != nil {
return "", err
}
if len(stdout) == 0 {
return "", ErrNotExist{ID: id.String()}
}
return strings.TrimSpace(stdout), nil
}
// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
id, err := NewIDFromString(sha)

View File

@@ -11,6 +11,8 @@ package git
import (
"strings"
"code.gitea.io/gitea/modules/log"
"github.com/go-git/go-git/v5/plumbing"
)
@@ -53,3 +55,83 @@ func (repo *Repository) GetTags(skip, limit int) ([]string, error) {
return tagNames, nil
}
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
func (repo *Repository) GetTagType(id SHA1) (string, error) {
// Get tag type
obj, err := repo.gogitRepo.Object(plumbing.AnyObject, id)
if err != nil {
if err == plumbing.ErrReferenceNotFound {
return "", &ErrNotExist{ID: id.String()}
}
return "", err
}
return obj.Type().String(), nil
}
func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
t, ok := repo.tagCache.Get(tagID.String())
if ok {
log.Debug("Hit cache: %s", tagID)
tagClone := *t.(*Tag)
tagClone.Name = name // This is necessary because lightweight tags may have same id
return &tagClone, nil
}
tp, err := repo.GetTagType(tagID)
if err != nil {
return nil, err
}
// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
commitIDStr, err := repo.GetTagCommitID(name)
if err != nil {
// every tag should have a commit ID so return all errors
return nil, err
}
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}
// If type is "commit, the tag is a lightweight tag
if ObjectType(tp) == ObjectCommit {
commit, err := repo.GetCommit(commitIDStr)
if err != nil {
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: commitID,
Type: tp,
Tagger: commit.Committer,
Message: commit.Message(),
}
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}
gogitTag, err := repo.gogitRepo.TagObject(tagID)
if err != nil {
if err == plumbing.ErrReferenceNotFound {
return nil, &ErrNotExist{ID: tagID.String()}
}
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: gogitTag.Target,
Type: tp,
Tagger: &gogitTag.Tagger,
Message: gogitTag.Message,
}
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}

View File

@@ -8,6 +8,13 @@
package git
import (
"errors"
"io"
"code.gitea.io/gitea/modules/log"
)
// IsTagExist returns true if given tag exists in the repository.
func (repo *Repository) IsTagExist(name string) bool {
if name == "" {
@@ -23,3 +30,104 @@ func (repo *Repository) GetTags(skip, limit int) (tags []string, err error) {
tags, _, err = callShowRef(repo.Ctx, repo.Path, TagPrefix, "--tags", skip, limit)
return
}
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
func (repo *Repository) GetTagType(id SHA1) (string, error) {
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
defer cancel()
_, err := wr.Write([]byte(id.String() + "\n"))
if err != nil {
return "", err
}
_, typ, _, err := ReadBatchLine(rd)
if IsErrNotExist(err) {
return "", ErrNotExist{ID: id.String()}
}
return typ, nil
}
func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
t, ok := repo.tagCache.Get(tagID.String())
if ok {
log.Debug("Hit cache: %s", tagID)
tagClone := *t.(*Tag)
tagClone.Name = name // This is necessary because lightweight tags may have same id
return &tagClone, nil
}
tp, err := repo.GetTagType(tagID)
if err != nil {
return nil, err
}
// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
commitIDStr, err := repo.GetTagCommitID(name)
if err != nil {
// every tag should have a commit ID so return all errors
return nil, err
}
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}
// If type is "commit, the tag is a lightweight tag
if ObjectType(tp) == ObjectCommit {
commit, err := repo.GetCommit(commitIDStr)
if err != nil {
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: commitID,
Type: tp,
Tagger: commit.Committer,
Message: commit.Message(),
}
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}
// The tag is an annotated tag with a message.
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
defer cancel()
if _, err := wr.Write([]byte(tagID.String() + "\n")); err != nil {
return nil, err
}
_, typ, size, err := ReadBatchLine(rd)
if err != nil {
if errors.Is(err, io.EOF) || IsErrNotExist(err) {
return nil, ErrNotExist{ID: tagID.String()}
}
return nil, err
}
if typ != "tag" {
return nil, ErrNotExist{ID: tagID.String()}
}
// then we need to parse the tag
// and load the commit
data, err := io.ReadAll(io.LimitReader(rd, size))
if err != nil {
return nil, err
}
_, err = rd.Discard(1)
if err != nil {
return nil, err
}
tag, err := parseTagData(data)
if err != nil {
return nil, err
}
tag.Name = name
tag.ID = tagID
tag.Type = tp
repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}

View File

@@ -16,11 +16,17 @@ import (
func TestRepository_GetTags(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
defer bareRepo1.Close()
tags, total, err := bareRepo1.GetTagInfos(0, 0)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.Len(t, tags, 1)
assert.Equal(t, len(tags), total)
assert.EqualValues(t, "test", tags[0].Name)
@@ -31,40 +37,75 @@ func TestRepository_GetTags(t *testing.T) {
func TestRepository_GetTag(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag")
assert.NoError(t, err)
clonedPath, err := cloneRepo(bareRepo1Path, "TestRepository_GetTag")
if err != nil {
assert.NoError(t, err)
return
}
defer util.RemoveAll(clonedPath)
bareRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
defer bareRepo1.Close()
// LIGHTWEIGHT TAGS
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
lTagName := "lightweightTag"
bareRepo1.CreateTag(lTagName, lTagCommitID)
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
aTagName := "annotatedTag"
aTagMessage := "my annotated message \n - test two line"
bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
aTagID, _ := bareRepo1.GetTagID(aTagName)
// Create the lightweight tag
err = bareRepo1.CreateTag(lTagName, lTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the lightweight tag: %s for ID: %s. Error: %v", lTagName, lTagCommitID, err)
return
}
// and try to get the Tag for lightweight tag
lTag, err := bareRepo1.GetTag(lTagName)
assert.NoError(t, err)
assert.NotNil(t, lTag)
if err != nil {
assert.NoError(t, err)
return
}
if lTag == nil {
assert.NotNil(t, lTag)
assert.FailNow(t, "nil lTag: %s", lTagName)
return
}
assert.EqualValues(t, lTagName, lTag.Name)
assert.EqualValues(t, lTagCommitID, lTag.ID.String())
assert.EqualValues(t, lTagCommitID, lTag.Object.String())
assert.EqualValues(t, "commit", lTag.Type)
// ANNOTATED TAGS
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
aTagName := "annotatedTag"
aTagMessage := "my annotated message \n - test two line"
// Create the annotated tag
err = bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the annotated tag: %s for ID: %s. Error: %v", aTagName, aTagCommitID, err)
return
}
// Now try to get the tag for the annotated Tag
aTagID, err := bareRepo1.GetTagID(aTagName)
if err != nil {
assert.NoError(t, err)
return
}
aTag, err := bareRepo1.GetTag(aTagName)
assert.NoError(t, err)
assert.NotNil(t, aTag)
if err != nil {
assert.NoError(t, err)
return
}
if aTag == nil {
assert.NotNil(t, aTag)
assert.FailNow(t, "nil aTag: %s", aTagName)
return
}
assert.EqualValues(t, aTagName, aTag.Name)
assert.EqualValues(t, aTagID, aTag.ID.String())
@@ -72,26 +113,47 @@ func TestRepository_GetTag(t *testing.T) {
assert.EqualValues(t, aTagCommitID, aTag.Object.String())
assert.EqualValues(t, "tag", aTag.Type)
// RELEASE TAGS
rTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
rTagName := "release/" + lTagName
bareRepo1.CreateTag(rTagName, rTagCommitID)
err = bareRepo1.CreateTag(rTagName, rTagCommitID)
if err != nil {
assert.NoError(t, err, "Unable to create the tag: %s for ID: %s. Error: %v", rTagName, rTagCommitID, err)
return
}
rTagID, err := bareRepo1.GetTagID(rTagName)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.EqualValues(t, rTagCommitID, rTagID)
oTagID, err := bareRepo1.GetTagID(lTagName)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.EqualValues(t, lTagCommitID, oTagID)
}
func TestRepository_GetAnnotatedTag(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag")
assert.NoError(t, err)
clonedPath, err := cloneRepo(bareRepo1Path, "TestRepository_GetAnnotatedTag")
if err != nil {
assert.NoError(t, err)
return
}
defer util.RemoveAll(clonedPath)
bareRepo1, err := OpenRepository(clonedPath)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
defer bareRepo1.Close()
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
@@ -106,7 +168,10 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
// Try an annotated tag
tag, err := bareRepo1.GetAnnotatedTag(aTagID)
assert.NoError(t, err)
if err != nil {
assert.NoError(t, err)
return
}
assert.NotNil(t, tag)
assert.EqualValues(t, aTagName, tag.Name)
assert.EqualValues(t, aTagID, tag.ID.String())

View File

@@ -192,6 +192,7 @@ func (g *Manager) RunAtHammer(hammer func()) {
}
func (g *Manager) doShutdown() {
if !g.setStateTransition(stateRunning, stateShuttingDown) {
g.DoImmediateHammer()
return
}
g.lock.Lock()

View File

@@ -168,8 +168,12 @@ func (g *Manager) DoGracefulRestart() {
if setting.GracefulRestartable {
log.Info("PID: %d. Forking...", os.Getpid())
err := g.doFork()
if err != nil && err.Error() != "another process already forked. Ignoring this one" {
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
if err != nil {
if err.Error() == "another process already forked. Ignoring this one" {
g.DoImmediateHammer()
} else {
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
}
}
} else {
log.Info("PID: %d. Not set restartable. Shutting down...", os.Getpid())

View File

@@ -40,20 +40,19 @@ steps:
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
`,
want: []string{
`<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
`<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span>`,
`<span class="w">
</span>`,
`<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
`<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
`<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
`<span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
`<span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
`<span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
`<span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
`<span class="w"> </span>- <span class="l">go build -v</span>`,
`<span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span><span class="w">
</span>`,
`<span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default</span>`,
`</span></span><span class="line"><span class="cl">`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">go build -v</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span><span class="w">
</span></span></span>`,
`<span class="w">
</span>`,
},
@@ -76,20 +75,19 @@ steps:
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
`,
want: []string{
`<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
`<span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default </span>`,
`<span class="w">
</span>`,
`<span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
`<span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
`<span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
`<span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
`<span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
`<span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
`<span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
`<span class="w"> </span>- <span class="l">go build -v</span>`,
`<span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span>`,
`<span class="w"> </span>`,
`<span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">pipeline</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">default </span>`,
`</span></span><span class="line"><span class="cl">`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">steps</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">test</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">golang:1.13</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="w"> </span><span class="nt">GOPROXY</span><span class="p">:</span><span class="w"> </span><span class="l">https://goproxy.cn</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">commands</span><span class="p">:</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"></span><span class="w"> </span>- <span class="l">go get -u</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">go build -v</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">go test -v -race -coverprofile=coverage.txt -covermode=atomic</span>`,
`</span></span><span class="line"><span class="cl"><span class="w"> </span></span></span>`,
},
},
}

View File

@@ -127,13 +127,18 @@ func (hl *HostMatchList) checkIP(ip net.IP) bool {
// MatchHostName checks if the host matches an allow/deny(block) list
func (hl *HostMatchList) MatchHostName(host string) bool {
hostname, _, err := net.SplitHostPort(host)
if err != nil {
hostname = host
}
if hl == nil {
return false
}
if hl.checkPattern(host) {
if hl.checkPattern(hostname) {
return true
}
if ip := net.ParseIP(host); ip != nil {
if ip := net.ParseIP(hostname); ip != nil {
return hl.checkIP(ip)
}
return false

View File

@@ -38,6 +38,7 @@ func TestHostOrIPMatchesList(t *testing.T) {
{"", net.ParseIP("10.0.1.1"), true},
{"10.0.1.1", nil, true},
{"10.0.1.1:8080", nil, true},
{"", net.ParseIP("192.168.1.1"), true},
{"192.168.1.1", nil, true},
{"", net.ParseIP("fd00::1"), true},
@@ -48,6 +49,7 @@ func TestHostOrIPMatchesList(t *testing.T) {
{"mydomain.com", net.IPv4zero, false},
{"sub.mydomain.com", net.IPv4zero, true},
{"sub.mydomain.com:8080", net.IPv4zero, true},
{"", net.ParseIP("169.254.1.1"), true},
{"169.254.1.1", nil, true},

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