Compare commits

..

121 Commits

Author SHA1 Message Date
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
Lunny Xiao
bb77e6c12d Add changelog for v1.16.1 (#18614)
Add changelog for v1.16.1

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: zeripath <art27@cantab.net>
2022-02-06 12:35:24 +00:00
singuliere
fabc0ad157 comments on migrated issues/prs must link to the comment ID (#18637)
Instead of the issue ID which is not a valid anchor.

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

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-06 19:40:08 +08:00
zeripath
a13fb154ae Stop logging an error when notes are not found (#18626) (#18635)
Backport #18626

This is an unnecessary logging event.

Fix #18616

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-06 09:43:15 +00:00
zeripath
36c66303df Only attempt to flush queue if the underlying worker pool is not finished (#18593) (#18620)
* Only attempt to flush queue if the underlying worker pool is not finished (#18593)

Backport #18593

There is a possible race whereby a worker pool could be cancelled but yet the
underlying queue is not empty. This will lead to flush-all cycling because it
cannot empty the pool.

* On shutdown of Persistant Channel Queues close datachan and empty

Partial Backport #18415

Although we attempt to empty the datachan in queues - due to
races we are better off just closing the channel and forcibly emptying
it in shutdown.

Fix #18618

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

* Move zero workers warning to debug

Fix #18617

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

* Update modules/queue/manager.go

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

* Update modules/queue/manager.go

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

Co-authored-by: Gusted <williamzijl7@hotmail.com>
2022-02-06 14:55:44 +08:00
zeripath
f65e29c077 Ensure that blob-excerpt links work for wiki (#18587) (#18624)
Backport #18587

It appears that the blob-excerpt links do not work on the wiki - likely since their
introduction.

This PR adds support for the wiki on these links.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-06 04:22:20 +00:00
zeripath
a97c8a8966 Attempt to prevent intermittent failure TestGit/xxx/BranchProtectMerge/MergePR (#18451) (#18619)
Backport #18451

One of the repeated intermittent failures we see in testing is a failure due to
branches not being ready to merge.

Prior to the immediate queue implementation we would attempt to flush all the queues
and this would prevent the issue. However, the immediate queue is not flushable so
the flushall is not successful at preventing this.

This PR proposes an alternative solution - wait some time and try again up to 5 times.

If this fails then there is a genuine issue and we should fail.

Related #17719

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-05 20:49:53 +00:00
zeripath
69b7776af5 Ensure commit-statuses box is sized correctly in headers (#18538) (#18606)
* Ensure commit-statuses box is sized correctly in headers (#18538)

Backport #18538
Backport #18605

* Ensure commit-statuses box is sized correctly in headers

When viewing commits as commits the commit-status box will be fixed at 30px in height
due to being forced to be this size by a fomantic selector. This PR simply adds a
few more selectors to force this to have height auto.

Fix #18498

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

* Remove the spurious space in the .ui.right additional selector

Somehow a spurious space sneaked in to #18538
this PR simply removes it.

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

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-02-04 18:03:41 +01:00
zeripath
18c1edf15c Prevent merge messages from being sorted to the top of email chains (#18566) (#18588)
Backport #18566

Gitea will currrently resend the same message-id for the closed/merged/reopened
messages for issues. This will cause the merged message to leap to the top of an
email chain and become out of sync.

This PR adds specific suffices for these actions.

Fix #18560

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-04 08:30:36 +00:00
zeripath
70ffec4509 Fix pushing to 1-x-dev docker tag (#18578) (#18579)
* Fix pushing to 1-x-dev docker tag

It appears that #18551 and #18573 have a mistake in that raymond does not have
an {{else}} on {{#equal}}. This PR notes that Sprig has a hasPrefix function
and so we use this with another if.

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

* Fix pushing to 1-x-dev docker tag (part 2)

Although we now have the manifest working, we need to create the images.

Here we adjust the .drone.yml to force building of the images

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

* Fix pushing to 1-x-dev docker tag

OK now we have the images building we should make sure that the main ones stays
dev and the release/v* ones become *-dev-*

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-03 21:46:24 +00:00
zeripath
bc196a35e1 Collaborator trust model should trust collaborators (#18539) (#18557)
Backport #18539

There was an unintended regression in #17917 which leads to only
repository admin commits being trusted. This PR restores the old logic.

Fix #18501

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

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-03 11:20:37 -05:00
zeripath
8d31cfbfff Prevent panic on prohibited user login with oauth2 (#18562) (#18563)
Backport #18562

There was an unfortunate regression in #17962 where following detection of the
UserProhibitLogin error the err is cast to a pointer by mistake.

This causes a panic due to an interface error.

Fix #18561

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-03 21:36:42 +08:00
zeripath
e84a432f76 Make docker gitea/gitea:v1.16-dev etc refer to the latest build on that branch (#18551) (#18569)
Backport #18551

(Backporting this will enable this target to create 1.16-dev)

One of the problems with our current docker tagging is that although we
have strict version tags, latest and dev we do not have a way for docker
users to track the current release branch. This PR simply suggests that
we use the 1.x-dev tag for these and we build and push these. This will
give users who want or need unreleased bug fixes the option of tracking
the pre-release version instead of simply jumping to dev.

(Also contains backport for #18573)

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2022-02-03 12:00:33 +00:00
fnetX (aka fralix)
1fc9f11253 Add dropdown icon to template loading dropdown (#18571) 2022-02-03 11:28:27 +01:00
zeripath
0dfe5fa2d6 Detect conflicts with 3way merge (#18536) (#18537)
Backport #18536

Unforunately git apply --3way reports conflicts differently than standard patches
resulting in conflicts being missed.

Adjust the conflict detection code to account for this different error reporting.

Fix #18514

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-02 14:35:25 +00:00
silverwind
1d17313949 Update JS dependencies, fix lint (#18389) (#18540)
- Update all JS dependencies, including a security issue in mermaid
- Fix new linter errors related to value-keyword-case
- Tested Mermaid and Swagger

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-02-02 08:42:23 +00:00
zeripath
9c318a17f5 Add GetUserTeams (#18499) (#18531)
Backport #18499

* Correct use `UserID` in `SearchTeams`

- Use `UserID` in the `SearchTeams` function, currently it was useless
to pass such information. Now it does a INNER statement to `team_user`
which obtains UserID -> TeamID data.
- Make OrgID optional.
- Resolves #18484

* Seperate searching specific user

* Add condition back

* Use correct struct type

Co-authored-by: Gusted <williamzijl7@hotmail.com>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-02-02 08:40:04 +00:00
zeripath
72fa108cbc Fix review excerpt (#18502) (#18530)
Backport #18502

Currently the "File Changed" tab of a PR is somehow broken. This is also true for the current release 1.16.0.

When you are on the "File Changed" tab, and want to look at code excerpt before or after the code changes, the layout breaks. You can test this on try.gitea.io here: https://try.gitea.io/testnotexisting/magic_enum/pulls/2/files

The problem occurs for the unified view and for the split view.

Kind of the same problem was there for commenting a line of code, this was fixed in #18321 and #18403.

For consistency, I changed the solution of #18321, I removed the ``colspan`` and instead added a ``<td>``. The goal was to have code similarly with the split view.

Also the separator line in the split view was in the wrong column, this was fixed too.* more consistent unified review comment

Fix #18516

Co-authored-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: confusedsushi <confused.sushi@googlemail.com>
2022-02-02 08:38:28 +00:00
zeripath
db134c5d71 Fix for AvatarURL database type (#18487) (#18529)
Backport #18487

Co-authored-by: Viktor Kuzmin <kvaster@gmail.com>
2022-02-02 11:30:52 +08:00
zeripath
73b68015de In docker rootless use $GITEA_APP_INI if provided (#18524) (#18535)
Currently when calling `gitea` from any shell in rootless docker image it won't respect my `$GITEA_APP_INI`. Which this change it will use that value when defined instead of the default value.

- https://discourse.gitea.io/t/gitea-1-16-0-unable-to-find-configuration-file/4543
- https://gitea.com/gitea/helm-chart/issues/287

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2022-02-01 17:46:45 -05:00
zeripath
e4919e414f Update 1.16.0 changelog to set #17846 as breaking (#18533) (#18534)
Backport #18533

Unfortunately #17846 was determined to be breaking due to affecting ssh passthrough
however, this discovery happened after the changelog was created. Update the
Changelog to mark this as breaking.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-02-01 17:09:07 -05:00
Gusted
f7606de13a Use "read" value for General Access (#18496) (#18500)
- Backport of #18496
2022-02-01 20:24:27 +00:00
Gusted
483bda4b2d Use ImagedProvider for gplus oauth2 provider (#18504) (#18505)
- Bacport of #18504

Co-authored-by: 6543 <6543@obermui.de>
2022-02-01 10:45:58 +08:00
techknowlogick
edd57028a1 point to s3 endpoint directly (#18497) (#18510) 2022-01-31 17:50:41 -05:00
zeripath
083b85c655 Fix OAuth Source Edit Page (#18495) (#18503)
Backport #18495

* Fix OAuth Source Edit Page to ensure restricted and group settings are set
* Also tolerate []interface in the groups

Fix #18432

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-31 23:36:34 +02:00
Gusted
d5027b6c09 Prevent NPE on partial match of compare URL and allow short SHA1 compare URLs (#18472) (#18473)
* Don't panic & allow shorter sha1 (#18472)

- Backport of #18472

* Improve comment

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

Co-authored-by: Andrew Thornton <art27@cantab.net>
2022-01-31 01:49:17 +02:00
zeripath
a044ec8b53 Changelog 1.16.0 (#18468)
* Changelog for 1.16.0

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-31 01:42:12 +08:00
Aravinth Manivannan
f93d72c09b GitLab reviews may not have the updated_at field set (#18450) (#18461)
Fallback to created_at if that the case and to time.Now() if it is
also missing.

Fixes: #18434

Co-authored-by: Loïc Dachary <loic@dachary.org>

Conflicts:
	services/migrations/gitlab.go
	trivial context conflict because var reviews became reviews := in 1.17
2022-01-30 14:56:39 +01:00
Lunny Xiao
2f22337125 Fix broken when no commits and default branch is not master (#18423)
* Fix broken when no commits and default branch is not master

* Fix IsEmpty check

* Improve codes
2022-01-28 14:48:36 +08:00
zeripath
781ad8a79e Fix broken oauth2 authentication source edit page (#18412) (#18419)
Backport #18412

It appears that there was a broken merge of the edit.tmpl page during the merge
of #16594 - I am not entirely sure how this happened as the PR was correct.

This PR fixes the broken template.

Fix #18388

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-26 23:48:33 +00:00
zeripath
cada7202aa Only view milestones from current repo (#18414) (#18417)
Backport #18414

The endpoint /{username}/{reponame}/milestone/{id} is not currently restricted to
the repo. This PR restricts the milestones to those within the repo.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-26 22:09:07 +00:00
zeripath
0b331e2213 Place inline diff comment dialogs on split diff in 4th and 8th columns (#18403) (#18404)
Backport #18403

Fix #18391
Fix #18320

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-25 12:44:18 +00:00
Lunny Xiao
0734ca0132 Fix restore without topic failure (#18387) (#18400)
Co-authored-by: zeripath <art27@cantab.net>
2022-01-25 09:28:28 +02:00
Gusted
0b83cc21be Fix commit's time (#18375) (#18392)
- Backport of #18375
2022-01-25 05:48:56 +00:00
wxiaoguang
b68e605d56 Prevent showing webauthn error for every time visiting /user/settings/security (#18385) (#18386)
Backport #18385
2022-01-25 00:11:49 +00:00
Gusted
42991dc89a Fix partial cloning a repo (#18373) (#18377)
* Fix partial cloning a repo (#18373)

- Backport from: #18373
- Backport isn't 1-1, because the frontport had a refactor in that area,
which v1.16 doesn't have.

* Include diff & use copy

* Add partial clone test

* patch

* Apply suggestions from code review

* globalArgs first

* avoid copy but make GlobalCMDArgs append first

* please linter

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: 6543 <6543@obermui.de>
2022-01-23 21:46:09 +00:00
wxiaoguang
160de9fbda Fix mime-type detection for HTTP server (#18371) 2022-01-23 21:17:20 +08:00
Gusted
d644289fcb Backport: Disable content sniffing on PlainTextBytes (#18365)
- Backport of #18359
2022-01-23 01:58:09 +02:00
6543
fd9ff7cd6f Update github.com/duo-labs/webauthn (#18357) (#18364) 2022-01-22 13:32:10 -05:00
4702 changed files with 185454 additions and 202338 deletions

View File

@@ -5,6 +5,6 @@ tmp_dir = ".air"
cmd = "make backend"
bin = "gitea"
include_ext = ["go", "tmpl"]
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
exclude_regex = ["_test.go$", "_gen.go$"]
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata"]
include_dir = ["cmd", "models", "modules", "options", "routers", "services", "templates"]
exclude_regex = ["_test.go$"]

View File

@@ -1,114 +0,0 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# IntelliJ
.idea
# Goland's output filename can not be set manually
/go_build_*
# MS VSCode
.vscode
__debug_bin
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
*coverage.out
coverage.all
cpu.out
/modules/migration/bindata.go
/modules/migration/bindata.go.hash
/modules/options/bindata.go
/modules/options/bindata.go.hash
/modules/public/bindata.go
/modules/public/bindata.go.hash
/modules/templates/bindata.go
/modules/templates/bindata.go.hash
*.db
*.log
/gitea
/gitea-vet
/debug
/integrations.test
/bin
/dist
/custom/*
!/custom/conf
/custom/conf/*
!/custom/conf/app.example.ini
/data
/indexers
/log
/public/img/avatar
/tests/integration/gitea-integration-*
/tests/integration/indexers-*
/tests/e2e/gitea-e2e-*
/tests/e2e/indexers-*
/tests/e2e/reports
/tests/e2e/test-artifacts
/tests/e2e/test-snapshots
/tests/*.ini
/node_modules
/yarn.lock
/yarn-error.log
/npm-debug.log*
/public/js
/public/serviceworker.js
/public/css
/public/fonts
/public/img/webpack
/vendor
/web_src/fomantic/node_modules
/web_src/fomantic/build/*
!/web_src/fomantic/build/semantic.js
!/web_src/fomantic/build/semantic.css
!/web_src/fomantic/build/themes
/web_src/fomantic/build/themes/*
!/web_src/fomantic/build/themes/default
/web_src/fomantic/build/themes/default/assets/*
!/web_src/fomantic/build/themes/default/assets/fonts
/web_src/fomantic/build/themes/default/assets/fonts/*
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
/VERSION
/.air
/.go-licenses
# Snapcraft
snap/.snapcraft/
parts/
stage/
prime/
*.snap
*.snap-build
*_source.tar.bz2
.DS_Store
# Make evidence files
/.make_evidence
# Manpage
/man

View File

@@ -12,9 +12,6 @@ trigger:
- push
- tag
- pull_request
paths:
exclude:
- docs/**
volumes:
- name: deps
@@ -22,13 +19,13 @@ volumes:
steps:
- name: deps-frontend
image: node:18
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.20
image: golang:1.17
pull: always
commands:
- make deps-backend
@@ -37,7 +34,7 @@ steps:
path: /go
- name: lint-frontend
image: node:18
image: node:16
commands:
- make lint-frontend
depends_on: [deps-frontend]
@@ -48,74 +45,66 @@ steps:
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # 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
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make golangci-lint-windows vet
- make golangci-lint vet
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # 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
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # 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:18
image: node:16
commands:
- make checks-frontend
depends_on: [deps-frontend]
- name: checks-backend
image: golang:1.20
image: golang:1.17
commands:
- make --always-make checks-backend # ensure the 'go-licenses' make target runs
- make checks-backend
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: test-frontend
image: node:18
image: node:16
commands:
- make test-frontend
depends_on: [lint-frontend]
- name: build-frontend
image: node:18
image: node:16
commands:
- make frontend
depends_on: [deps-frontend]
depends_on: [test-frontend]
- name: build-backend-no-gcc
image: golang:1.19 # this step is kept as the lowest version of golang that we support
image: golang:1.16 # this step is kept as the lowest version of golang that we support
pull: always
environment:
GOPROXY: https://goproxy.io
GO111MODULE: on
GOPROXY: https://goproxy.cn
commands:
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
depends_on: [deps-backend, checks-backend]
@@ -124,9 +113,10 @@ steps:
path: /go
- name: build-backend-arm64
image: golang:1.20
image: golang:1.17
environment:
GOPROXY: https://goproxy.io
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOOS: linux
GOARCH: arm64
TAGS: bindata gogit
@@ -139,9 +129,10 @@ steps:
path: /go
- name: build-backend-windows
image: golang:1.20
image: golang:1.17
environment:
GOPROXY: https://goproxy.io
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOOS: windows
GOARCH: amd64
TAGS: bindata gogit
@@ -153,9 +144,10 @@ steps:
path: /go
- name: build-backend-386
image: golang:1.20
image: golang:1.17
environment:
GOPROXY: https://goproxy.io
GO111MODULE: on
GOPROXY: https://goproxy.cn
GOOS: linux
GOARCH: 386
commands:
@@ -182,9 +174,6 @@ trigger:
- push
- tag
- pull_request
paths:
exclude:
- docs/**
volumes:
- name: deps
@@ -232,16 +221,11 @@ services:
MINIO_ACCESS_KEY: 123456
MINIO_SECRET_KEY: 12345678
- name: smtpimap
image: tabascoterrier/docker-imap-devel:latest
pull: always
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
when:
event:
@@ -249,7 +233,7 @@ steps:
- pull_request
- name: deps-backend
image: golang:1.20
image: golang:1.17
pull: always
commands:
- make deps-backend
@@ -276,7 +260,7 @@ steps:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # 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, prepare-test-env]
@@ -290,7 +274,7 @@ steps:
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata sqlite sqlite_unlock_notify
RACE_ENABLED: true
GITHUB_READ_TOKEN:
@@ -306,7 +290,7 @@ steps:
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
GITHUB_READ_TOKEN:
@@ -322,7 +306,7 @@ steps:
commands:
- make test-mysql-migration integration-test-coverage
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
@@ -337,9 +321,9 @@ steps:
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-mysql8-migration test-mysql8
- timeout -s ABRT 40m make test-mysql8-migration test-mysql8
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
@@ -355,7 +339,7 @@ steps:
commands:
- make test-mssql-migration test-mssql
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata
RACE_ENABLED: true
TEST_LDAP: 1
@@ -366,11 +350,11 @@ steps:
path: /go
- name: generate-coverage
image: golang:1.20
image: golang:1.17
commands:
- make coverage
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata
depends_on: [unit-test, test-mysql]
when:
@@ -412,9 +396,6 @@ trigger:
- push
- tag
- pull_request
paths:
exclude:
- docs/**
volumes:
- name: deps
@@ -437,7 +418,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
when:
event:
@@ -445,7 +425,7 @@ steps:
- pull_request
- name: deps-backend
image: golang:1.20
image: golang:1.17
pull: always
commands:
- make deps-backend
@@ -466,7 +446,7 @@ steps:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # 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, prepare-test-env]
@@ -478,9 +458,9 @@ steps:
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-sqlite-migration test-sqlite
- timeout -s ABRT 40m make test-sqlite-migration test-sqlite
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
TEST_TAGS: gogit sqlite sqlite_unlock_notify
@@ -494,9 +474,9 @@ steps:
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-pgsql-migration test-pgsql
- timeout -s ABRT 40m make test-pgsql-migration test-pgsql
environment:
GOPROXY: https://goproxy.io
GOPROXY: https://goproxy.cn
TAGS: bindata gogit
RACE_ENABLED: true
TEST_TAGS: gogit
@@ -507,81 +487,6 @@ steps:
- name: deps
path: /go
---
kind: pipeline
type: docker
name: testing-e2e
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- docs/**
volumes:
- name: deps
temp: {}
services:
- name: pgsql
pull: default
image: postgres:10
environment:
POSTGRES_DB: testgitea-e2e
POSTGRES_PASSWORD: postgres
POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate='en_US.UTF-8' --lc-ctype='en_US.UTF-8'
steps:
- name: deps-frontend
image: node:18
pull: always
commands:
- make deps-frontend
- name: build-frontend
image: node:18
commands:
- make frontend
depends_on: [deps-frontend]
- name: deps-backend
image: golang:1.18
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
# TODO: We should probably build all dependencies into a test image
- name: test-e2e
image: mcr.microsoft.com/playwright:v1.29.2-focal
commands:
- curl -sLO https://go.dev/dl/go1.20.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
- apt-get -qq update && apt-get -qqy install build-essential
- export TEST_PGSQL_SCHEMA=''
- ./build/test-env-prepare.sh
- su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-pgsql"
environment:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
USE_REPO_TEST_DIR: 1
TEST_PGSQL_DBNAME: 'testgitea-e2e'
DEBIAN_FRONTEND: noninteractive
depends_on: [build-frontend, deps-backend]
volumes:
- name: deps
path: /go
---
kind: pipeline
name: update_translations
@@ -612,7 +517,7 @@ steps:
from_secret: crowdin_key
- name: update
image: alpine:3.17
image: alpine:3.13
pull: always
commands:
- ./build/update-locales.sh
@@ -628,8 +533,6 @@ steps:
commit_message: "[skip ci] Updated translations via Crowdin"
remote: "git@github.com:go-gitea/gitea.git"
environment:
DRONE_COMMIT_AUTHOR_EMAIL: "teabot@gitea.io"
DRONE_COMMIT_AUTHOR: GiteaBot
GIT_PUSH_SSH_KEY:
from_secret: git_push_ssh_key
@@ -664,7 +567,7 @@ trigger:
steps:
- name: download
image: golang:1.20
image: golang:1.17
pull: always
commands:
- timeout -s ABRT 40m make generate-license generate-gitignore
@@ -674,14 +577,12 @@ steps:
pull: always
settings:
author_email: "teabot@gitea.io"
author_name: "GiteaBot"
author_name: GiteaBot
branch: main
commit: true
commit_message: "[skip ci] Updated licenses and gitignores"
commit_message: "[skip ci] Updated licenses and gitignores "
remote: "git@github.com:go-gitea/gitea.git"
environment:
DRONE_COMMIT_AUTHOR_EMAIL: "teabot@gitea.io"
DRONE_COMMIT_AUTHOR: "GiteaBot"
GIT_PUSH_SSH_KEY:
from_secret: git_push_ssh_key
@@ -704,9 +605,6 @@ trigger:
- "release/*"
event:
- push
paths:
exclude:
- docs/**
depends_on:
- testing-amd64
@@ -721,17 +619,16 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: deps-frontend
image: node:18
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.20
image: golang:1.17
pull: always
commands:
- make deps-backend
@@ -740,17 +637,15 @@ steps:
path: /go
- name: static
image: techknowlogick/xgo:go-1.20.x
image: techknowlogick/xgo:go-1.17.x
pull: always
commands:
# Upgrade to node 18 once https://github.com/techknowlogick/xgo/issues/163 is resolved
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get -qqy install nodejs
- 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.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
DEBIAN_FRONTEND: noninteractive
volumes:
- name: deps
path: /go
@@ -774,16 +669,10 @@ steps:
image: woodpeckerci/plugin-s3:latest
pull: always
settings:
acl:
from_secret: aws_s3_acl
region:
from_secret: aws_s3_region
bucket:
from_secret: aws_s3_bucket
endpoint:
from_secret: aws_s3_endpoint
path_style:
from_secret: aws_s3_path_style
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
target: "/gitea/${DRONE_BRANCH##release/v}"
@@ -801,16 +690,10 @@ steps:
- name: release-main
image: woodpeckerci/plugin-s3:latest
settings:
acl:
from_secret: aws_s3_acl
region:
from_secret: aws_s3_region
bucket:
from_secret: aws_s3_bucket
endpoint:
from_secret: aws_s3_endpoint
path_style:
from_secret: aws_s3_path_style
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
target: /gitea/main
@@ -854,17 +737,16 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: deps-frontend
image: node:18
image: node:16
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: golang:1.20
image: golang:1.17
pull: always
commands:
- make deps-backend
@@ -873,17 +755,15 @@ steps:
path: /go
- name: static
image: techknowlogick/xgo:go-1.20.x
image: techknowlogick/xgo:go-1.17.x
pull: always
commands:
# Upgrade to node 18 once https://github.com/techknowlogick/xgo/issues/163 is resolved
- curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get -qqy install nodejs
- 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.io # proxy.golang.org is blocked in China, this proxy is not
GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
DEBIAN_FRONTEND: noninteractive
depends_on: [fetch-tags]
volumes:
- name: deps
@@ -909,16 +789,10 @@ steps:
image: woodpeckerci/plugin-s3:latest
pull: always
settings:
acl:
from_secret: aws_s3_acl
region:
from_secret: aws_s3_region
bucket:
from_secret: aws_s3_bucket
endpoint:
from_secret: aws_s3_endpoint
path_style:
from_secret: aws_s3_path_style
acl: public-read
bucket: gitea-artifacts
endpoint: https://ams3.digitaloceanspaces.com
path_style: true
source: "dist/release/*"
strip_prefix: dist/release/
target: "/gitea/${DRONE_TAG##v}"
@@ -958,14 +832,13 @@ trigger:
- push
- tag
- pull_request
paths:
include:
- docs/**
steps:
- name: build-docs
image: golang:1.20
image: plugins/hugo:latest
pull: always
commands:
- apk add --no-cache make bash curl
- cd docs
- make trans-copy clean build
@@ -999,10 +872,7 @@ depends_on:
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
- "refs/tags/**"
event:
exclude:
- cron
@@ -1012,7 +882,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1023,7 +892,7 @@ steps:
auto_tag_suffix: linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1041,69 +910,7 @@ steps:
auto_tag_suffix: linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-linux-amd64-release-candidate-version
platform:
os: linux
arch: amd64
depends_on:
- testing-amd64
- testing-arm64
trigger:
ref:
- "refs/tags/**-rc*"
event:
exclude:
- cron
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: techknowlogick/drone-docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1138,7 +945,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1149,7 +955,7 @@ steps:
tags: dev-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1167,7 +973,7 @@ steps:
tags: dev-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1201,7 +1007,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1212,7 +1017,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1230,7 +1035,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1255,9 +1060,6 @@ depends_on:
trigger:
ref:
- "refs/pull/**"
paths:
exclude:
- docs/**
steps:
- name: dryrun
@@ -1268,7 +1070,7 @@ steps:
repo: gitea/gitea
tags: linux-arm64
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
@@ -1291,10 +1093,7 @@ depends_on:
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
- "refs/tags/**"
event:
exclude:
- cron
@@ -1304,7 +1103,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1315,7 +1113,7 @@ steps:
auto_tag_suffix: linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1333,69 +1131,7 @@ steps:
auto_tag_suffix: linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-linux-arm64-release-candidate-version
platform:
os: linux
arch: arm64
depends_on:
- testing-amd64
- testing-arm64
trigger:
ref:
- "refs/tags/**-rc*"
event:
exclude:
- cron
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
image: techknowlogick/drone-docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: techknowlogick/drone-docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1430,7 +1166,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1441,7 +1176,7 @@ steps:
tags: dev-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1459,7 +1194,7 @@ steps:
tags: dev-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1493,7 +1228,6 @@ steps:
image: docker:git
pull: always
commands:
- git config --global --add safe.directory /drone/src
- git fetch --tags --force
- name: publish
@@ -1504,7 +1238,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1522,7 +1256,7 @@ steps:
tags: ${DRONE_BRANCH##release/v}-dev-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
- GOPROXY=https://goproxy.cn
password:
from_secret: docker_password
username:
@@ -1574,9 +1308,7 @@ trigger:
depends_on:
- docker-linux-amd64-release-version
- docker-linux-amd64-release-candidate-version
- docker-linux-arm64-release-version
- docker-linux-arm64-release-candidate-version
---
kind: pipeline
@@ -1658,8 +1390,6 @@ depends_on:
- docker-linux-arm64-release
- docker-linux-amd64-release-version
- docker-linux-arm64-release-version
- docker-linux-amd64-release-candidate-version
- docker-linux-arm64-release-candidate-version
- docker-linux-amd64-release-branch
- docker-linux-arm64-release-branch
- docker-manifest

View File

@@ -26,3 +26,6 @@ indent_style = tab
[*.svg]
insert_final_newline = false
[*.md]
trim_trailing_whitespace = false

461
.eslintrc Normal file
View File

@@ -0,0 +1,461 @@
root: true
reportUnusedDisableDirectives: true
ignorePatterns:
- /web_src/js/vendor
parserOptions:
sourceType: module
ecmaVersion: latest
plugins:
- eslint-plugin-unicorn
- eslint-plugin-import
- eslint-plugin-vue
- eslint-plugin-html
extends:
- plugin:vue/recommended
env:
es2021: true
node: true
globals:
__webpack_public_path__: true
CodeMirror: false
Dropzone: false
SimpleMDE: false
settings:
html/html-extensions: [".tmpl"]
overrides:
- files: ["web_src/**/*.js", "web_src/**/*.vue", "templates/**/*.tmpl"]
env:
browser: true
jquery: true
node: false
- files: ["templates/**/*.tmpl"]
rules:
no-tabs: [0]
indent: [2, tab, {SwitchCase: 1}]
- files: ["web_src/**/*worker.js"]
env:
worker: true
rules:
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, location, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
- files: ["build/generate-images.js"]
rules:
import/no-unresolved: [0]
import/no-extraneous-dependencies: [0]
- files: ["*.test.js"]
env:
jest: true
- files: ["*.config.js"]
rules:
import/no-unused-modules: [0]
rules:
accessor-pairs: [2]
array-bracket-newline: [0]
array-bracket-spacing: [2, never]
array-callback-return: [0]
array-element-newline: [0]
arrow-body-style: [0]
arrow-parens: [2, always]
arrow-spacing: [2, {before: true, after: true}]
block-scoped-var: [2]
brace-style: [2, 1tbs, {allowSingleLine: true}]
camelcase: [0]
capitalized-comments: [0]
class-methods-use-this: [0]
comma-dangle: [2, only-multiline]
comma-spacing: [2, {before: false, after: true}]
comma-style: [2, last]
complexity: [0]
computed-property-spacing: [2, never]
consistent-return: [0]
consistent-this: [0]
constructor-super: [2]
curly: [0]
default-case-last: [2]
default-case: [0]
default-param-last: [0]
dot-location: [2, property]
dot-notation: [0]
eol-last: [2]
eqeqeq: [2]
for-direction: [2]
func-call-spacing: [2, never]
func-name-matching: [2]
func-names: [0]
func-style: [0]
function-call-argument-newline: [0]
function-paren-newline: [0]
generator-star-spacing: [0]
getter-return: [2]
grouped-accessor-pairs: [2]
guard-for-in: [0]
id-blacklist: [0]
id-length: [0]
id-match: [0]
implicit-arrow-linebreak: [0]
import/default: [0]
import/dynamic-import-chunkname: [0]
import/export: [2]
import/exports-last: [0]
import/extensions: [2, always, {ignorePackages: true}]
import/first: [2]
import/group-exports: [0]
import/max-dependencies: [0]
import/named: [2]
import/namespace: [0]
import/newline-after-import: [0]
import/no-absolute-path: [0]
import/no-amd: [0]
import/no-anonymous-default-export: [0]
import/no-commonjs: [0]
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
import/no-default-export: [0]
import/no-deprecated: [0]
import/no-dynamic-require: [0]
import/no-extraneous-dependencies: [2]
import/no-import-module-exports: [0]
import/no-internal-modules: [0]
import/no-mutable-exports: [2]
import/no-named-as-default-member: [0]
import/no-named-as-default: [2]
import/no-named-default: [0]
import/no-named-export: [0]
import/no-namespace: [0]
import/no-nodejs-modules: [0]
import/no-relative-packages: [0]
import/no-relative-parent-imports: [0]
import/no-restricted-paths: [0]
import/no-self-import: [2]
import/no-unassigned-import: [0]
import/no-unresolved: [2, {commonjs: true}]
import/no-unused-modules: [2, {unusedExports: true}]
import/no-useless-path-segments: [2, {commonjs: true}]
import/no-webpack-loader-syntax: [2]
import/order: [0]
import/prefer-default-export: [0]
import/unambiguous: [0]
indent: [2, 2, {SwitchCase: 1}]
init-declarations: [0]
key-spacing: [2]
keyword-spacing: [2]
line-comment-position: [0]
linebreak-style: [2, unix]
lines-around-comment: [0]
lines-between-class-members: [0]
max-classes-per-file: [0]
max-depth: [0]
max-len: [0]
max-lines-per-function: [0]
max-lines: [0]
max-nested-callbacks: [0]
max-params: [0]
max-statements-per-line: [0]
max-statements: [0]
multiline-comment-style: [2, separate-lines]
multiline-ternary: [0]
new-cap: [0]
new-parens: [2]
newline-per-chained-call: [0]
no-alert: [0]
no-array-constructor: [2]
no-async-promise-executor: [2]
no-await-in-loop: [0]
no-bitwise: [0]
no-buffer-constructor: [0]
no-caller: [2]
no-case-declarations: [2]
no-class-assign: [2]
no-compare-neg-zero: [2]
no-cond-assign: [2, except-parens]
no-confusing-arrow: [0]
no-console: [1, {allow: [info, warn, error]}]
no-const-assign: [2]
no-constant-condition: [0]
no-constructor-return: [2]
no-continue: [0]
no-control-regex: [0]
no-debugger: [1]
no-delete-var: [2]
no-div-regex: [0]
no-dupe-args: [2]
no-dupe-class-members: [2]
no-dupe-else-if: [2]
no-dupe-keys: [2]
no-duplicate-case: [2]
no-duplicate-imports: [2]
no-else-return: [2]
no-empty-character-class: [2]
no-empty-function: [0]
no-empty-pattern: [2]
no-empty: [2, {allowEmptyCatch: true}]
no-eq-null: [2]
no-eval: [2]
no-ex-assign: [2]
no-extend-native: [2]
no-extra-bind: [2]
no-extra-boolean-cast: [2]
no-extra-label: [0]
no-extra-parens: [0]
no-extra-semi: [2]
no-fallthrough: [2]
no-floating-decimal: [0]
no-func-assign: [2]
no-global-assign: [2]
no-implicit-coercion: [0]
no-implicit-globals: [0]
no-implied-eval: [2]
no-import-assign: [2]
no-inline-comments: [0]
no-inner-declarations: [2]
no-invalid-regexp: [2]
no-invalid-this: [0]
no-irregular-whitespace: [2]
no-iterator: [2]
no-label-var: [2]
no-labels: [2]
no-lone-blocks: [2]
no-lonely-if: [0]
no-loop-func: [0]
no-loss-of-precision: [2]
no-magic-numbers: [0]
no-misleading-character-class: [2]
no-mixed-operators: [0]
no-mixed-spaces-and-tabs: [2]
no-multi-assign: [0]
no-multi-spaces: [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
no-multi-str: [2]
no-negated-condition: [0]
no-nested-ternary: [0]
no-new-func: [2]
no-new-object: [2]
no-new-symbol: [2]
no-new-wrappers: [2]
no-new: [0]
no-nonoctal-decimal-escape: [2]
no-obj-calls: [2]
no-octal-escape: [2]
no-octal: [2]
no-param-reassign: [0]
no-plusplus: [0]
no-promise-executor-return: [0]
no-proto: [2]
no-prototype-builtins: [2]
no-redeclare: [2]
no-regex-spaces: [2]
no-restricted-exports: [0]
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, location, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, self, status, statusbar, stop, toolbar, top]
no-restricted-imports: [0]
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement]
no-return-assign: [0]
no-return-await: [0]
no-script-url: [2]
no-self-assign: [2, {props: true}]
no-self-compare: [2]
no-sequences: [2]
no-setter-return: [2]
no-shadow-restricted-names: [2]
no-shadow: [0]
no-sparse-arrays: [2]
no-tabs: [2]
no-template-curly-in-string: [2]
no-ternary: [0]
no-this-before-super: [2]
no-throw-literal: [2]
no-trailing-spaces: [2]
no-undef-init: [2]
no-undef: [2, {typeof: true}]
no-undefined: [0]
no-underscore-dangle: [0]
no-unexpected-multiline: [2]
no-unmodified-loop-condition: [2]
no-unneeded-ternary: [0]
no-unreachable-loop: [2]
no-unreachable: [2]
no-unsafe-finally: [2]
no-unsafe-negation: [2]
no-unused-expressions: [2]
no-unused-labels: [2]
no-unused-private-class-members: [2]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, ignoreRestSiblings: false}]
no-use-before-define: [2, nofunc]
no-useless-backreference: [0]
no-useless-call: [2]
no-useless-catch: [2]
no-useless-computed-key: [2]
no-useless-concat: [2]
no-useless-constructor: [2]
no-useless-escape: [2]
no-useless-rename: [2]
no-useless-return: [2]
no-var: [2]
no-void: [2]
no-warning-comments: [0]
no-whitespace-before-property: [2]
no-with: [2]
nonblock-statement-body-position: [2]
object-curly-newline: [0]
object-curly-spacing: [2, never]
object-shorthand: [2, always]
one-var-declaration-per-line: [0]
one-var: [0]
operator-assignment: [2, always]
operator-linebreak: [2, after]
padded-blocks: [2, never]
padding-line-between-statements: [0]
prefer-arrow-callback: [2, {allowNamedFunctions: true, allowUnboundThis: true}]
prefer-const: [2, {destructuring: all}]
prefer-destructuring: [0]
prefer-exponentiation-operator: [2]
prefer-named-capture-group: [0]
prefer-numeric-literals: [2]
prefer-object-has-own: [0]
prefer-object-spread: [0]
prefer-promise-reject-errors: [2, {allowEmptyReject: false}]
prefer-regex-literals: [2]
prefer-rest-params: [2]
prefer-spread: [2]
prefer-template: [2]
quote-props: [0]
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
radix: [2, as-needed]
require-atomic-updates: [0]
require-await: [0]
require-unicode-regexp: [0]
require-yield: [2]
rest-spread-spacing: [2, never]
semi-spacing: [2, {before: false, after: true}]
semi-style: [2, last]
semi: [2, always, {omitLastInOneLineBlock: true}]
sort-imports: [0]
sort-keys: [0]
sort-vars: [0]
space-before-blocks: [2, always]
space-in-parens: [2, never]
space-infix-ops: [2]
space-unary-ops: [2]
spaced-comment: [2, always]
strict: [0]
switch-colon-spacing: [2]
symbol-description: [2]
template-curly-spacing: [2, never]
template-tag-spacing: [2, never]
unicode-bom: [2, never]
unicorn/better-regex: [0]
unicorn/catch-error-name: [0]
unicorn/consistent-destructuring: [2]
unicorn/consistent-function-scoping: [2]
unicorn/custom-error-definition: [0]
unicorn/empty-brace-spaces: [2]
unicorn/error-message: [0]
unicorn/escape-case: [0]
unicorn/expiring-todo-comments: [0]
unicorn/explicit-length-check: [0]
unicorn/filename-case: [0]
unicorn/import-index: [0]
unicorn/import-style: [0]
unicorn/new-for-builtins: [2]
unicorn/no-abusive-eslint-disable: [0]
unicorn/no-array-for-each: [2]
unicorn/no-array-instanceof: [0]
unicorn/no-array-method-this-argument: [2]
unicorn/no-array-push-push: [2]
unicorn/no-await-expression-member: [0]
unicorn/no-console-spaces: [0]
unicorn/no-document-cookie: [2]
unicorn/no-empty-file: [2]
unicorn/no-fn-reference-in-iterator: [0]
unicorn/no-for-loop: [0]
unicorn/no-hex-escape: [0]
unicorn/no-invalid-remove-event-listener: [2]
unicorn/no-keyword-prefix: [0]
unicorn/no-lonely-if: [2]
unicorn/no-nested-ternary: [0]
unicorn/no-new-array: [0]
unicorn/no-new-buffer: [0]
unicorn/no-null: [0]
unicorn/no-object-as-default-parameter: [2]
unicorn/no-process-exit: [0]
unicorn/no-reduce: [2]
unicorn/no-static-only-class: [2]
unicorn/no-thenable: [2]
unicorn/no-this-assignment: [2]
unicorn/no-unreadable-array-destructuring: [0]
unicorn/no-unsafe-regex: [0]
unicorn/no-unused-properties: [2]
unicorn/no-useless-fallback-in-spread: [2]
unicorn/no-useless-length-check: [2]
unicorn/no-useless-promise-resolve-reject: [2]
unicorn/no-useless-spread: [2]
unicorn/no-useless-undefined: [0]
unicorn/no-zero-fractions: [2]
unicorn/number-literal-case: [0]
unicorn/numeric-separators-style: [0]
unicorn/prefer-add-event-listener: [2]
unicorn/prefer-array-find: [2]
unicorn/prefer-array-flat-map: [2]
unicorn/prefer-array-flat: [2]
unicorn/prefer-array-index-of: [2]
unicorn/prefer-array-some: [2]
unicorn/prefer-at: [0]
unicorn/prefer-code-point: [2]
unicorn/prefer-dataset: [2]
unicorn/prefer-date-now: [2]
unicorn/prefer-default-parameters: [0]
unicorn/prefer-event-key: [2]
unicorn/prefer-export-from: [2]
unicorn/prefer-includes: [2]
unicorn/prefer-json-parse-buffer: [0]
unicorn/prefer-math-trunc: [2]
unicorn/prefer-modern-dom-apis: [0]
unicorn/prefer-module: [2]
unicorn/prefer-negative-index: [2]
unicorn/prefer-node-append: [0]
unicorn/prefer-node-protocol: [0]
unicorn/prefer-node-remove: [0]
unicorn/prefer-number-properties: [0]
unicorn/prefer-object-from-entries: [2]
unicorn/prefer-object-has-own: [0]
unicorn/prefer-optional-catch-binding: [2]
unicorn/prefer-prototype-methods: [0]
unicorn/prefer-query-selector: [0]
unicorn/prefer-reflect-apply: [0]
unicorn/prefer-regexp-test: [2]
unicorn/prefer-replace-all: [0]
unicorn/prefer-set-has: [0]
unicorn/prefer-spread: [0]
unicorn/prefer-starts-ends-with: [2]
unicorn/prefer-string-slice: [0]
unicorn/prefer-switch: [0]
unicorn/prefer-ternary: [0]
unicorn/prefer-text-content: [2]
unicorn/prefer-top-level-await: [0]
unicorn/prefer-trim-start-end: [2]
unicorn/prefer-type-error: [0]
unicorn/prevent-abbreviations: [0]
unicorn/relative-url-style: [2]
unicorn/require-array-join-separator: [2]
unicorn/require-number-to-fixed-digits-argument: [2]
unicorn/require-post-message-target-origin: [0]
unicorn/string-content: [0]
unicorn/template-indent: [2]
unicorn/throw-new-error: [2]
use-isnan: [2]
valid-typeof: [2, {requireStringLiterals: true}]
vars-on-top: [0]
vue/attributes-order: [0]
vue/component-definition-name-casing: [0]
vue/html-closing-bracket-spacing: [0]
vue/max-attributes-per-line: [0]
vue/one-component-per-file: [0]
wrap-iife: [2, inside]
wrap-regex: [0]
yield-star-spacing: [2, after]
yoda: [2, never]

View File

@@ -1,538 +0,0 @@
root: true
reportUnusedDisableDirectives: true
ignorePatterns:
- /web_src/js/vendor
parserOptions:
sourceType: module
ecmaVersion: latest
plugins:
- eslint-plugin-unicorn
- eslint-plugin-import
- eslint-plugin-jquery
- eslint-plugin-sonarjs
env:
es2022: true
node: true
globals:
__webpack_public_path__: true
overrides:
- files: ["web_src/**/*.js", "docs/**/*.js"]
env:
browser: true
node: false
- files: ["web_src/**/*worker.js"]
env:
worker: true
rules:
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
- files: ["build/generate-images.js"]
rules:
import/no-unresolved: [0]
import/no-extraneous-dependencies: [0]
- files: ["*.config.js"]
rules:
import/no-unused-modules: [0]
rules:
accessor-pairs: [2]
array-bracket-newline: [0]
array-bracket-spacing: [2, never]
array-callback-return: [2, {checkForEach: true}]
array-element-newline: [0]
arrow-body-style: [0]
arrow-parens: [2, always]
arrow-spacing: [2, {before: true, after: true}]
block-scoped-var: [2]
brace-style: [2, 1tbs, {allowSingleLine: true}]
camelcase: [0]
capitalized-comments: [0]
class-methods-use-this: [0]
comma-dangle: [2, only-multiline]
comma-spacing: [2, {before: false, after: true}]
comma-style: [2, last]
complexity: [0]
computed-property-spacing: [2, never]
consistent-return: [0]
consistent-this: [0]
constructor-super: [2]
curly: [0]
default-case-last: [2]
default-case: [0]
default-param-last: [0]
dot-location: [2, property]
dot-notation: [0]
eol-last: [2]
eqeqeq: [2]
for-direction: [2]
func-call-spacing: [2, never]
func-name-matching: [2]
func-names: [0]
func-style: [0]
function-call-argument-newline: [0]
function-paren-newline: [0]
generator-star-spacing: [0]
getter-return: [2]
grouped-accessor-pairs: [2]
guard-for-in: [0]
id-blacklist: [0]
id-length: [0]
id-match: [0]
implicit-arrow-linebreak: [0]
import/consistent-type-specifier-style: [0]
import/default: [0]
import/dynamic-import-chunkname: [0]
import/export: [2]
import/exports-last: [0]
import/extensions: [2, always, {ignorePackages: true}]
import/first: [2]
import/group-exports: [0]
import/max-dependencies: [0]
import/named: [2]
import/namespace: [0]
import/newline-after-import: [0]
import/no-absolute-path: [0]
import/no-amd: [0]
import/no-anonymous-default-export: [0]
import/no-commonjs: [0]
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
import/no-default-export: [0]
import/no-deprecated: [0]
import/no-dynamic-require: [0]
import/no-empty-named-blocks: [2]
import/no-extraneous-dependencies: [2]
import/no-import-module-exports: [0]
import/no-internal-modules: [0]
import/no-mutable-exports: [0]
import/no-named-as-default-member: [0]
import/no-named-as-default: [2]
import/no-named-default: [0]
import/no-named-export: [0]
import/no-namespace: [0]
import/no-nodejs-modules: [0]
import/no-relative-packages: [0]
import/no-relative-parent-imports: [0]
import/no-restricted-paths: [0]
import/no-self-import: [2]
import/no-unassigned-import: [0]
import/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$"]}]
import/no-unused-modules: [2, {unusedExports: true}]
import/no-useless-path-segments: [2, {commonjs: true}]
import/no-webpack-loader-syntax: [2]
import/order: [0]
import/prefer-default-export: [0]
import/unambiguous: [0]
indent: [2, 2, {SwitchCase: 1}]
init-declarations: [0]
jquery/no-ajax-events: [2]
jquery/no-ajax: [0]
jquery/no-animate: [2]
jquery/no-attr: [0]
jquery/no-bind: [2]
jquery/no-class: [0]
jquery/no-clone: [2]
jquery/no-closest: [0]
jquery/no-css: [0]
jquery/no-data: [0]
jquery/no-deferred: [2]
jquery/no-delegate: [2]
jquery/no-each: [0]
jquery/no-extend: [2]
jquery/no-fade: [0]
jquery/no-filter: [0]
jquery/no-find: [0]
jquery/no-global-eval: [2]
jquery/no-grep: [2]
jquery/no-has: [2]
jquery/no-hide: [2]
jquery/no-html: [0]
jquery/no-in-array: [2]
jquery/no-is-array: [2]
jquery/no-is-function: [2]
jquery/no-is: [0]
jquery/no-load: [2]
jquery/no-map: [0]
jquery/no-merge: [2]
jquery/no-param: [2]
jquery/no-parent: [0]
jquery/no-parents: [0]
jquery/no-parse-html: [2]
jquery/no-prop: [0]
jquery/no-proxy: [2]
jquery/no-ready: [0]
jquery/no-serialize: [2]
jquery/no-show: [2]
jquery/no-size: [2]
jquery/no-sizzle: [0]
jquery/no-slide: [0]
jquery/no-submit: [0]
jquery/no-text: [0]
jquery/no-toggle: [2]
jquery/no-trigger: [0]
jquery/no-trim: [2]
jquery/no-val: [0]
jquery/no-when: [2]
jquery/no-wrap: [2]
key-spacing: [2]
keyword-spacing: [2]
line-comment-position: [0]
linebreak-style: [2, unix]
lines-around-comment: [0]
lines-between-class-members: [0]
logical-assignment-operators: [0]
max-classes-per-file: [0]
max-depth: [0]
max-len: [0]
max-lines-per-function: [0]
max-lines: [0]
max-nested-callbacks: [0]
max-params: [0]
max-statements-per-line: [0]
max-statements: [0]
multiline-comment-style: [2, separate-lines]
multiline-ternary: [0]
new-cap: [0]
new-parens: [2]
newline-per-chained-call: [0]
no-alert: [0]
no-array-constructor: [2]
no-async-promise-executor: [0]
no-await-in-loop: [0]
no-bitwise: [0]
no-buffer-constructor: [0]
no-caller: [2]
no-case-declarations: [2]
no-class-assign: [2]
no-compare-neg-zero: [2]
no-cond-assign: [2, except-parens]
no-confusing-arrow: [0]
no-console: [1, {allow: [debug, info, warn, error]}]
no-const-assign: [2]
no-constant-binary-expression: [2]
no-constant-condition: [0]
no-constructor-return: [2]
no-continue: [0]
no-control-regex: [0]
no-debugger: [1]
no-delete-var: [2]
no-div-regex: [0]
no-dupe-args: [2]
no-dupe-class-members: [2]
no-dupe-else-if: [2]
no-dupe-keys: [2]
no-duplicate-case: [2]
no-duplicate-imports: [2]
no-else-return: [2]
no-empty-character-class: [2]
no-empty-function: [0]
no-empty-pattern: [2]
no-empty-static-block: [2]
no-empty: [2, {allowEmptyCatch: true}]
no-eq-null: [2]
no-eval: [2]
no-ex-assign: [2]
no-extend-native: [2]
no-extra-bind: [2]
no-extra-boolean-cast: [2]
no-extra-label: [0]
no-extra-parens: [0]
no-extra-semi: [2]
no-fallthrough: [2]
no-floating-decimal: [0]
no-func-assign: [2]
no-global-assign: [2]
no-implicit-coercion: [2]
no-implicit-globals: [0]
no-implied-eval: [2]
no-import-assign: [2]
no-inline-comments: [0]
no-inner-declarations: [2]
no-invalid-regexp: [2]
no-invalid-this: [0]
no-irregular-whitespace: [2]
no-iterator: [2]
no-label-var: [2]
no-labels: [0] # handled by no-restricted-syntax
no-lone-blocks: [2]
no-lonely-if: [0]
no-loop-func: [0]
no-loss-of-precision: [2]
no-magic-numbers: [0]
no-misleading-character-class: [2]
no-mixed-operators: [0]
no-mixed-spaces-and-tabs: [2]
no-multi-assign: [0]
no-multi-spaces: [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
no-multi-str: [2]
no-negated-condition: [0]
no-nested-ternary: [0]
no-new-func: [2]
no-new-native-nonconstructor: [2]
no-new-object: [2]
no-new-symbol: [2]
no-new-wrappers: [2]
no-new: [0]
no-nonoctal-decimal-escape: [2]
no-obj-calls: [2]
no-octal-escape: [2]
no-octal: [2]
no-param-reassign: [0]
no-plusplus: [0]
no-promise-executor-return: [0]
no-proto: [2]
no-prototype-builtins: [2]
no-redeclare: [2]
no-regex-spaces: [2]
no-restricted-exports: [0]
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, location, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, self, status, statusbar, stop, toolbar, top, __dirname, __filename]
no-restricted-imports: [0]
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement]
no-return-assign: [0]
no-return-await: [0]
no-script-url: [2]
no-self-assign: [2, {props: true}]
no-self-compare: [2]
no-sequences: [2]
no-setter-return: [2]
no-shadow-restricted-names: [2]
no-shadow: [0]
no-sparse-arrays: [2]
no-tabs: [2]
no-template-curly-in-string: [2]
no-ternary: [0]
no-this-before-super: [2]
no-throw-literal: [2]
no-trailing-spaces: [2]
no-undef-init: [2]
no-undef: [2, {typeof: true}]
no-undefined: [0]
no-underscore-dangle: [0]
no-unexpected-multiline: [2]
no-unmodified-loop-condition: [2]
no-unneeded-ternary: [0]
no-unreachable-loop: [2]
no-unreachable: [2]
no-unsafe-finally: [2]
no-unsafe-negation: [2]
no-unused-expressions: [2]
no-unused-labels: [2]
no-unused-private-class-members: [2]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
no-useless-backreference: [2]
no-useless-call: [2]
no-useless-catch: [2]
no-useless-computed-key: [2]
no-useless-concat: [2]
no-useless-constructor: [2]
no-useless-escape: [2]
no-useless-rename: [2]
no-useless-return: [2]
no-var: [2]
no-void: [2]
no-warning-comments: [0]
no-whitespace-before-property: [2]
no-with: [0] # handled by no-restricted-syntax
nonblock-statement-body-position: [2]
object-curly-newline: [0]
object-curly-spacing: [2, never]
object-shorthand: [2, always]
one-var-declaration-per-line: [0]
one-var: [0]
operator-assignment: [2, always]
operator-linebreak: [2, after]
padded-blocks: [2, never]
padding-line-between-statements: [0]
prefer-arrow-callback: [2, {allowNamedFunctions: true, allowUnboundThis: true}]
prefer-const: [2, {destructuring: all, ignoreReadBeforeAssign: true}]
prefer-destructuring: [0]
prefer-exponentiation-operator: [2]
prefer-named-capture-group: [0]
prefer-numeric-literals: [2]
prefer-object-has-own: [0]
prefer-object-spread: [2]
prefer-promise-reject-errors: [2, {allowEmptyReject: false}]
prefer-regex-literals: [2]
prefer-rest-params: [2]
prefer-spread: [2]
prefer-template: [2]
quote-props: [0]
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
radix: [2, as-needed]
require-atomic-updates: [0]
require-await: [0]
require-unicode-regexp: [0]
require-yield: [2]
rest-spread-spacing: [2, never]
semi-spacing: [2, {before: false, after: true}]
semi-style: [2, last]
semi: [2, always, {omitLastInOneLineBlock: true}]
sonarjs/cognitive-complexity: [0]
sonarjs/elseif-without-else: [0]
sonarjs/max-switch-cases: [0]
sonarjs/no-all-duplicated-branches: [2]
sonarjs/no-collapsible-if: [0]
sonarjs/no-collection-size-mischeck: [2]
sonarjs/no-duplicate-string: [0]
sonarjs/no-duplicated-branches: [0]
sonarjs/no-element-overwrite: [2]
sonarjs/no-empty-collection: [2]
sonarjs/no-extra-arguments: [2]
sonarjs/no-gratuitous-expressions: [2]
sonarjs/no-identical-conditions: [2]
sonarjs/no-identical-expressions: [2]
sonarjs/no-identical-functions: [2, 5]
sonarjs/no-ignored-return: [2]
sonarjs/no-inverted-boolean-check: [2]
sonarjs/no-nested-switch: [0]
sonarjs/no-nested-template-literals: [0]
sonarjs/no-one-iteration-loop: [2]
sonarjs/no-redundant-boolean: [2]
sonarjs/no-redundant-jump: [0]
sonarjs/no-same-line-conditional: [2]
sonarjs/no-small-switch: [0]
sonarjs/no-unused-collection: [2]
sonarjs/no-use-of-empty-return-value: [2]
sonarjs/no-useless-catch: [2]
sonarjs/non-existent-operator: [2]
sonarjs/prefer-immediate-return: [0]
sonarjs/prefer-object-literal: [0]
sonarjs/prefer-single-boolean-return: [0]
sonarjs/prefer-while: [2]
sort-imports: [0]
sort-keys: [0]
sort-vars: [0]
space-before-blocks: [2, always]
space-in-parens: [2, never]
space-infix-ops: [2]
space-unary-ops: [2]
spaced-comment: [2, always]
strict: [0]
switch-colon-spacing: [2]
symbol-description: [2]
template-curly-spacing: [2, never]
template-tag-spacing: [2, never]
unicode-bom: [2, never]
unicorn/better-regex: [0]
unicorn/catch-error-name: [0]
unicorn/consistent-destructuring: [2]
unicorn/consistent-function-scoping: [2]
unicorn/custom-error-definition: [0]
unicorn/empty-brace-spaces: [2]
unicorn/error-message: [0]
unicorn/escape-case: [0]
unicorn/expiring-todo-comments: [0]
unicorn/explicit-length-check: [0]
unicorn/filename-case: [0]
unicorn/import-index: [0]
unicorn/import-style: [0]
unicorn/new-for-builtins: [2]
unicorn/no-abusive-eslint-disable: [0]
unicorn/no-array-for-each: [2]
unicorn/no-array-instanceof: [0]
unicorn/no-array-method-this-argument: [2]
unicorn/no-array-push-push: [2]
unicorn/no-await-expression-member: [0]
unicorn/no-console-spaces: [0]
unicorn/no-document-cookie: [2]
unicorn/no-empty-file: [2]
unicorn/no-fn-reference-in-iterator: [0]
unicorn/no-for-loop: [0]
unicorn/no-hex-escape: [0]
unicorn/no-invalid-remove-event-listener: [2]
unicorn/no-keyword-prefix: [0]
unicorn/no-lonely-if: [2]
unicorn/no-negated-condition: [0]
unicorn/no-nested-ternary: [0]
unicorn/no-new-array: [0]
unicorn/no-new-buffer: [0]
unicorn/no-null: [0]
unicorn/no-object-as-default-parameter: [0]
unicorn/no-process-exit: [0]
unicorn/no-reduce: [2]
unicorn/no-static-only-class: [2]
unicorn/no-thenable: [2]
unicorn/no-this-assignment: [2]
unicorn/no-typeof-undefined: [2]
unicorn/no-unnecessary-await: [2]
unicorn/no-unreadable-array-destructuring: [0]
unicorn/no-unreadable-iife: [2]
unicorn/no-unsafe-regex: [0]
unicorn/no-unused-properties: [2]
unicorn/no-useless-fallback-in-spread: [2]
unicorn/no-useless-length-check: [2]
unicorn/no-useless-promise-resolve-reject: [2]
unicorn/no-useless-spread: [2]
unicorn/no-useless-switch-case: [2]
unicorn/no-useless-undefined: [0]
unicorn/no-zero-fractions: [2]
unicorn/number-literal-case: [0]
unicorn/numeric-separators-style: [0]
unicorn/prefer-add-event-listener: [2]
unicorn/prefer-array-find: [2]
unicorn/prefer-array-flat-map: [2]
unicorn/prefer-array-flat: [2]
unicorn/prefer-array-index-of: [2]
unicorn/prefer-array-some: [2]
unicorn/prefer-at: [0]
unicorn/prefer-code-point: [0]
unicorn/prefer-dataset: [2]
unicorn/prefer-date-now: [2]
unicorn/prefer-default-parameters: [0]
unicorn/prefer-event-key: [2]
unicorn/prefer-event-target: [2]
unicorn/prefer-export-from: [2]
unicorn/prefer-includes: [2]
unicorn/prefer-json-parse-buffer: [0]
unicorn/prefer-logical-operator-over-ternary: [2]
unicorn/prefer-math-trunc: [2]
unicorn/prefer-modern-dom-apis: [0]
unicorn/prefer-modern-math-apis: [2]
unicorn/prefer-module: [2]
unicorn/prefer-native-coercion-functions: [2]
unicorn/prefer-negative-index: [2]
unicorn/prefer-node-append: [0]
unicorn/prefer-node-protocol: [2]
unicorn/prefer-node-remove: [0]
unicorn/prefer-number-properties: [0]
unicorn/prefer-object-from-entries: [2]
unicorn/prefer-object-has-own: [0]
unicorn/prefer-optional-catch-binding: [2]
unicorn/prefer-prototype-methods: [0]
unicorn/prefer-query-selector: [0]
unicorn/prefer-reflect-apply: [0]
unicorn/prefer-regexp-test: [2]
unicorn/prefer-replace-all: [0]
unicorn/prefer-set-has: [0]
unicorn/prefer-set-size: [2]
unicorn/prefer-spread: [0]
unicorn/prefer-starts-ends-with: [2]
unicorn/prefer-string-slice: [0]
unicorn/prefer-switch: [0]
unicorn/prefer-ternary: [0]
unicorn/prefer-text-content: [2]
unicorn/prefer-top-level-await: [0]
unicorn/prefer-trim-start-end: [2]
unicorn/prefer-type-error: [0]
unicorn/prevent-abbreviations: [0]
unicorn/relative-url-style: [2]
unicorn/require-array-join-separator: [2]
unicorn/require-number-to-fixed-digits-argument: [2]
unicorn/require-post-message-target-origin: [0]
unicorn/string-content: [0]
unicorn/switch-case-braces: [0]
unicorn/template-indent: [2]
unicorn/text-encoding-identifier-case: [0]
unicorn/throw-new-error: [2]
use-isnan: [2]
valid-typeof: [2, {requireStringLiterals: true}]
vars-on-top: [0]
wrap-iife: [2, inside]
wrap-regex: [0]
yield-star-spacing: [2, after]
yoda: [2, never]

8
.gitattributes vendored
View File

@@ -1,8 +1,8 @@
* text=auto eol=lf
*.tmpl linguist-language=Handlebars
/assets/*.json linguist-generated
/public/vendor/** -text -eol linguist-vendored
/vendor/** -text -eol linguist-vendored
/public/vendor/** -text -eol linguist-vendored
/templates/**/*.tmpl linguist-language=Handlebars
/.eslintrc linguist-language=YAML
/.stylelintrc linguist-language=YAML
/web_src/fomantic/build/** linguist-generated
/web_src/js/vendor/** -text -eol linguist-vendored
Dockerfile.* linguist-language=Dockerfile

View File

@@ -1,6 +1,5 @@
name: Bug Report
description: Found something you weren't expecting? Report it here!
labels: kind/bug
body:
- type: markdown
attributes:
@@ -17,16 +16,6 @@ body:
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.io/en-us/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
6. In particular it's really important to provide pertinent logs. You must give us DEBUG level logs.
Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: textarea
id: description
attributes:
label: Description
description: |
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below)
If you are using a proxy or a CDN (e.g. Cloudflare) in front of Gitea, please disable the proxy/CDN fully and access Gitea directly to confirm the issue still persists without those services.
- type: input
id: gitea-ver
attributes:
@@ -34,34 +23,6 @@ body:
description: Gitea version (or commit reference) of your instance
validations:
required: true
- type: dropdown
id: can-reproduce
attributes:
label: Can you reproduce the bug on the Gitea demo site?
description: |
If so, please provide a URL in the Description field
URL of Gitea demo: https://try.gitea.io
options:
- "Yes"
- "No"
validations:
required: true
- type: markdown
attributes:
value: |
It's really important to provide pertinent logs
Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: input
id: logs
attributes:
label: Log Gist
description: Please provide a gist URL of your logs, with any sensitive information (e.g. API keys) removed/hidden
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If this issue involves the Web Interface, please provide one or more screenshots
- type: input
id: git-ver
attributes:
@@ -92,3 +53,38 @@ body:
- MySQL
- MSSQL
- SQLite
- type: dropdown
id: can-reproduce
attributes:
label: Can you reproduce the bug on the Gitea demo site?
description: |
If so, please provide a URL in the Description field
URL of Gitea demo: https://try.gitea.io
options:
- "Yes"
- "No"
validations:
required: true
- type: markdown
attributes:
value: |
It's really important to provide pertinent logs
Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: input
id: logs
attributes:
label: Log Gist
description: Please provide a gist URL of your logs, with any sensitive information (e.g. API keys) removed/hidden
- type: textarea
id: description
attributes:
label: Description
description: |
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see above)
If you are using a proxy or a CDN (e.g. Cloudflare) in front of Gitea, please disable the proxy/CDN fully and access Gitea directly to confirm the issue still persists without those services.
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If this issue involves the Web Interface, please provide one or more screenshots

View File

@@ -1,10 +1,10 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Security Concern
url: https://tinyurl.com/security-gitea
about: For security concerns, please send a mail to security@gitea.io instead of opening a public issue.
- name: Discord Server
url: https://discord.gg/Gitea
url: https://discord.gg/gitea
about: Please ask questions and discuss configuration or deployment problems here.
- name: Discourse Forum
url: https://discourse.gitea.io

View File

@@ -1,6 +1,5 @@
name: Feature Request
description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here!
labels: ["kind/feature", "kind/proposal"]
body:
- type: markdown
attributes:

View File

@@ -1,6 +1,5 @@
name: Web Interface Bug Report
description: Something doesn't look quite as it should? Report it here!
labels: ["kind/bug", "kind/ui"]
body:
- type: markdown
attributes:
@@ -16,23 +15,6 @@ body:
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.io/en-us/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
6. In particular it's really important to provide pertinent logs. If you are certain that this is a javascript
error, show us the javascript console. If the error appears to relate to Gitea the server you must also give us
DEBUG level logs. (See https://docs.gitea.io/en-us/logging-configuration/#debugging-problems)
- type: textarea
id: description
attributes:
label: Description
description: |
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below)
If using a proxy or a CDN (e.g. CloudFlare) in front of gitea, please disable the proxy/CDN fully and connect to gitea directly to confirm the issue still persists without those services.
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: Please provide at least 1 screenshot showing the issue.
validations:
required: true
- type: input
id: gitea-ver
attributes:
@@ -40,18 +22,6 @@ body:
description: Gitea version (or commit reference) your instance is running
validations:
required: true
- type: dropdown
id: can-reproduce
attributes:
label: Can you reproduce the bug on the Gitea demo site?
description: |
If so, please provide a URL in the Description field
URL of Gitea demo: https://try.gitea.io
options:
- "Yes"
- "No"
validations:
required: true
- type: input
id: os-ver
attributes:
@@ -64,3 +34,29 @@ body:
description: The browser and version that you are using to access Gitea
validations:
required: true
- type: dropdown
id: can-reproduce
attributes:
label: Can you reproduce the bug on the Gitea demo site?
description: |
If so, please provide a URL in the Description field
URL of Gitea demo: https://try.gitea.io
options:
- "Yes"
- "No"
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: |
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see above)
If using a proxy or a CDN (e.g. CloudFlare) in front of gitea, please disable the proxy/CDN fully and connect to gitea directly to confirm the issue still persists without those services.
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: Please provide at least 1 screenshot showing the issue.
validations:
required: true

View File

@@ -1,9 +1,9 @@
<!-- start tips -->
<!--
Please check the following:
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for backports.
2. Make sure you have read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md .
3. Describe what your pull request does and which issue you're targeting (if any).
4. It is recommended to enable "Allow edits by maintainers", so maintainers can help more easily.
5. Your input here will be included in the commit message when this PR has been merged. If you don't want some content to be included, please separate them with a line like `---`.
6. Delete all these tips before posting.
<!-- end tips -->
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for bug fixes.
2. Read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md
3. Describe what your pull request does and which issue you're targeting (if any)
-->

24
.gitignore vendored
View File

@@ -63,14 +63,21 @@ cpu.out
/indexers
/log
/public/img/avatar
/tests/integration/gitea-integration-*
/tests/integration/indexers-*
/tests/e2e/gitea-e2e-*
/tests/e2e/indexers-*
/tests/e2e/reports
/tests/e2e/test-artifacts
/tests/e2e/test-snapshots
/tests/*.ini
/integrations/gitea-integration-mysql
/integrations/gitea-integration-mysql8
/integrations/gitea-integration-pgsql
/integrations/gitea-integration-sqlite
/integrations/gitea-integration-mssql
/integrations/indexers-mysql
/integrations/indexers-mysql8
/integrations/indexers-pgsql
/integrations/indexers-sqlite
/integrations/indexers-mssql
/integrations/sqlite.ini
/integrations/mysql.ini
/integrations/mysql8.ini
/integrations/pgsql.ini
/integrations/mssql.ini
/node_modules
/yarn.lock
/yarn-error.log
@@ -95,7 +102,6 @@ cpu.out
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
/VERSION
/.air
/.go-licenses
# Snapcraft
snap/.snapcraft/

View File

@@ -1,44 +0,0 @@
tasks:
- name: Setup
init: |
cp -r contrib/ide/vscode .vscode
make deps
make build
command: |
gp sync-done setup
exit 0
- name: Run backend
command: |
gp sync-await setup
mkdir -p custom/conf/
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
export TAGS="sqlite sqlite_unlock_notify"
make watch-backend
- name: Run frontend
command: |
gp sync-await setup
make watch-frontend
openMode: split-right
- name: Run docs
before: sudo bash -c "$(grep 'https://github.com/gohugoio/hugo/releases/download' Makefile | tr -d '\')" # install hugo
command: cd docs && make clean update && hugo server -D -F --baseUrl $(gp url 1313) --liveReloadPort=443 --appendPort=false --bind=0.0.0.0
openMode: split-right
vscode:
extensions:
- editorconfig.editorconfig
- dbaeumer.vscode-eslint
- golang.go
- stylelint.vscode-stylelint
- DavidAnson.vscode-markdownlint
- johnsoncodehk.volar
- ms-azuretools.vscode-docker
- zixuanchen.vitest-explorer
- alexcvzz.vscode-sqlite
ports:
- name: Gitea
port: 3000
- name: Docs
port: 1313

View File

@@ -1,45 +1,34 @@
linters:
enable:
- bidichk
# - deadcode # deprecated - https://github.com/golangci/golangci-lint/issues/1841
- depguard
- dupl
- errcheck
- gocritic
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
- gofmt
- gofumpt
- gosimple
- govet
- ineffassign
- nakedret
- nolintlint
- revive
- staticcheck
# - structcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
- stylecheck
- deadcode
- typecheck
- unconvert
- govet
- errcheck
- staticcheck
- unused
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
# - wastedassign # disabled - https://github.com/golangci/golangci-lint/issues/2649
- structcheck
- varcheck
- dupl
#- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
- gofmt
- misspell
- gocritic
- bidichk
- ineffassign
- revive
enable-all: false
disable-all: true
fast: false
run:
go: "1.20"
timeout: 10m
timeout: 3m
skip-dirs:
- node_modules
- public
- web_src
linters-settings:
stylecheck:
checks: ["all", "-ST1005", "-ST1003"]
nakedret:
max-func-lines: 0
gocritic:
disabled-checks:
- ifElseChain
@@ -72,23 +61,8 @@ linters-settings:
- name: errorf
- name: duplicated-imports
- name: modifies-value-receiver
gofumpt:
extra-rules: true
lang-version: "1.20"
depguard:
list-type: denylist
# Check the list against standard lib.
include-go-root: true
packages-with-error-message:
- encoding/json: "use gitea's modules/json instead of encoding/json"
- github.com/unknwon/com: "use gitea's util and replacements"
- io/ioutil: "use os or io instead"
- golang.org/x/exp: "it's experimental and unreliable."
- code.gitea.io/gitea/modules/git/internal: "do not use the internal package, use AddXxx function instead"
issues:
max-issues-per-linter: 0
max-same-issues: 0
exclude-rules:
# Exclude some linters from running on tests files.
- path: _test\.go
@@ -149,6 +123,9 @@ issues:
- path: models/issue_comment_list.go
linters:
- dupl
- linters:
- misspell
text: '`Unknwon` is a misspelling of `Unknown`'
- path: models/update.go
linters:
- unused
@@ -171,7 +148,3 @@ issues:
- path: models/user/openid.go
linters:
- golint
- path: models/user/badge.go
linters:
- revive
text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"

View File

@@ -1,18 +0,0 @@
commands-show-output: false
fenced-code-language: false
first-line-h1: false
header-increment: false
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1}
no-alt-text: false
no-bare-urls: false
no-blanks-blockquote: false
no-duplicate-header: {allow_different_nesting: true}
no-emphasis-as-header: false
no-empty-links: false
no-hard-tabs: {code_blocks: false}
no-inline-html: false
no-space-in-code: false
no-space-in-emphasis: false
no-trailing-punctuation: false
no-trailing-spaces: {br_spaces: 0}
single-h1: false

View File

@@ -1,12 +0,0 @@
extends: [[spectral:oas, all]]
rules:
info-contact: off
oas2-api-host: off
oas2-parameter-description: off
oas2-schema: off
oas2-valid-schema-example: off
openapi-tags: off
operation-description: off
operation-singular-tag: off
operation-tag-defined: off

31
.stylelintrc Normal file
View File

@@ -0,0 +1,31 @@
extends: stylelint-config-standard
overrides:
- files: ["**/*.less"]
customSyntax: postcss-less
rules:
alpha-value-notation: null
at-rule-empty-line-before: null
block-closing-brace-empty-line-before: null
color-function-notation: null
color-hex-length: null
comment-empty-line-before: null
declaration-block-no-redundant-longhand-properties: null
declaration-block-single-line-max-declarations: null
declaration-empty-line-before: null
hue-degree-notation: null
indentation: 2
max-line-length: null
no-descending-specificity: null
no-invalid-position-at-import-rule: null
number-leading-zero: never
number-max-precision: null
property-no-vendor-prefix: null
rule-empty-line-before: null
selector-class-pattern: null
selector-id-pattern: null
selector-pseudo-element-colon-notation: double
shorthand-property-no-redundant-values: true
string-quotes: null
value-no-vendor-prefix: null

View File

@@ -1,133 +0,0 @@
plugins:
- stylelint-declaration-strict-value
overrides:
- files: ["**/*.less"]
customSyntax: postcss-less
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
rules:
scale-unlimited/declaration-strict-value: null
rules:
alpha-value-notation: null
annotation-no-unknown: true
at-rule-allowed-list: null
at-rule-disallowed-list: null
at-rule-empty-line-before: null
at-rule-no-unknown: true
at-rule-no-vendor-prefix: true
at-rule-property-required-list: null
block-no-empty: true
color-function-notation: null
color-hex-alpha: null
color-hex-length: null
color-named: null
color-no-hex: null
color-no-invalid-hex: true
comment-empty-line-before: null
comment-no-empty: true
comment-pattern: null
comment-whitespace-inside: null
comment-word-disallowed-list: null
custom-media-pattern: null
custom-property-empty-line-before: null
custom-property-no-missing-var-function: true
custom-property-pattern: null
declaration-block-no-duplicate-custom-properties: true
declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}]
declaration-block-no-redundant-longhand-properties: null
declaration-block-no-shorthand-property-overrides: null
declaration-block-single-line-max-declarations: null
declaration-empty-line-before: null
declaration-no-important: null
declaration-property-max-values: null
declaration-property-unit-allowed-list: null
declaration-property-unit-disallowed-list: null
declaration-property-value-allowed-list: null
declaration-property-value-disallowed-list: null
declaration-property-value-no-unknown: true
font-family-name-quotes: always-where-recommended
font-family-no-duplicate-names: true
font-family-no-missing-generic-family-keyword: true
font-weight-notation: null
function-allowed-list: null
function-calc-no-unspaced-operator: true
function-disallowed-list: null
function-linear-gradient-no-nonstandard-direction: true
function-name-case: lower
function-no-unknown: null
function-url-no-scheme-relative: null
function-url-quotes: always
function-url-scheme-allowed-list: null
function-url-scheme-disallowed-list: null
hue-degree-notation: null
import-notation: string
keyframe-block-no-duplicate-selectors: true
keyframe-declaration-no-important: true
keyframe-selector-notation: null
keyframes-name-pattern: null
length-zero-no-unit: true
max-nesting-depth: null
media-feature-name-allowed-list: null
media-feature-name-disallowed-list: null
media-feature-name-no-unknown: true
media-feature-name-no-vendor-prefix: true
media-feature-name-unit-allowed-list: null
media-feature-name-value-allowed-list: null
media-feature-range-notation: null
named-grid-areas-no-invalid: true
no-descending-specificity: null
no-duplicate-at-import-rules: true
no-duplicate-selectors: true
no-empty-source: true
no-invalid-double-slash-comments: true
no-invalid-position-at-import-rule: null
no-irregular-whitespace: true
no-unknown-animations: null
number-max-precision: null
property-allowed-list: null
property-disallowed-list: null
property-no-unknown: true
property-no-vendor-prefix: null
rule-empty-line-before: null
rule-selector-property-disallowed-list: null
scale-unlimited/declaration-strict-value: [color, {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor)$/}]
selector-attribute-name-disallowed-list: null
selector-attribute-operator-allowed-list: null
selector-attribute-operator-disallowed-list: null
selector-attribute-quotes: always
selector-class-pattern: null
selector-combinator-allowed-list: null
selector-combinator-disallowed-list: null
selector-disallowed-list: null
selector-id-pattern: null
selector-max-attribute: null
selector-max-class: null
selector-max-combinators: null
selector-max-compound-selectors: null
selector-max-id: null
selector-max-pseudo-class: null
selector-max-specificity: null
selector-max-type: null
selector-max-universal: null
selector-nested-pattern: null
selector-no-qualifying-type: null
selector-no-vendor-prefix: true
selector-not-notation: null
selector-pseudo-class-allowed-list: null
selector-pseudo-class-disallowed-list: null
selector-pseudo-class-no-unknown: true
selector-pseudo-element-allowed-list: null
selector-pseudo-element-colon-notation: double
selector-pseudo-element-disallowed-list: null
selector-pseudo-element-no-unknown: true
selector-type-case: lower
selector-type-no-unknown: [true, {ignore: [custom-elements]}]
shorthand-property-no-redundant-values: true
string-no-newline: true
time-min-milliseconds: null
unit-allowed-list: null
unit-disallowed-list: null
unit-no-unknown: true
value-keyword-case: null
value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}]

File diff suppressed because it is too large Load Diff

View File

@@ -81,15 +81,13 @@ Here's how to run the test suite:
|``make lint-frontend`` | lint frontend files |
|``make lint-backend`` | lint backend files |
- run test code (Suggest run in Linux)
- run test code (Suggest run in Linux)
| | |
| :------------------------------------- | :----------------------------------------------- |
|``make test[\#TestSpecificName]`` | run unit test |
|``make test-sqlite[\#TestSpecificName]``| run [integration](tests/integration) test for SQLite |
|[More details about integration tests](tests/integration/README.md) |
|``make test-e2e-sqlite[\#TestSpecificFileName]``| run [end-to-end](tests/e2e) test for SQLite |
|[More details about e2e tests](tests/e2e/README.md) |
|``make test-sqlite[\#TestSpecificName]``| run [integration](integrations) test for SQLite |
|[More details about integrations](integrations/README.md) |
## Vendoring
@@ -129,42 +127,22 @@ the *[How to get faster PR reviews](https://github.com/kubernetes/community/blob
it has lots of useful tips for any project you may want to contribute.
Some of the key points:
- Make small pull requests. The smaller, the faster to review and the
* Make small pull requests. The smaller, the faster to review and the
more likely it will be merged soon.
- Don't make changes unrelated to your PR. Maybe there are typos on
* Don't make changes unrelated to your PR. Maybe there are typos on
some comments, maybe refactoring would be welcome on a function... but
if that is not related to your PR, please make *another* PR for that.
- Split big pull requests into multiple small ones. An incremental change
* Split big pull requests into multiple small ones. An incremental change
will be faster to review than a huge PR.
- Use the first comment as a summary explainer of your PR and you should keep this up-to-date as the PR evolves.
If your PR could cause a breaking change you must add a BREAKING section to this comment e.g.:
```
## :warning: BREAKING :warning:
```
To explain how this could affect users and how to mitigate these changes.
Once code review starts on your PR, do not rebase nor squash your branch as it makes it
difficult to review the new changes. Only if there is a need, sync your branch by merging
the base branch into yours. Don't worry about merge commits messing up your tree as
the final merge process squashes all commits into one, with the visible commit message (first
line) being the PR title + PR index and description being the PR's first comment.
Once your PR gets the `lgtm/done` label, don't worry about keeping it up-to-date or breaking
builds (unless there's a merge conflict or a request is made by a maintainer to make
modifications). It is the maintainer team's responsibility from this point to get it merged.
## Styleguide
For imports you should use the following format (*without* the comments)
For imports you should use the following format (_without_ the comments)
```go
import (
// stdlib
"encoding/json"
"fmt"
"math"
// local packages
"code.gitea.io/gitea/models"
@@ -180,36 +158,25 @@ import (
To maintain understandable code and avoid circular dependencies it is important to have a good structure of the code. The Gitea code is divided into the following parts:
- **integration:** Integrations tests
- **models:** Contains the data structures used by xorm to construct database tables. It also contains supporting functions to query and update the database. Dependencies to other code in Gitea should be avoided although some modules might be needed (for example for logging).
- **models/fixtures:** Sample model data used in integration tests.
- **models/migrations:** Handling of database migrations between versions. PRs that changes a database structure shall also have a migration step.
- **modules:** Different modules to handle specific functionality in Gitea. Shall only depend on other modules but not other packages (models, services).
- **modules:** Different modules to handle specific functionality in Gitea.
- **public:** 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) shall not depend on routers
- **services:** Support functions for common routing operations. Uses models and modules to handle the request.
- **templates:** Golang templates for generating the html output.
- **tests/e2e:** End to end tests
- **tests/integration:** Integration tests
- **tests/gitea-repositories-meta:** Sample repos used in integration tests. Adding a new repo requires editing `models/fixtures/repositories.yml` and `models/fixtures/repo_unit.yml` to match.
- **tests/gitea-lfs-meta:** Sample LFS objects used in integration tests. Adding a new object requires editing `models/fixtures/lfs_meta_object.yml` to match.
- **vendor:** External code that Gitea depends on.
## Documentation
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated.
## API v1
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [GitHub API v3](https://developer.github.com/v3/).
Thus, Gitea´s API should use the same endpoints and fields as GitHub´s API as far as possible, unless there are good reasons to deviate.
If Gitea provides functionality that GitHub does not, a new endpoint can be created.
Thus, Gitea´s API should use the same endpoints and fields as GitHub´s API as far as possible, unless there are good reasons to deviate.
If Gitea provides functionality that GitHub does not, a new endpoint can be created.
If information is provided by Gitea that is not provided by the GitHub API, a new field can be used that doesn't collide with any GitHub fields.
Updating an existing API should not remove existing fields unless there is a really good reason to do so.
The same applies to status responses. If you notice a problem, feel free to leave a comment in the code for future refactoring to APIv2 (which is currently not planned).
All expected results (errors, success, fail messages) should be documented
@@ -218,60 +185,31 @@ All expected results (errors, success, fail messages) should be documented
All JSON input types must be defined as a struct in [modules/structs/](modules/structs/)
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91))
and referenced in
[routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go).
[routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go).
They can then be used like the following:
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318)).
All JSON responses must be defined as a struct in [modules/structs/](modules/structs/)
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L36-L68))
and referenced in its category in [routers/api/v1/swagger/](routers/api/v1/swagger/)
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16))
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16))
They can be used like the following:
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279))
In general, HTTP methods are chosen as follows:
* **GET** endpoints return requested object and status **OK (200)**
* **DELETE** endpoints return status **No Content (204)**
* **POST** endpoints return status **Created (201)**, used to **create** new objects (e.g. a User)
* **PUT** endpoints return status **No Content (204)**, used to **add/assign** existing Objects (e.g. User) to something (e.g. Org-Team)
* **PATCH** endpoints return changed object and status **OK (200)**, used to **edit/change** an existing object
- **GET** endpoints return requested object and status **OK (200)**
- **DELETE** endpoints return status **No Content (204)**
- **POST** endpoints return status **Created (201)**, used to **create** new objects (e.g. a User)
- **PUT** endpoints return status **No Content (204)**, used to **add/assign** existing Objects (e.g. User) to something (e.g. Org-Team)
- **PATCH** endpoints return changed object and status **OK (200)**, used to **edit/change** an existing object
An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
### Endpoints returning lists should
* support pagination (`page` & `limit` options in query)
* set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
- support pagination (`page` & `limit` options in query)
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
## Backports and Frontports
Occasionally backports of PRs are required.
The backported PR title should be:
```
Title of backported PR (#ORIGINAL_PR_NUMBER)
```
The first two lines of the summary of the backporting PR should be:
```
Backport #ORIGINAL_PR_NUMBER
```
with the rest of the summary matching the original PR. Similarly for frontports
---
A command to help create backports can be found in `contrib/backport` and can be installed (from inside the gitea repo root directory) using:
```bash
go install contrib/backport/backport.go
```
## Developer Certificate of Origin (DCO)
@@ -299,7 +237,9 @@ known as the release freeze. All the feature pull requests should be
merged before feature freeze. And, during the frozen period, a corresponding
release branch is open for fixes backported from main branch. Release candidates
are made during this period for user testing to
obtain a final version that is maintained in this branch.
obtain a final version that is maintained in this branch. A release is
maintained by issuing patch releases to only correct critical problems
such as crashes or security issues.
Major release cycles are seasonal. They always begin on the 25th and end on
the 24th (i.e., the 25th of December to March 24th).
@@ -309,16 +249,6 @@ for the previous version. For example, if the latest, published release is
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
still possible.
The previous release gets fixes for:
- Security issues
- Critical bugs
- Regressions
- Build issues
- Necessary enhancements (including necessary UI/UX fixes)
The backported fixes should avoid breaking downgrade between minor releases as much as possible.
## Maintainers
To make sure every PR is checked, we have [team
@@ -368,35 +298,35 @@ and lead the development of Gitea.
To honor the past owners, here's the history of the owners and the time
they served:
- 2022-01-01 ~ 2022-12-31 - https://github.com/go-gitea/gitea/issues/17872
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
* 2022-01-01 ~ 2022-12-31 - https://github.com/go-gitea/gitea/issues/17872
* [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
* [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
* [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
- 2021-01-01 ~ 2021-12-31 - https://github.com/go-gitea/gitea/issues/13801
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
* 2021-01-01 ~ 2021-12-31 - https://github.com/go-gitea/gitea/issues/13801
* [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
* [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
* [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
- 2020-01-01 ~ 2020-12-31 - https://github.com/go-gitea/gitea/issues/9230
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
* 2020-01-01 ~ 2020-12-31 - https://github.com/go-gitea/gitea/issues/9230
* [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
* [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
* [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
- 2019-01-01 ~ 2019-12-31 - https://github.com/go-gitea/gitea/issues/5572
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
- [Matti Ranta](https://github.com/techknowlogick) <techknowlogick@gitea.io>
* 2019-01-01 ~ 2019-12-31 - https://github.com/go-gitea/gitea/issues/5572
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
* [Matti Ranta](https://github.com/techknowlogick) <techknowlogick@gitea.io>
- 2018-01-01 ~ 2018-12-31 - https://github.com/go-gitea/gitea/issues/3255
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
* 2018-01-01 ~ 2018-12-31 - https://github.com/go-gitea/gitea/issues/3255
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
* [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
* [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
- 2016-11-04 ~ 2017-12-31
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
- [Thomas Boerger](https://github.com/tboerger) <thomas@webhippie.de>
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
* 2016-11-04 ~ 2017-12-31
* [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
* [Thomas Boerger](https://github.com/tboerger) <thomas@webhippie.de>
* [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
## Versions
@@ -413,29 +343,25 @@ be reviewed by two maintainers and must pass the automatic tests.
## Releasing Gitea
- Let $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin will be kept the same as milestones on github or gitea in future.
- Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on Discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody against in about serval hours.
- If this is a big version first you have to create PR for changelog on branch `main` with PRs with label `changelog` and after it has been merged do following steps:
- Create `-dev` tag as `git tag -s -F release.notes v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
- When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
- If it is bugfix version create PR for changelog on branch `release/v$vmaj.$vmin` and wait till it is reviewed and merged.
- Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
- And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
- Verify all release assets were correctly published through CI on dl.gitea.io and GitHub releases. Once ACKed:
- bump the version of https://dl.gitea.io/gitea/version.json
- merge the blog post PR
- announce the release in discord `#announcements`
* Let $vmaj, $vmin and $vpat be Major, Minor and Patch version numbers, $vpat should be rc1, rc2, 0, 1, ...... $vmaj.$vmin will be kept the same as milestones on github or gitea in future.
* Before releasing, confirm all the version's milestone issues or PRs has been resolved. Then discuss the release on Discord channel #maintainers and get agreed with almost all the owners and mergers. Or you can declare the version and if nobody against in about serval hours.
* If this is a big version first you have to create PR for changelog on branch `main` with PRs with label `changelog` and after it has been merged do following steps:
* Create `-dev` tag as `git tag -s -F release.notes v$vmaj.$vmin.0-dev` and push the tag as `git push origin v$vmaj.$vmin.0-dev`.
* When CI has finished building tag then you have to create a new branch named `release/v$vmaj.$vmin`
* If it is bugfix version create PR for changelog on branch `release/v$vmaj.$vmin` and wait till it is reviewed and merged.
* Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
* And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
* If needed send PR for changelog on branch `main`.
* Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
## Copyright
Code that you contribute should use the standard copyright header:
```
// Copyright <year> The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Copyright 2020 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.
```
Files in the repository contain copyright from the year they are added

4
DCO
View File

@@ -2,6 +2,8 @@ Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
@@ -31,4 +33,4 @@ By making a contribution to this project, I certify that:
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
this project or the open source license(s) involved.

View File

@@ -1,5 +1,7 @@
#Build stage
FROM golang:1.20-alpine3.17 AS build-env
###################################
#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
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
@@ -23,7 +25,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
# Begin env-to-ini build
RUN go build contrib/environment-to-ini/environment-to-ini.go
FROM alpine:3.17
FROM alpine:3.13
LABEL maintainer="maintainers@gitea.io"
EXPOSE 22 3000
@@ -64,7 +66,5 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
COPY docker/root /
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
RUN chmod 755 /usr/bin/entrypoint /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
RUN chmod 755 /etc/s6/gitea/* /etc/s6/openssh/* /etc/s6/.s6-svscan/*
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh

View File

@@ -1,5 +1,7 @@
#Build stage
FROM golang:1.20-alpine3.17 AS build-env
###################################
#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
ARG GOPROXY
ENV GOPROXY ${GOPROXY:-direct}
@@ -23,7 +25,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
# Begin env-to-ini build
RUN go build contrib/environment-to-ini/environment-to-ini.go
FROM alpine:3.17
FROM alpine:3.13
LABEL maintainer="maintainers@gitea.io"
EXPOSE 2222 3000
@@ -31,7 +33,6 @@ EXPOSE 2222 3000
RUN apk --no-cache add \
bash \
ca-certificates \
dumb-init \
gettext \
git \
curl \
@@ -54,9 +55,7 @@ RUN chown git:git /var/lib/gitea /etc/gitea
COPY docker/rootless /
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-setup.sh /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh
#git:git
USER 1000:1000
@@ -65,12 +64,12 @@ ENV GITEA_CUSTOM /var/lib/gitea/custom
ENV GITEA_TEMP /tmp/gitea
ENV TMPDIR /tmp/gitea
#TODO add to docs the ability to define the ini to load (useful to test and revert a config)
#TODO add to docs the ability to define the ini to load (usefull to test and revert a config)
ENV GITEA_APP_INI /etc/gitea/app.ini
ENV HOME "/var/lib/gitea/git"
VOLUME ["/var/lib/gitea", "/etc/gitea"]
WORKDIR /var/lib/gitea
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD []

View File

@@ -6,6 +6,7 @@ Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
Matthias Loibl <mail@matthiasloibl.com> (@metalmatze)
Morgan Bazalgette <the@howl.moe> (@thehowl)
Rachid Zarouali <nobody@nobody.tld> (@xinity)
Rémy Boulanouar <admin@dblk.org> (@DblK)
Sandro Santilli <strk@kbt.io> (@strk)
@@ -43,10 +44,5 @@ Janis Estelmann <admin@oldschoolhack.me> (@KN4CK3R)
Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
Leon Hofmeister <dev.lh@web.de> (@delvh)
Wim <wim@42.be> (@42wim)
Xinyu Zhou <i@sourcehut.net> (@xin-u)
Jason Song <i@wolfogre.com> (@wolfogre)
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
Yu Tian <zettat123@gmail.com> (@Zettat123)
Eddie Yang <576951401@qq.com> (@yp05327)
Dong Ge <gedong_1994@163.com> (@sillyguodong)
Gusted <williamzijl7@hotmail.com) (@Gusted)
singuliere <singuliere@autistici.org> (@singuliere)

496
Makefile
View File

@@ -17,25 +17,17 @@ else
DIST := dist
DIST_DIRS := $(DIST)/binaries $(DIST)/release
IMPORT := code.gitea.io/gitea
export GO111MODULE=on
GO ?= go
SHASUM ?= shasum -a 256
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
COMMA := ,
XGO_VERSION := go-1.20.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0
ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0
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.30.3
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.5.0
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
XGO_VERSION := go-1.17.x
MIN_GO_VERSION := 001016000
MIN_NODE_VERSION := 012017000
MIN_GOLANGCI_LINT_VERSION := 001043000
DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest
@@ -68,7 +60,7 @@ endif
EXTRA_GOFLAGS ?=
MAKE_VERSION := $(shell "$(MAKE)" -v | head -n 1)
MAKE_VERSION := $(shell $(MAKE) -v | head -n 1)
MAKE_EVIDENCE_DIR := .make_evidence
ifeq ($(RACE_ENABLED),true)
@@ -100,8 +92,7 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/models/migrations code.gitea.io/gitea/integrations/migration-test code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/))
FOMANTIC_WORK_DIR := web_src/fomantic
@@ -113,41 +104,29 @@ WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack pub
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go
SVG_DEST_DIR := public/img/svg
AIR_TMP_DIR := .air
GO_LICENSE_TMP_DIR := .go-licenses
GO_LICENSE_FILE := assets/go-licenses.json
TAGS ?=
TAGS_SPLIT := $(subst $(COMMA), ,$(TAGS))
TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
TEST_TAGS ?= sqlite sqlite_unlock_notify
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR)
GO_DIRS := cmd tests models modules routers build services tools
WEB_DIRS := web_src/js web_src/less
GO_DIRS := cmd integrations models modules routers build services tools
GO_SOURCES := $(wildcard *.go)
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" -not -path modules/options/bindata.go -not -path modules/public/bindata.go -not -path modules/templates/bindata.go)
GO_SOURCES += $(GENERATED_GO_DEST)
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
GO_SOURCES += $(BINDATA_DEST)
GENERATED_GO_DEST += $(BINDATA_DEST)
endif
# Force installation of playwright dependencies by setting this flag
ifdef DEPS_PLAYWRIGHT
PLAYWRIGHT_FLAGS += --with-deps
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
@@ -199,7 +178,6 @@ help:
@echo " - test test everything"
@echo " - test-frontend test frontend files"
@echo " - test-backend test backend files"
@echo " - test-e2e[\#TestSpecificName] test end to end using playwright"
@echo " - webpack build webpack files"
@echo " - svg build svg files"
@echo " - fomantic build fomantic files"
@@ -211,20 +189,16 @@ help:
@echo " - generate-swagger generate the swagger spec from code comments"
@echo " - swagger-validate check if the swagger spec is valid"
@echo " - golangci-lint run golangci-lint linter"
@echo " - go-licenses regenerate go licenses"
@echo " - vet examines Go source code and reports suspicious constructs"
@echo " - tidy run go mod tidy"
@echo " - test[\#TestSpecificName] run unit test"
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
@echo " - pr#<index> build and start gitea from a PR with integration test data loaded"
.PHONY: go-check
go-check:
$(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" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9.]+' | tr '.' ' ');))
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
echo "Gitea requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
echo "Gitea requires Go 1.16 or greater to build. You can get it at https://golang.org/dl/"; \
exit 1; \
fi
@@ -237,12 +211,11 @@ 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_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
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/"; \
exit 1; \
fi
@@ -255,33 +228,14 @@ clean:
$(GO) clean -i ./...
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \
integrations*.test \
e2e*.test \
tests/integration/gitea-integration-pgsql/ tests/integration/gitea-integration-mysql/ tests/integration/gitea-integration-mysql8/ tests/integration/gitea-integration-sqlite/ \
tests/integration/gitea-integration-mssql/ tests/integration/indexers-mysql/ tests/integration/indexers-mysql8/ tests/integration/indexers-pgsql tests/integration/indexers-sqlite \
tests/integration/indexers-mssql tests/mysql.ini tests/mysql8.ini tests/pgsql.ini tests/mssql.ini man/ \
tests/e2e/gitea-e2e-pgsql/ tests/e2e/gitea-e2e-mysql/ tests/e2e/gitea-e2e-mysql8/ tests/e2e/gitea-e2e-sqlite/ \
tests/e2e/gitea-e2e-mssql/ tests/e2e/indexers-mysql/ tests/e2e/indexers-mysql8/ tests/e2e/indexers-pgsql/ tests/e2e/indexers-sqlite/ \
tests/e2e/indexers-mssql/ tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-mysql8/ integrations/gitea-integration-sqlite/ \
integrations/gitea-integration-mssql/ integrations/indexers-mysql/ integrations/indexers-mysql8/ integrations/indexers-pgsql integrations/indexers-sqlite \
integrations/indexers-mssql integrations/mysql.ini integrations/mysql8.ini integrations/pgsql.ini integrations/mssql.ini man/
.PHONY: fmt
fmt:
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
@# strip whitespace after '{{' and before `}}` unless there is only whitespace before it
@$(SED_INPLACE) -e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' $(TEMPLATES)
.PHONY: fmt-check
fmt-check: fmt
@diff=$$(git diff $(GO_SOURCES) templates $(WEB_DIRS)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi
.PHONY: misspell-check
misspell-check:
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
@echo "Running gitea-fmt(with gofmt)..."
@$(GO) run build/code-batch-process.go gitea-fmt -s -w '{file-list}'
.PHONY: vet
vet:
@@ -299,10 +253,8 @@ TAGS_PREREQ := $(TAGS_EVIDENCE)
endif
.PHONY: generate-swagger
generate-swagger: $(SWAGGER_SPEC)
$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
$(GO) run $(SWAGGER_PACKAGE) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
generate-swagger:
$(SWAGGER) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
@@ -318,13 +270,26 @@ swagger-check: generate-swagger
.PHONY: swagger-validate
swagger-validate:
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
$(SWAGGER) 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..."
$(GO) run $(ERRCHECK_PACKAGE) $(GO_PACKAGES)
@errcheck $(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}'); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi
.PHONY: checks
checks: checks-frontend checks-backend
@@ -333,20 +298,19 @@ checks: checks-frontend checks-backend
checks-frontend: lockfile-check svg-check
.PHONY: checks-backend
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check
checks-backend: gomod-check swagger-check swagger-validate
.PHONY: lint
lint: lint-frontend lint-backend
.PHONY: lint-frontend
lint-frontend: node_modules
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e
npx eslint --color --max-warnings=0 web_src/js build templates *.config.js docs/assets/js
npx stylelint --color --max-warnings=0 web_src/less
npx spectral lint -q -F hint $(SWAGGER_SPEC)
npx markdownlint docs *.md
npx editorconfig-checker templates
.PHONY: lint-backend
lint-backend: golangci-lint vet editorconfig-checker
lint-backend: golangci-lint vet
.PHONY: watch
watch:
@@ -359,7 +323,10 @@ watch-frontend: node-check node_modules
.PHONY: watch-backend
watch-backend: go-check
GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml
@hash air > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install github.com/cosmtrek/air@bedc18201271882c2be66d216d0e1a275b526ec4; \
fi
air -c .air.toml
.PHONY: test
test: test-frontend test-backend
@@ -367,11 +334,11 @@ test: test-frontend test-backend
.PHONY: test-backend
test-backend:
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_PACKAGES)
.PHONY: test-frontend
test-frontend: node_modules
npx vitest
@NODE_OPTIONS="--experimental-vm-modules --no-warnings" npx jest --color
.PHONY: test-check
test-check:
@@ -388,62 +355,54 @@ test-check:
.PHONY: test\#%
test\#%:
@echo "Running go test with -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_PACKAGES)
.PHONY: coverage
coverage:
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' coverage.out > coverage-bodged.out
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' integration.coverage.out > integration.coverage-bodged.out
$(GO) run build/gocovmerge.go integration.coverage-bodged.out coverage-bodged.out > coverage.all
GO111MODULE=on $(GO) run build/gocovmerge.go integration.coverage-bodged.out coverage-bodged.out > coverage.all || (echo "gocovmerge failed"; echo "integration.coverage.out"; cat integration.coverage.out; echo "coverage.out"; cat coverage.out; exit 1)
.PHONY: unit-test-coverage
unit-test-coverage:
@echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
@$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
.PHONY: tidy
tidy:
$(eval MIN_GO_VERSION := $(shell grep -Eo '^go\s+[0-9]+\.[0-9.]+' go.mod | cut -d' ' -f2))
$(GO) mod tidy -compat=$(MIN_GO_VERSION)
@$(MAKE) --no-print-directory $(GO_LICENSE_FILE)
.PHONY: vendor
vendor:
$(GO) mod tidy && $(GO) mod vendor
vendor: go.mod go.sum
$(GO) mod vendor
@touch vendor
.PHONY: tidy-check
tidy-check: tidy
@diff=$$(git diff go.mod go.sum $(GO_LICENSE_FILE)); \
.PHONY: gomod-check
gomod-check:
@$(GO) mod tidy
@diff=$$(git diff go.sum); \
if [ -n "$$diff" ]; then \
echo "Please run 'make tidy' and commit the result:"; \
echo "Please run '$(GO) mod tidy' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi
.PHONY: go-licenses
go-licenses: $(GO_LICENSE_FILE)
$(GO_LICENSE_FILE): go.mod go.sum
-$(GO) run $(GO_LICENSES_PACKAGE) save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
@rm -rf $(GO_LICENSE_TMP_DIR)
generate-ini-sqlite:
sed -e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
tests/sqlite.ini.tmpl > tests/sqlite.ini
integrations/sqlite.ini.tmpl > integrations/sqlite.ini
.PHONY: test-sqlite
test-sqlite: integrations.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test
.PHONY: test-sqlite\#%
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
.PHONY: test-sqlite-migration
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test generate-ini-sqlite
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' \
@@ -451,20 +410,20 @@ generate-ini-mysql:
-e 's|{{TEST_MYSQL_USERNAME}}|${TEST_MYSQL_USERNAME}|g' \
-e 's|{{TEST_MYSQL_PASSWORD}}|${TEST_MYSQL_PASSWORD}|g' \
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
tests/mysql.ini.tmpl > tests/mysql.ini
integrations/mysql.ini.tmpl > integrations/mysql.ini
.PHONY: test-mysql
test-mysql: integrations.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test
.PHONY: test-mysql\#%
test-mysql\#%: integrations.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
.PHONY: test-mysql-migration
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./migrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./migrations.individual.mysql.test
generate-ini-mysql8:
sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \
@@ -472,20 +431,20 @@ generate-ini-mysql8:
-e 's|{{TEST_MYSQL8_USERNAME}}|${TEST_MYSQL8_USERNAME}|g' \
-e 's|{{TEST_MYSQL8_PASSWORD}}|${TEST_MYSQL8_PASSWORD}|g' \
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
tests/mysql8.ini.tmpl > tests/mysql8.ini
integrations/mysql8.ini.tmpl > integrations/mysql8.ini
.PHONY: test-mysql8
test-mysql8: integrations.mysql8.test generate-ini-mysql8
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test
.PHONY: test-mysql8\#%
test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*)
.PHONY: test-mysql8-migration
test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test
test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test generate-ini-mysql8
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./migrations.mysql8.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql8.ini ./migrations.individual.mysql8.test
generate-ini-pgsql:
sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \
@@ -494,20 +453,20 @@ generate-ini-pgsql:
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
-e 's|{{TEST_PGSQL_SCHEMA}}|${TEST_PGSQL_SCHEMA}|g' \
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
tests/pgsql.ini.tmpl > tests/pgsql.ini
integrations/pgsql.ini.tmpl > integrations/pgsql.ini
.PHONY: test-pgsql
test-pgsql: integrations.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test
.PHONY: test-pgsql\#%
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
.PHONY: test-pgsql-migration
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./migrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./migrations.individual.pgsql.test
generate-ini-mssql:
sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
@@ -515,205 +474,98 @@ generate-ini-mssql:
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
tests/mssql.ini.tmpl > tests/mssql.ini
integrations/mssql.ini.tmpl > integrations/mssql.ini
.PHONY: test-mssql
test-mssql: integrations.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test
.PHONY: test-mssql\#%
test-mssql\#%: integrations.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
.PHONY: test-mssql-migration
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
.PHONY: playwright
playwright: $(PLAYWRIGHT_DIR)
npm install --no-save @playwright/test
npx playwright install $(PLAYWRIGHT_FLAGS)
.PHONY: test-e2e%
test-e2e%: TEST_TYPE ?= e2e
# Clear display env variable. Otherwise, chromium tests can fail.
DISPLAY=
.PHONY: test-e2e
test-e2e: test-e2e-sqlite
.PHONY: test-e2e-sqlite
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test
.PHONY: test-e2e-sqlite\#%
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e/$*
.PHONY: test-e2e-mysql
test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test
.PHONY: test-e2e-mysql\#%
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$*
.PHONY: test-e2e-mysql8
test-e2e-mysql8: playwright e2e.mysql8.test generate-ini-mysql8
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test
.PHONY: test-e2e-mysql8\#%
test-e2e-mysql8\#%: playwright e2e.mysql8.test generate-ini-mysql8
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test -test.run TestE2e/$*
.PHONY: test-e2e-pgsql
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test
.PHONY: test-e2e-pgsql\#%
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e/$*
.PHONY: test-e2e-mssql
test-e2e-mssql: playwright e2e.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test
.PHONY: test-e2e-mssql\#%
test-e2e-mssql\#%: playwright e2e.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test -test.run TestE2e/$*
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./migrations.mssql.test -test.failfast
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./migrations.individual.mssql.test -test.failfast
.PHONY: bench-sqlite
bench-sqlite: integrations.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
.PHONY: bench-mysql
bench-mysql: integrations.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
.PHONY: bench-mssql
bench-mssql: integrations.mssql.test generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
.PHONY: bench-pgsql
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
.PHONY: integration-test-coverage
integration-test-coverage: integrations.cover.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
.PHONY: integration-test-coverage-sqlite
integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
GITEA_ROOT="$(CURDIR)" GITEA_CONF=integrations/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
integrations.mysql.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mysql.test
integrations.mysql8.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql8.test
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mysql8.test
integrations.pgsql.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.pgsql.test
integrations.mssql.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mssql.test
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.mssql.test
integrations.sqlite.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -o integrations.sqlite.test -tags '$(TEST_TAGS)'
integrations.cover.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test
integrations.cover.sqlite.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(GO_PACKAGES) | tr ' ' ',') -o integrations.cover.test
.PHONY: migrations.mysql.test
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test
migrations.mysql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql.test
.PHONY: migrations.mysql8.test
migrations.mysql8.test: $(GO_SOURCES) generate-ini-mysql8
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql8.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test
migrations.mysql8.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mysql8.test
.PHONY: migrations.pgsql.test
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test
migrations.pgsql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.pgsql.test
.PHONY: migrations.mssql.test
migrations.mssql.test: $(GO_SOURCES) generate-ini-mssql
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test
migrations.mssql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.mssql.test
.PHONY: migrations.sqlite.test
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test
migrations.sqlite.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/integrations/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
.PHONY: migrations.individual.mysql.test
migrations.individual.mysql.test: $(GO_SOURCES)
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
done
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mysql.test
.PHONY: migrations.individual.mysql8.test
migrations.individual.mysql8.test: $(GO_SOURCES)
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
done
.PHONY: migrations.individual.mysql8.test\#%
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mysql8.test
.PHONY: migrations.individual.pgsql.test
migrations.individual.pgsql.test: $(GO_SOURCES)
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
done
.PHONY: migrations.individual.pgsql.test\#%
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.pgsql.test
.PHONY: migrations.individual.mssql.test
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \
done
.PHONY: migrations.individual.mssql.test\#%
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
migrations.individual.mssql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.mssql.test
.PHONY: migrations.individual.sqlite.test
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
done
.PHONY: migrations.individual.sqlite.test\#%
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
e2e.mysql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
e2e.mysql8.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql8.test
e2e.pgsql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
e2e.mssql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mssql.test
e2e.sqlite.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
migrations.individual.sqlite.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/models/migrations -o migrations.individual.sqlite.test -tags '$(TEST_TAGS)'
.PHONY: check
check: test
@@ -729,67 +581,58 @@ build: frontend backend
frontend: $(WEBPACK_DEST)
.PHONY: backend
backend: go-check generate-backend $(EXECUTABLE)
backend: go-check generate $(EXECUTABLE)
# We generate the backend before the frontend in case we in future we want to generate things in the frontend from generated files in backend
.PHONY: generate
generate: generate-backend
.PHONY: generate-backend
generate-backend: $(TAGS_PREREQ) generate-go
.PHONY: generate-go
generate-go: $(TAGS_PREREQ)
generate: $(TAGS_PREREQ)
@echo "Running go generate..."
@CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' $(GO_PACKAGES)
.PHONY: security-check
security-check:
go run $(GOVULNCHECK_PACKAGE) -v ./...
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
.PHONY: release
release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-docs release-check
release: frontend generate release-windows release-linux release-darwin release-copy release-compress vendor release-sources release-docs release-check
$(DIST_DIRS):
mkdir -p $(DIST_DIRS)
.PHONY: release-windows
release-windows: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
@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) .
ifeq (,$(findstring gogit,$(TAGS)))
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
CGO_CFLAGS="$(CGO_CFLAGS)" 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 .
endif
ifeq ($(CI),true)
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
.PHONY: release-linux
release-linux: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
ifeq ($(CI),true)
@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) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
.PHONY: release-darwin
release-darwin: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
ifeq ($(CI),true)
cp /build/* $(DIST)/binaries
endif
.PHONY: release-freebsd
release-freebsd: | $(DIST_DIRS)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
ifeq ($(CI),true)
@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) .
ifeq ($(CI),drone)
cp /build/* $(DIST)/binaries
endif
.PHONY: release-copy
release-copy: | $(DIST_DIRS)
cd $(DIST); for file in `find . -type f -name "*"`; do cp $${file} ./release/; done;
cd $(DIST); for file in `find /build -type f -name "*"`; do cp $${file} ./release/; done;
.PHONY: release-check
release-check: | $(DIST_DIRS)
@@ -797,16 +640,17 @@ release-check: | $(DIST_DIRS)
.PHONY: release-compress
release-compress: | $(DIST_DIRS)
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done;
@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;
.PHONY: release-sources
release-sources: | $(DIST_DIRS)
echo $(VERSION) > $(STORED_VERSION_FILE)
# bsdtar needs a ^ to prevent matching subdirectories
$(eval EXCL := --exclude=$(shell tar --help | grep -q bsdtar && echo "^")./)
# use transform to a add a release-folder prefix; in bsdtar the transform parameter equivalent is -s
$(eval TRANSFORM := $(shell tar --help | grep -q bsdtar && echo "-s '/^./gitea-src-$(VERSION)/'" || echo "--transform 's|^./|gitea-src-$(VERSION)/|'"))
tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) $(TRANSFORM) -czf $(DIST)/release/gitea-src-$(VERSION).tar.gz .
tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) -czf $(DIST)/release/gitea-src-$(VERSION).tar.gz .
rm -f $(STORED_VERSION_FILE)
.PHONY: release-docs
@@ -829,17 +673,6 @@ 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)
$(GO) install $(GO_LICENSES_PACKAGE)
$(GO) install $(GOVULNCHECK_PACKAGE)
node_modules: package-lock.json
npm install --no-save
@@ -858,8 +691,8 @@ fomantic:
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
cp -f web_src/js/vendor/dropdown.js $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/definitions/modules
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
$(SED_INPLACE) -e 's/\r//g' $(FOMANTIC_WORK_DIR)/build/semantic.css $(FOMANTIC_WORK_DIR)/build/semantic.js
rm -f $(FOMANTIC_WORK_DIR)/build/*.min.*
.PHONY: webpack
@@ -909,15 +742,15 @@ update-translations:
.PHONY: generate-license
generate-license:
$(GO) run build/generate-licenses.go
GO111MODULE=on $(GO) run build/generate-licenses.go
.PHONY: generate-gitignore
generate-gitignore:
$(GO) run build/generate-gitignores.go
GO111MODULE=on $(GO) run build/generate-gitignores.go
.PHONY: generate-images
generate-images: | node_modules
npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7
npm install --no-save --no-package-lock fabric@4 imagemin-zopfli@7
node build/generate-images.js $(TAGS)
.PHONY: generate-manpage
@@ -926,26 +759,29 @@ generate-manpage:
@mkdir -p man/man1/ man/man5
@./gitea docs --man > man/man1/gitea.1
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
@#TODO A smal script witch format config-cheat-sheet.en-us.md nicely to suit as config man page
.PHONY: pr\#%
pr\#%: clean-all
$(GO) run contrib/pr/checkout.go $*
.PHONY: golangci-lint
golangci-lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
golangci-lint: golangci-lint-check
golangci-lint run --timeout 10m
# 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: 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
.PHONY: docker
docker:

View File

@@ -12,14 +12,14 @@
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea">
<img src="https://img.shields.io/discord/322538954119184384.svg">
</a>
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov">
<a href="https://codecov.io/gh/go-gitea/gitea" title="Codecov">
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg">
</a>
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card">
<img src="https://goreportcard.com/badge/code.gitea.io/gitea">
</a>
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc">
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg">
<a href="https://godoc.org/code.gitea.io/gitea" title="GoDoc">
<img src="https://godoc.org/code.gitea.io/gitea?status.svg">
</a>
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release">
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg">
@@ -33,39 +33,33 @@
<a href="https://opensource.org/licenses/MIT" title="License: MIT">
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
</a>
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea">
<img
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod"
alt="Contribute with Gitpod"
/>
</a>
<a href="https://crowdin.com/project/gitea" title="Crowdin">
<img src="https://badges.crowdin.net/gitea/localized.svg">
</a>
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs">
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main">
</a>
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource">
<a href="https://www.bountysource.com/teams/gitea" title="Bountysource">
<img src="https://img.shields.io/bountysource/team/gitea/activity">
</a>
</p>
<p align="center">
<a href="README_ZH.md">View this document in Chinese</a>
<a href="README_ZH.md">View the chinese version of this document</a>
</p>
## Purpose
The goal of this project is to make the easiest, fastest, and most
painless way of setting up a self-hosted Git service.
As Gitea is written in Go, it works across **all** the platforms and
architectures that are supported by Go, including Linux, macOS, and
Windows on x86, amd64, ARM and PowerPC architectures.
You can try it out using [the online demo](https://try.gitea.io/).
Using Go, this can be done with an independent binary distribution across
**all platforms** which Go supports, including Linux, macOS, and Windows
on x86, amd64, ARM and PowerPC architectures.
Want to try it before doing anything else?
Do it [with the online demo](https://try.gitea.io/)!
This project has been
[forked](https://blog.gitea.io/2016/12/welcome-to-gitea/) from
[Gogs](https://gogs.io) since November of 2016, but a lot has changed.
[Gogs](https://gogs.io) since 2016.11 but changed a lot.
## Building
@@ -79,7 +73,7 @@ or if SQLite support is required:
The `build` target is split into two sub-targets:
- `make backend` which requires [Go Stable](https://go.dev/dl/), required version is defined in [go.mod](/go.mod).
- `make backend` which requires [Go 1.16](https://golang.org/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.
@@ -106,9 +100,9 @@ NOTES:
## Translating
Translations are done through Crowdin. If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there.
Translations are done through Crowdin. If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there.
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope fo fill it as questions pop up.
https://docs.gitea.io/en-us/translation-guidelines/
@@ -119,17 +113,15 @@ https://docs.gitea.io/en-us/translation-guidelines/
For more information and instructions about how to install Gitea, please look at our [documentation](https://docs.gitea.io/en-us/).
If you have questions that are not covered by the documentation, you can get in contact with us on our [Discord server](https://discord.gg/Gitea) or create a post in the [discourse forum](https://discourse.gitea.io/).
We maintain a list of Gitea-related projects at [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea).
The Hugo-based documentation theme is hosted at [gitea/theme](https://gitea.com/gitea/theme).
We maintain a list of Gitea-related projects at [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea).
The hugo-based documentation theme is hosted at [gitea/theme](https://gitea.com/gitea/theme).
The official Gitea CLI is developed at [gitea/tea](https://gitea.com/gitea/tea).
## Authors
- [Maintainers](https://github.com/orgs/go-gitea/people)
- [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
- [Translators](options/locale/TRANSLATORS)
* [Maintainers](https://github.com/orgs/go-gitea/people)
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
* [Translators](options/locale/TRANSLATORS)
## Backers
@@ -151,7 +143,6 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
<a href="https://opencollective.com/gitea/sponsor/7/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/8/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/9/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/9/avatar.svg"></a>
<a href="https://cynkra.com/" target="_blank"><img src="https://images.opencollective.com/cynkra/logo/square/64/192.png"></a>
## FAQ
@@ -170,7 +161,6 @@ See the [LICENSE](https://github.com/go-gitea/gitea/blob/main/LICENSE) file
for the full license text.
## Screenshots
Looking for an overview of the interface? Check it out!
|![Dashboard](https://dl.gitea.io/screenshots/home_timeline.png)|![User Profile](https://dl.gitea.io/screenshots/user_profile.png)|![Global Issues](https://dl.gitea.io/screenshots/global_issues.png)|

View File

@@ -12,14 +12,14 @@
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea">
<img src="https://img.shields.io/discord/322538954119184384.svg">
</a>
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov">
<a href="https://codecov.io/gh/go-gitea/gitea" title="Codecov">
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg">
</a>
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card">
<img src="https://goreportcard.com/badge/code.gitea.io/gitea">
</a>
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc">
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg">
<a href="https://godoc.org/code.gitea.io/gitea" title="GoDoc">
<img src="https://godoc.org/code.gitea.io/gitea?status.svg">
</a>
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release">
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg">
@@ -33,25 +33,19 @@
<a href="https://opensource.org/licenses/MIT" title="License: MIT">
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
</a>
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea">
<img
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod"
alt="Contribute with Gitpod"
/>
</a>
<a href="https://crowdin.com/project/gitea" title="Crowdin">
<img src="https://badges.crowdin.net/gitea/localized.svg">
</a>
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs">
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main">
</a>
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource">
<a href="https://img.shields.io/bountysource/team/gitea" title="Bountysource">
<img src="https://img.shields.io/bountysource/team/gitea/activity">
</a>
</p>
<p align="center">
<a href="README.md">View this document in English</a>
<a href="README.md">View the english version of this document</a>
</p>
## 目标

View File

@@ -1,83 +1,10 @@
# Reporting security issues
The Gitea maintainers take security seriously.
The Gitea maintainers take security seriously.
If you discover a security issue, please bring it to their attention right away!
## Reporting a Vulnerability
### Reporting a Vulnerability
Please **DO NOT** file a public issue, instead send your report privately to `security@gitea.io`.
## Protecting Security Information
Due to the sensitive nature of security information, you can use below GPG public key encrypt your mail body.
The PGP key is valid until June 24, 2024.
```
Key ID: 6FCD2D5B
Key Type: RSA
Expires: 6/24/2024
Key Size: 4096/4096
Fingerprint: 3DE0 3D1E 144A 7F06 9359 99DC AAFD 2381 6FCD 2D5B
```
UserID: Gitea Security <security@gitea.io>
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGK1Z/4BEADFMqXA9DeeChmSxUjF0Be5sq99ZUhgrZjcN/wOzz0wuCJZC0l8
4uC+d6mfv7JpJYlzYzOK97/x5UguKHkYNZ6mm1G9KHaXmoIBDLKDzfPdJopVNv2r
OajijaE0uMCnMjadlg5pbhMLRQG8a9J32yyaz7ZEAw72Ab31fvvcA53NkuqO4j2w
k7dtFQzhbNOYV0VffQT90WDZdalYHB1JHyEQ+70U9OjVD5ggNYSzX98Eu3Hjn7V7
kqFrcAxr5TE1elf0IXJcuBJtFzQSTUGlQldKOHtGTGgGjj9r/FFAE5ioBgVD05bV
rEEgIMM/GqYaG/nbNpWE6P3mEc2Mnn3pZaRJL0LuF26TLjnqEcMMDp5iIhLdFzXR
3tMdtKgQFu+Mtzs3ipwWARYgHyU09RJsI2HeBx7RmZO/Xqrec763Z7zdJ7SpCn0Z
q+pHZl24JYR0Kf3T/ZiOC0cGd2QJqpJtg5J6S/OqfX9NH6MsCczO8pUC1N/aHH2X
CTme2nF56izORqDWKoiICteL3GpYsCV9nyCidcCmoQsS+DKvE86YhIhVIVWGRY2F
lzpAjnN9/KLtQroutrm+Ft0mdjDiJUeFVl1cOHDhoyfCsQh62HumoyZoZvqzQd6e
AbN11nq6aViMe2Q3je1AbiBnRnQSHxt1Tc8X4IshO3MQK1Sk7oPI6LA5oQARAQAB
tCJHaXRlYSBTZWN1cml0eSA8c2VjdXJpdHlAZ2l0ZWEuaW8+iQJXBBMBCABBFiEE
PeA9HhRKfwaTWZncqv0jgW/NLVsFAmK1Z/4CGwMFCQPCZwAFCwkIBwICIgIGFQoJ
CAsCBBYCAwECHgcCF4AACgkQqv0jgW/NLVvnyxAAhxyNnWzw/rQO2qhzqicmZM94
njSbOg+U2qMBvCdaqCQQeC+uaMmMzkDPanUUmLcyCkWqfCjPNjeSXAkE9npepVJI
4HtmgxZQ94OU/h3CLbft+9GVRzUkVI29TSYGdvNtV2/BkNGoFFnKWQr119um0o6A
bgha2Uy5uY8o3ZIoiKkiHRaEoWIjjeBxJxYAojsZY4YElUmsQ3ik2joG6rhFesTa
ofVt/bL8G2xzpOG26WGIxBbqf2qjV6OtZ0hu/vtTPHeIWMLq0Mz0V3PEDQWfkGPE
i2RYxxYDs2xzJhSQWqTNVLSq0m5xTJnbHhQPfdCX4C2jvFKgLdfmytQq49S7jiJb
Z03HVOZ/PsyBlQfH9xJi06R5yQCMEA8h8Z5r3/NXW09kQ6OFRe6xshoTcxZGRPTo
srhwr3uPbmCRh+YEl7qBLU6+BC5k8IRTZXqhrj/aPJu3MxgbgwV8u3vLoFSXM2lb
a61FgeCQ0O7lkgVswwF0RppCaH9Ul3ZDapet/vCRg4NVwm9zOI/8q/Vj0FKA1GDR
JhRu8+Ce8zlFL65D34t+PprAzSeTlbv9um3x/ZIjCco7EEKSBylt+AZj/VyA6+e5
kjOQwRRc6dFJWBcorsSI2dG+H+QMF7ZabzmeCcz1v9HjLOPzYHoZAHhCmSppWTvX
AJy6+lhfW2OUTqQeYSi5Ag0EYrVn/gEQALrFLQjCR3GjuHSindz0rd3Fnx/t7Sen
T+p07yCSSoSlmnJHCQmwh4vfg1blyz0zZ4vkIhtpHsEgc+ZAG+WQXSsJ2iRz+eSN
GwoOQl4XC3n+QWkc1ws+btr48+6UqXIQU+F8TPQyx/PIgi2nZXJB7f5+mjCqsk46
XvH4nTr4kJjuqMSR/++wvre2qNQRa/q/dTsK0OaN/mJsdX6Oi+aGNaQJUhIG7F+E
ZDMkn/O6xnwWNzy/+bpg43qH/Gk0eakOmz5NmQLRkV58SZLiJvuCUtkttf6CyhnX
03OcWaajv5W8qA39dBYQgDrrPbBWUnwfO3yMveqhwV4JjDoe8sPAyn1NwzakNYqP
RzsWyLrLS7R7J9s3FkZXhQw/QQcsaSMcGNQO047dm1P83N8JY5aEpiRo9zSWjoiw
qoExANj5lUTZPe8M50lI182FrcjAN7dClO3QI6pg7wy0erMxfFly3j8UQ91ysS9T
s+GsP9I3cmWWQcKYxWHtE8xTXnNCVPFZQj2nwhJzae8ypfOtulBRA3dUKWGKuDH/
axFENhUsT397aOU3qkP/od4a64JyNIEo4CTTSPVeWd7njsGqli2U3A4xL2CcyYvt
D/MWcMBGEoLSNTswwKdom4FaJpn5KThnK/T0bQcmJblJhoCtppXisbexZnCpuS0x
Zdlm2T14KJ3LABEBAAGJAjwEGAEIACYWIQQ94D0eFEp/BpNZmdyq/SOBb80tWwUC
YrVn/gIbDAUJA8JnAAAKCRCq/SOBb80tWyTBD/9AGpW6QoDF7zYjHAozH9S5RGCA
Y7E82dG/0xmFUwPprAG0BKmmgU6TiipyVGmKIXGYYYU92pMnbvXkYQMoa+WJNncN
D3fY52UeXeffTf4cFpStlzi9xgYtOLhFamzYu/4xhkjOX+xhOSXscCiFRyT8cF3B
O6c5BHU+Zj0/rGPgOyPUbx7l7B9MubB/41nNX35k08e+8T3wtWDb4XF+15HnRfva
6fblO8wgU25Orv2Rm1jnKGa9DxJ8nE40IMrqDapENtDuL+zKJsvR0+ptWvEyL56U
GtJJG5un6mXiLKuRQT0DEv4MdZRHDgDstDnqcbEiazVEbUuvhZZob6lRY2A19m1+
7zfnDxkhqCA1RCnv4fdvcPdCMMFHwLpdhjgW0aI/uwgwrvsEz5+JRlnLvdQHlPAg
q7l2fGcBSpz9U0ayyfRPjPntsNCtZl1UDxGLeciPkZhyG84zEWQbk/j52ZpRN+Ik
ALpRLa8RBFmFSmXDUmwQrmm1EmARyQXwweKU31hf8ZGbCp2lPuRYm1LuGiirXSVP
GysjRAJgW+VRpBKOzFQoUAUbReVWSaCwT8s17THzf71DdDb6CTj31jMLLYWwBpA/
i73DgobDZMIGEZZC1EKqza8eh11xfyHFzGec03tbh+lIen+5IiRtWiEWkDS9ll0G
zgS/ZdziCvdAutqnGA==
=gZWO
-----END PGP PUBLIC KEY BLOCK-----
```
Security reports are greatly appreciated and we will publicly thank you for it, although we keep your name confidential if you request it.

File diff suppressed because one or more lines are too long

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="main_outline" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640;" xml:space="preserve">
<g>
<path id="teabag" style="fill:#FFFFFF" d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8
c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4
c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"/>
<g>
<g>
<path style="fill:#609926" d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2
c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5
c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5
c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3
c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1
C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4
c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7
S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55
c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8
l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"/>
<path style="fill:#609926" d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4
c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1
c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9
c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3
c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3
c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29
c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8
C343.2,346.5,335,363.3,326.8,380.1z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,9 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build vendor
// +build vendor
package main

View File

@@ -1,7 +1,9 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
@@ -19,7 +21,7 @@ import (
)
// Windows has a limitation for command line arguments, the size can not exceed 32KB.
// So we have to feed the files to some tools (like gofmt) batch by batch
// So we have to feed the files to some tools (like gofmt/misspell) batch by batch
// We also introduce a `gitea-fmt` command, it does better import formatting than gofmt/goimports. `gitea-fmt` calls `gofmt` internally.
@@ -38,7 +40,7 @@ func passThroughCmd(cmd string, args []string) error {
}
c := exec.Cmd{
Path: foundCmd,
Args: append([]string{cmd}, args...),
Args: args,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
@@ -60,7 +62,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
"build",
"cmd",
"contrib",
"tests",
"integrations",
"models",
"modules",
"routers",
@@ -70,8 +72,8 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`integrations/gitea-repositories-meta`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`integrations/migration-test`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/fixtures`))
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`models/migrations/fixtures`))
@@ -134,7 +136,7 @@ func (fc *fileCollector) collectFiles() (res [][]string, err error) {
}
// substArgFiles expands the {file-list} to a real file list for commands
func substArgFiles(args, files []string) []string {
func substArgFiles(args []string, files []string) []string {
for i, s := range args {
if s == "{file-list}" {
newArgs := append(args[:i], files...)
@@ -194,6 +196,7 @@ Options:
Commands:
%[1]s gofmt ...
%[1]s misspell ...
Arguments:
{file-list} the file list
@@ -204,17 +207,6 @@ Example:
`, "file-batch-exec")
}
func getGoVersion() string {
goModFile, err := os.ReadFile("go.mod")
if err != nil {
log.Fatalf(`Faild to read "go.mod": %v`, err)
os.Exit(1)
}
goModVersionRegex := regexp.MustCompile(`go \d+\.\d+`)
goModVersionLine := goModVersionRegex.Find(goModFile)
return string(goModVersionLine[3:])
}
func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) {
fileFilter := mainOptions["file-filter"]
if fileFilter == "" {
@@ -237,9 +229,9 @@ func containsString(a []string, s string) bool {
return false
}
func giteaFormatGoImports(files []string, doWriteFile bool) error {
func giteaFormatGoImports(files []string) error {
for _, file := range files {
if err := codeformat.FormatGoImports(file, doWriteFile); err != nil {
if err := codeformat.FormatGoImports(file); err != nil {
log.Printf("failed to format go imports: %s, err=%v", file, err)
return err
}
@@ -275,11 +267,12 @@ func main() {
logVerbose("batch cmd: %s %v", subCmd, substArgs)
switch subCmd {
case "gitea-fmt":
if containsString(subArgs, "-d") {
log.Print("the -d option is not supported by gitea-fmt")
if containsString(subArgs, "-w") {
cmdErrors = append(cmdErrors, giteaFormatGoImports(files))
}
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w")))
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", getGoVersion()}, substArgs...)))
cmdErrors = append(cmdErrors, passThroughCmd("gofmt", substArgs))
case "misspell":
cmdErrors = append(cmdErrors, passThroughCmd("misspell", substArgs))
default:
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package codeformat
@@ -19,10 +20,8 @@ var importPackageGroupOrders = map[string]int{
var errInvalidCommentBetweenImports = errors.New("comments between imported packages are invalid, please move comments to the end of the package line")
var (
importBlockBegin = []byte("\nimport (\n")
importBlockEnd = []byte("\n)")
)
var importBlockBegin = []byte("\nimport (\n")
var importBlockEnd = []byte("\n)")
type importLineParsed struct {
group string
@@ -60,10 +59,8 @@ func parseImportLine(line string) (*importLineParsed, error) {
return il, nil
}
type (
importLineGroup []*importLineParsed
importLineGroupMap map[string]importLineGroup
)
type importLineGroup []*importLineParsed
type importLineGroupMap map[string]importLineGroup
func formatGoImports(contentBytes []byte) ([]byte, error) {
p1 := bytes.Index(contentBytes, importBlockBegin)
@@ -156,8 +153,8 @@ func formatGoImports(contentBytes []byte) ([]byte, error) {
return formattedBytes, nil
}
// FormatGoImports format the imports by our rules (see unit tests)
func FormatGoImports(file string, doWriteFile bool) error {
//FormatGoImports format the imports by our rules (see unit tests)
func FormatGoImports(file string) error {
f, err := os.Open(file)
if err != nil {
return err
@@ -180,16 +177,11 @@ func FormatGoImports(file string, doWriteFile bool) error {
if bytes.Equal(contentBytes, formattedBytes) {
return nil
}
if doWriteFile {
f, err = os.OpenFile(file, os.O_TRUNC|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(formattedBytes)
f, err = os.OpenFile(file, os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(formattedBytes)
return err
}

View File

@@ -1,5 +1,6 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package codeformat

View File

@@ -1,7 +1,9 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
@@ -18,7 +20,7 @@ import (
"github.com/shurcooL/vfsgen"
)
func needsUpdate(dir, filename string) (bool, []byte) {
func needsUpdate(dir string, filename string) (bool, []byte) {
needRegen := false
_, err := os.Stat(filename)
if err != nil {
@@ -32,15 +34,11 @@ func needsUpdate(dir, filename string) (bool, []byte) {
hasher := sha1.New()
err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
info, err := d.Info()
if err != nil {
return err
}
_, _ = hasher.Write([]byte(d.Name()))
_, _ = hasher.Write([]byte(info.Name()))
_, _ = hasher.Write([]byte(info.ModTime().String()))
_, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16)))
return nil
@@ -52,6 +50,7 @@ func needsUpdate(dir, filename string) (bool, []byte) {
newHash := hasher.Sum([]byte{})
if bytes.Compare(oldHash, newHash) != 0 {
return true, newHash
}
@@ -88,5 +87,5 @@ func main() {
if err != nil {
log.Fatalf("%v\n", err)
}
_ = os.WriteFile(filename+".hash", newHash, 0o666)
_ = os.WriteFile(filename+".hash", newHash, 0666)
}

View File

@@ -1,8 +1,10 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Copyright 2015 Kenneth Shaw
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
@@ -25,10 +27,12 @@ import (
const (
gemojiURL = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
maxUnicodeVersion = 14
maxUnicodeVersion = 12
)
var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
var (
flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
)
// Gemoji is a set of emoji data.
type Gemoji []Emoji
@@ -64,7 +68,7 @@ func main() {
}
// write
err = os.WriteFile(*flagOut, buf, 0o644)
err = os.WriteFile(*flagOut, buf, 0644)
if err != nil {
log.Fatal(err)
}
@@ -105,7 +109,7 @@ func generate() ([]byte, error) {
return nil, err
}
skinTones := make(map[string]string)
var skinTones = make(map[string]string)
skinTones["\U0001f3fb"] = "Light Skin Tone"
skinTones["\U0001f3fc"] = "Medium-Light Skin Tone"
@@ -115,7 +119,7 @@ func generate() ([]byte, error) {
var tmp Gemoji
// filter out emoji that require greater than max unicode version
//filter out emoji that require greater than max unicode version
for i := range data {
val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
if int(val) <= maxUnicodeVersion {
@@ -154,7 +158,7 @@ func generate() ([]byte, error) {
// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
file, _ := json.Marshal(data)
_ = os.WriteFile("assets/emoji.json", file, 0o644)
_ = os.WriteFile("assets/emoji.json", file, 0644)
// Add skin tones to emoji that support it
var (
@@ -189,10 +193,6 @@ func generate() ([]byte, error) {
}
}
sort.Slice(data, func(i, j int) bool {
return data[i].Aliases[0] < data[j].Aliases[0]
})
// add header
str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
@@ -212,12 +212,13 @@ func generate() ([]byte, error) {
const hdr = `
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package emoji
// Code generated by build/generate-emoji.go. DO NOT EDIT.
// Code generated by gen.go. DO NOT EDIT.
// Sourced from %s
//
var GemojiData = %#v
`

View File

@@ -1,4 +1,5 @@
//go:build ignore
// +build ignore
package main
@@ -33,6 +34,7 @@ func main() {
flag.Parse()
file, err := os.CreateTemp(os.TempDir(), prefix)
if err != nil {
log.Fatalf("Failed to create temp file. %s", err)
}
@@ -63,6 +65,7 @@ func main() {
}
gz, err := gzip.NewReader(file)
if err != nil {
log.Fatalf("Failed to gunzip the archive. %s", err)
}
@@ -93,6 +96,7 @@ func main() {
}
out, err := os.Create(path.Join(destination, strings.TrimSuffix(filepath.Base(hdr.Name), ".gitignore")))
if err != nil {
log.Fatalf("Failed to create new file. %s", err)
}
@@ -115,7 +119,7 @@ func main() {
}
// Write data to dst
dst = path.Join(destination, dst)
err = os.WriteFile(dst, data, 0o644)
err = os.WriteFile(dst, data, 0644)
if err != nil {
log.Fatalf("Failed to write new file. %s", err)
}

View File

@@ -1,84 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build ignore
package main
import (
"encoding/json"
"io/fs"
"os"
goPath "path"
"path/filepath"
"regexp"
"sort"
"strings"
)
// regexp is based on go-license, excluding README and NOTICE
// https://github.com/google/go-licenses/blob/master/licenses/find.go
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
type LicenseEntry struct {
Name string `json:"name"`
Path string `json:"path"`
LicenseText string `json:"licenseText"`
}
func main() {
base, out := os.Args[1], os.Args[2]
paths := []string{}
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
}
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) {
return nil
}
paths = append(paths, path)
return nil
})
if err != nil {
panic(err)
}
sort.Strings(paths)
entries := []LicenseEntry{}
for _, path := range paths {
path := filepath.ToSlash(path)
licenseText, err := os.ReadFile(path)
if err != nil {
panic(err)
}
path = strings.Replace(path, base+"/", "", 1)
name := goPath.Dir(path)
// There might be a bug somewhere in go-licenses that sometimes interprets the
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
// removing both of them for the sake of stable output.
if name == "." || name == "code.gitea.io/gitea" {
continue
}
entries = append(entries, LicenseEntry{
Name: name,
Path: path,
LicenseText: string(licenseText),
})
}
jsonBytes, err := json.MarshalIndent(entries, "", " ")
if err != nil {
panic(err)
}
err = os.WriteFile(out, jsonBytes, 0o644)
if err != nil {
panic(err)
}
}

View File

@@ -1,8 +1,13 @@
#!/usr/bin/env node
import imageminZopfli from 'imagemin-zopfli';
import {optimize} from 'svgo';
import {fabric} from 'fabric';
import {readFile, writeFile} from 'node:fs/promises';
import fs from 'fs';
import {resolve, dirname} from 'path';
import {fileURLToPath} from 'url';
const {readFile, writeFile} = fs.promises;
const __dirname = dirname(fileURLToPath(import.meta.url));
const logoFile = resolve(__dirname, '../assets/logo.svg');
function exit(err) {
if (err) console.error(err);
@@ -17,10 +22,8 @@ function loadSvg(svg) {
});
}
async function generate(svg, path, {size, bg}) {
const outputFile = new URL(path, import.meta.url);
if (String(outputFile).endsWith('.svg')) {
async function generate(svg, outputFile, {size, bg}) {
if (outputFile.endsWith('.svg')) {
const {data} = optimize(svg, {
plugins: [
'preset-default',
@@ -65,18 +68,17 @@ async function generate(svg, path, {size, bg}) {
async function main() {
const gitea = process.argv.slice(2).includes('gitea');
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
const svg = await readFile(logoFile, 'utf8');
await Promise.all([
generate(logoSvg, '../public/img/logo.svg', {size: 32}),
generate(logoSvg, '../public/img/logo.png', {size: 512}),
generate(faviconSvg, '../public/img/favicon.svg', {size: 32}),
generate(faviconSvg, '../public/img/favicon.png', {size: 180}),
generate(logoSvg, '../public/img/avatar_default.png', {size: 200}),
generate(logoSvg, '../public/img/apple-touch-icon.png', {size: 180, bg: true}),
gitea && generate(logoSvg, '../public/img/gitea.svg', {size: 32}),
generate(svg, resolve(__dirname, '../public/img/logo.svg'), {size: 32}),
generate(svg, resolve(__dirname, '../public/img/logo.png'), {size: 512}),
generate(svg, resolve(__dirname, '../public/img/favicon.png'), {size: 180}),
generate(svg, resolve(__dirname, '../public/img/avatar_default.png'), {size: 200}),
generate(svg, resolve(__dirname, '../public/img/apple-touch-icon.png'), {size: 180, bg: true}),
gitea && generate(svg, resolve(__dirname, '../public/img/gitea.svg'), {size: 32}),
]);
}
main().then(exit).catch(exit);

View File

@@ -1,4 +1,5 @@
//go:build ignore
// +build ignore
package main
@@ -33,20 +34,13 @@ func main() {
flag.Parse()
file, err := os.CreateTemp(os.TempDir(), prefix)
if err != nil {
log.Fatalf("Failed to create temp file. %s", err)
}
defer util.Remove(file.Name())
if err := os.RemoveAll(destination); err != nil {
log.Fatalf("Cannot clean destination folder: %v", err)
}
if err := os.MkdirAll(destination, 0o755); err != nil {
log.Fatalf("Cannot create destination: %v", err)
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Fatalf("Failed to download archive. %s", err)
@@ -72,6 +66,7 @@ func main() {
}
gz, err := gzip.NewReader(file)
if err != nil {
log.Fatalf("Failed to gunzip the archive. %s", err)
}
@@ -105,6 +100,7 @@ func main() {
continue
}
out, err := os.Create(path.Join(destination, strings.TrimSuffix(filepath.Base(hdr.Name), ".txt")))
if err != nil {
log.Fatalf("Failed to create new file. %s", err)
}

View File

@@ -1,14 +1,13 @@
#!/usr/bin/env node
import fastGlob from 'fast-glob';
import {optimize} from 'svgo';
import {parse} from 'node:path';
import {readFile, writeFile, mkdir} from 'node:fs/promises';
import {fileURLToPath} from 'node:url';
import {resolve, parse, dirname} from 'path';
import fs from 'fs';
import {fileURLToPath} from 'url';
const glob = (pattern) => fastGlob.sync(pattern, {
cwd: fileURLToPath(new URL('..', import.meta.url)),
absolute: true,
});
const {readFile, writeFile, mkdir} = fs.promises;
const __dirname = dirname(fileURLToPath(import.meta.url));
const glob = (pattern) => fastGlob.sync(pattern, {cwd: resolve(__dirname), absolute: true});
const outputDir = resolve(__dirname, '../public/img/svg');
function exit(err) {
if (err) console.error(err);
@@ -17,6 +16,7 @@ function exit(err) {
async function processFile(file, {prefix, fullName} = {}) {
let name;
if (fullName) {
name = fullName;
} else {
@@ -35,8 +35,7 @@ async function processFile(file, {prefix, fullName} = {}) {
{name: 'addAttributesToSVGElement', params: {attributes: [{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'}]}},
],
});
await writeFile(fileURLToPath(new URL(`../public/img/svg/${name}.svg`, import.meta.url)), data);
await writeFile(resolve(outputDir, `${name}.svg`), data);
}
function processFiles(pattern, opts) {
@@ -45,14 +44,15 @@ function processFiles(pattern, opts) {
async function main() {
try {
await mkdir(fileURLToPath(new URL('../public/img/svg', import.meta.url)), {recursive: true});
await mkdir(outputDir);
} catch {}
await Promise.all([
...processFiles('node_modules/@primer/octicons/build/svg/*-16.svg', {prefix: 'octicon'}),
...processFiles('web_src/svg/*.svg'),
...processFiles('public/img/gitea.svg', {fullName: 'gitea-gitea'}),
...processFiles('../node_modules/@primer/octicons/build/svg/*-16.svg', {prefix: 'octicon'}),
...processFiles('../web_src/svg/*.svg'),
...processFiles('../public/img/gitea.svg', {fullName: 'gitea-gitea'}),
]);
}
main().then(exit).catch(exit);

View File

@@ -0,0 +1,27 @@
// 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.
//go:build ignore
// +build ignore
package main
import (
"log"
"os"
"code.gitea.io/gitea/build/codeformat"
)
func main() {
if len(os.Args) <= 1 {
log.Fatalf("Usage: gitea-format-imports [files...]")
}
for _, file := range os.Args[1:] {
if err := codeformat.FormatGoImports(file); err != nil {
log.Fatalf("can not format file %s, err=%v", file, err)
}
}
}

View File

@@ -1,11 +1,13 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Copyright (c) 2015, Wade Simmons
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// gocovmerge takes the results from multiple `go test -coverprofile` runs and
// merges them into one profile
//go:build ignore
// +build ignore
package main
@@ -20,7 +22,7 @@ import (
"golang.org/x/tools/cover"
)
func mergeProfiles(p, merge *cover.Profile) {
func mergeProfiles(p *cover.Profile, merge *cover.Profile) {
if p.Mode != merge.Mode {
log.Fatalf("cannot merge profiles with different modes")
}

View File

@@ -1,29 +1,35 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"context"
"errors"
"fmt"
"os"
"strings"
"text/tabwriter"
"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
pwd "code.gitea.io/gitea/modules/password"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
"code.gitea.io/gitea/services/auth/source/smtp"
repo_service "code.gitea.io/gitea/services/repository"
user_service "code.gitea.io/gitea/services/user"
"github.com/urfave/cli"
)
@@ -42,6 +48,112 @@ var (
},
}
subcmdUser = cli.Command{
Name: "user",
Usage: "Modify users",
Subcommands: []cli.Command{
microcmdUserCreate,
microcmdUserList,
microcmdUserChangePassword,
microcmdUserDelete,
},
}
microcmdUserList = cli.Command{
Name: "list",
Usage: "List users",
Action: runListUsers,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "admin",
Usage: "List only admin users",
},
},
}
microcmdUserCreate = cli.Command{
Name: "create",
Usage: "Create a new user in database",
Action: runCreateUser,
Flags: []cli.Flag{
cli.StringFlag{
Name: "name",
Usage: "Username. DEPRECATED: use username instead",
},
cli.StringFlag{
Name: "username",
Usage: "Username",
},
cli.StringFlag{
Name: "password",
Usage: "User password",
},
cli.StringFlag{
Name: "email",
Usage: "User email address",
},
cli.BoolFlag{
Name: "admin",
Usage: "User is an admin",
},
cli.BoolFlag{
Name: "random-password",
Usage: "Generate a random password for the user",
},
cli.BoolFlag{
Name: "must-change-password",
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
},
cli.IntFlag{
Name: "random-password-length",
Usage: "Length of the random password to be generated",
Value: 12,
},
cli.BoolFlag{
Name: "access-token",
Usage: "Generate access token for the user",
},
},
}
microcmdUserChangePassword = cli.Command{
Name: "change-password",
Usage: "Change a user's password",
Action: runChangePassword,
Flags: []cli.Flag{
cli.StringFlag{
Name: "username,u",
Value: "",
Usage: "The user to change password for",
},
cli.StringFlag{
Name: "password,p",
Value: "",
Usage: "New password to set for user",
},
},
}
microcmdUserDelete = cli.Command{
Name: "delete",
Usage: "Delete specific user by id, name or email",
Flags: []cli.Flag{
cli.Int64Flag{
Name: "id",
Usage: "ID of user of the user to delete",
},
cli.StringFlag{
Name: "username,u",
Usage: "Username of the user to delete",
},
cli.StringFlag{
Name: "email,e",
Usage: "Email of the user to delete",
},
},
Action: runDeleteUser,
}
subcmdRepoSyncReleases = cli.Command{
Name: "repo-sync-releases",
Usage: "Synchronize repository releases with tags",
@@ -161,11 +273,6 @@ var (
Value: "false",
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
},
cli.StringFlag{
Name: "custom-tenant-id",
Value: "",
Usage: "Use custom Tenant ID for OAuth endpoints",
},
cli.StringFlag{
Name: "custom-auth-url",
Value: "",
@@ -225,15 +332,6 @@ var (
Value: "",
Usage: "Group Claim value for restricted users",
},
cli.StringFlag{
Name: "group-team-map",
Value: "",
Usage: "JSON mapping between groups and org teams",
},
cli.BoolFlag{
Name: "group-team-map-removal",
Usage: "Activate automatic team membership removal depending on groups",
},
}
microcmdAuthUpdateOauth = cli.Command{
@@ -339,6 +437,212 @@ var (
}
)
func runChangePassword(c *cli.Context) error {
if err := argsSet(c, "username", "password"); err != nil {
return err
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
if len(c.String("password")) < setting.MinPasswordLength {
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
}
if !pwd.IsComplexEnough(c.String("password")) {
return errors.New("Password does not meet complexity requirements")
}
pwned, err := pwd.IsPwned(context.Background(), c.String("password"))
if err != nil {
return err
}
if pwned {
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords")
}
uname := c.String("username")
user, err := user_model.GetUserByName(uname)
if err != nil {
return err
}
if err = user.SetPassword(c.String("password")); err != nil {
return err
}
if err = user_model.UpdateUserCols(db.DefaultContext, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
return err
}
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
return nil
}
func runCreateUser(c *cli.Context) error {
if err := argsSet(c, "email"); err != nil {
return err
}
if c.IsSet("name") && c.IsSet("username") {
return errors.New("Cannot set both --name and --username flags")
}
if !c.IsSet("name") && !c.IsSet("username") {
return errors.New("One of --name or --username flags must be set")
}
if c.IsSet("password") && c.IsSet("random-password") {
return errors.New("cannot set both -random-password and -password flags")
}
var username string
if c.IsSet("username") {
username = c.String("username")
} else {
username = c.String("name")
fmt.Fprintf(os.Stderr, "--name flag is deprecated. Use --username instead.\n")
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
var password string
if c.IsSet("password") {
password = c.String("password")
} else if c.IsSet("random-password") {
var err error
password, err = pwd.Generate(c.Int("random-password-length"))
if err != nil {
return err
}
fmt.Printf("generated random password is '%s'\n", password)
} else {
return errors.New("must set either password or random-password flag")
}
// always default to true
var changePassword = true
// If this is the first user being created.
// Take it as the admin and don't force a password update.
if n := user_model.CountUsers(); n == 0 {
changePassword = false
}
if c.IsSet("must-change-password") {
changePassword = c.Bool("must-change-password")
}
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 {
return fmt.Errorf("CreateUser: %v", err)
}
if c.Bool("access-token") {
t := &models.AccessToken{
Name: "gitea-admin",
UID: u.ID,
}
if err := models.NewAccessToken(t); err != nil {
return err
}
fmt.Printf("Access token was successfully created... %s\n", t.Token)
}
fmt.Printf("New user '%s' has been successfully created!\n", username)
return nil
}
func runListUsers(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
users, err := user_model.GetAllUsers()
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 5, 0, 1, ' ', 0)
if c.IsSet("admin") {
fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\n")
for _, u := range users {
if u.IsAdmin {
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", u.ID, u.Name, u.Email, u.IsActive)
}
}
} else {
fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\tIsAdmin\n")
for _, u := range users {
fmt.Fprintf(w, "%d\t%s\t%s\t%t\t%t\n", u.ID, u.Name, u.Email, u.IsActive, u.IsAdmin)
}
}
w.Flush()
return nil
}
func runDeleteUser(c *cli.Context) error {
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
return fmt.Errorf("You must provide the id, username or email of a user to delete")
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
if err := storage.Init(); err != nil {
return err
}
var err error
var user *user_model.User
if c.IsSet("email") {
user, err = user_model.GetUserByEmail(c.String("email"))
} else if c.IsSet("username") {
user, err = user_model.GetUserByName(c.String("username"))
} else {
user, err = user_model.GetUserByID(c.Int64("id"))
}
if err != nil {
return err
}
if c.IsSet("username") && user.LowerName != strings.ToLower(strings.TrimSpace(c.String("username"))) {
return fmt.Errorf("The user %s who has email %s does not match the provided username %s", user.Name, c.String("email"), c.String("username"))
}
if c.IsSet("id") && user.ID != c.Int64("id") {
return fmt.Errorf("The user %s does not match the provided id %d", user.Name, c.Int64("id"))
}
return user_service.DeleteUser(user)
}
func runRepoSyncReleases(_ *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
@@ -349,15 +653,15 @@ func runRepoSyncReleases(_ *cli.Context) error {
log.Trace("Synchronizing repository releases (this may take a while)")
for page := 1; ; page++ {
repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
ListOptions: db.ListOptions{
PageSize: repo_model.RepositoryListDefaultPageSize,
PageSize: models.RepositoryListDefaultPageSize,
Page: page,
},
Private: true,
})
if err != nil {
return fmt.Errorf("SearchRepositoryByName: %w", err)
return fmt.Errorf("SearchRepositoryByName: %v", err)
}
if len(repos) == 0 {
break
@@ -365,7 +669,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
log.Trace("Processing next %d repos of %d", len(repos), count)
for _, repo := range repos {
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Warn("OpenRepository: %v", err)
continue
@@ -400,10 +704,9 @@ func runRepoSyncReleases(_ *cli.Context) error {
}
func getReleaseCount(id int64) (int64, error) {
return repo_model.GetReleaseCountByRepoID(
db.DefaultContext,
return models.GetReleaseCountByRepoID(
id,
repo_model.FindReleasesOptions{
models.FindReleasesOptions{
IncludeTags: true,
},
)
@@ -437,7 +740,6 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
AuthURL: c.String("custom-auth-url"),
ProfileURL: c.String("custom-profile-url"),
EmailURL: c.String("custom-email-url"),
Tenant: c.String("custom-tenant-id"),
}
} else {
customURLMapping = nil
@@ -456,8 +758,6 @@ func parseOAuth2Config(c *cli.Context) *oauth2.Source {
GroupClaimName: c.String("group-claim-name"),
AdminGroup: c.String("admin-group"),
RestrictedGroup: c.String("restricted-group"),
GroupTeamMap: c.String("group-team-map"),
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
}
}
@@ -469,8 +769,8 @@ func runAddOauth(c *cli.Context) error {
return err
}
return auth_model.CreateSource(&auth_model.Source{
Type: auth_model.OAuth2,
return auth.CreateSource(&auth.Source{
Type: auth.OAuth2,
Name: c.String("name"),
IsActive: true,
Cfg: parseOAuth2Config(c),
@@ -489,7 +789,7 @@ func runUpdateOauth(c *cli.Context) error {
return err
}
source, err := auth_model.GetSourceByID(c.Int64("id"))
source, err := auth.GetSourceByID(c.Int64("id"))
if err != nil {
return err
}
@@ -526,6 +826,7 @@ func runUpdateOauth(c *cli.Context) error {
if c.IsSet("required-claim-name") {
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
}
if c.IsSet("required-claim-value") {
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
@@ -540,22 +841,15 @@ func runUpdateOauth(c *cli.Context) error {
if c.IsSet("restricted-group") {
oAuth2Config.RestrictedGroup = c.String("restricted-group")
}
if c.IsSet("group-team-map") {
oAuth2Config.GroupTeamMap = c.String("group-team-map")
}
if c.IsSet("group-team-map-removal") {
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
}
// update custom URL mapping
customURLMapping := &oauth2.CustomURLMapping{}
var customURLMapping = &oauth2.CustomURLMapping{}
if oAuth2Config.CustomURLMapping != nil {
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
customURLMapping.Tenant = oAuth2Config.CustomURLMapping.Tenant
}
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
customURLMapping.TokenURL = c.String("custom-token-url")
@@ -573,21 +867,17 @@ func runUpdateOauth(c *cli.Context) error {
customURLMapping.EmailURL = c.String("custom-email-url")
}
if c.IsSet("use-custom-urls") && c.IsSet("custom-tenant-id") {
customURLMapping.Tenant = c.String("custom-tenant-id")
}
oAuth2Config.CustomURLMapping = customURLMapping
source.Cfg = oAuth2Config
return auth_model.UpdateSource(source)
return auth.UpdateSource(source)
}
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
if c.IsSet("auth-type") {
conf.Auth = c.String("auth-type")
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
if !contains(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
}
conf.Auth = c.String("auth-type")
@@ -636,7 +926,7 @@ func runAddSMTP(c *cli.Context) error {
if !c.IsSet("port") {
return errors.New("port must be set")
}
active := true
var active = true
if c.IsSet("active") {
active = c.BoolT("active")
}
@@ -651,8 +941,8 @@ func runAddSMTP(c *cli.Context) error {
smtpConfig.Auth = "PLAIN"
}
return auth_model.CreateSource(&auth_model.Source{
Type: auth_model.SMTP,
return auth.CreateSource(&auth.Source{
Type: auth.SMTP,
Name: c.String("name"),
IsActive: active,
Cfg: &smtpConfig,
@@ -671,7 +961,7 @@ func runUpdateSMTP(c *cli.Context) error {
return err
}
source, err := auth_model.GetSourceByID(c.Int64("id"))
source, err := auth.GetSourceByID(c.Int64("id"))
if err != nil {
return err
}
@@ -692,7 +982,7 @@ func runUpdateSMTP(c *cli.Context) error {
source.Cfg = smtpConfig
return auth_model.UpdateSource(source)
return auth.UpdateSource(source)
}
func runListAuth(c *cli.Context) error {
@@ -703,7 +993,8 @@ func runListAuth(c *cli.Context) error {
return err
}
authSources, err := auth_model.Sources()
authSources, err := auth.Sources()
if err != nil {
return err
}
@@ -741,7 +1032,7 @@ func runDeleteAuth(c *cli.Context) error {
return err
}
source, err := auth_model.GetSourceByID(c.Int64("id"))
source, err := auth.GetSourceByID(c.Int64("id"))
if err != nil {
return err
}

View File

@@ -1,5 +1,6 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -33,10 +34,6 @@ var (
Name: "not-active",
Usage: "Deactivate the authentication source.",
},
cli.BoolFlag{
Name: "active",
Usage: "Activate the authentication source.",
},
cli.StringFlag{
Name: "security-protocol",
Usage: "Security protocol name.",
@@ -120,10 +117,6 @@ var (
Name: "synchronize-users",
Usage: "Enable user synchronization.",
},
cli.BoolFlag{
Name: "disable-synchronize-users",
Usage: "Disable user synchronization.",
},
cli.UintFlag{
Name: "page-size",
Usage: "Search page size.",
@@ -190,15 +183,9 @@ func parseAuthSource(c *cli.Context, authSource *auth.Source) {
if c.IsSet("not-active") {
authSource.IsActive = !c.Bool("not-active")
}
if c.IsSet("active") {
authSource.IsActive = c.Bool("active")
}
if c.IsSet("synchronize-users") {
authSource.IsSyncEnabled = c.Bool("synchronize-users")
}
if c.IsSet("disable-synchronize-users") {
authSource.IsSyncEnabled = !c.Bool("disable-synchronize-users")
}
}
// parseLdapConfig assigns values on config according to command line flags.
@@ -273,6 +260,7 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
if c.IsSet("skip-local-2fa") {
config.SkipLocalTwoFA = c.Bool("skip-local-2fa")
}
return nil
}

View File

@@ -1,5 +1,6 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -16,12 +17,12 @@ import (
func TestAddLdapBindDn(t *testing.T) {
// Mock cli functions to do not exit on error
osExiter := cli.OsExiter
var osExiter = cli.OsExiter
defer func() { cli.OsExiter = osExiter }()
cli.OsExiter = func(code int) {}
// Test cases
cases := []struct {
var cases = []struct {
args []string
source *auth.Source
errMsg string
@@ -242,12 +243,12 @@ func TestAddLdapBindDn(t *testing.T) {
func TestAddLdapSimpleAuth(t *testing.T) {
// Mock cli functions to do not exit on error
osExiter := cli.OsExiter
var osExiter = cli.OsExiter
defer func() { cli.OsExiter = osExiter }()
cli.OsExiter = func(code int) {}
// Test cases
cases := []struct {
var cases = []struct {
args []string
authSource *auth.Source
errMsg string
@@ -473,12 +474,12 @@ func TestAddLdapSimpleAuth(t *testing.T) {
func TestUpdateLdapBindDn(t *testing.T) {
// Mock cli functions to do not exit on error
osExiter := cli.OsExiter
var osExiter = cli.OsExiter
defer func() { cli.OsExiter = osExiter }()
cli.OsExiter = func(code int) {}
// Test cases
cases := []struct {
var cases = []struct {
args []string
id int64
existingAuthSource *auth.Source
@@ -857,36 +858,6 @@ func TestUpdateLdapBindDn(t *testing.T) {
},
errMsg: "Invalid authentication type. expected: LDAP (via BindDN), actual: OAuth2",
},
// case 24
{
args: []string{
"ldap-test",
"--id", "24",
"--name", "ldap (via Bind DN) flip 'active' and 'user sync' attributes",
"--active",
"--disable-synchronize-users",
},
id: 24,
existingAuthSource: &auth.Source{
Type: auth.LDAP,
IsActive: false,
IsSyncEnabled: true,
Cfg: &ldap.Source{
Name: "ldap (via Bind DN) flip 'active' and 'user sync' attributes",
Enabled: true,
},
},
authSource: &auth.Source{
Type: auth.LDAP,
Name: "ldap (via Bind DN) flip 'active' and 'user sync' attributes",
IsActive: true,
IsSyncEnabled: false,
Cfg: &ldap.Source{
Name: "ldap (via Bind DN) flip 'active' and 'user sync' attributes",
Enabled: true,
},
},
},
}
for n, c := range cases {
@@ -936,12 +907,12 @@ func TestUpdateLdapBindDn(t *testing.T) {
func TestUpdateLdapSimpleAuth(t *testing.T) {
// Mock cli functions to do not exit on error
osExiter := cli.OsExiter
var osExiter = cli.OsExiter
defer func() { cli.OsExiter = osExiter }()
cli.OsExiter = func(code int) {}
// Test cases
cases := []struct {
var cases = []struct {
args []string
id int64
existingAuthSource *auth.Source
@@ -1190,6 +1161,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
authSource: &auth.Source{
Type: auth.DLDAP,
Cfg: &ldap.Source{
AttributeMail: "mail",
},
},
@@ -1250,33 +1222,6 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
},
errMsg: "Invalid authentication type. expected: LDAP (simple auth), actual: PAM",
},
// case 20
{
args: []string{
"ldap-test",
"--id", "20",
"--name", "ldap (simple auth) flip 'active' attribute",
"--active",
},
id: 20,
existingAuthSource: &auth.Source{
Type: auth.DLDAP,
IsActive: false,
Cfg: &ldap.Source{
Name: "ldap (simple auth) flip 'active' attribute",
Enabled: true,
},
},
authSource: &auth.Source{
Type: auth.DLDAP,
Name: "ldap (simple auth) flip 'active' attribute",
IsActive: true,
Cfg: &ldap.Source{
Name: "ldap (simple auth) flip 'active' attribute",
Enabled: true,
},
},
},
}
for n, c := range cases {

View File

@@ -1,21 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"github.com/urfave/cli"
)
var subcmdUser = cli.Command{
Name: "user",
Usage: "Modify users",
Subcommands: []cli.Command{
microcmdUserCreate,
microcmdUserList,
microcmdUserChangePassword,
microcmdUserDelete,
microcmdUserGenerateAccessToken,
microcmdUserMustChangePassword,
},
}

View File

@@ -1,76 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"errors"
"fmt"
user_model "code.gitea.io/gitea/models/user"
pwd "code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/setting"
"github.com/urfave/cli"
)
var microcmdUserChangePassword = cli.Command{
Name: "change-password",
Usage: "Change a user's password",
Action: runChangePassword,
Flags: []cli.Flag{
cli.StringFlag{
Name: "username,u",
Value: "",
Usage: "The user to change password for",
},
cli.StringFlag{
Name: "password,p",
Value: "",
Usage: "New password to set for user",
},
},
}
func runChangePassword(c *cli.Context) error {
if err := argsSet(c, "username", "password"); err != nil {
return err
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
if len(c.String("password")) < setting.MinPasswordLength {
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
}
if !pwd.IsComplexEnough(c.String("password")) {
return errors.New("Password does not meet complexity requirements")
}
pwned, err := pwd.IsPwned(context.Background(), c.String("password"))
if err != nil {
return err
}
if pwned {
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords")
}
uname := c.String("username")
user, err := user_model.GetUserByName(ctx, uname)
if err != nil {
return err
}
if err = user.SetPassword(c.String("password")); err != nil {
return err
}
if err = user_model.UpdateUserCols(ctx, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
return err
}
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
return nil
}

View File

@@ -1,169 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"errors"
"fmt"
"os"
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
pwd "code.gitea.io/gitea/modules/auth/password"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/urfave/cli"
)
var microcmdUserCreate = cli.Command{
Name: "create",
Usage: "Create a new user in database",
Action: runCreateUser,
Flags: []cli.Flag{
cli.StringFlag{
Name: "name",
Usage: "Username. DEPRECATED: use username instead",
},
cli.StringFlag{
Name: "username",
Usage: "Username",
},
cli.StringFlag{
Name: "password",
Usage: "User password",
},
cli.StringFlag{
Name: "email",
Usage: "User email address",
},
cli.BoolFlag{
Name: "admin",
Usage: "User is an admin",
},
cli.BoolFlag{
Name: "random-password",
Usage: "Generate a random password for the user",
},
cli.BoolFlag{
Name: "must-change-password",
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
},
cli.IntFlag{
Name: "random-password-length",
Usage: "Length of the random password to be generated",
Value: 12,
},
cli.BoolFlag{
Name: "access-token",
Usage: "Generate access token for the user",
},
cli.BoolFlag{
Name: "restricted",
Usage: "Make a restricted user account",
},
},
}
func runCreateUser(c *cli.Context) error {
if err := argsSet(c, "email"); err != nil {
return err
}
if c.IsSet("name") && c.IsSet("username") {
return errors.New("Cannot set both --name and --username flags")
}
if !c.IsSet("name") && !c.IsSet("username") {
return errors.New("One of --name or --username flags must be set")
}
if c.IsSet("password") && c.IsSet("random-password") {
return errors.New("cannot set both -random-password and -password flags")
}
var username string
if c.IsSet("username") {
username = c.String("username")
} else {
username = c.String("name")
fmt.Fprintf(os.Stderr, "--name flag is deprecated. Use --username instead.\n")
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
var password string
if c.IsSet("password") {
password = c.String("password")
} else if c.IsSet("random-password") {
var err error
password, err = pwd.Generate(c.Int("random-password-length"))
if err != nil {
return err
}
fmt.Printf("generated random password is '%s'\n", password)
} else {
return errors.New("must set either password or random-password flag")
}
// always default to true
changePassword := true
// If this is the first user being created.
// Take it as the admin and don't force a password update.
if n := user_model.CountUsers(nil); n == 0 {
changePassword = false
}
if c.IsSet("must-change-password") {
changePassword = c.Bool("must-change-password")
}
restricted := util.OptionalBoolNone
if c.IsSet("restricted") {
restricted = util.OptionalBoolOf(c.Bool("restricted"))
}
// default user visibility in app.ini
visibility := setting.Service.DefaultUserVisibilityMode
u := &user_model.User{
Name: username,
Email: c.String("email"),
Passwd: password,
IsAdmin: c.Bool("admin"),
MustChangePassword: changePassword,
Visibility: visibility,
}
overwriteDefault := &user_model.CreateUserOverwriteOptions{
IsActive: util.OptionalBoolTrue,
IsRestricted: restricted,
}
if err := user_model.CreateUser(u, overwriteDefault); err != nil {
return fmt.Errorf("CreateUser: %w", err)
}
if c.Bool("access-token") {
t := &auth_model.AccessToken{
Name: "gitea-admin",
UID: u.ID,
}
if err := auth_model.NewAccessToken(t); err != nil {
return err
}
fmt.Printf("Access token was successfully created... %s\n", t.Token)
}
fmt.Printf("New user '%s' has been successfully created!\n", username)
return nil
}

View File

@@ -1,78 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"fmt"
"strings"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/storage"
user_service "code.gitea.io/gitea/services/user"
"github.com/urfave/cli"
)
var microcmdUserDelete = cli.Command{
Name: "delete",
Usage: "Delete specific user by id, name or email",
Flags: []cli.Flag{
cli.Int64Flag{
Name: "id",
Usage: "ID of user of the user to delete",
},
cli.StringFlag{
Name: "username,u",
Usage: "Username of the user to delete",
},
cli.StringFlag{
Name: "email,e",
Usage: "Email of the user to delete",
},
cli.BoolFlag{
Name: "purge",
Usage: "Purge user, all their repositories, organizations and comments",
},
},
Action: runDeleteUser,
}
func runDeleteUser(c *cli.Context) error {
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
return fmt.Errorf("You must provide the id, username or email of a user to delete")
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
if err := storage.Init(); err != nil {
return err
}
var err error
var user *user_model.User
if c.IsSet("email") {
user, err = user_model.GetUserByEmail(ctx, c.String("email"))
} else if c.IsSet("username") {
user, err = user_model.GetUserByName(ctx, c.String("username"))
} else {
user, err = user_model.GetUserByID(ctx, c.Int64("id"))
}
if err != nil {
return err
}
if c.IsSet("username") && user.LowerName != strings.ToLower(strings.TrimSpace(c.String("username"))) {
return fmt.Errorf("The user %s who has email %s does not match the provided username %s", user.Name, c.String("email"), c.String("username"))
}
if c.IsSet("id") && user.ID != c.Int64("id") {
return fmt.Errorf("The user %s does not match the provided id %d", user.Name, c.Int64("id"))
}
return user_service.DeleteUser(ctx, user, c.Bool("purge"))
}

View File

@@ -1,80 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"fmt"
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"github.com/urfave/cli"
)
var microcmdUserGenerateAccessToken = cli.Command{
Name: "generate-access-token",
Usage: "Generate an access token for a specific user",
Flags: []cli.Flag{
cli.StringFlag{
Name: "username,u",
Usage: "Username",
},
cli.StringFlag{
Name: "token-name,t",
Usage: "Token name",
Value: "gitea-admin",
},
cli.BoolFlag{
Name: "raw",
Usage: "Display only the token value",
},
cli.StringFlag{
Name: "scopes",
Value: "",
Usage: "Comma separated list of scopes to apply to access token",
},
},
Action: runGenerateAccessToken,
}
func runGenerateAccessToken(c *cli.Context) error {
if !c.IsSet("username") {
return fmt.Errorf("You must provide a username to generate a token for")
}
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
user, err := user_model.GetUserByName(ctx, c.String("username"))
if err != nil {
return err
}
accessTokenScope, err := auth_model.AccessTokenScope(c.String("scopes")).Normalize()
if err != nil {
return err
}
t := &auth_model.AccessToken{
Name: c.String("token-name"),
UID: user.ID,
Scope: accessTokenScope,
}
if err := auth_model.NewAccessToken(t); err != nil {
return err
}
if c.Bool("raw") {
fmt.Printf("%s\n", t.Token)
} else {
fmt.Printf("Access token was successfully created: %s\n", t.Token)
}
return nil
}

View File

@@ -1,60 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"fmt"
"os"
"text/tabwriter"
user_model "code.gitea.io/gitea/models/user"
"github.com/urfave/cli"
)
var microcmdUserList = cli.Command{
Name: "list",
Usage: "List users",
Action: runListUsers,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "admin",
Usage: "List only admin users",
},
},
}
func runListUsers(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
users, err := user_model.GetAllUsers()
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 5, 0, 1, ' ', 0)
if c.IsSet("admin") {
fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\n")
for _, u := range users {
if u.IsAdmin {
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", u.ID, u.Name, u.Email, u.IsActive)
}
}
} else {
twofa := user_model.UserList(users).GetTwoFaStatus()
fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\tIsAdmin\t2FA\n")
for _, u := range users {
fmt.Fprintf(w, "%d\t%s\t%s\t%t\t%t\t%t\n", u.ID, u.Name, u.Email, u.IsActive, u.IsAdmin, twofa[u.ID])
}
}
w.Flush()
return nil
}

View File

@@ -1,58 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"errors"
"fmt"
user_model "code.gitea.io/gitea/models/user"
"github.com/urfave/cli"
)
var microcmdUserMustChangePassword = cli.Command{
Name: "must-change-password",
Usage: "Set the must change password flag for the provided users or all users",
Action: runMustChangePassword,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "all,A",
Usage: "All users must change password, except those explicitly excluded with --exclude",
},
cli.StringSliceFlag{
Name: "exclude,e",
Usage: "Do not change the must-change-password flag for these users",
},
cli.BoolFlag{
Name: "unset",
Usage: "Instead of setting the must-change-password flag, unset it",
},
},
}
func runMustChangePassword(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
if c.NArg() == 0 && !c.IsSet("all") {
return errors.New("either usernames or --all must be provided")
}
mustChangePassword := !c.Bool("unset")
all := c.Bool("all")
exclude := c.StringSlice("exclude")
if err := initDB(ctx); err != nil {
return err
}
n, err := user_model.SetMustChangePassword(ctx, all, mustChangePassword, c.Args(), exclude)
if err != nil {
return err
}
fmt.Printf("Updated %d users setting MustChangePassword to %t\n", n, mustChangePassword)
return nil
}

View File

@@ -1,7 +1,8 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -179,7 +180,7 @@ func runCert(c *cli.Context) error {
}
log.Println("Written cert.pem")
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("Failed to open key.pem for writing: %v", err)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package cmd provides subcommands to the gitea binary - such as "web" or
// "admin".
@@ -57,10 +58,9 @@ func confirm() (bool, error) {
}
func initDB(ctx context.Context) error {
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadDBSetting()
setting.InitSQLLog(false)
setting.LoadFromExisting()
setting.InitDBConfig()
setting.NewXORMLogService(false)
if setting.Database.Type == "" {
log.Fatal(`Database settings are missing from the configuration file: %q.
@@ -68,7 +68,7 @@ Ensure you are running in the correct environment or set the correct configurati
If this is the intended configuration file complete the [database] section.`, setting.CustomConf)
}
if err := db.InitEngine(ctx); err != nil {
return fmt.Errorf("unable to initialize the database using the configuration in %q. Error: %w", setting.CustomConf, err)
return fmt.Errorf("unable to initialise the database using the configuration in %q. Error: %v", setting.CustomConf, err)
}
return nil
}

View File

@@ -1,5 +1,6 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -32,7 +33,7 @@ func runConvert(ctx *cli.Context) error {
log.Info("AppPath: %s", setting.AppPath)
log.Info("AppWorkPath: %s", setting.AppWorkPath)
log.Info("Custom path: %s", setting.CustomPath)
log.Info("Log path: %s", setting.Log.RootPath)
log.Info("Log path: %s", setting.LogRootPath)
log.Info("Configuration file: %s", setting.CustomConf)
if !setting.Database.UseMySQL {

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd

View File

@@ -1,10 +1,11 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"errors"
"context"
"fmt"
golog "log"
"os"
@@ -13,7 +14,6 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/migrations"
migrate_base "code.gitea.io/gitea/models/migrations/base"
"code.gitea.io/gitea/modules/doctor"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -25,8 +25,8 @@ import (
// CmdDoctor represents the available doctor sub-command.
var CmdDoctor = cli.Command{
Name: "doctor",
Usage: "Diagnose and optionally fix problems",
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
Usage: "Diagnose problems",
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration.",
Action: runDoctor,
Flags: []cli.Flag{
cli.BoolFlag{
@@ -87,16 +87,14 @@ func runRecreateTable(ctx *cli.Context) error {
golog.SetPrefix("")
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadDBSetting()
setting.LoadFromExisting()
setting.InitDBConfig()
setting.Log.EnableXORMLog = ctx.Bool("debug")
setting.EnableXORMLog = ctx.Bool("debug")
setting.Database.LogSQL = ctx.Bool("debug")
// FIXME: don't use CfgProvider directly
setting.CfgProvider.Section("log").Key("XORM").SetValue(",")
setting.Cfg.Section("log").Key("XORM").SetValue(",")
setting.InitSQLLog(!ctx.Bool("debug"))
setting.NewXORMLogService(!ctx.Bool("debug"))
stdCtx, cancel := installSignals()
defer cancel()
@@ -116,21 +114,31 @@ func runRecreateTable(ctx *cli.Context) error {
if err != nil {
return err
}
recreateTables := migrate_base.RecreateTables(beans...)
recreateTables := migrations.RecreateTables(beans...)
return db.InitEngineWithMigration(stdCtx, func(x *xorm.Engine) error {
return db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error {
if err := migrations.EnsureUpToDate(x); err != nil {
return err
}
return recreateTables(x)
})
}
func setDoctorLogger(ctx *cli.Context) {
func runDoctor(ctx *cli.Context) error {
// Silence the default loggers
log.DelNamedLogger("console")
log.DelNamedLogger(log.DEFAULT)
stdCtx, cancel := installSignals()
defer cancel()
// Now setup our own
logFile := ctx.String("log-file")
if !ctx.IsSet("log-file") {
logFile = "doctor.log"
}
colorize := log.CanColorStdout
if ctx.IsSet("color") {
colorize = ctx.Bool("color")
@@ -138,50 +146,11 @@ func setDoctorLogger(ctx *cli.Context) {
if len(logFile) == 0 {
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
return
}
defer func() {
recovered := recover()
if recovered == nil {
return
}
err, ok := recovered.(error)
if !ok {
panic(recovered)
}
if errors.Is(err, os.ErrPermission) {
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file due to permissions error: %s\n %v\n", logFile, err)
} else {
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file: %s\n %v\n", logFile, err)
}
fmt.Fprintf(os.Stderr, "WARN: Logging will be disabled\n Use `--log-file` to configure log file location\n")
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
}()
if logFile == "-" {
} else if logFile == "-" {
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"trace","stacktracelevel":"NONE","colorize":%t}`, colorize))
} else {
log.NewLogger(1000, "doctor", "file", fmt.Sprintf(`{"filename":%q,"level":"trace","stacktracelevel":"NONE"}`, logFile))
}
}
func runDoctor(ctx *cli.Context) error {
stdCtx, cancel := installSignals()
defer cancel()
// Silence the default loggers
log.DelNamedLogger("console")
log.DelNamedLogger(log.DEFAULT)
// Now setup our own
setDoctorLogger(ctx)
colorize := log.CanColorStdout
if ctx.IsSet("color") {
colorize = ctx.Bool("color")
}
// Finally redirect the default golog to here
golog.SetFlags(0)
@@ -236,7 +205,7 @@ func runDoctor(ctx *cli.Context) error {
// Now we can set up our own logger to return information about what the doctor is doing
if err := log.NewNamedLogger("doctorouter",
0,
1000,
"console",
"console",
fmt.Sprintf(`{"level":"INFO","stacktracelevel":"NONE","colorize":%t,"flags":-1}`, colorize)); err != nil {

View File

@@ -1,12 +1,12 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"fmt"
"io"
"os"
"path"
"path/filepath"
@@ -21,25 +21,14 @@ import (
"code.gitea.io/gitea/modules/util"
"gitea.com/go-chi/session"
"github.com/mholt/archiver/v3"
archiver "github.com/mholt/archiver/v3"
"github.com/urfave/cli"
)
func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error {
if verbose {
log.Info("Adding file %s", customName)
}
return w.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: customName,
},
ReadCloser: r,
})
}
func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error {
if verbose {
log.Info("Adding file %s\n", filePath)
}
file, err := os.Open(absPath)
if err != nil {
return err
@@ -50,7 +39,13 @@ func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error {
return err
}
return addReader(w, file, fileInfo, filePath, verbose)
return w.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: fileInfo,
CustomName: filePath,
},
ReadCloser: file,
})
}
func isSubdir(upper, lower string) (bool, error) {
@@ -91,7 +86,7 @@ func (o outputType) String() string {
}
var outputTypeEnum = &outputType{
Enum: []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4", "tar.zst"},
Enum: []string{"zip", "rar", "tar", "sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4"},
Default: "zip",
}
@@ -141,14 +136,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
Name: "skip-attachment-data",
Usage: "Skip attachment data",
},
cli.BoolFlag{
Name: "skip-package-data",
Usage: "Skip package data",
},
cli.BoolFlag{
Name: "skip-index",
Usage: "Skip bleve index data",
},
cli.GenericFlag{
Name: "type",
Value: outputTypeEnum,
@@ -173,30 +160,23 @@ func runDump(ctx *cli.Context) error {
fatal("Deleting default logger failed. Can not write to stdout: %v", err)
}
} else {
for _, suffix := range outputTypeEnum.Enum {
if strings.HasSuffix(fileName, "."+suffix) {
fileName = strings.TrimSuffix(fileName, "."+suffix)
break
}
}
fileName = strings.TrimSuffix(fileName, path.Ext(fileName))
fileName += "." + outType
}
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadFromExisting()
// make sure we are logging to the console no matter what the configuration tells us do to
// FIXME: don't use CfgProvider directly
if _, err := setting.CfgProvider.Section("log").NewKey("MODE", "console"); err != nil {
if _, err := setting.Cfg.Section("log").NewKey("MODE", "console"); err != nil {
fatal("Setting logging mode to console failed: %v", err)
}
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
if _, err := setting.Cfg.Section("log.console").NewKey("STDERR", "true"); err != nil {
fatal("Setting console logger to stderr failed: %v", err)
}
if !setting.InstallLock {
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
return fmt.Errorf("gitea is not initialized")
}
setting.LoadSettings() // cannot access session settings otherwise
setting.NewServices() // cannot access session settings otherwise
stdCtx, cancel := installSignals()
defer cancel()
@@ -256,7 +236,13 @@ func runDump(ctx *cli.Context) error {
return err
}
return addReader(w, object, info, path.Join("data", "lfs", objPath), verbose)
return w.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: path.Join("data", "lfs", objPath),
},
ReadCloser: object,
})
}); err != nil {
fatal("Failed to dump LFS objects: %v", err)
}
@@ -324,7 +310,7 @@ func runDump(ctx *cli.Context) error {
log.Info("Packing data directory...%s", setting.AppDataPath)
var excludes []string
if setting.SessionConfig.OriginalProvider == "file" {
if setting.Cfg.Section("session").Key("PROVIDER").Value() == "file" {
var opts session.Options
if err = json.Unmarshal([]byte(setting.SessionConfig.ProviderConfig), &opts); err != nil {
return err
@@ -332,16 +318,10 @@ func runDump(ctx *cli.Context) error {
excludes = append(excludes, opts.ProviderConfig)
}
if ctx.IsSet("skip-index") && ctx.Bool("skip-index") {
excludes = append(excludes, setting.Indexer.RepoPath)
excludes = append(excludes, setting.Indexer.IssuePath)
}
excludes = append(excludes, setting.RepoRootPath)
excludes = append(excludes, setting.LFS.Path)
excludes = append(excludes, setting.Attachment.Path)
excludes = append(excludes, setting.Packages.Path)
excludes = append(excludes, setting.Log.RootPath)
excludes = append(excludes, setting.LogRootPath)
excludes = append(excludes, absFileName)
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
fatal("Failed to include data directory: %v", err)
@@ -356,36 +336,29 @@ func runDump(ctx *cli.Context) error {
return err
}
return addReader(w, object, info, path.Join("data", "attachments", objPath), verbose)
return w.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: path.Join("data", "attachments", objPath),
},
ReadCloser: object,
})
}); err != nil {
fatal("Failed to dump attachments: %v", err)
}
if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") {
log.Info("Skip dumping package data")
} else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error {
info, err := object.Stat()
if err != nil {
return err
}
return addReader(w, object, info, path.Join("data", "packages", objPath), verbose)
}); err != nil {
fatal("Failed to dump packages: %v", err)
}
// Doesn't check if LogRootPath exists before processing --skip-log intentionally,
// ensuring that it's clear the dump is skipped whether the directory's initialized
// yet or not.
if ctx.IsSet("skip-log") && ctx.Bool("skip-log") {
log.Info("Skip dumping log files")
} else {
isExist, err := util.IsExist(setting.Log.RootPath)
isExist, err := util.IsExist(setting.LogRootPath)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", setting.Log.RootPath, err)
log.Error("Unable to check if %s exists. Error: %v", setting.LogRootPath, err)
}
if isExist {
if err := addRecursiveExclude(w, "log", setting.Log.RootPath, []string{absFileName}, verbose); err != nil {
if err := addRecursiveExclude(w, "log", setting.LogRootPath, []string{absFileName}, verbose); err != nil {
fatal("Failed to include log: %v", err)
}
}
@@ -397,7 +370,7 @@ func runDump(ctx *cli.Context) error {
fatal("Failed to save %s: %v", fileName, err)
}
if err := os.Chmod(fileName, 0o600); err != nil {
if err := os.Chmod(fileName, 0600); err != nil {
log.Info("Can't change file access permissions mask to 0600: %v", err)
}
}
@@ -411,6 +384,15 @@ func runDump(ctx *cli.Context) error {
return nil
}
func contains(slice []string, s string) bool {
for _, v := range slice {
if v == s {
return true
}
}
return false
}
// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath
func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error {
absPath, err := filepath.Abs(absPath)
@@ -431,7 +413,7 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA
currentAbsPath := path.Join(absPath, file.Name())
currentInsidePath := path.Join(insidePath, file.Name())
if file.IsDir() {
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
if !contains(excludeAbsPath, currentAbsPath) {
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
return err
}
@@ -440,23 +422,8 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA
}
}
} else {
// only copy regular files and symlink regular files, skip non-regular files like socket/pipe/...
shouldAdd := file.Mode().IsRegular()
if !shouldAdd && file.Mode()&os.ModeSymlink == os.ModeSymlink {
target, err := filepath.EvalSymlinks(currentAbsPath)
if err != nil {
return err
}
targetStat, err := os.Stat(target)
if err != nil {
return err
}
shouldAdd = targetStat.Mode().IsRegular()
}
if shouldAdd {
if err = addFile(w, currentInsidePath, currentAbsPath, verbose); err != nil {
return err
}
if err = addFile(w, currentInsidePath, currentAbsPath, verbose); err != nil {
return err
}
}
}

View File

@@ -1,22 +1,19 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"context"
"errors"
"fmt"
"os"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/convert"
"code.gitea.io/gitea/services/migrations"
"github.com/urfave/cli"
@@ -86,15 +83,10 @@ func runDumpRepository(ctx *cli.Context) error {
return err
}
// migrations.GiteaLocalUploader depends on git module
if err := git.InitSimple(context.Background()); err != nil {
return err
}
log.Info("AppPath: %s", setting.AppPath)
log.Info("AppWorkPath: %s", setting.AppWorkPath)
log.Info("Custom path: %s", setting.CustomPath)
log.Info("Log path: %s", setting.Log.RootPath)
log.Info("Log path: %s", setting.LogRootPath)
log.Info("Configuration file: %s", setting.CustomConf)
var (
@@ -115,7 +107,7 @@ func runDumpRepository(ctx *cli.Context) error {
}
serviceType = convert.ToGitServiceType(serviceStr)
opts := base.MigrateOptions{
var opts = base.MigrateOptions{
GitServiceType: serviceType,
CloneAddr: cloneAddr,
AuthUsername: ctx.String("auth_username"),
@@ -136,9 +128,7 @@ func runDumpRepository(ctx *cli.Context) error {
} else {
units := strings.Split(ctx.String("units"), ",")
for _, unit := range units {
switch strings.ToLower(strings.TrimSpace(unit)) {
case "":
continue
switch strings.ToLower(unit) {
case "wiki":
opts.Wiki = true
case "issues":
@@ -155,29 +145,13 @@ func runDumpRepository(ctx *cli.Context) error {
opts.Comments = true
case "pull_requests":
opts.PullRequests = true
default:
return errors.New("invalid unit: " + unit)
}
}
}
// the repo_dir will be removed if error occurs in DumpRepository
// make sure the directory doesn't exist or is empty, prevent from deleting user files
repoDir := ctx.String("repo_dir")
if exists, err := util.IsExist(repoDir); err != nil {
return fmt.Errorf("unable to stat repo_dir %q: %w", repoDir, err)
} else if exists {
if isDir, _ := util.IsDir(repoDir); !isDir {
return fmt.Errorf("repo_dir %q already exists but it's not a directory", repoDir)
}
if dir, _ := os.ReadDir(repoDir); len(dir) > 0 {
return fmt.Errorf("repo_dir %q is not empty", repoDir)
}
}
if err := migrations.DumpRepository(
context.Background(),
repoDir,
ctx.String("repo_dir"),
ctx.String("owner_name"),
opts,
); err != nil {

View File

@@ -1,7 +1,9 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build bindata
// +build bindata
package cmd
@@ -107,13 +109,13 @@ type asset struct {
}
func initEmbeddedExtractor(c *cli.Context) error {
// Silence the console logger
log.DelNamedLogger("console")
log.DelNamedLogger(log.DEFAULT)
// Read configuration file
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.LoadAllowEmpty()
pats, err := getPatterns(c.Args())
if err != nil {
@@ -123,7 +125,7 @@ func initEmbeddedExtractor(c *cli.Context) error {
sections["public"] = &section{Path: "public", Names: public.AssetNames, IsDir: public.AssetIsDir, Asset: public.Asset}
sections["options"] = &section{Path: "options", Names: options.AssetNames, IsDir: options.AssetIsDir, Asset: options.Asset}
sections["templates"] = &section{Path: "templates", Names: templates.BuiltinAssetNames, IsDir: templates.BuiltinAssetIsDir, Asset: templates.BuiltinAsset}
sections["templates"] = &section{Path: "templates", Names: templates.AssetNames, IsDir: templates.AssetIsDir, Asset: templates.Asset}
for _, sec := range sections {
assets = append(assets, buildAssetList(sec, pats, c)...)
@@ -186,11 +188,11 @@ func runViewDo(c *cli.Context) error {
data, err := assets[0].Section.Asset(assets[0].Name)
if err != nil {
return fmt.Errorf("%s: %w", assets[0].Path, err)
return fmt.Errorf("%s: %v", assets[0].Path, err)
}
if _, err = os.Stdout.Write(data); err != nil {
return fmt.Errorf("%s: %w", assets[0].Path, err)
return fmt.Errorf("%s: %v", assets[0].Path, err)
}
return nil
@@ -251,19 +253,19 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
data, err := a.Section.Asset(a.Name)
if err != nil {
return fmt.Errorf("%s: %w", a.Path, err)
return fmt.Errorf("%s: %v", a.Path, err)
}
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("%s: %w", dir, err)
return fmt.Errorf("%s: %v", dir, err)
}
perms := os.ModePerm & 0o666
perms := os.ModePerm & 0666
fi, err := os.Lstat(dest)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("%s: %w", dest, err)
return fmt.Errorf("%s: %v", dest, err)
}
} else if !overwrite && !rename {
fmt.Printf("%s already exists; skipped.\n", dest)
@@ -272,7 +274,7 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
return fmt.Errorf("%s already exists, but it's not a regular file", dest)
} else if rename {
if err := util.Rename(dest, dest+".bak"); err != nil {
return fmt.Errorf("Error creating backup for %s: %w", dest, err)
return fmt.Errorf("Error creating backup for %s: %v", dest, err)
}
// Attempt to respect file permissions mask (even if user:group will be set anew)
perms = fi.Mode()
@@ -280,12 +282,12 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
file, err := os.OpenFile(dest, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, perms)
if err != nil {
return fmt.Errorf("%s: %w", dest, err)
return fmt.Errorf("%s: %v", dest, err)
}
defer file.Close()
if _, err = file.Write(data); err != nil {
return fmt.Errorf("%s: %w", dest, err)
return fmt.Errorf("%s: %v", dest, err)
}
fmt.Println(dest)
@@ -294,7 +296,7 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
}
func buildAssetList(sec *section, globs []glob.Glob, c *cli.Context) []asset {
results := make([]asset, 0, 64)
var results = make([]asset, 0, 64)
for _, name := range sec.Names() {
if isdir, err := sec.IsDir(name); !isdir && err == nil {
if sec.Path == "public" &&
@@ -305,11 +307,9 @@ func buildAssetList(sec *section, globs []glob.Glob, c *cli.Context) []asset {
matchName := sec.Path + "/" + name
for _, g := range globs {
if g.Match(matchName) {
results = append(results, asset{
Section: sec,
Name: name,
Path: sec.Path + "/" + name,
})
results = append(results, asset{Section: sec,
Name: name,
Path: sec.Path + "/" + name})
break
}
}
@@ -325,7 +325,7 @@ func getPatterns(args []string) ([]glob.Glob, error) {
pat := make([]glob.Glob, len(args))
for i := range args {
if g, err := glob.Compile(args[i], '/'); err != nil {
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
return nil, fmt.Errorf("'%s': Invalid glob pattern: %v", args[i], err)
} else {
pat[i] = g
}

View File

@@ -1,7 +1,9 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build !bindata
// +build !bindata
package cmd

View File

@@ -1,6 +1,7 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd

View File

@@ -1,5 +1,6 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -14,9 +15,9 @@ import (
"strings"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/private"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -161,7 +162,7 @@ func (n *nilWriter) WriteString(s string) (int, error) {
}
func runHookPreReceive(c *cli.Context) error {
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
if os.Getenv(models.EnvIsInternal) == "true" {
return nil
}
ctx, cancel := installSignals()
@@ -179,13 +180,12 @@ Gitea or set your environment appropriately.`, "")
}
// the environment is set by serv command
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
username := os.Getenv(repo_module.EnvRepoUsername)
reponame := os.Getenv(repo_module.EnvRepoName)
userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
deployKeyID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvDeployKeyID), 10, 64)
actionPerm, _ := strconv.ParseInt(os.Getenv(repo_module.EnvActionPerm), 10, 64)
isWiki := os.Getenv(models.EnvRepoIsWiki) == "true"
username := os.Getenv(models.EnvRepoUsername)
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))
hookOptions := private.HookOptions{
UserID: userID,
@@ -194,8 +194,7 @@ Gitea or set your environment appropriately.`, "")
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
GitPushOptions: pushOptions(),
PullRequestID: prID,
DeployKeyID: deployKeyID,
ActionPerm: int(actionPerm),
IsDeployKey: isDeployKey,
}
scanner := bufio.NewScanner(os.Stdin)
@@ -219,9 +218,9 @@ Gitea or set your environment appropriately.`, "")
}
}
supportProcReceive := false
supportProcRecive := false
if git.CheckGitVersionAtLeast("2.29") == nil {
supportProcReceive = true
supportProcRecive = true
}
for scanner.Scan() {
@@ -242,9 +241,9 @@ Gitea or set your environment appropriately.`, "")
lastline++
// If the ref is a branch or tag, check if it's protected
// if supportProcReceive all ref should be checked because
// if supportProcRecive all ref should be checked because
// permission check was delayed
if supportProcReceive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
if supportProcRecive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
oldCommitIDs[count] = oldCommitID
newCommitIDs[count] = newCommitID
refFullNames[count] = refFullName
@@ -309,18 +308,18 @@ func runHookPostReceive(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("hooks/post-receive.log", c.Bool("debug"))
// First of all run update-server-info no matter what
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
return fmt.Errorf("Failed to call 'git update-server-info': %w", err)
if _, err := git.NewCommandContext(ctx, "update-server-info").Run(); err != nil {
return fmt.Errorf("Failed to call 'git update-server-info': %v", err)
}
// Now if we're an internal don't do anything else
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
if os.Getenv(models.EnvIsInternal) == "true" {
return nil
}
setup("hooks/post-receive.log", c.Bool("debug"))
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
return fail(`Rejecting changes as Gitea environment not set.
@@ -344,11 +343,11 @@ Gitea or set your environment appropriately.`, "")
}
// the environment is set by serv command
repoUser := os.Getenv(repo_module.EnvRepoUsername)
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
repoName := os.Getenv(repo_module.EnvRepoName)
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
pusherName := os.Getenv(repo_module.EnvPusherName)
repoUser := os.Getenv(models.EnvRepoUsername)
isWiki := os.Getenv(models.EnvRepoIsWiki) == "true"
repoName := os.Getenv(models.EnvRepoName)
pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
pusherName := os.Getenv(models.EnvPusherName)
hookOptions := private.HookOptions{
UserName: pusherName,
@@ -504,10 +503,10 @@ Gitea or set your environment appropriately.`, "")
}
reader := bufio.NewReader(os.Stdin)
repoUser := os.Getenv(repo_module.EnvRepoUsername)
repoName := os.Getenv(repo_module.EnvRepoName)
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
pusherName := os.Getenv(repo_module.EnvPusherName)
repoUser := os.Getenv(models.EnvRepoUsername)
repoName := os.Getenv(models.EnvRepoName)
pusherID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
pusherName := os.Getenv(models.EnvPusherName)
// 1. Version and features negotiation.
// S: PKT-LINE(version=1\0push-options atomic...) / PKT-LINE(version=1\n)
@@ -793,7 +792,7 @@ func writeDataPktLine(out io.Writer, data []byte) error {
if err != nil {
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
}
if lr != 4 {
if 4 != lr {
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd

View File

@@ -1,5 +1,6 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -17,8 +18,7 @@ func runSendMail(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadFromExisting()
if err := argsSet(c, "title"); err != nil {
return err

View File

@@ -1,22 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
func TestMain(m *testing.M) {
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: "..",
})
}

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -9,6 +10,7 @@ import (
"os"
"time"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"github.com/urfave/cli"
@@ -25,7 +27,6 @@ var (
subcmdRestart,
subcmdFlushQueues,
subcmdLogging,
subCmdProcesses,
},
}
subcmdShutdown = cli.Command{
@@ -57,8 +58,7 @@ var (
Name: "timeout",
Value: 60 * time.Second,
Usage: "Timeout for the flushing process",
},
cli.BoolFlag{
}, cli.BoolFlag{
Name: "non-blocking",
Usage: "Set to true to not wait for flush to complete before returning",
},
@@ -67,38 +67,326 @@ var (
},
},
}
subCmdProcesses = cli.Command{
Name: "processes",
Usage: "Display running processes within the current process",
Action: runProcesses,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
cli.BoolFlag{
Name: "flat",
Usage: "Show processes as flat table rather than as tree",
},
cli.BoolFlag{
Name: "no-system",
Usage: "Do not show system processes",
},
cli.BoolFlag{
Name: "stacktraces",
Usage: "Show stacktraces",
},
cli.BoolFlag{
Name: "json",
Usage: "Output as json",
},
cli.StringFlag{
Name: "cancel",
Usage: "Process PID to cancel. (Only available for non-system processes.)",
defaultLoggingFlags = []cli.Flag{
cli.StringFlag{
Name: "group, g",
Usage: "Group to add logger to - will default to \"default\"",
}, cli.StringFlag{
Name: "name, n",
Usage: "Name of the new logger - will default to mode",
}, cli.StringFlag{
Name: "level, l",
Usage: "Logging level for the new logger",
}, cli.StringFlag{
Name: "stacktrace-level, L",
Usage: "Stacktrace logging level",
}, cli.StringFlag{
Name: "flags, F",
Usage: "Flags for the logger",
}, cli.StringFlag{
Name: "expression, e",
Usage: "Matching expression for the logger",
}, cli.StringFlag{
Name: "prefix, p",
Usage: "Prefix for the logger",
}, cli.BoolFlag{
Name: "color",
Usage: "Use color in the logs",
}, cli.BoolFlag{
Name: "debug",
},
}
subcmdLogging = cli.Command{
Name: "logging",
Usage: "Adjust logging commands",
Subcommands: []cli.Command{
{
Name: "pause",
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runPauseLogging,
}, {
Name: "resume",
Usage: "Resume logging",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runResumeLogging,
}, {
Name: "release-and-reopen",
Usage: "Cause Gitea to release and re-open files used for logging",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runReleaseReopenLogging,
}, {
Name: "remove",
Usage: "Remove a logger",
ArgsUsage: "[name] Name of logger to remove",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
}, cli.StringFlag{
Name: "group, g",
Usage: "Group to add logger to - will default to \"default\"",
},
},
Action: runRemoveLogger,
}, {
Name: "add",
Usage: "Add a logger",
Subcommands: []cli.Command{
{
Name: "console",
Usage: "Add a console logger",
Flags: append(defaultLoggingFlags,
cli.BoolFlag{
Name: "stderr",
Usage: "Output console logs to stderr - only relevant for console",
}),
Action: runAddConsoleLogger,
}, {
Name: "file",
Usage: "Add a file logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.StringFlag{
Name: "filename, f",
Usage: "Filename for the logger - this must be set.",
}, cli.BoolTFlag{
Name: "rotate, r",
Usage: "Rotate logs",
}, cli.Int64Flag{
Name: "max-size, s",
Usage: "Maximum size in bytes before rotation",
}, cli.BoolTFlag{
Name: "daily, d",
Usage: "Rotate logs daily",
}, cli.IntFlag{
Name: "max-days, D",
Usage: "Maximum number of daily logs to keep",
}, cli.BoolTFlag{
Name: "compress, z",
Usage: "Compress rotated logs",
}, cli.IntFlag{
Name: "compression-level, Z",
Usage: "Compression level to use",
},
}...),
Action: runAddFileLogger,
}, {
Name: "conn",
Usage: "Add a net conn logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.BoolFlag{
Name: "reconnect-on-message, R",
Usage: "Reconnect to host for every message",
}, cli.BoolFlag{
Name: "reconnect, r",
Usage: "Reconnect to host when connection is dropped",
}, cli.StringFlag{
Name: "protocol, P",
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)",
}, cli.StringFlag{
Name: "address, a",
Usage: "Host address and port to connect to (defaults to :7020)",
},
}...),
Action: runAddConnLogger,
}, {
Name: "smtp",
Usage: "Add an SMTP logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.StringFlag{
Name: "username, u",
Usage: "Mail server username",
}, cli.StringFlag{
Name: "password, P",
Usage: "Mail server password",
}, cli.StringFlag{
Name: "host, H",
Usage: "Mail server host (defaults to: 127.0.0.1:25)",
}, cli.StringSliceFlag{
Name: "send-to, s",
Usage: "Email address(es) to send to",
}, cli.StringFlag{
Name: "subject, S",
Usage: "Subject header of sent emails",
},
}...),
Action: runAddSMTPLogger,
},
},
},
},
}
)
func runRemoveLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
group := c.String("group")
if len(group) == 0 {
group = log.DEFAULT
}
name := c.Args().First()
ctx, cancel := installSignals()
defer cancel()
statusCode, msg := private.RemoveLogger(ctx, group, name)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runAddSMTPLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "smtp"
if c.IsSet("host") {
vals["host"] = c.String("host")
} else {
vals["host"] = "127.0.0.1:25"
}
if c.IsSet("username") {
vals["username"] = c.String("username")
}
if c.IsSet("password") {
vals["password"] = c.String("password")
}
if !c.IsSet("send-to") {
return fmt.Errorf("Some recipients must be provided")
}
vals["sendTos"] = c.StringSlice("send-to")
if c.IsSet("subject") {
vals["subject"] = c.String("subject")
} else {
vals["subject"] = "Diagnostic message from Gitea"
}
return commonAddLogger(c, mode, vals)
}
func runAddConnLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "conn"
vals["net"] = "tcp"
if c.IsSet("protocol") {
switch c.String("protocol") {
case "udp":
vals["net"] = "udp"
case "unix":
vals["net"] = "unix"
}
}
if c.IsSet("address") {
vals["address"] = c.String("address")
} else {
vals["address"] = ":7020"
}
if c.IsSet("reconnect") {
vals["reconnect"] = c.Bool("reconnect")
}
if c.IsSet("reconnect-on-message") {
vals["reconnectOnMsg"] = c.Bool("reconnect-on-message")
}
return commonAddLogger(c, mode, vals)
}
func runAddFileLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "file"
if c.IsSet("filename") {
vals["filename"] = c.String("filename")
} else {
return fmt.Errorf("filename must be set when creating a file logger")
}
if c.IsSet("rotate") {
vals["rotate"] = c.Bool("rotate")
}
if c.IsSet("max-size") {
vals["maxsize"] = c.Int64("max-size")
}
if c.IsSet("daily") {
vals["daily"] = c.Bool("daily")
}
if c.IsSet("max-days") {
vals["maxdays"] = c.Int("max-days")
}
if c.IsSet("compress") {
vals["compress"] = c.Bool("compress")
}
if c.IsSet("compression-level") {
vals["compressionLevel"] = c.Int("compression-level")
}
return commonAddLogger(c, mode, vals)
}
func runAddConsoleLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "console"
if c.IsSet("stderr") && c.Bool("stderr") {
vals["stderr"] = c.Bool("stderr")
}
return commonAddLogger(c, mode, vals)
}
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
if len(c.String("level")) > 0 {
vals["level"] = log.FromString(c.String("level")).String()
}
if len(c.String("stacktrace-level")) > 0 {
vals["stacktraceLevel"] = log.FromString(c.String("stacktrace-level")).String()
}
if len(c.String("expression")) > 0 {
vals["expression"] = c.String("expression")
}
if len(c.String("prefix")) > 0 {
vals["prefix"] = c.String("prefix")
}
if len(c.String("flags")) > 0 {
vals["flags"] = log.FlagsFromString(c.String("flags"))
}
if c.IsSet("color") {
vals["colorize"] = c.Bool("color")
}
group := "default"
if c.IsSet("group") {
group = c.String("group")
}
name := mode
if c.IsSet("name") {
name = c.String("name")
}
ctx, cancel := installSignals()
defer cancel()
statusCode, msg := private.AddLogger(ctx, group, name, mode, vals)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runShutdown(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
@@ -144,16 +432,47 @@ func runFlushQueues(c *cli.Context) error {
return nil
}
func runProcesses(c *cli.Context) error {
func runPauseLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
statusCode, msg := private.PauseLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runResumeLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.ResumeLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runReleaseReopenLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.ReleaseReopenLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}

View File

@@ -1,409 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"fmt"
"net/http"
"os"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"github.com/urfave/cli"
)
var (
defaultLoggingFlags = []cli.Flag{
cli.StringFlag{
Name: "group, g",
Usage: "Group to add logger to - will default to \"default\"",
}, cli.StringFlag{
Name: "name, n",
Usage: "Name of the new logger - will default to mode",
}, cli.StringFlag{
Name: "level, l",
Usage: "Logging level for the new logger",
}, cli.StringFlag{
Name: "stacktrace-level, L",
Usage: "Stacktrace logging level",
}, cli.StringFlag{
Name: "flags, F",
Usage: "Flags for the logger",
}, cli.StringFlag{
Name: "expression, e",
Usage: "Matching expression for the logger",
}, cli.StringFlag{
Name: "prefix, p",
Usage: "Prefix for the logger",
}, cli.BoolFlag{
Name: "color",
Usage: "Use color in the logs",
}, cli.BoolFlag{
Name: "debug",
},
}
subcmdLogging = cli.Command{
Name: "logging",
Usage: "Adjust logging commands",
Subcommands: []cli.Command{
{
Name: "pause",
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runPauseLogging,
}, {
Name: "resume",
Usage: "Resume logging",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runResumeLogging,
}, {
Name: "release-and-reopen",
Usage: "Cause Gitea to release and re-open files used for logging",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
},
},
Action: runReleaseReopenLogging,
}, {
Name: "remove",
Usage: "Remove a logger",
ArgsUsage: "[name] Name of logger to remove",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
}, cli.StringFlag{
Name: "group, g",
Usage: "Group to add logger to - will default to \"default\"",
},
},
Action: runRemoveLogger,
}, {
Name: "add",
Usage: "Add a logger",
Subcommands: []cli.Command{
{
Name: "console",
Usage: "Add a console logger",
Flags: append(defaultLoggingFlags,
cli.BoolFlag{
Name: "stderr",
Usage: "Output console logs to stderr - only relevant for console",
}),
Action: runAddConsoleLogger,
}, {
Name: "file",
Usage: "Add a file logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.StringFlag{
Name: "filename, f",
Usage: "Filename for the logger - this must be set.",
}, cli.BoolTFlag{
Name: "rotate, r",
Usage: "Rotate logs",
}, cli.Int64Flag{
Name: "max-size, s",
Usage: "Maximum size in bytes before rotation",
}, cli.BoolTFlag{
Name: "daily, d",
Usage: "Rotate logs daily",
}, cli.IntFlag{
Name: "max-days, D",
Usage: "Maximum number of daily logs to keep",
}, cli.BoolTFlag{
Name: "compress, z",
Usage: "Compress rotated logs",
}, cli.IntFlag{
Name: "compression-level, Z",
Usage: "Compression level to use",
},
}...),
Action: runAddFileLogger,
}, {
Name: "conn",
Usage: "Add a net conn logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.BoolFlag{
Name: "reconnect-on-message, R",
Usage: "Reconnect to host for every message",
}, cli.BoolFlag{
Name: "reconnect, r",
Usage: "Reconnect to host when connection is dropped",
}, cli.StringFlag{
Name: "protocol, P",
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)",
}, cli.StringFlag{
Name: "address, a",
Usage: "Host address and port to connect to (defaults to :7020)",
},
}...),
Action: runAddConnLogger,
}, {
Name: "smtp",
Usage: "Add an SMTP logger",
Flags: append(defaultLoggingFlags, []cli.Flag{
cli.StringFlag{
Name: "username, u",
Usage: "Mail server username",
}, cli.StringFlag{
Name: "password, P",
Usage: "Mail server password",
}, cli.StringFlag{
Name: "host, H",
Usage: "Mail server host (defaults to: 127.0.0.1:25)",
}, cli.StringSliceFlag{
Name: "send-to, s",
Usage: "Email address(es) to send to",
}, cli.StringFlag{
Name: "subject, S",
Usage: "Subject header of sent emails",
},
}...),
Action: runAddSMTPLogger,
},
},
}, {
Name: "log-sql",
Usage: "Set LogSQL",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "debug",
}, cli.BoolFlag{
Name: "off",
Usage: "Switch off SQL logging",
},
},
Action: runSetLogSQL,
},
},
}
)
func runRemoveLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
group := c.String("group")
if len(group) == 0 {
group = log.DEFAULT
}
name := c.Args().First()
ctx, cancel := installSignals()
defer cancel()
statusCode, msg := private.RemoveLogger(ctx, group, name)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runAddSMTPLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "smtp"
if c.IsSet("host") {
vals["host"] = c.String("host")
} else {
vals["host"] = "127.0.0.1:25"
}
if c.IsSet("username") {
vals["username"] = c.String("username")
}
if c.IsSet("password") {
vals["password"] = c.String("password")
}
if !c.IsSet("send-to") {
return fmt.Errorf("Some recipients must be provided")
}
vals["sendTos"] = c.StringSlice("send-to")
if c.IsSet("subject") {
vals["subject"] = c.String("subject")
} else {
vals["subject"] = "Diagnostic message from Gitea"
}
return commonAddLogger(c, mode, vals)
}
func runAddConnLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "conn"
vals["net"] = "tcp"
if c.IsSet("protocol") {
switch c.String("protocol") {
case "udp":
vals["net"] = "udp"
case "unix":
vals["net"] = "unix"
}
}
if c.IsSet("address") {
vals["address"] = c.String("address")
} else {
vals["address"] = ":7020"
}
if c.IsSet("reconnect") {
vals["reconnect"] = c.Bool("reconnect")
}
if c.IsSet("reconnect-on-message") {
vals["reconnectOnMsg"] = c.Bool("reconnect-on-message")
}
return commonAddLogger(c, mode, vals)
}
func runAddFileLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "file"
if c.IsSet("filename") {
vals["filename"] = c.String("filename")
} else {
return fmt.Errorf("filename must be set when creating a file logger")
}
if c.IsSet("rotate") {
vals["rotate"] = c.Bool("rotate")
}
if c.IsSet("max-size") {
vals["maxsize"] = c.Int64("max-size")
}
if c.IsSet("daily") {
vals["daily"] = c.Bool("daily")
}
if c.IsSet("max-days") {
vals["maxdays"] = c.Int("max-days")
}
if c.IsSet("compress") {
vals["compress"] = c.Bool("compress")
}
if c.IsSet("compression-level") {
vals["compressionLevel"] = c.Int("compression-level")
}
return commonAddLogger(c, mode, vals)
}
func runAddConsoleLogger(c *cli.Context) error {
setup("manager", c.Bool("debug"))
vals := map[string]interface{}{}
mode := "console"
if c.IsSet("stderr") && c.Bool("stderr") {
vals["stderr"] = c.Bool("stderr")
}
return commonAddLogger(c, mode, vals)
}
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
if len(c.String("level")) > 0 {
vals["level"] = log.FromString(c.String("level")).String()
}
if len(c.String("stacktrace-level")) > 0 {
vals["stacktraceLevel"] = log.FromString(c.String("stacktrace-level")).String()
}
if len(c.String("expression")) > 0 {
vals["expression"] = c.String("expression")
}
if len(c.String("prefix")) > 0 {
vals["prefix"] = c.String("prefix")
}
if len(c.String("flags")) > 0 {
vals["flags"] = log.FlagsFromString(c.String("flags"))
}
if c.IsSet("color") {
vals["colorize"] = c.Bool("color")
}
group := "default"
if c.IsSet("group") {
group = c.String("group")
}
name := mode
if c.IsSet("name") {
name = c.String("name")
}
ctx, cancel := installSignals()
defer cancel()
statusCode, msg := private.AddLogger(ctx, group, name, mode, vals)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runPauseLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.PauseLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runResumeLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.ResumeLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runReleaseReopenLogging(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.ReleaseReopenLogging(ctx)
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}
func runSetLogSQL(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setup("manager", c.Bool("debug"))
statusCode, msg := private.SetLogSQL(ctx, !c.Bool("off"))
switch statusCode {
case http.StatusInternalServerError:
return fail("InternalServerError", msg)
}
fmt.Fprintln(os.Stdout, msg)
return nil
}

View File

@@ -1,5 +1,6 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -33,7 +34,7 @@ func runMigrate(ctx *cli.Context) error {
log.Info("AppPath: %s", setting.AppPath)
log.Info("AppWorkPath: %s", setting.AppWorkPath)
log.Info("Custom path: %s", setting.CustomPath)
log.Info("Log path: %s", setting.Log.RootPath)
log.Info("Log path: %s", setting.LogRootPath)
log.Info("Configuration file: %s", setting.CustomConf)
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -8,14 +9,12 @@ import (
"fmt"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/migrations"
packages_model "code.gitea.io/gitea/models/packages"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
@@ -26,13 +25,13 @@ import (
var CmdMigrateStorage = cli.Command{
Name: "migrate-storage",
Usage: "Migrate the storage",
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage",
Description: "This is a command for migrating storage.",
Action: runMigrateStorage,
Flags: []cli.Flag{
cli.StringFlag{
Name: "type, t",
Value: "",
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages'",
Usage: "Kinds of files to migrate, currently only 'attachments' is supported",
},
cli.StringFlag{
Name: "storage, s",
@@ -81,50 +80,34 @@ var CmdMigrateStorage = cli.Command{
},
}
func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, attach *repo_model.Attachment) error {
func migrateAttachments(dstStorage storage.ObjectStorage) error {
return repo_model.IterateAttachment(func(attach *repo_model.Attachment) error {
_, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath())
return err
})
}
func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, mo *git_model.LFSMetaObject) error {
func migrateLFS(dstStorage storage.ObjectStorage) error {
return models.IterateLFS(func(mo *models.LFSMetaObject) error {
_, err := storage.Copy(dstStorage, mo.RelativePath(), storage.LFS, mo.RelativePath())
return err
})
}
func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, user *user_model.User) error {
func migrateAvatars(dstStorage storage.ObjectStorage) error {
return user_model.IterateUser(func(user *user_model.User) error {
_, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath())
return err
})
}
func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, repo *repo_model.Repository) error {
func migrateRepoAvatars(dstStorage storage.ObjectStorage) error {
return repo_model.IterateRepository(func(repo *repo_model.Repository) error {
_, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath())
return err
})
}
func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, archiver *repo_model.RepoArchiver) error {
p := archiver.RelativePath()
_, err := storage.Copy(dstStorage, p, storage.RepoArchives, p)
return err
})
}
func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) error {
return db.Iterate(ctx, nil, func(ctx context.Context, pb *packages_model.PackageBlob) error {
p := packages_module.KeyToRelativePath(packages_module.BlobHash256Key(pb.HashSHA256))
_, err := storage.Copy(dstStorage, p, storage.Packages, p)
return err
})
}
func runMigrateStorage(ctx *cli.Context) error {
stdCtx, cancel := installSignals()
defer cancel()
@@ -136,7 +119,7 @@ func runMigrateStorage(ctx *cli.Context) error {
log.Info("AppPath: %s", setting.AppPath)
log.Info("AppWorkPath: %s", setting.AppWorkPath)
log.Info("Custom path: %s", setting.CustomPath)
log.Info("Log path: %s", setting.Log.RootPath)
log.Info("Log path: %s", setting.LogRootPath)
log.Info("Configuration file: %s", setting.CustomConf)
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {
@@ -144,6 +127,8 @@ func runMigrateStorage(ctx *cli.Context) error {
return err
}
goCtx := context.Background()
if err := storage.Init(); err != nil {
return err
}
@@ -160,13 +145,13 @@ func runMigrateStorage(ctx *cli.Context) error {
return nil
}
dstStorage, err = storage.NewLocalStorage(
stdCtx,
goCtx,
storage.LocalStorageConfig{
Path: p,
})
case string(storage.MinioStorageType):
dstStorage, err = storage.NewMinioStorage(
stdCtx,
goCtx,
storage.MinioStorageConfig{
Endpoint: ctx.String("minio-endpoint"),
AccessKeyID: ctx.String("minio-access-key-id"),
@@ -177,29 +162,35 @@ func runMigrateStorage(ctx *cli.Context) error {
UseSSL: ctx.Bool("minio-use-ssl"),
})
default:
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))
return fmt.Errorf("Unsupported storage type: %s", ctx.String("storage"))
}
if err != nil {
return err
}
migratedMethods := map[string]func(context.Context, storage.ObjectStorage) error{
"attachments": migrateAttachments,
"lfs": migrateLFS,
"avatars": migrateAvatars,
"repo-avatars": migrateRepoAvatars,
"repo-archivers": migrateRepoArchivers,
"packages": migratePackages,
}
tp := strings.ToLower(ctx.String("type"))
if m, ok := migratedMethods[tp]; ok {
if err := m(stdCtx, dstStorage); err != nil {
switch tp {
case "attachments":
if err := migrateAttachments(dstStorage); err != nil {
return err
}
log.Info("%s files have successfully been copied to the new storage.", tp)
return nil
case "lfs":
if err := migrateLFS(dstStorage); err != nil {
return err
}
case "avatars":
if err := migrateAvatars(dstStorage); err != nil {
return err
}
case "repo-avatars":
if err := migrateRepoAvatars(dstStorage); err != nil {
return err
}
default:
return fmt.Errorf("Unsupported storage: %s", ctx.String("type"))
}
return fmt.Errorf("unsupported storage: %s", ctx.String("type"))
log.Warn("All files have been copied to the new placement but old files are still on the original placement.")
return nil
}

View File

@@ -1,73 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"os"
"strings"
"testing"
"code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/storage"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/stretchr/testify/assert"
)
func TestMigratePackages(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
buf, err := packages_module.CreateHashedBufferFromReader(strings.NewReader(content), 1024)
assert.NoError(t, err)
defer buf.Close()
v, f, err := packages_service.CreatePackageAndAddFile(&packages_service.PackageCreationInfo{
PackageInfo: packages_service.PackageInfo{
Owner: creator,
PackageType: packages.TypeGeneric,
Name: "test",
Version: "1.0.0",
},
Creator: creator,
SemverCompatible: true,
VersionProperties: map[string]string{},
}, &packages_service.PackageFileCreationInfo{
PackageFileInfo: packages_service.PackageFileInfo{
Filename: "a.go",
},
Creator: creator,
Data: buf,
IsLead: true,
})
assert.NoError(t, err)
assert.NotNil(t, v)
assert.NotNil(t, f)
ctx := context.Background()
p := t.TempDir()
dstStorage, err := storage.NewLocalStorage(
ctx,
storage.LocalStorageConfig{
Path: p,
})
assert.NoError(t, err)
err = migratePackages(ctx, dstStorage)
assert.NoError(t, err)
entries, err := os.ReadDir(p)
assert.NoError(t, err)
assert.EqualValues(t, 2, len(entries))
assert.EqualValues(t, "01", entries[0].Name())
assert.EqualValues(t, "tmp", entries[1].Name())
}

View File

@@ -1,12 +1,12 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"errors"
"net/http"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
@@ -43,10 +43,6 @@ var CmdRestoreRepository = cli.Command{
Usage: `Which items will be restored, one or more units should be separated as comma.
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
},
cli.BoolFlag{
Name: "validation",
Usage: "Sanity check the content of the files before trying to load them",
},
},
}
@@ -54,19 +50,14 @@ func runRestoreRepository(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
var units []string
if s := c.String("units"); s != "" {
units = strings.Split(s, ",")
}
setting.LoadFromExisting()
statusCode, errStr := private.RestoreRepo(
ctx,
c.String("repo_dir"),
c.String("owner_name"),
c.String("repo_name"),
units,
c.Bool("validation"),
c.StringSlice("units"),
)
if statusCode == http.StatusOK {
return nil

View File

@@ -1,11 +1,11 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
import (
"context"
"fmt"
"net/http"
"net/url"
@@ -16,16 +16,14 @@ import (
"strings"
"time"
"code.gitea.io/gitea/models"
asymkey_model "code.gitea.io/gitea/models/asymkey"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/pprof"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/process"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/lfs"
@@ -42,7 +40,7 @@ const (
var CmdServ = cli.Command{
Name: "serv",
Usage: "This command should only be called by SSH shell",
Description: "Serv provides access auth for repositories",
Description: `Serv provide access auth for repositories`,
Action: runServ,
Flags: []cli.Flag{
cli.BoolFlag{
@@ -61,26 +59,10 @@ func setup(logPath string, debug bool) {
} else {
_ = log.NewLogger(1000, "console", "console", `{"level":"fatal","stacktracelevel":"NONE","stderr":true}`)
}
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadFromExisting()
if debug {
setting.RunMode = "dev"
}
// 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) {
_ = fail("Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
} else {
_ = fail("Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
}
return
}
if err := git.InitSimple(context.Background()); err != nil {
_ = fail("Failed to init git", "Failed to init git, err: %v", err)
}
}
var (
@@ -96,12 +78,12 @@ var (
func fail(userMessage, logMessage string, args ...interface{}) error {
// There appears to be a chance to cause a zombie process and failure to read the Exit status
// if nothing is outputted on stdout.
_, _ = fmt.Fprintln(os.Stdout, "")
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
fmt.Fprintln(os.Stdout, "")
fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
if len(logMessage) > 0 {
if !setting.IsProd {
_, _ = fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
}
}
ctx, cancel := installSignals()
@@ -253,16 +235,28 @@ func runServ(c *cli.Context) error {
}
return fail("Internal Server Error", "%s", err.Error())
}
os.Setenv(models.EnvRepoIsWiki, strconv.FormatBool(results.IsWiki))
os.Setenv(models.EnvRepoName, results.RepoName)
os.Setenv(models.EnvRepoUsername, results.OwnerName)
os.Setenv(models.EnvPusherName, results.UserName)
os.Setenv(models.EnvPusherEmail, results.UserEmail)
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.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
os.Setenv(models.EnvAppURL, setting.AppURL)
// LFS token authentication
//LFS token authentication
if verb == lfsAuthenticateVerb {
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
now := time.Now()
claims := lfs.Claims{
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(now.Add(setting.LFS.HTTPAuthExpiry)),
NotBefore: jwt.NewNumericDate(now),
// FIXME: we need to migrate to RegisteredClaims
StandardClaims: jwt.StandardClaims{ // nolint
ExpiresAt: now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
NotBefore: now.Unix(),
},
RepoID: results.RepoID,
Op: lfsVerb,
@@ -276,7 +270,7 @@ func runServ(c *cli.Context) error {
return fail("Internal error", "Failed to sign JWT token: %v", err)
}
tokenAuthentication := &git_model.LFSTokenResponse{
tokenAuthentication := &models.LFSTokenResponse{
Header: make(map[string]string),
Href: url,
}
@@ -303,29 +297,10 @@ func runServ(c *cli.Context) error {
gitcmd = exec.CommandContext(ctx, verb, repoPath)
}
process.SetSysProcAttribute(gitcmd)
gitcmd.Dir = setting.RepoRootPath
gitcmd.Stdout = os.Stdout
gitcmd.Stdin = os.Stdin
gitcmd.Stderr = os.Stderr
gitcmd.Env = append(gitcmd.Env, os.Environ()...)
gitcmd.Env = append(gitcmd.Env,
repo_module.EnvRepoIsWiki+"="+strconv.FormatBool(results.IsWiki),
repo_module.EnvRepoName+"="+results.RepoName,
repo_module.EnvRepoUsername+"="+results.OwnerName,
repo_module.EnvPusherName+"="+results.UserName,
repo_module.EnvPusherEmail+"="+results.UserEmail,
repo_module.EnvPusherID+"="+strconv.FormatInt(results.UserID, 10),
repo_module.EnvRepoID+"="+strconv.FormatInt(results.RepoID, 10),
repo_module.EnvPRID+"="+fmt.Sprintf("%d", 0),
repo_module.EnvDeployKeyID+"="+fmt.Sprintf("%d", results.DeployKeyID),
repo_module.EnvKeyID+"="+fmt.Sprintf("%d", results.KeyID),
repo_module.EnvAppURL+"="+setting.AppURL,
)
// to avoid breaking, here only use the minimal environment variables for the "gitea serv" command.
// it could be re-considered whether to use the same git.CommonGitCmdEnvs() as "git" command later.
gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...)
if err = gitcmd.Run(); err != nil {
return fail("Internal error", "Failed to execute git command: %v", err)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -15,12 +16,10 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers"
"code.gitea.io/gitea/routers/install"
"github.com/felixge/fgprof"
"github.com/urfave/cli"
ini "gopkg.in/ini.v1"
)
@@ -60,9 +59,6 @@ and it takes care of all the other things for you`,
}
func runHTTPRedirector() {
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Web: HTTP Redirector", process.SystemProcessType, true)
defer finished()
source := fmt.Sprintf("%s:%s", setting.HTTPAddr, setting.PortToRedirect)
dest := strings.TrimSuffix(setting.AppURL, "/")
log.Info("Redirecting: %s to %s", source, dest)
@@ -75,7 +71,8 @@ func runHTTPRedirector() {
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
})
err := runHTTP("tcp", source, "HTTP Redirector", handler, setting.RedirectorUseProxyProtocol)
var err = runHTTP("tcp", source, "HTTP Redirector", handler)
if err != nil {
log.Fatal("Failed to start port redirection: %v", err)
}
@@ -91,7 +88,7 @@ func runWeb(ctx *cli.Context) error {
}
defer func() {
if panicked := recover(); panicked != nil {
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
log.Fatal("PANIC: %v\n%s", panicked, string(log.Stack(2)))
}
}()
@@ -125,10 +122,8 @@ func runWeb(ctx *cli.Context) error {
return err
}
}
installCtx, cancel := context.WithCancel(graceful.GetManager().HammerContext())
c := install.Routes(installCtx)
c := install.Routes()
err := listen(c, false)
cancel()
if err != nil {
log.Critical("Unable to open listener for installer. Is Gitea already running?")
graceful.GetManager().DoGracefulShutdown()
@@ -147,19 +142,14 @@ func runWeb(ctx *cli.Context) error {
if setting.EnablePprof {
go func() {
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
_, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true)
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it.
log.Info("Starting pprof server on localhost:6060")
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
finished()
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
}()
}
log.Info("Global init")
// Perform global initialization
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.LoadFromExisting()
routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
// We check that AppDataPath exists here (it should have been created during installation)
@@ -177,7 +167,7 @@ func runWeb(ctx *cli.Context) error {
}
// Set up Chi routes
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
c := routers.NormalRoutes()
err := listen(c, true)
<-graceful.GetManager().Done()
log.Info("PID: %d Gitea Web Finished", os.Getpid())
@@ -203,7 +193,7 @@ func setPort(port string) error {
defaultLocalURL += ":" + setting.HTTPPort + "/"
// Save LOCAL_ROOT_URL if port changed
setting.CreateOrAppendToCustomConf("server.LOCAL_ROOT_URL", func(cfg *ini.File) {
setting.CreateOrAppendToCustomConf(func(cfg *ini.File) {
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
})
}
@@ -215,8 +205,6 @@ func listen(m http.Handler, handleRedirector bool) error {
if setting.Protocol != setting.HTTPUnix && setting.Protocol != setting.FCGIUnix {
listenAddr = net.JoinHostPort(listenAddr, setting.HTTPPort)
}
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Web: Gitea Server", process.SystemProcessType, true)
defer finished()
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
// This can be useful for users, many users do wrong to their config and get strange behaviors behind a reverse-proxy.
// A user may fix the configuration mistake when he sees this log.
@@ -233,10 +221,10 @@ func listen(m http.Handler, handleRedirector bool) error {
if handleRedirector {
NoHTTPRedirector()
}
err = runHTTP("tcp", listenAddr, "Web", m, setting.UseProxyProtocol)
err = runHTTP("tcp", listenAddr, "Web", m)
case setting.HTTPS:
if setting.EnableAcme {
err = runACME(listenAddr, m)
if setting.EnableLetsEncrypt {
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, m)
break
}
if handleRedirector {
@@ -246,25 +234,26 @@ func listen(m http.Handler, handleRedirector bool) error {
NoHTTPRedirector()
}
}
err = runHTTPS("tcp", listenAddr, "Web", setting.CertFile, setting.KeyFile, m, setting.UseProxyProtocol, setting.ProxyProtocolTLSBridging)
err = runHTTPS("tcp", listenAddr, "Web", setting.CertFile, setting.KeyFile, m)
case setting.FCGI:
if handleRedirector {
NoHTTPRedirector()
}
err = runFCGI("tcp", listenAddr, "FCGI Web", m, setting.UseProxyProtocol)
err = runFCGI("tcp", listenAddr, "FCGI Web", m)
case setting.HTTPUnix:
if handleRedirector {
NoHTTPRedirector()
}
err = runHTTP("unix", listenAddr, "Web", m, setting.UseProxyProtocol)
err = runHTTP("unix", listenAddr, "Web", m)
case setting.FCGIUnix:
if handleRedirector {
NoHTTPRedirector()
}
err = runFCGI("unix", listenAddr, "Web", m, setting.UseProxyProtocol)
err = runFCGI("unix", listenAddr, "Web", m)
default:
log.Fatal("Invalid protocol: %s", setting.Protocol)
}
if err != nil {
log.Critical("Failed to start server: %v", err)
}

View File

@@ -1,135 +0,0 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"crypto/x509"
"encoding/pem"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"github.com/caddyserver/certmagic"
)
func getCARoot(path string) (*x509.CertPool, error) {
r, err := os.ReadFile(path)
if err != nil {
return nil, err
}
block, _ := pem.Decode(r)
if block == nil {
return nil, fmt.Errorf("no PEM found in the file %s", path)
}
caRoot, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
certPool.AddCert(caRoot)
return certPool, nil
}
func runACME(listenAddr string, m http.Handler) error {
// If HTTP Challenge enabled, needs to be serving on port 80. For TLSALPN needs 443.
// Due to docker port mapping this can't be checked programmatically
// TODO: these are placeholders until we add options for each in settings with appropriate warning
enableHTTPChallenge := true
enableTLSALPNChallenge := true
altHTTPPort := 0
altTLSALPNPort := 0
if p, err := strconv.Atoi(setting.PortToRedirect); err == nil {
altHTTPPort = p
}
if p, err := strconv.Atoi(setting.HTTPPort); err == nil {
altTLSALPNPort = p
}
magic := certmagic.NewDefault()
magic.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
// Try to use private CA root if provided, otherwise defaults to system's trust
var certPool *x509.CertPool
if setting.AcmeCARoot != "" {
var err error
certPool, err = getCARoot(setting.AcmeCARoot)
if err != nil {
log.Warn("Failed to parse CA Root certificate, using default CA trust: %v", err)
}
}
myACME := certmagic.NewACMEIssuer(magic, certmagic.ACMEIssuer{
CA: setting.AcmeURL,
TrustedRoots: certPool,
Email: setting.AcmeEmail,
Agreed: setting.AcmeTOS,
DisableHTTPChallenge: !enableHTTPChallenge,
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
ListenHost: setting.HTTPAddr,
AltTLSALPNPort: altTLSALPNPort,
AltHTTPPort: altHTTPPort,
})
magic.Issuers = []certmagic.Issuer{myACME}
// this obtains certificates or renews them if necessary
err := magic.ManageSync(graceful.GetManager().HammerContext(), []string{setting.Domain})
if err != nil {
return err
}
tlsConfig := magic.TLSConfig()
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "h2")
if version := toTLSVersion(setting.SSLMinimumVersion); version != 0 {
tlsConfig.MinVersion = version
}
if version := toTLSVersion(setting.SSLMaximumVersion); version != 0 {
tlsConfig.MaxVersion = version
}
// Set curve preferences
if curves := toCurvePreferences(setting.SSLCurvePreferences); len(curves) > 0 {
tlsConfig.CurvePreferences = curves
}
// Set cipher suites
if ciphers := toTLSCiphers(setting.SSLCipherSuites); len(ciphers) > 0 {
tlsConfig.CipherSuites = ciphers
}
if enableHTTPChallenge {
go func() {
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Web: ACME HTTP challenge server", process.SystemProcessType, true)
defer finished()
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
// all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
err := runHTTP("tcp", setting.HTTPAddr+":"+setting.PortToRedirect, "Let's Encrypt HTTP Challenge", myACME.HTTPChallengeHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)), setting.RedirectorUseProxyProtocol)
if err != nil {
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
}
}()
}
return runHTTPSWithTLSConfig("tcp", listenAddr, "Web", tlsConfig, m, setting.UseProxyProtocol, setting.ProxyProtocolTLSBridging)
}
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" && r.Method != "HEAD" {
http.Error(w, "Use HTTPS", http.StatusBadRequest)
return
}
// Remove the trailing slash at the end of setting.AppURL, the request
// URI always contains a leading slash, which would result in a double
// slash
target := strings.TrimSuffix(setting.AppURL, "/") + r.URL.RequestURI()
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -14,8 +15,8 @@ import (
"code.gitea.io/gitea/modules/setting"
)
func runHTTP(network, listenAddr, name string, m http.Handler, useProxyProtocol bool) error {
return graceful.HTTPListenAndServe(network, listenAddr, name, m, useProxyProtocol)
func runHTTP(network, listenAddr, name string, m http.Handler) error {
return graceful.HTTPListenAndServe(network, listenAddr, name, m)
}
// NoHTTPRedirector tells our cleanup routine that we will not be using a fallback http redirector
@@ -35,7 +36,7 @@ func NoInstallListener() {
graceful.GetManager().InformCleanup()
}
func runFCGI(network, listenAddr, name string, m http.Handler, useProxyProtocol bool) error {
func runFCGI(network, listenAddr, name string, m http.Handler) error {
// This needs to handle stdin as fcgi point
fcgiServer := graceful.NewServer(network, listenAddr, name)
@@ -46,7 +47,7 @@ func runFCGI(network, listenAddr, name string, m http.Handler, useProxyProtocol
}
m.ServeHTTP(resp, req)
}))
}, useProxyProtocol)
})
if err != nil {
log.Fatal("Failed to start FCGI main server: %v", err)
}

View File

@@ -1,5 +1,6 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
@@ -128,14 +129,14 @@ var (
defaultCiphersChaChaFirst = append(defaultCiphersChaCha, defaultCiphersAES...)
)
// runHTTPS listens on the provided network address and then calls
// runHTTPs listens on the provided network address and then calls
// Serve to handle requests on incoming TLS connections.
//
// Filenames containing a certificate and matching private key for the server must
// be provided. If the certificate is signed by a certificate authority, the
// certFile should be the concatenation of the server's certificate followed by the
// CA's certificate.
func runHTTPS(network, listenAddr, name, certFile, keyFile string, m http.Handler, useProxyProtocol, proxyProtocolTLSBridging bool) error {
func runHTTPS(network, listenAddr, name, certFile, keyFile string, m http.Handler) error {
tlsConfig := &tls.Config{}
if tlsConfig.NextProtos == nil {
tlsConfig.NextProtos = []string{"h2", "http/1.1"}
@@ -183,9 +184,9 @@ func runHTTPS(network, listenAddr, name, certFile, keyFile string, m http.Handle
return err
}
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m, useProxyProtocol, proxyProtocolTLSBridging)
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m)
}
func runHTTPSWithTLSConfig(network, listenAddr, name string, tlsConfig *tls.Config, m http.Handler, useProxyProtocol, proxyProtocolTLSBridging bool) error {
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m, useProxyProtocol, proxyProtocolTLSBridging)
func runHTTPSWithTLSConfig(network, listenAddr, name string, tlsConfig *tls.Config, m http.Handler) error {
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, name, tlsConfig, m)
}

100
cmd/web_letsencrypt.go Normal file
View File

@@ -0,0 +1,100 @@
// Copyright 2020 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 cmd
import (
"net/http"
"strconv"
"strings"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/caddyserver/certmagic"
)
func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) error {
// If HTTP Challenge enabled, needs to be serving on port 80. For TLSALPN needs 443.
// Due to docker port mapping this can't be checked programmatically
// TODO: these are placeholders until we add options for each in settings with appropriate warning
enableHTTPChallenge := true
enableTLSALPNChallenge := true
altHTTPPort := 0
altTLSALPNPort := 0
if p, err := strconv.Atoi(setting.PortToRedirect); err == nil {
altHTTPPort = p
}
if p, err := strconv.Atoi(setting.HTTPPort); err == nil {
altTLSALPNPort = p
}
magic := certmagic.NewDefault()
magic.Storage = &certmagic.FileStorage{Path: directory}
myACME := certmagic.NewACMEManager(magic, certmagic.ACMEManager{
Email: email,
Agreed: setting.LetsEncryptTOS,
DisableHTTPChallenge: !enableHTTPChallenge,
DisableTLSALPNChallenge: !enableTLSALPNChallenge,
ListenHost: setting.HTTPAddr,
AltTLSALPNPort: altTLSALPNPort,
AltHTTPPort: altHTTPPort,
})
magic.Issuers = []certmagic.Issuer{myACME}
// this obtains certificates or renews them if necessary
err := magic.ManageSync(graceful.GetManager().HammerContext(), []string{domain})
if err != nil {
return err
}
tlsConfig := magic.TLSConfig()
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "h2")
if version := toTLSVersion(setting.SSLMinimumVersion); version != 0 {
tlsConfig.MinVersion = version
}
if version := toTLSVersion(setting.SSLMaximumVersion); version != 0 {
tlsConfig.MaxVersion = version
}
// Set curve preferences
if curves := toCurvePreferences(setting.SSLCurvePreferences); len(curves) > 0 {
tlsConfig.CurvePreferences = curves
}
// Set cipher suites
if ciphers := toTLSCiphers(setting.SSLCipherSuites); len(ciphers) > 0 {
tlsConfig.CipherSuites = ciphers
}
if enableHTTPChallenge {
go func() {
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
// all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
var err = runHTTP("tcp", setting.HTTPAddr+":"+setting.PortToRedirect, "Let's Encrypt HTTP Challenge", myACME.HTTPChallengeHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)))
if err != nil {
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
}
}()
}
return runHTTPSWithTLSConfig("tcp", listenAddr, "Web", tlsConfig, m)
}
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" && r.Method != "HEAD" {
http.Error(w, "Use HTTPS", http.StatusBadRequest)
return
}
// Remove the trailing slash at the end of setting.AppURL, the request
// URI always contains a leading slash, which would result in a double
// slash
target := strings.TrimSuffix(setting.AppURL, "/") + r.URL.RequestURI()
http.Redirect(w, r, target, http.StatusFound)
}

View File

@@ -1,17 +0,0 @@
Bash and Zsh completion
=======================
From within the gitea root run:
```bash
source contrib/autocompletion/bash_autocomplete
```
or for zsh run:
```bash
source contrib/autocompletion/zsh_autocomplete
```
These scripts will check if gitea is on the path and if so add autocompletion for `gitea`. Or if not autocompletion will work for `./gitea`.
If gitea has been installed as a different program pass in the `PROG` environment variable to set the correct program name.

View File

@@ -1,30 +0,0 @@
#! /bin/bash
# Heavily inspired by https://github.com/urfave/cli
_cli_bash_autocomplete() {
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
local cur opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ "$cur" == "-"* ]]; then
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
else
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
if [ -z "$PROG" ] && [ ! "$(command -v gitea &> /dev/null)" ] ; then
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete gitea
elif [ -z "$PROG" ]; then
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete ./gitea
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete "$PWD/gitea"
else
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete "$PROG"
unset PROG
fi

View File

@@ -1,30 +0,0 @@
#compdef ${PROG:=gitea}
# Heavily inspired by https://github.com/urfave/cli
_cli_zsh_autocomplete() {
local -a opts
local cur
cur=${words[-1]}
if [[ "$cur" == "-"* ]]; then
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
else
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}")
fi
if [[ "${opts[1]}" != "" ]]; then
_describe 'values' opts
else
_files
fi
return
}
if [ -z $PROG ] ; then
compdef _cli_zsh_autocomplete gitea
else
compdef _cli_zsh_autocomplete $(basename $PROG)
fi

View File

@@ -1,41 +0,0 @@
`backport`
==========
`backport` is a command to help create backports of PRs. It backports a
provided PR from main on to a released version.
It will create a backport branch, cherry-pick the PR's merge commit, adjust
the commit message and then push this back up to your fork's remote.
The default version will read from `docs/config.yml`. You can override this
using the option `--version`.
The upstream branches will be fetched, using the remote `origin`. This can
be overrided using `--upstream`, and fetching can be avoided using
`--no-fetch`.
By default the branch created will be called `backport-$PR-$VERSION`. You
can override this using the option `--backport-branch`. This branch will
be created from `--release-branch` which is `release/$(VERSION)`
by default and will be pulled from `$(UPSTREAM)`.
The merge-commit as determined by the github API will be used as the SHA to
cherry-pick. You can override this using `--cherry-pick`.
The commit message will be amended to add the `Backport` header.
`--no-amend-message` can be set to stop this from happening.
If cherry-pick is successful the backported branch will be pushed up to your
fork using your remote. These will be determined using `git remote -v`. You
can set your fork name using `--fork-user` and your remote name using
`--remote`. You can avoid pushing using `--no-push`.
If the push is successful, `xdg-open` will be called to open a backport url.
You can stop this using `--no-xdg-open`.
Installation
============
```bash
go install contrib/backport/backport.go
```

View File

@@ -1,473 +0,0 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/exec"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
"github.com/google/go-github/v45/github"
"github.com/urfave/cli"
"gopkg.in/yaml.v3"
)
const defaultVersion = "v1.18" // to backport to
func main() {
app := cli.NewApp()
app.Name = "backport"
app.Usage = "Backport provided PR-number on to the current or previous released version"
app.Description = `Backport will look-up the PR in Gitea's git log and attempt to cherry-pick it on the current version`
app.ArgsUsage = "<PR-to-backport>"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "version",
Usage: "Version branch to backport on to",
},
cli.StringFlag{
Name: "upstream",
Value: "origin",
Usage: "Upstream remote for the Gitea upstream",
},
cli.StringFlag{
Name: "release-branch",
Value: "",
Usage: "Release branch to backport on. Will default to release/<version>",
},
cli.StringFlag{
Name: "cherry-pick",
Usage: "SHA to cherry-pick as backport",
},
cli.StringFlag{
Name: "backport-branch",
Usage: "Backport branch to backport on to (default: backport-<pr>-<version>",
},
cli.StringFlag{
Name: "remote",
Value: "",
Usage: "Remote for your fork of the Gitea upstream",
},
cli.StringFlag{
Name: "fork-user",
Value: "",
Usage: "Forked user name on Github",
},
cli.BoolFlag{
Name: "no-fetch",
Usage: "Set this flag to prevent fetch of remote branches",
},
cli.BoolFlag{
Name: "no-amend-message",
Usage: "Set this flag to prevent automatic amendment of the commit message",
},
cli.BoolFlag{
Name: "no-push",
Usage: "Set this flag to prevent pushing the backport up to your fork",
},
cli.BoolFlag{
Name: "no-xdg-open",
Usage: "Set this flag to not use xdg-open to open the PR URL",
},
cli.BoolFlag{
Name: "continue",
Usage: "Set this flag to continue from a git cherry-pick that has broken",
},
}
cli.AppHelpTemplate = `NAME:
{{.Name}} - {{.Usage}}
USAGE:
{{.HelpName}} {{if .VisibleFlags}}[options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
{{if len .Authors}}
AUTHOR:
{{range .Authors}}{{ . }}{{end}}
{{end}}{{if .Commands}}
OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}
`
app.Action = runBackport
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "Unable to backport: %v\n", err)
}
}
func runBackport(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
continuing := c.Bool("continue")
var pr string
version := c.String("version")
if version == "" && continuing {
// determine version from current branch name
var err error
pr, version, err = readCurrentBranch(ctx)
if err != nil {
return err
}
}
if version == "" {
version = readVersion()
}
if version == "" {
version = defaultVersion
}
upstream := c.String("upstream")
if upstream == "" {
upstream = "origin"
}
forkUser := c.String("fork-user")
remote := c.String("remote")
if remote == "" && !c.Bool("--no-push") {
var err error
remote, forkUser, err = determineRemote(ctx, forkUser)
if err != nil {
return err
}
}
upstreamReleaseBranch := c.String("release-branch")
if upstreamReleaseBranch == "" {
upstreamReleaseBranch = path.Join("release", version)
}
localReleaseBranch := path.Join(upstream, upstreamReleaseBranch)
args := c.Args()
if len(args) == 0 && pr == "" {
return fmt.Errorf("no PR number provided\nProvide a PR number to backport")
} else if len(args) != 1 && pr == "" {
return fmt.Errorf("multiple PRs provided %v\nOnly a single PR can be backported at a time", args)
}
if pr == "" {
pr = args[0]
}
backportBranch := c.String("backport-branch")
if backportBranch == "" {
backportBranch = "backport-" + pr + "-" + version
}
fmt.Printf("* Backporting %s to %s as %s\n", pr, localReleaseBranch, backportBranch)
sha := c.String("cherry-pick")
if sha == "" {
var err error
sha, err = determineSHAforPR(ctx, pr)
if err != nil {
return err
}
}
if sha == "" {
return fmt.Errorf("unable to determine sha for cherry-pick of %s", pr)
}
if !c.Bool("no-fetch") {
if err := fetchRemoteAndMain(ctx, upstream, upstreamReleaseBranch); err != nil {
return err
}
}
if !continuing {
if err := checkoutBackportBranch(ctx, backportBranch, localReleaseBranch); err != nil {
return err
}
}
if err := cherrypick(ctx, sha); err != nil {
return err
}
if !c.Bool("no-amend-message") {
if err := amendCommit(ctx, pr); err != nil {
return err
}
}
if !c.Bool("no-push") {
url := "https://github.com/go-gitea/gitea/compare/" + upstreamReleaseBranch + "..." + forkUser + ":" + backportBranch
if err := gitPushUp(ctx, remote, backportBranch); err != nil {
return err
}
if !c.Bool("no-xdg-open") {
if err := xdgOpen(ctx, url); err != nil {
return err
}
} else {
fmt.Printf("* Navigate to %s to open PR\n", url)
}
}
return nil
}
func xdgOpen(ctx context.Context, url string) error {
fmt.Printf("* `xdg-open %s`\n", url)
out, err := exec.CommandContext(ctx, "xdg-open", url).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "%s", string(out))
return fmt.Errorf("unable to xdg-open to %s: %w", url, err)
}
return nil
}
func gitPushUp(ctx context.Context, remote, backportBranch string) error {
fmt.Printf("* `git push -u %s %s`\n", remote, backportBranch)
out, err := exec.CommandContext(ctx, "git", "push", "-u", remote, backportBranch).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "%s", string(out))
return fmt.Errorf("unable to push up to %s: %w", remote, err)
}
return nil
}
func amendCommit(ctx context.Context, pr string) error {
fmt.Printf("* Amending commit to prepend `Backport #%s` to body\n", pr)
out, err := exec.CommandContext(ctx, "git", "log", "-1", "--pretty=format:%B").Output()
if err != nil {
fmt.Fprintf(os.Stderr, "%s", string(out))
return fmt.Errorf("unable to get last log message: %w", err)
}
parts := strings.SplitN(string(out), "\n", 2)
if len(parts) != 2 {
return fmt.Errorf("unable to interpret log message:\n%s", string(out))
}
subject, body := parts[0], parts[1]
if !strings.HasSuffix(subject, " (#"+pr+")") {
subject = subject + " (#" + pr + ")"
}
out, err = exec.CommandContext(ctx, "git", "commit", "--amend", "-m", subject+"\n\nBackport #"+pr+"\n"+body).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "%s", string(out))
return fmt.Errorf("unable to amend last log message: %w", err)
}
return nil
}
func cherrypick(ctx context.Context, sha string) error {
// Check if a CHERRY_PICK_HEAD exists
if _, err := os.Stat(".git/CHERRY_PICK_HEAD"); err == nil {
// Assume that we are in the middle of cherry-pick - continue it
fmt.Println("* Attempting git cherry-pick --continue")
out, err := exec.CommandContext(ctx, "git", "cherry-pick", "--continue").Output()
if err != nil {
fmt.Fprintf(os.Stderr, "git cherry-pick --continue failed:\n%s\n", string(out))
return fmt.Errorf("unable to continue cherry-pick: %w", err)
}
return nil
}
fmt.Printf("* Attempting git cherry-pick %s\n", sha)
out, err := exec.CommandContext(ctx, "git", "cherry-pick", sha).Output()
if err != nil {
fmt.Fprintf(os.Stderr, "git cherry-pick %s failed:\n%s\n", sha, string(out))
return fmt.Errorf("git cherry-pick %s failed: %w", sha, err)
}
return nil
}
func checkoutBackportBranch(ctx context.Context, backportBranch, releaseBranch string) error {
out, err := exec.CommandContext(ctx, "git", "branch", "--show-current").Output()
if err != nil {
return fmt.Errorf("unable to check current branch %w", err)
}
currentBranch := strings.TrimSpace(string(out))
fmt.Printf("* Current branch is %s\n", currentBranch)
if currentBranch == backportBranch {
fmt.Printf("* Current branch is %s - not checking out\n", currentBranch)
return nil
}
if _, err := exec.CommandContext(ctx, "git", "rev-list", "-1", backportBranch).Output(); err == nil {
fmt.Printf("* Branch %s already exists. Checking it out...\n", backportBranch)
return exec.CommandContext(ctx, "git", "checkout", "-f", backportBranch).Run()
}
fmt.Printf("* `git checkout -b %s %s`\n", backportBranch, releaseBranch)
return exec.CommandContext(ctx, "git", "checkout", "-b", backportBranch, releaseBranch).Run()
}
func fetchRemoteAndMain(ctx context.Context, remote, releaseBranch string) error {
fmt.Printf("* `git fetch %s main`\n", remote)
out, err := exec.CommandContext(ctx, "git", "fetch", remote, "main").Output()
if err != nil {
fmt.Println(string(out))
return fmt.Errorf("unable to fetch %s from %s: %w", "main", remote, err)
}
fmt.Println(string(out))
fmt.Printf("* `git fetch %s %s`\n", remote, releaseBranch)
out, err = exec.CommandContext(ctx, "git", "fetch", remote, releaseBranch).Output()
if err != nil {
fmt.Println(string(out))
return fmt.Errorf("unable to fetch %s from %s: %w", releaseBranch, remote, err)
}
fmt.Println(string(out))
return nil
}
func determineRemote(ctx context.Context, forkUser string) (string, string, error) {
out, err := exec.CommandContext(ctx, "git", "remote", "-v").Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out))
return "", "", fmt.Errorf("unable to determine forked remote: %w", err)
}
lines := strings.Split(string(out), "\n")
for _, line := range lines {
fields := strings.Split(line, "\t")
name, remote := fields[0], fields[1]
// only look at pushers
if !strings.HasSuffix(remote, " (push)") {
continue
}
// only look at github.com pushes
if !strings.Contains(remote, "github.com") {
continue
}
// ignore go-gitea/gitea
if strings.Contains(remote, "go-gitea/gitea") {
continue
}
if !strings.Contains(remote, forkUser) {
continue
}
if strings.HasPrefix(remote, "git@github.com:") {
forkUser = strings.TrimPrefix(remote, "git@github.com:")
} else if strings.HasPrefix(remote, "https://github.com/") {
forkUser = strings.TrimPrefix(remote, "https://github.com/")
} else if strings.HasPrefix(remote, "https://www.github.com/") {
forkUser = strings.TrimPrefix(remote, "https://www.github.com/")
} else if forkUser == "" {
return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote)
}
idx := strings.Index(forkUser, "/")
if idx >= 0 {
forkUser = forkUser[:idx]
}
return name, forkUser, nil
}
return "", "", fmt.Errorf("unable to find appropriate remote in:\n%s", string(out))
}
func readCurrentBranch(ctx context.Context) (pr, version string, err error) {
out, err := exec.CommandContext(ctx, "git", "branch", "--show-current").Output()
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read current git branch:\n%s\n", string(out))
return "", "", fmt.Errorf("unable to read current git branch: %w", err)
}
parts := strings.Split(strings.TrimSpace(string(out)), "-")
if len(parts) != 3 || parts[0] != "backport" {
fmt.Fprintf(os.Stderr, "Unable to continue from git branch:\n%s\n", string(out))
return "", "", fmt.Errorf("unable to continue from git branch:\n%s", string(out))
}
return parts[1], parts[2], nil
}
func readVersion() string {
bs, err := os.ReadFile("docs/config.yaml")
if err != nil {
if err == os.ErrNotExist {
log.Println("`docs/config.yaml` not present")
return ""
}
fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err)
return ""
}
type params struct {
Version string
}
type docConfig struct {
Params params
}
dc := &docConfig{}
if err := yaml.Unmarshal(bs, dc); err != nil {
fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err)
return ""
}
if dc.Params.Version == "" {
fmt.Fprintf(os.Stderr, "No version in `docs/config.yaml`")
return ""
}
version := dc.Params.Version
if version[0] != 'v' {
version = "v" + version
}
split := strings.SplitN(version, ".", 3)
return strings.Join(split[:2], ".")
}
func determineSHAforPR(ctx context.Context, prStr string) (string, error) {
prNum, err := strconv.Atoi(prStr)
if err != nil {
return "", err
}
client := github.NewClient(http.DefaultClient)
pr, _, err := client.PullRequests.Get(ctx, "go-gitea", "gitea", prNum)
if err != nil {
return "", err
}
if pr.Merged == nil || !*pr.Merged {
return "", fmt.Errorf("PR #%d is not yet merged - cannot determine sha to backport", prNum)
}
if pr.MergeCommitSHA != nil {
return *pr.MergeCommitSHA, nil
}
return "", nil
}
func installSignals() (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(context.Background())
go func() {
// install notify
signalChannel := make(chan os.Signal, 1)
signal.Notify(
signalChannel,
syscall.SIGINT,
syscall.SIGTERM,
)
select {
case <-signalChannel:
case <-ctx.Done():
}
cancel()
signal.Reset()
}()
return ctx, cancel
}

View File

@@ -1,5 +1,6 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package main

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package main
@@ -65,7 +66,7 @@ func generate(name string) error {
return err
}
path := filepath.Join(fixturesDir, name+".yml")
if err := os.WriteFile(path, []byte(data), 0o644); err != nil {
if err := os.WriteFile(path, []byte(data), 0644); err != nil {
return fmt.Errorf("%s: %+v", path, err)
}
fmt.Printf("%s created.\n", path)

View File

@@ -29,7 +29,7 @@ local addIssueLabelsOverrides(labels) =
grafanaDashboards+:: {
local giteaSelector = 'job=~"$job", instance=~"$instance"',
local giteaSelector = 'job="$job", instance="$instance"',
local giteaStatsPanel =
grafana.statPanel.new(
'Gitea stats',
@@ -399,31 +399,25 @@ local addIssueLabelsOverrides(labels) =
.addTemplate(
{
hide: 0,
label: 'job',
label: null,
name: 'job',
options: [],
datasource: '$datasource',
query: 'label_values(gitea_organizations, job)',
refresh: 1,
regex: '',
type: 'query',
multi: true,
allValue: '.+'
},
)
.addTemplate(
{
hide: 0,
label: 'instance',
label: null,
name: 'instance',
options: [],
datasource: '$datasource',
query: 'label_values(gitea_organizations{job="$job"}, instance)',
refresh: 1,
regex: '',
type: 'query',
multi: true,
allValue: '.+'
},
)
.addTemplate(

View File

@@ -7,10 +7,10 @@
"request": "launch",
"mode": "debug",
"buildFlags": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/main.go",
"env": {
"GITEA_WORK_DIR": "${workspaceRoot}",
},
"env": {},
"args": ["web"],
"showLog": true
},
@@ -20,10 +20,10 @@
"request": "launch",
"mode": "debug",
"buildFlags": "-tags='sqlite sqlite_unlock_notify'",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/main.go",
"env": {
"GITEA_WORK_DIR": "${workspaceRoot}",
},
"env": {},
"args": ["web"],
"showLog": true
}

View File

@@ -2,43 +2,14 @@
DIR=/var/lib/gitea
USER=git
HOME=/home/${USER}
GITEA_WORK_DIR=${DIR}
EXECUTABLE=/usr/local/bin/gitea
export USER
export HOME
export GITEA_WORK_DIR
name=$RC_SVCNAME
cfgfile="/etc/$RC_SVCNAME/app.ini"
command="${EXECUTABLE}"
command_user="${USER}"
command_args="web -c /etc/$RC_SVCNAME/app.ini"
command_background="yes"
pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid"
start_stop_daemon_args="--user ${USER} --chdir ${DIR}"
command="/usr/local/bin/gitea"
command_args="web -c /etc/gitea/app.ini"
command_background=yes
pidfile=/run/gitea.pid
depend()
{
need net
###
# Don't forget to add the database service requirements
###
#after postgresql
#after mysql
#after mariadb
#after memcached
#after redis
}
start_pre()
{
checkpath --directory --owner $command_user:$command_user --mode 0750 \
/run/$RC_SVCNAME /var/log/$RC_SVCNAME
##
# If you want to bind Gitea to a port below 1024, uncomment
# the value below
##
#setcap cap_net_bind_service=+ep "${EXECUTABLE}"
}

View File

@@ -1,35 +0,0 @@
#!/bin/sh /etc/rc.common
USE_PROCD=1
# PROCD_DEBUG=1
START=90
STOP=10
PROG=/opt/gitea/gitea
GITEA_WORK_DIR=/opt/gitea
CONF_FILE=$GITEA_WORK_DIR/app.ini
start_service(){
procd_open_instance gitea
procd_set_param env GITEA_WORK_DIR=$GITEA_WORK_DIR
procd_set_param env HOME=$GITEA_WORK_DIR
procd_set_param command $PROG web -c $CONF_FILE
procd_set_param file $CONF_FILE
procd_set_param user git
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} # respawn automatically if something died, be careful if you have an alternative process supervisor
procd_close_instance
}
start(){
service_start $PROG
}
stop(){
service_stop $PROG
}
reload(){
service_reload $PROG
}

View File

@@ -1,5 +1,6 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package main
@@ -13,6 +14,7 @@ import (
"fmt"
"log"
"net/http"
"net/url"
"os"
"os/exec"
"os/user"
@@ -22,17 +24,15 @@ import (
"strconv"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
gitea_git "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/external"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers"
markup_service "code.gitea.io/gitea/services/markup"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
@@ -49,8 +49,7 @@ func runPR() {
log.Fatal(err)
}
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.LoadAllowEmpty()
setting.RepoRootPath, err = os.MkdirTemp(os.TempDir(), "repos")
if err != nil {
@@ -62,7 +61,11 @@ func runPR() {
}
setting.AppWorkPath = curDir
setting.StaticRootPath = curDir
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/")
if err != nil {
log.Fatalf("url.Parse: %v\n", err)
}
setting.AppURL = "http://localhost:8080/"
setting.HTTPPort = "8080"
setting.SSH.Domain = "localhost"
@@ -77,25 +80,26 @@ func runPR() {
setting.RunUser = curUser.Username
log.Printf("[PR] Loading fixtures data ...\n")
gitea_git.CheckLFSVersion()
//models.LoadConfigs()
/*
setting.Database.Type = "sqlite3"
setting.Database.Path = ":memory:"
setting.Database.Timeout = 500
*/
dbCfg := setting.CfgProvider.Section("database")
dbCfg := setting.Cfg.Section("database")
dbCfg.NewKey("DB_TYPE", "sqlite3")
dbCfg.NewKey("PATH", ":memory:")
routers.InitGitServices()
setting.Database.LogSQL = true
// x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
db.InitEngineWithMigration(context.Background(), func(_ *xorm.Engine) error {
return nil
})
db.HasEngine = true
// x.ShowSQL(true)
//x.ShowSQL(true)
err = unittest.InitFixtures(
unittest.FixturesOptions{
Dir: path.Join(curDir, "models/fixtures/"),
@@ -107,14 +111,14 @@ func runPR() {
}
unittest.LoadFixtures()
util.RemoveAll(setting.RepoRootPath)
util.RemoveAll(repo_module.LocalCopyPath())
unittest.CopyDir(path.Join(curDir, "tests/gitea-repositories-meta"), setting.RepoRootPath)
util.RemoveAll(models.LocalCopyPath())
util.CopyDir(path.Join(curDir, "integrations/gitea-repositories-meta"), setting.RepoRootPath)
log.Printf("[PR] Setting up router\n")
// routers.GlobalInit()
//routers.GlobalInit()
external.RegisterRenderers()
markup.Init(markup_service.ProcessorHelper())
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
markup.Init()
c := routers.NormalRoutes()
log.Printf("[PR] Ready for testing !\n")
log.Printf("[PR] Login with user1, user2, user3, ... with pass: password\n")
@@ -133,7 +137,7 @@ func runPR() {
}
*/
// Start the server
//Start the server
http.ListenAndServe(":8080", c)
log.Printf("[PR] Cleaning up ...\n")
@@ -156,7 +160,7 @@ func runPR() {
}
func main() {
runPRFlag := flag.Bool("run", false, "Run the PR code")
var runPRFlag = flag.Bool("run", false, "Run the PR code")
flag.Parse()
if *runPRFlag {
runPR()
@@ -169,15 +173,15 @@ func main() {
force = false
}
// Otherwise checkout PR
//Otherwise checkout PR
if len(os.Args) != 2 {
log.Fatal("Need only one arg: the PR number")
}
pr := os.Args[1]
codeFilePath = filepath.FromSlash(codeFilePath) // Convert to running OS
codeFilePath = filepath.FromSlash(codeFilePath) //Convert to running OS
// Copy this file if it will not exist in the PR branch
//Copy this file if it will not exist in the PR branch
dat, err := os.ReadFile(codeFilePath)
if err != nil {
log.Fatalf("Failed to cache this code file : %v", err)
@@ -188,16 +192,16 @@ func main() {
log.Fatalf("Failed to open the repo : %v", err)
}
// Find remote upstream
//Find remote upstream
remotes, err := repo.Remotes()
if err != nil {
log.Fatalf("Failed to list remotes of repo : %v", err)
}
remoteUpstream := "origin" // Default
remoteUpstream := "origin" //Default
for _, r := range remotes {
if r.Config().URLs[0] == "https://github.com/go-gitea/gitea.git" ||
r.Config().URLs[0] == "https://github.com/go-gitea/gitea" ||
r.Config().URLs[0] == "git@github.com:go-gitea/gitea.git" { // fetch at index 0
r.Config().URLs[0] == "git@github.com:go-gitea/gitea.git" { //fetch at index 0
remoteUpstream = r.Config().Name
break
}
@@ -208,7 +212,7 @@ func main() {
log.Printf("Fetching PR #%s in %s\n", pr, branch)
if runtime.GOOS == "windows" {
// Use git cli command for windows
//Use git cli command for windows
runCmd("git", "fetch", remoteUpstream, fmt.Sprintf("pull/%s/head:%s", pr, branch))
} else {
ref := fmt.Sprintf("%s%s/head:%s", gitea_git.PullPrefix, pr, branchRef)
@@ -236,23 +240,22 @@ func main() {
log.Fatalf("Failed to checkout %s : %v", branch, err)
}
// Copy this file if not exist
//Copy this file if not exist
if _, err := os.Stat(codeFilePath); os.IsNotExist(err) {
err = os.MkdirAll(filepath.Dir(codeFilePath), 0o755)
err = os.MkdirAll(filepath.Dir(codeFilePath), 0755)
if err != nil {
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
}
err = os.WriteFile(codeFilePath, dat, 0o644)
err = os.WriteFile(codeFilePath, dat, 0644)
if err != nil {
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
}
}
// Force build of js, css, bin, ...
//Force build of js, css, bin, ...
runCmd("make", "build")
// Start with integration test
//Start with integration test
runCmd("go", "run", "-mod", "vendor", "-tags", "sqlite sqlite_unlock_notify", codeFilePath, "-run")
}
func runCmd(cmd ...string) {
log.Printf("Executing : %s ...\n", cmd)
c := exec.Command(cmd[0], cmd[1:]...)

View File

@@ -49,8 +49,12 @@ After=network.target
###
[Service]
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
# LimitNOFILE=524288:524288
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
RestartSec=2s
Type=simple
User=git
@@ -74,13 +78,6 @@ Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
###
# In some cases, when using CapabilityBoundingSet and AmbientCapabilities option, you may want to
# set the following value to false to allow capabilities to be applied on gitea process. The following
# value if set to true sandboxes gitea service and prevent any processes from running with privileges
# in the host user namespace.
###
#PrivateUsers=false
###
[Install]
WantedBy=multi-user.target

View File

@@ -4,5 +4,5 @@ grep 'git' go.mod | grep '\.com' | grep -v indirect | grep -v replace | cut -f 2
go get -u "$line"
make vendor
git add .
git commit -m "update $line"
git commit -S -m "update $line"
done

View File

@@ -1,126 +0,0 @@
#!/usr/bin/env bash
# This is an update script for gitea installed via the binary distribution
# from dl.gitea.io on linux as systemd service. It performs a backup and updates
# Gitea in place.
# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
# See section below for available environment vars.
# When no version is specified, updates to the latest release.
# Examples:
# upgrade.sh 1.15.10
# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
# apply variables from environment
: "${giteabin:="/usr/local/bin/gitea"}"
: "${giteahome:="/var/lib/gitea"}"
: "${giteaconf:="/etc/gitea/app.ini"}"
: "${giteauser:="git"}"
: "${sudocmd:="sudo"}"
: "${arch:="linux-amd64"}"
: "${service_start:="$sudocmd systemctl start gitea"}"
: "${service_stop:="$sudocmd systemctl stop gitea"}"
: "${service_status:="$sudocmd systemctl status gitea"}"
: "${backupopts:=""}" # see `gitea dump --help` for available options
function giteacmd {
if [[ $sudocmd = "su" ]]; then
# `-c` only accept one string as argument.
"$sudocmd" - "$giteauser" -c "$(printf "%q " "$giteabin" "--config" "$giteaconf" "--work-path" "$giteahome" "$@")"
else
"$sudocmd" --user "$giteauser" "$giteabin" --config "$giteaconf" --work-path "$giteahome" "$@"
fi
}
function require {
for exe in "$@"; do
command -v "$exe" &>/dev/null || (echo "missing dependency '$exe'"; exit 1)
done
}
# parse command line arguments
while true; do
case "$1" in
-v | --version ) giteaversion="$2"; shift 2 ;;
-y | --yes ) no_confirm="yes"; shift ;;
--ignore-gpg) ignore_gpg="yes"; shift ;;
"" | -- ) shift; break ;;
* ) echo "Usage: [<environment vars>] upgrade.sh [-v <version>] [-y] [--ignore-gpg]"; exit 1;;
esac
done
# exit once any command fails. this means that each step should be idempotent!
set -euo pipefail
if [[ -f /etc/os-release ]]; then
os_release=$(cat /etc/os-release)
if [[ "$os_release" =~ "OpenWrt" ]]; then
sudocmd="su"
service_start="/etc/init.d/gitea start"
service_stop="/etc/init.d/gitea stop"
service_status="/etc/init.d/gitea status"
else
require systemctl
fi
fi
require curl xz sha256sum "$sudocmd"
# select version to install
if [[ -z "${giteaversion:-}" ]]; then
require jq
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.io/gitea/version.json | jq -r .latest.version)
echo "Latest available version is $giteaversion"
fi
# confirm update
echo "Checking currently installed version..."
current=$(giteacmd --version | cut -d ' ' -f 3)
[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 1
if [[ -z "${no_confirm:-}" ]]; then
echo "Make sure to read the changelog first: https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md"
echo "Are you ready to update Gitea from ${current} to ${giteaversion}? (y/N)"
read -r confirm
[[ "$confirm" == "y" ]] || [[ "$confirm" == "Y" ]] || exit 1
fi
echo "Upgrading gitea from $current to $giteaversion ..."
pushd "$(pwd)" &>/dev/null
cd "$giteahome" # needed for gitea dump later
# download new binary
binname="gitea-${giteaversion}-${arch}"
binurl="https://dl.gitea.io/gitea/${giteaversion}/${binname}.xz"
echo "Downloading $binurl..."
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
# validate checksum & gpg signature
sha256sum -c "${binname}.xz.sha256"
if [[ -z "${ignore_gpg:-}" ]]; then
require gpg
gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
gpg --verify "${binname}.xz.asc" "${binname}.xz" || { echo 'Signature does not match'; exit 1; }
fi
rm "${binname}".xz.{sha256,asc}
# unpack binary + make executable
xz --decompress --force "${binname}.xz"
chown "$giteauser" "$binname"
chmod +x "$binname"
# stop gitea, create backup, replace binary, restart gitea
echo "Flushing gitea queues at $(date)"
giteacmd manager flush-queues
echo "Stopping gitea at $(date)"
$service_stop
echo "Creating backup in $giteahome"
giteacmd dump $backupopts
echo "Updating binary at $giteabin"
cp -f "$giteabin" "$giteabin.bak" && mv -f "$binname" "$giteabin"
$service_start
$service_status
echo "Upgrade to $giteaversion successful!"
popd

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,10 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless
{{#if build.tags}}
{{#unless contains "-rc" build.tag}}
tags:
{{#each build.tags}}
- {{this}}-rootless
{{/each}}
- "latest-rootless"
{{/unless}}
{{/if}}
manifests:
-

View File

@@ -1,12 +1,10 @@
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}
{{#if build.tags}}
{{#unless contains "-rc" build.tag }}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
- "latest"
{{/unless}}
{{/if}}
manifests:
-

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