mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-05-12 00:52:40 +00:00
Compare commits
39 commits
f521b838ed
...
cd54f1b027
Author | SHA1 | Date | |
---|---|---|---|
cd54f1b027 | |||
c9ba62b005 | |||
8da64860e7 | |||
d90b1e2c00 | |||
004fe91d37 | |||
08f5a25d3b | |||
4da76d0e5f | |||
c4db84ad0e | |||
a5df622099 | |||
dad16cd589 | |||
d6c36ec406 | |||
20350846fc | |||
c31ae1a651 | |||
0819ed2053 | |||
51a610d46c | |||
2bc226eb57 | |||
801554f708 | |||
c864448dc9 | |||
127eff49ee | |||
5247fd50db | |||
3dfa5ba43a | |||
90c56a9d66 | |||
aa2af10f67 | |||
a641ebf221 | |||
40d0f50838 | |||
2385f3c9db | |||
b51c608d3f | |||
a3be70f0a5 | |||
7f187f9857 | |||
4036448c02 | |||
94d7523f83 | |||
f7786e207e | |||
9e212c515e | |||
ad9872d884 | |||
44a1f90308 | |||
ea9051624d | |||
0d37f3a79b | |||
f23fd221e4 | |||
dc39043cd6 |
|
@ -4,6 +4,7 @@ reportUnusedDisableDirectives: true
|
|||
ignorePatterns:
|
||||
- /web_src/js/vendor
|
||||
- /web_src/fomantic
|
||||
- /public/assets/js
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
|
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: ghcr.io/visualon/renovate:37.316.2
|
||||
image: ghcr.io/visualon/renovate:37.323.3
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
|
@ -4,21 +4,4 @@ The Forgejo project is run by a community of people who are expected to follow t
|
|||
|
||||
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
|
||||
|
||||
## For everyone involved
|
||||
|
||||
- [Documentation](https://forgejo.org/docs/next/)
|
||||
- [Code of Conduct](https://forgejo.org/docs/latest/developer/coc/)
|
||||
- [Bugs, features, security and others discussions](https://forgejo.org/docs/latest/developer/discussions/)
|
||||
- [Governance](https://forgejo.org/docs/latest/developer/governance/)
|
||||
- [Sustainability and funding](https://codeberg.org/forgejo/sustainability/src/branch/main/README.md)
|
||||
|
||||
## For contributors
|
||||
|
||||
- [Developer Certificate of Origin (DCO)](https://forgejo.org/docs/latest/developer/dco/)
|
||||
- [Development workflow](https://forgejo.org/docs/latest/developer/workflow/)
|
||||
- [Compiling from source](https://forgejo.org/docs/latest/developer/from-source/)
|
||||
|
||||
## For maintainers
|
||||
|
||||
- [Release management](https://forgejo.org/docs/latest/developer/release/)
|
||||
- [Secrets](https://forgejo.org/docs/latest/developer/secrets/)
|
||||
You can find links to the different aspects of Developer documentation on this page: [Forgejo developer guide](https://forgejo.org/docs/next/developer/).
|
||||
|
|
|
@ -100,8 +100,11 @@ 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)
|
||||
ENV GITEA_APP_INI /etc/gitea/app.ini
|
||||
# Legacy config file for backwards compatibility
|
||||
# TODO: remove on next major version release
|
||||
ENV GITEA_APP_INI_LEGACY /etc/gitea/app.ini
|
||||
|
||||
ENV GITEA_APP_INI ${GITEA_CUSTOM}/conf/app.ini
|
||||
ENV HOME "/var/lib/gitea/git"
|
||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||
WORKDIR /var/lib/gitea
|
||||
|
|
|
@ -4,19 +4,9 @@ A minor or major Forgejo release is published every [three months](https://forge
|
|||
|
||||
A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading from v7.0.0 to v7.0.1 or v7.1.0) does not require manual intervention. But [major releases](https://semver.org/spec/v2.0.0.html#spec-item-8) where the first version number changes (e.g. upgrading from v1.21 to v7.0) contain breaking changes and the release notes explain how to deal with them.
|
||||
|
||||
## 8.0.0
|
||||
## Upcoming releases (not available yet)
|
||||
|
||||
This is a major release. It contains breaking changes that may require manual intervention. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
|
||||
|
||||
* **Breaking changes:**
|
||||
|
||||
In addition to the following notable bug fixes, you can browse the [full list of commits](https://codeberg.org/forgejo/forgejo/compare/v8.0.0...v7.0.0) included in this release.
|
||||
|
||||
If you have any feedback or suggestions for Forgejo do not hold back, it is also your project.
|
||||
Open an issue in [the issue tracker](https://codeberg.org/forgejo/forgejo/issues)
|
||||
for feature requests or bug reports, reach out [on the Fediverse](https://floss.social/@forgejo),
|
||||
or drop into [the Matrix space](https://matrix.to/#/#forgejo:matrix.org)
|
||||
([main chat room](https://matrix.to/#/#forgejo-chat:matrix.org)) and say hi!
|
||||
- [8.0.0](/release-notes/8.0.0/)
|
||||
|
||||
## 7.0.1
|
||||
|
||||
|
@ -25,9 +15,11 @@ This is a bug fix release. See the documentation for more information on the [up
|
|||
In addition to the following notable bug fixes, you can browse the [full list of commits](https://codeberg.org/forgejo/forgejo/compare/v7.0.0...v7.0.1) included in this release.
|
||||
|
||||
* **Bug fixes:**
|
||||
* The regression in the [`fogejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [is fixed](https://codeberg.org/forgejo/forgejo/issues/3399) and it is backward compatible.
|
||||
* Fixed a bug where the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints were using a hardcoded "master" branch for the wiki, rather than the branch they really use. ([#3430](https://codeberg.org/forgejo/forgejo/pulls/3430))
|
||||
* Fixed an error 500 when visiting [the LFS settings]() at `/{owner}/{repo}/settings/lfs/find?oid=...`.
|
||||
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3466): LFS data corruption when running the [`forgejo doctor check --fix`](https://forgejo.org/docs/v7.0/admin/command-line/#doctor-check) CLI command or setting [`[cron.gc_lfs].ENABLED=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#cron---garbage-collect-lfs-pointers-in-repositories-crongc_lfs) (the default is `false`).
|
||||
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3412): [non backward compatible change](https://codeberg.org/forgejo/forgejo/issues/3399) in the [`forgejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command.
|
||||
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3448): error 500 because of an incorrect evaluation of the template when visiting the LFS settings of a repository.
|
||||
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3464): `GET /repos/{owner}/{name}` API endpoint [always returns an empty string for the `object_format_name` field](https://codeberg.org/forgejo/forgejo/issues/3458).
|
||||
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3444): fuzzy search [may fail with bleve](https://codeberg.org/forgejo/forgejo/issues/3443).
|
||||
|
||||
## 7.0.0
|
||||
|
||||
|
@ -38,8 +30,9 @@ $ git clone https://codeberg.org/forgejo/forgejo/
|
|||
$ git -C forgejo log --oneline --no-merges origin/v1.21/forgejo..origin/v7.0/forgejo
|
||||
```
|
||||
|
||||
* **Regression and workaround:**
|
||||
* The [`fogejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [requires a password](https://codeberg.org/forgejo/forgejo/commit/b122c6ef8b9254120432aed373cbe075331132ac) change by default when creating the first user and the `--admin` flag is not specified. The `--must-change-password=false` argument must be given to not require a password change. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3399).
|
||||
* **Regressions and workarounds:**
|
||||
* Running the [`forgejo doctor check --fix`](https://forgejo.org/docs/v7.0/admin/command-line/#doctor-check) CLI command or setting [`[cron.gc_lfs].ENABLED=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#cron---garbage-collect-lfs-pointers-in-repositories-crongc_lfs) (the default is `false`) will corrupt the LFS storage. The workaround is to not run the doctor CLI command and disable the `cron.gc_lfs`. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3438).
|
||||
* The [`forgejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [requires a password](https://codeberg.org/forgejo/forgejo/commit/b122c6ef8b9254120432aed373cbe075331132ac) change by default when creating the first user and the `--admin` flag is not specified. The `--must-change-password=false` argument must be given to not require a password change. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3399).
|
||||
* **Breaking changes requiring manual intervention:**
|
||||
* [MySQL 8.0 or PostgreSQL 12](https://codeberg.org/forgejo/forgejo/commit/e94f9fcafdcf284561e7fb33f60156a69c4ad6a5) are the minimum supported versions. The database must be migrated before upgrading. The requirements regarding SQLite did not change.
|
||||
* The `per_page` parameter is [no longer a synonym for `limit`](https://codeberg.org/forgejo/forgejo/commit/0aab2d38a7d91bc8caff332e452364468ce52d9a) in the [/repos/{owner}/{repo}/releases](https://code.forgejo.org/api/swagger/#/repository/repoListReleases) API endpoint.
|
||||
|
|
|
@ -407,8 +407,8 @@ USER = root
|
|||
;; Database connection max life time, default is 0 or 3s mysql (See #6804 & #7071 for reasoning)
|
||||
;CONN_MAX_LIFETIME = 3s
|
||||
;;
|
||||
;; Database maximum number of open connections, default is 0 meaning no maximum
|
||||
;MAX_OPEN_CONNS = 0
|
||||
;; Database maximum number of open connections, default is 100 which is the lowest default from Postgres (MariaDB + MySQL default to 151). Ensure you only increase the value if you configured your database server accordingly.
|
||||
;MAX_OPEN_CONNS = 100
|
||||
;;
|
||||
;; Whether execute database models migrations automatically
|
||||
;AUTO_MIGRATION = true
|
||||
|
|
|
@ -13,5 +13,10 @@ fi
|
|||
if [ $# -gt 0 ]; then
|
||||
exec "$@"
|
||||
else
|
||||
# TODO: remove on next major version release
|
||||
# Honour legacy config file if existing
|
||||
if [ -f ${GITEA_APP_INI_LEGACY} ]; then
|
||||
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
|
||||
fi
|
||||
exec /usr/local/bin/gitea -c ${GITEA_APP_INI} web
|
||||
fi
|
||||
|
|
|
@ -11,6 +11,18 @@ mkdir -p ${GITEA_CUSTOM} && chmod 0700 ${GITEA_CUSTOM}
|
|||
mkdir -p ${GITEA_TEMP} && chmod 0700 ${GITEA_TEMP}
|
||||
if [ ! -w ${GITEA_TEMP} ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi
|
||||
|
||||
# TODO: remove on next major version release
|
||||
# Honour legacy config file if existing, but inform the user
|
||||
if [ -f ${GITEA_APP_INI_LEGACY} ] && [ ${GITEA_APP_INI} != ${GITEA_APP_INI_LEGACY} ]; then
|
||||
GITEA_APP_INI_DEFAULT=/var/lib/gitea/custom/conf/app.ini
|
||||
echo -e \
|
||||
"\033[33mWARNING\033[0m: detected configuration file in deprecated default path ${GITEA_APP_INI_LEGACY}." \
|
||||
"The new default is ${GITEA_APP_INI_DEFAULT}. To remove this warning, choose one of the options:\n" \
|
||||
"* Move ${GITEA_APP_INI_LEGACY} to ${GITEA_APP_INI_DEFAULT} (or to \$GITEA_APP_INI if you want to override this variable)\n" \
|
||||
"* Explicitly override GITEA_APP_INI=${GITEA_APP_INI_LEGACY} in the container environment"
|
||||
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
|
||||
fi
|
||||
|
||||
#Prepare config file
|
||||
if [ ! -f ${GITEA_APP_INI} ]; then
|
||||
|
||||
|
|
12
go.mod
12
go.mod
|
@ -89,13 +89,13 @@ require (
|
|||
github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd
|
||||
github.com/sergi/go-diff v1.3.1
|
||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/ulikunitz/xz v0.5.11
|
||||
github.com/urfave/cli/v2 v2.27.1
|
||||
github.com/xanzy/go-gitlab v0.96.0
|
||||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.6.0
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.21.0
|
||||
|
@ -243,8 +243,8 @@ require (
|
|||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.46.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rhysd/actionlint v1.6.26 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rhysd/actionlint v1.6.27 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
@ -272,7 +272,7 @@ require (
|
|||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
go.etcd.io/bbolt v1.3.9 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
go.opentelemetry.io/otel v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
|
@ -294,7 +294,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
|||
|
||||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||
|
||||
replace github.com/nektos/act => gitea.com/gitea/act v0.259.1
|
||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.1
|
||||
|
||||
replace github.com/gorilla/feeds => github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5
|
||||
|
||||
|
|
23
go.sum
23
go.sum
|
@ -52,8 +52,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
|||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||
gitea.com/gitea/act v0.259.1 h1:8GG1o/xtUHl3qjn5f0h/2FXrT5ubBn05TJOM5ry+FBw=
|
||||
gitea.com/gitea/act v0.259.1/go.mod h1:UxZWRYqQG2Yj4+4OqfGWW5a3HELwejyWFQyU7F1jUD8=
|
||||
gitea.com/gitea/act v0.261.1 h1:iACWLc/k8wct9fCF2WdYKqn2Hxx6NjW9zbOP79HF4H4=
|
||||
gitea.com/gitea/act v0.261.1/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo=
|
||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
||||
gitea.com/go-chi/cache v0.2.0 h1:E0npuTfDW6CT1yD8NMDVc1SK6IeRjfmRL2zlEsCEd7w=
|
||||
|
@ -708,11 +708,11 @@ github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwy
|
|||
github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rhysd/actionlint v1.6.26 h1:zi7jPZf3Ks14gCXYAAL47uBziyFlX7+Xwilqhexct9g=
|
||||
github.com/rhysd/actionlint v1.6.26/go.mod h1:TIj1DlCgtYLOv5CH9wCK+WJTOr1qAdnFzkGi0IgSCO4=
|
||||
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
||||
github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
|
@ -785,8 +785,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
|
@ -837,8 +838,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
|
||||
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
|
||||
|
@ -849,8 +850,8 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
|||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
-
|
||||
|
||||
id: 2
|
||||
id: 2 # this is an LFS orphan object
|
||||
oid: 2eccdb43825d2a49d99d542daa20075cff1d97d9d2349a8977efe9c03661737c
|
||||
size: 107
|
||||
repository_id: 54
|
||||
|
|
|
@ -64,6 +64,8 @@ var migrations = []*Migration{
|
|||
NewMigration("Add repo_archive_download_count table", forgejo_v1_22.AddRepoArchiveDownloadCount),
|
||||
// v13 -> v14
|
||||
NewMigration("Add `hide_archive_links` column to `release` table", AddHideArchiveLinksToRelease),
|
||||
// v14 -> v15
|
||||
NewMigration("Remove Gitea-specific columns from the repository and badge tables", RemoveGiteaSpecificColumnsFromRepositoryAndBadge),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
43
models/forgejo_migrations/v14.go
Normal file
43
models/forgejo_migrations/v14.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/models/migrations/base"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func RemoveGiteaSpecificColumnsFromRepositoryAndBadge(x *xorm.Engine) error {
|
||||
// Make sure the columns exist before dropping them
|
||||
type Repository struct {
|
||||
ID int64
|
||||
DefaultWikiBranch string
|
||||
}
|
||||
if err := x.Sync(&Repository{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type Badge struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Slug string
|
||||
}
|
||||
err := x.Sync(new(Badge))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := base.DropTableColumns(sess, "repository", "default_wiki_branch"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := base.DropTableColumns(sess, "badge", "slug"); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
|
@ -6,6 +6,7 @@ package git
|
|||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
@ -33,6 +34,15 @@ type ObjectFormat interface {
|
|||
ComputeHash(t ObjectType, content []byte) ObjectID
|
||||
}
|
||||
|
||||
func computeHash(dst []byte, hasher hash.Hash, t ObjectType, content []byte) []byte {
|
||||
_, _ = hasher.Write(t.Bytes())
|
||||
_, _ = hasher.Write([]byte(" "))
|
||||
_, _ = hasher.Write([]byte(strconv.Itoa(len(content))))
|
||||
_, _ = hasher.Write([]byte{0})
|
||||
_, _ = hasher.Write(content)
|
||||
return hasher.Sum(dst)
|
||||
}
|
||||
|
||||
/* SHA1 Type */
|
||||
type Sha1ObjectFormatImpl struct{}
|
||||
|
||||
|
@ -65,16 +75,9 @@ func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
|
|||
|
||||
// ComputeHash compute the hash for a given ObjectType and content
|
||||
func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
|
||||
hasher := sha1.New()
|
||||
_, _ = hasher.Write(t.Bytes())
|
||||
_, _ = hasher.Write([]byte(" "))
|
||||
_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
||||
_, _ = hasher.Write([]byte{0})
|
||||
|
||||
// HashSum generates a SHA1 for the provided hash
|
||||
var sha1 Sha1Hash
|
||||
copy(sha1[:], hasher.Sum(nil))
|
||||
return &sha1
|
||||
var obj Sha1Hash
|
||||
computeHash(obj[:0], sha1.New(), t, content)
|
||||
return &obj
|
||||
}
|
||||
|
||||
/* SHA256 Type */
|
||||
|
@ -111,16 +114,9 @@ func (Sha256ObjectFormatImpl) MustID(b []byte) ObjectID {
|
|||
|
||||
// ComputeHash compute the hash for a given ObjectType and content
|
||||
func (h Sha256ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
|
||||
hasher := sha256.New()
|
||||
_, _ = hasher.Write(t.Bytes())
|
||||
_, _ = hasher.Write([]byte(" "))
|
||||
_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
||||
_, _ = hasher.Write([]byte{0})
|
||||
|
||||
// HashSum generates a SHA256 for the provided hash
|
||||
var sha256 Sha1Hash
|
||||
copy(sha256[:], hasher.Sum(nil))
|
||||
return &sha256
|
||||
var obj Sha256Hash
|
||||
computeHash(obj[:0], sha256.New(), t, content)
|
||||
return &obj
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -18,4 +18,8 @@ func TestIsValidSHAPattern(t *testing.T) {
|
|||
assert.False(t, h.IsValid("abc"))
|
||||
assert.False(t, h.IsValid("123g"))
|
||||
assert.False(t, h.IsValid("some random text"))
|
||||
|
||||
assert.Equal(t, "79ee38a6416c1ede423ec7ee0a8639ceea4aad22", ComputeBlobHash(Sha1ObjectFormat, []byte("some random blob")).String())
|
||||
assert.Equal(t, "d5c6407415d85df49592672aa421aed39b9db5e3", ComputeBlobHash(Sha1ObjectFormat, []byte("same length blob")).String())
|
||||
assert.Equal(t, "df0b5174ed06ae65aea40d43316bcbc21d82c9e3158ce2661df2ad28d7931dd6", ComputeBlobHash(Sha256ObjectFormat, []byte("some random blob")).String())
|
||||
}
|
||||
|
|
32
modules/git/pipeline/lfs_common.go
Normal file
32
modules/git/pipeline/lfs_common.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
)
|
||||
|
||||
// LFSResult represents commits found using a provided pointer file hash
|
||||
type LFSResult struct {
|
||||
Name string
|
||||
SHA string
|
||||
Summary string
|
||||
When time.Time
|
||||
ParentHashes []git.ObjectID
|
||||
BranchName string
|
||||
FullCommitName string
|
||||
}
|
||||
|
||||
type lfsResultSlice []*LFSResult
|
||||
|
||||
func (a lfsResultSlice) Len() int { return len(a) }
|
||||
func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
|
||||
|
||||
func lfsError(msg string, err error) error {
|
||||
return fmt.Errorf("LFS error occurred, %s: err: %w", msg, err)
|
||||
}
|
|
@ -7,12 +7,10 @@ package pipeline
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
|
||||
|
@ -21,23 +19,6 @@ import (
|
|||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
)
|
||||
|
||||
// LFSResult represents commits found using a provided pointer file hash
|
||||
type LFSResult struct {
|
||||
Name string
|
||||
SHA string
|
||||
Summary string
|
||||
When time.Time
|
||||
ParentHashes []git.ObjectID
|
||||
BranchName string
|
||||
FullCommitName string
|
||||
}
|
||||
|
||||
type lfsResultSlice []*LFSResult
|
||||
|
||||
func (a lfsResultSlice) Len() int { return len(a) }
|
||||
func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
|
||||
|
||||
// FindLFSFile finds commits that contain a provided pointer file hash
|
||||
func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) {
|
||||
resultsMap := map[string]*LFSResult{}
|
||||
|
@ -51,7 +32,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
All: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get GoGit CommitsIter. Error: %w", err)
|
||||
return nil, lfsError("failed to get GoGit CommitsIter", err)
|
||||
}
|
||||
|
||||
err = commitsIter.ForEach(func(gitCommit *object.Commit) error {
|
||||
|
@ -85,7 +66,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
return nil
|
||||
})
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, fmt.Errorf("Failure in CommitIter.ForEach: %w", err)
|
||||
return nil, lfsError("failure in CommitIter.ForEach", err)
|
||||
}
|
||||
|
||||
for _, result := range resultsMap {
|
||||
|
@ -156,7 +137,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
select {
|
||||
case err, has := <-errChan:
|
||||
if has {
|
||||
return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err)
|
||||
return nil, lfsError("unable to obtain name for LFS files", err)
|
||||
}
|
||||
default:
|
||||
}
|
|
@ -8,33 +8,14 @@ package pipeline
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
)
|
||||
|
||||
// LFSResult represents commits found using a provided pointer file hash
|
||||
type LFSResult struct {
|
||||
Name string
|
||||
SHA string
|
||||
Summary string
|
||||
When time.Time
|
||||
ParentIDs []git.ObjectID
|
||||
BranchName string
|
||||
FullCommitName string
|
||||
}
|
||||
|
||||
type lfsResultSlice []*LFSResult
|
||||
|
||||
func (a lfsResultSlice) Len() int { return len(a) }
|
||||
func (a lfsResultSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a lfsResultSlice) Less(i, j int) bool { return a[j].When.After(a[i].When) }
|
||||
|
||||
// FindLFSFile finds commits that contain a provided pointer file hash
|
||||
func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, error) {
|
||||
resultsMap := map[string]*LFSResult{}
|
||||
|
@ -137,11 +118,11 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
n += int64(count)
|
||||
if bytes.Equal(binObjectID, objectID.RawValue()) {
|
||||
result := LFSResult{
|
||||
Name: curPath + string(fname),
|
||||
SHA: curCommit.ID.String(),
|
||||
Summary: strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0],
|
||||
When: curCommit.Author.When,
|
||||
ParentIDs: curCommit.Parents,
|
||||
Name: curPath + string(fname),
|
||||
SHA: curCommit.ID.String(),
|
||||
Summary: strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0],
|
||||
When: curCommit.Author.When,
|
||||
ParentHashes: curCommit.Parents,
|
||||
}
|
||||
resultsMap[curCommit.ID.String()+":"+curPath+string(fname)] = &result
|
||||
} else if string(mode) == git.EntryModeTree.String() {
|
||||
|
@ -183,7 +164,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
|
||||
for _, result := range resultsMap {
|
||||
hasParent := false
|
||||
for _, parentID := range result.ParentIDs {
|
||||
for _, parentID := range result.ParentHashes {
|
||||
if _, hasParent = resultsMap[parentID.String()+":"+result.Name]; hasParent {
|
||||
break
|
||||
}
|
||||
|
@ -241,7 +222,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
select {
|
||||
case err, has := <-errChan:
|
||||
if has {
|
||||
return nil, fmt.Errorf("Unable to obtain name for LFS files. Error: %w", err)
|
||||
return nil, lfsError("unable to obtain name for LFS files", err)
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ const (
|
|||
maxBatchSize = 16
|
||||
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||
fuzzyDenominator = 4
|
||||
// see https://github.com/blevesearch/bleve/issues/1563#issuecomment-786822311
|
||||
maxFuzziness = 2
|
||||
)
|
||||
|
||||
func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||
|
@ -246,7 +248,7 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
||||
keywordQuery = phraseQuery
|
||||
if opts.IsKeywordFuzzy {
|
||||
phraseQuery.Fuzziness = len(opts.Keyword) / fuzzyDenominator
|
||||
phraseQuery.Fuzziness = min(maxFuzziness, len(opts.Keyword)/fuzzyDenominator)
|
||||
}
|
||||
|
||||
if len(opts.RepoIDs) > 0 {
|
||||
|
|
|
@ -49,6 +49,12 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
|||
IDs: []int64{},
|
||||
Langs: 0,
|
||||
},
|
||||
{
|
||||
RepoIDs: nil,
|
||||
Keyword: "Description for",
|
||||
IDs: []int64{repoID},
|
||||
Langs: 1,
|
||||
},
|
||||
{
|
||||
RepoIDs: nil,
|
||||
Keyword: "repo1",
|
||||
|
|
|
@ -39,6 +39,8 @@ const (
|
|||
maxBatchSize = 16
|
||||
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||
fuzzyDenominator = 4
|
||||
// see https://github.com/blevesearch/bleve/issues/1563#issuecomment-786822311
|
||||
maxFuzziness = 2
|
||||
)
|
||||
|
||||
// IndexerData an update to the issue indexer
|
||||
|
@ -162,7 +164,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
|||
if options.Keyword != "" {
|
||||
fuzziness := 0
|
||||
if options.IsFuzzyKeyword {
|
||||
fuzziness = len(options.Keyword) / fuzzyDenominator
|
||||
fuzziness = min(maxFuzziness, len(options.Keyword)/fuzzyDenominator)
|
||||
}
|
||||
|
||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
||||
|
|
|
@ -130,6 +130,20 @@ var cases = []*testIndexerCase{
|
|||
ExpectedIDs: []int64{1002, 1001, 1000},
|
||||
ExpectedTotal: 3,
|
||||
},
|
||||
{
|
||||
Name: "Keyword Fuzzy",
|
||||
ExtraData: []*internal.IndexerData{
|
||||
{ID: 1000, Title: "hi hello world"},
|
||||
{ID: 1001, Content: "hi hello world"},
|
||||
{ID: 1002, Comments: []string{"hi", "hello world"}},
|
||||
},
|
||||
SearchOptions: &internal.SearchOptions{
|
||||
Keyword: "hello wrold",
|
||||
IsFuzzyKeyword: true,
|
||||
},
|
||||
ExpectedIDs: []int64{1002, 1001, 1000},
|
||||
ExpectedTotal: 3,
|
||||
},
|
||||
{
|
||||
Name: "RepoIDs",
|
||||
ExtraData: []*internal.IndexerData{
|
||||
|
|
|
@ -83,7 +83,7 @@ func loadDBSetting(rootCfg ConfigProvider) {
|
|||
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFETIME").MustDuration(0)
|
||||
}
|
||||
Database.ConnMaxIdleTime = sec.Key("CONN_MAX_IDLETIME").MustDuration(0)
|
||||
Database.MaxOpenConns = sec.Key("MAX_OPEN_CONNS").MustInt(0)
|
||||
Database.MaxOpenConns = sec.Key("MAX_OPEN_CONNS").MustInt(100)
|
||||
|
||||
Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50)
|
||||
Database.LogSQL = sec.Key("LOG_SQL").MustBool(false)
|
||||
|
|
|
@ -162,7 +162,7 @@ var (
|
|||
PreferredLicenses: []string{"Apache-2.0", "MIT"},
|
||||
DisableHTTPGit: false,
|
||||
AccessControlAllowOrigin: "",
|
||||
UseCompatSSHURI: false,
|
||||
UseCompatSSHURI: true,
|
||||
DefaultCloseIssuesViaCommitsInAnyBranch: false,
|
||||
EnablePushCreateUser: false,
|
||||
EnablePushCreateOrg: false,
|
||||
|
|
|
@ -3100,6 +3100,7 @@ auths.attribute_mail = Email attribute
|
|||
auths.attribute_ssh_public_key = Public SSH key attribute
|
||||
auths.attribute_avatar = Avatar attribute
|
||||
auths.attributes_in_bind = Fetch attributes in bind DN context
|
||||
auths.default_domain_name = Default domain name used for the email address
|
||||
auths.allow_deactivate_all = Allow an empty search result to deactivate all users
|
||||
auths.use_paged_search = Use paged search
|
||||
auths.search_page_size = Page size
|
||||
|
|
74
package-lock.json
generated
74
package-lock.json
generated
|
@ -44,7 +44,7 @@
|
|||
"postcss-nesting": "12.1.2",
|
||||
"pretty-ms": "9.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"swagger-ui-dist": "5.17.1",
|
||||
"swagger-ui-dist": "5.17.2",
|
||||
"tailwindcss": "3.4.3",
|
||||
"temporal-polyfill": "0.2.4",
|
||||
"throttle-debounce": "5.0.0",
|
||||
|
@ -96,7 +96,7 @@
|
|||
"svgo": "3.2.0",
|
||||
"updates": "16.0.1",
|
||||
"vite-string-plugin": "1.2.0",
|
||||
"vitest": "1.5.1"
|
||||
"vitest": "1.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.0.0"
|
||||
|
@ -2545,13 +2545,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.1.tgz",
|
||||
"integrity": "sha512-w3Bn+VUMqku+oWmxvPhTE86uMTbfmBl35aGaIPlwVW7Q89ZREC/icfo2HBsEZ3AAW6YR9lObfZKPEzstw9tJOQ==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.2.tgz",
|
||||
"integrity": "sha512-rf7MTD1WCoDlN3FfYJ9Llfp0PbdtOMZ3FIF0AVkDnKbp3oiMW1c8AmvRZBcqbAhDUAvF52e9zx4WQM1r3oraVA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vitest/spy": "1.5.1",
|
||||
"@vitest/utils": "1.5.1",
|
||||
"@vitest/spy": "1.5.2",
|
||||
"@vitest/utils": "1.5.2",
|
||||
"chai": "^4.3.10"
|
||||
},
|
||||
"funding": {
|
||||
|
@ -2559,12 +2559,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.1.tgz",
|
||||
"integrity": "sha512-mt372zsz0vFR7L1xF/ert4t+teD66oSuXoTyaZbl0eJgilvyzCKP1tJ21gVa8cDklkBOM3DLnkE1ljj/BskyEw==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.2.tgz",
|
||||
"integrity": "sha512-7IJ7sJhMZrqx7HIEpv3WrMYcq8ZNz9L6alo81Y6f8hV5mIE6yVZsFoivLZmr0D777klm1ReqonE9LyChdcmw6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vitest/utils": "1.5.1",
|
||||
"@vitest/utils": "1.5.2",
|
||||
"p-limit": "^5.0.0",
|
||||
"pathe": "^1.1.1"
|
||||
},
|
||||
|
@ -2600,9 +2600,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.1.tgz",
|
||||
"integrity": "sha512-h/1SGaZYXmjn6hULRBOlqam2z4oTlEe6WwARRzLErAPBqljAs6eX7tfdyN0K+MpipIwSZ5sZsubDWkCPAiVXZQ==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.2.tgz",
|
||||
"integrity": "sha512-CTEp/lTYos8fuCc9+Z55Ga5NVPKUgExritjF5VY7heRFUfheoAqBneUlvXSUJHUZPjnPmyZA96yLRJDP1QATFQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"magic-string": "^0.30.5",
|
||||
|
@ -2626,9 +2626,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.1.tgz",
|
||||
"integrity": "sha512-vsqczk6uPJjmPLy6AEtqfbFqgLYcGBe9BTY+XL8L6y8vrGOhyE23CJN9P/hPimKXnScbqiZ/r/UtUSOQ2jIDGg==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.2.tgz",
|
||||
"integrity": "sha512-xCcPvI8JpCtgikT9nLpHPL1/81AYqZy1GCy4+MCHBE7xi8jgsYkULpW5hrx5PGLgOQjUpb6fd15lqcriJ40tfQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tinyspy": "^2.2.0"
|
||||
|
@ -2638,9 +2638,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.1.tgz",
|
||||
"integrity": "sha512-92pE17bBXUxA0Y7goPcvnATMCuq4NQLOmqsG0e2BtzRi7KLwZB5jpiELi/8ybY8IQNWemKjSD5rMoO7xTdv8ug==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.2.tgz",
|
||||
"integrity": "sha512-sWOmyofuXLJ85VvXNsroZur7mOJGiQeM0JN3/0D1uU8U9bGFM69X1iqHaRXl6R8BwaLY6yPCogP257zxTzkUdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"diff-sequences": "^29.6.3",
|
||||
|
@ -11495,9 +11495,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/swagger-ui-dist": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.1.tgz",
|
||||
"integrity": "sha512-6MNu1MYNALLFvcPpo2MJVJFIxz2rFkH+XoX+J72LBLdj4JLjVaP4lHmNHtJ/tXZUXHdsb2Iw9JhPlqspjkomQg=="
|
||||
"version": "5.17.2",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.2.tgz",
|
||||
"integrity": "sha512-V/NqUw6QoTrjSpctp2oLQvxrl3vW29UsUtZyq7B1CF0v870KOFbYGDQw8rpKaKm0JxTwHpWnW1SN9YuKZdiCyw=="
|
||||
},
|
||||
"node_modules/sync-fetch": {
|
||||
"version": "0.4.5",
|
||||
|
@ -12257,9 +12257,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vite-node": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.1.tgz",
|
||||
"integrity": "sha512-HNpfV7BrAsjkYVNWIcPleJwvJmydJqqJRrRbpoQ/U7QDwJKyEzNa4g5aYg8MjXJyKsk29IUCcMLFRcsEvqUIsA==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.2.tgz",
|
||||
"integrity": "sha512-Y8p91kz9zU+bWtF7HGt6DVw2JbhyuB2RlZix3FPYAYmUyZ3n7iTp8eSyLyY6sxtPegvxQtmlTMhfPhUfCUF93A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cac": "^6.7.14",
|
||||
|
@ -12339,16 +12339,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.1.tgz",
|
||||
"integrity": "sha512-3GvBMpoRnUNbZRX1L3mJCv3Ou3NAobb4dM48y8k9ZGwDofePpclTOyO+lqJFKSQpubH1V8tEcAEw/Y3mJKGJQQ==",
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.2.tgz",
|
||||
"integrity": "sha512-l9gwIkq16ug3xY7BxHwcBQovLZG75zZL0PlsiYQbf76Rz6QGs54416UWMtC0jXeihvHvcHrf2ROEjkQRVpoZYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "1.5.1",
|
||||
"@vitest/runner": "1.5.1",
|
||||
"@vitest/snapshot": "1.5.1",
|
||||
"@vitest/spy": "1.5.1",
|
||||
"@vitest/utils": "1.5.1",
|
||||
"@vitest/expect": "1.5.2",
|
||||
"@vitest/runner": "1.5.2",
|
||||
"@vitest/snapshot": "1.5.2",
|
||||
"@vitest/spy": "1.5.2",
|
||||
"@vitest/utils": "1.5.2",
|
||||
"acorn-walk": "^8.3.2",
|
||||
"chai": "^4.3.10",
|
||||
"debug": "^4.3.4",
|
||||
|
@ -12362,7 +12362,7 @@
|
|||
"tinybench": "^2.5.1",
|
||||
"tinypool": "^0.8.3",
|
||||
"vite": "^5.0.0",
|
||||
"vite-node": "1.5.1",
|
||||
"vite-node": "1.5.2",
|
||||
"why-is-node-running": "^2.2.2"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -12377,8 +12377,8 @@
|
|||
"peerDependencies": {
|
||||
"@edge-runtime/vm": "*",
|
||||
"@types/node": "^18.0.0 || >=20.0.0",
|
||||
"@vitest/browser": "1.5.1",
|
||||
"@vitest/ui": "1.5.1",
|
||||
"@vitest/browser": "1.5.2",
|
||||
"@vitest/ui": "1.5.2",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*"
|
||||
},
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
"postcss-nesting": "12.1.2",
|
||||
"pretty-ms": "9.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"swagger-ui-dist": "5.17.1",
|
||||
"swagger-ui-dist": "5.17.2",
|
||||
"tailwindcss": "3.4.3",
|
||||
"temporal-polyfill": "0.2.4",
|
||||
"throttle-debounce": "5.0.0",
|
||||
|
@ -95,7 +95,7 @@
|
|||
"svgo": "3.2.0",
|
||||
"updates": "16.0.1",
|
||||
"vite-string-plugin": "1.2.0",
|
||||
"vitest": "1.5.1"
|
||||
"vitest": "1.5.2"
|
||||
},
|
||||
"browserslist": ["defaults"]
|
||||
}
|
||||
|
|
1
release-notes/8.0.0/3414.md
Normal file
1
release-notes/8.0.0/3414.md
Normal file
|
@ -0,0 +1 @@
|
|||
Allow to customize the domain name used as a fallback when synchronizing sources from ldap [`ldap: default domain name`](https://codeberg.org/forgejo/forgejo/pulls/3414)
|
6
release-notes/8.0.0/fix/3363.md
Normal file
6
release-notes/8.0.0/fix/3363.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Reverted the rootless container image path in `GITEA_APP_INI` from
|
||||
`/etc/gitea/app.ini` to its default value of
|
||||
`/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have
|
||||
to mount two separate volumes (one for the configuration data and one for the
|
||||
configuration `.ini` file). A warning is issued for users with the legacy
|
||||
configuration on how to update to the new path.
|
1
release-notes/8.0.0/fix/3430.md
Normal file
1
release-notes/8.0.0/fix/3430.md
Normal file
|
@ -0,0 +1 @@
|
|||
Fixed a bug where the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints were using a hardcoded "master" branch for the wiki, rather than the branch they really use.
|
1
release-notes/8.0.0/fix/3442.md
Normal file
1
release-notes/8.0.0/fix/3442.md
Normal file
|
@ -0,0 +1 @@
|
|||
Save updated empty comments instead of skipping the update silently, [which prevented the removal of attachments of such comments](https://codeberg.org/forgejo/forgejo/issues/3424).
|
|
@ -37,7 +37,8 @@
|
|||
"matchDepNames": [
|
||||
"bitnami/minio",
|
||||
"github.com/go-ap/activitypub",
|
||||
"github.com/nektos/act"
|
||||
"github.com/nektos/act",
|
||||
"gitea.com/gitea/act"
|
||||
],
|
||||
"dependencyDashboardApproval": true
|
||||
},
|
||||
|
|
|
@ -129,6 +129,7 @@ func parseLDAPConfig(form forms.AuthenticationForm) *ldap.Source {
|
|||
UserDN: form.UserDN,
|
||||
BindPassword: form.BindPassword,
|
||||
UserBase: form.UserBase,
|
||||
DefaultDomainName: form.DefaultDomainName,
|
||||
AttributeUsername: form.AttributeUsername,
|
||||
AttributeName: form.AttributeName,
|
||||
AttributeSurname: form.AttributeSurname,
|
||||
|
|
|
@ -57,7 +57,7 @@ func Activity(ctx *context.Context) {
|
|||
ctx.Repo.CanRead(unit.TypeReleases),
|
||||
ctx.Repo.CanRead(unit.TypeIssues),
|
||||
ctx.Repo.CanRead(unit.TypePullRequests),
|
||||
ctx.Repo.CanRead(unit.TypeCode)); err != nil {
|
||||
ctx.Repo.CanRead(unit.TypeCode) && !ctx.Repo.Repository.IsEmpty); err != nil {
|
||||
ctx.ServerError("GetActivityStats", err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -3160,12 +3160,6 @@ func UpdateCommentContent(ctx *context.Context) {
|
|||
|
||||
oldContent := comment.Content
|
||||
comment.Content = ctx.FormString("content")
|
||||
if len(comment.Content) == 0 {
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"content": "",
|
||||
})
|
||||
return
|
||||
}
|
||||
if err = issue_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
|
||||
ctx.ServerError("UpdateComment", err)
|
||||
return
|
||||
|
|
|
@ -1423,16 +1423,16 @@ func registerRoutes(m *web.Route) {
|
|||
m.Group("/contributors", func() {
|
||||
m.Get("", repo.Contributors)
|
||||
m.Get("/data", repo.ContributorsData)
|
||||
})
|
||||
}, repo.MustBeNotEmpty)
|
||||
m.Group("/code-frequency", func() {
|
||||
m.Get("", repo.CodeFrequency)
|
||||
m.Get("/data", repo.CodeFrequencyData)
|
||||
})
|
||||
}, repo.MustBeNotEmpty)
|
||||
m.Group("/recent-commits", func() {
|
||||
m.Get("", repo.RecentCommits)
|
||||
m.Get("/data", repo.RecentCommitsData)
|
||||
})
|
||||
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases))
|
||||
}, repo.MustBeNotEmpty)
|
||||
}, context.RepoRef(), context.RequireRepoReaderOr(unit.TypeCode, unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases))
|
||||
|
||||
m.Group("/activity_author_data", func() {
|
||||
m.Get("", repo.ActivityAuthors)
|
||||
|
|
|
@ -34,6 +34,7 @@ type Source struct {
|
|||
BindPassword string // Bind DN password
|
||||
UserBase string // Base search path for users
|
||||
UserDN string // Template for the DN of the user for simple auth
|
||||
DefaultDomainName string // DomainName used if none are in the field, default "localhost.local"
|
||||
AttributeUsername string // Username attribute
|
||||
AttributeName string // First name attribute
|
||||
AttributeSurname string // Surname attribute
|
||||
|
|
|
@ -105,7 +105,11 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
|
|||
}
|
||||
|
||||
if len(su.Mail) == 0 {
|
||||
su.Mail = fmt.Sprintf("%s@localhost.local", su.Username)
|
||||
domainName := source.DefaultDomainName
|
||||
if len(domainName) == 0 {
|
||||
domainName = "localhost.local"
|
||||
}
|
||||
su.Mail = fmt.Sprintf("%s@%s", su.Username, domainName)
|
||||
}
|
||||
|
||||
fullName := composeFullName(su.Name, su.Surname, su.Username)
|
||||
|
|
|
@ -237,6 +237,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
|||
MirrorInterval: mirrorInterval,
|
||||
MirrorUpdated: mirrorUpdated,
|
||||
RepoTransfer: transfer,
|
||||
ObjectFormatName: repo.ObjectFormatName,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ type AuthenticationForm struct {
|
|||
AttributeUsername string
|
||||
AttributeName string
|
||||
AttributeSurname string
|
||||
DefaultDomainName string
|
||||
AttributeMail string
|
||||
AttributeSSHPublicKey string
|
||||
AttributeAvatar string
|
||||
|
|
|
@ -28,9 +28,13 @@ func TestGarbageCollectLFSMetaObjects(t *testing.T) {
|
|||
err := storage.Init()
|
||||
assert.NoError(t, err)
|
||||
|
||||
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1")
|
||||
repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "lfs")
|
||||
assert.NoError(t, err)
|
||||
|
||||
validLFSObjects, err := db.GetEngine(db.DefaultContext).Count(git_model.LFSMetaObject{RepositoryID: repo.ID})
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, validLFSObjects, int64(1))
|
||||
|
||||
// add lfs object
|
||||
lfsContent := []byte("gitea1")
|
||||
lfsOid := storeObjectInRepo(t, repo.ID, &lfsContent)
|
||||
|
@ -39,13 +43,18 @@ func TestGarbageCollectLFSMetaObjects(t *testing.T) {
|
|||
err = repo_service.GarbageCollectLFSMetaObjects(context.Background(), repo_service.GarbageCollectLFSMetaObjectsOptions{
|
||||
AutoFix: true,
|
||||
OlderThan: time.Now().Add(7 * 24 * time.Hour).Add(5 * 24 * time.Hour),
|
||||
UpdatedLessRecentlyThan: time.Now().Add(7 * 24 * time.Hour).Add(3 * 24 * time.Hour),
|
||||
UpdatedLessRecentlyThan: time.Time{}, // ensure that the models/fixtures/lfs_meta_object.yml objects are considered as well
|
||||
LogDetail: t.Logf,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// lfs meta has been deleted
|
||||
_, err = git_model.GetLFSMetaObjectByOid(db.DefaultContext, repo.ID, lfsOid)
|
||||
assert.ErrorIs(t, err, git_model.ErrLFSObjectNotExist)
|
||||
|
||||
remainingLFSObjects, err := db.GetEngine(db.DefaultContext).Count(git_model.LFSMetaObject{RepositoryID: repo.ID})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, validLFSObjects-1, remainingLFSObjects)
|
||||
}
|
||||
|
||||
func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string {
|
||||
|
|
|
@ -97,6 +97,10 @@
|
|||
<label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label>
|
||||
<input id="attribute_mail" name="attribute_mail" value="{{$cfg.AttributeMail}}" placeholder="mail" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label>
|
||||
<input id="default_domain_name" name="default_domain_name" value="{{$cfg.DefaultDomainName}}" placeholder="localhost.local" >
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label>
|
||||
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{$cfg.AttributeSSHPublicKey}}" placeholder="SshPublicKey">
|
||||
|
|
|
@ -71,6 +71,10 @@
|
|||
<label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label>
|
||||
<input id="attribute_mail" name="attribute_mail" value="{{.attribute_mail}}" placeholder="mail">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label>
|
||||
<input id="default_domain_name" name="default_domain_name" value="{{.default_domain_name}}" placeholder="localhost.local">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label>
|
||||
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{.attribute_ssh_public_key}}" placeholder="SshPublicKey">
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
<div role="main" aria-label="{{.Title}}" class="page-content repository commits">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container flex-container">
|
||||
<div class="flex-container-nav">
|
||||
{{template "repo/navbar" .}}
|
||||
</div>
|
||||
{{if and (not .IsEmptyRepo) (.Permission.CanRead $.UnitTypeCode)}}
|
||||
<div class="flex-container-nav">
|
||||
{{template "repo/navbar" .}}
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="flex-container-main">
|
||||
{{if .PageIsPulse}}{{template "repo/pulse" .}}{{end}}
|
||||
{{if .PageIsContributors}}{{template "repo/contributors" .}}{{end}}
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}}
|
||||
{{if and (.Permission.CanReadAny $.UnitTypeCode $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases)}}
|
||||
<a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity">
|
||||
{{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}}
|
||||
</a>
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
<span class="text grey">{{svg "octicon-git-branch"}}{{.BranchName}}</span>
|
||||
</td>
|
||||
<td>
|
||||
{{if .ParentIDs}}
|
||||
{{if .ParentHashes}}
|
||||
{{ctx.Locale.Tr "repo.diff.parent"}}
|
||||
{{range .ParentIDs}}
|
||||
{{range .ParentHashes}}
|
||||
<a class="ui primary sha label" href="{{$.RepoLink}}/commit/{{.String}}">{{ShortSha .String}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -701,3 +701,14 @@ func TestAPIRepoGetAssignees(t *testing.T) {
|
|||
DecodeJSON(t, resp, &assignees)
|
||||
assert.Len(t, assignees, 1)
|
||||
}
|
||||
|
||||
func TestAPIViewRepoObjectFormat(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
var repo api.Repository
|
||||
|
||||
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.EqualValues(t, "sha1", repo.ObjectFormatName)
|
||||
}
|
||||
|
|
|
@ -112,13 +112,17 @@ func getLDAPServerPort() string {
|
|||
return port
|
||||
}
|
||||
|
||||
func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval string) map[string]string {
|
||||
func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter, groupTeamMap, groupTeamMapRemoval string) map[string]string {
|
||||
// Modify user filter to test group filter explicitly
|
||||
userFilter := "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))"
|
||||
if groupFilter != "" {
|
||||
userFilter = "(&(objectClass=inetOrgPerson)(uid=%s))"
|
||||
}
|
||||
|
||||
if len(mailKeyAttribute) == 0 {
|
||||
mailKeyAttribute = "mail"
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
"_csrf": csrf,
|
||||
"type": "2",
|
||||
|
@ -134,8 +138,9 @@ func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap
|
|||
"attribute_username": "uid",
|
||||
"attribute_name": "givenName",
|
||||
"attribute_surname": "sn",
|
||||
"attribute_mail": "mail",
|
||||
"attribute_mail": mailKeyAttribute,
|
||||
"attribute_ssh_public_key": sshKeyAttribute,
|
||||
"default_domain_name": defaultDomainName,
|
||||
"is_sync_enabled": "on",
|
||||
"is_active": "on",
|
||||
"groups_enabled": "on",
|
||||
|
@ -148,7 +153,7 @@ func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap
|
|||
}
|
||||
}
|
||||
|
||||
func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupMapParams ...string) {
|
||||
func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter string, groupMapParams ...string) {
|
||||
groupTeamMapRemoval := "off"
|
||||
groupTeamMap := ""
|
||||
if len(groupMapParams) == 2 {
|
||||
|
@ -157,7 +162,7 @@ func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupM
|
|||
}
|
||||
session := loginUser(t, "user1")
|
||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval))
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter, groupTeamMap, groupTeamMapRemoval))
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
|
@ -167,7 +172,7 @@ func TestLDAPUserSignin(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "")
|
||||
addAuthSourceLDAP(t, "", "", "", "")
|
||||
|
||||
u := gitLDAPUsers[0]
|
||||
|
||||
|
@ -184,7 +189,7 @@ func TestLDAPUserSignin(t *testing.T) {
|
|||
|
||||
func TestLDAPAuthChange(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "")
|
||||
addAuthSourceLDAP(t, "", "", "", "")
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
req := NewRequest(t, "GET", "/admin/auths")
|
||||
|
@ -205,7 +210,7 @@ func TestLDAPAuthChange(t *testing.T) {
|
|||
binddn, _ := doc.Find(`input[name="bind_dn"]`).Attr("value")
|
||||
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
|
||||
|
||||
req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "", "off"))
|
||||
req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "", "", "", "off"))
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
req = NewRequest(t, "GET", href)
|
||||
|
@ -215,6 +220,21 @@ func TestLDAPAuthChange(t *testing.T) {
|
|||
assert.Equal(t, host, getLDAPServerHost())
|
||||
binddn, _ = doc.Find(`input[name="bind_dn"]`).Attr("value")
|
||||
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
|
||||
domainname, _ := doc.Find(`input[name="default_domain_name"]`).Attr("value")
|
||||
assert.Equal(t, "", domainname)
|
||||
|
||||
req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "test.org", "", "", "off"))
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
req = NewRequest(t, "GET", href)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
host, _ = doc.Find(`input[name="host"]`).Attr("value")
|
||||
assert.Equal(t, host, getLDAPServerHost())
|
||||
binddn, _ = doc.Find(`input[name="bind_dn"]`).Attr("value")
|
||||
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
|
||||
domainname, _ = doc.Find(`input[name="default_domain_name"]`).Attr("value")
|
||||
assert.Equal(t, "test.org", domainname)
|
||||
}
|
||||
|
||||
func TestLDAPUserSync(t *testing.T) {
|
||||
|
@ -223,7 +243,7 @@ func TestLDAPUserSync(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "")
|
||||
addAuthSourceLDAP(t, "", "", "", "")
|
||||
auth.SyncExternalUsers(context.Background(), true)
|
||||
|
||||
// Check if users exists
|
||||
|
@ -252,7 +272,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) {
|
|||
|
||||
session := loginUser(t, "user1")
|
||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
||||
payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "")
|
||||
payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "", "", "")
|
||||
payload["attribute_username"] = ""
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", payload)
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
@ -300,7 +320,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "(cn=git)")
|
||||
addAuthSourceLDAP(t, "", "", "", "(cn=git)")
|
||||
|
||||
// Assert a user not a member of the LDAP group "cn=git" cannot login
|
||||
// This test may look like TestLDAPUserSigninFailed but it is not.
|
||||
|
@ -359,7 +379,7 @@ func TestLDAPUserSigninFailed(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "")
|
||||
addAuthSourceLDAP(t, "", "", "", "")
|
||||
|
||||
u := otherLDAPUsers[0]
|
||||
testLoginFailed(t, u.UserName, u.Password, translation.NewLocale("en-US").TrString("form.username_password_incorrect"))
|
||||
|
@ -371,7 +391,7 @@ func TestLDAPUserSSHKeySync(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "sshPublicKey", "")
|
||||
addAuthSourceLDAP(t, "sshPublicKey", "", "", "")
|
||||
|
||||
auth.SyncExternalUsers(context.Background(), true)
|
||||
|
||||
|
@ -404,7 +424,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
|
||||
addAuthSourceLDAP(t, "", "", "", "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
|
||||
org, err := organization.GetOrgByName(db.DefaultContext, "org26")
|
||||
assert.NoError(t, err)
|
||||
team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11")
|
||||
|
@ -449,7 +469,7 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) {
|
|||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
|
||||
addAuthSourceLDAP(t, "", "", "", "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
|
||||
org, err := organization.GetOrgByName(db.DefaultContext, "org26")
|
||||
assert.NoError(t, err)
|
||||
team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11")
|
||||
|
@ -487,6 +507,58 @@ func TestLDAPPreventInvalidGroupTeamMap(t *testing.T) {
|
|||
|
||||
session := loginUser(t, "user1")
|
||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off"))
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off"))
|
||||
session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok
|
||||
}
|
||||
|
||||
func TestLDAPUserSyncInvalidMail(t *testing.T) {
|
||||
if skipLDAPTests() {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "nonexisting", "", "")
|
||||
auth.SyncExternalUsers(context.Background(), true)
|
||||
|
||||
// Check if users exists
|
||||
for _, gitLDAPUser := range gitLDAPUsers {
|
||||
dbUser, err := user_model.GetUserByName(db.DefaultContext, gitLDAPUser.UserName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gitLDAPUser.UserName, dbUser.Name)
|
||||
assert.Equal(t, gitLDAPUser.UserName+"@localhost.local", dbUser.Email)
|
||||
assert.Equal(t, gitLDAPUser.IsAdmin, dbUser.IsAdmin)
|
||||
assert.Equal(t, gitLDAPUser.IsRestricted, dbUser.IsRestricted)
|
||||
}
|
||||
|
||||
// Check if no users exist
|
||||
for _, otherLDAPUser := range otherLDAPUsers {
|
||||
_, err := user_model.GetUserByName(db.DefaultContext, otherLDAPUser.UserName)
|
||||
assert.True(t, user_model.IsErrUserNotExist(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLDAPUserSyncInvalidMailDefaultDomain(t *testing.T) {
|
||||
if skipLDAPTests() {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
addAuthSourceLDAP(t, "", "nonexisting", "test.org", "")
|
||||
auth.SyncExternalUsers(context.Background(), true)
|
||||
|
||||
// Check if users exists
|
||||
for _, gitLDAPUser := range gitLDAPUsers {
|
||||
dbUser, err := user_model.GetUserByName(db.DefaultContext, gitLDAPUser.UserName)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, gitLDAPUser.UserName, dbUser.Name)
|
||||
assert.Equal(t, gitLDAPUser.UserName+"@test.org", dbUser.Email)
|
||||
assert.Equal(t, gitLDAPUser.IsAdmin, dbUser.IsAdmin)
|
||||
assert.Equal(t, gitLDAPUser.IsRestricted, dbUser.IsRestricted)
|
||||
}
|
||||
|
||||
// Check if no users exist
|
||||
for _, otherLDAPUser := range otherLDAPUsers {
|
||||
_, err := user_model.GetUserByName(db.DefaultContext, otherLDAPUser.UserName)
|
||||
assert.True(t, user_model.IsErrUserNotExist(err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,6 +307,16 @@ func TestIssueCommentUpdate(t *testing.T) {
|
|||
|
||||
comment = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: commentID})
|
||||
assert.Equal(t, modifiedContent, comment.Content)
|
||||
|
||||
// make the comment empty
|
||||
req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, issueURL),
|
||||
"content": "",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
comment = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: commentID})
|
||||
assert.Equal(t, "", comment.Content)
|
||||
}
|
||||
|
||||
func TestIssueReaction(t *testing.T) {
|
||||
|
|
|
@ -100,6 +100,6 @@ func TestLFSRender(t *testing.T) {
|
|||
req = NewRequest(t, "GET", lfsFindPath)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body).doc
|
||||
assert.Contains(t, doc.Text(), "README.md")
|
||||
assert.Equal(t, 1, doc.Find(`.sha.label[href="/user2/lfs/commit/73cf03db6ece34e12bf91e8853dc58f678f2f82d"]`).Length(), "could not find link to commit")
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue